From 93412d3c9e0ca32944d6e88e6cb222dd42364eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Wed, 25 Oct 2023 08:31:56 +0200 Subject: [PATCH 01/13] set bigquery client timeout for deploy --- clouds/bigquery/common/run-script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clouds/bigquery/common/run-script.js b/clouds/bigquery/common/run-script.js index 8378eae9c..dead9ab52 100755 --- a/clouds/bigquery/common/run-script.js +++ b/clouds/bigquery/common/run-script.js @@ -14,7 +14,7 @@ const options = { }; const bar = new cliProgress.SingleBar(options, cliProgress.Presets.shades_classic); -const client = new BigQuery({ projectId: `${BQ_PROJECT}` }); +const client = new BigQuery({ projectId: `${BQ_PROJECT}`, timeout: 600000 }); async function runQueries (queries) { const query_options = { 'timeoutMs' : 120000 }; From 68598186c67db0144840af7201ecc1db2ff0c0c6 Mon Sep 17 00:00:00 2001 From: Valentin de la Cruz Barquero <6054336+vdelacruzb@users.noreply.github.com> Date: Thu, 28 Dec 2023 16:16:09 +0100 Subject: [PATCH 02/13] fix(bq|h3): fix broken reference in H3_POLYFILL_TABLE (#459) --- .../modules/sql/h3/H3_POLYFILL_TABLE.sql | 2 +- .../modules/test/h3/H3_POLYFILL_TABLE.test.js | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/clouds/bigquery/modules/sql/h3/H3_POLYFILL_TABLE.sql b/clouds/bigquery/modules/sql/h3/H3_POLYFILL_TABLE.sql index 846d3feb6..e0c0df18b 100644 --- a/clouds/bigquery/modules/sql/h3/H3_POLYFILL_TABLE.sql +++ b/clouds/bigquery/modules/sql/h3/H3_POLYFILL_TABLE.sql @@ -29,7 +29,7 @@ AS """ return 'CREATE TABLE `' + output_table + '` CLUSTER BY (h3) AS\\n' + 'WITH __input AS (' + input_query + '),\\n' + '__cells AS (SELECT h3, i.* FROM __input AS i,\\n' + - 'UNNEST(`@@BQ_DATASET@@.__H3_POLYFILL_INIT`(geom,`@@BQ_DATASET@@.__H3_POLYFILL_INIT_Z`(geom,' + resolution + '))) AS parent,\\n' + + 'UNNEST(`@@BQ_DATASET@@.__H3_POLYFILL_INIT_BBOX`(geom,`@@BQ_DATASET@@.__H3_POLYFILL_INIT_Z`(geom,' + resolution + '))) AS parent,\\n' + 'UNNEST(`@@BQ_DATASET@@.H3_TOCHILDREN`(parent,' + resolution + ')) AS h3)\\n' + 'SELECT * EXCEPT (geom) FROM __cells\\n' + 'WHERE ' + containmentFunction + '(geom, `' + cellFunction + '`(h3));' diff --git a/clouds/bigquery/modules/test/h3/H3_POLYFILL_TABLE.test.js b/clouds/bigquery/modules/test/h3/H3_POLYFILL_TABLE.test.js index 9675f27f7..13e8d8e04 100644 --- a/clouds/bigquery/modules/test/h3/H3_POLYFILL_TABLE.test.js +++ b/clouds/bigquery/modules/test/h3/H3_POLYFILL_TABLE.test.js @@ -2,6 +2,24 @@ const { runQuery } = require('../../../common/test-utils'); const BQ_DATASET = process.env.BQ_DATASET; +test('H3_POLYFILL_TABLE should work', async () => { + output_table_name = 'h3_polyfill_table_geom_output' + let query = `DROP TABLE IF EXISTS \`@@BQ_DATASET@@.${output_table_name}\`; + CALL \`@@BQ_DATASET@@.H3_POLYFILL_TABLE\`( + 'SELECT ST_GEOGFROMTEXT("POLYGON ((-3.71219873428345 40.413365349070865, -3.7144088745117 40.40965661286395, -3.70659828186035 40.409525904775634, -3.71219873428345 40.413365349070865))") as geom', + 9, 'center', + '@@BQ_DATASET@@.${output_table_name}' + )`; + await runQuery(query); + + const rows = await runQuery(`SELECT * FROM \`@@BQ_DATASET@@.${output_table_name}\``); + expect(rows.length).toEqual(1); + expect(rows[0].h3).toEqual('89390cb1b4bffff'); + + query = `DROP TABLE IF EXISTS \`@@BQ_DATASET@@.${output_table_name}\``; + await runQuery(query); +}); + test('H3_POLYFILL_TABLE should generate the correct query', async () => { const query = `SELECT \`@@BQ_DATASET@@.__H3_POLYFILL_QUERY\`( 'SELECT geom, name, value FROM \`..\`', @@ -13,7 +31,7 @@ test('H3_POLYFILL_TABLE should generate the correct query', async () => { expect(rows[0].output).toEqual(`CREATE TABLE \`..\` CLUSTER BY (h3) AS WITH __input AS (SELECT geom, name, value FROM \`..
\`), __cells AS (SELECT h3, i.* FROM __input AS i, -UNNEST(\`@@BQ_DATASET@@.__H3_POLYFILL_INIT\`(geom,\`@@BQ_DATASET@@.__H3_POLYFILL_INIT_Z\`(geom,12))) AS parent, +UNNEST(\`@@BQ_DATASET@@.__H3_POLYFILL_INIT_BBOX\`(geom,\`@@BQ_DATASET@@.__H3_POLYFILL_INIT_Z\`(geom,12))) AS parent, UNNEST(\`@@BQ_DATASET@@.H3_TOCHILDREN\`(parent,12)) AS h3) SELECT * EXCEPT (geom) FROM __cells WHERE ST_INTERSECTS(geom, \`@@BQ_DATASET@@.H3_CENTER\`(h3));`.replace(/@@BQ_DATASET@@/g, BQ_DATASET)); From 1f1ff3c58fc43f1ebb9e3bea7504682be7650474 Mon Sep 17 00:00:00 2001 From: Valentin de la Cruz Barquero <6054336+vdelacruzb@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:34:07 +0100 Subject: [PATCH 03/13] release: 2024-01-17 (#471) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Javier Goizueta Co-authored-by: Alberto Hernández Co-authored-by: Jesús Arroyo Torrens Co-authored-by: Pedro-Juan Ferrer --- .github/workflows/bigquery-ded.yml | 8 +- .github/workflows/postgres-ded.yml | 8 +- .github/workflows/redshift-ded.yml | 22 +- .github/workflows/snowflake-ded.yml | 10 +- .github/workflows/snowflake.yml | 33 ++- CHANGELOG.md | 13 + CONTRIBUTING.md | 65 +++++ clouds/bigquery/CHANGELOG.md | 10 + clouds/bigquery/common/build_modules.js | 4 +- clouds/bigquery/common/package.json | 2 +- clouds/bigquery/common/run-query.js | 3 +- clouds/bigquery/common/run-script.js | 23 +- clouds/bigquery/common/test-utils.js | 2 +- .../javascript/src/transformations.js | 2 + clouds/bigquery/modules/Makefile | 6 +- .../modules/doc/quadbin/QUADBIN_DISTANCE.md | 23 ++ .../doc/transformations/ST_POINTONSURFACE.md | 24 ++ .../sql/constructors/ST_TILEENVELOPE.sql | 4 +- .../modules/sql/quadbin/QUADBIN_DISTANCE.sql | 25 ++ .../sql/quadbin/QUADBIN_FROMLONGLAT.sql | 21 +- .../modules/sql/quadbin/QUADBIN_POLYFILL.sql | 28 +- .../sql/transformations/ST_POINTONSURFACE.sql | 30 +++ .../test/constructors/ST_TILEENVELOPE.test.js | 6 +- .../modules/test/h3/H3_POLYFILL_TABLE.test.js | 2 +- .../test/quadbin/QUADBIN_DISTANCE.test.js | 8 + .../test/quadbin/QUADBIN_FROMLONGLAT.test.js | 20 +- .../quadbin/QUADBIN_POLYFILL_TABLE.test.js | 2 +- .../transformations/ST_POINTONSURFACE.test.js | 17 ++ clouds/bigquery/version | 2 +- clouds/postgres/CHANGELOG.md | 8 + clouds/postgres/common/run_script.py | 14 +- clouds/postgres/modules/Makefile | 3 +- .../modules/doc/quadbin/QUADBIN_DISTANCE.md | 23 ++ .../modules/sql/quadbin/QUADBIN_DISTANCE.sql | 32 +++ .../sql/quadbin/QUADBIN_FROMLONGLAT.sql | 10 +- .../test/quadbin/test_QUADBIN_DISTANCE.py | 10 + .../test/quadbin/test_QUADBIN_FROMLONGLAT.py | 24 +- clouds/postgres/version | 2 +- clouds/redshift/CHANGELOG.md | 8 + clouds/redshift/common/run_script.py | 13 +- .../libraries/python/requirements.txt | 2 +- clouds/redshift/modules/Makefile | 3 +- .../modules/doc/quadbin/QUADBIN_DISTANCE.md | 23 ++ .../sql/constructors/ST_BEZIERSPLINE.sql | 18 +- .../sql/constructors/ST_MAKEELLIPSE.sql | 24 +- .../sql/constructors/ST_MAKEENVELOPE.sql | 2 +- .../sql/helpers/__ST_GEOMFROMGEOJSON.sql | 22 -- .../modules/sql/quadbin/QUADBIN_DISTANCE.sql | 28 ++ .../modules/sql/quadbin/QUADBIN_TOZXY.sql | 84 ------ .../modules/sql/quadbin/__QUADBIN_TOZXY_X.sql | 78 ++++++ .../modules/sql/quadbin/__QUADBIN_TOZXY_Y.sql | 12 + .../sql/transformations/ST_CENTERMEAN.sql | 2 +- .../sql/transformations/ST_CENTERMEDIAN.sql | 2 +- .../sql/transformations/ST_CENTROID.sql | 2 +- .../sql/transformations/ST_DESTINATION.sql | 4 +- .../sql/transformations/ST_GREATCIRCLE.sql | 4 +- .../fixtures/st_bezierspline_out.txt | 2 +- .../fixtures/st_makeellipse_out.txt | 2 +- .../test/constructors/test_ST_BEZIERSPLINE.py | 8 +- .../test/constructors/test_ST_MAKEELLIPSE.py | 12 +- .../test/quadbin/test_QUADBIN_DISTANCE.py | 11 + .../test/quadbin/test_QUADBIN_FROMLONGLAT.py | 26 +- clouds/redshift/version | 2 +- clouds/snowflake/CHANGELOG.md | 9 + clouds/snowflake/Makefile | 19 +- clouds/snowflake/README.md | 7 +- clouds/snowflake/common/Makefile | 2 + .../common/build_native_app_setup_script.js | 245 ++++++++++++++++++ clouds/snowflake/common/native-app-utils.js | 151 +++++++++++ clouds/snowflake/common/package.json | 2 +- clouds/snowflake/common/run-script.js | 15 +- .../javascript/libs/transformations_center.js | 6 +- clouds/snowflake/modules/Makefile | 17 +- .../modules/doc/quadbin/QUADBIN_DISTANCE.md | 23 ++ .../doc/transformations/ST_POINTONSURFACE.md | 24 ++ .../modules/sql/quadbin/QUADBIN_DISTANCE.sql | 33 +++ .../sql/quadbin/QUADBIN_FROMLONGLAT.sql | 13 +- .../sql/quadbin/QUADBIN_FROMQUADKEY.sql | 11 +- .../modules/sql/quadbin/QUADBIN_FROMZXY.sql | 13 +- .../modules/sql/quadbin/QUADBIN_KRING.sql | 11 +- .../sql/quadbin/QUADBIN_KRING_DISTANCES.sql | 11 +- .../modules/sql/quadbin/QUADBIN_SIBLING.sql | 33 +-- .../modules/sql/quadbin/QUADBIN_TOPARENT.sql | 37 +-- .../modules/sql/quadbin/QUADBIN_TOQUADKEY.sql | 11 +- .../modules/sql/quadbin/QUADBIN_TOZXY.sql | 11 +- .../sql/transformations/ST_POINTONSURFACE.sql | 27 ++ .../test/constructors/ST_TILEENVELOPE.test.js | 8 +- .../test/quadbin/QUADBIN_DISTANCE.test.js | 8 + .../test/quadbin/QUADBIN_FROMLONGLAT.test.js | 20 +- .../transformations/ST_POINTONSURFACE.test.js | 17 ++ clouds/snowflake/native_app/Makefile | 101 ++++++++ clouds/snowflake/native_app/README.md | 47 ++++ clouds/snowflake/native_app/manifest.yml | 10 + clouds/snowflake/version | 2 +- 94 files changed, 1556 insertions(+), 331 deletions(-) create mode 100644 clouds/bigquery/modules/doc/quadbin/QUADBIN_DISTANCE.md create mode 100644 clouds/bigquery/modules/doc/transformations/ST_POINTONSURFACE.md create mode 100644 clouds/bigquery/modules/sql/quadbin/QUADBIN_DISTANCE.sql create mode 100644 clouds/bigquery/modules/sql/transformations/ST_POINTONSURFACE.sql create mode 100644 clouds/bigquery/modules/test/quadbin/QUADBIN_DISTANCE.test.js create mode 100644 clouds/bigquery/modules/test/transformations/ST_POINTONSURFACE.test.js create mode 100644 clouds/postgres/modules/doc/quadbin/QUADBIN_DISTANCE.md create mode 100644 clouds/postgres/modules/sql/quadbin/QUADBIN_DISTANCE.sql create mode 100644 clouds/postgres/modules/test/quadbin/test_QUADBIN_DISTANCE.py create mode 100644 clouds/redshift/modules/doc/quadbin/QUADBIN_DISTANCE.md delete mode 100644 clouds/redshift/modules/sql/helpers/__ST_GEOMFROMGEOJSON.sql create mode 100644 clouds/redshift/modules/sql/quadbin/QUADBIN_DISTANCE.sql create mode 100644 clouds/redshift/modules/sql/quadbin/__QUADBIN_TOZXY_X.sql create mode 100644 clouds/redshift/modules/sql/quadbin/__QUADBIN_TOZXY_Y.sql create mode 100644 clouds/redshift/modules/test/quadbin/test_QUADBIN_DISTANCE.py create mode 100755 clouds/snowflake/common/build_native_app_setup_script.js create mode 100755 clouds/snowflake/common/native-app-utils.js create mode 100644 clouds/snowflake/modules/doc/quadbin/QUADBIN_DISTANCE.md create mode 100644 clouds/snowflake/modules/doc/transformations/ST_POINTONSURFACE.md create mode 100644 clouds/snowflake/modules/sql/quadbin/QUADBIN_DISTANCE.sql create mode 100644 clouds/snowflake/modules/sql/transformations/ST_POINTONSURFACE.sql create mode 100644 clouds/snowflake/modules/test/quadbin/QUADBIN_DISTANCE.test.js create mode 100644 clouds/snowflake/modules/test/transformations/ST_POINTONSURFACE.test.js create mode 100644 clouds/snowflake/native_app/Makefile create mode 100644 clouds/snowflake/native_app/README.md create mode 100644 clouds/snowflake/native_app/manifest.yml diff --git a/.github/workflows/bigquery-ded.yml b/.github/workflows/bigquery-ded.yml index abcc20d06..a4eb69dd6 100644 --- a/.github/workflows/bigquery-ded.yml +++ b/.github/workflows/bigquery-ded.yml @@ -27,15 +27,11 @@ jobs: - name: Set BQ_PREFIX for releases if: startsWith(github.event.pull_request.head.ref, 'release/') run: | - BRANCH_NAME="${{ github.event.pull_request.head.ref }}" - VERSION=${BRANCH_NAME#release/} - echo "BQ_PREFIX=dedicated_release_${VERSION}_" >> $GITHUB_ENV + echo "BQ_PREFIX=dedicated_release_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV - name: Set BQ_PREFIX for hotfixes if: startsWith(github.event.pull_request.head.ref, 'hotfix/') run: | - BRANCH_NAME="${{ github.event.pull_request.head.ref }}" - VERSION=${BRANCH_NAME#hotfix/} - echo "BQ_PREFIX=dedicated_release_${VERSION}_" >> $GITHUB_ENV + echo "BQ_PREFIX=dedicated_hotfix_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV - name: Set BQ_PREFIX for regular deploys if: | !(startsWith(github.event.pull_request.head.ref, 'hotfix/')) && diff --git a/.github/workflows/postgres-ded.yml b/.github/workflows/postgres-ded.yml index 82ab96343..db50fcc16 100644 --- a/.github/workflows/postgres-ded.yml +++ b/.github/workflows/postgres-ded.yml @@ -29,15 +29,11 @@ jobs: - name: Set PG_PREFIX for releases if: startsWith(github.event.pull_request.head.ref, 'release/') run: | - BRANCH_NAME="${{ github.event.pull_request.head.ref }}" - VERSION=${BRANCH_NAME#release/} - echo "PG_PREFIX=dedicated_release_${VERSION}_" >> $GITHUB_ENV + echo "PG_PREFIX=dedicated_release_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV - name: Set PG_PREFIX for hotfixes if: startsWith(github.event.pull_request.head.ref, 'hotfix/') run: | - BRANCH_NAME="${{ github.event.pull_request.head.ref }}" - VERSION=${BRANCH_NAME#hotfix/} - echo "PG_PREFIX=dedicated_release_${VERSION}_" >> $GITHUB_ENV + echo "PG_PREFIX=dedicated_hotfix_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV - name: Set PG_PREFIX for regular deploys if: | !(startsWith(github.event.pull_request.head.ref, 'hotfix/')) && diff --git a/.github/workflows/redshift-ded.yml b/.github/workflows/redshift-ded.yml index dc2d20494..0c5e71c2b 100644 --- a/.github/workflows/redshift-ded.yml +++ b/.github/workflows/redshift-ded.yml @@ -18,6 +18,7 @@ jobs: (github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'dedicated_redshift')) || (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'dedicated_redshift')) runs-on: ubuntu-20.04 + container: python:2.7.18-buster timeout-minutes: 20 env: RS_HOST: ${{ secrets.RS_HOST_CD }} @@ -30,23 +31,8 @@ jobs: steps: - name: Checkout repo uses: actions/checkout@v2 - - name: Set RS_PREFIX for releases - if: startsWith(github.event.pull_request.head.ref, 'release/') - run: | - BRANCH_NAME="${{ github.event.pull_request.head.ref }}" - VERSION=${BRANCH_NAME#release/} - echo "RS_PREFIX=dedicated_release_${VERSION}_" >> $GITHUB_ENV - - name: Set RS_PREFIX for hotfixes - if: startsWith(github.event.pull_request.head.ref, 'hotfix/') - run: | - BRANCH_NAME="${{ github.event.pull_request.head.ref }}" - VERSION=${BRANCH_NAME#hotfix/} - echo "RS_PREFIX=dedicated_release_${VERSION}_" >> $GITHUB_ENV - - name: Set RS_PREFIX for regular deploys - if: | - !(startsWith(github.event.pull_request.head.ref, 'hotfix/')) && - !(startsWith(github.event.pull_request.head.ref, 'release/')) - run: echo "RS_PREFIX=dedicated_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV + - name: Check diff + uses: technote-space/get-diff-action@v4 - name: Setup node uses: actions/setup-node@v1 with: @@ -62,6 +48,8 @@ jobs: curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip ./aws/install + - name: Setup virtualenv + run: pip install virtualenv==${{ env.VIRTUALENV_VERSION }} - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: diff --git a/.github/workflows/snowflake-ded.yml b/.github/workflows/snowflake-ded.yml index 250fe4e90..324dfc2c4 100644 --- a/.github/workflows/snowflake-ded.yml +++ b/.github/workflows/snowflake-ded.yml @@ -5,7 +5,7 @@ on: types: [closed, unlabeled, labeled, synchronize] env: - NODE_VERSION: 14 + NODE_VERSION: 16 jobs: @@ -28,15 +28,11 @@ jobs: - name: Set SF_PREFIX for releases if: startsWith(github.event.pull_request.head.ref, 'release/') run: | - BRANCH_NAME="${{ github.event.pull_request.head.ref }}" - VERSION=${BRANCH_NAME#release/} - echo "SF_PREFIX=dedicated_release_${VERSION}_" >> $GITHUB_ENV + echo "SF_PREFIX=dedicated_release_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV - name: Set SF_PREFIX for hotfixes if: startsWith(github.event.pull_request.head.ref, 'hotfix/') run: | - BRANCH_NAME="${{ github.event.pull_request.head.ref }}" - VERSION=${BRANCH_NAME#hotfix/} - echo "SF_PREFIX=dedicated_release_${VERSION}_" >> $GITHUB_ENV + echo "SF_PREFIX=dedicated_hotfix_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV - name: Set SF_PREFIX for regular deploys if: | !(startsWith(github.event.pull_request.head.ref, 'hotfix/')) && diff --git a/.github/workflows/snowflake.yml b/.github/workflows/snowflake.yml index 8c37e4726..cbb102107 100644 --- a/.github/workflows/snowflake.yml +++ b/.github/workflows/snowflake.yml @@ -15,7 +15,7 @@ on: workflow_call: env: - NODE_VERSION: 14 + NODE_VERSION: 16 PYTHON3_VERSION: 3.8.10 VIRTUALENV_VERSION: 20.21.1 GCLOUD_VERSION: 290.0.1 @@ -88,6 +88,37 @@ jobs: cd clouds/snowflake make deploy diff="$GIT_DIFF" production=1 + deploy-internal-app: + if: github.ref_name == 'main' + needs: test + runs-on: ubuntu-20.04 + timeout-minutes: 20 + env: + APP_PACKAGE_NAME: ${{ secrets.SF_NATIVE_APP_PACKAGE_NAME_CD }} + APP_NAME: ${{ secrets.SF_NATIVE_APP_NAME_CD }} + SF_ACCOUNT: ${{ secrets.SF_ACCOUNT_NATIVE_APP }} + SF_DATABASE: ${{ secrets.SF_DATABASE_NATIVE_APP }} + SF_USER: ${{ secrets.SF_USER_NATIVE_APP }} + SF_PASSWORD: ${{ secrets.SF_PASSWORD_NATIVE_APP }} + SF_ROLE: ${{ secrets.SF_ROLE_NATIVE_APP }} + steps: + - name: Checkout repo + uses: actions/checkout@v2 + - name: Check diff + uses: technote-space/get-diff-action@v4 + - name: Setup node + uses: actions/setup-node@v1 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Deploy native app package + run: | + cd clouds/snowflake + make deploy-native-app-package production=1 + - name: Deploy native app locally + run: | + cd clouds/snowflake + make deploy-native-app production=1 + deploy-share: if: github.ref_name == 'stable' needs: test diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fa961081..4b703f537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ CARTO Analytics Toolbox Core. All notable commits to this project will be documented in this file. +## 2024-01-17 + +- chore(bq): increase tests timeout to 200000 (#455) +- feat(bq,sf,rs,pg|quadbin): add function QUADBIN_DISTANCE (#457) +- fix(bq|h3): fix broken reference in H3_POLYFILL_TABLE (#458, #460) +- chore(bq,sf,rs,pg): fix naming dedicated deployments for releases (#462) +- fix(sf|quadbin): QUADBIN_FROMLONGLAT not clamping latitudes and return some quadbin functions return NULL when NULL parameters (#456) +- fix(rs|constructors,transformations): adjust SRID and use native ST_GEOMFROMGEOJSON to return geometries instead of VARCHAR (#463) +- chore(pg): fix typo naming dedicated deployments for releases (#464) +- chore(bq,sf,rs,pg): make remove drop functions instead of whole schema (#466) +- fix(bq,sf,rs,pg|quadbin): improve precision of long lat conversion near the latitude limits (#461) +- feat(bq,sf|transformations): add function ST_POINTONSURFACE (#469, #470) + ## 2023-08-04 - chore(bq|quadbin,h3): optimize quadbin/h3 polyfill performance (#421) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 633aa7874..90c5e1b75 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -162,3 +162,68 @@ Images must be stored in `common/assets/`, and included with the following synta ```md ![My image](my_image.png) ``` + +## Naming requirements + +The format of function and procedure names in the code must follow some conventions, so that the scripts that build the SQL code can determine the dependencies between them. + +### BigQuery + +Function/procedure invocations: the name must be quoted with backticks, including the project/dataset name. The opening bracket must follow the closing quote with no space between them: + +```sql +SELECT `@@BQ_DATASET@@.A_FUNCTION`(); +CALL `@@BQ_DATASET@@.A_PROCEDURE`(); +``` + +Function/procedure definitions: must be quoted as invocations, but parentheses should be on a separate line: + +```sql +CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.A_FUNCTION` +( + an_argument STRING +) +... +``` + +### Other clouds (Snowflake, Redshift, Postgres) + +Function/procedure invocations: The opening bracket must follow name with no space between them: + + +```sql +SELECT @@XX_SCHEMA@@.A_FUNCTION(); +CALL @@XX_SCHEMA@@.A_PROCEDURE(); +``` + +Function/procedure definitions: must be quoted as invocations, but parentheses should be on a separate line: + +```sql +CREATE OR REPLACE FUNCTION @@XX_SCHEMA@@.A_FUNCTION +( + an_argument STRING +) +RETURNS STRING +IMMUTABLE +... +``` + +### Extra dependencies + +Sometimes the name of an invoked function or procedure is dynamically generated in the SQL code; +in those cases it's necessary to add a coment in the file referencing all the functions/procedures that can potentially be called. + +In this comment, the names must appear as in actual invocations, following the rules of each cloud, i.e. including the argument parentheses, and +in the case of BigQuery, the backtick quotes. For example: + +```sql +/* +Extra dependencies: +`@@BQ_DATASET@@.SOME_FUNCTION`() +*/ +``` + +## Known Limitations +### Snowflake + +Due to Snowflake Native Apps limitations at this moment TEMPORARY tables cannot be used within procedures. For the time being create normal tables and ensure that they are dropped. \ No newline at end of file diff --git a/clouds/bigquery/CHANGELOG.md b/clouds/bigquery/CHANGELOG.md index fea3008be..3a1801276 100644 --- a/clouds/bigquery/CHANGELOG.md +++ b/clouds/bigquery/CHANGELOG.md @@ -4,6 +4,16 @@ CARTO Analytics Toolbox Core for BigQuery. All notable commits to this project will be documented in this file. +## [1.2.0] - 2024-01-17 + +- chore: increase tests timeout to 200000 (#455) +- feat(quadbin): add function QUADBIN_DISTANCE (#457) +- fix(h3): fix broken reference in H3_POLYFILL_TABLE (#458, #460) +- chore: fix naming dedicated deployments for releases (#462) +- chore: make remove drop functions instead of whole schema (#466) +- fix(quadbin): improve precision of long lat conversion near the latitude limits (#461) +- feat(transformations): add function ST_POINTONSURFACE (#469) + ## [1.1.0] - 2023-08-04 - chore(quadbin,h3): optimize quadbin/h3 polyfill performance (#421) diff --git a/clouds/bigquery/common/build_modules.js b/clouds/bigquery/common/build_modules.js index ae2620d18..e691541c1 100755 --- a/clouds/bigquery/common/build_modules.js +++ b/clouds/bigquery/common/build_modules.js @@ -99,7 +99,7 @@ functionsFilter.forEach(f => { if (!nodeps) { functions.forEach(mainFunction => { functions.forEach(depFunction => { - if (mainFunction.name != depFunction.name && depFunction.name !== 'SETUP') { + if (mainFunction.name != depFunction.name) { const depFunctionMatches = []; depFunctionMatches.push(...depFunction.content.replace(/(\r\n|\n|\r)/gm,' ').matchAll(new RegExp('(?<=(? mainFunction.content.includes(`DATASET@@.${depFunctionName}`))) { + if (depFunctionNames.some((depFunctionName) => mainFunction.content.includes(`DATASET@@.${depFunctionName}\`(`))) { mainFunction.dependencies.push(depFunction.name); } } diff --git a/clouds/bigquery/common/package.json b/clouds/bigquery/common/package.json index 2cd1cbd06..cb669992e 100644 --- a/clouds/bigquery/common/package.json +++ b/clouds/bigquery/common/package.json @@ -1,7 +1,7 @@ { "license": "BSD-3-Clause", "devDependencies": { - "@google-cloud/bigquery": "^5.3.0", + "@google-cloud/bigquery": "^7.3.0", "@rollup/plugin-commonjs": "^17.1.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.0.0", diff --git a/clouds/bigquery/common/run-query.js b/clouds/bigquery/common/run-query.js index 92fda2f90..51aa90440 100755 --- a/clouds/bigquery/common/run-query.js +++ b/clouds/bigquery/common/run-query.js @@ -7,8 +7,7 @@ const BQ_PROJECT = process.env.BQ_PROJECT; const client = new BigQuery({ projectId: `${BQ_PROJECT}` }); function runQuery (query) { - const query_options = { 'timeoutMs' : 120000 }; - client.query(query, query_options); + client.query(query, { timeoutMs : 120000 }); } const query = process.argv[2]; diff --git a/clouds/bigquery/common/run-script.js b/clouds/bigquery/common/run-script.js index e00e07bd5..6f5c04e23 100755 --- a/clouds/bigquery/common/run-script.js +++ b/clouds/bigquery/common/run-script.js @@ -14,21 +14,36 @@ const options = { }; const bar = new cliProgress.SingleBar(options, cliProgress.Presets.shades_classic); -const client = new BigQuery({ projectId: `${BQ_PROJECT}`, timeout: 600000 }); +const client = new BigQuery({ projectId: `${BQ_PROJECT}` }); + +function apply_replacements (text) { + if (process.env.REPLACEMENTS) { + const replacements = process.env.REPLACEMENTS.split(' '); + for (let replacement of replacements) { + if (replacement) { + const pattern = new RegExp(`@@${replacement}@@`, 'g'); + text = text.replace(pattern, process.env[replacement]); + } + } + } + return text; +} async function runQueries (queries) { - const query_options = { 'timeoutMs' : 600000 }; const n = queries.length; bar.start(n, 0); for (let i = 0; i < n; i++) { - let query = queries[i]; + let query = apply_replacements(queries[i]); const pattern = /(FUNCTION|PROCEDURE)\s+(.*?)[(\n]/g; const results = pattern.exec(query); const result = results && results.reverse()[0] sqlFunction = result && result.split('.').reverse()[0] - await client.query(query, query_options); + await client.query({ + query, + jobTimeoutMs: 600000 + }); bar.increment(); } bar.stop(n); diff --git a/clouds/bigquery/common/test-utils.js b/clouds/bigquery/common/test-utils.js index 11cf3fd99..76f0d70da 100644 --- a/clouds/bigquery/common/test-utils.js +++ b/clouds/bigquery/common/test-utils.js @@ -10,7 +10,7 @@ const BQ_DATASET = process.env.BQ_DATASET; const client = new BigQuery({ projectId: `${BQ_PROJECT}` }); async function runQuery (query, options) { - options = Object.assign({}, { 'timeoutMs' : 120000 }, options); + options = Object.assign({}, { timeoutMs : 120000 }, options); query = replaceBQPrefix(query); const [rows] = await client.query(query, options); return rows; diff --git a/clouds/bigquery/libraries/javascript/src/transformations.js b/clouds/bigquery/libraries/javascript/src/transformations.js index a7e95d0b2..86a944063 100644 --- a/clouds/bigquery/libraries/javascript/src/transformations.js +++ b/clouds/bigquery/libraries/javascript/src/transformations.js @@ -11,6 +11,7 @@ import { along, lineString, cleanCoords, + pointOnFeature, multiPoint, point } from '@turf/turf'; @@ -28,6 +29,7 @@ export default { along, lineString, cleanCoords, + pointOnFeature, multiPoint, point }; \ No newline at end of file diff --git a/clouds/bigquery/modules/Makefile b/clouds/bigquery/modules/Makefile index 46031c30d..ca2f9abfe 100644 --- a/clouds/bigquery/modules/Makefile +++ b/clouds/bigquery/modules/Makefile @@ -85,7 +85,7 @@ test: check $(NODE_MODULES_DEV) if [ ! -z "$$TESTS" ]; then \ GOOGLE_APPLICATION_CREDENTIALS=$(GOOGLE_APPLICATION_CREDENTIALS) \ PATH="$(NODE_MODULES_DEV)/.bin/:$(PATH)" \ - jest --testTimeout=150000 $(BAIL) --verbose --slowTestThreshold=20 --maxConcurrency=10 $$TESTS \ + jest --testTimeout=200000 $(BAIL) --verbose --slowTestThreshold=20 --maxConcurrency=10 $$TESTS \ --setupFilesAfterEnv "$(COMMON_DIR)/test-extend.js" || exit 1; \ OLD_TEST=$(TEST_DIR)/$$m/old-test; \ if [ -d $$OLD_TEST ]; then \ @@ -97,7 +97,9 @@ test: check $(NODE_MODULES_DEV) remove: check echo "Removing modules..." - $(BQ) rm -r -f -d $(BQ_DEPLOY_DATASET) + REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ + GOOGLE_APPLICATION_CREDENTIALS=$(GOOGLE_APPLICATION_CREDENTIALS) \ + $(COMMON_DIR)/run-script.js $(COMMON_DIR)/DROP_FUNCTIONS.sql clean: echo "Cleaning modules..." diff --git a/clouds/bigquery/modules/doc/quadbin/QUADBIN_DISTANCE.md b/clouds/bigquery/modules/doc/quadbin/QUADBIN_DISTANCE.md new file mode 100644 index 000000000..0ea67d80a --- /dev/null +++ b/clouds/bigquery/modules/doc/quadbin/QUADBIN_DISTANCE.md @@ -0,0 +1,23 @@ +## QUADBIN_DISTANCE + +```sql:signature +QUADBIN_DISTANCE(origin, destination) +``` + +**Description** + +Returns the [Chebyshev distance](https://en.wikipedia.org/wiki/Chebyshev_distance) between two quadbin indexes. The origin and destination indices must have the same resolution. Otherwise `NULL` will be returned. + +* `origin`: `INT64` origin quadbin index. +* `destination`: `INT64` destination quadbin index. + +**Return type** + +`INT64` + +**Example** + +```sql +SELECT carto.QUADBIN_DISTANCE(5207251884775047167, 5207128739472736255); +-- 1 +``` diff --git a/clouds/bigquery/modules/doc/transformations/ST_POINTONSURFACE.md b/clouds/bigquery/modules/doc/transformations/ST_POINTONSURFACE.md new file mode 100644 index 000000000..b27f53596 --- /dev/null +++ b/clouds/bigquery/modules/doc/transformations/ST_POINTONSURFACE.md @@ -0,0 +1,24 @@ +## ST_POINTONSURFACE + +```sql:signature +ST_POINTONSURFACE(geog) +``` + +**Description** + +Takes any Feature or a FeatureCollection and returns a point that is granted to be inside one of the polygons. + +* `geog`: `GEOGRAPHY` feature to be centered. + +**Return type** + +`GEOGRAPHY` + +**Example** + +```sql +SELECT carto.ST_POINTONSURFACE( + ST_GEOGFROMTEXT("POLYGON ((1.444057 38.791203 , 1.450457 38.793763 , 1.457178 38.792403 , 1.458298 38.781282 , 1.453418 38.778242 , 1.445977 38.780482 , 1.453498 38.781042 , 1.456218 38.786883 , 1.450617 38.790643 , 1.444057 38.791203))") +); +-- POINT(1.456218 38.786883) +``` diff --git a/clouds/bigquery/modules/sql/constructors/ST_TILEENVELOPE.sql b/clouds/bigquery/modules/sql/constructors/ST_TILEENVELOPE.sql index e736abb7c..d1e699e8f 100644 --- a/clouds/bigquery/modules/sql/constructors/ST_TILEENVELOPE.sql +++ b/clouds/bigquery/modules/sql/constructors/ST_TILEENVELOPE.sql @@ -6,8 +6,8 @@ CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.ST_TILEENVELOPE` (zoomLevel INT64, xTile INT64, yTile INT64) RETURNS GEOGRAPHY AS ( - `@@BQ_DATASET@@.QUADINT_BOUNDARY`( - `@@BQ_DATASET@@.QUADINT_FROMZXY`( + `@@BQ_DATASET@@.QUADBIN_BOUNDARY`( + `@@BQ_DATASET@@.QUADBIN_FROMZXY`( zoomlevel, xtile, ytile ) ) diff --git a/clouds/bigquery/modules/sql/quadbin/QUADBIN_DISTANCE.sql b/clouds/bigquery/modules/sql/quadbin/QUADBIN_DISTANCE.sql new file mode 100644 index 000000000..7bdb8945b --- /dev/null +++ b/clouds/bigquery/modules/sql/quadbin/QUADBIN_DISTANCE.sql @@ -0,0 +1,25 @@ +---------------------------- +-- Copyright (C) 2023 CARTO +---------------------------- + +CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.QUADBIN_DISTANCE` +(origin INT64, destination INT64) +RETURNS INT64 +AS (( + IF(origin IS NULL OR destination IS NULL, + NULL, + (WITH __quadbin_coords AS ( + SELECT + `@@BQ_DATASET@@.QUADBIN_TOZXY`(origin) AS origin_coords, + `@@BQ_DATASET@@.QUADBIN_TOZXY`(destination) AS destination_coords + ) + SELECT IF(origin_coords.z != destination_coords.z, + NULL, + GREATEST( + ABS(destination_coords.x - origin_coords.x), + ABS(destination_coords.y - origin_coords.y) + ) + ) + FROM __quadbin_coords) + ) +)); diff --git a/clouds/bigquery/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql b/clouds/bigquery/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql index 4fcd6cc2d..1b904e70b 100644 --- a/clouds/bigquery/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql +++ b/clouds/bigquery/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2024 CARTO +-------------------------------- CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.QUADBIN_FROMLONGLAT` (longitude FLOAT64, latitude FLOAT64, resolution INT64) @@ -17,7 +17,7 @@ AS (( resolution AS z, (1 << resolution) AS __z2, ACOS(-1) AS pi, - GREATEST(-85.05, LEAST(85.05, latitude)) AS latitude + GREATEST(-89, LEAST(89, latitude)) AS latitude ), ___sinlat AS ( @@ -47,12 +47,13 @@ AS (( CAST( -- floor before cast to avoid up rounding to the next tiLe FLOOR( - __z2 * ( - 0.5 - 0.25 - * LN( - (1 + __sinlat) / (1 - __sinlat) - ) / pi - ) + GREATEST(0, LEAST(__z2 - 1, + __z2 * ( + 0.5 - 0.25 + * LN( + (1 + __sinlat) / (1 - __sinlat) + ) / pi + ))) ) AS INT64 ) AS y FROM diff --git a/clouds/bigquery/modules/sql/quadbin/QUADBIN_POLYFILL.sql b/clouds/bigquery/modules/sql/quadbin/QUADBIN_POLYFILL.sql index e2ea6a68d..09c835317 100644 --- a/clouds/bigquery/modules/sql/quadbin/QUADBIN_POLYFILL.sql +++ b/clouds/bigquery/modules/sql/quadbin/QUADBIN_POLYFILL.sql @@ -16,9 +16,9 @@ AS (( __params AS ( SELECT box.xmin AS minlon, - box.ymin AS minlat, box.xmax AS maxlon, - box.ymax AS maxlat, + GREATEST(-89, LEAST(89, box.ymin)) AS minlat, + GREATEST(-89, LEAST(89, box.ymax)) AS maxlat, (1 << resolution) AS z2, ACOS(-1) AS pi FROM __bbox @@ -37,11 +37,13 @@ AS (( ) AS xmin, CAST( FLOOR( - z2 * ( - 0.5 - 0.25 * LN( - (1 + sinlat_max) / (1 - sinlat_max) - ) / pi - ) + GREATEST(0, LEAST(z2 - 1, + z2 * ( + 0.5 - 0.25 * LN( + (1 + sinlat_max) / (1 - sinlat_max) + ) / pi + ) + )) ) AS INT64 ) AS ymin, CAST( @@ -49,11 +51,13 @@ AS (( ) AS xmax, CAST( FLOOR( - z2 * ( - 0.5 - 0.25 * LN( - (1 + sinlat_min) / (1 - sinlat_min) - ) / pi - ) + GREATEST(0, LEAST(z2 - 1, + z2 * ( + 0.5 - 0.25 * LN( + (1 + sinlat_min) / (1 - sinlat_min) + ) / pi + ) + )) ) AS INT64 ) AS ymax FROM __params, __sinlat diff --git a/clouds/bigquery/modules/sql/transformations/ST_POINTONSURFACE.sql b/clouds/bigquery/modules/sql/transformations/ST_POINTONSURFACE.sql new file mode 100644 index 000000000..9fcce0575 --- /dev/null +++ b/clouds/bigquery/modules/sql/transformations/ST_POINTONSURFACE.sql @@ -0,0 +1,30 @@ +---------------------------- +-- Copyright (C) 2024 CARTO +---------------------------- + +CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.__POINTONSURFACE` +(geojson STRING) +RETURNS STRING +DETERMINISTIC +LANGUAGE js +OPTIONS ( + library = ["@@BQ_LIBRARY_BUCKET@@"] +) +AS """ + if (!geojson) { + return null; + } + const center = lib.transformations.pointOnFeature(JSON.parse(geojson)); + return JSON.stringify(center.geometry); +"""; + +CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.ST_POINTONSURFACE` +(geog GEOGRAPHY) +RETURNS GEOGRAPHY +AS ( + ST_GEOGFROMGEOJSON( + `@@BQ_DATASET@@.__POINTONSURFACE`( + ST_ASGEOJSON(geog) + ) + ) +); diff --git a/clouds/bigquery/modules/test/constructors/ST_TILEENVELOPE.test.js b/clouds/bigquery/modules/test/constructors/ST_TILEENVELOPE.test.js index 19a460d99..bd0e5de83 100644 --- a/clouds/bigquery/modules/test/constructors/ST_TILEENVELOPE.test.js +++ b/clouds/bigquery/modules/test/constructors/ST_TILEENVELOPE.test.js @@ -15,7 +15,9 @@ test('ST_TILEENVELOPE should work', async () => { test('ST_TILEENVELOPE should fail if any NULL argument', async () => { const query = ` - SELECT \`@@BQ_DATASET@@.ST_TILEENVELOPE\`(10, 384, null) + SELECT \`@@BQ_DATASET@@.ST_TILEENVELOPE\`(10, 384, null) AS geog `; - await expect(runQuery(query)).rejects.toThrow(); + const rows = await runQuery(query); + expect(rows.length).toEqual(1); + expect(rows[0].geog).toEqual(null); }); \ No newline at end of file diff --git a/clouds/bigquery/modules/test/h3/H3_POLYFILL_TABLE.test.js b/clouds/bigquery/modules/test/h3/H3_POLYFILL_TABLE.test.js index 13e8d8e04..bb1634eb4 100644 --- a/clouds/bigquery/modules/test/h3/H3_POLYFILL_TABLE.test.js +++ b/clouds/bigquery/modules/test/h3/H3_POLYFILL_TABLE.test.js @@ -35,4 +35,4 @@ UNNEST(\`@@BQ_DATASET@@.__H3_POLYFILL_INIT_BBOX\`(geom,\`@@BQ_DATASET@@.__H3_POL UNNEST(\`@@BQ_DATASET@@.H3_TOCHILDREN\`(parent,12)) AS h3) SELECT * EXCEPT (geom) FROM __cells WHERE ST_INTERSECTS(geom, \`@@BQ_DATASET@@.H3_CENTER\`(h3));`.replace(/@@BQ_DATASET@@/g, BQ_DATASET)); -}); +}); \ No newline at end of file diff --git a/clouds/bigquery/modules/test/quadbin/QUADBIN_DISTANCE.test.js b/clouds/bigquery/modules/test/quadbin/QUADBIN_DISTANCE.test.js new file mode 100644 index 000000000..47a57b191 --- /dev/null +++ b/clouds/bigquery/modules/test/quadbin/QUADBIN_DISTANCE.test.js @@ -0,0 +1,8 @@ +const { runQuery } = require('../../../common/test-utils'); + +test('QUADBIN_DISTANCE should work', async () => { + const query = 'SELECT `@@BQ_DATASET@@.QUADBIN_DISTANCE`(5207251884775047167, 5207128739472736255) AS output'; + const rows = await runQuery(query); + expect(rows.length).toEqual(1); + expect(rows[0].output).toEqual(1); +}); \ No newline at end of file diff --git a/clouds/bigquery/modules/test/quadbin/QUADBIN_FROMLONGLAT.test.js b/clouds/bigquery/modules/test/quadbin/QUADBIN_FROMLONGLAT.test.js index 86e4bb918..a6ff20a17 100644 --- a/clouds/bigquery/modules/test/quadbin/QUADBIN_FROMLONGLAT.test.js +++ b/clouds/bigquery/modules/test/quadbin/QUADBIN_FROMLONGLAT.test.js @@ -1,10 +1,26 @@ const { runQuery } = require('../../../common/test-utils'); test('QUADBIN_FROMLONGLAT should work', async () => { - const query = 'SELECT CAST(`@@BQ_DATASET@@.QUADBIN_FROMLONGLAT`(40.4168, -3.7038, 4) AS STRING) AS output'; + const query = ` + WITH inputs AS ( + SELECT 1 AS id, CAST(\`@@BQ_DATASET@@.QUADBIN_FROMLONGLAT\`(40.4168, -3.7038, 4) AS STRING) AS output + UNION ALL SELECT 2, CAST(\`@@BQ_DATASET@@.QUADBIN_FROMLONGLAT\`(0, 85.05112877980659, 26) AS STRING) + UNION ALL SELECT 3, CAST(\`@@BQ_DATASET@@.QUADBIN_FROMLONGLAT\`(0, 88, 26) AS STRING) + UNION ALL SELECT 4, CAST(\`@@BQ_DATASET@@.QUADBIN_FROMLONGLAT\`(0, 90, 26) AS STRING) + UNION ALL SELECT 5, CAST(\`@@BQ_DATASET@@.QUADBIN_FROMLONGLAT\`(0, -85.05112877980659, 26) AS STRING) + UNION ALL SELECT 6, CAST(\`@@BQ_DATASET@@.QUADBIN_FROMLONGLAT\`(0, -88, 26) AS STRING) + UNION ALL SELECT 7, CAST(\`@@BQ_DATASET@@.QUADBIN_FROMLONGLAT\`(0, -90, 26) AS STRING) + ) + SELECT * FROM inputs ORDER BY id ASC`; const rows = await runQuery(query); - expect(rows.length).toEqual(1); + expect(rows.length).toEqual(7); expect(rows[0].output).toEqual('5209574053332910079'); + expect(rows[1].output).toEqual('5306366260949286912'); + expect(rows[2].output).toEqual('5306366260949286912'); + expect(rows[3].output).toEqual('5306366260949286912'); + expect(rows[4].output).toEqual('5309368660700867242'); + expect(rows[5].output).toEqual('5309368660700867242'); + expect(rows[6].output).toEqual('5309368660700867242'); }); test('QUADBIN_FROMLONGLAT should return null if the input is null', async () => { diff --git a/clouds/bigquery/modules/test/quadbin/QUADBIN_POLYFILL_TABLE.test.js b/clouds/bigquery/modules/test/quadbin/QUADBIN_POLYFILL_TABLE.test.js index ff444e35f..977d996a9 100644 --- a/clouds/bigquery/modules/test/quadbin/QUADBIN_POLYFILL_TABLE.test.js +++ b/clouds/bigquery/modules/test/quadbin/QUADBIN_POLYFILL_TABLE.test.js @@ -17,4 +17,4 @@ UNNEST(\`@@BQ_DATASET@@.__QUADBIN_POLYFILL_INIT\`(geom,\`@@BQ_DATASET@@.__QUADBI UNNEST(\`@@BQ_DATASET@@.QUADBIN_TOCHILDREN\`(parent,12)) AS quadbin) SELECT * EXCEPT (geom) FROM __cells WHERE ST_INTERSECTS(geom, \`@@BQ_DATASET@@.QUADBIN_CENTER\`(quadbin));`.replace(/@@BQ_DATASET@@/g, BQ_DATASET)); -}); +}); \ No newline at end of file diff --git a/clouds/bigquery/modules/test/transformations/ST_POINTONSURFACE.test.js b/clouds/bigquery/modules/test/transformations/ST_POINTONSURFACE.test.js new file mode 100644 index 000000000..b44cdeef4 --- /dev/null +++ b/clouds/bigquery/modules/test/transformations/ST_POINTONSURFACE.test.js @@ -0,0 +1,17 @@ +const { runQuery } = require('../../../common/test-utils'); + +test('ST_POINTONSURFACE should work', async () => { + const query = `SELECT \`@@BQ_DATASET@@.ST_POINTONSURFACE\`(ST_GEOGFROMTEXT("MULTIPOLYGON ( (( 1.432239 38.774949 , 1.430004 38.776613 , 1.429594 38.779004 , 1.429017 38.780159 , 1.427593 38.781527 , 1.425098 38.782440 , 1.423667 38.782105 , 1.423500 38.780778 , 1.421648 38.780213 , 1.420044 38.778803 , 1.419783 38.779692 , 1.419998 38.780884 , 1.418469 38.782359 , 1.417274 38.784848 , 1.417280 38.785641 , 1.418790 38.786572 , 1.419115 38.787496 , 1.420219 38.788078 , 1.422245 38.790701 , 1.422430 38.792226 , 1.421102 38.794001 , 1.419421 38.794483 , 1.419112 38.794921 , 1.420578 38.795797 , 1.421985 38.797293 , 1.424319 38.796379 , 1.425594 38.795468 , 1.424784 38.794619 , 1.424858 38.793340 , 1.426658 38.791067 , 1.428010 38.789823 , 1.428901 38.787502 , 1.429748 38.786711 , 1.430096 38.785544 , 1.430951 38.785375 , 1.431356 38.784263 , 1.431377 38.781200 , 1.431665 38.780104 , 1.431531 38.778868 , 1.432695 38.777271 , 1.432404 38.776888 , 1.433254 38.775386 , 1.432239 38.774949)), (( 1.479401 38.788441 , 1.477737 38.789852 , 1.477167 38.791727 , 1.476344 38.792537 , 1.475231 38.795045 , 1.474967 38.796087 , 1.474324 38.796538 , 1.474129 38.799221 , 1.475761 38.800972 , 1.477059 38.804368 , 1.477770 38.805054 , 1.478568 38.804866 , 1.477156 38.801982 , 1.477438 38.800634 , 1.479283 38.799423 , 1.481316 38.799135 , 1.481027 38.798076 , 1.479663 38.797248 , 1.478855 38.796246 , 1.478892 38.794525 , 1.479432 38.794064 , 1.479328 38.791900 , 1.479850 38.789546 , 1.479401 38.788441)))")) as pointOnSurface1, + \`@@BQ_DATASET@@.ST_POINTONSURFACE\`(ST_GEOGFROMTEXT("POLYGON ((1.444057 38.791203 , 1.450457 38.793763 , 1.457178 38.792403 , 1.458298 38.781282 , 1.453418 38.778242 , 1.445977 38.780482 , 1.453498 38.781042 , 1.456218 38.786883 , 1.450617 38.790643 , 1.444057 38.791203))")) as pointOnSurface2`; + const rows = await runQuery(query); + expect(rows.length).toEqual(1); + expect(rows[0].pointOnSurface1.value).toEqual('POINT(1.430951 38.785375)'); + expect(rows[0].pointOnSurface2.value).toEqual('POINT(1.456218 38.786883)'); +}); + +test('ST_POINTONSURFACE should return NULL if any NULL mandatory argument', async () => { + const query = 'SELECT `@@BQ_DATASET@@.ST_POINTONSURFACE`(NULL) as pointonsurface1'; + const rows = await runQuery(query); + expect(rows.length).toEqual(1); + expect(rows[0].pointonsurface1).toEqual(null); +}); \ No newline at end of file diff --git a/clouds/bigquery/version b/clouds/bigquery/version index 9084fa2f7..26aaba0e8 100644 --- a/clouds/bigquery/version +++ b/clouds/bigquery/version @@ -1 +1 @@ -1.1.0 +1.2.0 diff --git a/clouds/postgres/CHANGELOG.md b/clouds/postgres/CHANGELOG.md index 36d948b1a..c79ebd098 100644 --- a/clouds/postgres/CHANGELOG.md +++ b/clouds/postgres/CHANGELOG.md @@ -4,6 +4,14 @@ CARTO Analytics Toolbox Core for Postgres. All notable commits to this project will be documented in this file. +## [1.3.0] - 2024-01-17 + +- feat(quadbin): add function QUADBIN_DISTANCE (#457) +- chore: fix naming dedicated deployments for releases (#462) +- chore: fix typo naming dedicated deployments for releases (#464) +- chore: make remove drop functions instead of whole schema (#466) +- fix(quadbin): improve precision of long lat conversion near the latitude limits (#461) + ## [1.2.0] - 2023-08-04 - chore(quadbin,h3): optimize quadbin/h3 polyfill performance (#418) diff --git a/clouds/postgres/common/run_script.py b/clouds/postgres/common/run_script.py index fcf9570e6..1bcd7f264 100644 --- a/clouds/postgres/common/run_script.py +++ b/clouds/postgres/common/run_script.py @@ -9,6 +9,16 @@ function = '' +def apply_replacements(text): + if os.environ.get('REPLACEMENTS'): + replacements = os.environ.get('REPLACEMENTS').split(' ') + for replacement in replacements: + if replacement: + pattern = re.compile(f'@@{replacement}@@', re.MULTILINE) + text = pattern.sub(os.environ.get(replacement, ''), text) + return text + + def run_queries(queries): global function with connect( @@ -20,7 +30,7 @@ def run_queries(queries): conn.autocommit = True with conn.cursor() as cursor: for i in trange(len(queries), ncols=97): - query = queries[i] + query = apply_replacements(queries[i]) pattern = os.environ['PG_SCHEMA'] + '.(.*?)[(|\n]' result = re.search(pattern, query) if result: @@ -42,9 +52,11 @@ def run_queries(queries): except Exception as error: error_msg = str(error) print(f'ERROR: {error_msg}') + exit(1) else: try: run_queries(split(content)) except Exception as error: error_msg = str(error) print(f'[{function}] ERROR: {error_msg}') + exit(1) diff --git a/clouds/postgres/modules/Makefile b/clouds/postgres/modules/Makefile index 44f26d760..ba3603b36 100644 --- a/clouds/postgres/modules/Makefile +++ b/clouds/postgres/modules/Makefile @@ -61,7 +61,8 @@ test: check venv3 $(NODE_MODULES_DEV) remove: venv3 echo "Removing modules..." - $(VENV3_BIN)/python $(COMMON_DIR)/run_query.py "DROP SCHEMA IF EXISTS $(PG_SCHEMA) CASCADE;" + REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ + $(VENV3_BIN)/python $(COMMON_DIR)/run_script.py $(COMMON_DIR)/DROP_FUNCTIONS.sql clean: echo "Cleaning modules..." diff --git a/clouds/postgres/modules/doc/quadbin/QUADBIN_DISTANCE.md b/clouds/postgres/modules/doc/quadbin/QUADBIN_DISTANCE.md new file mode 100644 index 000000000..3e711d8cd --- /dev/null +++ b/clouds/postgres/modules/doc/quadbin/QUADBIN_DISTANCE.md @@ -0,0 +1,23 @@ +## QUADBIN_DISTANCE + +```sql:signature +QUADBIN_DISTANCE(origin, destination) +``` + +**Description** + +Returns the [Chebyshev distance](https://en.wikipedia.org/wiki/Chebyshev_distance) between two quadbin indexes. The origin and destination indices must have the same resolution. Otherwise `NULL` will be returned. + +* `origin`: `BIGINT` origin quadbin index. +* `destination`: `BIGINT` destination quadbin index. + +**Return type** + +`BIGINT` + +**Example** + +```sql +SELECT carto.QUADBIN_DISTANCE(5207251884775047167, 5207128739472736255); +-- 1 +``` diff --git a/clouds/postgres/modules/sql/quadbin/QUADBIN_DISTANCE.sql b/clouds/postgres/modules/sql/quadbin/QUADBIN_DISTANCE.sql new file mode 100644 index 000000000..24cb236de --- /dev/null +++ b/clouds/postgres/modules/sql/quadbin/QUADBIN_DISTANCE.sql @@ -0,0 +1,32 @@ +---------------------------- +-- Copyright (C) 2023 CARTO +---------------------------- + +CREATE OR REPLACE FUNCTION @@PG_SCHEMA@@.QUADBIN_DISTANCE +(origin BIGINT, destination BIGINT) +RETURNS BIGINT +AS +$BODY$ + SELECT + CASE WHEN origin IS NULL OR destination IS NULL THEN + NULL + ELSE + (WITH __quadbin_coords AS ( + SELECT + @@PG_SCHEMA@@.QUADBIN_TOZXY(origin) AS origin_coords, + @@PG_SCHEMA@@.QUADBIN_TOZXY(destination) AS destination_coords + ) + SELECT + CASE WHEN (origin_coords->>'z')::INT != (destination_coords->>'z')::INT THEN + NULL + ELSE + GREATEST( + ABS((destination_coords->>'x')::BIGINT - (origin_coords->>'x')::BIGINT), + ABS((destination_coords->>'y')::BIGINT - (origin_coords->>'y')::BIGINT) + ) + END + FROM __quadbin_coords + ) + END +$BODY$ +LANGUAGE sql IMMUTABLE PARALLEL SAFE; diff --git a/clouds/postgres/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql b/clouds/postgres/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql index e059b33f9..2ff080032 100644 --- a/clouds/postgres/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql +++ b/clouds/postgres/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2024 CARTO +-------------------------------- CREATE OR REPLACE FUNCTION @@PG_SCHEMA@@.QUADBIN_FROMLONGLAT( longitude DOUBLE PRECISION, @@ -21,7 +21,7 @@ $BODY$ SELECT resolution AS z, (1 << resolution) AS __z2, - GREATEST(-85.05, LEAST(85.05, latitude)) AS latitude + GREATEST(-89, LEAST(89, latitude)) AS latitude ), ___sinlat AS ( SELECT @@ -41,7 +41,7 @@ $BODY$ WHEN __x < 0 THEN __x + __z2 ELSE __x END AS x, - (FLOOR(__z2 * (0.5 - 0.25 * (LN((1 + __sinlat)/(1 - __sinlat)) / PI()))))::BIGINT AS y + (FLOOR(GREATEST(0, LEAST(__z2 - 1, __z2 * (0.5 - 0.25 * (LN((1 + __sinlat)/(1 - __sinlat)) / PI()))))))::BIGINT AS y FROM __params, ___sinlat, diff --git a/clouds/postgres/modules/test/quadbin/test_QUADBIN_DISTANCE.py b/clouds/postgres/modules/test/quadbin/test_QUADBIN_DISTANCE.py new file mode 100644 index 000000000..68bb559c1 --- /dev/null +++ b/clouds/postgres/modules/test/quadbin/test_QUADBIN_DISTANCE.py @@ -0,0 +1,10 @@ +from test_utils import run_query + + +def test_quadbin_resolution(): + """Computes distance between quadbins.""" + result = run_query( + 'SELECT @@PG_SCHEMA@@.QUADBIN_DISTANCE' + '(5207251884775047167, 5207128739472736255)' + ) + assert result[0][0] == 1 diff --git a/clouds/postgres/modules/test/quadbin/test_QUADBIN_FROMLONGLAT.py b/clouds/postgres/modules/test/quadbin/test_QUADBIN_FROMLONGLAT.py index 3984f82b4..0d9db7543 100644 --- a/clouds/postgres/modules/test/quadbin/test_QUADBIN_FROMLONGLAT.py +++ b/clouds/postgres/modules/test/quadbin/test_QUADBIN_FROMLONGLAT.py @@ -4,8 +4,28 @@ def test_quadbin_longlat(): """Computes quadbin for longitude latitude.""" - result = run_query('SELECT @@PG_SCHEMA@@.QUADBIN_FROMLONGLAT(40.4168, -3.7038, 4)') - assert result[0][0] == 5209574053332910079 + result = run_query( + """ + WITH inputs AS ( + SELECT 1 AS ID, @@PG_SCHEMA@@.QUADBIN_FROMLONGLAT(40.4168, -3.7038, 4) + UNION ALL SELECT 2, + @@PG_SCHEMA@@.QUADBIN_FROMLONGLAT(0, 85.05112877980659, 26) + UNION ALL SELECT 3, @@PG_SCHEMA@@.QUADBIN_FROMLONGLAT(0, 88, 26) + UNION ALL SELECT 4, @@PG_SCHEMA@@.QUADBIN_FROMLONGLAT(0, 90, 26) + UNION ALL SELECT 5, + @@PG_SCHEMA@@.QUADBIN_FROMLONGLAT(0, -85.05112877980659, 26) + UNION ALL SELECT 6, @@PG_SCHEMA@@.QUADBIN_FROMLONGLAT(0, -88, 26) + UNION ALL SELECT 7, @@PG_SCHEMA@@.QUADBIN_FROMLONGLAT(0, -90, 26) + ) + SELECT * FROM inputs ORDER BY id ASC""" + ) + assert result[0][1] == 5209574053332910079 + assert result[1][1] == 5306366260949286912 + assert result[2][1] == 5306366260949286912 + assert result[3][1] == 5306366260949286912 + assert result[4][1] == 5309368660700867242 + assert result[5][1] == 5309368660700867242 + assert result[6][1] == 5309368660700867242 def test_quadbin_longlat_null_input(): diff --git a/clouds/postgres/version b/clouds/postgres/version index 26aaba0e8..f0bb29e76 100644 --- a/clouds/postgres/version +++ b/clouds/postgres/version @@ -1 +1 @@ -1.2.0 +1.3.0 diff --git a/clouds/redshift/CHANGELOG.md b/clouds/redshift/CHANGELOG.md index 59b5d8651..156f25ca8 100644 --- a/clouds/redshift/CHANGELOG.md +++ b/clouds/redshift/CHANGELOG.md @@ -4,6 +4,14 @@ CARTO Analytics Toolbox Core for Redshift. All notable commits to this project will be documented in this file. +## [1.1.0] - 2024-01-17 + +- feat(quadbin): add function QUADBIN_DISTANCE (#457) +- chore: fix naming dedicated deployments for releases (#462) +- fix(constructors,transformations): adjust SRID and use native ST_GEOMFROMGEOJSON to return geometries instead of VARCHAR (#463) +- chore: make remove drop functions instead of whole schema (#466) +- fix(quadbin): improve precision of long lat conversion near the latitude limits (#461) + ## [1.0.2] - 2023-07-11 - chore(quadbin): update QUADBIN_FROMLONGLAT formula (#409, #411) diff --git a/clouds/redshift/common/run_script.py b/clouds/redshift/common/run_script.py index d6574d048..167b42730 100644 --- a/clouds/redshift/common/run_script.py +++ b/clouds/redshift/common/run_script.py @@ -10,6 +10,16 @@ function = '' +def apply_replacements(text): + if os.environ.get('REPLACEMENTS'): + replacements = os.environ.get('REPLACEMENTS').split(' ') + for replacement in replacements: + if replacement: + pattern = re.compile(f'@@{replacement}@@', re.MULTILINE) + text = pattern.sub(os.environ.get(replacement, ''), text) + return text + + def run_queries(queries): global function with connect( @@ -22,7 +32,7 @@ def run_queries(queries): filter = os.environ.get('FILTER') with conn.cursor() as cursor: for i in trange(len(queries) if not filter else 1, ncols=97): - query = queries[i] + query = apply_replacements(queries[i]) if (not filter) or (filter in query): pattern = os.environ['RS_SCHEMA'] + '.(.*?)[(|\n]' result = re.search(pattern, str(query)) @@ -42,3 +52,4 @@ def run_queries(queries): except ProgrammingError as error: error_msg = re.search("'M': '(.*?)',", str(error)).group(1) print(f'[{function}] ERROR: {error_msg}') + exit(1) diff --git a/clouds/redshift/libraries/python/requirements.txt b/clouds/redshift/libraries/python/requirements.txt index 1df70396a..cc61ca38d 100644 --- a/clouds/redshift/libraries/python/requirements.txt +++ b/clouds/redshift/libraries/python/requirements.txt @@ -1,4 +1,4 @@ -quadbin==0.2.0 +quadbin==0.2.2 geojson==2.5.0 pygc==1.1.0 numpy==1.8.2 diff --git a/clouds/redshift/modules/Makefile b/clouds/redshift/modules/Makefile index bc16e6576..d56d2c3c4 100644 --- a/clouds/redshift/modules/Makefile +++ b/clouds/redshift/modules/Makefile @@ -61,7 +61,8 @@ test: check venv3 $(NODE_MODULES_DEV) remove: venv3 echo "Removing modules..." - $(VENV3_BIN)/python $(COMMON_DIR)/run_query.py "DROP SCHEMA IF EXISTS $(RS_SCHEMA) CASCADE;" + REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ + $(VENV3_BIN)/python $(COMMON_DIR)/run_script.py $(COMMON_DIR)/DROP_FUNCTIONS.sql clean: echo "Cleaning modules..." diff --git a/clouds/redshift/modules/doc/quadbin/QUADBIN_DISTANCE.md b/clouds/redshift/modules/doc/quadbin/QUADBIN_DISTANCE.md new file mode 100644 index 000000000..3e711d8cd --- /dev/null +++ b/clouds/redshift/modules/doc/quadbin/QUADBIN_DISTANCE.md @@ -0,0 +1,23 @@ +## QUADBIN_DISTANCE + +```sql:signature +QUADBIN_DISTANCE(origin, destination) +``` + +**Description** + +Returns the [Chebyshev distance](https://en.wikipedia.org/wiki/Chebyshev_distance) between two quadbin indexes. The origin and destination indices must have the same resolution. Otherwise `NULL` will be returned. + +* `origin`: `BIGINT` origin quadbin index. +* `destination`: `BIGINT` destination quadbin index. + +**Return type** + +`BIGINT` + +**Example** + +```sql +SELECT carto.QUADBIN_DISTANCE(5207251884775047167, 5207128739472736255); +-- 1 +``` diff --git a/clouds/redshift/modules/sql/constructors/ST_BEZIERSPLINE.sql b/clouds/redshift/modules/sql/constructors/ST_BEZIERSPLINE.sql index 7bf2e5052..32b851367 100644 --- a/clouds/redshift/modules/sql/constructors/ST_BEZIERSPLINE.sql +++ b/clouds/redshift/modules/sql/constructors/ST_BEZIERSPLINE.sql @@ -18,32 +18,26 @@ $$ LANGUAGE plpythonu; CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_BEZIERSPLINE (GEOMETRY) -- (linestring) -RETURNS VARCHAR(MAX) --- RETURNS GEOMETRY +RETURNS GEOMETRY STABLE AS $$ - SELECT @@RS_SCHEMA@@.__BEZIERSPLINE(ST_ASGEOJSON($1)::VARCHAR(MAX), 10000, 0.85) - -- SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__BEZIERSPLINE(ST_ASGEOJSON($1)::VARCHAR(MAX), 10000, 0.85)) + SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__BEZIERSPLINE(ST_ASGEOJSON($1)::VARCHAR(MAX), 10000, 0.85)) $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_BEZIERSPLINE (GEOMETRY, INT) -- (linestring, resolution) -RETURNS VARCHAR(MAX) --- RETURNS GEOMETRY +RETURNS GEOMETRY STABLE AS $$ - SELECT @@RS_SCHEMA@@.__BEZIERSPLINE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, 0.85) - -- SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__BEZIERSPLINE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, 0.85)) + SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__BEZIERSPLINE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, 0.85)) $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_BEZIERSPLINE (GEOMETRY, INT, FLOAT8) -- (linestring, resolution, sharpness) -RETURNS VARCHAR(MAX) --- RETURNS GEOMETRY +RETURNS GEOMETRY STABLE AS $$ - SELECT @@RS_SCHEMA@@.__BEZIERSPLINE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3) - -- SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__BEZIERSPLINE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3)) + SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__BEZIERSPLINE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3)) $$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/constructors/ST_MAKEELLIPSE.sql b/clouds/redshift/modules/sql/constructors/ST_MAKEELLIPSE.sql index c8314d6e0..06b0d4e36 100644 --- a/clouds/redshift/modules/sql/constructors/ST_MAKEELLIPSE.sql +++ b/clouds/redshift/modules/sql/constructors/ST_MAKEELLIPSE.sql @@ -34,43 +34,35 @@ $$ LANGUAGE plpythonu; CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_MAKEELLIPSE (GEOMETRY, FLOAT8, FLOAT8) -- (center, xSemiAxis, ySemiAxis) -RETURNS VARCHAR(MAX) --- RETURNS GEOMETRY +RETURNS GEOMETRY STABLE AS $$ - SELECT @@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, 0, 'kilometers', 64) - -- SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, 0, 'kilometers', 64)) + SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, 0, 'kilometers', 64)) $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_MAKEELLIPSE (GEOMETRY, FLOAT8, FLOAT8, FLOAT8) -- (center, xSemiAxis, ySemiAxis, angle) -RETURNS VARCHAR(MAX) --- RETURNS GEOMETRY +RETURNS GEOMETRY STABLE AS $$ - SELECT @@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4, 'kilometers', 64) - -- SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4, 'kilometers', 64)) + SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4, 'kilometers', 64)) $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_MAKEELLIPSE (GEOMETRY, FLOAT8, FLOAT8, FLOAT8, VARCHAR(10)) -- (center, xSemiAxis, ySemiAxis, angle, units) -RETURNS VARCHAR(MAX) --- RETURNS GEOMETRY +RETURNS GEOMETRY STABLE AS $$ - SELECT @@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4, $5, 64) - -- SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4, $5, 64)) + SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4, $5, 64)) $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_MAKEELLIPSE (GEOMETRY, FLOAT8, FLOAT8, FLOAT8, VARCHAR(10), INT) -- (center, xSemiAxis, ySemiAxis, angle, units, steps) -RETURNS VARCHAR(MAX) --- RETURNS GEOMETRY +RETURNS GEOMETRY STABLE AS $$ - SELECT @@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4, $5, $6) - -- SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4, $5, $6)) + SELECT ST_GEOMFROMGEOJSON(@@RS_SCHEMA@@.__MAKEELLIPSE(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4, $5, $6)) $$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/constructors/ST_MAKEENVELOPE.sql b/clouds/redshift/modules/sql/constructors/ST_MAKEENVELOPE.sql index 189d62d92..8d1c37e64 100644 --- a/clouds/redshift/modules/sql/constructors/ST_MAKEENVELOPE.sql +++ b/clouds/redshift/modules/sql/constructors/ST_MAKEENVELOPE.sql @@ -8,5 +8,5 @@ CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_MAKEENVELOPE RETURNS GEOMETRY STABLE AS $$ - SELECT ST_GEOMFROMTEXT('POLYGON((' || $1 || ' ' || $2 || ',' || $1 || ' ' || $4 || ',' || $3 || ' ' || $4 || ',' || $3 || ' ' || $2 || ',' || $1 || ' ' || $2 || '))') + SELECT ST_GEOMFROMTEXT('POLYGON((' || $1 || ' ' || $2 || ',' || $1 || ' ' || $4 || ',' || $3 || ' ' || $4 || ',' || $3 || ' ' || $2 || ',' || $1 || ' ' || $2 || '))', 4326) $$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/helpers/__ST_GEOMFROMGEOJSON.sql b/clouds/redshift/modules/sql/helpers/__ST_GEOMFROMGEOJSON.sql deleted file mode 100644 index 74ab5da1b..000000000 --- a/clouds/redshift/modules/sql/helpers/__ST_GEOMFROMGEOJSON.sql +++ /dev/null @@ -1,22 +0,0 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- - -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__GEOJSONTOWKT -(geom VARCHAR(MAX)) -RETURNS VARCHAR(MAX) -STABLE -AS $$ - from @@RS_LIBRARY@@.transformations import wkt_from_geojson - - return wkt_from_geojson(geom) -$$ LANGUAGE plpythonu; - -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__ST_GEOMFROMGEOJSON -(VARCHAR(MAX)) --- (geom) -RETURNS GEOMETRY -STABLE -AS $$ - SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__GEOJSONTOWKT($1), 4326) -$$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/quadbin/QUADBIN_DISTANCE.sql b/clouds/redshift/modules/sql/quadbin/QUADBIN_DISTANCE.sql new file mode 100644 index 000000000..44c3cf092 --- /dev/null +++ b/clouds/redshift/modules/sql/quadbin/QUADBIN_DISTANCE.sql @@ -0,0 +1,28 @@ +---------------------------- +-- Copyright (C) 2023 CARTO +---------------------------- + +CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.QUADBIN_DISTANCE +(origin BIGINT, destination BIGINT) +RETURNS BIGINT +STABLE +AS $$ + SELECT CASE WHEN $1 IS NULL OR $2 IS NULL THEN + NULL + ELSE + CASE WHEN @@RS_SCHEMA@@.QUADBIN_RESOLUTION($1) != @@RS_SCHEMA@@.QUADBIN_RESOLUTION($2) THEN + NULL + ELSE + GREATEST( + ABS( + (@@RS_SCHEMA@@.__QUADBIN_TOZXY_X($2) >> (32 - CAST(@@RS_SCHEMA@@.QUADBIN_RESOLUTION($2) AS INT))) - + (@@RS_SCHEMA@@.__QUADBIN_TOZXY_X($1) >> (32 - CAST(@@RS_SCHEMA@@.QUADBIN_RESOLUTION($1) AS INT))) + ), + ABS( + (@@RS_SCHEMA@@.__QUADBIN_TOZXY_Y($2) >> (32 - CAST(@@RS_SCHEMA@@.QUADBIN_RESOLUTION($2) AS INT))) - + (@@RS_SCHEMA@@.__QUADBIN_TOZXY_Y($1) >> (32 - CAST(@@RS_SCHEMA@@.QUADBIN_RESOLUTION($1) AS INT))) + ) + ) + END + END +$$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/quadbin/QUADBIN_TOZXY.sql b/clouds/redshift/modules/sql/quadbin/QUADBIN_TOZXY.sql index 610162174..597086670 100644 --- a/clouds/redshift/modules/sql/quadbin/QUADBIN_TOZXY.sql +++ b/clouds/redshift/modules/sql/quadbin/QUADBIN_TOZXY.sql @@ -2,90 +2,6 @@ -- Copyright (C) 2022 CARTO ---------------------------- -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED5 -(BIGINT) --- (quadbin) -RETURNS BIGINT -STABLE -AS $$ - SELECT ($1 | ($1 >> 16)) & CAST(FROM_HEX('00000000FFFFFFFF') AS BIGINT) -$$ LANGUAGE sql; - -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED4 -(BIGINT) --- (quadbin) -RETURNS BIGINT -STABLE -AS $$ - SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED5( - ($1 | ($1 >> 8)) & CAST(FROM_HEX('0000FFFF0000FFFF') AS BIGINT) - ) -$$ LANGUAGE sql; - -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED3 -(BIGINT) --- (quadbin) -RETURNS BIGINT -STABLE -AS $$ - SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED4( - ($1 | ($1 >> 4)) & CAST(FROM_HEX('00FF00FF00FF00FF') AS BIGINT) - ) -$$ LANGUAGE sql; - -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED2 -(BIGINT) --- (quadbin) -RETURNS BIGINT -STABLE -AS $$ - SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED3( - ($1 | ($1 >> 2)) & CAST(FROM_HEX('0F0F0F0F0F0F0F0F') AS BIGINT) - ) -$$ LANGUAGE sql; - -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED1 -(BIGINT) --- (quadbin) -RETURNS BIGINT -STABLE -AS $$ - SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED2( - ($1 | ($1 >> 1)) & CAST(FROM_HEX('3333333333333333') AS BIGINT) - ) -$$ LANGUAGE sql; - -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_PREINTERLEAVED -(BIGINT) --- (quadbin) -RETURNS BIGINT -STABLE -AS $$ - SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED1( - $1 & CAST(FROM_HEX('5555555555555555') AS BIGINT) - ) -$$ LANGUAGE sql; - -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_X -(BIGINT) --- (quadbin) -RETURNS BIGINT -STABLE -AS $$ - SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_PREINTERLEAVED( - ($1 & CAST(FROM_HEX('00FFFFFFFFFFFFF') AS BIGINT)) << 12 - ) -$$ LANGUAGE sql; - -CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_Y -(BIGINT) --- (quadbin) -RETURNS BIGINT -STABLE -AS $$ - SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_X($1 >> 1) -$$ LANGUAGE sql; - CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.QUADBIN_TOZXY (BIGINT) -- (quadbin) diff --git a/clouds/redshift/modules/sql/quadbin/__QUADBIN_TOZXY_X.sql b/clouds/redshift/modules/sql/quadbin/__QUADBIN_TOZXY_X.sql new file mode 100644 index 000000000..fb9467ea8 --- /dev/null +++ b/clouds/redshift/modules/sql/quadbin/__QUADBIN_TOZXY_X.sql @@ -0,0 +1,78 @@ +---------------------------- +-- Copyright (C) 2022 CARTO +---------------------------- + +CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED5 +(BIGINT) +-- (quadbin) +RETURNS BIGINT +STABLE +AS $$ + SELECT ($1 | ($1 >> 16)) & CAST(FROM_HEX('00000000FFFFFFFF') AS BIGINT) +$$ LANGUAGE sql; + +CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED4 +(BIGINT) +-- (quadbin) +RETURNS BIGINT +STABLE +AS $$ + SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED5( + ($1 | ($1 >> 8)) & CAST(FROM_HEX('0000FFFF0000FFFF') AS BIGINT) + ) +$$ LANGUAGE sql; + +CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED3 +(BIGINT) +-- (quadbin) +RETURNS BIGINT +STABLE +AS $$ + SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED4( + ($1 | ($1 >> 4)) & CAST(FROM_HEX('00FF00FF00FF00FF') AS BIGINT) + ) +$$ LANGUAGE sql; + +CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED2 +(BIGINT) +-- (quadbin) +RETURNS BIGINT +STABLE +AS $$ + SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED3( + ($1 | ($1 >> 2)) & CAST(FROM_HEX('0F0F0F0F0F0F0F0F') AS BIGINT) + ) +$$ LANGUAGE sql; + +CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED1 +(BIGINT) +-- (quadbin) +RETURNS BIGINT +STABLE +AS $$ + SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED2( + ($1 | ($1 >> 1)) & CAST(FROM_HEX('3333333333333333') AS BIGINT) + ) +$$ LANGUAGE sql; + +CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_PREINTERLEAVED +(BIGINT) +-- (quadbin) +RETURNS BIGINT +STABLE +AS $$ + SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_INTERLEAVED1( + $1 & CAST(FROM_HEX('5555555555555555') AS BIGINT) + ) +$$ LANGUAGE sql; + +CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_X +(BIGINT) +-- (quadbin) +RETURNS BIGINT +STABLE +AS $$ + SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_XY_PREINTERLEAVED( + ($1 & CAST(FROM_HEX('00FFFFFFFFFFFFF') AS BIGINT)) << 12 + ) +$$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/quadbin/__QUADBIN_TOZXY_Y.sql b/clouds/redshift/modules/sql/quadbin/__QUADBIN_TOZXY_Y.sql new file mode 100644 index 000000000..1941fc51a --- /dev/null +++ b/clouds/redshift/modules/sql/quadbin/__QUADBIN_TOZXY_Y.sql @@ -0,0 +1,12 @@ +---------------------------- +-- Copyright (C) 2022 CARTO +---------------------------- + +CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__QUADBIN_TOZXY_Y +(BIGINT) +-- (quadbin) +RETURNS BIGINT +STABLE +AS $$ + SELECT @@RS_SCHEMA@@.__QUADBIN_TOZXY_X($1 >> 1) +$$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/transformations/ST_CENTERMEAN.sql b/clouds/redshift/modules/sql/transformations/ST_CENTERMEAN.sql index 9d3f8b244..616e5de68 100644 --- a/clouds/redshift/modules/sql/transformations/ST_CENTERMEAN.sql +++ b/clouds/redshift/modules/sql/transformations/ST_CENTERMEAN.sql @@ -31,6 +31,6 @@ RETURNS GEOMETRY STABLE AS $$ - SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__CENTERMEAN(ST_ASGEOJSON($1)::VARCHAR(MAX))) + SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__CENTERMEAN(ST_ASGEOJSON($1)::VARCHAR(MAX)), 4326) $$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/transformations/ST_CENTERMEDIAN.sql b/clouds/redshift/modules/sql/transformations/ST_CENTERMEDIAN.sql index 9cd10ed4c..a7994d475 100644 --- a/clouds/redshift/modules/sql/transformations/ST_CENTERMEDIAN.sql +++ b/clouds/redshift/modules/sql/transformations/ST_CENTERMEDIAN.sql @@ -29,5 +29,5 @@ CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_CENTERMEDIAN RETURNS GEOMETRY STABLE AS $$ - SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__CENTERMEDIAN(ST_ASGEOJSON($1)::VARCHAR(MAX), 100)) + SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__CENTERMEDIAN(ST_ASGEOJSON($1)::VARCHAR(MAX), 100), 4326) $$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/transformations/ST_CENTROID.sql b/clouds/redshift/modules/sql/transformations/ST_CENTROID.sql index 0b6fc0de1..ad4e9a6cf 100644 --- a/clouds/redshift/modules/sql/transformations/ST_CENTROID.sql +++ b/clouds/redshift/modules/sql/transformations/ST_CENTROID.sql @@ -30,5 +30,5 @@ CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_CENTROID RETURNS GEOMETRY STABLE AS $$ - SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__CENTROID(ST_ASGEOJSON($1)::VARCHAR(MAX))) + SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__CENTROID(ST_ASGEOJSON($1)::VARCHAR(MAX)), 4326) $$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/transformations/ST_DESTINATION.sql b/clouds/redshift/modules/sql/transformations/ST_DESTINATION.sql index 73dd95f47..0c4eb72b5 100644 --- a/clouds/redshift/modules/sql/transformations/ST_DESTINATION.sql +++ b/clouds/redshift/modules/sql/transformations/ST_DESTINATION.sql @@ -31,7 +31,7 @@ CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_DESTINATION RETURNS GEOMETRY STABLE AS $$ - SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__DESTINATION(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, 'kilometers')) + SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__DESTINATION(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, 'kilometers'), 4326) $$ LANGUAGE sql; @@ -41,5 +41,5 @@ CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_DESTINATION RETURNS GEOMETRY STABLE AS $$ - SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__DESTINATION(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4)) + SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__DESTINATION(ST_ASGEOJSON($1)::VARCHAR(MAX), $2, $3, $4), 4326) $$ LANGUAGE sql; diff --git a/clouds/redshift/modules/sql/transformations/ST_GREATCIRCLE.sql b/clouds/redshift/modules/sql/transformations/ST_GREATCIRCLE.sql index 3755d8ab7..973c7e389 100644 --- a/clouds/redshift/modules/sql/transformations/ST_GREATCIRCLE.sql +++ b/clouds/redshift/modules/sql/transformations/ST_GREATCIRCLE.sql @@ -35,7 +35,7 @@ CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_GREATCIRCLE RETURNS GEOMETRY STABLE AS $$ - SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__GREATCIRCLE(ST_ASGEOJSON($1)::VARCHAR(MAX), ST_ASGEOJSON($2)::VARCHAR(MAX), 100)) + SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__GREATCIRCLE(ST_ASGEOJSON($1)::VARCHAR(MAX), ST_ASGEOJSON($2)::VARCHAR(MAX), 100), 4326) $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_GREATCIRCLE @@ -44,5 +44,5 @@ CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.ST_GREATCIRCLE RETURNS GEOMETRY STABLE AS $$ - SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__GREATCIRCLE(ST_ASGEOJSON($1)::VARCHAR(MAX), ST_ASGEOJSON($2)::VARCHAR(MAX), $3)) + SELECT ST_GEOMFROMTEXT(@@RS_SCHEMA@@.__GREATCIRCLE(ST_ASGEOJSON($1)::VARCHAR(MAX), ST_ASGEOJSON($2)::VARCHAR(MAX), $3), 4326) $$ LANGUAGE sql; diff --git a/clouds/redshift/modules/test/constructors/fixtures/st_bezierspline_out.txt b/clouds/redshift/modules/test/constructors/fixtures/st_bezierspline_out.txt index 02f44c32f..0ff69e91b 100644 --- a/clouds/redshift/modules/test/constructors/fixtures/st_bezierspline_out.txt +++ b/clouds/redshift/modules/test/constructors/fixtures/st_bezierspline_out.txt @@ -1,2 +1,2 @@ -{"type": "LineString", "coordinates": [[121.025390625, -22.917922936146], [122.40878796386718, -22.04579264902263], [125.672291015625, -20.38080178786268], [129.4858663330078, -19.350050352981373], [132.704296875, -20.01569558887107], [135.25804138183594, -21.751132890668433], [137.26212890625, -24.05282839437401], [138.7404580078125, -26.51113113177312], [139.065328125, -29.074453813709233], [138.68492871093753, -31.163421738140773]]} +{"type":"LineString","coordinates":[[121.025390625,-22.917922936146],[122.408787963867,-22.0457926490226],[125.672291015625,-20.3808017878627],[129.485866333008,-19.3500503529814],[132.704296875,-20.0156955888711],[135.258041381836,-21.7511328906684],[137.26212890625,-24.052828394374],[138.740458007812,-26.5111311317731],[139.065328125,-29.0744538137092],[138.684928710938,-31.1634217381408]]} {"type": "LineString", "coordinates": [[-6.0, -0.5], [-3.664930555555555, 0.425925925925926], [-1.061111111111112, -0.240740740740741], [1.5, 0.0], [4.06111111111111, 0.240740740740741], [6.664930555555557, -0.425925925925926]]} \ No newline at end of file diff --git a/clouds/redshift/modules/test/constructors/fixtures/st_makeellipse_out.txt b/clouds/redshift/modules/test/constructors/fixtures/st_makeellipse_out.txt index 2bcc04e0d..d0583feba 100644 --- a/clouds/redshift/modules/test/constructors/fixtures/st_makeellipse_out.txt +++ b/clouds/redshift/modules/test/constructors/fixtures/st_makeellipse_out.txt @@ -1,3 +1,3 @@ -{"type": "Polygon", "coordinates": [[[-73.8552510279278, 40.69875990076168], [-73.88727305602106, 40.71386857048946], [-73.91829086593725, 40.71364680576012], [-73.9391348512039, 40.709634787504875], [-73.95412635366824, 40.70506682134275], [-73.96651925076043, 40.70017993435736], [-73.97829506044877, 40.69448398629664], [-73.99100359724105, 40.686922671018635], [-74.00599882433386, 40.675240797295416], [-74.02174378146566, 40.65498289773168], [-74.02048678071606, 40.626394109162135], [-73.98849608124772, 40.61127430054531], [-73.95750094517604, 40.6114966073818], [-73.93666467847032, 40.61551220163249], [-73.92167439274749, 40.620083780265865], [-73.9092795100774, 40.62497407601799], [-73.89749910603689, 40.63067343282612], [-73.88478237941126, 40.638238360505696], [-73.86977253117084, 40.64992381005887], [-73.85400385410401, 40.670182251386066], [-73.8552510279278, 40.69875990076168]]]} +{"type":"Polygon","coordinates":[[[-73.8552510279278,40.6987599007617],[-73.8872730560211,40.7138685704895],[-73.9182908659373,40.7136468057601],[-73.9391348512039,40.7096347875049],[-73.9541263536682,40.7050668213427],[-73.9665192507604,40.7001799343574],[-73.9782950604488,40.6944839862966],[-73.991003597241,40.6869226710186],[-74.0059988243339,40.6752407972954],[-74.0217437814657,40.6549828977317],[-74.0204867807161,40.6263941091621],[-73.9884960812477,40.6112743005453],[-73.957500945176,40.6114966073818],[-73.9366646784703,40.6155122016325],[-73.9216743927475,40.6200837802659],[-73.9092795100774,40.624974076018],[-73.8974991060369,40.6306734328261],[-73.8847823794113,40.6382383605057],[-73.8697725311708,40.6499238100589],[-73.854003854104,40.6701822513861],[-73.8552510279278,40.6987599007617]]]} {"type": "Polygon", "coordinates": [[[14.025651945102595, 0.643139887474501], [13.966322350235714, 0.676989374696651], [13.949057469288164, 0.682243693130648], [13.937791218833695, 0.685262266671341], [13.920212025893079, 0.689343743449833], [13.851904834790275, 0.689692135030598], [13.91123481846546, 0.655842669421623], [13.928499733699255, 0.650588334787248], [13.939765988224167, 0.647569750282519], [13.95734515890399, 0.643488257312855], [14.025651945102595, 0.643139887474501]]]} {"type": "Polygon", "coordinates": [[[53.926679820162576, -10.771199588624045], [53.97565947191276, -10.766527634873915], [54.014901920097486, -10.7408989284746], [54.03942438052616, -10.704804086251515], [54.05009893077397, -10.664428129854691], [54.04717127681056, -10.622218072052796], [54.02828566737185, -10.581418796142149], [53.99135946342335, -10.550695880491965], [53.942640575928976, -10.542261926784727], [53.897252008932924, -10.558730567354848], [53.8653117158799, -10.590720059776746], [53.847874755112, -10.629391395890822], [53.84385496291736, -10.670909005067212], [53.85433410007079, -10.713061260528669], [53.882284838651685, -10.750335109689678], [53.926679820162576, -10.771199588624045]]]} \ No newline at end of file diff --git a/clouds/redshift/modules/test/constructors/test_ST_BEZIERSPLINE.py b/clouds/redshift/modules/test/constructors/test_ST_BEZIERSPLINE.py index e62a4c453..cdbc6483f 100644 --- a/clouds/redshift/modules/test/constructors/test_ST_BEZIERSPLINE.py +++ b/clouds/redshift/modules/test/constructors/test_ST_BEZIERSPLINE.py @@ -12,10 +12,10 @@ def test_bezierspline_success(): results = run_query( f""" - SELECT @@RS_SCHEMA@@.ST_BEZIERSPLINE( - ST_GEOMFROMTEXT('{lines[0].rstrip()}'), 100, 0.85), - @@RS_SCHEMA@@.ST_BEZIERSPLINE( - ST_GEOMFROMTEXT('{lines[1].rstrip()}'), 60, 0.85) + SELECT ST_ASGEOJSON(@@RS_SCHEMA@@.ST_BEZIERSPLINE( + ST_GEOMFROMTEXT('{lines[0].rstrip()}'), 100, 0.85)), + ST_ASGEOJSON(@@RS_SCHEMA@@.ST_BEZIERSPLINE( + ST_GEOMFROMTEXT('{lines[1].rstrip()}'), 60, 0.85)) """ ) diff --git a/clouds/redshift/modules/test/constructors/test_ST_MAKEELLIPSE.py b/clouds/redshift/modules/test/constructors/test_ST_MAKEELLIPSE.py index ad57ec415..523c61a12 100644 --- a/clouds/redshift/modules/test/constructors/test_ST_MAKEELLIPSE.py +++ b/clouds/redshift/modules/test/constructors/test_ST_MAKEELLIPSE.py @@ -8,12 +8,12 @@ def test_makeellipse_success(): results = run_query( """ - SELECT @@RS_SCHEMA@@.ST_MAKEELLIPSE( - ST_POINT(-73.9385,40.6643), 5, 3, -30, 'miles', 20), - @@RS_SCHEMA@@.ST_MAKEELLIPSE( - ST_POINT(13.9385,0.6643), 10, 2, 15, 'kilometers', 10), - @@RS_SCHEMA@@.ST_MAKEELLIPSE( - ST_POINT(53.9385,-10.6643), 8, 7, 100, 'miles', 15) + SELECT ST_ASGEOJSON(@@RS_SCHEMA@@.ST_MAKEELLIPSE( + ST_POINT(-73.9385,40.6643), 5, 3, -30, 'miles', 20)), + ST_ASGEOJSON(@@RS_SCHEMA@@.ST_MAKEELLIPSE( + ST_POINT(13.9385,0.6643), 10, 2, 15, 'kilometers', 10)), + ST_ASGEOJSON(@@RS_SCHEMA@@.ST_MAKEELLIPSE( + ST_POINT(53.9385,-10.6643), 8, 7, 100, 'miles', 15)) """ ) diff --git a/clouds/redshift/modules/test/quadbin/test_QUADBIN_DISTANCE.py b/clouds/redshift/modules/test/quadbin/test_QUADBIN_DISTANCE.py new file mode 100644 index 000000000..ac06ab904 --- /dev/null +++ b/clouds/redshift/modules/test/quadbin/test_QUADBIN_DISTANCE.py @@ -0,0 +1,11 @@ +from test_utils import run_query + + +def test_quadbin_distance(): + result = run_query( + 'SELECT @@RS_SCHEMA@@.QUADBIN_DISTANCE' + '(5207251884775047167, 5207128739472736255)' + ) + + assert len(result[0]) == 1 + assert result[0][0] == 1 diff --git a/clouds/redshift/modules/test/quadbin/test_QUADBIN_FROMLONGLAT.py b/clouds/redshift/modules/test/quadbin/test_QUADBIN_FROMLONGLAT.py index 4b4719049..724ef228d 100644 --- a/clouds/redshift/modules/test/quadbin/test_QUADBIN_FROMLONGLAT.py +++ b/clouds/redshift/modules/test/quadbin/test_QUADBIN_FROMLONGLAT.py @@ -4,10 +4,28 @@ def test_quadbin_fromlonglat(): - result = run_query('SELECT @@RS_SCHEMA@@.QUADBIN_FROMLONGLAT(40.4168, -3.7038, 4)') - - assert len(result[0]) == 1 - assert result[0][0] == 5209574053332910079 + result = run_query( + """ + WITH inputs AS ( + SELECT 1 AS ID, @@RS_SCHEMA@@.QUADBIN_FROMLONGLAT(40.4168, -3.7038, 4) + UNION ALL SELECT 2, + @@RS_SCHEMA@@.QUADBIN_FROMLONGLAT(0, 85.05112877980659, 26) + UNION ALL SELECT 3, @@RS_SCHEMA@@.QUADBIN_FROMLONGLAT(0, 88, 26) + UNION ALL SELECT 4, @@RS_SCHEMA@@.QUADBIN_FROMLONGLAT(0, 90, 26) + UNION ALL SELECT 5, + @@RS_SCHEMA@@.QUADBIN_FROMLONGLAT(0, -85.05112877980659, 26) + UNION ALL SELECT 6, @@RS_SCHEMA@@.QUADBIN_FROMLONGLAT(0, -88, 26) + UNION ALL SELECT 7, @@RS_SCHEMA@@.QUADBIN_FROMLONGLAT(0, -90, 26) + ) + SELECT * FROM inputs ORDER BY id ASC""" + ) + assert result[0][1] == 5209574053332910079 + assert result[1][1] == 5306366260949286912 + assert result[2][1] == 5306366260949286912 + assert result[3][1] == 5306366260949286912 + assert result[4][1] == 5309368660700867242 + assert result[5][1] == 5309368660700867242 + assert result[6][1] == 5309368660700867242 def test_quadbin_fromlonglat_null(): diff --git a/clouds/redshift/version b/clouds/redshift/version index 6d7de6e6a..9084fa2f7 100644 --- a/clouds/redshift/version +++ b/clouds/redshift/version @@ -1 +1 @@ -1.0.2 +1.1.0 diff --git a/clouds/snowflake/CHANGELOG.md b/clouds/snowflake/CHANGELOG.md index 9751c3668..1b9e62c70 100644 --- a/clouds/snowflake/CHANGELOG.md +++ b/clouds/snowflake/CHANGELOG.md @@ -4,6 +4,15 @@ CARTO Analytics Toolbox Core for Snowflake. All notable commits to this project will be documented in this file. +## [1.2.0] - 2024-01-17 + +- feat(quadbin): add function QUADBIN_DISTANCE (#457) +- chore: fix naming dedicated deployments for releases (#462) +- fix(quadbin): QUADBIN_FROMLONGLAT not clamping latitudes and return some quadbin functions return NULL when NULL parameters (#456) +- chore: make remove drop functions instead of whole schema (#466) +- fix(quadbin): improve precision of long lat conversion near the latitude limits (#461) +- feat(transformations): add function ST_POINTONSURFACE (#470) + ## [1.1.0] - 2023-05-05 - feat(h3): add H3_CENTER function (#395) diff --git a/clouds/snowflake/Makefile b/clouds/snowflake/Makefile index b61dccc75..391bd6391 100644 --- a/clouds/snowflake/Makefile +++ b/clouds/snowflake/Makefile @@ -13,10 +13,10 @@ include $(COMMON_DIR)/Makefile .SILENT: -.PHONY: help lint build deploy test remove clean create-package +.PHONY: help lint build deploy test remove clean create-package deploy-native-app-package deploy-native-app help: - echo "Available targets: lint build deploy test remove clean create-package" + echo "Available targets: lint build deploy test remove clean create-package deploy-native-app-package deploy-native-app" lint: $(MAKE) lint-libraries @@ -54,6 +54,13 @@ build-modules: $(MAKE) -C modules build cp modules/build/modules.sql $(BUILD_DIR) +build-native-app-setup-script: + rm -rf $(BUILD_DIR) + $(MAKE) build-libraries + mkdir -p $(BUILD_DIR) + $(MAKE) -C modules build-native-app-setup-script + cp modules/build/setup_script.sql $(BUILD_DIR) + deploy: $(MAKE) build-libraries $(MAKE) deploy-modules @@ -102,3 +109,11 @@ create-package: echo '{"latest_version": "$(PACKAGE_VERSION)"}' > $(DIST_DIR)/metadata.json extra-package:: + +deploy-native-app-package: + $(MAKE) build-native-app-setup-script + $(MAKE) -C native_app build + $(MAKE) -C native_app deploy-app-package + +deploy-native-app: + $(MAKE) -C native_app deploy-app diff --git a/clouds/snowflake/README.md b/clouds/snowflake/README.md index 623c3fa00..d87854d61 100644 --- a/clouds/snowflake/README.md +++ b/clouds/snowflake/README.md @@ -38,6 +38,7 @@ SF_SHARE= # optional - `doc`: contains the functions' documentation - `sql`: contains the functions' SQL code - `test`: contains the functions' tests +- `native_app` ## Make commands @@ -49,12 +50,14 @@ SF_SHARE= # optional - `make remove`: removes the SQL scripts from the Snowflake database - `make clean`: cleans the installed dependencies and generated files locally - `make create-package`: creates the installation package in the dist folder (zip) +- `make deploy-native-app-package`: builds the JS libraries and SQL scripts and deploys a native app package. When the new version does not imply a major version change a patch is deployed. +- `make deploy-native-app`: deploys a native app from a deployed native app package or upgrade it if already exists. Make commands can be run also inside `libraries/javascript` and `modules` folders, or be called like `make lint-libraries`, `make deploy-modules`. **Filtering** -Commands `build-libraries`, `build-modules`, `deploy-modules`, `test-libraries`, `test-modules` and `create-package` can be filtered by the following. All the filters are additive: +Commands `build-libraries`, `build-modules`, `deploy-modules`, `test-libraries`, `test-modules`, `create-package` and `deploy-native-app-package` can be filtered by the following. All the filters are additive: - `diff`: list of changed files - `modules`: list of modules to filter @@ -68,6 +71,8 @@ make build-modules diff=modules/sql/quadbin/QUADBIN_RESOLUTION.sql make deploy-modules modules=quadbin,constructors make test-modules functions=ST_MAKEENVELOPE make create-package modules=quadbin +make deploy-native-app-package modules=quadbin +make deploy-native-app ``` Command `test-libraries` can be also filtered by setting the `test` variable with a path of the test file. It supports passing the name of the test. Note that `build-libraries` will rebuild the libraries to make them suitable for testing. diff --git a/clouds/snowflake/common/Makefile b/clouds/snowflake/common/Makefile index 1935c8dbe..5b1d5f00c 100644 --- a/clouds/snowflake/common/Makefile +++ b/clouds/snowflake/common/Makefile @@ -13,8 +13,10 @@ endif ifeq ($(production),1) export SF_SCHEMA = $(SF_DATABASE).$(SF_SCHEMA_DEFAULT) +export SF_UNQUALIFIED_SCHEMA = $(SF_SCHEMA_DEFAULT) else export SF_SCHEMA = $(SF_DATABASE).$(SF_PREFIX)$(SF_SCHEMA_DEFAULT) +export SF_UNQUALIFIED_SCHEMA = $(SF_PREFIX)$(SF_SCHEMA_DEFAULT) endif .PHONY: check venv3 $(NODE_MODULES_DEV) diff --git a/clouds/snowflake/common/build_native_app_setup_script.js b/clouds/snowflake/common/build_native_app_setup_script.js new file mode 100755 index 000000000..6db6f6f2f --- /dev/null +++ b/clouds/snowflake/common/build_native_app_setup_script.js @@ -0,0 +1,245 @@ +#!/usr/bin/env node + +// Build the setup_script for the native app file based on the input filters +// and ordered to solve the dependencies + +// ./build_native_app_setup_script.js modules --output=build --diff="clouds/snowflake/modules/sql/quadbin/QUADBIN_TOZXY.sql" +// ./build_native_app_setup_script.js modules --output=build --functions=ST_TILEENVELOPE +// ./build_native_app_setup_script.js modules --output=build --modules=quadbin +// ./build_native_app_setup_script.js modules --output=build --production --dropfirst + +const fs = require('fs'); +const path = require('path'); +const argv = require('minimist')(process.argv.slice(2)); + +const inputDirs = argv._[0] && argv._[0].split(','); +const outputDir = argv.output || 'build'; +const libsBuildDir = argv.libs_build_dir || '../libraries/javascript/build'; +const diff = argv.diff || []; +const nodeps = argv.nodeps; +let modulesFilter = (argv.modules && argv.modules.split(',')) || []; +let functionsFilter = (argv.functions && argv.functions.split(',')) || []; +let all = !(diff.length || modulesFilter.length || functionsFilter.length); + +if (all) { + console.log('- Build all'); +} else if (diff && diff.length) { + console.log(`- Build input diff: ${argv.diff}`); +} else if (modulesFilter && modulesFilter.length) { + console.log(`- Build input modules: ${argv.modules}`); +} else if (functionsFilter && functionsFilter.length) { + console.log(`- Build input functions: ${argv.functions}`); +} + +// Convert diff to modules +if (diff.length) { + const patternsAll = [ + /\.github\/workflows\/snowflake\.yml/, + /clouds\/snowflake\/common\/.+/, + /clouds\/snowflake\/libraries\/.+/, + /clouds\/snowflake\/.*Makefile/, + /clouds\/snowflake\/version/ + ]; + const patternModulesSql = /clouds\/snowflake\/modules\/sql\/([^\s]*?)\//g; + const patternModulesTest = /clouds\/snowflake\/modules\/test\/([^\s]*?)\//g; + const diffAll = patternsAll.some(p => diff.match(p)); + if (diffAll) { + console.log('-- all'); + all = diffAll; + } else { + const modulesSql = [...diff.matchAll(patternModulesSql)].map(m => m[1]); + const modulesTest = [...diff.matchAll(patternModulesTest)].map(m => m[1]); + const diffModulesFilter = [...new Set(modulesSql.concat(modulesTest))]; + if (diffModulesFilter) { + console.log(`-- modules: ${diffModulesFilter}`); + modulesFilter = diffModulesFilter; + } + } +} + +// Extract functions +const functions = []; +for (let inputDir of inputDirs) { + const sqldir = path.join(inputDir, 'sql'); + const modules = fs.readdirSync(sqldir); + modules.forEach(module => { + const moduledir = path.join(sqldir, module); + if (fs.statSync(moduledir).isDirectory()) { + const files = fs.readdirSync(moduledir); + files.forEach(file => { + if (file.endsWith('.sql')) { + const name = path.parse(file).name; + const content = fs.readFileSync(path.join(moduledir, file)).toString().replace(/--.*\n/g, ''); + functions.push({ + name, + module, + content, + dependencies: [] + }); + } + }); + } + }); +} + +// Check filters +modulesFilter.forEach(m => { + if (!functions.map(fn => fn.module).includes(m)) { + console.log(`ERROR: Module not found ${m}`); + process.exit(1); + } +}); +functionsFilter.forEach(f => { + if (!functions.map(fn => fn.name).includes(f)) { + console.log(`ERROR: Function not found ${f}`); + process.exit(1); + } +}); + +// Extract function dependencies +if (!nodeps) { + functions.forEach(mainFunction => { + functions.forEach(depFunction => { + if (mainFunction.name != depFunction.name) { + if (mainFunction.content.includes(`SCHEMA@@.${depFunction.name}(`)) { + mainFunction.dependencies.push(depFunction.name); + } + } + }); + }); +} + +// Check circular dependencies +if (!nodeps) { + functions.forEach(mainFunction => { + functions.forEach(depFunction => { + if (mainFunction.dependencies.includes(depFunction.name) && + depFunction.dependencies.includes(mainFunction.name)) { + console.log(`ERROR: Circular dependency between ${mainFunction.name} and ${depFunction.name}`); + process.exit(1); + } + }); + }); +} + +// Filter and order functions +const output = []; +function add (f, include) { + include = include || all || functionsFilter.includes(f.name) || modulesFilter.includes(f.module); + for (const dependency of f.dependencies) { + add(functions.find(f => f.name === dependency), include); + } + if (!output.map(f => f.name).includes(f.name) && include) { + output.push({ + name: f.name, + content: f.content + }); + } +} +functions.forEach(f => add(f)); + +// Replace environment variables +let separator; +if (argv.production) { + separator = '\n'; +} else { + separator = '\n-->\n'; // marker to future SQL split +} +let content = output.map(f => fetchPermissionsGrant(f.content)).join(separator); + +function apply_replacements (text) { + const libraries = [... new Set(text.match(new RegExp('@@SF_LIBRARY_.*@@', 'g')))]; + for (let library of libraries) { + const libraryName = library.replace('@@SF_LIBRARY_', '').replace('@@', '').toLowerCase() + '.js'; + const libraryPath = path.join(libsBuildDir, libraryName); + if (fs.existsSync(libraryPath)) { + const libraryContent = fs.readFileSync(libraryPath).toString(); + text = text.replace(new RegExp(library, 'g'), libraryContent); + } + else { + console.log(`Warning: library "${libraryName}" does not exist. Run "make build-libraries" with the same filters.`); + process.exit(1); + } + } + const replacements = process.env.REPLACEMENTS.split(' '); + for (let replacement of replacements) { + if (replacement) { + const pattern = new RegExp(`@@${replacement}@@`, 'g'); + text = text.replace(pattern, process.env[replacement]); + } + } + return text; +} + +function getFunctionSignatures (functionMatches) +{ + const functSignatures = [] + for (const functionMatch of functionMatches) { + //Remove spaces and diacritics + let qualifiedFunctName = functionMatch[0].split('(')[0].replace(/\s+/gm,''); + qualifiedFunctNameArr = qualifiedFunctName.split('.'); + const functName = qualifiedFunctNameArr[qualifiedFunctNameArr.length - 1]; + if (functName.startsWith('_')) + { + continue; + } + //Remove diacritics and go greedy to take the outer parentheses + let functArgs = functionMatch[0].matchAll(new RegExp('(?<=\\()(.*)(?=\\))','g')).next().value; + if (functArgs) + { + functArgs = functArgs[0]; + } + else + { + continue; + } + functArgs = functArgs.split(',') + let functArgsTypes = []; + for (const functArg of functArgs) { + const functArgSplitted = functArg.trim(' ').split(' '); + functArgsTypes.push(functArgSplitted[functArgSplitted.length - 1]); + } + const functSignature = qualifiedFunctName + '(' + functArgsTypes.join(',') + ')'; + functSignatures.push(functSignature) + } + return functSignatures +} + +function fetchPermissionsGrant (content) +{ + let fileContent = content.split('\n'); + for (let i = 0 ; i < fileContent.length; i++) + { + if (fileContent[i].startsWith('--')) + { + delete fileContent[i]; + } + } + fileContent = fileContent.join(' ').replace(/[\p{Diacritic}]/gu, '').replace(/\s+/gm,' '); + const functionMatches = fileContent.matchAll(new RegExp(/(?<=(? `GRANT USAGE ON FUNCTION ${f} TO APPLICATION ROLE @@APP_ROLE@@;`).join('\n') + const procMatches = fileContent.matchAll(new RegExp(/(?<=PROCEDURE)(.*?)(?=AS)/gs)); + const procSignatures = getFunctionSignatures(procMatches).map(f => `GRANT USAGE ON PROCEDURE ${f} TO APPLICATION ROLE @@APP_ROLE@@;`).join('\n') + return content + functSignatures +procSignatures +} + +if (argv.dropfirst) { + const header = fs.readFileSync(path.resolve(__dirname, 'DROP_FUNCTIONS.sql')).toString(); + content = header + separator + content +} + +const header = `CREATE OR REPLACE APPLICATION ROLE @@APP_ROLE@@; +CREATE OR ALTER VERSIONED SCHEMA @@SF_SCHEMA@@; +GRANT USAGE ON SCHEMA @@SF_SCHEMA@@ TO APPLICATION ROLE @@APP_ROLE@@;\n`; + +const footer = fetchPermissionsGrant (fs.readFileSync(path.resolve(__dirname, 'VERSION.sql')).toString()); +content = header + separator + content + separator + footer; + +content = apply_replacements(content); + +// Execute as caller replacement +content = content.replace(/EXECUTE\s+AS\s+CALLER/g, 'EXECUTE AS OWNER'); + +// Write setup_script.sql file +fs.writeFileSync(path.join(outputDir, 'setup_script.sql'), content); +console.log(`Write ${outputDir}/setup_script.sql`); \ No newline at end of file diff --git a/clouds/snowflake/common/native-app-utils.js b/clouds/snowflake/common/native-app-utils.js new file mode 100755 index 000000000..5fff5bbfb --- /dev/null +++ b/clouds/snowflake/common/native-app-utils.js @@ -0,0 +1,151 @@ +#!/usr/bin/env node + +// Perform operations related with the versioning of the native app + +// -- Set the app package release to the max patch of a given version. This is the version that will be used by default by customers. +// ./native-app-utils.js SET_PACKAGE_RELEASE=1 APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) VERSION=$(APP_MAJOR_VERSION) + +// -- Drop the previous version of the app package. This is done to avoid having more than two versions of the package. +// ./native-app-utils.js DROP_PREVIOUS_VERSION=1 APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) VERSION=$(APP_MAJOR_VERSION) + +// -- Check if a given version exists in the app package. This is checked in order to deploy a version or a patch +// ./native-app-utils.js CHECK_VERSION_EXISTENCE=1 APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) VERSION=$(APP_MAJOR_VERSION) + +// -- Count the number of versions in an app package. This is checked in order to drop a version if necessary +// ./native-app-utils.js COUNT_VERSIONS=1 APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) + +// -- Check if a given app package exists. This is checked in order to create a package or not +// ./native-app-utils.js CHECK_APP_PACKAGE_EXISTENCE=1 APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) + +// -- Check if a given app exists. This is checked in order to create an app or launch an upgrade +// ./native-app-utils.js CHECK_APP_EXISTENCE=1 APP_NAME=$(APP_NAME) + +const snowflake = require('snowflake-sdk'); + +snowflake.configure({ insecureConnect: true }); + +const connection = snowflake.createConnection({ + account: process.env.SF_ACCOUNT, + username: process.env.SF_USER, + password: process.env.SF_PASSWORD, + role: process.env.SF_ROLE +}); + +connection.connect((err) => { + if (err) { + console.error(`Unable to connect: ${err.message}`); + } +}); + +function runSetRelease (err, stmt, rows) { + // Get the patches for a given version + patchesArr = rows.filter(obj => obj['version'] === process.env.VERSION.toUpperCase()) + // Get the max patch number for a given version + maxPatch = patchesArr.reduce((maxObj, currentObj) => { + return currentObj['patch'] > maxObj['patch'] ? currentObj : maxObj; + }, patchesArr[0])['patch'] + const query = ` + ALTER APPLICATION PACKAGE ${process.env.APP_PACKAGE_NAME} + SET DEFAULT RELEASE DIRECTIVE + VERSION = ${process.env.VERSION} + PATCH = ${maxPatch};` + connection.execute({ + sqlText: query, + complete: (err, stmt, rows) => { + if (err) { + console.log(err.message); + } + } + }); +} + +function runDropPreviousVersionQuery (err, stmt, rows) { + // Get the patches different of a given version + patchesArr = rows.filter(obj => obj['version'] !== process.env.VERSION.toUpperCase()) + if (patchesArr.length > 0) { + // As there can only be two versions we take any patch + const previousVersion = patchesArr[0]['version'] + const query = ` + ALTER APPLICATION PACKAGE ${process.env.APP_PACKAGE_NAME} + DROP VERSION ${previousVersion};` + connection.execute({ + sqlText: query, + complete: (err, stmt, rows) => { + if (err) { + console.log(err.message); + } + } + }); + } +} + +function runCheckVersionExistenceQuery (err, stmt, rows) { + // Get the different patches for a given version + patchesArr = rows.filter(obj => obj['version'] === process.env.VERSION.toUpperCase()) + if (patchesArr.length > 0) { + console.log('1') + } else { + console.log('0') + } +} + +function runCountVersionsQuery (err, stmt, rows) { + uniqueVersions = new Set(rows.map(obj => obj['version'])) + console.log(uniqueVersions.size) +} + +function runGetVersionsQuery (callback) { + const query = `SHOW VERSIONS IN APPLICATION PACKAGE ${process.env.APP_PACKAGE_NAME};` + connection.execute({ + sqlText: query, + complete: callback + }); +} + +function runCheckAppPackageExistenceQuery (err, stmt, rows) { + packagesArr = rows.filter(obj => obj['name'] === process.env.APP_PACKAGE_NAME.toUpperCase()) + if (packagesArr.length > 0) { + console.log('1') + } else { + console.log('0') + } +} + +function runGetAppPackagesQuery (callback) { + const query = 'SHOW APPLICATION PACKAGES;' + connection.execute({ + sqlText: query, + complete: callback + }); +} + +function runCheckAppExistenceQuery (err, stmt, rows) { + packagesArr = rows.filter(obj => obj['name'] === process.env.APP_NAME.toUpperCase()) + if (packagesArr.length > 0) { + console.log('1') + } else { + console.log('0') + } +} + +function runGetAppsQuery (callback) { + const query = 'SHOW APPLICATIONS;' + connection.execute({ + sqlText: query, + complete: callback + }); +} + +if (process.env.SET_PACKAGE_RELEASE) { + runGetVersionsQuery(runSetRelease) +} else if (process.env.DROP_PREVIOUS_VERSION) { + runGetVersionsQuery (runDropPreviousVersionQuery) +} else if (process.env.CHECK_VERSION_EXISTENCE) { + runGetVersionsQuery (runCheckVersionExistenceQuery) +} else if (process.env.COUNT_VERSIONS) { + runGetVersionsQuery (runCountVersionsQuery) +} else if (process.env.CHECK_APP_PACKAGE_EXISTENCE) { + runGetAppPackagesQuery(runCheckAppPackageExistenceQuery) +} else if (process.env.CHECK_APP_EXISTENCE) { + runGetAppsQuery(runCheckAppExistenceQuery) +} \ No newline at end of file diff --git a/clouds/snowflake/common/package.json b/clouds/snowflake/common/package.json index d25a03ddb..f852c7570 100644 --- a/clouds/snowflake/common/package.json +++ b/clouds/snowflake/common/package.json @@ -11,6 +11,6 @@ "rollup": "^2.47.0", "rollup-plugin-bundle-size": "^1.0.3", "rollup-plugin-terser": "^7.0.2", - "snowflake-sdk": "^1.6.0" + "snowflake-sdk": "^1.6.6" } } diff --git a/clouds/snowflake/common/run-script.js b/clouds/snowflake/common/run-script.js index 0d04aa737..902808742 100755 --- a/clouds/snowflake/common/run-script.js +++ b/clouds/snowflake/common/run-script.js @@ -42,11 +42,24 @@ async function runQuery (query) { }); } +function apply_replacements (text) { + if (process.env.REPLACEMENTS) { + const replacements = process.env.REPLACEMENTS.split(' '); + for (let replacement of replacements) { + if (replacement) { + const pattern = new RegExp(`@@${replacement}@@`, 'g'); + text = text.replace(pattern, process.env[replacement]); + } + } + } + return text; +} + async function runQueries (queries) { const n = queries.length; bar.start(n, 0); for (let i = 0; i < n; i++) { - let query = `BEGIN\n${queries[i]}\nEND;`; + let query = apply_replacements (`BEGIN\n${queries[i]}\nEND;`); const pattern = /(FUNCTION|PROCEDURE)\s+(.*?)[(\n]/g; const results = pattern.exec(query); diff --git a/clouds/snowflake/libraries/javascript/libs/transformations_center.js b/clouds/snowflake/libraries/javascript/libs/transformations_center.js index 9a7af8487..df3cf6ecd 100644 --- a/clouds/snowflake/libraries/javascript/libs/transformations_center.js +++ b/clouds/snowflake/libraries/javascript/libs/transformations_center.js @@ -2,12 +2,14 @@ import { feature, centerMean, centerMedian, - centerOfMass + centerOfMass, + pointOnSurface } from '@turf/turf'; export default { feature, centerMean, centerMedian, - centerOfMass + centerOfMass, + pointOnSurface }; \ No newline at end of file diff --git a/clouds/snowflake/modules/Makefile b/clouds/snowflake/modules/Makefile index 02f2be59f..0ec3c5edb 100644 --- a/clouds/snowflake/modules/Makefile +++ b/clouds/snowflake/modules/Makefile @@ -25,13 +25,13 @@ else BAIL=--bail endif -REPLACEMENTS = "SF_SCHEMA SF_VERSION_FUNCTION SF_PACKAGE_VERSION SF_SHARE" +REPLACEMENTS = "SF_SCHEMA SF_VERSION_FUNCTION SF_PACKAGE_VERSION SF_SHARE APP_ROLE" include $(COMMON_DIR)/Makefile .SILENT: -.PHONY: help lint build build-share deploy deploy-share test remove remove-share clean +.PHONY: help lint build build-share build-native-app-setup-script deploy deploy-share test remove remove-share clean help: echo "Available targets: lint build deploy test remove clean" @@ -68,6 +68,16 @@ build-share: $(NODE_MODULES_DEV) --output=$(BUILD_DIR) --libs_build_dir=$(LIBS_BUILD_DIR) --diff="$(diff)" \ --modules=$(modules) --functions=$(functions) --production=$(production) --nodeps=$(nodeps) --dropfirst=$(dropfirst) +build-native-app-setup-script: $(NODE_MODULES_DEV) + echo "Building native app setup script..." + rm -rf $(BUILD_DIR) + mkdir $(BUILD_DIR) + SF_SCHEMA=$(SF_UNQUALIFIED_SCHEMA) APP_ROLE=app_public \ + REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ + $(COMMON_DIR)/build_native_app_setup_script.js $(MODULES_DIRS) \ + --output=$(BUILD_DIR) --libs_build_dir=$(LIBS_BUILD_DIR) --diff="$(diff)" \ + --modules=$(modules) --functions=$(functions) --production=$(production) --nodeps=$(nodeps) --dropfirst=1 + deploy: check build echo "Deploying modules..." $(COMMON_DIR)/run-query.js "CREATE SCHEMA IF NOT EXISTS $(SF_SCHEMA);" @@ -96,7 +106,8 @@ test: check $(NODE_MODULES_DEV) remove: $(NODE_MODULES_DEV) echo "Removing modules..." - $(COMMON_DIR)/run-query.js "DROP SCHEMA IF EXISTS $(SF_SCHEMA) CASCADE;" + REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ + $(COMMON_DIR)/run-script.js $(COMMON_DIR)/DROP_FUNCTIONS.sql remove-share: $(NODE_MODULES_DEV) echo "Removing share..." diff --git a/clouds/snowflake/modules/doc/quadbin/QUADBIN_DISTANCE.md b/clouds/snowflake/modules/doc/quadbin/QUADBIN_DISTANCE.md new file mode 100644 index 000000000..3e711d8cd --- /dev/null +++ b/clouds/snowflake/modules/doc/quadbin/QUADBIN_DISTANCE.md @@ -0,0 +1,23 @@ +## QUADBIN_DISTANCE + +```sql:signature +QUADBIN_DISTANCE(origin, destination) +``` + +**Description** + +Returns the [Chebyshev distance](https://en.wikipedia.org/wiki/Chebyshev_distance) between two quadbin indexes. The origin and destination indices must have the same resolution. Otherwise `NULL` will be returned. + +* `origin`: `BIGINT` origin quadbin index. +* `destination`: `BIGINT` destination quadbin index. + +**Return type** + +`BIGINT` + +**Example** + +```sql +SELECT carto.QUADBIN_DISTANCE(5207251884775047167, 5207128739472736255); +-- 1 +``` diff --git a/clouds/snowflake/modules/doc/transformations/ST_POINTONSURFACE.md b/clouds/snowflake/modules/doc/transformations/ST_POINTONSURFACE.md new file mode 100644 index 000000000..b27f53596 --- /dev/null +++ b/clouds/snowflake/modules/doc/transformations/ST_POINTONSURFACE.md @@ -0,0 +1,24 @@ +## ST_POINTONSURFACE + +```sql:signature +ST_POINTONSURFACE(geog) +``` + +**Description** + +Takes any Feature or a FeatureCollection and returns a point that is granted to be inside one of the polygons. + +* `geog`: `GEOGRAPHY` feature to be centered. + +**Return type** + +`GEOGRAPHY` + +**Example** + +```sql +SELECT carto.ST_POINTONSURFACE( + ST_GEOGFROMTEXT("POLYGON ((1.444057 38.791203 , 1.450457 38.793763 , 1.457178 38.792403 , 1.458298 38.781282 , 1.453418 38.778242 , 1.445977 38.780482 , 1.453498 38.781042 , 1.456218 38.786883 , 1.450617 38.790643 , 1.444057 38.791203))") +); +-- POINT(1.456218 38.786883) +``` diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_DISTANCE.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_DISTANCE.sql new file mode 100644 index 000000000..a7979336b --- /dev/null +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_DISTANCE.sql @@ -0,0 +1,33 @@ +---------------------------- +-- Copyright (C) 2023 CARTO +---------------------------- + +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._QUADBIN_DISTANCE +(origin STRING, destination STRING) +RETURNS STRING +LANGUAGE JAVASCRIPT +IMMUTABLE +AS $$ + if (!ORIGIN || !DESTINATION) { + return null; + } + + @@SF_LIBRARY_QUADBIN@@ + + origin_coords = quadbinLib.quadbinToTile(ORIGIN); + destination_coords = quadbinLib.quadbinToTile(DESTINATION); + + if (origin_coords.z != destination_coords.z) { + return null; + } + return Math.max(Math.abs(origin_coords.x - destination_coords.x), Math.abs(origin_coords.y - destination_coords.y)); +$$; + + +CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_DISTANCE +(origin BIGINT, destination BIGINT) +RETURNS BIGINT +IMMUTABLE +AS $$ + CAST(@@SF_SCHEMA@@._QUADBIN_DISTANCE(TO_VARCHAR(ORIGIN, 'xxxxxxxxxxxxxxxx'), TO_VARCHAR(DESTINATION, 'xxxxxxxxxxxxxxxx')) AS BIGINT) +$$; diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql index 0ee2eafcd..35b7bc677 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2024 CARTO +-------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_FROMLONGLAT (longitude FLOAT, latitude FLOAT, resolution INT) @@ -16,14 +16,13 @@ AS $$ SELECT resolution AS z, ACOS(-1) AS PI, - GREATEST(-85.05, LEAST(85.05, latitude)) AS latitude + GREATEST(-89, LEAST(89, latitude)) AS params_latitude ), __zxy AS ( SELECT z, - bitand( CAST(FLOOR(BITSHIFTLEFT(1, z) * ((longitude / 360.0) + 0.5)) AS INT), (BITSHIFTLEFT(1, z) - 1)) AS x, - bitand( CAST(FLOOR(BITSHIFTLEFT(1, z) * (0.5 - (LN(TAN(PI/4.0 + latitude/2.0 * PI/180.0)) / (2*PI)))) AS INT), - (BITSHIFTLEFT(1, z) - 1)) AS y + BITAND( CAST(FLOOR(BITSHIFTLEFT(1, z) * ((longitude / 360.0) + 0.5)) AS INT), (BITSHIFTLEFT(1, z) - 1)) AS x, + BITAND( CAST(FLOOR(GREATEST(0, LEAST(BITSHIFTLEFT(1, z) - 1, BITSHIFTLEFT(1, z) * (0.5 - (LN(TAN(PI/4.0 + params_latitude/2.0 * PI/180.0)) / (2*PI)))))) AS INT),(BITSHIFTLEFT(1, z) - 1)) AS y FROM __params ) SELECT @@SF_SCHEMA@@.QUADBIN_FROMZXY(z, x, y) diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMQUADKEY.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMQUADKEY.sql index d8991f85a..ac37f8e22 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMQUADKEY.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMQUADKEY.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2023 CARTO +-------------------------------- CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._QUADBIN_FROMQUADKEY (quadkey STRING) @@ -22,5 +22,8 @@ CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@.QUADBIN_FROMQUADKEY RETURNS BIGINT IMMUTABLE AS $$ - SELECT CAST(@@SF_SCHEMA@@._QUADBIN_FROMQUADKEY(QUADKEY) AS BIGINT) + IFF(quadkey IS NULL, + NULL, + CAST(@@SF_SCHEMA@@._QUADBIN_FROMQUADKEY(QUADKEY) AS BIGINT) + ) $$; diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMZXY.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMZXY.sql index 008e1c29b..6404b8895 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMZXY.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMZXY.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2023 CARTO +-------------------------------- CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._QUADBIN_FROMZXY (z DOUBLE, x DOUBLE, y DOUBLE) @@ -25,7 +25,10 @@ CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_FROMZXY RETURNS BIGINT IMMUTABLE AS $$ - @@SF_SCHEMA@@._QUADBIN_STRING_TOINT( - @@SF_SCHEMA@@._QUADBIN_FROMZXY(Z, X, Y) + IFF(z IS NULL OR x IS NULL OR y IS NULL, + NULL, + @@SF_SCHEMA@@._QUADBIN_STRING_TOINT( + @@SF_SCHEMA@@._QUADBIN_FROMZXY(Z, X, Y) + ) ) $$; diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_KRING.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_KRING.sql index 6e4819ad6..7c56caa8f 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_KRING.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_KRING.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2023 CARTO +-------------------------------- -- The function returns a STRING for two main issues related with Snowflake limitations -- 1. Snowflake has a native support of BigInt numbers, however, if the UDF @@ -14,5 +14,8 @@ CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_KRING RETURNS ARRAY IMMUTABLE AS $$ - TO_ARRAY(PARSE_JSON(@@SF_SCHEMA@@._QUADBIN_KRING(TO_VARCHAR(ORIGIN, 'xxxxxxxxxxxxxxxx'), SIZE, false))) + IFF(origin IS NULL OR size IS NULL, + NULL, + TO_ARRAY(PARSE_JSON(@@SF_SCHEMA@@._QUADBIN_KRING(TO_VARCHAR(ORIGIN, 'xxxxxxxxxxxxxxxx'), SIZE, false))) + ) $$; diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_KRING_DISTANCES.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_KRING_DISTANCES.sql index e75e7f9eb..80ec7e764 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_KRING_DISTANCES.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_KRING_DISTANCES.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2023 CARTO +-------------------------------- -- The function returns a STRING for two main issues related with Snowflake limitations -- 1. Snowflake has a native support of BigInt numbers, however, if the UDF @@ -14,5 +14,8 @@ CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_KRING_DISTANCES RETURNS ARRAY IMMUTABLE AS $$ - TO_ARRAY(PARSE_JSON(@@SF_SCHEMA@@._QUADBIN_KRING(TO_VARCHAR(ORIGIN, 'xxxxxxxxxxxxxxxx'), SIZE, true))) + IFF(origin IS NULL OR size IS NULL, + NULL, + TO_ARRAY(PARSE_JSON(@@SF_SCHEMA@@._QUADBIN_KRING(TO_VARCHAR(ORIGIN, 'xxxxxxxxxxxxxxxx'), SIZE, true))) + ) $$; diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_SIBLING.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_SIBLING.sql index c79ec79fd..877711c64 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_SIBLING.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_SIBLING.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2023 CARTO +-------------------------------- -- FIXME: slow @@ -9,16 +9,19 @@ CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_SIBLING RETURNS INT IMMUTABLE AS $$ - CASE direction - WHEN 'left' THEN - @@SF_SCHEMA@@._QUADBIN_SIBLING(quadbin, -1, 0) - WHEN 'right' THEN - @@SF_SCHEMA@@._QUADBIN_SIBLING(quadbin, 1, 0) - WHEN 'up' THEN - @@SF_SCHEMA@@._QUADBIN_SIBLING(quadbin, 0, -1) - WHEN 'down' THEN - @@SF_SCHEMA@@._QUADBIN_SIBLING(quadbin, 0, 1) - ELSE - NULL - END + IFF(quadbin IS NULL OR direction IS NULL, + NULL, + CASE direction + WHEN 'left' THEN + @@SF_SCHEMA@@._QUADBIN_SIBLING(quadbin, -1, 0) + WHEN 'right' THEN + @@SF_SCHEMA@@._QUADBIN_SIBLING(quadbin, 1, 0) + WHEN 'up' THEN + @@SF_SCHEMA@@._QUADBIN_SIBLING(quadbin, 0, -1) + WHEN 'down' THEN + @@SF_SCHEMA@@._QUADBIN_SIBLING(quadbin, 0, 1) + ELSE + NULL + END + ) $$; diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql index 322e1ef33..d75a9b600 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql @@ -1,25 +1,30 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2023 CARTO +-------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_TOPARENT (quadbin BIGINT, resolution INT) RETURNS BIGINT IMMUTABLE AS $$ - SELECT bitor( - bitor( - bitand( - quadbin, - bitnot( - bitshiftleft(31, 52) - ) + IFF(quadbin IS NULL OR resolution IS NULL OR resolution < 0 OR resolution > 26, + NULL, + ( + SELECT bitor( + bitor( + bitand( + quadbin, + bitnot( + bitshiftleft(31, 52) + ) + ), + bitshiftleft(resolution, 52) ), - bitshiftleft(resolution, 52) - ), - bitshiftright( - 4503599627370495, - resolution * 2 + bitshiftright( + 4503599627370495, + resolution * 2 + ) ) - ) + ) + ) $$; diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOQUADKEY.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOQUADKEY.sql index d418ae0d4..af62d8a6f 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOQUADKEY.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOQUADKEY.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2023 CARTO +-------------------------------- CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._QUADBIN_TOQUADKEY (quadbin STRING) @@ -20,5 +20,8 @@ CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@.QUADBIN_TOQUADKEY RETURNS STRING IMMUTABLE AS $$ - SELECT @@SF_SCHEMA@@._QUADBIN_TOQUADKEY(CAST(QUADBIN AS STRING)) + IFF(quadbin IS NULL, + NULL, + @@SF_SCHEMA@@._QUADBIN_TOQUADKEY(CAST(QUADBIN AS STRING)) + ) $$; diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOZXY.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOZXY.sql index 6b7d0462c..d46b2e6c1 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOZXY.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOZXY.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2022 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2022-2023 CARTO +-------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_TOZXY @@ -8,5 +8,8 @@ CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_TOZXY RETURNS OBJECT IMMUTABLE AS $$ - @@SF_SCHEMA@@._QUADBIN_TOZXY(TO_VARCHAR(QUADBIN, 'xxxxxxxxxxxxxxxx')) + IFF(quadbin IS NULL, + NULL, + @@SF_SCHEMA@@._QUADBIN_TOZXY(TO_VARCHAR(QUADBIN, 'xxxxxxxxxxxxxxxx')) + ) $$; diff --git a/clouds/snowflake/modules/sql/transformations/ST_POINTONSURFACE.sql b/clouds/snowflake/modules/sql/transformations/ST_POINTONSURFACE.sql new file mode 100644 index 000000000..237dbb71f --- /dev/null +++ b/clouds/snowflake/modules/sql/transformations/ST_POINTONSURFACE.sql @@ -0,0 +1,27 @@ +---------------------------- +-- Copyright (C) 2024 CARTO +---------------------------- + +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._POINTONSURFACE +(geojson STRING) +RETURNS STRING +LANGUAGE JAVASCRIPT +IMMUTABLE +AS $$ + if (!GEOJSON) { + return null; + } + + @@SF_LIBRARY_TRANSFORMATIONS_CENTER@@ + + const center = transformationsCenterLib.pointOnSurface(JSON.parse(GEOJSON)); + return JSON.stringify(center.geometry); +$$; + +CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.ST_POINTONSURFACE +(geog GEOGRAPHY) +RETURNS GEOGRAPHY +IMMUTABLE +AS $$ + TO_GEOGRAPHY(@@SF_SCHEMA@@._POINTONSURFACE(CAST(ST_ASGEOJSON(GEOG) AS STRING))) +$$; diff --git a/clouds/snowflake/modules/test/constructors/ST_TILEENVELOPE.test.js b/clouds/snowflake/modules/test/constructors/ST_TILEENVELOPE.test.js index 6b37e520c..1b48fea56 100644 --- a/clouds/snowflake/modules/test/constructors/ST_TILEENVELOPE.test.js +++ b/clouds/snowflake/modules/test/constructors/ST_TILEENVELOPE.test.js @@ -13,9 +13,11 @@ test('ST_TILEENVELOPE should work', async () => { expect(JSON.stringify(rows[0].GEOG3)).toEqual('{"coordinates":[[[-44.99998927116395,45.000002199069606],[-44.99998927116395,44.99999461263666],[-45,44.99999461263666],[-45,45.000002199069606],[-44.99998927116395,45.000002199069606]]],"type":"Polygon"}'); }); -test('ST_TILEENVELOPE should fail if any NULL argument', async () => { +test('ST_TILEENVELOPE should return NULL if any NULL argument', async () => { const query = ` - SELECT ST_TILEENVELOPE(10, 384, null) + SELECT ST_TILEENVELOPE(10, 384, null) as geog `; - await expect(runQuery(query)).rejects.toThrow(); + const rows = await runQuery(query); + expect(rows.length).toEqual(1); + expect(rows[0].GEOG).toEqual(null); }); \ No newline at end of file diff --git a/clouds/snowflake/modules/test/quadbin/QUADBIN_DISTANCE.test.js b/clouds/snowflake/modules/test/quadbin/QUADBIN_DISTANCE.test.js new file mode 100644 index 000000000..ff80129ad --- /dev/null +++ b/clouds/snowflake/modules/test/quadbin/QUADBIN_DISTANCE.test.js @@ -0,0 +1,8 @@ +const { runQuery } = require('../../../common/test-utils'); + +test('QUADBIN_DISTANCE should work', async () => { + const query = 'SELECT QUADBIN_DISTANCE(5207251884775047167, 5207128739472736255) AS OUTPUT'; + const rows = await runQuery(query); + expect(rows.length).toEqual(1); + expect(rows[0].OUTPUT).toEqual(1); +}); \ No newline at end of file diff --git a/clouds/snowflake/modules/test/quadbin/QUADBIN_FROMLONGLAT.test.js b/clouds/snowflake/modules/test/quadbin/QUADBIN_FROMLONGLAT.test.js index af6e22e61..870bca686 100644 --- a/clouds/snowflake/modules/test/quadbin/QUADBIN_FROMLONGLAT.test.js +++ b/clouds/snowflake/modules/test/quadbin/QUADBIN_FROMLONGLAT.test.js @@ -1,8 +1,24 @@ const { runQuery } = require('../../../common/test-utils'); test('QUADBIN_FROMLONGLAT should work', async () => { - const query = 'SELECT CAST(QUADBIN_FROMLONGLAT(40.4168, -3.7038, 4) AS STRING) AS OUTPUT'; + const query = ` + WITH inputs AS ( + SELECT 1 AS ID, CAST(QUADBIN_FROMLONGLAT(40.4168, -3.7038, 4) AS STRING) AS OUTPUT + UNION ALL SELECT 2, CAST(QUADBIN_FROMLONGLAT(0, 85.05112877980659, 26) AS STRING) + UNION ALL SELECT 3, CAST(QUADBIN_FROMLONGLAT(0, 88, 26) AS STRING) + UNION ALL SELECT 4, CAST(QUADBIN_FROMLONGLAT(0, 90, 26) AS STRING) + UNION ALL SELECT 5, CAST(QUADBIN_FROMLONGLAT(0, -85.05112877980659, 26) AS STRING) + UNION ALL SELECT 6, CAST(QUADBIN_FROMLONGLAT(0, -88, 26) AS STRING) + UNION ALL SELECT 7, CAST(QUADBIN_FROMLONGLAT(0, -90, 26) AS STRING) + ) + SELECT * FROM inputs ORDER BY id ASC`; const rows = await runQuery(query); - expect(rows.length).toEqual(1); + expect(rows.length).toEqual(7); expect(rows[0].OUTPUT).toEqual('5209574053332910079'); + expect(rows[1].OUTPUT).toEqual('5306366260949286912'); + expect(rows[2].OUTPUT).toEqual('5306366260949286912'); + expect(rows[3].OUTPUT).toEqual('5306366260949286912'); + expect(rows[4].OUTPUT).toEqual('5309368660700867242'); + expect(rows[5].OUTPUT).toEqual('5309368660700867242'); + expect(rows[6].OUTPUT).toEqual('5309368660700867242'); }); \ No newline at end of file diff --git a/clouds/snowflake/modules/test/transformations/ST_POINTONSURFACE.test.js b/clouds/snowflake/modules/test/transformations/ST_POINTONSURFACE.test.js new file mode 100644 index 000000000..e3f707da0 --- /dev/null +++ b/clouds/snowflake/modules/test/transformations/ST_POINTONSURFACE.test.js @@ -0,0 +1,17 @@ +const { runQuery } = require('../../../common/test-utils'); + +test('ST_POINTONSURFACE should work', async () => { + const query = `SELECT ST_POINTONSURFACE(TO_GEOGRAPHY('MULTIPOLYGON ( (( 1.432239 38.774949 , 1.430004 38.776613 , 1.429594 38.779004 , 1.429017 38.780159 , 1.427593 38.781527 , 1.425098 38.782440 , 1.423667 38.782105 , 1.423500 38.780778 , 1.421648 38.780213 , 1.420044 38.778803 , 1.419783 38.779692 , 1.419998 38.780884 , 1.418469 38.782359 , 1.417274 38.784848 , 1.417280 38.785641 , 1.418790 38.786572 , 1.419115 38.787496 , 1.420219 38.788078 , 1.422245 38.790701 , 1.422430 38.792226 , 1.421102 38.794001 , 1.419421 38.794483 , 1.419112 38.794921 , 1.420578 38.795797 , 1.421985 38.797293 , 1.424319 38.796379 , 1.425594 38.795468 , 1.424784 38.794619 , 1.424858 38.793340 , 1.426658 38.791067 , 1.428010 38.789823 , 1.428901 38.787502 , 1.429748 38.786711 , 1.430096 38.785544 , 1.430951 38.785375 , 1.431356 38.784263 , 1.431377 38.781200 , 1.431665 38.780104 , 1.431531 38.778868 , 1.432695 38.777271 , 1.432404 38.776888 , 1.433254 38.775386 , 1.432239 38.774949)), (( 1.479401 38.788441 , 1.477737 38.789852 , 1.477167 38.791727 , 1.476344 38.792537 , 1.475231 38.795045 , 1.474967 38.796087 , 1.474324 38.796538 , 1.474129 38.799221 , 1.475761 38.800972 , 1.477059 38.804368 , 1.477770 38.805054 , 1.478568 38.804866 , 1.477156 38.801982 , 1.477438 38.800634 , 1.479283 38.799423 , 1.481316 38.799135 , 1.481027 38.798076 , 1.479663 38.797248 , 1.478855 38.796246 , 1.478892 38.794525 , 1.479432 38.794064 , 1.479328 38.791900 , 1.479850 38.789546 , 1.479401 38.788441)))')) as pointOnSurface1, + ST_POINTONSURFACE(TO_GEOGRAPHY('POLYGON ((1.444057 38.791203 , 1.450457 38.793763 , 1.457178 38.792403 , 1.458298 38.781282 , 1.453418 38.778242 , 1.445977 38.780482 , 1.453498 38.781042 , 1.456218 38.786883 , 1.450617 38.790643 , 1.444057 38.791203))')) as pointOnSurface2`; + const rows = await runQuery(query); + expect(rows.length).toEqual(1); + expect(JSON.stringify(rows[0].POINTONSURFACE1)).toEqual('{"coordinates":[1.430951,38.785375],"type":"Point"}'); + expect(JSON.stringify(rows[0].POINTONSURFACE2)).toEqual('{"coordinates":[1.456218,38.786883],"type":"Point"}'); +}); + +test('ST_POINTONSURFACE should return NULL if any NULL mandatory argument', async () => { + const query = 'SELECT ST_POINTONSURFACE(NULL) as pointOnSurface1'; + const rows = await runQuery(query); + expect(rows.length).toEqual(1); + expect(rows[0].POINTONSURFACE1).toEqual(null); +}); \ No newline at end of file diff --git a/clouds/snowflake/native_app/Makefile b/clouds/snowflake/native_app/Makefile new file mode 100644 index 000000000..beab7de0f --- /dev/null +++ b/clouds/snowflake/native_app/Makefile @@ -0,0 +1,101 @@ +# Makefile native app for Snowflake + +ROOT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) + +DIST_DIR ?= $(ROOT_DIR)/../dist +ENV_DIR ?= $(ROOT_DIR)/.. +BUILD_DIR ?= $(ROOT_DIR)/../build +COMMON_DIR = $(ROOT_DIR)/../common +APP_DIR ?= $(ROOT_DIR) + +include $(COMMON_DIR)/Makefile + +APP_NAME ?= APP_$(SF_UNQUALIFIED_SCHEMA) +APP_PACKAGE_NAME ?= APP_PACKAGE_$(SF_UNQUALIFIED_SCHEMA) +APP_PACKAGE_DIST_NAME ?= carto-analytics-toolbox-core-snowflake-native-app-$(APP_VERSION) +APP_VERSION ?= $(shell cat $(ROOT_DIR)/../version) +APP_MAJOR_VERSION = v$(firstword $(subst ., ,$(APP_VERSION))) +APP_FORMATTED_VERSION = v$(subst .,_,$(APP_VERSION)) + +APP_STAGE_NAME ?= $(SF_SCHEMA).$(APP_NAME) +ifeq ($(production),1) + APP_STAGE_LOCATION ?= $(APP_STAGE_NAME)/$(APP_FORMATTED_VERSION) +else + APP_STAGE_LOCATION ?= $(APP_STAGE_NAME) +endif + +.SILENT: + +.PHONY: help build deploy-app-package deploy-app drop-app-package drop-app + +help: + echo "Available targets: help build deploy-app-package deploy-app drop-app-package drop-app" + +build: + rm -rf $(DIST_DIR) + mkdir -p $(DIST_DIR)/$(APP_PACKAGE_DIST_NAME) + cp $(BUILD_DIR)/setup_script.sql $(DIST_DIR)/$(APP_PACKAGE_DIST_NAME)/ + sed 's/@@VERSION@@/$(APP_VERSION)/g' $(APP_DIR)/manifest.yml > $(DIST_DIR)/$(APP_PACKAGE_DIST_NAME)/manifest.yml + cp $(APP_DIR)/README.md $(DIST_DIR)/$(APP_PACKAGE_DIST_NAME)/ + + +deploy-app-package: + $(COMMON_DIR)/run-query.js "CREATE STAGE IF NOT EXISTS $(APP_STAGE_NAME);" + $(COMMON_DIR)/run-query.js "PUT file://$(DIST_DIR)/$(APP_PACKAGE_DIST_NAME)/* @$(APP_STAGE_LOCATION) overwrite=true auto_compress=false;" + + result=$$(CHECK_APP_PACKAGE_EXISTENCE=1 APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) $(COMMON_DIR)/native-app-utils.js) && \ + if [ $${result} -eq 0 ]; then \ + echo "Creating native app package..."; \ + $(COMMON_DIR)/run-query.js "CREATE APPLICATION PACKAGE $(APP_PACKAGE_NAME);"; \ + fi + + result=$$(CHECK_VERSION_EXISTENCE=1 APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) VERSION=$(APP_MAJOR_VERSION) $(COMMON_DIR)/native-app-utils.js) && \ + if [ $${result} -eq 1 ]; then \ + echo "Deploying native app package patch..."; \ + $(COMMON_DIR)/run-query.js "ALTER APPLICATION PACKAGE $(APP_PACKAGE_NAME) \ + ADD PATCH FOR VERSION $(APP_MAJOR_VERSION) \ + USING @$(APP_STAGE_LOCATION);"; \ + else \ + echo "Deploying native app package version..."; \ + $(COMMON_DIR)/run-query.js "ALTER APPLICATION PACKAGE $(APP_PACKAGE_NAME) \ + ADD VERSION $(APP_MAJOR_VERSION) \ + USING @$(APP_STAGE_LOCATION);"; \ + fi + + echo "Setting release package to the newest patch..." + SET_PACKAGE_RELEASE=1 \ + APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) \ + VERSION=$(APP_MAJOR_VERSION) \ + $(COMMON_DIR)/native-app-utils.js + +# This ensures that there are no more than 2 versions which is a Snowflake limitations + result=$$(COUNT_VERSIONS=1 APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) $(COMMON_DIR)/native-app-utils.js) && \ + if [ $${result} -eq 2 ]; then \ + echo "Requesting previous native app package version drop..."; \ + DROP_PREVIOUS_VERSION=1 \ + APP_PACKAGE_NAME=$(APP_PACKAGE_NAME) \ + VERSION=$(APP_MAJOR_VERSION) \ + $(COMMON_DIR)/native-app-utils.js; \ + fi + +drop-app-package: + echo "Dropping native app package..." + $(COMMON_DIR)/run-query.js "DROP APPLICATION PACKAGE IF EXISTS $(APP_PACKAGE_NAME);" + +deploy-app: + result=$$(CHECK_APP_EXISTENCE=1 APP_NAME=$(APP_NAME) $(COMMON_DIR)/native-app-utils.js) && \ + if [ $${result} -eq 0 ]; then \ + echo "Installing native app... (this may take a while)"; \ + $(COMMON_DIR)/run-query.js "CREATE APPLICATION $(APP_NAME) \ + FROM APPLICATION PACKAGE $(APP_PACKAGE_NAME);"; \ + $(MAKE) extra-app-deploy; \ + else \ + echo "Upgrading native app... (this may take a while)"; \ + $(COMMON_DIR)/run-query.js "ALTER APPLICATION $(APP_NAME) UPGRADE;"; \ + fi + +extra-app-deploy:: + +drop-app: + echo "Dropping native app..." + $(COMMON_DIR)/run-query.js "DROP APPLICATION IF EXISTS $(APP_NAME);" \ No newline at end of file diff --git a/clouds/snowflake/native_app/README.md b/clouds/snowflake/native_app/README.md new file mode 100644 index 000000000..dedecaecf --- /dev/null +++ b/clouds/snowflake/native_app/README.md @@ -0,0 +1,47 @@ +## ANALYTICS TOOLBOX CORE + +### Introduction + +The CARTO Analytics Toolbox for Snowflake is composed of a set of user-defined functions and procedures organized in a set of modules based on the functionality they offer. This app gives you access to the Open Source modules included in the CARTO's Analytics Toolbox, supporting different spatial indexes and other geospatial operations: quadkeys, H3, S2, placekey, geometry constructors, accessors, transformations, etc. + +We recommend that at the moment of installing the app you name the app "CARTO". The next guidelines and examples will assume that in order to simplify the onboarding process. + +### Installation + +#### Grant Usage + +This step is required by procedures that have input tables/queries or output tables. The user will have to manually provide permissions to access the tables of a given database. Providing ALL permissions on an SCHEMA ensures that the app can write new tables in that schema. + +On the other hand, those tables generated by a procedure belong to the app itself. If the user wants to recover control over those tables (performing SELECT, UPDATE, DELETE...), updating the ownership on those tables is required. + +``` +-- Set read and write permissions +GRANT USAGE ON DATABASE TO APPLICATION CARTO; +GRANT ALL ON SCHEMA . TO APPLICATION CARTO; +GRANT SELECT ON TABLE IN SCHEMA ..
TO APPLICATION CARTO; + +-- Update ownership (when a table is created within the app) +GRANT OWNERSHIP ON TABLE .. TO ROLE ACCOUNTADMIN; +``` + +### Usage Examples + +Please refer to CARTO's [SQL reference](https://docs.carto.com/data-and-analysis/analytics-toolbox-for-snowflake/sql-reference) to find the full list of available functions and procedures as well as examples. + +#### H3_POLYFILL + +Returns an array with all the H3 cell indexes **with centers** contained in a given polygon. + +``` +SELECT carto.H3_POLYFILL( + TO_GEOGRAPHY('POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))'), 4); +-- 842da29ffffffff +-- 843f725ffffffff +-- 843eac1ffffffff +-- 8453945ffffffff +-- ... +``` + +Learn how to visualize the result of these queries in CARTO by visiting [https://docs.carto.com/carto-user-manual/maps/data-sources#add-source-from-a-custom-query](https://docs.carto.com/carto-user-manual/maps/data-sources#add-source-from-a-custom-query). + +Get a CARTO account in [https://app.carto.com/signup](https://app.carto.com/signup). \ No newline at end of file diff --git a/clouds/snowflake/native_app/manifest.yml b/clouds/snowflake/native_app/manifest.yml new file mode 100644 index 000000000..9b8163b12 --- /dev/null +++ b/clouds/snowflake/native_app/manifest.yml @@ -0,0 +1,10 @@ +manifest_version: 1 # required +version: + name: @@VERSION@@ + label: "@@VERSION@@" + comment: "Analytics Toolbox Core" + +artifacts: + readme: README.md + setup_script: setup_script.sql + extension_code: true diff --git a/clouds/snowflake/version b/clouds/snowflake/version index 9084fa2f7..26aaba0e8 100644 --- a/clouds/snowflake/version +++ b/clouds/snowflake/version @@ -1 +1 @@ -1.1.0 +1.2.0 From 3f7804b7e7c75bc502333447136c1f312861379a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Fri, 16 Feb 2024 11:39:01 +0100 Subject: [PATCH 04/13] release: 2024-02-15 (#481) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Javier Goizueta Co-authored-by: Alberto Hernández Co-authored-by: Valentin de la Cruz Barquero <6054336+vdelacruzb@users.noreply.github.com> Co-authored-by: Pedro-Juan Ferrer Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: vdelacruzb --- .github/workflows/snowflake-ded.yml | 2 +- .github/workflows/snowflake.yml | 2 +- CHANGELOG.md | 8 ++ .../doc/constructors/ST_MAKEELLIPSE.md | 2 +- .../doc/transformations/ST_DESTINATION.md | 2 +- .../doc/constructors/ST_MAKEELLIPSE.md | 2 +- .../doc/transformations/ST_DESTINATION.md | 2 +- clouds/snowflake/CHANGELOG.md | 6 + .../common/build_native_app_setup_script.js | 8 +- clouds/snowflake/common/test-utils.js | 8 ++ .../libraries/javascript/libs/random.js | 7 +- .../libraries/javascript/src/random.js | 12 ++ .../libraries/javascript/test/random.test.js | 2 +- clouds/snowflake/modules/Makefile | 3 +- .../doc/constructors/ST_MAKEELLIPSE.md | 2 +- .../doc/transformations/ST_DESTINATION.md | 2 +- .../sql/quadbin/QUADBIN_RESOLUTION.sql | 2 +- .../modules/sql/quadbin/QUADBIN_TOPARENT.sql | 28 ++-- .../modules/sql/random/ST_GENERATEPOINTS.sql | 68 +++------- .../modules/sql/random/_BBOX_FROM_GEOJSON.sql | 14 -- .../test/processing/ST_DELAUNAYLINES.test.js | 2 +- .../processing/ST_DELAUNAYPOLYGONS.test.js | 2 +- .../test/processing/ST_POLYGONIZE.test.js | 2 +- .../test/processing/ST_VORONOILINES.test.js | 2 +- .../processing/ST_VORONOIPOLYGONS.test.js | 2 +- .../test/quadbin/QUADBIN_TOPARENT.test.js | 18 ++- .../test/quadbin/fixtures/coords_sample.sql | 120 ++++++++++++++++++ .../modules/test/quadbin/global/setup.js | 12 ++ .../modules/test/quadbin/global/teardown.js | 9 ++ .../test/random/ST_GENERATEPOINTS.test.js | 13 +- .../native_app/ADDITIONAL_TABLES.sql | 0 clouds/snowflake/version | 2 +- 32 files changed, 265 insertions(+), 101 deletions(-) create mode 100644 clouds/snowflake/libraries/javascript/src/random.js delete mode 100644 clouds/snowflake/modules/sql/random/_BBOX_FROM_GEOJSON.sql create mode 100644 clouds/snowflake/modules/test/quadbin/fixtures/coords_sample.sql create mode 100644 clouds/snowflake/modules/test/quadbin/global/setup.js create mode 100644 clouds/snowflake/modules/test/quadbin/global/teardown.js create mode 100644 clouds/snowflake/native_app/ADDITIONAL_TABLES.sql diff --git a/.github/workflows/snowflake-ded.yml b/.github/workflows/snowflake-ded.yml index 324dfc2c4..d022bc061 100644 --- a/.github/workflows/snowflake-ded.yml +++ b/.github/workflows/snowflake-ded.yml @@ -5,7 +5,7 @@ on: types: [closed, unlabeled, labeled, synchronize] env: - NODE_VERSION: 16 + NODE_VERSION: 18.16 jobs: diff --git a/.github/workflows/snowflake.yml b/.github/workflows/snowflake.yml index cbb102107..c71d94534 100644 --- a/.github/workflows/snowflake.yml +++ b/.github/workflows/snowflake.yml @@ -15,7 +15,7 @@ on: workflow_call: env: - NODE_VERSION: 16 + NODE_VERSION: 18.16 PYTHON3_VERSION: 3.8.10 VIRTUALENV_VERSION: 20.21.1 GCLOUD_VERSION: 290.0.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b703f537..0d97a718d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ CARTO Analytics Toolbox Core. All notable commits to this project will be documented in this file. +## 2024-02-15 + +- chore(sf): add additional tables to native apps (#473) +- docs(bs,sf,rs|transformations): fix ST_DESTINATION bearing parameter description (#475) +- fix(sf|quadbin): QUADBIN_TOPARENT not working with views (#476) +- docs(bq,sf,rs|constructors): fix angle parameter description in ST_MAKEELLIPSE (#477) +- fix(sf|random): ST_GENERATEPOINTS was not accepting column names (#480) + ## 2024-01-17 - chore(bq): increase tests timeout to 200000 (#455) diff --git a/clouds/bigquery/modules/doc/constructors/ST_MAKEELLIPSE.md b/clouds/bigquery/modules/doc/constructors/ST_MAKEELLIPSE.md index d773d9cb2..c5512fe23 100644 --- a/clouds/bigquery/modules/doc/constructors/ST_MAKEELLIPSE.md +++ b/clouds/bigquery/modules/doc/constructors/ST_MAKEELLIPSE.md @@ -11,7 +11,7 @@ Takes a Point and calculates the ellipse polygon given two semi-axes expressed i * `center`: `GEOGRAPHY` center point. * `xSemiAxis`: `FLOAT64` semi (major) axis of the ellipse along the x-axis. * `ySemiAxis`: `FLOAT64` semi (minor) axis of the ellipse along the y-axis. -* `angle`: `FLOAT64`|`NULL` angle of rotation (along the vertical axis), from North in decimal degrees, negative clockwise. If `NULL` the default value `0` is used. +* `angle`: `FLOAT64`|`NULL` angle of rotation (along the vertical axis), from North in decimal degrees, positive clockwise. If `NULL` the default value `0` is used. * `units`: `STRING`|`NULL` units of length, the supported options are: miles, kilometers, and degrees. If `NULL`the default value `kilometers` is used. * `steps`: `INT64`|`NULL` number of steps. If `NULL` the default value `64` is used. diff --git a/clouds/bigquery/modules/doc/transformations/ST_DESTINATION.md b/clouds/bigquery/modules/doc/transformations/ST_DESTINATION.md index c78ac1db6..dc42308d0 100644 --- a/clouds/bigquery/modules/doc/transformations/ST_DESTINATION.md +++ b/clouds/bigquery/modules/doc/transformations/ST_DESTINATION.md @@ -10,7 +10,7 @@ Takes a Point and calculates the location of a destination point given a distanc * `origin`: `GEOGRAPHY` starting point. * `distance`: `FLOAT64` distance from the origin point in the units specified. -* `bearing`: `FLOAT64` counter-clockwise angle from East, ranging from -180 to 180 (e.g. 0 is East, 90 is North, 180 is West, -90 is South). +* `bearing`: `FLOAT64` ranging from -180 to 180 (e.g. 0 is North, 90 is East, 180 is South, -90 is West). * `units`: `STRING`|`NULL` units of length, the supported options are: `miles`, `kilometers`, `degrees` or `radians`. If `NULL`the default value `kilometers` is used. **Return type** diff --git a/clouds/redshift/modules/doc/constructors/ST_MAKEELLIPSE.md b/clouds/redshift/modules/doc/constructors/ST_MAKEELLIPSE.md index 8b9623acc..380a10437 100644 --- a/clouds/redshift/modules/doc/constructors/ST_MAKEELLIPSE.md +++ b/clouds/redshift/modules/doc/constructors/ST_MAKEELLIPSE.md @@ -11,7 +11,7 @@ Takes a Point as input and calculates the ellipse polygon given two semi-axes ex * `center`: `GEOMETRY` center point. * `xSemiAxis`: `FLOAT8` semi (major) axis of the ellipse along the x-axis. * `ySemiAxis`: `FLOAT8` semi (minor) axis of the ellipse along the y-axis. -* `angle` (optional): `FLOAT8` angle of rotation (along the vertical axis), from North in decimal degrees, negative clockwise. If not specified, the default value of `0` will be used. +* `angle` (optional): `FLOAT8` angle of rotation (along the vertical axis), from North in decimal degrees, positive clockwise. If not specified, the default value of `0` will be used. * `units` (optional): `VARCHAR(10)` units of length. The supported options are: miles, kilometers, meters, and degrees. If not specified, `kilometers` will be used. * `steps` (optional): `INT` number of steps. If not specified, the default value of `64` will be used. diff --git a/clouds/redshift/modules/doc/transformations/ST_DESTINATION.md b/clouds/redshift/modules/doc/transformations/ST_DESTINATION.md index e8ea9bf19..26d096e35 100644 --- a/clouds/redshift/modules/doc/transformations/ST_DESTINATION.md +++ b/clouds/redshift/modules/doc/transformations/ST_DESTINATION.md @@ -10,7 +10,7 @@ Takes a Point and calculates the location of a destination point given a distanc * `geom`: `GEOMETRY` starting point. * `distance`: `FLOAT8` distance from the origin point in the units specified. -* `bearing`: `FLOAT8` counter-clockwise angle from East, ranging from -180 to 180 (e.g. 0 is East, 90 is North, 180 is West, -90 is South). +* `bearing`: `FLOAT8` ranging from -180 to 180 (e.g. 0 is North, 90 is East, 180 is South, -90 is West). * `units` (optional): `VARCHAR(15)` units of length. The supported options are: `miles`, `kilometers`, `degrees` or `radians`. If `NULL`the default value `kilometers` is used. **Return type** diff --git a/clouds/snowflake/CHANGELOG.md b/clouds/snowflake/CHANGELOG.md index 1b9e62c70..cbb151706 100644 --- a/clouds/snowflake/CHANGELOG.md +++ b/clouds/snowflake/CHANGELOG.md @@ -4,6 +4,12 @@ CARTO Analytics Toolbox Core for Snowflake. All notable commits to this project will be documented in this file. +## [1.2.1] - 2024-02-15 + +- chore: add additional tables to native apps (#473) +- fix(quadbin): QUADBIN_TOPARENT not working with views (#476) +- fix(random): ST_GENERATEPOINTS was not accepting column names (#480) + ## [1.2.0] - 2024-01-17 - feat(quadbin): add function QUADBIN_DISTANCE (#457) diff --git a/clouds/snowflake/common/build_native_app_setup_script.js b/clouds/snowflake/common/build_native_app_setup_script.js index 6db6f6f2f..f70752eda 100755 --- a/clouds/snowflake/common/build_native_app_setup_script.js +++ b/clouds/snowflake/common/build_native_app_setup_script.js @@ -15,6 +15,7 @@ const argv = require('minimist')(process.argv.slice(2)); const inputDirs = argv._[0] && argv._[0].split(','); const outputDir = argv.output || 'build'; const libsBuildDir = argv.libs_build_dir || '../libraries/javascript/build'; +const nativeAppDir = argv.native_app_dir || '../native_app'; const diff = argv.diff || []; const nodeps = argv.nodeps; let modulesFilter = (argv.modules && argv.modules.split(',')) || []; @@ -232,8 +233,13 @@ const header = `CREATE OR REPLACE APPLICATION ROLE @@APP_ROLE@@; CREATE OR ALTER VERSIONED SCHEMA @@SF_SCHEMA@@; GRANT USAGE ON SCHEMA @@SF_SCHEMA@@ TO APPLICATION ROLE @@APP_ROLE@@;\n`; +let additionalTables = ''; +if (argv.production) { + additionalTables = fs.readFileSync(path.resolve(nativeAppDir, 'ADDITIONAL_TABLES.sql')).toString() + separator; +} + const footer = fetchPermissionsGrant (fs.readFileSync(path.resolve(__dirname, 'VERSION.sql')).toString()); -content = header + separator + content + separator + footer; +content = header + separator + additionalTables + content + separator + footer; content = apply_replacements(content); diff --git a/clouds/snowflake/common/test-utils.js b/clouds/snowflake/common/test-utils.js index b73a2dac4..3dd81e65b 100644 --- a/clouds/snowflake/common/test-utils.js +++ b/clouds/snowflake/common/test-utils.js @@ -56,6 +56,13 @@ async function deleteTable (tablename) { await runQuery(query); } +async function deleteView (tablename) { + const query = ` + DROP VIEW IF EXISTS ${tablename} + `; + await runQuery(query); +} + function sortByKey (list, key) { return list.sort((a, b) => (a[key] > b[key]) ? 1 : -1); } @@ -113,6 +120,7 @@ module.exports = { runQuery, createTable, deleteTable, + deleteView, sortByKey, sortByKeyAndRound, existsTable, diff --git a/clouds/snowflake/libraries/javascript/libs/random.js b/clouds/snowflake/libraries/javascript/libs/random.js index 939a44b0c..70dcd1cc6 100644 --- a/clouds/snowflake/libraries/javascript/libs/random.js +++ b/clouds/snowflake/libraries/javascript/libs/random.js @@ -1,5 +1,8 @@ -import { bbox } from '@turf/turf'; +import { + generateRandomPointsInPolygon + +} from '../src/random'; export default { - bbox + generateRandomPointsInPolygon }; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/random.js b/clouds/snowflake/libraries/javascript/src/random.js new file mode 100644 index 000000000..4326c343b --- /dev/null +++ b/clouds/snowflake/libraries/javascript/src/random.js @@ -0,0 +1,12 @@ +import { bbox, booleanPointInPolygon, randomPoint } from '@turf/turf'; + +export function generateRandomPointsInPolygon (polygon, numPoints) { + const randomPoints = []; + while (randomPoints.length < numPoints) { + const point = randomPoint(1, { bbox: bbox(polygon) }).features[0]; + if (booleanPointInPolygon(point, polygon)) { + randomPoints.push(JSON.stringify(point.geometry)); + } + } + return randomPoints; +} \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/test/random.test.js b/clouds/snowflake/libraries/javascript/test/random.test.js index e77f6a4e3..4a02d3648 100644 --- a/clouds/snowflake/libraries/javascript/test/random.test.js +++ b/clouds/snowflake/libraries/javascript/test/random.test.js @@ -1,5 +1,5 @@ const randomLib = require('../build/random'); test('random library defined', () => { - expect(randomLib.bbox).toBeDefined(); + expect(randomLib.generateRandomPointsInPolygon).toBeDefined(); }); \ No newline at end of file diff --git a/clouds/snowflake/modules/Makefile b/clouds/snowflake/modules/Makefile index 0ec3c5edb..c2f7ac8e2 100644 --- a/clouds/snowflake/modules/Makefile +++ b/clouds/snowflake/modules/Makefile @@ -9,6 +9,7 @@ SQL_DIR ?= $(ROOT_DIR)/sql ESLINTRC_DIR ?= $(ROOT_DIR)/../../.. COMMON_DIR = $(ROOT_DIR)/../common LIBS_BUILD_DIR ?= $(ROOT_DIR)/../libraries/javascript/build +NATIVE_APP_DIR ?= $(ROOT_DIR)/../native_app MODULES_DIRS ?= $(ROOT_DIR) export SF_VERSION_FUNCTION ?= VERSION_CORE @@ -75,7 +76,7 @@ build-native-app-setup-script: $(NODE_MODULES_DEV) SF_SCHEMA=$(SF_UNQUALIFIED_SCHEMA) APP_ROLE=app_public \ REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ $(COMMON_DIR)/build_native_app_setup_script.js $(MODULES_DIRS) \ - --output=$(BUILD_DIR) --libs_build_dir=$(LIBS_BUILD_DIR) --diff="$(diff)" \ + --output=$(BUILD_DIR) --libs_build_dir=$(LIBS_BUILD_DIR) --native_app_dir=$(NATIVE_APP_DIR) --diff="$(diff)" \ --modules=$(modules) --functions=$(functions) --production=$(production) --nodeps=$(nodeps) --dropfirst=1 deploy: check build diff --git a/clouds/snowflake/modules/doc/constructors/ST_MAKEELLIPSE.md b/clouds/snowflake/modules/doc/constructors/ST_MAKEELLIPSE.md index 1d9bb9d80..97c6de035 100644 --- a/clouds/snowflake/modules/doc/constructors/ST_MAKEELLIPSE.md +++ b/clouds/snowflake/modules/doc/constructors/ST_MAKEELLIPSE.md @@ -11,7 +11,7 @@ Takes a Point and calculates the ellipse polygon given two semi-axes expressed i * `center`: `GEOGRAPHY` center point. * `xSemiAxis`: `DOUBLE` semi (major) axis of the ellipse along the x-axis. * `ySemiAxis`: `DOUBLE` semi (minor) axis of the ellipse along the y-axis. -* `angle` (optional): `DOUBLE` angle of rotation (along the vertical axis), from North in decimal degrees, negative clockwise. By default `angle` is `0`. +* `angle` (optional): `DOUBLE` angle of rotation (along the vertical axis), from North in decimal degrees, positive clockwise. By default `angle` is `0`. * `units` (optional): `STRING` units of length, the supported options are: miles, kilometers, and degrees. By default `units` is `kilometers`. * `steps` (optional): `INT` number of steps. By default `steps` is `64`. diff --git a/clouds/snowflake/modules/doc/transformations/ST_DESTINATION.md b/clouds/snowflake/modules/doc/transformations/ST_DESTINATION.md index f3755268b..7c85d9b79 100644 --- a/clouds/snowflake/modules/doc/transformations/ST_DESTINATION.md +++ b/clouds/snowflake/modules/doc/transformations/ST_DESTINATION.md @@ -10,7 +10,7 @@ Takes a Point and calculates the location of a destination point given a distanc * `origin`: `GEOGRAPHY` starting point. * `distance`: `DOUBLE` distance from the origin point in the units specified. -* `bearing`: `DOUBLE` counter-clockwise angle from East, ranging from -180 to 180 (e.g. 0 is East, 90 is North, 180 is West, -90 is South). +* `bearing`: `DOUBLE` ranging from -180 to 180 (e.g. 0 is North, 90 is East, 180 is South, -90 is West). * `units` (optional): `STRING` units of length, the supported options are: `miles`, `kilometers`, `degrees` or `radians`. If `NULL`the default value `kilometers` is used. **Return type** diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_RESOLUTION.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_RESOLUTION.sql index 2f31f02c9..61128bfec 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_RESOLUTION.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_RESOLUTION.sql @@ -7,5 +7,5 @@ CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.QUADBIN_RESOLUTION RETURNS INT IMMUTABLE AS $$ - SELECT BITAND(BITSHIFTRIGHT(quadbin, 52), 31) + BITAND(BITSHIFTRIGHT(quadbin, 52), 31) $$; diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql index d75a9b600..6854ce95c 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql @@ -9,22 +9,20 @@ IMMUTABLE AS $$ IFF(quadbin IS NULL OR resolution IS NULL OR resolution < 0 OR resolution > 26, NULL, - ( - SELECT bitor( - bitor( - bitand( - quadbin, - bitnot( - bitshiftleft(31, 52) - ) - ), - bitshiftleft(resolution, 52) - ), - bitshiftright( - 4503599627370495, - resolution * 2 + bitor( + bitor( + bitand( + quadbin, + bitnot( + bitshiftleft(31, 52) ) - ) + ), + bitshiftleft(resolution, 52) + ), + bitshiftright( + 4503599627370495, + resolution * 2 + ) ) ) $$; diff --git a/clouds/snowflake/modules/sql/random/ST_GENERATEPOINTS.sql b/clouds/snowflake/modules/sql/random/ST_GENERATEPOINTS.sql index 07386d576..a948f2a83 100644 --- a/clouds/snowflake/modules/sql/random/ST_GENERATEPOINTS.sql +++ b/clouds/snowflake/modules/sql/random/ST_GENERATEPOINTS.sql @@ -1,53 +1,25 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2021-2024 CARTO +-------------------------------- + +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._ST_GENERATEPOINTS +(geojson STRING, npoints DOUBLE) +RETURNS ARRAY +LANGUAGE JAVASCRIPT +IMMUTABLE +AS $$ + @@SF_LIBRARY_RANDOM@@ + + return randomLib.generateRandomPointsInPolygon(JSON.parse(GEOJSON), NPOINTS); +$$; CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.ST_GENERATEPOINTS (geog GEOGRAPHY, npoints INT) RETURNS ARRAY -VOLATILE -AS $$( - WITH bbox AS ( - -- compute the bounding box of the polygon - SELECT @@SF_SCHEMA@@._BBOX_FROM_GEOJSON(ST_ASGEOJSON(GEOG)::STRING) AS box - ), - bbox_coords AS ( - -- break down the bbox array into minx, miny, maxx, maxy - SELECT - GET(box, 0) AS minx, GET(box, 1) AS miny, - GET(box, 2) AS maxx, GET(box, 3) AS maxy - FROM bbox - ), - bbox_data AS ( - -- compute area of bbox and put some handy values here too - SELECT minx, miny, maxx, maxy, - 1.2 AS k, -- security factor to make it more likely that at least npoints fall within the polygon - ST_AREA(@@SF_SCHEMA@@.ST_MAKEENVELOPE(minx, miny, maxx, maxy)) AS bbox_area, - CEIL(k*NPOINTS*bbox_area/ST_AREA(GEOG)) AS nRows - FROM bbox_coords - ), - point_seeds AS ( - -- generate enough values so that we will hopefully have at least npoints of them randomly placed inside geog - SELECT SPLIT(lpad('', (nRows - 1), '0'),'0') as rowsArray, - SIN(miny*PI()/180.0) AS minsin, - SIN(maxy*PI()/180.0) AS maxsin, - 180.0/PI() AS radtodeg - FROM bbox_data - ), - bbox_points AS ( - -- compute the random points uniformly in the bbox; - SELECT - ST_POINT(minx+UNIFORM(0::FLOAT, 1::FLOAT, random())*(maxx-minx), radtodeg*ASIN(minsin+UNIFORM(0::FLOAT, 1::FLOAT, random())*(maxsin-minsin))) AS point - FROM bbox_coords, point_seeds, lateral FLATTEN(input => rowsArray) - ), - poly_points AS ( - -- now we need to select the points inside the polygon and number them, so we can limit - -- the end result to npoints (note that we can't have a dynamic LIMIT) - SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rn, point - FROM bbox_points - WHERE ST_WITHIN(point, GEOG) +IMMUTABLE +AS $$ + @@SF_SCHEMA@@._ST_GENERATEPOINTS( + ST_ASGEOJSON(GEOG)::STRING, + NPOINTS ) - -- finally select at most npoints and return them in an array - SELECT ARRAY_AGG(ST_ASGEOJSON(point)::STRING) - FROM poly_points WHERE rn <= NPOINTS -)$$; +$$; diff --git a/clouds/snowflake/modules/sql/random/_BBOX_FROM_GEOJSON.sql b/clouds/snowflake/modules/sql/random/_BBOX_FROM_GEOJSON.sql deleted file mode 100644 index 891d27b29..000000000 --- a/clouds/snowflake/modules/sql/random/_BBOX_FROM_GEOJSON.sql +++ /dev/null @@ -1,14 +0,0 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._BBOX_FROM_GEOJSON -(geojson STRING) -RETURNS ARRAY -LANGUAGE JAVASCRIPT -IMMUTABLE -AS $$ - @@SF_LIBRARY_RANDOM@@ - - return randomLib.bbox(JSON.parse(GEOJSON)); -$$; diff --git a/clouds/snowflake/modules/test/processing/ST_DELAUNAYLINES.test.js b/clouds/snowflake/modules/test/processing/ST_DELAUNAYLINES.test.js index 2bd545092..151008101 100644 --- a/clouds/snowflake/modules/test/processing/ST_DELAUNAYLINES.test.js +++ b/clouds/snowflake/modules/test/processing/ST_DELAUNAYLINES.test.js @@ -12,7 +12,7 @@ test('ST_DELAUNAYLINES should work', async () => { const rows = await runQuery(query); expect(rows.length).toEqual(fixturesOut.expectedTriangles1.length); - expect(rows.map(item => item.GEOM)).toEqual(fixturesOut.expectedTriangles1); + expect(rows.map(item => item.GEOM)).toEqual(expect.arrayContaining(fixturesOut.expectedTriangles1)); }); test('ST_DELAUNAYLINES should return an empty array if passed an empty array geometry', async () => { diff --git a/clouds/snowflake/modules/test/processing/ST_DELAUNAYPOLYGONS.test.js b/clouds/snowflake/modules/test/processing/ST_DELAUNAYPOLYGONS.test.js index 64b680247..e71187c6c 100644 --- a/clouds/snowflake/modules/test/processing/ST_DELAUNAYPOLYGONS.test.js +++ b/clouds/snowflake/modules/test/processing/ST_DELAUNAYPOLYGONS.test.js @@ -12,7 +12,7 @@ test('ST_DELAUNAYPOLYGONS should work', async () => { const rows = await runQuery(query); expect(rows.length).toEqual(fixturesOut.expectedPolygons1.length); - expect(rows.map(item => item.GEOM)).toEqual(fixturesOut.expectedPolygons1); + expect(rows.map(item => item.GEOM)).toEqual(expect.arrayContaining(fixturesOut.expectedPolygons1)); }); test('ST_DELAUNAYPOLYGONS should return an empty array if passed null geometry', async () => { diff --git a/clouds/snowflake/modules/test/processing/ST_POLYGONIZE.test.js b/clouds/snowflake/modules/test/processing/ST_POLYGONIZE.test.js index 659aff2d4..9a3ee2fea 100644 --- a/clouds/snowflake/modules/test/processing/ST_POLYGONIZE.test.js +++ b/clouds/snowflake/modules/test/processing/ST_POLYGONIZE.test.js @@ -12,7 +12,7 @@ test('ST_POLYGONIZE should work', async () => { const rows = await runQuery(query); expect(rows.length).toEqual(fixturesOut.expectedPolygons.length); - expect(rows.map(item => item.GEOM)).toEqual(fixturesOut.expectedPolygons); + expect(rows.map(item => item.GEOM)).toEqual(expect.arrayContaining(fixturesOut.expectedPolygons)); }); test('ST_POLYGONIZE should fail if a degenerated line path is received', async () => { diff --git a/clouds/snowflake/modules/test/processing/ST_VORONOILINES.test.js b/clouds/snowflake/modules/test/processing/ST_VORONOILINES.test.js index 5838d98f4..feb297ed9 100644 --- a/clouds/snowflake/modules/test/processing/ST_VORONOILINES.test.js +++ b/clouds/snowflake/modules/test/processing/ST_VORONOILINES.test.js @@ -18,7 +18,7 @@ test('ST_VORONOILINES should work', async () => { FROM voronoi, LATERAL FLATTEN(input => voronoi.geomArray) as unnestedFeatures`; const rows = await runQuery(query); expect(rows.length).toEqual(fixturesOut.expectedLines1.length); - expect(rows.map(item => item.GEOM)).toEqual(fixturesOut.expectedLines1); + expect(rows.map(item => item.GEOM)).toEqual(expect.arrayContaining(fixturesOut.expectedLines1)); }); diff --git a/clouds/snowflake/modules/test/processing/ST_VORONOIPOLYGONS.test.js b/clouds/snowflake/modules/test/processing/ST_VORONOIPOLYGONS.test.js index 030630ed3..548a5b1eb 100644 --- a/clouds/snowflake/modules/test/processing/ST_VORONOIPOLYGONS.test.js +++ b/clouds/snowflake/modules/test/processing/ST_VORONOIPOLYGONS.test.js @@ -18,7 +18,7 @@ test('ST_VORONOIPOLYGONS should work', async () => { FROM voronoi, LATERAL FLATTEN(input => voronoi.geomArray) as unnestedFeatures`; const rows = await runQuery(query); expect(rows.length).toEqual(fixturesOut.expectedPoly1.length); - expect(rows.map(item => item.GEOM)).toEqual(fixturesOut.expectedPoly1); + expect(rows.map(item => item.GEOM)).toEqual(expect.arrayContaining(fixturesOut.expectedPoly1)); }); diff --git a/clouds/snowflake/modules/test/quadbin/QUADBIN_TOPARENT.test.js b/clouds/snowflake/modules/test/quadbin/QUADBIN_TOPARENT.test.js index d7b173ff9..31930e4e9 100644 --- a/clouds/snowflake/modules/test/quadbin/QUADBIN_TOPARENT.test.js +++ b/clouds/snowflake/modules/test/quadbin/QUADBIN_TOPARENT.test.js @@ -1,8 +1,24 @@ -const { runQuery } = require('../../../common/test-utils'); +const { runQuery, deleteTable, deleteView } = require('../../../common/test-utils'); test('QUADBIN_TOPARENT should work', async () => { const query = 'SELECT CAST(QUADBIN_TOPARENT(5209574053332910079, 3) AS STRING) AS OUTPUT'; const rows = await runQuery(query); expect(rows.length).toEqual(1); expect(rows[0].OUTPUT).toEqual('5205105638077628415'); +}); + +test('QUADBIN_TOPARENT should work with nested functions when readin data from views', async () => { + const inputTable = '@@SF_SCHEMA@@.coords_sample'; + const inputTableView = '@@SF_SCHEMA@@.test_quadbin_toparent_view'; + + query = `CREATE VIEW IF NOT EXISTS ${inputTableView} AS + SELECT * FROM ${inputTable};`; + await runQuery(query); + + query = `SELECT CAST(QUADBIN_TOPARENT(QUADBIN_FROMLONGLAT(long, lat, zoom), 6) AS STRING) AS OUTPUT + FROM ${inputTableView};`; + const rows = await runQuery(query); + expect(rows.length).toEqual(120); + + deleteView(inputTableView); }); \ No newline at end of file diff --git a/clouds/snowflake/modules/test/quadbin/fixtures/coords_sample.sql b/clouds/snowflake/modules/test/quadbin/fixtures/coords_sample.sql new file mode 100644 index 000000000..ccd22a555 --- /dev/null +++ b/clouds/snowflake/modules/test/quadbin/fixtures/coords_sample.sql @@ -0,0 +1,120 @@ +SELECT 9 AS zoom,-180.000000 as long,36.000000 as lat +UNION ALL SELECT 8,-180.000000,54.000000 +UNION ALL SELECT 9,-180.000000,54.000000 +UNION ALL SELECT 7,-180.000000,18.000000 +UNION ALL SELECT 8,-180.000000,18.000000 +UNION ALL SELECT 8,-180.000000,72.000000 +UNION ALL SELECT 9,-180.000000,72.000000 +UNION ALL SELECT 7,-180.000000,54.000000 +UNION ALL SELECT 7,-144.000000,18.000000 +UNION ALL SELECT 8,-144.000000,18.000000 +UNION ALL SELECT 8,-144.000000,36.000000 +UNION ALL SELECT 8,-72.000000,54.000000 +UNION ALL SELECT 9,-72.000000,54.000000 +UNION ALL SELECT 7,-72.000000,72.000000 +UNION ALL SELECT 7,-36.000000,18.000000 +UNION ALL SELECT 9,0.000000,54.000000 +UNION ALL SELECT 9,0.000000,72.000000 +UNION ALL SELECT 7,-180.000000,36.000000 +UNION ALL SELECT 8,-180.000000,36.000000 +UNION ALL SELECT 7,-180.000000,72.000000 +UNION ALL SELECT 9,-144.000000,18.000000 +UNION ALL SELECT 7,-144.000000,36.000000 +UNION ALL SELECT 9,-144.000000,54.000000 +UNION ALL SELECT 7,-108.000000,72.000000 +UNION ALL SELECT 9,-36.000000,18.000000 +UNION ALL SELECT 7,144.000000,18.000000 +UNION ALL SELECT 9,-180.000000,18.000000 +UNION ALL SELECT 9,-144.000000,36.000000 +UNION ALL SELECT 7,-144.000000,54.000000 +UNION ALL SELECT 8,-144.000000,54.000000 +UNION ALL SELECT 7,-108.000000,54.000000 +UNION ALL SELECT 8,-108.000000,54.000000 +UNION ALL SELECT 8,-108.000000,72.000000 +UNION ALL SELECT 7,-72.000000,54.000000 +UNION ALL SELECT 9,-72.000000,72.000000 +UNION ALL SELECT 8,-36.000000,18.000000 +UNION ALL SELECT 7,-36.000000,36.000000 +UNION ALL SELECT 8,-36.000000,36.000000 +UNION ALL SELECT 7,0.000000,54.000000 +UNION ALL SELECT 8,0.000000,54.000000 +UNION ALL SELECT 7,0.000000,72.000000 +UNION ALL SELECT 8,36.000000,18.000000 +UNION ALL SELECT 9,36.000000,18.000000 +UNION ALL SELECT 7,72.000000,36.000000 +UNION ALL SELECT 8,72.000000,36.000000 +UNION ALL SELECT 9,0.000000,36.000000 +UNION ALL SELECT 8,144.000000,18.000000 +UNION ALL SELECT 9,144.000000,18.000000 +UNION ALL SELECT 7,-144.000000,72.000000 +UNION ALL SELECT 8,-144.000000,72.000000 +UNION ALL SELECT 8,-108.000000,36.000000 +UNION ALL SELECT 9,-108.000000,36.000000 +UNION ALL SELECT 7,-72.000000,18.000000 +UNION ALL SELECT 9,-72.000000,18.000000 +UNION ALL SELECT 7,-72.000000,36.000000 +UNION ALL SELECT 9,-72.000000,36.000000 +UNION ALL SELECT 8,-36.000000,54.000000 +UNION ALL SELECT 7,0.000000,18.000000 +UNION ALL SELECT 8,0.000000,18.000000 +UNION ALL SELECT 9,0.000000,18.000000 +UNION ALL SELECT 8,36.000000,54.000000 +UNION ALL SELECT 8,36.000000,72.000000 +UNION ALL SELECT 7,72.000000,18.000000 +UNION ALL SELECT 8,72.000000,18.000000 +UNION ALL SELECT 7,108.000000,54.000000 +UNION ALL SELECT 9,108.000000,54.000000 +UNION ALL SELECT 7,144.000000,36.000000 +UNION ALL SELECT 8,144.000000,36.000000 +UNION ALL SELECT 9,144.000000,54.000000 +UNION ALL SELECT 9,-36.000000,72.000000 +UNION ALL SELECT 8,-72.000000,36.000000 +UNION ALL SELECT 7,36.000000,72.000000 +UNION ALL SELECT 8,108.000000,18.000000 +UNION ALL SELECT 9,144.000000,72.000000 +UNION ALL SELECT 7,108.000000,72.000000 +UNION ALL SELECT 9,108.000000,72.000000 +UNION ALL SELECT 9,-108.000000,54.000000 +UNION ALL SELECT 9,-108.000000,72.000000 +UNION ALL SELECT 7,0.000000,36.000000 +UNION ALL SELECT 8,0.000000,36.000000 +UNION ALL SELECT 8,0.000000,72.000000 +UNION ALL SELECT 7,36.000000,18.000000 +UNION ALL SELECT 7,36.000000,36.000000 +UNION ALL SELECT 8,36.000000,36.000000 +UNION ALL SELECT 9,36.000000,36.000000 +UNION ALL SELECT 9,72.000000,36.000000 +UNION ALL SELECT 9,-144.000000,72.000000 +UNION ALL SELECT 7,-108.000000,36.000000 +UNION ALL SELECT 8,-72.000000,18.000000 +UNION ALL SELECT 7,-36.000000,54.000000 +UNION ALL SELECT 9,-36.000000,54.000000 +UNION ALL SELECT 9,36.000000,54.000000 +UNION ALL SELECT 9,72.000000,18.000000 +UNION ALL SELECT 7,72.000000,54.000000 +UNION ALL SELECT 8,72.000000,54.000000 +UNION ALL SELECT 9,72.000000,54.000000 +UNION ALL SELECT 7,72.000000,72.000000 +UNION ALL SELECT 9,108.000000,18.000000 +UNION ALL SELECT 9,144.000000,36.000000 +UNION ALL SELECT 7,144.000000,54.000000 +UNION ALL SELECT 8,144.000000,54.000000 +UNION ALL SELECT 8,144.000000,72.000000 +UNION ALL SELECT 7,-108.000000,18.000000 +UNION ALL SELECT 9,-108.000000,18.000000 +UNION ALL SELECT 8,-36.000000,72.000000 +UNION ALL SELECT 8,-72.000000,72.000000 +UNION ALL SELECT 7,36.000000,54.000000 +UNION ALL SELECT 9,72.000000,72.000000 +UNION ALL SELECT 7,108.000000,18.000000 +UNION ALL SELECT 8,108.000000,54.000000 +UNION ALL SELECT 7,-36.000000,72.000000 +UNION ALL SELECT 7,108.000000,36.000000 +UNION ALL SELECT 9,108.000000,36.000000 +UNION ALL SELECT 8,108.000000,72.000000 +UNION ALL SELECT 9,-36.000000,36.000000 +UNION ALL SELECT 9,36.000000,72.000000 +UNION ALL SELECT 8,72.000000,72.000000 +UNION ALL SELECT 8,-108.000000,18.000000 +UNION ALL SELECT 8,108.000000,36.000000 +UNION ALL SELECT 7,144.000000,72.000000 \ No newline at end of file diff --git a/clouds/snowflake/modules/test/quadbin/global/setup.js b/clouds/snowflake/modules/test/quadbin/global/setup.js new file mode 100644 index 000000000..e8e15a20b --- /dev/null +++ b/clouds/snowflake/modules/test/quadbin/global/setup.js @@ -0,0 +1,12 @@ +const { createTable, deleteTable } = require('../../../../common/test-utils'); + +async function initializeTables () { + await Promise.all([ + createTable( + 'coords_sample', + './test/quadbin/fixtures/coords_sample.sql' + ) + ]); +} + +module.exports = initializeTables; \ No newline at end of file diff --git a/clouds/snowflake/modules/test/quadbin/global/teardown.js b/clouds/snowflake/modules/test/quadbin/global/teardown.js new file mode 100644 index 000000000..03bb1e78a --- /dev/null +++ b/clouds/snowflake/modules/test/quadbin/global/teardown.js @@ -0,0 +1,9 @@ +const { deleteTable } = require('../../../../common/test-utils'); + +async function deleteTables () { + await Promise.all([ + deleteTable('coords_sample') + ]); +} + +module.exports = deleteTables; \ No newline at end of file diff --git a/clouds/snowflake/modules/test/random/ST_GENERATEPOINTS.test.js b/clouds/snowflake/modules/test/random/ST_GENERATEPOINTS.test.js index 6240de6dc..8add093d0 100644 --- a/clouds/snowflake/modules/test/random/ST_GENERATEPOINTS.test.js +++ b/clouds/snowflake/modules/test/random/ST_GENERATEPOINTS.test.js @@ -1,10 +1,17 @@ -const { runQuery } = require('../../../common/test-utils'); +const { runQuery, deleteTable } = require('../../../common/test-utils'); test('ST_GENERATEPOINTS should work', async () => { - const query = `SELECT - @@SF_SCHEMA@@.ST_GENERATEPOINTS(TO_GEOGRAPHY('POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))'), 10) AS random + const table = 'input_geom_table'; + let query = `CREATE OR REPLACE TABLE ${table} AS + SELECT TO_GEOGRAPHY('POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))') geog, 10 AS npoints;` + await runQuery(query); + query = `SELECT + @@SF_SCHEMA@@.ST_GENERATEPOINTS(geog, npoints) AS random + FROM @@SF_SCHEMA@@.${table} `; const rows = await runQuery(query); expect(rows.length).toEqual(1); expect(rows[0].RANDOM.length).toEqual(10); + + deleteTable(table); }); \ No newline at end of file diff --git a/clouds/snowflake/native_app/ADDITIONAL_TABLES.sql b/clouds/snowflake/native_app/ADDITIONAL_TABLES.sql new file mode 100644 index 000000000..e69de29bb diff --git a/clouds/snowflake/version b/clouds/snowflake/version index 26aaba0e8..6085e9465 100644 --- a/clouds/snowflake/version +++ b/clouds/snowflake/version @@ -1 +1 @@ -1.2.0 +1.2.1 From 532fc226ede0d8fc5aa80d191515f86a64af99f4 Mon Sep 17 00:00:00 2001 From: Valentin de la Cruz Barquero <6054336+vdelacruzb@users.noreply.github.com> Date: Thu, 21 Mar 2024 13:37:52 +0100 Subject: [PATCH 05/13] release: 2024-03-18 (#487) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: Javier Goizueta Co-authored-by: Alberto Hernández Co-authored-by: Jesús Arroyo Torrens Co-authored-by: Pedro-Juan Ferrer Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/redshift-ded.yml | 15 +- CHANGELOG.md | 8 + clouds/bigquery/CHANGELOG.md | 4 + .../libraries/javascript/src/random.js | 23 ++- .../libraries/javascript/test/random.test.js | 2 +- clouds/bigquery/modules/Makefile | 12 +- .../modules/doc/random/ST_GENERATEPOINTS.md | 7 - .../doc/transformations/ST_CONCAVEHULL.md | 2 +- .../modules/sql/random/ST_GENERATEPOINTS.sql | 81 ++------- .../sql/random/__BBOX_FROM_GEOJSON.sql | 13 -- clouds/bigquery/version | 2 +- .../common/requirements_create_it.txt | 2 +- clouds/postgres/modules/Makefile | 9 +- clouds/redshift/modules/Makefile | 9 +- .../modules/doc/random/ST_GENERATEPOINTS.md | 7 - clouds/snowflake/common/package.json | 2 +- clouds/snowflake/modules/Makefile | 9 +- .../modules/doc/random/ST_GENERATEPOINTS.md | 7 - .../doc/transformations/ST_CONCAVEHULL.md | 2 +- tools/installer/.gitignore | 170 ------------------ tools/installer/README.md | 71 -------- tools/installer/requirements.txt | 1 - tools/installer/setup.cfg | 44 ----- tools/installer/setup.py | 3 - tools/installer/src/__init__.py | 170 ------------------ 25 files changed, 98 insertions(+), 577 deletions(-) delete mode 100644 clouds/bigquery/modules/sql/random/__BBOX_FROM_GEOJSON.sql delete mode 100644 tools/installer/.gitignore delete mode 100644 tools/installer/README.md delete mode 100644 tools/installer/requirements.txt delete mode 100644 tools/installer/setup.cfg delete mode 100644 tools/installer/setup.py delete mode 100644 tools/installer/src/__init__.py diff --git a/.github/workflows/redshift-ded.yml b/.github/workflows/redshift-ded.yml index 0c5e71c2b..333159823 100644 --- a/.github/workflows/redshift-ded.yml +++ b/.github/workflows/redshift-ded.yml @@ -33,6 +33,19 @@ jobs: uses: actions/checkout@v2 - name: Check diff uses: technote-space/get-diff-action@v4 + - name: Set RS_PREFIX for releases + if: startsWith(github.event.pull_request.head.ref, 'release/') + run: | + echo "RS_PREFIX=dedicated_release_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV + - name: Set RS_PREFIX for hotfixes + if: startsWith(github.event.pull_request.head.ref, 'hotfix/') + run: | + echo "RS_PREFIX=dedicated_hotfix_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV + - name: Set RS_PREFIX for the rest + if: | + !(startsWith(github.event.pull_request.head.ref, 'hotfix/')) && + !(startsWith(github.event.pull_request.head.ref, 'release/')) + run: echo "RS_PREFIX=dedicated_${{ github.event.pull_request.number }}_" >> $GITHUB_ENV - name: Setup node uses: actions/setup-node@v1 with: @@ -63,7 +76,7 @@ jobs: if: github.event.action == 'synchronize' || github.event.action == 'labeled' run: | cd clouds/redshift - make deploy + make deploy dropfirst=1 - name: Run remove id: remove if: github.event.action == 'unlabeled' || github.event.action == 'closed' diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d97a718d..f939a6f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ CARTO Analytics Toolbox Core. All notable commits to this project will be documented in this file. +## 2024-03-18 + +- fix(sf): CI and CD not working because of snowflake driver breaking changes (#484) +- fix(bq,sf,rs,pg): drop schemas when dedicateds gets released (#485) +- fix(bq|random): ST_GENERATEPOINTS returning exact name of points (#486) +- chore(rs,pg): remove installer tool (#483) +- chore(deps): bump jinja2 from 3.1.2 to 3.1.3 in /clouds/databricks/common (#468) + ## 2024-02-15 - chore(sf): add additional tables to native apps (#473) diff --git a/clouds/bigquery/CHANGELOG.md b/clouds/bigquery/CHANGELOG.md index 3a1801276..f510577fd 100644 --- a/clouds/bigquery/CHANGELOG.md +++ b/clouds/bigquery/CHANGELOG.md @@ -4,6 +4,10 @@ CARTO Analytics Toolbox Core for BigQuery. All notable commits to this project will be documented in this file. +## [1.2.1] - 2024-03-18 + +- fix(random): ST_GENERATEPOINTS returning exact name of points (#486) + ## [1.2.0] - 2024-01-17 - chore: increase tests timeout to 200000 (#455) diff --git a/clouds/bigquery/libraries/javascript/src/random.js b/clouds/bigquery/libraries/javascript/src/random.js index 939a44b0c..fde5772e1 100644 --- a/clouds/bigquery/libraries/javascript/src/random.js +++ b/clouds/bigquery/libraries/javascript/src/random.js @@ -1,5 +1,24 @@ -import { bbox } from '@turf/turf'; +import { bbox, booleanPointInPolygon, randomPoint } from '@turf/turf'; + +function generateRandomPointsInPolygon (polygon, numPoints) { + const randomPoints = []; + while (randomPoints.length < numPoints) { + const point = randomPoint(1, { bbox: bbox(polygon) }).features[0]; + if (booleanPointInPolygon(point, polygon)) { + randomPoints.push(JSON.stringify(point.geometry)); + } + } + return randomPoints; +} + +function generateRandomPointInPolygon (polygon) { + let point + do { + point = randomPoint(1, { bbox: bbox(polygon) }).features[0]; + } while (!booleanPointInPolygon(point, polygon)) + return JSON.stringify(point.geometry); +} export default { - bbox + generateRandomPointsInPolygon }; \ No newline at end of file diff --git a/clouds/bigquery/libraries/javascript/test/random.test.js b/clouds/bigquery/libraries/javascript/test/random.test.js index e8855ee2c..f21b4dd35 100644 --- a/clouds/bigquery/libraries/javascript/test/random.test.js +++ b/clouds/bigquery/libraries/javascript/test/random.test.js @@ -1,5 +1,5 @@ const lib = require('../build/index'); test('random library defined', () => { - expect(lib.random.bbox).toBeDefined(); + expect(lib.random.generateRandomPointsInPolygon).toBeDefined(); }); \ No newline at end of file diff --git a/clouds/bigquery/modules/Makefile b/clouds/bigquery/modules/Makefile index ca2f9abfe..521fe1ce2 100644 --- a/clouds/bigquery/modules/Makefile +++ b/clouds/bigquery/modules/Makefile @@ -34,10 +34,10 @@ include $(COMMON_DIR)/Makefile .SILENT: -.PHONY: help lint build build-share deploy deploy-share test remove remove-share clean +.PHONY: help lint build build-share deploy deploy-share test remove remove-functions remove-share clean help: - echo "Available targets: lint build deploy test remove clean" + echo "Available targets: lint build deploy test remove remove-functions clean" lint: venv3 $(NODE_MODULES_DEV) echo "Linting modules..." @@ -85,7 +85,7 @@ test: check $(NODE_MODULES_DEV) if [ ! -z "$$TESTS" ]; then \ GOOGLE_APPLICATION_CREDENTIALS=$(GOOGLE_APPLICATION_CREDENTIALS) \ PATH="$(NODE_MODULES_DEV)/.bin/:$(PATH)" \ - jest --testTimeout=200000 $(BAIL) --verbose --slowTestThreshold=20 --maxConcurrency=10 $$TESTS \ + jest --testTimeout=250000 $(BAIL) --verbose --slowTestThreshold=20 --maxConcurrency=10 $$TESTS \ --setupFilesAfterEnv "$(COMMON_DIR)/test-extend.js" || exit 1; \ OLD_TEST=$(TEST_DIR)/$$m/old-test; \ if [ -d $$OLD_TEST ]; then \ @@ -101,6 +101,12 @@ remove: check GOOGLE_APPLICATION_CREDENTIALS=$(GOOGLE_APPLICATION_CREDENTIALS) \ $(COMMON_DIR)/run-script.js $(COMMON_DIR)/DROP_FUNCTIONS.sql +remove-functions: check + echo "Removing functions..." + REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ + GOOGLE_APPLICATION_CREDENTIALS=$(GOOGLE_APPLICATION_CREDENTIALS) \ + $(COMMON_DIR)/run-script.js $(COMMON_DIR)/DROP_FUNCTIONS.sql + clean: echo "Cleaning modules..." rm -rf $(BUILD_DIR) $(NODE_MODULES_DEV) diff --git a/clouds/bigquery/modules/doc/random/ST_GENERATEPOINTS.md b/clouds/bigquery/modules/doc/random/ST_GENERATEPOINTS.md index cc119f749..91a082e72 100644 --- a/clouds/bigquery/modules/doc/random/ST_GENERATEPOINTS.md +++ b/clouds/bigquery/modules/doc/random/ST_GENERATEPOINTS.md @@ -10,13 +10,6 @@ Generates randomly placed points inside a polygon and returns them in an array o The distribution of the generated points is spherically uniform (i.e. if the coordinates are interpreted as longitude and latitude on a sphere); this means that WGS84 coordinates will be only approximately uniformly distributed, since WGS84 is based on an ellipsoidal model. -````hint:warning -**warning** - -It never generates more than the requested number of points, but there is a small chance of generating less points. - -```` - * `geog`: `GEOGRAPHY` a polygon; the random points generated will be inside this polygon. * `npoints`: `INT64` number of points to generate. diff --git a/clouds/bigquery/modules/doc/transformations/ST_CONCAVEHULL.md b/clouds/bigquery/modules/doc/transformations/ST_CONCAVEHULL.md index 3c1b94410..10070fa05 100644 --- a/clouds/bigquery/modules/doc/transformations/ST_CONCAVEHULL.md +++ b/clouds/bigquery/modules/doc/transformations/ST_CONCAVEHULL.md @@ -9,7 +9,7 @@ ST_CONCAVEHULL(geog, maxEdge, units) Takes a set of points and returns a concave hull Polygon or MultiPolygon. In case that a single or a couple of points are passed as input, the function will return that point or a segment respectively. * `geog`: `ARRAY` input points. -* `maxEdge`: `FLOAT64`|`NULL` the length (in 'units') of an edge necessary for part of the hull to become concave. If `NULL`the default value `infinity` is used. +* `maxEdge`: `FLOAT64`|`NULL` the maximum length allowed for an edge of the concave hull. Higher `maxEdge` values will produce more convex-like hulls. If `NULL`, the default value `infinity` is used and it would be equivalent to a Convex Hull. * `units`: `STRING`|`NULL` units of length, the supported options are: miles, kilometers, degrees or radians. If `NULL`the default value `kilometers` is used. **Return type** diff --git a/clouds/bigquery/modules/sql/random/ST_GENERATEPOINTS.sql b/clouds/bigquery/modules/sql/random/ST_GENERATEPOINTS.sql index 7c67550f8..e63946a21 100644 --- a/clouds/bigquery/modules/sql/random/ST_GENERATEPOINTS.sql +++ b/clouds/bigquery/modules/sql/random/ST_GENERATEPOINTS.sql @@ -1,74 +1,23 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2021-2024 CARTO +-------------------------------- + +CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.__ST_GENERATEPOINTS` +(geojson STRING, npoints INT64) +RETURNS ARRAY +DETERMINISTIC +LANGUAGE js +OPTIONS (library = ["@@BQ_LIBRARY_BUCKET@@"]) +AS """ + return lib.random.generateRandomPointsInPolygon(JSON.parse(geojson), npoints); +"""; CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.ST_GENERATEPOINTS` (geog GEOGRAPHY, npoints INT64) RETURNS ARRAY AS ( ( - WITH bbox AS ( - -- compute the bounding box of the polygon - SELECT `@@BQ_DATASET@@.__BBOX_FROM_GEOJSON`(ST_ASGEOJSON(geog)) AS box - ), - - bbox_coords AS ( - -- break down the bbox array into minx, miny, maxx, maxy - SELECT - box[ORDINAL(1)] AS minx, - box[ORDINAL(2)] AS miny, - box[ORDINAL(3)] AS maxx, - box[ORDINAL(4)] AS maxy - FROM bbox - ), - - bbox_data AS ( - -- compute area of bbox and put some handy values here too - SELECT - minx, - miny, - maxx, - maxy, - 1.2 AS k, -- security factor to make it more likely that at least npoints fall within the polygon - ST_AREA( - ST_MAKEPOLYGON(ST_MAKELINE([ - ST_GEOGPOINT(minx, miny), - ST_GEOGPOINT(minx, maxy), - ST_GEOGPOINT(maxx, maxy), - ST_GEOGPOINT(maxx, miny), - ST_GEOGPOINT(minx, miny) - ])) - ) AS bbox_area - FROM bbox_coords - ), - - point_seeds AS ( - -- generate enough values so that we will hopefully have at least npoints of them randomly placed inside geog - SELECT - GENERATE_ARRAY(1, CEIL(k * npoints * bbox_area / ST_AREA(geog))) AS i, - SIN(miny * ACOS(-1) / 180.0) AS minsin, - SIN(maxy * ACOS(-1) / 180.0) AS maxsin, - 180.0 / ACOS(-1) AS radtodeg - FROM bbox_data - ), - - bbox_points AS ( - -- compute the random points uniformly in the bbox; - SELECT ST_GEOGPOINT(minx + RAND() * (maxx - minx), radtodeg * ASIN(minsin + RAND() * (maxsin - minsin))) AS point - FROM bbox_coords, point_seeds, UNNEST(i) - ), - - poly_points AS ( - -- now we need to select the points inside the polygon and number them, so we can limit - -- the end result to npoints (note that we can't have a dynamic LIMIT) - SELECT - point, - ROW_NUMBER() OVER () AS rn - FROM bbox_points - WHERE ST_WITHIN(point, geog) - ) - - -- finally select at most npoints and return them in an array - SELECT ARRAY(SELECT point FROM poly_points WHERE rn <= npoints) + SELECT ARRAY_AGG(ST_GEOGFROMGEOJSON(point)) + FROM UNNEST(`@@BQ_DATASET@@.__ST_GENERATEPOINTS`(ST_ASGEOJSON(geog), npoints)) AS point ) ); diff --git a/clouds/bigquery/modules/sql/random/__BBOX_FROM_GEOJSON.sql b/clouds/bigquery/modules/sql/random/__BBOX_FROM_GEOJSON.sql deleted file mode 100644 index 37994f268..000000000 --- a/clouds/bigquery/modules/sql/random/__BBOX_FROM_GEOJSON.sql +++ /dev/null @@ -1,13 +0,0 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- - -CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.__BBOX_FROM_GEOJSON` -(geojson STRING) -RETURNS ARRAY -DETERMINISTIC -LANGUAGE js -OPTIONS (library = ["@@BQ_LIBRARY_BUCKET@@"]) -AS """ - return lib.random.bbox(JSON.parse(geojson)); -"""; diff --git a/clouds/bigquery/version b/clouds/bigquery/version index 26aaba0e8..6085e9465 100644 --- a/clouds/bigquery/version +++ b/clouds/bigquery/version @@ -1 +1 @@ -1.2.0 +1.2.1 diff --git a/clouds/databricks/common/requirements_create_it.txt b/clouds/databricks/common/requirements_create_it.txt index 769ef83ec..cd1737d67 100644 --- a/clouds/databricks/common/requirements_create_it.txt +++ b/clouds/databricks/common/requirements_create_it.txt @@ -1 +1 @@ -Jinja2==3.1.2 +Jinja2==3.1.3 diff --git a/clouds/postgres/modules/Makefile b/clouds/postgres/modules/Makefile index ba3603b36..4e62a6d7d 100644 --- a/clouds/postgres/modules/Makefile +++ b/clouds/postgres/modules/Makefile @@ -21,10 +21,10 @@ include $(COMMON_DIR)/Makefile .SILENT: -.PHONY: help lint build deploy test remove clean +.PHONY: help lint build deploy test remove remove-functions clean help: - echo "Available targets: lint build deploy test remove clean" + echo "Available targets: lint build deploy test remove remove-functions clean" lint: venv3 $(NODE_MODULES_DEV) echo "Linting modules..." @@ -64,6 +64,11 @@ remove: venv3 REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ $(VENV3_BIN)/python $(COMMON_DIR)/run_script.py $(COMMON_DIR)/DROP_FUNCTIONS.sql +remove-functions: venv3 + echo "Removing functions..." + REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ + $(VENV3_BIN)/python $(COMMON_DIR)/run_script.py $(COMMON_DIR)/DROP_FUNCTIONS.sql + clean: echo "Cleaning modules..." rm -rf $(BUILD_DIR) $(VENV3_DIR) $(NODE_MODULES_DEV) diff --git a/clouds/redshift/modules/Makefile b/clouds/redshift/modules/Makefile index d56d2c3c4..75a1d8554 100644 --- a/clouds/redshift/modules/Makefile +++ b/clouds/redshift/modules/Makefile @@ -21,10 +21,10 @@ include $(COMMON_DIR)/Makefile .SILENT: -.PHONY: help lint build deploy test remove clean +.PHONY: help lint build deploy test remove remove-functions clean help: - echo "Available targets: lint build deploy test remove clean" + echo "Available targets: lint build deploy test remove remove-functions clean" lint: venv3 $(NODE_MODULES_DEV) echo "Linting modules..." @@ -64,6 +64,11 @@ remove: venv3 REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ $(VENV3_BIN)/python $(COMMON_DIR)/run_script.py $(COMMON_DIR)/DROP_FUNCTIONS.sql +remove-functions: venv3 + echo "Removing functions..." + REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ + $(VENV3_BIN)/python $(COMMON_DIR)/run_script.py $(COMMON_DIR)/DROP_FUNCTIONS.sql + clean: echo "Cleaning modules..." rm -rf $(BUILD_DIR) $(VENV3_DIR) $(NODE_MODULES_DEV) diff --git a/clouds/redshift/modules/doc/random/ST_GENERATEPOINTS.md b/clouds/redshift/modules/doc/random/ST_GENERATEPOINTS.md index 341eb15b6..c1add4884 100644 --- a/clouds/redshift/modules/doc/random/ST_GENERATEPOINTS.md +++ b/clouds/redshift/modules/doc/random/ST_GENERATEPOINTS.md @@ -10,13 +10,6 @@ Generates randomly placed points inside a polygon and returns them in an array o The distribution of the generated points is spherically uniform (i.e. if the coordinates are interpreted as longitude and latitude on a sphere); this means that WGS84 coordinates will be only approximately uniformly distributed, since WGS84 is based on an ellipsoidal model. -````hint:warning -**warning** - -It never generates more than the requested number of points, but there is a small chance of generating less points. - -```` - * `geog`: `GEOMETRY` a polygon; the random points generated will be inside this polygon. * `npoints`: `INT` number of points to generate. diff --git a/clouds/snowflake/common/package.json b/clouds/snowflake/common/package.json index f852c7570..c227179cd 100644 --- a/clouds/snowflake/common/package.json +++ b/clouds/snowflake/common/package.json @@ -11,6 +11,6 @@ "rollup": "^2.47.0", "rollup-plugin-bundle-size": "^1.0.3", "rollup-plugin-terser": "^7.0.2", - "snowflake-sdk": "^1.6.6" + "snowflake-sdk": "1.9.3" } } diff --git a/clouds/snowflake/modules/Makefile b/clouds/snowflake/modules/Makefile index c2f7ac8e2..d557139f4 100644 --- a/clouds/snowflake/modules/Makefile +++ b/clouds/snowflake/modules/Makefile @@ -32,10 +32,10 @@ include $(COMMON_DIR)/Makefile .SILENT: -.PHONY: help lint build build-share build-native-app-setup-script deploy deploy-share test remove remove-share clean +.PHONY: help lint build build-share build-native-app-setup-script deploy deploy-share test remove remove-functions remove-share clean help: - echo "Available targets: lint build deploy test remove clean" + echo "Available targets: lint build deploy test remove remove-functions clean" lint: $(NODE_MODULES_DEV) venv3 echo "Linting modules..." @@ -110,6 +110,11 @@ remove: $(NODE_MODULES_DEV) REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ $(COMMON_DIR)/run-script.js $(COMMON_DIR)/DROP_FUNCTIONS.sql +remove-functions: $(NODE_MODULES_DEV) + echo "Removing functions..." + REPLACEMENTS=$(REPLACEMENTS)" "$(REPLACEMENTS_EXTRA) \ + $(COMMON_DIR)/run-script.js $(COMMON_DIR)/DROP_FUNCTIONS.sql + remove-share: $(NODE_MODULES_DEV) echo "Removing share..." $(COMMON_DIR)/run-query.js "DROP SHARE $(SF_SHARE);" diff --git a/clouds/snowflake/modules/doc/random/ST_GENERATEPOINTS.md b/clouds/snowflake/modules/doc/random/ST_GENERATEPOINTS.md index c94c76136..93e8f6cf9 100644 --- a/clouds/snowflake/modules/doc/random/ST_GENERATEPOINTS.md +++ b/clouds/snowflake/modules/doc/random/ST_GENERATEPOINTS.md @@ -10,13 +10,6 @@ Generates randomly placed points inside a polygon and returns them in an array o The distribution of the generated points is spherically uniform (i.e. if the coordinates are interpreted as longitude and latitude on a sphere); this means that WGS84 coordinates will be only approximately uniformly distributed, since WGS84 is based on an ellipsoidal model. -````hint:warning -**warning** - -It never generates more than the requested number of points, but there is a small chance of generating less points. - -```` - * `geog`: `GEOGRAPHY` a polygon; the random points generated will be inside this polygon. * `npoints`: `INT` number of points to generate. diff --git a/clouds/snowflake/modules/doc/transformations/ST_CONCAVEHULL.md b/clouds/snowflake/modules/doc/transformations/ST_CONCAVEHULL.md index 6f5ec8169..0a0173894 100644 --- a/clouds/snowflake/modules/doc/transformations/ST_CONCAVEHULL.md +++ b/clouds/snowflake/modules/doc/transformations/ST_CONCAVEHULL.md @@ -9,7 +9,7 @@ ST_CONCAVEHULL(geojsons [, maxEdge] [, units]) Takes a set of points and returns a concave hull Polygon or MultiPolygon. In case that a single or a couple of points are passed as input, the function will return that point or a segment respectively. * `geojsons`: `ARRAY` array of features in GeoJSON format casted to STRING. -* `maxEdge` (optional): `DOUBLE` the length (in 'units') of an edge necessary for part of the hull to become concave. By default `maxEdge` is `infinity`. +* `maxEdge` (optional): `DOUBLE` the maximum length allowed for an edge of the concave hull. Higher `maxEdge` values will produce more convex-like hulls. If not provided, the default value `infinity` is used and it would be equivalent to a Convex Hull. * `units` (optional): `STRING` units of length, the supported options are: miles, kilometers, degrees or radians. By default `units` is `kilometers`. **Return type** diff --git a/tools/installer/.gitignore b/tools/installer/.gitignore deleted file mode 100644 index 3bedfacaf..000000000 --- a/tools/installer/.gitignore +++ /dev/null @@ -1,170 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env*/ -venv*/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -# Images -*.svg - -# Visual Studio Code -.vscode - -# Custom -config.yml -carto-analytics-toolbox-redshift-* diff --git a/tools/installer/README.md b/tools/installer/README.md deleted file mode 100644 index 4c5907bc1..000000000 --- a/tools/installer/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# CARTO Analytics Toolbox installer - -A Python script to install the CARTO Analytics Toolbox in Redshift and Postgres. - -## Install - -1. Install Python >= 3.7: https://www.python.org/downloads/ - - Create a virtual environment (optional for Linux, macOS): - - ``` - python -m venv env - source env/bin/activate - ``` - -2. Install the tool: - - ``` - pip install -U pip - pip install git+https://github.com/cartodb/analytics-toolbox-core.git@main#subdirectory=tools/installer - ``` - -> Note: if `python` does not point to Python 3, use `python3` instead. - -## Usage - -1. Create a `config.yml` file: - - - Redshift packages `config.yml` file. This file must contain the information of the Redshift connection and LDS. - ```yml - connection: - cloud: redshift - host: CLUSTER.ACCOUNT.REGION.redshift.amazonaws.com - database: DATABASE - user: USER - password: PASSWORD - lds: - lambda: lds-function-europe-west1 - roles: arn:aws:iam::XXXXXXXXXXXX:role/CartoFunctionsRedshiftRole,arn:aws:iam::000955892807:role/CartoFunctionsRole - api_base_url: https://gcp-europe-west1.api.carto.com - token: eyJhbGciOiJ... - ``` - - > Note: Redshift core does not require setting up a `lds` configuration. - - - Postgres packages `config.yml` file. This file must contain the information of the Postgres connection. - ```yml - connection: - cloud: postgres - host: HOST - database: DATABASE - user: USER - password: PASSWORD - ``` - -2. Download the installation package (zip file). - -3. Run the script: - - ``` - cat-installer carto-analytics-toolbox-redshift-latest.zip - ``` - - ``` - Reading config file: config.yml - Reading package file: carto-analytics-toolbox-redshift-latest.zip - Installing libraries... - 100%|█████████████████████████████████████████████████████████████████| 8/8 [00:07<00:00, 1.05it/s] - Installing modules... - 100%|█████████████████████████████████████████████████████████████| 246/246 [02:09<00:00, 1.90it/s] - ``` diff --git a/tools/installer/requirements.txt b/tools/installer/requirements.txt deleted file mode 100644 index ecf975e2f..000000000 --- a/tools/installer/requirements.txt +++ /dev/null @@ -1 +0,0 @@ --e . \ No newline at end of file diff --git a/tools/installer/setup.cfg b/tools/installer/setup.cfg deleted file mode 100644 index 6c889c9dd..000000000 --- a/tools/installer/setup.cfg +++ /dev/null @@ -1,44 +0,0 @@ -[metadata] -name = cat-installer -version = 0.2.1 -description = Python script to install the CARTO Analytics Toolbox in Redshift and Postgres -long_description = file: README.md -long_description_content_type = text/markdown -keywords = - carto - analytics - toolbox - redshift -author = CARTO -url = https://github.com/cartodb/analytics-toolbox-core -license = BSD 3-Clause -classifiers = - Development Status :: 4 - Beta - Intended Audience :: Developers - License :: OSI Approved :: BSD License - Natural Language :: English - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 -[options] -packages = find: -python_requires = >=3.7 -install_requires = - pyyaml>=6.0 - click>8.1 - tqdm>4.64 - sqlparse>0.4 - redshift-connector>2.0 - psycopg2-binary>=2.9.1 - pyjwt==2.7.0 - validator-collection==1.5.0 -zip_safe = False -[options.entry_points] -console_scripts = - cat-installer = src:main -[flake8] -max-line-length = 88 -ignore = E203 diff --git a/tools/installer/setup.py b/tools/installer/setup.py deleted file mode 100644 index 606849326..000000000 --- a/tools/installer/setup.py +++ /dev/null @@ -1,3 +0,0 @@ -from setuptools import setup - -setup() diff --git a/tools/installer/src/__init__.py b/tools/installer/src/__init__.py deleted file mode 100644 index 4e776f6cd..000000000 --- a/tools/installer/src/__init__.py +++ /dev/null @@ -1,170 +0,0 @@ -import os -import re -import sys -import yaml -import click -import zipfile -import redshift_connector -import jwt -from validator_collection import checkers - -from tqdm import trange -from sqlparse import split -from psycopg2 import connect - - -def read_config(filename): - try: - with open(filename, 'r') as yamlfile: - config = yaml.load(yamlfile, Loader=yaml.FullLoader) - validate_config(config) - return config - except FileNotFoundError: - exit(f'ERROR: configuration file not found: {filename}') - - -def read_package(filename, config): - with zipfile.ZipFile(filename, 'r') as zip_ref: - folder = zip_ref.infolist()[0].filename - zip_ref.extractall('.') - - package = {} - - if config['connection']['cloud'] == 'redshift': - with open(os.path.join(folder, 'libraries.sql'), 'r') as lib_file: - package['libraries'] = lib_file.read() - - with open(os.path.join(folder, 'modules.sql'), 'r') as mod_file: - package['modules'] = mod_file.read() - - return package - - -def run_sql(sql, config): - if config['connection']['cloud'] == 'redshift': - with redshift_connector.connect( - host=config['connection']['host'], - database=config['connection']['database'], - user=config['connection']['user'], - password=config['connection']['password'], - ) as conn: - conn.autocommit = True - with conn.cursor() as cursor: - lds = config.get('lds') - if lds is not None: - sql = ( - sql.replace('@@API_BASE_URL@@', lds['api_base_url']) - .replace('@@LDS_LAMBDA@@', lds['lambda']) - .replace('@@LDS_ROLES@@', lds['roles']) - .replace('@@LDS_TOKEN@@', lds['token']) - ) - queries = split(sql) - for i in trange(len(queries), ncols=100): - query = queries[i] - cursor.execute(query) - elif config['connection']['cloud'] == 'postgres': - with connect( - host=config['connection']['host'], - database=config['connection']['database'], - user=config['connection']['user'], - password=config['connection']['password'], - ) as conn: - conn.autocommit = True - with conn.cursor() as cursor: - queries = split(sql) - for i in trange(len(queries), ncols=97): - query = queries[i] - cursor.execute(query) - for notice in list(set(conn.notices)): - print(notice.strip()) - - -def validate_lds_config(lds_config): - pattern = r'^(lds-function-asia-northeast1|lds-function-australia-southeast1|lds-function-europe-west1|lds-function-us-east1)$' # noqa: E501 - if not validate_str(lds_config.get('lambda'), pattern): - exit('incorrect configuration: missing or invalid lds.lambda') - - pattern = r'^arn:aws:iam::[0-9]+:role/CartoFunctionsRedshiftRole,arn:aws:iam::000955892807:role/CartoFunctionsRole$' # noqa: E501 - if not validate_str(lds_config.get('roles'), pattern): - exit('incorrect configuration: missing or invalid lds.roles') - - if not validate_str(lds_config.get('api_base_url')): - exit('incorrect configuration: missing lds.api_base_url') - - if not checkers.is_url(lds_config.get('api_base_url')): - exit('incorrect configuration: invalid lds.api_base_url') - - token = lds_config.get('token') - if not validate_str(token): - exit('incorrect configuration: missing lds.token') - algorithm = jwt.get_unverified_header(token).get('alg') - if not algorithm: - exit('incorrect configuration: invalid lds.token') - jwt_payload = jwt.decode( - token, algorithms=[algorithm], options={'verify_signature': False} - ) - if not jwt_payload.get('a') or not jwt_payload.get('jti'): - exit('incorrect configuration: invalid lds.token') - - -def validate_config(config): - connection = config.get('connection') - - cloud = connection.get('cloud') - if not validate_str(cloud): - exit('incorrect configuration: missing connection.cloud') - - if cloud not in ['redshift', 'postgres']: - exit('incorrect configuration: invalid connection.cloud') - - if connection is None: - exit('incorrect configuration: missing connection') - - if not validate_str(connection.get('host')): - exit('incorrect configuration: missing connection.host') - - if cloud == 'redshift': - pattern = r'^([^.]+)\.([^.]+)\.([^.]+)\.redshift(-serverless)?\.amazonaws\.com$' - if not validate_str(connection.get('host'), pattern): - exit('incorrect configuration: invalid connection.host') - - if not validate_str(connection.get('database')): - exit('incorrect configuration: missing connection.database') - - if not validate_str(connection.get('user')): - exit('incorrect configuration: missing connection.user') - - if not validate_str(connection.get('password')): - exit('incorrect configuration: missing connection.password') - - lds_config = config.get('lds') - if cloud == 'redshift' and lds_config is not None: - validate_lds_config(lds_config) - - -def validate_str(string, pattern=None): - return ( - isinstance(string, str) - and len(string) > 0 - and (not pattern or re.compile(pattern).match(string)) - ) - - -def exit(message): - print(f'ERROR: {message}') - sys.exit(1) - - -@click.command(help='Python installer for the CARTO Analytics Toolbox in Redshift.') -@click.argument('package_file', type=click.Path(exists=True), required=True) -def main(package_file): - config_file = 'config.yml' - print(f'Reading config file: {config_file}') - config = read_config(config_file) - print(f'Reading package file: {package_file}') - package = read_package(package_file, config) - if 'libraries' in package: - print('Installing libraries...') - run_sql(package['libraries'], config) - print('Installing modules...') - run_sql(package['modules'], config) From 703ca295dfee0db485dbd3d4ef5a54a4709be454 Mon Sep 17 00:00:00 2001 From: Valentin de la Cruz Barquero <6054336+vdelacruzb@users.noreply.github.com> Date: Thu, 18 Apr 2024 17:01:05 +0200 Subject: [PATCH 06/13] release: 2024-04-18 (#497) --- .github/workflows/snowflake.yml | 2 +- .gitignore | 3 + CHANGELOG.md | 10 + README.md | 17 + clouds/bigquery/CHANGELOG.md | 5 + .../libraries/javascript/src/clustering.js | 24 +- .../javascript/test/clustering.test.js | 1 + .../doc/clustering/ST_CLUSTERKMEANS.md | 2 +- .../doc/processing/ST_DELAUNAYLINES.md | 6 + .../doc/processing/ST_DELAUNAYPOLYGONS.md | 6 + .../modules/doc/processing/ST_VORONOILINES.md | 6 + .../doc/processing/ST_VORONOIPOLYGONS.md | 6 + .../sql/clustering/ST_CLUSTERKMEANS.sql | 10 +- .../test/clustering/ST_CLUSTERKMEANS.test.js | 18 + .../fixtures/st_clusterkmeans_points2_out.js | 2 +- .../fixtures/st_clusterkmeans_points3_out.js | 2 +- clouds/bigquery/version | 2 +- .../postgres/common/python3_requirements.txt | 2 +- clouds/redshift/CHANGELOG.md | 5 + .../python/lib/clustering/__init__.py | 70 +- .../libraries/python/lib/clustering/kmeans.py | 4 +- .../doc/clustering/ST_CLUSTERKMEANS.md | 2 +- .../doc/processing/ST_DELAUNAYLINES.md | 6 + .../doc/processing/ST_DELAUNAYPOLYGONS.md | 6 + .../modules/doc/processing/ST_VORONOILINES.md | 6 + .../doc/processing/ST_VORONOIPOLYGONS.md | 6 + .../sql/clustering/ST_CLUSTERKMEANS.sql | 6 +- .../fixtures/st_clusterkmeans_out.txt | 6 +- .../test/clustering/test_ST_CLUSTERKMEANS.py | 22 + clouds/redshift/version | 2 +- clouds/snowflake/.~lock.results.csv# | 1 + clouds/snowflake/CHANGELOG.md | 7 + .../libraries/javascript/libs/clustering.js | 24 +- .../libraries/javascript/libs/h3_center.js | 6 - .../libraries/javascript/libs/h3_distance.js | 5 - .../libraries/javascript/libs/h3_kring.js | 6 - .../javascript/libs/h3_kring_distances.js | 5 +- .../libraries/javascript/libs/h3_polyfill.js | 12 +- .../javascript/libs/h3_tochildren.js | 6 - .../libraries/javascript/libs/h3_toparent.js | 6 - .../libraries/javascript/src/h3/README.md | 19 + .../src/h3/h3_center/h3core_custom.js | 1352 ----------------- .../src/h3/h3_center/libh3_custom.js | 24 - .../src/h3/h3_distance/h3core_custom.js | 1352 ----------------- .../src/h3/h3_distance/libh3_custom.js | 24 - .../src/h3/h3_fromlonglat/h3core_custom.js | 1352 ----------------- .../src/h3/h3_fromlonglat/libh3_custom.js | 24 - .../src/h3/h3_kring/h3core_custom.js | 1352 ----------------- .../src/h3/h3_kring/libh3_custom.js | 24 - .../src/h3/h3_kring_distances/libh3_custom.js | 10 +- .../src/h3/h3_polyfill/libh3_custom.js | 10 +- .../src/h3/h3_tochildren/h3core_custom.js | 1352 ----------------- .../src/h3/h3_tochildren/libh3_custom.js | 24 - .../src/h3/h3_toparent/h3core_custom.js | 1352 ----------------- .../src/h3/h3_toparent/libh3_custom.js | 24 - .../javascript/test/clustering.test.js | 1 + .../libraries/javascript/test/h3.test.js | 23 +- .../doc/clustering/ST_CLUSTERKMEANS.md | 2 +- .../snowflake/modules/doc/h3/H3_POLYFILL.md | 59 +- .../doc/h3/images/H3_POLYFILL_MODE_center.png | Bin 0 -> 240546 bytes .../h3/images/H3_POLYFILL_MODE_contains.png | Bin 0 -> 252992 bytes .../h3/images/H3_POLYFILL_MODE_intersects.png | Bin 0 -> 138574 bytes .../doc/processing/ST_DELAUNAYLINES.md | 6 + .../doc/processing/ST_DELAUNAYPOLYGONS.md | 6 + .../modules/doc/processing/ST_VORONOILINES.md | 6 + .../doc/processing/ST_VORONOIPOLYGONS.md | 6 + .../sql/clustering/ST_CLUSTERKMEANS.sql | 8 +- .../snowflake/modules/sql/h3/H3_BOUNDARY.sql | 2 + clouds/snowflake/modules/sql/h3/H3_CENTER.sql | 28 +- .../snowflake/modules/sql/h3/H3_COMPACT.sql | 4 +- .../snowflake/modules/sql/h3/H3_DISTANCE.sql | 33 +- .../modules/sql/h3/H3_FROMGEOGPOINT.sql | 12 +- .../modules/sql/h3/H3_FROMLONGLAT.sql | 26 +- .../modules/sql/h3/H3_INT_TOSTRING.sql | 6 +- clouds/snowflake/modules/sql/h3/H3_KRING.sql | 31 +- .../modules/sql/h3/H3_KRING_DISTANCES.sql | 33 +- .../snowflake/modules/sql/h3/H3_POLYFILL.sql | 222 ++- .../modules/sql/h3/H3_POLYFILL_TABLE.sql | 189 +-- .../modules/sql/h3/H3_RESOLUTION.sql | 11 +- .../modules/sql/h3/H3_STRING_TOINT.sql | 8 +- .../modules/sql/h3/H3_TOCHILDREN.sql | 33 +- .../snowflake/modules/sql/h3/H3_TOPARENT.sql | 31 +- .../modules/sql/utils/_CARTO_ARRAY_ERROR.sql | 7 + .../modules/sql/utils/_GET_DATABASE.sql | 22 + .../modules/sql/utils/_GET_SCHEMA.sql | 24 + .../test/clustering/ST_CLUSTERKMEANS.test.js | 19 + .../fixtures/st_clusterkmeans_out_points1.js | 4 +- .../fixtures/st_clusterkmeans_out_points2.js | 4 +- .../fixtures/st_clusterkmeans_out_points3.js | 4 +- .../modules/test/h3/H3_CENTER.test.js | 6 +- .../modules/test/h3/H3_POLYFILL.spec.js | 163 -- .../modules/test/h3/H3_POLYFILL.test.js | 360 +++++ .../modules/test/h3/H3_POLYFILL_TABLE.test.js | 26 - .../modules/test/h3/H3_RESOLUTION.test.js | 2 +- .../modules/test/utils/GET_DATABASE.test.js | 24 + .../modules/test/utils/GET_SCHEMA.test.js | 22 + clouds/snowflake/version | 2 +- 97 files changed, 1146 insertions(+), 8967 deletions(-) create mode 100644 clouds/snowflake/.~lock.results.csv# delete mode 100644 clouds/snowflake/libraries/javascript/libs/h3_center.js delete mode 100644 clouds/snowflake/libraries/javascript/libs/h3_distance.js delete mode 100644 clouds/snowflake/libraries/javascript/libs/h3_kring.js delete mode 100644 clouds/snowflake/libraries/javascript/libs/h3_tochildren.js delete mode 100644 clouds/snowflake/libraries/javascript/libs/h3_toparent.js create mode 100644 clouds/snowflake/libraries/javascript/src/h3/README.md delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_center/h3core_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_center/libh3_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_distance/h3core_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_distance/libh3_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_fromlonglat/h3core_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_fromlonglat/libh3_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_kring/h3core_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_kring/libh3_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_tochildren/h3core_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_tochildren/libh3_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_toparent/h3core_custom.js delete mode 100644 clouds/snowflake/libraries/javascript/src/h3/h3_toparent/libh3_custom.js create mode 100644 clouds/snowflake/modules/doc/h3/images/H3_POLYFILL_MODE_center.png create mode 100644 clouds/snowflake/modules/doc/h3/images/H3_POLYFILL_MODE_contains.png create mode 100644 clouds/snowflake/modules/doc/h3/images/H3_POLYFILL_MODE_intersects.png create mode 100644 clouds/snowflake/modules/sql/utils/_CARTO_ARRAY_ERROR.sql create mode 100644 clouds/snowflake/modules/sql/utils/_GET_DATABASE.sql create mode 100644 clouds/snowflake/modules/sql/utils/_GET_SCHEMA.sql delete mode 100644 clouds/snowflake/modules/test/h3/H3_POLYFILL.spec.js create mode 100644 clouds/snowflake/modules/test/h3/H3_POLYFILL.test.js delete mode 100644 clouds/snowflake/modules/test/h3/H3_POLYFILL_TABLE.test.js create mode 100644 clouds/snowflake/modules/test/utils/GET_DATABASE.test.js create mode 100644 clouds/snowflake/modules/test/utils/GET_SCHEMA.test.js diff --git a/.github/workflows/snowflake.yml b/.github/workflows/snowflake.yml index c71d94534..b3ba35762 100644 --- a/.github/workflows/snowflake.yml +++ b/.github/workflows/snowflake.yml @@ -92,7 +92,7 @@ jobs: if: github.ref_name == 'main' needs: test runs-on: ubuntu-20.04 - timeout-minutes: 20 + timeout-minutes: 30 env: APP_PACKAGE_NAME: ${{ secrets.SF_NATIVE_APP_PACKAGE_NAME_CD }} APP_NAME: ${{ secrets.SF_NATIVE_APP_NAME_CD }} diff --git a/.gitignore b/.gitignore index d6ca85622..9288cf6dc 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ MANIFEST # IntelliJ .idea/ + +# Vim +*.swp diff --git a/CHANGELOG.md b/CHANGELOG.md index f939a6f08..6f8988155 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ CARTO Analytics Toolbox Core. All notable commits to this project will be documented in this file. +## 2024-04-18 + +- chore(sf|h3): reimplement basic h3 functions (#489) +- docs(bq,sf,rs|processing): update voronoi doc (#492) +- chore(sf|h3): reimplement polyfill h3 functions (#490) +- fix(bq,sf,rs|clustering): improve how ST_CLUSTERKMEANS deals with duplicates (#491, #495) +- chore(deps): bump sqlparse from 0.4.4 to 0.5.0 in /clouds/redshift/common (#494) +- chore(deps): bump sqlparse from 0.4.4 to 0.5.0 in /clouds/postgres/common (#493) +- chore(deps): fix CI crashing because native-apps timeout and sql-parse version (#496) + ## 2024-03-18 - fix(sf): CI and CD not working because of snowflake driver breaking changes (#484) diff --git a/README.md b/README.md index ee42e690c..b1f3b5ca4 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,23 @@ Right now the only way to get access the Analytics toolbox is by installing it d | Postgres | [README.md](./clouds/postgres/README.md) | | Databricks | [README.md](./clouds/databricks/README.md) | +### Useful make commands + +To run tests, switch to a specific cloud directory. For example, Showflake: `cd clouds/snowflake`. + +``` +# All tests +make test + +# Specific module(s) +make test modules=h3 +make test modules=h3,transformations + +# Specific function(s) +make test functions=H3_POLYFILL +make test functions=H3_POLYFILL,ST_BUFFER +``` + ## Contribute This project is public. We are more than happy of receiving feedback and contributions. Feel free to open a ticket with a bug, a doubt or a discussion, or open a pull request with a fix or a new feature. diff --git a/clouds/bigquery/CHANGELOG.md b/clouds/bigquery/CHANGELOG.md index f510577fd..2e7b143db 100644 --- a/clouds/bigquery/CHANGELOG.md +++ b/clouds/bigquery/CHANGELOG.md @@ -4,6 +4,11 @@ CARTO Analytics Toolbox Core for BigQuery. All notable commits to this project will be documented in this file. +## [1.2.2] - 2024-04-18 + +- docs(processing): update voronoi doc (#492) +- fix(clustering): improve how ST_CLUSTERKMEANS deals with duplicates (#491, #495) + ## [1.2.1] - 2024-03-18 - fix(random): ST_GENERATEPOINTS returning exact name of points (#486) diff --git a/clouds/bigquery/libraries/javascript/src/clustering.js b/clouds/bigquery/libraries/javascript/src/clustering.js index dd050e749..cf17cabfa 100644 --- a/clouds/bigquery/libraries/javascript/src/clustering.js +++ b/clouds/bigquery/libraries/javascript/src/clustering.js @@ -1,7 +1,29 @@ import { featureCollection, feature, clustersKmeans } from '@turf/turf'; +function prioritizeDistinctSort (arr) { + const uniqueValues = []; + const duplicatedValues = []; + + // Split the array into unique and duplicated values + const countMap = {}; + for (const item of arr) { + if (countMap[item] === undefined) { + countMap[item] = 1; + uniqueValues.push(item); + } else { + countMap[item]++; + duplicatedValues.push(item); + } + } + + // Concatenate unique and duplicated values + const result = [...uniqueValues, ...duplicatedValues]; + return result; +} + export default { featureCollection, feature, - clustersKmeans + clustersKmeans, + prioritizeDistinctSort }; \ No newline at end of file diff --git a/clouds/bigquery/libraries/javascript/test/clustering.test.js b/clouds/bigquery/libraries/javascript/test/clustering.test.js index 1f77e4efc..0441d1608 100644 --- a/clouds/bigquery/libraries/javascript/test/clustering.test.js +++ b/clouds/bigquery/libraries/javascript/test/clustering.test.js @@ -4,4 +4,5 @@ test('clustering library defined', () => { expect(lib.clustering.featureCollection).toBeDefined(); expect(lib.clustering.feature).toBeDefined(); expect(lib.clustering.clustersKmeans).toBeDefined(); + expect(lib.clustering.prioritizeDistinctSort).toBeDefined(); }); \ No newline at end of file diff --git a/clouds/bigquery/modules/doc/clustering/ST_CLUSTERKMEANS.md b/clouds/bigquery/modules/doc/clustering/ST_CLUSTERKMEANS.md index 5b3d6cd75..8234c6e0a 100644 --- a/clouds/bigquery/modules/doc/clustering/ST_CLUSTERKMEANS.md +++ b/clouds/bigquery/modules/doc/clustering/ST_CLUSTERKMEANS.md @@ -9,7 +9,7 @@ ST_CLUSTERKMEANS(geog, numberOfClusters) Takes a set of points as input and partitions them into clusters using the k-means algorithm. Returns an array of tuples with the cluster index for each of the input features and the input geometry. * `geog`: `ARRAY` points to be clustered. -* `numberOfClusters`: `INT64`|`NULL` numberOfClusters that will be generated. If `NULL` the default value `Math.sqrt(/2)` is used. +* `numberOfClusters`: `INT64`|`NULL` numberOfClusters that will be generated. If `NULL` the default value `Math.sqrt(/2)` is used. The output number of cluster cannot be greater to the number of distinct points of the `geog`. **Return type** diff --git a/clouds/bigquery/modules/doc/processing/ST_DELAUNAYLINES.md b/clouds/bigquery/modules/doc/processing/ST_DELAUNAYLINES.md index 4b96923d2..0c11c24ea 100644 --- a/clouds/bigquery/modules/doc/processing/ST_DELAUNAYLINES.md +++ b/clouds/bigquery/modules/doc/processing/ST_DELAUNAYLINES.md @@ -12,6 +12,12 @@ Calculates the Delaunay triangulation of the points provided. An array of line s Due to technical limitations of the underlying libraries used, the input points' coordinates are truncated to 5 decimal places in order to avoid problems that happen with close but distinct input points. This limits the precision of the results and can alter slightly the position of the resulting polygons (about 1 meter). This can also result in some points being merged together, so that fewer polygons than expected may result. +````hint:warning +**warning** + +The maximum number of points typically used to compute Delaunay diagrams is 300,000. This limit ensures efficient computation while maintaining accuracy in delineating regions based on proximity to specified points. +```` + **Return type** `ARRAY` diff --git a/clouds/bigquery/modules/doc/processing/ST_DELAUNAYPOLYGONS.md b/clouds/bigquery/modules/doc/processing/ST_DELAUNAYPOLYGONS.md index 70fe57865..221d62bfb 100644 --- a/clouds/bigquery/modules/doc/processing/ST_DELAUNAYPOLYGONS.md +++ b/clouds/bigquery/modules/doc/processing/ST_DELAUNAYPOLYGONS.md @@ -12,6 +12,12 @@ Calculates the Delaunay triangulation of the points provided. An array of polygo Due to technical limitations of the underlying libraries used, the input points' coordinates are truncated to 5 decimal places in order to avoid problems that happen with close but distinct input points. This limits the precision of the results and can alter slightly the position of the resulting polygons (about 1 meter). This can also result in some points being merged together, so that fewer polygons than expected may result. +````hint:warning +**warning** + +The maximum number of points typically used to compute Delaunay diagrams is 300,000. This limit ensures efficient computation while maintaining accuracy in delineating regions based on proximity to specified points. +```` + **Return type** `ARRAY` diff --git a/clouds/bigquery/modules/doc/processing/ST_VORONOILINES.md b/clouds/bigquery/modules/doc/processing/ST_VORONOILINES.md index a8c71d58e..6acabf128 100644 --- a/clouds/bigquery/modules/doc/processing/ST_VORONOILINES.md +++ b/clouds/bigquery/modules/doc/processing/ST_VORONOILINES.md @@ -13,6 +13,12 @@ Calculates the Voronoi diagram of the points provided. An array of lines is retu Due to technical limitations of the underlying libraries used, the input points' coordinates are truncated to 5 decimal places in order to avoid problems that happen with close but distinct input points. This limits the precision of the results and can alter slightly the position of the resulting lines (about 1 meter). This can also result in some points being merged together, so that fewer lines than input points may result. +````hint:warning +**warning** + +The maximum number of points typically used to compute Voronoi diagrams is 300,000. This limit ensures efficient computation while maintaining accuracy in delineating regions based on proximity to specified points. +```` + **Return type** `ARRAY` diff --git a/clouds/bigquery/modules/doc/processing/ST_VORONOIPOLYGONS.md b/clouds/bigquery/modules/doc/processing/ST_VORONOIPOLYGONS.md index f9d35af2a..4962e351f 100644 --- a/clouds/bigquery/modules/doc/processing/ST_VORONOIPOLYGONS.md +++ b/clouds/bigquery/modules/doc/processing/ST_VORONOIPOLYGONS.md @@ -13,6 +13,12 @@ Calculates the Voronoi diagram of the points provided. An array of polygons is r Due to technical limitations of the underlying libraries used, the input points' coordinates are truncated to 5 decimal places in order to avoid problems that happen with close but distinct input points. This limits the precision of the results and can alter slightly the position of the resulting polygons (about 1 meter). This can also result in some points being merged together, so that fewer polygons than input points may result. +````hint:warning +**warning** + +The maximum number of points typically used to compute Voronoi diagrams is 300,000. This limit ensures efficient computation while maintaining accuracy in delineating regions based on proximity to specified points. +```` + **Return type** `ARRAY` diff --git a/clouds/bigquery/modules/sql/clustering/ST_CLUSTERKMEANS.sql b/clouds/bigquery/modules/sql/clustering/ST_CLUSTERKMEANS.sql index 8431fb011..3a84db951 100644 --- a/clouds/bigquery/modules/sql/clustering/ST_CLUSTERKMEANS.sql +++ b/clouds/bigquery/modules/sql/clustering/ST_CLUSTERKMEANS.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2021-2024 CARTO +-------------------------------- CREATE OR REPLACE FUNCTION `@@BQ_DATASET@@.__CLUSTERKMEANS` (geojson ARRAY, numberOfClusters INT64) @@ -15,9 +15,11 @@ AS """ const options = {}; if (numberOfClusters != null) { options.numberOfClusters = Number(numberOfClusters); + } else { + options.numberOfClusters = parseInt(Math.sqrt(geojson.length/2)) } options.mutate = true; - const featuresCollection = lib.clustering.featureCollection(geojson.map(x => lib.clustering.feature(JSON.parse(x)))); + const featuresCollection = lib.clustering.featureCollection(lib.clustering.prioritizeDistinctSort(geojson).map(x => lib.clustering.feature(JSON.parse(x)))); lib.clustering.clustersKmeans(featuresCollection, options); const cluster = []; featuresCollection.features.forEach(function(item, index, array) { diff --git a/clouds/bigquery/modules/test/clustering/ST_CLUSTERKMEANS.test.js b/clouds/bigquery/modules/test/clustering/ST_CLUSTERKMEANS.test.js index 0b9867861..7e8f3fbf5 100644 --- a/clouds/bigquery/modules/test/clustering/ST_CLUSTERKMEANS.test.js +++ b/clouds/bigquery/modules/test/clustering/ST_CLUSTERKMEANS.test.js @@ -17,6 +17,24 @@ test('ST_CLUSTERKMEANS should work', async () => { expect(rows[0].clusterKMeans3).toEqual(JSON.parse(points3FixturesOut.value)); }); +test('ST_CLUSTERKMEANS should work for duplicated entries ', async () => { + const requestedClusters = 3; + // When the input array contains consecutives entries at the beggining, + // it should be reordered to the required number of clusters + const query = `SELECT + \`@@BQ_DATASET@@.ST_CLUSTERKMEANS\`([ST_GEOGPOINT(0, 0),ST_GEOGPOINT(0, 0), ST_GEOGPOINT(0, 0), ST_GEOGPOINT(0, 1), ST_GEOGPOINT(0, 1), ST_GEOGPOINT(0, 1), ST_GEOGPOINT(5, 0)], ${requestedClusters}) as clusterKMeans + `; + const rows = await runQuery(query); + const uniqueClusters = new Set(); + + rows[0].clusterKMeans.forEach(item => { + uniqueClusters.add(item.cluster); + }); + + expect(rows.length).toEqual(1); + expect(uniqueClusters.size).toEqual(requestedClusters); +}); + test('ST_CLUSTERKMEANS should return NULL if any NULL mandatory argument', async () => { const query = `SELECT \`@@BQ_DATASET@@.ST_CLUSTERKMEANS\`(NULL, 2) as clusterKMeans1 diff --git a/clouds/bigquery/modules/test/clustering/fixtures/st_clusterkmeans_points2_out.js b/clouds/bigquery/modules/test/clustering/fixtures/st_clusterkmeans_points2_out.js index f237c83ff..07aa17ffc 100644 --- a/clouds/bigquery/modules/test/clustering/fixtures/st_clusterkmeans_points2_out.js +++ b/clouds/bigquery/modules/test/clustering/fixtures/st_clusterkmeans_points2_out.js @@ -1,3 +1,3 @@ module.exports = { - value: '[{"cluster":0,"geom":{"value":"POINT(0 0)"}},{"cluster":0,"geom":{"value":"POINT(0 1)"}},{"cluster":2,"geom":{"value":"POINT(5 0)"}},{"cluster":0,"geom":{"value":"POINT(1 0)"}},{"cluster":0,"geom":{"value":"POINT(0 1)"}},{"cluster":2,"geom":{"value":"POINT(5 0)"}},{"cluster":1,"geom":{"value":"POINT(1 19)"}},{"cluster":2,"geom":{"value":"POINT(12 1)"}},{"cluster":2,"geom":{"value":"POINT(9 2)"}},{"cluster":1,"geom":{"value":"POINT(1 10)"}},{"cluster":0,"geom":{"value":"POINT(-3 1)"}},{"cluster":2,"geom":{"value":"POINT(5 5)"}},{"cluster":2,"geom":{"value":"POINT(8 6)"}},{"cluster":2,"geom":{"value":"POINT(10 10)"}},{"cluster":0,"geom":{"value":"POINT(-3 -5)"}},{"cluster":2,"geom":{"value":"POINT(6 5)"}},{"cluster":1,"geom":{"value":"POINT(-8 9)"}},{"cluster":0,"geom":{"value":"POINT(1 -10)"}},{"cluster":0,"geom":{"value":"POINT(2 -2)"}},{"cluster":0,"geom":{"value":"POINT(0 0)"}},{"cluster":1,"geom":{"value":"POINT(3 10)"}}]' + value: '[{"cluster":0,"geom":{"value":"POINT(0 0)"}},{"cluster":0,"geom":{"value":"POINT(0 1)"}},{"cluster":2,"geom":{"value":"POINT(5 0)"}},{"cluster":0,"geom":{"value":"POINT(1 0)"}},{"cluster":1,"geom":{"value":"POINT(1 19)"}},{"cluster":2,"geom":{"value":"POINT(12 1)"}},{"cluster":2,"geom":{"value":"POINT(9 2)"}},{"cluster":1,"geom":{"value":"POINT(1 10)"}},{"cluster":0,"geom":{"value":"POINT(-3 1)"}},{"cluster":2,"geom":{"value":"POINT(5 5)"}},{"cluster":2,"geom":{"value":"POINT(8 6)"}},{"cluster":2,"geom":{"value":"POINT(10 10)"}},{"cluster":0,"geom":{"value":"POINT(-3 -5)"}},{"cluster":2,"geom":{"value":"POINT(6 5)"}},{"cluster":1,"geom":{"value":"POINT(-8 9)"}},{"cluster":0,"geom":{"value":"POINT(1 -10)"}},{"cluster":0,"geom":{"value":"POINT(2 -2)"}},{"cluster":1,"geom":{"value":"POINT(3 10)"}},{"cluster":0,"geom":{"value":"POINT(0 1)"}},{"cluster":2,"geom":{"value":"POINT(5 0)"}},{"cluster":0,"geom":{"value":"POINT(0 0)"}}]' } \ No newline at end of file diff --git a/clouds/bigquery/modules/test/clustering/fixtures/st_clusterkmeans_points3_out.js b/clouds/bigquery/modules/test/clustering/fixtures/st_clusterkmeans_points3_out.js index 69840d2e1..a03a346df 100644 --- a/clouds/bigquery/modules/test/clustering/fixtures/st_clusterkmeans_points3_out.js +++ b/clouds/bigquery/modules/test/clustering/fixtures/st_clusterkmeans_points3_out.js @@ -1,3 +1,3 @@ module.exports = { - value: '[{"cluster":1,"geom":{"value":"POINT(0 0)"}},{"cluster":1,"geom":{"value":"POINT(0 1)"}},{"cluster":2,"geom":{"value":"POINT(5 0)"}},{"cluster":1,"geom":{"value":"POINT(1 0)"}},{"cluster":1,"geom":{"value":"POINT(0 1)"}},{"cluster":2,"geom":{"value":"POINT(5 0)"}},{"cluster":4,"geom":{"value":"POINT(1 19)"}},{"cluster":2,"geom":{"value":"POINT(12 1)"}},{"cluster":2,"geom":{"value":"POINT(9 2)"}},{"cluster":4,"geom":{"value":"POINT(1 10)"}},{"cluster":1,"geom":{"value":"POINT(-3 1)"}},{"cluster":2,"geom":{"value":"POINT(5 5)"}},{"cluster":2,"geom":{"value":"POINT(8 6)"}},{"cluster":2,"geom":{"value":"POINT(10 10)"}},{"cluster":0,"geom":{"value":"POINT(-3 -5)"}},{"cluster":2,"geom":{"value":"POINT(6 5)"}},{"cluster":4,"geom":{"value":"POINT(-8 9)"}},{"cluster":3,"geom":{"value":"POINT(1 -10)"}},{"cluster":1,"geom":{"value":"POINT(2 -2)"}},{"cluster":1,"geom":{"value":"POINT(0 0)"}},{"cluster":4,"geom":{"value":"POINT(3 10)"}}]' + value: '[{"cluster":0,"geom":{"value":"POINT(0 0)"}},{"cluster":0,"geom":{"value":"POINT(0 1)"}},{"cluster":2,"geom":{"value":"POINT(5 0)"}},{"cluster":0,"geom":{"value":"POINT(1 0)"}},{"cluster":4,"geom":{"value":"POINT(1 19)"}},{"cluster":2,"geom":{"value":"POINT(12 1)"}},{"cluster":2,"geom":{"value":"POINT(9 2)"}},{"cluster":4,"geom":{"value":"POINT(1 10)"}},{"cluster":0,"geom":{"value":"POINT(-3 1)"}},{"cluster":2,"geom":{"value":"POINT(5 5)"}},{"cluster":2,"geom":{"value":"POINT(8 6)"}},{"cluster":2,"geom":{"value":"POINT(10 10)"}},{"cluster":3,"geom":{"value":"POINT(-3 -5)"}},{"cluster":2,"geom":{"value":"POINT(6 5)"}},{"cluster":1,"geom":{"value":"POINT(-8 9)"}},{"cluster":3,"geom":{"value":"POINT(1 -10)"}},{"cluster":0,"geom":{"value":"POINT(2 -2)"}},{"cluster":4,"geom":{"value":"POINT(3 10)"}},{"cluster":0,"geom":{"value":"POINT(0 1)"}},{"cluster":2,"geom":{"value":"POINT(5 0)"}},{"cluster":0,"geom":{"value":"POINT(0 0)"}}]' } \ No newline at end of file diff --git a/clouds/bigquery/version b/clouds/bigquery/version index 6085e9465..23aa83906 100644 --- a/clouds/bigquery/version +++ b/clouds/bigquery/version @@ -1 +1 @@ -1.2.1 +1.2.2 diff --git a/clouds/postgres/common/python3_requirements.txt b/clouds/postgres/common/python3_requirements.txt index 0292bd135..ab1c68abe 100644 --- a/clouds/postgres/common/python3_requirements.txt +++ b/clouds/postgres/common/python3_requirements.txt @@ -5,7 +5,7 @@ pep8-naming==0.12.1 brunette==0.2.0 pytest==6.2.4 psycopg2-binary==2.9.1 -sqlparse==0.4.4 +sqlparse==0.5.0 wheel==0.38.1 tqdm==4.64.0 GeoAlchemy2==0.9.3 diff --git a/clouds/redshift/CHANGELOG.md b/clouds/redshift/CHANGELOG.md index 156f25ca8..2bb8d7e69 100644 --- a/clouds/redshift/CHANGELOG.md +++ b/clouds/redshift/CHANGELOG.md @@ -4,6 +4,11 @@ CARTO Analytics Toolbox Core for Redshift. All notable commits to this project will be documented in this file. +## [1.1.1] - 2024-04-18 + +- docs(processing): update voronoi doc (#492) +- fix(clustering): improve how ST_CLUSTERKMEANS deals with duplicates (#491, #495) + ## [1.1.0] - 2024-01-17 - feat(quadbin): add function QUADBIN_DISTANCE (#457) diff --git a/clouds/redshift/libraries/python/lib/clustering/__init__.py b/clouds/redshift/libraries/python/lib/clustering/__init__.py index 2f8b44878..8db9a6911 100644 --- a/clouds/redshift/libraries/python/lib/clustering/__init__.py +++ b/clouds/redshift/libraries/python/lib/clustering/__init__.py @@ -11,6 +11,61 @@ def load_geom(geom): return loads(geom) +def remove_duplicated_coords(arr): + import numpy as np + + unique_rows = [] + for row in arr: + if not any(np.array_equal(row, unique_row) for unique_row in unique_rows): + unique_rows.append(row) + return np.array(unique_rows) + + +def reorder_coords(coords): + import numpy as np + + unique_coords = [] + duplicated_coords = [] + + # Split the array into unique and duplicated coordinates + count_map = {} + for coord in coords: + coord_str = tuple(coord) + if coord_str not in count_map: + count_map[coord_str] = 1 + unique_coords.append(coord) + else: + count_map[coord_str] += 1 + duplicated_coords.append(coord) + + # Convert lists to NumPy arrays for sorting + unique_coords = np.array(unique_coords) + duplicated_coords = np.array(duplicated_coords) + + if unique_coords.size > 0: + if duplicated_coords.size > 0: + # Concatenate unique and duplicated coordinates + return np.concatenate((unique_coords, duplicated_coords)) + else: + return unique_coords + else: + if duplicated_coords.size > 0: + return duplicated_coords + else: + # This should never happen, so just returning the input + return coords + + +def count_distinct_coords(coords): + import numpy as np + + count_map = {} + for coord in coords: + coord_str = tuple(coord) + count_map[coord_str] = count_map.get(coord_str, 0) + 1 + return len(count_map) + + def clusterkmeanstable(geom, k): from .kmeans import KMeans import json @@ -18,9 +73,11 @@ def clusterkmeanstable(geom, k): geom = load_geom(geom) points = geom['_coords'] - coords = np.array( - [[points[i], points[i + 1]] for i in range(0, len(points) - 1, 2)] + coords = reorder_coords( + np.array([[points[i], points[i + 1]] for i in range(0, len(points) - 1, 2)]) ) + # k cannot be greater than the number of distinct coordinates + k = min(k, count_distinct_coords(coords)) cluster_idxs, centers, loss = KMeans()(coords, k) @@ -39,14 +96,17 @@ def clusterkmeans(geom, k): if geom.type != 'MultiPoint': raise Exception('Invalid operation: Input points parameter must be MultiPoint.') else: - coords = np.array(list(geojson.utils.coords(geom))) + coords = reorder_coords(np.array(list(geojson.utils.coords(geom)))) + # k cannot be greater than the number of distinct coordinates + k = min(k, count_distinct_coords(coords)) + cluster_idxs, centers, loss = KMeans()(coords, k) return geojson.dumps( [ { 'cluster': cluster_idxs[idx], - 'geom': {'coordinates': point, 'type': 'Point'}, + 'geom': {'coordinates': point.tolist(), 'type': 'Point'}, } - for idx, point in enumerate(geom['coordinates']) + for idx, point in enumerate(coords) ] ) diff --git a/clouds/redshift/libraries/python/lib/clustering/kmeans.py b/clouds/redshift/libraries/python/lib/clustering/kmeans.py index bad0c8db2..d86542f0d 100644 --- a/clouds/redshift/libraries/python/lib/clustering/kmeans.py +++ b/clouds/redshift/libraries/python/lib/clustering/kmeans.py @@ -154,7 +154,9 @@ def __call__( cluster centers: k x d numpy array, the centers loss: final loss value of the objective function of KMeans """ - centers = self._init_centers(points, k, **kwargs) + # centers = self._init_centers(points, k, **kwargs) + # instead of using random initialization, we will use the first k points + centers = points[:k] prev_loss = 0 for it in range(max_iters): cluster_idx = self._update_assignment(centers, points) diff --git a/clouds/redshift/modules/doc/clustering/ST_CLUSTERKMEANS.md b/clouds/redshift/modules/doc/clustering/ST_CLUSTERKMEANS.md index a4deaabb2..805acd5a6 100644 --- a/clouds/redshift/modules/doc/clustering/ST_CLUSTERKMEANS.md +++ b/clouds/redshift/modules/doc/clustering/ST_CLUSTERKMEANS.md @@ -9,7 +9,7 @@ ST_CLUSTERKMEANS(geog [, numberOfClusters]) Takes a set of points as input and partitions them into clusters using the k-means algorithm. Returns an array of tuples with the cluster index for each of the input features and the input geometry. * `geog`: `GEOMETRY` points to be clustered. -* `numberOfClusters` (optional): `INT` number of clusters that will be generated. It defaults to the square root of half the number of points (`sqrt(/2)`). +* `numberOfClusters` (optional): `INT` number of clusters that will be generated. It defaults to the square root of half the number of points (`sqrt(/2)`). The output number of cluster cannot be greater to the number of distinct points of the `geog`. **Return type** diff --git a/clouds/redshift/modules/doc/processing/ST_DELAUNAYLINES.md b/clouds/redshift/modules/doc/processing/ST_DELAUNAYLINES.md index 37802a1ae..4f9f17d73 100644 --- a/clouds/redshift/modules/doc/processing/ST_DELAUNAYLINES.md +++ b/clouds/redshift/modules/doc/processing/ST_DELAUNAYLINES.md @@ -10,6 +10,12 @@ Calculates the Delaunay triangulation of the points provided. A MultiLineString * `points`: `GEOMETRY` MultiPoint input to the Delaunay triangulation. +````hint:warning +**warning** + +The maximum number of points typically used to compute Delaunay diagrams is 300,000. This limit ensures efficient computation while maintaining accuracy in delineating regions based on proximity to specified points. +```` + **Return type** `VARCHAR(MAX)` diff --git a/clouds/redshift/modules/doc/processing/ST_DELAUNAYPOLYGONS.md b/clouds/redshift/modules/doc/processing/ST_DELAUNAYPOLYGONS.md index 4fb96ab0f..a001d8d41 100644 --- a/clouds/redshift/modules/doc/processing/ST_DELAUNAYPOLYGONS.md +++ b/clouds/redshift/modules/doc/processing/ST_DELAUNAYPOLYGONS.md @@ -10,6 +10,12 @@ Calculates the Delaunay triangulation of the points provided. A MultiPolygon obj * `points`: `GEOMETRY` MultiPoint input to the Delaunay triangulation. +````hint:warning +**warning** + +The maximum number of points typically used to compute Delaunay diagrams is 300,000. This limit ensures efficient computation while maintaining accuracy in delineating regions based on proximity to specified points. +```` + **Return type** `VARCHAR(MAX)` diff --git a/clouds/redshift/modules/doc/processing/ST_VORONOILINES.md b/clouds/redshift/modules/doc/processing/ST_VORONOILINES.md index 5404eefa1..77f4c9f9e 100644 --- a/clouds/redshift/modules/doc/processing/ST_VORONOILINES.md +++ b/clouds/redshift/modules/doc/processing/ST_VORONOILINES.md @@ -10,6 +10,12 @@ Calculates the Voronoi diagram of the points provided. A MultiLineString object * `points`: `GEOMETRY` MultiPoint input to the Voronoi diagram. +````hint:warning +**warning** + +The maximum number of points typically used to compute Voronoi diagrams is 300,000. This limit ensures efficient computation while maintaining accuracy in delineating regions based on proximity to specified points. +```` + **Return type** `VARCHAR(MAX)` diff --git a/clouds/redshift/modules/doc/processing/ST_VORONOIPOLYGONS.md b/clouds/redshift/modules/doc/processing/ST_VORONOIPOLYGONS.md index c9b70a672..e235f4c15 100644 --- a/clouds/redshift/modules/doc/processing/ST_VORONOIPOLYGONS.md +++ b/clouds/redshift/modules/doc/processing/ST_VORONOIPOLYGONS.md @@ -10,6 +10,12 @@ Calculates the Voronoi diagram of the points provided. A MultiPolygon object is * `points`: `GEOMETRY` MultiPoint input to the Voronoi diagram. +````hint:warning +**warning** + +The maximum number of points typically used to compute Voronoi diagrams is 300,000. This limit ensures efficient computation while maintaining accuracy in delineating regions based on proximity to specified points. +```` + **Return type** `VARCHAR(MAX)` diff --git a/clouds/redshift/modules/sql/clustering/ST_CLUSTERKMEANS.sql b/clouds/redshift/modules/sql/clustering/ST_CLUSTERKMEANS.sql index 728f4ffeb..aecfa64a1 100644 --- a/clouds/redshift/modules/sql/clustering/ST_CLUSTERKMEANS.sql +++ b/clouds/redshift/modules/sql/clustering/ST_CLUSTERKMEANS.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2021-2024 CARTO +-------------------------------- CREATE OR REPLACE FUNCTION @@RS_SCHEMA@@.__CLUSTERKMEANS (geom VARCHAR(MAX), numberofClusters INT) diff --git a/clouds/redshift/modules/test/clustering/fixtures/st_clusterkmeans_out.txt b/clouds/redshift/modules/test/clustering/fixtures/st_clusterkmeans_out.txt index b34349470..753914357 100644 --- a/clouds/redshift/modules/test/clustering/fixtures/st_clusterkmeans_out.txt +++ b/clouds/redshift/modules/test/clustering/fixtures/st_clusterkmeans_out.txt @@ -1,3 +1,3 @@ -[{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[1.0,0.0]}}] -[{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[1.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[1.0,19.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[12.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[9.0,2.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[1.0,10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[-3.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[5.0,5.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[8.0,6.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[10.0,10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[-3.0,-5.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[6.0,5.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[-8.0,9.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[1.0,-10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[2.0,-2.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,0.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[3.0,10.0]}}] -[{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[1.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":4,"geom":{"type":"Point","coordinates":[1.0,19.0]}},{"cluster":3,"geom":{"type":"Point","coordinates":[12.0,1.0]}},{"cluster":3,"geom":{"type":"Point","coordinates":[9.0,2.0]}},{"cluster":4,"geom":{"type":"Point","coordinates":[1.0,10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[-3.0,1.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[5.0,5.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[8.0,6.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[10.0,10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[-3.0,-5.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[6.0,5.0]}},{"cluster":4,"geom":{"type":"Point","coordinates":[-8.0,9.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[1.0,-10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[2.0,-2.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,0.0]}},{"cluster":4,"geom":{"type":"Point","coordinates":[3.0,10.0]}}] \ No newline at end of file +[{"cluster":1,"geom":{"type":"Point","coordinates":[0.0,0.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[1.0,0.0]}}] +[{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[1.0,0.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[1.0,19.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[12.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[9.0,2.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[1.0,10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[-3.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[5.0,5.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[8.0,6.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[10.0,10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[-3.0,-5.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[6.0,5.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[-8.0,9.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[1.0,-10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[2.0,-2.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[3.0,10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,0.0]}}] +[{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[1.0,0.0]}},{"cluster":4,"geom":{"type":"Point","coordinates":[1.0,19.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[12.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[9.0,2.0]}},{"cluster":4,"geom":{"type":"Point","coordinates":[1.0,10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[-3.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[5.0,5.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[8.0,6.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[10.0,10.0]}},{"cluster":3,"geom":{"type":"Point","coordinates":[-3.0,-5.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[6.0,5.0]}},{"cluster":1,"geom":{"type":"Point","coordinates":[-8.0,9.0]}},{"cluster":3,"geom":{"type":"Point","coordinates":[1.0,-10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[2.0,-2.0]}},{"cluster":4,"geom":{"type":"Point","coordinates":[3.0,10.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,1.0]}},{"cluster":2,"geom":{"type":"Point","coordinates":[5.0,0.0]}},{"cluster":0,"geom":{"type":"Point","coordinates":[0.0,0.0]}}] diff --git a/clouds/redshift/modules/test/clustering/test_ST_CLUSTERKMEANS.py b/clouds/redshift/modules/test/clustering/test_ST_CLUSTERKMEANS.py index 8d37a8e35..2073b1374 100644 --- a/clouds/redshift/modules/test/clustering/test_ST_CLUSTERKMEANS.py +++ b/clouds/redshift/modules/test/clustering/test_ST_CLUSTERKMEANS.py @@ -28,6 +28,28 @@ def test_st_clusterkmeans(): assert str(result[0]) == lines[idx].rstrip() +def test_st_clusterkmeans_duplicated_entries(): + import json + + requested_clusters = 3 + # When the input array contains consecutives entries at the beggining, + # it should be reordered to the required number of clusters + results = run_query( + f""" + SELECT @@RS_SCHEMA@@.ST_CLUSTERKMEANS( + ST_GEOMFROMTEXT( + 'MULTIPOINT ((0 0), (0 0), (0 0), (0 1), (0 1), (0 1), (5 0))'), + {requested_clusters}) + """ + ) + results_data = json.loads(results[0][0]) + unique_clusters = set() + for item in results_data: + unique_clusters.add(item['cluster']) + + assert len(unique_clusters) == requested_clusters + + def test_st_clusterkmeans_default_args_success(): with open(f'{here}/fixtures/st_clusterkmeans_in.txt', 'r') as fixture_file: lines = fixture_file.readlines() diff --git a/clouds/redshift/version b/clouds/redshift/version index 9084fa2f7..524cb5524 100644 --- a/clouds/redshift/version +++ b/clouds/redshift/version @@ -1 +1 @@ -1.1.0 +1.1.1 diff --git a/clouds/snowflake/.~lock.results.csv# b/clouds/snowflake/.~lock.results.csv# new file mode 100644 index 000000000..044c5a006 --- /dev/null +++ b/clouds/snowflake/.~lock.results.csv# @@ -0,0 +1 @@ +,dean,thinkpad,27.03.2024 10:56,file:///home/dean/.config/libreoffice/4; \ No newline at end of file diff --git a/clouds/snowflake/CHANGELOG.md b/clouds/snowflake/CHANGELOG.md index cbb151706..399c14cac 100644 --- a/clouds/snowflake/CHANGELOG.md +++ b/clouds/snowflake/CHANGELOG.md @@ -4,6 +4,13 @@ CARTO Analytics Toolbox Core for Snowflake. All notable commits to this project will be documented in this file. +## [1.2.2] - 2024-04-18 + +- chore(h3): reimplement basic h3 functions (#489) +- docs(processing): update voronoi doc (#492) +- chore(h3): reimplement polyfill h3 functions (#490) +- fix(clustering): improve how ST_CLUSTERKMEANS deals with duplicates (#491, #495) + ## [1.2.1] - 2024-02-15 - chore: add additional tables to native apps (#473) diff --git a/clouds/snowflake/libraries/javascript/libs/clustering.js b/clouds/snowflake/libraries/javascript/libs/clustering.js index dd050e749..cf17cabfa 100644 --- a/clouds/snowflake/libraries/javascript/libs/clustering.js +++ b/clouds/snowflake/libraries/javascript/libs/clustering.js @@ -1,7 +1,29 @@ import { featureCollection, feature, clustersKmeans } from '@turf/turf'; +function prioritizeDistinctSort (arr) { + const uniqueValues = []; + const duplicatedValues = []; + + // Split the array into unique and duplicated values + const countMap = {}; + for (const item of arr) { + if (countMap[item] === undefined) { + countMap[item] = 1; + uniqueValues.push(item); + } else { + countMap[item]++; + duplicatedValues.push(item); + } + } + + // Concatenate unique and duplicated values + const result = [...uniqueValues, ...duplicatedValues]; + return result; +} + export default { featureCollection, feature, - clustersKmeans + clustersKmeans, + prioritizeDistinctSort }; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/libs/h3_center.js b/clouds/snowflake/libraries/javascript/libs/h3_center.js deleted file mode 100644 index e1994b990..000000000 --- a/clouds/snowflake/libraries/javascript/libs/h3_center.js +++ /dev/null @@ -1,6 +0,0 @@ -import { h3IsValid, h3ToGeo } from '../src/h3/h3_center/h3core_custom'; - -export default { - h3IsValid, - h3ToGeo -}; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/libs/h3_distance.js b/clouds/snowflake/libraries/javascript/libs/h3_distance.js deleted file mode 100644 index 38bf0e1f9..000000000 --- a/clouds/snowflake/libraries/javascript/libs/h3_distance.js +++ /dev/null @@ -1,5 +0,0 @@ -import { h3Distance } from '../src/h3/h3_distance/h3core_custom'; - -export default { - h3Distance -}; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/libs/h3_kring.js b/clouds/snowflake/libraries/javascript/libs/h3_kring.js deleted file mode 100644 index e251ca62b..000000000 --- a/clouds/snowflake/libraries/javascript/libs/h3_kring.js +++ /dev/null @@ -1,6 +0,0 @@ -import { h3IsValid, kRing } from '../src/h3/h3_kring/h3core_custom'; - -export default { - h3IsValid, - kRing -}; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/libs/h3_kring_distances.js b/clouds/snowflake/libraries/javascript/libs/h3_kring_distances.js index c03191667..e55d7717c 100644 --- a/clouds/snowflake/libraries/javascript/libs/h3_kring_distances.js +++ b/clouds/snowflake/libraries/javascript/libs/h3_kring_distances.js @@ -1,6 +1,5 @@ -import { h3IsValid, kRingDistances } from '../src/h3/h3_kring_distances/h3core_custom'; +import { h3Distance } from '../src/h3/h3_kring_distances/h3core_custom'; export default { - h3IsValid, - kRingDistances + h3Distance }; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/libs/h3_polyfill.js b/clouds/snowflake/libraries/javascript/libs/h3_polyfill.js index 95ccc7e41..7570ca60a 100644 --- a/clouds/snowflake/libraries/javascript/libs/h3_polyfill.js +++ b/clouds/snowflake/libraries/javascript/libs/h3_polyfill.js @@ -1,7 +1,11 @@ -import { polyfill } from '../src/h3/h3_polyfill/h3core_custom'; -import { bboxClip } from '@turf/turf'; +import { booleanContains, booleanIntersects, intersect, polygon, multiPolygon } from '@turf/turf'; +import { h3ToGeoBoundary } from '../src/h3/h3_polyfill/h3core_custom'; export default { - bboxClip, - polyfill + booleanContains, + booleanIntersects, + intersect, + polygon, + multiPolygon, + h3ToGeoBoundary }; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/libs/h3_tochildren.js b/clouds/snowflake/libraries/javascript/libs/h3_tochildren.js deleted file mode 100644 index acae7a713..000000000 --- a/clouds/snowflake/libraries/javascript/libs/h3_tochildren.js +++ /dev/null @@ -1,6 +0,0 @@ -import { h3IsValid, h3ToChildren } from '../src/h3/h3_tochildren/h3core_custom'; - -export default { - h3IsValid, - h3ToChildren -}; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/libs/h3_toparent.js b/clouds/snowflake/libraries/javascript/libs/h3_toparent.js deleted file mode 100644 index 82e3f0e7f..000000000 --- a/clouds/snowflake/libraries/javascript/libs/h3_toparent.js +++ /dev/null @@ -1,6 +0,0 @@ -import { h3IsValid, h3ToParent } from '../src/h3/h3_toparent/h3core_custom'; - -export default { - h3IsValid, - h3ToParent -}; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/README.md b/clouds/snowflake/libraries/javascript/src/h3/README.md new file mode 100644 index 000000000..7217a5bf3 --- /dev/null +++ b/clouds/snowflake/libraries/javascript/src/h3/README.md @@ -0,0 +1,19 @@ +# Rebuild h3-js 3.7.2 dependency +First, ensure you have yarn and docker installed. + +``` +wget https://github.com/uber/h3-js/releases/tag/v3.7.2 +unzip h3-js-3.7.2.zip +cd h3-js-3.7.2 +yarn docker-boot && yarn build-emscripten +``` + +Remove all the unneeded bindings from the `lib/bindings.js` + +Then run: +``` +yarn docker-emscripten-run +``` + +Your new library file is available at `out/a.out.js`. Copy it to the correct location with the new filename. For example: `cp out/a.out.js ~/development/analytics-toolbox/core/clouds/snowflake/libraries/javascript/src/h3/h3_polyfill/libh3_custom.js`. Ensure it is named `libh3_custom.js`. + diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_center/h3core_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_center/h3core_custom.js deleted file mode 100644 index 54d5c4b75..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_center/h3core_custom.js +++ /dev/null @@ -1,1352 +0,0 @@ -/* - * Copyright 2018-2019 Uber Technologies, Inc. - * Copyright 2021 CARTO - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @module h3 - */ - -import C from './libh3_custom'; -import BINDINGS from 'h3-js/lib/bindings'; - -const H3 = {}; - -// Create the bound functions themselves -BINDINGS.forEach(function bind (def) { - // Bind only exported functions - if (C['_' + def[0]]) { - H3[def[0]] = C.cwrap(...def); - } -}); - -// Alias the hexidecimal base for legibility -const BASE_16 = 16; - -// ---------------------------------------------------------------------------- -// Byte size imports - -const SZ_INT = 4; -const SZ_PTR = 4; -const SZ_DBL = 8; -const SZ_H3INDEX = H3.sizeOfH3Index && H3.sizeOfH3Index(); -const SZ_GEOCOORD = H3.sizeOfGeoCoord && H3.sizeOfGeoCoord(); -const SZ_GEOBOUNDARY = H3.sizeOfGeoBoundary && H3.sizeOfGeoBoundary(); -const SZ_GEOPOLYGON = H3.sizeOfGeoPolygon && H3.sizeOfGeoPolygon(); -const SZ_GEOFENCE = H3.sizeOfGeofence && H3.sizeOfGeofence(); -const SZ_LINKED_GEOPOLYGON = H3.sizeOfLinkedGeoPolygon && H3.sizeOfLinkedGeoPolygon(); -const SZ_COORDIJ = H3.sizeOfCoordIJ && H3.sizeOfCoordIJ(); - -// ---------------------------------------------------------------------------- -// Custom types - -/** - * 64-bit hexidecimal string representation of an H3 index - * @static - * @typedef {string} H3Index - */ - -/** - * 64-bit hexidecimal string representation of an H3 index, - * or two 32-bit integers in little endian order in an array. - * @static - * @typedef {string | number[]} H3IndexInput - */ - -/** - * Coordinates as an `{i, j}` pair - * @static - * @typedef CoordIJ - * @type {Object} - * @property {number} i - * @property {number} j - */ - -// ---------------------------------------------------------------------------- -// Unit constants - -/** - * Length/Area units - * @static - * @typedef UNITS - * @type {Object} - * @property {string} m - * @property {string} m2 - * @property {string} km - * @property {string} km2 - * @property {string} rads - * @property {string} rads2 - */ -export const UNITS = { - m: 'm', - m2: 'm2', - km: 'km', - km2: 'km2', - rads: 'rads', - rads2: 'rads2' -}; - -// ---------------------------------------------------------------------------- -// Utilities and helpers - -/** - * Validate a resolution, throwing an error if invalid - * @private - * @param {mixed} res Value to validate - * @throws {Error} Error if invalid - */ -function validateRes (res) { - if (typeof res !== 'number' || res < 0 || res > 15 || Math.floor(res) !== res) { - throw new Error(`Invalid resolution: ${res}`); - } -} - -const INVALID_HEXIDECIMAL_CHAR = /[^0-9a-fA-F]/; - -/** - * Convert an H3 index (64-bit hexidecimal string) into a "split long" - a pair of 32-bit ints - * @private - * @param {H3IndexInput} h3Index H3 index to check - * @return {number[]} A two-element array with 32 lower bits and 32 upper bits - */ -export function h3IndexToSplitLong (h3Index) { - if ( - Array.isArray(h3Index) && - h3Index.length === 2 && - Number.isInteger(h3Index[0]) && - Number.isInteger(h3Index[1]) - ) { - return h3Index; - } - if (typeof h3Index !== 'string' || INVALID_HEXIDECIMAL_CHAR.test(h3Index)) { - return [0, 0]; - } - const upper = parseInt(h3Index.substring(0, h3Index.length - 8), BASE_16); - const lower = parseInt(h3Index.substring(h3Index.length - 8), BASE_16); - return [lower, upper]; -} - -/** - * Convert a 32-bit int to a hexdecimal string - * @private - * @param {number} num Integer to convert - * @return {H3Index} Hexidecimal string - */ -function hexFrom32Bit (num) { - if (num >= 0) { - return num.toString(BASE_16); - } - - // Handle negative numbers - num = num & 0x7fffffff; - let tempStr = zeroPad(8, num.toString(BASE_16)); - const topNum = (parseInt(tempStr[0], BASE_16) + 8).toString(BASE_16); - tempStr = topNum + tempStr.substring(1); - return tempStr; -} - -/** - * Get a H3 index from a split long (pair of 32-bit ints) - * @private - * @param {number} lower Lower 32 bits - * @param {number} upper Upper 32 bits - * @return {H3Index} H3 index - */ -export function splitLongToh3Index (lower, upper) { - return hexFrom32Bit(upper) + zeroPad(8, hexFrom32Bit(lower)); -} - -/** - * Zero-pad a string to a given length - * @private - * @param {number} fullLen Target length - * @param {string} numStr String to zero-pad - * @return {string} Zero-padded string - */ -function zeroPad (fullLen, numStr) { - const numZeroes = fullLen - numStr.length; - let outStr = ''; - for (let i = 0; i < numZeroes; i++) { - outStr += '0'; - } - outStr = outStr + numStr; - return outStr; -} - -/** - * Populate a C-appropriate Geofence struct from a polygon array - * @private - * @param {Array[]} polygonArray Polygon, as an array of coordinate pairs - * @param {number} geofence C pointer to a Geofence struct - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated Geofence struct - */ -function polygonArrayToGeofence (polygonArray, geofence, isGeoJson) { - const numVerts = polygonArray.length; - const geoCoordArray = C._calloc(numVerts, SZ_GEOCOORD); - // Support [lng, lat] pairs if GeoJSON is specified - const latIndex = isGeoJson ? 1 : 0; - const lngIndex = isGeoJson ? 0 : 1; - for (let i = 0; i < numVerts * 2; i += 2) { - C.HEAPF64.set( - [polygonArray[i / 2][latIndex], polygonArray[i / 2][lngIndex]].map(degsToRads), - geoCoordArray / SZ_DBL + i - ); - } - C.HEAPU32.set([numVerts, geoCoordArray], geofence / SZ_INT); - return geofence; -} - -/** - * Create a C-appropriate GeoPolygon struct from an array of polygons - * @private - * @param {Array[]} coordinates Array of polygons, each an array of coordinate pairs - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated GeoPolygon struct - */ -function coordinatesToGeoPolygon (coordinates, isGeoJson) { - // Any loops beyond the first loop are holes - const numHoles = coordinates.length - 1; - const geoPolygon = C._calloc(SZ_GEOPOLYGON); - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // geofence is first part of struct - polygonArrayToGeofence(coordinates[0], geoPolygon + geofenceOffset, isGeoJson); - let holes; - if (numHoles > 0) { - holes = C._calloc(numHoles, SZ_GEOFENCE); - for (let i = 0; i < numHoles; i++) { - polygonArrayToGeofence(coordinates[i + 1], holes + SZ_GEOFENCE * i, isGeoJson); - } - } - C.setValue(geoPolygon + numHolesOffset, numHoles, 'i32'); - C.setValue(geoPolygon + holesOffset, holes, 'i32'); - return geoPolygon; -} - -/** - * Free memory allocated for a GeoPolygon struct. It is an error to access the struct - * after passing it to this method. - * @private - * @return {number} geoPolygon C pointer to populated GeoPolygon struct - */ -function destroyGeoPolygon (geoPolygon) { - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // Offset of the geofence vertex array pointer within the Geofence struct - const geofenceArrayOffset = SZ_INT; - // Free the outer vertex array - C._free(C.getValue(geoPolygon + geofenceOffset + geofenceArrayOffset, 'i8*')); - // Free the vertex array for the holes, if any - const numHoles = C.getValue(geoPolygon + numHolesOffset, 'i32'); - if (numHoles > 0) { - const holes = C.getValue(geoPolygon + holesOffset, 'i32'); - for (let i = 0; i < numHoles; i++) { - C._free(C.getValue(holes + SZ_GEOFENCE * i + geofenceArrayOffset, 'i8*')); - } - C._free(holes); - } - C._free(geoPolygon); -} - -/** - * Read a long value, returning the lower and upper portions as separate 32-bit integers. - * Because the upper bits are returned via side effect, the argument to this function is - * intended to be the invocation that caused the side effect, e.g. readLong(H3.getSomeLong()) - * @private - * @param {number} invocation Invoked function returning a long value. The actual return - * value of these functions is a 32-bit integer. - * @return {number} Long value as a [lower, upper] pair - */ -function readLong (invocation) { - // Upper 32-bits of the long set via side-effect - const upper = C.getTempRet0(); - return [invocation, upper]; -} - -/** - * Read an H3 index from a C return value. As with readLong, the argument to this function - * is intended to be an invocation, e.g. readH3Index(H3.getSomeAddress()), to help ensure that - * the temp value storing the upper bits of the long is still set. - * @private - * @param {number} invocation Invoked function returning a single H3 index - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3Index (invocation) { - const [lower, upper] = readLong(invocation); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Read an H3 index from a pointer to C memory. - * @private - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes, in case we're - * reading an array - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3IndexFromPointer (cAddress, offset = 0) { - const lower = C.getValue(cAddress + SZ_INT * offset * 2, 'i32'); - const upper = C.getValue(cAddress + SZ_INT * (offset * 2 + 1), 'i32'); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Store an H3 index in C memory. Primarily used as an efficient way to - * write sets of hexagons. - * @private - * @param {H3IndexInput} h3Index H3 index to store - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes from beginning - * of the current array - */ -function storeH3Index (h3Index, cAddress, offset) { - // HEAPU32 is a typed array projection on the index space - // as unsigned 32-bit integers. This means the index needs - // to be divided by SZ_INT (4) to access correctly. Also, - // the H3 index is 64 bits, so we skip by twos as we're writing - // to 32-bit integers in the proper order. - C.HEAPU32.set(h3IndexToSplitLong(h3Index), cAddress / SZ_INT + 2 * offset); -} - -/** - * Read an array of 64-bit H3 indexes from C and convert to a JS array of - * H3 index strings - * @private - * @param {number} cAddress Pointer to C ouput array - * @param {number} maxCount Max number of hexagons in array. Hexagons with - * the value 0 will be skipped, so this isn't - * necessarily the length of the output array. - * @return {H3Index[]} Array of H3 indexes - */ -function readArrayOfHexagons (cAddress, maxCount) { - const out = []; - for (let i = 0; i < maxCount; i++) { - const h3Index = readH3IndexFromPointer(cAddress, i); - if (h3Index !== null) { - out.push(h3Index); - } - } - return out; -} - -/** - * Store an array of H3 index strings as a C array of 64-bit integers. - * @private - * @param {number} cAddress Pointer to C input array - * @param {H3IndexInput[]} hexagons H3 indexes to pass to the C lib - */ -function storeArrayOfHexagons (cAddress, hexagons) { - // Assuming the cAddress points to an already appropriately - // allocated space - const count = hexagons.length; - for (let i = 0; i < count; i++) { - storeH3Index(hexagons[i], cAddress, i); - } -} - -/** - * Populate a C-appropriate GeoCoord struct from a [lat, lng] array - * @private - * @param {number} lat Coordinate latitude - * @param {number} lng Coordinate longitude - * @return {number} C pointer to populated GeoCoord struct - */ -function storeGeoCoord (lat, lng) { - const geoCoord = C._calloc(1, SZ_GEOCOORD); - C.HEAPF64.set([lat, lng].map(degsToRads), geoCoord / SZ_DBL); - return geoCoord; -} - -function readSingleCoord (cAddress) { - return radsToDegs(C.getValue(cAddress, 'double')); -} - -/** - * Read a GeoCoord from C and return a [lat, lng] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lat, lng] pair - */ -function readGeoCoord (cAddress) { - return [readSingleCoord(cAddress), readSingleCoord(cAddress + SZ_DBL)]; -} - -/** - * Read a GeoCoord from C and return a GeoJSON-style [lng, lat] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lng, lat] pair - */ -function readGeoCoordGeoJson (cAddress) { - return [readSingleCoord(cAddress + SZ_DBL), readSingleCoord(cAddress)]; -} - -/** - * Read the GeoBoundary structure into a list of geo coordinate pairs - * @private - * @param {number} geoBoundary C pointer to GeoBoundary struct - * @param {boolean} geoJsonCoords Whether to provide GeoJSON coordinate order: [lng, lat] - * @param {boolean} closedLoop Whether to close the loop - * @return {Array[]} Array of geo coordinate pairs - */ -function readGeoBoundary (geoBoundary, geoJsonCoords, closedLoop) { - const numVerts = C.getValue(geoBoundary, 'i32'); - // Note that though numVerts is an int, the coordinate doubles have to be - // aligned to 8 bytes, hence the 8-byte offset here - const vertsPos = geoBoundary + SZ_DBL; - const out = []; - // Support [lng, lat] pairs if GeoJSON is specified - const readCoord = geoJsonCoords ? readGeoCoordGeoJson : readGeoCoord; - for (let i = 0; i < numVerts * 2; i += 2) { - out.push(readCoord(vertsPos + SZ_DBL * i)); - } - if (closedLoop) { - // Close loop if GeoJSON is specified - out.push(out[0]); - } - return out; -} - -/** - * Read the LinkedGeoPolygon structure into a nested array of MultiPolygon coordinates - * @private - * @param {number} polygon C pointer to LinkedGeoPolygon struct - * @param {boolean} formatAsGeoJson Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -function readMultiPolygon (polygon, formatAsGeoJson) { - const output = []; - const readCoord = formatAsGeoJson ? readGeoCoordGeoJson : readGeoCoord; - let loops; - let loop; - let coords; - let coord; - // Loop through the linked structure, building the output - while (polygon) { - output.push((loops = [])); - // Follow ->first pointer - loop = C.getValue(polygon, 'i8*'); - while (loop) { - loops.push((coords = [])); - // Follow ->first pointer - coord = C.getValue(loop, 'i8*'); - while (coord) { - coords.push(readCoord(coord)); - // Follow ->next pointer - coord = C.getValue(coord + SZ_DBL * 2, 'i8*'); - } - if (formatAsGeoJson) { - // Close loop if GeoJSON is requested - coords.push(coords[0]); - } - // Follow ->next pointer - loop = C.getValue(loop + SZ_PTR * 2, 'i8*'); - } - // Follow ->next pointer - polygon = C.getValue(polygon + SZ_PTR * 2, 'i8*'); - } - return output; -} - -/** - * Read a CoordIJ from C and return an {i, j} pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function readCoordIJ (cAddress) { - return { - i: C.getValue(cAddress, 'i32'), - j: C.getValue(cAddress + SZ_INT, 'i32') - }; -} - -/** - * Store an {i, j} pair to a C CoordIJ struct. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function storeCoordIJ (cAddress, {i, j}) { - C.setValue(cAddress, i, 'i32'); - C.setValue(cAddress + SZ_INT, j, 'i32'); -} - -/** - * Read an array of positive integers array from C. Negative - * values are considered invalid and ignored in output. - * @private - * @param {number} cAddress Pointer to C array - * @param {number} count Length of C array - * @return {number[]} Javascript integer array - */ -function readArrayOfPositiveIntegers (cAddress, count) { - const out = []; - for (let i = 0; i < count; i++) { - const int = C.getValue(cAddress + SZ_INT * i, 'i32'); - if (int >= 0) { - out.push(int); - } - } - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Core - -/** - * Whether a given string represents a valid H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} Whether the index is valid - */ -export function h3IsValid (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsValid(lower, upper)); -} - -/** - * Whether the given H3 index is a pentagon - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isPentagon - */ -export function h3IsPentagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsPentagon(lower, upper)); -} - -/** - * Whether the given H3 index is in a Class III resolution (rotated versus - * the icosahedron and subject to shape distortion adding extra points on - * icosahedron edges, making them not true hexagons). - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isResClassIII - */ -export function h3IsResClassIII (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsResClassIII(lower, upper)); -} - -/** - * Get the number of the base cell for a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get the base cell for - * @return {number} Index of the base cell (0-121) - */ -export function h3GetBaseCell (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return H3.h3GetBaseCell(lower, upper); -} - -/** - * Get the indices of all icosahedron faces intersected by a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get faces for - * @return {number[]} Indices (0-19) of all intersected faces - */ -export function h3GetFaces (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = H3.maxFaceCount(lower, upper); - const faces = C._malloc(SZ_INT * count); - H3.h3GetFaces(lower, upper, faces); - const out = readArrayOfPositiveIntegers(faces, count); - C._free(faces); - return out; -} - -/** - * Returns the resolution of an H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get resolution - * @return {number} The number (0-15) resolution, or -1 if invalid - */ -export function h3GetResolution (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - if (!H3.h3IsValid(lower, upper)) { - // Compatability with stated API - return -1; - } - return H3.h3GetResolution(lower, upper); -} - -/** - * Get the hexagon containing a lat,lon point - * @static - * @param {number} lat Latitude of point - * @param {number} lng Longtitude of point - * @param {number} res Resolution of hexagons to return - * @return {H3Index} H3 index - */ -export function geoToH3 (lat, lng, res) { - const latlng = C._malloc(SZ_GEOCOORD); - // Slightly more efficient way to set the memory - C.HEAPF64.set([lat, lng].map(degsToRads), latlng / SZ_DBL); - // Read value as a split long - const h3Index = readH3Index(H3.geoToH3(latlng, res)); - C._free(latlng); - return h3Index; -} - -/** - * Get the lat,lon center of a given hexagon - * @static - * @param {H3IndexInput} h3Index H3 index - * @return {number[]} Point as a [lat, lng] pair - */ -export function h3ToGeo (h3Index) { - const latlng = C._malloc(SZ_GEOCOORD); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeo(lower, upper, latlng); - const out = readGeoCoord(latlng); - C._free(latlng); - return out; -} - -/** - * Get the vertices of a given hexagon (or pentagon), as an array of [lat, lng] - * points. For pentagons and hexagons on the edge of an icosahedron face, this - * function may return up to 10 vertices. - * @static - * @param {H3Index} h3Index H3 index - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][]} Array of [lat, lng] pairs - */ -export function h3ToGeoBoundary (h3Index, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeoBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Algorithms - -/** - * Get the parent of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get parent for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of parent, or null for invalid input - */ -export function h3ToParent (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToParent(lower, upper, res)); -} - -/** - * Get the children/descendents of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get children for - * @param {number} res Resolution of hexagons to return - * @return {H3Index[]} H3 indexes of children, or empty array for invalid input - */ -export function h3ToChildren (h3Index, res) { - // Bad input in this case can potentially result in high computation volume - // using the current C algorithm. Validate and return an empty array on failure. - if (!h3IsValid(h3Index)) { - return []; - } - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxH3ToChildrenSize(lower, upper, res); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.h3ToChildren(lower, upper, res, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get the center child of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get center child for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of child, or null for invalid input - */ -export function h3ToCenterChild (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToCenterChild(lower, upper, res)); -} - -/** - * Get all hexagons in a k-ring around a given center. The order of the hexagons is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - */ -export function kRing (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.kRing(lower, upper, ringSize, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons in a k-ring around a given center, in an array of arrays - * ordered by distance from the origin. The order of the hexagons within each ring is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[][]} Array of arrays with H3 indexes for all hexagons each ring - */ -export function kRingDistances (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const kRings = C._calloc(maxCount, SZ_H3INDEX); - const distances = C._calloc(maxCount, SZ_INT); - H3.kRingDistances(lower, upper, ringSize, kRings, distances); - // Create an array of empty arrays to hold the output - const out = []; - for (let i = 0; i < ringSize + 1; i++) { - out.push([]); - } - // Read the array of hexagons, putting them into the appropriate rings - for (let i = 0; i < maxCount * 2; i += 2) { - const hexLower = C.getValue(kRings + SZ_INT * i, 'i32'); - const hexUpper = C.getValue(kRings + SZ_INT * (i + 1), 'i32'); - const index = C.getValue(distances + SZ_INT * (i / 2), 'i32'); - if (hexLower !== 0 || hexUpper !== 0) { - out[index].push(splitLongToh3Index(hexLower, hexUpper)); - } - } - C._free(kRings); - C._free(distances); - return out; -} - -/** - * Get all hexagons in a hollow hexagonal ring centered at origin with sides of a given length. - * Unlike kRing, this function will throw an error if there is a pentagon anywhere in the ring. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - * @throws {Error} If the algorithm could not calculate the ring - */ -export function hexRing (h3Index, ringSize) { - const maxCount = ringSize === 0 ? 1 : 6 * ringSize; - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - const retVal = H3.hexRing(...h3IndexToSplitLong(h3Index), ringSize, hexagons); - if (retVal !== 0) { - C._free(hexagons); - throw new Error('Failed to get hexRing (encountered a pentagon?)'); - } - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons with centers contained in a given polygon. The polygon - * is specified with GeoJson semantics as an array of loops. Each loop is - * an array of [lat, lng] pairs (or [lng, lat] if isGeoJson is specified). - * The first loop is the perimeter of the polygon, and subsequent loops are - * expected to be holes. - * @static - * @param {number[][] | number[][][]} coordinates - * Array of loops, or a single loop - * @param {number} res Resolution of hexagons to return - * @param {boolean} [isGeoJson] Whether to expect GeoJson-style [lng, lat] - * pairs instead of [lat, lng] - * @return {H3Index[]} H3 indexes for all hexagons in polygon - */ -export function polyfill (coordinates, res, isGeoJson) { - validateRes(res); - isGeoJson = Boolean(isGeoJson); - // Guard against empty input - if (coordinates.length === 0 || coordinates[0].length === 0) { - return []; - } - // Wrap to expected format if a single loop is provided - if (typeof coordinates[0][0] === 'number') { - coordinates = [coordinates]; - } - const geoPolygon = coordinatesToGeoPolygon(coordinates, isGeoJson); - const arrayLen = H3.maxPolyfillSize(geoPolygon, res); - const hexagons = C._calloc(arrayLen, SZ_H3INDEX); - H3.polyfill(geoPolygon, res, hexagons); - const out = readArrayOfHexagons(hexagons, arrayLen); - C._free(hexagons); - destroyGeoPolygon(geoPolygon); - return out; -} - -/** - * Get the outlines of a set of H3 hexagons, returned in GeoJSON MultiPolygon - * format (an array of polygons, each with an array of loops, each an array of - * coordinates). Coordinates are returned as [lat, lng] pairs unless GeoJSON - * is requested. - * - * It is the responsibility of the caller to ensure that all hexagons in the - * set have the same resolution and that the set contains no duplicates. Behavior - * is undefined if duplicates or multiple resolutions are present, and the - * algorithm may produce unexpected or invalid polygons. - * - * @static - * @param {H3IndexInput[]} h3Indexes H3 indexes to get outlines for - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: - * [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -export function h3SetToMultiPolygon (h3Indexes, formatAsGeoJson) { - // Early exit on empty input - if (!h3Indexes || !h3Indexes.length) { - return []; - } - // Set up input set - const indexCount = h3Indexes.length; - const set = C._calloc(indexCount, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Indexes); - // Allocate memory for output linked polygon - const polygon = C._calloc(SZ_LINKED_GEOPOLYGON); - // Store a reference to the first polygon - that's the one we need for - // memory deallocation - const originalPolygon = polygon; - H3.h3SetToLinkedGeo(set, indexCount, polygon); - const multiPolygon = readMultiPolygon(polygon, formatAsGeoJson); - // Clean up - H3.destroyLinkedPolygon(originalPolygon); - C._free(originalPolygon); - C._free(set); - return multiPolygon; -} - -/** - * Compact a set of hexagons of the same resolution into a set of hexagons across - * multiple levels that represents the same area. - * @static - * @param {H3IndexInput[]} h3Set H3 indexes to compact - * @return {H3Index[]} Compacted H3 indexes - * @throws {Error} If the input is invalid (e.g. duplicate hexagons) - */ -export function compact (h3Set) { - if (!h3Set || !h3Set.length) { - return []; - } - // Set up input set - const count = h3Set.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Set); - // Allocate memory for compacted hexagons, worst-case is no compaction - const compactedSet = C._calloc(count, SZ_H3INDEX); - const retVal = H3.compact(set, compactedSet, count); - if (retVal !== 0) { - C._free(set); - C._free(compactedSet); - throw new Error('Failed to compact, malformed input data (duplicate hexagons?)'); - } - const out = readArrayOfHexagons(compactedSet, count); - C._free(set); - C._free(compactedSet); - return out; -} - -/** - * Uncompact a compacted set of hexagons to hexagons of the same resolution - * @static - * @param {H3IndexInput[]} compactedSet H3 indexes to uncompact - * @param {number} res The resolution to uncompact to - * @return {H3Index[]} The uncompacted H3 indexes - * @throws {Error} If the input is invalid (e.g. invalid resolution) - */ -export function uncompact (compactedSet, res) { - validateRes(res); - if (!compactedSet || !compactedSet.length) { - return []; - } - // Set up input set - const count = compactedSet.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, compactedSet); - // Estimate how many hexagons we need (always overestimates if in error) - const maxUncompactedNum = H3.maxUncompactSize(set, count, res); - // Allocate memory for uncompacted hexagons - const uncompactedSet = C._calloc(maxUncompactedNum, SZ_H3INDEX); - const retVal = H3.uncompact(set, count, uncompactedSet, maxUncompactedNum, res); - if (retVal !== 0) { - C._free(set); - C._free(uncompactedSet); - throw new Error('Failed to uncompact (bad resolution?)'); - } - const out = readArrayOfHexagons(uncompactedSet, maxUncompactedNum); - C._free(set); - C._free(uncompactedSet); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Unidirectional edges - -/** - * Whether two H3 indexes are neighbors (share an edge) - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {boolean} Whether the hexagons share an edge - */ -export function h3IndexesAreNeighbors (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return Boolean(H3.h3IndexesAreNeighbors(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get an H3 index representing a unidirectional edge for a given origin and destination - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index} H3 index of the edge, or null if no edge is shared - */ -export function getH3UnidirectionalEdge (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return readH3Index(H3.getH3UnidirectionalEdge(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get the origin hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge origin - */ -export function getOriginH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getOriginH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Get the destination hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge destination - */ -export function getDestinationH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getDestinationH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Whether the input is a valid unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {boolean} Whether the index is valid - */ -export function h3UnidirectionalEdgeIsValid (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return Boolean(H3.h3UnidirectionalEdgeIsValid(lower, upper)); -} - -/** - * Get the [origin, destination] pair represented by a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index[]} [origin, destination] pair as H3 indexes - */ -export function getH3IndexesFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - const count = 2; - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.getH3IndexesFromUnidirectionalEdge(lower, upper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get all of the unidirectional edges with the given H3 index as the origin (i.e. an edge to - * every neighbor) - * @static - * @param {H3IndexInput} h3Index H3 index of the origin hexagon - * @return {H3Index[]} List of unidirectional edges - */ -export function getH3UnidirectionalEdgesFromHexagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = 6; - const edges = C._calloc(count, SZ_H3INDEX); - H3.getH3UnidirectionalEdgesFromHexagon(lower, upper, edges); - const out = readArrayOfHexagons(edges, count); - C._free(edges); - return out; -} - -/** - * Get the vertices of a given edge as an array of [lat, lng] points. Note that for edges that - * cross the edge of an icosahedron face, this may return 3 coordinates. - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat] - * @return {number[][]} Array of geo coordinate pairs - */ -export function getH3UnidirectionalEdgeBoundary (edgeIndex, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - H3.getH3UnidirectionalEdgeBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -/** - * Get the grid distance between two hex indexes. This function may fail - * to find the distance between two indexes if they are very far apart or - * on opposite sides of a pentagon. - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {number} Distance between hexagons, or a negative - * number if the distance could not be computed - */ -export function h3Distance (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return H3.h3Distance(oLower, oUpper, dLower, dUpper); -} - -/** - * Given two H3 indexes, return the line of indexes between them (inclusive). - * - * This function may fail to find the line between two indexes, for - * example if they are very far apart. It may also fail when finding - * distances for indexes on opposite sides of a pentagon. - * - * Notes: - * - * - The specific output of this function should not be considered stable - * across library versions. The only guarantees the library provides are - * that the line length will be `h3Distance(start, end) + 1` and that - * every index in the line will be a neighbor of the preceding index. - * - Lines are drawn in grid space, and may not correspond exactly to either - * Cartesian lines or great arcs. - * - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index[]} H3 indexes connecting origin and destination - * @throws {Error} If the line cannot be calculated - */ -export function h3Line (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - const count = H3.h3LineSize(oLower, oUpper, dLower, dUpper); - if (count < 0) { - // We can't get the specific error code here - may be any of - // the errors possible in experimentalH3ToLocalIj - throw new Error('Line cannot be calculated'); - } - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.h3Line(oLower, oUpper, dLower, dUpper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Produces IJ coordinates for an H3 index anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {H3IndexInput} destination H3 index for which to find relative coordinates - * @return {CoordIJ} Coordinates as an `{i, j}` pair - * @throws {Error} If the IJ coordinates cannot be calculated - */ -export function experimentalH3ToLocalIj (origin, destination) { - const ij = C._malloc(SZ_COORDIJ); - const retVal = H3.experimentalH3ToLocalIj( - ...h3IndexToSplitLong(origin), - ...h3IndexToSplitLong(destination), - ij - ); - const coords = readCoordIJ(ij); - C._free(ij); - // Return the pair, or throw if an error code was returned. - // Switch statement and error codes cribbed from h3-java's implementation. - switch (retVal) { - case 0: - return coords; - case 1: - throw new Error('Incompatible origin and index.'); - case 2: - default: - throw new Error( - 'Local IJ coordinates undefined for this origin and index pair. ' + - 'The index may be too far from the origin.' - ); - case 3: - case 4: - case 5: - throw new Error('Encountered possible pentagon distortion'); - } -} - -/** - * Produces an H3 index for IJ coordinates anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {CoordIJ} coords Coordinates as an `{i, j}` pair - * @return {H3Index} H3 index at the relative coordinates - * @throws {Error} If the H3 index cannot be calculated - */ -export function experimentalLocalIjToH3 (origin, coords) { - // Validate input coords - if (!coords || typeof coords.i !== 'number' || typeof coords.j !== 'number') { - throw new Error('Coordinates must be provided as an {i, j} object'); - } - // Allocate memory for the CoordIJ struct and an H3 index to hold the return value - const ij = C._malloc(SZ_COORDIJ); - const out = C._malloc(SZ_H3INDEX); - storeCoordIJ(ij, coords); - const retVal = H3.experimentalLocalIjToH3(...h3IndexToSplitLong(origin), ij, out); - const h3Index = readH3IndexFromPointer(out); - C._free(ij); - C._free(out); - if (retVal !== 0) { - throw new Error( - 'Index not defined for this origin and IJ coordinates pair. ' + - 'IJ coordinates may be too far from origin, or ' + - 'a pentagon distortion was encountered.' - ); - } - return h3Index; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Distance/area utilities - -/** - * Great circle distance between two geo points. This is not specific to H3, - * but is implemented in the library and provided here as a convenience. - * @static - * @param {number[]} latlng1 Origin coordinate as [lat, lng] - * @param {number[]} latlng2 Destination coordinate as [lat, lng] - * @param {string} unit Distance unit (either UNITS.m or UNITS.km) - * @return {number} Great circle distance - * @throws {Error} If the unit is invalid - */ -export function pointDist (latlng1, latlng2, unit) { - const coord1 = storeGeoCoord(latlng1[0], latlng1[1]); - const coord2 = storeGeoCoord(latlng2[0], latlng2[1]); - let result; - switch (unit) { - case UNITS.m: - result = H3.pointDistM(coord1, coord2); - break; - case UNITS.km: - result = H3.pointDistKm(coord1, coord2); - break; - case UNITS.rads: - result = H3.pointDistRads(coord1, coord2); - break; - default: - result = null; - } - C._free(coord1); - C._free(coord2); - if (result === null) { - throw new Error(`Unknown unit: ${unit}`); - } - return result; -} - -/** - * Exact area of a given cell - * @static - * @param {H3Index} h3Index H3 index of the hexagon to measure - * @param {string} unit Distance unit (either UNITS.m2 or UNITS.km2) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function cellArea (h3Index, unit) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - switch (unit) { - case UNITS.m2: - return H3.cellAreaM2(lower, upper); - case UNITS.km2: - return H3.cellAreaKm2(lower, upper); - case UNITS.rads2: - return H3.cellAreaRads2(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Exact length of a given unidirectional edge - * @static - * @param {H3Index} edge H3 index of the edge to measure - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function exactEdgeLength (edge, unit) { - const [lower, upper] = h3IndexToSplitLong(edge); - switch (unit) { - case UNITS.m: - return H3.exactEdgeLengthM(lower, upper); - case UNITS.km: - return H3.exactEdgeLengthKm(lower, upper); - case UNITS.rads: - return H3.exactEdgeLengthRads(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon area at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Area unit (either UNITS.m2, UNITS.km2, or UNITS.rads2) - * @return {number} Average area - * @throws {Error} If the unit is invalid - */ -export function hexArea (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m2: - return H3.hexAreaM2(res); - case UNITS.km2: - return H3.hexAreaKm2(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon edge length at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Average edge length - * @throws {Error} If the unit is invalid - */ -export function edgeLength (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m: - return H3.edgeLengthM(res); - case UNITS.km: - return H3.edgeLengthKm(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -// ---------------------------------------------------------------------------- -// Public informational utilities - -/** - * The total count of hexagons in the world at a given resolution. Note that above - * resolution 8 the exact count cannot be represented in a JavaScript 32-bit number, - * so consumers should use caution when applying further operations to the output. - * @static - * @param {number} res Hexagon resolution - * @return {number} Count - */ -export function numHexagons (res) { - validateRes(res); - // Get number as a long value - const [lower, upper] = readLong(H3.numHexagons(res)); - // If we're using <= 32 bits we can use normal JS numbers - if (!upper) { - return lower; - } - // Above 32 bit, make a JS number that's correct in order of magnitude - return upper * Math.pow(2, 32) + lower; -} - -/** - * Get all H3 indexes at resolution 0. As every index at every resolution > 0 is - * the descendant of a res 0 index, this can be used with h3ToChildren to iterate - * over H3 indexes at any resolution. - * @static - * @return {H3Index[]} All H3 indexes at res 0 - */ -export function getRes0Indexes () { - const count = H3.res0IndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getRes0Indexes(hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get the twelve pentagon indexes at a given resolution. - * @static - * @param {number} res Hexagon resolution - * @return {H3Index[]} All H3 pentagon indexes at res - */ -export function getPentagonIndexes (res) { - validateRes(res); - const count = H3.pentagonIndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getPentagonIndexes(res, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Convert degrees to radians - * @static - * @param {number} deg Value in degrees - * @return {number} Value in radians - */ -export function degsToRads (deg) { - return (deg * Math.PI) / 180; -} - -/** - * Convert radians to degrees - * @static - * @param {number} rad Value in radians - * @return {number} Value in degrees - */ -export function radsToDegs (rad) { - return (rad * 180) / Math.PI; -} \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_center/libh3_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_center/libh3_custom.js deleted file mode 100644 index f640229a4..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_center/libh3_custom.js +++ /dev/null @@ -1,24 +0,0 @@ - -var libh3 = ( -function(libh3) { - libh3 = libh3 || {}; - -var Module=typeof libh3!=="undefined"?libh3:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=6832,DYNAMIC_BASE=5249712,DYNAMICTOP_PTR=6800;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAD//////////wEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAACAAAAAAAAAAAAAAABAAAAAgAAAAYAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAKAAAAAgAAAAAAAAAAAAAAAQAAAAEAAAAFAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAACAAAAAAAAAAAAAAABAAAAAwAAAAcAAAAGAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADgAAAAIAAAAAAAAAAAAAAAEAAAAAAAAACQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAIAAAAAAAAAAAAAAAEAAAAEAAAACAAAAAoAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAgAAAAAAAAAAAAAAAQAAAAsAAAAPAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAIAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAgAAAAAAAAAAAAAAAQAAAAwAAAAQAAAADAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAACAAAAAAAAAAAAAAABAAAACgAAABMAAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAA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AAAAAAAAAAAEAAAAAgAAAAAAAAACAAAAAQAAAAEAAAACAAAAAgAAAAAAAAAFAAAABQAAAAAAAAACAAAAAgAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAABAAAAAgAAAAIAAAACAAAAAAAAAAUAAAAGAAAAAAAAAAIAAAACAAAAAwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAAAAAAAgAAAAEAAAADAAAAAgAAAAIAAAAAAAAABQAAAAcAAAAAAAAAAgAAAAIAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAgAAAAAAAAACAAAAAQAAAAQAAAACAAAAAgAAAAAAAAAFAAAACAAAAAAAAAACAAAAAgAAAAMAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAAAAAAAAAIAAAABAAAAAAAAAAIAAAACAAAAAAAAAAUAAAAJAAAAAAAAAAIAAAACAAAAAwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAIAAAACAAAAAAAAAAMAAAAOAAAAAgAAAAAAAAACAAAAAwAAAAAAAAAAAAAAAgAAAAIAAAADAAAABgAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAgAAAAIAAAAAAAAAAwAAAAoAAAACAAAAAAAAAAIAAAADAAAAAQAAAAAAAAACAAAAAgAAAAMAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAACAAAAAgAAAAAAAAADAAAACwAAAAIAAAAAAAAAAgAAAAMAAAACAAAAAAAAAAIAAAACAAAAAwAAAAgAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAIAAAACAAAAAAAAAAMAAAAMAAAAAgAAAAAAAAACAAAAAwAAAAMAAAAAAAAAAgAAAAIAAAADAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAgAAAAIAAAAAAAAAAwAAAA0AAAACAAAAAAAAAAIAAAADAAAABAAAAAAAAAACAAAAAgAAAAMAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAACAAAAAgAAAAAAAAADAAAABgAAAAIAAAAAAAAAAgAAAAMAAAAPAAAAAAAAAAIAAAACAAAAAwAAAAsAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAIAAAACAAAAAAAAAAMAAAAHAAAAAgAAAAAAAAACAAAAAwAAABAAAAAAAAAAAgAAAAIAAAADAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAgAAAAIAAAAAAAAAAwAAAAgAAAACAAAAAAAAAAIAAAADAAAAEQAAAAAAAAACAAAAAgAAAAMAAAANAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAACAAAAAgAAAAAAAAADAAAACQAAAAIAAAAAAAAAAgAAAAMAAAASAAAAAAAAAAIAAAACAAAAAwAAAA4AAAAAAAAAAAAAAAAAAAAAAAAACQAAAAIAAAACAAAAAAAAAAMAAAAFAAAAAgAAAAAAAAACAAAAAwAAABMAAAAAAAAAAgAAAAIAAAADAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAgAAAAAAAAACAAAAAQAAABMAAAACAAAAAgAAAAAAAAAFAAAACgAAAAAAAAACAAAAAgAAAAMAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABEAAAACAAAAAAAAAAIAAAABAAAADwAAAAIAAAACAAAAAAAAAAUAAAALAAAAAAAAAAIAAAACAAAAAwAAABEAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAIAAAAAAAAAAgAAAAEAAAAQAAAAAgAAAAIAAAAAAAAABQAAAAwAAAAAAAAAAgAAAAIAAAADAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAgAAAAAAAAACAAAAAQAAABEAAAACAAAAAgAAAAAAAAAFAAAADQAAAAAAAAACAAAAAgAAAAMAAAATAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAACAAAAAAAAAAIAAAABAAAAEgAAAAIAAAACAAAAAAAAAAUAAAAOAAAAAAAAAAIAAAACAAAAAw==";var tempDoublePtr=6816;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]|0}function U(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;b[a>>2]=c;b[a+4>>2]=d;b[a+8>>2]=e;return}function V(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;if((c|0)<0){d=d-c|0;b[h>>2]=d;g=a+8|0;b[g>>2]=(b[g>>2]|0)-c;b[a>>2]=0;c=0}if((d|0)<0){c=c-d|0;b[a>>2]=c;g=a+8|0;f=(b[g>>2]|0)-d|0;b[g>>2]=f;b[h>>2]=0;d=0}else{f=a+8|0;g=f;f=b[f>>2]|0}if((f|0)<0){c=c-f|0;b[a>>2]=c;d=d-f|0;b[h>>2]=d;b[g>>2]=0;f=0}e=(d|0)<(c|0)?d:c;e=(f|0)<(e|0)?f:e;if((e|0)<=0)return;b[a>>2]=c-e;b[h>>2]=d-e;b[g>>2]=f-e;return}function W(a,c){a=a|0;c=c|0;var e=0.0,f=0;f=b[a+8>>2]|0;e=+((b[a+4>>2]|0)-f|0);d[c>>3]=+((b[a>>2]|0)-f|0)-e*.5;d[c+8>>3]=e*.8660254037844386;return}function X(a,c,d){a=a|0;c=c|0;d=d|0;b[d>>2]=(b[c>>2]|0)+(b[a>>2]|0);b[d+4>>2]=(b[c+4>>2]|0)+(b[a+4>>2]|0);b[d+8>>2]=(b[c+8>>2]|0)+(b[a+8>>2]|0);return}function Y(a,c,d){a=a|0;c=c|0;d=d|0;b[d>>2]=(b[a>>2]|0)-(b[c>>2]|0);b[d+4>>2]=(b[a+4>>2]|0)-(b[c+4>>2]|0);b[d+8>>2]=(b[a+8>>2]|0)-(b[c+8>>2]|0);return}function Z(a,c){a=a|0;c=c|0;var d=0,e=0;d=x(b[a>>2]|0,c)|0;b[a>>2]=d;d=a+4|0;e=x(b[d>>2]|0,c)|0;b[d>>2]=e;a=a+8|0;c=x(b[a>>2]|0,c)|0;b[a>>2]=c;return}function _(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;h=a+8|0;d=b[h>>2]|0;c=(b[a>>2]|0)-d|0;i=a+4|0;d=(b[i>>2]|0)-d|0;e=sa(+((c<<1)+d|0)/7.0)|0;b[a>>2]=e;c=sa(+((d*3|0)-c|0)/7.0)|0;b[i>>2]=c;b[h>>2]=0;d=c-e|0;if((e|0)<0){g=0-e|0;b[i>>2]=d;b[h>>2]=g;b[a>>2]=0;c=d;e=0;d=g}else d=0;if((c|0)<0){e=e-c|0;b[a>>2]=e;d=d-c|0;b[h>>2]=d;b[i>>2]=0;c=0}g=e-d|0;f=c-d|0;if((d|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;c=f;f=g;d=0}else f=e;e=(c|0)<(f|0)?c:f;e=(d|0)<(e|0)?d:e;if((e|0)<=0)return;b[a>>2]=f-e;b[i>>2]=c-e;b[h>>2]=d-e;return}function $(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;i=a+8|0;e=b[i>>2]|0;f=d+(c*3|0)|0;b[a>>2]=f;d=e+(d*3|0)|0;b[h>>2]=d;c=(e*3|0)+c|0;b[i>>2]=c;e=d-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=e;b[i>>2]=c;b[a>>2]=0;d=e;e=0}else e=f;if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function aa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=(c*3|0)+f|0;f=d+(f*3|0)|0;b[a>>2]=f;b[h>>2]=e;c=(d*3|0)+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;f=0}else d=e;if((d|0)<0){f=f-d|0;b[a>>2]=f;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=f-c|0;e=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=e;b[i>>2]=0;f=g;c=0}else e=d;d=(e|0)<(f|0)?e:f;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=f-d;b[h>>2]=e-d;b[i>>2]=c-d;return}function ba(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0;if((c+-1|0)>>>0>=6)return;f=(b[3440+(c*12|0)>>2]|0)+(b[a>>2]|0)|0;b[a>>2]=f;i=a+4|0;e=(b[3440+(c*12|0)+4>>2]|0)+(b[i>>2]|0)|0;b[i>>2]=e;h=a+8|0;c=(b[3440+(c*12|0)+8>>2]|0)+(b[h>>2]|0)|0;b[h>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[i>>2]=d;b[h>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[h>>2]=c;b[i>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[i>>2]=f-d;b[h>>2]=c-d;return}function ca(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=c+f|0;f=d+f|0;b[a>>2]=f;b[h>>2]=e;c=d+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function da(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;e=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;f=e+c|0;b[a>>2]=f;e=d+e|0;b[h>>2]=e;c=d+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function ea(a){a=a|0;switch(a|0){case 1:{a=3;break}case 3:{a=2;break}case 2:{a=6;break}case 6:{a=4;break}case 4:{a=5;break}case 5:{a=1;break}default:{}}return a|0}function fa(a,c,e,f,g){a=a|0;c=c|0;e=e|0;f=f|0;g=g|0;var h=0.0,i=0.0;h=+pa(a);if(h<1.0e-16){c=3536+(c<<4)|0;b[g>>2]=b[c>>2];b[g+4>>2]=b[c+4>>2];b[g+8>>2]=b[c+8>>2];b[g+12>>2]=b[c+12>>2];return}i=+v(+(+d[a+8>>3]),+(+d[a>>3]));if((e|0)>0){a=0;do{h=h/2.6457513110645907;a=a+1|0}while((a|0)!=(e|0))}if(!f){h=+u(+(h*.381966011250105));if(la(e)|0)i=+ia(i+.3334731722518321)}else{h=h/3.0;e=(la(e)|0)==0;h=+u(+((e?h:h/2.6457513110645907)*.381966011250105))}ja(3536+(c<<4)|0,+ia(+d[3856+(c*24|0)>>3]-i),h,g);return}function ga(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0;e=L;L=L+16|0;f=e;W(a+4|0,f);fa(f,b[a>>2]|0,c,0,d);L=e;return}function ha(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;p=L;L=L+32|0;n=p+12|0;i=p;o=a+4|0;m=b[4416+(c<<2)>>2]|0;l=(e|0)!=0;m=l?m*3|0:m;f=b[o>>2]|0;k=a+8|0;h=b[k>>2]|0;if(l){g=a+12|0;e=b[g>>2]|0;f=h+f+e|0;if((f|0)==(m|0)){o=1;L=p;return o|0}else j=g}else{j=a+12|0;e=b[j>>2]|0;f=h+f+e|0}if((f|0)<=(m|0)){o=0;L=p;return o|0}do if((e|0)>0){e=b[a>>2]|0;if((h|0)>0){g=4496+(e*80|0)+60|0;e=a;break}e=4496+(e*80|0)+40|0;if(!d){g=e;e=a}else{U(n,m,0,0);Y(o,n,i);da(i);X(i,n,o);g=e;e=a}}else{g=4496+((b[a>>2]|0)*80|0)+20|0;e=a}while(0);b[e>>2]=b[g>>2];f=g+16|0;if((b[f>>2]|0)>0){e=0;do{ca(o);e=e+1|0}while((e|0)<(b[f>>2]|0))}a=g+4|0;b[n>>2]=b[a>>2];b[n+4>>2]=b[a+4>>2];b[n+8>>2]=b[a+8>>2];c=b[4336+(c<<2)>>2]|0;Z(n,l?c*3|0:c);X(o,n,o);V(o);if(l)e=((b[k>>2]|0)+(b[o>>2]|0)+(b[j>>2]|0)|0)==(m|0)?1:2;else e=2;o=e;L=p;return o|0}function ia(a){a=+a;var b=0.0;b=a<0.0?a+6.283185307179586:a;return +(!(a>=6.283185307179586)?b:b+-6.283185307179586)}function ja(a,c,e,f){a=a|0;c=+c;e=+e;f=f|0;var g=0,h=0.0,i=0.0,j=0.0;if(e<1.0e-16){b[f>>2]=b[a>>2];b[f+4>>2]=b[a+4>>2];b[f+8>>2]=b[a+8>>2];b[f+12>>2]=b[a+12>>2];return}h=c<0.0?c+6.283185307179586:c;h=!(c>=6.283185307179586)?h:h+-6.283185307179586;do if(h<1.0e-16){c=+d[a>>3]+e;d[f>>3]=c;g=f}else{g=+p(+(h+-3.141592653589793))<1.0e-16;c=+d[a>>3];if(g){c=c-e;d[f>>3]=c;g=f;break}i=+r(+e);e=+s(+e);c=i*+s(+c)+ +r(+h)*(e*+r(+c));c=c>1.0?1.0:c;c=+t(+(c<-1.0?-1.0:c));d[f>>3]=c;if(+p(+(c+-1.5707963267948966))<1.0e-16){d[f>>3]=1.5707963267948966;d[f+8>>3]=0.0;return}if(+p(+(c+1.5707963267948966))<1.0e-16){d[f>>3]=-1.5707963267948966;d[f+8>>3]=0.0;return}j=+r(+c);h=e*+s(+h)/j;e=+d[a>>3];c=(i-+s(+c)*+s(+e))/+r(+e)/j;i=h>1.0?1.0:h;c=c>1.0?1.0:c;c=+d[a+8>>3]+ +v(+(i<-1.0?-1.0:i),+(c<-1.0?-1.0:c));if(c>3.141592653589793)do c=c+-6.283185307179586;while(c>3.141592653589793);if(c<-3.141592653589793)do c=c+6.283185307179586;while(c<-3.141592653589793);d[f+8>>3]=c;return}while(0);if(+p(+(c+-1.5707963267948966))<1.0e-16){d[g>>3]=1.5707963267948966;d[f+8>>3]=0.0;return}if(+p(+(c+1.5707963267948966))<1.0e-16){d[g>>3]=-1.5707963267948966;d[f+8>>3]=0.0;return}c=+d[a+8>>3];if(c>3.141592653589793)do c=c+-6.283185307179586;while(c>3.141592653589793);if(c<-3.141592653589793)do c=c+6.283185307179586;while(c<-3.141592653589793);d[f+8>>3]=c;return}function ka(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0;if(!(0==0&(b&-16777216|0)==134217728)){b=0;return b|0}g=wa(a|0,b|0,45)|0;A()|0;g=g&127;if(g>>>0>121){b=0;return b|0}c=wa(a|0,b|0,52)|0;A()|0;c=c&15;do if(c|0){e=1;d=0;while(1){f=wa(a|0,b|0,(15-e|0)*3|0)|0;A()|0;f=f&7;if((f|0)!=0&(d^1))if((f|0)==1&(T(g)|0)!=0){h=0;d=13;break}else d=1;if((f|0)==7){h=0;d=13;break}if(e>>>0>>0)e=e+1|0;else{d=9;break}}if((d|0)==9){if((c|0)==15)h=1;else break;return h|0}else if((d|0)==13)return h|0}while(0);while(1){h=wa(a|0,b|0,(14-c|0)*3|0)|0;A()|0;if(!((h&7|0)==7&0==0)){h=0;d=13;break}if(c>>>0<14)c=c+1|0;else{h=1;d=13;break}}if((d|0)==13)return h|0;return 0}function la(a){a=a|0;return (a|0)%2|0|0}function ma(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;f=d+4|0;g=wa(a|0,c|0,52)|0;A()|0;g=g&15;h=wa(a|0,c|0,45)|0;A()|0;e=(g|0)==0;if(!(T(h&127)|0)){if(e){h=0;return h|0}if((b[f>>2]|0)==0?(b[d+8>>2]|0)==0:0)e=(b[d+12>>2]|0)!=0&1;else e=1}else if(e){h=1;return h|0}else e=1;d=1;while(1){if(!(d&1))aa(f);else $(f);h=wa(a|0,c|0,(15-d|0)*3|0)|0;A()|0;ba(f,h&7);if(d>>>0>>0)d=d+1|0;else break}return e|0}function na(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;l=L;L=L+16|0;j=l;k=wa(a|0,c|0,45)|0;A()|0;k=k&127;a:do if((T(k)|0)!=0?(g=wa(a|0,c|0,52)|0,A()|0,g=g&15,(g|0)!=0):0){e=1;b:while(1){i=wa(a|0,c|0,(15-e|0)*3|0)|0;A()|0;switch(i&7){case 5:break b;case 0:break;default:{e=c;break a}}if(e>>>0>>0)e=e+1|0;else{e=c;break a}}f=1;e=c;while(1){c=(15-f|0)*3|0;h=xa(7,0,c|0)|0;i=e&~(A()|0);e=wa(a|0,e|0,c|0)|0;A()|0;e=xa(ea(e&7)|0,0,c|0)|0;a=a&~h|e;e=i|(A()|0);if(f>>>0>>0)f=f+1|0;else break}}else e=c;while(0);i=16+(k*28|0)|0;b[d>>2]=b[i>>2];b[d+4>>2]=b[i+4>>2];b[d+8>>2]=b[i+8>>2];b[d+12>>2]=b[i+12>>2];if(!(ma(a,e,d)|0)){L=l;return}h=d+4|0;b[j>>2]=b[h>>2];b[j+4>>2]=b[h+4>>2];b[j+8>>2]=b[h+8>>2];g=wa(a|0,e|0,52)|0;A()|0;i=g&15;if(!(g&1))g=i;else{aa(h);g=i+1|0}if(!(T(k)|0))e=0;else{c:do if(!i)e=0;else{c=1;while(1){f=wa(a|0,e|0,(15-c|0)*3|0)|0;A()|0;f=f&7;if(f|0){e=f;break c}if(c>>>0>>0)c=c+1|0;else{e=0;break}}}while(0);e=(e|0)==4&1}if(!(ha(d,g,e,0)|0)){if((g|0)!=(i|0)){b[h>>2]=b[j>>2];b[h+4>>2]=b[j+4>>2];b[h+8>>2]=b[j+8>>2]}}else{if(T(k)|0)do{}while((ha(d,g,0,0)|0)!=0);if((g|0)!=(i|0))_(h)}L=l;return}function oa(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=L;L=L+16|0;e=d;na(a,b,e);b=wa(a|0,b|0,52)|0;A()|0;ga(e,b&15,c);L=d;return}function pa(a){a=a|0;var b=0.0,c=0.0;c=+d[a>>3];b=+d[a+8>>3];return +(+q(+(c*c+b*b)))}function qa(){return 6096}function ra(a){a=+a;return +(+Aa(+a))}function sa(a){a=+a;return ~~+ra(a)|0}function ta(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=L;L=L+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[1525]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=6140+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[1525]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;L=w;return v|0}l=b[1527]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=6140+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[1530]|0;c=l>>>3;d=6140+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[1527]=h;b[1530]=f;v=i;L=w;return v|0}g=b[1526]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[6404+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=6404+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[1526]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[1530]|0;c=l>>>3;d=6140+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[1527]=j;b[1530]=h}v=i+8|0;L=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[1526]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[6404+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[6404+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[1527]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=6404+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=6140+(c<<1<<2)|0;a=b[1525]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=6404+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;L=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[1527]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[1530]|0;if(c>>>0>15){v=a+m|0;b[1530]=v;b[1527]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[1527]=0;b[1530]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;L=w;return v|0}h=b[1528]|0;if(h>>>0>m>>>0){t=h-m|0;b[1528]=t;v=b[1531]|0;u=v+m|0;b[1531]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;L=w;return v|0}if(!(b[1643]|0)){b[1645]=4096;b[1644]=4096;b[1646]=-1;b[1647]=-1;b[1648]=0;b[1636]=0;b[1643]=n&-16^1431655768;a=4096}else a=b[1645]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;L=w;return v|0}a=b[1635]|0;if(a|0?(l=b[1633]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;L=w;return v|0}d:do if(!(b[1636]&4)){d=b[1531]|0;e:do if(d){e=6548;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=Ba(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=Ba(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[1644]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[1633]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[1635]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=Ba(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[1645]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((Ba(a|0)|0)==(-1|0)){Ba(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[1636]=b[1636]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=Ba(k|0)|0,p=Ba(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[1633]|0)+h|0;b[1633]=c;if(c>>>0>(b[1634]|0)>>>0)b[1634]=c;j=b[1531]|0;f:do if(j){c=6548;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[1528]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[1531]=u;b[1528]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[1532]=b[1647];break}if(g>>>0<(b[1529]|0)>>>0)b[1529]=g;d=g+h|0;c=6548;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[1528]|0)+i|0;b[1528]=v;b[1531]=k;b[k+4>>2]=v|1}else{if((b[1530]|0)==(c|0)){v=(b[1527]|0)+i|0;b[1527]=v;b[1530]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[1525]=b[1525]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=6404+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[1526]=b[1526]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=6140+(c<<1<<2)|0;a=b[1525]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=6404+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[1526]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;L=w;return v|0}c=6548;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[1531]=u;b[1528]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[1532]=b[1647];d=a+4|0;b[d>>2]=27;b[c>>2]=b[1637];b[c+4>>2]=b[1638];b[c+8>>2]=b[1639];b[c+12>>2]=b[1640];b[1637]=g;b[1638]=h;b[1640]=0;b[1639]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=6140+(c<<1<<2)|0;a=b[1525]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=6404+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[1526]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[1529]|0;if((v|0)==0|g>>>0>>0)b[1529]=g;b[1637]=g;b[1638]=h;b[1640]=0;b[1534]=b[1643];b[1533]=-1;b[1538]=6140;b[1537]=6140;b[1540]=6148;b[1539]=6148;b[1542]=6156;b[1541]=6156;b[1544]=6164;b[1543]=6164;b[1546]=6172;b[1545]=6172;b[1548]=6180;b[1547]=6180;b[1550]=6188;b[1549]=6188;b[1552]=6196;b[1551]=6196;b[1554]=6204;b[1553]=6204;b[1556]=6212;b[1555]=6212;b[1558]=6220;b[1557]=6220;b[1560]=6228;b[1559]=6228;b[1562]=6236;b[1561]=6236;b[1564]=6244;b[1563]=6244;b[1566]=6252;b[1565]=6252;b[1568]=6260;b[1567]=6260;b[1570]=6268;b[1569]=6268;b[1572]=6276;b[1571]=6276;b[1574]=6284;b[1573]=6284;b[1576]=6292;b[1575]=6292;b[1578]=6300;b[1577]=6300;b[1580]=6308;b[1579]=6308;b[1582]=6316;b[1581]=6316;b[1584]=6324;b[1583]=6324;b[1586]=6332;b[1585]=6332;b[1588]=6340;b[1587]=6340;b[1590]=6348;b[1589]=6348;b[1592]=6356;b[1591]=6356;b[1594]=6364;b[1593]=6364;b[1596]=6372;b[1595]=6372;b[1598]=6380;b[1597]=6380;b[1600]=6388;b[1599]=6388;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[1531]=u;b[1528]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[1532]=b[1647]}while(0);c=b[1528]|0;if(c>>>0>m>>>0){t=c-m|0;b[1528]=t;v=b[1531]|0;u=v+m|0;b[1531]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;L=w;return v|0}}v=qa()|0;b[v>>2]=12;v=0;L=w;return v|0}function ua(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[1529]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[1530]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[1527]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[1525]=b[1525]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=6404+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[1526]=b[1526]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[1531]|0)==(j|0)){j=(b[1528]|0)+c|0;b[1528]=j;b[1531]=i;b[i+4>>2]=j|1;if((i|0)!=(b[1530]|0))return;b[1530]=0;b[1527]=0;return}if((b[1530]|0)==(j|0)){j=(b[1527]|0)+c|0;b[1527]=j;b[1530]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[1525]=b[1525]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=6404+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[1526]=b[1526]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[1530]|0)){b[1527]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=6140+(a<<1<<2)|0;c=b[1525]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=6404+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[1526]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[1533]|0)+-1|0;b[1533]=j;if(j|0)return;a=6556;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[1533]=-1;return}function va(a,c){a=a|0;c=c|0;var d=0;if(a){d=x(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=ta(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;za(a|0,0,d|0)|0;return a|0}function wa(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){z(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function xa(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){z(b<>>32-c|0);return a<=8192){D(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function za(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function Aa(a){a=+a;return a>=0.0?+o(a+.5):+w(a-.5)}function Ba(a){a=a|0;var c=0,d=0,e=0;e=C()|0;d=b[f>>2]|0;c=d+a|0;if((a|0)>0&(c|0)<(d|0)|(c|0)<0){F(c|0)|0;B(12);return -1}if((c|0)>(e|0))if(!(E(c|0)|0)){B(12);return -1}b[f>>2]=c;return d|0} - -// EMSCRIPTEN_END_FUNCS -return{_bitshift64Lshr:wa,_bitshift64Shl:xa,_calloc:va,_emscripten_replace_memory:O,_free:ua,_h3IsValid:ka,_h3ToGeo:oa,_malloc:ta,_memcpy:ya,_memset:za,_round:Aa,_sbrk:Ba,establishStackSpace:S,stackAlloc:P,stackRestore:R,stackSave:Q}}) - - -// EMSCRIPTEN_END_ASM -(asmGlobalArg,asmLibraryArg,buffer);var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _h3IsValid=Module["_h3IsValid"]=asm["_h3IsValid"];var _h3ToGeo=Module["_h3ToGeo"]=asm["_h3ToGeo"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _round=Module["_round"]=asm["_round"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); - - - - return libh3 -} -)(typeof libh3 === 'object' ? libh3 : {}); -export default libh3; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_distance/h3core_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_distance/h3core_custom.js deleted file mode 100644 index 54d5c4b75..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_distance/h3core_custom.js +++ /dev/null @@ -1,1352 +0,0 @@ -/* - * Copyright 2018-2019 Uber Technologies, Inc. - * Copyright 2021 CARTO - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @module h3 - */ - -import C from './libh3_custom'; -import BINDINGS from 'h3-js/lib/bindings'; - -const H3 = {}; - -// Create the bound functions themselves -BINDINGS.forEach(function bind (def) { - // Bind only exported functions - if (C['_' + def[0]]) { - H3[def[0]] = C.cwrap(...def); - } -}); - -// Alias the hexidecimal base for legibility -const BASE_16 = 16; - -// ---------------------------------------------------------------------------- -// Byte size imports - -const SZ_INT = 4; -const SZ_PTR = 4; -const SZ_DBL = 8; -const SZ_H3INDEX = H3.sizeOfH3Index && H3.sizeOfH3Index(); -const SZ_GEOCOORD = H3.sizeOfGeoCoord && H3.sizeOfGeoCoord(); -const SZ_GEOBOUNDARY = H3.sizeOfGeoBoundary && H3.sizeOfGeoBoundary(); -const SZ_GEOPOLYGON = H3.sizeOfGeoPolygon && H3.sizeOfGeoPolygon(); -const SZ_GEOFENCE = H3.sizeOfGeofence && H3.sizeOfGeofence(); -const SZ_LINKED_GEOPOLYGON = H3.sizeOfLinkedGeoPolygon && H3.sizeOfLinkedGeoPolygon(); -const SZ_COORDIJ = H3.sizeOfCoordIJ && H3.sizeOfCoordIJ(); - -// ---------------------------------------------------------------------------- -// Custom types - -/** - * 64-bit hexidecimal string representation of an H3 index - * @static - * @typedef {string} H3Index - */ - -/** - * 64-bit hexidecimal string representation of an H3 index, - * or two 32-bit integers in little endian order in an array. - * @static - * @typedef {string | number[]} H3IndexInput - */ - -/** - * Coordinates as an `{i, j}` pair - * @static - * @typedef CoordIJ - * @type {Object} - * @property {number} i - * @property {number} j - */ - -// ---------------------------------------------------------------------------- -// Unit constants - -/** - * Length/Area units - * @static - * @typedef UNITS - * @type {Object} - * @property {string} m - * @property {string} m2 - * @property {string} km - * @property {string} km2 - * @property {string} rads - * @property {string} rads2 - */ -export const UNITS = { - m: 'm', - m2: 'm2', - km: 'km', - km2: 'km2', - rads: 'rads', - rads2: 'rads2' -}; - -// ---------------------------------------------------------------------------- -// Utilities and helpers - -/** - * Validate a resolution, throwing an error if invalid - * @private - * @param {mixed} res Value to validate - * @throws {Error} Error if invalid - */ -function validateRes (res) { - if (typeof res !== 'number' || res < 0 || res > 15 || Math.floor(res) !== res) { - throw new Error(`Invalid resolution: ${res}`); - } -} - -const INVALID_HEXIDECIMAL_CHAR = /[^0-9a-fA-F]/; - -/** - * Convert an H3 index (64-bit hexidecimal string) into a "split long" - a pair of 32-bit ints - * @private - * @param {H3IndexInput} h3Index H3 index to check - * @return {number[]} A two-element array with 32 lower bits and 32 upper bits - */ -export function h3IndexToSplitLong (h3Index) { - if ( - Array.isArray(h3Index) && - h3Index.length === 2 && - Number.isInteger(h3Index[0]) && - Number.isInteger(h3Index[1]) - ) { - return h3Index; - } - if (typeof h3Index !== 'string' || INVALID_HEXIDECIMAL_CHAR.test(h3Index)) { - return [0, 0]; - } - const upper = parseInt(h3Index.substring(0, h3Index.length - 8), BASE_16); - const lower = parseInt(h3Index.substring(h3Index.length - 8), BASE_16); - return [lower, upper]; -} - -/** - * Convert a 32-bit int to a hexdecimal string - * @private - * @param {number} num Integer to convert - * @return {H3Index} Hexidecimal string - */ -function hexFrom32Bit (num) { - if (num >= 0) { - return num.toString(BASE_16); - } - - // Handle negative numbers - num = num & 0x7fffffff; - let tempStr = zeroPad(8, num.toString(BASE_16)); - const topNum = (parseInt(tempStr[0], BASE_16) + 8).toString(BASE_16); - tempStr = topNum + tempStr.substring(1); - return tempStr; -} - -/** - * Get a H3 index from a split long (pair of 32-bit ints) - * @private - * @param {number} lower Lower 32 bits - * @param {number} upper Upper 32 bits - * @return {H3Index} H3 index - */ -export function splitLongToh3Index (lower, upper) { - return hexFrom32Bit(upper) + zeroPad(8, hexFrom32Bit(lower)); -} - -/** - * Zero-pad a string to a given length - * @private - * @param {number} fullLen Target length - * @param {string} numStr String to zero-pad - * @return {string} Zero-padded string - */ -function zeroPad (fullLen, numStr) { - const numZeroes = fullLen - numStr.length; - let outStr = ''; - for (let i = 0; i < numZeroes; i++) { - outStr += '0'; - } - outStr = outStr + numStr; - return outStr; -} - -/** - * Populate a C-appropriate Geofence struct from a polygon array - * @private - * @param {Array[]} polygonArray Polygon, as an array of coordinate pairs - * @param {number} geofence C pointer to a Geofence struct - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated Geofence struct - */ -function polygonArrayToGeofence (polygonArray, geofence, isGeoJson) { - const numVerts = polygonArray.length; - const geoCoordArray = C._calloc(numVerts, SZ_GEOCOORD); - // Support [lng, lat] pairs if GeoJSON is specified - const latIndex = isGeoJson ? 1 : 0; - const lngIndex = isGeoJson ? 0 : 1; - for (let i = 0; i < numVerts * 2; i += 2) { - C.HEAPF64.set( - [polygonArray[i / 2][latIndex], polygonArray[i / 2][lngIndex]].map(degsToRads), - geoCoordArray / SZ_DBL + i - ); - } - C.HEAPU32.set([numVerts, geoCoordArray], geofence / SZ_INT); - return geofence; -} - -/** - * Create a C-appropriate GeoPolygon struct from an array of polygons - * @private - * @param {Array[]} coordinates Array of polygons, each an array of coordinate pairs - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated GeoPolygon struct - */ -function coordinatesToGeoPolygon (coordinates, isGeoJson) { - // Any loops beyond the first loop are holes - const numHoles = coordinates.length - 1; - const geoPolygon = C._calloc(SZ_GEOPOLYGON); - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // geofence is first part of struct - polygonArrayToGeofence(coordinates[0], geoPolygon + geofenceOffset, isGeoJson); - let holes; - if (numHoles > 0) { - holes = C._calloc(numHoles, SZ_GEOFENCE); - for (let i = 0; i < numHoles; i++) { - polygonArrayToGeofence(coordinates[i + 1], holes + SZ_GEOFENCE * i, isGeoJson); - } - } - C.setValue(geoPolygon + numHolesOffset, numHoles, 'i32'); - C.setValue(geoPolygon + holesOffset, holes, 'i32'); - return geoPolygon; -} - -/** - * Free memory allocated for a GeoPolygon struct. It is an error to access the struct - * after passing it to this method. - * @private - * @return {number} geoPolygon C pointer to populated GeoPolygon struct - */ -function destroyGeoPolygon (geoPolygon) { - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // Offset of the geofence vertex array pointer within the Geofence struct - const geofenceArrayOffset = SZ_INT; - // Free the outer vertex array - C._free(C.getValue(geoPolygon + geofenceOffset + geofenceArrayOffset, 'i8*')); - // Free the vertex array for the holes, if any - const numHoles = C.getValue(geoPolygon + numHolesOffset, 'i32'); - if (numHoles > 0) { - const holes = C.getValue(geoPolygon + holesOffset, 'i32'); - for (let i = 0; i < numHoles; i++) { - C._free(C.getValue(holes + SZ_GEOFENCE * i + geofenceArrayOffset, 'i8*')); - } - C._free(holes); - } - C._free(geoPolygon); -} - -/** - * Read a long value, returning the lower and upper portions as separate 32-bit integers. - * Because the upper bits are returned via side effect, the argument to this function is - * intended to be the invocation that caused the side effect, e.g. readLong(H3.getSomeLong()) - * @private - * @param {number} invocation Invoked function returning a long value. The actual return - * value of these functions is a 32-bit integer. - * @return {number} Long value as a [lower, upper] pair - */ -function readLong (invocation) { - // Upper 32-bits of the long set via side-effect - const upper = C.getTempRet0(); - return [invocation, upper]; -} - -/** - * Read an H3 index from a C return value. As with readLong, the argument to this function - * is intended to be an invocation, e.g. readH3Index(H3.getSomeAddress()), to help ensure that - * the temp value storing the upper bits of the long is still set. - * @private - * @param {number} invocation Invoked function returning a single H3 index - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3Index (invocation) { - const [lower, upper] = readLong(invocation); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Read an H3 index from a pointer to C memory. - * @private - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes, in case we're - * reading an array - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3IndexFromPointer (cAddress, offset = 0) { - const lower = C.getValue(cAddress + SZ_INT * offset * 2, 'i32'); - const upper = C.getValue(cAddress + SZ_INT * (offset * 2 + 1), 'i32'); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Store an H3 index in C memory. Primarily used as an efficient way to - * write sets of hexagons. - * @private - * @param {H3IndexInput} h3Index H3 index to store - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes from beginning - * of the current array - */ -function storeH3Index (h3Index, cAddress, offset) { - // HEAPU32 is a typed array projection on the index space - // as unsigned 32-bit integers. This means the index needs - // to be divided by SZ_INT (4) to access correctly. Also, - // the H3 index is 64 bits, so we skip by twos as we're writing - // to 32-bit integers in the proper order. - C.HEAPU32.set(h3IndexToSplitLong(h3Index), cAddress / SZ_INT + 2 * offset); -} - -/** - * Read an array of 64-bit H3 indexes from C and convert to a JS array of - * H3 index strings - * @private - * @param {number} cAddress Pointer to C ouput array - * @param {number} maxCount Max number of hexagons in array. Hexagons with - * the value 0 will be skipped, so this isn't - * necessarily the length of the output array. - * @return {H3Index[]} Array of H3 indexes - */ -function readArrayOfHexagons (cAddress, maxCount) { - const out = []; - for (let i = 0; i < maxCount; i++) { - const h3Index = readH3IndexFromPointer(cAddress, i); - if (h3Index !== null) { - out.push(h3Index); - } - } - return out; -} - -/** - * Store an array of H3 index strings as a C array of 64-bit integers. - * @private - * @param {number} cAddress Pointer to C input array - * @param {H3IndexInput[]} hexagons H3 indexes to pass to the C lib - */ -function storeArrayOfHexagons (cAddress, hexagons) { - // Assuming the cAddress points to an already appropriately - // allocated space - const count = hexagons.length; - for (let i = 0; i < count; i++) { - storeH3Index(hexagons[i], cAddress, i); - } -} - -/** - * Populate a C-appropriate GeoCoord struct from a [lat, lng] array - * @private - * @param {number} lat Coordinate latitude - * @param {number} lng Coordinate longitude - * @return {number} C pointer to populated GeoCoord struct - */ -function storeGeoCoord (lat, lng) { - const geoCoord = C._calloc(1, SZ_GEOCOORD); - C.HEAPF64.set([lat, lng].map(degsToRads), geoCoord / SZ_DBL); - return geoCoord; -} - -function readSingleCoord (cAddress) { - return radsToDegs(C.getValue(cAddress, 'double')); -} - -/** - * Read a GeoCoord from C and return a [lat, lng] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lat, lng] pair - */ -function readGeoCoord (cAddress) { - return [readSingleCoord(cAddress), readSingleCoord(cAddress + SZ_DBL)]; -} - -/** - * Read a GeoCoord from C and return a GeoJSON-style [lng, lat] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lng, lat] pair - */ -function readGeoCoordGeoJson (cAddress) { - return [readSingleCoord(cAddress + SZ_DBL), readSingleCoord(cAddress)]; -} - -/** - * Read the GeoBoundary structure into a list of geo coordinate pairs - * @private - * @param {number} geoBoundary C pointer to GeoBoundary struct - * @param {boolean} geoJsonCoords Whether to provide GeoJSON coordinate order: [lng, lat] - * @param {boolean} closedLoop Whether to close the loop - * @return {Array[]} Array of geo coordinate pairs - */ -function readGeoBoundary (geoBoundary, geoJsonCoords, closedLoop) { - const numVerts = C.getValue(geoBoundary, 'i32'); - // Note that though numVerts is an int, the coordinate doubles have to be - // aligned to 8 bytes, hence the 8-byte offset here - const vertsPos = geoBoundary + SZ_DBL; - const out = []; - // Support [lng, lat] pairs if GeoJSON is specified - const readCoord = geoJsonCoords ? readGeoCoordGeoJson : readGeoCoord; - for (let i = 0; i < numVerts * 2; i += 2) { - out.push(readCoord(vertsPos + SZ_DBL * i)); - } - if (closedLoop) { - // Close loop if GeoJSON is specified - out.push(out[0]); - } - return out; -} - -/** - * Read the LinkedGeoPolygon structure into a nested array of MultiPolygon coordinates - * @private - * @param {number} polygon C pointer to LinkedGeoPolygon struct - * @param {boolean} formatAsGeoJson Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -function readMultiPolygon (polygon, formatAsGeoJson) { - const output = []; - const readCoord = formatAsGeoJson ? readGeoCoordGeoJson : readGeoCoord; - let loops; - let loop; - let coords; - let coord; - // Loop through the linked structure, building the output - while (polygon) { - output.push((loops = [])); - // Follow ->first pointer - loop = C.getValue(polygon, 'i8*'); - while (loop) { - loops.push((coords = [])); - // Follow ->first pointer - coord = C.getValue(loop, 'i8*'); - while (coord) { - coords.push(readCoord(coord)); - // Follow ->next pointer - coord = C.getValue(coord + SZ_DBL * 2, 'i8*'); - } - if (formatAsGeoJson) { - // Close loop if GeoJSON is requested - coords.push(coords[0]); - } - // Follow ->next pointer - loop = C.getValue(loop + SZ_PTR * 2, 'i8*'); - } - // Follow ->next pointer - polygon = C.getValue(polygon + SZ_PTR * 2, 'i8*'); - } - return output; -} - -/** - * Read a CoordIJ from C and return an {i, j} pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function readCoordIJ (cAddress) { - return { - i: C.getValue(cAddress, 'i32'), - j: C.getValue(cAddress + SZ_INT, 'i32') - }; -} - -/** - * Store an {i, j} pair to a C CoordIJ struct. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function storeCoordIJ (cAddress, {i, j}) { - C.setValue(cAddress, i, 'i32'); - C.setValue(cAddress + SZ_INT, j, 'i32'); -} - -/** - * Read an array of positive integers array from C. Negative - * values are considered invalid and ignored in output. - * @private - * @param {number} cAddress Pointer to C array - * @param {number} count Length of C array - * @return {number[]} Javascript integer array - */ -function readArrayOfPositiveIntegers (cAddress, count) { - const out = []; - for (let i = 0; i < count; i++) { - const int = C.getValue(cAddress + SZ_INT * i, 'i32'); - if (int >= 0) { - out.push(int); - } - } - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Core - -/** - * Whether a given string represents a valid H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} Whether the index is valid - */ -export function h3IsValid (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsValid(lower, upper)); -} - -/** - * Whether the given H3 index is a pentagon - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isPentagon - */ -export function h3IsPentagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsPentagon(lower, upper)); -} - -/** - * Whether the given H3 index is in a Class III resolution (rotated versus - * the icosahedron and subject to shape distortion adding extra points on - * icosahedron edges, making them not true hexagons). - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isResClassIII - */ -export function h3IsResClassIII (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsResClassIII(lower, upper)); -} - -/** - * Get the number of the base cell for a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get the base cell for - * @return {number} Index of the base cell (0-121) - */ -export function h3GetBaseCell (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return H3.h3GetBaseCell(lower, upper); -} - -/** - * Get the indices of all icosahedron faces intersected by a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get faces for - * @return {number[]} Indices (0-19) of all intersected faces - */ -export function h3GetFaces (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = H3.maxFaceCount(lower, upper); - const faces = C._malloc(SZ_INT * count); - H3.h3GetFaces(lower, upper, faces); - const out = readArrayOfPositiveIntegers(faces, count); - C._free(faces); - return out; -} - -/** - * Returns the resolution of an H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get resolution - * @return {number} The number (0-15) resolution, or -1 if invalid - */ -export function h3GetResolution (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - if (!H3.h3IsValid(lower, upper)) { - // Compatability with stated API - return -1; - } - return H3.h3GetResolution(lower, upper); -} - -/** - * Get the hexagon containing a lat,lon point - * @static - * @param {number} lat Latitude of point - * @param {number} lng Longtitude of point - * @param {number} res Resolution of hexagons to return - * @return {H3Index} H3 index - */ -export function geoToH3 (lat, lng, res) { - const latlng = C._malloc(SZ_GEOCOORD); - // Slightly more efficient way to set the memory - C.HEAPF64.set([lat, lng].map(degsToRads), latlng / SZ_DBL); - // Read value as a split long - const h3Index = readH3Index(H3.geoToH3(latlng, res)); - C._free(latlng); - return h3Index; -} - -/** - * Get the lat,lon center of a given hexagon - * @static - * @param {H3IndexInput} h3Index H3 index - * @return {number[]} Point as a [lat, lng] pair - */ -export function h3ToGeo (h3Index) { - const latlng = C._malloc(SZ_GEOCOORD); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeo(lower, upper, latlng); - const out = readGeoCoord(latlng); - C._free(latlng); - return out; -} - -/** - * Get the vertices of a given hexagon (or pentagon), as an array of [lat, lng] - * points. For pentagons and hexagons on the edge of an icosahedron face, this - * function may return up to 10 vertices. - * @static - * @param {H3Index} h3Index H3 index - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][]} Array of [lat, lng] pairs - */ -export function h3ToGeoBoundary (h3Index, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeoBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Algorithms - -/** - * Get the parent of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get parent for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of parent, or null for invalid input - */ -export function h3ToParent (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToParent(lower, upper, res)); -} - -/** - * Get the children/descendents of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get children for - * @param {number} res Resolution of hexagons to return - * @return {H3Index[]} H3 indexes of children, or empty array for invalid input - */ -export function h3ToChildren (h3Index, res) { - // Bad input in this case can potentially result in high computation volume - // using the current C algorithm. Validate and return an empty array on failure. - if (!h3IsValid(h3Index)) { - return []; - } - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxH3ToChildrenSize(lower, upper, res); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.h3ToChildren(lower, upper, res, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get the center child of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get center child for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of child, or null for invalid input - */ -export function h3ToCenterChild (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToCenterChild(lower, upper, res)); -} - -/** - * Get all hexagons in a k-ring around a given center. The order of the hexagons is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - */ -export function kRing (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.kRing(lower, upper, ringSize, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons in a k-ring around a given center, in an array of arrays - * ordered by distance from the origin. The order of the hexagons within each ring is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[][]} Array of arrays with H3 indexes for all hexagons each ring - */ -export function kRingDistances (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const kRings = C._calloc(maxCount, SZ_H3INDEX); - const distances = C._calloc(maxCount, SZ_INT); - H3.kRingDistances(lower, upper, ringSize, kRings, distances); - // Create an array of empty arrays to hold the output - const out = []; - for (let i = 0; i < ringSize + 1; i++) { - out.push([]); - } - // Read the array of hexagons, putting them into the appropriate rings - for (let i = 0; i < maxCount * 2; i += 2) { - const hexLower = C.getValue(kRings + SZ_INT * i, 'i32'); - const hexUpper = C.getValue(kRings + SZ_INT * (i + 1), 'i32'); - const index = C.getValue(distances + SZ_INT * (i / 2), 'i32'); - if (hexLower !== 0 || hexUpper !== 0) { - out[index].push(splitLongToh3Index(hexLower, hexUpper)); - } - } - C._free(kRings); - C._free(distances); - return out; -} - -/** - * Get all hexagons in a hollow hexagonal ring centered at origin with sides of a given length. - * Unlike kRing, this function will throw an error if there is a pentagon anywhere in the ring. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - * @throws {Error} If the algorithm could not calculate the ring - */ -export function hexRing (h3Index, ringSize) { - const maxCount = ringSize === 0 ? 1 : 6 * ringSize; - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - const retVal = H3.hexRing(...h3IndexToSplitLong(h3Index), ringSize, hexagons); - if (retVal !== 0) { - C._free(hexagons); - throw new Error('Failed to get hexRing (encountered a pentagon?)'); - } - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons with centers contained in a given polygon. The polygon - * is specified with GeoJson semantics as an array of loops. Each loop is - * an array of [lat, lng] pairs (or [lng, lat] if isGeoJson is specified). - * The first loop is the perimeter of the polygon, and subsequent loops are - * expected to be holes. - * @static - * @param {number[][] | number[][][]} coordinates - * Array of loops, or a single loop - * @param {number} res Resolution of hexagons to return - * @param {boolean} [isGeoJson] Whether to expect GeoJson-style [lng, lat] - * pairs instead of [lat, lng] - * @return {H3Index[]} H3 indexes for all hexagons in polygon - */ -export function polyfill (coordinates, res, isGeoJson) { - validateRes(res); - isGeoJson = Boolean(isGeoJson); - // Guard against empty input - if (coordinates.length === 0 || coordinates[0].length === 0) { - return []; - } - // Wrap to expected format if a single loop is provided - if (typeof coordinates[0][0] === 'number') { - coordinates = [coordinates]; - } - const geoPolygon = coordinatesToGeoPolygon(coordinates, isGeoJson); - const arrayLen = H3.maxPolyfillSize(geoPolygon, res); - const hexagons = C._calloc(arrayLen, SZ_H3INDEX); - H3.polyfill(geoPolygon, res, hexagons); - const out = readArrayOfHexagons(hexagons, arrayLen); - C._free(hexagons); - destroyGeoPolygon(geoPolygon); - return out; -} - -/** - * Get the outlines of a set of H3 hexagons, returned in GeoJSON MultiPolygon - * format (an array of polygons, each with an array of loops, each an array of - * coordinates). Coordinates are returned as [lat, lng] pairs unless GeoJSON - * is requested. - * - * It is the responsibility of the caller to ensure that all hexagons in the - * set have the same resolution and that the set contains no duplicates. Behavior - * is undefined if duplicates or multiple resolutions are present, and the - * algorithm may produce unexpected or invalid polygons. - * - * @static - * @param {H3IndexInput[]} h3Indexes H3 indexes to get outlines for - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: - * [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -export function h3SetToMultiPolygon (h3Indexes, formatAsGeoJson) { - // Early exit on empty input - if (!h3Indexes || !h3Indexes.length) { - return []; - } - // Set up input set - const indexCount = h3Indexes.length; - const set = C._calloc(indexCount, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Indexes); - // Allocate memory for output linked polygon - const polygon = C._calloc(SZ_LINKED_GEOPOLYGON); - // Store a reference to the first polygon - that's the one we need for - // memory deallocation - const originalPolygon = polygon; - H3.h3SetToLinkedGeo(set, indexCount, polygon); - const multiPolygon = readMultiPolygon(polygon, formatAsGeoJson); - // Clean up - H3.destroyLinkedPolygon(originalPolygon); - C._free(originalPolygon); - C._free(set); - return multiPolygon; -} - -/** - * Compact a set of hexagons of the same resolution into a set of hexagons across - * multiple levels that represents the same area. - * @static - * @param {H3IndexInput[]} h3Set H3 indexes to compact - * @return {H3Index[]} Compacted H3 indexes - * @throws {Error} If the input is invalid (e.g. duplicate hexagons) - */ -export function compact (h3Set) { - if (!h3Set || !h3Set.length) { - return []; - } - // Set up input set - const count = h3Set.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Set); - // Allocate memory for compacted hexagons, worst-case is no compaction - const compactedSet = C._calloc(count, SZ_H3INDEX); - const retVal = H3.compact(set, compactedSet, count); - if (retVal !== 0) { - C._free(set); - C._free(compactedSet); - throw new Error('Failed to compact, malformed input data (duplicate hexagons?)'); - } - const out = readArrayOfHexagons(compactedSet, count); - C._free(set); - C._free(compactedSet); - return out; -} - -/** - * Uncompact a compacted set of hexagons to hexagons of the same resolution - * @static - * @param {H3IndexInput[]} compactedSet H3 indexes to uncompact - * @param {number} res The resolution to uncompact to - * @return {H3Index[]} The uncompacted H3 indexes - * @throws {Error} If the input is invalid (e.g. invalid resolution) - */ -export function uncompact (compactedSet, res) { - validateRes(res); - if (!compactedSet || !compactedSet.length) { - return []; - } - // Set up input set - const count = compactedSet.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, compactedSet); - // Estimate how many hexagons we need (always overestimates if in error) - const maxUncompactedNum = H3.maxUncompactSize(set, count, res); - // Allocate memory for uncompacted hexagons - const uncompactedSet = C._calloc(maxUncompactedNum, SZ_H3INDEX); - const retVal = H3.uncompact(set, count, uncompactedSet, maxUncompactedNum, res); - if (retVal !== 0) { - C._free(set); - C._free(uncompactedSet); - throw new Error('Failed to uncompact (bad resolution?)'); - } - const out = readArrayOfHexagons(uncompactedSet, maxUncompactedNum); - C._free(set); - C._free(uncompactedSet); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Unidirectional edges - -/** - * Whether two H3 indexes are neighbors (share an edge) - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {boolean} Whether the hexagons share an edge - */ -export function h3IndexesAreNeighbors (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return Boolean(H3.h3IndexesAreNeighbors(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get an H3 index representing a unidirectional edge for a given origin and destination - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index} H3 index of the edge, or null if no edge is shared - */ -export function getH3UnidirectionalEdge (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return readH3Index(H3.getH3UnidirectionalEdge(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get the origin hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge origin - */ -export function getOriginH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getOriginH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Get the destination hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge destination - */ -export function getDestinationH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getDestinationH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Whether the input is a valid unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {boolean} Whether the index is valid - */ -export function h3UnidirectionalEdgeIsValid (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return Boolean(H3.h3UnidirectionalEdgeIsValid(lower, upper)); -} - -/** - * Get the [origin, destination] pair represented by a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index[]} [origin, destination] pair as H3 indexes - */ -export function getH3IndexesFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - const count = 2; - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.getH3IndexesFromUnidirectionalEdge(lower, upper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get all of the unidirectional edges with the given H3 index as the origin (i.e. an edge to - * every neighbor) - * @static - * @param {H3IndexInput} h3Index H3 index of the origin hexagon - * @return {H3Index[]} List of unidirectional edges - */ -export function getH3UnidirectionalEdgesFromHexagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = 6; - const edges = C._calloc(count, SZ_H3INDEX); - H3.getH3UnidirectionalEdgesFromHexagon(lower, upper, edges); - const out = readArrayOfHexagons(edges, count); - C._free(edges); - return out; -} - -/** - * Get the vertices of a given edge as an array of [lat, lng] points. Note that for edges that - * cross the edge of an icosahedron face, this may return 3 coordinates. - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat] - * @return {number[][]} Array of geo coordinate pairs - */ -export function getH3UnidirectionalEdgeBoundary (edgeIndex, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - H3.getH3UnidirectionalEdgeBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -/** - * Get the grid distance between two hex indexes. This function may fail - * to find the distance between two indexes if they are very far apart or - * on opposite sides of a pentagon. - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {number} Distance between hexagons, or a negative - * number if the distance could not be computed - */ -export function h3Distance (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return H3.h3Distance(oLower, oUpper, dLower, dUpper); -} - -/** - * Given two H3 indexes, return the line of indexes between them (inclusive). - * - * This function may fail to find the line between two indexes, for - * example if they are very far apart. It may also fail when finding - * distances for indexes on opposite sides of a pentagon. - * - * Notes: - * - * - The specific output of this function should not be considered stable - * across library versions. The only guarantees the library provides are - * that the line length will be `h3Distance(start, end) + 1` and that - * every index in the line will be a neighbor of the preceding index. - * - Lines are drawn in grid space, and may not correspond exactly to either - * Cartesian lines or great arcs. - * - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index[]} H3 indexes connecting origin and destination - * @throws {Error} If the line cannot be calculated - */ -export function h3Line (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - const count = H3.h3LineSize(oLower, oUpper, dLower, dUpper); - if (count < 0) { - // We can't get the specific error code here - may be any of - // the errors possible in experimentalH3ToLocalIj - throw new Error('Line cannot be calculated'); - } - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.h3Line(oLower, oUpper, dLower, dUpper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Produces IJ coordinates for an H3 index anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {H3IndexInput} destination H3 index for which to find relative coordinates - * @return {CoordIJ} Coordinates as an `{i, j}` pair - * @throws {Error} If the IJ coordinates cannot be calculated - */ -export function experimentalH3ToLocalIj (origin, destination) { - const ij = C._malloc(SZ_COORDIJ); - const retVal = H3.experimentalH3ToLocalIj( - ...h3IndexToSplitLong(origin), - ...h3IndexToSplitLong(destination), - ij - ); - const coords = readCoordIJ(ij); - C._free(ij); - // Return the pair, or throw if an error code was returned. - // Switch statement and error codes cribbed from h3-java's implementation. - switch (retVal) { - case 0: - return coords; - case 1: - throw new Error('Incompatible origin and index.'); - case 2: - default: - throw new Error( - 'Local IJ coordinates undefined for this origin and index pair. ' + - 'The index may be too far from the origin.' - ); - case 3: - case 4: - case 5: - throw new Error('Encountered possible pentagon distortion'); - } -} - -/** - * Produces an H3 index for IJ coordinates anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {CoordIJ} coords Coordinates as an `{i, j}` pair - * @return {H3Index} H3 index at the relative coordinates - * @throws {Error} If the H3 index cannot be calculated - */ -export function experimentalLocalIjToH3 (origin, coords) { - // Validate input coords - if (!coords || typeof coords.i !== 'number' || typeof coords.j !== 'number') { - throw new Error('Coordinates must be provided as an {i, j} object'); - } - // Allocate memory for the CoordIJ struct and an H3 index to hold the return value - const ij = C._malloc(SZ_COORDIJ); - const out = C._malloc(SZ_H3INDEX); - storeCoordIJ(ij, coords); - const retVal = H3.experimentalLocalIjToH3(...h3IndexToSplitLong(origin), ij, out); - const h3Index = readH3IndexFromPointer(out); - C._free(ij); - C._free(out); - if (retVal !== 0) { - throw new Error( - 'Index not defined for this origin and IJ coordinates pair. ' + - 'IJ coordinates may be too far from origin, or ' + - 'a pentagon distortion was encountered.' - ); - } - return h3Index; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Distance/area utilities - -/** - * Great circle distance between two geo points. This is not specific to H3, - * but is implemented in the library and provided here as a convenience. - * @static - * @param {number[]} latlng1 Origin coordinate as [lat, lng] - * @param {number[]} latlng2 Destination coordinate as [lat, lng] - * @param {string} unit Distance unit (either UNITS.m or UNITS.km) - * @return {number} Great circle distance - * @throws {Error} If the unit is invalid - */ -export function pointDist (latlng1, latlng2, unit) { - const coord1 = storeGeoCoord(latlng1[0], latlng1[1]); - const coord2 = storeGeoCoord(latlng2[0], latlng2[1]); - let result; - switch (unit) { - case UNITS.m: - result = H3.pointDistM(coord1, coord2); - break; - case UNITS.km: - result = H3.pointDistKm(coord1, coord2); - break; - case UNITS.rads: - result = H3.pointDistRads(coord1, coord2); - break; - default: - result = null; - } - C._free(coord1); - C._free(coord2); - if (result === null) { - throw new Error(`Unknown unit: ${unit}`); - } - return result; -} - -/** - * Exact area of a given cell - * @static - * @param {H3Index} h3Index H3 index of the hexagon to measure - * @param {string} unit Distance unit (either UNITS.m2 or UNITS.km2) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function cellArea (h3Index, unit) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - switch (unit) { - case UNITS.m2: - return H3.cellAreaM2(lower, upper); - case UNITS.km2: - return H3.cellAreaKm2(lower, upper); - case UNITS.rads2: - return H3.cellAreaRads2(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Exact length of a given unidirectional edge - * @static - * @param {H3Index} edge H3 index of the edge to measure - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function exactEdgeLength (edge, unit) { - const [lower, upper] = h3IndexToSplitLong(edge); - switch (unit) { - case UNITS.m: - return H3.exactEdgeLengthM(lower, upper); - case UNITS.km: - return H3.exactEdgeLengthKm(lower, upper); - case UNITS.rads: - return H3.exactEdgeLengthRads(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon area at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Area unit (either UNITS.m2, UNITS.km2, or UNITS.rads2) - * @return {number} Average area - * @throws {Error} If the unit is invalid - */ -export function hexArea (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m2: - return H3.hexAreaM2(res); - case UNITS.km2: - return H3.hexAreaKm2(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon edge length at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Average edge length - * @throws {Error} If the unit is invalid - */ -export function edgeLength (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m: - return H3.edgeLengthM(res); - case UNITS.km: - return H3.edgeLengthKm(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -// ---------------------------------------------------------------------------- -// Public informational utilities - -/** - * The total count of hexagons in the world at a given resolution. Note that above - * resolution 8 the exact count cannot be represented in a JavaScript 32-bit number, - * so consumers should use caution when applying further operations to the output. - * @static - * @param {number} res Hexagon resolution - * @return {number} Count - */ -export function numHexagons (res) { - validateRes(res); - // Get number as a long value - const [lower, upper] = readLong(H3.numHexagons(res)); - // If we're using <= 32 bits we can use normal JS numbers - if (!upper) { - return lower; - } - // Above 32 bit, make a JS number that's correct in order of magnitude - return upper * Math.pow(2, 32) + lower; -} - -/** - * Get all H3 indexes at resolution 0. As every index at every resolution > 0 is - * the descendant of a res 0 index, this can be used with h3ToChildren to iterate - * over H3 indexes at any resolution. - * @static - * @return {H3Index[]} All H3 indexes at res 0 - */ -export function getRes0Indexes () { - const count = H3.res0IndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getRes0Indexes(hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get the twelve pentagon indexes at a given resolution. - * @static - * @param {number} res Hexagon resolution - * @return {H3Index[]} All H3 pentagon indexes at res - */ -export function getPentagonIndexes (res) { - validateRes(res); - const count = H3.pentagonIndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getPentagonIndexes(res, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Convert degrees to radians - * @static - * @param {number} deg Value in degrees - * @return {number} Value in radians - */ -export function degsToRads (deg) { - return (deg * Math.PI) / 180; -} - -/** - * Convert radians to degrees - * @static - * @param {number} rad Value in radians - * @return {number} Value in degrees - */ -export function radsToDegs (rad) { - return (rad * 180) / Math.PI; -} \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_distance/libh3_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_distance/libh3_custom.js deleted file mode 100644 index b1c4c7d85..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_distance/libh3_custom.js +++ /dev/null @@ -1,24 +0,0 @@ - -var libh3 = ( -function(libh3) { - libh3 = libh3 || {}; - -var Module=typeof libh3!=="undefined"?libh3:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=11584,DYNAMIC_BASE=5254464,DYNAMICTOP_PTR=11552;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAQAAAAUAAAACAAAABAAAAAMAAAAIAAAAAQAAAAcAAAAGAAAACQAAAAAAAAADAAAAAgAAAAIAAAAGAAAACgAAAAsAAAAAAAAAAQAAAAUAAAADAAAADQAAAAEAAAAHAAAABAAAAAwAAAAAAAAABAAAAH8AAAAPAAAACAAAAAMAAAAAAAAADAAAAAUAAAACAAAAEgAAAAoAAAAIAAAAAAAAABAAAAAGAAAADgAAAAsAAAARAAAAAQAAAAkAAAACAAAABwAAABUAAAAJAAAAEwAAAAMAAAANAAAAAQAAAAgAAAAFAAAAFgAAABAAAAAEAAAAAAAAAA8AAAAJAAAAEwAAAA4AAAAUAAAAAQAAAAcAAAAGAAAACgAAAAsAAAAYAAAAFwAAAAUAAAACAAAAEgAAAAsAAAARAAAAFwAAABkAAAACAAAABgAAAAoAAAAMAAAAHAAAAA0AAAAaAAAABAAAAA8AAAADAAAADQAAABoAAAAVAAAAHQAAAAMAAAAMAAAABwAAAA4AAAB/AAAAEQAAABsAAAAJAAAAFAAAAAYAAAAPAAAAFgAAABwAAAAfAAAABAAAAAgAAAAMAAAAEAAAABIAAAAhAAAAHgAAAAgAAAAFAAAAFgAAABEAAAALAAAADgAAAAYAAAAjAAAAGQAAABsAAAASAAAAGAAAAB4AAAAgAAAABQAAAAoAAAAQAAAAEwAAACIAAAAUAAAAJAAAAAcAAAAVAAAACQAAABQAAAAOAAAAEwAAAAkAAAAoAAAAGwAAACQAAAAVAAAAJgAAABMAAAAiAAAADQAAAB0AAAAHAAAAFgAAABAAAAApAAAAIQAAAA8AAAAIAAAAHwAAABcAAAAYAAAACwAAAAoAAAAnAAAAJQAAABkAAAAYAAAAfwAAACAAAAAlAAAACgAAABcAAAASAAAAGQAAABcAAAARAAAACwAAAC0AAAAnAAAAIwAAABoAAAAqAAAAHQAAACsAAAAMAAAAHAAAAA0AAAAbAAAAKAAAACMAAAAuAAAADgAAABQAAAARAAAAHAAAAB8AAAAqAAAALAAAAAwAAAAPAAAAGgAAAB0AAAArAAAAJgAAAC8AAAANAAAAGgAAABUAAAAeAAAAIAAAADAAAAAyAAAAEAAAABIAAAAhAAAAHwAAACkAAAAsAAAANQAAAA8AAAAWAAAAHAAAACAAAAAeAAAAGAAAABIAAAA0AAAAMgAAACUAAAAhAAAAHgAAADEAAAAwAAAAFgAAABAAAAApAAAAIgAAABMAAAAmAAAAFQAAADYAAAAkAAAAMwAAACMAAAAuAAAALQAAADgAAAARAAAAGwAAABkAAAAkAAAAFAAAACIAAAATAAAANwAAACgAAAA2AAAAJQAAACcAAAA0AAAAOQAAABgAAAAXAAAAIAAAACYAAAB/AAAAIgAAADMAAAAdAAAALwAAABUAAAAnAAAAJQAAABkAAAAXAAAAOwAAADkAAAAtAAAAKAAAABsAAAAkAAAAFAAAADwAAAAuAAAANwAAACkAAAAxAAAANQAAAD0AAAAWAAAAIQAAAB8AAAAqAAAAOgAAACsAAAA+AAAAHAAAACwAAAAaAAAAKwAAAD4AAAAvAAAAQAAAABoAAAAqAAAAHQAAACwAAAA1AAAAOgAAAEEAAAAcAAAAHwAAACoAAAAtAAAAJwAAACMAAAAZAAAAPwAAADsAAAA4AAAALgAAADwAAAA4AAAARAAAABsAAAAoAAAAIwAAAC8AAAAmAAAAKwAAAB0AAABFAAAAMwAAAEAAAAAwAAAAMQAAAB4AAAAhAAAAQwAAAEIAAAAyAAAAMQAAAH8AAAA9AAAAQgAAACEAAAAwAAAAKQAAADIAAAAwAAAAIAAAAB4AAABGAAAAQwAAADQAAAAzAAAARQAAADYAAABHAAAAJgAAAC8AAAAiAAAANAAAADkAAABGAAAASgAAACAAAAAlAAAAMgAAADUAAAA9AAAAQQAAAEsAAAAfAAAAKQAAACwAAAA2AAAARwAAADcAAABJAAAAIgAAADMAAAAkAAAANwAAACgAAAA2AAAAJAAAAEgAAAA8AAAASQAAADgAAABEAAAAPwAAAE0AAAAjAAAALgAAAC0AAAA5AAAAOwAAAEoAAABOAAAAJQAAACcAAAA0AAAAOgAAAH8AAAA+AAAATAAAACwAAABBAAAAKgAAADsAAAA/AAAATgAAAE8AAAAnAAAALQAAADkAAAA8AAAASAAAAEQAAABQAAAAKAAAADcAAAAuAAAAPQAAADUAAAAxAAAAKQAAAFEAAABLAAAAQgAAAD4AAAArAAAAOgAAACoAAABSAAAAQAAAAEwAAAA/AAAAfwAAADgAAAAtAAAATwAAADsAAABNAAAAQAAAAC8AAAA+AAAAKwAAAFQAAABFAAAAUgAAAEEAAAA6AAAANQAAACwAAABWAAAATAAAAEsAAABCAAAAQwAAAFEAAABVAAAAMQAAADAAAAA9AAAAQwAAAEIAAAAyAAAAMAAAAFcAAABVAAAARgAAAEQAAAA4AAAAPAAAAC4AAABaAAAATQAAAFAAAABFAAAAMwAAAEAAAAAvAAAAWQAAAEcAAABUAAAARgAAAEMAAAA0AAAAMgAAAFMAAABXAAAASgAAAEcAAABZAAAASQAAAFsAAAAzAAAARQAAADYAAABIAAAAfwAAAEkAAAA3AAAAUAAAADwAAABYAAAASQAAAFsAAABIAAAAWAAAADYAAABHAAAANwAAAEoAAABOAAAAUwAAAFwAAAA0AAAAOQAAAEYAAABLAAAAQQAAAD0AAAA1AAAAXgAAAFYAAABRAAAATAAAAFYAAABSAAAAYAAAADoAAABBAAAAPgAAAE0AAAA/AAAARAAAADgAAABdAAAATwAAAFoAAABOAAAASgAAADsAAAA5AAAAXwAAAFwAAABPAAAATwAAAE4AAAA/AAAAOwAAAF0AAABfAAAATQAAAFAAAABEAAAASAAAADwAAABjAAAAWgAAAFgAAABRAAAAVQAAAF4AAABlAAAAPQAAAEIAAABLAAAAUgAAAGAAAABUAAAAYgAAAD4AAABMAAAAQAAAAFMAAAB/AAAASgAAAEYAAABkAAAAVwAAAFwAAABUAAAARQAAAFIAAABAAAAAYQAAAFkAAABiAAAAVQAAAFcAAABlAAAAZgAAAEIAAABDAAAAUQAAAFYAAABMAAAASwAAAEEAAABoAAAAYAAAAF4AAABXAAAAUwAAAGYAAABkAAAAQwAAAEYAAABVAAAAWAAAAEgAAABbAAAASQAAAGMAAABQAAAAaQAAAFkAAABhAAAAWwAAAGcAAABFAAAAVAAAAEcAAABaAAAATQAAAFAAAABEAAAAagAAAF0AAABjAAAAWwAAAEkAAABZAAAARwAAAGkAAABYAAAAZwAAAFwAAABTAAAATgAAAEoAAABsAAAAZAAAAF8AAABdAAAATwAAAFoAAABNAAAAbQAAAF8AAABqAAAAXgAAAFYAAABRAAAASwAAAGsAAABoAAAAZQAAAF8AAABcAAAATwAAAE4AAABtAAAAbAAAAF0AAABgAAAAaAAAAGIAAABuAAAATAAAAFYAAABSAAAAYQAAAH8AAABiAAAAVAAAAGcAAABZAAAAbwAAAGIAAABuAAAAYQAAAG8AAABSAAAAYAAAAFQAAABjAAAAUAAAAGkAAABYAAAAagAAAFoAAABxAAAAZAAAAGYAAABTAAAAVwAAAGwAAAByAAAAXAAAAGUAAABmAAAAawAAAHAAAABRAAAAVQAAAF4AAABmAAAAZQAAAFcAAABVAAAAcgAAAHAAAABkAAAAZwAAAFsAAABhAAAAWQAAAHQAAABpAAAAbwAAAGgAAABrAAAAbgAAAHMAAABWAAAAXgAAAGAAAABpAAAAWAAAAGcAAABbAAAAcQAAAGMAAAB0AAAAagAAAF0AAABjAAAAWgAAAHUAAABtAAAAcQAAAGsAAAB/AAAAZQAAAF4AAABzAAAAaAAAAHAAAABsAAAAZAAAAF8AAABcAAAAdgAAAHIAAABtAAAAbQAAAGwAAABdAAAAXwAAAHUAAAB2AAAAagAAAG4AAABiAAAAaAAAAGAAAAB3AAAAbwAAAHMAAABvAAAAYQAAAG4AAABiAAAAdAAAAGcAAAB3AAAAcAAAAGsAAABmAAAAZQAAAHgAAABzAAAAcgAAAHEAAABjAAAAdAAAAGkAAAB1AAAAagAAAHkAAAByAAAAcAAAAGQAAABmAAAAdgAAAHgAAABsAAAAcwAAAG4AAABrAAAAaAAAAHgAAAB3AAAAcAAAAHQAAABnAAAAdwAAAG8AAABxAAAAaQAAAHkAAAB1AAAAfwAAAG0AAAB2AAAAcQAAAHkAAABqAAAAdgAAAHgAAABsAAAAcgAAAHUAAAB5AAAAbQAAAHcAAABvAAAAcwAAAG4AAAB5AAAAdAAAAHgAAAB4AAAAcwAAAHIAAABwAAAAeQAAAHcAAAB2AAAAeQAAAHQAAAB4AAAAdwAAAHUAAABxAAAAdgAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAEAAAAFAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAIAAAAFAAAAAQAAAAAAAAD/////AQAAAAAAAAADAAAABAAAAAIAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAUAAAABAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAFAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAQAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAADAAAABQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAQAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAADAAAABQAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAABQAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAABQAAAAAAAAAAAAAABQAAAAUAAAAAAAAAAAAAAP////8BAAAAAAAAAAMAAAAEAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAABQAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAQAAAP//////////AQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAIAAAAAAAAAAAAAAAEAAAACAAAABgAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAoAAAACAAAAAAAAAAAAAAABAAAAAQAAAAUAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAIAAAAAAAAAAAAAAAEAAAADAAAABwAAAAYAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAJAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAgAAAAAAAAAAAAAAAQAAAAQAAAAIAAAACgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAACAAAAAAAAAAAAAAABAAAACwAAAA8AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAgAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAACAAAAAAAAAAAAAAABAAAADAAAABAAAAAMAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAEAAAAKAAAAEwAAAAgAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAgAAAAAAAAAAAAAAAQAAAA0AAAARAAAADQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABEAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAIAAAAAAAAAAAAAAAEAAAAOAAAAEgAAAA8AAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABMAAAACAAAAAAAAAAAAAAABAAAA//////////8TAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAASAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAAAAAABAAAAAAAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////////////////////////////wAAAAD/////AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA/////wAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAP////8AAAAABQAAAAAAAAAAAAAAAAAAAAAAAAD/////BQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAEAAQAAAQEAAAAAAAEAAAABAAAAAQABAAAAAAAAAAAAAAAAAAAAAHJldkRpciAhPSBJTlZBTElEX0RJR0lUAGxvY2FsaWouYwBoM1RvTG9jYWxJamsAYmFzZUNlbGwgIT0gb3JpZ2luQmFzZUNlbGwAIShvcmlnaW5PblBlbnQgJiYgaW5kZXhPblBlbnQpAHBlbnRhZ29uUm90YXRpb25zID49IDAAZGlyZWN0aW9uUm90YXRpb25zID49IDAAYmFzZUNlbGwgPT0gb3JpZ2luQmFzZUNlbGw=";var tempDoublePtr=11568;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]|0}function L(a,c){a=a|0;c=c|0;if((b[16+(a*28|0)>>2]|0)==(c|0)){c=0;return c|0}if((b[16+(a*28|0)+4>>2]|0)==(c|0)){c=1;return c|0}if((b[16+(a*28|0)+8>>2]|0)==(c|0)){c=2;return c|0}if((b[16+(a*28|0)+12>>2]|0)==(c|0)){c=3;return c|0}if((b[16+(a*28|0)+16>>2]|0)==(c|0)){c=4;return c|0}if((b[16+(a*28|0)+20>>2]|0)==(c|0)){c=5;return c|0}else return ((b[16+(a*28|0)+24>>2]|0)==(c|0)?6:7)|0;return 0}function M(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;if((c|0)<0){d=d-c|0;b[h>>2]=d;g=a+8|0;b[g>>2]=(b[g>>2]|0)-c;b[a>>2]=0;c=0}if((d|0)<0){c=c-d|0;b[a>>2]=c;g=a+8|0;f=(b[g>>2]|0)-d|0;b[g>>2]=f;b[h>>2]=0;d=0}else{f=a+8|0;g=f;f=b[f>>2]|0}if((f|0)<0){c=c-f|0;b[a>>2]=c;d=d-f|0;b[h>>2]=d;b[g>>2]=0;f=0}e=(d|0)<(c|0)?d:c;e=(f|0)<(e|0)?f:e;if((e|0)<=0)return;b[a>>2]=c-e;b[h>>2]=d-e;b[g>>2]=f-e;return}function N(a,c,d){a=a|0;c=c|0;d=d|0;b[d>>2]=(b[c>>2]|0)+(b[a>>2]|0);b[d+4>>2]=(b[c+4>>2]|0)+(b[a+4>>2]|0);b[d+8>>2]=(b[c+8>>2]|0)+(b[a+8>>2]|0);return}function O(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;i=a+8|0;e=b[i>>2]|0;f=d+(c*3|0)|0;b[a>>2]=f;d=e+(d*3|0)|0;b[h>>2]=d;c=(e*3|0)+c|0;b[i>>2]=c;e=d-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=e;b[i>>2]=c;b[a>>2]=0;d=e;e=0}else e=f;if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function P(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=(c*3|0)+f|0;f=d+(f*3|0)|0;b[a>>2]=f;b[h>>2]=e;c=(d*3|0)+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;f=0}else d=e;if((d|0)<0){f=f-d|0;b[a>>2]=f;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=f-c|0;e=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=e;b[i>>2]=0;f=g;c=0}else e=d;d=(e|0)<(f|0)?e:f;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=f-d;b[h>>2]=e-d;b[i>>2]=c-d;return}function Q(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0;if((c+-1|0)>>>0>=6)return;f=(b[10288+(c*12|0)>>2]|0)+(b[a>>2]|0)|0;b[a>>2]=f;i=a+4|0;e=(b[10288+(c*12|0)+4>>2]|0)+(b[i>>2]|0)|0;b[i>>2]=e;h=a+8|0;c=(b[10288+(c*12|0)+8>>2]|0)+(b[h>>2]|0)|0;b[h>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[i>>2]=d;b[h>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[h>>2]=c;b[i>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[i>>2]=f-d;b[h>>2]=c-d;return}function R(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;e=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;f=e+c|0;b[a>>2]=f;e=d+e|0;b[h>>2]=e;c=d+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function S(a){a=a|0;switch(a|0){case 1:{a=3;break}case 3:{a=2;break}case 2:{a=6;break}case 6:{a=4;break}case 4:{a=5;break}case 5:{a=1;break}default:{}}return a|0}function T(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=(b[a>>2]|0)-(b[c>>2]|0)|0;i=(h|0)<0;e=(b[a+4>>2]|0)-(b[c+4>>2]|0)-(i?h:0)|0;g=(e|0)<0;f=(i?0-h|0:0)+(b[a+8>>2]|0)-(b[c+8>>2]|0)+(g?0-e|0:0)|0;a=(f|0)<0;c=a?0:f;d=(g?0:e)-(a?f:0)|0;f=(i?0:h)-(g?e:0)-(a?f:0)|0;a=(d|0)<(f|0)?d:f;a=(c|0)<(a|0)?c:a;e=(a|0)>0;c=c-(e?a:0)|0;d=d-(e?a:0)|0;a=f-(e?a:0)|0;a=(a|0)>-1?a:0-a|0;d=(d|0)>-1?d:0-d|0;c=(c|0)>-1?c:0-c|0;c=(d|0)>(c|0)?d:c;return ((a|0)>(c|0)?a:c)|0}function U(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=da(a|0,b|0,52)|0;q()|0;e=e&15;if(!e){e=0;return e|0}d=1;while(1){c=da(a|0,b|0,(15-d|0)*3|0)|0;q()|0;c=c&7;if(c|0){d=5;break}if(d>>>0>>0)d=d+1|0;else{c=0;d=5;break}}if((d|0)==5)return c|0;return 0}function V(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;i=da(a|0,b|0,52)|0;q()|0;i=i&15;if(!i){h=b;i=a;p(h|0);return i|0}h=1;c=0;while(1){f=(15-h|0)*3|0;d=ea(7,0,f|0)|0;e=q()|0;g=da(a|0,b|0,f|0)|0;q()|0;f=ea(S(g&7)|0,0,f|0)|0;g=q()|0;a=f|a&~d;b=g|b&~e;a:do if(!c)if(!((f&d|0)==0&(g&e|0)==0)){d=da(a|0,b|0,52)|0;q()|0;d=d&15;if(!d)c=1;else{c=1;b:while(1){g=da(a|0,b|0,(15-c|0)*3|0)|0;q()|0;switch(g&7){case 1:break b;case 0:break;default:{c=1;break a}}if(c>>>0>>0)c=c+1|0;else{c=1;break a}}c=1;while(1){e=(15-c|0)*3|0;f=ea(7,0,e|0)|0;g=b&~(q()|0);b=da(a|0,b|0,e|0)|0;q()|0;b=ea(S(b&7)|0,0,e|0)|0;a=a&~f|b;b=g|(q()|0);if(c>>>0>>0)c=c+1|0;else{c=1;break}}}}else c=0;while(0);if(h>>>0>>0)h=h+1|0;else break}p(b|0);return a|0}function W(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;d=da(a|0,b|0,52)|0;q()|0;d=d&15;if(!d){c=b;d=a;p(c|0);return d|0}c=1;while(1){g=(15-c|0)*3|0;f=ea(7,0,g|0)|0;e=b&~(q()|0);b=da(a|0,b|0,g|0)|0;q()|0;b=ea(S(b&7)|0,0,g|0)|0;a=b|a&~f;b=q()|0|e;if(c>>>0>>0)c=c+1|0;else break}p(b|0);return a|0}function X(a){a=a|0;return (a|0)%2|0|0}function Y(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;f=d+4|0;g=da(a|0,c|0,52)|0;q()|0;g=g&15;h=da(a|0,c|0,45)|0;q()|0;e=(g|0)==0;if(!(K(h&127)|0)){if(e){h=0;return h|0}if((b[f>>2]|0)==0?(b[d+8>>2]|0)==0:0)e=(b[d+12>>2]|0)!=0&1;else e=1}else if(e){h=1;return h|0}else e=1;d=1;while(1){if(!(d&1))P(f);else O(f);h=da(a|0,c|0,(15-d|0)*3|0)|0;q()|0;Q(f,h&7);if(d>>>0>>0)d=d+1|0;else break}return e|0}function Z(c,d,e,f,g){c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,s=0,t=0,u=0,v=0,w=0;w=C;C=C+32|0;v=w+16|0;u=w;h=da(c|0,d|0,52)|0;q()|0;h=h&15;p=da(e|0,f|0,52)|0;q()|0;if((h|0)!=(p&15|0)){v=1;C=w;return v|0}l=da(c|0,d|0,45)|0;q()|0;l=l&127;m=da(e|0,f|0,45)|0;q()|0;m=m&127;p=(l|0)!=(m|0);if(p){j=L(l,m)|0;if((j|0)==7){v=2;C=w;return v|0}k=L(m,l)|0;if((k|0)==7)r(10656,10680,151,10690);else{s=j;i=k}}else{s=0;i=0}n=K(l)|0;o=K(m)|0;b[v>>2]=0;b[v+4>>2]=0;b[v+8>>2]=0;b[v+12>>2]=0;do if(!s){Y(e,f,v)|0;if((n|0)!=0&(o|0)!=0){if((m|0)!=(l|0))r(10808,10680,243,10690);i=U(c,d)|0;h=U(e,f)|0;if(!(a[10592+(i*7|0)+h>>0]|0)){i=b[10384+(i*28|0)+(h<<2)>>2]|0;if((i|0)>0){j=v+4|0;h=0;do{R(j);h=h+1|0}while((h|0)!=(i|0));t=50}else t=50}else h=5}else t=50}else{m=b[3440+(l*28|0)+(s<<2)>>2]|0;j=(m|0)>0;if(!o)if(j){l=0;k=e;j=f;do{k=W(k,j)|0;j=q()|0;i=S(i)|0;l=l+1|0}while((l|0)!=(m|0));m=i;l=k;k=j}else{m=i;l=e;k=f}else if(j){l=0;k=e;j=f;do{k=V(k,j)|0;j=q()|0;i=S(i)|0;if((i|0)==1)i=S(1)|0;l=l+1|0}while((l|0)!=(m|0));m=i;l=k;k=j}else{m=i;l=e;k=f}Y(l,k,v)|0;if(!p)r(10703,10680,181,10690);j=(n|0)!=0;i=(o|0)!=0;if(j&i)r(10730,10680,182,10690);if(!j)if(i){i=U(l,k)|0;if(a[10592+(i*7|0)+m>>0]|0){h=4;break}l=0;k=b[10384+(m*28|0)+(i<<2)>>2]|0;t=26}else i=0;else{i=U(c,d)|0;if(a[10592+(i*7|0)+s>>0]|0){h=3;break}k=b[10384+(i*28|0)+(s<<2)>>2]|0;l=k;t=26}if((t|0)==26){if((k|0)<=-1)r(10761,10680,212,10690);if((l|0)<=-1)r(10784,10680,213,10690);if((k|0)>0){j=v+4|0;i=0;do{R(j);i=i+1|0}while((i|0)!=(k|0));i=l}else i=l};b[u>>2]=0;b[u+4>>2]=0;b[u+8>>2]=0;Q(u,s);if(h|0)while(1){if(!(X(h)|0))P(u);else O(u);if((h|0)>1)h=h+-1|0;else break}if((i|0)>0){h=0;do{R(u);h=h+1|0}while((h|0)!=(i|0))}t=v+4|0;N(t,u,t);M(t);t=50}while(0);if((t|0)==50){h=v+4|0;b[g>>2]=b[h>>2];b[g+4>>2]=b[h+4>>2];b[g+8>>2]=b[h+8>>2];h=0}v=h;C=w;return v|0}function _(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;g=C;C=C+32|0;e=g+12|0;f=g;if((Z(a,b,a,b,e)|0)==0?(Z(a,b,c,d,f)|0)==0:0)a=T(e,f)|0;else a=-1;C=g;return a|0}function $(){return 10848}function aa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=C;C=C+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[2713]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=10892+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[2713]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;C=w;return v|0}l=b[2715]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=10892+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[2718]|0;c=l>>>3;d=10892+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2715]=h;b[2718]=f;v=i;C=w;return v|0}g=b[2714]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[11156+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=11156+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[2714]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[2718]|0;c=l>>>3;d=10892+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2715]=j;b[2718]=h}v=i+8|0;C=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[2714]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[11156+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[11156+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[2715]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=11156+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=10892+(c<<1<<2)|0;a=b[2713]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=11156+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;C=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[2715]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[2718]|0;if(c>>>0>15){v=a+m|0;b[2718]=v;b[2715]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[2715]=0;b[2718]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;C=w;return v|0}h=b[2716]|0;if(h>>>0>m>>>0){t=h-m|0;b[2716]=t;v=b[2719]|0;u=v+m|0;b[2719]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;C=w;return v|0}if(!(b[2831]|0)){b[2833]=4096;b[2832]=4096;b[2834]=-1;b[2835]=-1;b[2836]=0;b[2824]=0;b[2831]=n&-16^1431655768;a=4096}else a=b[2833]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;C=w;return v|0}a=b[2823]|0;if(a|0?(l=b[2821]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;C=w;return v|0}d:do if(!(b[2824]&4)){d=b[2719]|0;e:do if(d){e=11300;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=ha(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=ha(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[2832]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[2821]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[2823]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=ha(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[2833]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((ha(a|0)|0)==(-1|0)){ha(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[2824]=b[2824]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=ha(k|0)|0,p=ha(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[2821]|0)+h|0;b[2821]=c;if(c>>>0>(b[2822]|0)>>>0)b[2822]=c;j=b[2719]|0;f:do if(j){c=11300;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[2716]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[2719]=u;b[2716]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[2720]=b[2835];break}if(g>>>0<(b[2717]|0)>>>0)b[2717]=g;d=g+h|0;c=11300;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[2716]|0)+i|0;b[2716]=v;b[2719]=k;b[k+4>>2]=v|1}else{if((b[2718]|0)==(c|0)){v=(b[2715]|0)+i|0;b[2715]=v;b[2718]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[2713]=b[2713]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=11156+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[2714]=b[2714]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=10892+(c<<1<<2)|0;a=b[2713]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=11156+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[2714]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;C=w;return v|0}c=11300;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[2719]=u;b[2716]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[2720]=b[2835];d=a+4|0;b[d>>2]=27;b[c>>2]=b[2825];b[c+4>>2]=b[2826];b[c+8>>2]=b[2827];b[c+12>>2]=b[2828];b[2825]=g;b[2826]=h;b[2828]=0;b[2827]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=10892+(c<<1<<2)|0;a=b[2713]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=11156+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[2714]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[2717]|0;if((v|0)==0|g>>>0>>0)b[2717]=g;b[2825]=g;b[2826]=h;b[2828]=0;b[2722]=b[2831];b[2721]=-1;b[2726]=10892;b[2725]=10892;b[2728]=10900;b[2727]=10900;b[2730]=10908;b[2729]=10908;b[2732]=10916;b[2731]=10916;b[2734]=10924;b[2733]=10924;b[2736]=10932;b[2735]=10932;b[2738]=10940;b[2737]=10940;b[2740]=10948;b[2739]=10948;b[2742]=10956;b[2741]=10956;b[2744]=10964;b[2743]=10964;b[2746]=10972;b[2745]=10972;b[2748]=10980;b[2747]=10980;b[2750]=10988;b[2749]=10988;b[2752]=10996;b[2751]=10996;b[2754]=11004;b[2753]=11004;b[2756]=11012;b[2755]=11012;b[2758]=11020;b[2757]=11020;b[2760]=11028;b[2759]=11028;b[2762]=11036;b[2761]=11036;b[2764]=11044;b[2763]=11044;b[2766]=11052;b[2765]=11052;b[2768]=11060;b[2767]=11060;b[2770]=11068;b[2769]=11068;b[2772]=11076;b[2771]=11076;b[2774]=11084;b[2773]=11084;b[2776]=11092;b[2775]=11092;b[2778]=11100;b[2777]=11100;b[2780]=11108;b[2779]=11108;b[2782]=11116;b[2781]=11116;b[2784]=11124;b[2783]=11124;b[2786]=11132;b[2785]=11132;b[2788]=11140;b[2787]=11140;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[2719]=u;b[2716]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[2720]=b[2835]}while(0);c=b[2716]|0;if(c>>>0>m>>>0){t=c-m|0;b[2716]=t;v=b[2719]|0;u=v+m|0;b[2719]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;C=w;return v|0}}v=$()|0;b[v>>2]=12;v=0;C=w;return v|0}function ba(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[2717]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[2718]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[2715]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[2713]=b[2713]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=11156+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[2714]=b[2714]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[2719]|0)==(j|0)){j=(b[2716]|0)+c|0;b[2716]=j;b[2719]=i;b[i+4>>2]=j|1;if((i|0)!=(b[2718]|0))return;b[2718]=0;b[2715]=0;return}if((b[2718]|0)==(j|0)){j=(b[2715]|0)+c|0;b[2715]=j;b[2718]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[2713]=b[2713]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=11156+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[2714]=b[2714]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[2718]|0)){b[2715]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=10892+(a<<1<<2)|0;c=b[2713]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=11156+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[2714]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[2721]|0)+-1|0;b[2721]=j;if(j|0)return;a=11308;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[2721]=-1;return}function ca(a,c){a=a|0;c=c|0;var d=0;if(a){d=n(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=aa(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;ga(a|0,0,d|0)|0;return a|0}function da(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){p(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function ea(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){p(b<>>32-c|0);return a<=8192){u(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function ga(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function ha(a){a=a|0;var c=0,d=0,f=0;f=t()|0;d=b[e>>2]|0;c=d+a|0;if((a|0)>0&(c|0)<(d|0)|(c|0)<0){w(c|0)|0;s(12);return -1}if((c|0)>(f|0))if(!(v(c|0)|0)){s(12);return -1}b[e>>2]=c;return d|0} - -// EMSCRIPTEN_END_FUNCS -return{_bitshift64Lshr:da,_bitshift64Shl:ea,_calloc:ca,_emscripten_replace_memory:F,_free:ba,_h3Distance:_,_malloc:aa,_memcpy:fa,_memset:ga,_sbrk:ha,establishStackSpace:J,stackAlloc:G,stackRestore:I,stackSave:H}}) - - -// EMSCRIPTEN_END_ASM -(asmGlobalArg,asmLibraryArg,buffer);var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _h3Distance=Module["_h3Distance"]=asm["_h3Distance"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); - - - - return libh3 -} -)(typeof libh3 === 'object' ? libh3 : {}); -export default libh3; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_fromlonglat/h3core_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_fromlonglat/h3core_custom.js deleted file mode 100644 index 54d5c4b75..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_fromlonglat/h3core_custom.js +++ /dev/null @@ -1,1352 +0,0 @@ -/* - * Copyright 2018-2019 Uber Technologies, Inc. - * Copyright 2021 CARTO - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @module h3 - */ - -import C from './libh3_custom'; -import BINDINGS from 'h3-js/lib/bindings'; - -const H3 = {}; - -// Create the bound functions themselves -BINDINGS.forEach(function bind (def) { - // Bind only exported functions - if (C['_' + def[0]]) { - H3[def[0]] = C.cwrap(...def); - } -}); - -// Alias the hexidecimal base for legibility -const BASE_16 = 16; - -// ---------------------------------------------------------------------------- -// Byte size imports - -const SZ_INT = 4; -const SZ_PTR = 4; -const SZ_DBL = 8; -const SZ_H3INDEX = H3.sizeOfH3Index && H3.sizeOfH3Index(); -const SZ_GEOCOORD = H3.sizeOfGeoCoord && H3.sizeOfGeoCoord(); -const SZ_GEOBOUNDARY = H3.sizeOfGeoBoundary && H3.sizeOfGeoBoundary(); -const SZ_GEOPOLYGON = H3.sizeOfGeoPolygon && H3.sizeOfGeoPolygon(); -const SZ_GEOFENCE = H3.sizeOfGeofence && H3.sizeOfGeofence(); -const SZ_LINKED_GEOPOLYGON = H3.sizeOfLinkedGeoPolygon && H3.sizeOfLinkedGeoPolygon(); -const SZ_COORDIJ = H3.sizeOfCoordIJ && H3.sizeOfCoordIJ(); - -// ---------------------------------------------------------------------------- -// Custom types - -/** - * 64-bit hexidecimal string representation of an H3 index - * @static - * @typedef {string} H3Index - */ - -/** - * 64-bit hexidecimal string representation of an H3 index, - * or two 32-bit integers in little endian order in an array. - * @static - * @typedef {string | number[]} H3IndexInput - */ - -/** - * Coordinates as an `{i, j}` pair - * @static - * @typedef CoordIJ - * @type {Object} - * @property {number} i - * @property {number} j - */ - -// ---------------------------------------------------------------------------- -// Unit constants - -/** - * Length/Area units - * @static - * @typedef UNITS - * @type {Object} - * @property {string} m - * @property {string} m2 - * @property {string} km - * @property {string} km2 - * @property {string} rads - * @property {string} rads2 - */ -export const UNITS = { - m: 'm', - m2: 'm2', - km: 'km', - km2: 'km2', - rads: 'rads', - rads2: 'rads2' -}; - -// ---------------------------------------------------------------------------- -// Utilities and helpers - -/** - * Validate a resolution, throwing an error if invalid - * @private - * @param {mixed} res Value to validate - * @throws {Error} Error if invalid - */ -function validateRes (res) { - if (typeof res !== 'number' || res < 0 || res > 15 || Math.floor(res) !== res) { - throw new Error(`Invalid resolution: ${res}`); - } -} - -const INVALID_HEXIDECIMAL_CHAR = /[^0-9a-fA-F]/; - -/** - * Convert an H3 index (64-bit hexidecimal string) into a "split long" - a pair of 32-bit ints - * @private - * @param {H3IndexInput} h3Index H3 index to check - * @return {number[]} A two-element array with 32 lower bits and 32 upper bits - */ -export function h3IndexToSplitLong (h3Index) { - if ( - Array.isArray(h3Index) && - h3Index.length === 2 && - Number.isInteger(h3Index[0]) && - Number.isInteger(h3Index[1]) - ) { - return h3Index; - } - if (typeof h3Index !== 'string' || INVALID_HEXIDECIMAL_CHAR.test(h3Index)) { - return [0, 0]; - } - const upper = parseInt(h3Index.substring(0, h3Index.length - 8), BASE_16); - const lower = parseInt(h3Index.substring(h3Index.length - 8), BASE_16); - return [lower, upper]; -} - -/** - * Convert a 32-bit int to a hexdecimal string - * @private - * @param {number} num Integer to convert - * @return {H3Index} Hexidecimal string - */ -function hexFrom32Bit (num) { - if (num >= 0) { - return num.toString(BASE_16); - } - - // Handle negative numbers - num = num & 0x7fffffff; - let tempStr = zeroPad(8, num.toString(BASE_16)); - const topNum = (parseInt(tempStr[0], BASE_16) + 8).toString(BASE_16); - tempStr = topNum + tempStr.substring(1); - return tempStr; -} - -/** - * Get a H3 index from a split long (pair of 32-bit ints) - * @private - * @param {number} lower Lower 32 bits - * @param {number} upper Upper 32 bits - * @return {H3Index} H3 index - */ -export function splitLongToh3Index (lower, upper) { - return hexFrom32Bit(upper) + zeroPad(8, hexFrom32Bit(lower)); -} - -/** - * Zero-pad a string to a given length - * @private - * @param {number} fullLen Target length - * @param {string} numStr String to zero-pad - * @return {string} Zero-padded string - */ -function zeroPad (fullLen, numStr) { - const numZeroes = fullLen - numStr.length; - let outStr = ''; - for (let i = 0; i < numZeroes; i++) { - outStr += '0'; - } - outStr = outStr + numStr; - return outStr; -} - -/** - * Populate a C-appropriate Geofence struct from a polygon array - * @private - * @param {Array[]} polygonArray Polygon, as an array of coordinate pairs - * @param {number} geofence C pointer to a Geofence struct - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated Geofence struct - */ -function polygonArrayToGeofence (polygonArray, geofence, isGeoJson) { - const numVerts = polygonArray.length; - const geoCoordArray = C._calloc(numVerts, SZ_GEOCOORD); - // Support [lng, lat] pairs if GeoJSON is specified - const latIndex = isGeoJson ? 1 : 0; - const lngIndex = isGeoJson ? 0 : 1; - for (let i = 0; i < numVerts * 2; i += 2) { - C.HEAPF64.set( - [polygonArray[i / 2][latIndex], polygonArray[i / 2][lngIndex]].map(degsToRads), - geoCoordArray / SZ_DBL + i - ); - } - C.HEAPU32.set([numVerts, geoCoordArray], geofence / SZ_INT); - return geofence; -} - -/** - * Create a C-appropriate GeoPolygon struct from an array of polygons - * @private - * @param {Array[]} coordinates Array of polygons, each an array of coordinate pairs - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated GeoPolygon struct - */ -function coordinatesToGeoPolygon (coordinates, isGeoJson) { - // Any loops beyond the first loop are holes - const numHoles = coordinates.length - 1; - const geoPolygon = C._calloc(SZ_GEOPOLYGON); - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // geofence is first part of struct - polygonArrayToGeofence(coordinates[0], geoPolygon + geofenceOffset, isGeoJson); - let holes; - if (numHoles > 0) { - holes = C._calloc(numHoles, SZ_GEOFENCE); - for (let i = 0; i < numHoles; i++) { - polygonArrayToGeofence(coordinates[i + 1], holes + SZ_GEOFENCE * i, isGeoJson); - } - } - C.setValue(geoPolygon + numHolesOffset, numHoles, 'i32'); - C.setValue(geoPolygon + holesOffset, holes, 'i32'); - return geoPolygon; -} - -/** - * Free memory allocated for a GeoPolygon struct. It is an error to access the struct - * after passing it to this method. - * @private - * @return {number} geoPolygon C pointer to populated GeoPolygon struct - */ -function destroyGeoPolygon (geoPolygon) { - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // Offset of the geofence vertex array pointer within the Geofence struct - const geofenceArrayOffset = SZ_INT; - // Free the outer vertex array - C._free(C.getValue(geoPolygon + geofenceOffset + geofenceArrayOffset, 'i8*')); - // Free the vertex array for the holes, if any - const numHoles = C.getValue(geoPolygon + numHolesOffset, 'i32'); - if (numHoles > 0) { - const holes = C.getValue(geoPolygon + holesOffset, 'i32'); - for (let i = 0; i < numHoles; i++) { - C._free(C.getValue(holes + SZ_GEOFENCE * i + geofenceArrayOffset, 'i8*')); - } - C._free(holes); - } - C._free(geoPolygon); -} - -/** - * Read a long value, returning the lower and upper portions as separate 32-bit integers. - * Because the upper bits are returned via side effect, the argument to this function is - * intended to be the invocation that caused the side effect, e.g. readLong(H3.getSomeLong()) - * @private - * @param {number} invocation Invoked function returning a long value. The actual return - * value of these functions is a 32-bit integer. - * @return {number} Long value as a [lower, upper] pair - */ -function readLong (invocation) { - // Upper 32-bits of the long set via side-effect - const upper = C.getTempRet0(); - return [invocation, upper]; -} - -/** - * Read an H3 index from a C return value. As with readLong, the argument to this function - * is intended to be an invocation, e.g. readH3Index(H3.getSomeAddress()), to help ensure that - * the temp value storing the upper bits of the long is still set. - * @private - * @param {number} invocation Invoked function returning a single H3 index - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3Index (invocation) { - const [lower, upper] = readLong(invocation); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Read an H3 index from a pointer to C memory. - * @private - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes, in case we're - * reading an array - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3IndexFromPointer (cAddress, offset = 0) { - const lower = C.getValue(cAddress + SZ_INT * offset * 2, 'i32'); - const upper = C.getValue(cAddress + SZ_INT * (offset * 2 + 1), 'i32'); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Store an H3 index in C memory. Primarily used as an efficient way to - * write sets of hexagons. - * @private - * @param {H3IndexInput} h3Index H3 index to store - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes from beginning - * of the current array - */ -function storeH3Index (h3Index, cAddress, offset) { - // HEAPU32 is a typed array projection on the index space - // as unsigned 32-bit integers. This means the index needs - // to be divided by SZ_INT (4) to access correctly. Also, - // the H3 index is 64 bits, so we skip by twos as we're writing - // to 32-bit integers in the proper order. - C.HEAPU32.set(h3IndexToSplitLong(h3Index), cAddress / SZ_INT + 2 * offset); -} - -/** - * Read an array of 64-bit H3 indexes from C and convert to a JS array of - * H3 index strings - * @private - * @param {number} cAddress Pointer to C ouput array - * @param {number} maxCount Max number of hexagons in array. Hexagons with - * the value 0 will be skipped, so this isn't - * necessarily the length of the output array. - * @return {H3Index[]} Array of H3 indexes - */ -function readArrayOfHexagons (cAddress, maxCount) { - const out = []; - for (let i = 0; i < maxCount; i++) { - const h3Index = readH3IndexFromPointer(cAddress, i); - if (h3Index !== null) { - out.push(h3Index); - } - } - return out; -} - -/** - * Store an array of H3 index strings as a C array of 64-bit integers. - * @private - * @param {number} cAddress Pointer to C input array - * @param {H3IndexInput[]} hexagons H3 indexes to pass to the C lib - */ -function storeArrayOfHexagons (cAddress, hexagons) { - // Assuming the cAddress points to an already appropriately - // allocated space - const count = hexagons.length; - for (let i = 0; i < count; i++) { - storeH3Index(hexagons[i], cAddress, i); - } -} - -/** - * Populate a C-appropriate GeoCoord struct from a [lat, lng] array - * @private - * @param {number} lat Coordinate latitude - * @param {number} lng Coordinate longitude - * @return {number} C pointer to populated GeoCoord struct - */ -function storeGeoCoord (lat, lng) { - const geoCoord = C._calloc(1, SZ_GEOCOORD); - C.HEAPF64.set([lat, lng].map(degsToRads), geoCoord / SZ_DBL); - return geoCoord; -} - -function readSingleCoord (cAddress) { - return radsToDegs(C.getValue(cAddress, 'double')); -} - -/** - * Read a GeoCoord from C and return a [lat, lng] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lat, lng] pair - */ -function readGeoCoord (cAddress) { - return [readSingleCoord(cAddress), readSingleCoord(cAddress + SZ_DBL)]; -} - -/** - * Read a GeoCoord from C and return a GeoJSON-style [lng, lat] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lng, lat] pair - */ -function readGeoCoordGeoJson (cAddress) { - return [readSingleCoord(cAddress + SZ_DBL), readSingleCoord(cAddress)]; -} - -/** - * Read the GeoBoundary structure into a list of geo coordinate pairs - * @private - * @param {number} geoBoundary C pointer to GeoBoundary struct - * @param {boolean} geoJsonCoords Whether to provide GeoJSON coordinate order: [lng, lat] - * @param {boolean} closedLoop Whether to close the loop - * @return {Array[]} Array of geo coordinate pairs - */ -function readGeoBoundary (geoBoundary, geoJsonCoords, closedLoop) { - const numVerts = C.getValue(geoBoundary, 'i32'); - // Note that though numVerts is an int, the coordinate doubles have to be - // aligned to 8 bytes, hence the 8-byte offset here - const vertsPos = geoBoundary + SZ_DBL; - const out = []; - // Support [lng, lat] pairs if GeoJSON is specified - const readCoord = geoJsonCoords ? readGeoCoordGeoJson : readGeoCoord; - for (let i = 0; i < numVerts * 2; i += 2) { - out.push(readCoord(vertsPos + SZ_DBL * i)); - } - if (closedLoop) { - // Close loop if GeoJSON is specified - out.push(out[0]); - } - return out; -} - -/** - * Read the LinkedGeoPolygon structure into a nested array of MultiPolygon coordinates - * @private - * @param {number} polygon C pointer to LinkedGeoPolygon struct - * @param {boolean} formatAsGeoJson Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -function readMultiPolygon (polygon, formatAsGeoJson) { - const output = []; - const readCoord = formatAsGeoJson ? readGeoCoordGeoJson : readGeoCoord; - let loops; - let loop; - let coords; - let coord; - // Loop through the linked structure, building the output - while (polygon) { - output.push((loops = [])); - // Follow ->first pointer - loop = C.getValue(polygon, 'i8*'); - while (loop) { - loops.push((coords = [])); - // Follow ->first pointer - coord = C.getValue(loop, 'i8*'); - while (coord) { - coords.push(readCoord(coord)); - // Follow ->next pointer - coord = C.getValue(coord + SZ_DBL * 2, 'i8*'); - } - if (formatAsGeoJson) { - // Close loop if GeoJSON is requested - coords.push(coords[0]); - } - // Follow ->next pointer - loop = C.getValue(loop + SZ_PTR * 2, 'i8*'); - } - // Follow ->next pointer - polygon = C.getValue(polygon + SZ_PTR * 2, 'i8*'); - } - return output; -} - -/** - * Read a CoordIJ from C and return an {i, j} pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function readCoordIJ (cAddress) { - return { - i: C.getValue(cAddress, 'i32'), - j: C.getValue(cAddress + SZ_INT, 'i32') - }; -} - -/** - * Store an {i, j} pair to a C CoordIJ struct. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function storeCoordIJ (cAddress, {i, j}) { - C.setValue(cAddress, i, 'i32'); - C.setValue(cAddress + SZ_INT, j, 'i32'); -} - -/** - * Read an array of positive integers array from C. Negative - * values are considered invalid and ignored in output. - * @private - * @param {number} cAddress Pointer to C array - * @param {number} count Length of C array - * @return {number[]} Javascript integer array - */ -function readArrayOfPositiveIntegers (cAddress, count) { - const out = []; - for (let i = 0; i < count; i++) { - const int = C.getValue(cAddress + SZ_INT * i, 'i32'); - if (int >= 0) { - out.push(int); - } - } - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Core - -/** - * Whether a given string represents a valid H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} Whether the index is valid - */ -export function h3IsValid (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsValid(lower, upper)); -} - -/** - * Whether the given H3 index is a pentagon - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isPentagon - */ -export function h3IsPentagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsPentagon(lower, upper)); -} - -/** - * Whether the given H3 index is in a Class III resolution (rotated versus - * the icosahedron and subject to shape distortion adding extra points on - * icosahedron edges, making them not true hexagons). - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isResClassIII - */ -export function h3IsResClassIII (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsResClassIII(lower, upper)); -} - -/** - * Get the number of the base cell for a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get the base cell for - * @return {number} Index of the base cell (0-121) - */ -export function h3GetBaseCell (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return H3.h3GetBaseCell(lower, upper); -} - -/** - * Get the indices of all icosahedron faces intersected by a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get faces for - * @return {number[]} Indices (0-19) of all intersected faces - */ -export function h3GetFaces (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = H3.maxFaceCount(lower, upper); - const faces = C._malloc(SZ_INT * count); - H3.h3GetFaces(lower, upper, faces); - const out = readArrayOfPositiveIntegers(faces, count); - C._free(faces); - return out; -} - -/** - * Returns the resolution of an H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get resolution - * @return {number} The number (0-15) resolution, or -1 if invalid - */ -export function h3GetResolution (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - if (!H3.h3IsValid(lower, upper)) { - // Compatability with stated API - return -1; - } - return H3.h3GetResolution(lower, upper); -} - -/** - * Get the hexagon containing a lat,lon point - * @static - * @param {number} lat Latitude of point - * @param {number} lng Longtitude of point - * @param {number} res Resolution of hexagons to return - * @return {H3Index} H3 index - */ -export function geoToH3 (lat, lng, res) { - const latlng = C._malloc(SZ_GEOCOORD); - // Slightly more efficient way to set the memory - C.HEAPF64.set([lat, lng].map(degsToRads), latlng / SZ_DBL); - // Read value as a split long - const h3Index = readH3Index(H3.geoToH3(latlng, res)); - C._free(latlng); - return h3Index; -} - -/** - * Get the lat,lon center of a given hexagon - * @static - * @param {H3IndexInput} h3Index H3 index - * @return {number[]} Point as a [lat, lng] pair - */ -export function h3ToGeo (h3Index) { - const latlng = C._malloc(SZ_GEOCOORD); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeo(lower, upper, latlng); - const out = readGeoCoord(latlng); - C._free(latlng); - return out; -} - -/** - * Get the vertices of a given hexagon (or pentagon), as an array of [lat, lng] - * points. For pentagons and hexagons on the edge of an icosahedron face, this - * function may return up to 10 vertices. - * @static - * @param {H3Index} h3Index H3 index - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][]} Array of [lat, lng] pairs - */ -export function h3ToGeoBoundary (h3Index, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeoBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Algorithms - -/** - * Get the parent of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get parent for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of parent, or null for invalid input - */ -export function h3ToParent (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToParent(lower, upper, res)); -} - -/** - * Get the children/descendents of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get children for - * @param {number} res Resolution of hexagons to return - * @return {H3Index[]} H3 indexes of children, or empty array for invalid input - */ -export function h3ToChildren (h3Index, res) { - // Bad input in this case can potentially result in high computation volume - // using the current C algorithm. Validate and return an empty array on failure. - if (!h3IsValid(h3Index)) { - return []; - } - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxH3ToChildrenSize(lower, upper, res); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.h3ToChildren(lower, upper, res, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get the center child of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get center child for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of child, or null for invalid input - */ -export function h3ToCenterChild (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToCenterChild(lower, upper, res)); -} - -/** - * Get all hexagons in a k-ring around a given center. The order of the hexagons is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - */ -export function kRing (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.kRing(lower, upper, ringSize, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons in a k-ring around a given center, in an array of arrays - * ordered by distance from the origin. The order of the hexagons within each ring is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[][]} Array of arrays with H3 indexes for all hexagons each ring - */ -export function kRingDistances (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const kRings = C._calloc(maxCount, SZ_H3INDEX); - const distances = C._calloc(maxCount, SZ_INT); - H3.kRingDistances(lower, upper, ringSize, kRings, distances); - // Create an array of empty arrays to hold the output - const out = []; - for (let i = 0; i < ringSize + 1; i++) { - out.push([]); - } - // Read the array of hexagons, putting them into the appropriate rings - for (let i = 0; i < maxCount * 2; i += 2) { - const hexLower = C.getValue(kRings + SZ_INT * i, 'i32'); - const hexUpper = C.getValue(kRings + SZ_INT * (i + 1), 'i32'); - const index = C.getValue(distances + SZ_INT * (i / 2), 'i32'); - if (hexLower !== 0 || hexUpper !== 0) { - out[index].push(splitLongToh3Index(hexLower, hexUpper)); - } - } - C._free(kRings); - C._free(distances); - return out; -} - -/** - * Get all hexagons in a hollow hexagonal ring centered at origin with sides of a given length. - * Unlike kRing, this function will throw an error if there is a pentagon anywhere in the ring. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - * @throws {Error} If the algorithm could not calculate the ring - */ -export function hexRing (h3Index, ringSize) { - const maxCount = ringSize === 0 ? 1 : 6 * ringSize; - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - const retVal = H3.hexRing(...h3IndexToSplitLong(h3Index), ringSize, hexagons); - if (retVal !== 0) { - C._free(hexagons); - throw new Error('Failed to get hexRing (encountered a pentagon?)'); - } - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons with centers contained in a given polygon. The polygon - * is specified with GeoJson semantics as an array of loops. Each loop is - * an array of [lat, lng] pairs (or [lng, lat] if isGeoJson is specified). - * The first loop is the perimeter of the polygon, and subsequent loops are - * expected to be holes. - * @static - * @param {number[][] | number[][][]} coordinates - * Array of loops, or a single loop - * @param {number} res Resolution of hexagons to return - * @param {boolean} [isGeoJson] Whether to expect GeoJson-style [lng, lat] - * pairs instead of [lat, lng] - * @return {H3Index[]} H3 indexes for all hexagons in polygon - */ -export function polyfill (coordinates, res, isGeoJson) { - validateRes(res); - isGeoJson = Boolean(isGeoJson); - // Guard against empty input - if (coordinates.length === 0 || coordinates[0].length === 0) { - return []; - } - // Wrap to expected format if a single loop is provided - if (typeof coordinates[0][0] === 'number') { - coordinates = [coordinates]; - } - const geoPolygon = coordinatesToGeoPolygon(coordinates, isGeoJson); - const arrayLen = H3.maxPolyfillSize(geoPolygon, res); - const hexagons = C._calloc(arrayLen, SZ_H3INDEX); - H3.polyfill(geoPolygon, res, hexagons); - const out = readArrayOfHexagons(hexagons, arrayLen); - C._free(hexagons); - destroyGeoPolygon(geoPolygon); - return out; -} - -/** - * Get the outlines of a set of H3 hexagons, returned in GeoJSON MultiPolygon - * format (an array of polygons, each with an array of loops, each an array of - * coordinates). Coordinates are returned as [lat, lng] pairs unless GeoJSON - * is requested. - * - * It is the responsibility of the caller to ensure that all hexagons in the - * set have the same resolution and that the set contains no duplicates. Behavior - * is undefined if duplicates or multiple resolutions are present, and the - * algorithm may produce unexpected or invalid polygons. - * - * @static - * @param {H3IndexInput[]} h3Indexes H3 indexes to get outlines for - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: - * [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -export function h3SetToMultiPolygon (h3Indexes, formatAsGeoJson) { - // Early exit on empty input - if (!h3Indexes || !h3Indexes.length) { - return []; - } - // Set up input set - const indexCount = h3Indexes.length; - const set = C._calloc(indexCount, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Indexes); - // Allocate memory for output linked polygon - const polygon = C._calloc(SZ_LINKED_GEOPOLYGON); - // Store a reference to the first polygon - that's the one we need for - // memory deallocation - const originalPolygon = polygon; - H3.h3SetToLinkedGeo(set, indexCount, polygon); - const multiPolygon = readMultiPolygon(polygon, formatAsGeoJson); - // Clean up - H3.destroyLinkedPolygon(originalPolygon); - C._free(originalPolygon); - C._free(set); - return multiPolygon; -} - -/** - * Compact a set of hexagons of the same resolution into a set of hexagons across - * multiple levels that represents the same area. - * @static - * @param {H3IndexInput[]} h3Set H3 indexes to compact - * @return {H3Index[]} Compacted H3 indexes - * @throws {Error} If the input is invalid (e.g. duplicate hexagons) - */ -export function compact (h3Set) { - if (!h3Set || !h3Set.length) { - return []; - } - // Set up input set - const count = h3Set.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Set); - // Allocate memory for compacted hexagons, worst-case is no compaction - const compactedSet = C._calloc(count, SZ_H3INDEX); - const retVal = H3.compact(set, compactedSet, count); - if (retVal !== 0) { - C._free(set); - C._free(compactedSet); - throw new Error('Failed to compact, malformed input data (duplicate hexagons?)'); - } - const out = readArrayOfHexagons(compactedSet, count); - C._free(set); - C._free(compactedSet); - return out; -} - -/** - * Uncompact a compacted set of hexagons to hexagons of the same resolution - * @static - * @param {H3IndexInput[]} compactedSet H3 indexes to uncompact - * @param {number} res The resolution to uncompact to - * @return {H3Index[]} The uncompacted H3 indexes - * @throws {Error} If the input is invalid (e.g. invalid resolution) - */ -export function uncompact (compactedSet, res) { - validateRes(res); - if (!compactedSet || !compactedSet.length) { - return []; - } - // Set up input set - const count = compactedSet.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, compactedSet); - // Estimate how many hexagons we need (always overestimates if in error) - const maxUncompactedNum = H3.maxUncompactSize(set, count, res); - // Allocate memory for uncompacted hexagons - const uncompactedSet = C._calloc(maxUncompactedNum, SZ_H3INDEX); - const retVal = H3.uncompact(set, count, uncompactedSet, maxUncompactedNum, res); - if (retVal !== 0) { - C._free(set); - C._free(uncompactedSet); - throw new Error('Failed to uncompact (bad resolution?)'); - } - const out = readArrayOfHexagons(uncompactedSet, maxUncompactedNum); - C._free(set); - C._free(uncompactedSet); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Unidirectional edges - -/** - * Whether two H3 indexes are neighbors (share an edge) - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {boolean} Whether the hexagons share an edge - */ -export function h3IndexesAreNeighbors (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return Boolean(H3.h3IndexesAreNeighbors(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get an H3 index representing a unidirectional edge for a given origin and destination - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index} H3 index of the edge, or null if no edge is shared - */ -export function getH3UnidirectionalEdge (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return readH3Index(H3.getH3UnidirectionalEdge(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get the origin hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge origin - */ -export function getOriginH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getOriginH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Get the destination hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge destination - */ -export function getDestinationH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getDestinationH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Whether the input is a valid unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {boolean} Whether the index is valid - */ -export function h3UnidirectionalEdgeIsValid (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return Boolean(H3.h3UnidirectionalEdgeIsValid(lower, upper)); -} - -/** - * Get the [origin, destination] pair represented by a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index[]} [origin, destination] pair as H3 indexes - */ -export function getH3IndexesFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - const count = 2; - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.getH3IndexesFromUnidirectionalEdge(lower, upper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get all of the unidirectional edges with the given H3 index as the origin (i.e. an edge to - * every neighbor) - * @static - * @param {H3IndexInput} h3Index H3 index of the origin hexagon - * @return {H3Index[]} List of unidirectional edges - */ -export function getH3UnidirectionalEdgesFromHexagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = 6; - const edges = C._calloc(count, SZ_H3INDEX); - H3.getH3UnidirectionalEdgesFromHexagon(lower, upper, edges); - const out = readArrayOfHexagons(edges, count); - C._free(edges); - return out; -} - -/** - * Get the vertices of a given edge as an array of [lat, lng] points. Note that for edges that - * cross the edge of an icosahedron face, this may return 3 coordinates. - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat] - * @return {number[][]} Array of geo coordinate pairs - */ -export function getH3UnidirectionalEdgeBoundary (edgeIndex, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - H3.getH3UnidirectionalEdgeBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -/** - * Get the grid distance between two hex indexes. This function may fail - * to find the distance between two indexes if they are very far apart or - * on opposite sides of a pentagon. - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {number} Distance between hexagons, or a negative - * number if the distance could not be computed - */ -export function h3Distance (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return H3.h3Distance(oLower, oUpper, dLower, dUpper); -} - -/** - * Given two H3 indexes, return the line of indexes between them (inclusive). - * - * This function may fail to find the line between two indexes, for - * example if they are very far apart. It may also fail when finding - * distances for indexes on opposite sides of a pentagon. - * - * Notes: - * - * - The specific output of this function should not be considered stable - * across library versions. The only guarantees the library provides are - * that the line length will be `h3Distance(start, end) + 1` and that - * every index in the line will be a neighbor of the preceding index. - * - Lines are drawn in grid space, and may not correspond exactly to either - * Cartesian lines or great arcs. - * - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index[]} H3 indexes connecting origin and destination - * @throws {Error} If the line cannot be calculated - */ -export function h3Line (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - const count = H3.h3LineSize(oLower, oUpper, dLower, dUpper); - if (count < 0) { - // We can't get the specific error code here - may be any of - // the errors possible in experimentalH3ToLocalIj - throw new Error('Line cannot be calculated'); - } - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.h3Line(oLower, oUpper, dLower, dUpper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Produces IJ coordinates for an H3 index anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {H3IndexInput} destination H3 index for which to find relative coordinates - * @return {CoordIJ} Coordinates as an `{i, j}` pair - * @throws {Error} If the IJ coordinates cannot be calculated - */ -export function experimentalH3ToLocalIj (origin, destination) { - const ij = C._malloc(SZ_COORDIJ); - const retVal = H3.experimentalH3ToLocalIj( - ...h3IndexToSplitLong(origin), - ...h3IndexToSplitLong(destination), - ij - ); - const coords = readCoordIJ(ij); - C._free(ij); - // Return the pair, or throw if an error code was returned. - // Switch statement and error codes cribbed from h3-java's implementation. - switch (retVal) { - case 0: - return coords; - case 1: - throw new Error('Incompatible origin and index.'); - case 2: - default: - throw new Error( - 'Local IJ coordinates undefined for this origin and index pair. ' + - 'The index may be too far from the origin.' - ); - case 3: - case 4: - case 5: - throw new Error('Encountered possible pentagon distortion'); - } -} - -/** - * Produces an H3 index for IJ coordinates anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {CoordIJ} coords Coordinates as an `{i, j}` pair - * @return {H3Index} H3 index at the relative coordinates - * @throws {Error} If the H3 index cannot be calculated - */ -export function experimentalLocalIjToH3 (origin, coords) { - // Validate input coords - if (!coords || typeof coords.i !== 'number' || typeof coords.j !== 'number') { - throw new Error('Coordinates must be provided as an {i, j} object'); - } - // Allocate memory for the CoordIJ struct and an H3 index to hold the return value - const ij = C._malloc(SZ_COORDIJ); - const out = C._malloc(SZ_H3INDEX); - storeCoordIJ(ij, coords); - const retVal = H3.experimentalLocalIjToH3(...h3IndexToSplitLong(origin), ij, out); - const h3Index = readH3IndexFromPointer(out); - C._free(ij); - C._free(out); - if (retVal !== 0) { - throw new Error( - 'Index not defined for this origin and IJ coordinates pair. ' + - 'IJ coordinates may be too far from origin, or ' + - 'a pentagon distortion was encountered.' - ); - } - return h3Index; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Distance/area utilities - -/** - * Great circle distance between two geo points. This is not specific to H3, - * but is implemented in the library and provided here as a convenience. - * @static - * @param {number[]} latlng1 Origin coordinate as [lat, lng] - * @param {number[]} latlng2 Destination coordinate as [lat, lng] - * @param {string} unit Distance unit (either UNITS.m or UNITS.km) - * @return {number} Great circle distance - * @throws {Error} If the unit is invalid - */ -export function pointDist (latlng1, latlng2, unit) { - const coord1 = storeGeoCoord(latlng1[0], latlng1[1]); - const coord2 = storeGeoCoord(latlng2[0], latlng2[1]); - let result; - switch (unit) { - case UNITS.m: - result = H3.pointDistM(coord1, coord2); - break; - case UNITS.km: - result = H3.pointDistKm(coord1, coord2); - break; - case UNITS.rads: - result = H3.pointDistRads(coord1, coord2); - break; - default: - result = null; - } - C._free(coord1); - C._free(coord2); - if (result === null) { - throw new Error(`Unknown unit: ${unit}`); - } - return result; -} - -/** - * Exact area of a given cell - * @static - * @param {H3Index} h3Index H3 index of the hexagon to measure - * @param {string} unit Distance unit (either UNITS.m2 or UNITS.km2) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function cellArea (h3Index, unit) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - switch (unit) { - case UNITS.m2: - return H3.cellAreaM2(lower, upper); - case UNITS.km2: - return H3.cellAreaKm2(lower, upper); - case UNITS.rads2: - return H3.cellAreaRads2(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Exact length of a given unidirectional edge - * @static - * @param {H3Index} edge H3 index of the edge to measure - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function exactEdgeLength (edge, unit) { - const [lower, upper] = h3IndexToSplitLong(edge); - switch (unit) { - case UNITS.m: - return H3.exactEdgeLengthM(lower, upper); - case UNITS.km: - return H3.exactEdgeLengthKm(lower, upper); - case UNITS.rads: - return H3.exactEdgeLengthRads(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon area at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Area unit (either UNITS.m2, UNITS.km2, or UNITS.rads2) - * @return {number} Average area - * @throws {Error} If the unit is invalid - */ -export function hexArea (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m2: - return H3.hexAreaM2(res); - case UNITS.km2: - return H3.hexAreaKm2(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon edge length at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Average edge length - * @throws {Error} If the unit is invalid - */ -export function edgeLength (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m: - return H3.edgeLengthM(res); - case UNITS.km: - return H3.edgeLengthKm(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -// ---------------------------------------------------------------------------- -// Public informational utilities - -/** - * The total count of hexagons in the world at a given resolution. Note that above - * resolution 8 the exact count cannot be represented in a JavaScript 32-bit number, - * so consumers should use caution when applying further operations to the output. - * @static - * @param {number} res Hexagon resolution - * @return {number} Count - */ -export function numHexagons (res) { - validateRes(res); - // Get number as a long value - const [lower, upper] = readLong(H3.numHexagons(res)); - // If we're using <= 32 bits we can use normal JS numbers - if (!upper) { - return lower; - } - // Above 32 bit, make a JS number that's correct in order of magnitude - return upper * Math.pow(2, 32) + lower; -} - -/** - * Get all H3 indexes at resolution 0. As every index at every resolution > 0 is - * the descendant of a res 0 index, this can be used with h3ToChildren to iterate - * over H3 indexes at any resolution. - * @static - * @return {H3Index[]} All H3 indexes at res 0 - */ -export function getRes0Indexes () { - const count = H3.res0IndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getRes0Indexes(hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get the twelve pentagon indexes at a given resolution. - * @static - * @param {number} res Hexagon resolution - * @return {H3Index[]} All H3 pentagon indexes at res - */ -export function getPentagonIndexes (res) { - validateRes(res); - const count = H3.pentagonIndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getPentagonIndexes(res, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Convert degrees to radians - * @static - * @param {number} deg Value in degrees - * @return {number} Value in radians - */ -export function degsToRads (deg) { - return (deg * Math.PI) / 180; -} - -/** - * Convert radians to degrees - * @static - * @param {number} rad Value in radians - * @return {number} Value in degrees - */ -export function radsToDegs (rad) { - return (rad * 180) / Math.PI; -} \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_fromlonglat/libh3_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_fromlonglat/libh3_custom.js deleted file mode 100644 index edb1b4efc..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_fromlonglat/libh3_custom.js +++ /dev/null @@ -1,24 +0,0 @@ - -var libh3 = ( -function(libh3) { - libh3 = libh3 || {}; - -var Module=typeof libh3!=="undefined"?libh3:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=9776,DYNAMIC_BASE=5252656,DYNAMICTOP_PTR=9744;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAD//////////wEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAACAAAAAAAAAAAAAAABAAAAAgAAAAYAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAKAAAAAgAAAAAAAAAAAAAAAQAAAAEAAAAFAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAACAAAAAAAAAAAAAAABAAAAAwAAAAcAAAAGAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADgAAAAIAAAAAAAAAAAAAAAEAAAAAAAAACQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAIAAAAAAAAAAAAAAAEAAAAEAAAACAAAAAoAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAgAAAAAAAAAAAAAAAQAAAAsAAAAPAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAIAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAgAAAAAAAAAAAAAAAQAAAAwAAAAQAAAADAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAACAAAAAAAAAAAAAAABAAAACgAAABMAAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAIAAAAAAAAAAAAAAAEAAAANAAAAEQAAAA0AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAACAAAAAAAAAAAAAAABAAAADgAAABIAAAAPAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAADwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAASAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABIAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAgAAAAAAAAAAAAAAAQAAAP//////////EwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAASAAAAAAAAABgAAAAAAAAAIQAAAAAAAAAeAAAAAAAAACAAAAADAAAAMQAAAAEAAAAwAAAAAwAAADIAAAADAAAACAAAAAAAAAAFAAAABQAAAAoAAAAFAAAAFgAAAAAAAAAQAAAAAAAAABIAAAAAAAAAKQAAAAEAAAAhAAAAAAAAAB4AAAAAAAAABAAAAAAAAAAAAAAABQAAAAIAAAAFAAAADwAAAAEAAAAIAAAAAAAAAAUAAAAFAAAAHwAAAAEAAAAWAAAAAAAAABAAAAAAAAAAAgAAAAAAAAAGAAAAAAAAAA4AAAAAAAAACgAAAAAAAAALAAAAAAAAABEAAAADAAAAGAAAAAEAAAAXAAAAAwAAABkAAAADAAAAAAAAAAAAAAABAAAABQAAAAkAAAAFAAAABQAAAAAAAAACAAAAAAAAAAYAAAAAAAAAEgAAAAEAAAAKAAAAAAAAAAsAAAAAAAAABAAAAAEAAAADAAAABQAAAAcAAAAFAAAACAAAAAEAAAAAAAAAAAAAAAEAAAAFAAAAEAAAAAEAAAAFAAAAAAAAAAIAAAAAAAAABwAAAAAAAAAVAAAAAAAAACYAAAAAAAAACQAAAAAAAAATAAAAAAAAACIAAAADAAAADgAAAAEAAAAUAAAAAwAAACQAAAADAAAAAwAAAAAAAAANAAAABQAAAB0AAAAFAAAAAQAAAAAAAAAHAAAAAAAAABUAAAAAAAAABgAAAAEAAAAJAAAAAAAAABMAAAAAAAAABAAAAAIAAAAMAAAABQAAABoAAAAFAAAAAAAAAAEAAAADAAAAAAAAAA0AAAAFAAAAAgAAAAEAAAABAAAAAAAAAAcAAAAAAAAAGgAAAAAAAAAqAAAAAAAAADoAAAAAAAAAHQAAAAAAAAArAAAAAAAAAD4AAAADAAAAJgAAAAEAAAAvAAAAAwAAAEAAAAADAAAADAAAAAAAAAAcAAAABQAAACwAAAAFAAAADQAAAAAAAAAaAAAAAAAAACoAAAAAAAAAFQAAAAEAAAAdAAAAAAAAACsAAAAAAAAABAAAAAMAAAAPAAAABQAAAB8AAAAFAAAAAwAAAAEAAAAMAAAAAAAAABwAAAAFAAAABwAAAAEAAAANAAAAAAAAABoAAAAAAAAAHwAAAAAAAAApAAAAAAAAADEAAAAAAAAALAAAAAAAAAA1AAAAAAAAAD0AAAADAAAAOgAAAAEAAABBAAAAAwAAAEsAAAADAAAADwAAAAAAAAAWAAAABQAAACEAAAAFAAAAHAAAAAAAAAAfAAAAAAAAACkAAAAAAAAAKgAAAAEAAAAsAAAAAAAAADUAAAAAAAAABAAAAAQAAAAIAAAABQAAABAAAAAFAAAADAAAAAEAAAAPAAAAAAAAABYAAAAFAAAAGgAAAAEAAAAcAAAAAAAAAB8AAAAAAAAAMgAAAAAAAAAwAAAAAAAAADEAAAADAAAAIAAAAAAAAAAeAAAAAwAAACEAAAADAAAAGAAAAAMAAAASAAAAAwAAABAAAAADAAAARgAAAAAAAABDAAAAAAAAAEIAAAADAAAANAAAAAMAAAAyAAAAAAAAADAAAAAAAAAAJQAAAAMAAAAgAAAAAAAAAB4AAAADAAAAUwAAAAAAAABXAAAAAwAAAFUAAAADAAAASgAAAAMAAABGAAAAAAAAAEMAAAAAAAAAOQAAAAEAAAA0AAAAAwAAADIAAAAAAAAAGQAAAAAAAAAXAAAAAAAAABgAAAADAAAAEQAAAAAAAAALAAAAAwAAAAoAAAADAAAADgAAAAMAAAAGAAAAAwAAAAIAAAADAAAALQAAAAAAAAAnAAAAAAAAACUAAAADAAAAIwAAAAMAAAAZAAAAAAAAABcAAAAAAAAAGwAAAAMAAAARAAAAAAAAAAsAAAADAAAAPwAAAAAAAAA7AAAAAwAAADkAAAADAAAAOAAAAAMAAAAtAAAAAAAAACcAAAAAAAAALgAAAAMAAAAjAAAAAwAAABkAAAAAAAAAJAAAAAAAAAAUAAAAAAAAAA4AAAADAAAAIgAAAAAAAAATAAAAAwAAAAkAAAADAAAAJgAAAAMAAAAVAAAAAwAAAAcAAAADAAAANwAAAAAAAAAoAAAAAAAAABsAAAADAAAANgAAAAMAAAAkAAAAAAAAABQAAAAAAAAAMwAAAAMAAAAiAAAAAAAAABMAAAADAAAASAAAAAAAAAA8AAAAAwAAAC4AAAADAAAASQAAAAMAAAA3AAAAAAAAACgAAAAAAAAARwAAAAMAAAA2AAAAAwAAACQAAAAAAAAAQAAAAAAAAAAvAAAAAAAAACYAAAADAAAAPgAAAAAAAAArAAAAAwAAAB0AAAADAAAAOgAAAAMAAAAqAAAAAwAAABoAAAADAAAAVAAAAAAAAABFAAAAAAAAADMAAAADAAAAUgAAAAMAAABAAAAAAAAAAC8AAAAAAAAATAAAAAMAAAA+AAAAAAAAACsAAAADAAAAYQAAAAAAAABZAAAAAwAAAEcAAAADAAAAYgAAAAMAAABUAAAAAAAAAEUAAAAAAAAAYAAAAAMAAABSAAAAAwAAAEAAAAAAAAAASwAAAAAAAABBAAAAAAAAADoAAAADAAAAPQAAAAAAAAA1AAAAAwAAACwAAAADAAAAMQAAAAMAAAApAAAAAwAAAB8AAAADAAAAXgAAAAAAAABWAAAAAAAAAEwAAAADAAAAUQAAAAMAAABLAAAAAAAAAEEAAAAAAAAAQgAAAAMAAAA9AAAAAAAAADUAAAADAAAAawAAAAAAAABoAAAAAwAAAGAAAAADAAAAZQAAAAMAAABeAAAAAAAAAFYAAAAAAAAAVQAAAAMAAABRAAAAAwAAAEsAAAAAAAAAOQAAAAAAAAA7AAAAAAAAAD8AAAADAAAASgAAAAAAAABOAAAAAwAAAE8AAAADAAAAUwAAAAMAAABcAAAAAwAAAF8AAAADAAAAJQAAAAAAAAAnAAAAAwAAAC0AAAADAAAANAAAAAAAAAA5AAAAAAAAADsAAAAAAAAARgAAAAMAAABKAAAAAAAAAE4AAAADAAAAGAAAAAAAAAAXAAAAAwAAABkAAAADAAAAIAAAAAMAAAAlAAAAAAAAACcAAAADAAAAMgAAAAMAAAA0AAAAAAAAADkAAAAAAAAALgAAAAAAAAA8AAAAAAAAAEgAAAADAAAAOAAAAAAAAABEAAAAAwAAAFAAAAADAAAAPwAAAAMAAABNAAAAAwAAAFoAAAADAAAAGwAAAAAAAAAoAAAAAwAAADcAAAADAAAAIwAAAAAAAAAuAAAAAAAAADwAAAAAAAAALQAAAAMAAAA4AAAAAAAAAEQAAAADAAAADgAAAAAAAAAUAAAAAwAAACQAAAADAAAAEQAAAAMAAAAbAAAAAAAAACgAAAADAAAAGQAAAAMAAAAjAAAAAAAAAC4AAAAAAAAARwAAAAAAAABZAAAAAAAAAGEAAAADAAAASQAAAAAAAABbAAAAAwAAAGcAAAADAAAASAAAAAMAAABYAAAAAwAAAGkAAAADAAAAMwAAAAAAAABFAAAAAwAAAFQAAAADAAAANgAAAAAAAABHAAAAAAAAAFkAAAAAAAAANwAAAAMAAABJAAAAAAAAAFsAAAADAAAAJgAAAAAAAAAvAAAAAwAAAEAAAAADAAAAIgAAAAMAAAAzAAAAAAAAAEUAAAADAAAAJAAAAAMAAAA2AAAAAAAAAEcAAAAAAAAAYAAAAAAAAABoAAAAAAAAAGsAAAADAAAAYgAAAAAAAABuAAAAAwAAAHMAAAADAAAAYQAAAAMAAABvAAAAAwAAAHcAAAADAAAATAAAAAAAAABWAAAAAwAAAF4AAAADAAAAUgAAAAAAAABgAAAAAAAAAGgAAAAAAAAAVAAAAAMAAABiAAAAAAAAAG4AAAADAAAAOgAAAAAAAABBAAAAAwAAAEsAAAADAAAAPgAAAAMAAABMAAAAAAAAAFYAAAADAAAAQAAAAAMAAABSAAAAAAAAAGAAAAAAAAAAVQAAAAAAAABXAAAAAAAAAFMAAAADAAAAZQAAAAAAAABmAAAAAwAAAGQAAAADAAAAawAAAAMAAABwAAAAAwAAAHIAAAADAAAAQgAAAAAAAABDAAAAAwAAAEYAAAADAAAAUQAAAAAAAABVAAAAAAAAAFcAAAAAAAAAXgAAAAMAAABlAAAAAAAAAGYAAAADAAAAMQAAAAAAAAAwAAAAAwAAADIAAAADAAAAPQAAAAMAAABCAAAAAAAAAEMAAAADAAAASwAAAAMAAABRAAAAAAAAAFUAAAAAAAAAXwAAAAAAAABcAAAAAAAAAFMAAAAAAAAATwAAAAAAAABOAAAAAAAAAEoAAAADAAAAPwAAAAEAAAA7AAAAAwAAADkAAAADAAAAbQAAAAAAAABsAAAAAAAAAGQAAAAFAAAAXQAAAAEAAABfAAAAAAAAAFwAAAAAAAAATQAAAAEAAABPAAAAAAAAAE4AAAAAAAAAdQAAAAQAAAB2AAAABQAAAHIAAAAFAAAAagAAAAEAAABtAAAAAAAAAGwAAAAAAAAAWgAAAAEAAABdAAAAAQAAAF8AAAAAAAAAWgAAAAAAAABNAAAAAAAAAD8AAAAAAAAAUAAAAAAAAABEAAAAAAAAADgAAAADAAAASAAAAAEAAAA8AAAAAwAAAC4AAAADAAAAagAAAAAAAABdAAAAAAAAAE8AAAAFAAAAYwAAAAEAAABaAAAAAAAAAE0AAAAAAAAAWAAAAAEAAABQAAAAAAAAAEQAAAAAAAAAdQAAAAMAAABtAAAABQAAAF8AAAAFAAAAcQAAAAEAAABqAAAAAAAAAF0AAAAAAAAAaQAAAAEAAABjAAAAAQAAAFoAAAAAAAAAaQAAAAAAAABYAAAAAAAAAEgAAAAAAAAAZwAAAAAAAABbAAAAAAAAAEkAAAADAAAAYQAAAAEAAABZAAAAAwAAAEcAAAADAAAAcQAAAAAAAABjAAAAAAAAAFAAAAAFAAAAdAAAAAEAAABpAAAAAAAAAFgAAAAAAAAAbwAAAAEAAABnAAAAAAAAAFsAAAAAAAAAdQAAAAIAAABqAAAABQAAAFoAAAAFAAAAeQAAAAEAAABxAAAAAAAAAGMAAAAAAAAAdwAAAAEAAAB0AAAAAQAAAGkAAAAAAAAAdwAAAAAAAABvAAAAAAAAAGEAAAAAAAAAcwAAAAAAAABuAAAAAAAAAGIAAAADAAAAawAAAAEAAABoAAAAAwAAAGAAAAADAAAAeQAAAAAAAAB0AAAAAAAAAGcAAAAFAAAAeAAAAAEAAAB3AAAAAAAAAG8AAAAAAAAAcAAAAAEAAABzAAAAAAAAAG4AAAAAAAAAdQAAAAEAAABxAAAABQAAAGkAAAAFAAAAdgAAAAEAAAB5AAAAAAAAAHQAAAAAAAAAcgAAAAEAAAB4AAAAAQAAAHcAAAAAAAAAcgAAAAAAAABwAAAAAAAAAGsAAAAAAAAAZAAAAAAAAABmAAAAAAAAAGUAAAADAAAAUwAAAAEAAABXAAAAAwAAAFUAAAADAAAAdgAAAAAAAAB4AAAAAAAAAHMAAAAFAAAAbAAAAAEAAAByAAAAAAAAAHAAAAAAAAAAXAAAAAEAAABkAAAAAAAAAGYAAAAAAAAAdQAAAAAAAAB5AAAABQAAAHcAAAAFAAAAbQAAAAEAAAB2AAAAAAAAAHgAAAAAAAAAXwAAAAEAAABsAAAAAQAAAHIAAAAAAAAAfqIF9vK26T8arpqSb/nzP9eubQuJ7PQ/l2hJ06lLBEBazrTZQuDwP91PtFxuj/W/U3VFAcU04z+D1KfHsdbcvwdaw/xDeN8/pXA4uiy62T/2uOTVhBzGP6CeYoyw2fo/8cN648Vj4z9gfAOOoqEHQKLX398JWts/hTEqQNY4/r+m+WNZrT20v3CLvCtBeOe/9nrIsiaQzb/fJOU7NjXgP6b5Y1mtPbQ/PApVCetDA0D2esiyJpDNP+DjSsWtFAXA9rjk1YQcxr+RuyUcRmr3v/HDeuPFY+O/hwsLZIwFyL+i19/fCVrbv6soXmggC/Q/U3VFAcU047+IMk8bJYcFQAdaw/xDeN+/BB/9vLXqBcB+ogX28rbpvxes7RWHSv6/165tC4ns9L8HEusDRlnjv1rOtNlC4PC/UwrUS4i0/D/KYuUXsSbMPwZSCj1cEeU/eVsrtP0I5z+T46E+2GHLv5gYSmes68I/MEWEuzXm7j96luoHofi7P0i64sXmy96/qXMspjfV6z8JpDR6e8XnPxljTGVQANe/vNrPsdgS4j8J9srWyfXpPy4BB9bDEtY/Mqf9i4U33j/kp1sLUAW7v3d/IJKeV+8/MrbLh2gAxj81GDm3X9fpv+yGrhAlocM/nI0gAo854j++mfsFITfSv9fhhCs7qeu/vxmK/9OG2j8OonVjr7LnP2XnU1rEWuW/xCUDrkc4tL/zp3GIRz3rP4ePT4sWOd4/ovMFnwtNzb8NonVjr7Lnv2XnU1rEWuU/xCUDrkc4tD/yp3GIRz3rv4mPT4sWOd6/ovMFnwtNzT/Wp1sLUAW7P3d/IJKeV++/MrbLh2gAxr81GDm3X9fpP++GrhAlocO/nI0gAo854r/AmfsFITfSP9bhhCs7qes/vxmK/9OG2r8JpDR6e8XnvxdjTGVQANc/vNrPsdgS4r8K9srWyfXpvysBB9bDEta/Mqf9i4U33r/NYuUXsSbMvwZSCj1cEeW/eVsrtP0I57+Q46E+2GHLP5wYSmes68K/MEWEuzXm7r9zluoHofi7v0i64sXmy94/qXMspjfV67/KxyBX1noWQDAcFHZaNAxAk1HNexDm9j8aVQdUlgoXQM424W/aUw1A0IZnbxAl+T/RZTCggvfoPyCAM4xC4BNA2ow54DL/BkBYVg5gz4zbP8tYLi4fehJAMT4vJOwyBECQnOFEZYUYQN3iyii8JBBAqqTQMkwQ/z+saY13A4sFQBbZf/3EJuM/iG7d1yomE0DO5gi1G90HQKDNbfMlb+w/Gi2b9jZPFEBACT1eZ0MMQLUrH0wqBPc/Uz41y1yCFkAVWpwuVvQLQGDN3ewHZvY/vuZkM9RaFkAVE4cmlQYIQMB+ZrkLFe0/PUNar/NjFECaFhjnzbgXQM65ApZJsA5A0Iyqu+7d+z8voNHbYrbBP2cADE8FTxFAaI3qZbjcAUBmG7blvrfcPxzViCbOjBJA0zbkFEpYBECsZLTz+U3EP4sWywfCYxFAsLlo1zEGAkAEv0dPRZEXQKMKYmY4YQ5Aey5pXMw/+z9NYkJoYbAFQJ67U8A8vOM/2eo30Nk4E0AoTglzJ1sKQIa1t3WqM/M/x2Cb1TyOFUC094pORXAOQJ4IuyzmXfs/jTVcw8uYF0AV3b1UxVANQGDTIDnmHvk/Pqh1xgsJF0CkEzisGuQCQPIBVaBDFtE/hcMycrbSEUA=";var tempDoublePtr=9760;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]|0}function T(a){a=a|0;return b[3440+((b[a>>2]|0)*216|0)+((b[a+4>>2]|0)*72|0)+((b[a+8>>2]|0)*24|0)+(b[a+12>>2]<<3)>>2]|0}function U(a){a=a|0;return b[3440+((b[a>>2]|0)*216|0)+((b[a+4>>2]|0)*72|0)+((b[a+8>>2]|0)*24|0)+(b[a+12>>2]<<3)+4>>2]|0}function V(a,c){a=a|0;c=c|0;if((b[16+(a*28|0)+20>>2]|0)==(c|0)){c=1;return c|0}c=(b[16+(a*28|0)+24>>2]|0)==(c|0);return c|0}function W(a,c){a=a|0;c=c|0;var e=0,f=0,g=0,h=0,i=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0;n=c+8|0;b[n>>2]=0;k=+d[a>>3];i=+p(+k);l=+d[a+8>>3];j=+p(+l)/.8660254037844386;i=i+j*.5;e=~~i;a=~~j;i=i-+(e|0);j=j-+(a|0);do if(i<.5)if(i<.3333333333333333){b[c>>2]=e;if(j<(i+1.0)*.5){b[c+4>>2]=a;break}else{a=a+1|0;b[c+4>>2]=a;break}}else{o=1.0-i;a=(!(j>2]=a;if(o<=j&j>2]=e;break}else{b[c>>2]=e;break}}else{if(!(i<.6666666666666666)){e=e+1|0;b[c>>2]=e;if(j>2]=a;break}else{a=a+1|0;b[c+4>>2]=a;break}}if(j<1.0-i){b[c+4>>2]=a;if(i*2.0+-1.0>2]=e;break}}else{a=a+1|0;b[c+4>>2]=a}e=e+1|0;b[c>>2]=e}while(0);do if(k<0.0)if(!(a&1)){m=(a|0)/2|0;m=xa(e|0,((e|0)<0)<<31>>31|0,m|0,((m|0)<0)<<31>>31|0)|0;e=~~(+(e|0)-(+(m>>>0)+4294967296.0*+(z()|0))*2.0);b[c>>2]=e;break}else{m=(a+1|0)/2|0;m=xa(e|0,((e|0)<0)<<31>>31|0,m|0,((m|0)<0)<<31>>31|0)|0;e=~~(+(e|0)-((+(m>>>0)+4294967296.0*+(z()|0))*2.0+1.0));b[c>>2]=e;break}while(0);m=c+4|0;if(l<0.0){e=e-((a<<1|1|0)/2|0)|0;b[c>>2]=e;a=0-a|0;b[m>>2]=a}f=a-e|0;if((e|0)<0){g=0-e|0;b[m>>2]=f;b[n>>2]=g;b[c>>2]=0;a=f;e=0}else g=0;if((a|0)<0){e=e-a|0;b[c>>2]=e;g=g-a|0;b[n>>2]=g;b[m>>2]=0;a=0}h=e-g|0;f=a-g|0;if((g|0)<0){b[c>>2]=h;b[m>>2]=f;b[n>>2]=0;a=f;e=h;g=0}f=(a|0)<(e|0)?a:e;f=(g|0)<(f|0)?g:f;if((f|0)<=0)return;b[c>>2]=e-f;b[m>>2]=a-f;b[n>>2]=g-f;return}function X(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;if((c|0)<0){d=d-c|0;b[h>>2]=d;g=a+8|0;b[g>>2]=(b[g>>2]|0)-c;b[a>>2]=0;c=0}if((d|0)<0){c=c-d|0;b[a>>2]=c;g=a+8|0;f=(b[g>>2]|0)-d|0;b[g>>2]=f;b[h>>2]=0;d=0}else{f=a+8|0;g=f;f=b[f>>2]|0}if((f|0)<0){c=c-f|0;b[a>>2]=c;d=d-f|0;b[h>>2]=d;b[g>>2]=0;f=0}e=(d|0)<(c|0)?d:c;e=(f|0)<(e|0)?f:e;if((e|0)<=0)return;b[a>>2]=c-e;b[h>>2]=d-e;b[g>>2]=f-e;return}function Y(a,c,d){a=a|0;c=c|0;d=d|0;b[d>>2]=(b[a>>2]|0)-(b[c>>2]|0);b[d+4>>2]=(b[a+4>>2]|0)-(b[c+4>>2]|0);b[d+8>>2]=(b[a+8>>2]|0)-(b[c+8>>2]|0);return}function Z(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;h=b[a>>2]|0;i=(h|0)<0;e=(b[a+4>>2]|0)-(i?h:0)|0;g=(e|0)<0;f=(g?0-e|0:0)+((b[a+8>>2]|0)-(i?h:0))|0;d=(f|0)<0;a=d?0:f;c=(g?0:e)-(d?f:0)|0;f=(i?0:h)-(g?e:0)-(d?f:0)|0;d=(c|0)<(f|0)?c:f;d=(a|0)<(d|0)?a:d;e=(d|0)>0;a=a-(e?d:0)|0;c=c-(e?d:0)|0;a:do switch(f-(e?d:0)|0){case 0:switch(c|0){case 0:{i=(a|0)==0?0:(a|0)==1?1:7;return i|0}case 1:{i=(a|0)==0?2:(a|0)==1?3:7;return i|0}default:break a}case 1:switch(c|0){case 0:{i=(a|0)==0?4:(a|0)==1?5:7;return i|0}case 1:{if(!a)a=6;else break a;return a|0}default:break a}default:{}}while(0);i=7;return i|0}function _(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;h=a+8|0;d=b[h>>2]|0;c=(b[a>>2]|0)-d|0;i=a+4|0;d=(b[i>>2]|0)-d|0;e=ra(+((c*3|0)-d|0)/7.0)|0;b[a>>2]=e;c=ra(+((d<<1)+c|0)/7.0)|0;b[i>>2]=c;b[h>>2]=0;d=c-e|0;if((e|0)<0){g=0-e|0;b[i>>2]=d;b[h>>2]=g;b[a>>2]=0;c=d;e=0;d=g}else d=0;if((c|0)<0){e=e-c|0;b[a>>2]=e;d=d-c|0;b[h>>2]=d;b[i>>2]=0;c=0}g=e-d|0;f=c-d|0;if((d|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;c=f;f=g;d=0}else f=e;e=(c|0)<(f|0)?c:f;e=(d|0)<(e|0)?d:e;if((e|0)<=0)return;b[a>>2]=f-e;b[i>>2]=c-e;b[h>>2]=d-e;return}function $(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;h=a+8|0;d=b[h>>2]|0;c=(b[a>>2]|0)-d|0;i=a+4|0;d=(b[i>>2]|0)-d|0;e=ra(+((c<<1)+d|0)/7.0)|0;b[a>>2]=e;c=ra(+((d*3|0)-c|0)/7.0)|0;b[i>>2]=c;b[h>>2]=0;d=c-e|0;if((e|0)<0){g=0-e|0;b[i>>2]=d;b[h>>2]=g;b[a>>2]=0;c=d;e=0;d=g}else d=0;if((c|0)<0){e=e-c|0;b[a>>2]=e;d=d-c|0;b[h>>2]=d;b[i>>2]=0;c=0}g=e-d|0;f=c-d|0;if((d|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;c=f;f=g;d=0}else f=e;e=(c|0)<(f|0)?c:f;e=(d|0)<(e|0)?d:e;if((e|0)<=0)return;b[a>>2]=f-e;b[i>>2]=c-e;b[h>>2]=d-e;return}function aa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;i=a+8|0;e=b[i>>2]|0;f=d+(c*3|0)|0;b[a>>2]=f;d=e+(d*3|0)|0;b[h>>2]=d;c=(e*3|0)+c|0;b[i>>2]=c;e=d-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=e;b[i>>2]=c;b[a>>2]=0;d=e;e=0}else e=f;if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function ba(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=(c*3|0)+f|0;f=d+(f*3|0)|0;b[a>>2]=f;b[h>>2]=e;c=(d*3|0)+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;f=0}else d=e;if((d|0)<0){f=f-d|0;b[a>>2]=f;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=f-c|0;e=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=e;b[i>>2]=0;f=g;c=0}else e=d;d=(e|0)<(f|0)?e:f;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=f-d;b[h>>2]=e-d;b[i>>2]=c-d;return}function ca(a){a=a|0;switch(a|0){case 1:{a=5;break}case 5:{a=4;break}case 4:{a=6;break}case 6:{a=2;break}case 2:{a=3;break}case 3:{a=1;break}default:{}}return a|0}function da(a){a=a|0;switch(a|0){case 1:{a=3;break}case 3:{a=2;break}case 2:{a=6;break}case 6:{a=4;break}case 4:{a=5;break}case 5:{a=1;break}default:{}}return a|0}function ea(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=K;K=K+16|0;e=d;fa(a,b,c,e);W(e,c+4|0);K=d;return}function fa(a,c,e,f){a=a|0;c=c|0;e=e|0;f=f|0;var g=0.0,h=0,i=0.0,j=0.0,k=0;k=K;K=K+32|0;h=k;oa(a,h);b[e>>2]=0;g=+na(8080,h);i=+na(8104,h);if(i>2]=1;g=i}i=+na(8128,h);if(i>2]=2;g=i}i=+na(8152,h);if(i>2]=3;g=i}i=+na(8176,h);if(i>2]=4;g=i}i=+na(8200,h);if(i>2]=5;g=i}i=+na(8224,h);if(i>2]=6;g=i}i=+na(8248,h);if(i>2]=7;g=i}i=+na(8272,h);if(i>2]=8;g=i}i=+na(8296,h);if(i>2]=9;g=i}i=+na(8320,h);if(i>2]=10;g=i}i=+na(8344,h);if(i>2]=11;g=i}i=+na(8368,h);if(i>2]=12;g=i}i=+na(8392,h);if(i>2]=13;g=i}i=+na(8416,h);if(i>2]=14;g=i}i=+na(8440,h);if(i>2]=15;g=i}i=+na(8464,h);if(i>2]=16;g=i}i=+na(8488,h);if(i>2]=17;g=i}i=+na(8512,h);if(i>2]=18;g=i}i=+na(8536,h);if(i>2]=19;g=i}i=+t(+(1.0-g*.5));if(i<1.0e-16){b[f>>2]=0;b[f+4>>2]=0;b[f+8>>2]=0;b[f+12>>2]=0;K=k;return}e=b[e>>2]|0;g=+d[8560+(e*24|0)>>3];g=+ga(g-+ga(+ha(7760+(e<<4)|0,a)));if(!(ka(c)|0))j=g;else j=+ga(g+-.3334731722518321);g=+s(+i)/.381966011250105;if((c|0)>0){h=0;do{g=g*2.6457513110645907;h=h+1|0}while((h|0)!=(c|0))}i=+q(+j)*g;d[f>>3]=i;j=+r(+j)*g;d[f+8>>3]=j;K=k;return}function ga(a){a=+a;var b=0.0;b=a<0.0?a+6.283185307179586:a;return +(!(a>=6.283185307179586)?b:b+-6.283185307179586)}function ha(a,b){a=a|0;b=b|0;var c=0.0,e=0.0,f=0.0,g=0.0,h=0.0;g=+d[b>>3];e=+q(+g);f=+d[b+8>>3]-+d[a+8>>3];h=e*+r(+f);c=+d[a>>3];return +(+u(+h,+(+r(+g)*+q(+c)-+q(+f)*(e*+r(+c)))))}function ia(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;i=va(a|0,b|0,52)|0;z()|0;i=i&15;if(!i){h=b;i=a;y(h|0);return i|0}h=1;c=0;while(1){f=(15-h|0)*3|0;d=wa(7,0,f|0)|0;e=z()|0;g=va(a|0,b|0,f|0)|0;z()|0;f=wa(ca(g&7)|0,0,f|0)|0;g=z()|0;a=f|a&~d;b=g|b&~e;a:do if(!c)if(!((f&d|0)==0&(g&e|0)==0)){d=va(a|0,b|0,52)|0;z()|0;d=d&15;if(!d)c=1;else{c=1;b:while(1){g=va(a|0,b|0,(15-c|0)*3|0)|0;z()|0;switch(g&7){case 1:break b;case 0:break;default:{c=1;break a}}if(c>>>0>>0)c=c+1|0;else{c=1;break a}}c=1;while(1){g=(15-c|0)*3|0;e=va(a|0,b|0,g|0)|0;z()|0;f=wa(7,0,g|0)|0;b=b&~(z()|0);g=wa(ca(e&7)|0,0,g|0)|0;a=a&~f|g;b=b|(z()|0);if(c>>>0>>0)c=c+1|0;else{c=1;break}}}}else c=0;while(0);if(h>>>0>>0)h=h+1|0;else break}y(b|0);return a|0}function ja(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;j=K;K=K+64|0;i=j+40|0;e=j+24|0;f=j+12|0;g=j;wa(c|0,0,52)|0;d=z()|0|134225919;if(!c){if((b[a+4>>2]|0)>2){h=0;i=0;y(h|0);K=j;return i|0}if((b[a+8>>2]|0)>2){h=0;i=0;y(h|0);K=j;return i|0}if((b[a+12>>2]|0)>2){h=0;i=0;y(h|0);K=j;return i|0}wa(T(a)|0,0,45)|0;h=z()|0|d;i=-1;y(h|0);K=j;return i|0};b[i>>2]=b[a>>2];b[i+4>>2]=b[a+4>>2];b[i+8>>2]=b[a+8>>2];b[i+12>>2]=b[a+12>>2];h=i+4|0;if((c|0)>0){a=-1;while(1){b[e>>2]=b[h>>2];b[e+4>>2]=b[h+4>>2];b[e+8>>2]=b[h+8>>2];if(!(c&1)){$(h);b[f>>2]=b[h>>2];b[f+4>>2]=b[h+4>>2];b[f+8>>2]=b[h+8>>2];ba(f)}else{_(h);b[f>>2]=b[h>>2];b[f+4>>2]=b[h+4>>2];b[f+8>>2]=b[h+8>>2];aa(f)}Y(e,f,g);X(g);l=(15-c|0)*3|0;k=wa(7,0,l|0)|0;d=d&~(z()|0);l=wa(Z(g)|0,0,l|0)|0;a=l|a&~k;d=z()|0|d;if((c|0)>1)c=c+-1|0;else break}}else a=-1;a:do if(((b[h>>2]|0)<=2?(b[i+8>>2]|0)<=2:0)?(b[i+12>>2]|0)<=2:0){e=T(i)|0;c=wa(e|0,0,45)|0;c=c|a;a=z()|0|d&-1040385;g=U(i)|0;if(!(S(e)|0)){if((g|0)<=0)break;f=0;while(1){e=va(c|0,a|0,52)|0;z()|0;e=e&15;if(e){d=1;while(1){l=(15-d|0)*3|0;i=va(c|0,a|0,l|0)|0;z()|0;k=wa(7,0,l|0)|0;a=a&~(z()|0);l=wa(ca(i&7)|0,0,l|0)|0;c=c&~k|l;a=a|(z()|0);if(d>>>0>>0)d=d+1|0;else break}}f=f+1|0;if((f|0)==(g|0))break a}}f=va(c|0,a|0,52)|0;z()|0;f=f&15;b:do if(f){d=1;c:while(1){l=va(c|0,a|0,(15-d|0)*3|0)|0;z()|0;switch(l&7){case 1:break c;case 0:break;default:break b}if(d>>>0>>0)d=d+1|0;else break b}if(V(e,b[i>>2]|0)|0){d=1;while(1){i=(15-d|0)*3|0;k=wa(7,0,i|0)|0;l=a&~(z()|0);a=va(c|0,a|0,i|0)|0;z()|0;a=wa(da(a&7)|0,0,i|0)|0;c=c&~k|a;a=l|(z()|0);if(d>>>0>>0)d=d+1|0;else break}}else{d=1;while(1){l=(15-d|0)*3|0;i=va(c|0,a|0,l|0)|0;z()|0;k=wa(7,0,l|0)|0;a=a&~(z()|0);l=wa(ca(i&7)|0,0,l|0)|0;c=c&~k|l;a=a|(z()|0);if(d>>>0>>0)d=d+1|0;else break}}}while(0);if((g|0)>0){d=0;do{c=ia(c,a)|0;a=z()|0;d=d+1|0}while((d|0)!=(g|0))}}else{c=0;a=0}while(0);k=a;l=c;y(k|0);K=j;return l|0}function ka(a){a=a|0;return (a|0)%2|0|0}function la(a,c){a=a|0;c=c|0;var d=0,e=0;e=K;K=K+16|0;d=e;if((c>>>0<=15?!(0==0?(b[a+4>>2]&2146435072|0)==2146435072:0):0)?!(0==0?(b[a+8+4>>2]&2146435072|0)==2146435072:0):0){ea(a,c,d);c=ja(d,c)|0;a=z()|0}else{a=0;c=0}y(a|0);K=e;return c|0}function ma(){return 16}function na(a,b){a=a|0;b=b|0;var c=0.0,e=0.0,f=0.0;f=+d[a>>3]-+d[b>>3];e=+d[a+8>>3]-+d[b+8>>3];c=+d[a+16>>3]-+d[b+16>>3];return +(f*f+e*e+c*c)}function oa(a,b){a=a|0;b=b|0;var c=0.0,e=0.0,f=0.0;c=+d[a>>3];e=+q(+c);c=+r(+c);d[b+16>>3]=c;c=+d[a+8>>3];f=e*+q(+c);d[b>>3]=f;c=e*+r(+c);d[b+8>>3]=c;return}function pa(){return 9040}function qa(a){a=+a;return +(+Aa(+a))}function ra(a){a=+a;return ~~+qa(a)|0}function sa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=K;K=K+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[2261]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=9084+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[2261]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;K=w;return v|0}l=b[2263]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=9084+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[2266]|0;c=l>>>3;d=9084+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2263]=h;b[2266]=f;v=i;K=w;return v|0}g=b[2262]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[9348+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=9348+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[2262]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[2266]|0;c=l>>>3;d=9084+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2263]=j;b[2266]=h}v=i+8|0;K=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[2262]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[9348+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[9348+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[2263]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=9348+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=9084+(c<<1<<2)|0;a=b[2261]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=9348+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;K=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[2263]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[2266]|0;if(c>>>0>15){v=a+m|0;b[2266]=v;b[2263]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[2263]=0;b[2266]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;K=w;return v|0}h=b[2264]|0;if(h>>>0>m>>>0){t=h-m|0;b[2264]=t;v=b[2267]|0;u=v+m|0;b[2267]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;K=w;return v|0}if(!(b[2379]|0)){b[2381]=4096;b[2380]=4096;b[2382]=-1;b[2383]=-1;b[2384]=0;b[2372]=0;b[2379]=n&-16^1431655768;a=4096}else a=b[2381]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;K=w;return v|0}a=b[2371]|0;if(a|0?(l=b[2369]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;K=w;return v|0}d:do if(!(b[2372]&4)){d=b[2267]|0;e:do if(d){e=9492;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=Ba(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=Ba(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[2380]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[2369]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[2371]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=Ba(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[2381]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((Ba(a|0)|0)==(-1|0)){Ba(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[2372]=b[2372]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=Ba(k|0)|0,p=Ba(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[2369]|0)+h|0;b[2369]=c;if(c>>>0>(b[2370]|0)>>>0)b[2370]=c;j=b[2267]|0;f:do if(j){c=9492;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[2264]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[2267]=u;b[2264]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[2268]=b[2383];break}if(g>>>0<(b[2265]|0)>>>0)b[2265]=g;d=g+h|0;c=9492;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[2264]|0)+i|0;b[2264]=v;b[2267]=k;b[k+4>>2]=v|1}else{if((b[2266]|0)==(c|0)){v=(b[2263]|0)+i|0;b[2263]=v;b[2266]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[2261]=b[2261]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=9348+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[2262]=b[2262]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=9084+(c<<1<<2)|0;a=b[2261]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=9348+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[2262]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;K=w;return v|0}c=9492;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[2267]=u;b[2264]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[2268]=b[2383];d=a+4|0;b[d>>2]=27;b[c>>2]=b[2373];b[c+4>>2]=b[2374];b[c+8>>2]=b[2375];b[c+12>>2]=b[2376];b[2373]=g;b[2374]=h;b[2376]=0;b[2375]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=9084+(c<<1<<2)|0;a=b[2261]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=9348+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[2262]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[2265]|0;if((v|0)==0|g>>>0>>0)b[2265]=g;b[2373]=g;b[2374]=h;b[2376]=0;b[2270]=b[2379];b[2269]=-1;b[2274]=9084;b[2273]=9084;b[2276]=9092;b[2275]=9092;b[2278]=9100;b[2277]=9100;b[2280]=9108;b[2279]=9108;b[2282]=9116;b[2281]=9116;b[2284]=9124;b[2283]=9124;b[2286]=9132;b[2285]=9132;b[2288]=9140;b[2287]=9140;b[2290]=9148;b[2289]=9148;b[2292]=9156;b[2291]=9156;b[2294]=9164;b[2293]=9164;b[2296]=9172;b[2295]=9172;b[2298]=9180;b[2297]=9180;b[2300]=9188;b[2299]=9188;b[2302]=9196;b[2301]=9196;b[2304]=9204;b[2303]=9204;b[2306]=9212;b[2305]=9212;b[2308]=9220;b[2307]=9220;b[2310]=9228;b[2309]=9228;b[2312]=9236;b[2311]=9236;b[2314]=9244;b[2313]=9244;b[2316]=9252;b[2315]=9252;b[2318]=9260;b[2317]=9260;b[2320]=9268;b[2319]=9268;b[2322]=9276;b[2321]=9276;b[2324]=9284;b[2323]=9284;b[2326]=9292;b[2325]=9292;b[2328]=9300;b[2327]=9300;b[2330]=9308;b[2329]=9308;b[2332]=9316;b[2331]=9316;b[2334]=9324;b[2333]=9324;b[2336]=9332;b[2335]=9332;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[2267]=u;b[2264]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[2268]=b[2383]}while(0);c=b[2264]|0;if(c>>>0>m>>>0){t=c-m|0;b[2264]=t;v=b[2267]|0;u=v+m|0;b[2267]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;K=w;return v|0}}v=pa()|0;b[v>>2]=12;v=0;K=w;return v|0}function ta(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[2265]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[2266]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[2263]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[2261]=b[2261]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=9348+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[2262]=b[2262]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[2267]|0)==(j|0)){j=(b[2264]|0)+c|0;b[2264]=j;b[2267]=i;b[i+4>>2]=j|1;if((i|0)!=(b[2266]|0))return;b[2266]=0;b[2263]=0;return}if((b[2266]|0)==(j|0)){j=(b[2263]|0)+c|0;b[2263]=j;b[2266]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[2261]=b[2261]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=9348+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[2262]=b[2262]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[2266]|0)){b[2263]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=9084+(a<<1<<2)|0;c=b[2261]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=9348+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[2262]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[2269]|0)+-1|0;b[2269]=j;if(j|0)return;a=9500;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[2269]=-1;return}function ua(a,c){a=a|0;c=c|0;var d=0;if(a){d=w(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=sa(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;za(a|0,0,d|0)|0;return a|0}function va(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){y(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function wa(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){y(b<>>32-c|0);return a<>>0>a>>>0|0)>>>0;return (y(d|0),a-c>>>0|0)|0}function ya(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;if((e|0)>=8192){C(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function za(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function Aa(a){a=+a;return a>=0.0?+o(a+.5):+v(a-.5)}function Ba(a){a=a|0;var c=0,d=0,e=0;e=B()|0;d=b[f>>2]|0;c=d+a|0;if((a|0)>0&(c|0)<(d|0)|(c|0)<0){E(c|0)|0;A(12);return -1}if((c|0)>(e|0))if(!(D(c|0)|0)){A(12);return -1}b[f>>2]=c;return d|0} - -// EMSCRIPTEN_END_FUNCS -return{_bitshift64Lshr:va,_bitshift64Shl:wa,_calloc:ua,_emscripten_replace_memory:N,_free:ta,_geoToH3:la,_i64Subtract:xa,_malloc:sa,_memcpy:ya,_memset:za,_round:Aa,_sbrk:Ba,_sizeOfGeoCoord:ma,establishStackSpace:R,stackAlloc:O,stackRestore:Q,stackSave:P}}) - - -// EMSCRIPTEN_END_ASM -(asmGlobalArg,asmLibraryArg,buffer);var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _geoToH3=Module["_geoToH3"]=asm["_geoToH3"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _round=Module["_round"]=asm["_round"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _sizeOfGeoCoord=Module["_sizeOfGeoCoord"]=asm["_sizeOfGeoCoord"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); - - - - return libh3 -} -)(typeof libh3 === 'object' ? libh3 : {}); -export default libh3; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_kring/h3core_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_kring/h3core_custom.js deleted file mode 100644 index 54d5c4b75..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_kring/h3core_custom.js +++ /dev/null @@ -1,1352 +0,0 @@ -/* - * Copyright 2018-2019 Uber Technologies, Inc. - * Copyright 2021 CARTO - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @module h3 - */ - -import C from './libh3_custom'; -import BINDINGS from 'h3-js/lib/bindings'; - -const H3 = {}; - -// Create the bound functions themselves -BINDINGS.forEach(function bind (def) { - // Bind only exported functions - if (C['_' + def[0]]) { - H3[def[0]] = C.cwrap(...def); - } -}); - -// Alias the hexidecimal base for legibility -const BASE_16 = 16; - -// ---------------------------------------------------------------------------- -// Byte size imports - -const SZ_INT = 4; -const SZ_PTR = 4; -const SZ_DBL = 8; -const SZ_H3INDEX = H3.sizeOfH3Index && H3.sizeOfH3Index(); -const SZ_GEOCOORD = H3.sizeOfGeoCoord && H3.sizeOfGeoCoord(); -const SZ_GEOBOUNDARY = H3.sizeOfGeoBoundary && H3.sizeOfGeoBoundary(); -const SZ_GEOPOLYGON = H3.sizeOfGeoPolygon && H3.sizeOfGeoPolygon(); -const SZ_GEOFENCE = H3.sizeOfGeofence && H3.sizeOfGeofence(); -const SZ_LINKED_GEOPOLYGON = H3.sizeOfLinkedGeoPolygon && H3.sizeOfLinkedGeoPolygon(); -const SZ_COORDIJ = H3.sizeOfCoordIJ && H3.sizeOfCoordIJ(); - -// ---------------------------------------------------------------------------- -// Custom types - -/** - * 64-bit hexidecimal string representation of an H3 index - * @static - * @typedef {string} H3Index - */ - -/** - * 64-bit hexidecimal string representation of an H3 index, - * or two 32-bit integers in little endian order in an array. - * @static - * @typedef {string | number[]} H3IndexInput - */ - -/** - * Coordinates as an `{i, j}` pair - * @static - * @typedef CoordIJ - * @type {Object} - * @property {number} i - * @property {number} j - */ - -// ---------------------------------------------------------------------------- -// Unit constants - -/** - * Length/Area units - * @static - * @typedef UNITS - * @type {Object} - * @property {string} m - * @property {string} m2 - * @property {string} km - * @property {string} km2 - * @property {string} rads - * @property {string} rads2 - */ -export const UNITS = { - m: 'm', - m2: 'm2', - km: 'km', - km2: 'km2', - rads: 'rads', - rads2: 'rads2' -}; - -// ---------------------------------------------------------------------------- -// Utilities and helpers - -/** - * Validate a resolution, throwing an error if invalid - * @private - * @param {mixed} res Value to validate - * @throws {Error} Error if invalid - */ -function validateRes (res) { - if (typeof res !== 'number' || res < 0 || res > 15 || Math.floor(res) !== res) { - throw new Error(`Invalid resolution: ${res}`); - } -} - -const INVALID_HEXIDECIMAL_CHAR = /[^0-9a-fA-F]/; - -/** - * Convert an H3 index (64-bit hexidecimal string) into a "split long" - a pair of 32-bit ints - * @private - * @param {H3IndexInput} h3Index H3 index to check - * @return {number[]} A two-element array with 32 lower bits and 32 upper bits - */ -export function h3IndexToSplitLong (h3Index) { - if ( - Array.isArray(h3Index) && - h3Index.length === 2 && - Number.isInteger(h3Index[0]) && - Number.isInteger(h3Index[1]) - ) { - return h3Index; - } - if (typeof h3Index !== 'string' || INVALID_HEXIDECIMAL_CHAR.test(h3Index)) { - return [0, 0]; - } - const upper = parseInt(h3Index.substring(0, h3Index.length - 8), BASE_16); - const lower = parseInt(h3Index.substring(h3Index.length - 8), BASE_16); - return [lower, upper]; -} - -/** - * Convert a 32-bit int to a hexdecimal string - * @private - * @param {number} num Integer to convert - * @return {H3Index} Hexidecimal string - */ -function hexFrom32Bit (num) { - if (num >= 0) { - return num.toString(BASE_16); - } - - // Handle negative numbers - num = num & 0x7fffffff; - let tempStr = zeroPad(8, num.toString(BASE_16)); - const topNum = (parseInt(tempStr[0], BASE_16) + 8).toString(BASE_16); - tempStr = topNum + tempStr.substring(1); - return tempStr; -} - -/** - * Get a H3 index from a split long (pair of 32-bit ints) - * @private - * @param {number} lower Lower 32 bits - * @param {number} upper Upper 32 bits - * @return {H3Index} H3 index - */ -export function splitLongToh3Index (lower, upper) { - return hexFrom32Bit(upper) + zeroPad(8, hexFrom32Bit(lower)); -} - -/** - * Zero-pad a string to a given length - * @private - * @param {number} fullLen Target length - * @param {string} numStr String to zero-pad - * @return {string} Zero-padded string - */ -function zeroPad (fullLen, numStr) { - const numZeroes = fullLen - numStr.length; - let outStr = ''; - for (let i = 0; i < numZeroes; i++) { - outStr += '0'; - } - outStr = outStr + numStr; - return outStr; -} - -/** - * Populate a C-appropriate Geofence struct from a polygon array - * @private - * @param {Array[]} polygonArray Polygon, as an array of coordinate pairs - * @param {number} geofence C pointer to a Geofence struct - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated Geofence struct - */ -function polygonArrayToGeofence (polygonArray, geofence, isGeoJson) { - const numVerts = polygonArray.length; - const geoCoordArray = C._calloc(numVerts, SZ_GEOCOORD); - // Support [lng, lat] pairs if GeoJSON is specified - const latIndex = isGeoJson ? 1 : 0; - const lngIndex = isGeoJson ? 0 : 1; - for (let i = 0; i < numVerts * 2; i += 2) { - C.HEAPF64.set( - [polygonArray[i / 2][latIndex], polygonArray[i / 2][lngIndex]].map(degsToRads), - geoCoordArray / SZ_DBL + i - ); - } - C.HEAPU32.set([numVerts, geoCoordArray], geofence / SZ_INT); - return geofence; -} - -/** - * Create a C-appropriate GeoPolygon struct from an array of polygons - * @private - * @param {Array[]} coordinates Array of polygons, each an array of coordinate pairs - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated GeoPolygon struct - */ -function coordinatesToGeoPolygon (coordinates, isGeoJson) { - // Any loops beyond the first loop are holes - const numHoles = coordinates.length - 1; - const geoPolygon = C._calloc(SZ_GEOPOLYGON); - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // geofence is first part of struct - polygonArrayToGeofence(coordinates[0], geoPolygon + geofenceOffset, isGeoJson); - let holes; - if (numHoles > 0) { - holes = C._calloc(numHoles, SZ_GEOFENCE); - for (let i = 0; i < numHoles; i++) { - polygonArrayToGeofence(coordinates[i + 1], holes + SZ_GEOFENCE * i, isGeoJson); - } - } - C.setValue(geoPolygon + numHolesOffset, numHoles, 'i32'); - C.setValue(geoPolygon + holesOffset, holes, 'i32'); - return geoPolygon; -} - -/** - * Free memory allocated for a GeoPolygon struct. It is an error to access the struct - * after passing it to this method. - * @private - * @return {number} geoPolygon C pointer to populated GeoPolygon struct - */ -function destroyGeoPolygon (geoPolygon) { - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // Offset of the geofence vertex array pointer within the Geofence struct - const geofenceArrayOffset = SZ_INT; - // Free the outer vertex array - C._free(C.getValue(geoPolygon + geofenceOffset + geofenceArrayOffset, 'i8*')); - // Free the vertex array for the holes, if any - const numHoles = C.getValue(geoPolygon + numHolesOffset, 'i32'); - if (numHoles > 0) { - const holes = C.getValue(geoPolygon + holesOffset, 'i32'); - for (let i = 0; i < numHoles; i++) { - C._free(C.getValue(holes + SZ_GEOFENCE * i + geofenceArrayOffset, 'i8*')); - } - C._free(holes); - } - C._free(geoPolygon); -} - -/** - * Read a long value, returning the lower and upper portions as separate 32-bit integers. - * Because the upper bits are returned via side effect, the argument to this function is - * intended to be the invocation that caused the side effect, e.g. readLong(H3.getSomeLong()) - * @private - * @param {number} invocation Invoked function returning a long value. The actual return - * value of these functions is a 32-bit integer. - * @return {number} Long value as a [lower, upper] pair - */ -function readLong (invocation) { - // Upper 32-bits of the long set via side-effect - const upper = C.getTempRet0(); - return [invocation, upper]; -} - -/** - * Read an H3 index from a C return value. As with readLong, the argument to this function - * is intended to be an invocation, e.g. readH3Index(H3.getSomeAddress()), to help ensure that - * the temp value storing the upper bits of the long is still set. - * @private - * @param {number} invocation Invoked function returning a single H3 index - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3Index (invocation) { - const [lower, upper] = readLong(invocation); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Read an H3 index from a pointer to C memory. - * @private - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes, in case we're - * reading an array - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3IndexFromPointer (cAddress, offset = 0) { - const lower = C.getValue(cAddress + SZ_INT * offset * 2, 'i32'); - const upper = C.getValue(cAddress + SZ_INT * (offset * 2 + 1), 'i32'); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Store an H3 index in C memory. Primarily used as an efficient way to - * write sets of hexagons. - * @private - * @param {H3IndexInput} h3Index H3 index to store - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes from beginning - * of the current array - */ -function storeH3Index (h3Index, cAddress, offset) { - // HEAPU32 is a typed array projection on the index space - // as unsigned 32-bit integers. This means the index needs - // to be divided by SZ_INT (4) to access correctly. Also, - // the H3 index is 64 bits, so we skip by twos as we're writing - // to 32-bit integers in the proper order. - C.HEAPU32.set(h3IndexToSplitLong(h3Index), cAddress / SZ_INT + 2 * offset); -} - -/** - * Read an array of 64-bit H3 indexes from C and convert to a JS array of - * H3 index strings - * @private - * @param {number} cAddress Pointer to C ouput array - * @param {number} maxCount Max number of hexagons in array. Hexagons with - * the value 0 will be skipped, so this isn't - * necessarily the length of the output array. - * @return {H3Index[]} Array of H3 indexes - */ -function readArrayOfHexagons (cAddress, maxCount) { - const out = []; - for (let i = 0; i < maxCount; i++) { - const h3Index = readH3IndexFromPointer(cAddress, i); - if (h3Index !== null) { - out.push(h3Index); - } - } - return out; -} - -/** - * Store an array of H3 index strings as a C array of 64-bit integers. - * @private - * @param {number} cAddress Pointer to C input array - * @param {H3IndexInput[]} hexagons H3 indexes to pass to the C lib - */ -function storeArrayOfHexagons (cAddress, hexagons) { - // Assuming the cAddress points to an already appropriately - // allocated space - const count = hexagons.length; - for (let i = 0; i < count; i++) { - storeH3Index(hexagons[i], cAddress, i); - } -} - -/** - * Populate a C-appropriate GeoCoord struct from a [lat, lng] array - * @private - * @param {number} lat Coordinate latitude - * @param {number} lng Coordinate longitude - * @return {number} C pointer to populated GeoCoord struct - */ -function storeGeoCoord (lat, lng) { - const geoCoord = C._calloc(1, SZ_GEOCOORD); - C.HEAPF64.set([lat, lng].map(degsToRads), geoCoord / SZ_DBL); - return geoCoord; -} - -function readSingleCoord (cAddress) { - return radsToDegs(C.getValue(cAddress, 'double')); -} - -/** - * Read a GeoCoord from C and return a [lat, lng] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lat, lng] pair - */ -function readGeoCoord (cAddress) { - return [readSingleCoord(cAddress), readSingleCoord(cAddress + SZ_DBL)]; -} - -/** - * Read a GeoCoord from C and return a GeoJSON-style [lng, lat] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lng, lat] pair - */ -function readGeoCoordGeoJson (cAddress) { - return [readSingleCoord(cAddress + SZ_DBL), readSingleCoord(cAddress)]; -} - -/** - * Read the GeoBoundary structure into a list of geo coordinate pairs - * @private - * @param {number} geoBoundary C pointer to GeoBoundary struct - * @param {boolean} geoJsonCoords Whether to provide GeoJSON coordinate order: [lng, lat] - * @param {boolean} closedLoop Whether to close the loop - * @return {Array[]} Array of geo coordinate pairs - */ -function readGeoBoundary (geoBoundary, geoJsonCoords, closedLoop) { - const numVerts = C.getValue(geoBoundary, 'i32'); - // Note that though numVerts is an int, the coordinate doubles have to be - // aligned to 8 bytes, hence the 8-byte offset here - const vertsPos = geoBoundary + SZ_DBL; - const out = []; - // Support [lng, lat] pairs if GeoJSON is specified - const readCoord = geoJsonCoords ? readGeoCoordGeoJson : readGeoCoord; - for (let i = 0; i < numVerts * 2; i += 2) { - out.push(readCoord(vertsPos + SZ_DBL * i)); - } - if (closedLoop) { - // Close loop if GeoJSON is specified - out.push(out[0]); - } - return out; -} - -/** - * Read the LinkedGeoPolygon structure into a nested array of MultiPolygon coordinates - * @private - * @param {number} polygon C pointer to LinkedGeoPolygon struct - * @param {boolean} formatAsGeoJson Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -function readMultiPolygon (polygon, formatAsGeoJson) { - const output = []; - const readCoord = formatAsGeoJson ? readGeoCoordGeoJson : readGeoCoord; - let loops; - let loop; - let coords; - let coord; - // Loop through the linked structure, building the output - while (polygon) { - output.push((loops = [])); - // Follow ->first pointer - loop = C.getValue(polygon, 'i8*'); - while (loop) { - loops.push((coords = [])); - // Follow ->first pointer - coord = C.getValue(loop, 'i8*'); - while (coord) { - coords.push(readCoord(coord)); - // Follow ->next pointer - coord = C.getValue(coord + SZ_DBL * 2, 'i8*'); - } - if (formatAsGeoJson) { - // Close loop if GeoJSON is requested - coords.push(coords[0]); - } - // Follow ->next pointer - loop = C.getValue(loop + SZ_PTR * 2, 'i8*'); - } - // Follow ->next pointer - polygon = C.getValue(polygon + SZ_PTR * 2, 'i8*'); - } - return output; -} - -/** - * Read a CoordIJ from C and return an {i, j} pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function readCoordIJ (cAddress) { - return { - i: C.getValue(cAddress, 'i32'), - j: C.getValue(cAddress + SZ_INT, 'i32') - }; -} - -/** - * Store an {i, j} pair to a C CoordIJ struct. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function storeCoordIJ (cAddress, {i, j}) { - C.setValue(cAddress, i, 'i32'); - C.setValue(cAddress + SZ_INT, j, 'i32'); -} - -/** - * Read an array of positive integers array from C. Negative - * values are considered invalid and ignored in output. - * @private - * @param {number} cAddress Pointer to C array - * @param {number} count Length of C array - * @return {number[]} Javascript integer array - */ -function readArrayOfPositiveIntegers (cAddress, count) { - const out = []; - for (let i = 0; i < count; i++) { - const int = C.getValue(cAddress + SZ_INT * i, 'i32'); - if (int >= 0) { - out.push(int); - } - } - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Core - -/** - * Whether a given string represents a valid H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} Whether the index is valid - */ -export function h3IsValid (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsValid(lower, upper)); -} - -/** - * Whether the given H3 index is a pentagon - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isPentagon - */ -export function h3IsPentagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsPentagon(lower, upper)); -} - -/** - * Whether the given H3 index is in a Class III resolution (rotated versus - * the icosahedron and subject to shape distortion adding extra points on - * icosahedron edges, making them not true hexagons). - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isResClassIII - */ -export function h3IsResClassIII (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsResClassIII(lower, upper)); -} - -/** - * Get the number of the base cell for a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get the base cell for - * @return {number} Index of the base cell (0-121) - */ -export function h3GetBaseCell (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return H3.h3GetBaseCell(lower, upper); -} - -/** - * Get the indices of all icosahedron faces intersected by a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get faces for - * @return {number[]} Indices (0-19) of all intersected faces - */ -export function h3GetFaces (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = H3.maxFaceCount(lower, upper); - const faces = C._malloc(SZ_INT * count); - H3.h3GetFaces(lower, upper, faces); - const out = readArrayOfPositiveIntegers(faces, count); - C._free(faces); - return out; -} - -/** - * Returns the resolution of an H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get resolution - * @return {number} The number (0-15) resolution, or -1 if invalid - */ -export function h3GetResolution (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - if (!H3.h3IsValid(lower, upper)) { - // Compatability with stated API - return -1; - } - return H3.h3GetResolution(lower, upper); -} - -/** - * Get the hexagon containing a lat,lon point - * @static - * @param {number} lat Latitude of point - * @param {number} lng Longtitude of point - * @param {number} res Resolution of hexagons to return - * @return {H3Index} H3 index - */ -export function geoToH3 (lat, lng, res) { - const latlng = C._malloc(SZ_GEOCOORD); - // Slightly more efficient way to set the memory - C.HEAPF64.set([lat, lng].map(degsToRads), latlng / SZ_DBL); - // Read value as a split long - const h3Index = readH3Index(H3.geoToH3(latlng, res)); - C._free(latlng); - return h3Index; -} - -/** - * Get the lat,lon center of a given hexagon - * @static - * @param {H3IndexInput} h3Index H3 index - * @return {number[]} Point as a [lat, lng] pair - */ -export function h3ToGeo (h3Index) { - const latlng = C._malloc(SZ_GEOCOORD); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeo(lower, upper, latlng); - const out = readGeoCoord(latlng); - C._free(latlng); - return out; -} - -/** - * Get the vertices of a given hexagon (or pentagon), as an array of [lat, lng] - * points. For pentagons and hexagons on the edge of an icosahedron face, this - * function may return up to 10 vertices. - * @static - * @param {H3Index} h3Index H3 index - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][]} Array of [lat, lng] pairs - */ -export function h3ToGeoBoundary (h3Index, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeoBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Algorithms - -/** - * Get the parent of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get parent for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of parent, or null for invalid input - */ -export function h3ToParent (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToParent(lower, upper, res)); -} - -/** - * Get the children/descendents of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get children for - * @param {number} res Resolution of hexagons to return - * @return {H3Index[]} H3 indexes of children, or empty array for invalid input - */ -export function h3ToChildren (h3Index, res) { - // Bad input in this case can potentially result in high computation volume - // using the current C algorithm. Validate and return an empty array on failure. - if (!h3IsValid(h3Index)) { - return []; - } - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxH3ToChildrenSize(lower, upper, res); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.h3ToChildren(lower, upper, res, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get the center child of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get center child for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of child, or null for invalid input - */ -export function h3ToCenterChild (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToCenterChild(lower, upper, res)); -} - -/** - * Get all hexagons in a k-ring around a given center. The order of the hexagons is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - */ -export function kRing (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.kRing(lower, upper, ringSize, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons in a k-ring around a given center, in an array of arrays - * ordered by distance from the origin. The order of the hexagons within each ring is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[][]} Array of arrays with H3 indexes for all hexagons each ring - */ -export function kRingDistances (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const kRings = C._calloc(maxCount, SZ_H3INDEX); - const distances = C._calloc(maxCount, SZ_INT); - H3.kRingDistances(lower, upper, ringSize, kRings, distances); - // Create an array of empty arrays to hold the output - const out = []; - for (let i = 0; i < ringSize + 1; i++) { - out.push([]); - } - // Read the array of hexagons, putting them into the appropriate rings - for (let i = 0; i < maxCount * 2; i += 2) { - const hexLower = C.getValue(kRings + SZ_INT * i, 'i32'); - const hexUpper = C.getValue(kRings + SZ_INT * (i + 1), 'i32'); - const index = C.getValue(distances + SZ_INT * (i / 2), 'i32'); - if (hexLower !== 0 || hexUpper !== 0) { - out[index].push(splitLongToh3Index(hexLower, hexUpper)); - } - } - C._free(kRings); - C._free(distances); - return out; -} - -/** - * Get all hexagons in a hollow hexagonal ring centered at origin with sides of a given length. - * Unlike kRing, this function will throw an error if there is a pentagon anywhere in the ring. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - * @throws {Error} If the algorithm could not calculate the ring - */ -export function hexRing (h3Index, ringSize) { - const maxCount = ringSize === 0 ? 1 : 6 * ringSize; - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - const retVal = H3.hexRing(...h3IndexToSplitLong(h3Index), ringSize, hexagons); - if (retVal !== 0) { - C._free(hexagons); - throw new Error('Failed to get hexRing (encountered a pentagon?)'); - } - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons with centers contained in a given polygon. The polygon - * is specified with GeoJson semantics as an array of loops. Each loop is - * an array of [lat, lng] pairs (or [lng, lat] if isGeoJson is specified). - * The first loop is the perimeter of the polygon, and subsequent loops are - * expected to be holes. - * @static - * @param {number[][] | number[][][]} coordinates - * Array of loops, or a single loop - * @param {number} res Resolution of hexagons to return - * @param {boolean} [isGeoJson] Whether to expect GeoJson-style [lng, lat] - * pairs instead of [lat, lng] - * @return {H3Index[]} H3 indexes for all hexagons in polygon - */ -export function polyfill (coordinates, res, isGeoJson) { - validateRes(res); - isGeoJson = Boolean(isGeoJson); - // Guard against empty input - if (coordinates.length === 0 || coordinates[0].length === 0) { - return []; - } - // Wrap to expected format if a single loop is provided - if (typeof coordinates[0][0] === 'number') { - coordinates = [coordinates]; - } - const geoPolygon = coordinatesToGeoPolygon(coordinates, isGeoJson); - const arrayLen = H3.maxPolyfillSize(geoPolygon, res); - const hexagons = C._calloc(arrayLen, SZ_H3INDEX); - H3.polyfill(geoPolygon, res, hexagons); - const out = readArrayOfHexagons(hexagons, arrayLen); - C._free(hexagons); - destroyGeoPolygon(geoPolygon); - return out; -} - -/** - * Get the outlines of a set of H3 hexagons, returned in GeoJSON MultiPolygon - * format (an array of polygons, each with an array of loops, each an array of - * coordinates). Coordinates are returned as [lat, lng] pairs unless GeoJSON - * is requested. - * - * It is the responsibility of the caller to ensure that all hexagons in the - * set have the same resolution and that the set contains no duplicates. Behavior - * is undefined if duplicates or multiple resolutions are present, and the - * algorithm may produce unexpected or invalid polygons. - * - * @static - * @param {H3IndexInput[]} h3Indexes H3 indexes to get outlines for - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: - * [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -export function h3SetToMultiPolygon (h3Indexes, formatAsGeoJson) { - // Early exit on empty input - if (!h3Indexes || !h3Indexes.length) { - return []; - } - // Set up input set - const indexCount = h3Indexes.length; - const set = C._calloc(indexCount, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Indexes); - // Allocate memory for output linked polygon - const polygon = C._calloc(SZ_LINKED_GEOPOLYGON); - // Store a reference to the first polygon - that's the one we need for - // memory deallocation - const originalPolygon = polygon; - H3.h3SetToLinkedGeo(set, indexCount, polygon); - const multiPolygon = readMultiPolygon(polygon, formatAsGeoJson); - // Clean up - H3.destroyLinkedPolygon(originalPolygon); - C._free(originalPolygon); - C._free(set); - return multiPolygon; -} - -/** - * Compact a set of hexagons of the same resolution into a set of hexagons across - * multiple levels that represents the same area. - * @static - * @param {H3IndexInput[]} h3Set H3 indexes to compact - * @return {H3Index[]} Compacted H3 indexes - * @throws {Error} If the input is invalid (e.g. duplicate hexagons) - */ -export function compact (h3Set) { - if (!h3Set || !h3Set.length) { - return []; - } - // Set up input set - const count = h3Set.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Set); - // Allocate memory for compacted hexagons, worst-case is no compaction - const compactedSet = C._calloc(count, SZ_H3INDEX); - const retVal = H3.compact(set, compactedSet, count); - if (retVal !== 0) { - C._free(set); - C._free(compactedSet); - throw new Error('Failed to compact, malformed input data (duplicate hexagons?)'); - } - const out = readArrayOfHexagons(compactedSet, count); - C._free(set); - C._free(compactedSet); - return out; -} - -/** - * Uncompact a compacted set of hexagons to hexagons of the same resolution - * @static - * @param {H3IndexInput[]} compactedSet H3 indexes to uncompact - * @param {number} res The resolution to uncompact to - * @return {H3Index[]} The uncompacted H3 indexes - * @throws {Error} If the input is invalid (e.g. invalid resolution) - */ -export function uncompact (compactedSet, res) { - validateRes(res); - if (!compactedSet || !compactedSet.length) { - return []; - } - // Set up input set - const count = compactedSet.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, compactedSet); - // Estimate how many hexagons we need (always overestimates if in error) - const maxUncompactedNum = H3.maxUncompactSize(set, count, res); - // Allocate memory for uncompacted hexagons - const uncompactedSet = C._calloc(maxUncompactedNum, SZ_H3INDEX); - const retVal = H3.uncompact(set, count, uncompactedSet, maxUncompactedNum, res); - if (retVal !== 0) { - C._free(set); - C._free(uncompactedSet); - throw new Error('Failed to uncompact (bad resolution?)'); - } - const out = readArrayOfHexagons(uncompactedSet, maxUncompactedNum); - C._free(set); - C._free(uncompactedSet); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Unidirectional edges - -/** - * Whether two H3 indexes are neighbors (share an edge) - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {boolean} Whether the hexagons share an edge - */ -export function h3IndexesAreNeighbors (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return Boolean(H3.h3IndexesAreNeighbors(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get an H3 index representing a unidirectional edge for a given origin and destination - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index} H3 index of the edge, or null if no edge is shared - */ -export function getH3UnidirectionalEdge (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return readH3Index(H3.getH3UnidirectionalEdge(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get the origin hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge origin - */ -export function getOriginH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getOriginH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Get the destination hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge destination - */ -export function getDestinationH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getDestinationH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Whether the input is a valid unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {boolean} Whether the index is valid - */ -export function h3UnidirectionalEdgeIsValid (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return Boolean(H3.h3UnidirectionalEdgeIsValid(lower, upper)); -} - -/** - * Get the [origin, destination] pair represented by a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index[]} [origin, destination] pair as H3 indexes - */ -export function getH3IndexesFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - const count = 2; - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.getH3IndexesFromUnidirectionalEdge(lower, upper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get all of the unidirectional edges with the given H3 index as the origin (i.e. an edge to - * every neighbor) - * @static - * @param {H3IndexInput} h3Index H3 index of the origin hexagon - * @return {H3Index[]} List of unidirectional edges - */ -export function getH3UnidirectionalEdgesFromHexagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = 6; - const edges = C._calloc(count, SZ_H3INDEX); - H3.getH3UnidirectionalEdgesFromHexagon(lower, upper, edges); - const out = readArrayOfHexagons(edges, count); - C._free(edges); - return out; -} - -/** - * Get the vertices of a given edge as an array of [lat, lng] points. Note that for edges that - * cross the edge of an icosahedron face, this may return 3 coordinates. - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat] - * @return {number[][]} Array of geo coordinate pairs - */ -export function getH3UnidirectionalEdgeBoundary (edgeIndex, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - H3.getH3UnidirectionalEdgeBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -/** - * Get the grid distance between two hex indexes. This function may fail - * to find the distance between two indexes if they are very far apart or - * on opposite sides of a pentagon. - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {number} Distance between hexagons, or a negative - * number if the distance could not be computed - */ -export function h3Distance (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return H3.h3Distance(oLower, oUpper, dLower, dUpper); -} - -/** - * Given two H3 indexes, return the line of indexes between them (inclusive). - * - * This function may fail to find the line between two indexes, for - * example if they are very far apart. It may also fail when finding - * distances for indexes on opposite sides of a pentagon. - * - * Notes: - * - * - The specific output of this function should not be considered stable - * across library versions. The only guarantees the library provides are - * that the line length will be `h3Distance(start, end) + 1` and that - * every index in the line will be a neighbor of the preceding index. - * - Lines are drawn in grid space, and may not correspond exactly to either - * Cartesian lines or great arcs. - * - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index[]} H3 indexes connecting origin and destination - * @throws {Error} If the line cannot be calculated - */ -export function h3Line (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - const count = H3.h3LineSize(oLower, oUpper, dLower, dUpper); - if (count < 0) { - // We can't get the specific error code here - may be any of - // the errors possible in experimentalH3ToLocalIj - throw new Error('Line cannot be calculated'); - } - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.h3Line(oLower, oUpper, dLower, dUpper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Produces IJ coordinates for an H3 index anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {H3IndexInput} destination H3 index for which to find relative coordinates - * @return {CoordIJ} Coordinates as an `{i, j}` pair - * @throws {Error} If the IJ coordinates cannot be calculated - */ -export function experimentalH3ToLocalIj (origin, destination) { - const ij = C._malloc(SZ_COORDIJ); - const retVal = H3.experimentalH3ToLocalIj( - ...h3IndexToSplitLong(origin), - ...h3IndexToSplitLong(destination), - ij - ); - const coords = readCoordIJ(ij); - C._free(ij); - // Return the pair, or throw if an error code was returned. - // Switch statement and error codes cribbed from h3-java's implementation. - switch (retVal) { - case 0: - return coords; - case 1: - throw new Error('Incompatible origin and index.'); - case 2: - default: - throw new Error( - 'Local IJ coordinates undefined for this origin and index pair. ' + - 'The index may be too far from the origin.' - ); - case 3: - case 4: - case 5: - throw new Error('Encountered possible pentagon distortion'); - } -} - -/** - * Produces an H3 index for IJ coordinates anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {CoordIJ} coords Coordinates as an `{i, j}` pair - * @return {H3Index} H3 index at the relative coordinates - * @throws {Error} If the H3 index cannot be calculated - */ -export function experimentalLocalIjToH3 (origin, coords) { - // Validate input coords - if (!coords || typeof coords.i !== 'number' || typeof coords.j !== 'number') { - throw new Error('Coordinates must be provided as an {i, j} object'); - } - // Allocate memory for the CoordIJ struct and an H3 index to hold the return value - const ij = C._malloc(SZ_COORDIJ); - const out = C._malloc(SZ_H3INDEX); - storeCoordIJ(ij, coords); - const retVal = H3.experimentalLocalIjToH3(...h3IndexToSplitLong(origin), ij, out); - const h3Index = readH3IndexFromPointer(out); - C._free(ij); - C._free(out); - if (retVal !== 0) { - throw new Error( - 'Index not defined for this origin and IJ coordinates pair. ' + - 'IJ coordinates may be too far from origin, or ' + - 'a pentagon distortion was encountered.' - ); - } - return h3Index; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Distance/area utilities - -/** - * Great circle distance between two geo points. This is not specific to H3, - * but is implemented in the library and provided here as a convenience. - * @static - * @param {number[]} latlng1 Origin coordinate as [lat, lng] - * @param {number[]} latlng2 Destination coordinate as [lat, lng] - * @param {string} unit Distance unit (either UNITS.m or UNITS.km) - * @return {number} Great circle distance - * @throws {Error} If the unit is invalid - */ -export function pointDist (latlng1, latlng2, unit) { - const coord1 = storeGeoCoord(latlng1[0], latlng1[1]); - const coord2 = storeGeoCoord(latlng2[0], latlng2[1]); - let result; - switch (unit) { - case UNITS.m: - result = H3.pointDistM(coord1, coord2); - break; - case UNITS.km: - result = H3.pointDistKm(coord1, coord2); - break; - case UNITS.rads: - result = H3.pointDistRads(coord1, coord2); - break; - default: - result = null; - } - C._free(coord1); - C._free(coord2); - if (result === null) { - throw new Error(`Unknown unit: ${unit}`); - } - return result; -} - -/** - * Exact area of a given cell - * @static - * @param {H3Index} h3Index H3 index of the hexagon to measure - * @param {string} unit Distance unit (either UNITS.m2 or UNITS.km2) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function cellArea (h3Index, unit) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - switch (unit) { - case UNITS.m2: - return H3.cellAreaM2(lower, upper); - case UNITS.km2: - return H3.cellAreaKm2(lower, upper); - case UNITS.rads2: - return H3.cellAreaRads2(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Exact length of a given unidirectional edge - * @static - * @param {H3Index} edge H3 index of the edge to measure - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function exactEdgeLength (edge, unit) { - const [lower, upper] = h3IndexToSplitLong(edge); - switch (unit) { - case UNITS.m: - return H3.exactEdgeLengthM(lower, upper); - case UNITS.km: - return H3.exactEdgeLengthKm(lower, upper); - case UNITS.rads: - return H3.exactEdgeLengthRads(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon area at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Area unit (either UNITS.m2, UNITS.km2, or UNITS.rads2) - * @return {number} Average area - * @throws {Error} If the unit is invalid - */ -export function hexArea (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m2: - return H3.hexAreaM2(res); - case UNITS.km2: - return H3.hexAreaKm2(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon edge length at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Average edge length - * @throws {Error} If the unit is invalid - */ -export function edgeLength (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m: - return H3.edgeLengthM(res); - case UNITS.km: - return H3.edgeLengthKm(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -// ---------------------------------------------------------------------------- -// Public informational utilities - -/** - * The total count of hexagons in the world at a given resolution. Note that above - * resolution 8 the exact count cannot be represented in a JavaScript 32-bit number, - * so consumers should use caution when applying further operations to the output. - * @static - * @param {number} res Hexagon resolution - * @return {number} Count - */ -export function numHexagons (res) { - validateRes(res); - // Get number as a long value - const [lower, upper] = readLong(H3.numHexagons(res)); - // If we're using <= 32 bits we can use normal JS numbers - if (!upper) { - return lower; - } - // Above 32 bit, make a JS number that's correct in order of magnitude - return upper * Math.pow(2, 32) + lower; -} - -/** - * Get all H3 indexes at resolution 0. As every index at every resolution > 0 is - * the descendant of a res 0 index, this can be used with h3ToChildren to iterate - * over H3 indexes at any resolution. - * @static - * @return {H3Index[]} All H3 indexes at res 0 - */ -export function getRes0Indexes () { - const count = H3.res0IndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getRes0Indexes(hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get the twelve pentagon indexes at a given resolution. - * @static - * @param {number} res Hexagon resolution - * @return {H3Index[]} All H3 pentagon indexes at res - */ -export function getPentagonIndexes (res) { - validateRes(res); - const count = H3.pentagonIndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getPentagonIndexes(res, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Convert degrees to radians - * @static - * @param {number} deg Value in degrees - * @return {number} Value in radians - */ -export function degsToRads (deg) { - return (deg * Math.PI) / 180; -} - -/** - * Convert radians to degrees - * @static - * @param {number} rad Value in radians - * @return {number} Value in degrees - */ -export function radsToDegs (rad) { - return (rad * 180) / Math.PI; -} \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_kring/libh3_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_kring/libh3_custom.js deleted file mode 100644 index d331a7f77..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_kring/libh3_custom.js +++ /dev/null @@ -1,24 +0,0 @@ - -var libh3 = ( -function(libh3) { - libh3 = libh3 || {}; - -var Module=typeof libh3!=="undefined"?libh3:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=11888,DYNAMIC_BASE=5254768,DYNAMICTOP_PTR=11856;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAACAAAAAwAAAAEAAAAFAAAABAAAAAYAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAABAAAABAAAAAMAAAAGAAAABQAAAAIAAAAAAAAAAgAAAAMAAAABAAAABAAAAAYAAAAAAAAABQAAAAMAAAAGAAAABAAAAAUAAAAAAAAAAQAAAAIAAAAEAAAABQAAAAYAAAAAAAAAAgAAAAMAAAABAAAABQAAAAIAAAAAAAAAAQAAAAMAAAAGAAAABAAAAAYAAAAAAAAABQAAAAIAAAABAAAABAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAgAAAAMAAAAAAAAAAAAAAAIAAAAAAAAAAQAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABgAAAAAAAAAFAAAAAAAAAAAAAAAEAAAABQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAABgAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAAAAAACAAAAAwAAAAQAAAAFAAAABgAAAAAAAAABAAAAAwAAAAQAAAAFAAAABgAAAAAAAAABAAAAAgAAAAQAAAAFAAAABgAAAAAAAAABAAAAAgAAAAMAAAAFAAAABgAAAAAAAAABAAAAAgAAAAMAAAAEAAAABgAAAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAgAAAAAAAAAAAAAABgAAAAAAAAADAAAAAgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAUAAAAEAAAAAAAAAAEAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAEAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAUAAAACAAAABAAAAAMAAAAIAAAA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AAAAAAAAAAAAAAAABQAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAUAAAABAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAFAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAQAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAADAAAABQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAQAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAADAAAABQAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAABQAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAABQAAAAAAAAAAAAAABQAAAAUAAAAAAAAAAAAAAP////8BAAAAAAAAAAMAAAAEAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAABQAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAQAAAP//////////AQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAIAAAAAAAAAAAAAAAEAAAACAAAABgAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAoAAAACAAAAAAAAAAAAAAABAAAAAQAAAAUAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAIAAAAAAAAAAAAAAAEAAAADAAAABwAAAAYAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAJAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAgAAAAAAAAAAAAAAAQAAAAQAAAAIAAAACgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAACAAAAAAAAAAAAAAABAAAACwAAAA8AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAgAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAACAAAAAAAAAAAAAAABAAAADAAAABAAAAAMAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAEAAAAKAAAAEwAAAAgAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAgAAAAAAAAAAAAAAAQAAAA0AAAARAAAADQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABEAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAIAAAAAAAAAAAAAAAEAAAAOAAAAEgAAAA8AAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABMAAAACAAAAAAAAAAAAAAABAAAA//////////8TAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAASAAAAAQ==";var tempDoublePtr=11872;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]=a;b[g+4>>2]=c;g=(f|0)!=0;if(g)b[f>>2]=0;if(U(a,c)|0){n=1;B=o;return n|0}b[n>>2]=0;a:do if((d|0)>=1)if(g){k=0;l=1;m=1;h=0;g=a;while(1){if(!(h|k)){g=N(g,c,4,n)|0;c=q()|0;if((g|0)==0&(c|0)==0){g=2;break a}if(U(g,c)|0){g=1;break a}}g=N(g,c,b[16+(k<<2)>>2]|0,n)|0;c=q()|0;if((g|0)==0&(c|0)==0){g=2;break a}a=e+(m<<3)|0;b[a>>2]=g;b[a+4>>2]=c;b[f+(m<<2)>>2]=l;h=h+1|0;a=(h|0)==(l|0);i=k+1|0;j=(i|0)==6;if(U(g,c)|0){g=1;break a}l=l+(j&a&1)|0;if((l|0)>(d|0)){g=0;break}else{k=a?(j?0:i):k;m=m+1|0;h=a?0:h}}}else{k=0;l=1;m=1;h=0;g=a;while(1){if(!(h|k)){g=N(g,c,4,n)|0;c=q()|0;if((g|0)==0&(c|0)==0){g=2;break a}if(U(g,c)|0){g=1;break a}}g=N(g,c,b[16+(k<<2)>>2]|0,n)|0;c=q()|0;if((g|0)==0&(c|0)==0){g=2;break a}a=e+(m<<3)|0;b[a>>2]=g;b[a+4>>2]=c;h=h+1|0;a=(h|0)==(l|0);i=k+1|0;j=(i|0)==6;if(U(g,c)|0){g=1;break a}l=l+(j&a&1)|0;if((l|0)>(d|0)){g=0;break}else{k=a?(j?0:i):k;m=m+1|0;h=a?0:h}}}else g=0;while(0);n=g;B=o;return n|0}function M(a,c,d,e,f,g,h){a=a|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0;m=B;B=B+16|0;l=m;if((a|0)==0&(c|0)==0){B=m;return}i=ha(a|0,c|0,g|0,((g|0)<0)<<31>>31|0)|0;q()|0;j=e+(i<<3)|0;n=j;o=b[n>>2]|0;n=b[n+4>>2]|0;k=(o|0)==(a|0)&(n|0)==(c|0);if(!((o|0)==0&(n|0)==0|k))do{i=(i+1|0)%(g|0)|0;j=e+(i<<3)|0;o=j;n=b[o>>2]|0;o=b[o+4>>2]|0;k=(n|0)==(a|0)&(o|0)==(c|0)}while(!((n|0)==0&(o|0)==0|k));i=f+(i<<2)|0;if(k?(b[i>>2]|0)<=(h|0):0){B=m;return}o=j;b[o>>2]=a;b[o+4>>2]=c;b[i>>2]=h;if((h|0)>=(d|0)){B=m;return}o=h+1|0;b[l>>2]=0;n=N(a,c,2,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,3,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,1,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,5,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,4,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,6,l)|0;M(n,q()|0,d,e,f,g,o);B=m;return}function N(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;if((b[e>>2]|0)>0){f=0;do{d=R(d)|0;f=f+1|0}while((f|0)<(b[e>>2]|0))}i=ia(a|0,c|0,45)|0;q()|0;j=i&127;g=V(a,c)|0;f=ia(a|0,c|0,52)|0;q()|0;f=f&15;a:do if(!f)h=6;else while(1){m=(15-f|0)*3|0;n=ia(a|0,c|0,m|0)|0;q()|0;n=n&7;o=(Z(f)|0)==0;f=f+-1|0;l=ja(7,0,m|0)|0;c=c&~(q()|0);m=ja(b[(o?464:48)+(n*28|0)+(d<<2)>>2]|0,0,m|0)|0;k=q()|0;d=b[(o?672:256)+(n*28|0)+(d<<2)>>2]|0;a=m|a&~l;c=k|c;if(!d){d=0;break a}if(!f){h=6;break}}while(0);if((h|0)==6){o=b[880+(j*28|0)+(d<<2)>>2]|0;n=ja(o|0,0,45)|0;a=n|a;c=q()|0|c&-1040385;d=b[4304+(j*28|0)+(d<<2)>>2]|0;if((o&127|0)==127){o=ja(b[880+(j*28|0)+20>>2]|0,0,45)|0;c=q()|0|c&-1040385;d=b[4304+(j*28|0)+20>>2]|0;a=X(o|a,c)|0;c=q()|0;b[e>>2]=(b[e>>2]|0)+1}}h=ia(a|0,c|0,45)|0;q()|0;h=h&127;b:do if(!(O(h)|0)){if((d|0)>0){f=0;do{a=X(a,c)|0;c=q()|0;f=f+1|0}while((f|0)!=(d|0))}}else{c:do if((V(a,c)|0)==1){if((j|0)!=(h|0))if(Q(h,b[7728+(j*28|0)>>2]|0)|0){a=Y(a,c)|0;g=1;c=q()|0;break}else{a=X(a,c)|0;g=1;c=q()|0;break}switch(g|0){case 5:{a=Y(a,c)|0;c=q()|0;b[e>>2]=(b[e>>2]|0)+5;g=0;break c}case 3:{a=X(a,c)|0;c=q()|0;b[e>>2]=(b[e>>2]|0)+1;g=0;break c}default:{n=0;o=0;p(n|0);return o|0}}}else g=0;while(0);if((d|0)>0){f=0;do{a=W(a,c)|0;c=q()|0;f=f+1|0}while((f|0)!=(d|0))}if((j|0)!=(h|0)){if(!(P(h)|0)){if((g|0)!=0|(V(a,c)|0)!=5)break;b[e>>2]=(b[e>>2]|0)+1;break}switch(i&127){case 8:case 118:break b;default:{}}if((V(a,c)|0)!=3)b[e>>2]=(b[e>>2]|0)+1}}while(0);b[e>>2]=((b[e>>2]|0)+d|0)%6|0;n=c;o=a;p(n|0);return o|0}function O(a){a=a|0;return b[7728+(a*28|0)+16>>2]|0}function P(a){a=a|0;return (a|0)==4|(a|0)==117|0}function Q(a,c){a=a|0;c=c|0;if((b[7728+(a*28|0)+20>>2]|0)==(c|0)){c=1;return c|0}c=(b[7728+(a*28|0)+24>>2]|0)==(c|0);return c|0}function R(a){a=a|0;switch(a|0){case 1:{a=5;break}case 5:{a=4;break}case 4:{a=6;break}case 6:{a=2;break}case 2:{a=3;break}case 3:{a=1;break}default:{}}return a|0}function S(a){a=a|0;switch(a|0){case 1:{a=3;break}case 3:{a=2;break}case 2:{a=6;break}case 6:{a=4;break}case 4:{a=5;break}case 5:{a=1;break}default:{}}return a|0}function T(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0;if(!(0==0&(b&-16777216|0)==134217728)){b=0;return b|0}g=ia(a|0,b|0,45)|0;q()|0;g=g&127;if(g>>>0>121){b=0;return b|0}c=ia(a|0,b|0,52)|0;q()|0;c=c&15;do if(c|0){e=1;d=0;while(1){f=ia(a|0,b|0,(15-e|0)*3|0)|0;q()|0;f=f&7;if((f|0)!=0&(d^1))if((f|0)==1&(O(g)|0)!=0){h=0;d=13;break}else d=1;if((f|0)==7){h=0;d=13;break}if(e>>>0>>0)e=e+1|0;else{d=9;break}}if((d|0)==9){if((c|0)==15)h=1;else break;return h|0}else if((d|0)==13)return h|0}while(0);while(1){h=ia(a|0,b|0,(14-c|0)*3|0)|0;q()|0;if(!((h&7|0)==7&0==0)){h=0;d=13;break}if(c>>>0<14)c=c+1|0;else{h=1;d=13;break}}if((d|0)==13)return h|0;return 0}function U(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=ia(a|0,b|0,45)|0;q()|0;if(!(O(e&127)|0)){e=0;return e|0}e=ia(a|0,b|0,52)|0;q()|0;e=e&15;a:do if(!e)c=0;else{d=1;while(1){c=ia(a|0,b|0,(15-d|0)*3|0)|0;q()|0;c=c&7;if(c|0)break a;if(d>>>0>>0)d=d+1|0;else{c=0;break}}}while(0);e=(c|0)==0&1;return e|0}function V(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=ia(a|0,b|0,52)|0;q()|0;e=e&15;if(!e){e=0;return e|0}d=1;while(1){c=ia(a|0,b|0,(15-d|0)*3|0)|0;q()|0;c=c&7;if(c|0){d=5;break}if(d>>>0>>0)d=d+1|0;else{c=0;d=5;break}}if((d|0)==5)return c|0;return 0}function W(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;i=ia(a|0,b|0,52)|0;q()|0;i=i&15;if(!i){h=b;i=a;p(h|0);return i|0}h=1;c=0;while(1){f=(15-h|0)*3|0;d=ja(7,0,f|0)|0;e=q()|0;g=ia(a|0,b|0,f|0)|0;q()|0;f=ja(R(g&7)|0,0,f|0)|0;g=q()|0;a=f|a&~d;b=g|b&~e;a:do if(!c)if(!((f&d|0)==0&(g&e|0)==0)){d=ia(a|0,b|0,52)|0;q()|0;d=d&15;if(!d)c=1;else{c=1;b:while(1){g=ia(a|0,b|0,(15-c|0)*3|0)|0;q()|0;switch(g&7){case 1:break b;case 0:break;default:{c=1;break a}}if(c>>>0>>0)c=c+1|0;else{c=1;break a}}c=1;while(1){g=(15-c|0)*3|0;e=ia(a|0,b|0,g|0)|0;q()|0;f=ja(7,0,g|0)|0;b=b&~(q()|0);g=ja(R(e&7)|0,0,g|0)|0;a=a&~f|g;b=b|(q()|0);if(c>>>0>>0)c=c+1|0;else{c=1;break}}}}else c=0;while(0);if(h>>>0>>0)h=h+1|0;else break}p(b|0);return a|0}function X(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;d=ia(a|0,b|0,52)|0;q()|0;d=d&15;if(!d){c=b;d=a;p(c|0);return d|0}c=1;while(1){f=(15-c|0)*3|0;g=ia(a|0,b|0,f|0)|0;q()|0;e=ja(7,0,f|0)|0;b=b&~(q()|0);f=ja(R(g&7)|0,0,f|0)|0;a=f|a&~e;b=q()|0|b;if(c>>>0>>0)c=c+1|0;else break}p(b|0);return a|0}function Y(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;d=ia(a|0,b|0,52)|0;q()|0;d=d&15;if(!d){c=b;d=a;p(c|0);return d|0}c=1;while(1){g=(15-c|0)*3|0;f=ja(7,0,g|0)|0;e=b&~(q()|0);b=ia(a|0,b|0,g|0)|0;q()|0;b=ja(S(b&7)|0,0,g|0)|0;a=b|a&~f;b=q()|0|e;if(c>>>0>>0)c=c+1|0;else break}p(b|0);return a|0}function Z(a){a=a|0;return (a|0)%2|0|0}function _(){return 8}function $(){return 11152}function aa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=B;B=B+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[2789]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=11196+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[2789]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;B=w;return v|0}l=b[2791]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=11196+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[2794]|0;c=l>>>3;d=11196+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2791]=h;b[2794]=f;v=i;B=w;return v|0}g=b[2790]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[11460+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=11460+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[2790]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[2794]|0;c=l>>>3;d=11196+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2791]=j;b[2794]=h}v=i+8|0;B=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[2790]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[11460+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[11460+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[2791]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=11460+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=11196+(c<<1<<2)|0;a=b[2789]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=11460+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;B=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[2791]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[2794]|0;if(c>>>0>15){v=a+m|0;b[2794]=v;b[2791]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[2791]=0;b[2794]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;B=w;return v|0}h=b[2792]|0;if(h>>>0>m>>>0){t=h-m|0;b[2792]=t;v=b[2795]|0;u=v+m|0;b[2795]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;B=w;return v|0}if(!(b[2907]|0)){b[2909]=4096;b[2908]=4096;b[2910]=-1;b[2911]=-1;b[2912]=0;b[2900]=0;b[2907]=n&-16^1431655768;a=4096}else a=b[2909]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;B=w;return v|0}a=b[2899]|0;if(a|0?(l=b[2897]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;B=w;return v|0}d:do if(!(b[2900]&4)){d=b[2795]|0;e:do if(d){e=11604;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=ma(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=ma(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[2908]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[2897]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[2899]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=ma(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[2909]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((ma(a|0)|0)==(-1|0)){ma(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[2900]=b[2900]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=ma(k|0)|0,p=ma(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[2897]|0)+h|0;b[2897]=c;if(c>>>0>(b[2898]|0)>>>0)b[2898]=c;j=b[2795]|0;f:do if(j){c=11604;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[2792]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[2795]=u;b[2792]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[2796]=b[2911];break}if(g>>>0<(b[2793]|0)>>>0)b[2793]=g;d=g+h|0;c=11604;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[2792]|0)+i|0;b[2792]=v;b[2795]=k;b[k+4>>2]=v|1}else{if((b[2794]|0)==(c|0)){v=(b[2791]|0)+i|0;b[2791]=v;b[2794]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[2789]=b[2789]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=11460+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[2790]=b[2790]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=11196+(c<<1<<2)|0;a=b[2789]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=11460+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[2790]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;B=w;return v|0}c=11604;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[2795]=u;b[2792]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[2796]=b[2911];d=a+4|0;b[d>>2]=27;b[c>>2]=b[2901];b[c+4>>2]=b[2902];b[c+8>>2]=b[2903];b[c+12>>2]=b[2904];b[2901]=g;b[2902]=h;b[2904]=0;b[2903]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=11196+(c<<1<<2)|0;a=b[2789]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=11460+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[2790]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[2793]|0;if((v|0)==0|g>>>0>>0)b[2793]=g;b[2901]=g;b[2902]=h;b[2904]=0;b[2798]=b[2907];b[2797]=-1;b[2802]=11196;b[2801]=11196;b[2804]=11204;b[2803]=11204;b[2806]=11212;b[2805]=11212;b[2808]=11220;b[2807]=11220;b[2810]=11228;b[2809]=11228;b[2812]=11236;b[2811]=11236;b[2814]=11244;b[2813]=11244;b[2816]=11252;b[2815]=11252;b[2818]=11260;b[2817]=11260;b[2820]=11268;b[2819]=11268;b[2822]=11276;b[2821]=11276;b[2824]=11284;b[2823]=11284;b[2826]=11292;b[2825]=11292;b[2828]=11300;b[2827]=11300;b[2830]=11308;b[2829]=11308;b[2832]=11316;b[2831]=11316;b[2834]=11324;b[2833]=11324;b[2836]=11332;b[2835]=11332;b[2838]=11340;b[2837]=11340;b[2840]=11348;b[2839]=11348;b[2842]=11356;b[2841]=11356;b[2844]=11364;b[2843]=11364;b[2846]=11372;b[2845]=11372;b[2848]=11380;b[2847]=11380;b[2850]=11388;b[2849]=11388;b[2852]=11396;b[2851]=11396;b[2854]=11404;b[2853]=11404;b[2856]=11412;b[2855]=11412;b[2858]=11420;b[2857]=11420;b[2860]=11428;b[2859]=11428;b[2862]=11436;b[2861]=11436;b[2864]=11444;b[2863]=11444;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[2795]=u;b[2792]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[2796]=b[2911]}while(0);c=b[2792]|0;if(c>>>0>m>>>0){t=c-m|0;b[2792]=t;v=b[2795]|0;u=v+m|0;b[2795]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;B=w;return v|0}}v=$()|0;b[v>>2]=12;v=0;B=w;return v|0}function ba(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[2793]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[2794]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[2791]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[2789]=b[2789]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=11460+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[2790]=b[2790]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[2795]|0)==(j|0)){j=(b[2792]|0)+c|0;b[2792]=j;b[2795]=i;b[i+4>>2]=j|1;if((i|0)!=(b[2794]|0))return;b[2794]=0;b[2791]=0;return}if((b[2794]|0)==(j|0)){j=(b[2791]|0)+c|0;b[2791]=j;b[2794]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[2789]=b[2789]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=11460+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[2790]=b[2790]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[2794]|0)){b[2791]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=11196+(a<<1<<2)|0;c=b[2789]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=11460+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[2790]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[2797]|0)+-1|0;b[2797]=j;if(j|0)return;a=11612;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[2797]=-1;return}function ca(a,c){a=a|0;c=c|0;var d=0;if(a){d=m(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=aa(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;la(a|0,0,d|0)|0;return a|0}function da(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;c=a+c>>>0;return (p(b+d+(c>>>0>>0|0)>>>0|0),c|0)|0}function ea(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;d=b-d-(c>>>0>a>>>0|0)>>>0;return (p(d|0),a-c>>>0|0)|0}function fa(a){a=a|0;return (a?31-(n(a^a-1)|0)|0:32)|0}function ga(a,c,d,e,f){a=a|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,o=0,r=0,s=0;l=a;j=c;k=j;h=d;o=e;i=o;if(!k){g=(f|0)!=0;if(!i){if(g){b[f>>2]=(l>>>0)%(h>>>0);b[f+4>>2]=0}o=0;f=(l>>>0)/(h>>>0)>>>0;return (p(o|0),f)|0}else{if(!g){o=0;f=0;return (p(o|0),f)|0}b[f>>2]=a|0;b[f+4>>2]=c&0;o=0;f=0;return (p(o|0),f)|0}}g=(i|0)==0;do if(h){if(!g){g=(n(i|0)|0)-(n(k|0)|0)|0;if(g>>>0<=31){m=g+1|0;i=31-g|0;c=g-31>>31;h=m;a=l>>>(m>>>0)&c|k<>>(m>>>0)&c;g=0;i=l<>2]=a|0;b[f+4>>2]=j|c&0;o=0;f=0;return (p(o|0),f)|0}g=h-1|0;if(g&h|0){i=(n(h|0)|0)+33-(n(k|0)|0)|0;s=64-i|0;m=32-i|0;j=m>>31;r=i-32|0;c=r>>31;h=i;a=m-1>>31&k>>>(r>>>0)|(k<>>(i>>>0))&c;c=c&k>>>(i>>>0);g=l<>>(r>>>0))&j|l<>31;break}if(f|0){b[f>>2]=g&l;b[f+4>>2]=0}if((h|0)==1){r=j|c&0;s=a|0|0;return (p(r|0),s)|0}else{s=fa(h|0)|0;r=k>>>(s>>>0)|0;s=k<<32-s|l>>>(s>>>0)|0;return (p(r|0),s)|0}}else{if(g){if(f|0){b[f>>2]=(k>>>0)%(h>>>0);b[f+4>>2]=0}r=0;s=(k>>>0)/(h>>>0)>>>0;return (p(r|0),s)|0}if(!l){if(f|0){b[f>>2]=0;b[f+4>>2]=(k>>>0)%(i>>>0)}r=0;s=(k>>>0)/(i>>>0)>>>0;return (p(r|0),s)|0}g=i-1|0;if(!(g&i)){if(f|0){b[f>>2]=a|0;b[f+4>>2]=g&k|c&0}r=0;s=k>>>((fa(i|0)|0)>>>0);return (p(r|0),s)|0}g=(n(i|0)|0)-(n(k|0)|0)|0;if(g>>>0<=30){c=g+1|0;i=31-g|0;h=c;a=k<>>(c>>>0);c=k>>>(c>>>0);g=0;i=l<>2]=a|0;b[f+4>>2]=j|c&0;r=0;s=0;return (p(r|0),s)|0}while(0);if(!h){k=i;j=0;i=0}else{m=d|0|0;l=o|e&0;k=da(m|0,l|0,-1,-1)|0;d=q()|0;j=i;i=0;do{e=j;j=g>>>31|j<<1;g=i|g<<1;e=a<<1|e>>>31|0;o=a>>>31|c<<1|0;ea(k|0,d|0,e|0,o|0)|0;s=q()|0;r=s>>31|((s|0)<0?-1:0)<<1;i=r&1;a=ea(e|0,o|0,r&m|0,(((s|0)<0?-1:0)>>31|((s|0)<0?-1:0)<<1)&l|0)|0;c=q()|0;h=h-1|0}while((h|0)!=0);k=j;j=0}h=0;if(f|0){b[f>>2]=a;b[f+4>>2]=c}r=(g|0)>>>31|(k|h)<<1|(h<<1|g>>>31)&0|j;s=(g<<1|0>>>31)&-2|i;return (p(r|0),s)|0}function ha(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;g=B;B=B+16|0;f=g|0;ga(a,c,d,e,f)|0;B=g;return (p(b[f+4>>2]|0),b[f>>2]|0)|0}function ia(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){p(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function ja(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){p(b<>>32-c|0);return a<=8192){t(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function la(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function ma(a){a=a|0;var c=0,e=0,f=0;f=s()|0;e=b[d>>2]|0;c=e+a|0;if((a|0)>0&(c|0)<(e|0)|(c|0)<0){v(c|0)|0;r(12);return -1}if((c|0)>(f|0))if(!(u(c|0)|0)){r(12);return -1}b[d>>2]=c;return e|0} - -// EMSCRIPTEN_END_FUNCS -return{___uremdi3:ha,_bitshift64Lshr:ia,_bitshift64Shl:ja,_calloc:ca,_emscripten_replace_memory:E,_free:ba,_h3IsValid:T,_kRing:K,_malloc:aa,_maxKringSize:J,_memcpy:ka,_memset:la,_sbrk:ma,_sizeOfH3Index:_,establishStackSpace:I,stackAlloc:F,stackRestore:H,stackSave:G}}) - - -// EMSCRIPTEN_END_ASM -(asmGlobalArg,asmLibraryArg,buffer);var ___uremdi3=Module["___uremdi3"]=asm["___uremdi3"];var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _h3IsValid=Module["_h3IsValid"]=asm["_h3IsValid"];var _kRing=Module["_kRing"]=asm["_kRing"];var _malloc=Module["_malloc"]=asm["_malloc"];var _maxKringSize=Module["_maxKringSize"]=asm["_maxKringSize"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _sizeOfH3Index=Module["_sizeOfH3Index"]=asm["_sizeOfH3Index"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); - - - - return libh3 -} -)(typeof libh3 === 'object' ? libh3 : {}); -export default libh3; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_kring_distances/libh3_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_kring_distances/libh3_custom.js index 6698f4178..b1c4c7d85 100644 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_kring_distances/libh3_custom.js +++ b/clouds/snowflake/libraries/javascript/src/h3/h3_kring_distances/libh3_custom.js @@ -3,18 +3,18 @@ var libh3 = ( function(libh3) { libh3 = libh3 || {}; -var Module=typeof libh3!=="undefined"?libh3:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=11888,DYNAMIC_BASE=5254768,DYNAMICTOP_PTR=11856;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAACAAAAAwAAAAEAAAAFAAAABAAAAAYAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAABAAAABAAAAAMAAAAGAAAABQAAAAIAAAAAAAAAAgAAAAMAAAABAAAABAAAAAYAAAAAAAAABQAAAAMAAAAGAAAABAAAAAUAAAAAAAAAAQAAAAIAAAAEAAAABQAAAAYAAAAAAAAAAgAAAAMAAAABAAAABQAAAAIAAAAAAAAAAQAAAAMAAAAGAAAABAAAAAYAAAAAAAAABQAAAAIAAAABAAAABAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAgAAAAMAAAAAAAAAAAAAAAIAAAAAAAAAAQAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABgAAAAAAAAAFAAAAAAAAAAAAAAAEAAAABQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAABgAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAAAAAACAAAAAwAAAAQAAAAFAAAABgAAAAAAAAABAAAAAwAAAAQAAAAFAAAABgAAAAAAAAABAAAAAgAAAAQAAAAFAAAABgAAAAAAAAABAAAAAgAAAAMAAAAFAAAABgAAAAAAAAABAAAAAgAAAAMAAAAEAAAABgAAAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAgAAAAAAAAAAAAAABgAAAAAAAAADAAAAAgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAUAAAAEAAAAAAAAAAEAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAEAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAUAAAACAAAABAAAAAMAAAAIAAAA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AAAAAAAAAAAAAAAABQAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAUAAAABAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAFAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAQAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAADAAAABQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAQAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAADAAAABQAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAABQAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAABQAAAAAAAAAAAAAABQAAAAUAAAAAAAAAAAAAAP////8BAAAAAAAAAAMAAAAEAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAABQAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAQAAAP//////////AQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAIAAAAAAAAAAAAAAAEAAAACAAAABgAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAoAAAACAAAAAAAAAAAAAAABAAAAAQAAAAUAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAIAAAAAAAAAAAAAAAEAAAADAAAABwAAAAYAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAJAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAgAAAAAAAAAAAAAAAQAAAAQAAAAIAAAACgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAACAAAAAAAAAAAAAAABAAAACwAAAA8AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAgAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAACAAAAAAAAAAAAAAABAAAADAAAABAAAAAMAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAEAAAAKAAAAEwAAAAgAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAgAAAAAAAAAAAAAAAQAAAA0AAAARAAAADQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABEAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAIAAAAAAAAAAAAAAAEAAAAOAAAAEgAAAA8AAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABMAAAACAAAAAAAAAAAAAAABAAAA//////////8TAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAASAAAAAQ==";var tempDoublePtr=11872;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=11584,DYNAMIC_BASE=5254464,DYNAMICTOP_PTR=11552;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,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AAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAUAAAABAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAFAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAQAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAADAAAABQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAQAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAADAAAABQAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAABQAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAABQAAAAAAAAAAAAAABQAAAAUAAAAAAAAAAAAAAP////8BAAAAAAAAAAMAAAAEAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAABQAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAQAAAP//////////AQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAIAAAAAAAAAAAAAAAEAAAACAAAABgAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAoAAAACAAAAAAAAAAAAAAABAAAAAQAAAAUAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAIAAAAAAAAAAAAAAAEAAAADAAAABwAAAAYAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAJAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAgAAAAAAAAAAAAAAAQAAAAQAAAAIAAAACgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAACAAAAAAAAAAAAAAABAAAACwAAAA8AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAgAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAACAAAAAAAAAAAAAAABAAAADAAAABAAAAAMAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAEAAAAKAAAAEwAAAAgAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAgAAAAAAAAAAAAAAAQAAAA0AAAARAAAADQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABEAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAIAAAAAAAAAAAAAAAEAAAAOAAAAEgAAAA8AAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABMAAAACAAAAAAAAAAAAAAABAAAA//////////8TAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAASAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAAAAAABAAAAAAAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////////////////////////////wAAAAD/////AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA/////wAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAP////8AAAAABQAAAAAAAAAAAAAAAAAAAAAAAAD/////BQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAEAAQAAAQEAAAAAAAEAAAABAAAAAQABAAAAAAAAAAAAAAAAAAAAAHJldkRpciAhPSBJTlZBTElEX0RJR0lUAGxvY2FsaWouYwBoM1RvTG9jYWxJamsAYmFzZUNlbGwgIT0gb3JpZ2luQmFzZUNlbGwAIShvcmlnaW5PblBlbnQgJiYgaW5kZXhPblBlbnQpAHBlbnRhZ29uUm90YXRpb25zID49IDAAZGlyZWN0aW9uUm90YXRpb25zID49IDAAYmFzZUNlbGwgPT0gb3JpZ2luQmFzZUNlbGw=";var tempDoublePtr=11568;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]=a;b[g+4>>2]=c;g=(f|0)!=0;if(g)b[f>>2]=0;if(U(a,c)|0){n=1;B=o;return n|0}b[n>>2]=0;a:do if((d|0)>=1)if(g){k=0;l=1;m=1;h=0;g=a;while(1){if(!(h|k)){g=N(g,c,4,n)|0;c=q()|0;if((g|0)==0&(c|0)==0){g=2;break a}if(U(g,c)|0){g=1;break a}}g=N(g,c,b[16+(k<<2)>>2]|0,n)|0;c=q()|0;if((g|0)==0&(c|0)==0){g=2;break a}a=e+(m<<3)|0;b[a>>2]=g;b[a+4>>2]=c;b[f+(m<<2)>>2]=l;h=h+1|0;a=(h|0)==(l|0);i=k+1|0;j=(i|0)==6;if(U(g,c)|0){g=1;break a}l=l+(j&a&1)|0;if((l|0)>(d|0)){g=0;break}else{k=a?(j?0:i):k;m=m+1|0;h=a?0:h}}}else{k=0;l=1;m=1;h=0;g=a;while(1){if(!(h|k)){g=N(g,c,4,n)|0;c=q()|0;if((g|0)==0&(c|0)==0){g=2;break a}if(U(g,c)|0){g=1;break a}}g=N(g,c,b[16+(k<<2)>>2]|0,n)|0;c=q()|0;if((g|0)==0&(c|0)==0){g=2;break a}a=e+(m<<3)|0;b[a>>2]=g;b[a+4>>2]=c;h=h+1|0;a=(h|0)==(l|0);i=k+1|0;j=(i|0)==6;if(U(g,c)|0){g=1;break a}l=l+(j&a&1)|0;if((l|0)>(d|0)){g=0;break}else{k=a?(j?0:i):k;m=m+1|0;h=a?0:h}}}else g=0;while(0);n=g;B=o;return n|0}function M(a,c,d,e,f,g,h){a=a|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0;m=B;B=B+16|0;l=m;if((a|0)==0&(c|0)==0){B=m;return}i=ha(a|0,c|0,g|0,((g|0)<0)<<31>>31|0)|0;q()|0;j=e+(i<<3)|0;n=j;o=b[n>>2]|0;n=b[n+4>>2]|0;k=(o|0)==(a|0)&(n|0)==(c|0);if(!((o|0)==0&(n|0)==0|k))do{i=(i+1|0)%(g|0)|0;j=e+(i<<3)|0;o=j;n=b[o>>2]|0;o=b[o+4>>2]|0;k=(n|0)==(a|0)&(o|0)==(c|0)}while(!((n|0)==0&(o|0)==0|k));i=f+(i<<2)|0;if(k?(b[i>>2]|0)<=(h|0):0){B=m;return}o=j;b[o>>2]=a;b[o+4>>2]=c;b[i>>2]=h;if((h|0)>=(d|0)){B=m;return}o=h+1|0;b[l>>2]=0;n=N(a,c,2,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,3,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,1,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,5,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,4,l)|0;M(n,q()|0,d,e,f,g,o);b[l>>2]=0;n=N(a,c,6,l)|0;M(n,q()|0,d,e,f,g,o);B=m;return}function N(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;if((b[e>>2]|0)>0){f=0;do{d=R(d)|0;f=f+1|0}while((f|0)<(b[e>>2]|0))}i=ia(a|0,c|0,45)|0;q()|0;j=i&127;g=V(a,c)|0;f=ia(a|0,c|0,52)|0;q()|0;f=f&15;a:do if(!f)h=6;else while(1){m=(15-f|0)*3|0;n=ia(a|0,c|0,m|0)|0;q()|0;n=n&7;o=(Z(f)|0)==0;f=f+-1|0;l=ja(7,0,m|0)|0;c=c&~(q()|0);m=ja(b[(o?464:48)+(n*28|0)+(d<<2)>>2]|0,0,m|0)|0;k=q()|0;d=b[(o?672:256)+(n*28|0)+(d<<2)>>2]|0;a=m|a&~l;c=k|c;if(!d){d=0;break a}if(!f){h=6;break}}while(0);if((h|0)==6){o=b[880+(j*28|0)+(d<<2)>>2]|0;n=ja(o|0,0,45)|0;a=n|a;c=q()|0|c&-1040385;d=b[4304+(j*28|0)+(d<<2)>>2]|0;if((o&127|0)==127){o=ja(b[880+(j*28|0)+20>>2]|0,0,45)|0;c=q()|0|c&-1040385;d=b[4304+(j*28|0)+20>>2]|0;a=X(o|a,c)|0;c=q()|0;b[e>>2]=(b[e>>2]|0)+1}}h=ia(a|0,c|0,45)|0;q()|0;h=h&127;b:do if(!(O(h)|0)){if((d|0)>0){f=0;do{a=X(a,c)|0;c=q()|0;f=f+1|0}while((f|0)!=(d|0))}}else{c:do if((V(a,c)|0)==1){if((j|0)!=(h|0))if(Q(h,b[7728+(j*28|0)>>2]|0)|0){a=Y(a,c)|0;g=1;c=q()|0;break}else{a=X(a,c)|0;g=1;c=q()|0;break}switch(g|0){case 5:{a=Y(a,c)|0;c=q()|0;b[e>>2]=(b[e>>2]|0)+5;g=0;break c}case 3:{a=X(a,c)|0;c=q()|0;b[e>>2]=(b[e>>2]|0)+1;g=0;break c}default:{n=0;o=0;p(n|0);return o|0}}}else g=0;while(0);if((d|0)>0){f=0;do{a=W(a,c)|0;c=q()|0;f=f+1|0}while((f|0)!=(d|0))}if((j|0)!=(h|0)){if(!(P(h)|0)){if((g|0)!=0|(V(a,c)|0)!=5)break;b[e>>2]=(b[e>>2]|0)+1;break}switch(i&127){case 8:case 118:break b;default:{}}if((V(a,c)|0)!=3)b[e>>2]=(b[e>>2]|0)+1}}while(0);b[e>>2]=((b[e>>2]|0)+d|0)%6|0;n=c;o=a;p(n|0);return o|0}function O(a){a=a|0;return b[7728+(a*28|0)+16>>2]|0}function P(a){a=a|0;return (a|0)==4|(a|0)==117|0}function Q(a,c){a=a|0;c=c|0;if((b[7728+(a*28|0)+20>>2]|0)==(c|0)){c=1;return c|0}c=(b[7728+(a*28|0)+24>>2]|0)==(c|0);return c|0}function R(a){a=a|0;switch(a|0){case 1:{a=5;break}case 5:{a=4;break}case 4:{a=6;break}case 6:{a=2;break}case 2:{a=3;break}case 3:{a=1;break}default:{}}return a|0}function S(a){a=a|0;switch(a|0){case 1:{a=3;break}case 3:{a=2;break}case 2:{a=6;break}case 6:{a=4;break}case 4:{a=5;break}case 5:{a=1;break}default:{}}return a|0}function T(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0;if(!(0==0&(b&-16777216|0)==134217728)){b=0;return b|0}g=ia(a|0,b|0,45)|0;q()|0;g=g&127;if(g>>>0>121){b=0;return b|0}c=ia(a|0,b|0,52)|0;q()|0;c=c&15;do if(c|0){e=1;d=0;while(1){f=ia(a|0,b|0,(15-e|0)*3|0)|0;q()|0;f=f&7;if((f|0)!=0&(d^1))if((f|0)==1&(O(g)|0)!=0){h=0;d=13;break}else d=1;if((f|0)==7){h=0;d=13;break}if(e>>>0>>0)e=e+1|0;else{d=9;break}}if((d|0)==9){if((c|0)==15)h=1;else break;return h|0}else if((d|0)==13)return h|0}while(0);while(1){h=ia(a|0,b|0,(14-c|0)*3|0)|0;q()|0;if(!((h&7|0)==7&0==0)){h=0;d=13;break}if(c>>>0<14)c=c+1|0;else{h=1;d=13;break}}if((d|0)==13)return h|0;return 0}function U(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=ia(a|0,b|0,45)|0;q()|0;if(!(O(e&127)|0)){e=0;return e|0}e=ia(a|0,b|0,52)|0;q()|0;e=e&15;a:do if(!e)c=0;else{d=1;while(1){c=ia(a|0,b|0,(15-d|0)*3|0)|0;q()|0;c=c&7;if(c|0)break a;if(d>>>0>>0)d=d+1|0;else{c=0;break}}}while(0);e=(c|0)==0&1;return e|0}function V(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=ia(a|0,b|0,52)|0;q()|0;e=e&15;if(!e){e=0;return e|0}d=1;while(1){c=ia(a|0,b|0,(15-d|0)*3|0)|0;q()|0;c=c&7;if(c|0){d=5;break}if(d>>>0>>0)d=d+1|0;else{c=0;d=5;break}}if((d|0)==5)return c|0;return 0}function W(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;i=ia(a|0,b|0,52)|0;q()|0;i=i&15;if(!i){h=b;i=a;p(h|0);return i|0}h=1;c=0;while(1){f=(15-h|0)*3|0;d=ja(7,0,f|0)|0;e=q()|0;g=ia(a|0,b|0,f|0)|0;q()|0;f=ja(R(g&7)|0,0,f|0)|0;g=q()|0;a=f|a&~d;b=g|b&~e;a:do if(!c)if(!((f&d|0)==0&(g&e|0)==0)){d=ia(a|0,b|0,52)|0;q()|0;d=d&15;if(!d)c=1;else{c=1;b:while(1){g=ia(a|0,b|0,(15-c|0)*3|0)|0;q()|0;switch(g&7){case 1:break b;case 0:break;default:{c=1;break a}}if(c>>>0>>0)c=c+1|0;else{c=1;break a}}c=1;while(1){g=(15-c|0)*3|0;e=ia(a|0,b|0,g|0)|0;q()|0;f=ja(7,0,g|0)|0;b=b&~(q()|0);g=ja(R(e&7)|0,0,g|0)|0;a=a&~f|g;b=b|(q()|0);if(c>>>0>>0)c=c+1|0;else{c=1;break}}}}else c=0;while(0);if(h>>>0>>0)h=h+1|0;else break}p(b|0);return a|0}function X(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;d=ia(a|0,b|0,52)|0;q()|0;d=d&15;if(!d){c=b;d=a;p(c|0);return d|0}c=1;while(1){f=(15-c|0)*3|0;g=ia(a|0,b|0,f|0)|0;q()|0;e=ja(7,0,f|0)|0;b=b&~(q()|0);f=ja(R(g&7)|0,0,f|0)|0;a=f|a&~e;b=q()|0|b;if(c>>>0>>0)c=c+1|0;else break}p(b|0);return a|0}function Y(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;d=ia(a|0,b|0,52)|0;q()|0;d=d&15;if(!d){c=b;d=a;p(c|0);return d|0}c=1;while(1){g=(15-c|0)*3|0;f=ja(7,0,g|0)|0;e=b&~(q()|0);b=ia(a|0,b|0,g|0)|0;q()|0;b=ja(S(b&7)|0,0,g|0)|0;a=b|a&~f;b=q()|0|e;if(c>>>0>>0)c=c+1|0;else break}p(b|0);return a|0}function Z(a){a=a|0;return (a|0)%2|0|0}function _(){return 8}function $(){return 11152}function aa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=B;B=B+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[2789]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=11196+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[2789]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;B=w;return v|0}l=b[2791]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=11196+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[2794]|0;c=l>>>3;d=11196+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2791]=h;b[2794]=f;v=i;B=w;return v|0}g=b[2790]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[11460+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=11460+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[2790]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[2794]|0;c=l>>>3;d=11196+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2791]=j;b[2794]=h}v=i+8|0;B=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[2790]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[11460+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[11460+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[2791]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=11460+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=11196+(c<<1<<2)|0;a=b[2789]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=11460+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;B=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[2791]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[2794]|0;if(c>>>0>15){v=a+m|0;b[2794]=v;b[2791]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[2791]=0;b[2794]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;B=w;return v|0}h=b[2792]|0;if(h>>>0>m>>>0){t=h-m|0;b[2792]=t;v=b[2795]|0;u=v+m|0;b[2795]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;B=w;return v|0}if(!(b[2907]|0)){b[2909]=4096;b[2908]=4096;b[2910]=-1;b[2911]=-1;b[2912]=0;b[2900]=0;b[2907]=n&-16^1431655768;a=4096}else a=b[2909]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;B=w;return v|0}a=b[2899]|0;if(a|0?(l=b[2897]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;B=w;return v|0}d:do if(!(b[2900]&4)){d=b[2795]|0;e:do if(d){e=11604;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=ma(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=ma(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[2908]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[2897]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[2899]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=ma(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[2909]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((ma(a|0)|0)==(-1|0)){ma(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[2900]=b[2900]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=ma(k|0)|0,p=ma(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[2897]|0)+h|0;b[2897]=c;if(c>>>0>(b[2898]|0)>>>0)b[2898]=c;j=b[2795]|0;f:do if(j){c=11604;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[2792]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[2795]=u;b[2792]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[2796]=b[2911];break}if(g>>>0<(b[2793]|0)>>>0)b[2793]=g;d=g+h|0;c=11604;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[2792]|0)+i|0;b[2792]=v;b[2795]=k;b[k+4>>2]=v|1}else{if((b[2794]|0)==(c|0)){v=(b[2791]|0)+i|0;b[2791]=v;b[2794]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[2789]=b[2789]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=11460+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[2790]=b[2790]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=11196+(c<<1<<2)|0;a=b[2789]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=11460+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[2790]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;B=w;return v|0}c=11604;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[2795]=u;b[2792]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[2796]=b[2911];d=a+4|0;b[d>>2]=27;b[c>>2]=b[2901];b[c+4>>2]=b[2902];b[c+8>>2]=b[2903];b[c+12>>2]=b[2904];b[2901]=g;b[2902]=h;b[2904]=0;b[2903]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=11196+(c<<1<<2)|0;a=b[2789]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=11460+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[2790]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[2793]|0;if((v|0)==0|g>>>0>>0)b[2793]=g;b[2901]=g;b[2902]=h;b[2904]=0;b[2798]=b[2907];b[2797]=-1;b[2802]=11196;b[2801]=11196;b[2804]=11204;b[2803]=11204;b[2806]=11212;b[2805]=11212;b[2808]=11220;b[2807]=11220;b[2810]=11228;b[2809]=11228;b[2812]=11236;b[2811]=11236;b[2814]=11244;b[2813]=11244;b[2816]=11252;b[2815]=11252;b[2818]=11260;b[2817]=11260;b[2820]=11268;b[2819]=11268;b[2822]=11276;b[2821]=11276;b[2824]=11284;b[2823]=11284;b[2826]=11292;b[2825]=11292;b[2828]=11300;b[2827]=11300;b[2830]=11308;b[2829]=11308;b[2832]=11316;b[2831]=11316;b[2834]=11324;b[2833]=11324;b[2836]=11332;b[2835]=11332;b[2838]=11340;b[2837]=11340;b[2840]=11348;b[2839]=11348;b[2842]=11356;b[2841]=11356;b[2844]=11364;b[2843]=11364;b[2846]=11372;b[2845]=11372;b[2848]=11380;b[2847]=11380;b[2850]=11388;b[2849]=11388;b[2852]=11396;b[2851]=11396;b[2854]=11404;b[2853]=11404;b[2856]=11412;b[2855]=11412;b[2858]=11420;b[2857]=11420;b[2860]=11428;b[2859]=11428;b[2862]=11436;b[2861]=11436;b[2864]=11444;b[2863]=11444;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[2795]=u;b[2792]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[2796]=b[2911]}while(0);c=b[2792]|0;if(c>>>0>m>>>0){t=c-m|0;b[2792]=t;v=b[2795]|0;u=v+m|0;b[2795]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;B=w;return v|0}}v=$()|0;b[v>>2]=12;v=0;B=w;return v|0}function ba(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[2793]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[2794]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[2791]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[2789]=b[2789]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=11460+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[2790]=b[2790]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[2795]|0)==(j|0)){j=(b[2792]|0)+c|0;b[2792]=j;b[2795]=i;b[i+4>>2]=j|1;if((i|0)!=(b[2794]|0))return;b[2794]=0;b[2791]=0;return}if((b[2794]|0)==(j|0)){j=(b[2791]|0)+c|0;b[2791]=j;b[2794]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[2789]=b[2789]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=11460+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[2790]=b[2790]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[2794]|0)){b[2791]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=11196+(a<<1<<2)|0;c=b[2789]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=11460+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[2790]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[2797]|0)+-1|0;b[2797]=j;if(j|0)return;a=11612;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[2797]=-1;return}function ca(a,c){a=a|0;c=c|0;var d=0;if(a){d=m(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=aa(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;la(a|0,0,d|0)|0;return a|0}function da(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;c=a+c>>>0;return (p(b+d+(c>>>0>>0|0)>>>0|0),c|0)|0}function ea(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;d=b-d-(c>>>0>a>>>0|0)>>>0;return (p(d|0),a-c>>>0|0)|0}function fa(a){a=a|0;return (a?31-(n(a^a-1)|0)|0:32)|0}function ga(a,c,d,e,f){a=a|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,o=0,r=0,s=0;l=a;j=c;k=j;h=d;o=e;i=o;if(!k){g=(f|0)!=0;if(!i){if(g){b[f>>2]=(l>>>0)%(h>>>0);b[f+4>>2]=0}o=0;f=(l>>>0)/(h>>>0)>>>0;return (p(o|0),f)|0}else{if(!g){o=0;f=0;return (p(o|0),f)|0}b[f>>2]=a|0;b[f+4>>2]=c&0;o=0;f=0;return (p(o|0),f)|0}}g=(i|0)==0;do if(h){if(!g){g=(n(i|0)|0)-(n(k|0)|0)|0;if(g>>>0<=31){m=g+1|0;i=31-g|0;c=g-31>>31;h=m;a=l>>>(m>>>0)&c|k<>>(m>>>0)&c;g=0;i=l<>2]=a|0;b[f+4>>2]=j|c&0;o=0;f=0;return (p(o|0),f)|0}g=h-1|0;if(g&h|0){i=(n(h|0)|0)+33-(n(k|0)|0)|0;s=64-i|0;m=32-i|0;j=m>>31;r=i-32|0;c=r>>31;h=i;a=m-1>>31&k>>>(r>>>0)|(k<>>(i>>>0))&c;c=c&k>>>(i>>>0);g=l<>>(r>>>0))&j|l<>31;break}if(f|0){b[f>>2]=g&l;b[f+4>>2]=0}if((h|0)==1){r=j|c&0;s=a|0|0;return (p(r|0),s)|0}else{s=fa(h|0)|0;r=k>>>(s>>>0)|0;s=k<<32-s|l>>>(s>>>0)|0;return (p(r|0),s)|0}}else{if(g){if(f|0){b[f>>2]=(k>>>0)%(h>>>0);b[f+4>>2]=0}r=0;s=(k>>>0)/(h>>>0)>>>0;return (p(r|0),s)|0}if(!l){if(f|0){b[f>>2]=0;b[f+4>>2]=(k>>>0)%(i>>>0)}r=0;s=(k>>>0)/(i>>>0)>>>0;return (p(r|0),s)|0}g=i-1|0;if(!(g&i)){if(f|0){b[f>>2]=a|0;b[f+4>>2]=g&k|c&0}r=0;s=k>>>((fa(i|0)|0)>>>0);return (p(r|0),s)|0}g=(n(i|0)|0)-(n(k|0)|0)|0;if(g>>>0<=30){c=g+1|0;i=31-g|0;h=c;a=k<>>(c>>>0);c=k>>>(c>>>0);g=0;i=l<>2]=a|0;b[f+4>>2]=j|c&0;r=0;s=0;return (p(r|0),s)|0}while(0);if(!h){k=i;j=0;i=0}else{m=d|0|0;l=o|e&0;k=da(m|0,l|0,-1,-1)|0;d=q()|0;j=i;i=0;do{e=j;j=g>>>31|j<<1;g=i|g<<1;e=a<<1|e>>>31|0;o=a>>>31|c<<1|0;ea(k|0,d|0,e|0,o|0)|0;s=q()|0;r=s>>31|((s|0)<0?-1:0)<<1;i=r&1;a=ea(e|0,o|0,r&m|0,(((s|0)<0?-1:0)>>31|((s|0)<0?-1:0)<<1)&l|0)|0;c=q()|0;h=h-1|0}while((h|0)!=0);k=j;j=0}h=0;if(f|0){b[f>>2]=a;b[f+4>>2]=c}r=(g|0)>>>31|(k|h)<<1|(h<<1|g>>>31)&0|j;s=(g<<1|0>>>31)&-2|i;return (p(r|0),s)|0}function ha(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;g=B;B=B+16|0;f=g|0;ga(a,c,d,e,f)|0;B=g;return (p(b[f+4>>2]|0),b[f>>2]|0)|0}function ia(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){p(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function ja(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){p(b<>>32-c|0);return a<=8192){t(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function la(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function ma(a){a=a|0;var c=0,e=0,f=0;f=s()|0;e=b[d>>2]|0;c=e+a|0;if((a|0)>0&(c|0)<(e|0)|(c|0)<0){v(c|0)|0;r(12);return -1}if((c|0)>(f|0))if(!(u(c|0)|0)){r(12);return -1}b[d>>2]=c;return e|0} +function G(a){a=a|0;var b=0;b=C;C=C+a|0;C=C+15&-16;return b|0}function H(){return C|0}function I(a){a=a|0;C=a}function J(a,b){a=a|0;b=b|0;C=a;D=b}function K(a){a=a|0;return b[6864+(a*28|0)+16>>2]|0}function L(a,c){a=a|0;c=c|0;if((b[16+(a*28|0)>>2]|0)==(c|0)){c=0;return c|0}if((b[16+(a*28|0)+4>>2]|0)==(c|0)){c=1;return c|0}if((b[16+(a*28|0)+8>>2]|0)==(c|0)){c=2;return c|0}if((b[16+(a*28|0)+12>>2]|0)==(c|0)){c=3;return c|0}if((b[16+(a*28|0)+16>>2]|0)==(c|0)){c=4;return c|0}if((b[16+(a*28|0)+20>>2]|0)==(c|0)){c=5;return c|0}else return ((b[16+(a*28|0)+24>>2]|0)==(c|0)?6:7)|0;return 0}function M(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;if((c|0)<0){d=d-c|0;b[h>>2]=d;g=a+8|0;b[g>>2]=(b[g>>2]|0)-c;b[a>>2]=0;c=0}if((d|0)<0){c=c-d|0;b[a>>2]=c;g=a+8|0;f=(b[g>>2]|0)-d|0;b[g>>2]=f;b[h>>2]=0;d=0}else{f=a+8|0;g=f;f=b[f>>2]|0}if((f|0)<0){c=c-f|0;b[a>>2]=c;d=d-f|0;b[h>>2]=d;b[g>>2]=0;f=0}e=(d|0)<(c|0)?d:c;e=(f|0)<(e|0)?f:e;if((e|0)<=0)return;b[a>>2]=c-e;b[h>>2]=d-e;b[g>>2]=f-e;return}function N(a,c,d){a=a|0;c=c|0;d=d|0;b[d>>2]=(b[c>>2]|0)+(b[a>>2]|0);b[d+4>>2]=(b[c+4>>2]|0)+(b[a+4>>2]|0);b[d+8>>2]=(b[c+8>>2]|0)+(b[a+8>>2]|0);return}function O(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;i=a+8|0;e=b[i>>2]|0;f=d+(c*3|0)|0;b[a>>2]=f;d=e+(d*3|0)|0;b[h>>2]=d;c=(e*3|0)+c|0;b[i>>2]=c;e=d-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=e;b[i>>2]=c;b[a>>2]=0;d=e;e=0}else e=f;if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function P(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=(c*3|0)+f|0;f=d+(f*3|0)|0;b[a>>2]=f;b[h>>2]=e;c=(d*3|0)+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;f=0}else d=e;if((d|0)<0){f=f-d|0;b[a>>2]=f;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=f-c|0;e=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=e;b[i>>2]=0;f=g;c=0}else e=d;d=(e|0)<(f|0)?e:f;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=f-d;b[h>>2]=e-d;b[i>>2]=c-d;return}function Q(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0;if((c+-1|0)>>>0>=6)return;f=(b[10288+(c*12|0)>>2]|0)+(b[a>>2]|0)|0;b[a>>2]=f;i=a+4|0;e=(b[10288+(c*12|0)+4>>2]|0)+(b[i>>2]|0)|0;b[i>>2]=e;h=a+8|0;c=(b[10288+(c*12|0)+8>>2]|0)+(b[h>>2]|0)|0;b[h>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[i>>2]=d;b[h>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[h>>2]=c;b[i>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[i>>2]=f-d;b[h>>2]=c-d;return}function R(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;e=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;f=e+c|0;b[a>>2]=f;e=d+e|0;b[h>>2]=e;c=d+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function S(a){a=a|0;switch(a|0){case 1:{a=3;break}case 3:{a=2;break}case 2:{a=6;break}case 6:{a=4;break}case 4:{a=5;break}case 5:{a=1;break}default:{}}return a|0}function T(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=(b[a>>2]|0)-(b[c>>2]|0)|0;i=(h|0)<0;e=(b[a+4>>2]|0)-(b[c+4>>2]|0)-(i?h:0)|0;g=(e|0)<0;f=(i?0-h|0:0)+(b[a+8>>2]|0)-(b[c+8>>2]|0)+(g?0-e|0:0)|0;a=(f|0)<0;c=a?0:f;d=(g?0:e)-(a?f:0)|0;f=(i?0:h)-(g?e:0)-(a?f:0)|0;a=(d|0)<(f|0)?d:f;a=(c|0)<(a|0)?c:a;e=(a|0)>0;c=c-(e?a:0)|0;d=d-(e?a:0)|0;a=f-(e?a:0)|0;a=(a|0)>-1?a:0-a|0;d=(d|0)>-1?d:0-d|0;c=(c|0)>-1?c:0-c|0;c=(d|0)>(c|0)?d:c;return ((a|0)>(c|0)?a:c)|0}function U(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=da(a|0,b|0,52)|0;q()|0;e=e&15;if(!e){e=0;return e|0}d=1;while(1){c=da(a|0,b|0,(15-d|0)*3|0)|0;q()|0;c=c&7;if(c|0){d=5;break}if(d>>>0>>0)d=d+1|0;else{c=0;d=5;break}}if((d|0)==5)return c|0;return 0}function V(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;i=da(a|0,b|0,52)|0;q()|0;i=i&15;if(!i){h=b;i=a;p(h|0);return i|0}h=1;c=0;while(1){f=(15-h|0)*3|0;d=ea(7,0,f|0)|0;e=q()|0;g=da(a|0,b|0,f|0)|0;q()|0;f=ea(S(g&7)|0,0,f|0)|0;g=q()|0;a=f|a&~d;b=g|b&~e;a:do if(!c)if(!((f&d|0)==0&(g&e|0)==0)){d=da(a|0,b|0,52)|0;q()|0;d=d&15;if(!d)c=1;else{c=1;b:while(1){g=da(a|0,b|0,(15-c|0)*3|0)|0;q()|0;switch(g&7){case 1:break b;case 0:break;default:{c=1;break a}}if(c>>>0>>0)c=c+1|0;else{c=1;break a}}c=1;while(1){e=(15-c|0)*3|0;f=ea(7,0,e|0)|0;g=b&~(q()|0);b=da(a|0,b|0,e|0)|0;q()|0;b=ea(S(b&7)|0,0,e|0)|0;a=a&~f|b;b=g|(q()|0);if(c>>>0>>0)c=c+1|0;else{c=1;break}}}}else c=0;while(0);if(h>>>0>>0)h=h+1|0;else break}p(b|0);return a|0}function W(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;d=da(a|0,b|0,52)|0;q()|0;d=d&15;if(!d){c=b;d=a;p(c|0);return d|0}c=1;while(1){g=(15-c|0)*3|0;f=ea(7,0,g|0)|0;e=b&~(q()|0);b=da(a|0,b|0,g|0)|0;q()|0;b=ea(S(b&7)|0,0,g|0)|0;a=b|a&~f;b=q()|0|e;if(c>>>0>>0)c=c+1|0;else break}p(b|0);return a|0}function X(a){a=a|0;return (a|0)%2|0|0}function Y(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;f=d+4|0;g=da(a|0,c|0,52)|0;q()|0;g=g&15;h=da(a|0,c|0,45)|0;q()|0;e=(g|0)==0;if(!(K(h&127)|0)){if(e){h=0;return h|0}if((b[f>>2]|0)==0?(b[d+8>>2]|0)==0:0)e=(b[d+12>>2]|0)!=0&1;else e=1}else if(e){h=1;return h|0}else e=1;d=1;while(1){if(!(d&1))P(f);else O(f);h=da(a|0,c|0,(15-d|0)*3|0)|0;q()|0;Q(f,h&7);if(d>>>0>>0)d=d+1|0;else break}return e|0}function Z(c,d,e,f,g){c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,s=0,t=0,u=0,v=0,w=0;w=C;C=C+32|0;v=w+16|0;u=w;h=da(c|0,d|0,52)|0;q()|0;h=h&15;p=da(e|0,f|0,52)|0;q()|0;if((h|0)!=(p&15|0)){v=1;C=w;return v|0}l=da(c|0,d|0,45)|0;q()|0;l=l&127;m=da(e|0,f|0,45)|0;q()|0;m=m&127;p=(l|0)!=(m|0);if(p){j=L(l,m)|0;if((j|0)==7){v=2;C=w;return v|0}k=L(m,l)|0;if((k|0)==7)r(10656,10680,151,10690);else{s=j;i=k}}else{s=0;i=0}n=K(l)|0;o=K(m)|0;b[v>>2]=0;b[v+4>>2]=0;b[v+8>>2]=0;b[v+12>>2]=0;do if(!s){Y(e,f,v)|0;if((n|0)!=0&(o|0)!=0){if((m|0)!=(l|0))r(10808,10680,243,10690);i=U(c,d)|0;h=U(e,f)|0;if(!(a[10592+(i*7|0)+h>>0]|0)){i=b[10384+(i*28|0)+(h<<2)>>2]|0;if((i|0)>0){j=v+4|0;h=0;do{R(j);h=h+1|0}while((h|0)!=(i|0));t=50}else t=50}else h=5}else t=50}else{m=b[3440+(l*28|0)+(s<<2)>>2]|0;j=(m|0)>0;if(!o)if(j){l=0;k=e;j=f;do{k=W(k,j)|0;j=q()|0;i=S(i)|0;l=l+1|0}while((l|0)!=(m|0));m=i;l=k;k=j}else{m=i;l=e;k=f}else if(j){l=0;k=e;j=f;do{k=V(k,j)|0;j=q()|0;i=S(i)|0;if((i|0)==1)i=S(1)|0;l=l+1|0}while((l|0)!=(m|0));m=i;l=k;k=j}else{m=i;l=e;k=f}Y(l,k,v)|0;if(!p)r(10703,10680,181,10690);j=(n|0)!=0;i=(o|0)!=0;if(j&i)r(10730,10680,182,10690);if(!j)if(i){i=U(l,k)|0;if(a[10592+(i*7|0)+m>>0]|0){h=4;break}l=0;k=b[10384+(m*28|0)+(i<<2)>>2]|0;t=26}else i=0;else{i=U(c,d)|0;if(a[10592+(i*7|0)+s>>0]|0){h=3;break}k=b[10384+(i*28|0)+(s<<2)>>2]|0;l=k;t=26}if((t|0)==26){if((k|0)<=-1)r(10761,10680,212,10690);if((l|0)<=-1)r(10784,10680,213,10690);if((k|0)>0){j=v+4|0;i=0;do{R(j);i=i+1|0}while((i|0)!=(k|0));i=l}else i=l};b[u>>2]=0;b[u+4>>2]=0;b[u+8>>2]=0;Q(u,s);if(h|0)while(1){if(!(X(h)|0))P(u);else O(u);if((h|0)>1)h=h+-1|0;else break}if((i|0)>0){h=0;do{R(u);h=h+1|0}while((h|0)!=(i|0))}t=v+4|0;N(t,u,t);M(t);t=50}while(0);if((t|0)==50){h=v+4|0;b[g>>2]=b[h>>2];b[g+4>>2]=b[h+4>>2];b[g+8>>2]=b[h+8>>2];h=0}v=h;C=w;return v|0}function _(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;g=C;C=C+32|0;e=g+12|0;f=g;if((Z(a,b,a,b,e)|0)==0?(Z(a,b,c,d,f)|0)==0:0)a=T(e,f)|0;else a=-1;C=g;return a|0}function $(){return 10848}function aa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=C;C=C+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[2713]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=10892+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[2713]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;C=w;return v|0}l=b[2715]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=10892+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[2718]|0;c=l>>>3;d=10892+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2715]=h;b[2718]=f;v=i;C=w;return v|0}g=b[2714]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[11156+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=11156+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[2714]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[2718]|0;c=l>>>3;d=10892+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2715]=j;b[2718]=h}v=i+8|0;C=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[2714]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[11156+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[11156+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[2715]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=11156+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=10892+(c<<1<<2)|0;a=b[2713]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=11156+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;C=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[2715]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[2718]|0;if(c>>>0>15){v=a+m|0;b[2718]=v;b[2715]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[2715]=0;b[2718]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;C=w;return v|0}h=b[2716]|0;if(h>>>0>m>>>0){t=h-m|0;b[2716]=t;v=b[2719]|0;u=v+m|0;b[2719]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;C=w;return v|0}if(!(b[2831]|0)){b[2833]=4096;b[2832]=4096;b[2834]=-1;b[2835]=-1;b[2836]=0;b[2824]=0;b[2831]=n&-16^1431655768;a=4096}else a=b[2833]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;C=w;return v|0}a=b[2823]|0;if(a|0?(l=b[2821]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;C=w;return v|0}d:do if(!(b[2824]&4)){d=b[2719]|0;e:do if(d){e=11300;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=ha(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=ha(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[2832]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[2821]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[2823]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=ha(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[2833]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((ha(a|0)|0)==(-1|0)){ha(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[2824]=b[2824]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=ha(k|0)|0,p=ha(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[2821]|0)+h|0;b[2821]=c;if(c>>>0>(b[2822]|0)>>>0)b[2822]=c;j=b[2719]|0;f:do if(j){c=11300;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[2716]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[2719]=u;b[2716]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[2720]=b[2835];break}if(g>>>0<(b[2717]|0)>>>0)b[2717]=g;d=g+h|0;c=11300;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[2716]|0)+i|0;b[2716]=v;b[2719]=k;b[k+4>>2]=v|1}else{if((b[2718]|0)==(c|0)){v=(b[2715]|0)+i|0;b[2715]=v;b[2718]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[2713]=b[2713]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=11156+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[2714]=b[2714]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=10892+(c<<1<<2)|0;a=b[2713]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=11156+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[2714]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;C=w;return v|0}c=11300;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[2719]=u;b[2716]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[2720]=b[2835];d=a+4|0;b[d>>2]=27;b[c>>2]=b[2825];b[c+4>>2]=b[2826];b[c+8>>2]=b[2827];b[c+12>>2]=b[2828];b[2825]=g;b[2826]=h;b[2828]=0;b[2827]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=10892+(c<<1<<2)|0;a=b[2713]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=11156+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[2714]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[2717]|0;if((v|0)==0|g>>>0>>0)b[2717]=g;b[2825]=g;b[2826]=h;b[2828]=0;b[2722]=b[2831];b[2721]=-1;b[2726]=10892;b[2725]=10892;b[2728]=10900;b[2727]=10900;b[2730]=10908;b[2729]=10908;b[2732]=10916;b[2731]=10916;b[2734]=10924;b[2733]=10924;b[2736]=10932;b[2735]=10932;b[2738]=10940;b[2737]=10940;b[2740]=10948;b[2739]=10948;b[2742]=10956;b[2741]=10956;b[2744]=10964;b[2743]=10964;b[2746]=10972;b[2745]=10972;b[2748]=10980;b[2747]=10980;b[2750]=10988;b[2749]=10988;b[2752]=10996;b[2751]=10996;b[2754]=11004;b[2753]=11004;b[2756]=11012;b[2755]=11012;b[2758]=11020;b[2757]=11020;b[2760]=11028;b[2759]=11028;b[2762]=11036;b[2761]=11036;b[2764]=11044;b[2763]=11044;b[2766]=11052;b[2765]=11052;b[2768]=11060;b[2767]=11060;b[2770]=11068;b[2769]=11068;b[2772]=11076;b[2771]=11076;b[2774]=11084;b[2773]=11084;b[2776]=11092;b[2775]=11092;b[2778]=11100;b[2777]=11100;b[2780]=11108;b[2779]=11108;b[2782]=11116;b[2781]=11116;b[2784]=11124;b[2783]=11124;b[2786]=11132;b[2785]=11132;b[2788]=11140;b[2787]=11140;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[2719]=u;b[2716]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[2720]=b[2835]}while(0);c=b[2716]|0;if(c>>>0>m>>>0){t=c-m|0;b[2716]=t;v=b[2719]|0;u=v+m|0;b[2719]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;C=w;return v|0}}v=$()|0;b[v>>2]=12;v=0;C=w;return v|0}function ba(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[2717]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[2718]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[2715]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[2713]=b[2713]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=11156+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[2714]=b[2714]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[2719]|0)==(j|0)){j=(b[2716]|0)+c|0;b[2716]=j;b[2719]=i;b[i+4>>2]=j|1;if((i|0)!=(b[2718]|0))return;b[2718]=0;b[2715]=0;return}if((b[2718]|0)==(j|0)){j=(b[2715]|0)+c|0;b[2715]=j;b[2718]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[2713]=b[2713]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=11156+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[2714]=b[2714]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[2718]|0)){b[2715]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=10892+(a<<1<<2)|0;c=b[2713]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=11156+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[2714]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[2721]|0)+-1|0;b[2721]=j;if(j|0)return;a=11308;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[2721]=-1;return}function ca(a,c){a=a|0;c=c|0;var d=0;if(a){d=n(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=aa(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;ga(a|0,0,d|0)|0;return a|0}function da(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){p(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function ea(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){p(b<>>32-c|0);return a<=8192){u(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function ga(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function ha(a){a=a|0;var c=0,d=0,f=0;f=t()|0;d=b[e>>2]|0;c=d+a|0;if((a|0)>0&(c|0)<(d|0)|(c|0)<0){w(c|0)|0;s(12);return -1}if((c|0)>(f|0))if(!(v(c|0)|0)){s(12);return -1}b[e>>2]=c;return d|0} // EMSCRIPTEN_END_FUNCS -return{___uremdi3:ha,_bitshift64Lshr:ia,_bitshift64Shl:ja,_calloc:ca,_emscripten_replace_memory:E,_free:ba,_h3IsValid:T,_kRingDistances:K,_malloc:aa,_maxKringSize:J,_memcpy:ka,_memset:la,_sbrk:ma,_sizeOfH3Index:_,establishStackSpace:I,stackAlloc:F,stackRestore:H,stackSave:G}}) +return{_bitshift64Lshr:da,_bitshift64Shl:ea,_calloc:ca,_emscripten_replace_memory:F,_free:ba,_h3Distance:_,_malloc:aa,_memcpy:fa,_memset:ga,_sbrk:ha,establishStackSpace:J,stackAlloc:G,stackRestore:I,stackSave:H}}) // EMSCRIPTEN_END_ASM -(asmGlobalArg,asmLibraryArg,buffer);var ___uremdi3=Module["___uremdi3"]=asm["___uremdi3"];var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _h3IsValid=Module["_h3IsValid"]=asm["_h3IsValid"];var _kRingDistances=Module["_kRingDistances"]=asm["_kRingDistances"];var _malloc=Module["_malloc"]=asm["_malloc"];var _maxKringSize=Module["_maxKringSize"]=asm["_maxKringSize"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _sizeOfH3Index=Module["_sizeOfH3Index"]=asm["_sizeOfH3Index"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); +(asmGlobalArg,asmLibraryArg,buffer);var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _h3Distance=Module["_h3Distance"]=asm["_h3Distance"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_polyfill/libh3_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_polyfill/libh3_custom.js index 3efc019ba..f598ee229 100644 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_polyfill/libh3_custom.js +++ b/clouds/snowflake/libraries/javascript/src/h3/h3_polyfill/libh3_custom.js @@ -3,18 +3,18 @@ var libh3 = ( function(libh3) { libh3 = libh3 || {}; -var Module=typeof libh3!=="undefined"?libh3:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=21424,DYNAMIC_BASE=5264304,DYNAMICTOP_PTR=21392;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAACAAAAAwAAAAEAAAAFAAAABAAAAAYAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAABAAAABAAAAAMAAAAGAAAABQAAAAIAAAAAAAAAAgAAAAMAAAABAAAABAAAAAYAAAAAAAAABQAAAAMAAAAGAAAABAAAAAUAAAAAAAAAAQAAAAIAAAAEAAAABQAAAAYAAAAAAAAAAgAAAAMAAAABAAAABQAAAAIAAAAAAAAAAQAAAAMAAAAGAAAABAAAAAYAAAAAAAAABQAAAAIAAAABAAAABAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAgAAAAMAAAAAAAAAAAAAAAIAAAAAAAAAAQAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABgAAAAAAAAAFAAAAAAAAAAAAAAAEAAAABQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAABgAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAAAAAACAAAAAwAAAAQAAAAFAAAABgAAAAAAAAABAAAAAwAAAAQAAAAFAAAABgAAAAAAAAABAAAAAgAAAAQAAAAFAAAABgAAAAAAAAABAAAAAgAAAAMAAAAFAAAABgAAAAAAAAABAAAAAgAAAAMAAAAEAAAABgAAAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAgAAAAAAAAAAAAAABgAAAAAAAAADAAAAAgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAUAAAAEAAAAAAAAAAEAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAEAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAUAAAACAAAABAAAAAMAAAAIAAAA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AAAAAAAAAAAAAAAABQAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAUAAAABAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAFAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAQAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAADAAAABQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAUAAAAFAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAADAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAAAP////8DAAAAAAAAAAUAAAACAAAAAAAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAADAAAAAQAAAAAAAAABAAAAAAAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAAAAAD/////AwAAAAAAAAAFAAAAAgAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAAAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAADAAAABQAAAAEAAAAAAAAA/////wMAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAEAAAABQAAAAEAAAAAAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAMAAAABAAAAAAAAAAEAAAAAAAAABQAAAAAAAAAAAAAABQAAAAUAAAAAAAAAAAAAAP////8BAAAAAAAAAAMAAAAEAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAABQAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAQAAAP//////////AQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAIAAAAAAAAAAAAAAAEAAAACAAAABgAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAoAAAACAAAAAAAAAAAAAAABAAAAAQAAAAUAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAIAAAAAAAAAAAAAAAEAAAADAAAABwAAAAYAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAgAAAAAAAAAAAAAAAQAAAAAAAAAJAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAgAAAAAAAAAAAAAAAQAAAAQAAAAIAAAACgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAACAAAAAAAAAAAAAAABAAAACwAAAA8AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAgAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAACAAAAAAAAAAAAAAABAAAADAAAABAAAAAMAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAIAAAAAAAAAAAAAAAEAAAAKAAAAEwAAAAgAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAgAAAAAAAAAAAAAAAQAAAA0AAAARAAAADQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABEAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAIAAAAAAAAAAAAAAAEAAAAOAAAAEgAAAA8AAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABMAAAACAAAAAAAAAAAAAAABAAAA//////////8TAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAASAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABIAAAAAAAAAGAAAAAAAAAAhAAAAAAAAAB4AAAAAAAAAIAAAAAMAAAAxAAAAAQAAADAAAAADAAAAMgAAAAMAAAAIAAAAAAAAAAUAAAAFAAAACgAAAAUAAAAWAAAAAAAAABAAAAAAAAAAEgAAAAAAAAApAAAAAQAAACEAAAAAAAAAHgAAAAAAAAAEAAAAAAAAAAAAAAAFAAAAAgAAAAUAAAAPAAAAAQAAAAgAAAAAAAAABQAAAAUAAAAfAAAAAQAAABYAAAAAAAAAEAAAAAAAAAACAAAAAAAAAAYAAAAAAAAADgAAAAAAAAAKAAAAAAAAAAsAAAAAAAAAEQAAAAMAAAAYAAAAAQAAABcAAAADAAAAGQAAAAMAAAAAAAAAAAAAAAEAAAAFAAAACQAAAAUAAAAFAAAAAAAAAAIAAAAAAAAABgAAAAAAAAASAAAAAQAAAAoAAAAAAAAACwAAAAAAAAAEAAAAAQAAAAMAAAAFAAAABwAAAAUAAAAIAAAAAQAAAAAAAAAAAAAAAQAAAAUAAAAQAAAAAQAAAAUAAAAAAAAAAgAAAAAAAAAHAAAAAAAAABUAAAAAAAAAJgAAAAAAAAAJAAAAAAAAABMAAAAAAAAAIgAAAAMAAAAOAAAAAQAAABQAAAADAAAAJAAAAAMAAAADAAAAAAAAAA0AAAAFAAAAHQAAAAUAAAABAAAAAAAAAAcAAAAAAAAAFQAAAAAAAAAGAAAA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74auECWhw7+cjSACjzniv8CZ+wUhN9I/1uGEKzup6z+/GYr/04bavwmkNHp7xee/F2NMZVAA1z+82s+x2BLivwr2ytbJ9em/KwEH1sMS1r8yp/2LhTfev81i5RexJsy/BlIKPVwR5b95Wyu0/Qjnv5DjoT7YYcs/nBhKZ6zrwr8wRYS7Nebuv3OW6geh+Lu/SLrixebL3j+pcyymN9Xrv8rHIFfWehZAMBwUdlo0DECTUc17EOb2PxpVB1SWChdAzjbhb9pTDUDQhmdvECX5P9FlMKCC9+g/IIAzjELgE0DajDngMv8GQFhWDmDPjNs/y1guLh96EkAxPi8k7DIEQJCc4URlhRhA3eLKKLwkEECqpNAyTBD/P6xpjXcDiwVAFtl//cQm4z+Ibt3XKiYTQM7mCLUb3QdAoM1t8yVv7D8aLZv2Nk8UQEAJPV5nQwxAtSsfTCoE9z9TPjXLXIIWQBVanC5W9AtAYM3d7Adm9j++5mQz1FoWQBUThyaVBghAwH5muQsV7T89Q1qv82MUQJoWGOfNuBdAzrkClkmwDkDQjKq77t37Py+g0dtitsE/ZwAMTwVPEUBojepluNwBQGYbtuW+t9w/HNWIJs6MEkDTNuQUSlgEQKxktPP5TcQ/ixbLB8JjEUCwuWjXMQYCQAS/R09FkRdAowpiZjhhDkB7LmlczD/7P01iQmhhsAVAnrtTwDy84z/Z6jfQ2TgTQChOCXMnWwpAhrW3daoz8z/HYJvVPI4VQLT3ik5FcA5Angi7LOZd+z+NNVzDy5gXQBXdvVTFUA1AYNMgOeYe+T8+qHXGCwkXQKQTOKwa5AJA8gFVoEMW0T+FwzJyttIRQAEAAAD/////BwAAAP////8xAAAA/////1cBAAD/////YQkAAP////+nQQAA/////5HLAQD/////95AMAP/////B9lcAAAAAAAAAAAAAAAAAAgAAAP////8OAAAA/////2IAAAD/////rgIAAP/////CEgAA/////06DAAD/////IpcDAP/////uIRkA/////4LtrwAAAAAAAAAAAAAAAAAAAAAAAgAAAP//////////AQAAAAMAAAD//////////////////////////////////////////////////////////////////////////wEAAAAAAAAAAgAAAP///////////////wMAAAD//////////////////////////////////////////////////////////////////////////wEAAAAAAAAAAgAAAP///////////////wMAAAD//////////////////////////////////////////////////////////////////////////wEAAAAAAAAAAgAAAP///////////////wMAAAD//////////////////////////////////////////////////////////wIAAAD//////////wEAAAAAAAAA/////////////////////wMAAAD/////////////////////////////////////////////////////AwAAAP////////////////////8AAAAA/////////////////////wEAAAD///////////////8CAAAA////////////////////////////////AwAAAP////////////////////8AAAAA////////////////AgAAAAEAAAD/////////////////////////////////////////////////////AwAAAP////////////////////8AAAAA////////////////AgAAAAEAAAD/////////////////////////////////////////////////////AwAAAP////////////////////8AAAAA////////////////AgAAAAEAAAD/////////////////////////////////////////////////////AwAAAP////////////////////8AAAAA////////////////AgAAAAEAAAD/////////////////////////////////////////////////////AQAAAAIAAAD///////////////8AAAAA/////////////////////wMAAAD/////////////////////////////////////////////////////AQAAAAIAAAD///////////////8AAAAA/////////////////////wMAAAD/////////////////////////////////////////////////////AQAAAAIAAAD///////////////8AAAAA/////////////////////wMAAAD/////////////////////////////////////////////////////AQAAAAIAAAD///////////////8AAAAA/////////////////////wMAAAD///////////////////////////////8CAAAA////////////////AQAAAP////////////////////8AAAAA/////////////////////wMAAAD/////////////////////////////////////////////////////AwAAAP////////////////////8AAAAAAQAAAP//////////AgAAAP//////////////////////////////////////////////////////////AwAAAP///////////////wIAAAAAAAAAAQAAAP//////////////////////////////////////////////////////////////////////////AwAAAP///////////////wIAAAAAAAAAAQAAAP//////////////////////////////////////////////////////////////////////////AwAAAP///////////////wIAAAAAAAAAAQAAAP//////////////////////////////////////////////////////////////////////////AwAAAAEAAAD//////////wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAgAAAAAAAAACAAAAAQAAAAEAAAACAAAAAgAAAAAAAAAFAAAABQAAAAAAAAACAAAAAgAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAABAAAAAgAAAAIAAAACAAAAAAAAAAUAAAAGAAAAAAAAAAIAAAACAAAAAwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAAAAAAAgAAAAEAAAADAAAAAgAAAAIAAAAAAAAABQAAAAcAAAAAAAAAAgAAAAIAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAgAAAAAAAAACAAAAAQAAAAQAAAACAAAAAgAAAAAAAAAFAAAACAAAAAAAAAACAAAAAgAAAAMAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAAAAAAAAAIAAAABAAAAAAAAAAIAAAACAAAAAAAAAAUAAAAJAAAAAAAAAAIAAAACAAAAAwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAIAAAACAAAAAAAAAAMAAAAOAAAAAgAAAAAAAAACAAAAAwAAAAAAAAAAAAAAAgAAAAIAAAADAAAABgAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAgAAAAIAAAAAAAAAAwAAAAoAAAACAAAAAAAAAAIAAAADAAAAAQAAAAAAAAACAAAAAgAAAAMAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAACAAAAAgAAAAAAAAADAAAACwAAAAIAAAAAAAAAAgAAAAMAAAACAAAAAAAAAAIAAAACAAAAAwAAAAgAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAIAAAACAAAAAAAAAAMAAAAMAAAAAgAAAAAAAAACAAAAAwAAAAMAAAAAAAAAAgAAAAIAAAADAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAgAAAAIAAAAAAAAAAwAAAA0AAAACAAAAAAAAAAIAAAADAAAABAAAAAAAAAACAAAAAgAAAAMAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAACAAAAAgAAAAAAAAADAAAABgAAAAIAAAAAAAAAAgAAAAMAAAAPAAAAAAAAAAIAAAACAAAAAwAAAAsAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAIAAAACAAAAAAAAAAMAAAAHAAAAAgAAAAAAAAACAAAAAwAAABAAAAAAAAAAAgAAAAIAAAADAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAgAAAAIAAAAAAAAAAwAAAAgAAAACAAAAAAAAAAIAAAADAAAAEQAAAAAAAAACAAAAAgAAAAMAAAANAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAACAAAAAgAAAAAAAAADAAAACQAAAAIAAAAAAAAAAgAAAAMAAAASAAAAAAAAAAIAAAACAAAAAwAAAA4AAAAAAAAAAAAAAAAAAAAAAAAACQAAAAIAAAACAAAAAAAAAAMAAAAFAAAAAgAAAAAAAAACAAAAAwAAABMAAAAAAAAAAgAAAAIAAAADAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAgAAAAAAAAACAAAAAQAAABMAAAACAAAAAgAAAAAAAAAFAAAACgAAAAAAAAACAAAAAgAAAAMAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABEAAAACAAAAAAAAAAIAAAABAAAADwAAAAIAAAACAAAAAAAAAAUAAAALAAAAAAAAAAIAAAACAAAAAwAAABEAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAIAAAAAAAAAAgAAAAEAAAAQAAAAAgAAAAIAAAAAAAAABQAAAAwAAAAAAAAAAgAAAAIAAAADAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAgAAAAAAAAACAAAAAQAAABEAAAACAAAAAgAAAAAAAAAFAAAADQAAAAAAAAACAAAAAgAAAAMAAAATAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAACAAAAAAAAAAIAAAABAAAAEgAAAAIAAAACAAAAAAAAAAUAAAAOAAAAAAAAAAIAAAACAAAAAwAAAAIAAAABAAAAAAAAAAEAAAACAAAAAAAAAAAAAAACAAAAAQAAAAAAAAABAAAAAgAAAAEAAAAAAAAAAgAAAAAAAAAFAAAABAAAAAAAAAABAAAABQAAAAAAAAAAAAAABQAAAAQAAAAAAAAAAQAAAAUAAAAEAAAAAAAAAAUAAAAAAAAAAgAAAAEAAAAAAAAAAQAAAAIAAAAAAAAAAAAAAAIAAAABAAAAAAAAAAEAAAACAAAAAQAAAAAAAAACAAAAAgAAAAAAAAABAAAAAAAAAAAAAAAFAAAABAAAAAAAAAABAAAABQAAAAAAAAAAAAAABQAAAAQAAAAAAAAAAQAAAAUAAAAEAAAAAAAAAAUAAAAFAAAAAAAAAAEAAAAAAAAAAAAAAGJib3hlcyAhPSBOVUxMAGFsZ29zLmMAX3BvbHlmaWxsSW50ZXJuYWwAYWRqYWNlbnRGYWNlRGlyW3RtcEZpamsuZmFjZV1bZmlqay5mYWNlXSA9PSBLSQBmYWNlaWprLmMAX2ZhY2VJamtQZW50VG9HZW9Cb3VuZGFyeQBhZGphY2VudEZhY2VEaXJbY2VudGVySUpLLmZhY2VdW2ZhY2UyXSA9PSBLSQBfZmFjZUlqa1RvR2VvQm91bmRhcnk=";var tempDoublePtr=21408;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=8880,DYNAMIC_BASE=5251760,DYNAMICTOP_PTR=8848;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAD//////////wEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAACAAAAAAAAAAAAAAABAAAAAgAAAAYAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAKAAAAAgAAAAAAAAAAAAAAAQAAAAEAAAAFAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAACAAAAAAAAAAAAAAABAAAAAwAAAAcAAAAGAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADgAAAAIAAAAAAAAAAAAAAAEAAAAAAAAACQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAIAAAAAAAAAAAAAAAEAAAAEAAAACAAAAAoAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAgAAAAAAAAAAAAAAAQAAAAsAAAAPAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAIAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAgAAAAAAAAAAAAAAAQAAAAwAAAAQAAAADAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAACAAAAAAAAAAAAAAABAAAACgAAABMAAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAA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/////wEAAAADAAAA//////////////////////////////////////////////////////////////////////////8BAAAAAAAAAAIAAAD///////////////8DAAAA//////////////////////////////////////////////////////////////////////////8BAAAAAAAAAAIAAAD///////////////8DAAAA//////////////////////////////////////////////////////////////////////////8BAAAAAAAAAAIAAAD///////////////8DAAAA//////////////////////////////////////////////////////////8CAAAA//////////8BAAAAAAAAAP////////////////////8DAAAA/////////////////////////////////////////////////////wMAAAD/////////////////////AAAAAP////////////////////8BAAAA////////////////AgAAAP///////////////////////////////wMAAAD/////////////////////AAAAAP///////////////wIAAAABAAAA/////////////////////////////////////////////////////wMAAAD/////////////////////AAAAAP///////////////wIAAAABAAAA/////////////////////////////////////////////////////wMAAAD/////////////////////AAAAAP///////////////wIAAAABAAAA/////////////////////////////////////////////////////wMAAAD/////////////////////AAAAAP///////////////wIAAAABAAAA/////////////////////////////////////////////////////wEAAAACAAAA////////////////AAAAAP////////////////////8DAAAA/////////////////////////////////////////////////////wEAAAACAAAA////////////////AAAAAP////////////////////8DAAAA/////////////////////////////////////////////////////wEAAAACAAAA////////////////AAAAAP////////////////////8DAAAA/////////////////////////////////////////////////////wEAAAACAAAA////////////////AAAAAP////////////////////8DAAAA////////////////////////////////AgAAAP///////////////wEAAAD/////////////////////AAAAAP////////////////////8DAAAA/////////////////////////////////////////////////////wMAAAD/////////////////////AAAAAAEAAAD//////////wIAAAD//////////////////////////////////////////////////////////wMAAAD///////////////8CAAAAAAAAAAEAAAD//////////////////////////////////////////////////////////////////////////wMAAAD///////////////8CAAAAAAAAAAEAAAD//////////////////////////////////////////////////////////////////////////wMAAAD///////////////8CAAAAAAAAAAEAAAD//////////////////////////////////////////////////////////////////////////wMAAAABAAAA//////////8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAIAAAAAAAAAAgAAAAEAAAABAAAAAgAAAAIAAAAAAAAABQAAAAUAAAAAAAAAAgAAAAIAAAADAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAAAAQAAAAIAAAACAAAAAgAAAAAAAAAFAAAABgAAAAAAAAACAAAAAgAAAAMAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAAAAAAIAAAABAAAAAwAAAAIAAAACAAAAAAAAAAUAAAAHAAAAAAAAAAIAAAACAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAAAgAAAAEAAAAEAAAAAgAAAAIAAAAAAAAABQAAAAgAAAAAAAAAAgAAAAIAAAADAAAABAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAgAAAAAAAAACAAAAAQAAAAAAAAACAAAAAgAAAAAAAAAFAAAACQAAAAAAAAACAAAAAgAAAAMAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAACAAAAAgAAAAAAAAADAAAADgAAAAIAAAAAAAAAAgAAAAMAAAAAAAAAAAAAAAIAAAACAAAAAwAAAAYAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAIAAAACAAAAAAAAAAMAAAAKAAAAAgAAAAAAAAACAAAAAwAAAAEAAAAAAAAAAgAAAAIAAAADAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAgAAAAIAAAAAAAAAAwAAAAsAAAACAAAAAAAAAAIAAAADAAAAAgAAAAAAAAACAAAAAgAAAAMAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAACAAAAAgAAAAAAAAADAAAADAAAAAIAAAAAAAAAAgAAAAMAAAADAAAAAAAAAAIAAAACAAAAAwAAAAkAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAIAAAACAAAAAAAAAAMAAAANAAAAAgAAAAAAAAACAAAAAwAAAAQAAAAAAAAAAgAAAAIAAAADAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAgAAAAIAAAAAAAAAAwAAAAYAAAACAAAAAAAAAAIAAAADAAAADwAAAAAAAAACAAAAAgAAAAMAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAACAAAAAgAAAAAAAAADAAAABwAAAAIAAAAAAAAAAgAAAAMAAAAQAAAAAAAAAAIAAAACAAAAAwAAAAwAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAIAAAACAAAAAAAAAAMAAAAIAAAAAgAAAAAAAAACAAAAAwAAABEAAAAAAAAAAgAAAAIAAAADAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAgAAAAIAAAAAAAAAAwAAAAkAAAACAAAAAAAAAAIAAAADAAAAEgAAAAAAAAACAAAAAgAAAAMAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAACAAAAAgAAAAAAAAADAAAABQAAAAIAAAAAAAAAAgAAAAMAAAATAAAAAAAAAAIAAAACAAAAAwAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAIAAAAAAAAAAgAAAAEAAAATAAAAAgAAAAIAAAAAAAAABQAAAAoAAAAAAAAAAgAAAAIAAAADAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAgAAAAAAAAACAAAAAQAAAA8AAAACAAAAAgAAAAAAAAAFAAAACwAAAAAAAAACAAAAAgAAAAMAAAARAAAAAAAAAAAAAAAAAAAAAAAAABIAAAACAAAAAAAAAAIAAAABAAAAEAAAAAIAAAACAAAAAAAAAAUAAAAMAAAAAAAAAAIAAAACAAAAAwAAABIAAAAAAAAAAAAAAAAAAAAAAAAAEwAAAAIAAAAAAAAAAgAAAAEAAAARAAAAAgAAAAIAAAAAAAAABQAAAA0AAAAAAAAAAgAAAAIAAAADAAAAEwAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAgAAAAAAAAACAAAAAQAAABIAAAACAAAAAgAAAAAAAAAFAAAADgAAAAAAAAACAAAAAgAAAAMAAAACAAAAAQAAAAAAAAABAAAAAgAAAAAAAAAAAAAAAgAAAAEAAAAAAAAAAQAAAAIAAAABAAAAAAAAAAIAAAAAAAAABQAAAAQAAAAAAAAAAQAAAAUAAAAAAAAAAAAAAAUAAAAEAAAAAAAAAAEAAAAFAAAABAAAAAAAAAAFAAAAAAAAAAIAAAABAAAAAAAAAAEAAAACAAAAAAAAAAAAAAACAAAAAQAAAAAAAAABAAAAAgAAAAEAAAAAAAAAAgAAAAIAAAAAAAAAAQAAAAAAAAAAAAAABQAAAAQAAAAAAAAAAQAAAAUAAAAAAAAAAAAAAAUAAAAEAAAAAAAAAAEAAAAFAAAABAAAAAAAAAAFAAAABQAAAAAAAAABAAAAAAAAAAAAAABhZGphY2VudEZhY2VEaXJbdG1wRmlqay5mYWNlXVtmaWprLmZhY2VdID09IEtJAGZhY2VpamsuYwBfZmFjZUlqa1BlbnRUb0dlb0JvdW5kYXJ5AGFkamFjZW50RmFjZURpcltjZW50ZXJJSksuZmFjZV1bZmFjZTJdID09IEtJAF9mYWNlSWprVG9HZW9Cb3VuZGFyeQ==";var tempDoublePtr=8864;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]=a;b[g+4>>2]=c;g=(f|0)!=0;if(g)b[f>>2]=0;if(Sa(a,c)|0){n=1;Q=o;return n|0}b[n>>2]=0;a:do if((d|0)>=1)if(g){k=0;l=1;m=1;h=0;g=a;while(1){if(!(h|k)){g=_(g,c,4,n)|0;c=E()|0;if((g|0)==0&(c|0)==0){g=2;break a}if(Sa(g,c)|0){g=1;break a}}g=_(g,c,b[16+(k<<2)>>2]|0,n)|0;c=E()|0;if((g|0)==0&(c|0)==0){g=2;break a}a=e+(m<<3)|0;b[a>>2]=g;b[a+4>>2]=c;b[f+(m<<2)>>2]=l;h=h+1|0;a=(h|0)==(l|0);i=k+1|0;j=(i|0)==6;if(Sa(g,c)|0){g=1;break a}l=l+(j&a&1)|0;if((l|0)>(d|0)){g=0;break}else{k=a?(j?0:i):k;m=m+1|0;h=a?0:h}}}else{k=0;l=1;m=1;h=0;g=a;while(1){if(!(h|k)){g=_(g,c,4,n)|0;c=E()|0;if((g|0)==0&(c|0)==0){g=2;break a}if(Sa(g,c)|0){g=1;break a}}g=_(g,c,b[16+(k<<2)>>2]|0,n)|0;c=E()|0;if((g|0)==0&(c|0)==0){g=2;break a}a=e+(m<<3)|0;b[a>>2]=g;b[a+4>>2]=c;h=h+1|0;a=(h|0)==(l|0);i=k+1|0;j=(i|0)==6;if(Sa(g,c)|0){g=1;break a}l=l+(j&a&1)|0;if((l|0)>(d|0)){g=0;break}else{k=a?(j?0:i):k;m=m+1|0;h=a?0:h}}}else g=0;while(0);n=g;Q=o;return n|0}function Z(a,c,d,e,f,g,h){a=a|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0;m=Q;Q=Q+16|0;l=m;if((a|0)==0&(c|0)==0){Q=m;return}i=Ab(a|0,c|0,g|0,((g|0)<0)<<31>>31|0)|0;E()|0;j=e+(i<<3)|0;n=j;o=b[n>>2]|0;n=b[n+4>>2]|0;k=(o|0)==(a|0)&(n|0)==(c|0);if(!((o|0)==0&(n|0)==0|k))do{i=(i+1|0)%(g|0)|0;j=e+(i<<3)|0;o=j;n=b[o>>2]|0;o=b[o+4>>2]|0;k=(n|0)==(a|0)&(o|0)==(c|0)}while(!((n|0)==0&(o|0)==0|k));i=f+(i<<2)|0;if(k?(b[i>>2]|0)<=(h|0):0){Q=m;return}o=j;b[o>>2]=a;b[o+4>>2]=c;b[i>>2]=h;if((h|0)>=(d|0)){Q=m;return}o=h+1|0;b[l>>2]=0;n=_(a,c,2,l)|0;Z(n,E()|0,d,e,f,g,o);b[l>>2]=0;n=_(a,c,3,l)|0;Z(n,E()|0,d,e,f,g,o);b[l>>2]=0;n=_(a,c,1,l)|0;Z(n,E()|0,d,e,f,g,o);b[l>>2]=0;n=_(a,c,5,l)|0;Z(n,E()|0,d,e,f,g,o);b[l>>2]=0;n=_(a,c,4,l)|0;Z(n,E()|0,d,e,f,g,o);b[l>>2]=0;n=_(a,c,6,l)|0;Z(n,E()|0,d,e,f,g,o);Q=m;return}function _(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;if((b[e>>2]|0)>0){f=0;do{d=Ba(d)|0;f=f+1|0}while((f|0)<(b[e>>2]|0))}i=Bb(a|0,c|0,45)|0;E()|0;j=i&127;g=Ta(a,c)|0;f=Bb(a|0,c|0,52)|0;E()|0;f=f&15;a:do if(!f)h=6;else while(1){m=(15-f|0)*3|0;n=Bb(a|0,c|0,m|0)|0;E()|0;n=n&7;o=(Ya(f)|0)==0;f=f+-1|0;l=Cb(7,0,m|0)|0;c=c&~(E()|0);m=Cb(b[(o?464:48)+(n*28|0)+(d<<2)>>2]|0,0,m|0)|0;k=E()|0;d=b[(o?672:256)+(n*28|0)+(d<<2)>>2]|0;a=m|a&~l;c=k|c;if(!d){d=0;break a}if(!f){h=6;break}}while(0);if((h|0)==6){o=b[880+(j*28|0)+(d<<2)>>2]|0;n=Cb(o|0,0,45)|0;a=n|a;c=E()|0|c&-1040385;d=b[4304+(j*28|0)+(d<<2)>>2]|0;if((o&127|0)==127){o=Cb(b[880+(j*28|0)+20>>2]|0,0,45)|0;c=E()|0|c&-1040385;d=b[4304+(j*28|0)+20>>2]|0;a=Va(o|a,c)|0;c=E()|0;b[e>>2]=(b[e>>2]|0)+1}}h=Bb(a|0,c|0,45)|0;E()|0;h=h&127;b:do if(!(da(h)|0)){if((d|0)>0){f=0;do{a=Va(a,c)|0;c=E()|0;f=f+1|0}while((f|0)!=(d|0))}}else{c:do if((Ta(a,c)|0)==1){if((j|0)!=(h|0))if(ha(h,b[7728+(j*28|0)>>2]|0)|0){a=Wa(a,c)|0;g=1;c=E()|0;break}else{a=Va(a,c)|0;g=1;c=E()|0;break}switch(g|0){case 5:{a=Wa(a,c)|0;c=E()|0;b[e>>2]=(b[e>>2]|0)+5;g=0;break c}case 3:{a=Va(a,c)|0;c=E()|0;b[e>>2]=(b[e>>2]|0)+1;g=0;break c}default:{n=0;o=0;D(n|0);return o|0}}}else g=0;while(0);if((d|0)>0){f=0;do{a=Ua(a,c)|0;c=E()|0;f=f+1|0}while((f|0)!=(d|0))}if((j|0)!=(h|0)){if(!(ea(h)|0)){if((g|0)!=0|(Ta(a,c)|0)!=5)break;b[e>>2]=(b[e>>2]|0)+1;break}switch(i&127){case 8:case 118:break b;default:{}}if((Ta(a,c)|0)!=3)b[e>>2]=(b[e>>2]|0)+1}}while(0);b[e>>2]=((b[e>>2]|0)+d|0)%6|0;n=c;o=a;D(n|0);return o|0}function $(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0;g=Q;Q=Q+48|0;f=g+8|0;e=g;i=a;h=b[i+4>>2]|0;d=e;b[d>>2]=b[i>>2];b[d+4>>2]=h;eb(e,f);f=ka(f,c)|0;c=b[e>>2]|0;e=b[a+8>>2]|0;if((e|0)<=0){i=c;h=(f|0)<(i|0);i=h?i:f;i=i+12|0;Q=g;return i|0}d=b[a+12>>2]|0;a=0;do{c=(b[d+(a<<3)>>2]|0)+c|0;a=a+1|0}while((a|0)<(e|0));i=(f|0)<(c|0);i=i?c:f;i=i+12|0;Q=g;return i|0}function aa(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;i=Q;Q=Q+48|0;e=i+8|0;f=i;if(!(ba(a,c,d)|0)){Q=i;return}j=a;g=b[j+4>>2]|0;h=f;b[h>>2]=b[j>>2];b[h+4>>2]=g;eb(f,e);h=ka(e,c)|0;c=b[f>>2]|0;g=b[a+8>>2]|0;if((g|0)>0){f=b[a+12>>2]|0;e=0;do{c=(b[f+(e<<3)>>2]|0)+c|0;e=e+1|0}while((e|0)!=(g|0))}c=(h|0)<(c|0)?c:h;if((c|0)<=-12){Q=i;return}j=c+11|0;Fb(d|0,0,(((j|0)>0?j:0)<<3)+8|0)|0;Q=i;return}function ba(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,G=0,H=0,I=0,J=0;J=Q;Q=Q+112|0;D=J+80|0;j=J+72|0;G=J;H=J+56|0;k=a+8|0;I=tb((b[k>>2]<<5)+32|0)|0;if(!I)F(20496,20511,800,20519);fb(a,I);g=a;e=b[g+4>>2]|0;i=j;b[i>>2]=b[g>>2];b[i+4>>2]=e;eb(j,D);i=ka(D,c)|0;e=b[j>>2]|0;g=b[k>>2]|0;if((g|0)>0){h=b[a+12>>2]|0;f=0;do{e=(b[h+(f<<3)>>2]|0)+e|0;f=f+1|0}while((f|0)!=(g|0))}i=(i|0)<(e|0)?e:i;C=i+12|0;f=vb(C,8)|0;l=vb(C,8)|0;b[D>>2]=0;A=a;B=b[A+4>>2]|0;e=j;b[e>>2]=b[A>>2];b[e+4>>2]=B;e=ca(j,C,c,D,f,l)|0;if(e|0){ub(f);ub(l);ub(I);I=e;Q=J;return I|0}a:do if((b[k>>2]|0)>0){g=a+12|0;e=0;while(1){h=ca((b[g>>2]|0)+(e<<3)|0,C,c,D,f,l)|0;e=e+1|0;if(h|0)break;if((e|0)>=(b[k>>2]|0))break a}ub(f);ub(l);ub(I);I=h;Q=J;return I|0}while(0);if((i|0)>-12)Fb(l|0,0,((C|0)>1?C:1)<<3|0)|0;b:do if((b[D>>2]|0)>0){B=((C|0)<0)<<31>>31;v=f;w=l;x=f;y=f;z=l;A=f;e=f;r=f;s=l;t=l;u=l;f=l;c:while(1){q=b[D>>2]|0;o=0;p=0;g=0;while(1){h=G;i=h+56|0;do{b[h>>2]=0;h=h+4|0}while((h|0)<(i|0));c=v+(o<<3)|0;j=b[c>>2]|0;c=b[c+4>>2]|0;if(Y(j,c,1,G,0)|0){h=G;i=h+56|0;do{b[h>>2]=0;h=h+4|0}while((h|0)<(i|0));h=vb(7,4)|0;if(h|0){Z(j,c,1,G,h,7,0);ub(h)}}n=0;do{m=G+(n<<3)|0;l=b[m>>2]|0;m=b[m+4>>2]|0;d:do if(!((l|0)==0&(m|0)==0)){j=Ab(l|0,m|0,C|0,B|0)|0;E()|0;h=d+(j<<3)|0;i=h;c=b[i>>2]|0;i=b[i+4>>2]|0;if(!((c|0)==0&(i|0)==0)){k=0;while(1){if((k|0)>(C|0))break c;if((c|0)==(l|0)&(i|0)==(m|0))break d;j=(j+1|0)%(C|0)|0;h=d+(j<<3)|0;i=h;c=b[i>>2]|0;i=b[i+4>>2]|0;if((c|0)==0&(i|0)==0)break;else k=k+1|0}}if(!((l|0)==0&(m|0)==0)){ab(l,m,H);if(gb(a,I,H)|0){k=h;b[k>>2]=l;b[k+4>>2]=m;k=w+(g<<3)|0;b[k>>2]=l;b[k+4>>2]=m;g=g+1|0}}}while(0);n=n+1|0}while(n>>>0<7);p=p+1|0;if((p|0)>=(q|0))break;else o=o+1|0}if((q|0)>0)Fb(x|0,0,q<<3|0)|0;b[D>>2]=g;if((g|0)>0){l=f;m=u;n=A;o=t;p=s;q=w;f=r;u=e;t=y;s=x;r=l;e=m;A=z;z=n;y=o;x=p;w=v;v=q}else break b}ub(y);ub(z);ub(I);I=-1;Q=J;return I|0}else e=l;while(0);ub(I);ub(f);ub(e);I=0;Q=J;return I|0}function ca(a,c,e,f,g,h){a=a|0;c=c|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,F=0.0;C=Q;Q=Q+48|0;y=C+32|0;z=C+16|0;A=C;i=b[a>>2]|0;if((i|0)<=0){B=0;Q=C;return B|0}t=a+4|0;u=y+8|0;v=z+8|0;w=A+8|0;x=((c|0)<0)<<31>>31;s=0;a:while(1){j=b[t>>2]|0;q=j+(s<<4)|0;b[y>>2]=b[q>>2];b[y+4>>2]=b[q+4>>2];b[y+8>>2]=b[q+8>>2];b[y+12>>2]=b[q+12>>2];if((s|0)==(i+-1|0)){b[z>>2]=b[j>>2];b[z+4>>2]=b[j+4>>2];b[z+8>>2]=b[j+8>>2];b[z+12>>2]=b[j+12>>2]}else{q=j+(s+1<<4)|0;b[z>>2]=b[q>>2];b[z+4>>2]=b[q+4>>2];b[z+8>>2]=b[q+8>>2];b[z+12>>2]=b[q+12>>2]}q=la(y,z,e)|0;b:do if((q|0)>0){r=+(q|0);p=0;c:while(1){F=+(q-p|0);D=+(p|0);d[A>>3]=+d[y>>3]*F/r+ +d[z>>3]*D/r;d[w>>3]=+d[u>>3]*F/r+ +d[v>>3]*D/r;n=Za(A,e)|0;o=E()|0;j=Ab(n|0,o|0,c|0,x|0)|0;E()|0;i=h+(j<<3)|0;k=i;l=b[k>>2]|0;k=b[k+4>>2]|0;d:do if((l|0)==0&(k|0)==0)B=14;else{m=0;while(1){if((m|0)>(c|0)){i=1;break d}if((l|0)==(n|0)&(k|0)==(o|0)){i=7;break d}j=(j+1|0)%(c|0)|0;i=h+(j<<3)|0;k=i;l=b[k>>2]|0;k=b[k+4>>2]|0;if((l|0)==0&(k|0)==0){B=14;break}else m=m+1|0}}while(0);if((B|0)==14){B=0;if((n|0)==0&(o|0)==0)i=7;else{b[i>>2]=n;b[i+4>>2]=o;i=b[f>>2]|0;m=g+(i<<3)|0;b[m>>2]=n;b[m+4>>2]=o;b[f>>2]=i+1;i=0}}switch(i&7){case 7:case 0:break;default:break c}p=p+1|0;if((q|0)<=(p|0)){B=8;break b}}if(i|0){i=-1;B=20;break a}}else B=8;while(0);if((B|0)==8)B=0;s=s+1|0;i=b[a>>2]|0;if((s|0)>=(i|0)){i=0;B=20;break}}if((B|0)==20){Q=C;return i|0}return 0}function da(a){a=a|0;return b[7728+(a*28|0)+16>>2]|0}function ea(a){a=a|0;return (a|0)==4|(a|0)==117|0}function fa(a){a=a|0;return b[11152+((b[a>>2]|0)*216|0)+((b[a+4>>2]|0)*72|0)+((b[a+8>>2]|0)*24|0)+(b[a+12>>2]<<3)>>2]|0}function ga(a){a=a|0;return b[11152+((b[a>>2]|0)*216|0)+((b[a+4>>2]|0)*72|0)+((b[a+8>>2]|0)*24|0)+(b[a+12>>2]<<3)+4>>2]|0}function ha(a,c){a=a|0;c=c|0;if((b[7728+(a*28|0)+20>>2]|0)==(c|0)){c=1;return c|0}c=(b[7728+(a*28|0)+24>>2]|0)==(c|0);return c|0}function ia(a){a=a|0;return +d[a+16>>3]<+d[a+24>>3]|0}function ja(a,b){a=a|0;b=b|0;var c=0.0,e=0.0,f=0.0;c=+d[b>>3];if(!(c>=+d[a+8>>3])){b=0;return b|0}if(!(c<=+d[a>>3])){b=0;return b|0}e=+d[a+16>>3];c=+d[a+24>>3];f=+d[b+8>>3];b=f>=c;a=f<=e&1;if(e>2]=0;h=h+4|0}while((h|0)<(j|0));cb(c,g);h=g;j=b[h>>2]|0;h=b[h+4>>2]|0;ab(j,h,e);bb(j,h,f);k=+Pa(e,f+8|0);d[e>>3]=+d[a>>3];h=e+8|0;d[h>>3]=+d[a+16>>3];d[f>>3]=+d[a+8>>3];j=f+8|0;d[j>>3]=+d[a+24>>3];l=+Pa(e,f);j=~~+y(+(l*l/+Db(+(+p(+((+d[h>>3]-+d[j>>3])/(+d[e>>3]-+d[f>>3])))),3.0)/(k*(k*2.59807621135)*.8)));Q=i;return ((j|0)==0?1:j)|0}function la(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0.0;i=Q;Q=Q+288|0;e=i+264|0;f=i+96|0;g=i;h=g;j=h+96|0;do{b[h>>2]=0;h=h+4|0}while((h|0)<(j|0));cb(d,g);j=g;h=b[j>>2]|0;j=b[j+4>>2]|0;ab(h,j,e);bb(h,j,f);k=+Pa(e,f+8|0);j=~~+y(+(+Pa(a,c)/(k*2.0)));Q=i;return ((j|0)==0?1:j)|0}function ma(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;b[a>>2]=c;b[a+4>>2]=d;b[a+8>>2]=e;return}function na(a,c){a=a|0;c=c|0;var e=0,f=0,g=0,h=0,i=0.0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0.0;n=c+8|0;b[n>>2]=0;k=+d[a>>3];i=+p(+k);l=+d[a+8>>3];j=+p(+l)/.8660254037844386;i=i+j*.5;e=~~i;a=~~j;i=i-+(e|0);j=j-+(a|0);do if(i<.5)if(i<.3333333333333333){b[c>>2]=e;if(j<(i+1.0)*.5){b[c+4>>2]=a;break}else{a=a+1|0;b[c+4>>2]=a;break}}else{o=1.0-i;a=(!(j>2]=a;if(o<=j&j>2]=e;break}else{b[c>>2]=e;break}}else{if(!(i<.6666666666666666)){e=e+1|0;b[c>>2]=e;if(j>2]=a;break}else{a=a+1|0;b[c+4>>2]=a;break}}if(j<1.0-i){b[c+4>>2]=a;if(i*2.0+-1.0>2]=e;break}}else{a=a+1|0;b[c+4>>2]=a}e=e+1|0;b[c>>2]=e}while(0);do if(k<0.0)if(!(a&1)){m=(a|0)/2|0;m=xb(e|0,((e|0)<0)<<31>>31|0,m|0,((m|0)<0)<<31>>31|0)|0;e=~~(+(e|0)-(+(m>>>0)+4294967296.0*+(E()|0))*2.0);b[c>>2]=e;break}else{m=(a+1|0)/2|0;m=xb(e|0,((e|0)<0)<<31>>31|0,m|0,((m|0)<0)<<31>>31|0)|0;e=~~(+(e|0)-((+(m>>>0)+4294967296.0*+(E()|0))*2.0+1.0));b[c>>2]=e;break}while(0);m=c+4|0;if(l<0.0){e=e-((a<<1|1|0)/2|0)|0;b[c>>2]=e;a=0-a|0;b[m>>2]=a}f=a-e|0;if((e|0)<0){g=0-e|0;b[m>>2]=f;b[n>>2]=g;b[c>>2]=0;a=f;e=0}else g=0;if((a|0)<0){e=e-a|0;b[c>>2]=e;g=g-a|0;b[n>>2]=g;b[m>>2]=0;a=0}h=e-g|0;f=a-g|0;if((g|0)<0){b[c>>2]=h;b[m>>2]=f;b[n>>2]=0;a=f;e=h;g=0}f=(a|0)<(e|0)?a:e;f=(g|0)<(f|0)?g:f;if((f|0)<=0)return;b[c>>2]=e-f;b[m>>2]=a-f;b[n>>2]=g-f;return}function oa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;if((c|0)<0){d=d-c|0;b[h>>2]=d;g=a+8|0;b[g>>2]=(b[g>>2]|0)-c;b[a>>2]=0;c=0}if((d|0)<0){c=c-d|0;b[a>>2]=c;g=a+8|0;f=(b[g>>2]|0)-d|0;b[g>>2]=f;b[h>>2]=0;d=0}else{f=a+8|0;g=f;f=b[f>>2]|0}if((f|0)<0){c=c-f|0;b[a>>2]=c;d=d-f|0;b[h>>2]=d;b[g>>2]=0;f=0}e=(d|0)<(c|0)?d:c;e=(f|0)<(e|0)?f:e;if((e|0)<=0)return;b[a>>2]=c-e;b[h>>2]=d-e;b[g>>2]=f-e;return}function pa(a,c){a=a|0;c=c|0;var e=0.0,f=0;f=b[a+8>>2]|0;e=+((b[a+4>>2]|0)-f|0);d[c>>3]=+((b[a>>2]|0)-f|0)-e*.5;d[c+8>>3]=e*.8660254037844386;return}function qa(a,c,d){a=a|0;c=c|0;d=d|0;b[d>>2]=(b[c>>2]|0)+(b[a>>2]|0);b[d+4>>2]=(b[c+4>>2]|0)+(b[a+4>>2]|0);b[d+8>>2]=(b[c+8>>2]|0)+(b[a+8>>2]|0);return}function ra(a,c,d){a=a|0;c=c|0;d=d|0;b[d>>2]=(b[a>>2]|0)-(b[c>>2]|0);b[d+4>>2]=(b[a+4>>2]|0)-(b[c+4>>2]|0);b[d+8>>2]=(b[a+8>>2]|0)-(b[c+8>>2]|0);return}function sa(a,c){a=a|0;c=c|0;var d=0,e=0;d=z(b[a>>2]|0,c)|0;b[a>>2]=d;d=a+4|0;e=z(b[d>>2]|0,c)|0;b[d>>2]=e;a=a+8|0;c=z(b[a>>2]|0,c)|0;b[a>>2]=c;return}function ta(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;h=b[a>>2]|0;i=(h|0)<0;e=(b[a+4>>2]|0)-(i?h:0)|0;g=(e|0)<0;f=(g?0-e|0:0)+((b[a+8>>2]|0)-(i?h:0))|0;d=(f|0)<0;a=d?0:f;c=(g?0:e)-(d?f:0)|0;f=(i?0:h)-(g?e:0)-(d?f:0)|0;d=(c|0)<(f|0)?c:f;d=(a|0)<(d|0)?a:d;e=(d|0)>0;a=a-(e?d:0)|0;c=c-(e?d:0)|0;a:do switch(f-(e?d:0)|0){case 0:switch(c|0){case 0:{i=(a|0)==0?0:(a|0)==1?1:7;return i|0}case 1:{i=(a|0)==0?2:(a|0)==1?3:7;return i|0}default:break a}case 1:switch(c|0){case 0:{i=(a|0)==0?4:(a|0)==1?5:7;return i|0}case 1:{if(!a)a=6;else break a;return a|0}default:break a}default:{}}while(0);i=7;return i|0}function ua(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;h=a+8|0;d=b[h>>2]|0;c=(b[a>>2]|0)-d|0;i=a+4|0;d=(b[i>>2]|0)-d|0;e=sb(+((c*3|0)-d|0)/7.0)|0;b[a>>2]=e;c=sb(+((d<<1)+c|0)/7.0)|0;b[i>>2]=c;b[h>>2]=0;d=c-e|0;if((e|0)<0){g=0-e|0;b[i>>2]=d;b[h>>2]=g;b[a>>2]=0;c=d;e=0;d=g}else d=0;if((c|0)<0){e=e-c|0;b[a>>2]=e;d=d-c|0;b[h>>2]=d;b[i>>2]=0;c=0}g=e-d|0;f=c-d|0;if((d|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;c=f;f=g;d=0}else f=e;e=(c|0)<(f|0)?c:f;e=(d|0)<(e|0)?d:e;if((e|0)<=0)return;b[a>>2]=f-e;b[i>>2]=c-e;b[h>>2]=d-e;return}function va(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;h=a+8|0;d=b[h>>2]|0;c=(b[a>>2]|0)-d|0;i=a+4|0;d=(b[i>>2]|0)-d|0;e=sb(+((c<<1)+d|0)/7.0)|0;b[a>>2]=e;c=sb(+((d*3|0)-c|0)/7.0)|0;b[i>>2]=c;b[h>>2]=0;d=c-e|0;if((e|0)<0){g=0-e|0;b[i>>2]=d;b[h>>2]=g;b[a>>2]=0;c=d;e=0;d=g}else d=0;if((c|0)<0){e=e-c|0;b[a>>2]=e;d=d-c|0;b[h>>2]=d;b[i>>2]=0;c=0}g=e-d|0;f=c-d|0;if((d|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;c=f;f=g;d=0}else f=e;e=(c|0)<(f|0)?c:f;e=(d|0)<(e|0)?d:e;if((e|0)<=0)return;b[a>>2]=f-e;b[i>>2]=c-e;b[h>>2]=d-e;return}function wa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;i=a+8|0;e=b[i>>2]|0;f=d+(c*3|0)|0;b[a>>2]=f;d=e+(d*3|0)|0;b[h>>2]=d;c=(e*3|0)+c|0;b[i>>2]=c;e=d-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=e;b[i>>2]=c;b[a>>2]=0;d=e;e=0}else e=f;if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function xa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=(c*3|0)+f|0;f=d+(f*3|0)|0;b[a>>2]=f;b[h>>2]=e;c=(d*3|0)+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;f=0}else d=e;if((d|0)<0){f=f-d|0;b[a>>2]=f;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=f-c|0;e=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=e;b[i>>2]=0;f=g;c=0}else e=d;d=(e|0)<(f|0)?e:f;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=f-d;b[h>>2]=e-d;b[i>>2]=c-d;return}function ya(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0;if((c+-1|0)>>>0>=6)return;f=(b[15472+(c*12|0)>>2]|0)+(b[a>>2]|0)|0;b[a>>2]=f;i=a+4|0;e=(b[15472+(c*12|0)+4>>2]|0)+(b[i>>2]|0)|0;b[i>>2]=e;h=a+8|0;c=(b[15472+(c*12|0)+8>>2]|0)+(b[h>>2]|0)|0;b[h>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[i>>2]=d;b[h>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[h>>2]=c;b[i>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[i>>2]=f-d;b[h>>2]=c-d;return}function za(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=c+f|0;f=d+f|0;b[a>>2]=f;b[h>>2]=e;c=d+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function Aa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;e=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;f=e+c|0;b[a>>2]=f;e=d+e|0;b[h>>2]=e;c=d+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function Ba(a){a=a|0;switch(a|0){case 1:{a=5;break}case 5:{a=4;break}case 4:{a=6;break}case 6:{a=2;break}case 2:{a=3;break}case 3:{a=1;break}default:{}}return a|0}function Ca(a){a=a|0;switch(a|0){case 1:{a=3;break}case 3:{a=2;break}case 2:{a=6;break}case 6:{a=4;break}case 4:{a=5;break}case 5:{a=1;break}default:{}}return a|0}function Da(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;i=a+8|0;e=b[i>>2]|0;f=d+(c<<1)|0;b[a>>2]=f;d=e+(d<<1)|0;b[h>>2]=d;c=(e<<1)+c|0;b[i>>2]=c;e=d-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=e;b[i>>2]=c;b[a>>2]=0;d=e;e=0}else e=f;if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function Ea(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=(c<<1)+f|0;f=d+(f<<1)|0;b[a>>2]=f;b[h>>2]=e;c=(d<<1)+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;f=0}else d=e;if((d|0)<0){f=f-d|0;b[a>>2]=f;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=f-c|0;e=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=e;b[i>>2]=0;f=g;c=0}else e=d;d=(e|0)<(f|0)?e:f;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=f-d;b[h>>2]=e-d;b[i>>2]=c-d;return}function Fa(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=Q;Q=Q+16|0;e=d;Ga(a,b,c,e);na(e,c+4|0);Q=d;return}function Ga(a,c,e,f){a=a|0;c=c|0;e=e|0;f=f|0;var g=0.0,h=0,i=0.0,j=0.0,k=0;k=Q;Q=Q+32|0;h=k;pb(a,h);b[e>>2]=0;g=+ob(15888,h);i=+ob(15912,h);if(i>2]=1;g=i}i=+ob(15936,h);if(i>2]=2;g=i}i=+ob(15960,h);if(i>2]=3;g=i}i=+ob(15984,h);if(i>2]=4;g=i}i=+ob(16008,h);if(i>2]=5;g=i}i=+ob(16032,h);if(i>2]=6;g=i}i=+ob(16056,h);if(i>2]=7;g=i}i=+ob(16080,h);if(i>2]=8;g=i}i=+ob(16104,h);if(i>2]=9;g=i}i=+ob(16128,h);if(i>2]=10;g=i}i=+ob(16152,h);if(i>2]=11;g=i}i=+ob(16176,h);if(i>2]=12;g=i}i=+ob(16200,h);if(i>2]=13;g=i}i=+ob(16224,h);if(i>2]=14;g=i}i=+ob(16248,h);if(i>2]=15;g=i}i=+ob(16272,h);if(i>2]=16;g=i}i=+ob(16296,h);if(i>2]=17;g=i}i=+ob(16320,h);if(i>2]=18;g=i}i=+ob(16344,h);if(i>2]=19;g=i}i=+u(+(1.0-g*.5));if(i<1.0e-16){b[f>>2]=0;b[f+4>>2]=0;b[f+8>>2]=0;b[f+12>>2]=0;Q=k;return}e=b[e>>2]|0;g=+d[16368+(e*24|0)>>3];g=+Oa(g-+Oa(+Qa(15568+(e<<4)|0,a)));if(!(Ya(c)|0))j=g;else j=+Oa(g+-.3334731722518321);g=+t(+i)/.381966011250105;if((c|0)>0){h=0;do{g=g*2.6457513110645907;h=h+1|0}while((h|0)!=(c|0))}i=+r(+j)*g;d[f>>3]=i;j=+s(+j)*g;d[f+8>>3]=j;Q=k;return}function Ha(a,c,e,f,g){a=a|0;c=c|0;e=e|0;f=f|0;g=g|0;var h=0.0,i=0.0;h=+lb(a);if(h<1.0e-16){c=15568+(c<<4)|0;b[g>>2]=b[c>>2];b[g+4>>2]=b[c+4>>2];b[g+8>>2]=b[c+8>>2];b[g+12>>2]=b[c+12>>2];return}i=+x(+(+d[a+8>>3]),+(+d[a>>3]));if((e|0)>0){a=0;do{h=h/2.6457513110645907;a=a+1|0}while((a|0)!=(e|0))}if(!f){h=+w(+(h*.381966011250105));if(Ya(e)|0)i=+Oa(i+.3334731722518321)}else{h=h/3.0;e=(Ya(e)|0)==0;h=+w(+((e?h:h/2.6457513110645907)*.381966011250105))}Ra(15568+(c<<4)|0,+Oa(+d[16368+(c*24|0)>>3]-i),h,g);return}function Ia(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0;e=Q;Q=Q+16|0;f=e;pa(a+4|0,f);Ha(f,b[a>>2]|0,c,0,d);Q=e;return}function Ja(a,c,e,f,g){a=a|0;c=c|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,G=0,H=0,I=0.0,J=0.0;H=Q;Q=Q+272|0;h=H+256|0;u=H+240|0;D=H;E=H+224|0;G=H+208|0;v=H+176|0;w=H+160|0;x=H+192|0;y=H+144|0;z=H+128|0;A=H+112|0;B=H+96|0;C=H+80|0;b[h>>2]=c;b[u>>2]=b[a>>2];b[u+4>>2]=b[a+4>>2];b[u+8>>2]=b[a+8>>2];b[u+12>>2]=b[a+12>>2];Ka(u,h,D);b[g>>2]=0;u=f+e+((f|0)==5&1)|0;if((u|0)<=(e|0)){Q=H;return}k=b[h>>2]|0;l=E+4|0;m=v+4|0;n=e+5|0;o=16848+(k<<2)|0;p=16928+(k<<2)|0;q=z+8|0;r=A+8|0;s=B+8|0;t=G+4|0;j=e;a:while(1){i=D+(((j|0)%5|0)<<4)|0;b[G>>2]=b[i>>2];b[G+4>>2]=b[i+4>>2];b[G+8>>2]=b[i+8>>2];b[G+12>>2]=b[i+12>>2];do{}while((La(G,k,0,1)|0)==2);if((j|0)>(e|0)&(Ya(c)|0)!=0){b[v>>2]=b[G>>2];b[v+4>>2]=b[G+4>>2];b[v+8>>2]=b[G+8>>2];b[v+12>>2]=b[G+12>>2];pa(l,w);f=b[v>>2]|0;h=b[17008+(f*80|0)+(b[E>>2]<<2)>>2]|0;b[v>>2]=b[18608+(f*80|0)+(h*20|0)>>2];i=b[18608+(f*80|0)+(h*20|0)+16>>2]|0;if((i|0)>0){a=0;do{za(m);a=a+1|0}while((a|0)<(i|0))}i=18608+(f*80|0)+(h*20|0)+4|0;b[x>>2]=b[i>>2];b[x+4>>2]=b[i+4>>2];b[x+8>>2]=b[i+8>>2];sa(x,(b[o>>2]|0)*3|0);qa(m,x,m);oa(m);pa(m,y);I=+(b[p>>2]|0);d[z>>3]=I*3.0;d[q>>3]=0.0;J=I*-1.5;d[A>>3]=J;d[r>>3]=I*2.598076211353316;d[B>>3]=J;d[s>>3]=I*-2.598076211353316;switch(b[17008+((b[v>>2]|0)*80|0)+(b[G>>2]<<2)>>2]|0){case 1:{a=A;f=z;break}case 3:{a=B;f=A;break}case 2:{a=z;f=B;break}default:{a=12;break a}}mb(w,y,f,a,C);Ha(C,b[v>>2]|0,k,1,g+8+(b[g>>2]<<4)|0);b[g>>2]=(b[g>>2]|0)+1}if((j|0)<(n|0)){pa(t,v);Ha(v,b[G>>2]|0,k,1,g+8+(b[g>>2]<<4)|0);b[g>>2]=(b[g>>2]|0)+1};b[E>>2]=b[G>>2];b[E+4>>2]=b[G+4>>2];b[E+8>>2]=b[G+8>>2];b[E+12>>2]=b[G+12>>2];j=j+1|0;if((j|0)>=(u|0)){a=3;break}}if((a|0)==3){Q=H;return}else if((a|0)==12)F(20537,20584,581,20594)}function Ka(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=Q;Q=Q+128|0;e=j+64|0;f=j;g=e;h=20208;i=g+60|0;do{b[g>>2]=b[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));g=f;h=20272;i=g+60|0;do{b[g>>2]=b[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));i=(Ya(b[c>>2]|0)|0)==0;e=i?e:f;f=a+4|0;Da(f);Ea(f);if(Ya(b[c>>2]|0)|0){xa(f);b[c>>2]=(b[c>>2]|0)+1}b[d>>2]=b[a>>2];c=d+4|0;qa(f,e,c);oa(c);b[d+16>>2]=b[a>>2];c=d+20|0;qa(f,e+12|0,c);oa(c);b[d+32>>2]=b[a>>2];c=d+36|0;qa(f,e+24|0,c);oa(c);b[d+48>>2]=b[a>>2];c=d+52|0;qa(f,e+36|0,c);oa(c);b[d+64>>2]=b[a>>2];d=d+68|0;qa(f,e+48|0,d);oa(d);Q=j;return}function La(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;p=Q;Q=Q+32|0;n=p+12|0;i=p;o=a+4|0;m=b[16928+(c<<2)>>2]|0;l=(e|0)!=0;m=l?m*3|0:m;f=b[o>>2]|0;k=a+8|0;h=b[k>>2]|0;if(l){g=a+12|0;e=b[g>>2]|0;f=h+f+e|0;if((f|0)==(m|0)){o=1;Q=p;return o|0}else j=g}else{j=a+12|0;e=b[j>>2]|0;f=h+f+e|0}if((f|0)<=(m|0)){o=0;Q=p;return o|0}do if((e|0)>0){e=b[a>>2]|0;if((h|0)>0){g=18608+(e*80|0)+60|0;e=a;break}e=18608+(e*80|0)+40|0;if(!d){g=e;e=a}else{ma(n,m,0,0);ra(o,n,i);Aa(i);qa(i,n,o);g=e;e=a}}else{g=18608+((b[a>>2]|0)*80|0)+20|0;e=a}while(0);b[e>>2]=b[g>>2];f=g+16|0;if((b[f>>2]|0)>0){e=0;do{za(o);e=e+1|0}while((e|0)<(b[f>>2]|0))}a=g+4|0;b[n>>2]=b[a>>2];b[n+4>>2]=b[a+4>>2];b[n+8>>2]=b[a+8>>2];c=b[16848+(c<<2)>>2]|0;sa(n,l?c*3|0:c);qa(o,n,o);oa(o);if(l)e=((b[k>>2]|0)+(b[o>>2]|0)+(b[j>>2]|0)|0)==(m|0)?1:2;else e=2;o=e;Q=p;return o|0}function Ma(a,c,e,f,g){a=a|0;c=c|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0.0,D=0.0;B=Q;Q=Q+240|0;h=B+224|0;x=B+208|0;y=B;z=B+192|0;A=B+176|0;s=B+160|0;t=B+144|0;u=B+128|0;v=B+112|0;w=B+96|0;b[h>>2]=c;b[x>>2]=b[a>>2];b[x+4>>2]=b[a+4>>2];b[x+8>>2]=b[a+8>>2];b[x+12>>2]=b[a+12>>2];Na(x,h,y);b[g>>2]=0;r=f+e+((f|0)==6&1)|0;if((r|0)<=(e|0)){Q=B;return}k=b[h>>2]|0;l=e+6|0;m=16928+(k<<2)|0;n=t+8|0;o=u+8|0;p=v+8|0;q=z+4|0;i=0;j=e;f=-1;a:while(1){h=(j|0)%6|0;a=y+(h<<4)|0;b[z>>2]=b[a>>2];b[z+4>>2]=b[a+4>>2];b[z+8>>2]=b[a+8>>2];b[z+12>>2]=b[a+12>>2];a=i;i=La(z,k,0,1)|0;if((j|0)>(e|0)&(Ya(c)|0)!=0?((a|0)!=1?(b[z>>2]|0)!=(f|0):0):0){pa(y+(((h+5|0)%6|0)<<4)+4|0,A);pa(y+(h<<4)+4|0,s);C=+(b[m>>2]|0);d[t>>3]=C*3.0;d[n>>3]=0.0;D=C*-1.5;d[u>>3]=D;d[o>>3]=C*2.598076211353316;d[v>>3]=D;d[p>>3]=C*-2.598076211353316;h=b[x>>2]|0;switch(b[17008+(h*80|0)+(((f|0)==(h|0)?b[z>>2]|0:f)<<2)>>2]|0){case 1:{a=u;f=t;break}case 3:{a=v;f=u;break}case 2:{a=t;f=v;break}default:{a=8;break a}}mb(A,s,f,a,w);if(!(nb(A,w)|0)?!(nb(s,w)|0):0){Ha(w,b[x>>2]|0,k,1,g+8+(b[g>>2]<<4)|0);b[g>>2]=(b[g>>2]|0)+1}}if((j|0)<(l|0)){pa(q,A);Ha(A,b[z>>2]|0,k,1,g+8+(b[g>>2]<<4)|0);b[g>>2]=(b[g>>2]|0)+1}j=j+1|0;if((j|0)>=(r|0)){a=3;break}else f=b[z>>2]|0}if((a|0)==3){Q=B;return}else if((a|0)==8)F(20620,20584,746,20665)}function Na(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=Q;Q=Q+160|0;e=j+80|0;f=j;g=e;h=20336;i=g+72|0;do{b[g>>2]=b[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));g=f;h=20416;i=g+72|0;do{b[g>>2]=b[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));i=(Ya(b[c>>2]|0)|0)==0;e=i?e:f;f=a+4|0;Da(f);Ea(f);if(Ya(b[c>>2]|0)|0){xa(f);b[c>>2]=(b[c>>2]|0)+1}b[d>>2]=b[a>>2];c=d+4|0;qa(f,e,c);oa(c);b[d+16>>2]=b[a>>2];c=d+20|0;qa(f,e+12|0,c);oa(c);b[d+32>>2]=b[a>>2];c=d+36|0;qa(f,e+24|0,c);oa(c);b[d+48>>2]=b[a>>2];c=d+52|0;qa(f,e+36|0,c);oa(c);b[d+64>>2]=b[a>>2];c=d+68|0;qa(f,e+48|0,c);oa(c);b[d+80>>2]=b[a>>2];d=d+84|0;qa(f,e+60|0,d);oa(d);Q=j;return}function Oa(a){a=+a;var b=0.0;b=a<0.0?a+6.283185307179586:a;return +(!(a>=6.283185307179586)?b:b+-6.283185307179586)}function Pa(a,b){a=a|0;b=b|0;var c=0.0,e=0.0,f=0.0,g=0.0;f=+d[b>>3];e=+d[a>>3];g=+s(+((f-e)*.5));c=+s(+((+d[b+8>>3]-+d[a+8>>3])*.5));c=g*g+c*(+r(+f)*+r(+e)*c);return +(+x(+(+q(+c)),+(+q(+(1.0-c))))*2.0*6371.007180918475)}function Qa(a,b){a=a|0;b=b|0;var c=0.0,e=0.0,f=0.0,g=0.0,h=0.0;g=+d[b>>3];e=+r(+g);f=+d[b+8>>3]-+d[a+8>>3];h=e*+s(+f);c=+d[a>>3];return +(+x(+h,+(+s(+g)*+r(+c)-+r(+f)*(e*+s(+c)))))}function Ra(a,c,e,f){a=a|0;c=+c;e=+e;f=f|0;var g=0,h=0.0,i=0.0,j=0.0;if(e<1.0e-16){b[f>>2]=b[a>>2];b[f+4>>2]=b[a+4>>2];b[f+8>>2]=b[a+8>>2];b[f+12>>2]=b[a+12>>2];return}h=c<0.0?c+6.283185307179586:c;h=!(c>=6.283185307179586)?h:h+-6.283185307179586;do if(h<1.0e-16){c=+d[a>>3]+e;d[f>>3]=c;g=f}else{g=+p(+(h+-3.141592653589793))<1.0e-16;c=+d[a>>3];if(g){c=c-e;d[f>>3]=c;g=f;break}i=+r(+e);e=+s(+e);c=i*+s(+c)+ +r(+h)*(e*+r(+c));c=c>1.0?1.0:c;c=+v(+(c<-1.0?-1.0:c));d[f>>3]=c;if(+p(+(c+-1.5707963267948966))<1.0e-16){d[f>>3]=1.5707963267948966;d[f+8>>3]=0.0;return}if(+p(+(c+1.5707963267948966))<1.0e-16){d[f>>3]=-1.5707963267948966;d[f+8>>3]=0.0;return}j=+r(+c);h=e*+s(+h)/j;e=+d[a>>3];c=(i-+s(+c)*+s(+e))/+r(+e)/j;i=h>1.0?1.0:h;c=c>1.0?1.0:c;c=+d[a+8>>3]+ +x(+(i<-1.0?-1.0:i),+(c<-1.0?-1.0:c));if(c>3.141592653589793)do c=c+-6.283185307179586;while(c>3.141592653589793);if(c<-3.141592653589793)do c=c+6.283185307179586;while(c<-3.141592653589793);d[f+8>>3]=c;return}while(0);if(+p(+(c+-1.5707963267948966))<1.0e-16){d[g>>3]=1.5707963267948966;d[f+8>>3]=0.0;return}if(+p(+(c+1.5707963267948966))<1.0e-16){d[g>>3]=-1.5707963267948966;d[f+8>>3]=0.0;return}c=+d[a+8>>3];if(c>3.141592653589793)do c=c+-6.283185307179586;while(c>3.141592653589793);if(c<-3.141592653589793)do c=c+6.283185307179586;while(c<-3.141592653589793);d[f+8>>3]=c;return}function Sa(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=Bb(a|0,b|0,45)|0;E()|0;if(!(da(e&127)|0)){e=0;return e|0}e=Bb(a|0,b|0,52)|0;E()|0;e=e&15;a:do if(!e)c=0;else{d=1;while(1){c=Bb(a|0,b|0,(15-d|0)*3|0)|0;E()|0;c=c&7;if(c|0)break a;if(d>>>0>>0)d=d+1|0;else{c=0;break}}}while(0);e=(c|0)==0&1;return e|0}function Ta(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=Bb(a|0,b|0,52)|0;E()|0;e=e&15;if(!e){e=0;return e|0}d=1;while(1){c=Bb(a|0,b|0,(15-d|0)*3|0)|0;E()|0;c=c&7;if(c|0){d=5;break}if(d>>>0>>0)d=d+1|0;else{c=0;d=5;break}}if((d|0)==5)return c|0;return 0}function Ua(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;i=Bb(a|0,b|0,52)|0;E()|0;i=i&15;if(!i){h=b;i=a;D(h|0);return i|0}h=1;c=0;while(1){f=(15-h|0)*3|0;d=Cb(7,0,f|0)|0;e=E()|0;g=Bb(a|0,b|0,f|0)|0;E()|0;f=Cb(Ba(g&7)|0,0,f|0)|0;g=E()|0;a=f|a&~d;b=g|b&~e;a:do if(!c)if(!((f&d|0)==0&(g&e|0)==0)){d=Bb(a|0,b|0,52)|0;E()|0;d=d&15;if(!d)c=1;else{c=1;b:while(1){g=Bb(a|0,b|0,(15-c|0)*3|0)|0;E()|0;switch(g&7){case 1:break b;case 0:break;default:{c=1;break a}}if(c>>>0>>0)c=c+1|0;else{c=1;break a}}c=1;while(1){g=(15-c|0)*3|0;e=Bb(a|0,b|0,g|0)|0;E()|0;f=Cb(7,0,g|0)|0;b=b&~(E()|0);g=Cb(Ba(e&7)|0,0,g|0)|0;a=a&~f|g;b=b|(E()|0);if(c>>>0>>0)c=c+1|0;else{c=1;break}}}}else c=0;while(0);if(h>>>0>>0)h=h+1|0;else break}D(b|0);return a|0}function Va(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;d=Bb(a|0,b|0,52)|0;E()|0;d=d&15;if(!d){c=b;d=a;D(c|0);return d|0}c=1;while(1){f=(15-c|0)*3|0;g=Bb(a|0,b|0,f|0)|0;E()|0;e=Cb(7,0,f|0)|0;b=b&~(E()|0);f=Cb(Ba(g&7)|0,0,f|0)|0;a=f|a&~e;b=E()|0|b;if(c>>>0>>0)c=c+1|0;else break}D(b|0);return a|0}function Wa(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;d=Bb(a|0,b|0,52)|0;E()|0;d=d&15;if(!d){c=b;d=a;D(c|0);return d|0}c=1;while(1){g=(15-c|0)*3|0;f=Cb(7,0,g|0)|0;e=b&~(E()|0);b=Bb(a|0,b|0,g|0)|0;E()|0;b=Cb(Ca(b&7)|0,0,g|0)|0;a=b|a&~f;b=E()|0|e;if(c>>>0>>0)c=c+1|0;else break}D(b|0);return a|0}function Xa(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;j=Q;Q=Q+64|0;i=j+40|0;e=j+24|0;f=j+12|0;g=j;Cb(c|0,0,52)|0;d=E()|0|134225919;if(!c){if((b[a+4>>2]|0)>2){h=0;i=0;D(h|0);Q=j;return i|0}if((b[a+8>>2]|0)>2){h=0;i=0;D(h|0);Q=j;return i|0}if((b[a+12>>2]|0)>2){h=0;i=0;D(h|0);Q=j;return i|0}Cb(fa(a)|0,0,45)|0;h=E()|0|d;i=-1;D(h|0);Q=j;return i|0};b[i>>2]=b[a>>2];b[i+4>>2]=b[a+4>>2];b[i+8>>2]=b[a+8>>2];b[i+12>>2]=b[a+12>>2];h=i+4|0;if((c|0)>0){a=-1;while(1){b[e>>2]=b[h>>2];b[e+4>>2]=b[h+4>>2];b[e+8>>2]=b[h+8>>2];if(!(c&1)){va(h);b[f>>2]=b[h>>2];b[f+4>>2]=b[h+4>>2];b[f+8>>2]=b[h+8>>2];xa(f)}else{ua(h);b[f>>2]=b[h>>2];b[f+4>>2]=b[h+4>>2];b[f+8>>2]=b[h+8>>2];wa(f)}ra(e,f,g);oa(g);l=(15-c|0)*3|0;k=Cb(7,0,l|0)|0;d=d&~(E()|0);l=Cb(ta(g)|0,0,l|0)|0;a=l|a&~k;d=E()|0|d;if((c|0)>1)c=c+-1|0;else break}}else a=-1;a:do if(((b[h>>2]|0)<=2?(b[i+8>>2]|0)<=2:0)?(b[i+12>>2]|0)<=2:0){e=fa(i)|0;c=Cb(e|0,0,45)|0;c=c|a;a=E()|0|d&-1040385;g=ga(i)|0;if(!(da(e)|0)){if((g|0)<=0)break;f=0;while(1){e=Bb(c|0,a|0,52)|0;E()|0;e=e&15;if(e){d=1;while(1){l=(15-d|0)*3|0;i=Bb(c|0,a|0,l|0)|0;E()|0;k=Cb(7,0,l|0)|0;a=a&~(E()|0);l=Cb(Ba(i&7)|0,0,l|0)|0;c=c&~k|l;a=a|(E()|0);if(d>>>0>>0)d=d+1|0;else break}}f=f+1|0;if((f|0)==(g|0))break a}}f=Bb(c|0,a|0,52)|0;E()|0;f=f&15;b:do if(f){d=1;c:while(1){l=Bb(c|0,a|0,(15-d|0)*3|0)|0;E()|0;switch(l&7){case 1:break c;case 0:break;default:break b}if(d>>>0>>0)d=d+1|0;else break b}if(ha(e,b[i>>2]|0)|0){d=1;while(1){i=(15-d|0)*3|0;k=Cb(7,0,i|0)|0;l=a&~(E()|0);a=Bb(c|0,a|0,i|0)|0;E()|0;a=Cb(Ca(a&7)|0,0,i|0)|0;c=c&~k|a;a=l|(E()|0);if(d>>>0>>0)d=d+1|0;else break}}else{d=1;while(1){l=(15-d|0)*3|0;i=Bb(c|0,a|0,l|0)|0;E()|0;k=Cb(7,0,l|0)|0;a=a&~(E()|0);l=Cb(Ba(i&7)|0,0,l|0)|0;c=c&~k|l;a=a|(E()|0);if(d>>>0>>0)d=d+1|0;else break}}}while(0);if((g|0)>0){d=0;do{c=Ua(c,a)|0;a=E()|0;d=d+1|0}while((d|0)!=(g|0))}}else{c=0;a=0}while(0);k=a;l=c;D(k|0);Q=j;return l|0}function Ya(a){a=a|0;return (a|0)%2|0|0}function Za(a,c){a=a|0;c=c|0;var d=0,e=0;e=Q;Q=Q+16|0;d=e;if((c>>>0<=15?!(0==0?(b[a+4>>2]&2146435072|0)==2146435072:0):0)?!(0==0?(b[a+8+4>>2]&2146435072|0)==2146435072:0):0){Fa(a,c,d);c=Xa(d,c)|0;a=E()|0}else{a=0;c=0}D(a|0);Q=e;return c|0}function _a(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;f=d+4|0;g=Bb(a|0,c|0,52)|0;E()|0;g=g&15;h=Bb(a|0,c|0,45)|0;E()|0;e=(g|0)==0;if(!(da(h&127)|0)){if(e){h=0;return h|0}if((b[f>>2]|0)==0?(b[d+8>>2]|0)==0:0)e=(b[d+12>>2]|0)!=0&1;else e=1}else if(e){h=1;return h|0}else e=1;d=1;while(1){if(!(d&1))xa(f);else wa(f);h=Bb(a|0,c|0,(15-d|0)*3|0)|0;E()|0;ya(f,h&7);if(d>>>0>>0)d=d+1|0;else break}return e|0}function $a(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;l=Q;Q=Q+16|0;j=l;k=Bb(a|0,c|0,45)|0;E()|0;k=k&127;a:do if((da(k)|0)!=0?(g=Bb(a|0,c|0,52)|0,E()|0,g=g&15,(g|0)!=0):0){e=1;b:while(1){i=Bb(a|0,c|0,(15-e|0)*3|0)|0;E()|0;switch(i&7){case 5:break b;case 0:break;default:{e=c;break a}}if(e>>>0>>0)e=e+1|0;else{e=c;break a}}f=1;e=c;while(1){c=(15-f|0)*3|0;h=Cb(7,0,c|0)|0;i=e&~(E()|0);e=Bb(a|0,e|0,c|0)|0;E()|0;e=Cb(Ca(e&7)|0,0,c|0)|0;a=a&~h|e;e=i|(E()|0);if(f>>>0>>0)f=f+1|0;else break}}else e=c;while(0);i=7728+(k*28|0)|0;b[d>>2]=b[i>>2];b[d+4>>2]=b[i+4>>2];b[d+8>>2]=b[i+8>>2];b[d+12>>2]=b[i+12>>2];if(!(_a(a,e,d)|0)){Q=l;return}h=d+4|0;b[j>>2]=b[h>>2];b[j+4>>2]=b[h+4>>2];b[j+8>>2]=b[h+8>>2];g=Bb(a|0,e|0,52)|0;E()|0;i=g&15;if(!(g&1))g=i;else{xa(h);g=i+1|0}if(!(da(k)|0))e=0;else{c:do if(!i)e=0;else{c=1;while(1){f=Bb(a|0,e|0,(15-c|0)*3|0)|0;E()|0;f=f&7;if(f|0){e=f;break c}if(c>>>0>>0)c=c+1|0;else{e=0;break}}}while(0);e=(e|0)==4&1}if(!(La(d,g,e,0)|0)){if((g|0)!=(i|0)){b[h>>2]=b[j>>2];b[h+4>>2]=b[j+4>>2];b[h+8>>2]=b[j+8>>2]}}else{if(da(k)|0)do{}while((La(d,g,0,0)|0)!=0);if((g|0)!=(i|0))va(h)}Q=l;return}function ab(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=Q;Q=Q+16|0;e=d;$a(a,b,e);b=Bb(a|0,b|0,52)|0;E()|0;Ia(e,b&15,c);Q=d;return}function bb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0;g=Q;Q=Q+16|0;f=g;$a(a,b,f);d=Bb(a|0,b|0,45)|0;E()|0;d=(da(d&127)|0)==0;e=Bb(a|0,b|0,52)|0;E()|0;e=e&15;a:do if(!d){if(e|0){d=1;while(1){h=Cb(7,0,(15-d|0)*3|0)|0;if(!((h&a|0)==0&((E()|0)&b|0)==0))break a;if(d>>>0>>0)d=d+1|0;else break}}Ja(f,e,0,5,c);Q=g;return}while(0);Ma(f,e,0,6,c);Q=g;return}function cb(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;Cb(a|0,0,52)|0;i=E()|0|134225919;if((a|0)<1){e=0;d=0;do{if(da(e)|0){Cb(e|0,0,45)|0;h=i|(E()|0);a=c+(d<<3)|0;b[a>>2]=-1;b[a+4>>2]=h;d=d+1|0}e=e+1|0}while((e|0)!=122);return}h=0;d=0;do{if(da(h)|0){Cb(h|0,0,45)|0;e=1;f=-1;g=i|(E()|0);while(1){j=Cb(7,0,(15-e|0)*3|0)|0;f=f&~j;g=g&~(E()|0);if((e|0)==(a|0))break;else e=e+1|0}j=c+(d<<3)|0;b[j>>2]=f;b[j+4>>2]=g;d=d+1|0}h=h+1|0}while((h|0)!=122);return}function db(a,c,e){a=a|0;c=c|0;e=e|0;var f=0.0,g=0.0,h=0.0,i=0.0,j=0.0,k=0.0,l=0,m=0,n=0,o=0.0;if(!(ja(c,e)|0)){n=0;return n|0}c=ia(c)|0;o=+d[e>>3];f=+d[e+8>>3];f=c&f<0.0?f+6.283185307179586:f;n=b[a>>2]|0;if((n|0)<=0){n=0;return n|0}m=b[a+4>>2]|0;if(c){c=0;e=-1;a=0;a:while(1){l=a;while(1){i=+d[m+(l<<4)>>3];k=+d[m+(l<<4)+8>>3];a=(e+2|0)%(n|0)|0;h=+d[m+(a<<4)>>3];g=+d[m+(a<<4)+8>>3];if(i>h){j=i;i=k}else{j=h;h=i;i=g;g=k}if(!(oj))break;e=l+1|0;if((e|0)<(n|0)){a=l;l=e;e=a}else{e=22;break a}}k=g<0.0?g+6.283185307179586:g;i=i<0.0?i+6.283185307179586:i;f=i==f|k==f?f+-2.220446049250313e-16:f;k=k+(o-h)/(j-h)*(i-k);if((k<0.0?k+6.283185307179586:k)>f)c=c^1;a=l+1|0;if((a|0)>=(n|0)){e=22;break}else e=l}if((e|0)==22)return c|0}else{c=0;e=-1;a=0;b:while(1){l=a;while(1){i=+d[m+(l<<4)>>3];k=+d[m+(l<<4)+8>>3];a=(e+2|0)%(n|0)|0;h=+d[m+(a<<4)>>3];g=+d[m+(a<<4)+8>>3];if(i>h){j=i;i=k}else{j=h;h=i;i=g;g=k}if(!(oj))break;e=l+1|0;if((e|0)<(n|0)){a=l;l=e;e=a}else{e=22;break b}}f=i==f|g==f?f+-2.220446049250313e-16:f;if(g+(o-h)/(j-h)*(i-g)>f)c=c^1;a=l+1|0;if((a|0)>=(n|0)){e=22;break}else e=l}if((e|0)==22)return c|0}return 0}function eb(a,c){a=a|0;c=c|0;var e=0.0,f=0.0,g=0.0,h=0.0,i=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0,o=0,q=0,r=0,s=0,t=0,u=0,v=0;r=b[a>>2]|0;if(!r){b[c>>2]=0;b[c+4>>2]=0;b[c+8>>2]=0;b[c+12>>2]=0;b[c+16>>2]=0;b[c+20>>2]=0;b[c+24>>2]=0;b[c+28>>2]=0;return}s=c+8|0;d[s>>3]=1797693134862315708145274.0e284;t=c+24|0;d[t>>3]=1797693134862315708145274.0e284;d[c>>3]=-1797693134862315708145274.0e284;u=c+16|0;d[u>>3]=-1797693134862315708145274.0e284;if((r|0)<=0)return;o=b[a+4>>2]|0;l=1797693134862315708145274.0e284;m=-1797693134862315708145274.0e284;n=0;a=-1;h=1797693134862315708145274.0e284;i=1797693134862315708145274.0e284;k=-1797693134862315708145274.0e284;f=-1797693134862315708145274.0e284;q=0;while(1){e=+d[o+(q<<4)>>3];j=+d[o+(q<<4)+8>>3];a=a+2|0;g=+d[o+(((a|0)==(r|0)?0:a)<<4)+8>>3];if(e>3]=e;h=e}if(j>3]=j;i=j}if(e>k)d[c>>3]=e;else e=k;if(j>f){d[u>>3]=j;f=j}l=j>0.0&jm?j:m;n=n|+p(+(j-g))>3.141592653589793;a=q+1|0;if((a|0)==(r|0))break;else{v=q;k=e;q=a;a=v}}if(!n)return;d[u>>3]=m;d[t>>3]=l;return}function fb(a,c){a=a|0;c=c|0;var e=0,f=0,g=0,h=0.0,i=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;r=b[a>>2]|0;if(r){s=c+8|0;d[s>>3]=1797693134862315708145274.0e284;t=c+24|0;d[t>>3]=1797693134862315708145274.0e284;d[c>>3]=-1797693134862315708145274.0e284;u=c+16|0;d[u>>3]=-1797693134862315708145274.0e284;if((r|0)>0){g=b[a+4>>2]|0;o=1797693134862315708145274.0e284;q=-1797693134862315708145274.0e284;f=0;e=-1;k=1797693134862315708145274.0e284;l=1797693134862315708145274.0e284;n=-1797693134862315708145274.0e284;i=-1797693134862315708145274.0e284;v=0;while(1){h=+d[g+(v<<4)>>3];m=+d[g+(v<<4)+8>>3];z=e+2|0;j=+d[g+(((z|0)==(r|0)?0:z)<<4)+8>>3];if(h>3]=h;k=h}if(m>3]=m;l=m}if(h>n)d[c>>3]=h;else h=n;if(m>i){d[u>>3]=m;i=m}o=m>0.0&mq?m:q;f=f|+p(+(m-j))>3.141592653589793;e=v+1|0;if((e|0)==(r|0))break;else{z=v;n=h;v=e;e=z}}if(f){d[u>>3]=q;d[t>>3]=o}}}else{b[c>>2]=0;b[c+4>>2]=0;b[c+8>>2]=0;b[c+12>>2]=0;b[c+16>>2]=0;b[c+20>>2]=0;b[c+24>>2]=0;b[c+28>>2]=0}z=a+8|0;e=b[z>>2]|0;if((e|0)<=0)return;y=a+12|0;x=0;do{g=b[y>>2]|0;f=x;x=x+1|0;t=c+(x<<5)|0;u=b[g+(f<<3)>>2]|0;if(u){v=c+(x<<5)+8|0;d[v>>3]=1797693134862315708145274.0e284;a=c+(x<<5)+24|0;d[a>>3]=1797693134862315708145274.0e284;d[t>>3]=-1797693134862315708145274.0e284;w=c+(x<<5)+16|0;d[w>>3]=-1797693134862315708145274.0e284;if((u|0)>0){r=b[g+(f<<3)+4>>2]|0;o=1797693134862315708145274.0e284;q=-1797693134862315708145274.0e284;g=0;f=-1;s=0;k=1797693134862315708145274.0e284;l=1797693134862315708145274.0e284;m=-1797693134862315708145274.0e284;i=-1797693134862315708145274.0e284;while(1){h=+d[r+(s<<4)>>3];n=+d[r+(s<<4)+8>>3];f=f+2|0;j=+d[r+(((f|0)==(u|0)?0:f)<<4)+8>>3];if(h>3]=h;k=h}if(n>3]=n;l=n}if(h>m)d[t>>3]=h;else h=m;if(n>i){d[w>>3]=n;i=n}o=n>0.0&nq?n:q;g=g|+p(+(n-j))>3.141592653589793;f=s+1|0;if((f|0)==(u|0))break;else{A=s;s=f;m=h;f=A}}if(g){d[w>>3]=q;d[a>>3]=o}}}else{b[t>>2]=0;b[t+4>>2]=0;b[t+8>>2]=0;b[t+12>>2]=0;b[t+16>>2]=0;b[t+20>>2]=0;b[t+24>>2]=0;b[t+28>>2]=0;e=b[z>>2]|0}}while((x|0)<(e|0));return}function gb(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0;if(!(db(a,c,d)|0)){f=0;return f|0}f=a+8|0;if((b[f>>2]|0)<=0){f=1;return f|0}e=a+12|0;a=0;while(1){g=a;a=a+1|0;if(db((b[e>>2]|0)+(g<<3)|0,c+(a<<5)|0,d)|0){a=0;e=6;break}if((a|0)>=(b[f>>2]|0)){a=1;e=6;break}}if((e|0)==6)return a|0;return 0}function hb(){return 8}function ib(){return 16}function jb(){return 8}function kb(){return 16}function lb(a){a=a|0;var b=0.0,c=0.0;c=+d[a>>3];b=+d[a+8>>3];return +(+q(+(c*c+b*b)))}function mb(a,b,c,e,f){a=a|0;b=b|0;c=c|0;e=e|0;f=f|0;var g=0.0,h=0.0,i=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0;k=+d[a>>3];j=+d[b>>3]-k;i=+d[a+8>>3];h=+d[b+8>>3]-i;m=+d[c>>3];g=+d[e>>3]-m;n=+d[c+8>>3];l=+d[e+8>>3]-n;g=(g*(i-n)-(k-m)*l)/(j*l-h*g);d[f>>3]=k+j*g;d[f+8>>3]=i+h*g;return}function nb(a,b){a=a|0;b=b|0;if(!(+d[a>>3]==+d[b>>3])){b=0;return b|0}b=+d[a+8>>3]==+d[b+8>>3];return b|0}function ob(a,b){a=a|0;b=b|0;var c=0.0,e=0.0,f=0.0;f=+d[a>>3]-+d[b>>3];e=+d[a+8>>3]-+d[b+8>>3];c=+d[a+16>>3]-+d[b+16>>3];return +(f*f+e*e+c*c)}function pb(a,b){a=a|0;b=b|0;var c=0.0,e=0.0,f=0.0;c=+d[a>>3];e=+r(+c);c=+s(+c);d[b+16>>3]=c;c=+d[a+8>>3];f=e*+r(+c);d[b>>3]=f;c=e*+s(+c);d[b+8>>3]=c;return}function qb(){return 20688}function rb(a){a=+a;return +(+Gb(+a))}function sb(a){a=+a;return ~~+rb(a)|0}function tb(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=Q;Q=Q+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[5173]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=20732+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[5173]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;Q=w;return v|0}l=b[5175]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=20732+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[5178]|0;c=l>>>3;d=20732+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[5175]=h;b[5178]=f;v=i;Q=w;return v|0}g=b[5174]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[20996+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=20996+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[5174]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[5178]|0;c=l>>>3;d=20732+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[5175]=j;b[5178]=h}v=i+8|0;Q=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[5174]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[20996+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[20996+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[5175]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=20996+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=20732+(c<<1<<2)|0;a=b[5173]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=20996+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;Q=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[5175]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[5178]|0;if(c>>>0>15){v=a+m|0;b[5178]=v;b[5175]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[5175]=0;b[5178]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;Q=w;return v|0}h=b[5176]|0;if(h>>>0>m>>>0){t=h-m|0;b[5176]=t;v=b[5179]|0;u=v+m|0;b[5179]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;Q=w;return v|0}if(!(b[5291]|0)){b[5293]=4096;b[5292]=4096;b[5294]=-1;b[5295]=-1;b[5296]=0;b[5284]=0;b[5291]=n&-16^1431655768;a=4096}else a=b[5293]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;Q=w;return v|0}a=b[5283]|0;if(a|0?(l=b[5281]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;Q=w;return v|0}d:do if(!(b[5284]&4)){d=b[5179]|0;e:do if(d){e=21140;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=Hb(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=Hb(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[5292]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[5281]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[5283]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=Hb(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[5293]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((Hb(a|0)|0)==(-1|0)){Hb(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[5284]=b[5284]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=Hb(k|0)|0,p=Hb(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[5281]|0)+h|0;b[5281]=c;if(c>>>0>(b[5282]|0)>>>0)b[5282]=c;j=b[5179]|0;f:do if(j){c=21140;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[5176]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[5179]=u;b[5176]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[5180]=b[5295];break}if(g>>>0<(b[5177]|0)>>>0)b[5177]=g;d=g+h|0;c=21140;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[5176]|0)+i|0;b[5176]=v;b[5179]=k;b[k+4>>2]=v|1}else{if((b[5178]|0)==(c|0)){v=(b[5175]|0)+i|0;b[5175]=v;b[5178]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[5173]=b[5173]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=20996+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[5174]=b[5174]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=20732+(c<<1<<2)|0;a=b[5173]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=20996+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[5174]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;Q=w;return v|0}c=21140;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[5179]=u;b[5176]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[5180]=b[5295];d=a+4|0;b[d>>2]=27;b[c>>2]=b[5285];b[c+4>>2]=b[5286];b[c+8>>2]=b[5287];b[c+12>>2]=b[5288];b[5285]=g;b[5286]=h;b[5288]=0;b[5287]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=20732+(c<<1<<2)|0;a=b[5173]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=20996+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[5174]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[5177]|0;if((v|0)==0|g>>>0>>0)b[5177]=g;b[5285]=g;b[5286]=h;b[5288]=0;b[5182]=b[5291];b[5181]=-1;b[5186]=20732;b[5185]=20732;b[5188]=20740;b[5187]=20740;b[5190]=20748;b[5189]=20748;b[5192]=20756;b[5191]=20756;b[5194]=20764;b[5193]=20764;b[5196]=20772;b[5195]=20772;b[5198]=20780;b[5197]=20780;b[5200]=20788;b[5199]=20788;b[5202]=20796;b[5201]=20796;b[5204]=20804;b[5203]=20804;b[5206]=20812;b[5205]=20812;b[5208]=20820;b[5207]=20820;b[5210]=20828;b[5209]=20828;b[5212]=20836;b[5211]=20836;b[5214]=20844;b[5213]=20844;b[5216]=20852;b[5215]=20852;b[5218]=20860;b[5217]=20860;b[5220]=20868;b[5219]=20868;b[5222]=20876;b[5221]=20876;b[5224]=20884;b[5223]=20884;b[5226]=20892;b[5225]=20892;b[5228]=20900;b[5227]=20900;b[5230]=20908;b[5229]=20908;b[5232]=20916;b[5231]=20916;b[5234]=20924;b[5233]=20924;b[5236]=20932;b[5235]=20932;b[5238]=20940;b[5237]=20940;b[5240]=20948;b[5239]=20948;b[5242]=20956;b[5241]=20956;b[5244]=20964;b[5243]=20964;b[5246]=20972;b[5245]=20972;b[5248]=20980;b[5247]=20980;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[5179]=u;b[5176]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[5180]=b[5295]}while(0);c=b[5176]|0;if(c>>>0>m>>>0){t=c-m|0;b[5176]=t;v=b[5179]|0;u=v+m|0;b[5179]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;Q=w;return v|0}}v=qb()|0;b[v>>2]=12;v=0;Q=w;return v|0}function ub(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[5177]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[5178]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[5175]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[5173]=b[5173]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=20996+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[5174]=b[5174]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[5179]|0)==(j|0)){j=(b[5176]|0)+c|0;b[5176]=j;b[5179]=i;b[i+4>>2]=j|1;if((i|0)!=(b[5178]|0))return;b[5178]=0;b[5175]=0;return}if((b[5178]|0)==(j|0)){j=(b[5175]|0)+c|0;b[5175]=j;b[5178]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[5173]=b[5173]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=20996+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[5174]=b[5174]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[5178]|0)){b[5175]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=20732+(a<<1<<2)|0;c=b[5173]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=20996+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[5174]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[5181]|0)+-1|0;b[5181]=j;if(j|0)return;a=21148;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[5181]=-1;return}function vb(a,c){a=a|0;c=c|0;var d=0;if(a){d=z(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=tb(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;Fb(a|0,0,d|0)|0;return a|0}function wb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;c=a+c>>>0;return (D(b+d+(c>>>0>>0|0)>>>0|0),c|0)|0}function xb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;d=b-d-(c>>>0>a>>>0|0)>>>0;return (D(d|0),a-c>>>0|0)|0}function yb(a){a=a|0;return (a?31-(B(a^a-1)|0)|0:32)|0}function zb(a,c,d,e,f){a=a|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;l=a;j=c;k=j;h=d;n=e;i=n;if(!k){g=(f|0)!=0;if(!i){if(g){b[f>>2]=(l>>>0)%(h>>>0);b[f+4>>2]=0}n=0;f=(l>>>0)/(h>>>0)>>>0;return (D(n|0),f)|0}else{if(!g){n=0;f=0;return (D(n|0),f)|0}b[f>>2]=a|0;b[f+4>>2]=c&0;n=0;f=0;return (D(n|0),f)|0}}g=(i|0)==0;do if(h){if(!g){g=(B(i|0)|0)-(B(k|0)|0)|0;if(g>>>0<=31){m=g+1|0;i=31-g|0;c=g-31>>31;h=m;a=l>>>(m>>>0)&c|k<>>(m>>>0)&c;g=0;i=l<>2]=a|0;b[f+4>>2]=j|c&0;n=0;f=0;return (D(n|0),f)|0}g=h-1|0;if(g&h|0){i=(B(h|0)|0)+33-(B(k|0)|0)|0;p=64-i|0;m=32-i|0;j=m>>31;o=i-32|0;c=o>>31;h=i;a=m-1>>31&k>>>(o>>>0)|(k<>>(i>>>0))&c;c=c&k>>>(i>>>0);g=l<>>(o>>>0))&j|l<>31;break}if(f|0){b[f>>2]=g&l;b[f+4>>2]=0}if((h|0)==1){o=j|c&0;p=a|0|0;return (D(o|0),p)|0}else{p=yb(h|0)|0;o=k>>>(p>>>0)|0;p=k<<32-p|l>>>(p>>>0)|0;return (D(o|0),p)|0}}else{if(g){if(f|0){b[f>>2]=(k>>>0)%(h>>>0);b[f+4>>2]=0}o=0;p=(k>>>0)/(h>>>0)>>>0;return (D(o|0),p)|0}if(!l){if(f|0){b[f>>2]=0;b[f+4>>2]=(k>>>0)%(i>>>0)}o=0;p=(k>>>0)/(i>>>0)>>>0;return (D(o|0),p)|0}g=i-1|0;if(!(g&i)){if(f|0){b[f>>2]=a|0;b[f+4>>2]=g&k|c&0}o=0;p=k>>>((yb(i|0)|0)>>>0);return (D(o|0),p)|0}g=(B(i|0)|0)-(B(k|0)|0)|0;if(g>>>0<=30){c=g+1|0;i=31-g|0;h=c;a=k<>>(c>>>0);c=k>>>(c>>>0);g=0;i=l<>2]=a|0;b[f+4>>2]=j|c&0;o=0;p=0;return (D(o|0),p)|0}while(0);if(!h){k=i;j=0;i=0}else{m=d|0|0;l=n|e&0;k=wb(m|0,l|0,-1,-1)|0;d=E()|0;j=i;i=0;do{e=j;j=g>>>31|j<<1;g=i|g<<1;e=a<<1|e>>>31|0;n=a>>>31|c<<1|0;xb(k|0,d|0,e|0,n|0)|0;p=E()|0;o=p>>31|((p|0)<0?-1:0)<<1;i=o&1;a=xb(e|0,n|0,o&m|0,(((p|0)<0?-1:0)>>31|((p|0)<0?-1:0)<<1)&l|0)|0;c=E()|0;h=h-1|0}while((h|0)!=0);k=j;j=0}h=0;if(f|0){b[f>>2]=a;b[f+4>>2]=c}o=(g|0)>>>31|(k|h)<<1|(h<<1|g>>>31)&0|j;p=(g<<1|0>>>31)&-2|i;return (D(o|0),p)|0}function Ab(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;g=Q;Q=Q+16|0;f=g|0;zb(a,c,d,e,f)|0;Q=g;return (D(b[f+4>>2]|0),b[f>>2]|0)|0}function Bb(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){D(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function Cb(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){D(b<>>32-c|0);return a<=8192){I(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function Fb(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function Gb(a){a=+a;return a>=0.0?+o(a+.5):+y(a-.5)}function Hb(a){a=a|0;var c=0,d=0,e=0;e=H()|0;d=b[f>>2]|0;c=d+a|0;if((a|0)>0&(c|0)<(d|0)|(c|0)<0){K(c|0)|0;G(12);return -1}if((c|0)>(e|0))if(!(J(c|0)|0)){G(12);return -1}b[f>>2]=c;return d|0} +function Q(a){a=a|0;var b=0;b=M;M=M+a|0;M=M+15&-16;return b|0}function R(){return M|0}function S(a){a=a|0;M=a}function T(a,b){a=a|0;b=b|0;M=a;N=b}function U(a){a=a|0;return b[16+(a*28|0)+16>>2]|0}function V(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;b[a>>2]=c;b[a+4>>2]=d;b[a+8>>2]=e;return}function W(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;if((c|0)<0){d=d-c|0;b[h>>2]=d;g=a+8|0;b[g>>2]=(b[g>>2]|0)-c;b[a>>2]=0;c=0}if((d|0)<0){c=c-d|0;b[a>>2]=c;g=a+8|0;f=(b[g>>2]|0)-d|0;b[g>>2]=f;b[h>>2]=0;d=0}else{f=a+8|0;g=f;f=b[f>>2]|0}if((f|0)<0){c=c-f|0;b[a>>2]=c;d=d-f|0;b[h>>2]=d;b[g>>2]=0;f=0}e=(d|0)<(c|0)?d:c;e=(f|0)<(e|0)?f:e;if((e|0)<=0)return;b[a>>2]=c-e;b[h>>2]=d-e;b[g>>2]=f-e;return}function X(a,c){a=a|0;c=c|0;var e=0.0,f=0;f=b[a+8>>2]|0;e=+((b[a+4>>2]|0)-f|0);d[c>>3]=+((b[a>>2]|0)-f|0)-e*.5;d[c+8>>3]=e*.8660254037844386;return}function Y(a,c,d){a=a|0;c=c|0;d=d|0;b[d>>2]=(b[c>>2]|0)+(b[a>>2]|0);b[d+4>>2]=(b[c+4>>2]|0)+(b[a+4>>2]|0);b[d+8>>2]=(b[c+8>>2]|0)+(b[a+8>>2]|0);return}function Z(a,c,d){a=a|0;c=c|0;d=d|0;b[d>>2]=(b[a>>2]|0)-(b[c>>2]|0);b[d+4>>2]=(b[a+4>>2]|0)-(b[c+4>>2]|0);b[d+8>>2]=(b[a+8>>2]|0)-(b[c+8>>2]|0);return}function _(a,c){a=a|0;c=c|0;var d=0,e=0;d=x(b[a>>2]|0,c)|0;b[a>>2]=d;d=a+4|0;e=x(b[d>>2]|0,c)|0;b[d>>2]=e;a=a+8|0;c=x(b[a>>2]|0,c)|0;b[a>>2]=c;return}function $(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;h=a+8|0;d=b[h>>2]|0;c=(b[a>>2]|0)-d|0;i=a+4|0;d=(b[i>>2]|0)-d|0;e=za(+((c<<1)+d|0)/7.0)|0;b[a>>2]=e;c=za(+((d*3|0)-c|0)/7.0)|0;b[i>>2]=c;b[h>>2]=0;d=c-e|0;if((e|0)<0){g=0-e|0;b[i>>2]=d;b[h>>2]=g;b[a>>2]=0;c=d;e=0;d=g}else d=0;if((c|0)<0){e=e-c|0;b[a>>2]=e;d=d-c|0;b[h>>2]=d;b[i>>2]=0;c=0}g=e-d|0;f=c-d|0;if((d|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;c=f;f=g;d=0}else f=e;e=(c|0)<(f|0)?c:f;e=(d|0)<(e|0)?d:e;if((e|0)<=0)return;b[a>>2]=f-e;b[i>>2]=c-e;b[h>>2]=d-e;return}function aa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;i=a+8|0;e=b[i>>2]|0;f=d+(c*3|0)|0;b[a>>2]=f;d=e+(d*3|0)|0;b[h>>2]=d;c=(e*3|0)+c|0;b[i>>2]=c;e=d-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=e;b[i>>2]=c;b[a>>2]=0;d=e;e=0}else e=f;if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function ba(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=(c*3|0)+f|0;f=d+(f*3|0)|0;b[a>>2]=f;b[h>>2]=e;c=(d*3|0)+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;f=0}else d=e;if((d|0)<0){f=f-d|0;b[a>>2]=f;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=f-c|0;e=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=e;b[i>>2]=0;f=g;c=0}else e=d;d=(e|0)<(f|0)?e:f;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=f-d;b[h>>2]=e-d;b[i>>2]=c-d;return}function ca(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0;if((c+-1|0)>>>0>=6)return;f=(b[3440+(c*12|0)>>2]|0)+(b[a>>2]|0)|0;b[a>>2]=f;i=a+4|0;e=(b[3440+(c*12|0)+4>>2]|0)+(b[i>>2]|0)|0;b[i>>2]=e;h=a+8|0;c=(b[3440+(c*12|0)+8>>2]|0)+(b[h>>2]|0)|0;b[h>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[i>>2]=d;b[h>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[h>>2]=c;b[i>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[i>>2]=f;b[h>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[i>>2]=f-d;b[h>>2]=c-d;return}function da(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=c+f|0;f=d+f|0;b[a>>2]=f;b[h>>2]=e;c=d+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function ea(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;e=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;f=e+c|0;b[a>>2]=f;e=d+e|0;b[h>>2]=e;c=d+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;e=0}else{d=e;e=f}if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function fa(a){a=a|0;switch(a|0){case 1:{a=3;break}case 3:{a=2;break}case 2:{a=6;break}case 6:{a=4;break}case 4:{a=5;break}case 5:{a=1;break}default:{}}return a|0}function ga(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;c=b[a>>2]|0;h=a+4|0;d=b[h>>2]|0;i=a+8|0;e=b[i>>2]|0;f=d+(c<<1)|0;b[a>>2]=f;d=e+(d<<1)|0;b[h>>2]=d;c=(e<<1)+c|0;b[i>>2]=c;e=d-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=e;b[i>>2]=c;b[a>>2]=0;d=e;e=0}else e=f;if((d|0)<0){e=e-d|0;b[a>>2]=e;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=e-c|0;f=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=f;b[i>>2]=0;e=g;c=0}else f=d;d=(f|0)<(e|0)?f:e;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=e-d;b[h>>2]=f-d;b[i>>2]=c-d;return}function ha(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=b[a>>2]|0;h=a+4|0;c=b[h>>2]|0;i=a+8|0;d=b[i>>2]|0;e=(c<<1)+f|0;f=d+(f<<1)|0;b[a>>2]=f;b[h>>2]=e;c=(d<<1)+c|0;b[i>>2]=c;d=e-f|0;if((f|0)<0){c=c-f|0;b[h>>2]=d;b[i>>2]=c;b[a>>2]=0;f=0}else d=e;if((d|0)<0){f=f-d|0;b[a>>2]=f;c=c-d|0;b[i>>2]=c;b[h>>2]=0;d=0}g=f-c|0;e=d-c|0;if((c|0)<0){b[a>>2]=g;b[h>>2]=e;b[i>>2]=0;f=g;c=0}else e=d;d=(e|0)<(f|0)?e:f;d=(c|0)<(d|0)?c:d;if((d|0)<=0)return;b[a>>2]=f-d;b[h>>2]=e-d;b[i>>2]=c-d;return}function ia(a,c,e,f,g){a=a|0;c=c|0;e=e|0;f=f|0;g=g|0;var h=0.0,i=0.0;h=+ua(a);if(h<1.0e-16){c=3536+(c<<4)|0;b[g>>2]=b[c>>2];b[g+4>>2]=b[c+4>>2];b[g+8>>2]=b[c+8>>2];b[g+12>>2]=b[c+12>>2];return}i=+v(+(+d[a+8>>3]),+(+d[a>>3]));if((e|0)>0){a=0;do{h=h/2.6457513110645907;a=a+1|0}while((a|0)!=(e|0))}if(!f){h=+u(+(h*.381966011250105));if(qa(e)|0)i=+oa(i+.3334731722518321)}else{h=h/3.0;e=(qa(e)|0)==0;h=+u(+((e?h:h/2.6457513110645907)*.381966011250105))}pa(3536+(c<<4)|0,+oa(+d[3856+(c*24|0)>>3]-i),h,g);return}function ja(a,c,e,f,g){a=a|0;c=c|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0.0,J=0.0;H=M;M=M+272|0;h=H+256|0;u=H+240|0;E=H;F=H+224|0;G=H+208|0;v=H+176|0;w=H+160|0;x=H+192|0;y=H+144|0;z=H+128|0;A=H+112|0;C=H+96|0;D=H+80|0;b[h>>2]=c;b[u>>2]=b[a>>2];b[u+4>>2]=b[a+4>>2];b[u+8>>2]=b[a+8>>2];b[u+12>>2]=b[a+12>>2];ka(u,h,E);b[g>>2]=0;u=f+e+((f|0)==5&1)|0;if((u|0)<=(e|0)){M=H;return}k=b[h>>2]|0;l=F+4|0;m=v+4|0;n=e+5|0;o=4336+(k<<2)|0;p=4416+(k<<2)|0;q=z+8|0;r=A+8|0;s=C+8|0;t=G+4|0;j=e;a:while(1){i=E+(((j|0)%5|0)<<4)|0;b[G>>2]=b[i>>2];b[G+4>>2]=b[i+4>>2];b[G+8>>2]=b[i+8>>2];b[G+12>>2]=b[i+12>>2];do{}while((la(G,k,0,1)|0)==2);if((j|0)>(e|0)&(qa(c)|0)!=0){b[v>>2]=b[G>>2];b[v+4>>2]=b[G+4>>2];b[v+8>>2]=b[G+8>>2];b[v+12>>2]=b[G+12>>2];X(l,w);f=b[v>>2]|0;h=b[4496+(f*80|0)+(b[F>>2]<<2)>>2]|0;b[v>>2]=b[6096+(f*80|0)+(h*20|0)>>2];i=b[6096+(f*80|0)+(h*20|0)+16>>2]|0;if((i|0)>0){a=0;do{da(m);a=a+1|0}while((a|0)<(i|0))}i=6096+(f*80|0)+(h*20|0)+4|0;b[x>>2]=b[i>>2];b[x+4>>2]=b[i+4>>2];b[x+8>>2]=b[i+8>>2];_(x,(b[o>>2]|0)*3|0);Y(m,x,m);W(m);X(m,y);I=+(b[p>>2]|0);d[z>>3]=I*3.0;d[q>>3]=0.0;J=I*-1.5;d[A>>3]=J;d[r>>3]=I*2.598076211353316;d[C>>3]=J;d[s>>3]=I*-2.598076211353316;switch(b[4496+((b[v>>2]|0)*80|0)+(b[G>>2]<<2)>>2]|0){case 1:{a=A;f=z;break}case 3:{a=C;f=A;break}case 2:{a=z;f=C;break}default:{a=12;break a}}va(w,y,f,a,D);ia(D,b[v>>2]|0,k,1,g+8+(b[g>>2]<<4)|0);b[g>>2]=(b[g>>2]|0)+1}if((j|0)<(n|0)){X(t,v);ia(v,b[G>>2]|0,k,1,g+8+(b[g>>2]<<4)|0);b[g>>2]=(b[g>>2]|0)+1};b[F>>2]=b[G>>2];b[F+4>>2]=b[G+4>>2];b[F+8>>2]=b[G+8>>2];b[F+12>>2]=b[G+12>>2];j=j+1|0;if((j|0)>=(u|0)){a=3;break}}if((a|0)==3){M=H;return}else if((a|0)==12)B(7984,8031,581,8041)}function ka(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=M;M=M+128|0;e=j+64|0;f=j;g=e;h=7696;i=g+60|0;do{b[g>>2]=b[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));g=f;h=7760;i=g+60|0;do{b[g>>2]=b[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));i=(qa(b[c>>2]|0)|0)==0;e=i?e:f;f=a+4|0;ga(f);ha(f);if(qa(b[c>>2]|0)|0){ba(f);b[c>>2]=(b[c>>2]|0)+1}b[d>>2]=b[a>>2];c=d+4|0;Y(f,e,c);W(c);b[d+16>>2]=b[a>>2];c=d+20|0;Y(f,e+12|0,c);W(c);b[d+32>>2]=b[a>>2];c=d+36|0;Y(f,e+24|0,c);W(c);b[d+48>>2]=b[a>>2];c=d+52|0;Y(f,e+36|0,c);W(c);b[d+64>>2]=b[a>>2];d=d+68|0;Y(f,e+48|0,d);W(d);M=j;return}function la(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;p=M;M=M+32|0;n=p+12|0;i=p;o=a+4|0;m=b[4416+(c<<2)>>2]|0;l=(e|0)!=0;m=l?m*3|0:m;f=b[o>>2]|0;k=a+8|0;h=b[k>>2]|0;if(l){g=a+12|0;e=b[g>>2]|0;f=h+f+e|0;if((f|0)==(m|0)){o=1;M=p;return o|0}else j=g}else{j=a+12|0;e=b[j>>2]|0;f=h+f+e|0}if((f|0)<=(m|0)){o=0;M=p;return o|0}do if((e|0)>0){e=b[a>>2]|0;if((h|0)>0){g=6096+(e*80|0)+60|0;e=a;break}e=6096+(e*80|0)+40|0;if(!d){g=e;e=a}else{V(n,m,0,0);Z(o,n,i);ea(i);Y(i,n,o);g=e;e=a}}else{g=6096+((b[a>>2]|0)*80|0)+20|0;e=a}while(0);b[e>>2]=b[g>>2];f=g+16|0;if((b[f>>2]|0)>0){e=0;do{da(o);e=e+1|0}while((e|0)<(b[f>>2]|0))}a=g+4|0;b[n>>2]=b[a>>2];b[n+4>>2]=b[a+4>>2];b[n+8>>2]=b[a+8>>2];c=b[4336+(c<<2)>>2]|0;_(n,l?c*3|0:c);Y(o,n,o);W(o);if(l)e=((b[k>>2]|0)+(b[o>>2]|0)+(b[j>>2]|0)|0)==(m|0)?1:2;else e=2;o=e;M=p;return o|0}function ma(a,c,e,f,g){a=a|0;c=c|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,C=0,D=0.0,E=0.0;C=M;M=M+240|0;h=C+224|0;x=C+208|0;y=C;z=C+192|0;A=C+176|0;s=C+160|0;t=C+144|0;u=C+128|0;v=C+112|0;w=C+96|0;b[h>>2]=c;b[x>>2]=b[a>>2];b[x+4>>2]=b[a+4>>2];b[x+8>>2]=b[a+8>>2];b[x+12>>2]=b[a+12>>2];na(x,h,y);b[g>>2]=0;r=f+e+((f|0)==6&1)|0;if((r|0)<=(e|0)){M=C;return}k=b[h>>2]|0;l=e+6|0;m=4416+(k<<2)|0;n=t+8|0;o=u+8|0;p=v+8|0;q=z+4|0;i=0;j=e;f=-1;a:while(1){h=(j|0)%6|0;a=y+(h<<4)|0;b[z>>2]=b[a>>2];b[z+4>>2]=b[a+4>>2];b[z+8>>2]=b[a+8>>2];b[z+12>>2]=b[a+12>>2];a=i;i=la(z,k,0,1)|0;if((j|0)>(e|0)&(qa(c)|0)!=0?((a|0)!=1?(b[z>>2]|0)!=(f|0):0):0){X(y+(((h+5|0)%6|0)<<4)+4|0,A);X(y+(h<<4)+4|0,s);D=+(b[m>>2]|0);d[t>>3]=D*3.0;d[n>>3]=0.0;E=D*-1.5;d[u>>3]=E;d[o>>3]=D*2.598076211353316;d[v>>3]=E;d[p>>3]=D*-2.598076211353316;h=b[x>>2]|0;switch(b[4496+(h*80|0)+(((f|0)==(h|0)?b[z>>2]|0:f)<<2)>>2]|0){case 1:{a=u;f=t;break}case 3:{a=v;f=u;break}case 2:{a=t;f=v;break}default:{a=8;break a}}va(A,s,f,a,w);if(!(wa(A,w)|0)?!(wa(s,w)|0):0){ia(w,b[x>>2]|0,k,1,g+8+(b[g>>2]<<4)|0);b[g>>2]=(b[g>>2]|0)+1}}if((j|0)<(l|0)){X(q,A);ia(A,b[z>>2]|0,k,1,g+8+(b[g>>2]<<4)|0);b[g>>2]=(b[g>>2]|0)+1}j=j+1|0;if((j|0)>=(r|0)){a=3;break}else f=b[z>>2]|0}if((a|0)==3){M=C;return}else if((a|0)==8)B(8067,8031,746,8112)}function na(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=M;M=M+160|0;e=j+80|0;f=j;g=e;h=7824;i=g+72|0;do{b[g>>2]=b[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));g=f;h=7904;i=g+72|0;do{b[g>>2]=b[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));i=(qa(b[c>>2]|0)|0)==0;e=i?e:f;f=a+4|0;ga(f);ha(f);if(qa(b[c>>2]|0)|0){ba(f);b[c>>2]=(b[c>>2]|0)+1}b[d>>2]=b[a>>2];c=d+4|0;Y(f,e,c);W(c);b[d+16>>2]=b[a>>2];c=d+20|0;Y(f,e+12|0,c);W(c);b[d+32>>2]=b[a>>2];c=d+36|0;Y(f,e+24|0,c);W(c);b[d+48>>2]=b[a>>2];c=d+52|0;Y(f,e+36|0,c);W(c);b[d+64>>2]=b[a>>2];c=d+68|0;Y(f,e+48|0,c);W(c);b[d+80>>2]=b[a>>2];d=d+84|0;Y(f,e+60|0,d);W(d);M=j;return}function oa(a){a=+a;var b=0.0;b=a<0.0?a+6.283185307179586:a;return +(!(a>=6.283185307179586)?b:b+-6.283185307179586)}function pa(a,c,e,f){a=a|0;c=+c;e=+e;f=f|0;var g=0,h=0.0,i=0.0,j=0.0;if(e<1.0e-16){b[f>>2]=b[a>>2];b[f+4>>2]=b[a+4>>2];b[f+8>>2]=b[a+8>>2];b[f+12>>2]=b[a+12>>2];return}h=c<0.0?c+6.283185307179586:c;h=!(c>=6.283185307179586)?h:h+-6.283185307179586;do if(h<1.0e-16){c=+d[a>>3]+e;d[f>>3]=c;g=f}else{g=+p(+(h+-3.141592653589793))<1.0e-16;c=+d[a>>3];if(g){c=c-e;d[f>>3]=c;g=f;break}i=+r(+e);e=+s(+e);c=i*+s(+c)+ +r(+h)*(e*+r(+c));c=c>1.0?1.0:c;c=+t(+(c<-1.0?-1.0:c));d[f>>3]=c;if(+p(+(c+-1.5707963267948966))<1.0e-16){d[f>>3]=1.5707963267948966;d[f+8>>3]=0.0;return}if(+p(+(c+1.5707963267948966))<1.0e-16){d[f>>3]=-1.5707963267948966;d[f+8>>3]=0.0;return}j=+r(+c);h=e*+s(+h)/j;e=+d[a>>3];c=(i-+s(+c)*+s(+e))/+r(+e)/j;i=h>1.0?1.0:h;c=c>1.0?1.0:c;c=+d[a+8>>3]+ +v(+(i<-1.0?-1.0:i),+(c<-1.0?-1.0:c));if(c>3.141592653589793)do c=c+-6.283185307179586;while(c>3.141592653589793);if(c<-3.141592653589793)do c=c+6.283185307179586;while(c<-3.141592653589793);d[f+8>>3]=c;return}while(0);if(+p(+(c+-1.5707963267948966))<1.0e-16){d[g>>3]=1.5707963267948966;d[f+8>>3]=0.0;return}if(+p(+(c+1.5707963267948966))<1.0e-16){d[g>>3]=-1.5707963267948966;d[f+8>>3]=0.0;return}c=+d[a+8>>3];if(c>3.141592653589793)do c=c+-6.283185307179586;while(c>3.141592653589793);if(c<-3.141592653589793)do c=c+6.283185307179586;while(c<-3.141592653589793);d[f+8>>3]=c;return}function qa(a){a=a|0;return (a|0)%2|0|0}function ra(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;f=d+4|0;g=Da(a|0,c|0,52)|0;A()|0;g=g&15;h=Da(a|0,c|0,45)|0;A()|0;e=(g|0)==0;if(!(U(h&127)|0)){if(e){h=0;return h|0}if((b[f>>2]|0)==0?(b[d+8>>2]|0)==0:0)e=(b[d+12>>2]|0)!=0&1;else e=1}else if(e){h=1;return h|0}else e=1;d=1;while(1){if(!(d&1))ba(f);else aa(f);h=Da(a|0,c|0,(15-d|0)*3|0)|0;A()|0;ca(f,h&7);if(d>>>0>>0)d=d+1|0;else break}return e|0}function sa(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;l=M;M=M+16|0;j=l;k=Da(a|0,c|0,45)|0;A()|0;k=k&127;a:do if((U(k)|0)!=0?(g=Da(a|0,c|0,52)|0,A()|0,g=g&15,(g|0)!=0):0){e=1;b:while(1){i=Da(a|0,c|0,(15-e|0)*3|0)|0;A()|0;switch(i&7){case 5:break b;case 0:break;default:{e=c;break a}}if(e>>>0>>0)e=e+1|0;else{e=c;break a}}f=1;e=c;while(1){c=(15-f|0)*3|0;h=Ea(7,0,c|0)|0;i=e&~(A()|0);e=Da(a|0,e|0,c|0)|0;A()|0;e=Ea(fa(e&7)|0,0,c|0)|0;a=a&~h|e;e=i|(A()|0);if(f>>>0>>0)f=f+1|0;else break}}else e=c;while(0);i=16+(k*28|0)|0;b[d>>2]=b[i>>2];b[d+4>>2]=b[i+4>>2];b[d+8>>2]=b[i+8>>2];b[d+12>>2]=b[i+12>>2];if(!(ra(a,e,d)|0)){M=l;return}h=d+4|0;b[j>>2]=b[h>>2];b[j+4>>2]=b[h+4>>2];b[j+8>>2]=b[h+8>>2];g=Da(a|0,e|0,52)|0;A()|0;i=g&15;if(!(g&1))g=i;else{ba(h);g=i+1|0}if(!(U(k)|0))e=0;else{c:do if(!i)e=0;else{c=1;while(1){f=Da(a|0,e|0,(15-c|0)*3|0)|0;A()|0;f=f&7;if(f|0){e=f;break c}if(c>>>0>>0)c=c+1|0;else{e=0;break}}}while(0);e=(e|0)==4&1}if(!(la(d,g,e,0)|0)){if((g|0)!=(i|0)){b[h>>2]=b[j>>2];b[h+4>>2]=b[j+4>>2];b[h+8>>2]=b[j+8>>2]}}else{if(U(k)|0)do{}while((la(d,g,0,0)|0)!=0);if((g|0)!=(i|0))$(h)}M=l;return}function ta(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0;g=M;M=M+16|0;f=g;sa(a,b,f);d=Da(a|0,b|0,45)|0;A()|0;d=(U(d&127)|0)==0;e=Da(a|0,b|0,52)|0;A()|0;e=e&15;a:do if(!d){if(e|0){d=1;while(1){h=Ea(7,0,(15-d|0)*3|0)|0;if(!((h&a|0)==0&((A()|0)&b|0)==0))break a;if(d>>>0>>0)d=d+1|0;else break}}ja(f,e,0,5,c);M=g;return}while(0);ma(f,e,0,6,c);M=g;return}function ua(a){a=a|0;var b=0.0,c=0.0;c=+d[a>>3];b=+d[a+8>>3];return +(+q(+(c*c+b*b)))}function va(a,b,c,e,f){a=a|0;b=b|0;c=c|0;e=e|0;f=f|0;var g=0.0,h=0.0,i=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0;k=+d[a>>3];j=+d[b>>3]-k;i=+d[a+8>>3];h=+d[b+8>>3]-i;m=+d[c>>3];g=+d[e>>3]-m;n=+d[c+8>>3];l=+d[e+8>>3]-n;g=(g*(i-n)-(k-m)*l)/(j*l-h*g);d[f>>3]=k+j*g;d[f+8>>3]=i+h*g;return}function wa(a,b){a=a|0;b=b|0;if(!(+d[a>>3]==+d[b>>3])){b=0;return b|0}b=+d[a+8>>3]==+d[b+8>>3];return b|0}function xa(){return 8144}function ya(a){a=+a;return +(+Ha(+a))}function za(a){a=+a;return ~~+ya(a)|0}function Aa(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=M;M=M+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[2037]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=8188+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[2037]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;M=w;return v|0}l=b[2039]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=8188+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[2042]|0;c=l>>>3;d=8188+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2039]=h;b[2042]=f;v=i;M=w;return v|0}g=b[2038]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[8452+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=8452+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[2038]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[2042]|0;c=l>>>3;d=8188+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[2039]=j;b[2042]=h}v=i+8|0;M=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[2038]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[8452+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[8452+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[2039]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=8452+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=8188+(c<<1<<2)|0;a=b[2037]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=8452+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;M=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[2039]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[2042]|0;if(c>>>0>15){v=a+m|0;b[2042]=v;b[2039]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[2039]=0;b[2042]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;M=w;return v|0}h=b[2040]|0;if(h>>>0>m>>>0){t=h-m|0;b[2040]=t;v=b[2043]|0;u=v+m|0;b[2043]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;M=w;return v|0}if(!(b[2155]|0)){b[2157]=4096;b[2156]=4096;b[2158]=-1;b[2159]=-1;b[2160]=0;b[2148]=0;b[2155]=n&-16^1431655768;a=4096}else a=b[2157]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;M=w;return v|0}a=b[2147]|0;if(a|0?(l=b[2145]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;M=w;return v|0}d:do if(!(b[2148]&4)){d=b[2043]|0;e:do if(d){e=8596;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=Ia(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=Ia(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[2156]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[2145]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[2147]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=Ia(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[2157]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((Ia(a|0)|0)==(-1|0)){Ia(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[2148]=b[2148]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=Ia(k|0)|0,p=Ia(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[2145]|0)+h|0;b[2145]=c;if(c>>>0>(b[2146]|0)>>>0)b[2146]=c;j=b[2043]|0;f:do if(j){c=8596;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[2040]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[2043]=u;b[2040]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[2044]=b[2159];break}if(g>>>0<(b[2041]|0)>>>0)b[2041]=g;d=g+h|0;c=8596;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[2040]|0)+i|0;b[2040]=v;b[2043]=k;b[k+4>>2]=v|1}else{if((b[2042]|0)==(c|0)){v=(b[2039]|0)+i|0;b[2039]=v;b[2042]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[2037]=b[2037]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=8452+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[2038]=b[2038]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=8188+(c<<1<<2)|0;a=b[2037]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=8452+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[2038]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;M=w;return v|0}c=8596;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[2043]=u;b[2040]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[2044]=b[2159];d=a+4|0;b[d>>2]=27;b[c>>2]=b[2149];b[c+4>>2]=b[2150];b[c+8>>2]=b[2151];b[c+12>>2]=b[2152];b[2149]=g;b[2150]=h;b[2152]=0;b[2151]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=8188+(c<<1<<2)|0;a=b[2037]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=8452+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[2038]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[2041]|0;if((v|0)==0|g>>>0>>0)b[2041]=g;b[2149]=g;b[2150]=h;b[2152]=0;b[2046]=b[2155];b[2045]=-1;b[2050]=8188;b[2049]=8188;b[2052]=8196;b[2051]=8196;b[2054]=8204;b[2053]=8204;b[2056]=8212;b[2055]=8212;b[2058]=8220;b[2057]=8220;b[2060]=8228;b[2059]=8228;b[2062]=8236;b[2061]=8236;b[2064]=8244;b[2063]=8244;b[2066]=8252;b[2065]=8252;b[2068]=8260;b[2067]=8260;b[2070]=8268;b[2069]=8268;b[2072]=8276;b[2071]=8276;b[2074]=8284;b[2073]=8284;b[2076]=8292;b[2075]=8292;b[2078]=8300;b[2077]=8300;b[2080]=8308;b[2079]=8308;b[2082]=8316;b[2081]=8316;b[2084]=8324;b[2083]=8324;b[2086]=8332;b[2085]=8332;b[2088]=8340;b[2087]=8340;b[2090]=8348;b[2089]=8348;b[2092]=8356;b[2091]=8356;b[2094]=8364;b[2093]=8364;b[2096]=8372;b[2095]=8372;b[2098]=8380;b[2097]=8380;b[2100]=8388;b[2099]=8388;b[2102]=8396;b[2101]=8396;b[2104]=8404;b[2103]=8404;b[2106]=8412;b[2105]=8412;b[2108]=8420;b[2107]=8420;b[2110]=8428;b[2109]=8428;b[2112]=8436;b[2111]=8436;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[2043]=u;b[2040]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[2044]=b[2159]}while(0);c=b[2040]|0;if(c>>>0>m>>>0){t=c-m|0;b[2040]=t;v=b[2043]|0;u=v+m|0;b[2043]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;M=w;return v|0}}v=xa()|0;b[v>>2]=12;v=0;M=w;return v|0}function Ba(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[2041]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[2042]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[2039]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[2037]=b[2037]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=8452+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[2038]=b[2038]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[2043]|0)==(j|0)){j=(b[2040]|0)+c|0;b[2040]=j;b[2043]=i;b[i+4>>2]=j|1;if((i|0)!=(b[2042]|0))return;b[2042]=0;b[2039]=0;return}if((b[2042]|0)==(j|0)){j=(b[2039]|0)+c|0;b[2039]=j;b[2042]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[2037]=b[2037]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=8452+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[2038]=b[2038]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[2042]|0)){b[2039]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=8188+(a<<1<<2)|0;c=b[2037]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=8452+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[2038]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[2045]|0)+-1|0;b[2045]=j;if(j|0)return;a=8604;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[2045]=-1;return}function Ca(a,c){a=a|0;c=c|0;var d=0;if(a){d=x(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=Aa(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;Ga(a|0,0,d|0)|0;return a|0}function Da(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){z(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function Ea(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){z(b<>>32-c|0);return a<=8192){E(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function Ga(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function Ha(a){a=+a;return a>=0.0?+o(a+.5):+w(a-.5)}function Ia(a){a=a|0;var c=0,d=0,e=0;e=D()|0;d=b[f>>2]|0;c=d+a|0;if((a|0)>0&(c|0)<(d|0)|(c|0)<0){G(c|0)|0;C(12);return -1}if((c|0)>(e|0))if(!(F(c|0)|0)){C(12);return -1}b[f>>2]=c;return d|0} // EMSCRIPTEN_END_FUNCS -return{___uremdi3:Ab,_bitshift64Lshr:Bb,_bitshift64Shl:Cb,_calloc:vb,_emscripten_replace_memory:T,_free:ub,_i64Subtract:xb,_llvm_minnum_f64:Db,_malloc:tb,_maxPolyfillSize:$,_memcpy:Eb,_memset:Fb,_polyfill:aa,_round:Gb,_sbrk:Hb,_sizeOfGeoCoord:ib,_sizeOfGeoPolygon:kb,_sizeOfGeofence:jb,_sizeOfH3Index:hb,establishStackSpace:X,stackAlloc:U,stackRestore:W,stackSave:V}}) +return{_bitshift64Lshr:Da,_bitshift64Shl:Ea,_calloc:Ca,_emscripten_replace_memory:P,_free:Ba,_h3ToGeoBoundary:ta,_malloc:Aa,_memcpy:Fa,_memset:Ga,_round:Ha,_sbrk:Ia,establishStackSpace:T,stackAlloc:Q,stackRestore:S,stackSave:R}}) // EMSCRIPTEN_END_ASM -(asmGlobalArg,asmLibraryArg,buffer);var ___uremdi3=Module["___uremdi3"]=asm["___uremdi3"];var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _llvm_minnum_f64=Module["_llvm_minnum_f64"]=asm["_llvm_minnum_f64"];var _malloc=Module["_malloc"]=asm["_malloc"];var _maxPolyfillSize=Module["_maxPolyfillSize"]=asm["_maxPolyfillSize"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _polyfill=Module["_polyfill"]=asm["_polyfill"];var _round=Module["_round"]=asm["_round"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _sizeOfGeoCoord=Module["_sizeOfGeoCoord"]=asm["_sizeOfGeoCoord"];var _sizeOfGeoPolygon=Module["_sizeOfGeoPolygon"]=asm["_sizeOfGeoPolygon"];var _sizeOfGeofence=Module["_sizeOfGeofence"]=asm["_sizeOfGeofence"];var _sizeOfH3Index=Module["_sizeOfH3Index"]=asm["_sizeOfH3Index"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); +(asmGlobalArg,asmLibraryArg,buffer);var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _h3ToGeoBoundary=Module["_h3ToGeoBoundary"]=asm["_h3ToGeoBoundary"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _round=Module["_round"]=asm["_round"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_tochildren/h3core_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_tochildren/h3core_custom.js deleted file mode 100644 index 54d5c4b75..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_tochildren/h3core_custom.js +++ /dev/null @@ -1,1352 +0,0 @@ -/* - * Copyright 2018-2019 Uber Technologies, Inc. - * Copyright 2021 CARTO - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @module h3 - */ - -import C from './libh3_custom'; -import BINDINGS from 'h3-js/lib/bindings'; - -const H3 = {}; - -// Create the bound functions themselves -BINDINGS.forEach(function bind (def) { - // Bind only exported functions - if (C['_' + def[0]]) { - H3[def[0]] = C.cwrap(...def); - } -}); - -// Alias the hexidecimal base for legibility -const BASE_16 = 16; - -// ---------------------------------------------------------------------------- -// Byte size imports - -const SZ_INT = 4; -const SZ_PTR = 4; -const SZ_DBL = 8; -const SZ_H3INDEX = H3.sizeOfH3Index && H3.sizeOfH3Index(); -const SZ_GEOCOORD = H3.sizeOfGeoCoord && H3.sizeOfGeoCoord(); -const SZ_GEOBOUNDARY = H3.sizeOfGeoBoundary && H3.sizeOfGeoBoundary(); -const SZ_GEOPOLYGON = H3.sizeOfGeoPolygon && H3.sizeOfGeoPolygon(); -const SZ_GEOFENCE = H3.sizeOfGeofence && H3.sizeOfGeofence(); -const SZ_LINKED_GEOPOLYGON = H3.sizeOfLinkedGeoPolygon && H3.sizeOfLinkedGeoPolygon(); -const SZ_COORDIJ = H3.sizeOfCoordIJ && H3.sizeOfCoordIJ(); - -// ---------------------------------------------------------------------------- -// Custom types - -/** - * 64-bit hexidecimal string representation of an H3 index - * @static - * @typedef {string} H3Index - */ - -/** - * 64-bit hexidecimal string representation of an H3 index, - * or two 32-bit integers in little endian order in an array. - * @static - * @typedef {string | number[]} H3IndexInput - */ - -/** - * Coordinates as an `{i, j}` pair - * @static - * @typedef CoordIJ - * @type {Object} - * @property {number} i - * @property {number} j - */ - -// ---------------------------------------------------------------------------- -// Unit constants - -/** - * Length/Area units - * @static - * @typedef UNITS - * @type {Object} - * @property {string} m - * @property {string} m2 - * @property {string} km - * @property {string} km2 - * @property {string} rads - * @property {string} rads2 - */ -export const UNITS = { - m: 'm', - m2: 'm2', - km: 'km', - km2: 'km2', - rads: 'rads', - rads2: 'rads2' -}; - -// ---------------------------------------------------------------------------- -// Utilities and helpers - -/** - * Validate a resolution, throwing an error if invalid - * @private - * @param {mixed} res Value to validate - * @throws {Error} Error if invalid - */ -function validateRes (res) { - if (typeof res !== 'number' || res < 0 || res > 15 || Math.floor(res) !== res) { - throw new Error(`Invalid resolution: ${res}`); - } -} - -const INVALID_HEXIDECIMAL_CHAR = /[^0-9a-fA-F]/; - -/** - * Convert an H3 index (64-bit hexidecimal string) into a "split long" - a pair of 32-bit ints - * @private - * @param {H3IndexInput} h3Index H3 index to check - * @return {number[]} A two-element array with 32 lower bits and 32 upper bits - */ -export function h3IndexToSplitLong (h3Index) { - if ( - Array.isArray(h3Index) && - h3Index.length === 2 && - Number.isInteger(h3Index[0]) && - Number.isInteger(h3Index[1]) - ) { - return h3Index; - } - if (typeof h3Index !== 'string' || INVALID_HEXIDECIMAL_CHAR.test(h3Index)) { - return [0, 0]; - } - const upper = parseInt(h3Index.substring(0, h3Index.length - 8), BASE_16); - const lower = parseInt(h3Index.substring(h3Index.length - 8), BASE_16); - return [lower, upper]; -} - -/** - * Convert a 32-bit int to a hexdecimal string - * @private - * @param {number} num Integer to convert - * @return {H3Index} Hexidecimal string - */ -function hexFrom32Bit (num) { - if (num >= 0) { - return num.toString(BASE_16); - } - - // Handle negative numbers - num = num & 0x7fffffff; - let tempStr = zeroPad(8, num.toString(BASE_16)); - const topNum = (parseInt(tempStr[0], BASE_16) + 8).toString(BASE_16); - tempStr = topNum + tempStr.substring(1); - return tempStr; -} - -/** - * Get a H3 index from a split long (pair of 32-bit ints) - * @private - * @param {number} lower Lower 32 bits - * @param {number} upper Upper 32 bits - * @return {H3Index} H3 index - */ -export function splitLongToh3Index (lower, upper) { - return hexFrom32Bit(upper) + zeroPad(8, hexFrom32Bit(lower)); -} - -/** - * Zero-pad a string to a given length - * @private - * @param {number} fullLen Target length - * @param {string} numStr String to zero-pad - * @return {string} Zero-padded string - */ -function zeroPad (fullLen, numStr) { - const numZeroes = fullLen - numStr.length; - let outStr = ''; - for (let i = 0; i < numZeroes; i++) { - outStr += '0'; - } - outStr = outStr + numStr; - return outStr; -} - -/** - * Populate a C-appropriate Geofence struct from a polygon array - * @private - * @param {Array[]} polygonArray Polygon, as an array of coordinate pairs - * @param {number} geofence C pointer to a Geofence struct - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated Geofence struct - */ -function polygonArrayToGeofence (polygonArray, geofence, isGeoJson) { - const numVerts = polygonArray.length; - const geoCoordArray = C._calloc(numVerts, SZ_GEOCOORD); - // Support [lng, lat] pairs if GeoJSON is specified - const latIndex = isGeoJson ? 1 : 0; - const lngIndex = isGeoJson ? 0 : 1; - for (let i = 0; i < numVerts * 2; i += 2) { - C.HEAPF64.set( - [polygonArray[i / 2][latIndex], polygonArray[i / 2][lngIndex]].map(degsToRads), - geoCoordArray / SZ_DBL + i - ); - } - C.HEAPU32.set([numVerts, geoCoordArray], geofence / SZ_INT); - return geofence; -} - -/** - * Create a C-appropriate GeoPolygon struct from an array of polygons - * @private - * @param {Array[]} coordinates Array of polygons, each an array of coordinate pairs - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated GeoPolygon struct - */ -function coordinatesToGeoPolygon (coordinates, isGeoJson) { - // Any loops beyond the first loop are holes - const numHoles = coordinates.length - 1; - const geoPolygon = C._calloc(SZ_GEOPOLYGON); - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // geofence is first part of struct - polygonArrayToGeofence(coordinates[0], geoPolygon + geofenceOffset, isGeoJson); - let holes; - if (numHoles > 0) { - holes = C._calloc(numHoles, SZ_GEOFENCE); - for (let i = 0; i < numHoles; i++) { - polygonArrayToGeofence(coordinates[i + 1], holes + SZ_GEOFENCE * i, isGeoJson); - } - } - C.setValue(geoPolygon + numHolesOffset, numHoles, 'i32'); - C.setValue(geoPolygon + holesOffset, holes, 'i32'); - return geoPolygon; -} - -/** - * Free memory allocated for a GeoPolygon struct. It is an error to access the struct - * after passing it to this method. - * @private - * @return {number} geoPolygon C pointer to populated GeoPolygon struct - */ -function destroyGeoPolygon (geoPolygon) { - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // Offset of the geofence vertex array pointer within the Geofence struct - const geofenceArrayOffset = SZ_INT; - // Free the outer vertex array - C._free(C.getValue(geoPolygon + geofenceOffset + geofenceArrayOffset, 'i8*')); - // Free the vertex array for the holes, if any - const numHoles = C.getValue(geoPolygon + numHolesOffset, 'i32'); - if (numHoles > 0) { - const holes = C.getValue(geoPolygon + holesOffset, 'i32'); - for (let i = 0; i < numHoles; i++) { - C._free(C.getValue(holes + SZ_GEOFENCE * i + geofenceArrayOffset, 'i8*')); - } - C._free(holes); - } - C._free(geoPolygon); -} - -/** - * Read a long value, returning the lower and upper portions as separate 32-bit integers. - * Because the upper bits are returned via side effect, the argument to this function is - * intended to be the invocation that caused the side effect, e.g. readLong(H3.getSomeLong()) - * @private - * @param {number} invocation Invoked function returning a long value. The actual return - * value of these functions is a 32-bit integer. - * @return {number} Long value as a [lower, upper] pair - */ -function readLong (invocation) { - // Upper 32-bits of the long set via side-effect - const upper = C.getTempRet0(); - return [invocation, upper]; -} - -/** - * Read an H3 index from a C return value. As with readLong, the argument to this function - * is intended to be an invocation, e.g. readH3Index(H3.getSomeAddress()), to help ensure that - * the temp value storing the upper bits of the long is still set. - * @private - * @param {number} invocation Invoked function returning a single H3 index - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3Index (invocation) { - const [lower, upper] = readLong(invocation); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Read an H3 index from a pointer to C memory. - * @private - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes, in case we're - * reading an array - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3IndexFromPointer (cAddress, offset = 0) { - const lower = C.getValue(cAddress + SZ_INT * offset * 2, 'i32'); - const upper = C.getValue(cAddress + SZ_INT * (offset * 2 + 1), 'i32'); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Store an H3 index in C memory. Primarily used as an efficient way to - * write sets of hexagons. - * @private - * @param {H3IndexInput} h3Index H3 index to store - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes from beginning - * of the current array - */ -function storeH3Index (h3Index, cAddress, offset) { - // HEAPU32 is a typed array projection on the index space - // as unsigned 32-bit integers. This means the index needs - // to be divided by SZ_INT (4) to access correctly. Also, - // the H3 index is 64 bits, so we skip by twos as we're writing - // to 32-bit integers in the proper order. - C.HEAPU32.set(h3IndexToSplitLong(h3Index), cAddress / SZ_INT + 2 * offset); -} - -/** - * Read an array of 64-bit H3 indexes from C and convert to a JS array of - * H3 index strings - * @private - * @param {number} cAddress Pointer to C ouput array - * @param {number} maxCount Max number of hexagons in array. Hexagons with - * the value 0 will be skipped, so this isn't - * necessarily the length of the output array. - * @return {H3Index[]} Array of H3 indexes - */ -function readArrayOfHexagons (cAddress, maxCount) { - const out = []; - for (let i = 0; i < maxCount; i++) { - const h3Index = readH3IndexFromPointer(cAddress, i); - if (h3Index !== null) { - out.push(h3Index); - } - } - return out; -} - -/** - * Store an array of H3 index strings as a C array of 64-bit integers. - * @private - * @param {number} cAddress Pointer to C input array - * @param {H3IndexInput[]} hexagons H3 indexes to pass to the C lib - */ -function storeArrayOfHexagons (cAddress, hexagons) { - // Assuming the cAddress points to an already appropriately - // allocated space - const count = hexagons.length; - for (let i = 0; i < count; i++) { - storeH3Index(hexagons[i], cAddress, i); - } -} - -/** - * Populate a C-appropriate GeoCoord struct from a [lat, lng] array - * @private - * @param {number} lat Coordinate latitude - * @param {number} lng Coordinate longitude - * @return {number} C pointer to populated GeoCoord struct - */ -function storeGeoCoord (lat, lng) { - const geoCoord = C._calloc(1, SZ_GEOCOORD); - C.HEAPF64.set([lat, lng].map(degsToRads), geoCoord / SZ_DBL); - return geoCoord; -} - -function readSingleCoord (cAddress) { - return radsToDegs(C.getValue(cAddress, 'double')); -} - -/** - * Read a GeoCoord from C and return a [lat, lng] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lat, lng] pair - */ -function readGeoCoord (cAddress) { - return [readSingleCoord(cAddress), readSingleCoord(cAddress + SZ_DBL)]; -} - -/** - * Read a GeoCoord from C and return a GeoJSON-style [lng, lat] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lng, lat] pair - */ -function readGeoCoordGeoJson (cAddress) { - return [readSingleCoord(cAddress + SZ_DBL), readSingleCoord(cAddress)]; -} - -/** - * Read the GeoBoundary structure into a list of geo coordinate pairs - * @private - * @param {number} geoBoundary C pointer to GeoBoundary struct - * @param {boolean} geoJsonCoords Whether to provide GeoJSON coordinate order: [lng, lat] - * @param {boolean} closedLoop Whether to close the loop - * @return {Array[]} Array of geo coordinate pairs - */ -function readGeoBoundary (geoBoundary, geoJsonCoords, closedLoop) { - const numVerts = C.getValue(geoBoundary, 'i32'); - // Note that though numVerts is an int, the coordinate doubles have to be - // aligned to 8 bytes, hence the 8-byte offset here - const vertsPos = geoBoundary + SZ_DBL; - const out = []; - // Support [lng, lat] pairs if GeoJSON is specified - const readCoord = geoJsonCoords ? readGeoCoordGeoJson : readGeoCoord; - for (let i = 0; i < numVerts * 2; i += 2) { - out.push(readCoord(vertsPos + SZ_DBL * i)); - } - if (closedLoop) { - // Close loop if GeoJSON is specified - out.push(out[0]); - } - return out; -} - -/** - * Read the LinkedGeoPolygon structure into a nested array of MultiPolygon coordinates - * @private - * @param {number} polygon C pointer to LinkedGeoPolygon struct - * @param {boolean} formatAsGeoJson Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -function readMultiPolygon (polygon, formatAsGeoJson) { - const output = []; - const readCoord = formatAsGeoJson ? readGeoCoordGeoJson : readGeoCoord; - let loops; - let loop; - let coords; - let coord; - // Loop through the linked structure, building the output - while (polygon) { - output.push((loops = [])); - // Follow ->first pointer - loop = C.getValue(polygon, 'i8*'); - while (loop) { - loops.push((coords = [])); - // Follow ->first pointer - coord = C.getValue(loop, 'i8*'); - while (coord) { - coords.push(readCoord(coord)); - // Follow ->next pointer - coord = C.getValue(coord + SZ_DBL * 2, 'i8*'); - } - if (formatAsGeoJson) { - // Close loop if GeoJSON is requested - coords.push(coords[0]); - } - // Follow ->next pointer - loop = C.getValue(loop + SZ_PTR * 2, 'i8*'); - } - // Follow ->next pointer - polygon = C.getValue(polygon + SZ_PTR * 2, 'i8*'); - } - return output; -} - -/** - * Read a CoordIJ from C and return an {i, j} pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function readCoordIJ (cAddress) { - return { - i: C.getValue(cAddress, 'i32'), - j: C.getValue(cAddress + SZ_INT, 'i32') - }; -} - -/** - * Store an {i, j} pair to a C CoordIJ struct. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function storeCoordIJ (cAddress, {i, j}) { - C.setValue(cAddress, i, 'i32'); - C.setValue(cAddress + SZ_INT, j, 'i32'); -} - -/** - * Read an array of positive integers array from C. Negative - * values are considered invalid and ignored in output. - * @private - * @param {number} cAddress Pointer to C array - * @param {number} count Length of C array - * @return {number[]} Javascript integer array - */ -function readArrayOfPositiveIntegers (cAddress, count) { - const out = []; - for (let i = 0; i < count; i++) { - const int = C.getValue(cAddress + SZ_INT * i, 'i32'); - if (int >= 0) { - out.push(int); - } - } - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Core - -/** - * Whether a given string represents a valid H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} Whether the index is valid - */ -export function h3IsValid (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsValid(lower, upper)); -} - -/** - * Whether the given H3 index is a pentagon - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isPentagon - */ -export function h3IsPentagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsPentagon(lower, upper)); -} - -/** - * Whether the given H3 index is in a Class III resolution (rotated versus - * the icosahedron and subject to shape distortion adding extra points on - * icosahedron edges, making them not true hexagons). - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isResClassIII - */ -export function h3IsResClassIII (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsResClassIII(lower, upper)); -} - -/** - * Get the number of the base cell for a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get the base cell for - * @return {number} Index of the base cell (0-121) - */ -export function h3GetBaseCell (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return H3.h3GetBaseCell(lower, upper); -} - -/** - * Get the indices of all icosahedron faces intersected by a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get faces for - * @return {number[]} Indices (0-19) of all intersected faces - */ -export function h3GetFaces (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = H3.maxFaceCount(lower, upper); - const faces = C._malloc(SZ_INT * count); - H3.h3GetFaces(lower, upper, faces); - const out = readArrayOfPositiveIntegers(faces, count); - C._free(faces); - return out; -} - -/** - * Returns the resolution of an H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get resolution - * @return {number} The number (0-15) resolution, or -1 if invalid - */ -export function h3GetResolution (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - if (!H3.h3IsValid(lower, upper)) { - // Compatability with stated API - return -1; - } - return H3.h3GetResolution(lower, upper); -} - -/** - * Get the hexagon containing a lat,lon point - * @static - * @param {number} lat Latitude of point - * @param {number} lng Longtitude of point - * @param {number} res Resolution of hexagons to return - * @return {H3Index} H3 index - */ -export function geoToH3 (lat, lng, res) { - const latlng = C._malloc(SZ_GEOCOORD); - // Slightly more efficient way to set the memory - C.HEAPF64.set([lat, lng].map(degsToRads), latlng / SZ_DBL); - // Read value as a split long - const h3Index = readH3Index(H3.geoToH3(latlng, res)); - C._free(latlng); - return h3Index; -} - -/** - * Get the lat,lon center of a given hexagon - * @static - * @param {H3IndexInput} h3Index H3 index - * @return {number[]} Point as a [lat, lng] pair - */ -export function h3ToGeo (h3Index) { - const latlng = C._malloc(SZ_GEOCOORD); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeo(lower, upper, latlng); - const out = readGeoCoord(latlng); - C._free(latlng); - return out; -} - -/** - * Get the vertices of a given hexagon (or pentagon), as an array of [lat, lng] - * points. For pentagons and hexagons on the edge of an icosahedron face, this - * function may return up to 10 vertices. - * @static - * @param {H3Index} h3Index H3 index - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][]} Array of [lat, lng] pairs - */ -export function h3ToGeoBoundary (h3Index, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeoBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Algorithms - -/** - * Get the parent of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get parent for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of parent, or null for invalid input - */ -export function h3ToParent (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToParent(lower, upper, res)); -} - -/** - * Get the children/descendents of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get children for - * @param {number} res Resolution of hexagons to return - * @return {H3Index[]} H3 indexes of children, or empty array for invalid input - */ -export function h3ToChildren (h3Index, res) { - // Bad input in this case can potentially result in high computation volume - // using the current C algorithm. Validate and return an empty array on failure. - if (!h3IsValid(h3Index)) { - return []; - } - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxH3ToChildrenSize(lower, upper, res); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.h3ToChildren(lower, upper, res, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get the center child of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get center child for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of child, or null for invalid input - */ -export function h3ToCenterChild (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToCenterChild(lower, upper, res)); -} - -/** - * Get all hexagons in a k-ring around a given center. The order of the hexagons is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - */ -export function kRing (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.kRing(lower, upper, ringSize, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons in a k-ring around a given center, in an array of arrays - * ordered by distance from the origin. The order of the hexagons within each ring is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[][]} Array of arrays with H3 indexes for all hexagons each ring - */ -export function kRingDistances (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const kRings = C._calloc(maxCount, SZ_H3INDEX); - const distances = C._calloc(maxCount, SZ_INT); - H3.kRingDistances(lower, upper, ringSize, kRings, distances); - // Create an array of empty arrays to hold the output - const out = []; - for (let i = 0; i < ringSize + 1; i++) { - out.push([]); - } - // Read the array of hexagons, putting them into the appropriate rings - for (let i = 0; i < maxCount * 2; i += 2) { - const hexLower = C.getValue(kRings + SZ_INT * i, 'i32'); - const hexUpper = C.getValue(kRings + SZ_INT * (i + 1), 'i32'); - const index = C.getValue(distances + SZ_INT * (i / 2), 'i32'); - if (hexLower !== 0 || hexUpper !== 0) { - out[index].push(splitLongToh3Index(hexLower, hexUpper)); - } - } - C._free(kRings); - C._free(distances); - return out; -} - -/** - * Get all hexagons in a hollow hexagonal ring centered at origin with sides of a given length. - * Unlike kRing, this function will throw an error if there is a pentagon anywhere in the ring. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - * @throws {Error} If the algorithm could not calculate the ring - */ -export function hexRing (h3Index, ringSize) { - const maxCount = ringSize === 0 ? 1 : 6 * ringSize; - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - const retVal = H3.hexRing(...h3IndexToSplitLong(h3Index), ringSize, hexagons); - if (retVal !== 0) { - C._free(hexagons); - throw new Error('Failed to get hexRing (encountered a pentagon?)'); - } - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons with centers contained in a given polygon. The polygon - * is specified with GeoJson semantics as an array of loops. Each loop is - * an array of [lat, lng] pairs (or [lng, lat] if isGeoJson is specified). - * The first loop is the perimeter of the polygon, and subsequent loops are - * expected to be holes. - * @static - * @param {number[][] | number[][][]} coordinates - * Array of loops, or a single loop - * @param {number} res Resolution of hexagons to return - * @param {boolean} [isGeoJson] Whether to expect GeoJson-style [lng, lat] - * pairs instead of [lat, lng] - * @return {H3Index[]} H3 indexes for all hexagons in polygon - */ -export function polyfill (coordinates, res, isGeoJson) { - validateRes(res); - isGeoJson = Boolean(isGeoJson); - // Guard against empty input - if (coordinates.length === 0 || coordinates[0].length === 0) { - return []; - } - // Wrap to expected format if a single loop is provided - if (typeof coordinates[0][0] === 'number') { - coordinates = [coordinates]; - } - const geoPolygon = coordinatesToGeoPolygon(coordinates, isGeoJson); - const arrayLen = H3.maxPolyfillSize(geoPolygon, res); - const hexagons = C._calloc(arrayLen, SZ_H3INDEX); - H3.polyfill(geoPolygon, res, hexagons); - const out = readArrayOfHexagons(hexagons, arrayLen); - C._free(hexagons); - destroyGeoPolygon(geoPolygon); - return out; -} - -/** - * Get the outlines of a set of H3 hexagons, returned in GeoJSON MultiPolygon - * format (an array of polygons, each with an array of loops, each an array of - * coordinates). Coordinates are returned as [lat, lng] pairs unless GeoJSON - * is requested. - * - * It is the responsibility of the caller to ensure that all hexagons in the - * set have the same resolution and that the set contains no duplicates. Behavior - * is undefined if duplicates or multiple resolutions are present, and the - * algorithm may produce unexpected or invalid polygons. - * - * @static - * @param {H3IndexInput[]} h3Indexes H3 indexes to get outlines for - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: - * [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -export function h3SetToMultiPolygon (h3Indexes, formatAsGeoJson) { - // Early exit on empty input - if (!h3Indexes || !h3Indexes.length) { - return []; - } - // Set up input set - const indexCount = h3Indexes.length; - const set = C._calloc(indexCount, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Indexes); - // Allocate memory for output linked polygon - const polygon = C._calloc(SZ_LINKED_GEOPOLYGON); - // Store a reference to the first polygon - that's the one we need for - // memory deallocation - const originalPolygon = polygon; - H3.h3SetToLinkedGeo(set, indexCount, polygon); - const multiPolygon = readMultiPolygon(polygon, formatAsGeoJson); - // Clean up - H3.destroyLinkedPolygon(originalPolygon); - C._free(originalPolygon); - C._free(set); - return multiPolygon; -} - -/** - * Compact a set of hexagons of the same resolution into a set of hexagons across - * multiple levels that represents the same area. - * @static - * @param {H3IndexInput[]} h3Set H3 indexes to compact - * @return {H3Index[]} Compacted H3 indexes - * @throws {Error} If the input is invalid (e.g. duplicate hexagons) - */ -export function compact (h3Set) { - if (!h3Set || !h3Set.length) { - return []; - } - // Set up input set - const count = h3Set.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Set); - // Allocate memory for compacted hexagons, worst-case is no compaction - const compactedSet = C._calloc(count, SZ_H3INDEX); - const retVal = H3.compact(set, compactedSet, count); - if (retVal !== 0) { - C._free(set); - C._free(compactedSet); - throw new Error('Failed to compact, malformed input data (duplicate hexagons?)'); - } - const out = readArrayOfHexagons(compactedSet, count); - C._free(set); - C._free(compactedSet); - return out; -} - -/** - * Uncompact a compacted set of hexagons to hexagons of the same resolution - * @static - * @param {H3IndexInput[]} compactedSet H3 indexes to uncompact - * @param {number} res The resolution to uncompact to - * @return {H3Index[]} The uncompacted H3 indexes - * @throws {Error} If the input is invalid (e.g. invalid resolution) - */ -export function uncompact (compactedSet, res) { - validateRes(res); - if (!compactedSet || !compactedSet.length) { - return []; - } - // Set up input set - const count = compactedSet.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, compactedSet); - // Estimate how many hexagons we need (always overestimates if in error) - const maxUncompactedNum = H3.maxUncompactSize(set, count, res); - // Allocate memory for uncompacted hexagons - const uncompactedSet = C._calloc(maxUncompactedNum, SZ_H3INDEX); - const retVal = H3.uncompact(set, count, uncompactedSet, maxUncompactedNum, res); - if (retVal !== 0) { - C._free(set); - C._free(uncompactedSet); - throw new Error('Failed to uncompact (bad resolution?)'); - } - const out = readArrayOfHexagons(uncompactedSet, maxUncompactedNum); - C._free(set); - C._free(uncompactedSet); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Unidirectional edges - -/** - * Whether two H3 indexes are neighbors (share an edge) - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {boolean} Whether the hexagons share an edge - */ -export function h3IndexesAreNeighbors (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return Boolean(H3.h3IndexesAreNeighbors(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get an H3 index representing a unidirectional edge for a given origin and destination - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index} H3 index of the edge, or null if no edge is shared - */ -export function getH3UnidirectionalEdge (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return readH3Index(H3.getH3UnidirectionalEdge(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get the origin hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge origin - */ -export function getOriginH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getOriginH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Get the destination hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge destination - */ -export function getDestinationH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getDestinationH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Whether the input is a valid unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {boolean} Whether the index is valid - */ -export function h3UnidirectionalEdgeIsValid (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return Boolean(H3.h3UnidirectionalEdgeIsValid(lower, upper)); -} - -/** - * Get the [origin, destination] pair represented by a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index[]} [origin, destination] pair as H3 indexes - */ -export function getH3IndexesFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - const count = 2; - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.getH3IndexesFromUnidirectionalEdge(lower, upper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get all of the unidirectional edges with the given H3 index as the origin (i.e. an edge to - * every neighbor) - * @static - * @param {H3IndexInput} h3Index H3 index of the origin hexagon - * @return {H3Index[]} List of unidirectional edges - */ -export function getH3UnidirectionalEdgesFromHexagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = 6; - const edges = C._calloc(count, SZ_H3INDEX); - H3.getH3UnidirectionalEdgesFromHexagon(lower, upper, edges); - const out = readArrayOfHexagons(edges, count); - C._free(edges); - return out; -} - -/** - * Get the vertices of a given edge as an array of [lat, lng] points. Note that for edges that - * cross the edge of an icosahedron face, this may return 3 coordinates. - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat] - * @return {number[][]} Array of geo coordinate pairs - */ -export function getH3UnidirectionalEdgeBoundary (edgeIndex, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - H3.getH3UnidirectionalEdgeBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -/** - * Get the grid distance between two hex indexes. This function may fail - * to find the distance between two indexes if they are very far apart or - * on opposite sides of a pentagon. - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {number} Distance between hexagons, or a negative - * number if the distance could not be computed - */ -export function h3Distance (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return H3.h3Distance(oLower, oUpper, dLower, dUpper); -} - -/** - * Given two H3 indexes, return the line of indexes between them (inclusive). - * - * This function may fail to find the line between two indexes, for - * example if they are very far apart. It may also fail when finding - * distances for indexes on opposite sides of a pentagon. - * - * Notes: - * - * - The specific output of this function should not be considered stable - * across library versions. The only guarantees the library provides are - * that the line length will be `h3Distance(start, end) + 1` and that - * every index in the line will be a neighbor of the preceding index. - * - Lines are drawn in grid space, and may not correspond exactly to either - * Cartesian lines or great arcs. - * - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index[]} H3 indexes connecting origin and destination - * @throws {Error} If the line cannot be calculated - */ -export function h3Line (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - const count = H3.h3LineSize(oLower, oUpper, dLower, dUpper); - if (count < 0) { - // We can't get the specific error code here - may be any of - // the errors possible in experimentalH3ToLocalIj - throw new Error('Line cannot be calculated'); - } - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.h3Line(oLower, oUpper, dLower, dUpper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Produces IJ coordinates for an H3 index anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {H3IndexInput} destination H3 index for which to find relative coordinates - * @return {CoordIJ} Coordinates as an `{i, j}` pair - * @throws {Error} If the IJ coordinates cannot be calculated - */ -export function experimentalH3ToLocalIj (origin, destination) { - const ij = C._malloc(SZ_COORDIJ); - const retVal = H3.experimentalH3ToLocalIj( - ...h3IndexToSplitLong(origin), - ...h3IndexToSplitLong(destination), - ij - ); - const coords = readCoordIJ(ij); - C._free(ij); - // Return the pair, or throw if an error code was returned. - // Switch statement and error codes cribbed from h3-java's implementation. - switch (retVal) { - case 0: - return coords; - case 1: - throw new Error('Incompatible origin and index.'); - case 2: - default: - throw new Error( - 'Local IJ coordinates undefined for this origin and index pair. ' + - 'The index may be too far from the origin.' - ); - case 3: - case 4: - case 5: - throw new Error('Encountered possible pentagon distortion'); - } -} - -/** - * Produces an H3 index for IJ coordinates anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {CoordIJ} coords Coordinates as an `{i, j}` pair - * @return {H3Index} H3 index at the relative coordinates - * @throws {Error} If the H3 index cannot be calculated - */ -export function experimentalLocalIjToH3 (origin, coords) { - // Validate input coords - if (!coords || typeof coords.i !== 'number' || typeof coords.j !== 'number') { - throw new Error('Coordinates must be provided as an {i, j} object'); - } - // Allocate memory for the CoordIJ struct and an H3 index to hold the return value - const ij = C._malloc(SZ_COORDIJ); - const out = C._malloc(SZ_H3INDEX); - storeCoordIJ(ij, coords); - const retVal = H3.experimentalLocalIjToH3(...h3IndexToSplitLong(origin), ij, out); - const h3Index = readH3IndexFromPointer(out); - C._free(ij); - C._free(out); - if (retVal !== 0) { - throw new Error( - 'Index not defined for this origin and IJ coordinates pair. ' + - 'IJ coordinates may be too far from origin, or ' + - 'a pentagon distortion was encountered.' - ); - } - return h3Index; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Distance/area utilities - -/** - * Great circle distance between two geo points. This is not specific to H3, - * but is implemented in the library and provided here as a convenience. - * @static - * @param {number[]} latlng1 Origin coordinate as [lat, lng] - * @param {number[]} latlng2 Destination coordinate as [lat, lng] - * @param {string} unit Distance unit (either UNITS.m or UNITS.km) - * @return {number} Great circle distance - * @throws {Error} If the unit is invalid - */ -export function pointDist (latlng1, latlng2, unit) { - const coord1 = storeGeoCoord(latlng1[0], latlng1[1]); - const coord2 = storeGeoCoord(latlng2[0], latlng2[1]); - let result; - switch (unit) { - case UNITS.m: - result = H3.pointDistM(coord1, coord2); - break; - case UNITS.km: - result = H3.pointDistKm(coord1, coord2); - break; - case UNITS.rads: - result = H3.pointDistRads(coord1, coord2); - break; - default: - result = null; - } - C._free(coord1); - C._free(coord2); - if (result === null) { - throw new Error(`Unknown unit: ${unit}`); - } - return result; -} - -/** - * Exact area of a given cell - * @static - * @param {H3Index} h3Index H3 index of the hexagon to measure - * @param {string} unit Distance unit (either UNITS.m2 or UNITS.km2) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function cellArea (h3Index, unit) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - switch (unit) { - case UNITS.m2: - return H3.cellAreaM2(lower, upper); - case UNITS.km2: - return H3.cellAreaKm2(lower, upper); - case UNITS.rads2: - return H3.cellAreaRads2(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Exact length of a given unidirectional edge - * @static - * @param {H3Index} edge H3 index of the edge to measure - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function exactEdgeLength (edge, unit) { - const [lower, upper] = h3IndexToSplitLong(edge); - switch (unit) { - case UNITS.m: - return H3.exactEdgeLengthM(lower, upper); - case UNITS.km: - return H3.exactEdgeLengthKm(lower, upper); - case UNITS.rads: - return H3.exactEdgeLengthRads(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon area at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Area unit (either UNITS.m2, UNITS.km2, or UNITS.rads2) - * @return {number} Average area - * @throws {Error} If the unit is invalid - */ -export function hexArea (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m2: - return H3.hexAreaM2(res); - case UNITS.km2: - return H3.hexAreaKm2(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon edge length at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Average edge length - * @throws {Error} If the unit is invalid - */ -export function edgeLength (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m: - return H3.edgeLengthM(res); - case UNITS.km: - return H3.edgeLengthKm(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -// ---------------------------------------------------------------------------- -// Public informational utilities - -/** - * The total count of hexagons in the world at a given resolution. Note that above - * resolution 8 the exact count cannot be represented in a JavaScript 32-bit number, - * so consumers should use caution when applying further operations to the output. - * @static - * @param {number} res Hexagon resolution - * @return {number} Count - */ -export function numHexagons (res) { - validateRes(res); - // Get number as a long value - const [lower, upper] = readLong(H3.numHexagons(res)); - // If we're using <= 32 bits we can use normal JS numbers - if (!upper) { - return lower; - } - // Above 32 bit, make a JS number that's correct in order of magnitude - return upper * Math.pow(2, 32) + lower; -} - -/** - * Get all H3 indexes at resolution 0. As every index at every resolution > 0 is - * the descendant of a res 0 index, this can be used with h3ToChildren to iterate - * over H3 indexes at any resolution. - * @static - * @return {H3Index[]} All H3 indexes at res 0 - */ -export function getRes0Indexes () { - const count = H3.res0IndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getRes0Indexes(hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get the twelve pentagon indexes at a given resolution. - * @static - * @param {number} res Hexagon resolution - * @return {H3Index[]} All H3 pentagon indexes at res - */ -export function getPentagonIndexes (res) { - validateRes(res); - const count = H3.pentagonIndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getPentagonIndexes(res, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Convert degrees to radians - * @static - * @param {number} deg Value in degrees - * @return {number} Value in radians - */ -export function degsToRads (deg) { - return (deg * Math.PI) / 180; -} - -/** - * Convert radians to degrees - * @static - * @param {number} rad Value in radians - * @return {number} Value in degrees - */ -export function radsToDegs (rad) { - return (rad * 180) / Math.PI; -} \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_tochildren/libh3_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_tochildren/libh3_custom.js deleted file mode 100644 index ae4a0c1d7..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_tochildren/libh3_custom.js +++ /dev/null @@ -1,24 +0,0 @@ - -var libh3 = ( -function(libh3) { - libh3 = libh3 || {}; - -var Module=typeof libh3!=="undefined"?libh3:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=4176,DYNAMIC_BASE=5247056,DYNAMICTOP_PTR=4144;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAD//////////wEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAACAAAAAAAAAAAAAAABAAAAAgAAAAYAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAKAAAAAgAAAAAAAAAAAAAAAQAAAAEAAAAFAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAACAAAAAAAAAAAAAAABAAAAAwAAAAcAAAAGAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADgAAAAIAAAAAAAAAAAAAAAEAAAAAAAAACQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAIAAAAAAAAAAAAAAAEAAAAEAAAACAAAAAoAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAgAAAAAAAAAAAAAAAQAAAAsAAAAPAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAIAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAgAAAAAAAAAAAAAAAQAAAAwAAAAQAAAADAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAACAAAAAAAAAAAAAAABAAAACgAAABMAAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAIAAAAAAAAAAAAAAAEAAAANAAAAEQAAAA0AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAACAAAAAAAAAAAAAAABAAAADgAAABIAAAAPAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAADwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAASAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABIAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAgAAAAAAAAAAAAAAAQAAAP//////////EwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEgAAAAE=";var tempDoublePtr=4160;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]|0}function J(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0;if(!(0==0&(b&-16777216|0)==134217728)){b=0;return b|0}g=S(a|0,b|0,45)|0;p()|0;g=g&127;if(g>>>0>121){b=0;return b|0}c=S(a|0,b|0,52)|0;p()|0;c=c&15;do if(c|0){e=1;d=0;while(1){f=S(a|0,b|0,(15-e|0)*3|0)|0;p()|0;f=f&7;if((f|0)!=0&(d^1))if((f|0)==1&(I(g)|0)!=0){h=0;d=13;break}else d=1;if((f|0)==7){h=0;d=13;break}if(e>>>0>>0)e=e+1|0;else{d=9;break}}if((d|0)==9){if((c|0)==15)h=1;else break;return h|0}else if((d|0)==13)return h|0}while(0);while(1){h=S(a|0,b|0,(14-c|0)*3|0)|0;p()|0;if(!((h&7|0)==7&0==0)){h=0;d=13;break}if(c>>>0<14)c=c+1|0;else{h=1;d=13;break}}if((d|0)==13)return h|0;return 0}function K(a,b,c){a=a|0;b=b|0;c=c|0;a=S(a|0,b|0,52)|0;p()|0;a=a&15;if(!((c|0)<16&(a|0)<=(c|0))){c=0;return c|0}c=M(7,c-a|0)|0;return c|0}function L(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0;h=S(a|0,c|0,52)|0;p()|0;h=h&15;if(!((d|0)<16&(h|0)<=(d|0)))return;if((h|0)==(d|0)){d=e;b[d>>2]=a;b[d+4>>2]=c;return}j=M(7,d-h|0)|0;k=(j|0)/7|0;i=S(a|0,c|0,45)|0;p()|0;if(!(I(i&127)|0))g=0;else{a:do if(!h)f=0;else{g=1;while(1){f=S(a|0,c|0,(15-g|0)*3|0)|0;p()|0;f=f&7;if(f|0)break a;if(g>>>0>>0)g=g+1|0;else{f=0;break}}}while(0);g=(f|0)==0}l=T(h+1|0,0,52)|0;f=p()|0|c&-15728641;i=(14-h|0)*3|0;c=T(7,0,i|0)|0;c=(l|a)&~c;h=f&~(p()|0);L(c,h,d,e);f=e+(k<<3)|0;if(!g){l=T(1,0,i|0)|0;L(l|c,p()|0|h,d,f);l=f+(k<<3)|0;j=T(2,0,i|0)|0;L(j|c,p()|0|h,d,l);l=l+(k<<3)|0;j=T(3,0,i|0)|0;L(j|c,p()|0|h,d,l);l=l+(k<<3)|0;j=T(4,0,i|0)|0;L(j|c,p()|0|h,d,l);l=l+(k<<3)|0;j=T(5,0,i|0)|0;L(j|c,p()|0|h,d,l);j=T(6,0,i|0)|0;L(j|c,p()|0|h,d,l+(k<<3)|0);return}g=f+(k<<3)|0;if((j|0)>6){j=f+8|0;l=(g>>>0>j>>>0?g:j)+-1+(0-f)|0;V(f|0,0,l+8&-8|0)|0;f=j+(l>>>3<<3)|0}l=T(2,0,i|0)|0;L(l|c,p()|0|h,d,f);l=f+(k<<3)|0;j=T(3,0,i|0)|0;L(j|c,p()|0|h,d,l);l=l+(k<<3)|0;j=T(4,0,i|0)|0;L(j|c,p()|0|h,d,l);l=l+(k<<3)|0;j=T(5,0,i|0)|0;L(j|c,p()|0|h,d,l);j=T(6,0,i|0)|0;L(j|c,p()|0|h,d,l+(k<<3)|0);return}function M(a,b){a=a|0;b=b|0;var c=0;if(!b){c=1;return c|0}c=a;a=1;do{a=m((b&1|0)==0?1:c,a)|0;b=b>>1;c=m(c,c)|0}while((b|0)!=0);return a|0}function N(){return 8}function O(){return 3440}function P(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=A;A=A+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[861]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=3484+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[861]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;A=w;return v|0}l=b[863]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=3484+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[866]|0;c=l>>>3;d=3484+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[863]=h;b[866]=f;v=i;A=w;return v|0}g=b[862]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[3748+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=3748+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[862]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[866]|0;c=l>>>3;d=3484+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[863]=j;b[866]=h}v=i+8|0;A=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[862]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[3748+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[3748+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[863]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=3748+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=3484+(c<<1<<2)|0;a=b[861]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=3748+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;A=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[863]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[866]|0;if(c>>>0>15){v=a+m|0;b[866]=v;b[863]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[863]=0;b[866]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;A=w;return v|0}h=b[864]|0;if(h>>>0>m>>>0){t=h-m|0;b[864]=t;v=b[867]|0;u=v+m|0;b[867]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;A=w;return v|0}if(!(b[979]|0)){b[981]=4096;b[980]=4096;b[982]=-1;b[983]=-1;b[984]=0;b[972]=0;b[979]=n&-16^1431655768;a=4096}else a=b[981]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;A=w;return v|0}a=b[971]|0;if(a|0?(l=b[969]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;A=w;return v|0}d:do if(!(b[972]&4)){d=b[867]|0;e:do if(d){e=3892;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=W(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=W(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[980]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[969]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[971]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=W(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[981]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((W(a|0)|0)==(-1|0)){W(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[972]=b[972]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=W(k|0)|0,p=W(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[969]|0)+h|0;b[969]=c;if(c>>>0>(b[970]|0)>>>0)b[970]=c;j=b[867]|0;f:do if(j){c=3892;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[864]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[867]=u;b[864]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[868]=b[983];break}if(g>>>0<(b[865]|0)>>>0)b[865]=g;d=g+h|0;c=3892;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[864]|0)+i|0;b[864]=v;b[867]=k;b[k+4>>2]=v|1}else{if((b[866]|0)==(c|0)){v=(b[863]|0)+i|0;b[863]=v;b[866]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[861]=b[861]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=3748+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[862]=b[862]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=3484+(c<<1<<2)|0;a=b[861]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=3748+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[862]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;A=w;return v|0}c=3892;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[867]=u;b[864]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[868]=b[983];d=a+4|0;b[d>>2]=27;b[c>>2]=b[973];b[c+4>>2]=b[974];b[c+8>>2]=b[975];b[c+12>>2]=b[976];b[973]=g;b[974]=h;b[976]=0;b[975]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=3484+(c<<1<<2)|0;a=b[861]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=3748+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[862]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[865]|0;if((v|0)==0|g>>>0>>0)b[865]=g;b[973]=g;b[974]=h;b[976]=0;b[870]=b[979];b[869]=-1;b[874]=3484;b[873]=3484;b[876]=3492;b[875]=3492;b[878]=3500;b[877]=3500;b[880]=3508;b[879]=3508;b[882]=3516;b[881]=3516;b[884]=3524;b[883]=3524;b[886]=3532;b[885]=3532;b[888]=3540;b[887]=3540;b[890]=3548;b[889]=3548;b[892]=3556;b[891]=3556;b[894]=3564;b[893]=3564;b[896]=3572;b[895]=3572;b[898]=3580;b[897]=3580;b[900]=3588;b[899]=3588;b[902]=3596;b[901]=3596;b[904]=3604;b[903]=3604;b[906]=3612;b[905]=3612;b[908]=3620;b[907]=3620;b[910]=3628;b[909]=3628;b[912]=3636;b[911]=3636;b[914]=3644;b[913]=3644;b[916]=3652;b[915]=3652;b[918]=3660;b[917]=3660;b[920]=3668;b[919]=3668;b[922]=3676;b[921]=3676;b[924]=3684;b[923]=3684;b[926]=3692;b[925]=3692;b[928]=3700;b[927]=3700;b[930]=3708;b[929]=3708;b[932]=3716;b[931]=3716;b[934]=3724;b[933]=3724;b[936]=3732;b[935]=3732;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[867]=u;b[864]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[868]=b[983]}while(0);c=b[864]|0;if(c>>>0>m>>>0){t=c-m|0;b[864]=t;v=b[867]|0;u=v+m|0;b[867]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;A=w;return v|0}}v=O()|0;b[v>>2]=12;v=0;A=w;return v|0}function Q(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[865]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[866]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[863]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[861]=b[861]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=3748+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[862]=b[862]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[867]|0)==(j|0)){j=(b[864]|0)+c|0;b[864]=j;b[867]=i;b[i+4>>2]=j|1;if((i|0)!=(b[866]|0))return;b[866]=0;b[863]=0;return}if((b[866]|0)==(j|0)){j=(b[863]|0)+c|0;b[863]=j;b[866]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[861]=b[861]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=3748+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[862]=b[862]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[866]|0)){b[863]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=3484+(a<<1<<2)|0;c=b[861]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=3748+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[862]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[869]|0)+-1|0;b[869]=j;if(j|0)return;a=3900;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[869]=-1;return}function R(a,c){a=a|0;c=c|0;var d=0;if(a){d=m(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=P(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;V(a|0,0,d|0)|0;return a|0}function S(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){o(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function T(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){o(b<>>32-c|0);return a<=8192){s(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function V(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function W(a){a=a|0;var c=0,e=0,f=0;f=r()|0;e=b[d>>2]|0;c=e+a|0;if((a|0)>0&(c|0)<(e|0)|(c|0)<0){u(c|0)|0;q(12);return -1}if((c|0)>(f|0))if(!(t(c|0)|0)){q(12);return -1}b[d>>2]=c;return e|0} - -// EMSCRIPTEN_END_FUNCS -return{_bitshift64Lshr:S,_bitshift64Shl:T,_calloc:R,_emscripten_replace_memory:D,_free:Q,_h3IsValid:J,_h3ToChildren:L,_malloc:P,_maxH3ToChildrenSize:K,_memcpy:U,_memset:V,_sbrk:W,_sizeOfH3Index:N,establishStackSpace:H,stackAlloc:E,stackRestore:G,stackSave:F}}) - - -// EMSCRIPTEN_END_ASM -(asmGlobalArg,asmLibraryArg,buffer);var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _h3IsValid=Module["_h3IsValid"]=asm["_h3IsValid"];var _h3ToChildren=Module["_h3ToChildren"]=asm["_h3ToChildren"];var _malloc=Module["_malloc"]=asm["_malloc"];var _maxH3ToChildrenSize=Module["_maxH3ToChildrenSize"]=asm["_maxH3ToChildrenSize"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _sizeOfH3Index=Module["_sizeOfH3Index"]=asm["_sizeOfH3Index"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); - - - - return libh3 -} -)(typeof libh3 === 'object' ? libh3 : {}); -export default libh3; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_toparent/h3core_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_toparent/h3core_custom.js deleted file mode 100644 index 54d5c4b75..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_toparent/h3core_custom.js +++ /dev/null @@ -1,1352 +0,0 @@ -/* - * Copyright 2018-2019 Uber Technologies, Inc. - * Copyright 2021 CARTO - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @module h3 - */ - -import C from './libh3_custom'; -import BINDINGS from 'h3-js/lib/bindings'; - -const H3 = {}; - -// Create the bound functions themselves -BINDINGS.forEach(function bind (def) { - // Bind only exported functions - if (C['_' + def[0]]) { - H3[def[0]] = C.cwrap(...def); - } -}); - -// Alias the hexidecimal base for legibility -const BASE_16 = 16; - -// ---------------------------------------------------------------------------- -// Byte size imports - -const SZ_INT = 4; -const SZ_PTR = 4; -const SZ_DBL = 8; -const SZ_H3INDEX = H3.sizeOfH3Index && H3.sizeOfH3Index(); -const SZ_GEOCOORD = H3.sizeOfGeoCoord && H3.sizeOfGeoCoord(); -const SZ_GEOBOUNDARY = H3.sizeOfGeoBoundary && H3.sizeOfGeoBoundary(); -const SZ_GEOPOLYGON = H3.sizeOfGeoPolygon && H3.sizeOfGeoPolygon(); -const SZ_GEOFENCE = H3.sizeOfGeofence && H3.sizeOfGeofence(); -const SZ_LINKED_GEOPOLYGON = H3.sizeOfLinkedGeoPolygon && H3.sizeOfLinkedGeoPolygon(); -const SZ_COORDIJ = H3.sizeOfCoordIJ && H3.sizeOfCoordIJ(); - -// ---------------------------------------------------------------------------- -// Custom types - -/** - * 64-bit hexidecimal string representation of an H3 index - * @static - * @typedef {string} H3Index - */ - -/** - * 64-bit hexidecimal string representation of an H3 index, - * or two 32-bit integers in little endian order in an array. - * @static - * @typedef {string | number[]} H3IndexInput - */ - -/** - * Coordinates as an `{i, j}` pair - * @static - * @typedef CoordIJ - * @type {Object} - * @property {number} i - * @property {number} j - */ - -// ---------------------------------------------------------------------------- -// Unit constants - -/** - * Length/Area units - * @static - * @typedef UNITS - * @type {Object} - * @property {string} m - * @property {string} m2 - * @property {string} km - * @property {string} km2 - * @property {string} rads - * @property {string} rads2 - */ -export const UNITS = { - m: 'm', - m2: 'm2', - km: 'km', - km2: 'km2', - rads: 'rads', - rads2: 'rads2' -}; - -// ---------------------------------------------------------------------------- -// Utilities and helpers - -/** - * Validate a resolution, throwing an error if invalid - * @private - * @param {mixed} res Value to validate - * @throws {Error} Error if invalid - */ -function validateRes (res) { - if (typeof res !== 'number' || res < 0 || res > 15 || Math.floor(res) !== res) { - throw new Error(`Invalid resolution: ${res}`); - } -} - -const INVALID_HEXIDECIMAL_CHAR = /[^0-9a-fA-F]/; - -/** - * Convert an H3 index (64-bit hexidecimal string) into a "split long" - a pair of 32-bit ints - * @private - * @param {H3IndexInput} h3Index H3 index to check - * @return {number[]} A two-element array with 32 lower bits and 32 upper bits - */ -export function h3IndexToSplitLong (h3Index) { - if ( - Array.isArray(h3Index) && - h3Index.length === 2 && - Number.isInteger(h3Index[0]) && - Number.isInteger(h3Index[1]) - ) { - return h3Index; - } - if (typeof h3Index !== 'string' || INVALID_HEXIDECIMAL_CHAR.test(h3Index)) { - return [0, 0]; - } - const upper = parseInt(h3Index.substring(0, h3Index.length - 8), BASE_16); - const lower = parseInt(h3Index.substring(h3Index.length - 8), BASE_16); - return [lower, upper]; -} - -/** - * Convert a 32-bit int to a hexdecimal string - * @private - * @param {number} num Integer to convert - * @return {H3Index} Hexidecimal string - */ -function hexFrom32Bit (num) { - if (num >= 0) { - return num.toString(BASE_16); - } - - // Handle negative numbers - num = num & 0x7fffffff; - let tempStr = zeroPad(8, num.toString(BASE_16)); - const topNum = (parseInt(tempStr[0], BASE_16) + 8).toString(BASE_16); - tempStr = topNum + tempStr.substring(1); - return tempStr; -} - -/** - * Get a H3 index from a split long (pair of 32-bit ints) - * @private - * @param {number} lower Lower 32 bits - * @param {number} upper Upper 32 bits - * @return {H3Index} H3 index - */ -export function splitLongToh3Index (lower, upper) { - return hexFrom32Bit(upper) + zeroPad(8, hexFrom32Bit(lower)); -} - -/** - * Zero-pad a string to a given length - * @private - * @param {number} fullLen Target length - * @param {string} numStr String to zero-pad - * @return {string} Zero-padded string - */ -function zeroPad (fullLen, numStr) { - const numZeroes = fullLen - numStr.length; - let outStr = ''; - for (let i = 0; i < numZeroes; i++) { - outStr += '0'; - } - outStr = outStr + numStr; - return outStr; -} - -/** - * Populate a C-appropriate Geofence struct from a polygon array - * @private - * @param {Array[]} polygonArray Polygon, as an array of coordinate pairs - * @param {number} geofence C pointer to a Geofence struct - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated Geofence struct - */ -function polygonArrayToGeofence (polygonArray, geofence, isGeoJson) { - const numVerts = polygonArray.length; - const geoCoordArray = C._calloc(numVerts, SZ_GEOCOORD); - // Support [lng, lat] pairs if GeoJSON is specified - const latIndex = isGeoJson ? 1 : 0; - const lngIndex = isGeoJson ? 0 : 1; - for (let i = 0; i < numVerts * 2; i += 2) { - C.HEAPF64.set( - [polygonArray[i / 2][latIndex], polygonArray[i / 2][lngIndex]].map(degsToRads), - geoCoordArray / SZ_DBL + i - ); - } - C.HEAPU32.set([numVerts, geoCoordArray], geofence / SZ_INT); - return geofence; -} - -/** - * Create a C-appropriate GeoPolygon struct from an array of polygons - * @private - * @param {Array[]} coordinates Array of polygons, each an array of coordinate pairs - * @param {boolean} isGeoJson Whether coordinates are in [lng, lat] order per GeoJSON spec - * @return {number} C pointer to populated GeoPolygon struct - */ -function coordinatesToGeoPolygon (coordinates, isGeoJson) { - // Any loops beyond the first loop are holes - const numHoles = coordinates.length - 1; - const geoPolygon = C._calloc(SZ_GEOPOLYGON); - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // geofence is first part of struct - polygonArrayToGeofence(coordinates[0], geoPolygon + geofenceOffset, isGeoJson); - let holes; - if (numHoles > 0) { - holes = C._calloc(numHoles, SZ_GEOFENCE); - for (let i = 0; i < numHoles; i++) { - polygonArrayToGeofence(coordinates[i + 1], holes + SZ_GEOFENCE * i, isGeoJson); - } - } - C.setValue(geoPolygon + numHolesOffset, numHoles, 'i32'); - C.setValue(geoPolygon + holesOffset, holes, 'i32'); - return geoPolygon; -} - -/** - * Free memory allocated for a GeoPolygon struct. It is an error to access the struct - * after passing it to this method. - * @private - * @return {number} geoPolygon C pointer to populated GeoPolygon struct - */ -function destroyGeoPolygon (geoPolygon) { - // Byte positions within the struct - const geofenceOffset = 0; - const numHolesOffset = geofenceOffset + SZ_GEOFENCE; - const holesOffset = numHolesOffset + SZ_INT; - // Offset of the geofence vertex array pointer within the Geofence struct - const geofenceArrayOffset = SZ_INT; - // Free the outer vertex array - C._free(C.getValue(geoPolygon + geofenceOffset + geofenceArrayOffset, 'i8*')); - // Free the vertex array for the holes, if any - const numHoles = C.getValue(geoPolygon + numHolesOffset, 'i32'); - if (numHoles > 0) { - const holes = C.getValue(geoPolygon + holesOffset, 'i32'); - for (let i = 0; i < numHoles; i++) { - C._free(C.getValue(holes + SZ_GEOFENCE * i + geofenceArrayOffset, 'i8*')); - } - C._free(holes); - } - C._free(geoPolygon); -} - -/** - * Read a long value, returning the lower and upper portions as separate 32-bit integers. - * Because the upper bits are returned via side effect, the argument to this function is - * intended to be the invocation that caused the side effect, e.g. readLong(H3.getSomeLong()) - * @private - * @param {number} invocation Invoked function returning a long value. The actual return - * value of these functions is a 32-bit integer. - * @return {number} Long value as a [lower, upper] pair - */ -function readLong (invocation) { - // Upper 32-bits of the long set via side-effect - const upper = C.getTempRet0(); - return [invocation, upper]; -} - -/** - * Read an H3 index from a C return value. As with readLong, the argument to this function - * is intended to be an invocation, e.g. readH3Index(H3.getSomeAddress()), to help ensure that - * the temp value storing the upper bits of the long is still set. - * @private - * @param {number} invocation Invoked function returning a single H3 index - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3Index (invocation) { - const [lower, upper] = readLong(invocation); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Read an H3 index from a pointer to C memory. - * @private - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes, in case we're - * reading an array - * @return {H3Index} H3 index, or null if index was invalid - */ -function readH3IndexFromPointer (cAddress, offset = 0) { - const lower = C.getValue(cAddress + SZ_INT * offset * 2, 'i32'); - const upper = C.getValue(cAddress + SZ_INT * (offset * 2 + 1), 'i32'); - // The lower bits are allowed to be 0s, but if the upper bits are 0 - // this represents an invalid H3 index - return upper ? splitLongToh3Index(lower, upper) : null; -} - -/** - * Store an H3 index in C memory. Primarily used as an efficient way to - * write sets of hexagons. - * @private - * @param {H3IndexInput} h3Index H3 index to store - * @param {number} cAddress Pointer to allocated C memory - * @param {number} offset Offset, in number of H3 indexes from beginning - * of the current array - */ -function storeH3Index (h3Index, cAddress, offset) { - // HEAPU32 is a typed array projection on the index space - // as unsigned 32-bit integers. This means the index needs - // to be divided by SZ_INT (4) to access correctly. Also, - // the H3 index is 64 bits, so we skip by twos as we're writing - // to 32-bit integers in the proper order. - C.HEAPU32.set(h3IndexToSplitLong(h3Index), cAddress / SZ_INT + 2 * offset); -} - -/** - * Read an array of 64-bit H3 indexes from C and convert to a JS array of - * H3 index strings - * @private - * @param {number} cAddress Pointer to C ouput array - * @param {number} maxCount Max number of hexagons in array. Hexagons with - * the value 0 will be skipped, so this isn't - * necessarily the length of the output array. - * @return {H3Index[]} Array of H3 indexes - */ -function readArrayOfHexagons (cAddress, maxCount) { - const out = []; - for (let i = 0; i < maxCount; i++) { - const h3Index = readH3IndexFromPointer(cAddress, i); - if (h3Index !== null) { - out.push(h3Index); - } - } - return out; -} - -/** - * Store an array of H3 index strings as a C array of 64-bit integers. - * @private - * @param {number} cAddress Pointer to C input array - * @param {H3IndexInput[]} hexagons H3 indexes to pass to the C lib - */ -function storeArrayOfHexagons (cAddress, hexagons) { - // Assuming the cAddress points to an already appropriately - // allocated space - const count = hexagons.length; - for (let i = 0; i < count; i++) { - storeH3Index(hexagons[i], cAddress, i); - } -} - -/** - * Populate a C-appropriate GeoCoord struct from a [lat, lng] array - * @private - * @param {number} lat Coordinate latitude - * @param {number} lng Coordinate longitude - * @return {number} C pointer to populated GeoCoord struct - */ -function storeGeoCoord (lat, lng) { - const geoCoord = C._calloc(1, SZ_GEOCOORD); - C.HEAPF64.set([lat, lng].map(degsToRads), geoCoord / SZ_DBL); - return geoCoord; -} - -function readSingleCoord (cAddress) { - return radsToDegs(C.getValue(cAddress, 'double')); -} - -/** - * Read a GeoCoord from C and return a [lat, lng] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lat, lng] pair - */ -function readGeoCoord (cAddress) { - return [readSingleCoord(cAddress), readSingleCoord(cAddress + SZ_DBL)]; -} - -/** - * Read a GeoCoord from C and return a GeoJSON-style [lng, lat] pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {number[]} [lng, lat] pair - */ -function readGeoCoordGeoJson (cAddress) { - return [readSingleCoord(cAddress + SZ_DBL), readSingleCoord(cAddress)]; -} - -/** - * Read the GeoBoundary structure into a list of geo coordinate pairs - * @private - * @param {number} geoBoundary C pointer to GeoBoundary struct - * @param {boolean} geoJsonCoords Whether to provide GeoJSON coordinate order: [lng, lat] - * @param {boolean} closedLoop Whether to close the loop - * @return {Array[]} Array of geo coordinate pairs - */ -function readGeoBoundary (geoBoundary, geoJsonCoords, closedLoop) { - const numVerts = C.getValue(geoBoundary, 'i32'); - // Note that though numVerts is an int, the coordinate doubles have to be - // aligned to 8 bytes, hence the 8-byte offset here - const vertsPos = geoBoundary + SZ_DBL; - const out = []; - // Support [lng, lat] pairs if GeoJSON is specified - const readCoord = geoJsonCoords ? readGeoCoordGeoJson : readGeoCoord; - for (let i = 0; i < numVerts * 2; i += 2) { - out.push(readCoord(vertsPos + SZ_DBL * i)); - } - if (closedLoop) { - // Close loop if GeoJSON is specified - out.push(out[0]); - } - return out; -} - -/** - * Read the LinkedGeoPolygon structure into a nested array of MultiPolygon coordinates - * @private - * @param {number} polygon C pointer to LinkedGeoPolygon struct - * @param {boolean} formatAsGeoJson Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -function readMultiPolygon (polygon, formatAsGeoJson) { - const output = []; - const readCoord = formatAsGeoJson ? readGeoCoordGeoJson : readGeoCoord; - let loops; - let loop; - let coords; - let coord; - // Loop through the linked structure, building the output - while (polygon) { - output.push((loops = [])); - // Follow ->first pointer - loop = C.getValue(polygon, 'i8*'); - while (loop) { - loops.push((coords = [])); - // Follow ->first pointer - coord = C.getValue(loop, 'i8*'); - while (coord) { - coords.push(readCoord(coord)); - // Follow ->next pointer - coord = C.getValue(coord + SZ_DBL * 2, 'i8*'); - } - if (formatAsGeoJson) { - // Close loop if GeoJSON is requested - coords.push(coords[0]); - } - // Follow ->next pointer - loop = C.getValue(loop + SZ_PTR * 2, 'i8*'); - } - // Follow ->next pointer - polygon = C.getValue(polygon + SZ_PTR * 2, 'i8*'); - } - return output; -} - -/** - * Read a CoordIJ from C and return an {i, j} pair. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function readCoordIJ (cAddress) { - return { - i: C.getValue(cAddress, 'i32'), - j: C.getValue(cAddress + SZ_INT, 'i32') - }; -} - -/** - * Store an {i, j} pair to a C CoordIJ struct. - * @private - * @param {number} cAddress Pointer to C struct - * @return {CoordIJ} {i, j} pair - */ -function storeCoordIJ (cAddress, {i, j}) { - C.setValue(cAddress, i, 'i32'); - C.setValue(cAddress + SZ_INT, j, 'i32'); -} - -/** - * Read an array of positive integers array from C. Negative - * values are considered invalid and ignored in output. - * @private - * @param {number} cAddress Pointer to C array - * @param {number} count Length of C array - * @return {number[]} Javascript integer array - */ -function readArrayOfPositiveIntegers (cAddress, count) { - const out = []; - for (let i = 0; i < count; i++) { - const int = C.getValue(cAddress + SZ_INT * i, 'i32'); - if (int >= 0) { - out.push(int); - } - } - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Core - -/** - * Whether a given string represents a valid H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} Whether the index is valid - */ -export function h3IsValid (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsValid(lower, upper)); -} - -/** - * Whether the given H3 index is a pentagon - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isPentagon - */ -export function h3IsPentagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsPentagon(lower, upper)); -} - -/** - * Whether the given H3 index is in a Class III resolution (rotated versus - * the icosahedron and subject to shape distortion adding extra points on - * icosahedron edges, making them not true hexagons). - * @static - * @param {H3IndexInput} h3Index H3 index to check - * @return {boolean} isResClassIII - */ -export function h3IsResClassIII (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return Boolean(H3.h3IsResClassIII(lower, upper)); -} - -/** - * Get the number of the base cell for a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get the base cell for - * @return {number} Index of the base cell (0-121) - */ -export function h3GetBaseCell (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return H3.h3GetBaseCell(lower, upper); -} - -/** - * Get the indices of all icosahedron faces intersected by a given H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get faces for - * @return {number[]} Indices (0-19) of all intersected faces - */ -export function h3GetFaces (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = H3.maxFaceCount(lower, upper); - const faces = C._malloc(SZ_INT * count); - H3.h3GetFaces(lower, upper, faces); - const out = readArrayOfPositiveIntegers(faces, count); - C._free(faces); - return out; -} - -/** - * Returns the resolution of an H3 index - * @static - * @param {H3IndexInput} h3Index H3 index to get resolution - * @return {number} The number (0-15) resolution, or -1 if invalid - */ -export function h3GetResolution (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - if (!H3.h3IsValid(lower, upper)) { - // Compatability with stated API - return -1; - } - return H3.h3GetResolution(lower, upper); -} - -/** - * Get the hexagon containing a lat,lon point - * @static - * @param {number} lat Latitude of point - * @param {number} lng Longtitude of point - * @param {number} res Resolution of hexagons to return - * @return {H3Index} H3 index - */ -export function geoToH3 (lat, lng, res) { - const latlng = C._malloc(SZ_GEOCOORD); - // Slightly more efficient way to set the memory - C.HEAPF64.set([lat, lng].map(degsToRads), latlng / SZ_DBL); - // Read value as a split long - const h3Index = readH3Index(H3.geoToH3(latlng, res)); - C._free(latlng); - return h3Index; -} - -/** - * Get the lat,lon center of a given hexagon - * @static - * @param {H3IndexInput} h3Index H3 index - * @return {number[]} Point as a [lat, lng] pair - */ -export function h3ToGeo (h3Index) { - const latlng = C._malloc(SZ_GEOCOORD); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeo(lower, upper, latlng); - const out = readGeoCoord(latlng); - C._free(latlng); - return out; -} - -/** - * Get the vertices of a given hexagon (or pentagon), as an array of [lat, lng] - * points. For pentagons and hexagons on the edge of an icosahedron face, this - * function may return up to 10 vertices. - * @static - * @param {H3Index} h3Index H3 index - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat], closed loops - * @return {number[][]} Array of [lat, lng] pairs - */ -export function h3ToGeoBoundary (h3Index, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(h3Index); - H3.h3ToGeoBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Algorithms - -/** - * Get the parent of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get parent for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of parent, or null for invalid input - */ -export function h3ToParent (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToParent(lower, upper, res)); -} - -/** - * Get the children/descendents of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get children for - * @param {number} res Resolution of hexagons to return - * @return {H3Index[]} H3 indexes of children, or empty array for invalid input - */ -export function h3ToChildren (h3Index, res) { - // Bad input in this case can potentially result in high computation volume - // using the current C algorithm. Validate and return an empty array on failure. - if (!h3IsValid(h3Index)) { - return []; - } - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxH3ToChildrenSize(lower, upper, res); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.h3ToChildren(lower, upper, res, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get the center child of the given hexagon at a particular resolution - * @static - * @param {H3IndexInput} h3Index H3 index to get center child for - * @param {number} res Resolution of hexagon to return - * @return {H3Index} H3 index of child, or null for invalid input - */ -export function h3ToCenterChild (h3Index, res) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - return readH3Index(H3.h3ToCenterChild(lower, upper, res)); -} - -/** - * Get all hexagons in a k-ring around a given center. The order of the hexagons is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - */ -export function kRing (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - H3.kRing(lower, upper, ringSize, hexagons); - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons in a k-ring around a given center, in an array of arrays - * ordered by distance from the origin. The order of the hexagons within each ring is undefined. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of k-ring - * @return {H3Index[][]} Array of arrays with H3 indexes for all hexagons each ring - */ -export function kRingDistances (h3Index, ringSize) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const maxCount = H3.maxKringSize(ringSize); - const kRings = C._calloc(maxCount, SZ_H3INDEX); - const distances = C._calloc(maxCount, SZ_INT); - H3.kRingDistances(lower, upper, ringSize, kRings, distances); - // Create an array of empty arrays to hold the output - const out = []; - for (let i = 0; i < ringSize + 1; i++) { - out.push([]); - } - // Read the array of hexagons, putting them into the appropriate rings - for (let i = 0; i < maxCount * 2; i += 2) { - const hexLower = C.getValue(kRings + SZ_INT * i, 'i32'); - const hexUpper = C.getValue(kRings + SZ_INT * (i + 1), 'i32'); - const index = C.getValue(distances + SZ_INT * (i / 2), 'i32'); - if (hexLower !== 0 || hexUpper !== 0) { - out[index].push(splitLongToh3Index(hexLower, hexUpper)); - } - } - C._free(kRings); - C._free(distances); - return out; -} - -/** - * Get all hexagons in a hollow hexagonal ring centered at origin with sides of a given length. - * Unlike kRing, this function will throw an error if there is a pentagon anywhere in the ring. - * @static - * @param {H3IndexInput} h3Index H3 index of center hexagon - * @param {number} ringSize Radius of ring - * @return {H3Index[]} H3 indexes for all hexagons in ring - * @throws {Error} If the algorithm could not calculate the ring - */ -export function hexRing (h3Index, ringSize) { - const maxCount = ringSize === 0 ? 1 : 6 * ringSize; - const hexagons = C._calloc(maxCount, SZ_H3INDEX); - const retVal = H3.hexRing(...h3IndexToSplitLong(h3Index), ringSize, hexagons); - if (retVal !== 0) { - C._free(hexagons); - throw new Error('Failed to get hexRing (encountered a pentagon?)'); - } - const out = readArrayOfHexagons(hexagons, maxCount); - C._free(hexagons); - return out; -} - -/** - * Get all hexagons with centers contained in a given polygon. The polygon - * is specified with GeoJson semantics as an array of loops. Each loop is - * an array of [lat, lng] pairs (or [lng, lat] if isGeoJson is specified). - * The first loop is the perimeter of the polygon, and subsequent loops are - * expected to be holes. - * @static - * @param {number[][] | number[][][]} coordinates - * Array of loops, or a single loop - * @param {number} res Resolution of hexagons to return - * @param {boolean} [isGeoJson] Whether to expect GeoJson-style [lng, lat] - * pairs instead of [lat, lng] - * @return {H3Index[]} H3 indexes for all hexagons in polygon - */ -export function polyfill (coordinates, res, isGeoJson) { - validateRes(res); - isGeoJson = Boolean(isGeoJson); - // Guard against empty input - if (coordinates.length === 0 || coordinates[0].length === 0) { - return []; - } - // Wrap to expected format if a single loop is provided - if (typeof coordinates[0][0] === 'number') { - coordinates = [coordinates]; - } - const geoPolygon = coordinatesToGeoPolygon(coordinates, isGeoJson); - const arrayLen = H3.maxPolyfillSize(geoPolygon, res); - const hexagons = C._calloc(arrayLen, SZ_H3INDEX); - H3.polyfill(geoPolygon, res, hexagons); - const out = readArrayOfHexagons(hexagons, arrayLen); - C._free(hexagons); - destroyGeoPolygon(geoPolygon); - return out; -} - -/** - * Get the outlines of a set of H3 hexagons, returned in GeoJSON MultiPolygon - * format (an array of polygons, each with an array of loops, each an array of - * coordinates). Coordinates are returned as [lat, lng] pairs unless GeoJSON - * is requested. - * - * It is the responsibility of the caller to ensure that all hexagons in the - * set have the same resolution and that the set contains no duplicates. Behavior - * is undefined if duplicates or multiple resolutions are present, and the - * algorithm may produce unexpected or invalid polygons. - * - * @static - * @param {H3IndexInput[]} h3Indexes H3 indexes to get outlines for - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: - * [lng, lat], closed loops - * @return {number[][][][]} MultiPolygon-style output. - */ -export function h3SetToMultiPolygon (h3Indexes, formatAsGeoJson) { - // Early exit on empty input - if (!h3Indexes || !h3Indexes.length) { - return []; - } - // Set up input set - const indexCount = h3Indexes.length; - const set = C._calloc(indexCount, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Indexes); - // Allocate memory for output linked polygon - const polygon = C._calloc(SZ_LINKED_GEOPOLYGON); - // Store a reference to the first polygon - that's the one we need for - // memory deallocation - const originalPolygon = polygon; - H3.h3SetToLinkedGeo(set, indexCount, polygon); - const multiPolygon = readMultiPolygon(polygon, formatAsGeoJson); - // Clean up - H3.destroyLinkedPolygon(originalPolygon); - C._free(originalPolygon); - C._free(set); - return multiPolygon; -} - -/** - * Compact a set of hexagons of the same resolution into a set of hexagons across - * multiple levels that represents the same area. - * @static - * @param {H3IndexInput[]} h3Set H3 indexes to compact - * @return {H3Index[]} Compacted H3 indexes - * @throws {Error} If the input is invalid (e.g. duplicate hexagons) - */ -export function compact (h3Set) { - if (!h3Set || !h3Set.length) { - return []; - } - // Set up input set - const count = h3Set.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, h3Set); - // Allocate memory for compacted hexagons, worst-case is no compaction - const compactedSet = C._calloc(count, SZ_H3INDEX); - const retVal = H3.compact(set, compactedSet, count); - if (retVal !== 0) { - C._free(set); - C._free(compactedSet); - throw new Error('Failed to compact, malformed input data (duplicate hexagons?)'); - } - const out = readArrayOfHexagons(compactedSet, count); - C._free(set); - C._free(compactedSet); - return out; -} - -/** - * Uncompact a compacted set of hexagons to hexagons of the same resolution - * @static - * @param {H3IndexInput[]} compactedSet H3 indexes to uncompact - * @param {number} res The resolution to uncompact to - * @return {H3Index[]} The uncompacted H3 indexes - * @throws {Error} If the input is invalid (e.g. invalid resolution) - */ -export function uncompact (compactedSet, res) { - validateRes(res); - if (!compactedSet || !compactedSet.length) { - return []; - } - // Set up input set - const count = compactedSet.length; - const set = C._calloc(count, SZ_H3INDEX); - storeArrayOfHexagons(set, compactedSet); - // Estimate how many hexagons we need (always overestimates if in error) - const maxUncompactedNum = H3.maxUncompactSize(set, count, res); - // Allocate memory for uncompacted hexagons - const uncompactedSet = C._calloc(maxUncompactedNum, SZ_H3INDEX); - const retVal = H3.uncompact(set, count, uncompactedSet, maxUncompactedNum, res); - if (retVal !== 0) { - C._free(set); - C._free(uncompactedSet); - throw new Error('Failed to uncompact (bad resolution?)'); - } - const out = readArrayOfHexagons(uncompactedSet, maxUncompactedNum); - C._free(set); - C._free(uncompactedSet); - return out; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Unidirectional edges - -/** - * Whether two H3 indexes are neighbors (share an edge) - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {boolean} Whether the hexagons share an edge - */ -export function h3IndexesAreNeighbors (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return Boolean(H3.h3IndexesAreNeighbors(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get an H3 index representing a unidirectional edge for a given origin and destination - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index} H3 index of the edge, or null if no edge is shared - */ -export function getH3UnidirectionalEdge (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return readH3Index(H3.getH3UnidirectionalEdge(oLower, oUpper, dLower, dUpper)); -} - -/** - * Get the origin hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge origin - */ -export function getOriginH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getOriginH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Get the destination hexagon from an H3 index representing a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index} H3 index of the edge destination - */ -export function getDestinationH3IndexFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return readH3Index(H3.getDestinationH3IndexFromUnidirectionalEdge(lower, upper)); -} - -/** - * Whether the input is a valid unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {boolean} Whether the index is valid - */ -export function h3UnidirectionalEdgeIsValid (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - return Boolean(H3.h3UnidirectionalEdgeIsValid(lower, upper)); -} - -/** - * Get the [origin, destination] pair represented by a unidirectional edge - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @return {H3Index[]} [origin, destination] pair as H3 indexes - */ -export function getH3IndexesFromUnidirectionalEdge (edgeIndex) { - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - const count = 2; - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.getH3IndexesFromUnidirectionalEdge(lower, upper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get all of the unidirectional edges with the given H3 index as the origin (i.e. an edge to - * every neighbor) - * @static - * @param {H3IndexInput} h3Index H3 index of the origin hexagon - * @return {H3Index[]} List of unidirectional edges - */ -export function getH3UnidirectionalEdgesFromHexagon (h3Index) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - const count = 6; - const edges = C._calloc(count, SZ_H3INDEX); - H3.getH3UnidirectionalEdgesFromHexagon(lower, upper, edges); - const out = readArrayOfHexagons(edges, count); - C._free(edges); - return out; -} - -/** - * Get the vertices of a given edge as an array of [lat, lng] points. Note that for edges that - * cross the edge of an icosahedron face, this may return 3 coordinates. - * @static - * @param {H3IndexInput} edgeIndex H3 index of the edge - * @param {boolean} [formatAsGeoJson] Whether to provide GeoJSON output: [lng, lat] - * @return {number[][]} Array of geo coordinate pairs - */ -export function getH3UnidirectionalEdgeBoundary (edgeIndex, formatAsGeoJson) { - const geoBoundary = C._malloc(SZ_GEOBOUNDARY); - const [lower, upper] = h3IndexToSplitLong(edgeIndex); - H3.getH3UnidirectionalEdgeBoundary(lower, upper, geoBoundary); - const out = readGeoBoundary(geoBoundary, formatAsGeoJson); - C._free(geoBoundary); - return out; -} - -/** - * Get the grid distance between two hex indexes. This function may fail - * to find the distance between two indexes if they are very far apart or - * on opposite sides of a pentagon. - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {number} Distance between hexagons, or a negative - * number if the distance could not be computed - */ -export function h3Distance (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - return H3.h3Distance(oLower, oUpper, dLower, dUpper); -} - -/** - * Given two H3 indexes, return the line of indexes between them (inclusive). - * - * This function may fail to find the line between two indexes, for - * example if they are very far apart. It may also fail when finding - * distances for indexes on opposite sides of a pentagon. - * - * Notes: - * - * - The specific output of this function should not be considered stable - * across library versions. The only guarantees the library provides are - * that the line length will be `h3Distance(start, end) + 1` and that - * every index in the line will be a neighbor of the preceding index. - * - Lines are drawn in grid space, and may not correspond exactly to either - * Cartesian lines or great arcs. - * - * @static - * @param {H3IndexInput} origin Origin hexagon index - * @param {H3IndexInput} destination Destination hexagon index - * @return {H3Index[]} H3 indexes connecting origin and destination - * @throws {Error} If the line cannot be calculated - */ -export function h3Line (origin, destination) { - const [oLower, oUpper] = h3IndexToSplitLong(origin); - const [dLower, dUpper] = h3IndexToSplitLong(destination); - const count = H3.h3LineSize(oLower, oUpper, dLower, dUpper); - if (count < 0) { - // We can't get the specific error code here - may be any of - // the errors possible in experimentalH3ToLocalIj - throw new Error('Line cannot be calculated'); - } - const hexagons = C._calloc(count, SZ_H3INDEX); - H3.h3Line(oLower, oUpper, dLower, dUpper, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Produces IJ coordinates for an H3 index anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {H3IndexInput} destination H3 index for which to find relative coordinates - * @return {CoordIJ} Coordinates as an `{i, j}` pair - * @throws {Error} If the IJ coordinates cannot be calculated - */ -export function experimentalH3ToLocalIj (origin, destination) { - const ij = C._malloc(SZ_COORDIJ); - const retVal = H3.experimentalH3ToLocalIj( - ...h3IndexToSplitLong(origin), - ...h3IndexToSplitLong(destination), - ij - ); - const coords = readCoordIJ(ij); - C._free(ij); - // Return the pair, or throw if an error code was returned. - // Switch statement and error codes cribbed from h3-java's implementation. - switch (retVal) { - case 0: - return coords; - case 1: - throw new Error('Incompatible origin and index.'); - case 2: - default: - throw new Error( - 'Local IJ coordinates undefined for this origin and index pair. ' + - 'The index may be too far from the origin.' - ); - case 3: - case 4: - case 5: - throw new Error('Encountered possible pentagon distortion'); - } -} - -/** - * Produces an H3 index for IJ coordinates anchored by an origin. - * - * - The coordinate space used by this function may have deleted - * regions or warping due to pentagonal distortion. - * - Coordinates are only comparable if they come from the same - * origin index. - * - Failure may occur if the index is too far away from the origin - * or if the index is on the other side of a pentagon. - * - This function is experimental, and its output is not guaranteed - * to be compatible across different versions of H3. - * @static - * @param {H3IndexInput} origin Origin H3 index - * @param {CoordIJ} coords Coordinates as an `{i, j}` pair - * @return {H3Index} H3 index at the relative coordinates - * @throws {Error} If the H3 index cannot be calculated - */ -export function experimentalLocalIjToH3 (origin, coords) { - // Validate input coords - if (!coords || typeof coords.i !== 'number' || typeof coords.j !== 'number') { - throw new Error('Coordinates must be provided as an {i, j} object'); - } - // Allocate memory for the CoordIJ struct and an H3 index to hold the return value - const ij = C._malloc(SZ_COORDIJ); - const out = C._malloc(SZ_H3INDEX); - storeCoordIJ(ij, coords); - const retVal = H3.experimentalLocalIjToH3(...h3IndexToSplitLong(origin), ij, out); - const h3Index = readH3IndexFromPointer(out); - C._free(ij); - C._free(out); - if (retVal !== 0) { - throw new Error( - 'Index not defined for this origin and IJ coordinates pair. ' + - 'IJ coordinates may be too far from origin, or ' + - 'a pentagon distortion was encountered.' - ); - } - return h3Index; -} - -// ---------------------------------------------------------------------------- -// Public API functions: Distance/area utilities - -/** - * Great circle distance between two geo points. This is not specific to H3, - * but is implemented in the library and provided here as a convenience. - * @static - * @param {number[]} latlng1 Origin coordinate as [lat, lng] - * @param {number[]} latlng2 Destination coordinate as [lat, lng] - * @param {string} unit Distance unit (either UNITS.m or UNITS.km) - * @return {number} Great circle distance - * @throws {Error} If the unit is invalid - */ -export function pointDist (latlng1, latlng2, unit) { - const coord1 = storeGeoCoord(latlng1[0], latlng1[1]); - const coord2 = storeGeoCoord(latlng2[0], latlng2[1]); - let result; - switch (unit) { - case UNITS.m: - result = H3.pointDistM(coord1, coord2); - break; - case UNITS.km: - result = H3.pointDistKm(coord1, coord2); - break; - case UNITS.rads: - result = H3.pointDistRads(coord1, coord2); - break; - default: - result = null; - } - C._free(coord1); - C._free(coord2); - if (result === null) { - throw new Error(`Unknown unit: ${unit}`); - } - return result; -} - -/** - * Exact area of a given cell - * @static - * @param {H3Index} h3Index H3 index of the hexagon to measure - * @param {string} unit Distance unit (either UNITS.m2 or UNITS.km2) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function cellArea (h3Index, unit) { - const [lower, upper] = h3IndexToSplitLong(h3Index); - switch (unit) { - case UNITS.m2: - return H3.cellAreaM2(lower, upper); - case UNITS.km2: - return H3.cellAreaKm2(lower, upper); - case UNITS.rads2: - return H3.cellAreaRads2(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Exact length of a given unidirectional edge - * @static - * @param {H3Index} edge H3 index of the edge to measure - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Cell area - * @throws {Error} If the unit is invalid - */ -export function exactEdgeLength (edge, unit) { - const [lower, upper] = h3IndexToSplitLong(edge); - switch (unit) { - case UNITS.m: - return H3.exactEdgeLengthM(lower, upper); - case UNITS.km: - return H3.exactEdgeLengthKm(lower, upper); - case UNITS.rads: - return H3.exactEdgeLengthRads(lower, upper); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon area at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Area unit (either UNITS.m2, UNITS.km2, or UNITS.rads2) - * @return {number} Average area - * @throws {Error} If the unit is invalid - */ -export function hexArea (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m2: - return H3.hexAreaM2(res); - case UNITS.km2: - return H3.hexAreaKm2(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -/** - * Average hexagon edge length at a given resolution - * @static - * @param {number} res Hexagon resolution - * @param {string} unit Distance unit (either UNITS.m, UNITS.km, or UNITS.rads) - * @return {number} Average edge length - * @throws {Error} If the unit is invalid - */ -export function edgeLength (res, unit) { - validateRes(res); - switch (unit) { - case UNITS.m: - return H3.edgeLengthM(res); - case UNITS.km: - return H3.edgeLengthKm(res); - default: - throw new Error(`Unknown unit: ${unit}`); - } -} - -// ---------------------------------------------------------------------------- -// Public informational utilities - -/** - * The total count of hexagons in the world at a given resolution. Note that above - * resolution 8 the exact count cannot be represented in a JavaScript 32-bit number, - * so consumers should use caution when applying further operations to the output. - * @static - * @param {number} res Hexagon resolution - * @return {number} Count - */ -export function numHexagons (res) { - validateRes(res); - // Get number as a long value - const [lower, upper] = readLong(H3.numHexagons(res)); - // If we're using <= 32 bits we can use normal JS numbers - if (!upper) { - return lower; - } - // Above 32 bit, make a JS number that's correct in order of magnitude - return upper * Math.pow(2, 32) + lower; -} - -/** - * Get all H3 indexes at resolution 0. As every index at every resolution > 0 is - * the descendant of a res 0 index, this can be used with h3ToChildren to iterate - * over H3 indexes at any resolution. - * @static - * @return {H3Index[]} All H3 indexes at res 0 - */ -export function getRes0Indexes () { - const count = H3.res0IndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getRes0Indexes(hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Get the twelve pentagon indexes at a given resolution. - * @static - * @param {number} res Hexagon resolution - * @return {H3Index[]} All H3 pentagon indexes at res - */ -export function getPentagonIndexes (res) { - validateRes(res); - const count = H3.pentagonIndexCount(); - const hexagons = C._malloc(SZ_H3INDEX * count); - H3.getPentagonIndexes(res, hexagons); - const out = readArrayOfHexagons(hexagons, count); - C._free(hexagons); - return out; -} - -/** - * Convert degrees to radians - * @static - * @param {number} deg Value in degrees - * @return {number} Value in radians - */ -export function degsToRads (deg) { - return (deg * Math.PI) / 180; -} - -/** - * Convert radians to degrees - * @static - * @param {number} rad Value in radians - * @return {number} Value in degrees - */ -export function radsToDegs (rad) { - return (rad * 180) / Math.PI; -} \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/src/h3/h3_toparent/libh3_custom.js b/clouds/snowflake/libraries/javascript/src/h3/h3_toparent/libh3_custom.js deleted file mode 100644 index baff57b64..000000000 --- a/clouds/snowflake/libraries/javascript/src/h3/h3_toparent/libh3_custom.js +++ /dev/null @@ -1,24 +0,0 @@ - -var libh3 = ( -function(libh3) { - libh3 = libh3 || {}; - -var Module=typeof libh3!=="undefined"?libh3:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var GLOBAL_BASE=8;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=4176,DYNAMIC_BASE=5247056,DYNAMICTOP_PTR=4144;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;if(Module["buffer"]){buffer=Module["buffer"]}else{buffer=new ArrayBuffer(INITIAL_TOTAL_MEMORY)}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var tempDouble;var tempI64;memoryInitializer="data:application/octet-stream;base64,AAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAD//////////wEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAACAAAAAAAAAAAAAAABAAAAAgAAAAYAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAKAAAAAgAAAAAAAAAAAAAAAQAAAAEAAAAFAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAACAAAAAAAAAAAAAAABAAAAAwAAAAcAAAAGAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAADgAAAAIAAAAAAAAAAAAAAAEAAAAAAAAACQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAMAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAIAAAAAAAAAAAAAAAEAAAAEAAAACAAAAAoAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAgAAAAAAAAAAAAAAAQAAAAsAAAAPAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAIAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAgAAAAAAAAAAAAAAAQAAAAwAAAAQAAAADAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAADwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAACAAAAAAAAAAAAAAABAAAACgAAABMAAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAACQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAIAAAAAAAAAAAAAAAEAAAANAAAAEQAAAA0AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAACAAAAAAAAAAAAAAABAAAADgAAABIAAAAPAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAADwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAASAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABIAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAATAAAAAgAAAAAAAAAAAAAAAQAAAP//////////EwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEgAAAAE=";var tempDoublePtr=4160;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{var newBuffer=new ArrayBuffer(size);if(newBuffer.byteLength!=size)return;new Int8Array(newBuffer).set(HEAP8);_emscripten_replace_memory(newBuffer);updateGlobalBufferAndViews(newBuffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=16777216;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]|0}function J(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0;if(!(0==0&(b&-16777216|0)==134217728)){b=0;return b|0}g=P(a|0,b|0,45)|0;p()|0;g=g&127;if(g>>>0>121){b=0;return b|0}c=P(a|0,b|0,52)|0;p()|0;c=c&15;do if(c|0){e=1;d=0;while(1){f=P(a|0,b|0,(15-e|0)*3|0)|0;p()|0;f=f&7;if((f|0)!=0&(d^1))if((f|0)==1&(I(g)|0)!=0){h=0;d=13;break}else d=1;if((f|0)==7){h=0;d=13;break}if(e>>>0>>0)e=e+1|0;else{d=9;break}}if((d|0)==9){if((c|0)==15)h=1;else break;return h|0}else if((d|0)==13)return h|0}while(0);while(1){h=P(a|0,b|0,(14-c|0)*3|0)|0;p()|0;if(!((h&7|0)==7&0==0)){h=0;d=13;break}if(c>>>0<14)c=c+1|0;else{h=1;d=13;break}}if((d|0)==13)return h|0;return 0}function K(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=P(a|0,b|0,52)|0;p()|0;d=d&15;if((d|0)>=(c|0)){if((d|0)!=(c|0))if(c>>>0<=15){e=Q(c|0,0,52)|0;a=e|a;b=p()|0|b&-15728641;if((d|0)>(c|0))do{e=Q(7,0,(14-c|0)*3|0)|0;c=c+1|0;a=e|a;b=p()|0|b}while((c|0)<(d|0))}else{b=0;a=0}}else{b=0;a=0}o(b|0);return a|0}function L(){return 3440}function M(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=A;A=A+16|0;n=w;do if(a>>>0<245){k=a>>>0<11?16:a+11&-8;a=k>>>3;m=b[861]|0;d=m>>>a;if(d&3|0){c=(d&1^1)+a|0;a=3484+(c<<1<<2)|0;d=a+8|0;e=b[d>>2]|0;f=e+8|0;g=b[f>>2]|0;if((g|0)==(a|0))b[861]=m&~(1<>2]=a;b[d>>2]=g}v=c<<3;b[e+4>>2]=v|3;v=e+v+4|0;b[v>>2]=b[v>>2]|1;v=f;A=w;return v|0}l=b[863]|0;if(k>>>0>l>>>0){if(d|0){c=2<>>12&16;c=c>>>i;d=c>>>5&8;c=c>>>d;g=c>>>2&4;c=c>>>g;a=c>>>1&2;c=c>>>a;e=c>>>1&1;e=(d|i|g|a|e)+(c>>>e)|0;c=3484+(e<<1<<2)|0;a=c+8|0;g=b[a>>2]|0;i=g+8|0;d=b[i>>2]|0;if((d|0)==(c|0)){a=m&~(1<>2]=c;b[a>>2]=d;a=m}v=e<<3;h=v-k|0;b[g+4>>2]=k|3;f=g+k|0;b[f+4>>2]=h|1;b[g+v>>2]=h;if(l|0){e=b[866]|0;c=l>>>3;d=3484+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[863]=h;b[866]=f;v=i;A=w;return v|0}g=b[862]|0;if(g){d=(g&0-g)+-1|0;f=d>>>12&16;d=d>>>f;e=d>>>5&8;d=d>>>e;h=d>>>2&4;d=d>>>h;i=d>>>1&2;d=d>>>i;j=d>>>1&1;j=b[3748+((e|f|h|i|j)+(d>>>j)<<2)>>2]|0;d=j;i=j;j=(b[j+4>>2]&-8)-k|0;while(1){a=b[d+16>>2]|0;if(!a){a=b[d+20>>2]|0;if(!a)break}h=(b[a+4>>2]&-8)-k|0;f=h>>>0>>0;d=a;i=f?a:i;j=f?h:j}h=i+k|0;if(h>>>0>i>>>0){f=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){d=0;break}}while(1){e=c+20|0;d=b[e>>2]|0;if(!d){e=c+16|0;d=b[e>>2]|0;if(!d)break;else{c=d;a=e}}else{c=d;a=e}}b[a>>2]=0;d=c}else{d=b[i+8>>2]|0;b[d+12>>2]=c;b[c+8>>2]=d;d=c}while(0);do if(f|0){c=b[i+28>>2]|0;a=3748+(c<<2)|0;if((i|0)==(b[a>>2]|0)){b[a>>2]=d;if(!d){b[862]=g&~(1<>2]|0)==(i|0)?v:f+20|0)>>2]=d;if(!d)break}b[d+24>>2]=f;c=b[i+16>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}c=b[i+20>>2]|0;if(c|0){b[d+20>>2]=c;b[c+24>>2]=d}}while(0);if(j>>>0<16){v=j+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[h+4>>2]=j|1;b[h+j>>2]=j;if(l|0){e=b[866]|0;c=l>>>3;d=3484+(c<<1<<2)|0;c=1<>2]|0}b[a>>2]=e;b[c+12>>2]=e;b[e+8>>2]=c;b[e+12>>2]=d}b[863]=j;b[866]=h}v=i+8|0;A=w;return v|0}else m=k}else m=k}else m=k}else if(a>>>0<=4294967231){a=a+11|0;k=a&-8;e=b[862]|0;if(e){f=0-k|0;a=a>>>8;if(a)if(k>>>0>16777215)j=31;else{m=(a+1048320|0)>>>16&8;q=a<>>16&4;q=q<>>16&2;j=14-(i|m|j)+(q<>>15)|0;j=k>>>(j+7|0)&1|j<<1}else j=0;d=b[3748+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;q=61}else{a=0;i=k<<((j|0)==31?0:25-(j>>>1)|0);g=0;while(1){h=(b[d+4>>2]&-8)-k|0;if(h>>>0>>0)if(!h){a=d;f=0;q=65;break a}else{a=d;f=h}q=b[d+20>>2]|0;d=b[d+16+(i>>>31<<2)>>2]|0;g=(q|0)==0|(q|0)==(d|0)?g:q;if(!d){d=g;q=61;break}else i=i<<1}}while(0);if((q|0)==61){if((d|0)==0&(a|0)==0){a=2<>>12&16;m=m>>>h;g=m>>>5&8;m=m>>>g;i=m>>>2&4;m=m>>>i;j=m>>>1&2;m=m>>>j;d=m>>>1&1;a=0;d=b[3748+((g|h|i|j|d)+(m>>>d)<<2)>>2]|0}if(!d){i=a;h=f}else q=65}if((q|0)==65){g=d;while(1){m=(b[g+4>>2]&-8)-k|0;d=m>>>0>>0;f=d?m:f;a=d?g:a;d=b[g+16>>2]|0;if(!d)d=b[g+20>>2]|0;if(!d){i=a;h=f;break}else g=d}}if(((i|0)!=0?h>>>0<((b[863]|0)-k|0)>>>0:0)?(l=i+k|0,l>>>0>i>>>0):0){g=b[i+24>>2]|0;c=b[i+12>>2]|0;do if((c|0)==(i|0)){a=i+20|0;c=b[a>>2]|0;if(!c){a=i+16|0;c=b[a>>2]|0;if(!c){c=0;break}}while(1){f=c+20|0;d=b[f>>2]|0;if(!d){f=c+16|0;d=b[f>>2]|0;if(!d)break;else{c=d;a=f}}else{c=d;a=f}}b[a>>2]=0}else{v=b[i+8>>2]|0;b[v+12>>2]=c;b[c+8>>2]=v}while(0);do if(g){a=b[i+28>>2]|0;d=3748+(a<<2)|0;if((i|0)==(b[d>>2]|0)){b[d>>2]=c;if(!c){e=e&~(1<>2]|0)==(i|0)?v:g+20|0)>>2]=c;if(!c)break}b[c+24>>2]=g;a=b[i+16>>2]|0;if(a|0){b[c+16>>2]=a;b[a+24>>2]=c}a=b[i+20>>2]|0;if(a){b[c+20>>2]=a;b[a+24>>2]=c}}while(0);b:do if(h>>>0<16){v=h+k|0;b[i+4>>2]=v|3;v=i+v+4|0;b[v>>2]=b[v>>2]|1}else{b[i+4>>2]=k|3;b[l+4>>2]=h|1;b[l+h>>2]=h;c=h>>>3;if(h>>>0<256){d=3484+(c<<1<<2)|0;a=b[861]|0;c=1<>2]|0}b[a>>2]=l;b[c+12>>2]=l;b[l+8>>2]=c;b[l+12>>2]=d;break}c=h>>>8;if(c)if(h>>>0>16777215)d=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;d=14-(t|u|d)+(v<>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;c=3748+(d<<2)|0;b[l+28>>2]=d;a=l+16|0;b[a+4>>2]=0;b[a>>2]=0;a=1<>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break}c=b[c>>2]|0;c:do if((b[c+4>>2]&-8|0)!=(h|0)){e=h<<((d|0)==31?0:25-(d>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(h|0)){c=a;break c}else{e=e<<1;c=a}}b[d>>2]=l;b[l+24>>2]=c;b[l+12>>2]=l;b[l+8>>2]=l;break b}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=l;b[u>>2]=l;b[l+8>>2]=v;b[l+12>>2]=c;b[l+24>>2]=0}while(0);v=i+8|0;A=w;return v|0}else m=k}else m=k}else m=-1;while(0);d=b[863]|0;if(d>>>0>=m>>>0){c=d-m|0;a=b[866]|0;if(c>>>0>15){v=a+m|0;b[866]=v;b[863]=c;b[v+4>>2]=c|1;b[a+d>>2]=c;b[a+4>>2]=m|3}else{b[863]=0;b[866]=0;b[a+4>>2]=d|3;v=a+d+4|0;b[v>>2]=b[v>>2]|1}v=a+8|0;A=w;return v|0}h=b[864]|0;if(h>>>0>m>>>0){t=h-m|0;b[864]=t;v=b[867]|0;u=v+m|0;b[867]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;A=w;return v|0}if(!(b[979]|0)){b[981]=4096;b[980]=4096;b[982]=-1;b[983]=-1;b[984]=0;b[972]=0;b[979]=n&-16^1431655768;a=4096}else a=b[981]|0;i=m+48|0;j=m+47|0;g=a+j|0;f=0-a|0;k=g&f;if(k>>>0<=m>>>0){v=0;A=w;return v|0}a=b[971]|0;if(a|0?(l=b[969]|0,n=l+k|0,n>>>0<=l>>>0|n>>>0>a>>>0):0){v=0;A=w;return v|0}d:do if(!(b[972]&4)){d=b[867]|0;e:do if(d){e=3892;while(1){n=b[e>>2]|0;if(n>>>0<=d>>>0?(n+(b[e+4>>2]|0)|0)>>>0>d>>>0:0)break;a=b[e+8>>2]|0;if(!a){q=128;break e}else e=a}c=g-h&f;if(c>>>0<2147483647){a=T(c|0)|0;if((a|0)==((b[e>>2]|0)+(b[e+4>>2]|0)|0)){if((a|0)!=(-1|0)){h=c;g=a;q=145;break d}}else{e=a;q=136}}else c=0}else q=128;while(0);do if((q|0)==128){d=T(0)|0;if((d|0)!=(-1|0)?(c=d,o=b[980]|0,p=o+-1|0,c=((p&c|0)==0?0:(p+c&0-o)-c|0)+k|0,o=b[969]|0,p=c+o|0,c>>>0>m>>>0&c>>>0<2147483647):0){n=b[971]|0;if(n|0?p>>>0<=o>>>0|p>>>0>n>>>0:0){c=0;break}a=T(c|0)|0;if((a|0)==(d|0)){h=c;g=d;q=145;break d}else{e=a;q=136}}else c=0}while(0);do if((q|0)==136){d=0-c|0;if(!(i>>>0>c>>>0&(c>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){c=0;break}else{h=c;g=e;q=145;break d}a=b[981]|0;a=j-c+a&0-a;if(a>>>0>=2147483647){h=c;g=e;q=145;break d}if((T(a|0)|0)==(-1|0)){T(d|0)|0;c=0;break}else{h=a+c|0;g=e;q=145;break d}}while(0);b[972]=b[972]|4;q=143}else{c=0;q=143}while(0);if(((q|0)==143?k>>>0<2147483647:0)?(t=T(k|0)|0,p=T(0)|0,r=p-t|0,s=r>>>0>(m+40|0)>>>0,!((t|0)==(-1|0)|s^1|t>>>0

>>0&((t|0)!=(-1|0)&(p|0)!=(-1|0))^1)):0){h=s?r:c;g=t;q=145}if((q|0)==145){c=(b[969]|0)+h|0;b[969]=c;if(c>>>0>(b[970]|0)>>>0)b[970]=c;j=b[867]|0;f:do if(j){c=3892;while(1){a=b[c>>2]|0;d=b[c+4>>2]|0;if((g|0)==(a+d|0)){q=154;break}e=b[c+8>>2]|0;if(!e)break;else c=e}if(((q|0)==154?(u=c+4|0,(b[c+12>>2]&8|0)==0):0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){b[u>>2]=d+h;v=(b[864]|0)+h|0;t=j+8|0;t=(t&7|0)==0?0:0-t&7;u=j+t|0;t=v-t|0;b[867]=u;b[864]=t;b[u+4>>2]=t|1;b[j+v+4>>2]=40;b[868]=b[983];break}if(g>>>0<(b[865]|0)>>>0)b[865]=g;d=g+h|0;c=3892;while(1){if((b[c>>2]|0)==(d|0)){q=162;break}a=b[c+8>>2]|0;if(!a)break;else c=a}if((q|0)==162?(b[c+12>>2]&8|0)==0:0){b[c>>2]=g;l=c+4|0;b[l>>2]=(b[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;c=d+8|0;c=d+((c&7|0)==0?0:0-c&7)|0;k=l+m|0;i=c-l-m|0;b[l+4>>2]=m|3;g:do if((j|0)==(c|0)){v=(b[864]|0)+i|0;b[864]=v;b[867]=k;b[k+4>>2]=v|1}else{if((b[866]|0)==(c|0)){v=(b[863]|0)+i|0;b[863]=v;b[866]=k;b[k+4>>2]=v|1;b[k+v>>2]=v;break}a=b[c+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;h:do if(a>>>0<256){a=b[c+8>>2]|0;d=b[c+12>>2]|0;if((d|0)==(a|0)){b[861]=b[861]&~(1<>2]=d;b[d+8>>2]=a;break}}else{g=b[c+24>>2]|0;a=b[c+12>>2]|0;do if((a|0)==(c|0)){d=c+16|0;e=d+4|0;a=b[e>>2]|0;if(!a){a=b[d>>2]|0;if(!a){a=0;break}}else d=e;while(1){f=a+20|0;e=b[f>>2]|0;if(!e){f=a+16|0;e=b[f>>2]|0;if(!e)break;else{a=e;d=f}}else{a=e;d=f}}b[d>>2]=0}else{v=b[c+8>>2]|0;b[v+12>>2]=a;b[a+8>>2]=v}while(0);if(!g)break;d=b[c+28>>2]|0;e=3748+(d<<2)|0;do if((b[e>>2]|0)!=(c|0)){v=g+16|0;b[((b[v>>2]|0)==(c|0)?v:g+20|0)>>2]=a;if(!a)break h}else{b[e>>2]=a;if(a|0)break;b[862]=b[862]&~(1<>2]=g;d=c+16|0;e=b[d>>2]|0;if(e|0){b[a+16>>2]=e;b[e+24>>2]=a}d=b[d+4>>2]|0;if(!d)break;b[a+20>>2]=d;b[d+24>>2]=a}while(0);c=c+h|0;f=h+i|0}else f=i;c=c+4|0;b[c>>2]=b[c>>2]&-2;b[k+4>>2]=f|1;b[k+f>>2]=f;c=f>>>3;if(f>>>0<256){d=3484+(c<<1<<2)|0;a=b[861]|0;c=1<>2]|0}b[a>>2]=k;b[c+12>>2]=k;b[k+8>>2]=c;b[k+12>>2]=d;break}c=f>>>8;do if(!c)e=0;else{if(f>>>0>16777215){e=31;break}u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=f>>>(e+7|0)&1|e<<1}while(0);c=3748+(e<<2)|0;b[k+28>>2]=e;a=k+16|0;b[a+4>>2]=0;b[a>>2]=0;a=b[862]|0;d=1<>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break}c=b[c>>2]|0;i:do if((b[c+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(f|0)){c=a;break i}else{e=e<<1;c=a}}b[d>>2]=k;b[k+24>>2]=c;b[k+12>>2]=k;b[k+8>>2]=k;break g}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=k;b[u>>2]=k;b[k+8>>2]=v;b[k+12>>2]=c;b[k+24>>2]=0}while(0);v=l+8|0;A=w;return v|0}c=3892;while(1){a=b[c>>2]|0;if(a>>>0<=j>>>0?(v=a+(b[c+4>>2]|0)|0,v>>>0>j>>>0):0)break;c=b[c+8>>2]|0}f=v+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;c=a+8|0;d=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=d-t|0;b[867]=u;b[864]=t;b[u+4>>2]=t|1;b[g+d+4>>2]=40;b[868]=b[983];d=a+4|0;b[d>>2]=27;b[c>>2]=b[973];b[c+4>>2]=b[974];b[c+8>>2]=b[975];b[c+12>>2]=b[976];b[973]=g;b[974]=h;b[976]=0;b[975]=c;c=a+24|0;do{u=c;c=c+4|0;b[c>>2]=7}while((u+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;b[d>>2]=b[d>>2]&-2;b[j+4>>2]=g|1;b[a>>2]=g;c=g>>>3;if(g>>>0<256){d=3484+(c<<1<<2)|0;a=b[861]|0;c=1<>2]|0}b[a>>2]=j;b[c+12>>2]=j;b[j+8>>2]=c;b[j+12>>2]=d;break}c=g>>>8;if(c)if(g>>>0>16777215)e=31;else{u=(c+1048320|0)>>>16&8;v=c<>>16&4;v=v<>>16&2;e=14-(t|u|e)+(v<>>15)|0;e=g>>>(e+7|0)&1|e<<1}else e=0;d=3748+(e<<2)|0;b[j+28>>2]=e;b[j+20>>2]=0;b[f>>2]=0;c=b[862]|0;a=1<>2]=j;b[j+24>>2]=d;b[j+12>>2]=j;b[j+8>>2]=j;break}c=b[d>>2]|0;j:do if((b[c+4>>2]&-8|0)!=(g|0)){e=g<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=c+16+(e>>>31<<2)|0;a=b[d>>2]|0;if(!a)break;if((b[a+4>>2]&-8|0)==(g|0)){c=a;break j}else{e=e<<1;c=a}}b[d>>2]=j;b[j+24>>2]=c;b[j+12>>2]=j;b[j+8>>2]=j;break f}while(0);u=c+8|0;v=b[u>>2]|0;b[v+12>>2]=j;b[u>>2]=j;b[j+8>>2]=v;b[j+12>>2]=c;b[j+24>>2]=0}}else{v=b[865]|0;if((v|0)==0|g>>>0>>0)b[865]=g;b[973]=g;b[974]=h;b[976]=0;b[870]=b[979];b[869]=-1;b[874]=3484;b[873]=3484;b[876]=3492;b[875]=3492;b[878]=3500;b[877]=3500;b[880]=3508;b[879]=3508;b[882]=3516;b[881]=3516;b[884]=3524;b[883]=3524;b[886]=3532;b[885]=3532;b[888]=3540;b[887]=3540;b[890]=3548;b[889]=3548;b[892]=3556;b[891]=3556;b[894]=3564;b[893]=3564;b[896]=3572;b[895]=3572;b[898]=3580;b[897]=3580;b[900]=3588;b[899]=3588;b[902]=3596;b[901]=3596;b[904]=3604;b[903]=3604;b[906]=3612;b[905]=3612;b[908]=3620;b[907]=3620;b[910]=3628;b[909]=3628;b[912]=3636;b[911]=3636;b[914]=3644;b[913]=3644;b[916]=3652;b[915]=3652;b[918]=3660;b[917]=3660;b[920]=3668;b[919]=3668;b[922]=3676;b[921]=3676;b[924]=3684;b[923]=3684;b[926]=3692;b[925]=3692;b[928]=3700;b[927]=3700;b[930]=3708;b[929]=3708;b[932]=3716;b[931]=3716;b[934]=3724;b[933]=3724;b[936]=3732;b[935]=3732;v=h+-40|0;t=g+8|0;t=(t&7|0)==0?0:0-t&7;u=g+t|0;t=v-t|0;b[867]=u;b[864]=t;b[u+4>>2]=t|1;b[g+v+4>>2]=40;b[868]=b[983]}while(0);c=b[864]|0;if(c>>>0>m>>>0){t=c-m|0;b[864]=t;v=b[867]|0;u=v+m|0;b[867]=u;b[u+4>>2]=t|1;b[v+4>>2]=m|3;v=v+8|0;A=w;return v|0}}v=L()|0;b[v>>2]=12;v=0;A=w;return v|0}function N(a){a=a|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=b[865]|0;a=b[a+-4>>2]|0;c=a&-8;j=d+c|0;do if(!(a&1)){e=b[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+c|0;if(h>>>0>>0)return;if((b[866]|0)==(h|0)){a=j+4|0;c=b[a>>2]|0;if((c&3|0)!=3){i=h;c=g;break}b[863]=g;b[a>>2]=c&-2;b[h+4>>2]=g|1;b[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=b[h+8>>2]|0;c=b[h+12>>2]|0;if((c|0)==(a|0)){b[861]=b[861]&~(1<>2]=c;b[c+8>>2]=a;i=h;c=g;break}}f=b[h+24>>2]|0;a=b[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){a=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0}else{i=b[h+8>>2]|0;b[i+12>>2]=a;b[a+8>>2]=i}while(0);if(f){c=b[h+28>>2]|0;d=3748+(c<<2)|0;if((b[d>>2]|0)==(h|0)){b[d>>2]=a;if(!a){b[862]=b[862]&~(1<>2]|0)==(h|0)?i:f+20|0)>>2]=a;if(!a){i=h;c=g;break}}b[a+24>>2]=f;c=h+16|0;d=b[c>>2]|0;if(d|0){b[a+16>>2]=d;b[d+24>>2]=a}c=b[c+4>>2]|0;if(c){b[a+20>>2]=c;b[c+24>>2]=a;i=h;c=g}else{i=h;c=g}}else{i=h;c=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=b[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((b[867]|0)==(j|0)){j=(b[864]|0)+c|0;b[864]=j;b[867]=i;b[i+4>>2]=j|1;if((i|0)!=(b[866]|0))return;b[866]=0;b[863]=0;return}if((b[866]|0)==(j|0)){j=(b[863]|0)+c|0;b[863]=j;b[866]=h;b[i+4>>2]=j|1;b[h+j>>2]=j;return}f=(e&-8)+c|0;d=e>>>3;do if(e>>>0<256){c=b[j+8>>2]|0;a=b[j+12>>2]|0;if((a|0)==(c|0)){b[861]=b[861]&~(1<>2]=a;b[a+8>>2]=c;break}}else{g=b[j+24>>2]|0;a=b[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;d=c+4|0;a=b[d>>2]|0;if(!a){a=b[c>>2]|0;if(!a){d=0;break}}else c=d;while(1){e=a+20|0;d=b[e>>2]|0;if(!d){e=a+16|0;d=b[e>>2]|0;if(!d)break;else{a=d;c=e}}else{a=d;c=e}}b[c>>2]=0;d=a}else{d=b[j+8>>2]|0;b[d+12>>2]=a;b[a+8>>2]=d;d=a}while(0);if(g|0){a=b[j+28>>2]|0;c=3748+(a<<2)|0;if((b[c>>2]|0)==(j|0)){b[c>>2]=d;if(!d){b[862]=b[862]&~(1<>2]|0)==(j|0)?e:g+20|0)>>2]=d;if(!d)break}b[d+24>>2]=g;a=j+16|0;c=b[a>>2]|0;if(c|0){b[d+16>>2]=c;b[c+24>>2]=d}a=b[a+4>>2]|0;if(a|0){b[d+20>>2]=a;b[a+24>>2]=d}}}while(0);b[i+4>>2]=f|1;b[h+f>>2]=f;if((i|0)==(b[866]|0)){b[863]=f;return}}else{b[a>>2]=e&-2;b[i+4>>2]=c|1;b[h+c>>2]=c;f=c}a=f>>>3;if(f>>>0<256){d=3484+(a<<1<<2)|0;c=b[861]|0;a=1<>2]|0}b[c>>2]=i;b[a+12>>2]=i;b[i+8>>2]=a;b[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)e=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;e=14-(g|h|e)+(j<>>15)|0;e=f>>>(e+7|0)&1|e<<1}else e=0;a=3748+(e<<2)|0;b[i+28>>2]=e;b[i+20>>2]=0;b[i+16>>2]=0;c=b[862]|0;d=1<>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i}else{a=b[a>>2]|0;b:do if((b[a+4>>2]&-8|0)!=(f|0)){e=f<<((e|0)==31?0:25-(e>>>1)|0);while(1){d=a+16+(e>>>31<<2)|0;c=b[d>>2]|0;if(!c)break;if((b[c+4>>2]&-8|0)==(f|0)){a=c;break b}else{e=e<<1;a=c}}b[d>>2]=i;b[i+24>>2]=a;b[i+12>>2]=i;b[i+8>>2]=i;break a}while(0);h=a+8|0;j=b[h>>2]|0;b[j+12>>2]=i;b[h>>2]=i;b[i+8>>2]=j;b[i+12>>2]=a;b[i+24>>2]=0}while(0);j=(b[869]|0)+-1|0;b[869]=j;if(j|0)return;a=3900;while(1){a=b[a>>2]|0;if(!a)break;else a=a+8|0}b[869]=-1;return}function O(a,c){a=a|0;c=c|0;var d=0;if(a){d=m(c,a)|0;if((c|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(c|0)?d:-1}else d=0;a=M(d)|0;if(!a)return a|0;if(!(b[a+-4>>2]&3))return a|0;S(a|0,0,d|0)|0;return a|0}function P(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){o(b>>>c|0);return a>>>c|(b&(1<>>c-32|0}function Q(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){o(b<>>32-c|0);return a<=8192){s(c|0,d|0,e|0)|0;return c|0}h=c|0;g=c+e|0;if((c&3)==(d&3)){while(c&3){if(!e)return h|0;a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((c|0)<=(f|0)){b[c>>2]=b[d>>2];b[c+4>>2]=b[d+4>>2];b[c+8>>2]=b[d+8>>2];b[c+12>>2]=b[d+12>>2];b[c+16>>2]=b[d+16>>2];b[c+20>>2]=b[d+20>>2];b[c+24>>2]=b[d+24>>2];b[c+28>>2]=b[d+28>>2];b[c+32>>2]=b[d+32>>2];b[c+36>>2]=b[d+36>>2];b[c+40>>2]=b[d+40>>2];b[c+44>>2]=b[d+44>>2];b[c+48>>2]=b[d+48>>2];b[c+52>>2]=b[d+52>>2];b[c+56>>2]=b[d+56>>2];b[c+60>>2]=b[d+60>>2];c=c+64|0;d=d+64|0}while((c|0)<(e|0)){b[c>>2]=b[d>>2];c=c+4|0;d=d+4|0}}else{e=g-4|0;while((c|0)<(e|0)){a[c>>0]=a[d>>0]|0;a[c+1>>0]=a[d+1>>0]|0;a[c+2>>0]=a[d+2>>0]|0;a[c+3>>0]=a[d+3>>0]|0;c=c+4|0;d=d+4|0}}while((c|0)<(g|0)){a[c>>0]=a[d>>0]|0;c=c+1|0;d=d+1|0}return h|0}function S(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=c+e|0;d=d&255;if((e|0)>=67){while(c&3){a[c>>0]=d;c=c+1|0}f=h&-4|0;i=d|d<<8|d<<16|d<<24;g=f-64|0;while((c|0)<=(g|0)){b[c>>2]=i;b[c+4>>2]=i;b[c+8>>2]=i;b[c+12>>2]=i;b[c+16>>2]=i;b[c+20>>2]=i;b[c+24>>2]=i;b[c+28>>2]=i;b[c+32>>2]=i;b[c+36>>2]=i;b[c+40>>2]=i;b[c+44>>2]=i;b[c+48>>2]=i;b[c+52>>2]=i;b[c+56>>2]=i;b[c+60>>2]=i;c=c+64|0}while((c|0)<(f|0)){b[c>>2]=i;c=c+4|0}}while((c|0)<(h|0)){a[c>>0]=d;c=c+1|0}return h-e|0}function T(a){a=a|0;var c=0,e=0,f=0;f=r()|0;e=b[d>>2]|0;c=e+a|0;if((a|0)>0&(c|0)<(e|0)|(c|0)<0){u(c|0)|0;q(12);return -1}if((c|0)>(f|0))if(!(t(c|0)|0)){q(12);return -1}b[d>>2]=c;return e|0} - -// EMSCRIPTEN_END_FUNCS -return{_bitshift64Lshr:P,_bitshift64Shl:Q,_calloc:O,_emscripten_replace_memory:D,_free:N,_h3IsValid:J,_h3ToParent:K,_malloc:M,_memcpy:R,_memset:S,_sbrk:T,establishStackSpace:H,stackAlloc:E,stackRestore:G,stackSave:F}}) - - -// EMSCRIPTEN_END_ASM -(asmGlobalArg,asmLibraryArg,buffer);var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _calloc=Module["_calloc"]=asm["_calloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _free=Module["_free"]=asm["_free"];var _h3IsValid=Module["_h3IsValid"]=asm["_h3IsValid"];var _h3ToParent=Module["_h3ToParent"]=asm["_h3ToParent"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memset=Module["_memset"]=asm["_memset"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];Module["asm"]=asm;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["getTempRet0"]=getTempRet0;if(memoryInitializer){if(!isDataURI(memoryInitializer)){memoryInitializer=locateFile(memoryInitializer)}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=readBinary(memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")};var doBrowserLoad=function(){readAsync(memoryInitializer,applyMemoryInitializer,function(){throw"could not load memory initializer "+memoryInitializer})};var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){var useRequest=function(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)};if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); - - - - return libh3 -} -)(typeof libh3 === 'object' ? libh3 : {}); -export default libh3; \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/test/clustering.test.js b/clouds/snowflake/libraries/javascript/test/clustering.test.js index 774ab1a32..4a2166d60 100644 --- a/clouds/snowflake/libraries/javascript/test/clustering.test.js +++ b/clouds/snowflake/libraries/javascript/test/clustering.test.js @@ -4,4 +4,5 @@ test('clustering library defined', () => { expect(clusteringLib.featureCollection).toBeDefined(); expect(clusteringLib.feature).toBeDefined(); expect(clusteringLib.clustersKmeans).toBeDefined(); + expect(clusteringLib.prioritizeDistinctSort).toBeDefined(); }); \ No newline at end of file diff --git a/clouds/snowflake/libraries/javascript/test/h3.test.js b/clouds/snowflake/libraries/javascript/test/h3.test.js index ae037da2e..ebf1929ab 100644 --- a/clouds/snowflake/libraries/javascript/test/h3.test.js +++ b/clouds/snowflake/libraries/javascript/test/h3.test.js @@ -1,38 +1,21 @@ -const h3FromLonglatLib = require('../build/h3_fromlonglat'); -const centerLib = require('../build/h3_center'); const compactLib = require('../build/h3_compact'); -const distanceLib = require('../build/h3_distance'); const isValidLib = require('../build/h3_isvalid'); const hexRingLib = require('../build/h3_hexring'); const isPentagonLib = require('../build/h3_ispentagon'); -const kringLib = require('../build/h3_kring'); -const kringDistancesLib = require('../build/h3_kring_distances'); const h3PolyfillLib = require('../build/h3_polyfill'); const boundaryLib = require('../build/h3_boundary'); -const toChildrenLib = require('../build/h3_tochildren'); -const toParentLib = require('../build/h3_toparent'); +const kringDistancesLib = require('../build/h3_kring_distances'); const uncompactLib = require('../build/h3_uncompact'); test('h3 library defined', () => { - expect(h3FromLonglatLib.geoToH3).toBeDefined(); - expect(centerLib.h3IsValid).toBeDefined(); - expect(centerLib.h3ToGeo).toBeDefined(); expect(compactLib.compact).toBeDefined(); - expect(distanceLib.h3Distance).toBeDefined(); expect(isValidLib.h3IsValid).toBeDefined(); expect(hexRingLib.hexRing).toBeDefined(); expect(hexRingLib.h3IsValid).toBeDefined(); expect(isPentagonLib.h3IsPentagon).toBeDefined(); - expect(kringLib.kRing).toBeDefined(); - expect(kringLib.h3IsValid).toBeDefined(); - expect(kringDistancesLib.kRingDistances).toBeDefined(); - expect(kringDistancesLib.h3IsValid).toBeDefined(); - expect(h3PolyfillLib.polyfill).toBeDefined(); + expect(h3PolyfillLib.h3ToGeoBoundary).toBeDefined(); expect(boundaryLib.h3ToGeoBoundary).toBeDefined(); expect(boundaryLib.h3IsValid).toBeDefined(); - expect(toChildrenLib.h3ToChildren).toBeDefined(); - expect(toChildrenLib.h3IsValid).toBeDefined(); - expect(toParentLib.h3ToParent).toBeDefined(); - expect(toParentLib.h3IsValid).toBeDefined(); + expect(kringDistancesLib.h3Distance).toBeDefined(); expect(uncompactLib.uncompact).toBeDefined(); }); \ No newline at end of file diff --git a/clouds/snowflake/modules/doc/clustering/ST_CLUSTERKMEANS.md b/clouds/snowflake/modules/doc/clustering/ST_CLUSTERKMEANS.md index 7df42d4b5..28e98196d 100644 --- a/clouds/snowflake/modules/doc/clustering/ST_CLUSTERKMEANS.md +++ b/clouds/snowflake/modules/doc/clustering/ST_CLUSTERKMEANS.md @@ -9,7 +9,7 @@ ST_CLUSTERKMEANS(geog [, numberOfClusters]) Takes a set of points as input and partitions them into clusters using the k-means algorithm. Returns an array of tuples with the cluster index for each of the input features and the input geometry. * `geojsons`: `ARRAY` points to be clustered. -* `numberOfClusters` (optional): `INT` numberOfClusters that will be generated. By default `numberOfClusters` is `Math.sqrt(/2)`. +* `numberOfClusters` (optional): `INT` numberOfClusters that will be generated. By default `numberOfClusters` is `Math.sqrt(/2)`. The output number of cluster cannot be greater to the number of distinct points of the `geojsons`. **Return type** diff --git a/clouds/snowflake/modules/doc/h3/H3_POLYFILL.md b/clouds/snowflake/modules/doc/h3/H3_POLYFILL.md index 487e47b74..b9dee128b 100644 --- a/clouds/snowflake/modules/doc/h3/H3_POLYFILL.md +++ b/clouds/snowflake/modules/doc/h3/H3_POLYFILL.md @@ -1,21 +1,37 @@ ## H3_POLYFILL ```sql:signature -H3_POLYFILL(geography, resolution) +H3_POLYFILL(geography, resolution [, mode]) ``` **Description** -Returns an array with all the H3 cell indexes **with centers** contained in a given polygon. It will return `null` on error (invalid geography type or resolution out of bounds). +Returns an array with all H3 cell indexes contained in the given polygon. There are three modes which decide if a H3 cell is contained in the polygon: -* `geography`: `GEOGRAPHY` **polygon** or **multipolygon** representing the shape to cover. +* `geography`: `GEOGRAPHY` **polygon** or **multipolygon** representing the shape to cover. **GeometryCollections** are also allowed but they should contain **polygon** or **multipolygon** geographies. Non-Polygon types will not raise an error but will be ignored instead. * `resolution`: `INT` number between 0 and 15 with the [H3 resolution](https://h3geo.org/docs/core-library/restable). +* `mode`: `STRING` ``. Optional. Defaults to 'center' mode. + * `center` The center point of the H3 cell must be within the polygon + * `contains` The H3 cell must be fully contained within the polygon (least inclusive) + * `intersects` The H3 cell intersects in any way with the polygon (most inclusive) + +Mode `center`: + +![](h3_polyfill_mode_center.png) + +Mode `intersects`: + +![](h3_polyfill_mode_intersects.png) + +Mode `contains`: + +![](h3_polyfill_mode_contains.png) **Return type** -`ARRAY` +`ARRAY` -**Example** +**Examples** ```sql SELECT carto.H3_POLYFILL( @@ -26,3 +42,36 @@ SELECT carto.H3_POLYFILL( -- 8453945ffffffff -- ... ``` + +```sql +SELECT carto.H3_POLYFILL( + TO_GEOGRAPHY('POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))'), 4, 'center'); +-- 842da29ffffffff +-- 843f725ffffffff +-- 843eac1ffffffff +-- 8453945ffffffff +-- ... +``` + +```sql +SELECT carto.H3_POLYFILL( + TO_GEOGRAPHY('POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))'), 4, 'contains'); +-- 843f0cbffffffff +-- 842da01ffffffff +-- 843e467ffffffff +-- 843ea99ffffffff +-- 843f0c3ffffffff +-- ... +``` + +```sql +SELECT carto.H3_POLYFILL( + TO_GEOGRAPHY('POLYGON ((30 1040 4020 4010 2030 10))')4'intersects'); +-- 843f0cbffffffff +-- 842da01ffffffff +-- 843e467ffffffff +-- 843ea99ffffffff +-- 843f0c3ffffffff +-- 843ea91ffffffff +-- ... +``` diff --git a/clouds/snowflake/modules/doc/h3/images/H3_POLYFILL_MODE_center.png b/clouds/snowflake/modules/doc/h3/images/H3_POLYFILL_MODE_center.png new file mode 100644 index 0000000000000000000000000000000000000000..1b47ba3ccecd5a3281889e53f1a0310c457d0997 GIT binary patch literal 240546 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

M2yP5Ugc+ba#1* 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

  • D7Fo;FHMsNpruB=Sh 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 z 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

    ez{%q__na2T*et|*(JKy`=fn5bkxQTL!6PqKW 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 BJV*cl literal 0 HcmV?d00001 diff --git a/clouds/snowflake/modules/doc/h3/images/H3_POLYFILL_MODE_intersects.png b/clouds/snowflake/modules/doc/h3/images/H3_POLYFILL_MODE_intersects.png new file mode 100644 index 0000000000000000000000000000000000000000..b5b98d05406d730178c9f0abd9cfcaaedfefc634 GIT binary patch literal 138574 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�a5>CX?09R72KgjwBNJaWb-)6jIk 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¯t0R0~y5RKjU@4`=>pkMs5*9pAyCG^U5@bn1j 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 AeE clusteringLib.feature(JSON.parse(x)))); + const featuresCollection = clusteringLib.featureCollection(clusteringLib.prioritizeDistinctSort(GEOJSONS).map(x => clusteringLib.feature(JSON.parse(x)))); clusteringLib.clustersKmeans(featuresCollection, options); const cluster = []; featuresCollection.features.forEach(function(item, index, array) { diff --git a/clouds/snowflake/modules/sql/h3/H3_BOUNDARY.sql b/clouds/snowflake/modules/sql/h3/H3_BOUNDARY.sql index 8eac89bce..701cfa3fb 100644 --- a/clouds/snowflake/modules/sql/h3/H3_BOUNDARY.sql +++ b/clouds/snowflake/modules/sql/h3/H3_BOUNDARY.sql @@ -1,6 +1,8 @@ ---------------------------- -- Copyright (C) 2021 CARTO ---------------------------- +-- TODO: Re-implement this using SF's native H3_CELL_TO_BOUNDARY when they improve performance +-- Shortcut story/chore ID: 398796 CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_BOUNDARY (index STRING) diff --git a/clouds/snowflake/modules/sql/h3/H3_CENTER.sql b/clouds/snowflake/modules/sql/h3/H3_CENTER.sql index 4e004158b..1ea5003d5 100644 --- a/clouds/snowflake/modules/sql/h3/H3_CENTER.sql +++ b/clouds/snowflake/modules/sql/h3/H3_CENTER.sql @@ -1,31 +1,11 @@ ----------------------------- --- Copyright (C) 2023 CARTO ----------------------------- - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_CENTER -(index STRING) -RETURNS STRING -LANGUAGE JAVASCRIPT -IMMUTABLE -AS $$ - if (!INDEX) { - return null; - } - - @@SF_LIBRARY_H3_CENTER@@ - - if (!h3CenterLib.h3IsValid(INDEX)) { - return null; - } - - const center = h3CenterLib.h3ToGeo(INDEX); - return `POINT(${center[1]} ${center[0]})`; -$$; +-------------------------------- +-- Copyright (C) 2023-2024 CARTO +-------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_CENTER (index STRING) RETURNS GEOGRAPHY IMMUTABLE AS $$ - TRY_TO_GEOGRAPHY(@@SF_SCHEMA@@._H3_CENTER(INDEX)) + IFF(@@SF_SCHEMA@@.H3_ISVALID(INDEX), H3_CELL_TO_POINT(INDEX), NULL) $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_COMPACT.sql b/clouds/snowflake/modules/sql/h3/H3_COMPACT.sql index 138cd32f4..d5afa8d6f 100644 --- a/clouds/snowflake/modules/sql/h3/H3_COMPACT.sql +++ b/clouds/snowflake/modules/sql/h3/H3_COMPACT.sql @@ -1,6 +1,6 @@ ----------------------------- +--------------------------- -- Copyright (C) 2021 CARTO ----------------------------- +--------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_COMPACT (h3Array ARRAY) diff --git a/clouds/snowflake/modules/sql/h3/H3_DISTANCE.sql b/clouds/snowflake/modules/sql/h3/H3_DISTANCE.sql index 40130bf7d..7d3612a4d 100644 --- a/clouds/snowflake/modules/sql/h3/H3_DISTANCE.sql +++ b/clouds/snowflake/modules/sql/h3/H3_DISTANCE.sql @@ -1,30 +1,15 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_DISTANCE -(index1 STRING, index2 STRING) -RETURNS STRING -LANGUAGE JAVASCRIPT -IMMUTABLE -AS $$ - if (!INDEX1 || !INDEX2) { - return null; - } - - @@SF_LIBRARY_H3_DISTANCE@@ - - let dist = h3DistanceLib.h3Distance(INDEX1, INDEX2); - if (dist < 0) { - dist = null; - } - return dist; -$$; +-------------------------------- +-- Copyright (C) 2021-2024 CARTO +-------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_DISTANCE -(index1 STRING, index2 STRING) +(INDEX1 STRING, INDEX2 STRING) RETURNS BIGINT IMMUTABLE AS $$ - CAST(@@SF_SCHEMA@@._H3_DISTANCE(INDEX1, INDEX2) AS BIGINT) + IFF( + @@SF_SCHEMA@@.H3_ISVALID(INDEX1) AND @@SF_SCHEMA@@.H3_ISVALID(INDEX2) AND H3_GET_RESOLUTION(INDEX1) = H3_GET_RESOLUTION(INDEX2), + CAST(H3_GRID_DISTANCE(INDEX1, INDEX2) AS BIGINT), + NULL + ) $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_FROMGEOGPOINT.sql b/clouds/snowflake/modules/sql/h3/H3_FROMGEOGPOINT.sql index 159ce5f68..069551dd8 100644 --- a/clouds/snowflake/modules/sql/h3/H3_FROMGEOGPOINT.sql +++ b/clouds/snowflake/modules/sql/h3/H3_FROMGEOGPOINT.sql @@ -1,13 +1,13 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2021-2024 CARTO +-------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_FROMGEOGPOINT (geog GEOGRAPHY, resolution INT) RETURNS STRING IMMUTABLE AS $$ - IFF(ST_NPOINTS(geog) = 1, - @@SF_SCHEMA@@.H3_FROMLONGLAT(ST_X(GEOG), ST_Y(GEOG), CAST(RESOLUTION AS DOUBLE)), - null) + IFF(ST_NPOINTS(GEOG) = 1 AND RESOLUTION >= 0 AND RESOLUTION <= 15, + H3_POINT_TO_CELL_STRING(GEOG, RESOLUTION), + NULL) $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_FROMLONGLAT.sql b/clouds/snowflake/modules/sql/h3/H3_FROMLONGLAT.sql index 1e070ac48..592b58683 100644 --- a/clouds/snowflake/modules/sql/h3/H3_FROMLONGLAT.sql +++ b/clouds/snowflake/modules/sql/h3/H3_FROMLONGLAT.sql @@ -1,27 +1,13 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_FROMLONGLAT -(longitude DOUBLE, latitude DOUBLE, resolution DOUBLE) -RETURNS STRING -LANGUAGE JAVASCRIPT -IMMUTABLE -AS $$ - if (LONGITUDE == null || LATITUDE == null || RESOLUTION == null) { - return null; - } - - @@SF_LIBRARY_H3_FROMLONGLAT@@ - - const index = h3FromlonglatLib.geoToH3(Number(LATITUDE), Number(LONGITUDE), Number(RESOLUTION)); - return index; -$$; +--------------------------------- +-- Copyright (C) 2021-2024 CARTO +--------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_FROMLONGLAT (longitude DOUBLE, latitude DOUBLE, resolution INT) RETURNS STRING IMMUTABLE AS $$ - @@SF_SCHEMA@@._H3_FROMLONGLAT(LONGITUDE, LATITUDE, CAST(RESOLUTION AS DOUBLE)) + IFF(LONGITUDE IS NOT NULL AND LATITUDE IS NOT NULL AND RESOLUTION >= 0 AND RESOLUTION <= 15, + H3_LATLNG_TO_CELL_STRING(LATITUDE, LONGITUDE, RESOLUTION), + NULL) $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_INT_TOSTRING.sql b/clouds/snowflake/modules/sql/h3/H3_INT_TOSTRING.sql index 8069709ce..ad4ffdf03 100644 --- a/clouds/snowflake/modules/sql/h3/H3_INT_TOSTRING.sql +++ b/clouds/snowflake/modules/sql/h3/H3_INT_TOSTRING.sql @@ -1,8 +1,12 @@ +--------------------------------- +-- Copyright (C) 2022-2024 CARTO +--------------------------------- + CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_INT_TOSTRING ( h3int INT ) RETURNS STRING AS $$ - TO_VARCHAR(h3int, 'xxxxxxxxxxxxxxx') + H3_INT_TO_STRING(h3int) $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_KRING.sql b/clouds/snowflake/modules/sql/h3/H3_KRING.sql index 8b7f6774f..ed50befc6 100644 --- a/clouds/snowflake/modules/sql/h3/H3_KRING.sql +++ b/clouds/snowflake/modules/sql/h3/H3_KRING.sql @@ -1,30 +1,15 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_KRING -(origin STRING, size DOUBLE) -RETURNS ARRAY -LANGUAGE JAVASCRIPT -IMMUTABLE -AS $$ - if (SIZE == null || SIZE < 0) { - throw new Error('Invalid input size') - } - - @@SF_LIBRARY_H3_KRING@@ - - if (!h3KringLib.h3IsValid(ORIGIN)) { - throw new Error('Invalid input origin') - } - - return h3KringLib.kRing(ORIGIN, parseInt(SIZE)); -$$; +--------------------------------- +-- Copyright (C) 2021-2024 CARTO +--------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_KRING (origin STRING, size INT) RETURNS ARRAY IMMUTABLE AS $$ - @@SF_SCHEMA@@._H3_KRING(ORIGIN, CAST(SIZE AS DOUBLE)) + CASE + WHEN SIZE IS NULL or SIZE < 0 THEN @@SF_SCHEMA@@._CARTO_ARRAY_ERROR('Invalid input size') + WHEN NOT @@SF_SCHEMA@@.H3_ISVALID(ORIGIN) THEN @@SF_SCHEMA@@._CARTO_ARRAY_ERROR('Invalid input origin') + ELSE H3_GRID_DISK(ORIGIN, SIZE) + END $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_KRING_DISTANCES.sql b/clouds/snowflake/modules/sql/h3/H3_KRING_DISTANCES.sql index 474d090dc..8d5f68540 100644 --- a/clouds/snowflake/modules/sql/h3/H3_KRING_DISTANCES.sql +++ b/clouds/snowflake/modules/sql/h3/H3_KRING_DISTANCES.sql @@ -1,32 +1,19 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- +--------------------------------- +-- Copyright (C) 2021-2024 CARTO +--------------------------------- CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_KRING_DISTANCES -(origin STRING, size DOUBLE) +(origin STRING, hexarray ARRAY) RETURNS ARRAY LANGUAGE JAVASCRIPT IMMUTABLE AS $$ - if (SIZE == null || SIZE < 0) { - throw new Error('Invalid input size') - } @@SF_LIBRARY_H3_KRING_DISTANCES@@ - if (!h3KringDistancesLib.h3IsValid(ORIGIN)) { - throw new Error('Invalid input origin') - } - - const kringDistances = h3KringDistancesLib.kRingDistances(ORIGIN, parseInt(SIZE)); - const output = []; - for (let distance = 0; distance <= parseInt(SIZE); distance++) { - const indexes = kringDistances[distance]; - for (const index of indexes) { - output.push({ index, distance }); - } - } - return output; + var results = [] + HEXARRAY.forEach(hex => results.push({"index": hex, "distance": h3KringDistancesLib.h3Distance(ORIGIN, hex)})) + return results $$; CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_KRING_DISTANCES @@ -34,5 +21,9 @@ CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_KRING_DISTANCES RETURNS ARRAY IMMUTABLE AS $$ - @@SF_SCHEMA@@._H3_KRING_DISTANCES(ORIGIN, CAST(SIZE AS DOUBLE)) + CASE + WHEN SIZE IS NULL or SIZE < 0 THEN @@SF_SCHEMA@@._CARTO_ARRAY_ERROR('Invalid input size') + WHEN NOT @@SF_SCHEMA@@.H3_ISVALID(ORIGIN) THEN @@SF_SCHEMA@@._CARTO_ARRAY_ERROR('Invalid input origin') + ELSE @@SF_SCHEMA@@._H3_KRING_DISTANCES(origin, H3_GRID_DISK(ORIGIN, SIZE)) + END $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_POLYFILL.sql b/clouds/snowflake/modules/sql/h3/H3_POLYFILL.sql index 4da4fb24d..d0cb4e760 100644 --- a/clouds/snowflake/modules/sql/h3/H3_POLYFILL.sql +++ b/clouds/snowflake/modules/sql/h3/H3_POLYFILL.sql @@ -1,77 +1,151 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2021-2024 CARTO +-------------------------------- -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_POLYFILL -(geojson STRING, input_resolution DOUBLE) -RETURNS ARRAY +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._HAS_POLYGON_JS +(geojson STRING) +RETURNS BOOLEAN LANGUAGE JAVASCRIPT IMMUTABLE AS $$ - if (!GEOJSON || INPUT_RESOLUTION == null) { - return []; + let inputGeoJSON = JSON.parse(GEOJSON); + let geometries = inputGeoJSON.geometries ? inputGeoJSON.geometries : [inputGeoJSON] // geometrycollection or regular feature geometry + for (let g of geometries) { + if (g.type === 'Polygon' || g.type === 'MultiPolygon') { + return true + } } + return false +$$; + +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._HAS_POLYGON +(geog GEOGRAPHY) +RETURNS BOOLEAN +LANGUAGE SQL +IMMUTABLE +AS $$ + @@SF_SCHEMA@@._HAS_POLYGON_JS(CAST(ST_ASGEOJSON(GEOG) AS STRING)) +$$; + +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._FILTER_GEOG_JS +(geojson STRING) +RETURNS STRING +LANGUAGE JAVASCRIPT +IMMUTABLE +AS $$ + // remove non-polygons and split polygons >= 180 degrees + // output is a always MULTIPOLYGON + + let inputGeoJSON = JSON.parse(GEOJSON); @@SF_LIBRARY_H3_POLYFILL@@ - const resolution = Number(INPUT_RESOLUTION); - if (resolution < 0 || resolution > 15) { - return []; - } + const westernHemisphere = h3PolyfillLib.polygon([[ [-180, 90], [0, 90], [0, -90], [-180, -90], [-180, 90]]]); + const easternHemisphere = h3PolyfillLib.polygon([[ [0, 90], [180, 90], [180, -90], [0, -90], [0, 90] ]]); - const bboxA = [-180, -90, 0, 90] - const bboxB = [0, -90, 180, 90] - const featureGeometry = JSON.parse(GEOJSON) - let polygonCoordinatesA = []; - let polygonCoordinatesB = []; - switch(featureGeometry.type) { - case 'GeometryCollection': - featureGeometry.geometries.forEach(function (geom) { - if (geom.type === 'MultiPolygon') { - var clippedGeometryA = h3PolyfillLib.bboxClip(geom, bboxA).geometry; - polygonCoordinatesA = polygonCoordinatesA.concat(clippedGeometryA.coordinates); - var clippedGeometryB = h3PolyfillLib.bboxClip(geom, bboxB).geometry; - polygonCoordinatesB = polygonCoordinatesB.concat(clippedGeometryB.coordinates); - } else if (geom.type === 'Polygon') { - var clippedGeometryA = h3PolyfillLib.bboxClip(geom, bboxA).geometry; - polygonCoordinatesA = polygonCoordinatesA.concat([clippedGeometryA.coordinates]); - var clippedGeometryB = h3PolyfillLib.bboxClip(geom, bboxB).geometry; - polygonCoordinatesB = polygonCoordinatesB.concat([clippedGeometryB.coordinates]); - } - }); - break; - case 'MultiPolygon': - var clippedGeometryA = h3PolyfillLib.bboxClip(featureGeometry, bboxA).geometry; - polygonCoordinatesA = clippedGeometryA.coordinates; - var clippedGeometryB = h3PolyfillLib.bboxClip(featureGeometry, bboxB).geometry; - polygonCoordinatesB = clippedGeometryB.coordinates; - break; - case 'Polygon': - var clippedGeometryA = h3PolyfillLib.bboxClip(featureGeometry, bboxA).geometry; - polygonCoordinatesA = [clippedGeometryA.coordinates]; - var clippedGeometryB = h3PolyfillLib.bboxClip(featureGeometry, bboxB).geometry; - polygonCoordinatesB = [clippedGeometryB.coordinates]; - break; - default: - return []; - } + let polygons = []; + let geometries = inputGeoJSON.geometries ? inputGeoJSON.geometries : [inputGeoJSON] - if (polygonCoordinatesA.length + polygonCoordinatesB.length === 0) { - return []; - } + geometries.forEach(g => { + if (g.type === 'Polygon') { + polygons.push({type: 'Feature', geometry: g}) + } + else if (g.type === 'MultiPolygon') { + g.coordinates.forEach(ring => polygons.push({type: 'Feature', geometry: {type: 'Polygon', coordinates: ring}})) + } + }); + + + let intersections = []; + + let intersectAndPush = (hemisphere, poly) => { + const intersection = h3PolyfillLib.intersect(poly, hemisphere); + if (intersection) { + if (intersection.geometry.type === 'Polygon') { + intersections.push(intersection); + } + else if (intersection.geometry.type === 'MultiPolygon') { + intersection.geometry.coordinates.forEach(ring => intersections.push({type: 'Feature', geometry: {type: 'Polygon', coordinates: ring}})) + } + } + }; + + polygons.forEach(p => { + intersectAndPush(westernHemisphere, p); + intersectAndPush(easternHemisphere, p); + }) + + return JSON.stringify(h3PolyfillLib.multiPolygon(intersections.map(i => i.geometry.coordinates)).geometry) +$$; + +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._FILTER_GEOG +(geog GEOGRAPHY) +RETURNS GEOGRAPHY +LANGUAGE SQL +IMMUTABLE +AS $$ + TO_GEOGRAPHY(@@SF_SCHEMA@@._FILTER_GEOG_JS(CAST(ST_ASGEOJSON(GEOG) AS STRING))) +$$; + +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_POLYFILL_CONTAINS +(geojson STRING, indexes ARRAY) +RETURNS ARRAY +LANGUAGE JAVASCRIPT +IMMUTABLE +AS $$ + let results = [] + let inputGeoJSON = JSON.parse(GEOJSON); + + @@SF_LIBRARY_H3_POLYFILL@@ + + // @@SF_SCHEMA@@.ST_BUFFER demotes MULTIPOLYGONs to POLYGON if it only has one ring. So we check again here. + let polygons = inputGeoJSON.type === 'MultiPolygon' ? inputGeoJSON.coordinates.map(ring => h3PolyfillLib.polygon(ring)) : [h3PolyfillLib.polygon(inputGeoJSON.coordinates)] + + + INDEXES.forEach(h3Index => { + polygons.some(p => { + if (h3PolyfillLib.booleanContains(p, h3PolyfillLib.polygon([h3PolyfillLib.h3ToGeoBoundary(h3Index, true)]))) { + results.push(h3Index) + } + }) + }) + return results +$$; + +CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@._H3_POLYFILL_INTERSECTS_FILTER +(h3Indexes ARRAY, geojson STRING) +RETURNS ARRAY +LANGUAGE JAVASCRIPT +IMMUTABLE +AS $$ + + let results = [] + let inputGeoJSON = JSON.parse(GEOJSON); + + @@SF_LIBRARY_H3_POLYFILL@@ + + // @@SF_SCHEMA@@.ST_BUFFER demotes MULTIPOLYGONs to POLYGON if it only has one ring. So we check again here. + let polygons = inputGeoJSON.type === 'MultiPolygon' ? inputGeoJSON.coordinates.map(ring => h3PolyfillLib.polygon(ring)) : [h3PolyfillLib.polygon(inputGeoJSON.coordinates)] + + H3INDEXES.forEach(h3Index => { + if (polygons.some(p => h3PolyfillLib.booleanIntersects(p, h3PolyfillLib.polygon([h3PolyfillLib.h3ToGeoBoundary(h3Index, true)])))) { + results.push(h3Index) + } + }) + return [...new Set(results)] +$$; - let hexesA = polygonCoordinatesA.reduce( - (acc, coordinates) => acc.concat(h3PolyfillLib.polyfill(coordinates, resolution, true)), - [] - ).filter(h => h != null); - let hexesB = polygonCoordinatesB.reduce( - (acc, coordinates) => acc.concat(h3PolyfillLib.polyfill(coordinates, resolution, true)), - [] - ).filter(h => h != null); - hexes = [...hexesA, ...hexesB]; - hexes = [...new Set(hexes)]; - - return hexes; +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._CHECK_TOO_WIDE(geo GEOGRAPHY) +RETURNS BOOLEAN +AS +$$ + CASE + WHEN ST_XMax(geo) < ST_XMin(geo) THEN + -- Adjusts for crossing the antimeridian + 360 + ST_XMax(geo) - ST_XMin(geo) >= 180 + ELSE + ST_XMax(geo) - ST_XMin(geo) >= 180 + END $$; CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_POLYFILL @@ -79,5 +153,25 @@ CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_POLYFILL RETURNS ARRAY IMMUTABLE AS $$ - @@SF_SCHEMA@@._H3_POLYFILL(CAST(ST_ASGEOJSON(GEOG) AS STRING), CAST(RESOLUTION AS DOUBLE)) + IFF( + GEOG IS NOT NULL AND RESOLUTION >= 0 AND RESOLUTION <= 15 AND @@SF_SCHEMA@@._HAS_POLYGON(GEOG), + COALESCE(H3_POLYGON_TO_CELLS_STRINGS(@@SF_SCHEMA@@._FILTER_GEOG(GEOG), RESOLUTION), []), + [] + ) +$$; + +CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_POLYFILL +(geog GEOGRAPHY, resolution INT, mode STRING) +RETURNS ARRAY +IMMUTABLE +AS $$ + CASE WHEN GEOG IS NULL OR RESOLUTION < 0 OR RESOLUTION > 15 OR NOT @@SF_SCHEMA@@._HAS_POLYGON(GEOG) THEN [] + WHEN MODE = 'center' THEN @@SF_SCHEMA@@.H3_POLYFILL(GEOG, RESOLUTION) + WHEN MODE = 'intersects' THEN + CASE WHEN @@SF_SCHEMA@@._CHECK_TOO_WIDE(GEOG) THEN @@SF_SCHEMA@@._H3_POLYFILL_INTERSECTS_FILTER(H3_COVERAGE_STRINGS(@@SF_SCHEMA@@._FILTER_GEOG(GEOG), RESOLUTION), CAST(ST_ASGEOJSON(GEOG) AS STRING)) + ELSE H3_COVERAGE_STRINGS(@@SF_SCHEMA@@.ST_BUFFER(@@SF_SCHEMA@@._FILTER_GEOG(GEOG), CAST(0.00000001 AS DOUBLE)), RESOLUTION) + END + WHEN MODE = 'contains' THEN @@SF_SCHEMA@@._H3_POLYFILL_CONTAINS(CAST(ST_ASGEOJSON(@@SF_SCHEMA@@.ST_BUFFER(@@SF_SCHEMA@@._FILTER_GEOG(GEOG), CAST(0.00000001 AS DOUBLE)) ) AS STRING), @@SF_SCHEMA@@.H3_POLYFILL(GEOG, RESOLUTION)) + ELSE [] + END $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_POLYFILL_TABLE.sql b/clouds/snowflake/modules/sql/h3/H3_POLYFILL_TABLE.sql index 67442c591..741fa6e5a 100644 --- a/clouds/snowflake/modules/sql/h3/H3_POLYFILL_TABLE.sql +++ b/clouds/snowflake/modules/sql/h3/H3_POLYFILL_TABLE.sql @@ -1,182 +1,35 @@ ----------------------------- --- Copyright (C) 2023 CARTO ----------------------------- +-------------------------------- +-- Copyright (C) 2023-2024 CARTO +-------------------------------- -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_POLYFILL_GEOJSON -(geojson STRING, input_resolution DOUBLE) -RETURNS ARRAY -LANGUAGE JAVASCRIPT -IMMUTABLE -AS $$ - if (!GEOJSON || INPUT_RESOLUTION == null) { - return []; - } - - @@SF_LIBRARY_H3_POLYFILL@@ - - const resolution = Number(INPUT_RESOLUTION); - if (resolution < 0 || resolution > 15) { - return []; - } - - const bboxA = [-180, -90, 0, 90] - const bboxB = [0, -90, 180, 90] - const featureGeometry = JSON.parse(GEOJSON) - let polygonCoordinatesA = []; - let polygonCoordinatesB = []; - switch(featureGeometry.type) { - case 'GeometryCollection': - featureGeometry.geometries.forEach(function (geom) { - if (geom.type === 'MultiPolygon') { - var clippedGeometryA = h3PolyfillLib.bboxClip(geom, bboxA).geometry; - polygonCoordinatesA = polygonCoordinatesA.concat(clippedGeometryA.coordinates); - var clippedGeometryB = h3PolyfillLib.bboxClip(geom, bboxB).geometry; - polygonCoordinatesB = polygonCoordinatesB.concat(clippedGeometryB.coordinates); - } else if (geom.type === 'Polygon') { - var clippedGeometryA = h3PolyfillLib.bboxClip(geom, bboxA).geometry; - polygonCoordinatesA = polygonCoordinatesA.concat([clippedGeometryA.coordinates]); - var clippedGeometryB = h3PolyfillLib.bboxClip(geom, bboxB).geometry; - polygonCoordinatesB = polygonCoordinatesB.concat([clippedGeometryB.coordinates]); - } - }); - break; - case 'MultiPolygon': - var clippedGeometryA = h3PolyfillLib.bboxClip(featureGeometry, bboxA).geometry; - polygonCoordinatesA = clippedGeometryA.coordinates; - var clippedGeometryB = h3PolyfillLib.bboxClip(featureGeometry, bboxB).geometry; - polygonCoordinatesB = clippedGeometryB.coordinates; - break; - case 'Polygon': - var clippedGeometryA = h3PolyfillLib.bboxClip(featureGeometry, bboxA).geometry; - polygonCoordinatesA = [clippedGeometryA.coordinates]; - var clippedGeometryB = h3PolyfillLib.bboxClip(featureGeometry, bboxB).geometry; - polygonCoordinatesB = [clippedGeometryB.coordinates]; - break; - default: - return []; - } - - if (polygonCoordinatesA.length + polygonCoordinatesB.length === 0) { - return []; - } - - let hexesA = polygonCoordinatesA.reduce( - (acc, coordinates) => acc.concat(h3PolyfillLib.polyfill(coordinates, resolution, true)), - [] - ).filter(h => h != null); - let hexesB = polygonCoordinatesB.reduce( - (acc, coordinates) => acc.concat(h3PolyfillLib.polyfill(coordinates, resolution, true)), - [] - ).filter(h => h != null); - hexes = [...hexesA, ...hexesB]; - hexes = [...new Set(hexes)]; - - return hexes; -$$; - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_AVG_EDGE_LENGTH -(resolution INTEGER) -RETURNS DOUBLE -IMMUTABLE -AS $$ - SELECT CASE resolution - WHEN 0 THEN CAST(1281256.011 AS DOUBLE) - WHEN 1 THEN CAST(483056.8391 AS DOUBLE) - WHEN 2 THEN CAST(182512.9565 AS DOUBLE) - WHEN 3 THEN CAST(68979.22179 AS DOUBLE) - WHEN 4 THEN CAST(26071.75968 AS DOUBLE) - WHEN 5 THEN CAST(9854.090990 AS DOUBLE) - WHEN 6 THEN CAST(3724.532667 AS DOUBLE) - WHEN 7 THEN CAST(1406.475763 AS DOUBLE) - WHEN 8 THEN CAST(531.414010 AS DOUBLE) - WHEN 9 THEN CAST(200.786148 AS DOUBLE) - WHEN 10 THEN CAST(75.863783 AS DOUBLE) - WHEN 11 THEN CAST(28.663897 AS DOUBLE) - WHEN 12 THEN CAST(10.830188 AS DOUBLE) - WHEN 13 THEN CAST(4.092010 AS DOUBLE) - WHEN 14 THEN CAST(1.546100 AS DOUBLE) - WHEN 15 THEN CAST(0.584169 AS DOUBLE) - ELSE - NULL - END -$$; - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_POLYFILL_INIT -(geog GEOGRAPHY, resolution INTEGER) -RETURNS ARRAY -IMMUTABLE -AS $$ - SELECT @@SF_SCHEMA@@._H3_POLYFILL_GEOJSON( - CAST( - ST_ASGEOJSON( - @@SF_SCHEMA@@.ST_BUFFER( - geog, - @@SF_SCHEMA@@._H3_AVG_EDGE_LENGTH(resolution) - ) - ) AS STRING), - CAST(resolution AS DOUBLE) - ) -$$; - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_POLYFILL_QUERY +CREATE OR REPLACE PROCEDURE @@SF_SCHEMA@@.H3_POLYFILL_TABLE ( input_query STRING, - resolution DOUBLE, + resolution INT, mode STRING, output_table STRING ) RETURNS STRING -LANGUAGE JAVASCRIPT -IMMUTABLE +LANGUAGE SQL +EXECUTE AS CALLER AS $$ - if (!['center', 'intersects', 'contains'].includes(MODE)) { - throw Error('Invalid mode, should be center, intersects, or contains.'); - } +DECLARE + column_names_csv STRING; + polyfill_query STRING; +BEGIN - if (RESOLUTION < 0 || RESOLUTION > 15) { - throw Error('Invalid resolution, should be between 0 and 15.'); - } + -- Validate + EXECUTE IMMEDIATE 'SELECT * FROM (' || input_query || ') WHERE FALSE'; - const containmentFunction = (MODE === 'contains') ? 'ST_CONTAINS' : 'ST_INTERSECTS'; - const cellFunction = (MODE === 'center') ? '@@SF_SCHEMA@@.H3_CENTER' : '@@SF_SCHEMA@@.H3_BOUNDARY'; + -- New table with correct columns + EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE ' || output_table || ' CLUSTER BY (H3) AS SELECT * EXCLUDE geom, NULL as H3 FROM (' || input_query || ') WHERE FALSE'; - const parentResolution = Math.max(0, RESOLUTION - 4) + column_names_csv := (SELECT LISTAGG(COLUMN_NAME, ',') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ILIKE :output_table AND TABLE_CATALOG=@@SF_SCHEMA@@._GET_DATABASE(:output_table) AND TABLE_SCHEMA=@@SF_SCHEMA@@._GET_SCHEMA(:output_table)); - return ` - CREATE OR REPLACE TABLE ${OUTPUT_TABLE} CLUSTER BY (h3) AS - WITH __input AS (${INPUT_QUERY}), - __cells AS ( - SELECT CAST(children.value AS STRING) AS h3, i.* - FROM __input AS i, - TABLE(FLATTEN(@@SF_SCHEMA@@._H3_POLYFILL_INIT(geom, ${parentResolution}))) AS parent, - TABLE(FLATTEN(@@SF_SCHEMA@@.H3_TOCHILDREN(CAST(parent.value AS STRING), ${RESOLUTION}))) AS children - ) - SELECT * EXCLUDE(geom) - FROM __cells - WHERE ${containmentFunction}(geom, ${cellFunction}(h3)) - `; -$$; + polyfill_query := 'INSERT INTO ' || output_table || ' (' || column_names_csv || ') SELECT ' || column_names_csv || ' FROM (WITH virtual_table AS (' || input_query || ') SELECT *, value as H3 FROM virtual_table, LATERAL FLATTEN(input => @@SF_SCHEMA@@.H3_POLYFILL(virtual_table.geom, ' || resolution || ',\'' || mode || '\')))'; -CREATE OR REPLACE PROCEDURE @@SF_SCHEMA@@.H3_POLYFILL_TABLE -( - input_query STRING, - resolution INT, - mode STRING, - output_table STRING -) -RETURNS STRING -LANGUAGE SQL -EXECUTE AS CALLER -AS $$ - DECLARE polyfill_query STRING; - BEGIN - polyfill_query := (SELECT @@SF_SCHEMA@@._H3_POLYFILL_QUERY( - :input_query, - CAST(:resolution AS DOUBLE), - :mode, - :output_table - )); - EXECUTE IMMEDIATE polyfill_query; - RETURN 'Polyfill completed.'; - END; + EXECUTE IMMEDIATE polyfill_query; + + RETURN 'Finished!'; +END; $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_RESOLUTION.sql b/clouds/snowflake/modules/sql/h3/H3_RESOLUTION.sql index 15674dd14..ec9e11ffa 100644 --- a/clouds/snowflake/modules/sql/h3/H3_RESOLUTION.sql +++ b/clouds/snowflake/modules/sql/h3/H3_RESOLUTION.sql @@ -1,6 +1,6 @@ ----------------------------- --- Copyright (C) 2023 CARTO ----------------------------- +--------------------------------- +-- Copyright (C) 2023-2024 CARTO +--------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_RESOLUTION ( @@ -8,8 +8,5 @@ CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_RESOLUTION ) RETURNS INT AS $$ - IFF(@@SF_SCHEMA@@.H3_ISVALID(h3), - bitshiftright(bitand(@@SF_SCHEMA@@.H3_STRING_TOINT(h3), - bitshiftleft(15, 52)), 52), - NULL) + IFF(@@SF_SCHEMA@@.H3_ISVALID(h3), H3_GET_RESOLUTION(H3), NULL) $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_STRING_TOINT.sql b/clouds/snowflake/modules/sql/h3/H3_STRING_TOINT.sql index 1c1dcee08..519699e75 100644 --- a/clouds/snowflake/modules/sql/h3/H3_STRING_TOINT.sql +++ b/clouds/snowflake/modules/sql/h3/H3_STRING_TOINT.sql @@ -1,8 +1,12 @@ +--------------------------------- +-- Copyright (C) 2022-2024 CARTO +--------------------------------- + CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_STRING_TOINT ( - h3 STRING + index STRING ) RETURNS INT AS $$ - TO_NUMBER(h3, 'xxxxxxxxxxxxxxx') + H3_STRING_TO_INT(INDEX) $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_TOCHILDREN.sql b/clouds/snowflake/modules/sql/h3/H3_TOCHILDREN.sql index 486ab0950..de7172d8c 100644 --- a/clouds/snowflake/modules/sql/h3/H3_TOCHILDREN.sql +++ b/clouds/snowflake/modules/sql/h3/H3_TOCHILDREN.sql @@ -1,30 +1,15 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_TOCHILDREN -(index STRING, resolution DOUBLE) -RETURNS ARRAY -LANGUAGE JAVASCRIPT -IMMUTABLE -AS $$ - if (!INDEX) { - return []; - } - - @@SF_LIBRARY_H3_TOCHILDREN@@ - - if (!h3TochildrenLib.h3IsValid(INDEX)) { - return []; - } - - return h3TochildrenLib.h3ToChildren(INDEX, Number(RESOLUTION)); -$$; +--------------------------------- +-- Copyright (C) 2021-2024 CARTO +--------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_TOCHILDREN -(index STRING, resolution INT) +(index VARCHAR, resolution INT) RETURNS ARRAY IMMUTABLE AS $$ - @@SF_SCHEMA@@._H3_TOCHILDREN(INDEX, CAST(RESOLUTION AS DOUBLE)) + IFF( + @@SF_SCHEMA@@.H3_ISVALID(INDEX) AND RESOLUTION >= H3_GET_RESOLUTION(INDEX), + H3_CELL_TO_CHILDREN_STRING(INDEX, RESOLUTION), + [] + ) $$; diff --git a/clouds/snowflake/modules/sql/h3/H3_TOPARENT.sql b/clouds/snowflake/modules/sql/h3/H3_TOPARENT.sql index 7de82c8ce..7e7806b9e 100644 --- a/clouds/snowflake/modules/sql/h3/H3_TOPARENT.sql +++ b/clouds/snowflake/modules/sql/h3/H3_TOPARENT.sql @@ -1,30 +1,15 @@ ----------------------------- --- Copyright (C) 2021 CARTO ----------------------------- - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._H3_TOPARENT -(index STRING, resolution DOUBLE) -RETURNS STRING -LANGUAGE JAVASCRIPT -IMMUTABLE -AS $$ - if (!INDEX) { - return null; - } - - @@SF_LIBRARY_H3_TOPARENT@@ - - if (!h3ToparentLib.h3IsValid(INDEX)) { - return null; - } - - return h3ToparentLib.h3ToParent(INDEX, Number(RESOLUTION)); -$$; +--------------------------------- +-- Copyright (C) 2021-2024 CARTO +--------------------------------- CREATE OR REPLACE SECURE FUNCTION @@SF_SCHEMA@@.H3_TOPARENT (index STRING, resolution INT) RETURNS STRING IMMUTABLE AS $$ - @@SF_SCHEMA@@._H3_TOPARENT(INDEX, CAST(RESOLUTION AS DOUBLE)) + IFF( + @@SF_SCHEMA@@.H3_ISVALID(INDEX) AND RESOLUTION <= H3_GET_RESOLUTION(INDEX), + H3_CELL_TO_PARENT(INDEX, RESOLUTION), + NULL + ) $$; diff --git a/clouds/snowflake/modules/sql/utils/_CARTO_ARRAY_ERROR.sql b/clouds/snowflake/modules/sql/utils/_CARTO_ARRAY_ERROR.sql new file mode 100644 index 000000000..ca17059e4 --- /dev/null +++ b/clouds/snowflake/modules/sql/utils/_CARTO_ARRAY_ERROR.sql @@ -0,0 +1,7 @@ +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._CARTO_ARRAY_ERROR +(message STRING) +RETURNS ARRAY +LANGUAGE JAVASCRIPT +AS $$ + throw `${MESSAGE}` +$$; diff --git a/clouds/snowflake/modules/sql/utils/_GET_DATABASE.sql b/clouds/snowflake/modules/sql/utils/_GET_DATABASE.sql new file mode 100644 index 000000000..6b2eab342 --- /dev/null +++ b/clouds/snowflake/modules/sql/utils/_GET_DATABASE.sql @@ -0,0 +1,22 @@ +--------------------------- +-- Copyright (C) 2024 CARTO +--------------------------- + +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._GET_DATABASE +(table_identifier STRING) +RETURNS STRING +LANGUAGE SQL +IMMUTABLE +AS $$ + WITH split_identifier AS ( + SELECT ARRAY_SIZE(SPLIT(table_identifier, '.')) AS parts_count, + SPLIT_PART(table_identifier, '.', 1) AS first_part + FROM (SELECT TABLE_IDENTIFIER AS table_identifier) + ) + SELECT + CASE parts_count + WHEN 3 THEN first_part + ELSE CURRENT_DATABASE() + END + FROM split_identifier +$$; diff --git a/clouds/snowflake/modules/sql/utils/_GET_SCHEMA.sql b/clouds/snowflake/modules/sql/utils/_GET_SCHEMA.sql new file mode 100644 index 000000000..2178a0d76 --- /dev/null +++ b/clouds/snowflake/modules/sql/utils/_GET_SCHEMA.sql @@ -0,0 +1,24 @@ +--------------------------- +-- Copyright (C) 2023 CARTO +--------------------------- + +CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._GET_SCHEMA +(table_identifier STRING) +RETURNS STRING +LANGUAGE SQL +IMMUTABLE +AS $$ + WITH split_identifier AS ( + SELECT ARRAY_SIZE(SPLIT(table_identifier, '.')) AS parts_count, + SPLIT_PART(table_identifier, '.', 1) AS first_part, + SPLIT_PART(table_identifier, '.', 2) AS second_part + FROM (SELECT TABLE_IDENTIFIER AS table_identifier) + ) + SELECT + CASE parts_count + WHEN 3 THEN second_part + WHEN 2 THEN first_part + ELSE CURRENT_SCHEMA() + END + FROM split_identifier +$$; diff --git a/clouds/snowflake/modules/test/clustering/ST_CLUSTERKMEANS.test.js b/clouds/snowflake/modules/test/clustering/ST_CLUSTERKMEANS.test.js index c615ce403..f0e2a129c 100644 --- a/clouds/snowflake/modules/test/clustering/ST_CLUSTERKMEANS.test.js +++ b/clouds/snowflake/modules/test/clustering/ST_CLUSTERKMEANS.test.js @@ -17,6 +17,25 @@ test('ST_CLUSTERKMEANS should work', async () => { expect(JSON.stringify(rows[0].CLUSTERKMEANS3)).toEqual(points3FixturesOut.value); }); +test('ST_CLUSTERKMEANS should work for duplicated entries ', async () => { + const requestedClusters = 3; + // When the input array contains consecutives entries at the beggining, + // it should be reordered to the required number of clusters + const query = `SELECT + @@SF_SCHEMA@@.ST_CLUSTERKMEANS(ARRAY_CONSTRUCT(ST_ASGEOJSON(ST_POINT(0, 0))::STRING, ST_ASGEOJSON(ST_POINT(0, 0))::STRING, ST_ASGEOJSON(ST_POINT(0, 0))::STRING, ST_ASGEOJSON(ST_POINT(0, 1))::STRING, ST_ASGEOJSON(ST_POINT(0, 1))::STRING, ST_ASGEOJSON(ST_POINT(0, 1))::STRING, ST_ASGEOJSON(ST_POINT(5, 0))::STRING), ${requestedClusters}) as clusterKMeans + `; + const rows = await runQuery(query); + const uniqueClusters = new Set(); + + rows[0].CLUSTERKMEANS.forEach(item => { + uniqueClusters.add(item.cluster); + }); + + expect(rows.length).toEqual(1); + expect(uniqueClusters.size).toEqual(requestedClusters); + +}); + test('ST_CLUSTERKMEANS should return NULL if any NULL mandatory argument', async () => { const query = `SELECT @@SF_SCHEMA@@.ST_CLUSTERKMEANS(NULL, 2) as clusterKMeans1, diff --git a/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points1.js b/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points1.js index 0a0228f57..1d27769b6 100644 --- a/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points1.js +++ b/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points1.js @@ -1,3 +1,3 @@ module.exports = { - value: '[{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[0,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[0,1],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[5,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[1,0],\\\"type\\\":\\\"Point\\\"}\"}]' - } \ No newline at end of file + value: '[{"cluster":1,"geom":"{\\"coordinates\\":[0,0],\\"type\\":\\"Point\\"}"},{"cluster":1,"geom":"{\\"coordinates\\":[0,1],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[5,0],\\"type\\":\\"Point\\"}"},{"cluster":1,"geom":"{\\"coordinates\\":[1,0],\\"type\\":\\"Point\\"}"}]' +} \ No newline at end of file diff --git a/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points2.js b/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points2.js index 5ccf200e7..4bbee7ecb 100644 --- a/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points2.js +++ b/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points2.js @@ -1,3 +1,3 @@ module.exports = { - value: '[{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[0,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[0,1],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[5,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[1,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[0,1],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[5,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[1,19],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[12,1],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[9,2],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[1,10],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[-3,1],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[5,5],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[8,6],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[10,10],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[-3,-5],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[6,5],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[-8,9],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[1,-10],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[2,-2],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[0,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[3,10],\\\"type\\\":\\\"Point\\\"}\"}]' - } \ No newline at end of file + value: '[{"cluster":0,"geom":"{\\"coordinates\\":[0,0],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[0,1],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[5,0],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[1,0],\\"type\\":\\"Point\\"}"},{"cluster":1,"geom":"{\\"coordinates\\":[1,19],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[12,1],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[9,2],\\"type\\":\\"Point\\"}"},{"cluster":1,"geom":"{\\"coordinates\\":[1,10],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[-3,1],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[5,5],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[8,6],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[10,10],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[-3,-5],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[6,5],\\"type\\":\\"Point\\"}"},{"cluster":1,"geom":"{\\"coordinates\\":[-8,9],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[1,-10],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[2,-2],\\"type\\":\\"Point\\"}"},{"cluster":1,"geom":"{\\"coordinates\\":[3,10],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[0,1],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[5,0],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[0,0],\\"type\\":\\"Point\\"}"}]' +} \ No newline at end of file diff --git a/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points3.js b/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points3.js index 93a0b4efc..a004fc46c 100644 --- a/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points3.js +++ b/clouds/snowflake/modules/test/clustering/fixtures/st_clusterkmeans_out_points3.js @@ -1,3 +1,3 @@ module.exports = { - value: '[{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[0,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[0,1],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[5,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[1,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[0,1],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[5,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":4,\"geom\":\"{\\\"coordinates\\\":[1,19],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[12,1],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[9,2],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":4,\"geom\":\"{\\\"coordinates\\\":[1,10],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[-3,1],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[5,5],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[8,6],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[10,10],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":0,\"geom\":\"{\\\"coordinates\\\":[-3,-5],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":2,\"geom\":\"{\\\"coordinates\\\":[6,5],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":4,\"geom\":\"{\\\"coordinates\\\":[-8,9],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":3,\"geom\":\"{\\\"coordinates\\\":[1,-10],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[2,-2],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":1,\"geom\":\"{\\\"coordinates\\\":[0,0],\\\"type\\\":\\\"Point\\\"}\"},{\"cluster\":4,\"geom\":\"{\\\"coordinates\\\":[3,10],\\\"type\\\":\\\"Point\\\"}\"}]' - } \ No newline at end of file + value: '[{"cluster":0,"geom":"{\\"coordinates\\":[0,0],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[0,1],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[5,0],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[1,0],\\"type\\":\\"Point\\"}"},{"cluster":4,"geom":"{\\"coordinates\\":[1,19],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[12,1],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[9,2],\\"type\\":\\"Point\\"}"},{"cluster":4,"geom":"{\\"coordinates\\":[1,10],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[-3,1],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[5,5],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[8,6],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[10,10],\\"type\\":\\"Point\\"}"},{"cluster":3,"geom":"{\\"coordinates\\":[-3,-5],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[6,5],\\"type\\":\\"Point\\"}"},{"cluster":1,"geom":"{\\"coordinates\\":[-8,9],\\"type\\":\\"Point\\"}"},{"cluster":3,"geom":"{\\"coordinates\\":[1,-10],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[2,-2],\\"type\\":\\"Point\\"}"},{"cluster":4,"geom":"{\\"coordinates\\":[3,10],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[0,1],\\"type\\":\\"Point\\"}"},{"cluster":2,"geom":"{\\"coordinates\\":[5,0],\\"type\\":\\"Point\\"}"},{"cluster":0,"geom":"{\\"coordinates\\":[0,0],\\"type\\":\\"Point\\"}"}]' +} \ No newline at end of file diff --git a/clouds/snowflake/modules/test/h3/H3_CENTER.test.js b/clouds/snowflake/modules/test/h3/H3_CENTER.test.js index c9cb41d1a..d62b98da1 100644 --- a/clouds/snowflake/modules/test/h3/H3_CENTER.test.js +++ b/clouds/snowflake/modules/test/h3/H3_CENTER.test.js @@ -24,13 +24,13 @@ test('Returns NULL the expected geography', async () => { const query = ` WITH ids AS ( - SELECT 1 AS id, H3_CENTER('85283473fffffff') as bounds, TO_GEOGRAPHY('POINT(-121.9763759725512 37.34579337536848)') AS expected UNION ALL - SELECT 2 AS id, H3_CENTER('81623ffffffffff') as bounds, TO_GEOGRAPHY('POINT(58.1577058395726 10.447345187511)') AS expected + SELECT 1 AS id, H3_CENTER('85283473fffffff') as bounds, ST_GEOGRAPHYFROMWKB('010100000049ada5f17c7e5ec0c63013f542ac4240') AS expected UNION ALL + SELECT 2 AS id, H3_CENTER('81623ffffffffff') as bounds, ST_GEOGRAPHYFROMWKB('01010000001ead77b42f144d4007c4ac6d0ae52440') AS expected ) SELECT * FROM ids - WHERE ST_ASBINARY(expected) != ST_ASBINARY(expected) or bounds is null + WHERE ST_ASBINARY(bounds) != ST_ASBINARY(expected) or bounds is null `; const rows = await runQuery(query); diff --git a/clouds/snowflake/modules/test/h3/H3_POLYFILL.spec.js b/clouds/snowflake/modules/test/h3/H3_POLYFILL.spec.js deleted file mode 100644 index 4dc003718..000000000 --- a/clouds/snowflake/modules/test/h3/H3_POLYFILL.spec.js +++ /dev/null @@ -1,163 +0,0 @@ -const { runQuery } = require('../../../common/test-utils'); - -test('H3_POLYFILL returns the proper INT64s', async () => { - const query = ` - WITH inputs AS - ( - SELECT 1 AS id, TO_GEOGRAPHY('POLYGON((-122.4089866999972145 37.813318999983238, -122.3805436999997056 37.7866302000007224, -122.3544736999993603 37.7198061999978478, -122.5123436999983966 37.7076131999975672, -122.5247187000021967 37.7835871999971715, -122.4798767000009008 37.8151571999998453, -122.4089866999972145 37.813318999983238))') as geom, 9 as resolution UNION ALL - SELECT 2 AS id, TO_GEOGRAPHY('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))') as geom, 2 as resolution UNION ALL - SELECT 3 AS id, TO_GEOGRAPHY('POLYGON((20 20, 20 30, 30 30, 30 20, 20 20))') as geom, 2 as resolution UNION ALL - -- 4 is a multipolygon containing geom ids 2, 3 - SELECT 4 AS id, TO_GEOGRAPHY('MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0)), ((20 20, 20 30, 30 30, 30 20, 20 20)))') as geom, 2 as resolution UNION ALL - SELECT 5 AS id, TO_GEOGRAPHY('GEOMETRYCOLLECTION(POLYGON((20 20, 20 30, 30 30, 30 20, 20 20)), POINT(0 10), LINESTRING(0 0, 1 1),MULTIPOLYGON(((-50 -50, -50 -40, -40 -40, -40 -50, -50 -50)), ((50 50, 50 40, 40 40, 40 50, 50 50))))') as geom, 2 as resolution UNION ALL - - -- NULL and empty - SELECT 6 AS id, TRY_TO_GEOGRAPHY(NULL) as geom, 2 as resolution UNION ALL - SELECT 7 AS id, TO_GEOGRAPHY('POLYGON EMPTY') as geom, 2 as resolution UNION ALL - - -- Invalid resolution - SELECT 8 AS id, TO_GEOGRAPHY('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))') as geom, -1 as resolution UNION ALL - SELECT 9 AS id, TO_GEOGRAPHY('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))') as geom, 20 as resolution UNION ALL - SELECT 10 AS id, TO_GEOGRAPHY('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))') as geom, NULL as resolution UNION ALL - - -- Other types are not supported - SELECT 11 AS id, TO_GEOGRAPHY('POINT(0 0)') as geom, 15 as resolution UNION ALL - SELECT 12 AS id, TO_GEOGRAPHY('MULTIPOINT(0 0, 1 1)') as geom, 15 as resolution UNION ALL - SELECT 13 AS id, TO_GEOGRAPHY('LINESTRING(0 0, 1 1)') as geom, 15 as resolution UNION ALL - SELECT 14 AS id, TO_GEOGRAPHY('MULTILINESTRING((0 0, 1 1), (2 2, 3 3))') as geom, 15 as resolution UNION ALL - - -- 15 is a geometry collection containing only not supported types - SELECT 15 AS id, TO_GEOGRAPHY('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(1 2, 2 1))') as geom, 15 as resolution UNION ALL - - SELECT 16 AS id, TO_GEOGRAPHY('POLYGON((0 0, 0 .0001, .0001 .0001, .0001 0, 0 0))') as geom, 15 as resolution UNION ALL - SELECT 17 AS id, TO_GEOGRAPHY('POLYGON((0 0, 0 50, 50 50, 50 0, 0 0))') as geom, 0 as resolution UNION ALL - - -- Polygon larger than 180 degrees - SELECT 18 AS id, TO_GEOGRAPHY('{"type":"Polygon","coordinates":[[[-161.44993041898587,-3.77971025880735],[129.99811811657568,-3.77971025880735],[129.99811811657568,63.46915831771922],[-161.44993041898587,63.46915831771922],[-161.44993041898587,-3.77971025880735]]]}') as geom, 3 as resolution - ) - SELECT - ARRAY_SIZE(H3_POLYFILL(geom, resolution)) AS id_count - FROM inputs - ORDER BY id ASC - `; - - const rows = await runQuery(query); - expect(rows.length).toEqual(18); - expect(rows.map((r) => r.ID_COUNT)).toEqual([ - 1253, - 18, - 12, - 30, - 34, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 182, - 6, - 16110 - ]); -}); - -test('H3_POLYFILL returns the expected values', async () => { - /* Any cell should cover only 1 h3 cell at its resolution (itself) */ - /* This query has been splitted in Snowflake to avoid JS memory limits reached*/ - let query = ` - WITH points AS - ( - SELECT ST_POINT(0, 0) AS geog, - 7 AS resolution - ), - cells AS - ( - SELECT - resolution, - H3_FROMGEOGPOINT(geog, resolution) AS hex_id, - H3_BOUNDARY(H3_FROMGEOGPOINT(geog, resolution)) AS boundary - FROM points - ), - polyfill AS - ( - SELECT - *, - H3_POLYFILL(boundary, resolution) p - FROM cells - ) - SELECT - * - FROM polyfill - WHERE - ARRAY_SIZE(p) != 1 OR - GET(p,0) != hex_id; - `; - let rows = await runQuery(query); - expect(rows.length).toEqual(0); - - query = ` - WITH points AS - ( - SELECT ST_POINT(-122.4089866999972145, 37.813318999983238) AS geog, - 7 AS resolution - ), - cells AS - ( - SELECT - resolution, - H3_FROMGEOGPOINT(geog, resolution) AS hex_id, - H3_BOUNDARY(H3_FROMGEOGPOINT(geog, resolution)) AS boundary - FROM points - ), - polyfill AS - ( - SELECT - *, - H3_POLYFILL(boundary, resolution) p - FROM cells - ) - SELECT - * - FROM polyfill - WHERE - ARRAY_SIZE(p) != 1 OR - GET(p,0) != hex_id; - `; - rows = await runQuery(query); - expect(rows.length).toEqual(0); - - query = ` - WITH points AS - ( - SELECT ST_POINT(-122.0553238, 37.3615593) AS geog, - 7 AS resolution - ), - cells AS - ( - SELECT - resolution, - H3_FROMGEOGPOINT(geog, resolution) AS hex_id, - H3_BOUNDARY(H3_FROMGEOGPOINT(geog, resolution)) AS boundary - FROM points - ), - polyfill AS - ( - SELECT - *, - H3_POLYFILL(boundary, resolution) p - FROM cells - ) - SELECT - * - FROM polyfill - WHERE - ARRAY_SIZE(p) != 1 OR - GET(p,0) != hex_id; - `; - rows = await runQuery(query); - expect(rows.length).toEqual(0); -}); \ No newline at end of file diff --git a/clouds/snowflake/modules/test/h3/H3_POLYFILL.test.js b/clouds/snowflake/modules/test/h3/H3_POLYFILL.test.js new file mode 100644 index 000000000..22618888e --- /dev/null +++ b/clouds/snowflake/modules/test/h3/H3_POLYFILL.test.js @@ -0,0 +1,360 @@ +const { runQuery } = require('../../../common/test-utils'); + +const polygonsWkt = { + tennisCourt: 'POLYGON ((-6.28934449565433 53.3028222364194,-6.28920842134271 53.3028715188494,-6.28904265809039 53.3027162790024,-6.28917625832361 53.3026650250877,-6.28934449565433 53.3028222364194))', + footballPitch: 'POLYGON ((-0.016948635611556 51.5391870061221,-0.015923297482467 51.5391651657394,-0.015961923233906 51.5381692331516,-0.016994284226892 51.5381823376693,-0.016948635611556 51.5391870061221))', + centralPark: 'POLYGON ((-73.9581734481885 40.8003760047406,-73.9493041668766 40.7969504244806,-73.9728349132144 40.7642843507669,-73.9821265412556 40.7679400942305,-73.9581734481885 40.8003760047406))', + manhattanIsland: 'POLYGON ((-73.9277647658113 40.8765463305537,-73.9083455081116 40.8726131824587,-73.934006670072 40.8337935954031,-73.929498628106 40.7970514319678,-73.9437162989219 40.7818237174634,-73.9409421192505 40.7760467743388,-73.9714580956358 40.7413745658556,-73.9745790477661 40.7348058228905,-73.9707645507179 40.7277108519672,-73.9766596825197 40.7111529778644,-74.0127240182477 40.7001121070861,-74.0189659225084 40.7048441329741,-74.0092562936585 40.7539847340763,-73.9593210595734 40.8211985746244,-73.9478775684289 40.8393031647459,-73.9457969336754 40.8497963157552,-73.9347002149898 40.8626481615087,-73.9277647658113 40.8765463305537))', + spain: 'POLYGON ((-8.90806736221923 41.8706635124104,-8.11181452117029 42.1601631309042,-8.1456976207894 41.7949252059901,-6.31601024135781 41.933710300506,-6.12965319345274 41.4783847414197,-7.41721097897867 37.1960149081344,-6.31601024135781 36.8714369692099,-5.94329614554767 36.1223963607846,-5.57058204973753 36.012842475776,-4.31690736383071 36.6814599426408,-1.97897349011257 36.7222089343589,-1.53849319506422 37.4116285337434,-0.572824855919773 37.5863589975998,0.155661785890951 38.7319310221496,-0.318701608776497 39.546601475132,1.23992097370226 41.1347761010052,3.25596540103892 41.8328055614838,3.28984850065802 42.4233374273265,0.189544885510054 42.6729568637547,-1.80955799201705 43.3419396565053,-3.67312847106774 43.4896126871605,-6.29906869154826 43.5264746715754,-7.85769127402702 43.7716458491458,-9.45019695612488 43.0702706652373,-8.87418426260012 42.3607766281235,-8.90806736221923 41.8706635124104))', + africa: 'POLYGON ((-6.18681324230837 34.32975238713,10.6245368266105 36.8379847608463,11.0872345349294 33.433472073531,20.3411887013068 30.2903330071659,20.3411887013068 33.0464813781609,32.9882593953559 30.5563244246685,44.0930043950087 10.6175077622945,50.7250048809125 11.5256694933408,40.5456552978974 -2.43023717904863,38.6948644646219 -7.19320502027326,41.4710507145351 -14.3099721821406,34.8390502286313 -20.4877739075543,35.4559805063898 -25.3163707073876,32.525561687037 -26.5645756977869,31.7543988398389 -30.8908858266023,18.9530955763502 -34.6505294423347,11.8583973821275 -17.8659246687455,13.709188215403 -9.02540810631568,7.38565286837845 -1.50539755792676,8.61951342389544 3.11986341112736,-1.7140687285593 5.11960347139298,-10.9680228949367 4.35107870862103,-18.3711862280386 14.08219205561,-17.4457908114008 22.2795101913754,-10.5053251866178 29.6221985695737,-6.18681324230837 34.32975238713))' +} + +const multiPolygonsWkt = { + duckPonds: 'MULTIPOLYGON (((-0.1847365064947 51.5062187993979,-0.183896333915387 51.5065292989274,-0.182399776508484 51.5066927188826,-0.181795902467103 51.506055377743,-0.182084711791242 51.5053690003918,-0.184027610880904 51.5050421504002,-0.1847365064947 51.5054343701088,-0.184867783460218 51.5059409822358,-0.1847365064947 51.5062187993979)),((-0.175809672839494 51.5100590395608,-0.175100777225699 51.5101897654439,-0.174470647791213 51.5084085930252,-0.17326289970845 51.5072320005762,-0.172527748701551 51.5065946669799,-0.173079111956726 51.505924639997,-0.174313115432592 51.5065783249755,-0.175048266439491 51.507526151537,-0.175888439018805 51.5087190776324,-0.175993460591219 51.5095197913283,-0.175809672839494 51.5100590395608)),((-0.172081407018791 51.5065129568997,-0.172685281060172 51.5057939018759,-0.171214979046374 51.5051075205861,-0.169140802991194 51.5047479834032,-0.165701346494629 51.5044865000338,-0.162261889998064 51.5039471858456,-0.160660311018748 51.503914499932,-0.160371501694609 51.5043557577864,-0.160108947763574 51.5043884433834,-0.160135203156677 51.5046989553857,-0.16008269237047 51.5051402056439,-0.163312105722206 51.5058265864414,-0.164913684701523 51.5058756132456,-0.168353141198087 51.5058592709834,-0.169429612315333 51.5058429287153,-0.172081407018791 51.5065129568997)))', + farmFields: 'MULTIPOLYGON (((3.9314579363239 48.7451508148407,3.93669390339958 48.747308672349,3.94436085518898 48.7418213672108,3.93949888576156 48.7395399516807,3.9314579363239 48.7451508148407)),((3.95043831697326 48.7534734689634,3.95978825817985 48.7576034595499,3.96652021584858 48.7526104429706,3.9577312711144 48.7482950906354,3.95043831697326 48.7534734689634)),((3.95286930168697 48.7319550422314,3.95754427229026 48.7336201203865,3.96380873289868 48.7249857834619,3.95894676347125 48.7235671434568,3.95286930168697 48.7319550422314)))', + canaryIslands: 'MULTIPOLYGON (((-18.0194950057482 28.767294861495,-17.9189899416691 28.8621295769448,-17.7450388692247 28.831656407637,-17.7063830753481 28.7062841275009,-17.8455439333037 28.4584872782872,-18.0194950057482 28.767294861495)),((-16.9255360390419 28.3496802533479,-16.6974668551703 28.0021143999467,-16.4964567270123 28.0328273537469,-16.376623765995 28.3802935213973,-16.1176299470221 28.5196420808903,-16.1369578439604 28.6316671143085,-16.589230632316 28.4108979552096,-16.9255360390419 28.3496802533479)),((-17.2734381839308 28.2135145620708,-17.3198251365827 28.1964816166776,-17.3430186129086 28.1010469779639,-17.2579758663802 28.0225906758754,-17.0994871114864 28.0771750364543,-17.1110838496493 28.1658154736514,-17.2734381839308 28.2135145620708)),((-18.1354623873778 27.766357961642,-18.0388229026864 27.7526751978046,-17.9383178386074 27.8518362416617,-17.8571406714667 27.8279091042007,-17.976973632484 27.6328777264176,-18.0658819584 27.6842355964704,-18.166387022479 27.7013495231668,-18.1354623873778 27.766357961642)),((-15.7156096907061 28.1658154736514,-15.4720781892838 28.1317316716573,-15.4063633396937 28.1930747017532,-15.3522452282665 28.1555914721898,-15.3793042839801 27.8484184022801,-15.5957767296888 27.7492542381415,-15.7851901196838 27.8073959301359,-15.839308231111 27.9850478635236,-15.727206428869 28.0703535068871,-15.7156096907061 28.1658154736514)),((-14.0222131310203 28.7004147462901,-13.8678479301717 28.772072698678,-13.8194196318663 28.6499593420137,-13.9283833030535 28.2374447022957,-14.212899555598 28.1680914626501,-14.3400238386499 28.0426080438239,-14.512549651363 28.0666481420238,-14.4974158081426 28.1280595122995,-14.4035859801758 28.1093728157525,-14.2159263242421 28.2161100392333,-14.0222131310203 28.7004147462901)),((-13.8950888479685 28.8622386728752,-13.777044870849 28.8436814725666,-13.7316433411876 28.9072923672835,-13.6347867445767 28.9311364079211,-13.4531806259313 29.0158707898105,-13.4259397081345 29.2115528325736,-13.5137159988131 29.3171717181508,-13.5288498420336 29.1534159784119,-13.6408402818649 29.1322671389583,-13.7921787140694 29.0687945187246,-13.8466605496631 28.9946937003264,-13.8345534750867 28.933785407335,-13.8950888479685 28.8622386728752)))', + southAmericanCountries: 'MULTIPOLYGON (((-51.0402348797903 3.80921001016012,-58.8887341410253 1.323353025417,-60.4201486310223 4.95439442681803,-65.3972457235128 4.19113022719449,-73.8200254184967 -8.40894552471227,-59.2715877635245 -15.7045237045925,-54.1030638597844 -25.3698807594659,-58.505880518526 -33.2068574630847,-53.9116370485348 -35.4201585439674,-47.7859790885465 -25.0234557274646,-40.1289066385611 -22.9246716416212,-38.7889189598137 -13.1090750509028,-34.5775291123217 -5.36859469737905,-50.0831008235421 -0.207943331903141,-51.0402348797903 3.80921001016012)),((-69.1527969814148 -11.502562681899,-59.5468686637489 -15.8967321056371,-57.7496304623792 -19.2636677217718,-58.431341504278 -19.497515507521,-62.0877916380992 -19.497515507521,-62.5216077556713 -22.0468385195633,-67.8513486286988 -22.6772793895194,-69.33871817466 -17.5584981509195,-69.1527969814148 -11.502562681899)),((-57.8570538894109 -20.6597445927195,-55.7073592503026 -25.7613409063218,-58.9319012089652 -31.4203489873142,-59.6484660886679 -34.4271185412807,-57.1404890097082 -36.613916268976,-63.768714146959 -41.3456024887631,-65.9184087860674 -41.3456024887631,-68.7846683048786 -52.4295321805673,-71.6509278236897 -51.7692762704576,-72.7257751432439 -49.380862225017,-71.471786603764 -42.1475262020993,-70.3969392842098 -32.7860335716503,-69.14295074473 -27.5225687782282,-67.7098209853244 -24.3005522230791,-57.8570538894109 -20.6597445927195)))' +} + +describe('H3_POLYFILL should support POLYGON geographies', () => { + test.each([ + ['tennisCourt', 15, undefined, 262], + ['tennisCourt', 15, 'contains', 222], + ['tennisCourt', 15, 'center', 262], + ['tennisCourt', 15, 'intersects', 302], + ['footballPitch', 15, undefined, 9922], + ['footballPitch', 15, 'contains', 9669], + ['footballPitch', 15, 'center', 9922], + ['footballPitch', 15, 'intersects', 10150], + ['centralPark', 12, undefined, 11506], + ['centralPark', 12, 'contains', 11171], + ['centralPark', 12, 'center', 11506], + ['centralPark', 12, 'intersects', 11845], + ['manhattanIsland', 10, undefined, 3810], + ['manhattanIsland', 10, 'contains', 3591], + ['manhattanIsland', 10, 'center', 3810], + ['manhattanIsland', 10, 'intersects', 4037], + ['spain', 6, undefined, 13344], + ['spain', 6, 'contains', 13006], + ['spain', 6, 'center', 13344], + ['spain', 6, 'intersects', 13701], + ['africa', 3, undefined, 2323], + ['africa', 3, 'contains', 2178], + ['africa', 3, 'center', 2323], + ['africa', 3, 'intersects', 2470] + ])('Called with geography POLYGON:%s, a resolution of %i in %s mode, should return %i H3 cell identifiers', async (polygonName, resolution, mode, expectedCellCount) => { + const polygonWkt = polygonsWkt[polygonName]; // Assuming polygonsWkt is an object with WKT strings + + let query = mode === undefined ? + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${polygonWkt}'), ${resolution})) as cell_count` : + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${polygonWkt}'), ${resolution}, '${mode}')) as cell_count`; + + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); + +}); + + +describe('H3_POLYFILL should support MULTIPOLYGON geographies', () => { + test.each([ + ['duckPonds', 13, undefined, 4945], + ['duckPonds', 13, 'contains', 4585], + ['duckPonds', 13, 'center', 4945], + ['duckPonds', 13, 'intersects', 5293], + ['farmFields', 10, undefined, 102], + ['farmFields', 10, 'contains', 63], + ['farmFields', 10, 'center', 102], + ['farmFields', 10, 'intersects', 153], + ['canaryIslands', 7, undefined, 1312], + ['canaryIslands', 7, 'contains', 1068], + ['canaryIslands', 7, 'center', 1312], + ['canaryIslands', 7, 'intersects', 1570], + ['southAmericanCountries', 5, undefined, 49158], + ['southAmericanCountries', 5, 'contains', 48136], + ['southAmericanCountries', 5, 'center', 49158], + ['southAmericanCountries', 5, 'intersects', 50354] + ])('Called with geography MULTIPOLYGON:%s, a resolution of %i in %s mode, should return %i H3 cell identifiers', async (multiPolygonName, resolution, mode, expectedCellCount) => { + let query; + const polygonWkt = multiPolygonsWkt[multiPolygonName]; + + if (mode === undefined) { + query = `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${polygonWkt}'), ${resolution})) as cell_count`; + } else { + query = `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${polygonWkt}'), ${resolution}, '${mode}')) as cell_count`; + } + + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }) +}); + +describe('Support GEOMETRYCOLLECTION containing 1 or more POLYGON Geographies', () => { + const geometryCollection = 'GEOMETRYCOLLECTION( POLYGON((3.00 3.00, 3.20 3.40, 3.40 3.00, 3.00 3.00)), POLYGON((3.50 3.50, 3.50 3.70, 3.80 3.70, 3.80 3.50, 3.50 3.50)))'; + + test.each([ + ['center', 61], + ['contains', 36], + ['intersects', 90] + ])('H3_POLYFILL with mode %s should return expected cell count', async (mode, expectedCellCount) => { + const query = `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${geometryCollection}'), 6, '${mode}')) as cell_count`; + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); +}); + +describe('NOT Support a GEOMETRYCOLLECTION containing 0 POLYGON Geographies. Return [].', () => { + const geometryCollection = 'GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(1 2, 2 1))'; + + test.each([ + ['center', 0], + ['contains', 0], + ['intersects', 0] + ])('H3_POLYFILL with mode %s should return expected empty result', async (mode, expectedCellCount) => { + const query = `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${geometryCollection}'), 6, '${mode}')) as cell_count`; + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); +}); + + +describe('Resolution support between 0 and 15 inclusive for H3_POLYFILL', () => { + const testCases = [ + ['duckPonds',-1, 'contains', 0], + ['duckPonds',16, 'center', 0], + ['duckPonds',16, 'intersects', 0], + ['duckPonds',999, undefined, 0], + ['duckPonds',13, undefined, 4945] + ]; + + test.each(testCases)('For %s at resolution %i in %s mode, expected cell count is %i', async (polygonWkt, resolution, mode, expectedCellCount) => { + let query; + const wkt = multiPolygonsWkt[polygonWkt]; + + if (mode === undefined) { + query = `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${wkt}'), ${resolution})) as cell_count`; + } else { + query = `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${wkt}'), ${resolution}, '${mode}')) as cell_count`; + } + + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); +}); + +describe('H3_POLYFILL should not support POINT Geographies', () => { + const pointWkt = 'POINT(1.111 5.555)'; + + test.each([ + [undefined, 0], + ['center', 0], + ['contains', 0], + ['intersects', 0] + ])('with mode %s, should return empty array', async (mode, expectedCellCount) => { + let query = mode === undefined ? + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${pointWkt}'), 6)) as cell_count` : + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${pointWkt}'), 6, '${mode}')) as cell_count`; + + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); +}); + +describe('H3_POLYFILL should not support MULTIPOINT Geographies', () => { + const multiPointWkt = 'MULTIPOINT(1.111 5.555, 2.222 6.666)'; + + test.each([ + [undefined, 0], + ['center', 0], + ['contains', 0], + ['intersects', 0] + ])('with mode %s, should return empty array', async (mode, expectedCellCount) => { + let query = mode === undefined ? + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${multiPointWkt}'), 6)) as cell_count` : + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${multiPointWkt}'), 6, '${mode}')) as cell_count`; + + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); +}); + +describe('H3_POLYFILL should not support LINESTRING Geographies', () => { + const lineStringWkt = 'LINESTRING(0 0, 1 1)'; + + test.each([ + [undefined, 0], + ['center', 0], + ['contains', 0], + ['intersects', 0] + ])('with mode %s, should return empty array', async (mode, expectedCellCount) => { + let query = mode === undefined ? + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${lineStringWkt}'), 6)) as cell_count` : + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${lineStringWkt}'), 6, '${mode}')) as cell_count`; + + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); +}); + +describe('H3_POLYFILL should not support MULTILINESTRING Geographies', () => { + const multiLineStringWkt = 'MULTILINESTRING((0 0, 1 1), (2 2, 3 3))'; + + test.each([ + [undefined, 0], + ['center', 0], + ['contains', 0], + ['intersects', 0] + ])('with mode %s, should return empty array', async (mode, expectedCellCount) => { + let query = mode === undefined ? + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${multiLineStringWkt}'), 6)) as cell_count` : + `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${multiLineStringWkt}'), 6, '${mode}')) as cell_count`; + + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); +}); + +describe('H3_POLYFILL should NOT support NULL Geography', () => { + test('Returns []', async () => { + + let query = 'SELECT ARRAY_SIZE(H3_POLYFILL(NULL, 6, \'center\')) as cell_count' + let rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(0) + }); +}) + +describe('H3_POLYFILL for Geographies crossing the Prime-Meridian multiple times', () => { + const polygonWkt = 'POLYGON ((-16.226053271365 29.7435335822744,-13.1839184674949 35.1034853795694,9.26993365630844 26.9911259025824,-4.34724118006261 13.9534053145676,13.0363862706238 6.99995433429298,-15.9363261471869 -5.31344844327657,-19.5579151994132 0.191366916107455,-5.6510132388641 5.98590939966961,-15.6465990230088 10.6215433865193,-3.62292336961735 24.5284453470685,-16.226053271365 29.7435335822744))'; + const resolution = 3; + + test.each([ + ['center', 567], + ['contains', 469], + ['intersects', 667] + ])('with mode %s, should return expected cell count', async (mode, expectedCellCount) => { + const query = `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${polygonWkt}'), ${resolution}, '${mode}')) as cell_count`; + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); +}); + +describe('H3_POLYFILL for POLYGON Geographies over 180 degrees wide', () => { + const polygonWkt = 'POLYGON((-160 -30, -160 30, 160 30, 160 -30, -160 -30))'; + const resolution = 0; + + test.each([ + ['center', 56], + ['contains', 32], + ['intersects', 76] + ])('with mode %s, should return expected cell count', async (mode, expectedCellCount) => { + const query = `SELECT ARRAY_SIZE(H3_POLYFILL(TO_GEOGRAPHY('${polygonWkt}'), ${resolution}, '${mode}')) as cell_count`; + const rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(expectedCellCount); + }); +}); + +describe('H3_POLYFILL called with a H3 cell boundary/polygon in CENTER mode at the same resolution should return only that cell ID', () => { + + test.each([ + ['8029fffffffffff', 0], + ['81283ffffffffff', 1], + ['822837fffffffff', 2], + ['832834fffffffff', 3], + ['8428347ffffffff', 4], + ['85283463fffffff', 5], + ['862834637ffffff', 6], + ['872834636ffffff', 7], + ['882834636dfffff', 8], + ['892834636dbffff', 9], + ['8a2834636db7fff', 10], + ['8b2834636db5fff', 11], + ['8c2834636db5bff', 12], + ['8d2834636db5b3f', 13], + ['8e2834636db5b4f', 14], + ['8f2834636db5bac', 15] + ])('boundary of cell with id %s at resolution level %i', async (cellId, resolution) => { + let query = `SELECT H3_POLYFILL(H3_CELL_TO_BOUNDARY('${cellId}'), '${resolution}', 'center') as h3_cell`; + let rows = await runQuery(query); + expect(rows[0].H3_CELL).toEqual([cellId]) + }) + +}) + +describe('H3_POLYFILL called with a H3 cell boundary/polygon in CENTER mode as that cells resolution+1 should its 7 child cell ids. Same as calling H3_CELL_TO_CHILDREN_STRINGS.', () => { + + test.each([ + ['8029fffffffffff', 1], + ['81283ffffffffff', 2], + ['822837fffffffff', 3], + ['832834fffffffff', 4], + ['8428347ffffffff', 5], + ['85283463fffffff', 6], + ['862834637ffffff', 7], + ['872834636ffffff', 8], + ['882834636dfffff', 9], + ['892834636dbffff', 10], + ['8a2834636db7fff', 11], + ['8b2834636db5fff', 12], + ['8c2834636db5bff', 13], + ['8d2834636db5b3f', 14], + ['8e2834636db5b4f', 15] + ])('boundary of cell with id %s at resolution level %i', async (cellId, resolution) => { + let query = `SELECT ARRAY_SIZE(H3_POLYFILL(H3_CELL_TO_BOUNDARY('${cellId}'), '${resolution}', 'center')) as cell_count`; + let rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(7) + }) +}) + +describe('H3_POLYFILL called with a H3 cell boundary/polygon in INTERSECTS mode at the same resolution should return 7 ids. Itself and 6 neighbours.', () => { + + test.each([ + ['8029fffffffffff', 0], + ['81283ffffffffff', 1], + ['822837fffffffff', 2], + ['832834fffffffff', 3], + ['8428347ffffffff', 4], + ['85283463fffffff', 5], + ['862834637ffffff', 6], + ['872834636ffffff', 7], + ['882834636dfffff', 8], + ['892834636dbffff', 9], + ['8a2834636db7fff', 10], + ['8b2834636db5fff', 11], + ['8c2834636db5bff', 12], + ['8d2834636db5b3f', 13], + ['8e2834636db5b4f', 14], + ['8f2834636db5bac', 15] + ])('boundary of cell with id %s at resolution level %i', async (cellId, resolution) => { + let query = `SELECT ARRAY_SIZE(H3_POLYFILL(H3_CELL_TO_BOUNDARY('${cellId}'), '${resolution}', 'intersects')) as cell_count`; + let rows = await runQuery(query); + expect(rows[0].CELL_COUNT).toEqual(7) + }) + +}) + +describe('H3_POLYFILL called with a H3 cell boundary/polygon in CONTAINS mode at the same resolution should return its own ID. H3 cells contains themselves.', () => { + + test.each([ + ['8029fffffffffff', 0], + ['81283ffffffffff', 1], + ['822837fffffffff', 2], + ['832834fffffffff', 3], + ['8428347ffffffff', 4], + ['85283463fffffff', 5], + ['862834637ffffff', 6], + ['872834636ffffff', 7], + ['882834636dfffff', 8], + ['892834636dbffff', 9], + ['8a2834636db7fff', 10], + ['8b2834636db5fff', 11], + ['8c2834636db5bff', 12], + ['8d2834636db5b3f', 13], + ['8e2834636db5b4f', 14], + ['8f2834636db5bac', 15] + ])('boundary of cell with id %s at resolution level %i', async (cellId, resolution) => { + let query = `SELECT H3_POLYFILL(H3_CELL_TO_BOUNDARY('${cellId}'), '${resolution}', 'contains') as h3_cell`; + let rows = await runQuery(query); + expect(rows[0].H3_CELL).toEqual([cellId]) + }) + +}) \ No newline at end of file diff --git a/clouds/snowflake/modules/test/h3/H3_POLYFILL_TABLE.test.js b/clouds/snowflake/modules/test/h3/H3_POLYFILL_TABLE.test.js deleted file mode 100644 index 2c1b309d7..000000000 --- a/clouds/snowflake/modules/test/h3/H3_POLYFILL_TABLE.test.js +++ /dev/null @@ -1,26 +0,0 @@ -const { runQuery } = require('../../../common/test-utils'); - -const SF_SCHEMA = process.env.SF_SCHEMA; - -test('H3_POLYFILL_TABLE should generate the correct query', async () => { - const query = `SELECT @@SF_SCHEMA@@._H3_POLYFILL_QUERY( - 'SELECT geom, name, value FROM ..

  • ', - 12, 'center', - '..' - ) AS output`; - const rows = await runQuery(query); - expect(rows.length).toEqual(1); - expect(rows[0].OUTPUT).toEqual(` - CREATE OR REPLACE TABLE .. CLUSTER BY (h3) AS - WITH __input AS (SELECT geom, name, value FROM ..
    ), - __cells AS ( - SELECT CAST(children.value AS STRING) AS h3, i.* - FROM __input AS i, - TABLE(FLATTEN(@@SF_SCHEMA@@._H3_POLYFILL_INIT(geom, 8))) AS parent, - TABLE(FLATTEN(@@SF_SCHEMA@@.H3_TOCHILDREN(CAST(parent.value AS STRING), 12))) AS children - ) - SELECT * EXCLUDE(geom) - FROM __cells - WHERE ST_INTERSECTS(geom, @@SF_SCHEMA@@.H3_CENTER(h3)) - `.replace(/@@SF_SCHEMA@@/g, SF_SCHEMA)); -}); \ No newline at end of file diff --git a/clouds/snowflake/modules/test/h3/H3_RESOLUTION.test.js b/clouds/snowflake/modules/test/h3/H3_RESOLUTION.test.js index 2024584ad..8b725e406 100644 --- a/clouds/snowflake/modules/test/h3/H3_RESOLUTION.test.js +++ b/clouds/snowflake/modules/test/h3/H3_RESOLUTION.test.js @@ -20,7 +20,7 @@ test('Returns NULL with invalid parameters', async () => { expect(rows[1].RESOLUTION).toEqual(null); }); -test('Returns NULL the expected resolution', async () => { +test('Returns the expected resolution', async () => { const query = ` WITH ids AS ( diff --git a/clouds/snowflake/modules/test/utils/GET_DATABASE.test.js b/clouds/snowflake/modules/test/utils/GET_DATABASE.test.js new file mode 100644 index 000000000..f102345fb --- /dev/null +++ b/clouds/snowflake/modules/test/utils/GET_DATABASE.test.js @@ -0,0 +1,24 @@ +const { runQuery } = require('../../../common/test-utils'); + +describe('_GET_DATABASE should detect the correct DATABASE from table identifier', () => { + + test('when the identifier is in the format: ..
    ', async () => { + let rows = await runQuery("SELECT _GET_DATABASE('databasename.schemaname.tablename') AS result"); + expect(rows[0].RESULT).toEqual('databasename') + }) + + test('when the identifier is in the format: .
    ', async () => { + let rows = await runQuery('SELECT CURRENT_DATABASE() AS CURRENT_DATABASE'); + expected_db = rows[0].CURRENT_DATABASE + rows = await runQuery("SELECT _GET_DATABASE('schemaname.tablename') AS result"); + expect(rows[0].RESULT).toEqual(expected_db) + }) + + test('when the identifier is in the format:
    ', async () => { + let rows = await runQuery('SELECT CURRENT_DATABASE() AS CURRENT_DATABASE'); + expected_db = rows[0].CURRENT_DATABASE + rows = await runQuery("SELECT _GET_DATABASE('tablename') AS result"); + expect(rows[0].RESULT).toEqual(expected_db) + }) + +}) \ No newline at end of file diff --git a/clouds/snowflake/modules/test/utils/GET_SCHEMA.test.js b/clouds/snowflake/modules/test/utils/GET_SCHEMA.test.js new file mode 100644 index 000000000..f68864ef7 --- /dev/null +++ b/clouds/snowflake/modules/test/utils/GET_SCHEMA.test.js @@ -0,0 +1,22 @@ +const { runQuery } = require('../../../common/test-utils'); + +describe('_GET_SCHEMA should detect the correct SCHEMA from table identifier', () => { + + test('when the identifier is in the format: ..
    ', async () => { + let rows = await runQuery("SELECT _GET_SCHEMA('databasename.schemaname.tablename') AS result"); + expect(rows[0].RESULT).toEqual('schemaname') + }) + + test('when the identifier is in the format: .
    ', async () => { + let rows = await runQuery("SELECT _GET_SCHEMA('schemaname.tablename') AS result"); + expect(rows[0].RESULT).toEqual('schemaname') + }) + + test('when the identifier is in the format:
    ', async () => { + let rows = await runQuery('SELECT CURRENT_SCHEMA() AS CURRENT_SCHEMA'); + expected_schema = rows[0].CURRENT_SCHEMA + rows = await runQuery("SELECT _GET_SCHEMA('tablename') AS result"); + expect(rows[0].RESULT).toEqual(expected_schema) + }) + +}) \ No newline at end of file diff --git a/clouds/snowflake/version b/clouds/snowflake/version index 6085e9465..23aa83906 100644 --- a/clouds/snowflake/version +++ b/clouds/snowflake/version @@ -1 +1 @@ -1.2.1 +1.2.2 From b5c43e1bc7bc5f1bdad11e7436cb8431e2e200d2 Mon Sep 17 00:00:00 2001 From: Valentin de la Cruz Barquero <6054336+vdelacruzb@users.noreply.github.com> Date: Wed, 22 May 2024 11:39:20 +0200 Subject: [PATCH 07/13] release: 2024-05-21 (#510) --- .github/workflows/snowflake.yml | 3 +-- .gitignore | 1 + CHANGELOG.md | 7 ++++++ LICENSE | 2 +- clouds/bigquery/common/DROP_FUNCTIONS.sql | 2 +- .../doc/constructors/ST_MAKEELLIPSE.md | 2 +- clouds/postgres/common/DROP_FUNCTIONS.sql | 2 +- clouds/postgres/common/test_utils/__init__.py | 10 +++++++- clouds/redshift/common/DROP_FUNCTIONS.sql | 2 +- .../doc/constructors/ST_MAKEELLIPSE.md | 2 +- clouds/snowflake/.~lock.results.csv# | 1 - clouds/snowflake/CHANGELOG.md | 4 ++++ clouds/snowflake/Makefile | 2 +- clouds/snowflake/common/DROP_FUNCTIONS.sql | 2 +- clouds/snowflake/common/Makefile | 6 ++++- .../doc/constructors/ST_MAKEELLIPSE.md | 2 +- .../modules/sql/h3/H3_POLYFILL_TABLE.sql | 23 ++++++------------ .../modules/sql/utils/_GET_DATABASE.sql | 22 ----------------- .../modules/sql/utils/_GET_SCHEMA.sql | 24 ------------------- .../modules/test/utils/GET_DATABASE.test.js | 24 ------------------- .../modules/test/utils/GET_SCHEMA.test.js | 22 ----------------- clouds/snowflake/version | 2 +- 22 files changed, 44 insertions(+), 123 deletions(-) delete mode 100644 clouds/snowflake/.~lock.results.csv# delete mode 100644 clouds/snowflake/modules/sql/utils/_GET_DATABASE.sql delete mode 100644 clouds/snowflake/modules/sql/utils/_GET_SCHEMA.sql delete mode 100644 clouds/snowflake/modules/test/utils/GET_DATABASE.test.js delete mode 100644 clouds/snowflake/modules/test/utils/GET_SCHEMA.test.js diff --git a/.github/workflows/snowflake.yml b/.github/workflows/snowflake.yml index b3ba35762..f3ee08297 100644 --- a/.github/workflows/snowflake.yml +++ b/.github/workflows/snowflake.yml @@ -16,7 +16,7 @@ on: env: NODE_VERSION: 18.16 - PYTHON3_VERSION: 3.8.10 + PYTHON3_VERSION: 3.8.18 VIRTUALENV_VERSION: 20.21.1 GCLOUD_VERSION: 290.0.1 @@ -154,7 +154,6 @@ jobs: timeout-minutes: 10 env: PACKAGE_BUCKET: gs://carto-analytics-toolbox-core/snowflake - SF_DATABASE: 'carto' steps: - name: Checkout repo uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 9288cf6dc..a4b2a5fc1 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ package-lock.json MANIFEST *.ipynb .pgpass +.~lock.* # IntelliJ .idea/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f8988155..70682c788 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ CARTO Analytics Toolbox Core. All notable commits to this project will be documented in this file. +## 2024-05-21 + +- refactor(sf|h3): avoid memory limit exceeded in H3_POLYFILL_TABLE (#501) +- docs(bq,sf,rs|constructors): fix ST_MAKEELLIPSE angle parameter explanation (#505) +- chore(sf): update create-package and licenses year (#507) +- chore(pg): DB Connection Error in tests when % character in PG_PASSWORD (#509) + ## 2024-04-18 - chore(sf|h3): reimplement basic h3 functions (#489) diff --git a/LICENSE b/LICENSE index 3af7f2971..2fe2ec847 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ SPDX short identifier: BSD-3-Clause -Copyright (c) 2021-2022, CARTO +Copyright (c) 2021-2024, CARTO All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/clouds/bigquery/common/DROP_FUNCTIONS.sql b/clouds/bigquery/common/DROP_FUNCTIONS.sql index c24ad873b..48f24a7f1 100644 --- a/clouds/bigquery/common/DROP_FUNCTIONS.sql +++ b/clouds/bigquery/common/DROP_FUNCTIONS.sql @@ -1,5 +1,5 @@ --------------------------------- --- Copyright (C) 2021-2023 CARTO +-- Copyright (C) 2021-2024 CARTO --------------------------------- CREATE OR REPLACE PROCEDURE `@@BQ_DATASET@@.DROP_FUNCTIONS`() diff --git a/clouds/bigquery/modules/doc/constructors/ST_MAKEELLIPSE.md b/clouds/bigquery/modules/doc/constructors/ST_MAKEELLIPSE.md index c5512fe23..1d6e29d83 100644 --- a/clouds/bigquery/modules/doc/constructors/ST_MAKEELLIPSE.md +++ b/clouds/bigquery/modules/doc/constructors/ST_MAKEELLIPSE.md @@ -11,7 +11,7 @@ Takes a Point and calculates the ellipse polygon given two semi-axes expressed i * `center`: `GEOGRAPHY` center point. * `xSemiAxis`: `FLOAT64` semi (major) axis of the ellipse along the x-axis. * `ySemiAxis`: `FLOAT64` semi (minor) axis of the ellipse along the y-axis. -* `angle`: `FLOAT64`|`NULL` angle of rotation (along the vertical axis), from North in decimal degrees, positive clockwise. If `NULL` the default value `0` is used. +* `angle`: `FLOAT64`|`NULL` angle of rotation (along the horizontal axis), from East in decimal degrees, positive clockwise. If `NULL` the default value `0` is used. * `units`: `STRING`|`NULL` units of length, the supported options are: miles, kilometers, and degrees. If `NULL`the default value `kilometers` is used. * `steps`: `INT64`|`NULL` number of steps. If `NULL` the default value `64` is used. diff --git a/clouds/postgres/common/DROP_FUNCTIONS.sql b/clouds/postgres/common/DROP_FUNCTIONS.sql index d2c02c192..c1b879c3b 100644 --- a/clouds/postgres/common/DROP_FUNCTIONS.sql +++ b/clouds/postgres/common/DROP_FUNCTIONS.sql @@ -1,5 +1,5 @@ --------------------------------- --- Copyright (C) 2021-2023 CARTO +-- Copyright (C) 2021-2024 CARTO --------------------------------- CREATE OR REPLACE PROCEDURE @@PG_SCHEMA@@.__DROP_FUNCTIONS diff --git a/clouds/postgres/common/test_utils/__init__.py b/clouds/postgres/common/test_utils/__init__.py index 75fd7c083..2fa1d360c 100644 --- a/clouds/postgres/common/test_utils/__init__.py +++ b/clouds/postgres/common/test_utils/__init__.py @@ -5,6 +5,7 @@ import pandas as pd import psycopg2 +from urllib.parse import quote_plus from shapely import wkt from sqlalchemy import create_engine @@ -15,6 +16,13 @@ 'password': os.environ['PG_PASSWORD'], 'port': 5432, } +URL_PG_CONFIG = { + 'host': os.environ['PG_HOST'], + 'database': os.environ['PG_DATABASE'], + 'user': os.environ['PG_USER'], + 'password': quote_plus(os.environ['PG_PASSWORD']), + 'port': 5432, +} conn = psycopg2.connect(**PG_CONFIG) conn.autocommit = ( @@ -22,7 +30,7 @@ ) connection_string = 'postgresql://{user}:{password}@{host}:{port}/{database}'.format( - **PG_CONFIG + **URL_PG_CONFIG ) engine = create_engine(connection_string) diff --git a/clouds/redshift/common/DROP_FUNCTIONS.sql b/clouds/redshift/common/DROP_FUNCTIONS.sql index 57e194d57..a68ae6465 100644 --- a/clouds/redshift/common/DROP_FUNCTIONS.sql +++ b/clouds/redshift/common/DROP_FUNCTIONS.sql @@ -1,5 +1,5 @@ --------------------------------- --- Copyright (C) 2021-2023 CARTO +-- Copyright (C) 2021-2024 CARTO --------------------------------- CREATE OR REPLACE PROCEDURE @@RS_SCHEMA@@.__CREATE_DROP_TABLE diff --git a/clouds/redshift/modules/doc/constructors/ST_MAKEELLIPSE.md b/clouds/redshift/modules/doc/constructors/ST_MAKEELLIPSE.md index 380a10437..91251572f 100644 --- a/clouds/redshift/modules/doc/constructors/ST_MAKEELLIPSE.md +++ b/clouds/redshift/modules/doc/constructors/ST_MAKEELLIPSE.md @@ -11,7 +11,7 @@ Takes a Point as input and calculates the ellipse polygon given two semi-axes ex * `center`: `GEOMETRY` center point. * `xSemiAxis`: `FLOAT8` semi (major) axis of the ellipse along the x-axis. * `ySemiAxis`: `FLOAT8` semi (minor) axis of the ellipse along the y-axis. -* `angle` (optional): `FLOAT8` angle of rotation (along the vertical axis), from North in decimal degrees, positive clockwise. If not specified, the default value of `0` will be used. +* `angle` (optional): `FLOAT8` angle of rotation (along the horizontal axis), from East in decimal degrees, positive clockwise. If not specified, the default value of `0` will be used. * `units` (optional): `VARCHAR(10)` units of length. The supported options are: miles, kilometers, meters, and degrees. If not specified, `kilometers` will be used. * `steps` (optional): `INT` number of steps. If not specified, the default value of `64` will be used. diff --git a/clouds/snowflake/.~lock.results.csv# b/clouds/snowflake/.~lock.results.csv# deleted file mode 100644 index 044c5a006..000000000 --- a/clouds/snowflake/.~lock.results.csv# +++ /dev/null @@ -1 +0,0 @@ -,dean,thinkpad,27.03.2024 10:56,file:///home/dean/.config/libreoffice/4; \ No newline at end of file diff --git a/clouds/snowflake/CHANGELOG.md b/clouds/snowflake/CHANGELOG.md index 399c14cac..31d31204c 100644 --- a/clouds/snowflake/CHANGELOG.md +++ b/clouds/snowflake/CHANGELOG.md @@ -4,6 +4,10 @@ CARTO Analytics Toolbox Core for Snowflake. All notable commits to this project will be documented in this file. +## [1.2.3] - 2024-05-21 + +- refactor(h3): avoid memory limit exceeded in H3_POLYFILL_TABLE (#501) + ## [1.2.2] - 2024-04-18 - chore(h3): reimplement basic h3 functions (#489) diff --git a/clouds/snowflake/Makefile b/clouds/snowflake/Makefile index 391bd6391..6abab1657 100644 --- a/clouds/snowflake/Makefile +++ b/clouds/snowflake/Makefile @@ -96,7 +96,7 @@ clean-modules: $(MAKE) -C modules clean create-package: - $(MAKE) build production=1 dropfirst=1 + $(MAKE) build production=1 dropfirst=1 database=CARTO rm -rf $(DIST_DIR) mkdir -p $(DIST_DIR)/$(PACKAGE_NAME) diff --git a/clouds/snowflake/common/DROP_FUNCTIONS.sql b/clouds/snowflake/common/DROP_FUNCTIONS.sql index 143059442..997eecc65 100644 --- a/clouds/snowflake/common/DROP_FUNCTIONS.sql +++ b/clouds/snowflake/common/DROP_FUNCTIONS.sql @@ -1,5 +1,5 @@ --------------------------------- --- Copyright (C) 2021-2023 CARTO +-- Copyright (C) 2021-2024 CARTO --------------------------------- CREATE OR REPLACE PROCEDURE @@SF_SCHEMA@@._DROP_FUNCTIONS() diff --git a/clouds/snowflake/common/Makefile b/clouds/snowflake/common/Makefile index 5b1d5f00c..3021af7a9 100644 --- a/clouds/snowflake/common/Makefile +++ b/clouds/snowflake/common/Makefile @@ -4,13 +4,17 @@ PYTHON3_VERSION = 3 VENV3_DIR ?= $(COMMON_DIR)/../venv3 VENV3_BIN = $(VENV3_DIR)/bin NODE_MODULES_DEV = $(COMMON_DIR)/node_modules -export SF_SCHEMA_DEFAULT = carto +export SF_SCHEMA_DEFAULT = CARTO ifneq (,$(wildcard $(ENV_DIR)/.env)) include $(ENV_DIR)/.env export $(shell sed 's/=.*//' $(ENV_DIR)/.env) endif +ifdef database +export SF_DATABASE = $(database) +endif + ifeq ($(production),1) export SF_SCHEMA = $(SF_DATABASE).$(SF_SCHEMA_DEFAULT) export SF_UNQUALIFIED_SCHEMA = $(SF_SCHEMA_DEFAULT) diff --git a/clouds/snowflake/modules/doc/constructors/ST_MAKEELLIPSE.md b/clouds/snowflake/modules/doc/constructors/ST_MAKEELLIPSE.md index 97c6de035..e0c5ff2e3 100644 --- a/clouds/snowflake/modules/doc/constructors/ST_MAKEELLIPSE.md +++ b/clouds/snowflake/modules/doc/constructors/ST_MAKEELLIPSE.md @@ -11,7 +11,7 @@ Takes a Point and calculates the ellipse polygon given two semi-axes expressed i * `center`: `GEOGRAPHY` center point. * `xSemiAxis`: `DOUBLE` semi (major) axis of the ellipse along the x-axis. * `ySemiAxis`: `DOUBLE` semi (minor) axis of the ellipse along the y-axis. -* `angle` (optional): `DOUBLE` angle of rotation (along the vertical axis), from North in decimal degrees, positive clockwise. By default `angle` is `0`. +* `angle` (optional): `DOUBLE` angle of rotation (along the horizontal axis), from East in decimal degrees, positive clockwise. By default `angle` is `0`. * `units` (optional): `STRING` units of length, the supported options are: miles, kilometers, and degrees. By default `units` is `kilometers`. * `steps` (optional): `INT` number of steps. By default `steps` is `64`. diff --git a/clouds/snowflake/modules/sql/h3/H3_POLYFILL_TABLE.sql b/clouds/snowflake/modules/sql/h3/H3_POLYFILL_TABLE.sql index 741fa6e5a..e87d76474 100644 --- a/clouds/snowflake/modules/sql/h3/H3_POLYFILL_TABLE.sql +++ b/clouds/snowflake/modules/sql/h3/H3_POLYFILL_TABLE.sql @@ -13,23 +13,14 @@ RETURNS STRING LANGUAGE SQL EXECUTE AS CALLER AS $$ -DECLARE - column_names_csv STRING; - polyfill_query STRING; BEGIN + EXECUTE IMMEDIATE ' + CREATE OR REPLACE TABLE ' || output_table || ' CLUSTER BY (H3) AS + WITH __input AS ( ' || input_query || ' ) + SELECT CAST(cell.value AS STRING) AS h3, i.* EXCLUDE(geom) + FROM __input AS i, TABLE(FLATTEN(@@SF_SCHEMA@@.H3_POLYFILL(geom, ' || resolution || ', ''' || mode || '''))) AS cell; + '; - -- Validate - EXECUTE IMMEDIATE 'SELECT * FROM (' || input_query || ') WHERE FALSE'; - - -- New table with correct columns - EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE ' || output_table || ' CLUSTER BY (H3) AS SELECT * EXCLUDE geom, NULL as H3 FROM (' || input_query || ') WHERE FALSE'; - - column_names_csv := (SELECT LISTAGG(COLUMN_NAME, ',') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ILIKE :output_table AND TABLE_CATALOG=@@SF_SCHEMA@@._GET_DATABASE(:output_table) AND TABLE_SCHEMA=@@SF_SCHEMA@@._GET_SCHEMA(:output_table)); - - polyfill_query := 'INSERT INTO ' || output_table || ' (' || column_names_csv || ') SELECT ' || column_names_csv || ' FROM (WITH virtual_table AS (' || input_query || ') SELECT *, value as H3 FROM virtual_table, LATERAL FLATTEN(input => @@SF_SCHEMA@@.H3_POLYFILL(virtual_table.geom, ' || resolution || ',\'' || mode || '\')))'; - - EXECUTE IMMEDIATE polyfill_query; - - RETURN 'Finished!'; + RETURN 'H3 Polyfill result added in table ' || output_table; END; $$; diff --git a/clouds/snowflake/modules/sql/utils/_GET_DATABASE.sql b/clouds/snowflake/modules/sql/utils/_GET_DATABASE.sql deleted file mode 100644 index 6b2eab342..000000000 --- a/clouds/snowflake/modules/sql/utils/_GET_DATABASE.sql +++ /dev/null @@ -1,22 +0,0 @@ ---------------------------- --- Copyright (C) 2024 CARTO ---------------------------- - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._GET_DATABASE -(table_identifier STRING) -RETURNS STRING -LANGUAGE SQL -IMMUTABLE -AS $$ - WITH split_identifier AS ( - SELECT ARRAY_SIZE(SPLIT(table_identifier, '.')) AS parts_count, - SPLIT_PART(table_identifier, '.', 1) AS first_part - FROM (SELECT TABLE_IDENTIFIER AS table_identifier) - ) - SELECT - CASE parts_count - WHEN 3 THEN first_part - ELSE CURRENT_DATABASE() - END - FROM split_identifier -$$; diff --git a/clouds/snowflake/modules/sql/utils/_GET_SCHEMA.sql b/clouds/snowflake/modules/sql/utils/_GET_SCHEMA.sql deleted file mode 100644 index 2178a0d76..000000000 --- a/clouds/snowflake/modules/sql/utils/_GET_SCHEMA.sql +++ /dev/null @@ -1,24 +0,0 @@ ---------------------------- --- Copyright (C) 2023 CARTO ---------------------------- - -CREATE OR REPLACE FUNCTION @@SF_SCHEMA@@._GET_SCHEMA -(table_identifier STRING) -RETURNS STRING -LANGUAGE SQL -IMMUTABLE -AS $$ - WITH split_identifier AS ( - SELECT ARRAY_SIZE(SPLIT(table_identifier, '.')) AS parts_count, - SPLIT_PART(table_identifier, '.', 1) AS first_part, - SPLIT_PART(table_identifier, '.', 2) AS second_part - FROM (SELECT TABLE_IDENTIFIER AS table_identifier) - ) - SELECT - CASE parts_count - WHEN 3 THEN second_part - WHEN 2 THEN first_part - ELSE CURRENT_SCHEMA() - END - FROM split_identifier -$$; diff --git a/clouds/snowflake/modules/test/utils/GET_DATABASE.test.js b/clouds/snowflake/modules/test/utils/GET_DATABASE.test.js deleted file mode 100644 index f102345fb..000000000 --- a/clouds/snowflake/modules/test/utils/GET_DATABASE.test.js +++ /dev/null @@ -1,24 +0,0 @@ -const { runQuery } = require('../../../common/test-utils'); - -describe('_GET_DATABASE should detect the correct DATABASE from table identifier', () => { - - test('when the identifier is in the format: ..
    ', async () => { - let rows = await runQuery("SELECT _GET_DATABASE('databasename.schemaname.tablename') AS result"); - expect(rows[0].RESULT).toEqual('databasename') - }) - - test('when the identifier is in the format: .
    ', async () => { - let rows = await runQuery('SELECT CURRENT_DATABASE() AS CURRENT_DATABASE'); - expected_db = rows[0].CURRENT_DATABASE - rows = await runQuery("SELECT _GET_DATABASE('schemaname.tablename') AS result"); - expect(rows[0].RESULT).toEqual(expected_db) - }) - - test('when the identifier is in the format:
    ', async () => { - let rows = await runQuery('SELECT CURRENT_DATABASE() AS CURRENT_DATABASE'); - expected_db = rows[0].CURRENT_DATABASE - rows = await runQuery("SELECT _GET_DATABASE('tablename') AS result"); - expect(rows[0].RESULT).toEqual(expected_db) - }) - -}) \ No newline at end of file diff --git a/clouds/snowflake/modules/test/utils/GET_SCHEMA.test.js b/clouds/snowflake/modules/test/utils/GET_SCHEMA.test.js deleted file mode 100644 index f68864ef7..000000000 --- a/clouds/snowflake/modules/test/utils/GET_SCHEMA.test.js +++ /dev/null @@ -1,22 +0,0 @@ -const { runQuery } = require('../../../common/test-utils'); - -describe('_GET_SCHEMA should detect the correct SCHEMA from table identifier', () => { - - test('when the identifier is in the format: ..
    ', async () => { - let rows = await runQuery("SELECT _GET_SCHEMA('databasename.schemaname.tablename') AS result"); - expect(rows[0].RESULT).toEqual('schemaname') - }) - - test('when the identifier is in the format: .
    ', async () => { - let rows = await runQuery("SELECT _GET_SCHEMA('schemaname.tablename') AS result"); - expect(rows[0].RESULT).toEqual('schemaname') - }) - - test('when the identifier is in the format:
    ', async () => { - let rows = await runQuery('SELECT CURRENT_SCHEMA() AS CURRENT_SCHEMA'); - expected_schema = rows[0].CURRENT_SCHEMA - rows = await runQuery("SELECT _GET_SCHEMA('tablename') AS result"); - expect(rows[0].RESULT).toEqual(expected_schema) - }) - -}) \ No newline at end of file diff --git a/clouds/snowflake/version b/clouds/snowflake/version index 23aa83906..0495c4a88 100644 --- a/clouds/snowflake/version +++ b/clouds/snowflake/version @@ -1 +1 @@ -1.2.2 +1.2.3 From eff161e57ac24d7e02d5fcff0494445b0999af11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Tue, 2 Jul 2024 08:04:25 +0200 Subject: [PATCH 08/13] update changelogs --- CHANGELOG.md | 5 +++++ clouds/bigquery/CHANGELOG.md | 4 ++++ clouds/bigquery/version | 2 +- clouds/snowflake/CHANGELOG.md | 4 ++++ clouds/snowflake/version | 2 +- 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70682c788..f88bf367b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ CARTO Analytics Toolbox Core. All notable commits to this project will be documented in this file. +## 2024-06-27 + +- chore(sf): refactor at snowflake native app to an installer (#512) +- chore(bq|quadbin): optimize polyfill (#513) + ## 2024-05-21 - refactor(sf|h3): avoid memory limit exceeded in H3_POLYFILL_TABLE (#501) diff --git a/clouds/bigquery/CHANGELOG.md b/clouds/bigquery/CHANGELOG.md index 2e7b143db..d25171df8 100644 --- a/clouds/bigquery/CHANGELOG.md +++ b/clouds/bigquery/CHANGELOG.md @@ -4,6 +4,10 @@ CARTO Analytics Toolbox Core for BigQuery. All notable commits to this project will be documented in this file. +## [1.2.3] - 2024-06-27 + +- chore(quadbin): optimize polyfill (#513) + ## [1.2.2] - 2024-04-18 - docs(processing): update voronoi doc (#492) diff --git a/clouds/bigquery/version b/clouds/bigquery/version index 23aa83906..0495c4a88 100644 --- a/clouds/bigquery/version +++ b/clouds/bigquery/version @@ -1 +1 @@ -1.2.2 +1.2.3 diff --git a/clouds/snowflake/CHANGELOG.md b/clouds/snowflake/CHANGELOG.md index 31d31204c..176a981d9 100644 --- a/clouds/snowflake/CHANGELOG.md +++ b/clouds/snowflake/CHANGELOG.md @@ -4,6 +4,10 @@ CARTO Analytics Toolbox Core for Snowflake. All notable commits to this project will be documented in this file. +## [1.2.4] - 2024-06-27 + +- chore(sf): refactor at snowflake native app to an installer (#512) + ## [1.2.3] - 2024-05-21 - refactor(h3): avoid memory limit exceeded in H3_POLYFILL_TABLE (#501) diff --git a/clouds/snowflake/version b/clouds/snowflake/version index 0495c4a88..e8ea05db8 100644 --- a/clouds/snowflake/version +++ b/clouds/snowflake/version @@ -1 +1 @@ -1.2.3 +1.2.4 From ecf3a793a3b2319a6479206936e20baf0b5e862b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Tue, 2 Jul 2024 10:33:52 +0200 Subject: [PATCH 09/13] attempt to fix h3 bundle in sf --- clouds/snowflake/common/package.json | 1 + clouds/snowflake/common/rollup.config.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/clouds/snowflake/common/package.json b/clouds/snowflake/common/package.json index c227179cd..f5fd44491 100644 --- a/clouds/snowflake/common/package.json +++ b/clouds/snowflake/common/package.json @@ -10,6 +10,7 @@ "markdownlint-cli": "^0.32.2", "rollup": "^2.47.0", "rollup-plugin-bundle-size": "^1.0.3", + "rollup-plugin-polyfill-node": "^0.13.0", "rollup-plugin-terser": "^7.0.2", "snowflake-sdk": "1.9.3" } diff --git a/clouds/snowflake/common/rollup.config.js b/clouds/snowflake/common/rollup.config.js index 3c19ed6ed..51498f215 100644 --- a/clouds/snowflake/common/rollup.config.js +++ b/clouds/snowflake/common/rollup.config.js @@ -5,6 +5,7 @@ import resolve from '@rollup/plugin-node-resolve'; import json from '@rollup/plugin-json'; import { terser } from 'rollup-plugin-terser'; import bundleSize from 'rollup-plugin-bundle-size'; +import nodePolyfills from 'rollup-plugin-polyfill-node'; // Find final input path from dirs array let input; @@ -36,6 +37,7 @@ export default { footer: process.env.UNIT_TEST ? '' : name +' = _' + name + ';}' }, plugins: [ + nodePolyfills(), resolve(), commonjs({ requireReturnsDefault: 'auto' }), json(), From ff38eebe7ae2d3770ab15c5ea801f10dc4c98c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Tue, 2 Jul 2024 12:00:47 +0200 Subject: [PATCH 10/13] attempt to fix h3 bundle --- clouds/snowflake/common/rollup.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clouds/snowflake/common/rollup.config.js b/clouds/snowflake/common/rollup.config.js index 51498f215..1845c4901 100644 --- a/clouds/snowflake/common/rollup.config.js +++ b/clouds/snowflake/common/rollup.config.js @@ -7,6 +7,7 @@ import { terser } from 'rollup-plugin-terser'; import bundleSize from 'rollup-plugin-bundle-size'; import nodePolyfills from 'rollup-plugin-polyfill-node'; + // Find final input path from dirs array let input; const dirs = process.env.DIRS.split(','); @@ -37,9 +38,9 @@ export default { footer: process.env.UNIT_TEST ? '' : name +' = _' + name + ';}' }, plugins: [ - nodePolyfills(), resolve(), commonjs({ requireReturnsDefault: 'auto' }), + nodePolyfills(), json(), terser(), bundleSize() From 3e47deea790e98df8d495c032686f47e5ecee0a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Tue, 2 Jul 2024 15:12:50 +0200 Subject: [PATCH 11/13] test: fix h3 bundle in sf (#515) --- clouds/snowflake/common/package.json | 1 - clouds/snowflake/common/rollup.config.js | 3 --- clouds/snowflake/libraries/javascript/package.json | 5 ++++- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/clouds/snowflake/common/package.json b/clouds/snowflake/common/package.json index f5fd44491..c227179cd 100644 --- a/clouds/snowflake/common/package.json +++ b/clouds/snowflake/common/package.json @@ -10,7 +10,6 @@ "markdownlint-cli": "^0.32.2", "rollup": "^2.47.0", "rollup-plugin-bundle-size": "^1.0.3", - "rollup-plugin-polyfill-node": "^0.13.0", "rollup-plugin-terser": "^7.0.2", "snowflake-sdk": "1.9.3" } diff --git a/clouds/snowflake/common/rollup.config.js b/clouds/snowflake/common/rollup.config.js index 1845c4901..3c19ed6ed 100644 --- a/clouds/snowflake/common/rollup.config.js +++ b/clouds/snowflake/common/rollup.config.js @@ -5,8 +5,6 @@ import resolve from '@rollup/plugin-node-resolve'; import json from '@rollup/plugin-json'; import { terser } from 'rollup-plugin-terser'; import bundleSize from 'rollup-plugin-bundle-size'; -import nodePolyfills from 'rollup-plugin-polyfill-node'; - // Find final input path from dirs array let input; @@ -40,7 +38,6 @@ export default { plugins: [ resolve(), commonjs({ requireReturnsDefault: 'auto' }), - nodePolyfills(), json(), terser(), bundleSize() diff --git a/clouds/snowflake/libraries/javascript/package.json b/clouds/snowflake/libraries/javascript/package.json index 86fbebf39..9fb6f405f 100644 --- a/clouds/snowflake/libraries/javascript/package.json +++ b/clouds/snowflake/libraries/javascript/package.json @@ -6,12 +6,15 @@ "license": "BSD-3-Clause", "private": true, "dependencies": { - "@math.gl/web-mercator": "^3.6.2", + "@math.gl/web-mercator": "3.6.3", "@mapbox/tile-cover": "3.0.2", "@mapbox/tilebelt": "1.0.2", "long": "4.0.0", "@turf/turf": "6.3.0", "h3-js": "3.7.2", "@placekey/placekey": "1.0.3" + }, + "resolutions": { + "@turf/bbox": "6.5.0" } } From 62348482013a16584e099131efabbc2c822dc097 Mon Sep 17 00:00:00 2001 From: Valentin de la Cruz Barquero <6054336+vdelacruzb@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:10:06 +0200 Subject: [PATCH 12/13] release: 2024-08-22 (#521) --- CHANGELOG.md | 6 ++++++ clouds/postgres/common/python3_requirements.txt | 2 +- clouds/redshift/libraries/python/requirements.txt | 2 +- clouds/snowflake/native_app/README.md | 10 +++++----- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f88bf367b..ad0ccff19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ CARTO Analytics Toolbox Core. All notable commits to this project will be documented in this file. +## 2024-08-22 + +- chore(rs): bump scipy from 0.12.0 to 0.12.1 in /clouds/redshift/libraries/python (#518) +- docs(sf): fix native apps installation doc (#519) +- fix(pg): lock numpy to v1.24.4 until pandas supports 2.X.X (#520) + ## 2024-06-27 - chore(sf): refactor at snowflake native app to an installer (#512) diff --git a/clouds/postgres/common/python3_requirements.txt b/clouds/postgres/common/python3_requirements.txt index ab1c68abe..b97632d9f 100644 --- a/clouds/postgres/common/python3_requirements.txt +++ b/clouds/postgres/common/python3_requirements.txt @@ -14,4 +14,4 @@ pandas==1.3.2 SQLAlchemy==1.4.23 mapbox-vector-tile==1.2.1 sqlfluff==1.3.1 - +numpy==1.24.4 diff --git a/clouds/redshift/libraries/python/requirements.txt b/clouds/redshift/libraries/python/requirements.txt index cc61ca38d..da02dd9d3 100644 --- a/clouds/redshift/libraries/python/requirements.txt +++ b/clouds/redshift/libraries/python/requirements.txt @@ -2,6 +2,6 @@ quadbin==0.2.2 geojson==2.5.0 pygc==1.1.0 numpy==1.8.2 -scipy==0.12.0 +scipy==0.12.1 s2sphere==0.2.5 mercantile==1.2.1 diff --git a/clouds/snowflake/native_app/README.md b/clouds/snowflake/native_app/README.md index 4e2a27fca..36764875d 100644 --- a/clouds/snowflake/native_app/README.md +++ b/clouds/snowflake/native_app/README.md @@ -8,7 +8,7 @@ The CARTO Analytics Toolbox for Snowflake is composed of a set of user-defined f #### Install the Analytics Toolbox -This Native App is an installer so it does not contain the actual Analytics Toolbox functions and procedures. For the sake of documenting the process, we'll will assume a database named CARTO, as well as a schema named CARTO in that database, also we assume the app to be called CARTO_INSTALLER. The next guidelines and examples will assume that in order to simplify the onboarding process. +This Native App is an installer so it does not contain the actual Analytics Toolbox functions and procedures. For the sake of documenting the process, we'll will assume a database named CARTO, as well as a schema named CARTO in that database, also we assume the app to be called CARTO_ANALYTICS_TOOLBOX. The next guidelines and examples will assume that in order to simplify the onboarding process. All the database, schema and user can have a different name, but remember to adapt the code snippets accordingly. @@ -26,11 +26,11 @@ CREATE SCHEMA CARTO.CARTO; GRANT ALL ON SCHEMA CARTO.CARTO TO ROLE SYSADMIN; -- Set create function and procedure permissions -GRANT USAGE ON DATABASE CARTO TO APPLICATION CARTO; -GRANT USAGE, CREATE FUNCTION, CREATE PROCEDURE ON SCHEMA CARTO.CARTO TO APPLICATION CARTO; +GRANT USAGE ON DATABASE CARTO TO APPLICATION CARTO_ANALYTICS_TOOLBOX; +GRANT USAGE, CREATE FUNCTION, CREATE PROCEDURE ON SCHEMA CARTO.CARTO TO APPLICATION CARTO_ANALYTICS_TOOLBOX; -- Generate the installer procedure in the specified location -CALL CARTO_INSTALLER.CARTO.GENERATE_INSTALLER('CARTO.CARTO'); +CALL CARTO_ANALYTICS_TOOLBOX.CARTO.GENERATE_INSTALLER('CARTO.CARTO'); -- Update ownership of the install procedure GRANT OWNERSHIP ON PROCEDURE CARTO.CARTO.INSTALL(STRING, STRING) TO ROLE ACCOUNTADMIN REVOKE CURRENT GRANTS; @@ -44,7 +44,7 @@ GRANT USAGE ON FUTURE FUNCTIONS IN SCHEMA CARTO.CARTO TO ROLE PUBLIC; GRANT USAGE ON FUTURE PROCEDURES IN SCHEMA CARTO.CARTO TO ROLE PUBLIC; -- Install the Analytics Toolbox in CARTO.CARTO -CALL CARTO.CARTO.INSTALL('CARTO_INSTALLER', 'CARTO.CARTO'); +CALL CARTO.CARTO.INSTALL('CARTO_ANALYTICS_TOOLBOX', 'CARTO.CARTO'); ``` ### Usage Examples From 109a961aa41b89dbe6dcee361d676ce43ef69c48 Mon Sep 17 00:00:00 2001 From: Valentin de la Cruz Barquero <6054336+vdelacruzb@users.noreply.github.com> Date: Tue, 24 Sep 2024 10:32:15 +0200 Subject: [PATCH 13/13] release: 2024-09-23 (#529) --- CHANGELOG.md | 7 +++++++ clouds/bigquery/modules/Makefile | 2 +- .../modules/sql/quadbin/QUADBIN_POLYFILL.sql | 4 ++-- clouds/snowflake/.env.template | 1 + clouds/snowflake/CHANGELOG.md | 8 +++++++- clouds/snowflake/README.md | 1 + clouds/snowflake/common/run-query.js | 3 ++- clouds/snowflake/common/run-script.js | 3 ++- .../sql/quadbin/QUADBIN_FROMLONGLAT.sql | 1 - .../modules/sql/quadbin/QUADBIN_TOPARENT.sql | 2 +- clouds/snowflake/native_app/README.md | 20 +++++++++++++++++++ clouds/snowflake/native_app/SETUP_SCRIPT.sql | 2 +- clouds/snowflake/version | 2 +- 13 files changed, 46 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad0ccff19..8000d888a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ CARTO Analytics Toolbox Core. All notable commits to this project will be documented in this file. +## 2024-09-23 + +- feat(sf): added warehouse option for SF (#524) +- chore(bq): increse jest timeout to 30000 (#525) +- docs(sf): add docs on how to update the analytics toolbox from a native app (#527) +- chore(sf): update python version on stored procedures from 3.8 to 3.9 (#528) + ## 2024-08-22 - chore(rs): bump scipy from 0.12.0 to 0.12.1 in /clouds/redshift/libraries/python (#518) diff --git a/clouds/bigquery/modules/Makefile b/clouds/bigquery/modules/Makefile index 521fe1ce2..61892d7b8 100644 --- a/clouds/bigquery/modules/Makefile +++ b/clouds/bigquery/modules/Makefile @@ -85,7 +85,7 @@ test: check $(NODE_MODULES_DEV) if [ ! -z "$$TESTS" ]; then \ GOOGLE_APPLICATION_CREDENTIALS=$(GOOGLE_APPLICATION_CREDENTIALS) \ PATH="$(NODE_MODULES_DEV)/.bin/:$(PATH)" \ - jest --testTimeout=250000 $(BAIL) --verbose --slowTestThreshold=20 --maxConcurrency=10 $$TESTS \ + jest --testTimeout=300000 $(BAIL) --verbose --slowTestThreshold=20 --maxConcurrency=10 $$TESTS \ --setupFilesAfterEnv "$(COMMON_DIR)/test-extend.js" || exit 1; \ OLD_TEST=$(TEST_DIR)/$$m/old-test; \ if [ -d $$OLD_TEST ]; then \ diff --git a/clouds/bigquery/modules/sql/quadbin/QUADBIN_POLYFILL.sql b/clouds/bigquery/modules/sql/quadbin/QUADBIN_POLYFILL.sql index 93b69f8b9..9372273b8 100644 --- a/clouds/bigquery/modules/sql/quadbin/QUADBIN_POLYFILL.sql +++ b/clouds/bigquery/modules/sql/quadbin/QUADBIN_POLYFILL.sql @@ -76,9 +76,9 @@ RETURNS INT64 AS (( WITH __geog_area AS ( SELECT + 508164597540055.75 AS q0_area, ST_AREA(geog) AS geog_area, - COS(ST_Y(ST_CENTROID(geog)) * ACOS(-1) / 180) AS cos_geog_lat, - 508164597540055.75 AS q0_area + COS(ST_Y(ST_CENTROID(geog)) * ACOS(-1) / 180) AS cos_geog_lat ) -- compute the resolution of cells that match the geog area SELECT IF(geog_area > 0 AND cos_geog_lat > 0, diff --git a/clouds/snowflake/.env.template b/clouds/snowflake/.env.template index 0bfa4262b..967be5aa0 100644 --- a/clouds/snowflake/.env.template +++ b/clouds/snowflake/.env.template @@ -13,3 +13,4 @@ SF_USER= SF_PASSWORD= SF_ROLE= # optional SF_SHARE= # optional +SF_WAREHOUSE= # optional diff --git a/clouds/snowflake/CHANGELOG.md b/clouds/snowflake/CHANGELOG.md index 176a981d9..cd3735e94 100644 --- a/clouds/snowflake/CHANGELOG.md +++ b/clouds/snowflake/CHANGELOG.md @@ -4,9 +4,15 @@ CARTO Analytics Toolbox Core for Snowflake. All notable commits to this project will be documented in this file. +## [1.2.5] - 2024-09-23 + +- feat: added warehouse option for SF (#524) +- docs: add docs on how to update the analytics toolbox from a native app (#527) +- chore: update python version on stored procedures from 3.8 to 3.9 (#528) + ## [1.2.4] - 2024-06-27 -- chore(sf): refactor at snowflake native app to an installer (#512) +- chore: refactor at snowflake native app to an installer (#512) ## [1.2.3] - 2024-05-21 diff --git a/clouds/snowflake/README.md b/clouds/snowflake/README.md index d87854d61..2cd72ac99 100644 --- a/clouds/snowflake/README.md +++ b/clouds/snowflake/README.md @@ -24,6 +24,7 @@ SF_USER= SF_PASSWORD= SF_ROLE= # optional SF_SHARE= # optional +SF_WAREHOUSE= # optional ``` ## Structure diff --git a/clouds/snowflake/common/run-query.js b/clouds/snowflake/common/run-query.js index e5274e112..e9c0ef6eb 100755 --- a/clouds/snowflake/common/run-query.js +++ b/clouds/snowflake/common/run-query.js @@ -8,7 +8,8 @@ const connection = snowflake.createConnection({ account: process.env.SF_ACCOUNT, username: process.env.SF_USER, password: process.env.SF_PASSWORD, - role: process.env.SF_ROLE + role: process.env.SF_ROLE, + warehouse: process.env.SF_WAREHOUSE }); connection.connect((err) => { diff --git a/clouds/snowflake/common/run-script.js b/clouds/snowflake/common/run-script.js index 902808742..55d015c93 100755 --- a/clouds/snowflake/common/run-script.js +++ b/clouds/snowflake/common/run-script.js @@ -18,7 +18,8 @@ const connection = snowflake.createConnection({ account: process.env.SF_ACCOUNT, username: process.env.SF_USER, password: process.env.SF_PASSWORD, - role: process.env.SF_ROLE + role: process.env.SF_ROLE, + warehouse: process.env.SF_WAREHOUSE }); connection.connect((err) => { diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql index e56c62d90..cf4b8ce49 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_FROMLONGLAT.sql @@ -53,4 +53,3 @@ AS $$ SELECT @@SF_SCHEMA@@._QUADBIN_STRING_TOINT(@@SF_SCHEMA@@._QUADBIN_FROMZXY(z, x, y)) FROM __zxy $$; - diff --git a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql index 6e0dcf188..17bcf8990 100644 --- a/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql +++ b/clouds/snowflake/modules/sql/quadbin/QUADBIN_TOPARENT.sql @@ -47,4 +47,4 @@ AS $$ resolution * 2 ) ) -$$; \ No newline at end of file +$$; diff --git a/clouds/snowflake/native_app/README.md b/clouds/snowflake/native_app/README.md index 36764875d..2a35ba16b 100644 --- a/clouds/snowflake/native_app/README.md +++ b/clouds/snowflake/native_app/README.md @@ -47,6 +47,26 @@ GRANT USAGE ON FUTURE PROCEDURES IN SCHEMA CARTO.CARTO TO ROLE PUBLIC; CALL CARTO.CARTO.INSTALL('CARTO_ANALYTICS_TOOLBOX', 'CARTO.CARTO'); ``` +##### * Update the Analytics Toolbox + +When a new package of the Analytics Toolbox gets released, the Analytics Toolbox installer gets updated automatically. As in the first installation most of the required permissions were already set, only the next queries should be necessary in order to update the Analytics Toolbox. + +``` +-- Set admin permissions +USE ROLE ACCOUNTADMIN; + +-- Generate the installer procedure in the specified location +CALL CARTO_ANALYTICS_TOOLBOX.CARTO.GENERATE_INSTALLER('CARTO.CARTO'); + +-- Update ownership of the install procedure +GRANT OWNERSHIP ON PROCEDURE CARTO.CARTO.INSTALL(STRING, STRING) TO ROLE ACCOUNTADMIN REVOKE CURRENT GRANTS; + +-- Install the Analytics Toolbox in CARTO.CARTO +CALL CARTO.CARTO.INSTALL('CARTO_ANALYTICS_TOOLBOX', 'CARTO.CARTO'); +``` + +If your Analytics Toolbox doesn't get updated properly please try to drop the app, get it back from Snowflake Marketplace and follow the Step 1. + ### Usage Examples Please refer to CARTO's [SQL reference](https://docs.carto.com/data-and-analysis/analytics-toolbox-for-snowflake/sql-reference) to find the full list of available functions and procedures as well as examples. diff --git a/clouds/snowflake/native_app/SETUP_SCRIPT.sql b/clouds/snowflake/native_app/SETUP_SCRIPT.sql index 967e3204d..9983f186f 100644 --- a/clouds/snowflake/native_app/SETUP_SCRIPT.sql +++ b/clouds/snowflake/native_app/SETUP_SCRIPT.sql @@ -1,7 +1,7 @@ CREATE OR REPLACE PROCEDURE @@SF_APP_SCHEMA@@.GET_MODULES_SQL_FROM_STAGE() returns string language python - runtime_version = '3.8' + RUNTIME_VERSION = '3.9' packages = ('snowflake-snowpark-python') imports = ( '/get_modules_sql_from_stage.py', diff --git a/clouds/snowflake/version b/clouds/snowflake/version index e8ea05db8..c813fe116 100644 --- a/clouds/snowflake/version +++ b/clouds/snowflake/version @@ -1 +1 @@ -1.2.4 +1.2.5