diff --git a/.devcontainer/add_kitware_archive.sh b/.devcontainer/add_kitware_archive.sh deleted file mode 100755 index aff0b6c8d0f..00000000000 --- a/.devcontainer/add_kitware_archive.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/sh -# ----------------------------------------------------------------------------- -# This script is from: https://apt.kitware.com/kitware-archive.sh -# -# It installs key and repo for the kitware CMAKE-archive. -# -# Author: Bernhard Bablok -# -# ----------------------------------------------------------------------------- - -set -eu - -help() { - echo "Usage: $0 [--release ] [--rc]" > /dev/stderr -} - -doing= -rc= -release= -help= -for opt in "$@" -do - case "${doing}" in - release) - release="${opt}" - doing= - ;; - "") - case "${opt}" in - --rc) - rc=1 - ;; - --release) - doing=release - ;; - --help) - help=1 - ;; - esac - ;; - esac -done - -if [ -n "${doing}" ] -then - echo "--${doing} option given no argument." > /dev/stderr - echo > /dev/stderr - help - exit 1 -fi - -if [ -n "${help}" ] -then - help - exit -fi - -if [ -z "${release}" ] -then - unset UBUNTU_CODENAME - . /etc/os-release - - if [ -z "${UBUNTU_CODENAME+x}" ] - then - echo "This is not an Ubuntu system. Aborting." > /dev/stderr - exit 1 - fi - - release="${UBUNTU_CODENAME}" -fi - -case "${release}" in -noble|jammy|focal) - packages= - keyring_packages="ca-certificates gpg wget" - ;; -*) - echo "Only Ubuntu Noble (24.04), Jammy (22.04), and Focal (20.04) are supported. Aborting." > /dev/stderr - exit 1 - ;; -esac - -get_keyring= -if [ ! -f /usr/share/doc/kitware-archive-keyring/copyright ] -then - packages="${packages} ${keyring_packages}" - get_keyring=1 -fi - -# Start the real work -set -x - -apt-get update -# shellcheck disable=SC2086 -apt-get install -y ${packages} - -test -n "${get_keyring}" && (wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - > /usr/share/keyrings/kitware-archive-keyring.gpg) - -echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ${release} main" > /etc/apt/sources.list.d/kitware.list -if [ -n "${rc}" ] -then - echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ${release}-rc main" >> /etc/apt/sources.list.d/kitware.list -fi - -apt-get update -test -n "${get_keyring}" && rm /usr/share/keyrings/kitware-archive-keyring.gpg -apt-get install -y kitware-archive-keyring diff --git a/.devcontainer/common_tools.sh b/.devcontainer/common_tools.sh index d94977b01cc..1231b8e4f4b 100755 --- a/.devcontainer/common_tools.sh +++ b/.devcontainer/common_tools.sh @@ -9,16 +9,18 @@ # ----------------------------------------------------------------------------- REPO_ROOT="/workspaces/circuitpython" +CMAKE_VERSION="3.31.12" echo -e "[common_tools.sh] starting install" cd "$REPO_ROOT" # --- repositories and tools ------------------------------------------------ -echo -e "[common_tools.sh] adding kitware-archive (for current CMAKE)" -sudo .devcontainer/add_kitware_archive.sh -echo -e "[common_tools.sh] installing current version of CMAKE" -sudo apt-get -y install cmake +echo -e "[common_tools.sh] installing CMAKE $CMAKE_VERSION" +wget -q https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-linux-$(arch).sh +chmod +x cmake-$CMAKE_VERSION-linux-$(arch).sh +sudo ./cmake-$CMAKE_VERSION-linux-$(arch).sh --prefix=/usr/local --skip-license +rm cmake-$CMAKE_VERSION-linux-$(arch).sh echo -e "[common_tools.sh] adding pybricks/ppa" sudo add-apt-repository -y ppa:pybricks/ppa diff --git a/.gitattributes b/.gitattributes index 38bba729fc1..d226cebf5d8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -27,4 +27,5 @@ # These should also not be modified by git. tests/basics/string_cr_conversion.py -text tests/basics/string_crlf_conversion.py -text +tests/micropython/test_normalize_newlines.py.exp -text # CIRCUITPY-CHANGE: remove non-CircuitPython tests diff --git a/.github/actions/deps/external/action.yml b/.github/actions/deps/external/action.yml index 564c851cfc9..81e73f871ef 100644 --- a/.github/actions/deps/external/action.yml +++ b/.github/actions/deps/external/action.yml @@ -56,6 +56,16 @@ runs: uses: ./.github/actions/deps/python with: action: ${{ inputs.action }} + - name: Set ESP-IDF constraints path + if: inputs.port == 'espressif' + run: python3 -u tools/ci_set_idf_constraint.py + shell: bash + - name: Install python dependencies - run: pip install -r requirements-dev.txt + run: | + if [ -n "${IDF_CONSTRAINT_FILE:-}" ] && [ -f "$IDF_CONSTRAINT_FILE" ]; then + pip install -c "$IDF_CONSTRAINT_FILE" -r requirements-dev.txt + else + pip install -r requirements-dev.txt + fi shell: bash diff --git a/.github/actions/deps/ports/espressif/action.yml b/.github/actions/deps/ports/espressif/action.yml index 25965eb7ef0..321a0fb2b30 100644 --- a/.github/actions/deps/ports/espressif/action.yml +++ b/.github/actions/deps/ports/espressif/action.yml @@ -19,7 +19,7 @@ runs: shell: bash - name: Cache IDF submodules - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | .git/modules/ports/espressif/esp-idf @@ -27,7 +27,7 @@ runs: key: submodules-idf-${{ steps.idf-commit.outputs.commit }} - name: Cache IDF tools - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ${{ env.IDF_TOOLS_PATH }} key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-idf-${{ steps.idf-commit.outputs.commit }} diff --git a/.github/actions/deps/ports/zephyr-cp/action.yml b/.github/actions/deps/ports/zephyr-cp/action.yml index 5f52cc7f0c2..4475132e185 100644 --- a/.github/actions/deps/ports/zephyr-cp/action.yml +++ b/.github/actions/deps/ports/zephyr-cp/action.yml @@ -3,11 +3,18 @@ name: Fetch Zephyr port deps runs: using: composite steps: - - name: Get libusb and mtools + - name: Get Linux build dependencies if: runner.os == 'Linux' run: | + echo "--- cpu model ---" + grep "model name" /proc/cpuinfo | head -1 + sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install -y libusb-1.0-0-dev libudev-dev mtools + sudo apt-get install -y libusb-1.0-0-dev libudev-dev pkg-config mtools + # We have to hold python3 so the following install works. See https://github.com/actions/runner-images/issues/13803 + sudo apt-mark hold python3 + sudo apt-get install -y libsdl2-dev:i386 libsdl2-image-dev:i386 + echo "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" >> $GITHUB_ENV shell: bash - name: Setup Zephyr project uses: zephyrproject-rtos/action-zephyr-setup@v1 @@ -19,3 +26,6 @@ runs: run: west zephyr-export shell: bash working-directory: ports/zephyr-cp + - name: Install Zephyr protobuf dependency + run: pip install protobuf==6.33.5 + shell: bash diff --git a/.github/actions/deps/python/action.yml b/.github/actions/deps/python/action.yml index da59b87b17a..bc8b578c147 100644 --- a/.github/actions/deps/python/action.yml +++ b/.github/actions/deps/python/action.yml @@ -16,7 +16,7 @@ runs: - name: Cache python dependencies id: cache-python-deps if: inputs.action == 'cache' - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: .cp_tools key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }} @@ -24,7 +24,7 @@ runs: - name: Restore python dependencies id: restore-python-deps if: inputs.action == 'restore' - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 with: path: .cp_tools key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }} diff --git a/.github/actions/deps/submodules/action.yml b/.github/actions/deps/submodules/action.yml index eed83af41f4..5ec57b594c0 100644 --- a/.github/actions/deps/submodules/action.yml +++ b/.github/actions/deps/submodules/action.yml @@ -48,7 +48,7 @@ runs: - name: Cache submodules if: ${{ inputs.action == 'cache' }} - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}" key: submodules-common-${{ hashFiles('submodule_status') }} @@ -56,7 +56,7 @@ runs: - name: Restore submodules if: ${{ inputs.action == 'restore' }} - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 with: path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}" key: submodules-common-${{ hashFiles('submodule_status') }} diff --git a/.github/actions/mpy_cross/action.yml b/.github/actions/mpy_cross/action.yml index 8839f790915..469b8b0763e 100644 --- a/.github/actions/mpy_cross/action.yml +++ b/.github/actions/mpy_cross/action.yml @@ -16,7 +16,7 @@ runs: id: download-mpy-cross if: inputs.download == 'true' continue-on-error: true - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: mpy-cross path: mpy-cross/build @@ -36,7 +36,7 @@ runs: - name: Upload mpy-cross if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure' continue-on-error: true - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: mpy-cross path: mpy-cross/build/mpy-cross diff --git a/.github/workflows/build-board-custom.yml b/.github/workflows/build-board-custom.yml index bf18d7d7259..c17e1b13f97 100644 --- a/.github/workflows/build-board-custom.yml +++ b/.github/workflows/build-board-custom.yml @@ -70,7 +70,7 @@ jobs: run: | > custom-build && git add custom-build - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Board to port @@ -124,7 +124,7 @@ jobs: run: make -j4 $FLAGS BOARD="$BOARD" DEBUG=$DEBUG TRANSLATION="$TRANSLATION" working-directory: ports/${{ steps.board-to-port.outputs.port }} - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }} path: ports/${{ steps.board-to-port.outputs.port }}/build-${{ inputs.board }}/firmware.* diff --git a/.github/workflows/build-boards.yml b/.github/workflows/build-boards.yml index 7e5156d4011..6fbc5b6a08f 100644 --- a/.github/workflows/build-boards.yml +++ b/.github/workflows/build-boards.yml @@ -29,7 +29,7 @@ jobs: board: ${{ fromJSON(inputs.boards) }} steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x @@ -87,7 +87,7 @@ jobs: HEAD_COMMIT_MESSAGE: ${{ github.event.head_commit.message }} - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.board }} path: bin/${{ matrix.board }} diff --git a/.github/workflows/build-mpy-cross.yml b/.github/workflows/build-mpy-cross.yml index 831ad308227..9e5c1cdfc4a 100644 --- a/.github/workflows/build-mpy-cross.yml +++ b/.github/workflows/build-mpy-cross.yml @@ -28,14 +28,14 @@ jobs: OS_static-raspbian: linux-raspbian steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules @@ -66,7 +66,7 @@ jobs: echo >> $GITHUB_ENV "OS=$OS" - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: mpy-cross.${{ env.EX }} path: mpy-cross/build-${{ matrix.mpy-cross }}/mpy-cross.${{ env.EX }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5b755eb398e..bd803a5eb6b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,6 +6,9 @@ name: Build CI on: push: + branches: + - main + - '*.x' pull_request: release: types: [published] @@ -28,14 +31,14 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Duplicate USB VID/PID check @@ -114,14 +117,14 @@ jobs: CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules @@ -133,7 +136,7 @@ jobs: msgfmt --version - name: Build mpy-cross (arm64) run: make -C mpy-cross -j4 -f Makefile.m1 V=2 - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: mpy-cross-macos-arm64 path: mpy-cross/build-arm64/mpy-cross-arm64 @@ -156,14 +159,14 @@ jobs: CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules @@ -177,20 +180,20 @@ jobs: pip install -r requirements-doc.txt - name: Build and Validate Stubs run: make check-stubs -j4 - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: stubs path: circuitpython-stubs/dist/* - name: Test Documentation Build (HTML) run: sphinx-build -E -W -b html -D version="$CP_VERSION" -D release="$CP_VERSION" . _build/html - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: docs-html path: _build/html - name: Test Documentation Build (LaTeX/PDF) run: | make latexpdf - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: docs-latexpdf path: _build/latex @@ -260,7 +263,7 @@ jobs: which python; python --version; python -c "import cascadetoml" which python3; python3 --version; python3 -c "import cascadetoml" - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false @@ -295,13 +298,13 @@ jobs: CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 persist-credentials: false - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: '3.13' - name: Set up Zephyr diff --git a/.github/workflows/bundle_cron.yml b/.github/workflows/bundle_cron.yml index 606707d4102..eefffaaa5b9 100644 --- a/.github/workflows/bundle_cron.yml +++ b/.github/workflows/bundle_cron.yml @@ -29,18 +29,18 @@ jobs: if: startswith(github.repository, 'adafruit/') steps: - name: Set up Python 3.12 - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.12 - name: Load contributor cache - uses: actions/cache@v4 + uses: actions/cache@v5 with: key: "contributor-cache" path: "contributors.json" - name: Versions run: | python3 --version - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: repository: 'adafruit/adabot' submodules: true diff --git a/.github/workflows/create-website-pr.yml b/.github/workflows/create-website-pr.yml index 32c1792fa6c..559a41e67e7 100644 --- a/.github/workflows/create-website-pr.yml +++ b/.github/workflows/create-website-pr.yml @@ -17,14 +17,14 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules diff --git a/.github/workflows/learn_cron.yml b/.github/workflows/learn_cron.yml index 6100e6637c2..135089bfd5e 100644 --- a/.github/workflows/learn_cron.yml +++ b/.github/workflows/learn_cron.yml @@ -26,7 +26,7 @@ jobs: # default branches). if: ${{ (github.repository_owner == 'adafruit') }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: repository: ${{ github.repository_owner }}/Adafruit_Learning_System_Guides token: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 778270dc08c..21ae984e468 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -17,14 +17,14 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules @@ -42,7 +42,7 @@ jobs: run: git diff > ~/pre-commit.patch - name: Upload patch if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: patch path: ~/pre-commit.patch diff --git a/.github/workflows/reports_cron.yml b/.github/workflows/reports_cron.yml index b4e9a43024e..476ead95d25 100644 --- a/.github/workflows/reports_cron.yml +++ b/.github/workflows/reports_cron.yml @@ -38,13 +38,13 @@ jobs: BIGQUERY_CLIENT_EMAIL: ${{ secrets.BIGQUERY_CLIENT_EMAIL }} steps: - name: Set up Python 3.11 - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.11 - name: Versions run: | python3 --version - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: repository: 'adafruit/adabot' submodules: true diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 01172041b62..83154bbbd2b 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -24,13 +24,13 @@ jobs: TEST_native_mpy: --via-mpy --emit native -d basics float micropython steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.12 - name: Set up submodules @@ -75,13 +75,13 @@ jobs: CP_VERSION: ${{ inputs.cp-version }} steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.13 - name: Set up Zephyr @@ -95,5 +95,10 @@ jobs: uses: ./.github/actions/deps/external - name: Build native sim target run: make -C ports/zephyr-cp -j2 BOARD=native_native_sim + - name: Build bsim + run: make -j 2 everything + working-directory: ports/zephyr-cp/tools/bsim + - name: Build native_nrf5340bsim + run: make -C ports/zephyr-cp -j2 BOARD=native_nrf5340bsim - name: Run Zephyr tests run: make -C ports/zephyr-cp test diff --git a/.gitignore b/.gitignore index 3e9ee009cb3..ca6872387dd 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,10 @@ TAGS # windsurf rules .windsurfrules + +# git-review-web outputs +.review + +# Zephyr trace files +**/channel0_0 +**/*.perfetto-trace diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4db04e1d0ed..c39faf99f00 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-yaml - id: end-of-file-fixer @@ -55,7 +55,7 @@ repos: language: python - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.9.4 + rev: v0.15.7 hooks: # Run the linter. - id: ruff @@ -63,6 +63,6 @@ repos: # Run the formatter. - id: ruff-format - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.5.0" + rev: "v2.21.0" hooks: - id: pyproject-fmt diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..e7d2fdbbe8c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,4 @@ +- Capture CircuitPython output by finding the matching device in `/dev/serial/by-id` +- You can mount the CIRCUITPY drive by doing `udisksctl mount -b /dev/disk/by-label/CIRCUITPY` and access it via `/run/media//CIRCUITPY`. +- `circup` is a command line tool to install libraries and examples to CIRCUITPY. +- When connecting to serial devices on Linux use /dev/serial/by-id. These will be more stable than /dev/ttyACM*. diff --git a/LICENSE_MicroPython b/LICENSE_MicroPython index 469ae192739..1fad9b4134e 100644 --- a/LICENSE_MicroPython +++ b/LICENSE_MicroPython @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013-2024 Damien P. George +Copyright (c) 2013-2025 Damien P. George Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index c2aebc61f1c..175a1b6a302 100644 --- a/Makefile +++ b/Makefile @@ -375,5 +375,6 @@ coverage-fresh: make -j -C ports/unix VARIANT=coverage .PHONY: run-tests +# If TESTS="abc.py def.py" is specified as an arg, run only those tests. Otherwise, run all tests. run-tests: - cd tests; MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py + cd tests; MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py $(TESTS) diff --git a/README.rst b/README.rst index 80aa1b2aee2..89c7d9229d8 100644 --- a/README.rst +++ b/README.rst @@ -226,7 +226,7 @@ Ports Ports include the code unique to a microcontroller line. -The following ports are available: ``atmel-samd``, ``cxd56``, ``espressif``, ``litex``, ``mimxrt10xx``, ``nordic``, ``raspberrypi``, ``renode``, ``silabs`` (``efr32``), ``stm``, ``unix``. +The following ports are available: ``atmel-samd``, ``cxd56``, ``espressif``, ``litex``, ``mimxrt10xx``, ``nordic``, ``raspberrypi``, ``renode``, ``silabs`` (``efr32``), ``stm``, ``unix``, and ``zephyr-cp``. However, not all ports are fully functional. Some have limited functionality and known serious bugs. For details, refer to the **Port status** section in the `latest release `__ notes. diff --git a/conf.py b/conf.py index 34436c09020..e2a8cbbd82f 100644 --- a/conf.py +++ b/conf.py @@ -192,7 +192,12 @@ def autoapi_prepare_jinja_env(jinja_env): # Port READMEs in various formats "ports/*/README*", ] -exclude_patterns = ["docs/autoapi/templates/**", "docs/README.md"] +exclude_patterns = [ + "docs/autoapi/templates/**", + "docs/README.md", + "AGENTS.md", + "**/AGENTS.md", +] # The reST default role (used for this markup: `text`) to use for all # documents. diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index 03ec7a5588f..aaff47f42a6 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -259,6 +259,8 @@ static void _adapter_set_name(bleio_adapter_obj_t *self, mp_obj_str_t *name_obj) // Get various values and limits set by the adapter. // Set event mask. static void bleio_adapter_hci_init(bleio_adapter_obj_t *self) { + self->name = NULL; + mp_int_t name_len = 0; #if CIRCUITPY_SETTINGS_TOML @@ -950,7 +952,6 @@ void bleio_adapter_reset(bleio_adapter_obj_t *adapter) { } connection->connection_obj = mp_const_none; } - } void bleio_adapter_background(bleio_adapter_obj_t *adapter) { diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.c b/devices/ble_hci/common-hal/_bleio/Characteristic.c index a33b8ff4784..49b66d38e72 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.c +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -180,7 +180,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, } const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); - common_hal_bleio_check_connected(conn_handle); + bleio_check_connected(conn_handle); uint16_t cccd_value = (notify ? CCCD_NOTIFY : 0) | diff --git a/devices/ble_hci/common-hal/_bleio/Connection.h b/devices/ble_hci/common-hal/_bleio/Connection.h index 04edb104ddc..02a000501bf 100644 --- a/devices/ble_hci/common-hal/_bleio/Connection.h +++ b/devices/ble_hci/common-hal/_bleio/Connection.h @@ -61,6 +61,7 @@ typedef struct { uint8_t disconnect_reason; } bleio_connection_obj_t; +void bleio_check_connected(uint16_t conn_handle); uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection); bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle); diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c index 6376f6f10c8..f9fdbc50f64 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.c +++ b/devices/ble_hci/common-hal/_bleio/__init__.c @@ -84,7 +84,7 @@ bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void) { return &common_hal_bleio_adapter_obj; } -void common_hal_bleio_check_connected(uint16_t conn_handle) { +void bleio_check_connected(uint16_t conn_handle) { if (conn_handle == BLE_CONN_HANDLE_INVALID) { mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); } diff --git a/docs/environment.rst b/docs/environment.rst index 36404eb81f9..2c72b4f1004 100644 --- a/docs/environment.rst +++ b/docs/environment.rst @@ -1,69 +1,82 @@ Environment Variables ===================== -CircuitPython 8.0.0 introduces support for environment variables. Environment -variables are commonly used to store "secrets" such as Wi-Fi passwords and API -keys. This method *does not* make them secure. It only separates them from the -code. +CircuitPython provides support for environment variables. These values +can be examined by user code, and are also used as settings by CircuitPython during startup. -CircuitPython uses a file called ``settings.toml`` at the drive root (no -folder) as the environment. User code can access the values from the file -using `os.getenv()`. It is recommended to save any values used repeatedly in a -variable because `os.getenv()` will parse the ``settings.toml`` file contents -on every access. +CircuitPython looks for a file called ``settings.toml`` at the ``CIRCUITPY`` drive root +to find the values of environment variables, +The file format is a subset of the `TOML config file language `__. -CircuitPython only supports a subset of the full toml specification, see below -for more details. The subset is very "Python-like", which is a key reason we -selected the format. +User code can access the values from the file using either `os.getenv()` or `supervisor.get_setting()` +The value returned by `os.getenv()` is always a string, but `supervisor.get_setting()` +will parse a value into a Python object: a string, an integer, a float, or a boolean. -Due to technical limitations it probably also accepts some files that are -not valid TOML files; bugs of this nature are subject to change (i.e., be -fixed) without the usual deprecation period for incompatible changes. +Both `os.getenv()` and `supervisor.get_setting()` +read and parse the ``settings.toml`` file on every access. +It will save time to copy any values you use repeatedly into variables. -File format example: +Environment variables are sometimes used to store "secrets" such as Wi-Fi passwords and API +keys. The ``settings.toml`` file *does not* make the secrets secure. It only separates them from the +code. -.. code-block:: +CircuitPython supports only a subset of the full TOML specification; see below for more details. +The subset is very "Python-like", which is a key reason the format was selected. +To make the code simpler, the implementation accepts some files that are +not valid TOML, but do not depend on this. - str_key="Hello world" # with trailing comment - int_key = 7 - unicode_key="œuvre" - unicode_key2="\\u0153uvre" # same as above - unicode_key3="\\U00000153uvre" # same as above - escape_codes="supported, including \\r\\n\\"\\\\" - # comment - [subtable] - subvalue="cannot retrieve this using getenv" +The full TOML specification provides for tables labeled with table names in brackets, like +``[table_name]``. +CircuitPython does not support this and ignores any explicit inline TOML tables. +Here is an example ``settings.toml`` file. +Entries consist of a key and value, separated by an ``=`` sign. +Upper and lower case may both be used in the key name. -Details of the toml language subset +.. code-block:: + + # Comment. + CIRCUITPY_WIFI_PASSWORD = "mypassword" + GREETING="Hello world" # trailing comments are ok + REPEAT_COUNT = 7 # an integer + CIRCUITPY_SDCARD_USB = false # a boolean + delay = 0.75 # a float + FRENCH="œuvre" # unicode can be used + FRENCH2="\\u0153uvre" # same unicode string, using a 16-bit escape code + FRENCH3="\\U00000153uvre" # same unicode string, using a 32-bit escape code + STRING_WITH_ESCAPE_CODES="supported, including \\r\\n\\"\\\\" + +Details of the TOML language subset ----------------------------------- -* The content is required to be in UTF-8 encoding -* The supported data types are string and integer -* Only basic strings are supported, not triple-quoted strings -* Only integers supported by strtol. (no 0o, no 0b, no underscores 1_000, 011 - is 9, not 11) -* Only bare keys are supported +* The content must be in UTF-8 encoding +* The supported data types are strings, integers, floats, and booleans. +* Whitespace is allowed. +* Only basic strings are supported, not triple-quoted strings. +* Only integers supported by ``strtol()`` can be parsed: + no ``0o``, no ``0b``, no underscores ``1_000``, ``011`` is 9, not 11. +* Only bare keys are supported. * Duplicate keys are not diagnosed. -* Comments are supported -* Only values from the "root table" can be retrieved -* due to technical limitations, the content of multi-line - strings can erroneously be parsed as a value. +* Comments are allowed. +* Only values from the "root table" can be retrieved. + CircuitPython behavior ---------------------- -CircuitPython will also read the environment to configure its behavior. Some keys are read at -startup once and others are read on reload (ctrl-D in the REPL). If a reload doesn't change things, -then try a reset (a power cycle or pressing the reset button). Other keys are ignored by CircuitPython. -Here are the keys it uses: +On startup, CircuitPython looks for for certain key/value pairs to use as configuration values. +Some values are read only once, after a hard reset, and others are read on each reload (ctrl-D in the REPL). +If you edit ``settings.toml`` and a reload doesn't read your changes, +then try a hard reset (a power cycle or pressing the reset button). +You can also include any other key/value pairs in the file for use with your own code. -Core CircuitPython keys -^^^^^^^^^^^^^^^^^^^^^^^ +Keys that affect CircuitPython behavior +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CIRCUITPY_BLE_NAME ~~~~~~~~~~~~~~~~~~ -Default BLE name the board advertises as, including for the BLE workflow. +If supplied, sets the BLE name the board advertises as, including for the BLE workflow. +Otherwise, defaults to ``CIRCUITPYxxxx``, where ``xxxx`` varies per board. CIRCUITPY_HEAP_START_SIZE ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -83,24 +96,43 @@ Used to avoid "Pystack exhausted" errors when the code can't be reworked to avoi CIRCUITPY_WEB_API_PASSWORD ~~~~~~~~~~~~~~~~~~~~~~~~~~ Password required to make modifications to the board from the Web Workflow. +If the password is not specified, the Web Workflow is not enabled. CIRCUITPY_WEB_API_PORT ~~~~~~~~~~~~~~~~~~~~~~ -TCP port number used for the web HTTP API. Defaults to 80 when omitted. +TCP port number used for the Web Workflow HTTP API. Defaults to 80 when omitted. CIRCUITPY_WEB_INSTANCE_NAME ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Name the board advertises as for the WEB workflow. Defaults to human readable board name if omitted. - -CIRCUITPY_WIFI_PASSWORD -~~~~~~~~~~~~~~~~~~~~~~~ -Wi-Fi password used to auto connect to CIRCUITPY_WIFI_SSID. +Human-friendly name the board advertises over mDNS for the Web Workflow. +Defaults to the human-readable board name if omitted. +This is not the hostname. CIRCUITPY_WIFI_SSID ~~~~~~~~~~~~~~~~~~~ -Wi-Fi SSID to auto-connect to even if user code is not running. +CIRCUITPY_WIFI_PASSWORD +~~~~~~~~~~~~~~~~~~~~~~~ +If these values are supplied, connects automatically to a local WiFi network +with the specified SSID and password before ``boot.py`` and/or ``code.py`` are run. -Additional board specific keys +CIRCUITPY_WIFI_HOSTNAME +~~~~~~~~~~~~~~~~~~~~~~~ +If supplied, sets the initial ``wifi.radio.hostname`` to the given value. +Otherwise, the default value is ``cpy--``, +with some shortening for length if necessary. +If the supplied value is an invalid hostname or is too long, it is ignored. + +CIRCUITPY_SDCARD_USB +^^^^^^^^^^^^^^^^^^^^ +Present a mounted SD card as a USB MSC device. If the board has default pins for an SD card socket, +the card is mounted automatically on startup. +Only one card can be presented. +Defaults to ``true``. +SD card presentation can slow down board startup, +so set this to ``false`` if you don't need this feature. + + +Additional board-specific keys ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CIRCUITPY_DISPLAY_WIDTH (Sunton, MaTouch) @@ -181,6 +213,13 @@ Example: Configure the display to 640x480 black and white (1 bit per pixel): `Adafruit Feather RP2350 `_ `Adafruit Metro RP2350 `_ +CIRCUITPY_SAFEMODE_DELAY +~~~~~~~~~~~~~~~~~~~~~~~~ +Wait for the specified amount of time, in seconds (as a float), for the user to press the reset button +to initiate safe mode after a hard reset. +The status LED blinks during this time. +If not specified, use the default delay, which is one second. + CIRCUITPY_TERMINAL_SCALE ~~~~~~~~~~~~~~~~~~~~~~~~ Allows the entry of a display scaling factor used during the terminalio console construction. diff --git a/docs/library/collections.rst b/docs/library/collections.rst index b006a97dcaf..c3ec763d20e 100644 --- a/docs/library/collections.rst +++ b/docs/library/collections.rst @@ -109,3 +109,19 @@ Classes a 2 w 5 b 3 + + .. method:: OrderedDict.popitem() + + Remove and return a (key, value) pair from the dictionary. + Pairs are returned in LIFO order. + + .. admonition:: Difference to CPython + :class: attention + + ``OrderedDict.popitem()`` does not support the ``last=False`` argument and + will always remove and return the last item if present. + + A workaround for this is to use ``pop()`` to remove the first item:: + + first_key = next(iter(d)) + d.pop(first_key) diff --git a/docs/library/platform.rst b/docs/library/platform.rst index c091477d84c..c19ef0f5df5 100644 --- a/docs/library/platform.rst +++ b/docs/library/platform.rst @@ -36,3 +36,11 @@ Functions Returns a tuple of strings *(lib, version)*, where *lib* is the name of the libc that MicroPython is linked to, and *version* the corresponding version of this libc. + +.. function:: processor() + + Returns a string with a detailed name of the processor, if one is available. + If no name for the processor is known, it will return an empty string + instead. + + This is currently available only on RISC-V targets (both 32 and 64 bits). diff --git a/docs/library/re.rst b/docs/library/re.rst index 19b15d2d2c2..b8aeefd90cf 100644 --- a/docs/library/re.rst +++ b/docs/library/re.rst @@ -154,8 +154,8 @@ Regex objects Compiled regular expression. Instances of this class are created using `re.compile()`. -.. method:: regex.match(string) - regex.search(string) +.. method:: regex.match(string, [pos, [endpos]]) + regex.search(string, [pos, [endpos]]) regex.sub(replace, string, count=0, flags=0, /) Similar to the module-level functions :meth:`match`, :meth:`search` @@ -163,6 +163,16 @@ Compiled regular expression. Instances of this class are created using Using methods is (much) more efficient if the same regex is applied to multiple strings. + The optional second parameter *pos* gives an index in the string where the + search is to start; it defaults to ``0``. This is not completely equivalent + to slicing the string; the ``'^'`` pattern character matches at the real + beginning of the string and at positions just after a newline, but not + necessarily at the index where the search is to start. + + The optional parameter *endpos* limits how far the string will be searched; + it will be as if the string is *endpos* characters long, so only the + characters from *pos* to ``endpos - 1`` will be searched for a match. + .. method:: regex.split(string, max_split=-1, /) Split a *string* using regex. If *max_split* is given, it specifies diff --git a/docs/library/sys.rst b/docs/library/sys.rst index 8def36a2b07..c9c687df359 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -12,17 +12,9 @@ Functions .. function:: exit(retval=0, /) Terminate current program with a given exit code. Underlyingly, this - function raise as `SystemExit` exception. If an argument is given, its + function raises a `SystemExit` exception. If an argument is given, its value given as an argument to `SystemExit`. -.. function:: print_exception(exc, file=sys.stdout, /) - - This function is deprecated and will be removed starting in - CircuitPython 10.x, `traceback.print_exception()` should be used instead. - - Print exception with a traceback to a file-like object *file* (or - `sys.stdout` by default). - .. admonition:: Difference to CPython :class: attention @@ -52,6 +44,8 @@ Constants * *version* - tuple (major, minor, micro), e.g. (1, 7, 0) * *_machine* - string describing the underlying machine * *_mpy* - supported mpy file-format version (optional attribute) + * *_build* - string that can help identify the configuration that + MicroPython was built with This object is the recommended way to distinguish CircuitPython from other Python implementations (note that it still may not exist in the very @@ -116,15 +110,15 @@ Constants .. data:: stderr - Standard error ``stream``. + Standard error `stream`. .. data:: stdin - Standard input ``stream``. + Standard input `stream`. .. data:: stdout - Standard output ``stream``. + Standard output `stream`. .. data:: version diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst index 9e9330de4cc..391dc307d23 100644 --- a/docs/reference/glossary.rst +++ b/docs/reference/glossary.rst @@ -186,6 +186,13 @@ Glossary Most MicroPython boards make a REPL available over a UART, and this is typically accessible on a host PC via USB. + small integer + MicroPython optimises the internal representation of integers such that + "small" values do not take up space on the heap, and calculations with + them do not require heap allocation. On most 32-bit ports, this + corresponds to values in the interval ``-2**30 <= x < 2**30``, but this + should be considered an implementation detail and not relied upon. + stream Also known as a "file-like object". A Python object which provides sequential read-write access to the underlying data. A stream object diff --git a/docs/rstjinja.py b/docs/rstjinja.py index e7d8a312f1f..ab940dc7134 100644 --- a/docs/rstjinja.py +++ b/docs/rstjinja.py @@ -5,7 +5,7 @@ def render_with_jinja(docname, source): - if re.search("^\s*.. jinja$", source[0], re.M): + if re.search(r"^\s*.. jinja$", source[0], re.M): return True return False @@ -38,3 +38,7 @@ def rstjinja(app, docname, source): def setup(app): app.connect("source-read", rstjinja) + return { + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/docs/shared_bindings_matrix.py b/docs/shared_bindings_matrix.py index 8fbee4beea5..2f9eb796788 100644 --- a/docs/shared_bindings_matrix.py +++ b/docs/shared_bindings_matrix.py @@ -200,6 +200,8 @@ def get_settings_from_makefile(port_dir, board_name): contents = subprocess.run( [ "make", + # Don't let make run in parallel; it can mix up the output from the various "print-" targets. + "-j1", "-C", port_dir, "-f", diff --git a/extmod/extmod.mk b/extmod/extmod.mk index daa6f267342..5b2772e4e2a 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -162,7 +162,7 @@ endif ifeq ($(MICROPY_VFS_LFS2),1) CFLAGS_EXTMOD += -DMICROPY_VFS_LFS2=1 -CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT +CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT -DLFS2_DEFINES=extmod/littlefs-include/lfs2_defines.h SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\ lfs2.c \ lfs2_util.c \ @@ -461,7 +461,7 @@ ESP_HOSTED_SRC_C = $(addprefix $(ESP_HOSTED_DIR)/,\ ) ifeq ($(MICROPY_PY_BLUETOOTH),1) -ESP_HOSTED_SRC_C += $(ESP_HOSTED_DIR)/esp_hosted_bthci.c +ESP_HOSTED_SRC_C += $(ESP_HOSTED_DIR)/esp_hosted_bthci_uart.c endif # Include the protobuf-c support functions diff --git a/extmod/lwip-include/arch/cc.h b/extmod/lwip-include/arch/cc.h deleted file mode 100644 index 400dc6ec75d..00000000000 --- a/extmod/lwip-include/arch/cc.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_CC_H -#define MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_CC_H - -#include - -// Generate lwip's internal types from stdint - -typedef uint8_t u8_t; -typedef int8_t s8_t; -typedef uint16_t u16_t; -typedef int16_t s16_t; -typedef uint32_t u32_t; -typedef int32_t s32_t; - -typedef u32_t mem_ptr_t; - -#define U16_F "hu" -#define S16_F "hd" -#define X16_F "hx" -#define U32_F "u" -#define S32_F "d" -#define X32_F "x" - -#define X8_F "02x" -#define SZT_F "u" - -#define BYTE_ORDER LITTLE_ENDIAN - -#define LWIP_CHKSUM_ALGORITHM 2 - -#include -#define LWIP_PLATFORM_DIAG(x) -#define LWIP_PLATFORM_ASSERT(x) { assert(1); } - -//#define PACK_STRUCT_FIELD(x) x __attribute__((packed)) -#define PACK_STRUCT_FIELD(x) x -#define PACK_STRUCT_STRUCT __attribute__((packed)) -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_END - -#endif // MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_CC_H diff --git a/extmod/lwip-include/arch/perf.h b/extmod/lwip-include/arch/perf.h deleted file mode 100644 index d310fc339f1..00000000000 --- a/extmod/lwip-include/arch/perf.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_PERF_H -#define MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_PERF_H - -#define PERF_START /* null definition */ -#define PERF_STOP(x) /* null definition */ - -#endif // MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_PERF_H diff --git a/extmod/lwip-include/lwipopts.h b/extmod/lwip-include/lwipopts.h deleted file mode 100644 index 584decfe85f..00000000000 --- a/extmod/lwip-include/lwipopts.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_LWIPOPTS_H -#define MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_LWIPOPTS_H - -#include -#include -#include - -// We're running without an OS for this port. We don't provide any services except light protection. -#define NO_SYS 1 - -#define SYS_LIGHTWEIGHT_PROT 1 -#include -typedef uint32_t sys_prot_t; - -#define TCP_LISTEN_BACKLOG 1 - -// We'll put these into a proper ifdef once somebody implements an ethernet driver -#define LWIP_ARP 0 -#define LWIP_ETHERNET 0 - -#define LWIP_DNS 1 - -#define LWIP_NETCONN 0 -#define LWIP_SOCKET 0 - -// CIRCUITPY-CHANGE: #if instead of #ifdef -#if MICROPY_PY_LWIP_SLIP -#define LWIP_HAVE_SLIPIF 1 -#endif - -// For now, we can simply define this as a macro for the timer code. But this function isn't -// universal and other ports will need to do something else. It may be necessary to move -// things like this into a port-provided header file. -#define sys_now mp_hal_ticks_ms - -#endif // MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_LWIPOPTS_H diff --git a/extmod/lwip-include/lwipopts_common.h b/extmod/lwip-include/lwipopts_common.h deleted file mode 100644 index 3e423090949..00000000000 --- a/extmod/lwip-include/lwipopts_common.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2025 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_LWIPOPTS_COMMON_H -#define MICROPY_INCLUDED_LWIPOPTS_COMMON_H - -#include "py/mpconfig.h" - -// This sys-arch protection is not needed. -// Ports either protect lwIP code with flags, or run it at PendSV priority. -#define SYS_ARCH_DECL_PROTECT(lev) do { } while (0) -#define SYS_ARCH_PROTECT(lev) do { } while (0) -#define SYS_ARCH_UNPROTECT(lev) do { } while (0) - -#define NO_SYS 1 -#define SYS_LIGHTWEIGHT_PROT 1 -#define MEM_ALIGNMENT 4 - -#define LWIP_CHKSUM_ALGORITHM 3 -#define LWIP_CHECKSUM_CTRL_PER_NETIF 1 - -#define LWIP_ARP 1 -#define LWIP_ETHERNET 1 -#define LWIP_RAW 1 -#define LWIP_NETCONN 0 -#define LWIP_SOCKET 0 -#define LWIP_STATS 0 -#define LWIP_NETIF_HOSTNAME 1 - -#define LWIP_DHCP 1 -#define LWIP_DHCP_CHECK_LINK_UP 1 -#define LWIP_DHCP_DOES_ACD_CHECK 0 // to speed DHCP up -#define LWIP_DNS 1 -#define LWIP_DNS_SUPPORT_MDNS_QUERIES 1 -#define LWIP_MDNS_RESPONDER 1 -#define LWIP_IGMP 1 - -#if MICROPY_PY_LWIP_PPP -#define PPP_SUPPORT 1 -#define PAP_SUPPORT 1 -#define CHAP_SUPPORT 1 -#endif - -#define LWIP_NUM_NETIF_CLIENT_DATA LWIP_MDNS_RESPONDER -#define MEMP_NUM_UDP_PCB (4 + LWIP_MDNS_RESPONDER) - -// The mDNS responder requires 5 timers per IP version plus 2 others. Not having enough silently breaks it. -#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL + (LWIP_MDNS_RESPONDER * (2 + (5 * (LWIP_IPV4 + LWIP_IPV6))))) - -#define SO_REUSE 1 -#define TCP_LISTEN_BACKLOG 1 - -// TCP memory settings. -// Default lwIP settings takes 15800 bytes; TCP d/l: 380k/s local, 7.2k/s remote; TCP u/l is very slow. -#ifndef MEM_SIZE - -#if 0 -// lwIP takes 19159 bytes; TCP d/l and u/l are around 320k/s on local network. -#define MEM_SIZE (5000) -#define TCP_WND (4 * TCP_MSS) -#define TCP_SND_BUF (4 * TCP_MSS) -#endif - -#if 1 -// lwIP takes 26700 bytes; TCP dl/ul are around 750/600 k/s on local network. -#define MEM_SIZE (8000) -#define TCP_MSS (800) -#define TCP_WND (8 * TCP_MSS) -#define TCP_SND_BUF (8 * TCP_MSS) -#define MEMP_NUM_TCP_SEG (32) -#endif - -#if 0 -// lwIP takes 45600 bytes; TCP dl/ul are around 1200/1000 k/s on local network. -#define MEM_SIZE (16000) -#define TCP_MSS (1460) -#define TCP_WND (8 * TCP_MSS) -#define TCP_SND_BUF (8 * TCP_MSS) -#define MEMP_NUM_TCP_SEG (32) -#endif - -#endif // MEM_SIZE - -// Needed for PPP. -#define sys_jiffies sys_now - -typedef uint32_t sys_prot_t; - -#endif // MICROPY_INCLUDED_LWIPOPTS_COMMON_H diff --git a/extmod/modjson.c b/extmod/modjson.c index 67da36f0ccf..77f4a336aa8 100644 --- a/extmod/modjson.c +++ b/extmod/modjson.c @@ -227,7 +227,8 @@ static mp_obj_t _mod_json_load(mp_obj_t stream_obj, bool return_first_json) { for (;;) { cont: if (S_END(s)) { - break; + // Input finished abruptly in the middle of a composite entity. + goto fail; } mp_obj_t next = MP_OBJ_NULL; bool enter = false; diff --git a/extmod/modplatform.c b/extmod/modplatform.c index c6d4d31b97e..e1f5476c3b3 100644 --- a/extmod/modplatform.c +++ b/extmod/modplatform.c @@ -61,11 +61,49 @@ static mp_obj_t platform_libc_ver(size_t n_args, const mp_obj_t *pos_args, mp_ma } static MP_DEFINE_CONST_FUN_OBJ_KW(platform_libc_ver_obj, 0, platform_libc_ver); +#ifdef __riscv +static mp_obj_t platform_processor(void) { + #if (__riscv_xlen <= 64) && !defined(__linux__) + uintptr_t misa_csr = 0; + + // Load the MISA CSR directly. + __asm volatile ( + "csrr %0, misa \n" + : "+r" (misa_csr) + : + : + ); + + char processor_buffer[31] = { // "RV32"/"RV64" + up to 26 chars. + #if (__riscv_xlen < 64) + "RV32" + #else + "RV64" + #endif + }; + mp_uint_t offset = 4; + for (mp_uint_t bit = 0; bit < 26; bit++) { + if (misa_csr & (1U << bit)) { + processor_buffer[offset++] = 'A' + bit; + } + } + + return mp_obj_new_str(processor_buffer, offset); + #else + return MP_OBJ_NEW_QSTR(MP_QSTR_); + #endif +} +static MP_DEFINE_CONST_FUN_OBJ_0(platform_processor_obj, platform_processor); +#endif + static const mp_rom_map_elem_t modplatform_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_platform) }, { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_platform_obj) }, { MP_ROM_QSTR(MP_QSTR_python_compiler), MP_ROM_PTR(&platform_python_compiler_obj) }, { MP_ROM_QSTR(MP_QSTR_libc_ver), MP_ROM_PTR(&platform_libc_ver_obj) }, + #ifdef __riscv + { MP_ROM_QSTR(MP_QSTR_processor), MP_ROM_PTR(&platform_processor_obj) }, + #endif }; static MP_DEFINE_CONST_DICT(modplatform_globals, modplatform_globals_table); diff --git a/extmod/modre.c b/extmod/modre.c index ba2927eb4a8..36fff1d1dc6 100644 --- a/extmod/modre.c +++ b/extmod/modre.c @@ -196,10 +196,11 @@ static void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t // Note: this function can't be named re_exec because it may clash with system headers, eg on FreeBSD static mp_obj_t re_exec_helper(bool is_anchored, uint n_args, const mp_obj_t *args) { - (void)n_args; mp_obj_re_t *self; + bool was_compiled = false; if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { self = MP_OBJ_TO_PTR(args[0]); + was_compiled = true; } else { self = MP_OBJ_TO_PTR(mod_re_compile(1, args)); } @@ -207,37 +208,28 @@ static mp_obj_t re_exec_helper(bool is_anchored, uint n_args, const mp_obj_t *ar size_t len; subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; - // CIRCUITPY-CHANGE - #if MICROPY_PY_RE_MATCH_SPAN_START_END && !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME) - - if (n_args > 2) { - const mp_obj_type_t *self_type = mp_obj_get_type(args[1]); - mp_int_t str_len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len(args[1])); - const byte *begin = (const byte *)subj.begin; - int pos = mp_obj_get_int(args[2]); - if (pos >= str_len) { - return mp_const_none; - } - if (pos < 0) { - pos = 0; + if (was_compiled && n_args > 2) { + // Arg #2 is starting-pos + mp_int_t startpos = mp_obj_get_int(args[2]); + if (startpos > (mp_int_t)len) { + startpos = len; + } else if (startpos < 0) { + startpos = 0; } - const byte *pos_ptr = str_index_to_ptr(self_type, begin, len, MP_OBJ_NEW_SMALL_INT(pos), true); - - const byte *endpos_ptr = (const byte *)subj.end; + subj.begin += startpos; if (n_args > 3) { - int endpos = mp_obj_get_int(args[3]); - if (endpos <= pos) { - return mp_const_none; + // Arg #3 is ending-pos + mp_int_t endpos = mp_obj_get_int(args[3]); + if (endpos > (mp_int_t)len) { + endpos = len; + } else if (endpos < startpos) { + endpos = startpos; } - // Will cap to length - endpos_ptr = str_index_to_ptr(self_type, begin, len, args[3], true); + subj.end = subj.begin_line + endpos; } - - subj.begin = (const char *)pos_ptr; - subj.end = (const char *)endpos_ptr; } - #endif + int caps_num = (self->re.sub + 1) * 2; mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, caps, char *, caps_num); // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char @@ -458,6 +450,9 @@ static mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { const char *re_str = mp_obj_str_get_str(args[0]); int size = re1_5_sizecode(re_str); if (size == -1) { + #if MICROPY_ERROR_REPORTING >= MICROPY_ERROR_REPORTING_NORMAL + mp_raise_ValueError(MP_ERROR_TEXT("regex too complex")); + #endif goto error; } mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, re.insts, char, size, (mp_obj_type_t *)&re_type); @@ -470,6 +465,7 @@ static mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { int error = re1_5_compilecode(&o->re, re_str); if (error != 0) { error: + // CIRCUITPY-CHANGE: capitalized mp_raise_ValueError(MP_ERROR_TEXT("Error in regex")); } #if MICROPY_PY_RE_DEBUG diff --git a/extmod/modtime.c b/extmod/modtime.c index deb4bb4c9ac..ee898828a4a 100644 --- a/extmod/modtime.c +++ b/extmod/modtime.c @@ -53,26 +53,26 @@ // - weekday is 0-6 for Mon-Sun // - yearday is 1-366 static mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { + timeutils_struct_time_t tm; if (n_args == 0 || args[0] == mp_const_none) { // Get current date and time. - return mp_time_localtime_get(); + mp_time_localtime_get(&tm); } else { // Convert given seconds to tuple. - mp_int_t seconds = mp_obj_get_int(args[0]); - timeutils_struct_time_t tm; + mp_timestamp_t seconds = timeutils_obj_get_timestamp(args[0]); timeutils_seconds_since_epoch_to_struct_time(seconds, &tm); - mp_obj_t tuple[8] = { - tuple[0] = mp_obj_new_int(tm.tm_year), - tuple[1] = mp_obj_new_int(tm.tm_mon), - tuple[2] = mp_obj_new_int(tm.tm_mday), - tuple[3] = mp_obj_new_int(tm.tm_hour), - tuple[4] = mp_obj_new_int(tm.tm_min), - tuple[5] = mp_obj_new_int(tm.tm_sec), - tuple[6] = mp_obj_new_int(tm.tm_wday), - tuple[7] = mp_obj_new_int(tm.tm_yday), - }; - return mp_obj_new_tuple(8, tuple); } + mp_obj_t tuple[8] = { + mp_obj_new_int(tm.tm_year), + mp_obj_new_int(tm.tm_mon), + mp_obj_new_int(tm.tm_mday), + mp_obj_new_int(tm.tm_hour), + mp_obj_new_int(tm.tm_min), + mp_obj_new_int(tm.tm_sec), + mp_obj_new_int(tm.tm_wday), + mp_obj_new_int(tm.tm_yday), + }; + return mp_obj_new_tuple(8, tuple); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_time_localtime_obj, 0, 1, time_localtime); @@ -90,7 +90,7 @@ static mp_obj_t time_mktime(mp_obj_t tuple) { mp_raise_TypeError(MP_ERROR_TEXT("mktime needs a tuple of length 8 or 9")); } - return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), + return timeutils_obj_from_timestamp(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]))); } diff --git a/extmod/vfs.c b/extmod/vfs.c index 0cf93c3966c..c4156990bcc 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -101,7 +101,7 @@ mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out) { return MP_STATE_VM(vfs_cur); } -// Version of mp_vfs_lookup_path that takes and returns uPy string objects. +// Version of mp_vfs_lookup_path that takes and returns MicroPython string objects. static mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) { const char *path = mp_obj_str_get_str(path_in); const char *p_out; diff --git a/extmod/vfs_blockdev.c b/extmod/vfs_blockdev.c index 0cd3cc6f0c6..74d1262364e 100644 --- a/extmod/vfs_blockdev.c +++ b/extmod/vfs_blockdev.c @@ -108,7 +108,7 @@ static int mp_vfs_blockdev_call_rw(mp_obj_t *args, size_t block_num, size_t bloc // and negative integer on errors. Check for positive integer // results as some callers (i.e. littlefs) will produce corrupt // results from these. - int i = MP_OBJ_SMALL_INT_VALUE(ret); + int i = mp_obj_get_int(ret); return i > 0 ? (-MP_EINVAL) : i; } } diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 6267452cd32..95ed79eb18b 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -58,7 +58,7 @@ // CIRCUITPY-CHANGE // Factoring this common call saves about 90 bytes. -static NORETURN void mp_raise_OSError_fresult(FRESULT res) { +static MP_NORETURN void mp_raise_OSError_fresult(FRESULT res) { mp_raise_OSError(fresult_to_errno_table[res]); } diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index 4b10ca3aa59..bbdd21cfb91 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -104,6 +104,12 @@ static void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx * self, mp_obj_t bdev, size config->read_buffer = m_new(uint8_t, config->cache_size); config->prog_buffer = m_new(uint8_t, config->cache_size); config->lookahead_buffer = m_new(uint8_t, config->lookahead_size); + #ifdef LFS2_MULTIVERSION + // This can be set to override the on-disk lfs version. + // eg. for compat with lfs2 < v2.6 add the following to make: + // CFLAGS += '-DLFS2_MULTIVERSION=0x00020000' + config->disk_version = LFS2_MULTIVERSION; + #endif #endif } @@ -300,7 +306,7 @@ static mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) { struct LFSx_API (info) info; int ret = LFSx_API(stat)(&self->lfs, path, &info); if (ret < 0 || info.type != LFSx_MACRO(_TYPE_DIR)) { - mp_raise_OSError(-MP_ENOENT); + mp_raise_OSError(MP_ENOENT); } } @@ -378,7 +384,7 @@ static mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) { mp_raise_OSError(-ret); } - mp_uint_t mtime = 0; + mp_timestamp_t mtime = 0; #if LFS_BUILD_VERSION == 2 uint8_t mtime_buf[8]; lfs2_ssize_t sz = lfs2_getattr(&self->lfs, path, LFS_ATTR_MTIME, &mtime_buf, sizeof(mtime_buf)); @@ -400,9 +406,9 @@ static mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) { t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid t->items[6] = mp_obj_new_int_from_uint(info.size); // st_size - t->items[7] = mp_obj_new_int_from_uint(mtime); // st_atime - t->items[8] = mp_obj_new_int_from_uint(mtime); // st_mtime - t->items[9] = mp_obj_new_int_from_uint(mtime); // st_ctime + t->items[7] = timeutils_obj_from_timestamp(mtime); // st_atime + t->items[8] = timeutils_obj_from_timestamp(mtime); // st_mtime + t->items[9] = timeutils_obj_from_timestamp(mtime); // st_ctime return MP_OBJ_FROM_PTR(t); } diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c index ab5cce50088..56daa53e068 100644 --- a/extmod/vfs_lfsx_file.c +++ b/extmod/vfs_lfsx_file.c @@ -90,9 +90,9 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod } #if LFS_BUILD_VERSION == 1 - MP_OBJ_VFS_LFSx_FILE *o = mp_obj_malloc_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->prog_size, type); + MP_OBJ_VFS_LFSx_FILE *o = mp_obj_malloc_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->prog_size, type); #else - MP_OBJ_VFS_LFSx_FILE *o = mp_obj_malloc_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->cache_size, type); + MP_OBJ_VFS_LFSx_FILE *o = mp_obj_malloc_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->cache_size, type); #endif o->vfs = self; #if !MICROPY_GC_CONSERVATIVE_CLEAR diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index bd9a6d84062..27f833e802f 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -137,7 +137,7 @@ static mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, siz vstr_add_char(&vfs->root, '/'); } vfs->root_len = vfs->root.len; - vfs->readonly = false; + vfs->readonly = !MICROPY_VFS_POSIX_WRITABLE; return MP_OBJ_FROM_PTR(vfs); } @@ -160,10 +160,21 @@ static mp_obj_t vfs_posix_umount(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_umount_obj, vfs_posix_umount); +static inline bool vfs_posix_is_readonly(mp_obj_vfs_posix_t *self) { + return !MICROPY_VFS_POSIX_WRITABLE || self->readonly; +} + +static void vfs_posix_require_writable(mp_obj_t self_in) { + mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); + if (vfs_posix_is_readonly(self)) { + mp_raise_OSError(MP_EROFS); + } +} + static mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); const char *mode = mp_obj_str_get_str(mode_in); - if (self->readonly + if (vfs_posix_is_readonly(self) && (strchr(mode, 'w') != NULL || strchr(mode, 'a') != NULL || strchr(mode, '+') != NULL)) { mp_raise_OSError(MP_EROFS); } @@ -303,6 +314,7 @@ typedef struct _mp_obj_listdir_t { } mp_obj_listdir_t; static mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) { + vfs_posix_require_writable(self_in); mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); const char *path = vfs_posix_get_path_str(self, path_in); MP_THREAD_GIL_EXIT(); @@ -320,11 +332,13 @@ static mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) { static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_mkdir_obj, vfs_posix_mkdir); static mp_obj_t vfs_posix_remove(mp_obj_t self_in, mp_obj_t path_in) { + vfs_posix_require_writable(self_in); return vfs_posix_fun1_helper(self_in, path_in, unlink); } static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_remove_obj, vfs_posix_remove); static mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_t new_path_in) { + vfs_posix_require_writable(self_in); mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); const char *old_path = vfs_posix_get_path_str(self, old_path_in); const char *new_path = vfs_posix_get_path_str(self, new_path_in); @@ -339,6 +353,7 @@ static mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_ static MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_rename_obj, vfs_posix_rename); static mp_obj_t vfs_posix_rmdir(mp_obj_t self_in, mp_obj_t path_in) { + vfs_posix_require_writable(self_in); return vfs_posix_fun1_helper(self_in, path_in, rmdir); } static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_rmdir_obj, vfs_posix_rmdir); diff --git a/extmod/vfs_reader.c b/extmod/vfs_reader.c index de5c4e03d3c..6c36770295b 100644 --- a/extmod/vfs_reader.c +++ b/extmod/vfs_reader.c @@ -83,7 +83,7 @@ void mp_reader_new_file(mp_reader_t *reader, qstr filename) { }; mp_obj_t file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map); - const mp_stream_p_t *stream_p = mp_get_stream(file); + const mp_stream_p_t *stream_p = mp_get_stream_raise(file, MP_STREAM_OP_READ); int errcode = 0; #if MICROPY_VFS_ROM diff --git a/frozen/Adafruit_CircuitPython_AHTx0 b/frozen/Adafruit_CircuitPython_AHTx0 index 8c61ed111fc..3dd249f5695 160000 --- a/frozen/Adafruit_CircuitPython_AHTx0 +++ b/frozen/Adafruit_CircuitPython_AHTx0 @@ -1 +1 @@ -Subproject commit 8c61ed111fc83e4e1703cf5e014e645f4dbbef32 +Subproject commit 3dd249f56957d1927dee6e6e31742039c6699cef diff --git a/frozen/Adafruit_CircuitPython_APDS9960 b/frozen/Adafruit_CircuitPython_APDS9960 index f05a7239131..75a7b1abef0 160000 --- a/frozen/Adafruit_CircuitPython_APDS9960 +++ b/frozen/Adafruit_CircuitPython_APDS9960 @@ -1 +1 @@ -Subproject commit f05a7239131dc05df949e49c1bb5732529a864bf +Subproject commit 75a7b1abef02342a7cdead30271ce168243bf1fa diff --git a/frozen/Adafruit_CircuitPython_BLE b/frozen/Adafruit_CircuitPython_BLE index 0058a10ba53..82ada04a0f4 160000 --- a/frozen/Adafruit_CircuitPython_BLE +++ b/frozen/Adafruit_CircuitPython_BLE @@ -1 +1 @@ -Subproject commit 0058a10ba53e2d7bd6bcc84c7bf10dd30ee998dd +Subproject commit 82ada04a0f4019de00d103256621f73b80151a0d diff --git a/frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center b/frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center index e162713efa5..7c081325944 160000 --- a/frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center +++ b/frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center @@ -1 +1 @@ -Subproject commit e162713efa578b9967f7ec921b129362036571b3 +Subproject commit 7c08132594453a021812f45e86a2972d6945672e diff --git a/frozen/Adafruit_CircuitPython_Bitmap_Font b/frozen/Adafruit_CircuitPython_Bitmap_Font index cb6a08e2ca5..fe0cdfd5501 160000 --- a/frozen/Adafruit_CircuitPython_Bitmap_Font +++ b/frozen/Adafruit_CircuitPython_Bitmap_Font @@ -1 +1 @@ -Subproject commit cb6a08e2ca57df75b512b844cce78558088979fe +Subproject commit fe0cdfd5501070f5ca47b3e66dfd15e62c54011e diff --git a/frozen/Adafruit_CircuitPython_BusDevice b/frozen/Adafruit_CircuitPython_BusDevice index 69ebda79d40..686728c7b11 160000 --- a/frozen/Adafruit_CircuitPython_BusDevice +++ b/frozen/Adafruit_CircuitPython_BusDevice @@ -1 +1 @@ -Subproject commit 69ebda79d40d0e74c01e4f1aa293f219b8c7e086 +Subproject commit 686728c7b11eb0b7ffb62691b68ccead413e7cc5 diff --git a/frozen/Adafruit_CircuitPython_CircuitPlayground b/frozen/Adafruit_CircuitPython_CircuitPlayground index 65be0763bed..852e7206e5e 160000 --- a/frozen/Adafruit_CircuitPython_CircuitPlayground +++ b/frozen/Adafruit_CircuitPython_CircuitPlayground @@ -1 +1 @@ -Subproject commit 65be0763beda780d3a1a8c4c49b033628bc54d28 +Subproject commit 852e7206e5ed26ec3929a25bc8331b0951fee20e diff --git a/frozen/Adafruit_CircuitPython_ConnectionManager b/frozen/Adafruit_CircuitPython_ConnectionManager index 2c85f3b98d0..69542345f3d 160000 --- a/frozen/Adafruit_CircuitPython_ConnectionManager +++ b/frozen/Adafruit_CircuitPython_ConnectionManager @@ -1 +1 @@ -Subproject commit 2c85f3b98d08102d2494195074ad836fc3020610 +Subproject commit 69542345f3dc6f9060eb5d78d5dcd4e636bf66b9 diff --git a/frozen/Adafruit_CircuitPython_Crickit b/frozen/Adafruit_CircuitPython_Crickit index 722f7937bfb..aa213ba6f89 160000 --- a/frozen/Adafruit_CircuitPython_Crickit +++ b/frozen/Adafruit_CircuitPython_Crickit @@ -1 +1 @@ -Subproject commit 722f7937bfb0c02340dcf737ebf37cc4ecf86b83 +Subproject commit aa213ba6f897cdeb45ce4e961f44f862e3832c03 diff --git a/frozen/Adafruit_CircuitPython_DRV2605 b/frozen/Adafruit_CircuitPython_DRV2605 index 616d61c7495..2b8443ff94a 160000 --- a/frozen/Adafruit_CircuitPython_DRV2605 +++ b/frozen/Adafruit_CircuitPython_DRV2605 @@ -1 +1 @@ -Subproject commit 616d61c7495e5dadc6b77ea9fce07a3861580534 +Subproject commit 2b8443ff94a179a027efd9f62d905c398f4f7b43 diff --git a/frozen/Adafruit_CircuitPython_DS3231 b/frozen/Adafruit_CircuitPython_DS3231 index 62cc4dc49b5..5dc331cd999 160000 --- a/frozen/Adafruit_CircuitPython_DS3231 +++ b/frozen/Adafruit_CircuitPython_DS3231 @@ -1 +1 @@ -Subproject commit 62cc4dc49b587fad935368ed60b9ba1433250fdc +Subproject commit 5dc331cd99930dd209c63f77256764c2b41016f2 diff --git a/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 b/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 index 89463c9bd81..45520b642df 160000 --- a/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 +++ b/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 @@ -1 +1 @@ -Subproject commit 89463c9bd81aaf43a14fd4f3c7bdbb75d4e48b40 +Subproject commit 45520b642df77b1718befb24e5e6853b1172792f diff --git a/frozen/Adafruit_CircuitPython_Display_Shapes b/frozen/Adafruit_CircuitPython_Display_Shapes index e8867231041..7f0466c1d3a 160000 --- a/frozen/Adafruit_CircuitPython_Display_Shapes +++ b/frozen/Adafruit_CircuitPython_Display_Shapes @@ -1 +1 @@ -Subproject commit e8867231041837735ef2769a6dc793887d1979ca +Subproject commit 7f0466c1d3ac344bb8ef282d09c5eb8c1a521d72 diff --git a/frozen/Adafruit_CircuitPython_Display_Text b/frozen/Adafruit_CircuitPython_Display_Text index 372cbe27459..eae352b0970 160000 --- a/frozen/Adafruit_CircuitPython_Display_Text +++ b/frozen/Adafruit_CircuitPython_Display_Text @@ -1 +1 @@ -Subproject commit 372cbe27459c02db838fb65489cf8b4b5dba12f3 +Subproject commit eae352b09700e57b78507aace7ff682cb1beff5a diff --git a/frozen/Adafruit_CircuitPython_DotStar b/frozen/Adafruit_CircuitPython_DotStar index 8d19e1b23cb..d08e231d5f9 160000 --- a/frozen/Adafruit_CircuitPython_DotStar +++ b/frozen/Adafruit_CircuitPython_DotStar @@ -1 +1 @@ -Subproject commit 8d19e1b23cbe6c1d17a29f321d06b16d21909b92 +Subproject commit d08e231d5f95566a09f2a0c08cb647703882262d diff --git a/frozen/Adafruit_CircuitPython_ESP32SPI b/frozen/Adafruit_CircuitPython_ESP32SPI index 0b24c52f472..b0e2124a175 160000 --- a/frozen/Adafruit_CircuitPython_ESP32SPI +++ b/frozen/Adafruit_CircuitPython_ESP32SPI @@ -1 +1 @@ -Subproject commit 0b24c52f472f870fcd417301521a6f7895416a4e +Subproject commit b0e2124a175f421bb07ac5cc72b81f6209966a3b diff --git a/frozen/Adafruit_CircuitPython_FakeRequests b/frozen/Adafruit_CircuitPython_FakeRequests index ff942eaae83..130a3d7fcfb 160000 --- a/frozen/Adafruit_CircuitPython_FakeRequests +++ b/frozen/Adafruit_CircuitPython_FakeRequests @@ -1 +1 @@ -Subproject commit ff942eaae835144f7269d8206adf506c99f699f4 +Subproject commit 130a3d7fcfbba67bb86232f22ca08ba862873947 diff --git a/frozen/Adafruit_CircuitPython_FocalTouch b/frozen/Adafruit_CircuitPython_FocalTouch index f20c13bdffa..2070d7853cd 160000 --- a/frozen/Adafruit_CircuitPython_FocalTouch +++ b/frozen/Adafruit_CircuitPython_FocalTouch @@ -1 +1 @@ -Subproject commit f20c13bdffa9b586c648f331851f427368a995ae +Subproject commit 2070d7853cd1fe81381e02f4bc0af1bb145cb69e diff --git a/frozen/Adafruit_CircuitPython_HID b/frozen/Adafruit_CircuitPython_HID index 788e46ca2cb..693baa60eb6 160000 --- a/frozen/Adafruit_CircuitPython_HID +++ b/frozen/Adafruit_CircuitPython_HID @@ -1 +1 @@ -Subproject commit 788e46ca2cb2febddac83e0c660972598d6a8a27 +Subproject commit 693baa60eb684bb53379d98c6a036f56b8010666 diff --git a/frozen/Adafruit_CircuitPython_HTTPServer b/frozen/Adafruit_CircuitPython_HTTPServer index e234a494050..c1d964fe7bf 160000 --- a/frozen/Adafruit_CircuitPython_HTTPServer +++ b/frozen/Adafruit_CircuitPython_HTTPServer @@ -1 +1 @@ -Subproject commit e234a4940504b4fb21c7338d774ec273260ef672 +Subproject commit c1d964fe7bf8734f7a858e798583d0f1304ae1c1 diff --git a/frozen/Adafruit_CircuitPython_IRRemote b/frozen/Adafruit_CircuitPython_IRRemote index 98bd8fad8cd..bb14c81e07a 160000 --- a/frozen/Adafruit_CircuitPython_IRRemote +++ b/frozen/Adafruit_CircuitPython_IRRemote @@ -1 +1 @@ -Subproject commit 98bd8fad8cd65f481b8808e5de8cdbf62d0dd300 +Subproject commit bb14c81e07aa798b36a53923059b5ab8a914915b diff --git a/frozen/Adafruit_CircuitPython_IS31FL3731 b/frozen/Adafruit_CircuitPython_IS31FL3731 index 1babff02ea8..3becc08e451 160000 --- a/frozen/Adafruit_CircuitPython_IS31FL3731 +++ b/frozen/Adafruit_CircuitPython_IS31FL3731 @@ -1 +1 @@ -Subproject commit 1babff02ea87f5c4863aed20be0da553d76e9600 +Subproject commit 3becc08e451eeb2b6678a3d17547f5b0922e4660 diff --git a/frozen/Adafruit_CircuitPython_ImageLoad b/frozen/Adafruit_CircuitPython_ImageLoad index 67532099f7a..3bc5c15c707 160000 --- a/frozen/Adafruit_CircuitPython_ImageLoad +++ b/frozen/Adafruit_CircuitPython_ImageLoad @@ -1 +1 @@ -Subproject commit 67532099f7a574f08955b31efb7c1ca5cc3f143c +Subproject commit 3bc5c15c7079e076b49f9929bb956de8812c62f8 diff --git a/frozen/Adafruit_CircuitPython_LC709203F b/frozen/Adafruit_CircuitPython_LC709203F index 7fe15ca666b..bcbb0cfead8 160000 --- a/frozen/Adafruit_CircuitPython_LC709203F +++ b/frozen/Adafruit_CircuitPython_LC709203F @@ -1 +1 @@ -Subproject commit 7fe15ca666bd3730a17e13bb29ff884092345b5f +Subproject commit bcbb0cfead8650a61357a167bc47058f05fba159 diff --git a/frozen/Adafruit_CircuitPython_LED_Animation b/frozen/Adafruit_CircuitPython_LED_Animation index 515553f0b6c..38a3c7844b4 160000 --- a/frozen/Adafruit_CircuitPython_LED_Animation +++ b/frozen/Adafruit_CircuitPython_LED_Animation @@ -1 +1 @@ -Subproject commit 515553f0b6cb1290b92965f8e4e8beab9e83bcf1 +Subproject commit 38a3c7844b4c59235fac46ee01e20caf872dad43 diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH index 83333f8f6a5..cd40b482a09 160000 --- a/frozen/Adafruit_CircuitPython_LIS3DH +++ b/frozen/Adafruit_CircuitPython_LIS3DH @@ -1 +1 @@ -Subproject commit 83333f8f6a5501f9cbee215ebc791cd2fb67bd7d +Subproject commit cd40b482a098a62ecce1b4c62a1f1930be984e16 diff --git a/frozen/Adafruit_CircuitPython_LSM6DS b/frozen/Adafruit_CircuitPython_LSM6DS index 36247d1d9d7..cdfc14a687a 160000 --- a/frozen/Adafruit_CircuitPython_LSM6DS +++ b/frozen/Adafruit_CircuitPython_LSM6DS @@ -1 +1 @@ -Subproject commit 36247d1d9d769a23f40ca2c4371a5cd64e2a7204 +Subproject commit cdfc14a687a138aa0f2c6abab061bfc1bfafa561 diff --git a/frozen/Adafruit_CircuitPython_MIDI b/frozen/Adafruit_CircuitPython_MIDI index 2bc55548577..6f5d6812474 160000 --- a/frozen/Adafruit_CircuitPython_MIDI +++ b/frozen/Adafruit_CircuitPython_MIDI @@ -1 +1 @@ -Subproject commit 2bc555485772743b70f620fe939048020924a605 +Subproject commit 6f5d6812474a0460e9418278ea7da1e2269d2c0d diff --git a/frozen/Adafruit_CircuitPython_MPU6050 b/frozen/Adafruit_CircuitPython_MPU6050 index bb5100733f3..928d747a826 160000 --- a/frozen/Adafruit_CircuitPython_MPU6050 +++ b/frozen/Adafruit_CircuitPython_MPU6050 @@ -1 +1 @@ -Subproject commit bb5100733f339dcad24df7d32eeeb492023b5059 +Subproject commit 928d747a826fc8d8c4237ed1b40b53cf723cf1ee diff --git a/frozen/Adafruit_CircuitPython_Motor b/frozen/Adafruit_CircuitPython_Motor index 610c42f1187..20ebf51fe0d 160000 --- a/frozen/Adafruit_CircuitPython_Motor +++ b/frozen/Adafruit_CircuitPython_Motor @@ -1 +1 @@ -Subproject commit 610c42f1187045fb962807ac8d895e66e2612298 +Subproject commit 20ebf51fe0d2bb48b1780c3c9bd74c16c73bc02e diff --git a/frozen/Adafruit_CircuitPython_NeoPixel b/frozen/Adafruit_CircuitPython_NeoPixel index 5b8fe0e7064..aa82c0724cc 160000 --- a/frozen/Adafruit_CircuitPython_NeoPixel +++ b/frozen/Adafruit_CircuitPython_NeoPixel @@ -1 +1 @@ -Subproject commit 5b8fe0e70646d55bfa75a14cbc5136b9328be850 +Subproject commit aa82c0724ccb68fbd94605c9f4f09b19c5d2919d diff --git a/frozen/Adafruit_CircuitPython_OPT4048 b/frozen/Adafruit_CircuitPython_OPT4048 index b6a02e289e9..97e63d8cd24 160000 --- a/frozen/Adafruit_CircuitPython_OPT4048 +++ b/frozen/Adafruit_CircuitPython_OPT4048 @@ -1 +1 @@ -Subproject commit b6a02e289e922b328fd395908b6b89f12ee137ea +Subproject commit 97e63d8cd2425248c0aee323c3d8a6422404eaa5 diff --git a/frozen/Adafruit_CircuitPython_PCF8563 b/frozen/Adafruit_CircuitPython_PCF8563 index 3f40c877acb..c4ca8d355b7 160000 --- a/frozen/Adafruit_CircuitPython_PCF8563 +++ b/frozen/Adafruit_CircuitPython_PCF8563 @@ -1 +1 @@ -Subproject commit 3f40c877acbbda0ef82336c18f3620ce1b9013f5 +Subproject commit c4ca8d355b79179b44716544577925442a801bc0 diff --git a/frozen/Adafruit_CircuitPython_Pixel_Framebuf b/frozen/Adafruit_CircuitPython_Pixel_Framebuf index d355df47c0d..ffd3e8a6926 160000 --- a/frozen/Adafruit_CircuitPython_Pixel_Framebuf +++ b/frozen/Adafruit_CircuitPython_Pixel_Framebuf @@ -1 +1 @@ -Subproject commit d355df47c0d5c1f80da01c86d585223988f30a33 +Subproject commit ffd3e8a692676d076a2fa3f725e3a8ea63441139 diff --git a/frozen/Adafruit_CircuitPython_PortalBase b/frozen/Adafruit_CircuitPython_PortalBase index 067b1b80dfd..fc4aeea36ae 160000 --- a/frozen/Adafruit_CircuitPython_PortalBase +++ b/frozen/Adafruit_CircuitPython_PortalBase @@ -1 +1 @@ -Subproject commit 067b1b80dfd42fe1b62416eef2790b7d99d46206 +Subproject commit fc4aeea36ae462463eb1317b66e0f772c439b28a diff --git a/frozen/Adafruit_CircuitPython_ProgressBar b/frozen/Adafruit_CircuitPython_ProgressBar index 9fa23112cea..e720f6ff61a 160000 --- a/frozen/Adafruit_CircuitPython_ProgressBar +++ b/frozen/Adafruit_CircuitPython_ProgressBar @@ -1 +1 @@ -Subproject commit 9fa23112cea1a8db2b9b87cf2156cc4b039440a7 +Subproject commit e720f6ff61aa41485a5611d8df3f7fa25fe8fb79 diff --git a/frozen/Adafruit_CircuitPython_RFM69 b/frozen/Adafruit_CircuitPython_RFM69 index 763992bb084..2f8a38c3cae 160000 --- a/frozen/Adafruit_CircuitPython_RFM69 +++ b/frozen/Adafruit_CircuitPython_RFM69 @@ -1 +1 @@ -Subproject commit 763992bb084343ee1a7cfce72585e028ced0d890 +Subproject commit 2f8a38c3cae772aa73216499dd40fde695878566 diff --git a/frozen/Adafruit_CircuitPython_RFM9x b/frozen/Adafruit_CircuitPython_RFM9x index ad05a38fc96..b2a843ddff2 160000 --- a/frozen/Adafruit_CircuitPython_RFM9x +++ b/frozen/Adafruit_CircuitPython_RFM9x @@ -1 +1 @@ -Subproject commit ad05a38fc96edcae5d0ac9d107c268dd76e4a186 +Subproject commit b2a843ddff22cec5a2b6ee79ba0c52e17cbf9dd2 diff --git a/frozen/Adafruit_CircuitPython_Register b/frozen/Adafruit_CircuitPython_Register index 98faa16a0dd..e168e97a2c9 160000 --- a/frozen/Adafruit_CircuitPython_Register +++ b/frozen/Adafruit_CircuitPython_Register @@ -1 +1 @@ -Subproject commit 98faa16a0dd6c63a2726b291a53fde760a0fcabb +Subproject commit e168e97a2c9713ec0f82cb6171461873dfffd46d diff --git a/frozen/Adafruit_CircuitPython_Requests b/frozen/Adafruit_CircuitPython_Requests index 1479169b59d..82a656aa807 160000 --- a/frozen/Adafruit_CircuitPython_Requests +++ b/frozen/Adafruit_CircuitPython_Requests @@ -1 +1 @@ -Subproject commit 1479169b59d069b15384da64645f1e2d711a4679 +Subproject commit 82a656aa80797ae8c526b69061b9e75728d377c9 diff --git a/frozen/Adafruit_CircuitPython_SD b/frozen/Adafruit_CircuitPython_SD index dfbb9fd6ae2..e85d264ad6e 160000 --- a/frozen/Adafruit_CircuitPython_SD +++ b/frozen/Adafruit_CircuitPython_SD @@ -1 +1 @@ -Subproject commit dfbb9fd6ae297d6246554ea44e6c318970de98af +Subproject commit e85d264ad6eaa286333fd3dbbf7a95b9ea7f0af3 diff --git a/frozen/Adafruit_CircuitPython_SHT4x b/frozen/Adafruit_CircuitPython_SHT4x index 9da248ca944..c29695027b1 160000 --- a/frozen/Adafruit_CircuitPython_SHT4x +++ b/frozen/Adafruit_CircuitPython_SHT4x @@ -1 +1 @@ -Subproject commit 9da248ca944264cbc4278c1732f901f3e1229231 +Subproject commit c29695027b1d5f5140b570f31c91ace373f45843 diff --git a/frozen/Adafruit_CircuitPython_SSD1306 b/frozen/Adafruit_CircuitPython_SSD1306 index 2d7fd1fd8f7..f8fa41a320f 160000 --- a/frozen/Adafruit_CircuitPython_SSD1306 +++ b/frozen/Adafruit_CircuitPython_SSD1306 @@ -1 +1 @@ -Subproject commit 2d7fd1fd8f7bb1b83d60926a28ab01ffaf67fa3b +Subproject commit f8fa41a320f0bb29be6f37d340e69eba16b7a311 diff --git a/frozen/Adafruit_CircuitPython_SSD1680 b/frozen/Adafruit_CircuitPython_SSD1680 index c22e6d097b4..292f58b987d 160000 --- a/frozen/Adafruit_CircuitPython_SSD1680 +++ b/frozen/Adafruit_CircuitPython_SSD1680 @@ -1 +1 @@ -Subproject commit c22e6d097b44c6e9612ff6b866ebec569796e6f5 +Subproject commit 292f58b987db50dd622be5b83722893c58c16ab9 diff --git a/frozen/Adafruit_CircuitPython_ST7789 b/frozen/Adafruit_CircuitPython_ST7789 index 1060cf1753d..24a0feec2b2 160000 --- a/frozen/Adafruit_CircuitPython_ST7789 +++ b/frozen/Adafruit_CircuitPython_ST7789 @@ -1 +1 @@ -Subproject commit 1060cf1753df0024a95070132045357ddd9ce559 +Subproject commit 24a0feec2b24517c9f606f5063b6b48db4ce370e diff --git a/frozen/Adafruit_CircuitPython_SimpleIO b/frozen/Adafruit_CircuitPython_SimpleIO index 054d2643744..5762bd0ec13 160000 --- a/frozen/Adafruit_CircuitPython_SimpleIO +++ b/frozen/Adafruit_CircuitPython_SimpleIO @@ -1 +1 @@ -Subproject commit 054d2643744fe78fed3c4c8b371ced26c8ab2ebe +Subproject commit 5762bd0ec1309f9ef489633ed8bcc17d1bc7f560 diff --git a/frozen/Adafruit_CircuitPython_SimpleMath b/frozen/Adafruit_CircuitPython_SimpleMath index da27f052357..3653b67541b 160000 --- a/frozen/Adafruit_CircuitPython_SimpleMath +++ b/frozen/Adafruit_CircuitPython_SimpleMath @@ -1 +1 @@ -Subproject commit da27f05235713bc8e79cf3a005d11bab920e13bb +Subproject commit 3653b67541b7dbf0fbaaa65628c25cc6900dea87 diff --git a/frozen/Adafruit_CircuitPython_Thermistor b/frozen/Adafruit_CircuitPython_Thermistor index f109e9d847b..86b15255613 160000 --- a/frozen/Adafruit_CircuitPython_Thermistor +++ b/frozen/Adafruit_CircuitPython_Thermistor @@ -1 +1 @@ -Subproject commit f109e9d847b7f8ba8545a2b6be8d0c3dd6a8a280 +Subproject commit 86b152556138624979cad2df3210cadc38b5b344 diff --git a/frozen/Adafruit_CircuitPython_Ticks b/frozen/Adafruit_CircuitPython_Ticks index 83695404ab7..0b27bc3dad3 160000 --- a/frozen/Adafruit_CircuitPython_Ticks +++ b/frozen/Adafruit_CircuitPython_Ticks @@ -1 +1 @@ -Subproject commit 83695404ab734eb60d32c9e96784b9bd90c58a1a +Subproject commit 0b27bc3dad368b2cd6f18cb4faba3fcb41d54477 diff --git a/frozen/Adafruit_CircuitPython_UC8151D b/frozen/Adafruit_CircuitPython_UC8151D index b9bd61a0bbe..9a37fc43eeb 160000 --- a/frozen/Adafruit_CircuitPython_UC8151D +++ b/frozen/Adafruit_CircuitPython_UC8151D @@ -1 +1 @@ -Subproject commit b9bd61a0bbef1f4705abb831739d4888f1dcec95 +Subproject commit 9a37fc43eeb277f698614e8d657c4104a75a44aa diff --git a/frozen/Adafruit_CircuitPython_Wave b/frozen/Adafruit_CircuitPython_Wave index d302cd78d29..b2dd41fa0e3 160000 --- a/frozen/Adafruit_CircuitPython_Wave +++ b/frozen/Adafruit_CircuitPython_Wave @@ -1 +1 @@ -Subproject commit d302cd78d29ef821faa1c18482a0b20fdca1d4ee +Subproject commit b2dd41fa0e3757c187a4693147eb7d83a84b5119 diff --git a/frozen/Adafruit_CircuitPython_Wiznet5k b/frozen/Adafruit_CircuitPython_Wiznet5k index fa2e95d61fb..f01275e34ad 160000 --- a/frozen/Adafruit_CircuitPython_Wiznet5k +++ b/frozen/Adafruit_CircuitPython_Wiznet5k @@ -1 +1 @@ -Subproject commit fa2e95d61fb5a90b8bd59234b56d1acbfe9fd995 +Subproject commit f01275e34ad2e5f7ddd9d074e963a8359011a297 diff --git a/frozen/Adafruit_CircuitPython_asyncio b/frozen/Adafruit_CircuitPython_asyncio index e69ac03dccf..d0d63f113c7 160000 --- a/frozen/Adafruit_CircuitPython_asyncio +++ b/frozen/Adafruit_CircuitPython_asyncio @@ -1 +1 @@ -Subproject commit e69ac03dccfd87ccaf3655dc751331ff922f525f +Subproject commit d0d63f113c7da0852bdc5aa303cd738e45d40fbc diff --git a/frozen/Adafruit_CircuitPython_framebuf b/frozen/Adafruit_CircuitPython_framebuf index 8a94ddb7257..6f6c89891de 160000 --- a/frozen/Adafruit_CircuitPython_framebuf +++ b/frozen/Adafruit_CircuitPython_framebuf @@ -1 +1 @@ -Subproject commit 8a94ddb7257bebfb856fe476d9b851dfa63ce443 +Subproject commit 6f6c89891de7d96c43028c4fdff5765763dffe16 diff --git a/frozen/Adafruit_CircuitPython_seesaw b/frozen/Adafruit_CircuitPython_seesaw index 50628104824..13ba8ba2a2c 160000 --- a/frozen/Adafruit_CircuitPython_seesaw +++ b/frozen/Adafruit_CircuitPython_seesaw @@ -1 +1 @@ -Subproject commit 50628104824849fbdac093c8f18367623edff1c4 +Subproject commit 13ba8ba2a2cecb9df5a41390f991ce6c0cd76e14 diff --git a/lib/AnimatedGIF/gif.c b/lib/AnimatedGIF/gif.c index 0822b608c18..316fc1ab749 100644 --- a/lib/AnimatedGIF/gif.c +++ b/lib/AnimatedGIF/gif.c @@ -23,7 +23,7 @@ // #include "AnimatedGIF_circuitpy.h" -#ifdef HAL_ESP32_HAL_H_ +#ifndef memcpy_P #define memcpy_P memcpy #endif diff --git a/lib/berkeley-db-1.xx b/lib/berkeley-db-1.xx index 85373b548f1..0f3bb6947c2 160000 --- a/lib/berkeley-db-1.xx +++ b/lib/berkeley-db-1.xx @@ -1 +1 @@ -Subproject commit 85373b548f1fb0119a463582570b44189dfb09ae +Subproject commit 0f3bb6947c2f57233916dccd7bb425d7bf86e5a6 diff --git a/lib/libm_dbl/libm.h b/lib/libm_dbl/libm.h index cbae6916625..fa49ad1cddd 100644 --- a/lib/libm_dbl/libm.h +++ b/lib/libm_dbl/libm.h @@ -89,7 +89,9 @@ do { \ (d) = __u.f; \ } while (0) +#if !defined(DBL_EPSILON) #define DBL_EPSILON 2.22044604925031308085e-16 +#endif int __rem_pio2(double, double*); int __rem_pio2_large(double*, double*, int, int, int); diff --git a/lib/libm_dbl/rint.c b/lib/libm_dbl/rint.c index fbba390e7d7..b85dec8f246 100644 --- a/lib/libm_dbl/rint.c +++ b/lib/libm_dbl/rint.c @@ -2,7 +2,7 @@ #include #include -#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 +#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 || FLT_EVAL_METHOD==16 #define EPS DBL_EPSILON #elif FLT_EVAL_METHOD==2 #define EPS LDBL_EPSILON diff --git a/lib/littlefs/lfs2.c b/lib/littlefs/lfs2.c index 613213669c8..8d18b7d1105 100644 --- a/lib/littlefs/lfs2.c +++ b/lib/littlefs/lfs2.c @@ -93,6 +93,7 @@ static int lfs2_bd_read(lfs2_t *lfs2, // bypass cache? diff = lfs2_aligndown(diff, lfs2->cfg->read_size); int err = lfs2->cfg->read(lfs2->cfg, block, off, data, diff); + LFS2_ASSERT(err <= 0); if (err) { return err; } @@ -282,6 +283,21 @@ static int lfs2_bd_erase(lfs2_t *lfs2, lfs2_block_t block) { /// Small type-level utilities /// + +// some operations on paths +static inline lfs2_size_t lfs2_path_namelen(const char *path) { + return strcspn(path, "/"); +} + +static inline bool lfs2_path_islast(const char *path) { + lfs2_size_t namelen = lfs2_path_namelen(path); + return path[namelen + strspn(path + namelen, "/")] == '\0'; +} + +static inline bool lfs2_path_isdir(const char *path) { + return path[lfs2_path_namelen(path)] != '\0'; +} + // operations on block pairs static inline void lfs2_pair_swap(lfs2_block_t pair[2]) { lfs2_block_t t = pair[0]; @@ -389,18 +405,15 @@ struct lfs2_diskoff { // operations on global state static inline void lfs2_gstate_xor(lfs2_gstate_t *a, const lfs2_gstate_t *b) { - for (int i = 0; i < 3; i++) { - ((uint32_t*)a)[i] ^= ((const uint32_t*)b)[i]; - } + a->tag ^= b->tag; + a->pair[0] ^= b->pair[0]; + a->pair[1] ^= b->pair[1]; } static inline bool lfs2_gstate_iszero(const lfs2_gstate_t *a) { - for (int i = 0; i < 3; i++) { - if (((uint32_t*)a)[i] != 0) { - return false; - } - } - return true; + return a->tag == 0 + && a->pair[0] == 0 + && a->pair[1] == 0; } #ifndef LFS2_READONLY @@ -550,9 +563,9 @@ static int lfs2_dir_compact(lfs2_t *lfs2, lfs2_mdir_t *source, uint16_t begin, uint16_t end); static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file, const void *buffer, lfs2_size_t size); -static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_ssize_t lfs2_file_write_(lfs2_t *lfs2, lfs2_file_t *file, const void *buffer, lfs2_size_t size); -static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file); +static int lfs2_file_sync_(lfs2_t *lfs2, lfs2_file_t *file); static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file); static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file); @@ -574,65 +587,72 @@ static int lfs21_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data); #endif -static int lfs2_dir_rawrewind(lfs2_t *lfs2, lfs2_dir_t *dir); +static int lfs2_dir_rewind_(lfs2_t *lfs2, lfs2_dir_t *dir); static lfs2_ssize_t lfs2_file_flushedread(lfs2_t *lfs2, lfs2_file_t *file, void *buffer, lfs2_size_t size); -static lfs2_ssize_t lfs2_file_rawread(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_ssize_t lfs2_file_read_(lfs2_t *lfs2, lfs2_file_t *file, void *buffer, lfs2_size_t size); -static int lfs2_file_rawclose(lfs2_t *lfs2, lfs2_file_t *file); -static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file); +static int lfs2_file_close_(lfs2_t *lfs2, lfs2_file_t *file); +static lfs2_soff_t lfs2_file_size_(lfs2_t *lfs2, lfs2_file_t *file); -static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2); -static int lfs2_fs_rawtraverse(lfs2_t *lfs2, +static lfs2_ssize_t lfs2_fs_size_(lfs2_t *lfs2); +static int lfs2_fs_traverse_(lfs2_t *lfs2, int (*cb)(void *data, lfs2_block_t block), void *data, bool includeorphans); static int lfs2_deinit(lfs2_t *lfs2); -static int lfs2_rawunmount(lfs2_t *lfs2); +static int lfs2_unmount_(lfs2_t *lfs2); /// Block allocator /// + +// allocations should call this when all allocated blocks are committed to +// the filesystem +// +// after a checkpoint, the block allocator may realloc any untracked blocks +static void lfs2_alloc_ckpoint(lfs2_t *lfs2) { + lfs2->lookahead.ckpoint = lfs2->block_count; +} + +// drop the lookahead buffer, this is done during mounting and failed +// traversals in order to avoid invalid lookahead state +static void lfs2_alloc_drop(lfs2_t *lfs2) { + lfs2->lookahead.size = 0; + lfs2->lookahead.next = 0; + lfs2_alloc_ckpoint(lfs2); +} + #ifndef LFS2_READONLY static int lfs2_alloc_lookahead(void *p, lfs2_block_t block) { lfs2_t *lfs2 = (lfs2_t*)p; - lfs2_block_t off = ((block - lfs2->free.off) + lfs2_block_t off = ((block - lfs2->lookahead.start) + lfs2->block_count) % lfs2->block_count; - if (off < lfs2->free.size) { - lfs2->free.buffer[off / 32] |= 1U << (off % 32); + if (off < lfs2->lookahead.size) { + lfs2->lookahead.buffer[off / 8] |= 1U << (off % 8); } return 0; } #endif -// indicate allocated blocks have been committed into the filesystem, this -// is to prevent blocks from being garbage collected in the middle of a -// commit operation -static void lfs2_alloc_ack(lfs2_t *lfs2) { - lfs2->free.ack = lfs2->block_count; -} - -// drop the lookahead buffer, this is done during mounting and failed -// traversals in order to avoid invalid lookahead state -static void lfs2_alloc_drop(lfs2_t *lfs2) { - lfs2->free.size = 0; - lfs2->free.i = 0; - lfs2_alloc_ack(lfs2); -} - #ifndef LFS2_READONLY -static int lfs2_fs_rawgc(lfs2_t *lfs2) { - // Move free offset at the first unused block (lfs2->free.i) - // lfs2->free.i is equal lfs2->free.size when all blocks are used - lfs2->free.off = (lfs2->free.off + lfs2->free.i) % lfs2->block_count; - lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, lfs2->free.ack); - lfs2->free.i = 0; +static int lfs2_alloc_scan(lfs2_t *lfs2) { + // move lookahead buffer to the first unused block + // + // note we limit the lookahead buffer to at most the amount of blocks + // checkpointed, this prevents the math in lfs2_alloc from underflowing + lfs2->lookahead.start = (lfs2->lookahead.start + lfs2->lookahead.next) + % lfs2->block_count; + lfs2->lookahead.next = 0; + lfs2->lookahead.size = lfs2_min( + 8*lfs2->cfg->lookahead_size, + lfs2->lookahead.ckpoint); // find mask of free blocks from tree - memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size); - int err = lfs2_fs_rawtraverse(lfs2, lfs2_alloc_lookahead, lfs2, true); + memset(lfs2->lookahead.buffer, 0, lfs2->cfg->lookahead_size); + int err = lfs2_fs_traverse_(lfs2, lfs2_alloc_lookahead, lfs2, true); if (err) { lfs2_alloc_drop(lfs2); return err; @@ -645,36 +665,49 @@ static int lfs2_fs_rawgc(lfs2_t *lfs2) { #ifndef LFS2_READONLY static int lfs2_alloc(lfs2_t *lfs2, lfs2_block_t *block) { while (true) { - while (lfs2->free.i != lfs2->free.size) { - lfs2_block_t off = lfs2->free.i; - lfs2->free.i += 1; - lfs2->free.ack -= 1; - - if (!(lfs2->free.buffer[off / 32] & (1U << (off % 32)))) { + // scan our lookahead buffer for free blocks + while (lfs2->lookahead.next < lfs2->lookahead.size) { + if (!(lfs2->lookahead.buffer[lfs2->lookahead.next / 8] + & (1U << (lfs2->lookahead.next % 8)))) { // found a free block - *block = (lfs2->free.off + off) % lfs2->block_count; - - // eagerly find next off so an alloc ack can - // discredit old lookahead blocks - while (lfs2->free.i != lfs2->free.size && - (lfs2->free.buffer[lfs2->free.i / 32] - & (1U << (lfs2->free.i % 32)))) { - lfs2->free.i += 1; - lfs2->free.ack -= 1; + *block = (lfs2->lookahead.start + lfs2->lookahead.next) + % lfs2->block_count; + + // eagerly find next free block to maximize how many blocks + // lfs2_alloc_ckpoint makes available for scanning + while (true) { + lfs2->lookahead.next += 1; + lfs2->lookahead.ckpoint -= 1; + + if (lfs2->lookahead.next >= lfs2->lookahead.size + || !(lfs2->lookahead.buffer[lfs2->lookahead.next / 8] + & (1U << (lfs2->lookahead.next % 8)))) { + return 0; + } } - - return 0; } + + lfs2->lookahead.next += 1; + lfs2->lookahead.ckpoint -= 1; } - // check if we have looked at all blocks since last ack - if (lfs2->free.ack == 0) { - LFS2_ERROR("No more free space %"PRIu32, - lfs2->free.i + lfs2->free.off); + // In order to keep our block allocator from spinning forever when our + // filesystem is full, we mark points where there are no in-flight + // allocations with a checkpoint before starting a set of allocations. + // + // If we've looked at all blocks since the last checkpoint, we report + // the filesystem as out of storage. + // + if (lfs2->lookahead.ckpoint <= 0) { + LFS2_ERROR("No more free space 0x%"PRIx32, + (lfs2->lookahead.start + lfs2->lookahead.next) + % lfs2->block_count); return LFS2_ERR_NOSPC; } - int err = lfs2_fs_rawgc(lfs2); + // No blocks in our lookahead buffer, we need to scan the filesystem for + // unused blocks in the next lookahead window. + int err = lfs2_alloc_scan(lfs2); if(err) { return err; } @@ -690,11 +723,14 @@ static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir, lfs2_tag_t ntag = dir->etag; lfs2_stag_t gdiff = 0; + // synthetic moves if (lfs2_gstate_hasmovehere(&lfs2->gdisk, dir->pair) && - lfs2_tag_id(gmask) != 0 && - lfs2_tag_id(lfs2->gdisk.tag) <= lfs2_tag_id(gtag)) { - // synthetic moves - gdiff -= LFS2_MKTAG(0, 1, 0); + lfs2_tag_id(gmask) != 0) { + if (lfs2_tag_id(lfs2->gdisk.tag) == lfs2_tag_id(gtag)) { + return LFS2_ERR_NOENT; + } else if (lfs2_tag_id(lfs2->gdisk.tag) < lfs2_tag_id(gtag)) { + gdiff -= LFS2_MKTAG(0, 1, 0); + } } // iterate over dir block backwards (for faster lookups) @@ -704,6 +740,7 @@ static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir, int err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, sizeof(ntag), dir->pair[0], off, &ntag, sizeof(ntag)); + LFS2_ASSERT(err <= 0); if (err) { return err; } @@ -732,6 +769,7 @@ static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir, err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, diff, dir->pair[0], off+sizeof(tag)+goff, gbuffer, diff); + LFS2_ASSERT(err <= 0); if (err) { return err; } @@ -793,9 +831,6 @@ static int lfs2_dir_getread(lfs2_t *lfs2, const lfs2_mdir_t *dir, size -= diff; continue; } - - // rcache takes priority - diff = lfs2_min(diff, rcache->off-off); } // load to cache, first condition can no longer fail @@ -1247,6 +1282,7 @@ static lfs2_stag_t lfs2_dir_fetchmatch(lfs2_t *lfs2, if (err == LFS2_ERR_CORRUPT) { break; } + return err; } lfs2_fcrc_fromle32(&fcrc); @@ -1438,32 +1474,46 @@ static int lfs2_dir_find_match(void *data, return LFS2_CMP_EQ; } +// lfs2_dir_find tries to set path and id even if file is not found +// +// returns: +// - 0 if file is found +// - LFS2_ERR_NOENT if file or parent is not found +// - LFS2_ERR_NOTDIR if parent is not a dir static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, const char **path, uint16_t *id) { // we reduce path to a single name if we can find it const char *name = *path; - if (id) { - *id = 0x3ff; - } // default to root dir lfs2_stag_t tag = LFS2_MKTAG(LFS2_TYPE_DIR, 0x3ff, 0); dir->tail[0] = lfs2->root[0]; dir->tail[1] = lfs2->root[1]; + // empty paths are not allowed + if (*name == '\0') { + return LFS2_ERR_INVAL; + } + while (true) { nextname: - // skip slashes - name += strspn(name, "/"); + // skip slashes if we're a directory + if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) { + name += strspn(name, "/"); + } lfs2_size_t namelen = strcspn(name, "/"); - // skip '.' and root '..' - if ((namelen == 1 && memcmp(name, ".", 1) == 0) || - (namelen == 2 && memcmp(name, "..", 2) == 0)) { + // skip '.' + if (namelen == 1 && memcmp(name, ".", 1) == 0) { name += namelen; goto nextname; } + // error on unmatched '..', trying to go above root? + if (namelen == 2 && memcmp(name, "..", 2) == 0) { + return LFS2_ERR_INVAL; + } + // skip if matched by '..' in name const char *suffix = name + namelen; lfs2_size_t sufflen; @@ -1475,7 +1525,9 @@ static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, break; } - if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { + if (sufflen == 1 && memcmp(suffix, ".", 1) == 0) { + // noop + } else if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { depth -= 1; if (depth == 0) { name = suffix + sufflen; @@ -1489,14 +1541,14 @@ static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, } // found path - if (name[0] == '\0') { + if (*name == '\0') { return tag; } // update what we've found so far *path = name; - // only continue if we hit a directory + // only continue if we're a directory if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) { return LFS2_ERR_NOTDIR; } @@ -1516,8 +1568,7 @@ static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, tag = lfs2_dir_fetchmatch(lfs2, dir, dir->tail, LFS2_MKTAG(0x780, 0, 0), LFS2_MKTAG(LFS2_TYPE_NAME, 0, namelen), - // are we last name? - (strchr(name, '/') == NULL) ? id : NULL, + id, lfs2_dir_find_match, &(struct lfs2_dir_find_match){ lfs2, name, namelen}); if (tag < 0) { @@ -2105,13 +2156,14 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir, // And we cap at half a block to avoid degenerate cases with // nearly-full metadata blocks. // + lfs2_size_t metadata_max = (lfs2->cfg->metadata_max) + ? lfs2->cfg->metadata_max + : lfs2->cfg->block_size; if (end - split < 0xff && size <= lfs2_min( - lfs2->cfg->block_size - 40, + metadata_max - 40, lfs2_alignup( - (lfs2->cfg->metadata_max - ? lfs2->cfg->metadata_max - : lfs2->cfg->block_size)/2, + metadata_max/2, lfs2->cfg->prog_size))) { break; } @@ -2146,14 +2198,16 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir, && lfs2_pair_cmp(dir->pair, (const lfs2_block_t[2]){0, 1}) == 0) { // oh no! we're writing too much to the superblock, // should we expand? - lfs2_ssize_t size = lfs2_fs_rawsize(lfs2); + lfs2_ssize_t size = lfs2_fs_size_(lfs2); if (size < 0) { return size; } - // do we have extra space? littlefs can't reclaim this space - // by itself, so expand cautiously - if ((lfs2_size_t)size < lfs2->block_count/2) { + // littlefs cannot reclaim expanded superblocks, so expand cautiously + // + // if our filesystem is more than ~88% full, don't expand, this is + // somewhat arbitrary + if (lfs2->block_count - size > lfs2->block_count/8) { LFS2_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev); int err = lfs2_dir_split(lfs2, dir, attrs, attrcount, source, begin, end); @@ -2166,7 +2220,8 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir, // we can do, we'll error later if we've become frozen LFS2_WARN("Unable to expand superblock"); } else { - end = begin; + // duplicate the superblock entry into the new superblock + end = 1; } } } @@ -2213,7 +2268,7 @@ static int lfs2_dir_relocatingcommit(lfs2_t *lfs2, lfs2_mdir_t *dir, } } - if (dir->erased) { + if (dir->erased && dir->count < 0xff) { // try to commit struct lfs2_commit commit = { .block = dir->pair[0], @@ -2312,7 +2367,8 @@ fixmlist:; if (d->m.pair != pair) { for (int i = 0; i < attrcount; i++) { if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE && - d->id == lfs2_tag_id(attrs[i].tag)) { + d->id == lfs2_tag_id(attrs[i].tag) && + d->type != LFS2_TYPE_DIR) { d->m.pair[0] = LFS2_BLOCK_NULL; d->m.pair[1] = LFS2_BLOCK_NULL; } else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE && @@ -2333,7 +2389,9 @@ fixmlist:; while (d->id >= d->m.count && d->m.split) { // we split and id is on tail now - d->id -= d->m.count; + if (lfs2_pair_cmp(d->m.tail, lfs2->root) != 0) { + d->id -= d->m.count; + } int err = lfs2_dir_fetch(lfs2, &d->m, d->m.tail); if (err) { return err; @@ -2499,7 +2557,7 @@ static int lfs2_dir_orphaningcommit(lfs2_t *lfs2, lfs2_mdir_t *dir, if (err != LFS2_ERR_NOENT) { if (lfs2_gstate_hasorphans(&lfs2->gstate)) { // next step, clean up orphans - err = lfs2_fs_preporphans(lfs2, -hasparent); + err = lfs2_fs_preporphans(lfs2, -(int8_t)hasparent); if (err) { return err; } @@ -2564,7 +2622,7 @@ static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir, /// Top level directory operations /// #ifndef LFS2_READONLY -static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) { +static int lfs2_mkdir_(lfs2_t *lfs2, const char *path) { // deorphan if we haven't yet, needed at most once after poweron int err = lfs2_fs_forceconsistency(lfs2); if (err) { @@ -2575,18 +2633,18 @@ static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) { cwd.next = lfs2->mlist; uint16_t id; err = lfs2_dir_find(lfs2, &cwd.m, &path, &id); - if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) { + if (!(err == LFS2_ERR_NOENT && lfs2_path_islast(path))) { return (err < 0) ? err : LFS2_ERR_EXIST; } // check that name fits - lfs2_size_t nlen = strlen(path); + lfs2_size_t nlen = lfs2_path_namelen(path); if (nlen > lfs2->name_max) { return LFS2_ERR_NAMETOOLONG; } // build up new directory - lfs2_alloc_ack(lfs2); + lfs2_alloc_ckpoint(lfs2); lfs2_mdir_t dir; err = lfs2_dir_alloc(lfs2, &dir); if (err) { @@ -2660,7 +2718,7 @@ static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) { } #endif -static int lfs2_dir_rawopen(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { +static int lfs2_dir_open_(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { lfs2_stag_t tag = lfs2_dir_find(lfs2, &dir->m, &path, NULL); if (tag < 0) { return tag; @@ -2704,14 +2762,14 @@ static int lfs2_dir_rawopen(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { return 0; } -static int lfs2_dir_rawclose(lfs2_t *lfs2, lfs2_dir_t *dir) { +static int lfs2_dir_close_(lfs2_t *lfs2, lfs2_dir_t *dir) { // remove from list of mdirs lfs2_mlist_remove(lfs2, (struct lfs2_mlist *)dir); return 0; } -static int lfs2_dir_rawread(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) { +static int lfs2_dir_read_(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) { memset(info, 0, sizeof(*info)); // special offset for '.' and '..' @@ -2756,9 +2814,9 @@ static int lfs2_dir_rawread(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *inf return true; } -static int lfs2_dir_rawseek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { +static int lfs2_dir_seek_(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { // simply walk from head dir - int err = lfs2_dir_rawrewind(lfs2, dir); + int err = lfs2_dir_rewind_(lfs2, dir); if (err) { return err; } @@ -2793,12 +2851,12 @@ static int lfs2_dir_rawseek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { return 0; } -static lfs2_soff_t lfs2_dir_rawtell(lfs2_t *lfs2, lfs2_dir_t *dir) { +static lfs2_soff_t lfs2_dir_tell_(lfs2_t *lfs2, lfs2_dir_t *dir) { (void)lfs2; return dir->pos; } -static int lfs2_dir_rawrewind(lfs2_t *lfs2, lfs2_dir_t *dir) { +static int lfs2_dir_rewind_(lfs2_t *lfs2, lfs2_dir_t *dir) { // reload the head dir int err = lfs2_dir_fetch(lfs2, &dir->m, dir->head); if (err) { @@ -3004,7 +3062,7 @@ static int lfs2_ctz_traverse(lfs2_t *lfs2, /// Top level file operations /// -static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file, +static int lfs2_file_opencfg_(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags, const struct lfs2_file_config *cfg) { #ifndef LFS2_READONLY @@ -3029,7 +3087,7 @@ static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file, // allocate entry for file if it doesn't exist lfs2_stag_t tag = lfs2_dir_find(lfs2, &file->m, &path, &file->id); - if (tag < 0 && !(tag == LFS2_ERR_NOENT && file->id != 0x3ff)) { + if (tag < 0 && !(tag == LFS2_ERR_NOENT && lfs2_path_islast(path))) { err = tag; goto cleanup; } @@ -3049,8 +3107,14 @@ static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file, goto cleanup; } + // don't allow trailing slashes + if (lfs2_path_isdir(path)) { + err = LFS2_ERR_NOTDIR; + goto cleanup; + } + // check that name fits - lfs2_size_t nlen = strlen(path); + lfs2_size_t nlen = lfs2_path_namelen(path); if (nlen > lfs2->name_max) { err = LFS2_ERR_NAMETOOLONG; goto cleanup; @@ -3166,22 +3230,22 @@ static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file, #ifndef LFS2_READONLY file->flags |= LFS2_F_ERRED; #endif - lfs2_file_rawclose(lfs2, file); + lfs2_file_close_(lfs2, file); return err; } #ifndef LFS2_NO_MALLOC -static int lfs2_file_rawopen(lfs2_t *lfs2, lfs2_file_t *file, +static int lfs2_file_open_(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags) { static const struct lfs2_file_config defaults = {0}; - int err = lfs2_file_rawopencfg(lfs2, file, path, flags, &defaults); + int err = lfs2_file_opencfg_(lfs2, file, path, flags, &defaults); return err; } #endif -static int lfs2_file_rawclose(lfs2_t *lfs2, lfs2_file_t *file) { +static int lfs2_file_close_(lfs2_t *lfs2, lfs2_file_t *file) { #ifndef LFS2_READONLY - int err = lfs2_file_rawsync(lfs2, file); + int err = lfs2_file_sync_(lfs2, file); #else int err = 0; #endif @@ -3272,7 +3336,7 @@ static int lfs2_file_relocate(lfs2_t *lfs2, lfs2_file_t *file) { #ifndef LFS2_READONLY static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file) { file->off = file->pos; - lfs2_alloc_ack(lfs2); + lfs2_alloc_ckpoint(lfs2); int err = lfs2_file_relocate(lfs2, file); if (err) { return err; @@ -3364,7 +3428,7 @@ static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file) { } #ifndef LFS2_READONLY -static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file) { +static int lfs2_file_sync_(lfs2_t *lfs2, lfs2_file_t *file) { if (file->flags & LFS2_F_ERRED) { // it's not safe to do anything if our file errored return 0; @@ -3379,6 +3443,15 @@ static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file) { if ((file->flags & LFS2_F_DIRTY) && !lfs2_pair_isnull(file->m.pair)) { + // before we commit metadata, we need sync the disk to make sure + // data writes don't complete after metadata writes + if (!(file->flags & LFS2_F_INLINE)) { + err = lfs2_bd_sync(lfs2, &lfs2->pcache, &lfs2->rcache, false); + if (err) { + return err; + } + } + // update dir entry uint16_t type; const void *buffer; @@ -3477,7 +3550,7 @@ static lfs2_ssize_t lfs2_file_flushedread(lfs2_t *lfs2, lfs2_file_t *file, return size; } -static lfs2_ssize_t lfs2_file_rawread(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_ssize_t lfs2_file_read_(lfs2_t *lfs2, lfs2_file_t *file, void *buffer, lfs2_size_t size) { LFS2_ASSERT((file->flags & LFS2_O_RDONLY) == LFS2_O_RDONLY); @@ -3502,11 +3575,7 @@ static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file, lfs2_size_t nsize = size; if ((file->flags & LFS2_F_INLINE) && - lfs2_max(file->pos+nsize, file->ctz.size) > - lfs2_min(0x3fe, lfs2_min( - lfs2->cfg->cache_size, - (lfs2->cfg->metadata_max ? - lfs2->cfg->metadata_max : lfs2->cfg->block_size) / 8))) { + lfs2_max(file->pos+nsize, file->ctz.size) > lfs2->inline_max) { // inline file doesn't fit anymore int err = lfs2_file_outline(lfs2, file); if (err) { @@ -3535,7 +3604,7 @@ static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file, } // extend file with new blocks - lfs2_alloc_ack(lfs2); + lfs2_alloc_ckpoint(lfs2); int err = lfs2_ctz_extend(lfs2, &file->cache, &lfs2->rcache, file->block, file->pos, &file->block, &file->off); @@ -3578,13 +3647,13 @@ static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file, data += diff; nsize -= diff; - lfs2_alloc_ack(lfs2); + lfs2_alloc_ckpoint(lfs2); } return size; } -static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_ssize_t lfs2_file_write_(lfs2_t *lfs2, lfs2_file_t *file, const void *buffer, lfs2_size_t size) { LFS2_ASSERT((file->flags & LFS2_O_WRONLY) == LFS2_O_WRONLY); @@ -3628,25 +3697,19 @@ static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file, } #endif -static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_soff_t lfs2_file_seek_(lfs2_t *lfs2, lfs2_file_t *file, lfs2_soff_t off, int whence) { // find new pos + // + // fortunately for us, littlefs is limited to 31-bit file sizes, so we + // don't have to worry too much about integer overflow lfs2_off_t npos = file->pos; if (whence == LFS2_SEEK_SET) { npos = off; } else if (whence == LFS2_SEEK_CUR) { - if ((lfs2_soff_t)file->pos + off < 0) { - return LFS2_ERR_INVAL; - } else { - npos = file->pos + off; - } + npos = file->pos + (lfs2_off_t)off; } else if (whence == LFS2_SEEK_END) { - lfs2_soff_t res = lfs2_file_rawsize(lfs2, file) + off; - if (res < 0) { - return LFS2_ERR_INVAL; - } else { - npos = res; - } + npos = (lfs2_off_t)lfs2_file_size_(lfs2, file) + (lfs2_off_t)off; } if (npos > lfs2->file_max) { @@ -3661,13 +3724,8 @@ static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file, // if we're only reading and our new offset is still in the file's cache // we can avoid flushing and needing to reread the data - if ( -#ifndef LFS2_READONLY - !(file->flags & LFS2_F_WRITING) -#else - true -#endif - ) { + if ((file->flags & LFS2_F_READING) + && file->off != lfs2->cfg->block_size) { int oindex = lfs2_ctz_index(lfs2, &(lfs2_off_t){file->pos}); lfs2_off_t noff = npos; int nindex = lfs2_ctz_index(lfs2, &noff); @@ -3692,7 +3750,7 @@ static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file, } #ifndef LFS2_READONLY -static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) { +static int lfs2_file_truncate_(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) { LFS2_ASSERT((file->flags & LFS2_O_WRONLY) == LFS2_O_WRONLY); if (size > LFS2_FILE_MAX) { @@ -3700,15 +3758,12 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz } lfs2_off_t pos = file->pos; - lfs2_off_t oldsize = lfs2_file_rawsize(lfs2, file); + lfs2_off_t oldsize = lfs2_file_size_(lfs2, file); if (size < oldsize) { // revert to inline file? - if (size <= lfs2_min(0x3fe, lfs2_min( - lfs2->cfg->cache_size, - (lfs2->cfg->metadata_max ? - lfs2->cfg->metadata_max : lfs2->cfg->block_size) / 8))) { + if (size <= lfs2->inline_max) { // flush+seek to head - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_SET); + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, 0, LFS2_SEEK_SET); if (res < 0) { return (int)res; } @@ -3753,14 +3808,14 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz } } else if (size > oldsize) { // flush+seek if not already at end - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_END); + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, 0, LFS2_SEEK_END); if (res < 0) { return (int)res; } // fill with zeros while (file->pos < size) { - res = lfs2_file_rawwrite(lfs2, file, &(uint8_t){0}, 1); + res = lfs2_file_write_(lfs2, file, &(uint8_t){0}, 1); if (res < 0) { return (int)res; } @@ -3768,7 +3823,7 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz } // restore pos - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, pos, LFS2_SEEK_SET); + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, pos, LFS2_SEEK_SET); if (res < 0) { return (int)res; } @@ -3777,13 +3832,13 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz } #endif -static lfs2_soff_t lfs2_file_rawtell(lfs2_t *lfs2, lfs2_file_t *file) { +static lfs2_soff_t lfs2_file_tell_(lfs2_t *lfs2, lfs2_file_t *file) { (void)lfs2; return file->pos; } -static int lfs2_file_rawrewind(lfs2_t *lfs2, lfs2_file_t *file) { - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_SET); +static int lfs2_file_rewind_(lfs2_t *lfs2, lfs2_file_t *file) { + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, 0, LFS2_SEEK_SET); if (res < 0) { return (int)res; } @@ -3791,7 +3846,7 @@ static int lfs2_file_rawrewind(lfs2_t *lfs2, lfs2_file_t *file) { return 0; } -static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file) { +static lfs2_soff_t lfs2_file_size_(lfs2_t *lfs2, lfs2_file_t *file) { (void)lfs2; #ifndef LFS2_READONLY @@ -3805,18 +3860,24 @@ static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file) { /// General fs operations /// -static int lfs2_rawstat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) { +static int lfs2_stat_(lfs2_t *lfs2, const char *path, struct lfs2_info *info) { lfs2_mdir_t cwd; lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); if (tag < 0) { return (int)tag; } + // only allow trailing slashes on dirs + if (strchr(path, '/') != NULL + && lfs2_tag_type3(tag) != LFS2_TYPE_DIR) { + return LFS2_ERR_NOTDIR; + } + return lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info); } #ifndef LFS2_READONLY -static int lfs2_rawremove(lfs2_t *lfs2, const char *path) { +static int lfs2_remove_(lfs2_t *lfs2, const char *path) { // deorphan if we haven't yet, needed at most once after poweron int err = lfs2_fs_forceconsistency(lfs2); if (err) { @@ -3872,7 +3933,9 @@ static int lfs2_rawremove(lfs2_t *lfs2, const char *path) { } lfs2->mlist = dir.next; - if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) { + if (lfs2_gstate_hasorphans(&lfs2->gstate)) { + LFS2_ASSERT(lfs2_tag_type3(tag) == LFS2_TYPE_DIR); + // fix orphan err = lfs2_fs_preporphans(lfs2, -1); if (err) { @@ -3895,7 +3958,7 @@ static int lfs2_rawremove(lfs2_t *lfs2, const char *path) { #endif #ifndef LFS2_READONLY -static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath) { +static int lfs2_rename_(lfs2_t *lfs2, const char *oldpath, const char *newpath) { // deorphan if we haven't yet, needed at most once after poweron int err = lfs2_fs_forceconsistency(lfs2); if (err) { @@ -3914,7 +3977,7 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath uint16_t newid; lfs2_stag_t prevtag = lfs2_dir_find(lfs2, &newcwd, &newpath, &newid); if ((prevtag < 0 || lfs2_tag_id(prevtag) == 0x3ff) && - !(prevtag == LFS2_ERR_NOENT && newid != 0x3ff)) { + !(prevtag == LFS2_ERR_NOENT && lfs2_path_islast(newpath))) { return (prevtag < 0) ? (int)prevtag : LFS2_ERR_INVAL; } @@ -3925,8 +3988,14 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath struct lfs2_mlist prevdir; prevdir.next = lfs2->mlist; if (prevtag == LFS2_ERR_NOENT) { + // if we're a file, don't allow trailing slashes + if (lfs2_path_isdir(newpath) + && lfs2_tag_type3(oldtag) != LFS2_TYPE_DIR) { + return LFS2_ERR_NOTDIR; + } + // check that name fits - lfs2_size_t nlen = strlen(newpath); + lfs2_size_t nlen = lfs2_path_namelen(newpath); if (nlen > lfs2->name_max) { return LFS2_ERR_NAMETOOLONG; } @@ -3938,7 +4007,9 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath newoldid += 1; } } else if (lfs2_tag_type3(prevtag) != lfs2_tag_type3(oldtag)) { - return LFS2_ERR_ISDIR; + return (lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) + ? LFS2_ERR_ISDIR + : LFS2_ERR_NOTDIR; } else if (samepair && newid == newoldid) { // we're renaming to ourselves?? return 0; @@ -3984,7 +4055,8 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath {LFS2_MKTAG_IF(prevtag != LFS2_ERR_NOENT, LFS2_TYPE_DELETE, newid, 0), NULL}, {LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0), NULL}, - {LFS2_MKTAG(lfs2_tag_type3(oldtag), newid, strlen(newpath)), newpath}, + {LFS2_MKTAG(lfs2_tag_type3(oldtag), + newid, lfs2_path_namelen(newpath)), newpath}, {LFS2_MKTAG(LFS2_FROM_MOVE, newid, lfs2_tag_id(oldtag)), &oldcwd}, {LFS2_MKTAG_IF(samepair, LFS2_TYPE_DELETE, newoldid, 0), NULL})); @@ -4007,8 +4079,10 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath } lfs2->mlist = prevdir.next; - if (prevtag != LFS2_ERR_NOENT - && lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) { + if (lfs2_gstate_hasorphans(&lfs2->gstate)) { + LFS2_ASSERT(prevtag != LFS2_ERR_NOENT + && lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR); + // fix orphan err = lfs2_fs_preporphans(lfs2, -1); if (err) { @@ -4030,7 +4104,7 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath } #endif -static lfs2_ssize_t lfs2_rawgetattr(lfs2_t *lfs2, const char *path, +static lfs2_ssize_t lfs2_getattr_(lfs2_t *lfs2, const char *path, uint8_t type, void *buffer, lfs2_size_t size) { lfs2_mdir_t cwd; lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); @@ -4088,7 +4162,7 @@ static int lfs2_commitattr(lfs2_t *lfs2, const char *path, #endif #ifndef LFS2_READONLY -static int lfs2_rawsetattr(lfs2_t *lfs2, const char *path, +static int lfs2_setattr_(lfs2_t *lfs2, const char *path, uint8_t type, const void *buffer, lfs2_size_t size) { if (size > lfs2->attr_max) { return LFS2_ERR_NOSPC; @@ -4099,13 +4173,28 @@ static int lfs2_rawsetattr(lfs2_t *lfs2, const char *path, #endif #ifndef LFS2_READONLY -static int lfs2_rawremoveattr(lfs2_t *lfs2, const char *path, uint8_t type) { +static int lfs2_removeattr_(lfs2_t *lfs2, const char *path, uint8_t type) { return lfs2_commitattr(lfs2, path, type, NULL, 0x3ff); } #endif /// Filesystem operations /// + +// compile time checks, see lfs2.h for why these limits exist +#if LFS2_NAME_MAX > 1022 +#error "Invalid LFS2_NAME_MAX, must be <= 1022" +#endif + +#if LFS2_FILE_MAX > 2147483647 +#error "Invalid LFS2_FILE_MAX, must be <= 2147483647" +#endif + +#if LFS2_ATTR_MAX > 1022 +#error "Invalid LFS2_ATTR_MAX, must be <= 1022" +#endif + +// common filesystem initialization static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { lfs2->cfg = cfg; lfs2->block_count = cfg->block_count; // May be 0 @@ -4126,6 +4215,14 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { // which littlefs currently does not support LFS2_ASSERT((bool)0x80000000); + // check that the required io functions are provided + LFS2_ASSERT(lfs2->cfg->read != NULL); +#ifndef LFS2_READONLY + LFS2_ASSERT(lfs2->cfg->prog != NULL); + LFS2_ASSERT(lfs2->cfg->erase != NULL); + LFS2_ASSERT(lfs2->cfg->sync != NULL); +#endif + // validate that the lfs2-cfg sizes were initiated properly before // performing any arithmetic logics with them LFS2_ASSERT(lfs2->cfg->read_size != 0); @@ -4153,6 +4250,23 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { // wear-leveling. LFS2_ASSERT(lfs2->cfg->block_cycles != 0); + // check that compact_thresh makes sense + // + // metadata can't be compacted below block_size/2, and metadata can't + // exceed a block_size + LFS2_ASSERT(lfs2->cfg->compact_thresh == 0 + || lfs2->cfg->compact_thresh >= lfs2->cfg->block_size/2); + LFS2_ASSERT(lfs2->cfg->compact_thresh == (lfs2_size_t)-1 + || lfs2->cfg->compact_thresh <= lfs2->cfg->block_size); + + // check that metadata_max is a multiple of read_size and prog_size, + // and a factor of the block_size + LFS2_ASSERT(!lfs2->cfg->metadata_max + || lfs2->cfg->metadata_max % lfs2->cfg->read_size == 0); + LFS2_ASSERT(!lfs2->cfg->metadata_max + || lfs2->cfg->metadata_max % lfs2->cfg->prog_size == 0); + LFS2_ASSERT(!lfs2->cfg->metadata_max + || lfs2->cfg->block_size % lfs2->cfg->metadata_max == 0); // setup read cache if (lfs2->cfg->read_buffer) { @@ -4180,15 +4294,14 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { lfs2_cache_zero(lfs2, &lfs2->rcache); lfs2_cache_zero(lfs2, &lfs2->pcache); - // setup lookahead, must be multiple of 64-bits, 32-bit aligned + // setup lookahead buffer, note mount finishes initializing this after + // we establish a decent pseudo-random seed LFS2_ASSERT(lfs2->cfg->lookahead_size > 0); - LFS2_ASSERT(lfs2->cfg->lookahead_size % 8 == 0 && - (uintptr_t)lfs2->cfg->lookahead_buffer % 4 == 0); if (lfs2->cfg->lookahead_buffer) { - lfs2->free.buffer = lfs2->cfg->lookahead_buffer; + lfs2->lookahead.buffer = lfs2->cfg->lookahead_buffer; } else { - lfs2->free.buffer = lfs2_malloc(lfs2->cfg->lookahead_size); - if (!lfs2->free.buffer) { + lfs2->lookahead.buffer = lfs2_malloc(lfs2->cfg->lookahead_size); + if (!lfs2->lookahead.buffer) { err = LFS2_ERR_NOMEM; goto cleanup; } @@ -4215,6 +4328,27 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { LFS2_ASSERT(lfs2->cfg->metadata_max <= lfs2->cfg->block_size); + LFS2_ASSERT(lfs2->cfg->inline_max == (lfs2_size_t)-1 + || lfs2->cfg->inline_max <= lfs2->cfg->cache_size); + LFS2_ASSERT(lfs2->cfg->inline_max == (lfs2_size_t)-1 + || lfs2->cfg->inline_max <= lfs2->attr_max); + LFS2_ASSERT(lfs2->cfg->inline_max == (lfs2_size_t)-1 + || lfs2->cfg->inline_max <= ((lfs2->cfg->metadata_max) + ? lfs2->cfg->metadata_max + : lfs2->cfg->block_size)/8); + lfs2->inline_max = lfs2->cfg->inline_max; + if (lfs2->inline_max == (lfs2_size_t)-1) { + lfs2->inline_max = 0; + } else if (lfs2->inline_max == 0) { + lfs2->inline_max = lfs2_min( + lfs2->cfg->cache_size, + lfs2_min( + lfs2->attr_max, + ((lfs2->cfg->metadata_max) + ? lfs2->cfg->metadata_max + : lfs2->cfg->block_size)/8)); + } + // setup default state lfs2->root[0] = LFS2_BLOCK_NULL; lfs2->root[1] = LFS2_BLOCK_NULL; @@ -4245,7 +4379,7 @@ static int lfs2_deinit(lfs2_t *lfs2) { } if (!lfs2->cfg->lookahead_buffer) { - lfs2_free(lfs2->free.buffer); + lfs2_free(lfs2->lookahead.buffer); } return 0; @@ -4254,7 +4388,7 @@ static int lfs2_deinit(lfs2_t *lfs2) { #ifndef LFS2_READONLY -static int lfs2_rawformat(lfs2_t *lfs2, const struct lfs2_config *cfg) { +static int lfs2_format_(lfs2_t *lfs2, const struct lfs2_config *cfg) { int err = 0; { err = lfs2_init(lfs2, cfg); @@ -4265,12 +4399,12 @@ static int lfs2_rawformat(lfs2_t *lfs2, const struct lfs2_config *cfg) { LFS2_ASSERT(cfg->block_count != 0); // create free lookahead - memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size); - lfs2->free.off = 0; - lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, + memset(lfs2->lookahead.buffer, 0, lfs2->cfg->lookahead_size); + lfs2->lookahead.start = 0; + lfs2->lookahead.size = lfs2_min(8*lfs2->cfg->lookahead_size, lfs2->block_count); - lfs2->free.i = 0; - lfs2_alloc_ack(lfs2); + lfs2->lookahead.next = 0; + lfs2_alloc_ckpoint(lfs2); // create root dir lfs2_mdir_t root; @@ -4321,7 +4455,31 @@ static int lfs2_rawformat(lfs2_t *lfs2, const struct lfs2_config *cfg) { } #endif -static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { +struct lfs2_tortoise_t { + lfs2_block_t pair[2]; + lfs2_size_t i; + lfs2_size_t period; +}; + +static int lfs2_tortoise_detectcycles( + const lfs2_mdir_t *dir, struct lfs2_tortoise_t *tortoise) { + // detect cycles with Brent's algorithm + if (lfs2_pair_issync(dir->tail, tortoise->pair)) { + LFS2_WARN("Cycle detected in tail list"); + return LFS2_ERR_CORRUPT; + } + if (tortoise->i == tortoise->period) { + tortoise->pair[0] = dir->tail[0]; + tortoise->pair[1] = dir->tail[1]; + tortoise->i = 0; + tortoise->period *= 2; + } + tortoise->i += 1; + + return LFS2_ERR_OK; +} + +static int lfs2_mount_(lfs2_t *lfs2, const struct lfs2_config *cfg) { int err = lfs2_init(lfs2, cfg); if (err) { return err; @@ -4329,23 +4487,16 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { // scan directory blocks for superblock and any global updates lfs2_mdir_t dir = {.tail = {0, 1}}; - lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; - lfs2_size_t tortoise_i = 1; - lfs2_size_t tortoise_period = 1; + struct lfs2_tortoise_t tortoise = { + .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}, + .i = 1, + .period = 1, + }; while (!lfs2_pair_isnull(dir.tail)) { - // detect cycles with Brent's algorithm - if (lfs2_pair_issync(dir.tail, tortoise)) { - LFS2_WARN("Cycle detected in tail list"); - err = LFS2_ERR_CORRUPT; + err = lfs2_tortoise_detectcycles(&dir, &tortoise); + if (err < 0) { goto cleanup; } - if (tortoise_i == tortoise_period) { - tortoise[0] = dir.tail[0]; - tortoise[1] = dir.tail[1]; - tortoise_i = 0; - tortoise_period *= 2; - } - tortoise_i += 1; // fetch next block in tail list lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, &dir, dir.tail, @@ -4394,6 +4545,7 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { // found older minor version? set an in-device only bit in the // gstate so we know we need to rewrite the superblock before // the first write + bool needssuperblock = false; if (minor_version < lfs2_fs_disk_version_minor(lfs2)) { LFS2_DEBUG("Found older minor version " "v%"PRIu16".%"PRIu16" < v%"PRIu16".%"PRIu16, @@ -4401,10 +4553,11 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { minor_version, lfs2_fs_disk_version_major(lfs2), lfs2_fs_disk_version_minor(lfs2)); - // note this bit is reserved on disk, so fetching more gstate - // will not interfere here - lfs2_fs_prepsuperblock(lfs2, true); + needssuperblock = true; } + // note this bit is reserved on disk, so fetching more gstate + // will not interfere here + lfs2_fs_prepsuperblock(lfs2, needssuperblock); // check superblock configuration if (superblock.name_max) { @@ -4438,6 +4591,9 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { } lfs2->attr_max = superblock.attr_max; + + // we also need to update inline_max in case attr_max changed + lfs2->inline_max = lfs2_min(lfs2->inline_max, lfs2->attr_max); } // this is where we get the block_count from disk if block_count=0 @@ -4478,23 +4634,23 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { // setup free lookahead, to distribute allocations uniformly across // boots, we start the allocator at a random location - lfs2->free.off = lfs2->seed % lfs2->block_count; + lfs2->lookahead.start = lfs2->seed % lfs2->block_count; lfs2_alloc_drop(lfs2); return 0; cleanup: - lfs2_rawunmount(lfs2); + lfs2_unmount_(lfs2); return err; } -static int lfs2_rawunmount(lfs2_t *lfs2) { +static int lfs2_unmount_(lfs2_t *lfs2) { return lfs2_deinit(lfs2); } /// Filesystem filesystem operations /// -static int lfs2_fs_rawstat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) { +static int lfs2_fs_stat_(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) { // if the superblock is up-to-date, we must be on the most recent // minor version of littlefs if (!lfs2_gstate_needssuperblock(&lfs2->gstate)) { @@ -4534,7 +4690,7 @@ static int lfs2_fs_rawstat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) { return 0; } -int lfs2_fs_rawtraverse(lfs2_t *lfs2, +int lfs2_fs_traverse_(lfs2_t *lfs2, int (*cb)(void *data, lfs2_block_t block), void *data, bool includeorphans) { // iterate over metadata pairs @@ -4553,22 +4709,17 @@ int lfs2_fs_rawtraverse(lfs2_t *lfs2, } #endif - lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; - lfs2_size_t tortoise_i = 1; - lfs2_size_t tortoise_period = 1; + struct lfs2_tortoise_t tortoise = { + .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}, + .i = 1, + .period = 1, + }; + int err = LFS2_ERR_OK; while (!lfs2_pair_isnull(dir.tail)) { - // detect cycles with Brent's algorithm - if (lfs2_pair_issync(dir.tail, tortoise)) { - LFS2_WARN("Cycle detected in tail list"); + err = lfs2_tortoise_detectcycles(&dir, &tortoise); + if (err < 0) { return LFS2_ERR_CORRUPT; } - if (tortoise_i == tortoise_period) { - tortoise[0] = dir.tail[0]; - tortoise[1] = dir.tail[1]; - tortoise_i = 0; - tortoise_period *= 2; - } - tortoise_i += 1; for (int i = 0; i < 2; i++) { int err = cb(data, dir.tail[i]); @@ -4647,22 +4798,17 @@ static int lfs2_fs_pred(lfs2_t *lfs2, // iterate over all directory directory entries pdir->tail[0] = 0; pdir->tail[1] = 1; - lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; - lfs2_size_t tortoise_i = 1; - lfs2_size_t tortoise_period = 1; + struct lfs2_tortoise_t tortoise = { + .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}, + .i = 1, + .period = 1, + }; + int err = LFS2_ERR_OK; while (!lfs2_pair_isnull(pdir->tail)) { - // detect cycles with Brent's algorithm - if (lfs2_pair_issync(pdir->tail, tortoise)) { - LFS2_WARN("Cycle detected in tail list"); + err = lfs2_tortoise_detectcycles(pdir, &tortoise); + if (err < 0) { return LFS2_ERR_CORRUPT; } - if (tortoise_i == tortoise_period) { - tortoise[0] = pdir->tail[0]; - tortoise[1] = pdir->tail[1]; - tortoise_i = 0; - tortoise_period *= 2; - } - tortoise_i += 1; if (lfs2_pair_cmp(pdir->tail, pair) == 0) { return 0; @@ -4712,22 +4858,17 @@ static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t pair[2], // use fetchmatch with callback to find pairs parent->tail[0] = 0; parent->tail[1] = 1; - lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; - lfs2_size_t tortoise_i = 1; - lfs2_size_t tortoise_period = 1; + struct lfs2_tortoise_t tortoise = { + .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}, + .i = 1, + .period = 1, + }; + int err = LFS2_ERR_OK; while (!lfs2_pair_isnull(parent->tail)) { - // detect cycles with Brent's algorithm - if (lfs2_pair_issync(parent->tail, tortoise)) { - LFS2_WARN("Cycle detected in tail list"); - return LFS2_ERR_CORRUPT; - } - if (tortoise_i == tortoise_period) { - tortoise[0] = parent->tail[0]; - tortoise[1] = parent->tail[1]; - tortoise_i = 0; - tortoise_period *= 2; + err = lfs2_tortoise_detectcycles(parent, &tortoise); + if (err < 0) { + return err; } - tortoise_i += 1; lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, parent, parent->tail, LFS2_MKTAG(0x7ff, 0, 0x3ff), @@ -4999,7 +5140,7 @@ static int lfs2_fs_forceconsistency(lfs2_t *lfs2) { #endif #ifndef LFS2_READONLY -static int lfs2_fs_rawmkconsistent(lfs2_t *lfs2) { +static int lfs2_fs_mkconsistent_(lfs2_t *lfs2) { // lfs2_fs_forceconsistency does most of the work here int err = lfs2_fs_forceconsistency(lfs2); if (err) { @@ -5035,9 +5176,9 @@ static int lfs2_fs_size_count(void *p, lfs2_block_t block) { return 0; } -static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2) { +static lfs2_ssize_t lfs2_fs_size_(lfs2_t *lfs2) { lfs2_size_t size = 0; - int err = lfs2_fs_rawtraverse(lfs2, lfs2_fs_size_count, &size, false); + int err = lfs2_fs_traverse_(lfs2, lfs2_fs_size_count, &size, false); if (err) { return err; } @@ -5045,41 +5186,118 @@ static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2) { return size; } +// explicit garbage collection #ifndef LFS2_READONLY -static int lfs2_fs_rawgrow(lfs2_t *lfs2, lfs2_size_t block_count) { - // shrinking is not supported - LFS2_ASSERT(block_count >= lfs2->block_count); +static int lfs2_fs_gc_(lfs2_t *lfs2) { + // force consistency, even if we're not necessarily going to write, + // because this function is supposed to take care of janitorial work + // isn't it? + int err = lfs2_fs_forceconsistency(lfs2); + if (err) { + return err; + } - if (block_count > lfs2->block_count) { - lfs2->block_count = block_count; + // try to compact metadata pairs, note we can't really accomplish + // anything if compact_thresh doesn't at least leave a prog_size + // available + if (lfs2->cfg->compact_thresh + < lfs2->cfg->block_size - lfs2->cfg->prog_size) { + // iterate over all mdirs + lfs2_mdir_t mdir = {.tail = {0, 1}}; + while (!lfs2_pair_isnull(mdir.tail)) { + err = lfs2_dir_fetch(lfs2, &mdir, mdir.tail); + if (err) { + return err; + } - // fetch the root - lfs2_mdir_t root; - int err = lfs2_dir_fetch(lfs2, &root, lfs2->root); + // not erased? exceeds our compaction threshold? + if (!mdir.erased || ((lfs2->cfg->compact_thresh == 0) + ? mdir.off > lfs2->cfg->block_size - lfs2->cfg->block_size/8 + : mdir.off > lfs2->cfg->compact_thresh)) { + // the easiest way to trigger a compaction is to mark + // the mdir as unerased and add an empty commit + mdir.erased = false; + err = lfs2_dir_commit(lfs2, &mdir, NULL, 0); + if (err) { + return err; + } + } + } + } + + // try to populate the lookahead buffer, unless it's already full + if (lfs2->lookahead.size < lfs2_min( + 8 * lfs2->cfg->lookahead_size, + lfs2->block_count)) { + err = lfs2_alloc_scan(lfs2); if (err) { return err; } + } - // update the superblock - lfs2_superblock_t superblock; - lfs2_stag_t tag = lfs2_dir_get(lfs2, &root, LFS2_MKTAG(0x7ff, 0x3ff, 0), - LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), - &superblock); - if (tag < 0) { - return tag; - } - lfs2_superblock_fromle32(&superblock); + return 0; +} +#endif - superblock.block_count = lfs2->block_count; +#ifndef LFS2_READONLY +#ifdef LFS2_SHRINKNONRELOCATING +static int lfs2_shrink_checkblock(void *data, lfs2_block_t block) { + lfs2_size_t threshold = *((lfs2_size_t*)data); + if (block >= threshold) { + return LFS2_ERR_NOTEMPTY; + } + return 0; +} +#endif - lfs2_superblock_tole32(&superblock); - err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS( - {tag, &superblock})); +static int lfs2_fs_grow_(lfs2_t *lfs2, lfs2_size_t block_count) { + int err; + + if (block_count == lfs2->block_count) { + return 0; + } + + +#ifndef LFS2_SHRINKNONRELOCATING + // shrinking is not supported + LFS2_ASSERT(block_count >= lfs2->block_count); +#endif +#ifdef LFS2_SHRINKNONRELOCATING + if (block_count < lfs2->block_count) { + err = lfs2_fs_traverse_(lfs2, lfs2_shrink_checkblock, &block_count, true); if (err) { return err; } } +#endif + + lfs2->block_count = block_count; + // fetch the root + lfs2_mdir_t root; + err = lfs2_dir_fetch(lfs2, &root, lfs2->root); + if (err) { + return err; + } + + // update the superblock + lfs2_superblock_t superblock; + lfs2_stag_t tag = lfs2_dir_get(lfs2, &root, LFS2_MKTAG(0x7ff, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), + &superblock); + if (tag < 0) { + return tag; + } + lfs2_superblock_fromle32(&superblock); + + superblock.block_count = lfs2->block_count; + + lfs2_superblock_tole32(&superblock); + err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS( + {tag, &superblock})); + if (err) { + return err; + } return 0; } #endif @@ -5451,10 +5669,10 @@ static int lfs21_mount(lfs2_t *lfs2, struct lfs21 *lfs21, lfs2->lfs21->root[1] = LFS2_BLOCK_NULL; // setup free lookahead - lfs2->free.off = 0; - lfs2->free.size = 0; - lfs2->free.i = 0; - lfs2_alloc_ack(lfs2); + lfs2->lookahead.start = 0; + lfs2->lookahead.size = 0; + lfs2->lookahead.next = 0; + lfs2_alloc_ckpoint(lfs2); // load superblock lfs21_dir_t dir; @@ -5505,7 +5723,7 @@ static int lfs21_unmount(lfs2_t *lfs2) { } /// v1 migration /// -static int lfs2_rawmigrate(lfs2_t *lfs2, const struct lfs2_config *cfg) { +static int lfs2_migrate_(lfs2_t *lfs2, const struct lfs2_config *cfg) { struct lfs21 lfs21; // Indeterminate filesystem size not allowed for migration. @@ -5759,7 +5977,7 @@ int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) { ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", " - ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " + ".block_cycles=%"PRId32", .cache_size=%"PRIu32", " ".lookahead_size=%"PRIu32", .read_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " @@ -5772,7 +5990,7 @@ int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) { cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, cfg->name_max, cfg->file_max, cfg->attr_max); - err = lfs2_rawformat(lfs2, cfg); + err = lfs2_format_(lfs2, cfg); LFS2_TRACE("lfs2_format -> %d", err); LFS2_UNLOCK(cfg); @@ -5789,7 +6007,7 @@ int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) { ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", " - ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " + ".block_cycles=%"PRId32", .cache_size=%"PRIu32", " ".lookahead_size=%"PRIu32", .read_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " @@ -5802,7 +6020,7 @@ int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) { cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, cfg->name_max, cfg->file_max, cfg->attr_max); - err = lfs2_rawmount(lfs2, cfg); + err = lfs2_mount_(lfs2, cfg); LFS2_TRACE("lfs2_mount -> %d", err); LFS2_UNLOCK(cfg); @@ -5816,7 +6034,7 @@ int lfs2_unmount(lfs2_t *lfs2) { } LFS2_TRACE("lfs2_unmount(%p)", (void*)lfs2); - err = lfs2_rawunmount(lfs2); + err = lfs2_unmount_(lfs2); LFS2_TRACE("lfs2_unmount -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5831,7 +6049,7 @@ int lfs2_remove(lfs2_t *lfs2, const char *path) { } LFS2_TRACE("lfs2_remove(%p, \"%s\")", (void*)lfs2, path); - err = lfs2_rawremove(lfs2, path); + err = lfs2_remove_(lfs2, path); LFS2_TRACE("lfs2_remove -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5847,7 +6065,7 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) { } LFS2_TRACE("lfs2_rename(%p, \"%s\", \"%s\")", (void*)lfs2, oldpath, newpath); - err = lfs2_rawrename(lfs2, oldpath, newpath); + err = lfs2_rename_(lfs2, oldpath, newpath); LFS2_TRACE("lfs2_rename -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5862,7 +6080,7 @@ int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) { } LFS2_TRACE("lfs2_stat(%p, \"%s\", %p)", (void*)lfs2, path, (void*)info); - err = lfs2_rawstat(lfs2, path, info); + err = lfs2_stat_(lfs2, path, info); LFS2_TRACE("lfs2_stat -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5878,7 +6096,7 @@ lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path, LFS2_TRACE("lfs2_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", (void*)lfs2, path, type, buffer, size); - lfs2_ssize_t res = lfs2_rawgetattr(lfs2, path, type, buffer, size); + lfs2_ssize_t res = lfs2_getattr_(lfs2, path, type, buffer, size); LFS2_TRACE("lfs2_getattr -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -5895,7 +6113,7 @@ int lfs2_setattr(lfs2_t *lfs2, const char *path, LFS2_TRACE("lfs2_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", (void*)lfs2, path, type, buffer, size); - err = lfs2_rawsetattr(lfs2, path, type, buffer, size); + err = lfs2_setattr_(lfs2, path, type, buffer, size); LFS2_TRACE("lfs2_setattr -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5911,7 +6129,7 @@ int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type) { } LFS2_TRACE("lfs2_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs2, path, type); - err = lfs2_rawremoveattr(lfs2, path, type); + err = lfs2_removeattr_(lfs2, path, type); LFS2_TRACE("lfs2_removeattr -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5926,10 +6144,10 @@ int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags) return err; } LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)", - (void*)lfs2, (void*)file, path, flags); + (void*)lfs2, (void*)file, path, (unsigned)flags); LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawopen(lfs2, file, path, flags); + err = lfs2_file_open_(lfs2, file, path, flags); LFS2_TRACE("lfs2_file_open -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5946,11 +6164,11 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file, } LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {" ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})", - (void*)lfs2, (void*)file, path, flags, + (void*)lfs2, (void*)file, path, (unsigned)flags, (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count); LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawopencfg(lfs2, file, path, flags, cfg); + err = lfs2_file_opencfg_(lfs2, file, path, flags, cfg); LFS2_TRACE("lfs2_file_opencfg -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5965,7 +6183,7 @@ int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_close(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawclose(lfs2, file); + err = lfs2_file_close_(lfs2, file); LFS2_TRACE("lfs2_file_close -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5981,7 +6199,7 @@ int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_sync(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawsync(lfs2, file); + err = lfs2_file_sync_(lfs2, file); LFS2_TRACE("lfs2_file_sync -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5999,7 +6217,7 @@ lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file, (void*)lfs2, (void*)file, buffer, size); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_ssize_t res = lfs2_file_rawread(lfs2, file, buffer, size); + lfs2_ssize_t res = lfs2_file_read_(lfs2, file, buffer, size); LFS2_TRACE("lfs2_file_read -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6017,7 +6235,7 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file, (void*)lfs2, (void*)file, buffer, size); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_ssize_t res = lfs2_file_rawwrite(lfs2, file, buffer, size); + lfs2_ssize_t res = lfs2_file_write_(lfs2, file, buffer, size); LFS2_TRACE("lfs2_file_write -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6035,7 +6253,7 @@ lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file, (void*)lfs2, (void*)file, off, whence); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, off, whence); + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, off, whence); LFS2_TRACE("lfs2_file_seek -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6052,7 +6270,7 @@ int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) { (void*)lfs2, (void*)file, size); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawtruncate(lfs2, file, size); + err = lfs2_file_truncate_(lfs2, file, size); LFS2_TRACE("lfs2_file_truncate -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6068,7 +6286,7 @@ lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_tell(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_soff_t res = lfs2_file_rawtell(lfs2, file); + lfs2_soff_t res = lfs2_file_tell_(lfs2, file); LFS2_TRACE("lfs2_file_tell -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6082,7 +6300,7 @@ int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file) { } LFS2_TRACE("lfs2_file_rewind(%p, %p)", (void*)lfs2, (void*)file); - err = lfs2_file_rawrewind(lfs2, file); + err = lfs2_file_rewind_(lfs2, file); LFS2_TRACE("lfs2_file_rewind -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6097,9 +6315,9 @@ lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_size(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_soff_t res = lfs2_file_rawsize(lfs2, file); + lfs2_soff_t res = lfs2_file_size_(lfs2, file); - LFS2_TRACE("lfs2_file_size -> %"PRId32, res); + LFS2_TRACE("lfs2_file_size -> %"PRIu32, res); LFS2_UNLOCK(lfs2->cfg); return res; } @@ -6112,7 +6330,7 @@ int lfs2_mkdir(lfs2_t *lfs2, const char *path) { } LFS2_TRACE("lfs2_mkdir(%p, \"%s\")", (void*)lfs2, path); - err = lfs2_rawmkdir(lfs2, path); + err = lfs2_mkdir_(lfs2, path); LFS2_TRACE("lfs2_mkdir -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6128,7 +6346,7 @@ int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { LFS2_TRACE("lfs2_dir_open(%p, %p, \"%s\")", (void*)lfs2, (void*)dir, path); LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)dir)); - err = lfs2_dir_rawopen(lfs2, dir, path); + err = lfs2_dir_open_(lfs2, dir, path); LFS2_TRACE("lfs2_dir_open -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6142,7 +6360,7 @@ int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir) { } LFS2_TRACE("lfs2_dir_close(%p, %p)", (void*)lfs2, (void*)dir); - err = lfs2_dir_rawclose(lfs2, dir); + err = lfs2_dir_close_(lfs2, dir); LFS2_TRACE("lfs2_dir_close -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6157,7 +6375,7 @@ int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) { LFS2_TRACE("lfs2_dir_read(%p, %p, %p)", (void*)lfs2, (void*)dir, (void*)info); - err = lfs2_dir_rawread(lfs2, dir, info); + err = lfs2_dir_read_(lfs2, dir, info); LFS2_TRACE("lfs2_dir_read -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6172,7 +6390,7 @@ int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { LFS2_TRACE("lfs2_dir_seek(%p, %p, %"PRIu32")", (void*)lfs2, (void*)dir, off); - err = lfs2_dir_rawseek(lfs2, dir, off); + err = lfs2_dir_seek_(lfs2, dir, off); LFS2_TRACE("lfs2_dir_seek -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6186,7 +6404,7 @@ lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir) { } LFS2_TRACE("lfs2_dir_tell(%p, %p)", (void*)lfs2, (void*)dir); - lfs2_soff_t res = lfs2_dir_rawtell(lfs2, dir); + lfs2_soff_t res = lfs2_dir_tell_(lfs2, dir); LFS2_TRACE("lfs2_dir_tell -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6200,7 +6418,7 @@ int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir) { } LFS2_TRACE("lfs2_dir_rewind(%p, %p)", (void*)lfs2, (void*)dir); - err = lfs2_dir_rawrewind(lfs2, dir); + err = lfs2_dir_rewind_(lfs2, dir); LFS2_TRACE("lfs2_dir_rewind -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6214,7 +6432,7 @@ int lfs2_fs_stat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) { } LFS2_TRACE("lfs2_fs_stat(%p, %p)", (void*)lfs2, (void*)fsinfo); - err = lfs2_fs_rawstat(lfs2, fsinfo); + err = lfs2_fs_stat_(lfs2, fsinfo); LFS2_TRACE("lfs2_fs_stat -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6228,7 +6446,7 @@ lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2) { } LFS2_TRACE("lfs2_fs_size(%p)", (void*)lfs2); - lfs2_ssize_t res = lfs2_fs_rawsize(lfs2); + lfs2_ssize_t res = lfs2_fs_size_(lfs2); LFS2_TRACE("lfs2_fs_size -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6243,7 +6461,7 @@ int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void *, lfs2_block_t), void *data) LFS2_TRACE("lfs2_fs_traverse(%p, %p, %p)", (void*)lfs2, (void*)(uintptr_t)cb, data); - err = lfs2_fs_rawtraverse(lfs2, cb, data, true); + err = lfs2_fs_traverse_(lfs2, cb, data, true); LFS2_TRACE("lfs2_fs_traverse -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6251,32 +6469,32 @@ int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void *, lfs2_block_t), void *data) } #ifndef LFS2_READONLY -int lfs2_fs_gc(lfs2_t *lfs2) { +int lfs2_fs_mkconsistent(lfs2_t *lfs2) { int err = LFS2_LOCK(lfs2->cfg); if (err) { return err; } - LFS2_TRACE("lfs2_fs_gc(%p)", (void*)lfs2); + LFS2_TRACE("lfs2_fs_mkconsistent(%p)", (void*)lfs2); - err = lfs2_fs_rawgc(lfs2); + err = lfs2_fs_mkconsistent_(lfs2); - LFS2_TRACE("lfs2_fs_gc -> %d", err); + LFS2_TRACE("lfs2_fs_mkconsistent -> %d", err); LFS2_UNLOCK(lfs2->cfg); return err; } #endif #ifndef LFS2_READONLY -int lfs2_fs_mkconsistent(lfs2_t *lfs2) { +int lfs2_fs_gc(lfs2_t *lfs2) { int err = LFS2_LOCK(lfs2->cfg); if (err) { return err; } - LFS2_TRACE("lfs2_fs_mkconsistent(%p)", (void*)lfs2); + LFS2_TRACE("lfs2_fs_gc(%p)", (void*)lfs2); - err = lfs2_fs_rawmkconsistent(lfs2); + err = lfs2_fs_gc_(lfs2); - LFS2_TRACE("lfs2_fs_mkconsistent -> %d", err); + LFS2_TRACE("lfs2_fs_gc -> %d", err); LFS2_UNLOCK(lfs2->cfg); return err; } @@ -6290,7 +6508,7 @@ int lfs2_fs_grow(lfs2_t *lfs2, lfs2_size_t block_count) { } LFS2_TRACE("lfs2_fs_grow(%p, %"PRIu32")", (void*)lfs2, block_count); - err = lfs2_fs_rawgrow(lfs2, block_count); + err = lfs2_fs_grow_(lfs2, block_count); LFS2_TRACE("lfs2_fs_grow -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6308,7 +6526,7 @@ int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) { ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", " - ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " + ".block_cycles=%"PRId32", .cache_size=%"PRIu32", " ".lookahead_size=%"PRIu32", .read_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " @@ -6321,7 +6539,7 @@ int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) { cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, cfg->name_max, cfg->file_max, cfg->attr_max); - err = lfs2_rawmigrate(lfs2, cfg); + err = lfs2_migrate_(lfs2, cfg); LFS2_TRACE("lfs2_migrate -> %d", err); LFS2_UNLOCK(cfg); diff --git a/lib/littlefs/lfs2.h b/lib/littlefs/lfs2.h index 559ccebac92..aee0619e932 100644 --- a/lib/littlefs/lfs2.h +++ b/lib/littlefs/lfs2.h @@ -21,7 +21,7 @@ extern "C" // Software library version // Major (top-nibble), incremented on backwards incompatible changes // Minor (bottom-nibble), incremented on feature additions -#define LFS2_VERSION 0x00020008 +#define LFS2_VERSION 0x0002000b #define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16)) #define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0)) @@ -52,16 +52,15 @@ typedef uint32_t lfs2_block_t; #endif // Maximum size of a file in bytes, may be redefined to limit to support other -// drivers. Limited on disk to <= 4294967296. However, above 2147483647 the -// functions lfs2_file_seek, lfs2_file_size, and lfs2_file_tell will return -// incorrect values due to using signed integers. Stored in superblock and -// must be respected by other littlefs drivers. +// drivers. Limited on disk to <= 2147483647. Stored in superblock and must be +// respected by other littlefs drivers. #ifndef LFS2_FILE_MAX #define LFS2_FILE_MAX 2147483647 #endif // Maximum size of custom attributes in bytes, may be redefined, but there is -// no real benefit to using a smaller LFS2_ATTR_MAX. Limited to <= 1022. +// no real benefit to using a smaller LFS2_ATTR_MAX. Limited to <= 1022. Stored +// in superblock and must be respected by other littlefs drivers. #ifndef LFS2_ATTR_MAX #define LFS2_ATTR_MAX 1022 #endif @@ -205,7 +204,8 @@ struct lfs2_config { // program sizes. lfs2_size_t block_size; - // Number of erasable blocks on the device. + // Number of erasable blocks on the device. Defaults to block_count stored + // on disk when zero. lfs2_size_t block_count; // Number of erase cycles before littlefs evicts metadata logs and moves @@ -226,9 +226,20 @@ struct lfs2_config { // Size of the lookahead buffer in bytes. A larger lookahead buffer // increases the number of blocks found during an allocation pass. The // lookahead buffer is stored as a compact bitmap, so each byte of RAM - // can track 8 blocks. Must be a multiple of 8. + // can track 8 blocks. lfs2_size_t lookahead_size; + // Threshold for metadata compaction during lfs2_fs_gc in bytes. Metadata + // pairs that exceed this threshold will be compacted during lfs2_fs_gc. + // Defaults to ~88% block_size when zero, though the default may change + // in the future. + // + // Note this only affects lfs2_fs_gc. Normal compactions still only occur + // when full. + // + // Set to -1 to disable metadata compaction during lfs2_fs_gc. + lfs2_size_t compact_thresh; + // Optional statically allocated read buffer. Must be cache_size. // By default lfs2_malloc is used to allocate this buffer. void *read_buffer; @@ -237,25 +248,24 @@ struct lfs2_config { // By default lfs2_malloc is used to allocate this buffer. void *prog_buffer; - // Optional statically allocated lookahead buffer. Must be lookahead_size - // and aligned to a 32-bit boundary. By default lfs2_malloc is used to - // allocate this buffer. + // Optional statically allocated lookahead buffer. Must be lookahead_size. + // By default lfs2_malloc is used to allocate this buffer. void *lookahead_buffer; // Optional upper limit on length of file names in bytes. No downside for // larger names except the size of the info struct which is controlled by - // the LFS2_NAME_MAX define. Defaults to LFS2_NAME_MAX when zero. Stored in - // superblock and must be respected by other littlefs drivers. + // the LFS2_NAME_MAX define. Defaults to LFS2_NAME_MAX or name_max stored on + // disk when zero. lfs2_size_t name_max; // Optional upper limit on files in bytes. No downside for larger files - // but must be <= LFS2_FILE_MAX. Defaults to LFS2_FILE_MAX when zero. Stored - // in superblock and must be respected by other littlefs drivers. + // but must be <= LFS2_FILE_MAX. Defaults to LFS2_FILE_MAX or file_max stored + // on disk when zero. lfs2_size_t file_max; // Optional upper limit on custom attributes in bytes. No downside for // larger attributes size but must be <= LFS2_ATTR_MAX. Defaults to - // LFS2_ATTR_MAX when zero. + // LFS2_ATTR_MAX or attr_max stored on disk when zero. lfs2_size_t attr_max; // Optional upper limit on total space given to metadata pairs in bytes. On @@ -264,6 +274,15 @@ struct lfs2_config { // Defaults to block_size when zero. lfs2_size_t metadata_max; + // Optional upper limit on inlined files in bytes. Inlined files live in + // metadata and decrease storage requirements, but may be limited to + // improve metadata-related performance. Must be <= cache_size, <= + // attr_max, and <= block_size/8. Defaults to the largest possible + // inline_max when zero. + // + // Set to -1 to disable inlined files. + lfs2_size_t inline_max; + #ifdef LFS2_MULTIVERSION // On-disk version to use when writing in the form of 16-bit major version // + 16-bit minor version. This limiting metadata to what is supported by @@ -430,19 +449,20 @@ typedef struct lfs2 { lfs2_gstate_t gdisk; lfs2_gstate_t gdelta; - struct lfs2_free { - lfs2_block_t off; + struct lfs2_lookahead { + lfs2_block_t start; lfs2_block_t size; - lfs2_block_t i; - lfs2_block_t ack; - uint32_t *buffer; - } free; + lfs2_block_t next; + lfs2_block_t ckpoint; + uint8_t *buffer; + } lookahead; const struct lfs2_config *cfg; lfs2_size_t block_count; lfs2_size_t name_max; lfs2_size_t file_max; lfs2_size_t attr_max; + lfs2_size_t inline_max; #ifdef LFS2_MIGRATE struct lfs21 *lfs21; @@ -712,18 +732,6 @@ lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2); // Returns a negative error code on failure. int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data); -// Attempt to proactively find free blocks -// -// Calling this function is not required, but may allowing the offloading of -// the expensive block allocation scan to a less time-critical code path. -// -// Note: littlefs currently does not persist any found free blocks to disk. -// This may change in the future. -// -// Returns a negative error code on failure. Finding no free blocks is -// not an error. -int lfs2_fs_gc(lfs2_t *lfs2); - #ifndef LFS2_READONLY // Attempt to make the filesystem consistent and ready for writing // @@ -736,11 +744,33 @@ int lfs2_fs_gc(lfs2_t *lfs2); int lfs2_fs_mkconsistent(lfs2_t *lfs2); #endif +#ifndef LFS2_READONLY +// Attempt any janitorial work +// +// This currently: +// 1. Calls mkconsistent if not already consistent +// 2. Compacts metadata > compact_thresh +// 3. Populates the block allocator +// +// Though additional janitorial work may be added in the future. +// +// Calling this function is not required, but may allow the offloading of +// expensive janitorial work to a less time-critical code path. +// +// Returns a negative error code on failure. Accomplishing nothing is not +// an error. +int lfs2_fs_gc(lfs2_t *lfs2); +#endif + #ifndef LFS2_READONLY // Grows the filesystem to a new size, updating the superblock with the new // block count. // -// Note: This is irreversible. +// If LFS2_SHRINKNONRELOCATING is defined, this function will also accept +// block_counts smaller than the current configuration, after checking +// that none of the blocks that are being removed are in use. +// Note that littlefs's pseudorandom block allocation means that +// this is very unlikely to work in the general case. // // Returns a negative error code on failure. int lfs2_fs_grow(lfs2_t *lfs2, lfs2_size_t block_count); diff --git a/lib/littlefs/lfs2_util.c b/lib/littlefs/lfs2_util.c index c9850e78869..4fe7e5340ce 100644 --- a/lib/littlefs/lfs2_util.c +++ b/lib/littlefs/lfs2_util.c @@ -11,6 +11,8 @@ #ifndef LFS2_CONFIG +// If user provides their own CRC impl we don't need this +#ifndef LFS2_CRC // Software CRC implementation with small lookup table uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) { static const uint32_t rtable[16] = { @@ -29,6 +31,7 @@ uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) { return crc; } +#endif #endif diff --git a/lib/littlefs/lfs2_util.h b/lib/littlefs/lfs2_util.h index dd2cbcc106d..12c82a630b0 100644 --- a/lib/littlefs/lfs2_util.h +++ b/lib/littlefs/lfs2_util.h @@ -8,6 +8,9 @@ #ifndef LFS2_UTIL_H #define LFS2_UTIL_H +#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x) +#define LFS2_STRINGIZE2(x) #x + // Users can override lfs2_util.h with their own configuration by defining // LFS2_CONFIG as a header file to include (-DLFS2_CONFIG=lfs2_config.h). // @@ -15,11 +18,26 @@ // provided by the config file. To start, I would suggest copying lfs2_util.h // and modifying as needed. #ifdef LFS2_CONFIG -#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x) -#define LFS2_STRINGIZE2(x) #x #include LFS2_STRINGIZE(LFS2_CONFIG) #else +// Alternatively, users can provide a header file which defines +// macros and other things consumed by littlefs. +// +// For example, provide my_defines.h, which contains +// something like: +// +// #include +// extern void *my_malloc(size_t sz); +// #define LFS2_MALLOC(sz) my_malloc(sz) +// +// And build littlefs with the header by defining LFS2_DEFINES. +// (-DLFS2_DEFINES=my_defines.h) + +#ifdef LFS2_DEFINES +#include LFS2_STRINGIZE(LFS2_DEFINES) +#endif + // System includes #include #include @@ -177,10 +195,10 @@ static inline uint32_t lfs2_fromle32(uint32_t a) { (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) return __builtin_bswap32(a); #else - return (((uint8_t*)&a)[0] << 0) | - (((uint8_t*)&a)[1] << 8) | - (((uint8_t*)&a)[2] << 16) | - (((uint8_t*)&a)[3] << 24); + return ((uint32_t)((uint8_t*)&a)[0] << 0) | + ((uint32_t)((uint8_t*)&a)[1] << 8) | + ((uint32_t)((uint8_t*)&a)[2] << 16) | + ((uint32_t)((uint8_t*)&a)[3] << 24); #endif } @@ -200,10 +218,10 @@ static inline uint32_t lfs2_frombe32(uint32_t a) { (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) return a; #else - return (((uint8_t*)&a)[0] << 24) | - (((uint8_t*)&a)[1] << 16) | - (((uint8_t*)&a)[2] << 8) | - (((uint8_t*)&a)[3] << 0); + return ((uint32_t)((uint8_t*)&a)[0] << 24) | + ((uint32_t)((uint8_t*)&a)[1] << 16) | + ((uint32_t)((uint8_t*)&a)[2] << 8) | + ((uint32_t)((uint8_t*)&a)[3] << 0); #endif } @@ -212,12 +230,22 @@ static inline uint32_t lfs2_tobe32(uint32_t a) { } // Calculate CRC-32 with polynomial = 0x04c11db7 +#ifdef LFS2_CRC +static inline uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) { + return LFS2_CRC(crc, buffer, size); +} +#else uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size); +#endif // Allocate memory, only used if buffers are not provided to littlefs -// Note, memory must be 64-bit aligned +// +// littlefs current has no alignment requirements, as it only allocates +// byte-level buffers. static inline void *lfs2_malloc(size_t size) { -#ifndef LFS2_NO_MALLOC +#if defined(LFS2_MALLOC) + return LFS2_MALLOC(size); +#elif !defined(LFS2_NO_MALLOC) return malloc(size); #else (void)size; @@ -227,7 +255,9 @@ static inline void *lfs2_malloc(size_t size) { // Deallocate memory, only used if buffers are not provided to littlefs static inline void lfs2_free(void *p) { -#ifndef LFS2_NO_MALLOC +#if defined(LFS2_FREE) + LFS2_FREE(p); +#elif !defined(LFS2_NO_MALLOC) free(p); #else (void)p; diff --git a/lib/mbedtls_config/crt_bundle.c b/lib/mbedtls_config/crt_bundle.c index 9c546a26883..4a8836fb586 100644 --- a/lib/mbedtls_config/crt_bundle.c +++ b/lib/mbedtls_config/crt_bundle.c @@ -74,12 +74,14 @@ static int crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_b } + #if MBEDTLS_VERSION_MAJOR < 4 // Fast check to avoid expensive computations when not necessary if (!mbedtls_pk_can_do(&parent.pk, child->MBEDTLS_PRIVATE(sig_pk))) { LOGE(TAG, "Simple compare failed"); ret = -1; goto cleanup; } + #endif md_info = mbedtls_md_info_from_type(child->MBEDTLS_PRIVATE(sig_md)); if ((ret = mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash)) != 0) { @@ -87,10 +89,17 @@ static int crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_b goto cleanup; } + #if MBEDTLS_VERSION_MAJOR >= 4 + if ((ret = mbedtls_pk_verify_ext( + child->MBEDTLS_PRIVATE(sig_pk), &parent.pk, + child->MBEDTLS_PRIVATE(sig_md), hash, mbedtls_md_get_size(md_info), + child->MBEDTLS_PRIVATE(sig).p, child->MBEDTLS_PRIVATE(sig).len)) != 0) { + #else if ((ret = mbedtls_pk_verify_ext( child->MBEDTLS_PRIVATE(sig_pk), child->MBEDTLS_PRIVATE(sig_opts), &parent.pk, child->MBEDTLS_PRIVATE(sig_md), hash, mbedtls_md_get_size(md_info), child->MBEDTLS_PRIVATE(sig).p, child->MBEDTLS_PRIVATE(sig).len)) != 0) { + #endif LOGE(TAG, "PK verify failed with error %X", ret); goto cleanup; diff --git a/lib/micropython-lib b/lib/micropython-lib index 5b496e944ec..6ae440a8a14 160000 --- a/lib/micropython-lib +++ b/lib/micropython-lib @@ -1 +1 @@ -Subproject commit 5b496e944ec045177afa1620920a168410b7f60b +Subproject commit 6ae440a8a144233e6e703f6759b7e7a0afaa37a4 diff --git a/lib/protomatter b/lib/protomatter index f83bac7e421..425b6c7f887 160000 --- a/lib/protomatter +++ b/lib/protomatter @@ -1 +1 @@ -Subproject commit f83bac7e421077812523fddb83d3e25f29753315 +Subproject commit 425b6c7f887cca5d24d768d8c80c74ba7eb88dc6 diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 0a776db93db..117b3053610 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -78,6 +78,11 @@ msgid "" "%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d" msgstr "" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "" @@ -99,6 +104,7 @@ msgid "%q contains duplicate pins" msgstr "" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "" @@ -112,6 +118,7 @@ msgstr "" #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -133,7 +140,9 @@ msgid "%q indices must be integers, not %s" msgstr "" #: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: ports/stm/common-hal/audioio/AudioOut.c #: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "" @@ -165,8 +174,8 @@ msgstr "" msgid "%q must be %d" msgstr "" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -177,6 +186,20 @@ msgstr "" msgid "%q must be 1 when %q is True" msgstr "" +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 16, 24, or 32" +msgstr "" + +#: ports/espressif/common-hal/audioi2sin/I2SIn.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 8 or 16" +msgstr "" + +#: ports/espressif/common-hal/audiobusio/PDMIn.c +#: shared-bindings/audioi2sin/I2SIn.c +msgid "%q must be 8, 16, 24, or 32" +msgstr "" + #: py/argcheck.c shared-bindings/gifio/GifWriter.c #: shared-module/gifio/OnDiskGif.c msgid "%q must be <= %d" @@ -259,10 +282,6 @@ msgstr "" msgid "%q out of range" msgstr "" -#: py/objmodule.c -msgid "%q renamed %q" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -458,6 +477,7 @@ msgstr "" msgid ", in %q\n" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -476,7 +496,7 @@ msgstr "" msgid "AP could not be started" msgstr "" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "" @@ -610,6 +630,10 @@ msgstr "" msgid "Async SPI transfer in progress on this bus, keep awaiting." msgstr "" +#: shared-bindings/usb_audio/__init__.c +msgid "At least one of microphone and speaker must be enabled" +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -621,6 +645,7 @@ msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Audio source error" msgstr "" @@ -646,12 +671,14 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" @@ -668,16 +695,12 @@ msgstr "" msgid "Both RX and TX required for flow control" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "" @@ -720,10 +743,6 @@ msgstr "" msgid "Bus pin %d is already in use" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "" - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "" @@ -765,9 +784,9 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" -#: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c -#: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c -#: shared-bindings/usb_video/__init__.c +#: shared-bindings/storage/__init__.c shared-bindings/usb_audio/__init__.c +#: shared-bindings/usb_cdc/__init__.c shared-bindings/usb_hid/__init__.c +#: shared-bindings/usb_midi/__init__.c shared-bindings/usb_video/__init__.c msgid "Cannot change USB devices now" msgstr "" @@ -804,7 +823,7 @@ msgstr "" msgid "Cannot pull on input-only pin." msgstr "" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Cannot record to a file" msgstr "" @@ -864,7 +883,7 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" -#: shared-module/usb/core/Device.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c msgid "Could not allocate DMA capable buffer" msgstr "" @@ -890,10 +909,12 @@ msgid "Critical ROS failure during soft reboot, reset required: %d" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Channel Init Error" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Device Init Error" msgstr "" @@ -924,7 +945,7 @@ msgstr "" msgid "Deep sleep pins must use a rising edge with pulldown" msgstr "" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" @@ -965,8 +986,17 @@ msgstr "" msgid "ECB only operates on 16 bytes at a time" msgstr "" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "" @@ -1031,10 +1061,12 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" @@ -1144,6 +1176,7 @@ msgstr "" msgid "Generic Failure" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1242,7 +1275,8 @@ msgstr "" msgid "Internal define error" msgstr "" -#: shared-bindings/pwmio/PWMOut.c supervisor/shared/settings.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "" @@ -1298,6 +1332,7 @@ msgstr "" msgid "Invalid %q" msgstr "" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1331,6 +1366,10 @@ msgstr "" msgid "Invalid ROS domain ID" msgstr "" +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "" @@ -1421,6 +1460,14 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "" +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap must have 8 bits per pixel" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap size must match the other bitmaps" +msgstr "" + #: py/persistentcode.c msgid "MicroPython .mpy file; use CircuitPython mpy-cross" msgstr "" @@ -1513,7 +1560,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "" @@ -1524,6 +1571,7 @@ msgstr "" #: ports/atmel-samd/common-hal/analogio/AnalogOut.c #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "No DAC on chip" msgstr "" @@ -1531,6 +1579,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "" @@ -1645,7 +1694,8 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c +#: shared-bindings/usb_audio/USBMicrophone.c msgid "Not playing" msgstr "" @@ -1742,6 +1792,7 @@ msgid "Operation or feature not supported" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "" @@ -1784,6 +1835,7 @@ msgid "Parameter error" msgstr "" #: ports/espressif/common-hal/audiobusio/__init__.c +#: ports/espressif/common-hal/audioi2sin/I2SIn.c msgid "Peripheral in use" msgstr "" @@ -2063,10 +2115,13 @@ msgstr "" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c -#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -2103,7 +2158,7 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiocore/__init__.c +#: shared-module/audiocore/__init__.c shared-module/usb_audio/USBMicrophone.c msgid "The sample's %q does not match" msgstr "" @@ -2158,6 +2213,7 @@ msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2240,10 +2296,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "" @@ -2260,6 +2312,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2400,6 +2453,7 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c #: ports/zephyr-cp/common-hal/busio/I2C.c #: ports/zephyr-cp/common-hal/busio/SPI.c #: ports/zephyr-cp/common-hal/busio/UART.c @@ -2615,10 +2669,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2675,10 +2725,6 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" -#: ports/espressif/common-hal/audiobusio/PDMIn.c -msgid "bit_depth must be 8, 16, 24, or 32." -msgstr "" - #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2832,6 +2878,10 @@ msgstr "" msgid "can't create '%q' instances" msgstr "" +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2930,14 +2980,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -3072,6 +3122,10 @@ msgstr "" msgid "destination buffer must be an array of type 'H' for bit_depth = 16" msgstr "" +#: shared-bindings/usb_audio/USBSpeaker.c +msgid "destination must be an array of type 'h'" +msgstr "" + #: py/objdict.c msgid "dict update sequence has wrong length" msgstr "" @@ -3092,7 +3146,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -3231,10 +3285,6 @@ msgstr "" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" @@ -3316,10 +3366,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3386,10 +3432,6 @@ msgstr "" msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3480,6 +3522,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3493,6 +3539,11 @@ msgstr "" msgid "invalid cert" msgstr "" +#: shared-bindings/audioi2sin/I2SIn.c +#, c-format +msgid "invalid destination buffer, must be an array of type: %c" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element size %d for bits_per_pixel %d\n" @@ -3674,6 +3725,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3722,10 +3777,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3747,7 +3798,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -4036,7 +4087,7 @@ msgstr "" msgid "output array must be contiguous" msgstr "" -#: py/objint_mpz.c +#: py/objint_longlong.c py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -4045,10 +4096,6 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" -msgstr "" - #: py/emitinlinerv32.c msgid "parameters must be registers in sequence a0 to a3" msgstr "" @@ -4106,6 +4153,10 @@ msgstr "" msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -4115,6 +4166,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -4379,10 +4434,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4404,10 +4455,6 @@ msgstr "" msgid "unindent doesn't match any outer indent level" msgstr "" -#: py/emitinlinerv32.c -msgid "unknown RV32 instruction '%q'" -msgstr "" - #: py/objstr.c #, c-format msgid "unknown conversion specifier %c" diff --git a/locale/cs.po b/locale/cs.po index 24dc4292753..e4a09a220ee 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -89,6 +89,11 @@ msgid "" "%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d" msgstr "%d adresní pin, %d rgb pin a %d dlaždice indikuje výšku %d, ne %d" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q a %q obsahují duplicitní piny" @@ -110,6 +115,7 @@ msgid "%q contains duplicate pins" msgstr "%q obsahuje duplicitní piny" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q: selhání %d" @@ -123,6 +129,7 @@ msgstr "%q v %q musí být typu %q, ne %q" #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -144,7 +151,9 @@ msgid "%q indices must be integers, not %s" msgstr "Indexy %q musí být celá čísla, nikoli %s" #: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: ports/stm/common-hal/audioio/AudioOut.c #: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "Inicializace %q selhala" @@ -176,8 +185,8 @@ msgstr "Délka %q musí být >= %d" msgid "%q must be %d" msgstr "%q musí být %d" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -188,6 +197,20 @@ msgstr "%q musí být %d-%d" msgid "%q must be 1 when %q is True" msgstr "%q musí být 1, pokud %q je True" +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 16, 24, or 32" +msgstr "" + +#: ports/espressif/common-hal/audioi2sin/I2SIn.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 8 or 16" +msgstr "" + +#: ports/espressif/common-hal/audiobusio/PDMIn.c +#: shared-bindings/audioi2sin/I2SIn.c +msgid "%q must be 8, 16, 24, or 32" +msgstr "" + #: py/argcheck.c shared-bindings/gifio/GifWriter.c #: shared-module/gifio/OnDiskGif.c msgid "%q must be <= %d" @@ -270,10 +293,6 @@ msgstr "%q je mimo hranice" msgid "%q out of range" msgstr "%q je mimo rozsah" -#: py/objmodule.c -msgid "%q renamed %q" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q krok nemůže být nula" @@ -469,6 +488,7 @@ msgstr "∗x musí být cíl přiřazení" msgid ", in %q\n" msgstr ", v% q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -487,7 +507,7 @@ msgstr "pow() nepodporuje 3 argumenty" msgid "AP could not be started" msgstr "AP nemohl být spuštěn" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "Adresa musí být %d bajtů dlouhá" @@ -621,6 +641,10 @@ msgstr "Hodnoty pole by měly být jednoduché bajty." msgid "Async SPI transfer in progress on this bus, keep awaiting." msgstr "" +#: shared-bindings/usb_audio/__init__.c +msgid "At least one of microphone and speaker must be enabled" +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -632,6 +656,7 @@ msgstr "Konverze audia není implementována" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Audio source error" msgstr "" @@ -659,12 +684,14 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "Baudrate není podporován periférií" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" msgstr "Pod minimální obnovovací frekvencí" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" @@ -681,16 +708,12 @@ msgstr "Bootovací zařízení musí být první (rozhraní #0)." msgid "Both RX and TX required for flow control" msgstr "RX a TX jsou vyžadovány pro kontrolu toku" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "Jas není nastavitelný" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Vyrovnávací paměť + offset je příliš malý %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "Prvky bufferu musí být 4 bajty dlouhé nebo méně" @@ -733,10 +756,6 @@ msgstr "Buffer příliš malý" msgid "Bus pin %d is already in use" msgstr "Sběrnicový pin %d je již používán" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "Buffer musí být dlouhý 16 bajtů." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "Bloky CBC musí být násobky 16 bajtů" @@ -781,9 +800,9 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "Nelze nastavit CCCD na místní charakteristiku" -#: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c -#: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c -#: shared-bindings/usb_video/__init__.c +#: shared-bindings/storage/__init__.c shared-bindings/usb_audio/__init__.c +#: shared-bindings/usb_cdc/__init__.c shared-bindings/usb_hid/__init__.c +#: shared-bindings/usb_midi/__init__.c shared-bindings/usb_video/__init__.c msgid "Cannot change USB devices now" msgstr "Nelze změnit USB zařízení" @@ -820,7 +839,7 @@ msgstr "" msgid "Cannot pull on input-only pin." msgstr "Nelze aktivovat pull rezistor na pinu, který je pouze pro vstup." -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Cannot record to a file" msgstr "Nelze nahrávat do souboru" @@ -881,7 +900,7 @@ msgstr "Pole souřadnic mají různé délky" msgid "Coordinate arrays types have different sizes" msgstr "" -#: shared-module/usb/core/Device.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c msgid "Could not allocate DMA capable buffer" msgstr "" @@ -907,10 +926,12 @@ msgid "Critical ROS failure during soft reboot, reset required: %d" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Channel Init Error" msgstr "Chyba inicializace kanálu DAC" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Device Init Error" msgstr "Chyba inicializace zařízení DAC" @@ -942,7 +963,7 @@ msgid "Deep sleep pins must use a rising edge with pulldown" msgstr "" "Piny pro hluboký spánek musí používat náběžnou hranu s pulldown rezistorem" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Destination capacity is smaller than destination_length." msgstr "Cílová kapacita je menší než destination_length." @@ -983,8 +1004,17 @@ msgstr "Při zpracování uvedené výjimky nastala další výjimka:" msgid "ECB only operates on 16 bytes at a time" msgstr "ECB operuje najednou pouze 16 bajtů" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "ESP-IDF alokace paměti selhala" @@ -1049,10 +1079,12 @@ msgstr "Nepodařilo se nabufferovat sample" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "Připojení se nezdařilo: interní chyba" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Nepodařilo se připojit: časový limit" @@ -1164,6 +1196,7 @@ msgstr "Inicializace GNSS" msgid "Generic Failure" msgstr "Základní chyba" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1262,7 +1295,8 @@ msgstr "Interní audio buffer je příliš malý" msgid "Internal define error" msgstr "" -#: shared-bindings/pwmio/PWMOut.c supervisor/shared/settings.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "Interní chyba" @@ -1318,6 +1352,7 @@ msgstr "" msgid "Invalid %q" msgstr "Špatný %s" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1351,6 +1386,10 @@ msgstr "Chybná MAC adresa" msgid "Invalid ROS domain ID" msgstr "" +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Neplatný argument" @@ -1441,6 +1480,14 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "" +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap must have 8 bits per pixel" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap size must match the other bitmaps" +msgstr "" + #: py/persistentcode.c msgid "MicroPython .mpy file; use CircuitPython mpy-cross" msgstr "" @@ -1533,7 +1580,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "Žádný %q pin" @@ -1544,6 +1591,7 @@ msgstr "Žádné CCCD pro tuto charakteristiku" #: ports/atmel-samd/common-hal/analogio/AnalogOut.c #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "No DAC on chip" msgstr "Žádný DAC na čipu" @@ -1551,6 +1599,7 @@ msgstr "Žádný DAC na čipu" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "Nebyl nalezen žádný kanál DMA" @@ -1665,7 +1714,8 @@ msgid "Not connected" msgstr "Nepřipojený" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c +#: shared-bindings/usb_audio/USBMicrophone.c msgid "Not playing" msgstr "Nehraje" @@ -1763,6 +1813,7 @@ msgid "Operation or feature not supported" msgstr "Operace nebo funkce není podporována" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "Časový limit operace vypršel" @@ -1805,6 +1856,7 @@ msgid "Parameter error" msgstr "" #: ports/espressif/common-hal/audiobusio/__init__.c +#: ports/espressif/common-hal/audioi2sin/I2SIn.c msgid "Peripheral in use" msgstr "Periférie je používána" @@ -2086,10 +2138,13 @@ msgstr "" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c -#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool je možné použít pouze s wifi.radio" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "Zdrojové a cílové buffery musí být stejné délky" @@ -2126,7 +2181,7 @@ msgstr "Výše uvedená výjimka byla přímá příčina následující výjimk msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "Počet prvků rgb_pin musí být 6, 12, 18, 24, nebo 30" -#: shared-module/audiocore/__init__.c +#: shared-module/audiocore/__init__.c shared-module/usb_audio/USBMicrophone.c msgid "The sample's %q does not match" msgstr "" @@ -2181,6 +2236,7 @@ msgid "Too many channels in sample" msgstr "V samplu je příliš mnoho kanálů" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2264,10 +2320,6 @@ msgstr "USB zařízení používají příliš mnoho názvů rozhraní." msgid "USB error" msgstr "Chyba USB" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "UUID integer musí být 0-0xffff" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "UUID řetězec neodpovídá 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" @@ -2284,6 +2336,7 @@ msgstr "Nelze přistupovat k nezarovnanému IO registru" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2424,6 +2477,7 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c #: ports/zephyr-cp/common-hal/busio/I2C.c #: ports/zephyr-cp/common-hal/busio/SPI.c #: ports/zephyr-cp/common-hal/busio/UART.c @@ -2644,10 +2698,6 @@ msgstr "pole je příliš velké" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "přetečení v asm" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2704,10 +2754,6 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" -#: ports/espressif/common-hal/audiobusio/PDMIn.c -msgid "bit_depth must be 8, 16, 24, or 32." -msgstr "" - #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2861,6 +2907,10 @@ msgstr "" msgid "can't create '%q' instances" msgstr "" +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2959,14 +3009,14 @@ msgstr "nelze převést complex na dtype" msgid "cannot convert complex type" msgstr "nelze převést typ complex" -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "nelze smazat prvky pole" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "nelze změnit rozměry pole" @@ -3101,6 +3151,10 @@ msgstr "" msgid "destination buffer must be an array of type 'H' for bit_depth = 16" msgstr "" +#: shared-bindings/usb_audio/USBSpeaker.c +msgid "destination must be an array of type 'h'" +msgstr "" + #: py/objdict.c msgid "dict update sequence has wrong length" msgstr "" @@ -3121,7 +3175,7 @@ msgstr "dimenze nesouhlasí" msgid "div/mod not implemented for uint" msgstr "div/mod nejsou implementované pro uint" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "dělení nulou" @@ -3260,10 +3314,6 @@ msgstr "" msgid "float unsupported" msgstr "float není podporován" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" @@ -3345,10 +3395,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "generátor způsobil StopIteration" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "hash je konečný" @@ -3415,10 +3461,6 @@ msgstr "" msgid "initial values must be iterable" msgstr "výchozí hodnoty musí být iterovatelné" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "délka initial_value je chybná" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3509,6 +3551,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3522,6 +3568,11 @@ msgstr "chybné bits_per_pixel %d, musí být 1, 2, 4, 8, 16, 24, or 32" msgid "invalid cert" msgstr "špatný certifikár" +#: shared-bindings/audioi2sin/I2SIn.c +#, c-format +msgid "invalid destination buffer, must be an array of type: %c" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element size %d for bits_per_pixel %d\n" @@ -3703,6 +3754,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3751,10 +3806,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3776,7 +3827,7 @@ msgstr "záporný faktoriál" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -4065,7 +4116,7 @@ msgstr "" msgid "output array must be contiguous" msgstr "" -#: py/objint_mpz.c +#: py/objint_longlong.c py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -4074,10 +4125,6 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" -msgstr "" - #: py/emitinlinerv32.c msgid "parameters must be registers in sequence a0 to a3" msgstr "" @@ -4135,6 +4182,10 @@ msgstr "" msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -4144,6 +4195,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -4408,10 +4463,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "neočekávané odsazení" @@ -4433,10 +4484,6 @@ msgstr "" msgid "unindent doesn't match any outer indent level" msgstr "" -#: py/emitinlinerv32.c -msgid "unknown RV32 instruction '%q'" -msgstr "" - #: py/objstr.c #, c-format msgid "unknown conversion specifier %c" @@ -4605,6 +4652,22 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "asm overflow" +#~ msgstr "přetečení v asm" + +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Vyrovnávací paměť + offset je příliš malý %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "Buffer musí být dlouhý 16 bajtů." + +#~ msgid "UUID integer value must be 0-0xffff" +#~ msgstr "UUID integer musí být 0-0xffff" + +#~ msgid "initial_value length is wrong" +#~ msgstr "délka initial_value je chybná" + #, c-format #~ msgid "Invalid byte %.*s" #~ msgstr "Špatný byte %.*s" diff --git a/locale/el.po b/locale/el.po index 016fb3a381e..f4294d794a8 100644 --- a/locale/el.po +++ b/locale/el.po @@ -93,6 +93,11 @@ msgid "" msgstr "" "%d pin διεύθυνσης, %d rgb ping και %d πλακίδια αναδεικνύουν ύψος %d, όχι %d" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q και %q περιέχουν διπλότυπα pins" @@ -114,6 +119,7 @@ msgid "%q contains duplicate pins" msgstr "%q περιέχει διπλότυπα pins" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q αποτυχία: %d" @@ -127,6 +133,7 @@ msgstr "%q στο %q πρέπει να είναι τύπου %q, όχι %q" #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -148,7 +155,9 @@ msgid "%q indices must be integers, not %s" msgstr "%q δείκτες πρέπει να είναι ακέραιοι, όχι %s" #: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: ports/stm/common-hal/audioio/AudioOut.c #: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "%q εκκίνηση απέτυχε" @@ -180,8 +189,8 @@ msgstr "%q μήκος πρέπει να είναι >= %d" msgid "%q must be %d" msgstr "%q πρέπει να είναι %d" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -192,6 +201,20 @@ msgstr "%q πρέπει να είναι %d-%d" msgid "%q must be 1 when %q is True" msgstr "%q πρέπει να είναι 1 όταν %q είναι True" +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 16, 24, or 32" +msgstr "" + +#: ports/espressif/common-hal/audioi2sin/I2SIn.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 8 or 16" +msgstr "" + +#: ports/espressif/common-hal/audiobusio/PDMIn.c +#: shared-bindings/audioi2sin/I2SIn.c +msgid "%q must be 8, 16, 24, or 32" +msgstr "" + #: py/argcheck.c shared-bindings/gifio/GifWriter.c #: shared-module/gifio/OnDiskGif.c msgid "%q must be <= %d" @@ -274,10 +297,6 @@ msgstr "%q εκτός ορίων" msgid "%q out of range" msgstr "%q εκτός εμβέλειας" -#: py/objmodule.c -msgid "%q renamed %q" -msgstr "%q μεταονομάστηκε σε %q" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q βήμα δεν μπορεί να είναι μηδέν" @@ -473,6 +492,7 @@ msgstr "*x πρέπει να είναι στόχος ανάθεσης" msgid ", in %q\n" msgstr ", στο %q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -491,7 +511,7 @@ msgstr "pow() με 3 παραμέτρους δεν υποστηρίζεται" msgid "AP could not be started" msgstr "AP δεν μπόρεσε να εκκινηθεί" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "Η διεύθυνση πρέπει να είναι %d bytes μεγάλη" @@ -625,6 +645,10 @@ msgstr "Η τιμές της παράταξη πρέπει να είναι μο msgid "Async SPI transfer in progress on this bus, keep awaiting." msgstr "" +#: shared-bindings/usb_audio/__init__.c +msgid "At least one of microphone and speaker must be enabled" +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -636,6 +660,7 @@ msgstr "Η μετατροπή ήχου δεν υποστηρίζεται" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Audio source error" msgstr "" @@ -663,12 +688,14 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "Baudrate δεν υποστηρίζεται από την περιφεριακή συσκευή" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" msgstr "Χαμηλότερο από το ελάχιστο frame rate" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c msgid "Bit clock and word select must be sequential GPIO pins" msgstr "Ρολόι bit και ορισμού λέξης πρέπει να είναι διαδοχικά GPIO pins" @@ -685,16 +712,12 @@ msgstr "Η συσκευή εκκίνησης πρέπει να επιλεχθε msgid "Both RX and TX required for flow control" msgstr "Και RX και TX απαιτούνται για έλεγχο flow" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "H φωτεινότητα δεν μπορεί να προσαρμοστεί" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Buffer + offset είναι πολύ μικρά %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "Στοιχεία του buffer πρέπει να είναι το πολύ 4 bytes" @@ -737,10 +760,6 @@ msgstr "Buffer πολύ μικρός" msgid "Bus pin %d is already in use" msgstr "Bus pin %d είναι ήδη σε χρήση" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "Byte buffer πρέπει να είναι 16 bytes." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "CBC blocks πρέπει να είναι πολλαπλάσια του 16 bytes" @@ -783,9 +802,9 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "Δεν μπορεί να οριστεί CCCD σε τοπικό Characteristic" -#: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c -#: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c -#: shared-bindings/usb_video/__init__.c +#: shared-bindings/storage/__init__.c shared-bindings/usb_audio/__init__.c +#: shared-bindings/usb_cdc/__init__.c shared-bindings/usb_hid/__init__.c +#: shared-bindings/usb_midi/__init__.c shared-bindings/usb_video/__init__.c msgid "Cannot change USB devices now" msgstr "Δεν μπορούν να αλλάξουν οι USB συσκευές τώρα" @@ -825,7 +844,7 @@ msgstr "" msgid "Cannot pull on input-only pin." msgstr "Δεν γίνεται pull σε pin μόνο για εισόδο." -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Cannot record to a file" msgstr "Δεν μπορεί να γίνει καταγραφή σε αρχείο" @@ -887,7 +906,7 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" -#: shared-module/usb/core/Device.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c msgid "Could not allocate DMA capable buffer" msgstr "" @@ -913,10 +932,12 @@ msgid "Critical ROS failure during soft reboot, reset required: %d" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Channel Init Error" msgstr "Σφάλμα εκκίνησης καναλιού DAC" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Device Init Error" msgstr "Σφάλμα εκκίνησης συσκευής DAC" @@ -947,7 +968,7 @@ msgstr "Τα δεδομένα είναι πολύ μεγάλα για πακέτ msgid "Deep sleep pins must use a rising edge with pulldown" msgstr "Τα pins βαθύ ύπνου πρέπει να χρησιμοποιούν rising edge με pulldown" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" "Το μέγεθος προορισμού πρέπει να είναι μικρότερο από το destination_length." @@ -991,8 +1012,17 @@ msgstr "" msgid "ECB only operates on 16 bytes at a time" msgstr "ECB δουλεύει μόνο σε 16 bytes κάθε φορά" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "ESP-IDF δέσμευση μνήμης απέτυχε" @@ -1057,10 +1087,12 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" @@ -1170,6 +1202,7 @@ msgstr "" msgid "Generic Failure" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1268,7 +1301,8 @@ msgstr "" msgid "Internal define error" msgstr "" -#: shared-bindings/pwmio/PWMOut.c supervisor/shared/settings.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "" @@ -1324,6 +1358,7 @@ msgstr "" msgid "Invalid %q" msgstr "" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1357,6 +1392,10 @@ msgstr "" msgid "Invalid ROS domain ID" msgstr "" +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "" @@ -1447,6 +1486,14 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "" +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap must have 8 bits per pixel" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap size must match the other bitmaps" +msgstr "" + #: py/persistentcode.c msgid "MicroPython .mpy file; use CircuitPython mpy-cross" msgstr "" @@ -1539,7 +1586,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "" @@ -1550,6 +1597,7 @@ msgstr "" #: ports/atmel-samd/common-hal/analogio/AnalogOut.c #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "No DAC on chip" msgstr "" @@ -1557,6 +1605,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "" @@ -1671,7 +1720,8 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c +#: shared-bindings/usb_audio/USBMicrophone.c msgid "Not playing" msgstr "" @@ -1768,6 +1818,7 @@ msgid "Operation or feature not supported" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "" @@ -1810,6 +1861,7 @@ msgid "Parameter error" msgstr "" #: ports/espressif/common-hal/audiobusio/__init__.c +#: ports/espressif/common-hal/audioi2sin/I2SIn.c msgid "Peripheral in use" msgstr "" @@ -2091,10 +2143,13 @@ msgstr "" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c -#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -2131,7 +2186,7 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiocore/__init__.c +#: shared-module/audiocore/__init__.c shared-module/usb_audio/USBMicrophone.c msgid "The sample's %q does not match" msgstr "" @@ -2186,6 +2241,7 @@ msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2268,10 +2324,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "" @@ -2288,6 +2340,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2428,6 +2481,7 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c #: ports/zephyr-cp/common-hal/busio/I2C.c #: ports/zephyr-cp/common-hal/busio/SPI.c #: ports/zephyr-cp/common-hal/busio/UART.c @@ -2643,10 +2697,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2703,10 +2753,6 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" -#: ports/espressif/common-hal/audiobusio/PDMIn.c -msgid "bit_depth must be 8, 16, 24, or 32." -msgstr "" - #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2860,6 +2906,10 @@ msgstr "" msgid "can't create '%q' instances" msgstr "" +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2958,14 +3008,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -3100,6 +3150,10 @@ msgstr "" msgid "destination buffer must be an array of type 'H' for bit_depth = 16" msgstr "" +#: shared-bindings/usb_audio/USBSpeaker.c +msgid "destination must be an array of type 'h'" +msgstr "" + #: py/objdict.c msgid "dict update sequence has wrong length" msgstr "" @@ -3120,7 +3174,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -3259,10 +3313,6 @@ msgstr "" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" @@ -3344,10 +3394,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3414,10 +3460,6 @@ msgstr "" msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3508,6 +3550,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3521,6 +3567,11 @@ msgstr "" msgid "invalid cert" msgstr "" +#: shared-bindings/audioi2sin/I2SIn.c +#, c-format +msgid "invalid destination buffer, must be an array of type: %c" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element size %d for bits_per_pixel %d\n" @@ -3702,6 +3753,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3750,10 +3805,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3775,7 +3826,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -4064,7 +4115,7 @@ msgstr "" msgid "output array must be contiguous" msgstr "" -#: py/objint_mpz.c +#: py/objint_longlong.c py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -4073,10 +4124,6 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" -msgstr "" - #: py/emitinlinerv32.c msgid "parameters must be registers in sequence a0 to a3" msgstr "" @@ -4134,6 +4181,10 @@ msgstr "" msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -4143,6 +4194,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -4407,10 +4462,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4432,10 +4483,6 @@ msgstr "" msgid "unindent doesn't match any outer indent level" msgstr "" -#: py/emitinlinerv32.c -msgid "unknown RV32 instruction '%q'" -msgstr "" - #: py/objstr.c #, c-format msgid "unknown conversion specifier %c" @@ -4604,6 +4651,16 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "%q renamed %q" +#~ msgstr "%q μεταονομάστηκε σε %q" + +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Buffer + offset είναι πολύ μικρά %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "Byte buffer πρέπει να είναι 16 bytes." + #~ msgid "%q moved from %q to %q" #~ msgstr "%q μετακινήθηκε από το %q στο %q" diff --git a/locale/en_GB.po b/locale/en_GB.po index 8d640a3c680..29380c91c80 100644 --- a/locale/en_GB.po +++ b/locale/en_GB.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-06-15 23:04+0000\n" +"PO-Revision-Date: 2026-04-30 11:09+0000\n" "Last-Translator: Andi Chandler \n" "Language-Team: none\n" "Language: en_GB\n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.12-dev\n" +"X-Generator: Weblate 5.17.1\n" #: main.c msgid "" @@ -527,7 +527,7 @@ msgstr "All channels in use" #: ports/raspberrypi/common-hal/usb_host/Port.c msgid "All dma channels in use" -msgstr "All DMA channels in use" +msgstr "All dma channels in use" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "All event channels in use" diff --git a/locale/es.po b/locale/es.po index 85a03408b75..87589c2c28b 100644 --- a/locale/es.po +++ b/locale/es.po @@ -8,15 +8,15 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2025-08-03 08:01+0000\n" -"Last-Translator: MAE \n" +"PO-Revision-Date: 2026-05-06 18:11+0000\n" +"Last-Translator: Francisco Serrador \n" "Language-Team: \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.13-dev\n" +"X-Generator: Weblate 5.17.1\n" #: main.c msgid "" @@ -614,7 +614,6 @@ msgid "Array values should be single bytes." msgstr "Valores del array deben ser bytes individuales." #: ports/atmel-samd/common-hal/spitarget/SPITarget.c -#, fuzzy msgid "Async SPI transfer in progress on this bus, keep awaiting." msgstr "" "Transferencia SPI asíncrona en curso en este canal, manténgase esperando." @@ -1064,9 +1063,8 @@ msgid "Failed to create continuous channels: not found" msgstr "Error al crear canales continuos: no encontrado" #: ports/espressif/common-hal/audioio/AudioOut.c -#, fuzzy msgid "Failed to enable continuous" -msgstr "Fallo habilitando continous" +msgstr "Ha fallado al habilitar continuo" #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" @@ -1912,9 +1910,8 @@ msgid "Program too long" msgstr "El programa es demasiado grande" #: shared-bindings/rclcpy/Publisher.c -#, fuzzy msgid "Publishers can only be created from a parent node" -msgstr "Publicadores solo pueden ser creados desde un nodo padre" +msgstr "Las publicadores solo pueden ser creadas desde un nodo antecesor" #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." @@ -2170,9 +2167,8 @@ msgid "Tile width must exactly divide bitmap width" msgstr "Ancho del Tile debe dividir exactamente el ancho de mapa de bits" #: shared-module/tilepalettemapper/TilePaletteMapper.c -#, fuzzy msgid "TilePaletteMapper may only be bound to a TileGrid once" -msgstr "Tilepalettemapper sólo puede vincularse una vez a un TileGrid" +msgstr "TilePaletteMapper solo puede vincularse una vez a un TileGrid" #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." diff --git a/locale/hi.po b/locale/hi.po index be00c7cf1c9..21b28028a29 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -80,6 +80,11 @@ msgid "" "%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d" msgstr "" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "" @@ -101,6 +106,7 @@ msgid "%q contains duplicate pins" msgstr "" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "" @@ -114,6 +120,7 @@ msgstr "" #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -135,7 +142,9 @@ msgid "%q indices must be integers, not %s" msgstr "" #: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: ports/stm/common-hal/audioio/AudioOut.c #: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "" @@ -167,8 +176,8 @@ msgstr "" msgid "%q must be %d" msgstr "" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -179,6 +188,20 @@ msgstr "" msgid "%q must be 1 when %q is True" msgstr "" +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 16, 24, or 32" +msgstr "" + +#: ports/espressif/common-hal/audioi2sin/I2SIn.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 8 or 16" +msgstr "" + +#: ports/espressif/common-hal/audiobusio/PDMIn.c +#: shared-bindings/audioi2sin/I2SIn.c +msgid "%q must be 8, 16, 24, or 32" +msgstr "" + #: py/argcheck.c shared-bindings/gifio/GifWriter.c #: shared-module/gifio/OnDiskGif.c msgid "%q must be <= %d" @@ -261,10 +284,6 @@ msgstr "" msgid "%q out of range" msgstr "" -#: py/objmodule.c -msgid "%q renamed %q" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -460,6 +479,7 @@ msgstr "" msgid ", in %q\n" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -478,7 +498,7 @@ msgstr "" msgid "AP could not be started" msgstr "" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "" @@ -612,6 +632,10 @@ msgstr "" msgid "Async SPI transfer in progress on this bus, keep awaiting." msgstr "" +#: shared-bindings/usb_audio/__init__.c +msgid "At least one of microphone and speaker must be enabled" +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -623,6 +647,7 @@ msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Audio source error" msgstr "" @@ -648,12 +673,14 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" @@ -670,16 +697,12 @@ msgstr "" msgid "Both RX and TX required for flow control" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "" @@ -722,10 +745,6 @@ msgstr "" msgid "Bus pin %d is already in use" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "" - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "" @@ -767,9 +786,9 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" -#: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c -#: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c -#: shared-bindings/usb_video/__init__.c +#: shared-bindings/storage/__init__.c shared-bindings/usb_audio/__init__.c +#: shared-bindings/usb_cdc/__init__.c shared-bindings/usb_hid/__init__.c +#: shared-bindings/usb_midi/__init__.c shared-bindings/usb_video/__init__.c msgid "Cannot change USB devices now" msgstr "" @@ -806,7 +825,7 @@ msgstr "" msgid "Cannot pull on input-only pin." msgstr "" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Cannot record to a file" msgstr "" @@ -866,7 +885,7 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" -#: shared-module/usb/core/Device.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c msgid "Could not allocate DMA capable buffer" msgstr "" @@ -892,10 +911,12 @@ msgid "Critical ROS failure during soft reboot, reset required: %d" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Channel Init Error" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Device Init Error" msgstr "" @@ -926,7 +947,7 @@ msgstr "" msgid "Deep sleep pins must use a rising edge with pulldown" msgstr "" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" @@ -967,8 +988,17 @@ msgstr "" msgid "ECB only operates on 16 bytes at a time" msgstr "" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "" @@ -1033,10 +1063,12 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" @@ -1146,6 +1178,7 @@ msgstr "" msgid "Generic Failure" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1244,7 +1277,8 @@ msgstr "" msgid "Internal define error" msgstr "" -#: shared-bindings/pwmio/PWMOut.c supervisor/shared/settings.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "" @@ -1300,6 +1334,7 @@ msgstr "" msgid "Invalid %q" msgstr "" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1333,6 +1368,10 @@ msgstr "" msgid "Invalid ROS domain ID" msgstr "" +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "" @@ -1423,6 +1462,14 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "" +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap must have 8 bits per pixel" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap size must match the other bitmaps" +msgstr "" + #: py/persistentcode.c msgid "MicroPython .mpy file; use CircuitPython mpy-cross" msgstr "" @@ -1515,7 +1562,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "" @@ -1526,6 +1573,7 @@ msgstr "" #: ports/atmel-samd/common-hal/analogio/AnalogOut.c #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "No DAC on chip" msgstr "" @@ -1533,6 +1581,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "" @@ -1647,7 +1696,8 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c +#: shared-bindings/usb_audio/USBMicrophone.c msgid "Not playing" msgstr "" @@ -1744,6 +1794,7 @@ msgid "Operation or feature not supported" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "" @@ -1786,6 +1837,7 @@ msgid "Parameter error" msgstr "" #: ports/espressif/common-hal/audiobusio/__init__.c +#: ports/espressif/common-hal/audioi2sin/I2SIn.c msgid "Peripheral in use" msgstr "" @@ -2065,10 +2117,13 @@ msgstr "" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c -#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -2105,7 +2160,7 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiocore/__init__.c +#: shared-module/audiocore/__init__.c shared-module/usb_audio/USBMicrophone.c msgid "The sample's %q does not match" msgstr "" @@ -2160,6 +2215,7 @@ msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2242,10 +2298,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "" @@ -2262,6 +2314,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2402,6 +2455,7 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c #: ports/zephyr-cp/common-hal/busio/I2C.c #: ports/zephyr-cp/common-hal/busio/SPI.c #: ports/zephyr-cp/common-hal/busio/UART.c @@ -2617,10 +2671,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2677,10 +2727,6 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" -#: ports/espressif/common-hal/audiobusio/PDMIn.c -msgid "bit_depth must be 8, 16, 24, or 32." -msgstr "" - #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2834,6 +2880,10 @@ msgstr "" msgid "can't create '%q' instances" msgstr "" +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2932,14 +2982,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -3074,6 +3124,10 @@ msgstr "" msgid "destination buffer must be an array of type 'H' for bit_depth = 16" msgstr "" +#: shared-bindings/usb_audio/USBSpeaker.c +msgid "destination must be an array of type 'h'" +msgstr "" + #: py/objdict.c msgid "dict update sequence has wrong length" msgstr "" @@ -3094,7 +3148,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -3233,10 +3287,6 @@ msgstr "" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" @@ -3318,10 +3368,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3388,10 +3434,6 @@ msgstr "" msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3482,6 +3524,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3495,6 +3541,11 @@ msgstr "" msgid "invalid cert" msgstr "" +#: shared-bindings/audioi2sin/I2SIn.c +#, c-format +msgid "invalid destination buffer, must be an array of type: %c" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element size %d for bits_per_pixel %d\n" @@ -3676,6 +3727,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3724,10 +3779,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3749,7 +3800,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -4038,7 +4089,7 @@ msgstr "" msgid "output array must be contiguous" msgstr "" -#: py/objint_mpz.c +#: py/objint_longlong.c py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -4047,10 +4098,6 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" -msgstr "" - #: py/emitinlinerv32.c msgid "parameters must be registers in sequence a0 to a3" msgstr "" @@ -4108,6 +4155,10 @@ msgstr "" msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -4117,6 +4168,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -4381,10 +4436,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4406,10 +4457,6 @@ msgstr "" msgid "unindent doesn't match any outer indent level" msgstr "" -#: py/emitinlinerv32.c -msgid "unknown RV32 instruction '%q'" -msgstr "" - #: py/objstr.c #, c-format msgid "unknown conversion specifier %c" diff --git a/locale/ko.po b/locale/ko.po index 8e96781ed27..4789c8a566b 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -91,6 +91,11 @@ msgid "" msgstr "" "%d 주소 핀들, %d rgb 핀들과 %d 타일 들은 높이가 %d임을 나타낸다, %d가 아니라" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q 및 %q에 중복된 핀이 포함" @@ -112,6 +117,7 @@ msgid "%q contains duplicate pins" msgstr "%q에 중복된 핀이 포함" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q 실패: %d" @@ -125,6 +131,7 @@ msgstr "%q의 %q는 %q가 아니라 %q 유형이어야 합니다" #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -146,7 +153,9 @@ msgid "%q indices must be integers, not %s" msgstr "%q 인덱스는 %s 가 아닌 정수 여야합니다" #: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: ports/stm/common-hal/audioio/AudioOut.c #: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "%q 초기화 실패" @@ -178,8 +187,8 @@ msgstr "%q 길이는 >= %d이어야 합니다" msgid "%q must be %d" msgstr "%q는 %d이어야 합니다" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -190,6 +199,20 @@ msgstr "%q는 %d-%d이어야 합니다" msgid "%q must be 1 when %q is True" msgstr "%q가 참일 때 %q는 1이어야 합니다" +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 16, 24, or 32" +msgstr "" + +#: ports/espressif/common-hal/audioi2sin/I2SIn.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 8 or 16" +msgstr "" + +#: ports/espressif/common-hal/audiobusio/PDMIn.c +#: shared-bindings/audioi2sin/I2SIn.c +msgid "%q must be 8, 16, 24, or 32" +msgstr "" + #: py/argcheck.c shared-bindings/gifio/GifWriter.c #: shared-module/gifio/OnDiskGif.c #, fuzzy @@ -279,10 +302,6 @@ msgstr "%q가 경계를 벗어남" msgid "%q out of range" msgstr "%q가 범위를 벗어남" -#: py/objmodule.c -msgid "%q renamed %q" -msgstr "%q가 %q로 이름이 변경되었습니다" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c #, fuzzy msgid "%q step cannot be zero" @@ -488,6 +507,7 @@ msgstr "*x는 할당 대상이어야 합니다" msgid ", in %q\n" msgstr ", 에서 %q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -507,7 +527,7 @@ msgstr "pow() 는 3개의 인수를 지원하지 않습니다" msgid "AP could not be started" msgstr "AP를 시작할 수 없습니다" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "주소 길이는 %d 바이트 여야합니다" @@ -651,6 +671,10 @@ msgstr "배열 값은 1바이트 여야합니다." msgid "Async SPI transfer in progress on this bus, keep awaiting." msgstr "" +#: shared-bindings/usb_audio/__init__.c +msgid "At least one of microphone and speaker must be enabled" +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -662,6 +686,7 @@ msgstr "오디오 변환이 구현되지 않음" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Audio source error" msgstr "" @@ -689,12 +714,14 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "주변 기기에서 전송 속도가 지원되지 않습니다" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" msgstr "최소 프레임 속도 미만" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c msgid "Bit clock and word select must be sequential GPIO pins" msgstr "비트 클럭 및 워드 선택은 순차적 GPIO 핀이어야 합니다" @@ -711,16 +738,12 @@ msgstr "부팅 장치는 첫 번째(인터페이스 #0)여야 합니다." msgid "Both RX and TX required for flow control" msgstr "플로우 제어에 RX와 TX가 모두 필요합니다" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "밝기를 조절할 수 없습니다" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Buffer + offset이 너무 작습니다 %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "버퍼 요소는 4바이트 이하여야 합니다" @@ -763,10 +786,6 @@ msgstr "버퍼가 너무 작습니다" msgid "Bus pin %d is already in use" msgstr "Bus 핀 %d은 이미 사용 중입니다" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "잘못된 크기의 버퍼. 16 바이트 여야합니다." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "CBC 블록은 16 바이트의 배수여야 합니다" @@ -809,9 +828,9 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "로컬 특성에 CCCD를 설정할 수 없습니다" -#: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c -#: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c -#: shared-bindings/usb_video/__init__.c +#: shared-bindings/storage/__init__.c shared-bindings/usb_audio/__init__.c +#: shared-bindings/usb_cdc/__init__.c shared-bindings/usb_hid/__init__.c +#: shared-bindings/usb_midi/__init__.c shared-bindings/usb_video/__init__.c msgid "Cannot change USB devices now" msgstr "현재 USB 디바이스를 변경할 수 없습니다" @@ -848,7 +867,7 @@ msgstr "확장되고 연결 가능한 광고에 대한 검색 응답을 가질 msgid "Cannot pull on input-only pin." msgstr "입력 전용 핀을 끌어올 수 없습니다." -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Cannot record to a file" msgstr "파일에 녹음 할 수 없습니다" @@ -910,7 +929,7 @@ msgstr "좌표 배열의 길이가 다릅니다" msgid "Coordinate arrays types have different sizes" msgstr "좌표 배열 유형은 크기가 다릅니다" -#: shared-module/usb/core/Device.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c msgid "Could not allocate DMA capable buffer" msgstr "" @@ -936,10 +955,12 @@ msgid "Critical ROS failure during soft reboot, reset required: %d" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Channel Init Error" msgstr "DAC 채널 초기화 오류" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Device Init Error" msgstr "DAC 장치 초기화 오류" @@ -971,7 +992,7 @@ msgstr "광고 (브로드 캐스트) 패킷에 대한 데이터가 너무 큽니 msgid "Deep sleep pins must use a rising edge with pulldown" msgstr "딥 슬립 핀은 풀다운이 있는 상승 에지를 사용해야 합니다" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Destination capacity is smaller than destination_length." msgstr "대상 용량이 destination_length보다 작습니다." @@ -1012,8 +1033,17 @@ msgstr "위 예외를 처리하는 동안, 또 다른 예외가 발생하였습 msgid "ECB only operates on 16 bytes at a time" msgstr "ECB는 한 번에 16 바이트에서만 작동합니다" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "ESP-IDF 메모리 할당에 실패하였습니다" @@ -1081,10 +1111,12 @@ msgstr "샘플 버퍼링에 실패했습니다" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "연결에 실패했습니다: 내부 오류" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "연결에 실패했습니다: 시간 초과" @@ -1197,6 +1229,7 @@ msgstr "GNSS 초기화" msgid "Generic Failure" msgstr "일반 오류" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1295,7 +1328,8 @@ msgstr "내부 오디오 버퍼가 너무 작습니다" msgid "Internal define error" msgstr "내부 정의 오류" -#: shared-bindings/pwmio/PWMOut.c supervisor/shared/settings.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "내부 오류" @@ -1351,6 +1385,7 @@ msgstr "출력 함수로 인해 종료되었다" msgid "Invalid %q" msgstr "잘못된 %q" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1384,6 +1419,10 @@ msgstr "잘못된 MAC 주소" msgid "Invalid ROS domain ID" msgstr "" +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "잘못된 인수" @@ -1474,6 +1513,14 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "매핑은 투플이어야 합니다" +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap must have 8 bits per pixel" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap size must match the other bitmaps" +msgstr "" + #: py/persistentcode.c msgid "MicroPython .mpy file; use CircuitPython mpy-cross" msgstr "" @@ -1570,7 +1617,7 @@ msgstr "빠른 메모리 부족" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "%q 핀이 없습니다" @@ -1581,6 +1628,7 @@ msgstr "이 특성에 대한 CCCD가 없습니다" #: ports/atmel-samd/common-hal/analogio/AnalogOut.c #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "No DAC on chip" msgstr "칩에 DAC가 없습니다" @@ -1588,6 +1636,7 @@ msgstr "칩에 DAC가 없습니다" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "DMA 채널을 찾을 수 없습니다" @@ -1705,7 +1754,8 @@ msgid "Not connected" msgstr "연결되지 않았습니다" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c +#: shared-bindings/usb_audio/USBMicrophone.c msgid "Not playing" msgstr "재생되지 않았습니다" @@ -1807,6 +1857,7 @@ msgid "Operation or feature not supported" msgstr "작업 또는 기능이 지원되지 않습니다" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #, fuzzy msgid "Operation timed out" msgstr "작업 시간 초과되었습니다" @@ -1855,6 +1906,7 @@ msgid "Parameter error" msgstr "파라미터 오류" #: ports/espressif/common-hal/audiobusio/__init__.c +#: ports/espressif/common-hal/audioi2sin/I2SIn.c #, fuzzy msgid "Peripheral in use" msgstr "주변 기기가 사용 중입니다" @@ -2138,10 +2190,13 @@ msgstr "" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c -#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -2178,7 +2233,7 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiocore/__init__.c +#: shared-module/audiocore/__init__.c shared-module/usb_audio/USBMicrophone.c msgid "The sample's %q does not match" msgstr "" @@ -2233,6 +2288,7 @@ msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2315,10 +2371,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "UUID문자열이 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'형식이 아닙니다" @@ -2336,6 +2388,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2476,6 +2529,7 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c #: ports/zephyr-cp/common-hal/busio/I2C.c #: ports/zephyr-cp/common-hal/busio/SPI.c #: ports/zephyr-cp/common-hal/busio/UART.c @@ -2691,10 +2745,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2751,10 +2801,6 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" -#: ports/espressif/common-hal/audiobusio/PDMIn.c -msgid "bit_depth must be 8, 16, 24, or 32." -msgstr "" - #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2908,6 +2954,10 @@ msgstr "" msgid "can't create '%q' instances" msgstr "" +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -3006,14 +3056,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -3148,6 +3198,10 @@ msgstr "" msgid "destination buffer must be an array of type 'H' for bit_depth = 16" msgstr "" +#: shared-bindings/usb_audio/USBSpeaker.c +msgid "destination must be an array of type 'h'" +msgstr "" + #: py/objdict.c msgid "dict update sequence has wrong length" msgstr "" @@ -3168,7 +3222,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -3307,10 +3361,6 @@ msgstr "float이 너무 큽니다" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" @@ -3392,10 +3442,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3462,10 +3508,6 @@ msgstr "" msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3556,6 +3598,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3569,6 +3615,11 @@ msgstr "" msgid "invalid cert" msgstr "cert가 유효하지 않습니다" +#: shared-bindings/audioi2sin/I2SIn.c +#, c-format +msgid "invalid destination buffer, must be an array of type: %c" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element size %d for bits_per_pixel %d\n" @@ -3750,6 +3801,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3798,10 +3853,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3823,7 +3874,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -4112,7 +4163,7 @@ msgstr "" msgid "output array must be contiguous" msgstr "" -#: py/objint_mpz.c +#: py/objint_longlong.c py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -4121,10 +4172,6 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" -msgstr "" - #: py/emitinlinerv32.c msgid "parameters must be registers in sequence a0 to a3" msgstr "" @@ -4182,6 +4229,10 @@ msgstr "" msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -4191,6 +4242,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -4455,10 +4510,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4480,10 +4531,6 @@ msgstr "" msgid "unindent doesn't match any outer indent level" msgstr "" -#: py/emitinlinerv32.c -msgid "unknown RV32 instruction '%q'" -msgstr "" - #: py/objstr.c #, c-format msgid "unknown conversion specifier %c" @@ -4652,6 +4699,16 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "%q renamed %q" +#~ msgstr "%q가 %q로 이름이 변경되었습니다" + +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Buffer + offset이 너무 작습니다 %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "잘못된 크기의 버퍼. 16 바이트 여야합니다." + #, c-format #~ msgid "Invalid byte %.*s" #~ msgstr "잘못된 바이트 %.*s" diff --git a/locale/ru.po b/locale/ru.po index cff7a97b396..a88c6cbbea3 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -93,6 +93,11 @@ msgstr "" "Адресные контакты %d, контакты rgb %d и плитки %d обозначают высоту %d, а не " "%d" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q и %q содержат пины дупликаты" @@ -114,6 +119,7 @@ msgid "%q contains duplicate pins" msgstr "%q содержит пины дупликаты" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q сбой: %d" @@ -127,6 +133,7 @@ msgstr "%q в %q должно быть типа %q, а не %q" #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -148,7 +155,9 @@ msgid "%q indices must be integers, not %s" msgstr "Индексы %q должны быть целыми числами, а не %s" #: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: ports/stm/common-hal/audioio/AudioOut.c #: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "Инициализация %q не удалась" @@ -180,8 +189,8 @@ msgstr "Длинна %q должна быть >= %d" msgid "%q must be %d" msgstr "%q должно быть %d" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -192,6 +201,20 @@ msgstr "%q должно быть %d-%d" msgid "%q must be 1 when %q is True" msgstr "%q должен быть равен 1, если %q имеет значение True" +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 16, 24, or 32" +msgstr "" + +#: ports/espressif/common-hal/audioi2sin/I2SIn.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 8 or 16" +msgstr "" + +#: ports/espressif/common-hal/audiobusio/PDMIn.c +#: shared-bindings/audioi2sin/I2SIn.c +msgid "%q must be 8, 16, 24, or 32" +msgstr "" + #: py/argcheck.c shared-bindings/gifio/GifWriter.c #: shared-module/gifio/OnDiskGif.c msgid "%q must be <= %d" @@ -274,10 +297,6 @@ msgstr "%q за пределом" msgid "%q out of range" msgstr "%q вне диапазона" -#: py/objmodule.c -msgid "%q renamed %q" -msgstr "%q переименован %q" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "Шаг %q не может быть нулём" @@ -473,6 +492,7 @@ msgstr "*x должно быть целью назначения" msgid ", in %q\n" msgstr ", в %q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -491,7 +511,7 @@ msgstr "Pow() с 3 аргументами не поддерживается" msgid "AP could not be started" msgstr "AP не может быть запущен" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "Адрес должен быть длиной %d байт" @@ -625,6 +645,10 @@ msgstr "Значения массива должны быть однобайто msgid "Async SPI transfer in progress on this bus, keep awaiting." msgstr "" +#: shared-bindings/usb_audio/__init__.c +msgid "At least one of microphone and speaker must be enabled" +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -636,6 +660,7 @@ msgstr "Преобразование звука не реализовано" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Audio source error" msgstr "" @@ -663,12 +688,14 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "Скорость передачи данных не поддерживается периферийным устройством" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" msgstr "Ниже минимальной частоты кадров" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c msgid "Bit clock and word select must be sequential GPIO pins" msgstr "Несколько часов и слов должны быть последовательными GPIO пинами" @@ -686,16 +713,12 @@ msgstr "Загрузочное устройство должно быть пер msgid "Both RX and TX required for flow control" msgstr "Для управления потоком требуется как RX так и TX" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "Яркость не регулируется" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Буфер + сдвиг слишком малы %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "Элементы буфера должны иметь длину не более 4 байт" @@ -738,10 +761,6 @@ msgstr "Слишком маленький буфер" msgid "Bus pin %d is already in use" msgstr "Вывод шины %d уже используется" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "Буфер байтов должен быть размером 16 байтам." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "Блоки CBC должны быть кратны 16 байтам" @@ -786,9 +805,9 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "Невозможно установить CCCD для локальной характеристики" -#: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c -#: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c -#: shared-bindings/usb_video/__init__.c +#: shared-bindings/storage/__init__.c shared-bindings/usb_audio/__init__.c +#: shared-bindings/usb_cdc/__init__.c shared-bindings/usb_hid/__init__.c +#: shared-bindings/usb_midi/__init__.c shared-bindings/usb_video/__init__.c msgid "Cannot change USB devices now" msgstr "Невозможно изменить USB устройство сейчас" @@ -827,7 +846,7 @@ msgstr "" msgid "Cannot pull on input-only pin." msgstr "Невозможно вытащить контакт только для ввода." -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Cannot record to a file" msgstr "Невозможно записать в файл" @@ -890,7 +909,7 @@ msgstr "Координатные массивы имеют разные длин msgid "Coordinate arrays types have different sizes" msgstr "Типы массивов координат имеют разные размеры" -#: shared-module/usb/core/Device.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c msgid "Could not allocate DMA capable buffer" msgstr "" @@ -916,10 +935,12 @@ msgid "Critical ROS failure during soft reboot, reset required: %d" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Channel Init Error" msgstr "Ошибка инициализации канала DAC" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Device Init Error" msgstr "Ошибка инициализации устройства DAC" @@ -952,7 +973,7 @@ msgstr "" "Выводы глубокого сна должны использовать сигнал по возрастанию с подтяжкой к " "земле" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Destination capacity is smaller than destination_length." msgstr "Емкость места назначения меньше длины места назначения." @@ -994,8 +1015,17 @@ msgstr "" msgid "ECB only operates on 16 bytes at a time" msgstr "ECB работает только с 16 байтами за раз" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "Ошибка выделения памяти ESP-IDF" @@ -1062,10 +1092,12 @@ msgstr "Не удалось выполнить буферизацию образ #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "Не удалось подключиться: внутренняя ошибка" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Не удалось подключиться: таймаут" @@ -1181,6 +1213,7 @@ msgstr "Инициализация GNSS" msgid "Generic Failure" msgstr "Общий сбой" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1283,7 +1316,8 @@ msgstr "Внутренний звуковой буфер слишком мал" msgid "Internal define error" msgstr "Внутренняя ошибка определения" -#: shared-bindings/pwmio/PWMOut.c supervisor/shared/settings.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "Внутренняя ошибка" @@ -1339,6 +1373,7 @@ msgstr "Прерывается функцией выхода" msgid "Invalid %q" msgstr "Недопустимый %q" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1372,6 +1407,10 @@ msgstr "Неверный MAC-адрес" msgid "Invalid ROS domain ID" msgstr "" +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Недопустимый аргумент" @@ -1462,6 +1501,14 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "Сопоставление должно быть кортежом" +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap must have 8 bits per pixel" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap size must match the other bitmaps" +msgstr "" + #: py/persistentcode.c msgid "MicroPython .mpy file; use CircuitPython mpy-cross" msgstr "" @@ -1556,7 +1603,7 @@ msgstr "Изображение памяти" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "Нет пина %q" @@ -1567,6 +1614,7 @@ msgstr "Для этой характеристики нет CCCD" #: ports/atmel-samd/common-hal/analogio/AnalogOut.c #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "No DAC on chip" msgstr "DAC отсутствует на чипе" @@ -1574,6 +1622,7 @@ msgstr "DAC отсутствует на чипе" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "Канал DMA не найден" @@ -1688,7 +1737,8 @@ msgid "Not connected" msgstr "Не подключено" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c +#: shared-bindings/usb_audio/USBMicrophone.c msgid "Not playing" msgstr "Не воспроизводится (Not playing)" @@ -1789,6 +1839,7 @@ msgid "Operation or feature not supported" msgstr "Операция или функция, не поддерживаемые" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "Истекло время ожидания операции" @@ -1831,6 +1882,7 @@ msgid "Parameter error" msgstr "Ошибка параметра" #: ports/espressif/common-hal/audiobusio/__init__.c +#: ports/espressif/common-hal/audioi2sin/I2SIn.c msgid "Peripheral in use" msgstr "Периферийные устройства в использовании" @@ -2116,10 +2168,13 @@ msgstr "Фрагменты не поддерживаются" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c -#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool можно использовать только с wifi.radio" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "Исходный и конечный буферы должны иметь одинаковую длину" @@ -2159,7 +2214,7 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "Длина rgb_pins должна быть 6, 12, 18, 24 или 30" -#: shared-module/audiocore/__init__.c +#: shared-module/audiocore/__init__.c shared-module/usb_audio/USBMicrophone.c msgid "The sample's %q does not match" msgstr "%q образца не совпадает" @@ -2216,6 +2271,7 @@ msgid "Too many channels in sample" msgstr "Слишком много каналов в выборке" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "Слишком много каналов в выборке." @@ -2298,10 +2354,6 @@ msgstr "USB-устройства указывают слишком много и msgid "USB error" msgstr "Ошибка USB" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "Целое значение UUID должно быть равно 0-0xffff" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "UUID строка не 'xxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxxxx \"" @@ -2318,6 +2370,7 @@ msgstr "Невозможно получить доступ к невыровне #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "Не удается выделить буферы для подписанного преобразования" @@ -2461,6 +2514,7 @@ msgstr "Неподдерживаемый тип сокета" msgid "Update failed" msgstr "Обновление не удалось" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c #: ports/zephyr-cp/common-hal/busio/I2C.c #: ports/zephyr-cp/common-hal/busio/SPI.c #: ports/zephyr-cp/common-hal/busio/UART.c @@ -2683,10 +2737,6 @@ msgstr "массив слишком велик" msgid "array/bytes required on right side" msgstr "массив/байты, необходимые справа" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "Переполнение ASM" - #: py/compile.c msgid "async for/with outside async function" msgstr "async для/вместе с внешней async-функцией" @@ -2747,10 +2797,6 @@ msgstr "Неверный шрифт" msgid "binary op %q not implemented" msgstr "двоичная операция %q не реализована" -#: ports/espressif/common-hal/audiobusio/PDMIn.c -msgid "bit_depth must be 8, 16, 24, or 32." -msgstr "Глубина_бита должна быть равна 8, 16, 24 или 32." - #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "Размер и глубина растрового изображения должны совпадать" @@ -2905,6 +2951,10 @@ msgstr "не может превратиться в полосу неявно" msgid "can't create '%q' instances" msgstr "" +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "не может объявить нелокальный во внешнем коде" @@ -3007,14 +3057,14 @@ msgstr "не может превратить комплекс в dtype" msgid "cannot convert complex type" msgstr "Не удается преобразовать сложный тип" -#: py/objtype.c -msgid "cannot create instance" -msgstr "Не удается создать экземпляр" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "Не удается удалить элементы массива" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "Не удается изменить форму массива" @@ -3155,6 +3205,10 @@ msgid "destination buffer must be an array of type 'H' for bit_depth = 16" msgstr "" "буфер назначения должен быть массивом типа «H» для битовой_глубины = 16" +#: shared-bindings/usb_audio/USBSpeaker.c +msgid "destination must be an array of type 'h'" +msgstr "" + #: py/objdict.c msgid "dict update sequence has wrong length" msgstr "последовательность обновления дикта имеет неправильную длину" @@ -3175,7 +3229,7 @@ msgstr "Размеры не совпадают" msgid "div/mod not implemented for uint" msgstr "div/mod не реализован для uint" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "Делим на ноль" @@ -3314,10 +3368,6 @@ msgstr "Поплавок слишком большой" msgid "float unsupported" msgstr "Плавающий без поддержки" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "Длина шрифта должна составлять 2048 байт" - #: extmod/moddeflate.c msgid "format" msgstr "формат" @@ -3399,10 +3449,6 @@ msgstr "генератор проигнорировал Выход" msgid "generator raised StopIteration" msgstr "генератор поднят Остановить итерацию" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "Длина рисунка должна составлять 2048 байт" - #: extmod/modhashlib.c msgid "hash is final" msgstr "хэш является окончательным" @@ -3469,10 +3515,6 @@ msgstr "индексы должны быть целыми числами, сре msgid "initial values must be iterable" msgstr "Начальные значения должны быть итерируемыми" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "длина первоначального_значения ошибочна" - #: py/compile.c msgid "inline assembler must be a function" msgstr "Встроенный ассемблер должен быть функцией" @@ -3563,6 +3605,10 @@ msgstr "interp определен для 1D-итераций одинаково msgid "interval must be in range %s-%s" msgstr "Интервал должен находиться в диапазоне %s-%s" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "недействительная арка" @@ -3576,6 +3622,11 @@ msgstr "неверный бит_на_пиксель %d, должно быть 1, msgid "invalid cert" msgstr "Неверный сертификат" +#: shared-bindings/audioi2sin/I2SIn.c +#, c-format +msgid "invalid destination buffer, must be an array of type: %c" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element size %d for bits_per_pixel %d\n" @@ -3763,6 +3814,10 @@ msgstr "mktime нужен кортеж длины 8 или 9" msgid "mode must be complete, or reduced" msgstr "Режим должен быть завершенным или уменьшенным" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "модуль не найден" @@ -3811,10 +3866,6 @@ msgstr "слишком длинное имя" msgid "native code in .mpy unsupported" msgstr "Нативный код в .mpy не поддерживается" -#: py/asmthumb.c -msgid "native method too big" -msgstr "родной метод слишком большой" - #: py/emitnative.c msgid "native yield" msgstr "родной урожай" @@ -3836,7 +3887,7 @@ msgstr "отрицательный факториал" msgid "negative power with no float support" msgstr "Отрицательная мощность без поплавковой опоры" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "Количество отрицательных сдвигов" @@ -4127,7 +4178,7 @@ msgstr "Выходной массив имеет неправильный тип msgid "output array must be contiguous" msgstr "выходной массив должен быть непрерывным" -#: py/objint_mpz.c +#: py/objint_longlong.c py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "переполнение преобразование длинного целого в машинное слово" @@ -4136,10 +4187,6 @@ msgstr "переполнение преобразование длинного msgid "pack expected %d items for packing (got %d)" msgstr "Упаковка ожидаемых %d товаров для упаковки (получил %d)" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" -msgstr "Длина палитры должна составлять 32 байта" - #: py/emitinlinerv32.c msgid "parameters must be registers in sequence a0 to a3" msgstr "" @@ -4197,6 +4244,10 @@ msgstr "Маски вытягивания конфликтуют с маскам msgid "real and imaginary parts must be of equal length" msgstr "реальные и воображаемые части должны быть одинаковой длины" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "Относительный импорт" @@ -4206,6 +4257,10 @@ msgstr "Относительный импорт" msgid "requested length %d but object has length %d" msgstr "запрашиваемая длина %d, но объект имеет длину %d" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "Результаты не могут быть приведены к указанному типу" @@ -4472,10 +4527,6 @@ msgstr "тип объекта '%q' не имеет атрибута '%q \"" msgid "type takes 1 or 3 arguments" msgstr "тип занимает 1 или 3 аргумента" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "голова длинная слишком большая" - #: py/parse.c msgid "unexpected indent" msgstr "Неожиданный отступ" @@ -4497,10 +4548,6 @@ msgstr "Экранирование имен в Юникоде" msgid "unindent doesn't match any outer indent level" msgstr "Отступ не совпадает ни с одним уровнем внешнего отступа" -#: py/emitinlinerv32.c -msgid "unknown RV32 instruction '%q'" -msgstr "" - #: py/objstr.c #, c-format msgid "unknown conversion specifier %c" @@ -4671,6 +4718,46 @@ msgstr "zi должно быть типа float" msgid "zi must be of shape (n_section, 2)" msgstr "zi должен иметь форму (n_section, 2)" +#~ msgid "bit_depth must be 8, 16, 24, or 32." +#~ msgstr "Глубина_бита должна быть равна 8, 16, 24 или 32." + +#~ msgid "%q renamed %q" +#~ msgstr "%q переименован %q" + +#~ msgid "asm overflow" +#~ msgstr "Переполнение ASM" + +#~ msgid "cannot create instance" +#~ msgstr "Не удается создать экземпляр" + +#~ msgid "native method too big" +#~ msgstr "родной метод слишком большой" + +#~ msgid "ulonglong too large" +#~ msgstr "голова длинная слишком большая" + +#~ msgid "font must be 2048 bytes long" +#~ msgstr "Длина шрифта должна составлять 2048 байт" + +#~ msgid "graphic must be 2048 bytes long" +#~ msgstr "Длина рисунка должна составлять 2048 байт" + +#~ msgid "palette must be 32 bytes long" +#~ msgstr "Длина палитры должна составлять 32 байта" + +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Буфер + сдвиг слишком малы %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "Буфер байтов должен быть размером 16 байтам." + +#~ msgid "UUID integer value must be 0-0xffff" +#~ msgstr "Целое значение UUID должно быть равно 0-0xffff" + +#~ msgid "initial_value length is wrong" +#~ msgstr "длина первоначального_значения ошибочна" + #, c-format #~ msgid "Invalid byte %.*s" #~ msgstr "Неверный байт %.*s" diff --git a/locale/tr.po b/locale/tr.po index 0449d8d1261..2ff8c837768 100644 --- a/locale/tr.po +++ b/locale/tr.po @@ -91,6 +91,11 @@ msgstr "" "%d adres pinleri, %d RGB pinleri ve %d döşemeleri %d'nin yüksekliği " "gösterir, %d'nin değil" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q ve %q yinelenen pinler içeriyor" @@ -112,6 +117,7 @@ msgid "%q contains duplicate pins" msgstr "%q yinelenen pinler içeriyor" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q hata: %d" @@ -125,6 +131,7 @@ msgstr "" #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -146,7 +153,9 @@ msgid "%q indices must be integers, not %s" msgstr "%q indeksleri integer olmalı, %s değil" #: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: ports/stm/common-hal/audioio/AudioOut.c #: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "%q init başarısız oldu" @@ -178,8 +187,8 @@ msgstr "%q boyutu >= %d olmalıdır" msgid "%q must be %d" msgstr "%q, %d olmalıdır" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -190,6 +199,20 @@ msgstr "%q, %d-%d olmalıdır" msgid "%q must be 1 when %q is True" msgstr "%q 1 olmalı, %q True olduğu zaman" +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 16, 24, or 32" +msgstr "" + +#: ports/espressif/common-hal/audioi2sin/I2SIn.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c +msgid "%q must be 8 or 16" +msgstr "" + +#: ports/espressif/common-hal/audiobusio/PDMIn.c +#: shared-bindings/audioi2sin/I2SIn.c +msgid "%q must be 8, 16, 24, or 32" +msgstr "" + #: py/argcheck.c shared-bindings/gifio/GifWriter.c #: shared-module/gifio/OnDiskGif.c msgid "%q must be <= %d" @@ -272,10 +295,6 @@ msgstr "%q sınırların dışında" msgid "%q out of range" msgstr "%q aralık dışında" -#: py/objmodule.c -msgid "%q renamed %q" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q sıfır olamaz" @@ -471,6 +490,7 @@ msgstr "*x atama hedefi olmalıdır" msgid ", in %q\n" msgstr ", içinde %q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -489,7 +509,7 @@ msgstr "3-argümanlı pow() desteklenmemektedir" msgid "AP could not be started" msgstr "" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "Adres %d byte uzunluğunda olmalıdır" @@ -623,6 +643,10 @@ msgstr "Dizi değerleri tekil bytelar olmalıdır." msgid "Async SPI transfer in progress on this bus, keep awaiting." msgstr "" +#: shared-bindings/usb_audio/__init__.c +msgid "At least one of microphone and speaker must be enabled" +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -634,6 +658,7 @@ msgstr "Ses dönüşümü implemente edilmedi" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Audio source error" msgstr "" @@ -661,12 +686,14 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "Baudhızı, çevre birimi tarafından desteklenmiyor" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" msgstr "Minimum kare hızından altında" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audioi2sin/I2SIn.c msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" @@ -683,16 +710,12 @@ msgstr "" msgid "Both RX and TX required for flow control" msgstr "Hem RX hem de TX akış kontrolü için gerekli" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "Parlaklık ayarlanabilir değil" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Buffer + offset çok küçük %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "Buffer elementleri 4 bit olmak zorunda" @@ -735,10 +758,6 @@ msgstr "" msgid "Bus pin %d is already in use" msgstr "Veriyolu pini %d kullanımda" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "Bit buffer'ı 16bit olmalı." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "CBC blokları 16 baytın katları şeklinde olmalı" @@ -780,9 +799,9 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" -#: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c -#: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c -#: shared-bindings/usb_video/__init__.c +#: shared-bindings/storage/__init__.c shared-bindings/usb_audio/__init__.c +#: shared-bindings/usb_cdc/__init__.c shared-bindings/usb_hid/__init__.c +#: shared-bindings/usb_midi/__init__.c shared-bindings/usb_video/__init__.c msgid "Cannot change USB devices now" msgstr "USB aygıtları şu an değiştirilemez" @@ -820,7 +839,7 @@ msgstr "Genişletilmiş, bağlanabilir reklamlar için tarama yanıtları yapıl msgid "Cannot pull on input-only pin." msgstr "" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Cannot record to a file" msgstr "Dosyaya kayıt yapılamıyor" @@ -880,7 +899,7 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" -#: shared-module/usb/core/Device.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c msgid "Could not allocate DMA capable buffer" msgstr "" @@ -906,10 +925,12 @@ msgid "Critical ROS failure during soft reboot, reset required: %d" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Channel Init Error" msgstr "" #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "DAC Device Init Error" msgstr "" @@ -940,7 +961,7 @@ msgstr "" msgid "Deep sleep pins must use a rising edge with pulldown" msgstr "" -#: shared-bindings/audiobusio/PDMIn.c +#: shared-bindings/audiobusio/PDMIn.c shared-bindings/audioi2sin/I2SIn.c msgid "Destination capacity is smaller than destination_length." msgstr "Hedef kapasitesi, hedef_uzunluğundan daha küçük." @@ -981,8 +1002,17 @@ msgstr "Yukarıdaki hatanın işlenmesi sırasında başka bir hata oluştu:" msgid "ECB only operates on 16 bytes at a time" msgstr "ECB aynı anda yalnızca 16 baytla çalışır" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "" @@ -1047,10 +1077,12 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "Bağlantı kurulamadı: internal error" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Bağlantı kurulamadı: timeout" @@ -1164,6 +1196,7 @@ msgstr "GNSS init" msgid "Generic Failure" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1262,7 +1295,8 @@ msgstr "Dahili ses arabelleği çok küçük" msgid "Internal define error" msgstr "Dahili tanımlama hatası" -#: shared-bindings/pwmio/PWMOut.c supervisor/shared/settings.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "Dahili hata" @@ -1318,6 +1352,7 @@ msgstr "" msgid "Invalid %q" msgstr "Geçersiz %q" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1351,6 +1386,10 @@ msgstr "Geçersiz MAC adresi" msgid "Invalid ROS domain ID" msgstr "" +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Geçersiz argüman" @@ -1442,6 +1481,14 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "Map tuple olmalıdır" +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap must have 8 bits per pixel" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Mask bitmap size must match the other bitmaps" +msgstr "" + #: py/persistentcode.c msgid "MicroPython .mpy file; use CircuitPython mpy-cross" msgstr "" @@ -1534,7 +1581,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "%q pini yok" @@ -1545,6 +1592,7 @@ msgstr "" #: ports/atmel-samd/common-hal/analogio/AnalogOut.c #: ports/stm/common-hal/analogio/AnalogOut.c +#: ports/stm/common-hal/audioio/AudioOut.c msgid "No DAC on chip" msgstr "" @@ -1552,6 +1600,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "" @@ -1666,7 +1715,8 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c +#: shared-bindings/usb_audio/USBMicrophone.c msgid "Not playing" msgstr "" @@ -1763,6 +1813,7 @@ msgid "Operation or feature not supported" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "" @@ -1805,6 +1856,7 @@ msgid "Parameter error" msgstr "" #: ports/espressif/common-hal/audiobusio/__init__.c +#: ports/espressif/common-hal/audioi2sin/I2SIn.c msgid "Peripheral in use" msgstr "" @@ -2087,10 +2139,13 @@ msgstr "" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c -#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -2127,7 +2182,7 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiocore/__init__.c +#: shared-module/audiocore/__init__.c shared-module/usb_audio/USBMicrophone.c msgid "The sample's %q does not match" msgstr "" @@ -2182,6 +2237,7 @@ msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2264,10 +2320,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "" @@ -2284,6 +2336,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2424,6 +2477,7 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c #: ports/zephyr-cp/common-hal/busio/I2C.c #: ports/zephyr-cp/common-hal/busio/SPI.c #: ports/zephyr-cp/common-hal/busio/UART.c @@ -2639,10 +2693,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2699,10 +2749,6 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" -#: ports/espressif/common-hal/audiobusio/PDMIn.c -msgid "bit_depth must be 8, 16, 24, or 32." -msgstr "" - #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2856,6 +2902,10 @@ msgstr "" msgid "can't create '%q' instances" msgstr "" +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2954,14 +3004,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -3096,6 +3146,10 @@ msgstr "" msgid "destination buffer must be an array of type 'H' for bit_depth = 16" msgstr "" +#: shared-bindings/usb_audio/USBSpeaker.c +msgid "destination must be an array of type 'h'" +msgstr "" + #: py/objdict.c msgid "dict update sequence has wrong length" msgstr "" @@ -3116,7 +3170,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -3255,10 +3309,6 @@ msgstr "" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" @@ -3340,10 +3390,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3410,10 +3456,6 @@ msgstr "" msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3504,6 +3546,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3517,6 +3563,11 @@ msgstr "" msgid "invalid cert" msgstr "" +#: shared-bindings/audioi2sin/I2SIn.c +#, c-format +msgid "invalid destination buffer, must be an array of type: %c" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element size %d for bits_per_pixel %d\n" @@ -3698,6 +3749,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3746,10 +3801,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3771,7 +3822,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -4060,7 +4111,7 @@ msgstr "" msgid "output array must be contiguous" msgstr "" -#: py/objint_mpz.c +#: py/objint_longlong.c py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -4069,10 +4120,6 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" -msgstr "" - #: py/emitinlinerv32.c msgid "parameters must be registers in sequence a0 to a3" msgstr "" @@ -4130,6 +4177,10 @@ msgstr "" msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -4139,6 +4190,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -4403,10 +4458,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4428,10 +4479,6 @@ msgstr "" msgid "unindent doesn't match any outer indent level" msgstr "" -#: py/emitinlinerv32.c -msgid "unknown RV32 instruction '%q'" -msgstr "" - #: py/objstr.c #, c-format msgid "unknown conversion specifier %c" @@ -4600,6 +4647,13 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Buffer + offset çok küçük %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "Bit buffer'ı 16bit olmalı." + #, c-format #~ msgid "%%c requires int or char" #~ msgstr "%%c int veya char tipine ihtiyaç duyar" diff --git a/main.c b/main.c index 46b54f522b5..063044e44f2 100644 --- a/main.c +++ b/main.c @@ -441,17 +441,6 @@ static void print_code_py_status_message(safe_mode_t safe_mode) { } static bool __attribute__((noinline)) run_code_py(safe_mode_t safe_mode, bool *simulate_reset) { - bool serial_connected_at_start = serial_connected(); - bool printed_safe_mode_message = false; - #if CIRCUITPY_AUTORELOAD_DELAY_MS > 0 - if (serial_connected_at_start) { - serial_write("\r\n"); - print_code_py_status_message(safe_mode); - print_safe_mode_message(safe_mode); - printed_safe_mode_message = true; - } - #endif - bool skip_repl = false; bool skip_wait = false; bool found_main = false; @@ -651,20 +640,13 @@ static bool __attribute__((noinline)) run_code_py(safe_mode_t safe_mode, bool *s // If messages haven't been printed yet, print them if (!printed_press_any_key && serial_connected() && !autoreload_pending()) { - if (!serial_connected_at_start) { - print_code_py_status_message(safe_mode); - } - - if (!printed_safe_mode_message) { - print_safe_mode_message(safe_mode); - printed_safe_mode_message = true; - } + print_code_py_status_message(safe_mode); + print_safe_mode_message(safe_mode); serial_write("\r\n"); serial_write_compressed(MP_ERROR_TEXT("Press any key to enter the REPL. Use CTRL-D to reload.\n")); printed_press_any_key = true; } if (!serial_connected()) { - serial_connected_at_start = false; printed_press_any_key = false; } @@ -1020,8 +1002,12 @@ int __attribute__((used)) main(void) { // initialise the cpu and peripherals set_safe_mode(port_init()); + // All ports need pins reset, after never-reset pins are marked in port_init(); + reset_all_pins(); + port_heap_init(); + // Turn on RX and TX LEDs if we have them. init_rxtx_leds(); @@ -1036,18 +1022,12 @@ int __attribute__((used)) main(void) { serial_early_init(); mp_hal_stdout_tx_str(line_clear); - // Wait briefly to give a reset window where we'll enter safe mode after the reset. - if (get_safe_mode() == SAFE_MODE_NONE) { - set_safe_mode(wait_for_safe_mode_reset()); - } - stack_init(); #if CIRCUITPY_STATUS_BAR supervisor_status_bar_init(); #endif - #if !INTERNAL_FLASH_FILESYSTEM // Set up anything that might need to get done before we try to use SPI flash // This is needed for some boards where flash relies on GPIO setup to work @@ -1064,6 +1044,13 @@ int __attribute__((used)) main(void) { set_safe_mode(SAFE_MODE_NO_CIRCUITPY); } + // Wait briefly to give a reset window where we'll enter safe mode after the reset. + // Do this after mounting the filesystem because settings.toml can contain + // CIRCUITPY_SAFE_MODE_DELAY to change the default delay. + if (get_safe_mode() == SAFE_MODE_NONE) { + set_safe_mode(wait_for_safe_mode_reset()); + } + #if CIRCUITPY_BLEIO // Early init so that a reset press can cause BLE public advertising. Need the filesystem to // read settings.toml. @@ -1145,7 +1132,7 @@ int __attribute__((used)) main(void) { } else { skip_repl = false; } - } else if (exit_code != 0) { + } else if (exit_code != PYEXEC_NORMAL_EXIT) { break; } @@ -1202,7 +1189,7 @@ size_t gc_get_max_new_split(void) { return port_heap_get_largest_free_size(); } -void NORETURN nlr_jump_fail(void *val) { +void MP_NORETURN nlr_jump_fail(void *val) { reset_into_safe_mode(SAFE_MODE_NLR_JUMP_FAIL); while (true) { } @@ -1213,7 +1200,7 @@ bool vm_is_running(void) { } #ifndef NDEBUG -static void NORETURN __fatal_error(const char *msg) { +static void MP_NORETURN __fatal_error(const char *msg) { #if CIRCUITPY_DEBUG == 0 reset_into_safe_mode(SAFE_MODE_HARD_FAULT); #endif diff --git a/mpy-cross/main.c b/mpy-cross/main.c index 989aec68bb5..add07c3d49b 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -34,13 +34,19 @@ #include "py/persistentcode.h" #include "py/runtime.h" #include "py/gc.h" -#include "py/stackctrl.h" +#include "py/parsenum.h" #include "genhdr/mpversion.h" #ifdef _WIN32 // CIRCUITPY-CHANGE #include "fmode.h" #endif +#if MICROPY_EMIT_NATIVE && MICROPY_EMIT_RV32 +#include "py/asmrv32.h" + +static asm_rv32_backend_options_t rv32_options = { 0 }; +#endif + // Command line options, with their defaults static uint emit_opt = MP_EMIT_OPT_NONE; mp_uint_t mp_verbose_flag = 0; @@ -82,13 +88,20 @@ static int compile_and_save(const char *file, const char *output_file, const cha source_name = qstr_from_str(source_file); } - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); #endif mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_compiled_module_t cm; cm.context = m_new_obj(mp_module_context_t); + cm.arch_flags = 0; + #if MICROPY_EMIT_NATIVE && MICROPY_EMIT_RV32 + if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_RV32IMC && mp_dynamic_compiler.backend_options != NULL) { + cm.arch_flags = ((asm_rv32_backend_options_t *)mp_dynamic_compiler.backend_options)->allowed_extensions; + } + #endif + mp_compile_to_raw_code(&parse_tree, source_name, false, &cm); if ((output_file != NULL && strcmp(output_file, "-") == 0) || @@ -131,7 +144,10 @@ static int usage(char **argv) { "Target specific options:\n" "-msmall-int-bits=number : set the maximum bits used to encode a small-int\n" "-march= : set architecture for native emitter;\n" - " x86, x64, armv6, armv6m, armv7m, armv7em, armv7emsp, armv7emdp, xtensa, xtensawin, rv32imc, debug\n" + " x86, x64, armv6, armv6m, armv7m, armv7em, armv7emsp,\n" + " armv7emdp, xtensa, xtensawin, rv32imc, rv64imc, host, debug\n" + "-march-flags= : set architecture-specific flags (can be either a dec/hex/bin value or a string)\n" + " supported flags for rv32imc: zba\n" "\n" "Implementation specific options:\n", argv[0] ); @@ -212,9 +228,39 @@ static char *backslash_to_forwardslash(char *path) { return path; } -MP_NOINLINE int main_(int argc, char **argv) { - mp_stack_set_limit(40000 * (sizeof(void *) / 4)); +// This will need to be reworked in case mpy-cross needs to set more bits than +// what its small int representation allows to fit in there. +static bool parse_integer(const char *value, mp_uint_t *integer) { + assert(value && "Attempting to parse a NULL string"); + assert(integer && "Attempting to store into a NULL integer buffer"); + + size_t value_length = strlen(value); + int base = 10; + if (value_length > 2 && value[0] == '0') { + if ((value[1] | 0x20) == 'b') { + base = 2; + } else if ((value[1] | 0x20) == 'x') { + base = 16; + } else { + return false; + } + } + + bool valid = false; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t parsed = mp_parse_num_integer(value, value_length, base, NULL); + if (mp_obj_is_small_int(parsed)) { + *integer = MP_OBJ_SMALL_INT_VALUE(parsed); + valid = true; + } + nlr_pop(); + } + return valid; +} + +MP_NOINLINE int main_(int argc, char **argv) { pre_process_options(argc, argv); char *heap = malloc(heap_size); @@ -237,11 +283,13 @@ MP_NOINLINE int main_(int argc, char **argv) { // don't support native emitter unless -march is specified mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_NONE; mp_dynamic_compiler.nlr_buf_num_regs = 0; + mp_dynamic_compiler.backend_options = NULL; const char *input_file = NULL; const char *output_file = NULL; const char *source_file = NULL; bool option_parsing_active = true; + const char *arch_flags = NULL; // parse main options for (int a = 1; a < argc; a++) { @@ -318,6 +366,9 @@ MP_NOINLINE int main_(int argc, char **argv) { } else if (strcmp(arch, "rv32imc") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_RV32IMC; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_RV32I; + } else if (strcmp(arch, "rv64imc") == 0) { + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_RV64IMC; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_RV64I; } else if (strcmp(arch, "debug") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_DEBUG; mp_dynamic_compiler.nlr_buf_num_regs = 0; @@ -331,6 +382,9 @@ MP_NOINLINE int main_(int argc, char **argv) { #elif defined(__arm__) && !defined(__thumb2__) mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; + #elif defined(__riscv) && (__riscv_xlen == 64) + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_RV64IMC; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_RV64I; #else mp_printf(&mp_stderr_print, "unable to determine host architecture for -march=host\n"); exit(1); @@ -338,6 +392,8 @@ MP_NOINLINE int main_(int argc, char **argv) { } else { return usage(argv); } + } else if (strncmp(argv[a], "-march-flags=", sizeof("-march-flags=") - 1) == 0) { + arch_flags = argv[a] + sizeof("-march-flags=") - 1; } else if (strcmp(argv[a], "--") == 0) { option_parsing_active = false; } else { @@ -352,6 +408,38 @@ MP_NOINLINE int main_(int argc, char **argv) { } } + if (arch_flags && mp_dynamic_compiler.native_arch != MP_NATIVE_ARCH_NONE) { + bool processed = false; + #if MICROPY_EMIT_NATIVE && MICROPY_EMIT_RV32 + if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_RV32IMC) { + mp_dynamic_compiler.backend_options = (void *)&rv32_options; + mp_uint_t raw_flags = 0; + if (parse_integer(arch_flags, &raw_flags)) { + if ((raw_flags & ~((mp_uint_t)RV32_EXT_ALL)) == 0) { + rv32_options.allowed_extensions = raw_flags; + processed = true; + } + } else if (strncmp(arch_flags, "zba", sizeof("zba") - 1) == 0) { + rv32_options.allowed_extensions |= RV32_EXT_ZBA; + processed = true; + } + } + #endif + if (!processed) { + mp_printf(&mp_stderr_print, "unrecognised arch flags\n"); + exit(1); + } + } + + #if MICROPY_EMIT_NATIVE + if ((MP_STATE_VM(default_emit_opt) == MP_EMIT_OPT_NATIVE_PYTHON + || MP_STATE_VM(default_emit_opt) == MP_EMIT_OPT_VIPER) + && mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_NONE) { + mp_printf(&mp_stderr_print, "arch not specified\n"); + exit(1); + } + #endif + if (input_file == NULL) { mp_printf(&mp_stderr_print, "no input file\n"); exit(1); @@ -371,7 +459,7 @@ MP_NOINLINE int main_(int argc, char **argv) { } int main(int argc, char **argv) { - mp_stack_ctrl_init(); + mp_cstack_init_with_sp_here(40000 * (sizeof(void *) / 4)); return main_(argc, argv); } diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h index edbd9f87c05..36bcbc11394 100644 --- a/mpy-cross/mpconfigport.h +++ b/mpy-cross/mpconfigport.h @@ -59,6 +59,7 @@ #define MICROPY_COMP_CONST_FOLDING (1) #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_CONST (1) +#define MICROPY_COMP_CONST_FLOAT (1) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_RETURN_IF_EXPR (1) @@ -90,11 +91,12 @@ #define MICROPY_GCREGS_SETJMP (1) #endif -#define MICROPY_PY___FILE__ (0) +#define MICROPY_MODULE___FILE__ (0) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_ATTRTUPLE (0) #define MICROPY_PY_COLLECTIONS (0) -#define MICROPY_PY_MATH (0) +#define MICROPY_PY_MATH (MICROPY_COMP_CONST_FLOAT) +#define MICROPY_PY_MATH_CONSTANTS (MICROPY_COMP_CONST_FLOAT) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_GC (0) #define MICROPY_PY_IO (0) @@ -102,23 +104,6 @@ // type definitions for the specific machine -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#elif defined(__MINGW32__) && defined(_WIN64) -#include -typedef __int64 mp_int_t; -typedef unsigned __int64 mp_uint_t; -#elif defined(_MSC_VER) && defined(_WIN64) -typedef __int64 mp_int_t; -typedef unsigned __int64 mp_uint_t; -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless for actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif - // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; @@ -143,7 +128,7 @@ typedef long mp_off_t; #ifdef _MSC_VER #define MP_ENDIANNESS_LITTLE (1) -#define NORETURN __declspec(noreturn) +#define MP_NORETURN __declspec(noreturn) #define MP_NOINLINE __declspec(noinline) #define MP_ALWAYSINLINE __forceinline #define MP_LIKELY(x) (x) diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py index 91cd6f99335..6d7002a3b89 100644 --- a/mpy-cross/mpy_cross/__init__.py +++ b/mpy-cross/mpy_cross/__init__.py @@ -25,7 +25,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from __future__ import print_function import os import re import stat @@ -44,6 +43,7 @@ "NATIVE_ARCH_XTENSA": "xtensa", "NATIVE_ARCH_XTENSAWIN": "xtensawin", "NATIVE_ARCH_RV32IMC": "rv32imc", + "NATIVE_ARCH_RV64IMC": "rv64imc", } globals().update(NATIVE_ARCHS) diff --git a/mpy-cross/mpy_cross/__main__.py b/mpy-cross/mpy_cross/__main__.py index 2b6b81c3333..fe78a9e077e 100644 --- a/mpy-cross/mpy_cross/__main__.py +++ b/mpy-cross/mpy_cross/__main__.py @@ -25,7 +25,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from __future__ import print_function import argparse import sys diff --git a/ports/analog/common-hal/busio/SPI.c b/ports/analog/common-hal/busio/SPI.c index de3856b23b3..bdbe6da9d94 100644 --- a/ports/analog/common-hal/busio/SPI.c +++ b/ports/analog/common-hal/busio/SPI.c @@ -157,7 +157,6 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, mxc_spi_clkmode_t clk_mode; int ret; - self->baudrate = baudrate; self->polarity = polarity; self->phase = phase; self->bits = bits; @@ -185,6 +184,29 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, mp_raise_ValueError_varg(MP_ERROR_TEXT("%q out of range"), MP_QSTR_baudrate); return false; } + + // MXC_SPI_SetFrequency() floors the clock divisor, so the actual rate can be + // HIGHER than requested. Treat baudrate as a ceiling: if the hardware + // overshoots, bisect downward on the requested target for the highest rate + // that does not exceed baudrate. MXC_SPI_GetFrequency() reports the actual + // configured rate, so we don't depend on the divisor internals. + uint32_t actual = MXC_SPI_GetFrequency(self->spi_regs); + if (actual > baudrate) { + uint32_t lo = 1; // f(lo) <= baudrate + uint32_t hi = baudrate; // f(hi) > baudrate (just measured) + while (hi - lo > 1) { + uint32_t mid = lo + (hi - lo) / 2; + MXC_SPI_SetFrequency(self->spi_regs, mid); + if (MXC_SPI_GetFrequency(self->spi_regs) <= baudrate) { + lo = mid; + } else { + hi = mid; + } + } + MXC_SPI_SetFrequency(self->spi_regs, lo); + actual = MXC_SPI_GetFrequency(self->spi_regs); + } + self->baudrate = actual; ret = MXC_SPI_SetDataSize(self->spi_regs, bits); if (ret == E_BAD_PARAM) { mp_raise_ValueError_varg(MP_ERROR_TEXT("%q out of range"), MP_QSTR_bits); diff --git a/ports/analog/supervisor/port.c b/ports/analog/supervisor/port.c index 86d96bc251b..e95deaba2a8 100644 --- a/ports/analog/supervisor/port.c +++ b/ports/analog/supervisor/port.c @@ -67,7 +67,7 @@ static uint32_t subsec, sec = 0; static uint32_t tick_flag = 0; // defined by cmsis core files -extern void NVIC_SystemReset(void) NORETURN; +extern void NVIC_SystemReset(void) MP_NORETURN; volatile uint32_t system_ticks = 0; @@ -126,7 +126,7 @@ safe_mode_t port_init(void) { ; // enable TRNG (true random number generator) - #ifdef CIRCUITPY_RANDOM + #if CIRCUITPY_RANDOM MXC_TRNG_Init(); #endif diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index 2410f0fddb7..3d25bd340b1 100644 --- a/ports/atmel-samd/background.c +++ b/ports/atmel-samd/background.c @@ -14,7 +14,7 @@ #include "supervisor/shared/stack.h" #include "supervisor/port.h" -#ifdef CIRCUITPY_DISPLAYIO +#if CIRCUITPY_DISPLAYIO #include "shared-module/displayio/__init__.h" #endif diff --git a/ports/atmel-samd/boards/ugame10/board.c b/ports/atmel-samd/boards/ugame10/board.c index 78d03a3fd9a..34f769e358f 100644 --- a/ports/atmel-samd/boards/ugame10/board.c +++ b/ports/atmel-samd/boards/ugame10/board.c @@ -55,7 +55,7 @@ void board_init(void) { spi, MP_OBJ_FROM_PTR(&pin_PA09), // Command or data MP_OBJ_FROM_PTR(&pin_PA08), // Chip select - MP_OBJ_NULL, // Reset + mp_const_none, // Reset 24000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/common-hal/alarm/__init__.c b/ports/atmel-samd/common-hal/alarm/__init__.c index 483aa1a9679..38ef58bea76 100644 --- a/ports/atmel-samd/common-hal/alarm/__init__.c +++ b/ports/atmel-samd/common-hal/alarm/__init__.c @@ -133,7 +133,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep(); // port_disable_tick(); // TODO: Required for SAMD? diff --git a/ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c b/ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c index 3c1fbb5ba7b..de98b7ec85a 100644 --- a/ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c +++ b/ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c @@ -7,6 +7,6 @@ #include "shared-bindings/alarm/touch/TouchAlarm.h" #include "shared-bindings/microcontroller/__init__.h" -NORETURN void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) { +MP_NORETURN void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) { mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_TouchAlarm); } diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index fe53580afdf..19fd81e425d 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -194,14 +194,14 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { } allow_reset_sercom(self->spi_desc.dev.prvt); - // Mark as deinit early in case we are used in an interrupt. - common_hal_busio_spi_mark_deinit(self); - spi_m_sync_disable(&self->spi_desc); spi_m_sync_deinit(&self->spi_desc); reset_pin_number(self->clock_pin); reset_pin_number(self->MOSI_pin); reset_pin_number(self->MISO_pin); + + // This smashes self->clock_pin, so don't do it before resetting the pin above. + common_hal_busio_spi_mark_deinit(self); } bool common_hal_busio_spi_configure(busio_spi_obj_t *self, diff --git a/ports/atmel-samd/peripherals b/ports/atmel-samd/peripherals index da0a1d7dccb..e98b6b79976 160000 --- a/ports/atmel-samd/peripherals +++ b/ports/atmel-samd/peripherals @@ -1 +1 @@ -Subproject commit da0a1d7dccb34b7fa07738e7a8ce25118c88d1a3 +Subproject commit e98b6b799768d21d8f8e2d0a071f19cf7d80467d diff --git a/ports/atmel-samd/reset.c b/ports/atmel-samd/reset.c index 9cacd4ab951..816e23e3251 100644 --- a/ports/atmel-samd/reset.c +++ b/ports/atmel-samd/reset.c @@ -9,7 +9,7 @@ #include "reset.h" #include "supervisor/filesystem.h" -void NVIC_SystemReset(void) NORETURN; +void NVIC_SystemReset(void) MP_NORETURN; void reset(void) { filesystem_flush(); diff --git a/ports/atmel-samd/reset.h b/ports/atmel-samd/reset.h index c74d25fa01e..248d43779fd 100644 --- a/ports/atmel-samd/reset.h +++ b/ports/atmel-samd/reset.h @@ -16,6 +16,6 @@ extern uint32_t _bootloader_dbl_tap; -void reset_to_bootloader(void) NORETURN; -void reset(void) NORETURN; +void reset_to_bootloader(void) MP_NORETURN; +void reset(void) MP_NORETURN; bool bootloader_available(void); diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 31bc5faf827..288446cf62e 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -339,11 +339,9 @@ safe_mode_t port_init(void) { init_shared_dma(); // Reset everything into a known state before board_init. + // Pins are reset in main() after this routine returns. reset_port(); - // Reset the pins too. - reset_all_pins(); - #ifdef SAMD21 if (PM->RCAUSE.bit.BOD33 == 1 || PM->RCAUSE.bit.BOD12 == 1) { return SAFE_MODE_BROWNOUT; @@ -687,7 +685,7 @@ void port_idle_until_interrupt(void) { /** * \brief Default interrupt handler for unused IRQs. */ -__attribute__((used)) NORETURN void HardFault_Handler(void) { +__attribute__((used)) MP_NORETURN void HardFault_Handler(void) { #ifdef ENABLE_MICRO_TRACE_BUFFER // Turn off the micro trace buffer so we don't fill it up in the infinite // loop below. diff --git a/ports/cxd56/common-hal/busio/SPI.c b/ports/cxd56/common-hal/busio/SPI.c index 6c49e0f2750..595b868f348 100644 --- a/ports/cxd56/common-hal/busio/SPI.c +++ b/ports/cxd56/common-hal/busio/SPI.c @@ -72,8 +72,27 @@ void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { uint8_t mode; - self->frequency = baudrate; - SPI_SETFREQUENCY(self->spi_dev, baudrate); + // SPI_SETFREQUENCY() picks the nearest available frequency and returns it, + // which can be HIGHER than requested (it overshoots at low frequencies). + // Treat baudrate as a ceiling: if the driver overshoots, bisect downward on + // the requested target for the highest available frequency that does not + // exceed baudrate. The driver returns the actual frequency each call, so we + // don't depend on its divisor internals. + uint32_t actual = SPI_SETFREQUENCY(self->spi_dev, baudrate); + if (actual > baudrate) { + uint32_t lo = 1; // f(lo) <= baudrate + uint32_t hi = baudrate; // f(hi) > baudrate (just measured) + while (hi - lo > 1) { + uint32_t mid = lo + (hi - lo) / 2; + if (SPI_SETFREQUENCY(self->spi_dev, mid) <= baudrate) { + lo = mid; + } else { + hi = mid; + } + } + actual = SPI_SETFREQUENCY(self->spi_dev, lo); + } + self->frequency = actual; if (polarity == 0) { if (phase == 0) { diff --git a/ports/espressif/CMakeLists.txt b/ports/espressif/CMakeLists.txt index 387a18dac09..e612e4f31de 100644 --- a/ports/espressif/CMakeLists.txt +++ b/ports/espressif/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.16) set(ENV{IDF_PATH} ${CMAKE_SOURCE_DIR}/esp-idf) # The component list here determines what options we get in menuconfig and what the ninja file can build. -set(COMPONENTS bt driver esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_i2s esp_driver_ledc esp_driver_pcnt esp_driver_rmt esp_driver_spi esp_driver_tsens esp_driver_uart esp-tls esp_adc_cal esp_event esp_netif esp_psram esp_wifi esptool_py freertos log lwip main mbedtls mdns soc ulp usb wpa_supplicant esp-camera esp_lcd vfs esp_vfs_console sdmmc) +set(COMPONENTS bt driver esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_i2s esp_driver_ledc esp_driver_pcnt esp_driver_rmt esp_driver_sdmmc esp_driver_spi esp_driver_touch_sens esp_driver_tsens esp_driver_uart esp-tls esp_adc esp_event esp_netif esp_psram esp_security esp_wifi esptool_py freertos log lwip main mbedtls mdns pthread soc ulp wpa_supplicant esp_lcd vfs esp_stdio sdmmc esp-camera) set(EXTRA_COMPONENT_DIRS "esp-protocols/components/mdns" "esp-camera") include($ENV{IDF_PATH}/tools/cmake/project.cmake) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index ebc4fa3a4e1..ca70127565f 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -47,41 +47,43 @@ INC += \ -isystem esp-idf/components/bt/host/nimble/nimble/porting/nimble/include \ -isystem esp-idf/components/bt/host/nimble/nimble/porting/npl/freertos/include \ -isystem esp-idf/components/bt/host/nimble/port/include \ - -isystem esp-idf/components/driver/touch_sensor/include \ - -isystem esp-idf/components/driver/touch_sensor/$(IDF_TARGET)/include \ + -isystem esp-idf/components/bt/porting/include \ + -isystem esp-idf/components/bt/porting/npl/freertos/include \ + -isystem esp-idf/components/bt/porting/transport/include \ + -isystem esp-idf/components/esp_driver_touch_sens/include \ -isystem esp-idf/components/driver/twai/include \ + -isystem esp-idf/components/driver/i2c/include \ -isystem esp-idf/components/efuse/include \ -isystem esp-idf/components/efuse/$(IDF_TARGET)/include \ - -isystem esp-idf/components/$(IDF_TARGET)/include \ -isystem esp-idf/components/esp_adc/include \ -isystem esp-idf/components/esp_adc/$(IDF_TARGET)/include \ -isystem esp-idf/components/esp_app_format/include \ -isystem esp-idf/components/esp_bootloader_format/include \ -isystem esp-idf/components/esp_common/include \ - -isystem esp-idf/components/esp_driver_deprecated \ -isystem esp-idf/components/esp_driver_dac/include \ -isystem esp-idf/components/esp_driver_gpio/include \ -isystem esp-idf/components/esp_driver_gptimer/include \ -isystem esp-idf/components/esp_driver_i2c/include \ -isystem esp-idf/components/esp_driver_i2s/include \ - -isystem esp-idf/components/esp_driver_$(IDF_TARGET)/include \ -isystem esp-idf/components/esp_driver_ledc/include \ -isystem esp-idf/components/esp_driver_parlio/include \ -isystem esp-idf/components/esp_driver_pcnt/include \ -isystem esp-idf/components/esp_driver_rmt/include \ -isystem esp-idf/components/esp_driver_sdio/include \ -isystem esp-idf/components/esp_driver_sdmmc/include \ + -isystem esp-idf/components/esp_driver_sdmmc/legacy/include \ + -isystem esp-idf/components/esp_driver_dma/include \ -isystem esp-idf/components/esp_driver_spi/include \ -isystem esp-idf/components/esp_driver_tsens/include \ -isystem esp-idf/components/esp_driver_uart/include \ -isystem esp-idf/components/esp_event/include \ - -isystem esp-idf/components/esp_hw_support/dma/include \ - -isystem esp-idf/components/esp_hw_support/ldo/include \ -isystem esp-idf/components/esp_hw_support/include \ -isystem esp-idf/components/esp_hw_support/include/soc \ -isystem esp-idf/components/esp_hw_support/port/$(IDF_TARGET)/private_include \ + -isystem esp-idf/components/esp_hw_support/etm/include \ -isystem esp-idf/components/esp_mm/include \ -isystem esp-idf/components/esp_netif/include \ + -isystem esp-idf/components/esp_blockdev/include \ -isystem esp-idf/components/esp_partition/include \ -isystem esp-idf/components/esp_pm/include \ -isystem esp-idf/components/esp_psram/include \ @@ -106,6 +108,38 @@ INC += \ -isystem esp-idf/components/hal/include \ -isystem esp-idf/components/hal/$(IDF_TARGET)/include \ -isystem esp-idf/components/hal/platform_port/include \ + -isystem esp-idf/components/esp_hal_gpio/include \ + -isystem esp-idf/components/esp_hal_gpio/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_timg/include \ + -isystem esp-idf/components/esp_hal_ana_conv/include \ + -isystem esp-idf/components/esp_hal_touch_sens/include \ + -isystem esp-idf/components/esp_hal_uart/include \ + -isystem esp-idf/components/esp_hal_gpspi/include \ + -isystem esp-idf/components/esp_hal_i2c/include \ + -isystem esp-idf/components/esp_hal_i2s/include \ + -isystem esp-idf/components/esp_hal_i2s/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_ledc/include \ + -isystem esp-idf/components/esp_hal_pcnt/include \ + -isystem esp-idf/components/esp_hal_rmt/include \ + -isystem esp-idf/components/esp_hal_rmt/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_twai/include \ + -isystem esp-idf/components/esp_hal_twai/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_timg/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_gpspi/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_dma/include \ + -isystem esp-idf/components/esp_hal_dma/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_lcd/include \ + -isystem esp-idf/components/esp_hal_lcd/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_sd/include \ + -isystem esp-idf/components/esp_hal_sd/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_usb/include \ + -isystem esp-idf/components/esp_hal_usb/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_parlio/include \ + -isystem esp-idf/components/esp_hal_pmu/include \ + -isystem esp-idf/components/esp_hal_pmu/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_wdt/include \ + -isystem esp-idf/components/esp_hal_wdt/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_hal_security/include \ -isystem esp-idf/components/heap/include \ -isystem esp-idf/components/log/include \ -isystem esp-idf/components/lwip/include \ @@ -115,20 +149,20 @@ INC += \ -isystem esp-idf/components/lwip/port/freertos/include \ -isystem esp-idf/components/mbedtls/esp_crt_bundle/include \ -isystem esp-idf/components/mbedtls/mbedtls/include \ + -isystem esp-idf/components/mbedtls/mbedtls/tf-psa-crypto/include \ + -isystem esp-idf/components/mbedtls/mbedtls/tf-psa-crypto/drivers/builtin/include \ -isystem esp-idf/components/mbedtls/port/include \ - -isystem esp-idf/components/newlib/platform_include \ + -isystem esp-idf/components/mbedtls/port/psa_driver/include \ + -isystem esp-idf/components/esp_libc/platform_include \ -isystem esp-idf/components/nvs_flash/include \ - -isystem esp-idf/components/sdio/include \ -isystem esp-idf/components/sdmmc/include \ -isystem esp-idf/components/soc/include \ -isystem esp-idf/components/soc/$(IDF_TARGET)/include \ -isystem esp-idf/components/soc/$(IDF_TARGET)/register \ -isystem esp-idf/components/spi_flash/include \ - -isystem esp-idf/components/usb/include \ -isystem esp-idf/components/ulp/ulp_fsm/include \ -isystem esp-idf/components/ulp/ulp_riscv/include \ -isystem esp-idf/components/ulp/ulp_common/include \ - -isystem esp-idf/components/ulp/ulp_common/include/$(IDF_TARGET) \ -isystem esp-idf/components/$(IDF_TARGET_ARCH)/include \ -isystem esp-idf/components/$(IDF_TARGET_ARCH)/$(IDF_TARGET)/include \ -isystem esp-protocols/components/mdns/include @@ -137,6 +171,7 @@ CFLAGS += \ -DHAVE_CONFIG_H \ -DESP_PLATFORM=1 \ -DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\" \ + -DMBEDTLS_DECLARE_PRIVATE_IDENTIFIERS \ -DMBEDTLS_PADLOCK_FILE=\"ports/espressif/esp-idf/components/mbedtls/mbedtls/library/padlock.h\" \ -DUNITY_INCLUDE_CONFIG_H -DWITH_POSIX \ -DMP3DEC_GENERIC @@ -173,7 +208,55 @@ REGISTRATION_FUNCTIONS = \ -u include_esp_phy_override \ -u vfs_include_syscalls_impl \ -u esp_vfs_include_nullfs_register \ - -u usb_serial_jtag_vfs_include_dev_init + -u usb_serial_jtag_vfs_include_dev_init \ + -u usb_serial_jtag_connection_monitor_include \ + -u esp_flash_spi_init_include_func \ + -u pthread_include_pthread_impl \ + -u pthread_include_pthread_cond_var_impl \ + -u pthread_include_pthread_local_storage_impl \ + -u pthread_include_pthread_rwlock_impl \ + -u pthread_include_pthread_semaphore_impl \ + -u esp_security_init_include_impl \ + -u mbedtls_psa_crypto_init_include_impl + +# RISC-V picolibc ships optimized memcpy/memset/etc. that need forcing +# (gated by CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS in IDF's esp_libc CMake). +ifeq ($(IDF_TARGET_ARCH),riscv) +REGISTRATION_FUNCTIONS += \ + -u esp_libc_include_memcpy_impl \ + -u esp_libc_include_memmove_impl \ + -u esp_libc_include_memcmp_impl \ + -u esp_libc_include_memset_impl \ + -u esp_libc_include_strcpy_impl \ + -u esp_libc_include_strncpy_impl \ + -u esp_libc_include_strcmp_impl \ + -u esp_libc_include_strncmp_impl +endif + +# Chips with PAU + TOP power-down (SOC_PAU_SUPPORTED && SOC_PM_SUPPORT_TOP_PD): +# C5, C6, C61, H2, H21, H4, P4. These pull in sleep_gpio + system-peripheral +# retention, and the SW-driven RISC-V CPU register save/restore path. +ifneq ($(filter $(IDF_TARGET),esp32c5 esp32c6 esp32c61 esp32h2 esp32h21 esp32h4 esp32p4),) +REGISTRATION_FUNCTIONS += \ + -u esp_sleep_gpio_include \ + -u sleep_system_peripheral_dummy \ + -u rv_core_critical_regs_save \ + -u rv_core_critical_regs_restore +endif + +# RISC-V chips with a hardware FPU (H4, P4) need FPU register save/restore +# alongside the CPU retention path. +ifneq ($(filter $(IDF_TARGET),esp32h4 esp32p4),) +REGISTRATION_FUNCTIONS += \ + -u rv_core_fpu_save \ + -u rv_core_fpu_restore +endif + +ifneq ($(CIRCUITPY_WIFI),0) +ifeq ($(filter $(IDF_TARGET),esp32s2 esp32p4),) +REGISTRATION_FUNCTIONS += -u esp_coex_init_include_func +endif +endif #Debugging/Optimization @@ -202,20 +285,28 @@ endif # option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk CFLAGS += $(OPTIMIZATION_FLAGS) -CFLAGS += $(INC) -Werror -Wall -std=gnu11 -Wl,--gc-sections $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes -Werror=old-style-definition +# Default ROM symbol maps; per-chip blocks below may override. +IDF_TARGET_ROM_LD ?= $(IDF_TARGET).rom.ld +# Floating-point/libgcc ROM map. IDF picks between libgcc and rvfp based on +# CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB (rvfp xor libgcc, never both). Default +# to libgcc; targets that ship the rvfp variant in ROM (P4 in particular) +# override this. +IDF_TARGET_ROM_FLOAT_LD ?= $(IDF_TARGET).rom.libgcc.ld -# Most current ESPs have nano versions of newlib in ROM so we use them. -ifneq ($(IDF_TARGET),esp32c6) - CFLAGS += --specs=nano.specs -else - LDFLAGS += -T$(IDF_TARGET).rom.newlib-normal.ld -endif +CFLAGS += $(INC) -Werror -Wall -std=gnu11 -Wl,--gc-sections $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes -Werror=old-style-definition -Wno-error=cpp -Wno-cpp + +# ESP-IDF v6.0 uses picolibc instead of newlib. +CFLAGS += --specs=picolibc.specs ifeq ($(IDF_TARGET_ARCH),xtensa) # Remove the last two flags once TinyUSB is updated with the `#include ` instead of # `#include "xtensa/xtensa_api.h"`. - CFLAGS += -mlongcalls -isystem esp-idf/components/xtensa/deprecated_include/ -Wno-error=cpp + CFLAGS += -mlongcalls -fno-builtin-memcpy -fno-builtin-memset -fno-builtin-bzero + CFLAGS += -isystem esp-idf/components/xtensa/deprecated_include/ +ifeq ($(IDF_TARGET),esp32) + CFLAGS += -Wno-frame-address +endif CFLAGS += -DMICROPY_GCREGS_SETJMP=1 # Wrap longjmp with a patched version that protects register window update with a critical section @@ -225,9 +316,11 @@ ifeq ($(IDF_TARGET_ARCH),xtensa) else ifeq ($(IDF_TARGET_ARCH),riscv) ifeq ($(IDF_TARGET),esp32p4) - CFLAGS += -march=rv32imafc_zicsr_zifencei_xesppie -mabi=ilp32f + CFLAGS += -march=rv32imafc_zicsr_zifencei_zaamo_zalrsc -mabi=ilp32f + else ifeq ($(IDF_TARGET),$(filter $(IDF_TARGET),esp32c2 esp32c3)) + CFLAGS += -march=rv32imc_zicsr_zifencei else - CFLAGS += -march=rv32imac_zicsr_zifencei + CFLAGS += -march=rv32imac_zicsr_zifencei_zaamo_zalrsc endif LDFLAGS += \ @@ -239,18 +332,19 @@ else ifeq ($(IDF_TARGET_ARCH),riscv) endif -LDFLAGS += $(CFLAGS) -Wl,-nostdlib -Wl,-Map=$@.map -Wl,-cref -Wl,--undefined=uxTopUsedPriority +LDFLAGS += $(CFLAGS) -nostartfiles -Wl,-nostdlib -Wl,-Map=$@.map -Wl,-cref -Wl,--undefined=uxTopUsedPriority LDFLAGS += \ -L$(BUILD)/esp-idf/esp-idf/esp_system/ld \ -Lesp-idf/components/esp_rom/$(IDF_TARGET)/ld \ -Lesp-idf/components/soc/$(IDF_TARGET)/ld \ + -Lesp-idf/components/esp_hal_wdt/$(IDF_TARGET) \ -Tmemory.ld \ -Tsections.ld \ -T$(IDF_TARGET).peripherals.ld \ - -T$(IDF_TARGET).rom.ld \ + -T$(IDF_TARGET_ROM_LD) \ -T$(IDF_TARGET).rom.api.ld \ - -T$(IDF_TARGET).rom.libgcc.ld \ + -T$(IDF_TARGET_ROM_FLOAT_LD) \ -Wl,-Bstatic \ -Wl,--no-warn-mismatch \ -Wl,--build-id=none \ @@ -258,34 +352,40 @@ LDFLAGS += \ ifeq ($(IDF_TARGET),esp32) LDFLAGS += \ - -Tesp32.rom.newlib-data.ld \ - -Tesp32.rom.syscalls.ld \ - -Tesp32.rom.libc-funcs.ld \ - -Tesp32.rom.newlib-reent-funcs.ld \ - -Tesp32.rom.spiflash_legacy.ld + -Tesp32.rom.libc-funcs.ld + +CFLAGS += -isystem esp-idf/components/esp_driver_touch_sens/hw_ver1/include CHIP_COMPONENTS = \ - esp_driver_dac + esp_driver_dac \ + esp_driver_touch_sens \ + esp_hal_i2s \ + esp_hal_lcd \ + esp_hal_pcnt \ + esp_hal_pmu \ + esp_hal_rmt \ + esp_hal_touch_sens \ + esp_hal_twai else ifeq ($(IDF_TARGET),esp32c2) LDFLAGS += \ -Tesp32c2.rom.ble.ld \ -Tesp32c2.rom.heap.ld \ -Tesp32c2.rom.libc.ld \ - -Tesp32c2.rom.newlib.ld \ - -Tesp32c2.rom.newlib-nano.ld \ -Tesp32c2.rom.version.ld \ -Tesp32c2.rom.systimer.ld \ - -Tesp32c2.rom.wdt.ld + -Trom.wdt.ld CFLAGS += -DSOC_XTAL_FREQ_MHZ=CONFIG_XTAL_FREQ CHIP_COMPONENTS = \ - esp_driver_tsens + esp_driver_tsens \ + esp_hal_dma \ + esp_hal_pmu else ifeq ($(IDF_TARGET),esp32c3) +# esp32c2 has none of: esp_hal_i2s esp_hal_lcd esp_hal_pcnt esp_hal_touch_sens esp_hal_twai LDFLAGS += \ - -Tesp32c3.rom.newlib.ld \ -Tesp32c3.rom.libc.ld \ -Tesp32c3.rom.version.ld \ -Tesp32c3.rom.eco3_bt_funcs.ld \ @@ -293,7 +393,14 @@ LDFLAGS += \ -Tesp32c3.rom.bt_funcs.ld CHIP_COMPONENTS = \ - esp_driver_tsens + esp_driver_tsens \ + esp_driver_usb_serial_jtag \ + esp_hal_dma \ + esp_hal_i2s \ + esp_hal_pmu \ + esp_hal_rmt \ + esp_hal_twai \ + esp_hal_usb else ifeq ($(IDF_TARGET),esp32c6) LDFLAGS += \ @@ -301,15 +408,22 @@ LDFLAGS += \ -Tesp32c6.rom.pp.ld \ -Tesp32c6.rom.net80211.ld \ -Tesp32c6.rom.libc.ld \ - -Tesp32c6.rom.newlib.ld \ -Tesp32c6.rom.coexist.ld \ -Tesp32c6.rom.heap.ld \ -Tesp32c6.rom.systimer.ld \ - -Tesp32c6.rom.wdt.ld + -Trom.wdt.ld CHIP_COMPONENTS = \ - esp_driver_tsens + esp_driver_tsens \ + esp_driver_usb_serial_jtag \ + esp_hal_dma \ + esp_hal_i2s \ + esp_hal_pcnt \ + esp_hal_pmu \ + esp_hal_rmt \ + esp_hal_twai \ + esp_hal_usb else ifeq ($(IDF_TARGET),esp32c61) LDFLAGS += \ @@ -317,62 +431,122 @@ LDFLAGS += \ -Tesp32c61.rom.pp.ld \ -Tesp32c61.rom.net80211.ld \ -Tesp32c61.rom.libc.ld \ - -Tesp32c61.rom.newlib.ld \ -Tesp32c61.rom.version.ld \ -Tesp32c61.rom.coexist.ld \ -Tesp32c61.rom.heap.ld \ -Tesp32c61.rom.systimer.ld \ - -Tesp32c61.rom.wdt.ld + -Trom.wdt.ld CHIP_COMPONENTS = \ - esp_driver_tsens + esp_driver_tsens \ + esp_driver_usb_serial_jtag \ + esp_hal_dma \ + esp_hal_i2s \ + esp_hal_pmu \ + esp_hal_usb else ifeq ($(IDF_TARGET),esp32p4) +CIRCUITPY_ESP32P4_REV ?= 1 +CFLAGS += \ + -isystem esp-idf/components/soc/esp32p4/register/hw_ver$(CIRCUITPY_ESP32P4_REV) \ + -isystem esp-idf/components/esp_hw_support/ldo/include \ + -isystem esp-idf/components/esp_driver_touch_sens/hw_ver3/include + +ifeq ($(CIRCUITPY_ESP32P4_REV),3) +IDF_TARGET_ROM_LD = esp32p4.rom.eco5.ld +IDF_TARGET_ROM_FLOAT_LD = esp32p4.rom.eco5.rvfp.ld +LDFLAGS += \ + -Tesp32p4.rom.systimer.ld \ + -Tesp32p4.rom.eco5.libc.ld \ + -Tesp32p4.rom.version.ld \ + -Trom.wdt.ld +else +IDF_TARGET_ROM_FLOAT_LD = esp32p4.rom.rvfp.ld LDFLAGS += \ -Tesp32p4.rom.libc.ld \ - -Tesp32p4.rom.newlib.ld \ -Tesp32p4.rom.systimer.ld \ - -Tesp32p4.rom.wdt.ld + -Tesp32p4.rom.version.ld \ + -Trom.wdt.ld +endif CHIP_COMPONENTS = \ + esp_driver_touch_sens \ esp_driver_tsens \ - esp_driver_usb_serial_jtag + esp_driver_usb_serial_jtag \ + esp_hal_dma \ + esp_hal_i2s \ + esp_hal_lcd \ + esp_hal_pcnt \ + esp_hal_pmu \ + esp_hal_rmt \ + esp_hal_touch_sens \ + esp_hal_twai \ + esp_hal_usb else ifeq ($(IDF_TARGET),esp32h2) LDFLAGS += \ -Tesp32h2.rom.heap.ld \ -Tesp32h2.rom.libc.ld \ - -Tesp32h2.rom.newlib.ld \ -Tesp32h2.rom.systimer.ld \ - -Tesp32h2.rom.wdt.ld + -Trom.wdt.ld CHIP_COMPONENTS = \ - esp_driver_tsens + esp_driver_tsens \ + esp_driver_usb_serial_jtag \ + esp_hal_dma \ + esp_hal_i2s \ + esp_hal_pcnt \ + esp_hal_pmu \ + esp_hal_rmt \ + esp_hal_twai \ + esp_hal_usb else ifeq ($(IDF_TARGET),esp32s2) +CFLAGS += -isystem esp-idf/components/esp_driver_touch_sens/hw_ver2/include + LDFLAGS += \ -Tesp32s2.rom.libc-funcs.ld \ - -Tesp32s2.rom.newlib-data.ld \ - -Tesp32s2.rom.newlib-reent-funcs.ld \ -Tesp32s2.rom.spiflash_legacy.ld CHIP_COMPONENTS = \ esp_driver_dac \ - esp_driver_tsens + esp_driver_touch_sens \ + esp_driver_tsens \ + esp_hal_dma \ + esp_hal_i2s \ + esp_hal_lcd \ + esp_hal_pcnt \ + esp_hal_pmu \ + esp_hal_rmt \ + esp_hal_touch_sens \ + esp_hal_twai \ + esp_hal_usb else ifeq ($(IDF_TARGET),esp32s3) +CFLAGS += -isystem esp-idf/components/esp_driver_touch_sens/hw_ver2/include + LDFLAGS += \ -Tesp32s3.rom.libc.ld \ - -Tesp32s3.rom.newlib.ld \ -Tesp32s3.rom.version.ld \ -Tesp32s3.rom.systimer.ld \ - -Tesp32s3.rom.wdt.ld \ - -Tesp32s3.rom.bt_funcs.ld + -Tesp32s3.rom.bt_funcs.ld \ + -Trom.wdt.ld CHIP_COMPONENTS = \ - esp_driver_tsens + esp_driver_touch_sens \ + esp_driver_tsens \ + esp_driver_usb_serial_jtag \ + esp_hal_dma \ + esp_hal_i2s \ + esp_hal_lcd \ + esp_hal_pcnt \ + esp_hal_pmu \ + esp_hal_rmt \ + esp_hal_touch_sens \ + esp_hal_twai \ + esp_hal_usb endif @@ -465,6 +639,10 @@ ifneq ($(CIRCUITPY_AUDIOBUSIO),0) CHIP_COMPONENTS += esp_driver_i2s endif +ifneq ($(CIRCUITPY_AUDIOI2SIN),0) +CHIP_COMPONENTS += esp_driver_i2s +endif + ifneq ($(CIRCUITPY_BLEIO_NATIVE),0) SRC_C += common-hal/_bleio/ble_events.c endif @@ -665,17 +843,19 @@ ifeq ($(ENABLE_JTAG), 1) CFLAGS += -DENABLE_JTAG=1 endif -SDKCONFIGS := esp-idf-config/sdkconfig.defaults;$(DEBUG_SDKCONFIG);$(FLASH_SIZE_SDKCONFIG);$(FLASH_MODE_SDKCONFIG);$(FLASH_SPEED_SDKCONFIG);$(PSRAM_SDKCONFIG);$(PSRAM_SIZE_SDKCONFIG);$(PSRAM_MODE_SDKCONFIG);$(PSRAM_SPEED_SDKCONFIG);$(TARGET_SDKCONFIG);boards/$(BOARD)/sdkconfig ifneq ($(CIRCUITPY_BLEIO_NATIVE),0) - SDKCONFIGS := esp-idf-config/sdkconfig-ble.defaults;$(SDKCONFIGS) + BLE_SDKCONFIG := ;esp-idf-config/sdkconfig-ble.defaults endif + +SDKCONFIGS := esp-idf-config/sdkconfig.defaults;$(DEBUG_SDKCONFIG);$(FLASH_SIZE_SDKCONFIG);$(FLASH_MODE_SDKCONFIG);$(FLASH_SPEED_SDKCONFIG);$(PSRAM_SDKCONFIG);$(PSRAM_SIZE_SDKCONFIG);$(PSRAM_MODE_SDKCONFIG);$(PSRAM_SPEED_SDKCONFIG);$(BLE_SDKCONFIG);$(TARGET_SDKCONFIG);boards/$(BOARD)/sdkconfig + # create the config headers .PHONY: do-sdkconfig do-sdkconfig: $(BUILD)/esp-idf/config/sdkconfig.h QSTR_GLOBAL_REQUIREMENTS += $(BUILD)/esp-idf/config/sdkconfig.h $(BUILD)/esp-idf/config/sdkconfig.h: boards/$(BOARD)/sdkconfig boards/$(BOARD)/mpconfigboard.mk CMakeLists.txt | $(BUILD)/esp-idf - $(STEPECHO) "LINK $@" - $(Q)env IDF_PATH=$(IDF_PATH) cmake -S . -B $(BUILD)/esp-idf -DSDKCONFIG=$(BUILD)/esp-idf/sdkconfig -DSDKCONFIG_DEFAULTS="$(SDKCONFIGS)" -DCMAKE_TOOLCHAIN_FILE=$(IDF_PATH)/tools/cmake/toolchain-$(IDF_TARGET).cmake -DIDF_TARGET=$(IDF_TARGET) -GNinja + $(STEPECHO) "Create $@" + $(Q)env IDF_PATH=$(IDF_PATH) IDF_COMPONENT_MANAGER=0 cmake -S . -B $(BUILD)/esp-idf -DSDKCONFIG=$(BUILD)/esp-idf/sdkconfig -DSDKCONFIG_DEFAULTS="$(SDKCONFIGS)" -DCMAKE_TOOLCHAIN_FILE=$(IDF_PATH)/tools/cmake/toolchain-$(IDF_TARGET).cmake -DIDF_TARGET=$(IDF_TARGET) -GNinja $(Q)$(PYTHON) tools/check-sdkconfig.py \ CIRCUITPY_DUALBANK=$(CIRCUITPY_DUALBANK) \ CIRCUITPY_STORAGE_EXTEND=$(CIRCUITPY_STORAGE_EXTEND) \ @@ -723,7 +903,7 @@ ifeq ($(IDF_TARGET),esp32) BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/librtc.a endif -ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) $(CHIP_COMPONENTS) app_update bootloader_support driver esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_ledc esp_driver_spi esp_driver_uart efuse esp_adc esp_app_format esp_common esp_event esp_hw_support esp_mm esp_partition esp_pm esp_ringbuf esp_rom esp_system esp_timer freertos hal heap log newlib nvs_flash pthread soc spi_flash vfs esp_vfs_console +ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) $(CHIP_COMPONENTS) app_update bootloader_support driver esp_driver_dma esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_ledc esp_driver_spi esp_driver_uart efuse esp_adc esp_app_format esp_common esp_event esp_gdbstub esp_hal_ana_conv esp_hal_clock esp_hal_gpio esp_hal_gpspi esp_hal_i2c esp_hal_ledc esp_hal_mspi esp_hal_security esp_hal_timg esp_hal_uart esp_hal_wdt esp_hw_support esp_mm esp_partition esp_pm esp_ringbuf esp_rom esp_system esp_timer freertos hal heap log esp_libc nvs_flash nvs_sec_provider pthread soc spi_flash vfs esp_stdio ifneq ($(CIRCUITPY_WIFI),0) ESP_IDF_COMPONENTS_LINK += esp_coex esp_netif esp_security esp-tls esp_wifi lwip mbedtls mdns wpa_supplicant esp_phy endif @@ -777,17 +957,21 @@ endif ifneq ($(CIRCUITPY_PARALLELDISPLAYBUS),0) ESP_IDF_COMPONENTS_LINK += esp_lcd endif -ifneq ($(CIRCUITPY_USB_DEVICE),0) - ESP_IDF_COMPONENTS_LINK += usb +ifneq ($(CIRCUITPY_QSPIBUS),0) + ESP_IDF_COMPONENTS_LINK += esp_lcd endif ifneq ($(CIRCUITPY_SDIOIO),0) - ESP_IDF_COMPONENTS_LINK += sdmmc esp_driver_sdmmc + ESP_IDF_COMPONENTS_LINK += sdmmc esp_driver_sdmmc esp_driver_sd_intf esp_hal_sd endif ESP_IDF_COMPONENTS_EXPANDED = $(foreach component, $(ESP_IDF_COMPONENTS_LINK), $(BUILD)/esp-idf/esp-idf/$(component)/lib$(component).a) MBEDTLS_COMPONENTS_LINK = crypto tls x509 MBEDTLS_COMPONENTS_LINK_EXPANDED = $(foreach component, $(MBEDTLS_COMPONENTS_LINK), $(BUILD)/esp-idf/esp-idf/mbedtls/mbedtls/library/libmbed$(component).a) +MBEDTLS_COMPONENTS_LINK_EXPANDED += $(BUILD)/esp-idf/esp-idf/mbedtls/mbedtls/library/libtfpsacrypto.a +MBEDTLS_COMPONENTS_LINK_EXPANDED += $(BUILD)/esp-idf/esp-idf/mbedtls/mbedtls/tf-psa-crypto/drivers/builtin/libmbed-builtin.a +MBEDTLS_COMPONENTS_LINK_EXPANDED += $(BUILD)/esp-idf/esp-idf/mbedtls/mbedtls/tf-psa-crypto/drivers/everest/libeverest.a +MBEDTLS_COMPONENTS_LINK_EXPANDED += $(BUILD)/esp-idf/esp-idf/mbedtls/mbedtls/tf-psa-crypto/drivers/p256-m/libp256m.a ifeq ($(IDF_TARGET_ARCH),xtensa) BINARY_BLOBS += esp-idf/components/xtensa/$(IDF_TARGET)/libxt_hal.a @@ -864,9 +1048,9 @@ else ESPTOOLPY_FLASHFREQ = $(CIRCUITPY_ESP_FLASH_FREQ) endif -FLASH_FLAGS = --flash_mode $(ESPTOOLPY_FLASHMODE) --flash_freq $(ESPTOOLPY_FLASHFREQ) --flash_size $(CIRCUITPY_ESP_FLASH_SIZE) +FLASH_FLAGS = --flash-mode $(ESPTOOLPY_FLASHMODE) --flash-freq $(ESPTOOLPY_FLASHFREQ) --flash-size $(CIRCUITPY_ESP_FLASH_SIZE) -ESPTOOL_FLAGS ?= --before=default_reset --after=no_reset --baud 921600 +ESPTOOL_FLAGS ?= --before=default-reset --after=no-reset --baud 921600 ifeq ($(UF2_BOOTLOADER),1) all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 @@ -886,7 +1070,7 @@ $(BUILD)/firmware.elf: $(OBJ) | esp-idf-stamp $(IDF_CMAKE_TARGETS) $(BUILD)/circuitpython-firmware.bin: $(BUILD)/firmware.elf | tools/build_memory_info.py $(STEPECHO) "Create $@" - $(Q)esptool.py --chip $(IDF_TARGET) elf2image $(FLASH_FLAGS) --elf-sha256-offset 0xb0 -o $@ $^ + $(Q)esptool --chip $(IDF_TARGET) elf2image $(FLASH_FLAGS) --elf-sha256-offset 0xb0 -o $@ $^ $(Q)$(PYTHON) tools/build_memory_info.py $< $(BUILD)/esp-idf/sdkconfig $@ $(BUILD) ifeq ($(VALID_BOARD),) @@ -905,10 +1089,10 @@ $(BUILD)/firmware.uf2: $(BUILD)/circuitpython-firmware.bin $(Q)$(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID_$(IDF_TARGET)) -b 0x0000 -c -o $@ $^ flash: $(BUILD)/firmware.bin - esptool.py --chip $(IDF_TARGET) -p $(PORT) $(ESPTOOL_FLAGS) write_flash $(FLASH_FLAGS) 0x0000 $^ + esptool --chip $(IDF_TARGET) -p $(PORT) $(ESPTOOL_FLAGS) write-flash $(FLASH_FLAGS) 0x0000 $^ flash-circuitpython-only: $(BUILD)/circuitpython-firmware.bin - esptool.py --chip $(IDF_TARGET) -p $(PORT) $(ESPTOOL_FLAGS) write_flash $(FLASH_FLAGS) $(FIRMWARE_OFFSET) $^ + esptool --chip $(IDF_TARGET) -p $(PORT) $(ESPTOOL_FLAGS) write-flash $(FLASH_FLAGS) $(FIRMWARE_OFFSET) $^ monitor: $(BUILD)/firmware.elf cp $< build/circuitpython.elf diff --git a/ports/espressif/background.c b/ports/espressif/background.c index 61615c01615..b1b81ac2c83 100644 --- a/ports/espressif/background.c +++ b/ports/espressif/background.c @@ -13,8 +13,8 @@ #include "freertos/task.h" void port_background_tick(void) { - // Zero delay in case FreeRTOS wants to switch to something else. - vTaskDelay(0); + // Yield with zero delay in case FreeRTOS wants to switch to something else. + port_task_yield(); } void port_background_task(void) { diff --git a/ports/espressif/bindings/espcamera/Camera.c b/ports/espressif/bindings/espcamera/Camera.c index 712ff8827d7..9a74824a053 100644 --- a/ports/espressif/bindings/espcamera/Camera.c +++ b/ports/espressif/bindings/espcamera/Camera.c @@ -179,7 +179,7 @@ static void check_for_deinit(espcamera_camera_obj_t *self) { static mp_obj_t espcamera_camera_frame_available_get(const mp_obj_t self_in) { espcamera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); - return mp_obj_new_bool(esp_camera_fb_available()); + return mp_obj_new_bool(common_hal_espcamera_camera_available(self)); } static MP_DEFINE_CONST_FUN_OBJ_1(espcamera_camera_frame_available_get_obj, espcamera_camera_frame_available_get); diff --git a/ports/espressif/bindings/espidf/__init__.c b/ports/espressif/bindings/espidf/__init__.c index 012ed7d9f9a..897da0eb571 100644 --- a/ports/espressif/bindings/espidf/__init__.c +++ b/ports/espressif/bindings/espidf/__init__.c @@ -106,7 +106,7 @@ MP_DEFINE_CONST_OBJ_TYPE( //| ... //| //| -NORETURN void mp_raise_espidf_MemoryError(void) { +MP_NORETURN void mp_raise_espidf_MemoryError(void) { nlr_raise(mp_obj_new_exception(&mp_type_espidf_MemoryError)); } diff --git a/ports/espressif/bindings/espidf/__init__.h b/ports/espressif/bindings/espidf/__init__.h index 7c112abf736..92d2e0c2769 100644 --- a/ports/espressif/bindings/espidf/__init__.h +++ b/ports/espressif/bindings/espidf/__init__.h @@ -15,9 +15,9 @@ extern const mp_obj_type_t mp_type_espidf_IDFError; extern const mp_obj_type_t mp_type_espidf_MemoryError; -NORETURN void mp_raise_espidf_MemoryError(void); +MP_NORETURN void mp_raise_espidf_MemoryError(void); -void raise_esp_error(esp_err_t err) NORETURN; +void raise_esp_error(esp_err_t err) MP_NORETURN; #define CHECK_ESP_RESULT(x) do { int res = (x); if (res != ESP_OK) raise_esp_error(res); } while (0) size_t common_hal_espidf_get_total_psram(void); diff --git a/ports/espressif/bindings/espnow/ESPNow.c b/ports/espressif/bindings/espnow/ESPNow.c index 01cc06e3be4..345d51b6dff 100644 --- a/ports/espressif/bindings/espnow/ESPNow.c +++ b/ports/espressif/bindings/espnow/ESPNow.c @@ -40,6 +40,8 @@ static void espnow_check_for_deinit(espnow_obj_t *self) { //| :param int buffer_size: The size of the internal ring buffer. Default: 526 bytes. //| :param int phy_rate: The ESP-NOW physical layer rate. Default: 1 Mbps. //| `wifi_phy_rate_t `_ +//| +//| **Limitations:** Currently, setting ``phy_rate`` does nothing. The rate is always 1 Mbps. //| """ //| ... //| @@ -231,6 +233,8 @@ MP_PROPERTY_GETTER(espnow_buffer_size_obj, //| phy_rate: int //| """The ESP-NOW physical layer rate. //| `wifi_phy_rate_t `_ +//| +//| **Limitations:** Currently, setting ``phy_rate`` does nothing. The rate is always 1 Mbps. //| """ //| static mp_obj_t espnow_get_phy_rate(const mp_obj_t self_in) { diff --git a/ports/espressif/boards/adafruit_esp32s3_camera/mpconfigboard.mk b/ports/espressif/boards/adafruit_esp32s3_camera/mpconfigboard.mk index d1b6d503125..62b6d3612b3 100644 --- a/ports/espressif/boards/adafruit_esp32s3_camera/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_esp32s3_camera/mpconfigboard.mk @@ -16,6 +16,7 @@ CIRCUITPY_ESP_PSRAM_FREQ = 80m CIRCUITPY_ESPCAMERA = 1 CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOI2SIN = 0 CIRCUITPY_CANIO = 0 CIRCUITPY_DUALBANK = 0 CIRCUITPY_FRAMEBUFFERIO = 0 diff --git a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c index 1437f75165d..61659755be2 100644 --- a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c +++ b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c @@ -7,9 +7,11 @@ #include "supervisor/board.h" #include "mpconfigboard.h" +#include "driver/gpio.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/fourwire/FourWire.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-module/displayio/__init__.h" #include "supervisor/shared/board.h" @@ -127,6 +129,52 @@ const uint8_t ssd1680_display_start_sequence[] = { 0x22, 0x00, 0x01, 0xc7 // display update mode }; +// FPC-7519rev.b panels (User ID byte 0x44 or 0xca) need colstart=8 and tuned VCOM + LUT. +// LUT: Good Display reference (GxEPD2_4G / GDEM029T94) with VS rows reversed (L0↔L3, L1↔L2). +// Reason: CircuitPython maps luma 0→L0 and luma 255→L3. On this panel VSH1(0x40) drives WHITE and +// VSL(0x20) drives BLACK, so L0 must carry the black-driving waveform and L3 the white-driving +// waveform — opposite from GxEPD2_4G's Arduino convention (where index 0 = white constant). +// VS=0x48 = VSH1/GND/VSL/GND alternating for DC balance. +// VCOM=0x24 empirically tuned for FPC-7519rev.b contrast. Both 0x44 and 0xca share this sequence. +const uint8_t ssd1680_fpc7519_display_start_sequence[] = { + 0x12, DELAY, 0x00, 0x14, // soft reset and wait 20ms + 0x11, 0x00, 0x01, 0x03, // Ram data entry mode + 0x3c, 0x00, 0x01, 0x03, // border color + 0x2c, 0x00, 0x01, 0x24, // Set vcom voltage (0x24 tuned for FPC-7519rev.b contrast) + 0x03, 0x00, 0x01, 0x17, // Set gate voltage + 0x04, 0x00, 0x03, 0x41, 0xae, 0x32, // Set source voltage + 0x4e, 0x00, 0x01, 0x01, // ram x count + 0x4f, 0x00, 0x02, 0x00, 0x00, // ram y count + 0x01, 0x00, 0x03, 0x27, 0x01, 0x00, // set display size + 0x32, 0x00, 0x99, // Update waveforms (153 bytes follow) + // VS rows: only L0↔L3 are swapped relative to GxEPD2_4G; L1 and L2 stay in place. + // Reason: CircuitPython luma maps 0→L0, 64-127→L2, 128-191→L1, 255→L3. + // GxEPD2 uses L0=white-driver, L3=black-driver (opposite of CircuitPython for extremes). + // GxEPD2 L1=lighter-gray, L2=darker-gray; CircuitPython L1=mid-bright, L2=mid-dark — same ordering. + // So: swap only L0↔L3 (polarity); L1 and L2 keep their GxEPD2 positions (gradient preserved). + // 0x48 = VSH1/GND/VSL/GND alternating — better DC balance than 0x60 (VSH1/VSL/GND/GND) + 0x20, 0x48, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L0 (darkest/black) ← GxEPD2 L3 + 0x08, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L1 (mid-light) ← GxEPD2 L1 (luma 128-191 → lighter) + 0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L2 (mid-dark) ← GxEPD2 L2 (luma 64-127 → darker) + 0x40, 0x48, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L3 (lightest/white) ← GxEPD2 L0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L4 VCOM + // Timing groups — Good Display reference timing + 0x0A, 0x19, 0x00, 0x03, 0x08, 0x00, 0x00, // Group0: 10+25 / 3+8 frames activation + 0x14, 0x01, 0x00, 0x14, 0x01, 0x00, 0x03, // Group1: 20+1 / 20+1 frames, RP=3 repeats + 0x0A, 0x03, 0x00, 0x08, 0x19, 0x00, 0x00, // Group2: 10+3 / 8+25 frames (mirror of G0) + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // Group3: 1 frame settle + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group6 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group11 + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, // XON + 0x22, 0x00, 0x01, 0xc7 // display update mode +}; + const uint8_t ssd1680_display_stop_sequence[] = { 0x10, DELAY, 0x01, 0x01, 0x64 }; @@ -139,18 +187,23 @@ const uint8_t ssd1680_display_refresh_sequence[] = { typedef enum { DISPLAY_IL0373, DISPLAY_SSD1680_COLSTART_0, - DISPLAY_SSD1680_COLSTART_8, + DISPLAY_SSD1680_COLSTART_8, // FPC-7519rev.b (User ID 0x44 or 0xca) } display_type_t; static display_type_t detect_display_type(void) { - // Bitbang 4-wire SPI with a bidirectional data line to read the first word of register 0x2e, + // Bitbang 4-wire SPI with a bidirectional data line to read the first byte of register 0x2e, // which is the 10-byte USER ID. + // NOTE: the SSD1680 drives its response back on the MOSI/DATA line (GPIO35) in half-duplex + // mode, NOT on the separate MISO line (GPIO37). Read with GPIO35 switched to input. // On the IL0373 it will return 0xff because it's not a valid register. // With SSD1680, we have seen two types: // 1. The first batch of displays, labeled "FPC-A005 20.06.15 TRX", which needs colstart=0. - // These have 10 byes of zeros in the User ID - // 2. Second batch, labeled "FPC-7619rev.b", which needs colstart=8. - // The USER ID for these boards is [0x44, 0x0, 0x4, 0x0, 0x25, 0x0, 0x1, 0x78, 0x2b, 0xe] + // These have 10 bytes of zeros in the User ID. + // 2. Later panels, labeled "FPC-7519rev.b", which need colstart=8 and a tuned LUT/VCOM. + // Two controller variants exist within this panel generation: + // User ID [0x44, 0x0, 0x4, 0x0, 0x25, 0x0, 0x1, 0x78, 0x2b, 0xe] + // User ID [0xca, 0xfe, 0x0, 0x16, 0x80, 0x0, 0x75, 0x1, 0x0, 0x98] + // Both carry the same ribbon label and show the same display characteristics. // So let's distinguish just by the first byte. digitalio_digitalinout_obj_t data; digitalio_digitalinout_obj_t clock; @@ -173,9 +226,15 @@ static display_type_t detect_display_type(void) { common_hal_digitalio_digitalinout_switch_to_output(&chip_select, false, DRIVE_MODE_PUSH_PULL); common_hal_digitalio_digitalinout_switch_to_output(&data_command, false, DRIVE_MODE_PUSH_PULL); common_hal_digitalio_digitalinout_switch_to_output(&data, false, DRIVE_MODE_PUSH_PULL); - common_hal_digitalio_digitalinout_switch_to_output(&reset, true, DRIVE_MODE_PUSH_PULL); common_hal_digitalio_digitalinout_switch_to_output(&clock, false, DRIVE_MODE_PUSH_PULL); + // Pulse RESET low to wake SSD1680 from deep sleep (entered via stop_sequence on prior run). + // SSD1680 ignores all SPI commands while in deep sleep; only a hardware reset exits it. + common_hal_digitalio_digitalinout_switch_to_output(&reset, false, DRIVE_MODE_PUSH_PULL); + common_hal_mcu_delay_us(200); + common_hal_digitalio_digitalinout_set_value(&reset, true); + common_hal_mcu_delay_us(10000); // 10ms for controller to come out of reset + uint8_t status_read = 0x2e; // SSD1680 User ID register. Not a valid register on IL0373. for (int i = 0; i < 8; i++) { common_hal_digitalio_digitalinout_set_value(&data, (status_read & (1 << (7 - i))) != 0); @@ -209,10 +268,11 @@ static display_type_t detect_display_type(void) { switch (status) { case 0xff: return DISPLAY_IL0373; - default: // who knows? Just guess. case 0x00: return DISPLAY_SSD1680_COLSTART_0; + default: // unknown SSD1680 variant — assume newer panel needs colstart=8 case 0x44: + case 0xca: return DISPLAY_SSD1680_COLSTART_8; } } @@ -261,13 +321,15 @@ void board_init(void) { common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } else { epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; - // Default colstart is 0. + args.bus = bus; if (display_type == DISPLAY_SSD1680_COLSTART_8) { args.colstart = 8; + args.start_sequence = ssd1680_fpc7519_display_start_sequence; + args.start_sequence_len = sizeof(ssd1680_fpc7519_display_start_sequence); + } else { + args.start_sequence = ssd1680_display_start_sequence; + args.start_sequence_len = sizeof(ssd1680_display_start_sequence); } - args.bus = bus; - args.start_sequence = ssd1680_display_start_sequence; - args.start_sequence_len = sizeof(ssd1680_display_start_sequence); args.stop_sequence = ssd1680_display_stop_sequence; args.stop_sequence_len = sizeof(ssd1680_display_stop_sequence); args.width = 296; diff --git a/ports/espressif/boards/adafruit_p4gpio/board.c b/ports/espressif/boards/adafruit_p4gpio/board.c new file mode 100644 index 00000000000..8287c3ea247 --- /dev/null +++ b/ports/espressif/boards/adafruit_p4gpio/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/adafruit_p4gpio/mpconfigboard.h b/ports/espressif/boards/adafruit_p4gpio/mpconfigboard.h new file mode 100644 index 00000000000..294896c5c34 --- /dev/null +++ b/ports/espressif/boards/adafruit_p4gpio/mpconfigboard.h @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Adafruit P4 GPIO" +#define MICROPY_HW_MCU_NAME "ESP32P4" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO52) + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO35) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO54) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO53) + +// Use the second USB device (numbered 0 and 1) -- HS PHY routed to J1. +#define CIRCUITPY_USB_DEVICE_INSTANCE 1 +#define CIRCUITPY_USB_DEVICE_HIGH_SPEED (1) + +// FS USB on GPIO24/25 routed to J2. +#define CIRCUITPY_USB_HOST_INSTANCE 0 diff --git a/ports/espressif/boards/adafruit_p4gpio/mpconfigboard.mk b/ports/espressif/boards/adafruit_p4gpio/mpconfigboard.mk new file mode 100644 index 00000000000..dc1560b2bb5 --- /dev/null +++ b/ports/espressif/boards/adafruit_p4gpio/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x239A +USB_PID = 0x8174 +USB_PRODUCT = "Adafruit P4 GPIO" +USB_MANUFACTURER = "Adafruit" + +IDF_TARGET = esp32p4 + +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 32MB +CIRCUITPY_ESP_PSRAM_MODE = hpi +CIRCUITPY_ESP_PSRAM_FREQ = 200m diff --git a/ports/espressif/boards/adafruit_p4gpio/pins.c b/ports/espressif/boards/adafruit_p4gpio/pins.c new file mode 100644 index 00000000000..77ed1f89513 --- /dev/null +++ b/ports/espressif/boards/adafruit_p4gpio/pins.c @@ -0,0 +1,85 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Header J8 (B1) + { MP_ROM_QSTR(MP_QSTR_B1_0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_B1_1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_B1_2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_B1_3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_B1_4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_B1_5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_B1_6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_B1_7), MP_ROM_PTR(&pin_GPIO7) }, + + // Header J7 (B2) + { MP_ROM_QSTR(MP_QSTR_B2_0), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_B2_1), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_B2_2), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_B2_3), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_B2_4), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_B2_5), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_B2_6), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_B2_7), MP_ROM_PTR(&pin_GPIO15) }, + + // Header J6 (B3) + { MP_ROM_QSTR(MP_QSTR_B3_0), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_B3_1), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_B3_2), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_B3_3), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_B3_4), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_B3_5), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_B3_6), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_B3_7), MP_ROM_PTR(&pin_GPIO23) }, + + // Header J3 (T3) + { MP_ROM_QSTR(MP_QSTR_T3_0), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_T3_1), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_T3_2), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_T3_3), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_T3_4), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_T3_5), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_T3_6), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_T3_7), MP_ROM_PTR(&pin_GPIO26) }, + + // Header J4 (T2) + { MP_ROM_QSTR(MP_QSTR_T2_0), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_T2_1), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_T2_2), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_T2_3), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_T2_4), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_T2_5), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_T2_6), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_T2_7), MP_ROM_PTR(&pin_GPIO34) }, + + // Header J5 (T1) + { MP_ROM_QSTR(MP_QSTR_T1_0), MP_ROM_PTR(&pin_GPIO51) }, + { MP_ROM_QSTR(MP_QSTR_T1_1), MP_ROM_PTR(&pin_GPIO50) }, + { MP_ROM_QSTR(MP_QSTR_T1_2), MP_ROM_PTR(&pin_GPIO49) }, + { MP_ROM_QSTR(MP_QSTR_T1_3), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_T1_4), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_T1_5), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_T1_6), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_T1_7), MP_ROM_PTR(&pin_GPIO44) }, + + // Boot button (also exposed on J9/J10 pin 2) + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO35) }, + + // NeoPixel + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO52) }, + + // StemmaQT / Qwiic I2C (J11) + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO53) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO54) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/adafruit_p4gpio/sdkconfig b/ports/espressif/boards/adafruit_p4gpio/sdkconfig new file mode 100644 index 00000000000..681e52bf82c --- /dev/null +++ b/ports/espressif/boards/adafruit_p4gpio/sdkconfig @@ -0,0 +1,70 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Bootloader config +# +# +# Log +# +# +# Format +# +# CONFIG_BOOTLOADER_LOG_COLORS is not set +# end of Format + +# end of Log + +# default: +CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ=90 +# +# Serial Flash Configurations +# +# CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT is not set +# end of Serial Flash Configurations + +# end of Bootloader config + +# +# Component config +# +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +# end of Bluetooth + +# +# Hardware Settings +# +# +# Chip revision +# +CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y +CONFIG_ESP32P4_REV_MIN_100=y +# default: +CONFIG_ESP32P4_REV_MIN_FULL=100 +# default: +CONFIG_ESP_REV_MIN_FULL=100 +# default: +CONFIG_ESP32P4_REV_MAX_FULL=199 +# default: +CONFIG_ESP_REV_MAX_FULL=199 +# end of Chip revision + +# end of Hardware Settings + +# +# ESP System Settings +# +# default: +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_360=y +# default: +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_400 is not set +# default: +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=360 +# end of ESP System Settings + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.h b/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.h index ad97ab057fb..9760bbfeb44 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.h +++ b/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.h @@ -25,3 +25,6 @@ #define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO5, .rx = &pin_GPIO16}} #define DOUBLE_TAP_PIN (&pin_GPIO10) + +// Reduce wifi.radio.tx_power due to the antenna design of this board +#define CIRCUITPY_WIFI_DEFAULT_TX_POWER (15) diff --git a/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h b/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h index fcdefda3b40..6073bd47d0e 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h +++ b/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h @@ -25,3 +25,6 @@ #define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO5, .rx = &pin_GPIO16}} #define DOUBLE_TAP_PIN (&pin_GPIO10) + +// Reduce wifi.radio.tx_power due to the antenna design of this board +#define CIRCUITPY_WIFI_DEFAULT_TX_POWER (15) diff --git a/ports/espressif/boards/adafruit_sparkle_motion/pins.c b/ports/espressif/boards/adafruit_sparkle_motion/pins.c index d78c1e1c4c7..f22cb50608d 100644 --- a/ports/espressif/boards/adafruit_sparkle_motion/pins.c +++ b/ports/espressif/boards/adafruit_sparkle_motion/pins.c @@ -46,6 +46,10 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SIG4), MP_ROM_PTR(&pin_GPIO23) }, { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_D26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_D33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO9) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, diff --git a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk index 9ca2eee1577..e51bdc7d8cc 100644 --- a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk +++ b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk @@ -9,6 +9,12 @@ CIRCUITPY_ESP_FLASH_SIZE = 2MB CIRCUITPY_DUALBANK = 0 +CIRCUITPY_AESIO = 0 +CIRCUITPY_CANIO = 0 +CIRCUITPY_GETPASS = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 +CIRCUITPY_PS2IO = 0 +CIRCUITPY_ZLIB = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig index 5fd531f274a..79713bb57e8 100644 --- a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig +++ b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig @@ -21,6 +21,18 @@ # CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS is not set # end of LibC +# +# mbedTLS +# +# +# Certificate Bundle +# +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y +# end of Certificate Bundle +# +# end of mbedTLS + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/elecrow_crowpanel_3.5/board.c b/ports/espressif/boards/elecrow_crowpanel_3.5/board.c index 0748e03fce8..f52f23a9ae8 100755 --- a/ports/espressif/boards/elecrow_crowpanel_3.5/board.c +++ b/ports/espressif/boards/elecrow_crowpanel_3.5/board.c @@ -54,9 +54,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - MP_OBJ_FROM_PTR(&pin_GPIO2), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO2), // TFT_DC Command or data MP_OBJ_FROM_PTR(&pin_GPIO15), // TFT_CS Chip select - NULL, // TFT_RST Reset + mp_const_none, // TFT_RST Reset 20000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/espressif_esp32p4_function_ev/sdkconfig b/ports/espressif/boards/espressif_esp32p4_function_ev/sdkconfig index e69de29bb2d..3bce8cc0c13 100644 --- a/ports/espressif/boards/espressif_esp32p4_function_ev/sdkconfig +++ b/ports/espressif/boards/espressif_esp32p4_function_ev/sdkconfig @@ -0,0 +1,2 @@ +CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y +CONFIG_ESP32P4_REV_MIN_100=y diff --git a/ports/espressif/boards/espressif_esp32p4x_function_ev/board.c b/ports/espressif/boards/espressif_esp32p4x_function_ev/board.c new file mode 100644 index 00000000000..a3a9eec0471 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32p4x_function_ev/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32p4x_function_ev/mpconfigboard.h b/ports/espressif/boards/espressif_esp32p4x_function_ev/mpconfigboard.h new file mode 100644 index 00000000000..d0b44fdff58 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32p4x_function_ev/mpconfigboard.h @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "ESP32-P4X-Function-EV" +#define MICROPY_HW_MCU_NAME "ESP32P4" + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO38) +#define DEFAULT_UART_BUS_TX (&pin_GPIO37) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO8) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO7) + +// Use the second USB device (numbered 0 and 1) +#define CIRCUITPY_USB_DEVICE_INSTANCE 1 +#define CIRCUITPY_USB_DEVICE_HIGH_SPEED (1) + +#define CIRCUITPY_USB_HOST_INSTANCE 0 diff --git a/ports/espressif/boards/espressif_esp32p4x_function_ev/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32p4x_function_ev/mpconfigboard.mk new file mode 100644 index 00000000000..bad638a0018 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32p4x_function_ev/mpconfigboard.mk @@ -0,0 +1,16 @@ +USB_VID = 0x303A +USB_PID = 0x7014 +USB_PRODUCT = "ESP32-P4X-Function-EV" +USB_MANUFACTURER = "Espressif" + +IDF_TARGET = esp32p4 + +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 32MB +CIRCUITPY_ESP_PSRAM_MODE = hpi +CIRCUITPY_ESP_PSRAM_FREQ = 200m + +CIRCUITPY_ESP32P4_REV = 3 diff --git a/ports/espressif/boards/espressif_esp32p4x_function_ev/pins.c b/ports/espressif/boards/espressif_esp32p4x_function_ev/pins.c new file mode 100644 index 00000000000..165ce711b73 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32p4x_function_ev/pins.c @@ -0,0 +1,90 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Header Block J1 + { MP_ROM_QSTR(MP_QSTR_I2C_SDA), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_I2C_SCL), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_C6_WAKEUP), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_ROM_QSTR(MP_QSTR_IO32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_IO24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_C6_EN), MP_ROM_PTR(&pin_GPIO54) }, + { MP_ROM_QSTR(MP_QSTR_IO54), MP_ROM_PTR(&pin_GPIO54) }, + + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + { MP_ROM_QSTR(MP_QSTR_PA_CTRL), MP_ROM_PTR(&pin_GPIO53) }, + { MP_ROM_QSTR(MP_QSTR_IO53), MP_ROM_PTR(&pin_GPIO53) }, + + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) }, + + // I2S + { MP_ROM_QSTR(MP_QSTR_I2S_DSDIN), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_I2S_LRCK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_I2S_ASDOUT), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_I2S_SCLK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_ROM_PTR(&pin_GPIO13) }, + + // Ethernet + { MP_ROM_QSTR(MP_QSTR_RMII_RXDV), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_RMII_RXD0), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_RMII_RXD1), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_MDC), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_RMII_TXD0), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_RMII_TXD1), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_RMII_TXEN), MP_ROM_PTR(&pin_GPIO49) }, + { MP_ROM_QSTR(MP_QSTR_RMII_CLK), MP_ROM_PTR(&pin_GPIO50) }, + { MP_ROM_QSTR(MP_QSTR_PHY_RSTN), MP_ROM_PTR(&pin_GPIO51) }, + { MP_ROM_QSTR(MP_QSTR_MDIO), MP_ROM_PTR(&pin_GPIO52) }, + + // SD Card + { MP_ROM_QSTR(MP_QSTR_SD_DATA0), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_SD_DATA1), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_SD_DATA2), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_SD_DATA3), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_SD_CMD), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_SD_PWRN), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32p4x_function_ev/sdkconfig b/ports/espressif/boards/espressif_esp32p4x_function_ev/sdkconfig new file mode 100644 index 00000000000..a062a5b5c48 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32p4x_function_ev/sdkconfig @@ -0,0 +1,68 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Bootloader config +# +# +# Log +# +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +# CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set +# default: +CONFIG_BOOTLOADER_LOG_LEVEL=2 +# +# Format +# +# CONFIG_BOOTLOADER_LOG_COLORS is not set +# end of Format + +# end of Log + +# end of Bootloader config + +# +# Component config +# +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +# end of Bluetooth + +# +# Hardware Settings +# +# +# Chip revision +# +# CONFIG_ESP32P4_REV_MIN_300 is not set +CONFIG_ESP32P4_REV_MIN_301=y +# default: +CONFIG_ESP32P4_REV_MIN_FULL=301 +# default: +CONFIG_ESP_REV_MIN_FULL=301 +# end of Chip revision + +# default: +CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND=y +# default: +CONFIG_P4_REV3_MSPI_WORKAROUND_SIZE=0x100 +# end of Hardware Settings + +# +# ESP-STDIO +# +# CONFIG_ESP_CONSOLE_UART_DEFAULT is not set +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y +# default: +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +# default: +CONFIG_ESP_CONSOLE_UART_NUM=-1 +# default: +CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=6 +# end of ESP-STDIO + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.mk index 336b9f4dd89..b6ae3cf73b4 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.mk @@ -13,4 +13,4 @@ CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m -CIRCUITPY_RCLCPY = 1 +CIRCUITPY_RCLCPY = 0 diff --git a/ports/espressif/boards/espressif_esp32s3_eye/board.c b/ports/espressif/boards/espressif_esp32s3_eye/board.c index 09a05cc72c4..43445b034e4 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/board.c +++ b/ports/espressif/boards/espressif_esp32s3_eye/board.c @@ -58,7 +58,7 @@ void board_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO43), // DC MP_OBJ_FROM_PTR(&pin_GPIO44), // CS - NULL, // no reset pin + mp_const_none, // no reset pin 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/board.c b/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/board.c index 3b5aa06b676..96513a14741 100644 --- a/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/board.c +++ b/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/board.c @@ -7,6 +7,7 @@ #include "supervisor/board.h" #include "mpconfigboard.h" #include "shared-bindings/microcontroller/Pin.h" +#include "driver/gpio.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/fourwire/FourWire.h" diff --git a/ports/espressif/boards/hardkernel_odroid_go/board.c b/ports/espressif/boards/hardkernel_odroid_go/board.c index 5a8b6ccaefe..0c2fe8a87c3 100644 --- a/ports/espressif/boards/hardkernel_odroid_go/board.c +++ b/ports/espressif/boards/hardkernel_odroid_go/board.c @@ -6,6 +6,7 @@ #include "supervisor/board.h" #include "mpconfigboard.h" +#include "driver/gpio.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/fourwire/FourWire.h" #include "shared-module/displayio/__init__.h" @@ -52,8 +53,8 @@ void board_init(void) { common_hal_fourwire_fourwire_construct(bus, spi, MP_OBJ_FROM_PTR(&pin_GPIO21), // TFT_DC Command or data - MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select - NULL, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select + mp_const_none, // TFT_RST Reset 40000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/hiibot_iots2/board.c b/ports/espressif/boards/hiibot_iots2/board.c index e4bff05822c..e3af7b45835 100644 --- a/ports/espressif/boards/hiibot_iots2/board.c +++ b/ports/espressif/boards/hiibot_iots2/board.c @@ -64,7 +64,7 @@ static void display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO35), // DC MP_OBJ_FROM_PTR(&pin_GPIO36), // CS - NULL, // NO RST ? + mp_const_none, // NO RST ? 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/lilygo_tdeck/board.c b/ports/espressif/boards/lilygo_tdeck/board.c index a1008f2173f..45b889760a1 100644 --- a/ports/espressif/boards/lilygo_tdeck/board.c +++ b/ports/espressif/boards/lilygo_tdeck/board.c @@ -34,7 +34,7 @@ void board_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO11), // TFT_DC Command or data MP_OBJ_FROM_PTR(&pin_GPIO12), // TFT_CS Chip select - NULL, // TFT_RST Reset + mp_const_none, // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/lilygo_tdisplay_s3/board.c b/ports/espressif/boards/lilygo_tdisplay_s3/board.c index fe62edf1ed8..a02dab7173d 100644 --- a/ports/espressif/boards/lilygo_tdisplay_s3/board.c +++ b/ports/espressif/boards/lilygo_tdisplay_s3/board.c @@ -6,6 +6,7 @@ #include "supervisor/board.h" #include "mpconfigboard.h" +#include "driver/gpio.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-module/displayio/__init__.h" #include "shared-module/displayio/mipi_constants.h" diff --git a/ports/espressif/boards/lilygo_twatch_2020_v3/board.c b/ports/espressif/boards/lilygo_twatch_2020_v3/board.c index e88a82ea24f..5ea85ec00c6 100644 --- a/ports/espressif/boards/lilygo_twatch_2020_v3/board.c +++ b/ports/espressif/boards/lilygo_twatch_2020_v3/board.c @@ -48,7 +48,7 @@ static void display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO27), // DC MP_OBJ_FROM_PTR(&pin_GPIO5), // CS - NULL, // RST + mp_const_none, // RST 24000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/lilygo_twatch_s3/board.c b/ports/espressif/boards/lilygo_twatch_s3/board.c index 801914a4991..a9fd3db46e7 100644 --- a/ports/espressif/boards/lilygo_twatch_s3/board.c +++ b/ports/espressif/boards/lilygo_twatch_s3/board.c @@ -110,7 +110,7 @@ void board_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO38), // DC MP_OBJ_FROM_PTR(&pin_GPIO12), // CS - NULL, // RST + mp_const_none, // RST 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk b/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk index ede48c2f015..98d2ad502dd 100644 --- a/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk @@ -9,7 +9,7 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_RCLCPY = 1 +CIRCUITPY_RCLCPY = 0 # Very few pins. CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_core2/board.c b/ports/espressif/boards/m5stack_core2/board.c index 2d63436235a..2e13c06c44f 100644 --- a/ports/espressif/boards/m5stack_core2/board.c +++ b/ports/espressif/boards/m5stack_core2/board.c @@ -320,7 +320,7 @@ static bool display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO15), // DC MP_OBJ_FROM_PTR(&pin_GPIO5), // CS - MP_OBJ_NULL, // RST + mp_const_none, // RST 32000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/m5stack_cores3/board.c b/ports/espressif/boards/m5stack_cores3/board.c index c14be4ae0d1..629472da526 100644 --- a/ports/espressif/boards/m5stack_cores3/board.c +++ b/ports/espressif/boards/m5stack_cores3/board.c @@ -47,7 +47,7 @@ static bool display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO35), // DC MP_OBJ_FROM_PTR(&pin_GPIO3), // CS - MP_OBJ_NULL, // RST + mp_const_none, // RST 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/m5stack_cores3_se/board.c b/ports/espressif/boards/m5stack_cores3_se/board.c index bf5ccd17f36..623fe29f98f 100644 --- a/ports/espressif/boards/m5stack_cores3_se/board.c +++ b/ports/espressif/boards/m5stack_cores3_se/board.c @@ -48,7 +48,7 @@ static bool display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO35), // DC MP_OBJ_FROM_PTR(&pin_GPIO3), // CS - NULL, // RST + mp_const_none, // RST 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/m5stack_tab5/sdkconfig b/ports/espressif/boards/m5stack_tab5/sdkconfig index e69de29bb2d..3bce8cc0c13 100644 --- a/ports/espressif/boards/m5stack_tab5/sdkconfig +++ b/ports/espressif/boards/m5stack_tab5/sdkconfig @@ -0,0 +1,2 @@ +CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y +CONFIG_ESP32P4_REV_MIN_100=y diff --git a/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/board.c b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/board.c new file mode 100755 index 00000000000..e2517f8640a --- /dev/null +++ b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/board.c @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "driver/gpio.h" + +void board_init(void) { + reset_board(); +} + +void reset_board(void) { + // Turn on I2C power by default. + gpio_set_direction(14, GPIO_MODE_DEF_OUTPUT); + gpio_set_level(14, true); + + // Turn on SD power by default + gpio_set_direction(3, GPIO_MODE_DEF_OUTPUT); + gpio_set_level(3, true); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/mpconfigboard.h b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/mpconfigboard.h new file mode 100755 index 00000000000..c3181ea9431 --- /dev/null +++ b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/mpconfigboard.h @@ -0,0 +1,36 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "NHB Systems JL401-S3 4MB Flash 2MB PSRAM" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO1) +#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO2) + +// #define MICROPY_HW_LED_STATUS (&pin_GPIO13) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO48) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO47) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO12) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO11) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO13) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO18) +#define DEFAULT_UART_BUS_TX (&pin_GPIO17) + +#define DOUBLE_TAP_PIN (&pin_GPIO38) + +#define DEFAULT_SD_SCK (&pin_GPIO12) +#define DEFAULT_SD_MOSI (&pin_GPIO11) +#define DEFAULT_SD_MISO (&pin_GPIO13) +#define DEFAULT_SD_CS (&pin_GPIO10) +#define DEFAULT_SD_CARD_DETECT (&pin_GPIO9) +#define DEFAULT_SD_CARD_INSERTED true diff --git a/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/mpconfigboard.mk b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/mpconfigboard.mk new file mode 100755 index 00000000000..fdc981fdccc --- /dev/null +++ b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303A +USB_PID = 0x834A +USB_PRODUCT = "NHB Systems JL401-S3 4MB Flash 2MB PSRAM" +USB_MANUFACTURER = "NHB Systems" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_SIZE = 4MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/pins.c b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/pins.c new file mode 100644 index 00000000000..111659bee61 --- /dev/null +++ b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/pins.c @@ -0,0 +1,89 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_SD_PWR), MP_ROM_PTR(&pin_GPIO3)}, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + + + // { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO13) }, + // { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_I2C_POWER), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + + // D33 to D36 used for AD7124 SPI + { MP_ROM_QSTR(MP_QSTR_D33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_D34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_D36), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_ROM_QSTR(MP_QSTR_D37), MP_ROM_PTR(&pin_GPIO37) }, + // { MP_ROM_QSTR(MP_QSTR_D38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_D39), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_D43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_D44), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) } +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/sdkconfig b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/sdkconfig new file mode 100755 index 00000000000..e9628662160 --- /dev/null +++ b/ports/espressif/boards/nhbsystems_jl401_4mbflash_2mbpsram/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/pcbcupid_glyph_s3/board.c b/ports/espressif/boards/pcbcupid_glyph_s3/board.c new file mode 100644 index 00000000000..27b058c946f --- /dev/null +++ b/ports/espressif/boards/pcbcupid_glyph_s3/board.c @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 PCBCupid +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +void board_init(void) { +} diff --git a/ports/espressif/boards/pcbcupid_glyph_s3/mpconfigboard.h b/ports/espressif/boards/pcbcupid_glyph_s3/mpconfigboard.h new file mode 100644 index 00000000000..bc17cb65dfc --- /dev/null +++ b/ports/espressif/boards/pcbcupid_glyph_s3/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 PCBCupid +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "PCBCupid GLYPH S3" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO21) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO5) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO4) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO35) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO36) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO37) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/pcbcupid_glyph_s3/mpconfigboard.mk b/ports/espressif/boards/pcbcupid_glyph_s3/mpconfigboard.mk new file mode 100644 index 00000000000..9228197411f --- /dev/null +++ b/ports/espressif/boards/pcbcupid_glyph_s3/mpconfigboard.mk @@ -0,0 +1,10 @@ +USB_VID = 0x303A +USB_PID = 0x8373 +USB_PRODUCT = "GLYPH S3" +USB_MANUFACTURER = "PCBCupid" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB diff --git a/ports/espressif/boards/pcbcupid_glyph_s3/pins.c b/ports/espressif/boards/pcbcupid_glyph_s3/pins.c new file mode 100644 index 00000000000..5b962f2f74d --- /dev/null +++ b/ports/espressif/boards/pcbcupid_glyph_s3/pins.c @@ -0,0 +1,59 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 PCBCupid +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_A10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/tests/feature_check/io_module.py.exp b/ports/espressif/boards/pcbcupid_glyph_s3/sdkconfig similarity index 100% rename from tests/feature_check/io_module.py.exp rename to ports/espressif/boards/pcbcupid_glyph_s3/sdkconfig diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/board.c b/ports/espressif/boards/sensebox_mcu_eye_esp32s3/board.c similarity index 100% rename from ports/espressif/boards/sensebox_eye_esp32s3/board.c rename to ports/espressif/boards/sensebox_mcu_eye_esp32s3/board.c diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.h b/ports/espressif/boards/sensebox_mcu_eye_esp32s3/mpconfigboard.h similarity index 88% rename from ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.h rename to ports/espressif/boards/sensebox_mcu_eye_esp32s3/mpconfigboard.h index 3908c492f1b..300154fe344 100644 --- a/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.h +++ b/ports/espressif/boards/sensebox_mcu_eye_esp32s3/mpconfigboard.h @@ -6,7 +6,7 @@ // Micropython setup -#define MICROPY_HW_BOARD_NAME "senseBox-eye ESP32S3" +#define MICROPY_HW_BOARD_NAME "senseBox MCU Eye ESP32S3" #define MICROPY_HW_MCU_NAME "ESP32S3" #define MICROPY_HW_NEOPIXEL (&pin_GPIO45) diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.mk b/ports/espressif/boards/sensebox_mcu_eye_esp32s3/mpconfigboard.mk similarity index 93% rename from ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.mk rename to ports/espressif/boards/sensebox_mcu_eye_esp32s3/mpconfigboard.mk index 55e822c5dea..be3c65746c8 100644 --- a/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.mk +++ b/ports/espressif/boards/sensebox_mcu_eye_esp32s3/mpconfigboard.mk @@ -7,7 +7,7 @@ USB_MANUFACTURER = "senseBox" IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio -CIRCUITPY_ESP_FLASH_SIZE = 8MB +CIRCUITPY_ESP_FLASH_SIZE = 16MB CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_MODE = opi diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/pins.c b/ports/espressif/boards/sensebox_mcu_eye_esp32s3/pins.c similarity index 98% rename from ports/espressif/boards/sensebox_eye_esp32s3/pins.c rename to ports/espressif/boards/sensebox_mcu_eye_esp32s3/pins.c index c218fafa918..71b984f7ff5 100644 --- a/ports/espressif/boards/sensebox_eye_esp32s3/pins.c +++ b/ports/espressif/boards/sensebox_mcu_eye_esp32s3/pins.c @@ -33,7 +33,7 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, - {MP_ROM_QSTR(MP_QSTR_BUTTON_SW), MP_ROM_PTR(&pin_GPIO47) }, + {MP_ROM_QSTR(MP_QSTR_BUTTON_SW), MP_ROM_PTR(&pin_GPIO21) }, { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO1) }, diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/sdkconfig b/ports/espressif/boards/sensebox_mcu_eye_esp32s3/sdkconfig similarity index 100% rename from ports/espressif/boards/sensebox_eye_esp32s3/sdkconfig rename to ports/espressif/boards/sensebox_mcu_eye_esp32s3/sdkconfig diff --git a/ports/espressif/boards/solderparty_esp32p4_stamp_xl/sdkconfig b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/sdkconfig index e69de29bb2d..3bce8cc0c13 100644 --- a/ports/espressif/boards/solderparty_esp32p4_stamp_xl/sdkconfig +++ b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/sdkconfig @@ -0,0 +1,2 @@ +CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y +CONFIG_ESP32P4_REV_MIN_100=y diff --git a/ports/espressif/boards/sunton_esp32_2424S012/board.c b/ports/espressif/boards/sunton_esp32_2424S012/board.c index 731694a4e1b..4e56bee7d8b 100644 --- a/ports/espressif/boards/sunton_esp32_2424S012/board.c +++ b/ports/espressif/boards/sunton_esp32_2424S012/board.c @@ -107,7 +107,7 @@ static void display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO2), // DC MP_OBJ_FROM_PTR(&pin_GPIO10), // CS - MP_OBJ_NULL, // RST + mp_const_none, // RST 80000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/sunton_esp32_2432S024C/board.c b/ports/espressif/boards/sunton_esp32_2432S024C/board.c index de7504a8715..d50f19f9972 100644 --- a/ports/espressif/boards/sunton_esp32_2432S024C/board.c +++ b/ports/espressif/boards/sunton_esp32_2432S024C/board.c @@ -53,7 +53,7 @@ static void display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO2), // TFT_DC Command or data MP_OBJ_FROM_PTR(&pin_GPIO15), // TFT_CS Chip select - MP_OBJ_NULL, // TFT_RST Reset + mp_const_none, // TFT_RST Reset 6000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/sunton_esp32_2432S028/board.c b/ports/espressif/boards/sunton_esp32_2432S028/board.c index 214e3b13e15..6cd4a080c99 100644 --- a/ports/espressif/boards/sunton_esp32_2432S028/board.c +++ b/ports/espressif/boards/sunton_esp32_2432S028/board.c @@ -53,7 +53,7 @@ static void display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO2), // TFT_DC Command or data MP_OBJ_FROM_PTR(&pin_GPIO15), // TFT_CS Chip select - MP_OBJ_NULL, // TFT_RST Reset + mp_const_none, // TFT_RST Reset 6000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/sunton_esp32_2432S032C/board.c b/ports/espressif/boards/sunton_esp32_2432S032C/board.c index 48e206040d8..db621cfe8c9 100644 --- a/ports/espressif/boards/sunton_esp32_2432S032C/board.c +++ b/ports/espressif/boards/sunton_esp32_2432S032C/board.c @@ -45,7 +45,7 @@ static void display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO2), // TFT_DC MP_OBJ_FROM_PTR(&pin_GPIO15), // TFT_CS - MP_OBJ_NULL, // TFT_RST + mp_const_none, // TFT_RST 26600000, // Baudrate 0, // Polarity 0 // Phase diff --git a/ports/espressif/boards/sunton_esp32_8048S050/board.c b/ports/espressif/boards/sunton_esp32_8048S050/board.c index a6f573a86e7..b1794529ff0 100644 --- a/ports/espressif/boards/sunton_esp32_8048S050/board.c +++ b/ports/espressif/boards/sunton_esp32_8048S050/board.c @@ -7,6 +7,7 @@ #include "supervisor/board.h" #include "mpconfigboard.h" +#include "driver/gpio.h" #include "shared-bindings/board/__init__.h" #include "shared-bindings/dotclockframebuffer/DotClockFramebuffer.h" #include "shared-bindings/dotclockframebuffer/__init__.h" diff --git a/ports/espressif/boards/sunton_esp32_8048S070/board.c b/ports/espressif/boards/sunton_esp32_8048S070/board.c index ecc9b7c1236..3d6a9c81e6d 100644 --- a/ports/espressif/boards/sunton_esp32_8048S070/board.c +++ b/ports/espressif/boards/sunton_esp32_8048S070/board.c @@ -6,6 +6,7 @@ #include "supervisor/board.h" #include "mpconfigboard.h" +#include "driver/gpio.h" #include "shared-bindings/board/__init__.h" #include "shared-bindings/dotclockframebuffer/DotClockFramebuffer.h" #include "shared-bindings/dotclockframebuffer/__init__.h" diff --git a/ports/espressif/boards/unexpectedmaker_feathers3/pins.c b/ports/espressif/boards/unexpectedmaker_feathers3/pins.c index e611348caa0..63153d3d696 100644 --- a/ports/espressif/boards/unexpectedmaker_feathers3/pins.c +++ b/ports/espressif/boards/unexpectedmaker_feathers3/pins.c @@ -128,6 +128,10 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_LDO2), MP_ROM_PTR(&pin_GPIO39) }, { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + // built-in vs uFL antenna switch (LOW=built-in, HIGH=uFL, default=built-in) + { MP_ROM_QSTR(MP_QSTR_ANTENNA_SWITCH), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + // I2C { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, diff --git a/ports/espressif/boards/vidi_x/board.c b/ports/espressif/boards/vidi_x/board.c index 7ba7094b917..57e2b896213 100644 --- a/ports/espressif/boards/vidi_x/board.c +++ b/ports/espressif/boards/vidi_x/board.c @@ -6,6 +6,7 @@ #include "supervisor/board.h" #include "mpconfigboard.h" +#include "driver/gpio.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/fourwire/FourWire.h" #include "shared-module/displayio/__init__.h" @@ -53,7 +54,7 @@ void board_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO21), // TFT_DC Command or data MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select - MP_OBJ_NULL, // TFT_RST Reset + mp_const_none, // TFT_RST Reset 40000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c new file mode 100644 index 00000000000..7b57f48bcdb --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c @@ -0,0 +1,106 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +#include "shared-bindings/qspibus/QSPIBus.h" +#include "shared-bindings/busdisplay/BusDisplay.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" + +// RM690B0 AMOLED initialization sequence. +// Format: command byte, length | 0x80 (if delay), data bytes..., [delay ms] +// Based on vendor recommendations, tested with Waveshare 2.41" AMOLED panel. +// Non-const to match upstream common_hal_busdisplay_busdisplay_construct signature. +static uint8_t display_init_sequence[] = { + // Page select and configuration + 0xFE, 0x01, 0x20, // Enter user command mode + 0x26, 0x01, 0x0A, // Bias setting + 0x24, 0x01, 0x80, // Source output control + 0xFE, 0x01, 0x13, // Page 13 + 0xEB, 0x01, 0x0E, // Vendor command + 0xFE, 0x01, 0x00, // Return to page 0 + // Display configuration + 0x3A, 0x01, 0x55, // COLMOD: 16-bit RGB565 + 0xC2, 0x81, 0x00, 0x0A, // Vendor command + 10ms delay + 0x35, 0x00, // Tearing effect line on (no data) + 0x51, 0x81, 0x00, 0x0A, // Brightness control + 10ms delay + // Power on + 0x11, 0x80, 0x50, // Sleep out + 80ms delay + // Display window (MV=1: CASET→rows, RASET→cols) + 0x2A, 0x04, 0x00, 0x10, 0x01, 0xD1, // CASET: 16..465 (450px + 16 offset) + 0x2B, 0x04, 0x00, 0x00, 0x02, 0x57, // RASET: 0..599 (600px) + // Enable display + 0x29, 0x80, 0x0A, // Display on + 10ms delay + // Memory access: MV=1, ML=1 for landscape + 0x36, 0x81, 0x30, 0x0A, // MADCTL + 10ms delay + // Brightness + 0x51, 0x01, 0xFF, // Set brightness to maximum +}; + +void board_init(void) { + // 0. Enable display power before any bus/display init. + digitalio_digitalinout_obj_t power_pin; + power_pin.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&power_pin, CIRCUITPY_LCD_POWER); + common_hal_digitalio_digitalinout_set_value(&power_pin, true); + common_hal_digitalio_digitalinout_never_reset(&power_pin); + // Allow power rail to settle before reset/init. + mp_hal_delay_ms(200); + + // 1. Allocate and construct QSPI bus + qspibus_qspibus_obj_t *bus = &allocate_display_bus_or_raise()->qspi_bus; + bus->base.type = &qspibus_qspibus_type; + + common_hal_qspibus_qspibus_construct(bus, + CIRCUITPY_LCD_CLK, // clock + CIRCUITPY_LCD_D0, // data0 + CIRCUITPY_LCD_D1, // data1 + CIRCUITPY_LCD_D2, // data2 + CIRCUITPY_LCD_D3, // data3 + CIRCUITPY_LCD_CS, // cs + NULL, // dcx (not used, QSPI uses encoded commands) + CIRCUITPY_LCD_RESET, // reset + 40000000); // 40 MHz + + // 2. Allocate and construct BusDisplay with RM690B0 init sequence. + // Physical panel: 450 cols × 600 rows. + // MADCTL MV=1 swaps row/col → logical 600×450 landscape. + busdisplay_busdisplay_obj_t *display = &allocate_display_or_raise()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct(display, + bus, + 600, // width (logical, after MV=1 swap) + 450, // height (logical, after MV=1 swap) + 0, // colstart + 16, // rowstart (physical row offset) + 0, // rotation + 16, // color_depth (RGB565) + false, // grayscale + false, // pixels_in_byte_share_row + 1, // bytes_per_cell + false, // reverse_pixels_in_byte + false, // reverse_bytes_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set_column_command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set_row_command + MIPI_COMMAND_WRITE_MEMORY_START, // write_ram_command + display_init_sequence, + sizeof(display_init_sequence), + NULL, // backlight_pin (AMOLED — no backlight GPIO) + 0x51, // brightness_command + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000); // backlight_pwm_frequency +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h new file mode 100644 index 00000000000..9ac461ee61d --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h @@ -0,0 +1,34 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3-Touch-AMOLED-2.41" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +// I2C bus - Disabled on boot to avoid conflicts. User must manually initialize I2C. +#define CIRCUITPY_BOARD_I2C (0) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO48, .sda = &pin_GPIO47}} + +// Display refresh buffer: 8192 bytes = 2048 uint32_t words on stack. +// ESP32-S3 main task stack is 24KB; verified safe with this board. +#define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (8192) + +// AMOLED Display (displayio + qspibus path) - initialized in board_init() +#define CIRCUITPY_BOARD_DISPLAY (1) +#define CIRCUITPY_LCD_CS (&pin_GPIO9) +#define CIRCUITPY_LCD_CLK (&pin_GPIO10) +#define CIRCUITPY_LCD_D0 (&pin_GPIO11) +#define CIRCUITPY_LCD_D1 (&pin_GPIO12) +#define CIRCUITPY_LCD_D2 (&pin_GPIO13) +#define CIRCUITPY_LCD_D3 (&pin_GPIO14) +#define CIRCUITPY_LCD_RESET (&pin_GPIO21) +#define CIRCUITPY_LCD_POWER (&pin_GPIO16) + +// No default SPI bus — SD card uses SDIO, display uses QSPI. +#define CIRCUITPY_BOARD_SPI (0) + +// Default UART bus +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk new file mode 100644 index 00000000000..f901246804c --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -0,0 +1,35 @@ +# This file is part of the CircuitPython project: https://circuitpython.org +# SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +# SPDX-License-Identifier: MIT + +USB_VID = 0x303A +USB_PID = 0x8278 +USB_MANUFACTURER = "Waveshare" +USB_PRODUCT = "ESP32-S3-Touch-AMOLED-2.41" + +IDF_TARGET = esp32s3 + +# Flash configuration - 16MB QSPI Flash +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +# PSRAM configuration - 8MB Octal PSRAM +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +OPTIMIZATION_FLAGS = -Os + +# QSPI bus for RM690B0 AMOLED display +CIRCUITPY_QSPIBUS = 1 +CIRCUITPY_PARALLELDISPLAYBUS = 0 + +# No camera on this board +CIRCUITPY_ESPCAMERA = 0 + +# Capacitive touch not available; board uses I2C touch controller +CIRCUITPY_TOUCHIO = 0 + +# SD card via SDMMC interface +CIRCUITPY_SDIOIO = 1 diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c new file mode 100644 index 00000000000..8804cace06d --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c @@ -0,0 +1,109 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // ================================================================= + // ONBOARD PERIPHERALS - Functional Names + // ================================================================= + + // Boot/Control/Battery/Display Power + // NOTE: GPIO16 is shared between battery control circuitry and LCD power + // (see CIRCUITPY_QSPIBUS_PANEL_POWER_PIN in mpconfigboard.h). + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_KEY_BAT), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_BAT_CONTROL), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_LCD_POWER), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO17) }, + + // I2C Bus (shared by Touch, RTC, IMU, IO Expander) + // NOTE: board.I2C auto-initialization is disabled (CIRCUITPY_BOARD_I2C=0) + // to avoid boot conflicts. Users must manually create I2C bus: + // i2c = busio.I2C(board.SCL, board.SDA) + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // Touch Panel (FT6336U on I2C) + // NOTE: TP_INT is routed through the TCA9554 IO expander (EXIO2), + // not a direct ESP32-S3 GPIO — no TOUCH_INT alias is possible here. + { MP_ROM_QSTR(MP_QSTR_TP_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_TP_SCL), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_TP_RESET), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_SCL), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_RST), MP_ROM_PTR(&pin_GPIO3) }, + + // RTC (PCF85063 on I2C) + { MP_ROM_QSTR(MP_QSTR_RTC_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_RTC_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // IMU (QMI8658 on I2C) + { MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // I/O Expander (TCA9554 on I2C) + { MP_ROM_QSTR(MP_QSTR_EXIO_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_EXIO_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // USB + { MP_ROM_QSTR(MP_QSTR_USB_D_N), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_USB_D_P), MP_ROM_PTR(&pin_GPIO20) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // QSPI Display (RM690B0) - canonical generic LCD aliases. + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D1), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D3), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(&pin_GPIO21) }, + + // Display Aliases + { MP_ROM_QSTR(MP_QSTR_DISPLAY_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_SCK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D1), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D3), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_RST), MP_ROM_PTR(&pin_GPIO21) }, + + // SD Card (SDIO / SDMMC) + { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_D0), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_D3), MP_ROM_PTR(&pin_GPIO2) }, + + // ================================================================= + // GENERAL PURPOSE I/O (IOxx - Espressif Convention) + // ================================================================= + // Only pins NOT dedicated to onboard peripherals are exposed here. + // Use functional names above for dedicated pins (e.g., SDA, SD_CS). + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, // BOOT button (available when not holding BOOT) + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, // TP_RESET (available if touch not used) + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, // Available + + // Board display (initialized in board_init) + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig new file mode 100644 index 00000000000..fa60cc4c237 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig @@ -0,0 +1,3 @@ +# +# Configuration file for the Waveshare ESP32-S3 Touch AMOLED 2.41 +# diff --git a/ports/espressif/boards/waveshare_esp32_s3_matrix/pins.c b/ports/espressif/boards/waveshare_esp32_s3_matrix/pins.c index e21f542179c..a107cd61c22 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_matrix/pins.c +++ b/ports/espressif/boards/waveshare_esp32_s3_matrix/pins.c @@ -35,7 +35,7 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, - { MP_ROM_QSTR(MP_QSTR_I01), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, diff --git a/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/board.c b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/board.c new file mode 100644 index 00000000000..a3a9eec0471 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/mpconfigboard.h new file mode 100644 index 00000000000..296d751ab25 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/mpconfigboard.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3-Tiny-N8R8" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +// This corrects the color ordering so that the CircuitPython status lights behave as expected +#define MICROPY_HW_NEOPIXEL_ORDER_GRB (1) +#define MICROPY_HW_NEOPIXEL (&pin_GPIO38) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO19) +#define DEFAULT_UART_BUS_TX (&pin_GPIO20) diff --git a/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/mpconfigboard.mk new file mode 100644 index 00000000000..ebb8317c457 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/mpconfigboard.mk @@ -0,0 +1,16 @@ +USB_VID = 0x303a +USB_PID = 0x8379 +USB_PRODUCT = "ESP32-S3-Tiny-N8R8" +USB_MANUFACTURER = "Waveshare Electronics" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/pins.c b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/pins.c new file mode 100644 index 00000000000..917ef0506ab --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/pins.c @@ -0,0 +1,61 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + // NEOPIXEL (GRB Color Order) + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO38) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + // Any pins can be I2C + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + // Any pins can be SPI + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/sdkconfig new file mode 100644 index 00000000000..e9628662160 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_tiny_n8r8/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/xteink_x4/board.c b/ports/espressif/boards/xteink_x4/board.c new file mode 100644 index 00000000000..b5b193c65fe --- /dev/null +++ b/ports/espressif/boards/xteink_x4/board.c @@ -0,0 +1,130 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// SPDX-FileCopyrightText: Copyright (c) 2021 skieast/Bruce Segal +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/board.h" + +#define DELAY 0x80 + +// SSD1677 controller driving a GDEQ0426T82 4.26" 800x480 E-Ink display. + +const uint8_t ssd1677_display_start_sequence[] = { + // Software Reset + 0x12, DELAY, 0x00, 0x14, + + // Temperature Sensor Control (use internal sensor) + 0x18, 0x00, 0x01, 0x80, + + // Booster Soft Start + 0x0C, 0x00, 0x05, 0xAE, 0xC7, 0xC3, 0xC0, 0x40, + + // Driver Output Control: 480 gates, GD=0, SM=1, TB=0 = 0x02 + 0x01, 0x00, 0x03, 0xDF, 0x01, 0x02, + + // Data Entry Mode: X increment, Y decrement = 0x01 + 0x11, 0x00, 0x01, 0x01, + + // Border Waveform Control + 0x3C, 0x00, 0x01, 0x01, + + // Set RAM X Address Start/End: 0 to 799 + 0x44, 0x00, 0x04, 0x00, 0x00, 0x1F, 0x03, + + // Set RAM Y Address Start/End: 479 down to 0 + 0x45, 0x00, 0x04, 0xDF, 0x01, 0x00, 0x00, + + // Set RAM X Counter to 0 + 0x4E, 0x00, 0x02, 0x00, 0x00, + + // Set RAM Y Counter to 479 + 0x4F, 0x00, 0x02, 0xDF, 0x01, + + // Auto Write BW RAM (clear to white) + 0x46, DELAY, 0x01, 0xF7, 0xFF, + + // Display Update Control 1: bypass RED + 0x21, 0x00, 0x02, 0x40, 0x00, + + // Display Update Control 2: full refresh with OTP LUT + 0x22, 0x00, 0x01, 0xF7, +}; + +const uint8_t ssd1677_display_stop_sequence[] = { + 0x22, 0x00, 0x01, 0x83, + 0x20, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x01, +}; + +const uint8_t ssd1677_display_refresh_sequence[] = { + 0x20, 0x00, 0x00, +}; + +void board_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO8, &pin_GPIO10, NULL, false); + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO4), + MP_OBJ_FROM_PTR(&pin_GPIO21), + MP_OBJ_FROM_PTR(&pin_GPIO5), + 40000000, + 0, + 0); + + epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; + display->base.type = &epaperdisplay_epaperdisplay_type; + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = ssd1677_display_start_sequence; + args.start_sequence_len = sizeof(ssd1677_display_start_sequence); + args.stop_sequence = ssd1677_display_stop_sequence; + args.stop_sequence_len = sizeof(ssd1677_display_stop_sequence); + args.width = 800; + args.height = 480; + args.ram_width = 800; + args.ram_height = 480; + args.rotation = 0; + args.write_black_ram_command = 0x24; + args.black_bits_inverted = false; + args.refresh_sequence = ssd1677_display_refresh_sequence; + args.refresh_sequence_len = sizeof(ssd1677_display_refresh_sequence); + args.refresh_time = 1.6; + args.busy_pin = &pin_GPIO6; + args.busy_state = true; + args.seconds_per_frame = 5.0; + args.grayscale = false; + args.two_byte_sequence_length = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); +} + +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + return false; +} + +void board_deinit(void) { + epaperdisplay_epaperdisplay_obj_t *display = &displays[0].epaper_display; + if (display->base.type == &epaperdisplay_epaperdisplay_type) { + while (common_hal_epaperdisplay_epaperdisplay_get_busy(display)) { + RUN_BACKGROUND_TASKS; + } + } + common_hal_displayio_release_displays(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/xteink_x4/mpconfigboard.h b/ports/espressif/boards/xteink_x4/mpconfigboard.h new file mode 100644 index 00000000000..5d4bb372228 --- /dev/null +++ b/ports/espressif/boards/xteink_x4/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// SPDX-FileCopyrightText: Copyright (c) 2021 skieast/Bruce Segal +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Board setup +#define MICROPY_HW_BOARD_NAME "Xteink X4" +#define MICROPY_HW_MCU_NAME "ESP32-C3" + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO8, .mosi = &pin_GPIO10, .miso = &pin_GPIO7}} + +// For entering safe mode +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO3) diff --git a/ports/espressif/boards/xteink_x4/mpconfigboard.mk b/ports/espressif/boards/xteink_x4/mpconfigboard.mk new file mode 100644 index 00000000000..8668aad1818 --- /dev/null +++ b/ports/espressif/boards/xteink_x4/mpconfigboard.mk @@ -0,0 +1,29 @@ +CIRCUITPY_CREATOR_ID = 0x0EEE0000 +CIRCUITPY_CREATION_ID = 0x00C30001 + +IDF_TARGET = esp32c3 + +CIRCUITPY_ESP_FLASH_MODE = dio +CIRCUITPY_ESP_FLASH_FREQ = 40m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 + +CIRCUITPY_PARALLELDISPLAYBUS = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOCORE = 0 +CIRCUITPY_AUDIOMIXER = 0 +CIRCUITPY_AUDIOMP3 = 0 +CIRCUITPY_CAMERA = 0 +CIRCUITPY_CANIO = 0 +CIRCUITPY_DOTCLOCKFRAMEBUFFER = 0 +CIRCUITPY_KEYPAD = 0 +CIRCUITPY_ROTARYIO = 0 +CIRCUITPY_USB_HID = 0 +CIRCUITPY_USB_MIDI = 0 +CIRCUITPY_ULAB = 0 +CIRCUITPY_PULSEIO = 0 +CIRCUITPY_PWMIO = 0 +CIRCUITPY_RAINBOWIO = 0 +CIRCUITPY_SYNTHIO = 0 diff --git a/ports/espressif/boards/xteink_x4/pins.c b/ports/espressif/boards/xteink_x4/pins.c new file mode 100644 index 00000000000..6b8232d4cb3 --- /dev/null +++ b/ports/espressif/boards/xteink_x4/pins.c @@ -0,0 +1,52 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// SPDX-FileCopyrightText: Copyright (c) 2021 skieast/Bruce Segal +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_ADC_1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_ADC_2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_EPD_MOSI), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_EPD_SCK), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_EPD_BUSY), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_EPD_RESET), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_EPD_DC), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_EPD_CS), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].epaper_display)}, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/xteink_x4/sdkconfig b/ports/espressif/boards/xteink_x4/sdkconfig new file mode 100644 index 00000000000..e9628662160 --- /dev/null +++ b/ports/espressif/boards/xteink_x4/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/common-hal/_bleio/Adapter.c b/ports/espressif/common-hal/_bleio/Adapter.c index 327515da4de..4feb6b2b96b 100644 --- a/ports/espressif/common-hal/_bleio/Adapter.c +++ b/ports/espressif/common-hal/_bleio/Adapter.c @@ -61,7 +61,7 @@ static void nimble_host_task(void *param) { static void _on_sync(void) { - int rc = ble_hs_util_ensure_addr(false); + int rc __attribute__((unused)) = ble_hs_util_ensure_addr(false); assert(rc == 0); _nimble_sync = true; @@ -561,10 +561,6 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool high_duty_directed = directed_to != NULL && interval <= 3.5 && timeout <= 1; // Really 1.3, but it's an int uint32_t timeout_ms = timeout * 1000; - if (timeout_ms == 0) { - timeout_ms = BLE_HS_FOREVER; - } - #if MYNEWT_VAL(BLE_EXT_ADV) bool extended = advertising_data_len > BLE_ADV_LEGACY_DATA_MAX_LEN || @@ -626,8 +622,12 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, } } + // If timeout_ms is zero, it means advertise forever. This is different than ble_gap_adv_start(). rc = ble_gap_ext_adv_start(0, timeout_ms, 0); + #else + // Extended advertising not enabled. + uint8_t conn_mode = connectable ? BLE_GAP_CONN_MODE_UND : BLE_GAP_CONN_MODE_NON; if (directed_to != NULL) { conn_mode = BLE_GAP_CONN_MODE_DIR; @@ -654,8 +654,10 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, return rc; } } - rc = ble_gap_adv_start(own_addr_type, directed_to != NULL ? &peer: NULL, - timeout_ms, + // If timeout_ms is BLE_HS_FOREVER, it means advertise forever. This is different than ble_gap_ext_adv_start(). + rc = ble_gap_adv_start(own_addr_type, + directed_to != NULL ? &peer: NULL, + timeout_ms == 0 ? BLE_HS_FOREVER : timeout_ms, &adv_params, _advertising_event, self); #endif @@ -733,13 +735,13 @@ void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) { } bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) { - return ble_gap_adv_active(); + return common_hal_bleio_adapter_get_enabled(self) && ble_gap_adv_active(); } bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { bleio_connection_internal_t *connection = &bleio_connections[i]; - if (connection->conn_handle != BLEIO_HANDLE_INVALID && connection->mtu != 0) { + if (connection->conn_handle != BLEIO_HANDLE_INVALID) { return true; } } @@ -754,7 +756,7 @@ mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) { mp_obj_t items[BLEIO_TOTAL_CONNECTION_COUNT]; for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { bleio_connection_internal_t *connection = &bleio_connections[i]; - if (connection->conn_handle != BLEIO_HANDLE_INVALID && connection->mtu != 0) { + if (connection->conn_handle != BLEIO_HANDLE_INVALID) { if (connection->connection_obj == mp_const_none) { connection->connection_obj = bleio_connection_new_from_internal(connection); } @@ -817,10 +819,11 @@ void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) { } void bleio_adapter_reset(bleio_adapter_obj_t *adapter) { - common_hal_bleio_adapter_stop_scan(adapter); - if (common_hal_bleio_adapter_get_advertising(adapter)) { - common_hal_bleio_adapter_stop_advertising(adapter); + if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { + return; } + common_hal_bleio_adapter_stop_scan(adapter); + common_hal_bleio_adapter_stop_advertising(adapter); adapter->connection_objs = NULL; for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { diff --git a/ports/espressif/common-hal/_bleio/Characteristic.c b/ports/espressif/common-hal/_bleio/Characteristic.c index 805c6d160f3..ff9ab35c1b9 100644 --- a/ports/espressif/common-hal/_bleio/Characteristic.c +++ b/ports/espressif/common-hal/_bleio/Characteristic.c @@ -92,7 +92,7 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->max_length = max_length; self->fixed_length = fixed_length; - if (initial_value_bufinfo != NULL) { + if (!service->is_remote && initial_value_bufinfo != NULL) { common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo); } @@ -320,7 +320,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, } const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); - common_hal_bleio_check_connected(conn_handle); + bleio_check_connected(conn_handle); uint16_t cccd_value = (notify ? 1 << 0 : 0) | diff --git a/ports/espressif/common-hal/_bleio/Connection.c b/ports/espressif/common-hal/_bleio/Connection.c index 8c88bfe3ec5..8df4dc26545 100644 --- a/ports/espressif/common-hal/_bleio/Connection.c +++ b/ports/espressif/common-hal/_bleio/Connection.c @@ -65,7 +65,7 @@ int bleio_connection_event_cb(struct ble_gap_event *event, void *connection_in) case BLE_GAP_EVENT_CONN_UPDATE: { struct ble_gap_conn_desc desc; - int rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc); + int rc __attribute__((unused)) = ble_gap_conn_find(event->conn_update.conn_handle, &desc); assert(rc == 0); connection->conn_params_updating = false; break; @@ -181,17 +181,11 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // Zero when discovery is in process. BLE_HS_EDONE or a BLE_HS_ error code when done. static volatile int _last_discovery_status; -static uint64_t _discovery_start_time; - -// Give 20 seconds for discovery +// Give 20 seconds for each step of discovery: services, characteristics, attributes. #define DISCOVERY_TIMEOUT_MS 20000 -static void _start_discovery_timeout(void) { - _discovery_start_time = common_hal_time_monotonic_ms(); -} - static int _wait_for_discovery_step_done(void) { - const uint64_t timeout_time_ms = _discovery_start_time + DISCOVERY_TIMEOUT_MS; + const uint64_t timeout_time_ms = common_hal_time_monotonic_ms() + DISCOVERY_TIMEOUT_MS; while ((_last_discovery_status == 0) && (common_hal_time_monotonic_ms() < timeout_time_ms)) { RUN_BACKGROUND_TASKS; if (mp_hal_is_interrupted()) { @@ -199,6 +193,9 @@ static int _wait_for_discovery_step_done(void) { _last_discovery_status = BLE_HS_EDONE; } } + if (_last_discovery_status == 0) { + return BLE_HS_ETIMEOUT; + } return _last_discovery_status; } @@ -207,6 +204,17 @@ static void _set_discovery_step_status(int status) { _last_discovery_status = status; } +static void _check_discovery_status(int status) { + if (status == BLE_HS_EDONE) { + return; + } + if (status < BLE_HS_ERR_ATT_BASE) { + CHECK_NIMBLE_ERROR(status); + return; + } + CHECK_BLE_ERROR(status); +} + static int _discovered_service_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *svc, @@ -350,9 +358,6 @@ static void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t // Start over with an empty list. self->remote_service_list = mp_obj_new_list(0, NULL); - // Start timeout in case discovery gets stuck. - _start_discovery_timeout(); - if (service_uuids_whitelist == mp_const_none) { // Reset discovery status before starting callbacks _set_discovery_step_status(0); @@ -361,9 +366,7 @@ static void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t // Wait for _discovered_service_cb() to be called multiple times until it's done. int status = _wait_for_discovery_step_done(); - if (status != BLE_HS_EDONE) { - CHECK_BLE_ERROR(status); - } + _check_discovery_status(status); } else { mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf); @@ -382,9 +385,7 @@ static void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t // Wait for _discovered_service_cb() to be called multiple times until it's done. int status = _wait_for_discovery_step_done(); - if (status != BLE_HS_EDONE) { - CHECK_BLE_ERROR(status); - } + _check_discovery_status(status); } } @@ -404,9 +405,7 @@ static void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t // Wait for _discovered_characteristic_cb() to be called multiple times until it's done. int status = _wait_for_discovery_step_done(); - if (status != BLE_HS_EDONE) { - CHECK_BLE_ERROR(status); - } + _check_discovery_status(status); // Got characteristics for this service. Now discover descriptors for each characteristic. size_t char_list_len = service->characteristic_list->len; @@ -423,7 +422,7 @@ static void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t uint16_t end_handle = next_characteristic == NULL ? service->end_handle - : next_characteristic->handle - 1; + : next_characteristic->def_handle - 1; // Pre-check if there are no descriptors to discover so descriptor discovery doesn't fail if (end_handle <= characteristic->handle) { @@ -441,9 +440,7 @@ static void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t // Wait for _discovered_descriptor_cb to be called multiple times until it's done. status = _wait_for_discovery_step_done(); - if (status != BLE_HS_EDONE) { - CHECK_BLE_ERROR(status); - } + _check_discovery_status(status); } } } diff --git a/ports/espressif/common-hal/_bleio/Connection.h b/ports/espressif/common-hal/_bleio/Connection.h index 326eca02ecd..5f33eb43b5d 100644 --- a/ports/espressif/common-hal/_bleio/Connection.h +++ b/ports/espressif/common-hal/_bleio/Connection.h @@ -64,6 +64,7 @@ void bleio_connection_clear(bleio_connection_internal_t *self); int bleio_connection_event_cb(struct ble_gap_event *event, void *connection_in); +void bleio_check_connected(uint16_t conn_handle); uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection); bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle); diff --git a/ports/espressif/common-hal/_bleio/__init__.c b/ports/espressif/common-hal/_bleio/__init__.c index 119fe55921e..552ba0575b3 100644 --- a/ports/espressif/common-hal/_bleio/__init__.c +++ b/ports/espressif/common-hal/_bleio/__init__.c @@ -32,9 +32,12 @@ static uint64_t _timeout_start_time; background_callback_t bleio_background_callback; void bleio_user_reset(void) { - // Stop any user scanning or advertising. - common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); - common_hal_bleio_adapter_stop_advertising(&common_hal_bleio_adapter_obj); + if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { + return; + } + // Stop any user scanning or advertising, and stop all connections. + // TODO: Don't stop BLE workflow connection. + bleio_adapter_reset(&common_hal_bleio_adapter_obj); ble_event_remove_heap_handlers(); @@ -155,7 +158,7 @@ void check_notify(BaseType_t result) { mp_raise_msg(&mp_type_TimeoutError, NULL); } -void common_hal_bleio_check_connected(uint16_t conn_handle) { +void bleio_check_connected(uint16_t conn_handle) { if (conn_handle == BLEIO_HANDLE_INVALID) { mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); } diff --git a/ports/espressif/common-hal/alarm/SleepMemory.c b/ports/espressif/common-hal/alarm/SleepMemory.c index 938772e53ca..f2a6aaa7a95 100644 --- a/ports/espressif/common-hal/alarm/SleepMemory.c +++ b/ports/espressif/common-hal/alarm/SleepMemory.c @@ -15,14 +15,45 @@ // Data storage for singleton instance of SleepMemory. // Might be RTC_SLOW_MEM or RTC_FAST_MEM, depending on setting of CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM. -static RTC_DATA_ATTR uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH]; +#if defined(CONFIG_SOC_RTC_FAST_MEM_SUPPORTED) || defined(CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED) +static RTC_NOINIT_ATTR uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH]; void alarm_sleep_memory_reset(void) { - // ESP-IDF build system takes care of doing esp_sleep_pd_config() or the equivalent with - // the correct settings, depending on which RTC mem we are using. - // https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/system/sleep_modes.html#power-down-of-rtc-peripherals-and-memories + // With RTC_NOINIT_ATTR, the bootloader does not initialize sleep memory. + // Preserve contents on resets where the RTC domain stays powered (software + // reset, watchdog, panic, deep sleep wake). Clear on everything else — + // after power-on, SRAM contents are undefined; after brown-out, the RTC + // domain was reset by hardware (System Reset scope per TRM Figure 6.1-1). + esp_reset_reason_t reason = esp_reset_reason(); + switch (reason) { + case ESP_RST_SW: // microcontroller.reset() / esp_restart() + case ESP_RST_DEEPSLEEP: // deep sleep wake + case ESP_RST_PANIC: // unhandled exception + case ESP_RST_INT_WDT: // interrupt watchdog + case ESP_RST_TASK_WDT: // task watchdog + case ESP_RST_WDT: // other watchdog + // RTC domain was not reset — sleep memory is intact. + break; + default: + // Power-on, brown-out, unknown, or any other reason where + // RTC SRAM contents may be undefined. Clear to zero. + memset(_sleep_mem, 0, sizeof(_sleep_mem)); + break; + } +} + +#else + +// Chips without RTC memory can't persist SleepMemory across deep sleep. +static uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH]; + +void alarm_sleep_memory_reset(void) { + // Do nothing for chips without RTC memory. } +#endif + + uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) { return sizeof(_sleep_mem); } diff --git a/ports/espressif/common-hal/alarm/__init__.c b/ports/espressif/common-hal/alarm/__init__.c index 629f976039f..b2a6e00969a 100644 --- a/ports/espressif/common-hal/alarm/__init__.c +++ b/ports/espressif/common-hal/alarm/__init__.c @@ -57,68 +57,61 @@ void alarm_reset(void) { esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } -static esp_sleep_wakeup_cause_t _get_wakeup_cause(bool deep_sleep) { +static uint32_t _get_wakeup_causes(bool deep_sleep) { // First check if the modules remember what last woke up if (alarm_pin_pinalarm_woke_this_cycle()) { - return ESP_SLEEP_WAKEUP_GPIO; + return 1 << ESP_SLEEP_WAKEUP_GPIO; } if (alarm_time_timealarm_woke_this_cycle()) { - return ESP_SLEEP_WAKEUP_TIMER; + return 1 << ESP_SLEEP_WAKEUP_TIMER; } #if CIRCUITPY_ALARM_TOUCH if (alarm_touch_touchalarm_woke_this_cycle()) { - return ESP_SLEEP_WAKEUP_TOUCHPAD; + return 1 << ESP_SLEEP_WAKEUP_TOUCHPAD; } #endif #if CIRCUITPY_ESPULP if (espulp_ulpalarm_woke_this_cycle()) { - return ESP_SLEEP_WAKEUP_ULP; + return 1 << ESP_SLEEP_WAKEUP_ULP; } #endif // If waking from true deep sleep, modules will have lost their state, // so check the deep wakeup cause manually if (deep_sleep) { - return esp_sleep_get_wakeup_cause(); + return esp_sleep_get_wakeup_causes(); } - return ESP_SLEEP_WAKEUP_UNDEFINED; + return 0; } bool common_hal_alarm_woken_from_sleep(void) { - return _get_wakeup_cause(false) != ESP_SLEEP_WAKEUP_UNDEFINED; + return _get_wakeup_causes(false) != 0; } mp_obj_t common_hal_alarm_record_wake_alarm(void) { // If woken from deep sleep, create a copy alarm similar to what would have // been passed in originally. Otherwise, just return none - esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(true); - switch (cause) { - case ESP_SLEEP_WAKEUP_TIMER: { - return alarm_time_timealarm_record_wake_alarm(); - } + uint32_t causes = _get_wakeup_causes(true); - case ESP_SLEEP_WAKEUP_GPIO: - case ESP_SLEEP_WAKEUP_EXT0: - case ESP_SLEEP_WAKEUP_EXT1: { - return alarm_pin_pinalarm_record_wake_alarm(); - } + if (causes & (1 << ESP_SLEEP_WAKEUP_TIMER)) { + return alarm_time_timealarm_record_wake_alarm(); + } - #if CIRCUITPY_ALARM_TOUCH - case ESP_SLEEP_WAKEUP_TOUCHPAD: { - return alarm_touch_touchalarm_record_wake_alarm(); - } - #endif + if (causes & ((1 << ESP_SLEEP_WAKEUP_GPIO) | (1 << ESP_SLEEP_WAKEUP_EXT0) | (1 << ESP_SLEEP_WAKEUP_EXT1))) { + return alarm_pin_pinalarm_record_wake_alarm(); + } - #if CIRCUITPY_ESPULP - case ESP_SLEEP_WAKEUP_ULP: { - return espulp_ulpalarm_record_wake_alarm(); - } - #endif + #if CIRCUITPY_ALARM_TOUCH + if (causes & (1 << ESP_SLEEP_WAKEUP_TOUCHPAD)) { + return alarm_touch_touchalarm_record_wake_alarm(); + } + #endif - case ESP_SLEEP_WAKEUP_UNDEFINED: - default: - // Not a deep sleep reset. - break; + #if CIRCUITPY_ESPULP + if (causes & (1 << ESP_SLEEP_WAKEUP_ULP)) { + return espulp_ulpalarm_record_wake_alarm(); } + #endif + return mp_const_none; } @@ -144,32 +137,22 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj RUN_BACKGROUND_TASKS; // Detect if interrupt was alarm or ctrl-C interrupt. if (common_hal_alarm_woken_from_sleep()) { - esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(false); - switch (cause) { - case ESP_SLEEP_WAKEUP_TIMER: { - wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms, alarms); - break; - } - case ESP_SLEEP_WAKEUP_GPIO: { - wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms, alarms); - break; - } - #if CIRCUITPY_ALARM_TOUCH - case ESP_SLEEP_WAKEUP_TOUCHPAD: { - wake_alarm = alarm_touch_touchalarm_find_triggered_alarm(n_alarms, alarms); - break; - } - #endif - #if CIRCUITPY_ESPULP - case ESP_SLEEP_WAKEUP_ULP: { - wake_alarm = espulp_ulpalarm_find_triggered_alarm(n_alarms, alarms); - break; - } - #endif - default: - // Should not reach this, if all light sleep types are covered correctly - break; + uint32_t causes = _get_wakeup_causes(false); + if (causes & (1 << ESP_SLEEP_WAKEUP_TIMER)) { + wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms, alarms); + } else if (causes & (1 << ESP_SLEEP_WAKEUP_GPIO)) { + wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms, alarms); + } + #if CIRCUITPY_ALARM_TOUCH + else if (causes & (1 << ESP_SLEEP_WAKEUP_TOUCHPAD)) { + wake_alarm = alarm_touch_touchalarm_find_triggered_alarm(n_alarms, alarms); + } + #endif + #if CIRCUITPY_ESPULP + else if (causes & (1 << ESP_SLEEP_WAKEUP_ULP)) { + wake_alarm = espulp_ulpalarm_find_triggered_alarm(n_alarms, alarms); } + #endif shared_alarm_save_wake_alarm(wake_alarm); break; } @@ -189,7 +172,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); #if CIRCUITPY_ALARM_TOUCH alarm_touch_touchalarm_prepare_for_deep_sleep(); diff --git a/ports/espressif/common-hal/alarm/pin/PinAlarm.c b/ports/espressif/common-hal/alarm/pin/PinAlarm.c index 97ad3b2a942..3301612356b 100644 --- a/ports/espressif/common-hal/alarm/pin/PinAlarm.c +++ b/ports/espressif/common-hal/alarm/pin/PinAlarm.c @@ -102,14 +102,14 @@ mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t } mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void) { - esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + uint32_t causes = esp_sleep_get_wakeup_causes(); // Pin status will persist into a fake deep sleep uint64_t pin_status = ((uint64_t)pin_63_32_status) << 32 | pin_31_0_status; size_t pin_number = 64; #ifdef SOC_PM_SUPPORT_EXT0_WAKEUP - if (cause == ESP_SLEEP_WAKEUP_EXT0) { + if (causes & (1 << ESP_SLEEP_WAKEUP_EXT0)) { int rtc_io_pin_number = REG_GET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL); // Look up the GPIO equivalent pin for this RTC GPIO pin. On ESP32, the numbering // is different for RTC_GPIO and regular GPIO, and there's no mapping table. @@ -124,12 +124,12 @@ mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void) { } else { #endif #ifdef SOC_PM_SUPPORT_EXT1_WAKEUP - if (cause == ESP_SLEEP_WAKEUP_EXT1) { + if (causes & (1 << ESP_SLEEP_WAKEUP_EXT1)) { pin_status = esp_sleep_get_ext1_wakeup_status(); } #endif #ifdef SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP - if (cause == ESP_SLEEP_WAKEUP_GPIO) { + if (causes & (1 << ESP_SLEEP_WAKEUP_GPIO)) { pin_status = esp_sleep_get_gpio_wakeup_status(); } #endif @@ -307,11 +307,11 @@ static esp_err_t _setup_deep_sleep(size_t low_count, size_t high_count) { return _setup_ext1(low_count, high_count); } #endif - esp_err_t result = esp_deep_sleep_enable_gpio_wakeup(low_alarms, ESP_GPIO_WAKEUP_GPIO_LOW); + esp_err_t result = esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown(low_alarms, ESP_GPIO_WAKEUP_GPIO_LOW); if (result != ESP_OK) { return result; } - result = esp_deep_sleep_enable_gpio_wakeup(high_alarms, ESP_GPIO_WAKEUP_GPIO_HIGH); + result = esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown(high_alarms, ESP_GPIO_WAKEUP_GPIO_HIGH); return result; } #else diff --git a/ports/espressif/common-hal/alarm/touch/TouchAlarm.c b/ports/espressif/common-hal/alarm/touch/TouchAlarm.c index 5791a980d54..93756b3c2ca 100644 --- a/ports/espressif/common-hal/alarm/touch/TouchAlarm.c +++ b/ports/espressif/common-hal/alarm/touch/TouchAlarm.c @@ -17,7 +17,7 @@ static uint16_t touch_channel_mask; static volatile bool woke_up = false; void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) { - if (pin->touch_channel == TOUCH_PAD_MAX) { + if (pin->touch_channel == NO_TOUCH_CHANNEL) { raise_ValueError_invalid_pin(); } claim_pin(pin); @@ -40,35 +40,28 @@ mp_obj_t alarm_touch_touchalarm_record_wake_alarm(void) { alarm->base.type = &alarm_touch_touchalarm_type; alarm->pin = NULL; - #if defined(CONFIG_IDF_TARGET_ESP32) - touch_pad_t wake_channel; - if (touch_pad_get_wakeup_status(&wake_channel) != ESP_OK) { - return alarm; - } - #else - touch_pad_t wake_channel = touch_pad_get_current_meas_channel(); - if (wake_channel == TOUCH_PAD_MAX) { - return alarm; - } - #endif - // Map the pin number back to a pin object. for (size_t i = 0; i < mcu_pin_globals.map.used; i++) { const mcu_pin_obj_t *pin_obj = MP_OBJ_TO_PTR(mcu_pin_globals.map.table[i].value); - if (pin_obj->touch_channel == wake_channel) { - alarm->pin = mcu_pin_globals.map.table[i].value; - break; + if (pin_obj->touch_channel != NO_TOUCH_CHANNEL) { + if ((touch_channel_mask & (1 << pin_obj->touch_channel)) != 0) { + alarm->pin = mcu_pin_globals.map.table[i].value; + break; + } } } return alarm; } -// This is used to wake the main CircuitPython task. -static void touch_interrupt(void *arg) { - (void)arg; +// This callback is used to wake the main CircuitPython task during light sleep. +static bool touch_active_callback(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx) { + (void)sens_handle; + (void)event; + (void)user_ctx; woke_up = true; port_wake_main_task_from_isr(); + return false; } void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms) { @@ -81,7 +74,7 @@ void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alar mp_raise_ValueError_varg(MP_ERROR_TEXT("Only one %q can be set in deep sleep."), MP_QSTR_TouchAlarm); } touch_alarm = MP_OBJ_TO_PTR(alarms[i]); - touch_channel_mask |= 1 << touch_alarm->pin->number; + touch_channel_mask |= 1 << touch_alarm->pin->touch_channel; // Resetting the pin will set a pull-up, which we don't want. skip_reset_once_pin_number(touch_alarm->pin->number); touch_alarm_set = true; @@ -92,47 +85,76 @@ void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alar return; } - // configure interrupt for pretend to deep sleep - // this will be disabled if we actually deep sleep - - // reset touch peripheral + // Reset touch peripheral and keep it from being reset again peripherals_touch_reset(); peripherals_touch_never_reset(true); - for (uint8_t i = 1; i <= 14; i++) { - if ((touch_channel_mask & 1 << i) != 0) { - touch_pad_t touch_channel = (touch_pad_t)i; - // initialize touchpad - peripherals_touch_init(touch_channel); - - // wait for touch data to reset - mp_hal_delay_ms(10); - - // configure trigger threshold - #if defined(CONFIG_IDF_TARGET_ESP32) - uint16_t touch_value; - // ESP32 touch_pad_read() returns a lower value when a pin is touched, not a higher value - // Typical values on a Feather ESP32 V2 are 600 with a short jumper untouched, - // 70 touched. - touch_pad_read(touch_channel, &touch_value); - touch_pad_set_thresh(touch_channel, touch_value / 2); - #else - uint32_t touch_value; - touch_pad_read_benchmark(touch_channel, &touch_value); - touch_pad_set_thresh(touch_channel, touch_value / 10); // 10% - #endif + // Initialize all touch channels used for alarms + for (uint8_t i = TOUCH_MIN_CHAN_ID; i <= TOUCH_MAX_CHAN_ID; i++) { + if ((touch_channel_mask & (1 << i)) != 0) { + peripherals_touch_init(i); } } - // configure touch interrupt - #if defined(CONFIG_IDF_TARGET_ESP32) - touch_pad_isr_register(touch_interrupt, NULL); - touch_pad_intr_enable(); - #else - touch_pad_timeout_set(true, TOUCH_PAD_THRESHOLD_MAX); - touch_pad_isr_register(touch_interrupt, NULL, TOUCH_PAD_INTR_MASK_ALL); - touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); - #endif + // Wait for touch data to stabilize + mp_hal_delay_ms(10); + + // Now stop scanning and disable so we can reconfigure thresholds + touch_sensor_handle_t controller = peripherals_touch_get_controller(); + touch_sensor_stop_continuous_scanning(controller); + touch_sensor_disable(controller); + + // Configure thresholds based on initial readings + for (uint8_t i = TOUCH_MIN_CHAN_ID; i <= TOUCH_MAX_CHAN_ID; i++) { + if ((touch_channel_mask & (1 << i)) == 0) { + continue; + } + touch_channel_handle_t chan = peripherals_touch_get_handle(i); + + uint32_t benchmark = 0; + #if defined(SOC_TOUCH_SUPPORT_BENCHMARK) && SOC_TOUCH_SUPPORT_BENCHMARK + touch_channel_read_data(chan, TOUCH_CHAN_DATA_TYPE_BENCHMARK, &benchmark); + #else + touch_channel_read_data(chan, TOUCH_CHAN_DATA_TYPE_SMOOTH, &benchmark); + #endif + + #if SOC_TOUCH_SENSOR_VERSION == 1 + touch_channel_config_t chan_cfg = { + .abs_active_thresh = {(uint32_t)(benchmark / 2)}, + .charge_speed = TOUCH_CHARGE_SPEED_7, + .init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT, + .group = TOUCH_CHAN_TRIG_GROUP_BOTH, + }; + #elif SOC_TOUCH_SENSOR_VERSION == 2 + touch_channel_config_t chan_cfg = { + .active_thresh = {(uint32_t)(benchmark / 10)}, + .charge_speed = TOUCH_CHARGE_SPEED_7, + .init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT, + }; + #elif SOC_TOUCH_SENSOR_VERSION == 3 + // Values are similar to an ESP-IDF example: 1000, 2500, 5000. + touch_channel_config_t chan_cfg = { + .active_thresh = {(uint32_t)(benchmark / 10), (uint32_t)(benchmark / 4), (uint32_t)(benchmark / 2)}, + }; + #else + #error bad SOC_TOUCH_SENSOR_VERSION + #endif + touch_sensor_reconfig_channel(chan, &chan_cfg); + } + + // Set up filter for proper active/inactive detection + touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG(); + touch_sensor_config_filter(controller, &filter_cfg); + + // Register callback for light sleep wakeup + touch_event_callbacks_t callbacks = { + .on_active = touch_active_callback, + }; + touch_sensor_register_callbacks(controller, &callbacks, NULL); + + // Re-enable and start scanning + touch_sensor_enable(controller); + touch_sensor_start_continuous_scanning(controller); } void alarm_touch_touchalarm_prepare_for_deep_sleep(void) { @@ -140,45 +162,43 @@ void alarm_touch_touchalarm_prepare_for_deep_sleep(void) { return; } - touch_pad_t touch_channel = TOUCH_PAD_MAX; - for (uint8_t i = 1; i <= 14; i++) { - if ((touch_channel_mask & 1 << i) != 0) { - touch_channel = (touch_pad_t)i; + touch_sensor_handle_t controller = peripherals_touch_get_controller(); + + // Find the first alarm channel for deep sleep + int deep_slp_chan_id = -1; + for (uint8_t i = TOUCH_MIN_CHAN_ID; i <= TOUCH_MAX_CHAN_ID; i++) { + if ((touch_channel_mask & (1 << i)) != 0) { + deep_slp_chan_id = i; break; } } - // reset touch peripheral - peripherals_touch_never_reset(false); - peripherals_touch_reset(); - - // initialize touchpad - peripherals_touch_init(touch_channel); + if (deep_slp_chan_id < 0) { + return; + } - #if !defined(CONFIG_IDF_TARGET_ESP32) - // configure touchpad for sleep - touch_pad_sleep_channel_enable(touch_channel, true); - touch_pad_sleep_channel_enable_proximity(touch_channel, false); + // Stop scanning and disable to reconfigure for deep sleep + touch_sensor_stop_continuous_scanning(controller); + touch_sensor_disable(controller); + + #if SOC_TOUCH_SUPPORT_SLEEP_WAKEUP + touch_sleep_config_t sleep_cfg = { + .slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, + #if SOC_TOUCH_SENSOR_VERSION == 1 + .deep_slp_sens_cfg = NULL, + #else + .deep_slp_allow_pd = false, + .deep_slp_chan = peripherals_touch_get_handle(deep_slp_chan_id), + .deep_slp_sens_cfg = NULL, + #endif + }; + touch_sensor_config_sleep_wakeup(controller, &sleep_cfg); #endif - // wait for touch data to reset - mp_hal_delay_ms(10); - - // configure trigger threshold - #if defined(CONFIG_IDF_TARGET_ESP32) - uint16_t touch_value; - touch_pad_read(touch_channel, &touch_value); - // ESP32 touch_pad_read() returns a lower value when a pin is touched, not a higher value - // Typical values on a Feather ESP32 V2 are 600 with a short jumper untouched, - // 70 touched. - touch_pad_set_thresh(touch_channel, touch_value / 2); - #else - uint32_t touch_value; - touch_pad_sleep_channel_read_smooth(touch_channel, &touch_value); - touch_pad_sleep_set_threshold(touch_channel, touch_value / 10); // 10% - #endif + // Re-enable for sleep + touch_sensor_enable(controller); + touch_sensor_start_continuous_scanning(controller); - // enable touchpad wakeup esp_sleep_enable_touchpad_wakeup(); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); } diff --git a/ports/espressif/common-hal/analogbufio/BufferedIn.c b/ports/espressif/common-hal/analogbufio/BufferedIn.c index 20c5c060574..747d7d53878 100644 --- a/ports/espressif/common-hal/analogbufio/BufferedIn.c +++ b/ports/espressif/common-hal/analogbufio/BufferedIn.c @@ -23,7 +23,7 @@ #define NUM_SAMPLES_PER_INTERRUPT 256 #define NUM_ADC_CHANNELS 1 #define DMA_BUFFER_SIZE 1024 -#define ATTENUATION ADC_ATTEN_DB_11 +#define ATTENUATION ADC_ATTEN_DB_12 #define ADC_READ_TIMEOUT_MS 2000 #define ADC_PIN_MAX_VALUE 0xfff diff --git a/ports/espressif/common-hal/analogio/AnalogIn.c b/ports/espressif/common-hal/analogio/AnalogIn.c index 34cd5b846cf..9809962b394 100644 --- a/ports/espressif/common-hal/analogio/AnalogIn.c +++ b/ports/espressif/common-hal/analogio/AnalogIn.c @@ -23,7 +23,7 @@ #define DEFAULT_VREF 1100 #define NO_OF_SAMPLES 2 -#define ATTENUATION ADC_ATTEN_DB_11 +#define ATTENUATION ADC_ATTEN_DB_12 #if defined(CONFIG_IDF_TARGET_ESP32) #define DATA_WIDTH ADC_BITWIDTH_12 #elif defined(CONFIG_IDF_TARGET_ESP32C2) diff --git a/ports/espressif/common-hal/analogio/AnalogIn.h b/ports/espressif/common-hal/analogio/AnalogIn.h index 944039bec2a..cd5f1b5d9ef 100644 --- a/ports/espressif/common-hal/analogio/AnalogIn.h +++ b/ports/espressif/common-hal/analogio/AnalogIn.h @@ -8,7 +8,7 @@ #include "common-hal/microcontroller/Pin.h" -#include "components/hal/include/hal/adc_types.h" +#include "hal/adc_types.h" #include "FreeRTOS.h" #include "freertos/semphr.h" #include "py/obj.h" diff --git a/ports/espressif/common-hal/audiobusio/PDMIn.c b/ports/espressif/common-hal/audiobusio/PDMIn.c index c9d28ad7071..7718f096c89 100644 --- a/ports/espressif/common-hal/audiobusio/PDMIn.c +++ b/ports/espressif/common-hal/audiobusio/PDMIn.c @@ -40,7 +40,7 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self, && bit_depth != I2S_DATA_BIT_WIDTH_16BIT && bit_depth != I2S_DATA_BIT_WIDTH_24BIT && bit_depth != I2S_DATA_BIT_WIDTH_32BIT) { - mp_raise_ValueError(MP_ERROR_TEXT("bit_depth must be 8, 16, 24, or 32.")); + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be 8, 16, 24, or 32"), MP_QSTR_bit_depth); } i2s_chan_config_t chanConfig = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); diff --git a/ports/espressif/common-hal/audiobusio/__init__.c b/ports/espressif/common-hal/audiobusio/__init__.c index d07a0b521ba..2ae34d04960 100644 --- a/ports/espressif/common-hal/audiobusio/__init__.c +++ b/ports/espressif/common-hal/audiobusio/__init__.c @@ -108,7 +108,7 @@ static void i2s_callback_fun(void *self_in) { static bool i2s_event_interrupt(i2s_chan_handle_t handle, i2s_event_data_t *event, void *self_in) { i2s_t *self = self_in; self->underrun = self->underrun || self->next_buffer != NULL; - self->next_buffer = *(int16_t **)event->data; + self->next_buffer = *(int16_t **)event->dma_buf; self->next_buffer_size = event->size; background_callback_add(&self->callback, i2s_callback_fun, self_in); return false; diff --git a/ports/espressif/common-hal/audioi2sin/I2SIn.c b/ports/espressif/common-hal/audioi2sin/I2SIn.c new file mode 100644 index 00000000000..ef8e908e2de --- /dev/null +++ b/ports/espressif/common-hal/audioi2sin/I2SIn.c @@ -0,0 +1,437 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "bindings/espidf/__init__.h" + +#include "common-hal/audioi2sin/I2SIn.h" +#include "py/runtime.h" +#include "shared-bindings/audioi2sin/I2SIn.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/audioi2sin/__init__.h" +#include "supervisor/port.h" + +#include "driver/i2s_std.h" + +#if CIRCUITPY_AUDIOI2SIN + +void common_hal_audioi2sin_i2sin_construct(audioi2sin_i2sin_obj_t *self, + const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select, + const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, + uint32_t sample_rate, uint8_t bit_depth, uint8_t output_bit_depth, + bool mono, bool left_justified, bool samples_signed) { + + i2s_data_bit_width_t bit_width = (i2s_data_bit_width_t)bit_depth; + + i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER); + esp_err_t err = i2s_new_channel(&chan_cfg, NULL, &self->rx_chan); + if (err == ESP_ERR_NOT_FOUND) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Peripheral in use")); + } + CHECK_ESP_RESULT(err); + + // Always configure the bus as stereo. The newer-family I2S peripherals + // (S2/S3/C-series) ignore I2S_SLOT_MODE_MONO on RX and write both slots + // into the DMA buffer regardless, which yields buffers that fill at 2x + // the WS rate and produces half-speed audio. By configuring stereo and + // dropping one slot ourselves in record_to_buffer, behavior is uniform + // across chips. + i2s_std_slot_config_t slot_cfg = left_justified + ? (i2s_std_slot_config_t)I2S_STD_MSB_SLOT_DEFAULT_CONFIG(bit_width, I2S_SLOT_MODE_STEREO) + : (i2s_std_slot_config_t)I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(bit_width, I2S_SLOT_MODE_STEREO); + + i2s_std_config_t std_cfg = { + .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(sample_rate), + .slot_cfg = slot_cfg, + .gpio_cfg = { + .mclk = main_clock != NULL ? main_clock->number : I2S_GPIO_UNUSED, + .bclk = bit_clock->number, + .ws = word_select->number, + .dout = I2S_GPIO_UNUSED, + .din = data->number, + }, + }; + CHECK_ESP_RESULT(i2s_channel_init_std_mode(self->rx_chan, &std_cfg)); + CHECK_ESP_RESULT(i2s_channel_enable(self->rx_chan)); + + self->bit_clock = bit_clock; + self->word_select = word_select; + self->data = data; + self->mclk = main_clock; + self->sample_rate = sample_rate; + self->bit_depth = bit_depth; + self->mono = mono; + self->samples_signed = samples_signed; + + // Populate the audiosample base so I2SIn can stream into the audio pipeline. + // Streaming requires an 8- or 16-bit output depth (reset_buffer enforces it); + // the owned conversion buffer is allocated lazily on first reset_buffer(). + uint8_t channel_count = mono ? 1 : 2; + self->base.sample_rate = sample_rate; + self->base.bits_per_sample = output_bit_depth; + self->base.channel_count = channel_count; + self->base.samples_signed = samples_signed; + self->base.single_buffer = false; + self->base.max_buffer_length = + 2 * AUDIOI2SIN_STREAM_FRAMES * (output_bit_depth / 8) * channel_count; + self->output_buffer = NULL; + self->output_half_bytes = self->base.max_buffer_length / 2; + self->output_index = 0; + + claim_pin(bit_clock); + claim_pin(word_select); + claim_pin(data); + if (main_clock) { + claim_pin(main_clock); + } +} + +bool common_hal_audioi2sin_i2sin_deinited(audioi2sin_i2sin_obj_t *self) { + return self->data == NULL; +} + +void common_hal_audioi2sin_i2sin_deinit(audioi2sin_i2sin_obj_t *self) { + if (common_hal_audioi2sin_i2sin_deinited(self)) { + return; + } + + if (self->rx_chan) { + i2s_channel_disable(self->rx_chan); + i2s_del_channel(self->rx_chan); + self->rx_chan = NULL; + } + + if (self->bit_clock) { + reset_pin_number(self->bit_clock->number); + } + self->bit_clock = NULL; + + if (self->word_select) { + reset_pin_number(self->word_select->number); + } + self->word_select = NULL; + + if (self->data) { + reset_pin_number(self->data->number); + } + self->data = NULL; + + if (self->mclk) { + reset_pin_number(self->mclk->number); + } + self->mclk = NULL; + + if (self->output_buffer != NULL) { + port_free(self->output_buffer); + self->output_buffer = NULL; + } + audiosample_mark_deinit(&self->base); +} + +// Sign-extend a raw I2S sample (in the low `in_depth` bits of `raw`) to a +// canonical int32 value. +static inline int32_t i2sin_normalize_signed(uint32_t raw, uint8_t in_depth) { + if (in_depth == 32) { + return (int32_t)raw; + } + if (in_depth == 24) { + uint32_t sign_bit = 0x800000u; + return (int32_t)((raw ^ sign_bit) - sign_bit); + } + if (in_depth == 16) { + return (int16_t)(raw & 0xffffu); + } + return (int8_t)(raw & 0xffu); +} + +// Read a single sample from the DMA scratch at the given byte offset for the +// configured input bit depth. +static inline uint32_t i2sin_read_raw(const uint8_t *src, uint8_t in_depth) { + if (in_depth == 8) { + return (uint32_t)(*src); + } + if (in_depth == 16) { + uint16_t v; + memcpy(&v, src, sizeof(v)); + return v; + } + uint32_t v; + memcpy(&v, src, sizeof(v)); + return v; +} + +// Normalize `raw` from `in_depth` for this port's wire format, then hand off to +// the shared converter to rescale `in_depth` -> `out_depth` and write it to +// `buffer` at sample index `idx`. The depth conversion + unsigned-WAV flip + +// container store live in `shared_audioi2sin_write_converted` (shared with other +// ports); see that helper for the upscale/downscale semantics. +static inline void i2sin_write_converted(void *buffer, uint32_t idx, + uint32_t raw, uint8_t in_depth, uint8_t out_depth, bool samples_signed) { + int32_t s = i2sin_normalize_signed(raw, in_depth); + shared_audioi2sin_write_converted(buffer, idx, s, in_depth, out_depth, samples_signed); +} + +// I2S delivers signed PCM. When samples_signed is false, XOR each sample with +// the sign bit for its width to convert to unsigned PCM (WAV convention). +static void i2sin_convert_to_unsigned(void *buffer, uint32_t samples, + uint8_t bit_depth, size_t element_size) { + (void)element_size; + uint32_t *p = (uint32_t *)buffer; + + if (bit_depth == 8) { + // 4 samples per word + uint32_t words = samples / 4; + for (uint32_t i = 0; i < words; i++) { + p[i] ^= 0x80808080u; + } + // tail: 0–3 leftover bytes + uint8_t *tail = (uint8_t *)(p + words); + for (uint32_t i = 0; i < (samples & 3u); i++) { + tail[i] ^= 0x80u; + } + } else if (bit_depth == 16) { + // 2 samples per word + uint32_t words = samples / 2; + for (uint32_t i = 0; i < words; i++) { + p[i] ^= 0x80008000u; + } + if (samples & 1u) { + ((uint16_t *)(p + words))[0] ^= 0x8000u; + } + } else { + // 24- or 32-bit: one sample per 32-bit slot + uint32_t mask = (bit_depth == 24) ? 0x00800000u : 0x80000000u; + for (uint32_t i = 0; i < samples; i++) { + p[i] ^= mask; + } + } +} + + +uint32_t common_hal_audioi2sin_i2sin_record_to_buffer(audioi2sin_i2sin_obj_t *self, + void *buffer, uint32_t length) { + size_t element_size = self->bit_depth / 8; + // 24-bit samples occupy a 32-bit slot on the I2S bus. + if (self->bit_depth == 24) { + element_size = 4; + } + + if (self->base.bits_per_sample != self->bit_depth) { + // Bit-depth conversion path: always read at input width into scratch, + // convert each sample into the user's buffer at output width. + const uint8_t in_depth = self->bit_depth; + const uint8_t out_depth = self->base.bits_per_sample; + const bool samples_signed = self->samples_signed; + uint8_t scratch[256]; + const size_t in_frame_bytes = 2 * element_size; + const size_t scratch_frames = sizeof(scratch) / in_frame_bytes; + uint32_t produced = 0; + while (produced < length) { + size_t want_frames; + if (self->mono) { + want_frames = length - produced; + } else { + want_frames = (length - produced + 1) / 2; + } + if (want_frames > scratch_frames) { + want_frames = scratch_frames; + } + size_t got_bytes = 0; + esp_err_t err = i2s_channel_read(self->rx_chan, scratch, + want_frames * in_frame_bytes, &got_bytes, portMAX_DELAY); + CHECK_ESP_RESULT(err); + size_t got_frames = got_bytes / in_frame_bytes; + for (size_t i = 0; i < got_frames && produced < length; i++) { + const uint8_t *frame = scratch + i * in_frame_bytes; + uint32_t left_raw = i2sin_read_raw(frame, in_depth); + i2sin_write_converted(buffer, produced++, left_raw, + in_depth, out_depth, samples_signed); + if (!self->mono && produced < length) { + uint32_t right_raw = i2sin_read_raw(frame + element_size, in_depth); + i2sin_write_converted(buffer, produced++, right_raw, + in_depth, out_depth, samples_signed); + } + } + if (got_frames < want_frames) { + break; + } + } + return produced; + } + + uint32_t produced; + if (!self->mono) { + size_t result = 0; + esp_err_t err = i2s_channel_read(self->rx_chan, buffer, length * element_size, + &result, portMAX_DELAY); + CHECK_ESP_RESULT(err); + produced = result / element_size; + } else { + // Mono: bus is configured stereo, so each WS frame yields two slots in + // the DMA buffer. Read in chunks into a scratch and keep only the left + // slot of each frame. + uint8_t scratch[256]; + const size_t frame_bytes = 2 * element_size; + const size_t scratch_frames = sizeof(scratch) / frame_bytes; + uint8_t *out = (uint8_t *)buffer; + produced = 0; + while (produced < length) { + size_t want_frames = length - produced; + if (want_frames > scratch_frames) { + want_frames = scratch_frames; + } + size_t got_bytes = 0; + esp_err_t err = i2s_channel_read(self->rx_chan, scratch, + want_frames * frame_bytes, &got_bytes, portMAX_DELAY); + CHECK_ESP_RESULT(err); + size_t got_frames = got_bytes / frame_bytes; + for (size_t i = 0; i < got_frames; i++) { + memcpy(out + produced * element_size, + scratch + i * frame_bytes, + element_size); + produced++; + } + if (got_frames < want_frames) { + break; + } + } + } + + if (!self->samples_signed && produced > 0) { + i2sin_convert_to_unsigned(buffer, produced, self->bit_depth, element_size); + } + return produced; +} + +uint8_t common_hal_audioi2sin_i2sin_get_bit_depth(audioi2sin_i2sin_obj_t *self) { + return self->bit_depth; +} + +uint32_t common_hal_audioi2sin_i2sin_get_sample_rate(audioi2sin_i2sin_obj_t *self) { + return self->sample_rate; +} + +bool common_hal_audioi2sin_i2sin_get_samples_signed(audioi2sin_i2sin_obj_t *self) { + return self->samples_signed; +} + +// Write `count` silence samples at output depth starting at sample index `idx`. +// For signed PCM silence is 0; for unsigned (WAV) it is mid-scale. +static void i2sin_fill_silence(void *buffer, uint32_t idx, uint32_t count, + uint8_t out_depth, bool samples_signed) { + if (out_depth == 8) { + uint8_t v = samples_signed ? 0 : 0x80u; + memset((uint8_t *)buffer + idx, v, count); + } else { // 16-bit (the only other streamable width) + uint16_t v = samples_signed ? 0 : 0x8000u; + uint16_t *p = (uint16_t *)buffer + idx; + for (uint32_t i = 0; i < count; i++) { + p[i] = v; + } + } +} + +// Non-blocking fill: read whatever frames are immediately available from the I2S +// driver and convert them into `buffer` (output depth, interleaved), padding the +// remainder with silence on underrun. The bus is configured stereo, so each WS +// frame yields two slots; for mono we keep the left slot. `out_depth` is always 8 +// or 16 here (reset_buffer rejects 24/32). Runs in the output backend's refill +// (background callback) context, so i2s_channel_read is called with a 0 ms +// timeout and never blocks. +void common_hal_audioi2sin_i2sin_fill_buffer(audioi2sin_i2sin_obj_t *self, + uint8_t *buffer, uint32_t frames) { + const uint8_t in_depth = self->bit_depth; + const uint8_t out_depth = self->base.bits_per_sample; + const bool samples_signed = self->samples_signed; + const bool stereo = !self->mono; + const uint8_t channel_count = stereo ? 2 : 1; + size_t element_size = (in_depth == 24) ? 4 : (in_depth / 8); + const size_t in_frame_bytes = 2 * element_size; // bus is always stereo + const uint32_t total_samples = frames * channel_count; + + uint8_t scratch[256]; + const size_t scratch_frames = sizeof(scratch) / in_frame_bytes; + + uint32_t produced = 0; + while (produced < total_samples) { + size_t want_frames = (total_samples - produced + channel_count - 1) / channel_count; + if (want_frames > scratch_frames) { + want_frames = scratch_frames; + } + size_t got_bytes = 0; + // 0 ms timeout: return immediately with whatever is buffered. + esp_err_t err = i2s_channel_read(self->rx_chan, scratch, + want_frames * in_frame_bytes, &got_bytes, 0); + if (err != ESP_OK && err != ESP_ERR_TIMEOUT) { + break; + } + size_t got_frames = got_bytes / in_frame_bytes; + if (got_frames == 0) { + break; // underrun: pad with silence below + } + for (size_t i = 0; i < got_frames && produced < total_samples; i++) { + const uint8_t *frame = scratch + i * in_frame_bytes; + uint32_t left_raw = i2sin_read_raw(frame, in_depth); + i2sin_write_converted(buffer, produced++, left_raw, + in_depth, out_depth, samples_signed); + if (stereo && produced < total_samples) { + uint32_t right_raw = i2sin_read_raw(frame + element_size, in_depth); + i2sin_write_converted(buffer, produced++, right_raw, + in_depth, out_depth, samples_signed); + } + } + if (got_frames < want_frames) { + break; + } + } + if (produced < total_samples) { + i2sin_fill_silence(buffer, produced, total_samples - produced, + out_depth, samples_signed); + } +} + +void common_hal_audioi2sin_i2sin_reset_buffer(audioi2sin_i2sin_obj_t *self, + bool single_channel_output, uint8_t channel) { + (void)single_channel_output; + (void)channel; + // The audio pipeline only carries 8- or 16-bit samples; 24/32-bit modes can + // still record() but cannot stream. + if (self->base.bits_per_sample != 8 && self->base.bits_per_sample != 16) { + mp_raise_ValueError_varg( + MP_ERROR_TEXT("%q must be 8 or 16"), MP_QSTR_output_bit_depth); + } + if (self->output_buffer == NULL) { + self->output_buffer = (uint8_t *)port_malloc(self->base.max_buffer_length, false); + if (self->output_buffer == NULL) { + m_malloc_fail(self->base.max_buffer_length); + } + } + self->output_index = 0; +} + +audioio_get_buffer_result_t common_hal_audioi2sin_i2sin_get_buffer( + audioi2sin_i2sin_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + uint32_t half = self->output_half_bytes; + uint8_t *out = self->output_buffer + half * self->output_index; + self->output_index = 1 - self->output_index; + + uint32_t bytes_per_sample = self->base.bits_per_sample / 8; + uint32_t frames = half / (bytes_per_sample * self->base.channel_count); + common_hal_audioi2sin_i2sin_fill_buffer(self, out, frames); + + if (single_channel_output) { + out += (channel % self->base.channel_count) * bytes_per_sample; + } + *buffer = out; + *buffer_length = half; + // A live mic is an infinite stream; never report DONE or the backend stops. + return GET_BUFFER_MORE_DATA; +} + +#endif // CIRCUITPY_AUDIOI2SIN diff --git a/ports/espressif/common-hal/audioi2sin/I2SIn.h b/ports/espressif/common-hal/audioi2sin/I2SIn.h new file mode 100644 index 00000000000..a6fc7224c32 --- /dev/null +++ b/ports/espressif/common-hal/audioi2sin/I2SIn.h @@ -0,0 +1,43 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +#include "common-hal/microcontroller/Pin.h" + +#include "shared-module/audiocore/__init__.h" + +#include "driver/i2s_std.h" + +#if CIRCUITPY_AUDIOI2SIN + +// Frames handed to the output backend per get_buffer() call; see the matching +// rp2 header for the rationale. +#define AUDIOI2SIN_STREAM_FRAMES (256) + +typedef struct { + // so I2SIn can be used directly as an audiosample source. + audiosample_base_t base; + i2s_chan_handle_t rx_chan; + const mcu_pin_obj_t *bit_clock; + const mcu_pin_obj_t *word_select; + const mcu_pin_obj_t *data; + const mcu_pin_obj_t *mclk; + uint32_t sample_rate; + uint8_t bit_depth; + bool mono; + bool samples_signed; + // Owned double-buffer of converted (output-depth, interleaved) samples, + // allocated lazily on first reset_buffer(). base.max_buffer_length is the + // whole buffer; get_buffer() returns output_half_bytes of it. + uint8_t *output_buffer; + size_t output_half_bytes; + uint8_t output_index; +} audioi2sin_i2sin_obj_t; + +#endif diff --git a/ports/espressif/common-hal/audioi2sin/__init__.c b/ports/espressif/common-hal/audioi2sin/__init__.c new file mode 100644 index 00000000000..584c821b996 --- /dev/null +++ b/ports/espressif/common-hal/audioi2sin/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT diff --git a/ports/espressif/common-hal/busio/I2C.c b/ports/espressif/common-hal/busio/I2C.c index 890f9339c22..30f16276eae 100644 --- a/ports/espressif/common-hal/busio/I2C.c +++ b/ports/espressif/common-hal/busio/I2C.c @@ -9,7 +9,8 @@ #include "py/mphal.h" #include "py/runtime.h" -#include "components/driver/i2c/include/driver/i2c.h" +#include "driver/gpio.h" +#include "soc/soc_caps.h" #include "bindings/espidf/__init__.h" #include "shared-bindings/microcontroller/__init__.h" @@ -88,6 +89,19 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, } CHECK_ESP_RESULT(result); + // Record which port the auto-selected bus landed on. There is no public accessor to map + // a bus handle back to its port, so match the handle against each initialized port. + // Other code (e.g. espcamera) needs the port number to reuse this same bus rather than + // create a second master bus on the same pins. + self->port = -1; + for (i2c_port_num_t port = 0; port < (int)SOC_HP_I2C_NUM; port++) { + i2c_master_bus_handle_t bus_handle; + if (i2c_master_get_bus_handle(port, &bus_handle) == ESP_OK && bus_handle == self->handle) { + self->port = port; + break; + } + } + self->xSemaphore = xSemaphoreCreateMutex(); if (self->xSemaphore == NULL) { i2c_del_master_bus(self->handle); diff --git a/ports/espressif/common-hal/busio/I2C.h b/ports/espressif/common-hal/busio/I2C.h index 25d9791f252..ef69cba7091 100644 --- a/ports/espressif/common-hal/busio/I2C.h +++ b/ports/espressif/common-hal/busio/I2C.h @@ -8,7 +8,7 @@ #include "common-hal/microcontroller/Pin.h" -#include "components/hal/include/hal/i2c_types.h" +#include "hal/i2c_types.h" #include "FreeRTOS.h" #include "freertos/semphr.h" #include "py/obj.h" @@ -22,6 +22,7 @@ typedef struct { size_t timeout_ms; size_t frequency; i2c_master_bus_handle_t handle; + i2c_port_num_t port; SemaphoreHandle_t xSemaphore; bool has_lock; } busio_i2c_obj_t; diff --git a/ports/espressif/common-hal/busio/SPI.c b/ports/espressif/common-hal/busio/SPI.c index 4c07917b20b..b85f8cddd2a 100644 --- a/ports/espressif/common-hal/busio/SPI.c +++ b/ports/espressif/common-hal/busio/SPI.c @@ -22,22 +22,70 @@ static bool spi_bus_is_free(spi_host_device_t host_id) { return spi_bus_get_attr(host_id) == NULL; } +// Add a throwaway device at the given target clock, ask the driver what +// frequency it would actually produce, then remove it. Returns the actual +// frequency in Hz, or -1 if a device could not be added at that target. +static int spi_probe_actual_freq(busio_spi_obj_t *self, + spi_device_interface_config_t *device_config, int target_hz) { + device_config->clock_speed_hz = target_hz; + spi_device_handle_t handle; + if (spi_bus_add_device(self->host_id, device_config, &handle) != ESP_OK) { + return -1; + } + int freq_khz = 0; + spi_device_get_actual_freq(handle, &freq_khz); + spi_bus_remove_device(handle); + return freq_khz * 1000; +} + static void set_spi_config(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { - // 128 is a 50% duty cycle. - const int closest_clock = spi_get_actual_clock(APB_CLK_FREQ, baudrate, 128); - const spi_device_interface_config_t device_config = { - .clock_speed_hz = closest_clock, + spi_device_interface_config_t device_config = { + .clock_speed_hz = baudrate, .mode = phase | (polarity << 1), .spics_io_num = -1, // No CS pin .queue_size = MAX_SPI_TRANSACTIONS, .pre_cb = NULL }; + + // The ESP-IDF driver rounds clock_speed_hz to the nearest frequency it can + // produce, which may be HIGHER than requested. Treat baudrate as a ceiling: + // probe candidate targets (each time adding a throwaway device, asking the + // driver what it actually produced, and removing it) and keep the highest + // target whose actual frequency does not exceed baudrate. We don't inspect + // divisor internals -- those vary between Espressif chips -- only the + // public add/measure/remove API. + int target = baudrate; + int actual = spi_probe_actual_freq(self, &device_config, target); + if (actual < 0 || actual > (int)baudrate) { + // Bisect for the highest target whose actual frequency is <= baudrate. + // Stop refining once the interval is within 1 kHz, the resolution that + // spi_device_get_actual_freq reports. + int lo = 1; + int hi = baudrate; + while (hi - lo > 1000) { + int mid = lo + (hi - lo) / 2; + int mid_actual = spi_probe_actual_freq(self, &device_config, mid); + if (mid_actual >= 0 && mid_actual <= (int)baudrate) { + lo = mid; + } else { + hi = mid; + } + } + target = lo; + } + + device_config.clock_speed_hz = target; esp_err_t result = spi_bus_add_device(self->host_id, &device_config, &spi_handle[self->host_id]); if (result != ESP_OK) { mp_raise_RuntimeError(MP_ERROR_TEXT("SPI configuration failed")); } - self->baudrate = closest_clock; + + // Report the frequency the driver actually settled on for the real device. + int actual_khz = 0; + spi_device_get_actual_freq(spi_handle[self->host_id], &actual_khz); + self->baudrate = actual_khz * 1000; + self->requested_baudrate = baudrate; self->polarity = polarity; self->phase = phase; self->bits = bits; @@ -72,11 +120,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, mp_raise_ValueError(MP_ERROR_TEXT("All SPI peripherals are in use")); } - self->mutex = xSemaphoreCreateMutex(); - if (self->mutex == NULL) { - mp_raise_RuntimeError(MP_ERROR_TEXT("Unable to create lock")); - } - esp_err_t result = spi_bus_initialize(self->host_id, &bus_config, SPI_DMA_CH_AUTO); if (result == ESP_ERR_NO_MEM) { mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("ESP-IDF memory allocation failed")); @@ -151,7 +194,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { - if (baudrate == self->baudrate && + if (baudrate == self->requested_baudrate && polarity == self->polarity && phase == self->phase && bits == self->bits) { @@ -162,11 +205,17 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, return true; } -bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { +// Wait as long as needed for the lock. This is used by SD card access from USB. +// Overrides the default busy-wait implementation in shared-bindings/busio/SPI.c +bool common_hal_busio_spi_wait_for_lock(busio_spi_obj_t *self, uint32_t timeout_ms) { if (common_hal_busio_spi_deinited(self)) { return false; } - return xSemaphoreTake(self->mutex, 1) == pdTRUE; + return xSemaphoreTake(self->mutex, pdMS_TO_TICKS(timeout_ms)) == pdTRUE; +} + +bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + return common_hal_busio_spi_wait_for_lock(self, 0); } bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) { diff --git a/ports/espressif/common-hal/busio/SPI.h b/ports/espressif/common-hal/busio/SPI.h index ac2f404042b..4886ab173ab 100644 --- a/ports/espressif/common-hal/busio/SPI.h +++ b/ports/espressif/common-hal/busio/SPI.h @@ -21,7 +21,8 @@ typedef struct { uint8_t bits; uint8_t phase; uint8_t polarity; - uint32_t baudrate; + uint32_t baudrate; // Actual frequency, reported by the frequency property. + uint32_t requested_baudrate; // Value passed to configure(); used for the cache-hit check. SemaphoreHandle_t mutex; } busio_spi_obj_t; diff --git a/ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c b/ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c index 591c455722e..5df379432a9 100644 --- a/ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c +++ b/ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c @@ -14,7 +14,7 @@ #include "hal/dma_types.h" #include "hal/lcd_hal.h" #include "hal/lcd_ll.h" -#include "soc/lcd_periph.h" +#include "hal/lcd_periph.h" #include "esp_log.h" #define TAG "LCD" @@ -109,8 +109,7 @@ void common_hal_dotclockframebuffer_framebuffer_construct(dotclockframebuffer_fr cfg->timings.flags.pclk_idle_high = pclk_idle_high; cfg->data_width = 16; - cfg->sram_trans_align = 8; - cfg->psram_trans_align = 64; + cfg->dma_burst_size = 64; cfg->hsync_gpio_num = valid_pin(hsync, MP_QSTR_hsync); cfg->vsync_gpio_num = valid_pin(vsync, MP_QSTR_vsync); cfg->de_gpio_num = valid_pin(de, MP_QSTR_de); diff --git a/ports/espressif/common-hal/espcamera/Camera.c b/ports/espressif/common-hal/espcamera/Camera.c index 5b45a26951e..80111311bb7 100644 --- a/ports/espressif/common-hal/espcamera/Camera.c +++ b/ports/espressif/common-hal/espcamera/Camera.c @@ -86,7 +86,11 @@ void common_hal_espcamera_camera_construct( self->camera_config.pin_reset = reset_pin ? common_hal_mcu_pin_number(reset_pin) : NO_PIN; self->camera_config.pin_xclk = external_clock_pin ? common_hal_mcu_pin_number(external_clock_pin) : NO_PIN; - self->camera_config.sccb_i2c_master_bus_handle = self->i2c->handle; + // Reuse the I2C bus that CircuitPython already created on these pins instead of letting + // esp32-camera create a second master bus on the same pins, which doesn't work. + self->camera_config.pin_sccb_sda = -1; + self->camera_config.pin_sccb_scl = -1; + self->camera_config.sccb_i2c_port = i2c->port; self->camera_config.pin_d7 = data_pins[7]; self->camera_config.pin_d6 = data_pins[6]; @@ -153,7 +157,7 @@ bool common_hal_espcamera_camera_deinited(espcamera_camera_obj_t *self) { } bool common_hal_espcamera_camera_available(espcamera_camera_obj_t *self) { - return esp_camera_fb_available(); + return esp_camera_available_frames(); } camera_fb_t *common_hal_espcamera_camera_take(espcamera_camera_obj_t *self, int timeout_ms) { diff --git a/ports/espressif/common-hal/espnow/ESPNow.c b/ports/espressif/common-hal/espnow/ESPNow.c index ae11db25032..eb3b57174a3 100644 --- a/ports/espressif/common-hal/espnow/ESPNow.c +++ b/ports/espressif/common-hal/espnow/ESPNow.c @@ -17,6 +17,7 @@ #include "common-hal/espnow/ESPNow.h" +#include "esp_now.h" #include "mphalport.h" #include "esp_now.h" @@ -119,10 +120,20 @@ void common_hal_espnow_init(espnow_obj_t *self) { common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, true); } - CHECK_ESP_RESULT(esp_wifi_config_espnow_rate(ESP_IF_WIFI_STA, self->phy_rate)); - CHECK_ESP_RESULT(esp_wifi_config_espnow_rate(ESP_IF_WIFI_AP, self->phy_rate)); - CHECK_ESP_RESULT(esp_now_init()); + + // esp_now_set_peer_rate_config() is poorly documented, and we haven't figured out + // what the esp_now_rate_config_t settings should be. For now, just ignore phy_rate. + // Note that esp_now_set_peer_rate_config() must be called after esp_now-init(). + // + // esp_now_rate_config_t rate_config = { + // .phymode = WIFI_PHY_MODE_LR, + // .rate = self->phy_rate, + // .ersu = false, + // .dcm = false, + // }; + // CHECK_ESP_RESULT(esp_now_set_peer_rate_config(NULL, &rate_config)); + CHECK_ESP_RESULT(esp_now_register_send_cb(send_cb)); CHECK_ESP_RESULT(esp_now_register_recv_cb(recv_cb)); } diff --git a/ports/espressif/common-hal/i2ctarget/I2CTarget.c b/ports/espressif/common-hal/i2ctarget/I2CTarget.c index 003e7731faa..648f71e6953 100644 --- a/ports/espressif/common-hal/i2ctarget/I2CTarget.c +++ b/ports/espressif/common-hal/i2ctarget/I2CTarget.c @@ -12,6 +12,19 @@ #include "common-hal/i2ctarget/I2CTarget.h" #include "shared-bindings/microcontroller/Pin.h" +static bool i2c_slave_on_receive(i2c_slave_dev_handle_t i2c_slave, const i2c_slave_rx_done_event_data_t *evt_data, void *arg) { + i2ctarget_i2c_target_obj_t *self = (i2ctarget_i2c_target_obj_t *)arg; + for (uint32_t i = 0; i < evt_data->length; i++) { + uint16_t next_head = (self->recv_head + 1) % I2CTARGET_RECV_BUF_SIZE; + if (next_head == self->recv_tail) { + break; // buffer full + } + self->recv_buf[self->recv_head] = evt_data->buffer[i]; + self->recv_head = next_head; + } + return false; +} + void common_hal_i2ctarget_i2c_target_construct(i2ctarget_i2c_target_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint8_t *addresses, unsigned int num_addresses, bool smbus) { @@ -31,32 +44,40 @@ void common_hal_i2ctarget_i2c_target_construct(i2ctarget_i2c_target_obj_t *self, self->sda_pin = sda; self->scl_pin = scl; - self->i2c_num = peripherals_i2c_get_free_num(); - if (self->i2c_num == I2C_NUM_MAX) { - mp_raise_ValueError(MP_ERROR_TEXT("All I2C peripherals are in use")); - } - - const i2c_config_t i2c_conf = { - .mode = I2C_MODE_SLAVE, - .sda_io_num = self->sda_pin->number, - .scl_io_num = self->scl_pin->number, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .slave.addr_10bit_en = 0, - .slave.slave_addr = self->addresses[0], + self->recv_head = 0; + self->recv_tail = 0; + + i2c_slave_config_t slave_config = { + .i2c_port = -1, // auto + .sda_io_num = sda->number, + .scl_io_num = scl->number, + .clk_source = I2C_CLK_SRC_DEFAULT, + .send_buf_depth = 256, + .receive_buf_depth = 256, + .slave_addr = addresses[0], + .addr_bit_len = I2C_ADDR_BIT_LEN_7, + .flags = { + .enable_internal_pullup = true, + }, }; - // Initialize I2C. - esp_err_t err = peripherals_i2c_init(self->i2c_num, &i2c_conf); + esp_err_t err = i2c_new_slave_device(&slave_config, &self->handle); if (err != ESP_OK) { - if (err == ESP_FAIL) { + if (err == ESP_ERR_NOT_FOUND) { + mp_raise_ValueError(MP_ERROR_TEXT("All I2C peripherals are in use")); + } else if (err == ESP_FAIL) { mp_raise_OSError(MP_EIO); } else { mp_arg_error_invalid(MP_QSTR_I2CTarget); } } + i2c_slave_event_callbacks_t cbs = { + .on_receive = i2c_slave_on_receive, + }; + i2c_slave_register_event_callbacks(self->handle, &cbs, self); + claim_pin(sda); claim_pin(scl); } @@ -70,7 +91,8 @@ void common_hal_i2ctarget_i2c_target_deinit(i2ctarget_i2c_target_obj_t *self) { return; } - peripherals_i2c_deinit(self->i2c_num); + i2c_del_slave_device(self->handle); + self->handle = NULL; common_hal_reset_pin(self->sda_pin); common_hal_reset_pin(self->scl_pin); @@ -83,24 +105,34 @@ int common_hal_i2ctarget_i2c_target_is_addressed(i2ctarget_i2c_target_obj_t *sel *address = self->addresses[0]; *is_read = true; *is_restart = false; - return 1; + // Check if we have received data + if (self->recv_head != self->recv_tail) { + *is_read = false; + return 1; + } + return 0; } int common_hal_i2ctarget_i2c_target_read_byte(i2ctarget_i2c_target_obj_t *self, uint8_t *data) { - i2c_slave_read_buffer(self->i2c_num, data, 128, 0); + if (self->recv_head == self->recv_tail) { + return 0; // no data available + } + *data = self->recv_buf[self->recv_tail]; + self->recv_tail = (self->recv_tail + 1) % I2CTARGET_RECV_BUF_SIZE; return 1; } int common_hal_i2ctarget_i2c_target_write_byte(i2ctarget_i2c_target_obj_t *self, uint8_t data) { - i2c_reset_tx_fifo(self->i2c_num); - i2c_slave_write_buffer(self->i2c_num, &data, 128, 0); + uint32_t write_len; + esp_err_t err = i2c_slave_write(self->handle, &data, 1, &write_len, 100); + if (err != ESP_OK || write_len == 0) { + return 0; + } return 1; } void common_hal_i2ctarget_i2c_target_ack(i2ctarget_i2c_target_obj_t *self, bool ack) { - } void common_hal_i2ctarget_i2c_target_close(i2ctarget_i2c_target_obj_t *self) { - } diff --git a/ports/espressif/common-hal/i2ctarget/I2CTarget.h b/ports/espressif/common-hal/i2ctarget/I2CTarget.h index 2dcfb581eb3..fc41ac84ebc 100644 --- a/ports/espressif/common-hal/i2ctarget/I2CTarget.h +++ b/ports/espressif/common-hal/i2ctarget/I2CTarget.h @@ -7,14 +7,19 @@ #pragma once #include "py/obj.h" -#include "peripherals/i2c.h" +#include "driver/i2c_slave.h" #include "common-hal/microcontroller/Pin.h" +#define I2CTARGET_RECV_BUF_SIZE 128 + typedef struct { mp_obj_base_t base; - i2c_port_t i2c_num; + i2c_slave_dev_handle_t handle; uint8_t *addresses; uint8_t num_addresses; const mcu_pin_obj_t *scl_pin; const mcu_pin_obj_t *sda_pin; + uint8_t recv_buf[I2CTARGET_RECV_BUF_SIZE]; + volatile uint16_t recv_head; + volatile uint16_t recv_tail; } i2ctarget_i2c_target_obj_t; diff --git a/ports/espressif/common-hal/microcontroller/Processor.c b/ports/espressif/common-hal/microcontroller/Processor.c index 0056465f1c5..e87025067a3 100644 --- a/ports/espressif/common-hal/microcontroller/Processor.c +++ b/ports/espressif/common-hal/microcontroller/Processor.c @@ -183,19 +183,18 @@ mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { case ESP_RST_EXT: return RESET_REASON_RESET_PIN; - case ESP_RST_DEEPSLEEP: - switch (esp_sleep_get_wakeup_cause()) { - case ESP_SLEEP_WAKEUP_TIMER: - case ESP_SLEEP_WAKEUP_EXT0: - case ESP_SLEEP_WAKEUP_EXT1: - case ESP_SLEEP_WAKEUP_TOUCHPAD: - case ESP_SLEEP_WAKEUP_ULP: - return RESET_REASON_DEEP_SLEEP_ALARM; - - case ESP_SLEEP_WAKEUP_UNDEFINED: - default: - return RESET_REASON_UNKNOWN; + case ESP_RST_DEEPSLEEP: { + uint32_t wakeup_causes = esp_sleep_get_wakeup_causes(); + uint32_t alarm_causes = (1 << ESP_SLEEP_WAKEUP_TIMER) | + (1 << ESP_SLEEP_WAKEUP_EXT0) | + (1 << ESP_SLEEP_WAKEUP_EXT1) | + (1 << ESP_SLEEP_WAKEUP_TOUCHPAD) | + (1 << ESP_SLEEP_WAKEUP_ULP); + if (wakeup_causes & alarm_causes) { + return RESET_REASON_DEEP_SLEEP_ALARM; } + return RESET_REASON_UNKNOWN; + } case ESP_RST_UNKNOWN: default: diff --git a/ports/espressif/common-hal/microcontroller/__init__.c b/ports/espressif/common-hal/microcontroller/__init__.c index d23afce4d99..9b50cd7b5d2 100644 --- a/ports/espressif/common-hal/microcontroller/__init__.c +++ b/ports/espressif/common-hal/microcontroller/__init__.c @@ -142,7 +142,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { } } -void NORETURN common_hal_mcu_reset(void) { +void MP_NORETURN common_hal_mcu_reset(void) { filesystem_flush(); // TODO: implement as part of flash improvements esp_restart(); } diff --git a/ports/espressif/common-hal/mipidsi/Display.c b/ports/espressif/common-hal/mipidsi/Display.c index 46ef46ed601..dc70f901437 100644 --- a/ports/espressif/common-hal/mipidsi/Display.c +++ b/ports/espressif/common-hal/mipidsi/Display.c @@ -88,7 +88,6 @@ void common_hal_mipidsi_display_construct(mipidsi_display_obj_t *self, .vsync_front_porch = vsync_front_porch, }, .flags = { - .use_dma2d = false, .disable_lp = false, }, }; diff --git a/ports/espressif/common-hal/neopixel_write/__init__.c b/ports/espressif/common-hal/neopixel_write/__init__.c index d0d46a31797..cd62220f620 100644 --- a/ports/espressif/common-hal/neopixel_write/__init__.c +++ b/ports/espressif/common-hal/neopixel_write/__init__.c @@ -31,6 +31,8 @@ #include "driver/gpio.h" #include "driver/rmt_tx.h" +#include "hal/rmt_periph.h" +#include "soc/soc_caps.h" // Use closer to WS2812-style timings instead of WS2812B, to accommodate more varieties. #define WS2812_T0H_NS (316) @@ -53,14 +55,13 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout, .trans_queue_depth = 1, }; - // Greedily try and grab as much RMT memory as we can. The more we get, the - // smoother the output will be because we'll trigger fewer interrupts. We'll - // give it all back once we're done. + // Greedily allocate as much RMT memory as possible, stepping down by one + // channel's worth each time. More memory means fewer interrupts and smoother output. + // We'll give it all back once we're done. rmt_channel_handle_t channel; esp_err_t result = ESP_ERR_NOT_FOUND; - // If no other channels are in use, we can use all of the RMT RAM including the RX channels. - config.mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL * SOC_RMT_CHANNELS_PER_GROUP; - while (result == ESP_ERR_NOT_FOUND && config.mem_block_symbols > 0) { + config.mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL * RMT_LL_CHANS_PER_INST; + while (result == ESP_ERR_NOT_FOUND && config.mem_block_symbols >= SOC_RMT_MEM_WORDS_PER_CHANNEL) { result = rmt_new_tx_channel(&config, &channel); config.mem_block_symbols -= SOC_RMT_MEM_WORDS_PER_CHANNEL; } @@ -117,6 +118,7 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout, rmt_del_channel(channel); raise_esp_error(result); } + result = ESP_ERR_TIMEOUT; while (result == ESP_ERR_TIMEOUT) { RUN_BACKGROUND_TASKS; diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c new file mode 100644 index 00000000000..6fb872248e2 --- /dev/null +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -0,0 +1,571 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include "shared-bindings/qspibus/QSPIBus.h" + +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" + +#include "py/gc.h" +#include "py/runtime.h" + +#include "driver/gpio.h" +#include "esp_heap_caps.h" +#include "soc/soc_caps.h" +#include + +#define QSPI_OPCODE_WRITE_CMD (0x02U) +#define QSPI_OPCODE_WRITE_COLOR (0x32U) +#define LCD_CMD_RAMWR (0x2CU) +#define LCD_CMD_RAMWRC (0x3CU) +#define LCD_CMD_DISPOFF (0x28U) +#define LCD_CMD_SLPIN (0x10U) +#define QSPI_DMA_BUFFER_COUNT (2U) +#define QSPI_DMA_BUFFER_SIZE (16U * 1024U) +#define QSPI_COLOR_TIMEOUT_MS (1000U) +static void qspibus_release_dma_buffers(qspibus_qspibus_obj_t *self) { + for (size_t i = 0; i < QSPI_DMA_BUFFER_COUNT; i++) { + if (self->dma_buffer[i] != NULL) { + heap_caps_free(self->dma_buffer[i]); + self->dma_buffer[i] = NULL; + } + } + self->dma_buffer_size = 0; + self->active_buffer = 0; + self->inflight_transfers = 0; + self->transfer_in_progress = false; +} + +static bool qspibus_allocate_dma_buffers(qspibus_qspibus_obj_t *self) { + const size_t candidates[] = { + QSPI_DMA_BUFFER_SIZE, + QSPI_DMA_BUFFER_SIZE / 2, + QSPI_DMA_BUFFER_SIZE / 4, + }; + + for (size_t c = 0; c < MP_ARRAY_SIZE(candidates); c++) { + size_t size = candidates[c]; + bool ok = true; + for (size_t i = 0; i < QSPI_DMA_BUFFER_COUNT; i++) { + self->dma_buffer[i] = heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_8BIT); + if (self->dma_buffer[i] == NULL) { + ok = false; + break; + } + } + if (ok) { + self->dma_buffer_size = size; + self->active_buffer = 0; + self->inflight_transfers = 0; + self->transfer_in_progress = false; + return true; + } + qspibus_release_dma_buffers(self); + } + return false; +} + +// Reset transfer bookkeeping after timeout/error. Drains any stale semaphore +// tokens that late ISR completions may have posted after the timeout expired. +static void qspibus_reset_transfer_state(qspibus_qspibus_obj_t *self) { + self->inflight_transfers = 0; + self->transfer_in_progress = false; + if (self->transfer_done_sem != NULL) { + while (xSemaphoreTake(self->transfer_done_sem, 0) == pdTRUE) { + } + } +} + +static bool qspibus_wait_one_transfer_done(qspibus_qspibus_obj_t *self, TickType_t timeout) { + if (self->inflight_transfers == 0) { + self->transfer_in_progress = false; + return true; + } + + if (xSemaphoreTake(self->transfer_done_sem, timeout) != pdTRUE) { + return false; + } + self->inflight_transfers--; + self->transfer_in_progress = (self->inflight_transfers > 0); + return true; +} + +static bool qspibus_wait_all_transfers_done(qspibus_qspibus_obj_t *self, TickType_t timeout) { + while (self->inflight_transfers > 0) { + if (!qspibus_wait_one_transfer_done(self, timeout)) { + return false; + } + } + return true; +} + +static void qspibus_send_command_bytes( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len) { + + if (!self->bus_initialized) { + raise_deinited_error(); + } + if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { + if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg(MP_ERROR_TEXT("Operation timed out")); + } + } + + uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)command << 8); + esp_err_t err = esp_lcd_panel_io_tx_param(self->io_handle, packed_cmd, data, len); + if (err != ESP_OK) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("%q failure: %d"), MP_QSTR_QSPI, (int)err); + } +} + +static void qspibus_send_color_bytes( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len) { + + if (!self->bus_initialized) { + raise_deinited_error(); + } + + if (len == 0) { + qspibus_send_command_bytes(self, command, NULL, 0); + return; + } + + // RAMWR must transition to RAMWRC for continued payload chunks. + uint8_t chunk_command = command; + const uint8_t *cursor = data; + size_t remaining = len; + + // Drain stale semaphore tokens that late ISR completions may have + // posted after a previous qspibus_reset_transfer_state(). Without + // this, a stale token could satisfy a future wait, causing the next + // transfer to skip its real DMA-done wait. + if (self->inflight_transfers == 0 && self->transfer_done_sem != NULL) { + while (xSemaphoreTake(self->transfer_done_sem, 0) == pdTRUE) { + } + } + + while (remaining > 0) { + // inflight_transfers is only modified in task context (never from ISR), + // so no atomic/critical section is needed. The ISR only signals the + // counting semaphore; all counter bookkeeping happens task-side. + if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { + if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg(MP_ERROR_TEXT("Operation timed out")); + } + } + + size_t chunk = remaining; + if (chunk > self->dma_buffer_size) { + chunk = self->dma_buffer_size; + } + + uint8_t *buffer = self->dma_buffer[self->active_buffer]; + memcpy(buffer, cursor, chunk); + + uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_COLOR << 24) | ((uint32_t)chunk_command << 8); + esp_err_t err = esp_lcd_panel_io_tx_color(self->io_handle, packed_cmd, buffer, chunk); + if (err != ESP_OK) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("%q failure: %d"), MP_QSTR_QSPI, (int)err); + } + + self->inflight_transfers++; + self->transfer_in_progress = true; + self->active_buffer = (self->active_buffer + 1) % QSPI_DMA_BUFFER_COUNT; + + if (chunk_command == LCD_CMD_RAMWR) { + chunk_command = LCD_CMD_RAMWRC; + } + + cursor += chunk; + remaining -= chunk; + } + + // Let DMA complete asynchronously. The next begin_transaction() will + // wait for all in-flight transfers, allowing fill_area() computation + // to overlap with DMA. The explicit wait is only needed for the + // Python write_data() API path where callers expect the transfer to + // be finished on return. +} + +static bool qspibus_is_color_payload_command(uint8_t command) { + return command == LCD_CMD_RAMWR || command == LCD_CMD_RAMWRC; +} + +static void qspibus_panel_sleep_best_effort(qspibus_qspibus_obj_t *self) { + if (!self->bus_initialized || self->io_handle == NULL) { + return; + } + + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + } + + // If a command is buffered, flush it first so the panel state machine + // doesn't get a truncated transaction before sleep. + if (self->has_pending_command) { + uint32_t pending = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)self->pending_command << 8); + (void)esp_lcd_panel_io_tx_param(self->io_handle, pending, NULL, 0); + self->has_pending_command = false; + } + + uint32_t disp_off = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)LCD_CMD_DISPOFF << 8); + (void)esp_lcd_panel_io_tx_param(self->io_handle, disp_off, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(20)); + + uint32_t sleep_in = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)LCD_CMD_SLPIN << 8); + (void)esp_lcd_panel_io_tx_param(self->io_handle, sleep_in, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(120)); +} + +static bool IRAM_ATTR qspibus_on_color_trans_done( + esp_lcd_panel_io_handle_t io_handle, + esp_lcd_panel_io_event_data_t *event_data, + void *user_ctx) { + (void)io_handle; + (void)event_data; + + qspibus_qspibus_obj_t *self = (qspibus_qspibus_obj_t *)user_ctx; + if (self->transfer_done_sem == NULL) { + return false; + } + BaseType_t x_higher_priority_task_woken = pdFALSE; + + xSemaphoreGiveFromISR(self->transfer_done_sem, &x_higher_priority_task_woken); + return x_higher_priority_task_woken == pdTRUE; +} + +void common_hal_qspibus_qspibus_construct( + qspibus_qspibus_obj_t *self, + const mcu_pin_obj_t *clock, + const mcu_pin_obj_t *data0, + const mcu_pin_obj_t *data1, + const mcu_pin_obj_t *data2, + const mcu_pin_obj_t *data3, + const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *dcx, + const mcu_pin_obj_t *reset, + uint32_t frequency) { + + self->io_handle = NULL; + self->host_id = SPI2_HOST; + self->clock_pin = clock->number; + self->data0_pin = data0->number; + self->data1_pin = data1->number; + self->data2_pin = data2->number; + self->data3_pin = data3->number; + self->cs_pin = cs->number; + self->dcx_pin = (dcx != NULL) ? dcx->number : -1; + self->reset_pin = (reset != NULL) ? reset->number : -1; + self->frequency = frequency; + self->bus_initialized = false; + self->in_transaction = false; + self->has_pending_command = false; + self->pending_command = 0; + self->transfer_in_progress = false; + self->active_buffer = 0; + self->inflight_transfers = 0; + self->dma_buffer_size = 0; + self->dma_buffer[0] = NULL; + self->dma_buffer[1] = NULL; + self->transfer_done_sem = NULL; + + self->transfer_done_sem = xSemaphoreCreateCounting(QSPI_DMA_BUFFER_COUNT, 0); + if (self->transfer_done_sem == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("ESP-IDF memory allocation failed")); + } + + if (!qspibus_allocate_dma_buffers(self)) { + common_hal_qspibus_qspibus_deinit(self); + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Could not allocate DMA capable buffer")); + } + + const spi_bus_config_t bus_config = { + .sclk_io_num = self->clock_pin, + .mosi_io_num = self->data0_pin, + .miso_io_num = self->data1_pin, + .quadwp_io_num = self->data2_pin, + .quadhd_io_num = self->data3_pin, + .max_transfer_sz = self->dma_buffer_size, + .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS, + }; + + esp_err_t err = spi_bus_initialize(self->host_id, &bus_config, SPI_DMA_CH_AUTO); + if (err != ESP_OK) { + common_hal_qspibus_qspibus_deinit(self); + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q in use"), MP_QSTR_SPI); + } + + // Mark bus as initialized so deinit knows to call spi_bus_free(). + self->bus_initialized = true; + + const esp_lcd_panel_io_spi_config_t io_config = { + .cs_gpio_num = self->cs_pin, + .dc_gpio_num = -1, + .spi_mode = 0, + .pclk_hz = self->frequency, + .trans_queue_depth = QSPI_DMA_BUFFER_COUNT, + .on_color_trans_done = qspibus_on_color_trans_done, + .user_ctx = self, + .lcd_cmd_bits = 32, + .lcd_param_bits = 8, + .flags = { + .quad_mode = 1, + }, + }; + + err = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)self->host_id, &io_config, &self->io_handle); + if (err != ESP_OK) { + common_hal_qspibus_qspibus_deinit(self); + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("%q failure: %d"), MP_QSTR_QSPI, (int)err); + } + + claim_pin(clock); + claim_pin(data0); + claim_pin(data1); + claim_pin(data2); + claim_pin(data3); + claim_pin(cs); + if (dcx != NULL) { + claim_pin(dcx); + gpio_set_direction((gpio_num_t)self->dcx_pin, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)self->dcx_pin, 1); + } + + if (reset != NULL) { + claim_pin(reset); + + gpio_set_direction((gpio_num_t)self->reset_pin, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)self->reset_pin, 0); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level((gpio_num_t)self->reset_pin, 1); + vTaskDelay(pdMS_TO_TICKS(120)); + } +} + +void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { + if (self->bus_initialized) { + qspibus_panel_sleep_best_effort(self); + self->in_transaction = false; + + if (self->io_handle != NULL) { + esp_lcd_panel_io_del(self->io_handle); + self->io_handle = NULL; + } + + spi_bus_free(self->host_id); + self->bus_initialized = false; + } + + if (self->transfer_done_sem != NULL) { + // Set NULL before delete so late ISR callbacks (if any) see NULL and skip. + SemaphoreHandle_t sem = self->transfer_done_sem; + self->transfer_done_sem = NULL; + vSemaphoreDelete(sem); + } + + qspibus_release_dma_buffers(self); + + reset_pin_number(self->clock_pin); + reset_pin_number(self->data0_pin); + reset_pin_number(self->data1_pin); + reset_pin_number(self->data2_pin); + reset_pin_number(self->data3_pin); + reset_pin_number(self->cs_pin); + if (self->dcx_pin >= 0) { + reset_pin_number(self->dcx_pin); + } + if (self->reset_pin >= 0) { + reset_pin_number(self->reset_pin); + } + + self->bus_initialized = false; + self->in_transaction = false; + self->has_pending_command = false; + self->pending_command = 0; + self->transfer_in_progress = false; + self->inflight_transfers = 0; +} + +bool common_hal_qspibus_qspibus_deinited(qspibus_qspibus_obj_t *self) { + return !self->bus_initialized; +} + +void common_hal_qspibus_qspibus_write_command( + qspibus_qspibus_obj_t *self, + uint8_t command) { + if (!self->bus_initialized) { + raise_deinited_error(); + } + if (self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + + // If caller stages command-only operations repeatedly, flush the previous + // pending command as no-data before replacing it. + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + } + + self->pending_command = command; + self->has_pending_command = true; +} + +void common_hal_qspibus_qspibus_write_data( + qspibus_qspibus_obj_t *self, + const uint8_t *data, + size_t len) { + if (!self->bus_initialized) { + raise_deinited_error(); + } + if (self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + if (len == 0) { + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + } + return; + } + if (!self->has_pending_command) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + + if (qspibus_is_color_payload_command(self->pending_command)) { + qspibus_send_color_bytes(self, self->pending_command, data, len); + // Python API: wait for DMA to finish so callers see the transfer as + // complete on return. The internal displayio path skips this wait + // to allow fill_area/DMA overlap. + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg(MP_ERROR_TEXT("Operation timed out")); + } + } else { + qspibus_send_command_bytes(self, self->pending_command, data, len); + } + self->has_pending_command = false; +} + +bool common_hal_qspibus_qspibus_reset(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized || self->reset_pin < 0) { + return false; + } + + gpio_set_level((gpio_num_t)self->reset_pin, 0); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level((gpio_num_t)self->reset_pin, 1); + vTaskDelay(pdMS_TO_TICKS(120)); + return true; +} + +bool common_hal_qspibus_qspibus_bus_free(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + return self->bus_initialized && !self->in_transaction && !self->transfer_in_progress && !self->has_pending_command; +} + +bool common_hal_qspibus_qspibus_begin_transaction(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized || self->in_transaction || self->has_pending_command) { + return false; + } + // Wait for any in-flight DMA to complete before starting a new + // transaction. This replaces the old non-blocking bus_free() check + // and enables fill_area()/DMA overlap: the CPU fills the next + // subrectangle while the previous DMA runs, and this wait only + // blocks when we actually need the bus for the next send. + if (self->transfer_in_progress) { + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + return false; + } + } + self->in_transaction = true; + return true; +} + +void common_hal_qspibus_qspibus_send( + mp_obj_t obj, + display_byte_type_t data_type, + display_chip_select_behavior_t chip_select, + const uint8_t *data, + uint32_t data_length) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + (void)chip_select; + if (!self->bus_initialized) { + raise_deinited_error(); + } + if (!self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + + if (data_type == DISPLAY_COMMAND) { + for (uint32_t i = 0; i < data_length; i++) { + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + } + self->pending_command = data[i]; + self->has_pending_command = true; + } + return; + } + + if (!self->has_pending_command) { + if (data_length == 0) { + // Zero-length data write after a no-data command is benign. + return; + } + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + + if (data_length == 0) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + return; + } + + if (qspibus_is_color_payload_command(self->pending_command)) { + qspibus_send_color_bytes(self, self->pending_command, data, data_length); + } else { + qspibus_send_command_bytes(self, self->pending_command, data, data_length); + } + self->has_pending_command = false; +} + +void common_hal_qspibus_qspibus_end_transaction(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized) { + return; + } + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + } + self->in_transaction = false; +} + +void common_hal_qspibus_qspibus_flush(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized) { + return; + } + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + } +} + +void common_hal_qspibus_qspibus_collect_ptrs(mp_obj_t obj) { + (void)obj; +} diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.h b/ports/espressif/common-hal/qspibus/QSPIBus.h new file mode 100644 index 00000000000..eaaa971a79c --- /dev/null +++ b/ports/espressif/common-hal/qspibus/QSPIBus.h @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include + +#include "py/obj.h" + +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_io.h" +#include "driver/spi_master.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +typedef struct { + mp_obj_base_t base; + + // ESP LCD panel IO handle used for QSPI transactions. + esp_lcd_panel_io_handle_t io_handle; + + // SPI host (SPI2_HOST on ESP32-S3). + spi_host_device_t host_id; + + // Claimed GPIO numbers. + int8_t clock_pin; + int8_t data0_pin; + int8_t data1_pin; + int8_t data2_pin; + int8_t data3_pin; + int8_t cs_pin; + int8_t dcx_pin; // -1 when optional DCX line is not provided. + int8_t reset_pin; // -1 when reset line is not provided. + + uint32_t frequency; + bool bus_initialized; + bool in_transaction; + bool has_pending_command; + uint8_t pending_command; + bool transfer_in_progress; + uint8_t active_buffer; + uint8_t inflight_transfers; + size_t dma_buffer_size; + uint8_t *dma_buffer[2]; + + // Signaled from ISR when panel IO transfer completes. + SemaphoreHandle_t transfer_done_sem; +} qspibus_qspibus_obj_t; diff --git a/ports/espressif/common-hal/qspibus/__init__.c b/ports/espressif/common-hal/qspibus/__init__.c new file mode 100644 index 00000000000..2f763b218cb --- /dev/null +++ b/ports/espressif/common-hal/qspibus/__init__.c @@ -0,0 +1,3 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT diff --git a/ports/espressif/common-hal/qspibus/__init__.h b/ports/espressif/common-hal/qspibus/__init__.h new file mode 100644 index 00000000000..2f763b218cb --- /dev/null +++ b/ports/espressif/common-hal/qspibus/__init__.h @@ -0,0 +1,3 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT diff --git a/ports/espressif/common-hal/sdioio/SDCard.c b/ports/espressif/common-hal/sdioio/SDCard.c index 102f4a4048e..04a9b62ec3e 100644 --- a/ports/espressif/common-hal/sdioio/SDCard.c +++ b/ports/espressif/common-hal/sdioio/SDCard.c @@ -22,6 +22,7 @@ static const char *TAG = "SDCard.c"; static bool slot_in_use[2]; static bool never_reset_sdio[2] = { false, false }; +static bool host_initialized = false; static void common_hal_sdioio_sdcard_check_for_deinit(sdioio_sdcard_obj_t *self) { if (common_hal_sdioio_sdcard_deinited(self)) { @@ -112,6 +113,7 @@ void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self, if (err != ESP_OK) { mp_raise_OSError_msg_varg(MP_ERROR_TEXT("SDIO Init Error %x"), err); } + host_initialized = true; } err = sdmmc_host_init_slot(sd_slot, &slot_config); @@ -252,8 +254,9 @@ void common_hal_sdioio_sdcard_deinit(sdioio_sdcard_obj_t *self) { never_reset_sdio[get_slot_index(self)] = false; slot_in_use[get_slot_index(self)] = false; - if (!slot_in_use[0] && !slot_in_use[1]) { + if (!slot_in_use[0] && !slot_in_use[1] && host_initialized) { sdmmc_host_deinit(); + host_initialized = false; } reset_pin_number(self->command); @@ -293,8 +296,9 @@ void sdioio_reset(void) { slot_in_use[i] = false; } } - if (!slot_in_use[0] && !slot_in_use[1]) { + if (!slot_in_use[0] && !slot_in_use[1] && host_initialized) { sdmmc_host_deinit(); + host_initialized = false; } return; diff --git a/ports/espressif/common-hal/socketpool/SocketPool.c b/ports/espressif/common-hal/socketpool/SocketPool.c index aa7461d3ffe..5d7890af171 100644 --- a/ports/espressif/common-hal/socketpool/SocketPool.c +++ b/ports/espressif/common-hal/socketpool/SocketPool.c @@ -24,18 +24,6 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel // common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking. int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res) { - // As of 2022, the version of lwip in esp-idf does not handle the - // trailing-dot syntax of domain names, so emulate it. - // Remove this once https://github.com/espressif/esp-idf/issues/10013 has - // been implemented - if (host) { - size_t strlen_host = strlen(host); - if (strlen_host && host[strlen_host - 1] == '.') { - mp_obj_t nodot = mp_obj_new_str(host, strlen_host - 1); - host = mp_obj_str_get_str(nodot); - } - } - char service_buf[6]; snprintf(service_buf, sizeof(service_buf), "%d", service); diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index dc5311bb8ad..51d4913926f 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -13,6 +13,7 @@ #include "common-hal/wifi/__init__.h" #include "shared/runtime/interrupt_char.h" #include "py/gc.h" +#include "py/mphal.h" #include "py/obj.h" #include "py/runtime.h" #include "shared-bindings/ipaddress/IPv4Address.h" @@ -115,7 +116,7 @@ void common_hal_wifi_radio_set_hostname(wifi_radio_obj_t *self, const char *host mp_obj_t common_hal_wifi_radio_get_mac_address(wifi_radio_obj_t *self) { uint8_t mac[MAC_ADDRESS_LENGTH]; - esp_wifi_get_mac(ESP_IF_WIFI_STA, mac); + esp_wifi_get_mac(WIFI_IF_STA, mac); return mp_obj_new_bytes(mac, MAC_ADDRESS_LENGTH); } @@ -126,7 +127,7 @@ void common_hal_wifi_radio_set_mac_address(wifi_radio_obj_t *self, const uint8_t if ((mac[0] & 0b1) == 0b1) { mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid multicast MAC address")); } - esp_wifi_set_mac(ESP_IF_WIFI_STA, mac); + esp_wifi_set_mac(WIFI_IF_STA, mac); } mp_float_t common_hal_wifi_radio_get_tx_power(wifi_radio_obj_t *self) { @@ -167,7 +168,7 @@ void common_hal_wifi_radio_set_power_management(wifi_radio_obj_t *self, wifi_pow // This is a typical value seen in various examples. config->sta.listen_interval = 3; esp_wifi_set_ps(WIFI_PS_MAX_MODEM); - esp_wifi_set_config(ESP_IF_WIFI_STA, config); + esp_wifi_set_config(WIFI_IF_STA, config); } break; case POWER_MANAGEMENT_NONE: @@ -181,7 +182,7 @@ void common_hal_wifi_radio_set_power_management(wifi_radio_obj_t *self, wifi_pow mp_obj_t common_hal_wifi_radio_get_mac_address_ap(wifi_radio_obj_t *self) { uint8_t mac[MAC_ADDRESS_LENGTH]; - esp_wifi_get_mac(ESP_IF_WIFI_AP, mac); + esp_wifi_get_mac(WIFI_IF_AP, mac); return mp_obj_new_bytes(mac, MAC_ADDRESS_LENGTH); } @@ -192,7 +193,7 @@ void common_hal_wifi_radio_set_mac_address_ap(wifi_radio_obj_t *self, const uint if ((mac[0] & 0b1) == 0b1) { mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid multicast MAC address")); } - esp_wifi_set_mac(ESP_IF_WIFI_AP, mac); + esp_wifi_set_mac(WIFI_IF_AP, mac); } mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self, uint8_t start_channel, uint8_t stop_channel) { @@ -269,6 +270,13 @@ void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_ config->ap.max_connection = max_connections; esp_wifi_set_config(WIFI_IF_AP, config); + // Wait a few ms for the AP to start. Empirically, this takes < 3ms on ESP32, and < 1ms on other chips. + for (size_t ms = 0; ms < 10; ms++) { + if (common_hal_wifi_radio_get_ap_active(self)) { + break; + } + mp_hal_delay_ms(1); + } } bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self) { @@ -386,7 +394,7 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t } else { config->sta.scan_method = WIFI_FAST_SCAN; } - esp_wifi_set_config(ESP_IF_WIFI_STA, config); + esp_wifi_set_config(WIFI_IF_STA, config); self->starting_retries = 5; self->retries_left = 5; esp_wifi_connect(); diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index 0eacd2bab3e..7a9aea3b5e0 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -30,6 +30,10 @@ wifi_radio_obj_t common_hal_wifi_radio_obj; #include "lwip/sockets.h" +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" +#endif + #if CIRCUITPY_STATUS_BAR #include "supervisor/shared/status_bar.h" #endif @@ -88,7 +92,192 @@ static void event_handler(void *arg, esp_event_base_t event_base, ESP_LOGW(TAG, "disconnected"); wifi_event_sta_disconnected_t *d = (wifi_event_sta_disconnected_t *)event_data; uint8_t reason = d->reason; - ESP_LOGW(TAG, "reason %d 0x%02x", reason, reason); + const char *reason_str = "unknown"; + switch (reason) { + case WIFI_REASON_UNSPECIFIED: + reason_str = "unspecified"; + break; + case WIFI_REASON_AUTH_EXPIRE: + reason_str = "auth expire"; + break; + case WIFI_REASON_AUTH_LEAVE: + reason_str = "auth leave"; + break; + case WIFI_REASON_DISASSOC_DUE_TO_INACTIVITY: + reason_str = "disassoc inactivity"; + break; + case WIFI_REASON_ASSOC_TOOMANY: + reason_str = "assoc toomany"; + break; + case WIFI_REASON_CLASS2_FRAME_FROM_NONAUTH_STA: + reason_str = "class2 from nonauth"; + break; + case WIFI_REASON_CLASS3_FRAME_FROM_NONASSOC_STA: + reason_str = "class3 from nonassoc"; + break; + case WIFI_REASON_ASSOC_LEAVE: + reason_str = "assoc leave"; + break; + case WIFI_REASON_ASSOC_NOT_AUTHED: + reason_str = "assoc not authed"; + break; + case WIFI_REASON_DISASSOC_PWRCAP_BAD: + reason_str = "disassoc pwrcap bad"; + break; + case WIFI_REASON_DISASSOC_SUPCHAN_BAD: + reason_str = "disassoc supchan bad"; + break; + case WIFI_REASON_BSS_TRANSITION_DISASSOC: + reason_str = "bss transition disassoc"; + break; + case WIFI_REASON_IE_INVALID: + reason_str = "ie invalid"; + break; + case WIFI_REASON_MIC_FAILURE: + reason_str = "mic failure"; + break; + case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: + reason_str = "4way handshake timeout"; + break; + case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT: + reason_str = "group key update timeout"; + break; + case WIFI_REASON_IE_IN_4WAY_DIFFERS: + reason_str = "ie in 4way differs"; + break; + case WIFI_REASON_GROUP_CIPHER_INVALID: + reason_str = "group cipher invalid"; + break; + case WIFI_REASON_PAIRWISE_CIPHER_INVALID: + reason_str = "pairwise cipher invalid"; + break; + case WIFI_REASON_AKMP_INVALID: + reason_str = "akmp invalid"; + break; + case WIFI_REASON_UNSUPP_RSN_IE_VERSION: + reason_str = "unsupp rsn ie version"; + break; + case WIFI_REASON_INVALID_RSN_IE_CAP: + reason_str = "invalid rsn ie cap"; + break; + case WIFI_REASON_802_1X_AUTH_FAILED: + reason_str = "802.1x auth failed"; + break; + case WIFI_REASON_CIPHER_SUITE_REJECTED: + reason_str = "cipher suite rejected"; + break; + case WIFI_REASON_TDLS_PEER_UNREACHABLE: + reason_str = "tdls peer unreachable"; + break; + case WIFI_REASON_TDLS_UNSPECIFIED: + reason_str = "tdls unspecified"; + break; + case WIFI_REASON_SSP_REQUESTED_DISASSOC: + reason_str = "ssp requested disassoc"; + break; + case WIFI_REASON_NO_SSP_ROAMING_AGREEMENT: + reason_str = "no ssp roaming agreement"; + break; + case WIFI_REASON_BAD_CIPHER_OR_AKM: + reason_str = "bad cipher or akm"; + break; + case WIFI_REASON_NOT_AUTHORIZED_THIS_LOCATION: + reason_str = "not authorized this location"; + break; + case WIFI_REASON_SERVICE_CHANGE_PERCLUDES_TS: + reason_str = "service change precludes ts"; + break; + case WIFI_REASON_UNSPECIFIED_QOS: + reason_str = "unspecified qos"; + break; + case WIFI_REASON_NOT_ENOUGH_BANDWIDTH: + reason_str = "not enough bandwidth"; + break; + case WIFI_REASON_MISSING_ACKS: + reason_str = "missing acks"; + break; + case WIFI_REASON_EXCEEDED_TXOP: + reason_str = "exceeded txop"; + break; + case WIFI_REASON_STA_LEAVING: + reason_str = "sta leaving"; + break; + case WIFI_REASON_END_BA: + reason_str = "end ba"; + break; + case WIFI_REASON_UNKNOWN_BA: + reason_str = "unknown ba"; + break; + case WIFI_REASON_TIMEOUT: + reason_str = "timeout"; + break; + case WIFI_REASON_PEER_INITIATED: + reason_str = "peer initiated"; + break; + case WIFI_REASON_AP_INITIATED: + reason_str = "ap initiated"; + break; + case WIFI_REASON_INVALID_FT_ACTION_FRAME_COUNT: + reason_str = "invalid ft action frame count"; + break; + case WIFI_REASON_INVALID_PMKID: + reason_str = "invalid pmkid"; + break; + case WIFI_REASON_INVALID_MDE: + reason_str = "invalid mde"; + break; + case WIFI_REASON_INVALID_FTE: + reason_str = "invalid fte"; + break; + case WIFI_REASON_TRANSMISSION_LINK_ESTABLISH_FAILED: + reason_str = "transmission link establish failed"; + break; + case WIFI_REASON_ALTERATIVE_CHANNEL_OCCUPIED: + reason_str = "alternative channel occupied"; + break; + case WIFI_REASON_BEACON_TIMEOUT: + reason_str = "beacon timeout"; + break; + case WIFI_REASON_NO_AP_FOUND: + reason_str = "no ap found"; + break; + case WIFI_REASON_AUTH_FAIL: + reason_str = "auth fail"; + break; + case WIFI_REASON_ASSOC_FAIL: + reason_str = "assoc fail"; + break; + case WIFI_REASON_HANDSHAKE_TIMEOUT: + reason_str = "handshake timeout"; + break; + case WIFI_REASON_CONNECTION_FAIL: + reason_str = "connection fail"; + break; + case WIFI_REASON_AP_TSF_RESET: + reason_str = "ap tsf reset"; + break; + case WIFI_REASON_ROAMING: + reason_str = "roaming"; + break; + case WIFI_REASON_ASSOC_COMEBACK_TIME_TOO_LONG: + reason_str = "assoc comeback time too long"; + break; + case WIFI_REASON_SA_QUERY_TIMEOUT: + reason_str = "sa query timeout"; + break; + case WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY: + reason_str = "no ap found w compatible security"; + break; + case WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD: + reason_str = "no ap found in authmode threshold"; + break; + case WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD: + reason_str = "no ap found in rssi threshold"; + break; + default: + break; + } + ESP_LOGW(TAG, "reason %d 0x%02x %s", reason, reason, reason_str); if (radio->retries_left > 0 && reason != WIFI_REASON_AUTH_FAIL && reason != WIFI_REASON_NO_AP_FOUND && @@ -104,12 +293,132 @@ static void event_handler(void *arg, esp_event_base_t event_base, break; } - // Cases to handle later. - // case WIFI_EVENT_STA_AUTHMODE_CHANGE: - default: { - ESP_LOGW(TAG, "event %ld 0x%02ld", event_id, event_id); + case WIFI_EVENT_WIFI_READY: + ESP_LOGW(TAG, "wifi ready"); + break; + case WIFI_EVENT_STA_AUTHMODE_CHANGE: + ESP_LOGW(TAG, "sta authmode change"); + break; + case WIFI_EVENT_STA_WPS_ER_SUCCESS: + ESP_LOGW(TAG, "sta wps er success"); + break; + case WIFI_EVENT_STA_WPS_ER_FAILED: + ESP_LOGW(TAG, "sta wps er failed"); + break; + case WIFI_EVENT_STA_WPS_ER_TIMEOUT: + ESP_LOGW(TAG, "sta wps er timeout"); + break; + case WIFI_EVENT_STA_WPS_ER_PIN: + ESP_LOGW(TAG, "sta wps er pin"); + break; + case WIFI_EVENT_STA_WPS_ER_PBC_OVERLAP: + ESP_LOGW(TAG, "sta wps er pbc overlap"); + break; + case WIFI_EVENT_AP_PROBEREQRECVED: + ESP_LOGW(TAG, "ap probereqrecved"); + break; + case WIFI_EVENT_FTM_REPORT: + ESP_LOGW(TAG, "ftm report"); + break; + case WIFI_EVENT_STA_BSS_RSSI_LOW: + ESP_LOGW(TAG, "sta bss rssi low"); + break; + case WIFI_EVENT_ACTION_TX_STATUS: + ESP_LOGW(TAG, "action tx status"); + break; + case WIFI_EVENT_ROC_DONE: + ESP_LOGW(TAG, "roc done"); + break; + case WIFI_EVENT_STA_BEACON_TIMEOUT: + ESP_LOGW(TAG, "sta beacon timeout"); + break; + case WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START: + ESP_LOGW(TAG, "connectionless module wake interval start"); + break; + case WIFI_EVENT_AP_WPS_RG_SUCCESS: + ESP_LOGW(TAG, "ap wps rg success"); + break; + case WIFI_EVENT_AP_WPS_RG_FAILED: + ESP_LOGW(TAG, "ap wps rg failed"); + break; + case WIFI_EVENT_AP_WPS_RG_TIMEOUT: + ESP_LOGW(TAG, "ap wps rg timeout"); + break; + case WIFI_EVENT_AP_WPS_RG_PIN: + ESP_LOGW(TAG, "ap wps rg pin"); + break; + case WIFI_EVENT_AP_WPS_RG_PBC_OVERLAP: + ESP_LOGW(TAG, "ap wps rg pbc overlap"); + break; + case WIFI_EVENT_ITWT_SETUP: + ESP_LOGW(TAG, "itwt setup"); + break; + case WIFI_EVENT_ITWT_TEARDOWN: + ESP_LOGW(TAG, "itwt teardown"); + break; + case WIFI_EVENT_ITWT_PROBE: + ESP_LOGW(TAG, "itwt probe"); + break; + case WIFI_EVENT_ITWT_SUSPEND: + ESP_LOGW(TAG, "itwt suspend"); + break; + case WIFI_EVENT_TWT_WAKEUP: + ESP_LOGW(TAG, "twt wakeup"); + break; + case WIFI_EVENT_BTWT_SETUP: + ESP_LOGW(TAG, "btwt setup"); + break; + case WIFI_EVENT_BTWT_TEARDOWN: + ESP_LOGW(TAG, "btwt teardown"); + break; + case WIFI_EVENT_NAN_SYNC_STARTED: + ESP_LOGW(TAG, "nan sync started"); + break; + case WIFI_EVENT_NAN_SYNC_STOPPED: + ESP_LOGW(TAG, "nan sync stopped"); + break; + case WIFI_EVENT_NAN_SVC_MATCH: + ESP_LOGW(TAG, "nan svc match"); + break; + case WIFI_EVENT_NAN_REPLIED: + ESP_LOGW(TAG, "nan replied"); + break; + case WIFI_EVENT_NAN_RECEIVE: + ESP_LOGW(TAG, "nan receive"); + break; + case WIFI_EVENT_NDP_INDICATION: + ESP_LOGW(TAG, "ndp indication"); + break; + case WIFI_EVENT_NDP_CONFIRM: + ESP_LOGW(TAG, "ndp confirm"); + break; + case WIFI_EVENT_NDP_TERMINATED: + ESP_LOGW(TAG, "ndp terminated"); + break; + case WIFI_EVENT_HOME_CHANNEL_CHANGE: + ESP_LOGW(TAG, "home channel change"); + break; + case WIFI_EVENT_STA_NEIGHBOR_REP: + ESP_LOGW(TAG, "sta neighbor rep"); + break; + case WIFI_EVENT_AP_WRONG_PASSWORD: + ESP_LOGW(TAG, "ap wrong password"); + break; + case WIFI_EVENT_STA_BEACON_OFFSET_UNSTABLE: + ESP_LOGW(TAG, "sta beacon offset unstable"); + break; + case WIFI_EVENT_DPP_URI_READY: + ESP_LOGW(TAG, "dpp uri ready"); + break; + case WIFI_EVENT_DPP_CFG_RECVD: + ESP_LOGW(TAG, "dpp cfg recvd"); + break; + case WIFI_EVENT_DPP_FAILED: + ESP_LOGW(TAG, "dpp failed"); + break; + default: + ESP_LOGW(TAG, "unknown event %ld", event_id); break; - } } } @@ -202,23 +511,36 @@ void common_hal_wifi_init(bool user_initiated) { ESP_LOGE(TAG, "WiFi error code: %x", result); return; } - // Set the default lwip_local_hostname capped at 32 characters. We trim off - // the start of the board name (likely manufacturer) because the end is - // often more unique to the board. - size_t board_len = MIN(32 - ((MAC_ADDRESS_LENGTH * 2) + 6), strlen(CIRCUITPY_BOARD_ID)); - size_t board_trim = strlen(CIRCUITPY_BOARD_ID) - board_len; - // Avoid double _ in the hostname. - if (CIRCUITPY_BOARD_ID[board_trim] == '_') { - board_trim++; + + #if CIRCUITPY_SETTINGS_TOML + char hostname[CONFIG_LWIP_DHCPS_MAX_HOSTNAME_LEN]; + if (settings_get_str("CIRCUITPY_WIFI_HOSTNAME", hostname, sizeof(hostname)) == SETTINGS_OK) { + ESP_ERROR_CHECK(esp_netif_set_hostname(self->netif, hostname)); } + #else + if (false) { + } + #endif + else { + // Set the default lwip_local_hostname capped at 32 characters. We trim off + // the start of the board name (likely manufacturer) because the end is + // often more unique to the board. + size_t board_len = MIN(32 - ((MAC_ADDRESS_LENGTH * 2) + 6), strlen(CIRCUITPY_BOARD_ID)); + size_t board_trim = strlen(CIRCUITPY_BOARD_ID) - board_len; + // Avoid double _ in the hostname. + if (CIRCUITPY_BOARD_ID[board_trim] == '_') { + board_trim++; + } + + char cpy_default_hostname[board_len + (MAC_ADDRESS_LENGTH * 2) + 6]; + uint8_t mac[MAC_ADDRESS_LENGTH]; + esp_wifi_get_mac(WIFI_IF_STA, mac); + snprintf(cpy_default_hostname, sizeof(cpy_default_hostname), "cpy-%s-%02x%02x%02x%02x%02x%02x", CIRCUITPY_BOARD_ID + board_trim, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - char cpy_default_hostname[board_len + (MAC_ADDRESS_LENGTH * 2) + 6]; - uint8_t mac[MAC_ADDRESS_LENGTH]; - esp_wifi_get_mac(ESP_IF_WIFI_STA, mac); - snprintf(cpy_default_hostname, sizeof(cpy_default_hostname), "cpy-%s-%02x%02x%02x%02x%02x%02x", CIRCUITPY_BOARD_ID + board_trim, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + const char *default_lwip_local_hostname = cpy_default_hostname; + ESP_ERROR_CHECK(esp_netif_set_hostname(self->netif, default_lwip_local_hostname)); + } - const char *default_lwip_local_hostname = cpy_default_hostname; - ESP_ERROR_CHECK(esp_netif_set_hostname(self->netif, default_lwip_local_hostname)); // set station mode to avoid the default SoftAP common_hal_wifi_radio_start_station(self); // start wifi diff --git a/ports/espressif/esp-camera b/ports/espressif/esp-camera index 243560e9499..303985ab678 160000 --- a/ports/espressif/esp-camera +++ b/ports/espressif/esp-camera @@ -1 +1 @@ -Subproject commit 243560e94997c262565ed537154b0578b8ce2197 +Subproject commit 303985ab678391b78ebe0baff98edcc863f296c2 diff --git a/ports/espressif/esp-idf b/ports/espressif/esp-idf index f4fddd2d05b..2b900d1222c 160000 --- a/ports/espressif/esp-idf +++ b/ports/espressif/esp-idf @@ -1 +1 @@ -Subproject commit f4fddd2d05b44d1d606b546b596d17de0a73e9eb +Subproject commit 2b900d1222cfce5dfa340ed99375af69ec1ee192 diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32.defaults index 5789c442a62..1b2698068ed 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32.defaults @@ -62,10 +62,10 @@ CONFIG_ESP_IPC_TASK_STACK_SIZE=1536 # end of Wi-Fi # -# Newlib +# LibC # -CONFIG_NEWLIB_NANO_FORMAT=y -# end of Newlib +CONFIG_LIBC_NEWLIB_NANO_FORMAT=y +# end of LibC # # SPI Flash driver diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32c2.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32c2.defaults index 19c73ca5ee5..661b2b52801 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32c2.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32c2.defaults @@ -43,10 +43,10 @@ CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 # end of Wi-Fi # -# Newlib +# LibC # -CONFIG_NEWLIB_NANO_FORMAT=y -# end of Newlib +CONFIG_LIBC_NEWLIB_NANO_FORMAT=y +# end of LibC # end of Component config diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32c3.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32c3.defaults index 19c73ca5ee5..661b2b52801 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32c3.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32c3.defaults @@ -43,10 +43,10 @@ CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 # end of Wi-Fi # -# Newlib +# LibC # -CONFIG_NEWLIB_NANO_FORMAT=y -# end of Newlib +CONFIG_LIBC_NEWLIB_NANO_FORMAT=y +# end of LibC # end of Component config diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults index 101f90f9fa4..126b49c6fd3 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults @@ -43,10 +43,10 @@ CONFIG_ESP_WIFI_RX_BA_WIN=4 # end of Wi-Fi # -# Newlib +# LibC # -CONFIG_NEWLIB_NANO_FORMAT=y -# end of Newlib +CONFIG_LIBC_NEWLIB_NANO_FORMAT=y +# end of LibC # # Ultra Low Power (ULP) Co-processor @@ -58,12 +58,6 @@ CONFIG_ULP_COPROC_TYPE_RISCV=y # Note: enabling both ULPs simultaneously only w CONFIG_ULP_COPROC_RESERVE_MEM=8144 # end of Ultra Low Power (ULP) Co-processor -# -# FreeRTOS -# -CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y -# end of FreeRTOS - # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults index 2553c648018..b48bb58df3f 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults @@ -83,10 +83,10 @@ CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=16 # end of Wi-Fi # -# Newlib +# LibC # -CONFIG_NEWLIB_NANO_FORMAT=y -# end of Newlib +CONFIG_LIBC_NEWLIB_NANO_FORMAT=y +# end of LibC # # Ultra Low Power (ULP) Co-processor diff --git a/ports/espressif/esp-idf-config/sdkconfig-flash-120m.defaults b/ports/espressif/esp-idf-config/sdkconfig-flash-120m.defaults index 6a2285a2936..d582a77798c 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-flash-120m.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-flash-120m.defaults @@ -1,2 +1,4 @@ CONFIG_ESPTOOLPY_FLASHFREQ_120M=y CONFIG_SPI_FLASH_UNDER_HIGH_FREQ=y +CONFIG_SPI_FLASH_HPM_ENA=y +CONFIG_BOOTLOADER_FLASH_DC_AWARE=y diff --git a/ports/espressif/esp-idf-config/sdkconfig-flash-2MB-no-ota-no-uf2.defaults b/ports/espressif/esp-idf-config/sdkconfig-flash-2MB-no-ota-no-uf2.defaults index 2d0b2ac5eb9..21365b751d1 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-flash-2MB-no-ota-no-uf2.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-flash-2MB-no-ota-no-uf2.defaults @@ -7,7 +7,6 @@ CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set CONFIG_ESPTOOLPY_FLASHSIZE="2MB" -CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y # end of Serial flasher config CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-2MB-no-ota-no-uf2.csv" diff --git a/ports/espressif/esp-idf-config/sdkconfig-flash-32MB.defaults b/ports/espressif/esp-idf-config/sdkconfig-flash-32MB.defaults index bbdd32afb81..a5a93778864 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-flash-32MB.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-flash-32MB.defaults @@ -8,7 +8,6 @@ # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set CONFIG_ESPTOOLPY_FLASHSIZE_32MB=y CONFIG_ESPTOOLPY_FLASHSIZE="32MB" -CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y # end of Serial flasher config CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-32MB.csv" diff --git a/ports/espressif/esp-idf-config/sdkconfig.defaults b/ports/espressif/esp-idf-config/sdkconfig.defaults index 5c4d6a31a62..941f879ed42 100644 --- a/ports/espressif/esp-idf-config/sdkconfig.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig.defaults @@ -17,7 +17,7 @@ CONFIG_PARTITION_TABLE_CUSTOM=y # GPTimer Configuration # CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM=y -CONFIG_GPTIMER_ISR_IRAM_SAFE=y +CONFIG_GPTIMER_ISR_CACHE_SAFE=y # end of GPTimer Configuration # @@ -68,13 +68,12 @@ CONFIG_FREERTOS_HZ=1000 # # LibC # -# end of LWIP -CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS=y # end of LibC # # LWIP # +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 CONFIG_LWIP_MAX_SOCKETS=8 CONFIG_LWIP_SO_RCVBUF=y # @@ -116,11 +115,7 @@ CONFIG_MBEDTLS_SSL_PROTO_DTLS=y # CONFIG_MBEDTLS_PEM_WRITE_C is not set # end of Certificates -# CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED is not set -# CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED is not set # CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED is not set -# CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED is not set -# CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED is not set # CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED is not set # CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED is not set # CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED is not set diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index 67f8ca2987b..f7a14f83202 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -64,10 +64,11 @@ CIRCUITPY_LIBC_STRING0 = 0 # These modules are implemented in ports//common-hal: CIRCUITPY__EVE ?= 1 CIRCUITPY_ALARM ?= 1 -CIRCUITPY_ALARM_TOUCH ?= 0 +CIRCUITPY_ALARM_TOUCH ?= 1 CIRCUITPY_ANALOGBUFIO ?= 1 CIRCUITPY_AUDIOBUSIO ?= 1 -CIRCUITPY_AUDIOBUSIO_PDMIN ?= 0 +CIRCUITPY_AUDIOBUSIO_PDMIN ?= 1 +CIRCUITPY_AUDIOI2SIN ?= 1 CIRCUITPY_AUDIOIO ?= 1 CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_BLEIO_NATIVE ?= 1 @@ -79,7 +80,7 @@ CIRCUITPY_ESPULP ?= 1 CIRCUITPY_FRAMEBUFFERIO ?= 1 CIRCUITPY_FREQUENCYIO ?= 1 CIRCUITPY_HASHLIB ?= 1 -CIRCUITPY_I2CTARGET ?= 0 +CIRCUITPY_I2CTARGET = 0 CIRCUITPY_MAX3421E ?= 1 CIRCUITPY_MEMORYMAP ?= 1 CIRCUITPY_RCLCPY ?= 0 @@ -91,6 +92,7 @@ CIRCUITPY_ROTARYIO ?= 1 CIRCUITPY_SDIOIO ?= 1 CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY ?= 1 CIRCUITPY_SYNTHIO_MAX_CHANNELS ?= 12 +CIRCUITPY_TOUCHIO ?= 1 CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 CIRCUITPY_WATCHDOG ?= 1 CIRCUITPY_WIFI ?= 1 @@ -100,7 +102,6 @@ CIRCUITPY_SOCKETPOOL_IPV6 ?= 1 #### esp32 ############################################################ ifeq ($(IDF_TARGET),esp32) # Modules -CIRCUITPY_ALARM_TOUCH = 1 CIRCUITPY_RGBMATRIX = 0 # Has no USB @@ -116,6 +117,10 @@ CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_ESPULP = 0 CIRCUITPY_MEMORYMAP = 0 +# No capacitive touch peripheral +CIRCUITPY_ALARM_TOUCH = 0 +CIRCUITPY_TOUCHIO_USE_NATIVE = 0 + # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 @@ -132,6 +137,7 @@ CIRCUITPY_ANALOGBUFIO = 0 # No I2S CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOI2SIN = 0 # No DAC CIRCUITPY_AUDIOIO = 0 @@ -144,8 +150,6 @@ CIRCUITPY_RGBMATRIX = 0 # No SDMMC CIRCUITPY_SDIOIO = 0 -CIRCUITPY_TOUCHIO ?= 1 -CIRCUITPY_TOUCHIO_USE_NATIVE = 0 # Features CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 @@ -160,9 +164,17 @@ CIRCUITPY_MEMORYMAP = 0 # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 +# No capacitive touch peripheral +CIRCUITPY_ALARM_TOUCH = 0 +CIRCUITPY_TOUCHIO_USE_NATIVE = 0 + # No DAC CIRCUITPY_AUDIOIO = 0 +# No I2S peripheral PDM-to-PCM hardware support +CIRCUITPY_AUDIOBUSIO_PDMIN = 0 +CIRCUITPY_AUDIOI2SIN = 0 + # No PCNT peripheral CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_COUNTIO = 0 @@ -171,8 +183,6 @@ CIRCUITPY_ROTARYIO = 0 # No SDMMC CIRCUITPY_SDIOIO = 0 -CIRCUITPY_TOUCHIO ?= 1 -CIRCUITPY_TOUCHIO_USE_NATIVE = 0 # Features CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 @@ -185,11 +195,19 @@ CIRCUITPY_ESPULP = 0 CIRCUITPY_MEMORYMAP = 0 CIRCUITPY_RGBMATRIX = 0 +# No capacitive touch peripheral +CIRCUITPY_ALARM_TOUCH = 0 +CIRCUITPY_TOUCHIO_USE_NATIVE = 0 + # No DAC CIRCUITPY_AUDIOIO = 0 +# No I2S peripheral PDM-to-PCM hardware support +CIRCUITPY_AUDIOBUSIO_PDMIN = 0 + # No space for this CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOI2SIN = 0 # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 @@ -197,8 +215,6 @@ CIRCUITPY_PARALLELDISPLAYBUS = 0 # No SDMMC CIRCUITPY_SDIOIO = 0 -CIRCUITPY_TOUCHIO ?= 1 -CIRCUITPY_TOUCHIO_USE_NATIVE = 0 # Features CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 @@ -211,11 +227,16 @@ CIRCUITPY_ESPULP = 0 CIRCUITPY_MEMORYMAP = 0 CIRCUITPY_RGBMATRIX = 0 +# No capacitive touch peripheral +CIRCUITPY_ALARM_TOUCH = 0 +CIRCUITPY_TOUCHIO_USE_NATIVE = 0 + # No DAC CIRCUITPY_AUDIOIO = 0 # No space for this CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOI2SIN = 0 # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 @@ -223,8 +244,6 @@ CIRCUITPY_PARALLELDISPLAYBUS = 0 # No SDMMC CIRCUITPY_SDIOIO = 0 -CIRCUITPY_TOUCHIO ?= 1 -CIRCUITPY_TOUCHIO_USE_NATIVE = 0 # Features CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 @@ -250,18 +269,22 @@ CIRCUITPY_ESPULP = 0 CIRCUITPY_MEMORYMAP = 0 CIRCUITPY_RGBMATRIX = 0 +# No capacitive touch peripheral +CIRCUITPY_ALARM_TOUCH = 0 +CIRCUITPY_TOUCHIO_USE_NATIVE = 0 + # No DAC CIRCUITPY_AUDIOIO = 0 +# No I2S peripheral PDM-to-PCM hardware support +CIRCUITPY_AUDIOBUSIO_PDMIN = 0 + # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 # No SDMMC CIRCUITPY_SDIOIO = 0 -CIRCUITPY_TOUCHIO ?= 1 -CIRCUITPY_TOUCHIO_USE_NATIVE = 0 - # Features CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 @@ -281,9 +304,6 @@ CIRCUITPY_BLEIO_NATIVE = 0 CIRCUITPY_WIFI = 0 CIRCUITPY_SSL = 0 -CIRCUITPY_TOUCHIO = 1 -CIRCUITPY_TOUCHIO_USE_NATIVE = 0 - # Second stage bootloader doesn't work when the factory partition is empty due to # UF2 missing. UF2_BOOTLOADER = 0 @@ -314,9 +334,11 @@ CIRCUITPY_MIPIDSI = 1 #### esp32s2 ########################################################## else ifeq ($(IDF_TARGET),esp32s2) # Modules -CIRCUITPY_ALARM_TOUCH = $(CIRCUITPY_ALARM) CIRCUITPY_AUDIOIO ?= 1 +# No I2S peripheral PDM-to-PCM hardware support +CIRCUITPY_AUDIOBUSIO_PDMIN = 0 + # No BLE in hw CIRCUITPY_BLEIO_NATIVE = 0 @@ -329,8 +351,6 @@ CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 0 else ifeq ($(IDF_TARGET),esp32s3) # Modules -CIRCUITPY_ALARM_TOUCH = $(CIRCUITPY_ALARM) -CIRCUITPY_AUDIOBUSIO_PDMIN = 1 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 0 # No DAC @@ -339,6 +359,9 @@ CIRCUITPY_AUDIOIO = 0 endif #### end chip-specific choices ######################################## +# By default, enable dualbank, and it'll be disabled for small flash sizes +CIRCUITPY_DUALBANK ?= 1 + # No room for large modules on 2MB boards # 2MB boards have a single firmware partition, and can't do dualbank. ifeq ($(CIRCUITPY_ESP_FLASH_SIZE),2MB) diff --git a/ports/espressif/peripherals/esp32/pins.c b/ports/espressif/peripherals/esp32/pins.c index e2c45bd06fc..3aa12c9e675 100644 --- a/ports/espressif/peripherals/esp32/pins.c +++ b/ports/espressif/peripherals/esp32/pins.c @@ -6,11 +6,11 @@ #include "peripherals/pins.h" -const mcu_pin_obj_t pin_GPIO0 = PIN(0, ADC_UNIT_2, ADC_CHANNEL_1, TOUCH_PAD_NUM1); +const mcu_pin_obj_t pin_GPIO0 = PIN(0, ADC_UNIT_2, ADC_CHANNEL_1, 1); const mcu_pin_obj_t pin_GPIO1 = PIN(1, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); -const mcu_pin_obj_t pin_GPIO2 = PIN(2, ADC_UNIT_2, ADC_CHANNEL_2, TOUCH_PAD_NUM2); +const mcu_pin_obj_t pin_GPIO2 = PIN(2, ADC_UNIT_2, ADC_CHANNEL_2, 2); const mcu_pin_obj_t pin_GPIO3 = PIN(3, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); -const mcu_pin_obj_t pin_GPIO4 = PIN(4, ADC_UNIT_2, ADC_CHANNEL_0, TOUCH_PAD_NUM0); +const mcu_pin_obj_t pin_GPIO4 = PIN(4, ADC_UNIT_2, ADC_CHANNEL_0, 0); const mcu_pin_obj_t pin_GPIO5 = PIN(5, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO6 = PIN(6, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO7 = PIN(7, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); @@ -18,10 +18,10 @@ const mcu_pin_obj_t pin_GPIO8 = PIN(8, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL) const mcu_pin_obj_t pin_GPIO9 = PIN(9, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO10 = PIN(10, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO11 = PIN(11, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); -const mcu_pin_obj_t pin_GPIO12 = PIN(12, ADC_UNIT_2, ADC_CHANNEL_5, TOUCH_PAD_NUM5); -const mcu_pin_obj_t pin_GPIO13 = PIN(13, ADC_UNIT_2, ADC_CHANNEL_4, TOUCH_PAD_NUM4); -const mcu_pin_obj_t pin_GPIO14 = PIN(14, ADC_UNIT_2, ADC_CHANNEL_6, TOUCH_PAD_NUM6); -const mcu_pin_obj_t pin_GPIO15 = PIN(15, ADC_UNIT_2, ADC_CHANNEL_3, TOUCH_PAD_NUM3); +const mcu_pin_obj_t pin_GPIO12 = PIN(12, ADC_UNIT_2, ADC_CHANNEL_5, 5); +const mcu_pin_obj_t pin_GPIO13 = PIN(13, ADC_UNIT_2, ADC_CHANNEL_4, 4); +const mcu_pin_obj_t pin_GPIO14 = PIN(14, ADC_UNIT_2, ADC_CHANNEL_6, 6); +const mcu_pin_obj_t pin_GPIO15 = PIN(15, ADC_UNIT_2, ADC_CHANNEL_3, 3); const mcu_pin_obj_t pin_GPIO16 = PIN(16, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO17 = PIN(17, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO18 = PIN(18, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); @@ -34,13 +34,13 @@ const mcu_pin_obj_t pin_GPIO23 = PIN(23, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNE // no GPIO24 const mcu_pin_obj_t pin_GPIO25 = PIN(25, ADC_UNIT_2, ADC_CHANNEL_8, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO26 = PIN(26, ADC_UNIT_2, ADC_CHANNEL_9, NO_TOUCH_CHANNEL); -const mcu_pin_obj_t pin_GPIO27 = PIN(27, ADC_UNIT_2, ADC_CHANNEL_7, TOUCH_PAD_NUM7); +const mcu_pin_obj_t pin_GPIO27 = PIN(27, ADC_UNIT_2, ADC_CHANNEL_7, 7); // no GPIO28 // no GPIO29 // no GPIO30 // no GPIO31 -const mcu_pin_obj_t pin_GPIO32 = PIN(32, ADC_UNIT_1, ADC_CHANNEL_4, TOUCH_PAD_NUM9); -const mcu_pin_obj_t pin_GPIO33 = PIN(33, ADC_UNIT_1, ADC_CHANNEL_5, TOUCH_PAD_NUM8); +const mcu_pin_obj_t pin_GPIO32 = PIN(32, ADC_UNIT_1, ADC_CHANNEL_4, 9); +const mcu_pin_obj_t pin_GPIO33 = PIN(33, ADC_UNIT_1, ADC_CHANNEL_5, 8); const mcu_pin_obj_t pin_GPIO34 = PIN(34, ADC_UNIT_1, ADC_CHANNEL_6, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO35 = PIN(35, ADC_UNIT_1, ADC_CHANNEL_7, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO36 = PIN(36, ADC_UNIT_1, ADC_CHANNEL_0, NO_TOUCH_CHANNEL); diff --git a/ports/espressif/peripherals/esp32p4/pins.c b/ports/espressif/peripherals/esp32p4/pins.c index 24e509d40c6..a4e085e6971 100644 --- a/ports/espressif/peripherals/esp32p4/pins.c +++ b/ports/espressif/peripherals/esp32p4/pins.c @@ -8,20 +8,20 @@ const mcu_pin_obj_t pin_GPIO0 = PIN(0, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO1 = PIN(1, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); -const mcu_pin_obj_t pin_GPIO2 = PIN(2, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM0); -const mcu_pin_obj_t pin_GPIO3 = PIN(3, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM1); -const mcu_pin_obj_t pin_GPIO4 = PIN(4, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM2); -const mcu_pin_obj_t pin_GPIO5 = PIN(5, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM3); -const mcu_pin_obj_t pin_GPIO6 = PIN(6, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM4); -const mcu_pin_obj_t pin_GPIO7 = PIN(7, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM5); -const mcu_pin_obj_t pin_GPIO8 = PIN(8, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM6); -const mcu_pin_obj_t pin_GPIO9 = PIN(9, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM7); -const mcu_pin_obj_t pin_GPIO10 = PIN(10, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM8); -const mcu_pin_obj_t pin_GPIO11 = PIN(11, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM9); -const mcu_pin_obj_t pin_GPIO12 = PIN(12, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM10); -const mcu_pin_obj_t pin_GPIO13 = PIN(13, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM11); -const mcu_pin_obj_t pin_GPIO14 = PIN(14, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM12); -const mcu_pin_obj_t pin_GPIO15 = PIN(15, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM13); +const mcu_pin_obj_t pin_GPIO2 = PIN(2, NO_ADC, NO_ADC_CHANNEL, 0); +const mcu_pin_obj_t pin_GPIO3 = PIN(3, NO_ADC, NO_ADC_CHANNEL, 1); +const mcu_pin_obj_t pin_GPIO4 = PIN(4, NO_ADC, NO_ADC_CHANNEL, 2); +const mcu_pin_obj_t pin_GPIO5 = PIN(5, NO_ADC, NO_ADC_CHANNEL, 3); +const mcu_pin_obj_t pin_GPIO6 = PIN(6, NO_ADC, NO_ADC_CHANNEL, 4); +const mcu_pin_obj_t pin_GPIO7 = PIN(7, NO_ADC, NO_ADC_CHANNEL, 5); +const mcu_pin_obj_t pin_GPIO8 = PIN(8, NO_ADC, NO_ADC_CHANNEL, 6); +const mcu_pin_obj_t pin_GPIO9 = PIN(9, NO_ADC, NO_ADC_CHANNEL, 7); +const mcu_pin_obj_t pin_GPIO10 = PIN(10, NO_ADC, NO_ADC_CHANNEL, 8); +const mcu_pin_obj_t pin_GPIO11 = PIN(11, NO_ADC, NO_ADC_CHANNEL, 9); +const mcu_pin_obj_t pin_GPIO12 = PIN(12, NO_ADC, NO_ADC_CHANNEL, 10); +const mcu_pin_obj_t pin_GPIO13 = PIN(13, NO_ADC, NO_ADC_CHANNEL, 11); +const mcu_pin_obj_t pin_GPIO14 = PIN(14, NO_ADC, NO_ADC_CHANNEL, 12); +const mcu_pin_obj_t pin_GPIO15 = PIN(15, NO_ADC, NO_ADC_CHANNEL, 13); const mcu_pin_obj_t pin_GPIO16 = PIN(16, ADC_UNIT_1, ADC_CHANNEL_0, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO17 = PIN(17, ADC_UNIT_1, ADC_CHANNEL_1, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO18 = PIN(18, ADC_UNIT_1, ADC_CHANNEL_2, NO_TOUCH_CHANNEL); diff --git a/ports/espressif/peripherals/esp32s2/pins.c b/ports/espressif/peripherals/esp32s2/pins.c index b5e8d483175..cfaecd0ac6d 100644 --- a/ports/espressif/peripherals/esp32s2/pins.c +++ b/ports/espressif/peripherals/esp32s2/pins.c @@ -7,20 +7,20 @@ #include "peripherals/pins.h" const mcu_pin_obj_t pin_GPIO0 = PIN(0, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); -const mcu_pin_obj_t pin_GPIO1 = PIN(1, ADC_UNIT_1, ADC_CHANNEL_0, TOUCH_PAD_NUM1); -const mcu_pin_obj_t pin_GPIO2 = PIN(2, ADC_UNIT_1, ADC_CHANNEL_1, TOUCH_PAD_NUM2); -const mcu_pin_obj_t pin_GPIO3 = PIN(3, ADC_UNIT_1, ADC_CHANNEL_2, TOUCH_PAD_NUM3); -const mcu_pin_obj_t pin_GPIO4 = PIN(4, ADC_UNIT_1, ADC_CHANNEL_3, TOUCH_PAD_NUM4); -const mcu_pin_obj_t pin_GPIO5 = PIN(5, ADC_UNIT_1, ADC_CHANNEL_4, TOUCH_PAD_NUM5); -const mcu_pin_obj_t pin_GPIO6 = PIN(6, ADC_UNIT_1, ADC_CHANNEL_5, TOUCH_PAD_NUM6); -const mcu_pin_obj_t pin_GPIO7 = PIN(7, ADC_UNIT_1, ADC_CHANNEL_6, TOUCH_PAD_NUM7); -const mcu_pin_obj_t pin_GPIO8 = PIN(8, ADC_UNIT_1, ADC_CHANNEL_7, TOUCH_PAD_NUM8); -const mcu_pin_obj_t pin_GPIO9 = PIN(9, ADC_UNIT_1, ADC_CHANNEL_8, TOUCH_PAD_NUM9); -const mcu_pin_obj_t pin_GPIO10 = PIN(10, ADC_UNIT_1, ADC_CHANNEL_9, TOUCH_PAD_NUM10); -const mcu_pin_obj_t pin_GPIO11 = PIN(11, ADC_UNIT_2, ADC_CHANNEL_0, TOUCH_PAD_NUM11); -const mcu_pin_obj_t pin_GPIO12 = PIN(12, ADC_UNIT_2, ADC_CHANNEL_1, TOUCH_PAD_NUM12); -const mcu_pin_obj_t pin_GPIO13 = PIN(13, ADC_UNIT_2, ADC_CHANNEL_2, TOUCH_PAD_NUM13); -const mcu_pin_obj_t pin_GPIO14 = PIN(14, ADC_UNIT_2, ADC_CHANNEL_3, TOUCH_PAD_NUM14); +const mcu_pin_obj_t pin_GPIO1 = PIN(1, ADC_UNIT_1, ADC_CHANNEL_0, 1); +const mcu_pin_obj_t pin_GPIO2 = PIN(2, ADC_UNIT_1, ADC_CHANNEL_1, 2); +const mcu_pin_obj_t pin_GPIO3 = PIN(3, ADC_UNIT_1, ADC_CHANNEL_2, 3); +const mcu_pin_obj_t pin_GPIO4 = PIN(4, ADC_UNIT_1, ADC_CHANNEL_3, 4); +const mcu_pin_obj_t pin_GPIO5 = PIN(5, ADC_UNIT_1, ADC_CHANNEL_4, 5); +const mcu_pin_obj_t pin_GPIO6 = PIN(6, ADC_UNIT_1, ADC_CHANNEL_5, 6); +const mcu_pin_obj_t pin_GPIO7 = PIN(7, ADC_UNIT_1, ADC_CHANNEL_6, 7); +const mcu_pin_obj_t pin_GPIO8 = PIN(8, ADC_UNIT_1, ADC_CHANNEL_7, 8); +const mcu_pin_obj_t pin_GPIO9 = PIN(9, ADC_UNIT_1, ADC_CHANNEL_8, 9); +const mcu_pin_obj_t pin_GPIO10 = PIN(10, ADC_UNIT_1, ADC_CHANNEL_9, 10); +const mcu_pin_obj_t pin_GPIO11 = PIN(11, ADC_UNIT_2, ADC_CHANNEL_0, 11); +const mcu_pin_obj_t pin_GPIO12 = PIN(12, ADC_UNIT_2, ADC_CHANNEL_1, 12); +const mcu_pin_obj_t pin_GPIO13 = PIN(13, ADC_UNIT_2, ADC_CHANNEL_2, 13); +const mcu_pin_obj_t pin_GPIO14 = PIN(14, ADC_UNIT_2, ADC_CHANNEL_3, 14); const mcu_pin_obj_t pin_GPIO15 = PIN(15, ADC_UNIT_2, ADC_CHANNEL_4, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO16 = PIN(16, ADC_UNIT_2, ADC_CHANNEL_5, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO17 = PIN(17, ADC_UNIT_2, ADC_CHANNEL_6, NO_TOUCH_CHANNEL); diff --git a/ports/espressif/peripherals/esp32s3/pins.c b/ports/espressif/peripherals/esp32s3/pins.c index c51c4b93575..745cb4a7a67 100644 --- a/ports/espressif/peripherals/esp32s3/pins.c +++ b/ports/espressif/peripherals/esp32s3/pins.c @@ -9,20 +9,20 @@ // NOTE: These numbers do NOT always match the package and module pin number. // These are by solely by GPIO numbers. const mcu_pin_obj_t pin_GPIO0 = PIN(0, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); -const mcu_pin_obj_t pin_GPIO1 = PIN(1, ADC_UNIT_1, ADC_CHANNEL_0, TOUCH_PAD_NUM1); -const mcu_pin_obj_t pin_GPIO2 = PIN(2, ADC_UNIT_1, ADC_CHANNEL_1, TOUCH_PAD_NUM2); -const mcu_pin_obj_t pin_GPIO3 = PIN(3, ADC_UNIT_1, ADC_CHANNEL_2, TOUCH_PAD_NUM3); -const mcu_pin_obj_t pin_GPIO4 = PIN(4, ADC_UNIT_1, ADC_CHANNEL_3, TOUCH_PAD_NUM4); -const mcu_pin_obj_t pin_GPIO5 = PIN(5, ADC_UNIT_1, ADC_CHANNEL_4, TOUCH_PAD_NUM5); -const mcu_pin_obj_t pin_GPIO6 = PIN(6, ADC_UNIT_1, ADC_CHANNEL_5, TOUCH_PAD_NUM6); -const mcu_pin_obj_t pin_GPIO7 = PIN(7, ADC_UNIT_1, ADC_CHANNEL_6, TOUCH_PAD_NUM7); -const mcu_pin_obj_t pin_GPIO8 = PIN(8, ADC_UNIT_1, ADC_CHANNEL_7, TOUCH_PAD_NUM8); -const mcu_pin_obj_t pin_GPIO9 = PIN(9, ADC_UNIT_1, ADC_CHANNEL_8, TOUCH_PAD_NUM9); -const mcu_pin_obj_t pin_GPIO10 = PIN(10, ADC_UNIT_1, ADC_CHANNEL_9, TOUCH_PAD_NUM10); -const mcu_pin_obj_t pin_GPIO11 = PIN(11, ADC_UNIT_2, ADC_CHANNEL_0, TOUCH_PAD_NUM11); -const mcu_pin_obj_t pin_GPIO12 = PIN(12, ADC_UNIT_2, ADC_CHANNEL_1, TOUCH_PAD_NUM12); -const mcu_pin_obj_t pin_GPIO13 = PIN(13, ADC_UNIT_2, ADC_CHANNEL_2, TOUCH_PAD_NUM13); -const mcu_pin_obj_t pin_GPIO14 = PIN(14, ADC_UNIT_2, ADC_CHANNEL_3, TOUCH_PAD_NUM14); +const mcu_pin_obj_t pin_GPIO1 = PIN(1, ADC_UNIT_1, ADC_CHANNEL_0, 1); +const mcu_pin_obj_t pin_GPIO2 = PIN(2, ADC_UNIT_1, ADC_CHANNEL_1, 2); +const mcu_pin_obj_t pin_GPIO3 = PIN(3, ADC_UNIT_1, ADC_CHANNEL_2, 3); +const mcu_pin_obj_t pin_GPIO4 = PIN(4, ADC_UNIT_1, ADC_CHANNEL_3, 4); +const mcu_pin_obj_t pin_GPIO5 = PIN(5, ADC_UNIT_1, ADC_CHANNEL_4, 5); +const mcu_pin_obj_t pin_GPIO6 = PIN(6, ADC_UNIT_1, ADC_CHANNEL_5, 6); +const mcu_pin_obj_t pin_GPIO7 = PIN(7, ADC_UNIT_1, ADC_CHANNEL_6, 7); +const mcu_pin_obj_t pin_GPIO8 = PIN(8, ADC_UNIT_1, ADC_CHANNEL_7, 8); +const mcu_pin_obj_t pin_GPIO9 = PIN(9, ADC_UNIT_1, ADC_CHANNEL_8, 9); +const mcu_pin_obj_t pin_GPIO10 = PIN(10, ADC_UNIT_1, ADC_CHANNEL_9, 10); +const mcu_pin_obj_t pin_GPIO11 = PIN(11, ADC_UNIT_2, ADC_CHANNEL_0, 11); +const mcu_pin_obj_t pin_GPIO12 = PIN(12, ADC_UNIT_2, ADC_CHANNEL_1, 12); +const mcu_pin_obj_t pin_GPIO13 = PIN(13, ADC_UNIT_2, ADC_CHANNEL_2, 13); +const mcu_pin_obj_t pin_GPIO14 = PIN(14, ADC_UNIT_2, ADC_CHANNEL_3, 14); const mcu_pin_obj_t pin_GPIO15 = PIN(15, ADC_UNIT_2, ADC_CHANNEL_4, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO16 = PIN(16, ADC_UNIT_2, ADC_CHANNEL_5, NO_TOUCH_CHANNEL); const mcu_pin_obj_t pin_GPIO17 = PIN(17, ADC_UNIT_2, ADC_CHANNEL_6, NO_TOUCH_CHANNEL); diff --git a/ports/espressif/peripherals/pins.h b/ports/espressif/peripherals/pins.h index bbe42be1bca..431a136545a 100644 --- a/ports/espressif/peripherals/pins.h +++ b/ports/espressif/peripherals/pins.h @@ -12,16 +12,15 @@ #include "py/obj.h" -#include "components/hal/include/hal/gpio_types.h" -#include "components/hal/include/hal/adc_types.h" -#include "components/hal/include/hal/touch_sensor_legacy_types.h" +#include "hal/gpio_types.h" +#include "hal/adc_types.h" typedef struct { mp_obj_base_t base; gpio_num_t number; uint8_t adc_index : 2; uint8_t adc_channel : 6; - touch_pad_t touch_channel; + int8_t touch_channel; } mcu_pin_obj_t; extern const mp_obj_type_t mcu_pin_type; @@ -31,7 +30,7 @@ extern const mp_obj_type_t mcu_pin_type; #define NO_ADC SOC_ADC_PERIPH_NUM #define NO_ADC_CHANNEL SOC_ADC_MAX_CHANNEL_NUM -#define NO_TOUCH_CHANNEL TOUCH_PAD_MAX +#define NO_TOUCH_CHANNEL (-1) // This macro is used to simplify pin definition in peripherals//pins.c #define PIN(p_number, p_adc_index, p_adc_channel, p_touch_channel) \ diff --git a/ports/espressif/peripherals/touch.c b/ports/espressif/peripherals/touch.c index 71340d94371..f55c16d3969 100644 --- a/ports/espressif/peripherals/touch.c +++ b/ports/espressif/peripherals/touch.c @@ -4,54 +4,144 @@ // // SPDX-License-Identifier: MIT -#include "py/gc.h" #include "peripherals/touch.h" -static bool touch_inited = false; -static bool touch_never_reset = false; +static touch_sensor_handle_t touch_controller = NULL; +static touch_channel_handle_t touch_channels[TOUCH_TOTAL_CHAN_NUM] = {NULL}; +static bool touch_never_reset_flag = false; +static bool touch_enabled = false; +static bool touch_scanning = false; + +static int chan_index(int channel_id) { + return channel_id - TOUCH_MIN_CHAN_ID; +} + +touch_sensor_handle_t peripherals_touch_get_controller(void) { + return touch_controller; +} + +touch_channel_handle_t peripherals_touch_get_handle(int channel_id) { + return touch_channels[chan_index(channel_id)]; +} void peripherals_touch_reset(void) { - if (touch_inited && !touch_never_reset) { - touch_pad_deinit(); - touch_inited = false; + if (touch_controller != NULL && !touch_never_reset_flag) { + if (touch_scanning) { + touch_sensor_stop_continuous_scanning(touch_controller); + touch_scanning = false; + } + if (touch_enabled) { + touch_sensor_disable(touch_controller); + touch_enabled = false; + } + for (unsigned int i = 0; i < TOUCH_TOTAL_CHAN_NUM; i++) { + if (touch_channels[i] != NULL) { + touch_sensor_del_channel(touch_channels[i]); + touch_channels[i] = NULL; + } + } + touch_sensor_del_controller(touch_controller); + touch_controller = NULL; } } void peripherals_touch_never_reset(const bool enable) { - touch_never_reset = enable; + touch_never_reset_flag = enable; } -void peripherals_touch_init(const touch_pad_t touchpad) { - if (!touch_inited) { - touch_pad_init(); - touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); +void peripherals_touch_init(const int channel_id) { + int idx = chan_index(channel_id); + + // Already initialized this channel + if (touch_channels[idx] != NULL) { + return; } - // touch_pad_config() must be done before touch_pad_fsm_start() the first time. - // Otherwise the calibration is wrong and we get maximum raw values if there is - // a trace of any significant length on the pin. - #if defined(CONFIG_IDF_TARGET_ESP32) - touch_pad_config(touchpad, 0); + + // Stop scanning and disable before modifying channels + if (touch_scanning) { + touch_sensor_stop_continuous_scanning(touch_controller); + touch_scanning = false; + } + if (touch_enabled) { + touch_sensor_disable(touch_controller); + touch_enabled = false; + } + + if (touch_controller == NULL) { + #if SOC_TOUCH_SENSOR_VERSION == 1 + touch_sensor_sample_config_t sample_cfg = TOUCH_SENSOR_V1_DEFAULT_SAMPLE_CONFIG(5.0, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_1V7); + #elif SOC_TOUCH_SENSOR_VERSION == 2 + touch_sensor_sample_config_t sample_cfg = TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(500, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_2V2); + #elif SOC_TOUCH_SENSOR_VERSION == 3 + touch_sensor_sample_config_t sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(3, 29, 8, 3); + #else + #error bad SOC_TOUCH_SENSOR_VERSION + #endif + touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(1, &sample_cfg); + touch_sensor_new_controller(&sens_cfg, &touch_controller); + } + + #if SOC_TOUCH_SENSOR_VERSION == 1 + touch_channel_config_t chan_cfg = { + .abs_active_thresh = {1000}, + .charge_speed = TOUCH_CHARGE_SPEED_7, + .init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT, + .group = TOUCH_CHAN_TRIG_GROUP_BOTH, + }; + #elif SOC_TOUCH_SENSOR_VERSION == 2 + touch_channel_config_t chan_cfg = { + .active_thresh = {2000}, + .charge_speed = TOUCH_CHARGE_SPEED_7, + .init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT, + }; + #elif SOC_TOUCH_SENSOR_VERSION == 3 + // Values are similar to an ESP-IDF example: 1000, 2500, 5000. + touch_channel_config_t chan_cfg = { + .active_thresh = {1000, 2000, 5000}, + }; #else - touch_pad_config(touchpad); - touch_pad_fsm_start(); + #error bad SOC_TOUCH_SENSOR_VERSION #endif - touch_inited = true; + + touch_sensor_new_channel(touch_controller, channel_id, &chan_cfg, &touch_channels[idx]); + + // Enable and start continuous scanning + touch_sensor_enable(touch_controller); + touch_enabled = true; + touch_sensor_start_continuous_scanning(touch_controller); + touch_scanning = true; } -uint16_t peripherals_touch_read(touch_pad_t touchpad) { - #if defined(CONFIG_IDF_TARGET_ESP32) - uint16_t touch_value; - touch_pad_read(touchpad, &touch_value); +uint16_t peripherals_touch_read(int channel_id) { + int idx = chan_index(channel_id); + if (touch_channels[idx] == NULL) { + return 0; + } + + uint32_t touch_value = 0; - // ESP32 touch_pad_read() returns a lower value when a pin is touched instead of a higher value. - // Flip the values around to be consistent with TouchIn assumptions. - return UINT16_MAX - touch_value; - #else - uint32_t touch_value; - touch_pad_read_raw_data(touchpad, &touch_value); + #if SOC_TOUCH_SENSOR_VERSION == 1 + // ESP32 touch reads a lower value when touched. + // Flip the values to be consistent with TouchIn assumptions. + touch_channel_read_data(touch_channels[idx], TOUCH_CHAN_DATA_TYPE_RAW, &touch_value); + if (touch_value > UINT16_MAX) { + return 0; + } + return UINT16_MAX - (uint16_t)touch_value; + touch_channel_read_data(touch_channels[idx], TOUCH_CHAN_DATA_TYPE_RAW, &touch_value); + return UINT16_MAX - (uint16_t)touch_value; + #elif SOC_TOUCH_SENSOR_VERSION == 2 + if (touch_value > UINT16_MAX) { + return UINT16_MAX; + } + return (uint16_t)touch_value; + #elif SOC_TOUCH_SENSOR_VERSION == 3 + touch_channel_read_data(touch_channels[idx], TOUCH_CHAN_DATA_TYPE_SMOOTH, &touch_value); if (touch_value > UINT16_MAX) { return UINT16_MAX; } return (uint16_t)touch_value; + #else + #error bad SOC_TOUCH_SENSOR_VERSION #endif } diff --git a/ports/espressif/peripherals/touch.h b/ports/espressif/peripherals/touch.h index 6be4f8c2be1..00a96193c88 100644 --- a/ports/espressif/peripherals/touch.h +++ b/ports/espressif/peripherals/touch.h @@ -6,9 +6,11 @@ #pragma once -#include "driver/touch_pad.h" +#include "driver/touch_sens.h" -extern uint16_t peripherals_touch_read(touch_pad_t touchpad); +extern void peripherals_touch_init(const int channel_id); +extern uint16_t peripherals_touch_read(int channel_id); extern void peripherals_touch_reset(void); extern void peripherals_touch_never_reset(const bool enable); -extern void peripherals_touch_init(const touch_pad_t touchpad); +extern touch_sensor_handle_t peripherals_touch_get_controller(void); +extern touch_channel_handle_t peripherals_touch_get_handle(int channel_id); diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index 192a9171716..287fe54cc05 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -103,7 +103,7 @@ static esp_timer_handle_t _sleep_timer; TaskHandle_t circuitpython_task = NULL; -extern void esp_restart(void) NORETURN; +extern void esp_restart(void) MP_NORETURN; static void tick_on_cp_core(void *arg) { supervisor_tick(); @@ -251,12 +251,12 @@ safe_mode_t port_init(void) { #define pin_GPIOn(n) pin_GPIO##n #define pin_GPIOn_EXPAND(x) pin_GPIOn(x) - #ifdef CONFIG_CONSOLE_UART_TX_GPIO - common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_CONSOLE_UART_TX_GPIO)); + #ifdef CONFIG_ESP_CONSOLE_UART_TX_GPIO + common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_ESP_CONSOLE_UART_TX_GPIO)); #endif - #ifdef CONFIG_CONSOLE_UART_RX_GPIO - common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_CONSOLE_UART_RX_GPIO)); + #ifdef CONFIG_ESP_CONSOLE_UART_RX_GPIO + common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_ESP_CONSOLE_UART_RX_GPIO)); #endif #ifndef ENABLE_JTAG @@ -404,8 +404,8 @@ void reset_port(void) { watchdog_reset(); #endif - // Yield so the idle task can run and do any IDF cleanup needed. - port_yield(); + // Yield so the idle task, at priority 0, can run and do any IDF cleanup needed. + port_task_sleep_ms(4); } void reset_to_bootloader(void) { @@ -483,8 +483,13 @@ void port_wake_main_task_from_isr(void) { } } -void port_yield(void) { - vTaskDelay(4); +// Yield to other tasks at the same priority. +void port_task_yield(void) { + vTaskDelay(0); +} + +void port_task_sleep_ms(uint32_t msecs) { + vTaskDelay(pdMS_TO_TICKS(msecs)); } void sleep_timer_cb(void *arg) { @@ -510,7 +515,7 @@ void port_idle_until_interrupt(void) { #if CIRCUITPY_WIFI void port_boot_info(void) { uint8_t mac[6]; - esp_wifi_get_mac(ESP_IF_WIFI_STA, mac); + esp_wifi_get_mac(WIFI_IF_STA, mac); mp_printf(&mp_plat_print, "MAC"); for (int i = 0; i < 6; i++) { mp_printf(&mp_plat_print, ":%02X", mac[i]); diff --git a/ports/espressif/supervisor/usb.c b/ports/espressif/supervisor/usb.c index 62feea6981e..7c3b1561a44 100644 --- a/ports/espressif/supervisor/usb.c +++ b/ports/espressif/supervisor/usb.c @@ -21,8 +21,6 @@ #include "driver/gpio.h" #include "esp_private/periph_ctrl.h" -#include "rom/gpio.h" - #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -56,7 +54,8 @@ static void usb_device_task(void *param) { tud_task(); tud_cdc_write_flush(); } - vTaskDelay(1); + // Yield with zero delay to switch to any other tasks at same priority. + port_task_yield(); } } #endif // CIRCUITPY_USB_DEVICE @@ -112,7 +111,7 @@ void init_usb_hardware(void) { "usbd", USBD_STACK_SIZE, NULL, - 5, + 1, usb_device_stack, &usb_device_taskdef, xPortGetCoreID()); diff --git a/ports/espressif/tools/update_sdkconfig.py b/ports/espressif/tools/update_sdkconfig.py index 209b976b881..d46514873bd 100644 --- a/ports/espressif/tools/update_sdkconfig.py +++ b/ports/espressif/tools/update_sdkconfig.py @@ -5,7 +5,6 @@ import click import copy import kconfiglib -import kconfiglib.core import os OPT_SETTINGS = [ @@ -157,7 +156,7 @@ def sym_default(sym): default=False, help="Updates the sdkconfigs outside of the board directory.", ) -def update(debug, board, update_all): # noqa: C901: too complex +def update(debug, board, update_all): # noqa: C901 too complex """Updates related sdkconfig files based on the build directory version that was likely modified by menuconfig.""" @@ -203,7 +202,7 @@ def update(debug, board, update_all): # noqa: C901: too complex kconfig_path = pathlib.Path(f"build-{board}/esp-idf/kconfigs.in") kconfig_path = pathlib.Path("esp-idf/Kconfig") - kconfig = kconfiglib.Kconfig(kconfig_path) + kconfig = kconfiglib.Kconfig(str(kconfig_path)) input_config = pathlib.Path(f"build-{board}/esp-idf/sdkconfig") kconfig.load_config(input_config) @@ -244,7 +243,7 @@ def update(debug, board, update_all): # noqa: C901: too complex # Don't include the board file in cp defaults. The board may have custom # overrides. - cp_kconfig_defaults = kconfiglib.Kconfig(kconfig_path) + cp_kconfig_defaults = kconfiglib.Kconfig(str(kconfig_path)) for default_file in sdkconfigs: cp_kconfig_defaults.load_config(default_file, replace=False) @@ -332,7 +331,7 @@ def update(debug, board, update_all): # noqa: C901: too complex shared_keys = {} first = True for path in pathlib.Path(".").glob(loc): - kc = kconfiglib.Kconfig(path) + kc = kconfiglib.Kconfig(str(path)) all_file_syms = set() for sym in kc.unique_defined_syms: all_file_syms.add(sym) @@ -378,6 +377,8 @@ def update(debug, board, update_all): # noqa: C901: too complex all_references.update(rdep.referenced) psram_reference = False for referenced in all_references: + if not referenced.name: + continue if referenced.name.startswith("IDF_TARGET"): target_reference = True if referenced.name in target_symbols: diff --git a/ports/mimxrt10xx/reset.h b/ports/mimxrt10xx/reset.h index 04c951221e9..cae838556bc 100644 --- a/ports/mimxrt10xx/reset.h +++ b/ports/mimxrt10xx/reset.h @@ -16,6 +16,6 @@ #define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set #define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef -void reset_to_bootloader(void) NORETURN; -void reset(void) NORETURN; +void reset_to_bootloader(void) MP_NORETURN; +void reset(void) MP_NORETURN; bool bootloader_available(void); diff --git a/ports/nordic/boards/espruino_banglejs2/board.c b/ports/nordic/boards/espruino_banglejs2/board.c index 16af0269168..09adb43f8be 100644 --- a/ports/nordic/boards/espruino_banglejs2/board.c +++ b/ports/nordic/boards/espruino_banglejs2/board.c @@ -9,7 +9,6 @@ #include "mpconfigboard.h" #include "shared-bindings/busio/SPI.h" -#include "shared-bindings/fourwire/FourWire.h" #include "shared-bindings/framebufferio/FramebufferDisplay.h" #include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h" #include "shared-module/displayio/__init__.h" diff --git a/ports/nordic/boards/hiibot_bluefi/board.c b/ports/nordic/boards/hiibot_bluefi/board.c index 7a681140ddb..a05be7a0a63 100644 --- a/ports/nordic/boards/hiibot_bluefi/board.c +++ b/ports/nordic/boards/hiibot_bluefi/board.c @@ -36,7 +36,7 @@ void board_init(void) { spi, MP_OBJ_FROM_PTR(&pin_P0_27), // TFT_DC Command or data MP_OBJ_FROM_PTR(&pin_P0_05), // TFT_CS Chip select - MP_OBJ_NULL, // no TFT_RST Reset + mp_const_none, // no TFT_RST Reset // &pin_P1_14, // TFT_RST Reset 60000000, // Baudrate 0, // Polarity diff --git a/ports/nordic/common-hal/_bleio/Attribute.h b/ports/nordic/common-hal/_bleio/Attribute.h index 5fa6b4d6377..9a58e16bb86 100644 --- a/ports/nordic/common-hal/_bleio/Attribute.h +++ b/ports/nordic/common-hal/_bleio/Attribute.h @@ -6,6 +6,15 @@ #pragma once +#include + +#include "py/obj.h" + #include "shared-module/_bleio/Attribute.h" extern void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode); + +size_t bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len); +void bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo); +size_t bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len); +void bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response); diff --git a/ports/nordic/common-hal/_bleio/Characteristic.c b/ports/nordic/common-hal/_bleio/Characteristic.c index 51335be9e59..2e6042e48e7 100644 --- a/ports/nordic/common-hal/_bleio/Characteristic.c +++ b/ports/nordic/common-hal/_bleio/Characteristic.c @@ -138,10 +138,10 @@ size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *sel if (self->handle != BLE_GATT_HANDLE_INVALID) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); if (common_hal_bleio_service_get_is_remote(self->service)) { - return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); + return bleio_gattc_read(self->handle, conn_handle, buf, len); } else { // conn_handle is ignored for non-system attributes. - return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); + return bleio_gatts_read(self->handle, conn_handle, buf, len); } } @@ -159,7 +159,7 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, if (common_hal_bleio_service_get_is_remote(self->service)) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); // Last argument is true if write-no-reponse desired. - common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, + bleio_gattc_write(self->handle, conn_handle, bufinfo, (self->props & CHAR_PROP_WRITE_NO_RESPONSE)); } else { // Validate data length for local characteristics only. @@ -172,7 +172,7 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, // Always write the value locally even if no connections are active. // conn_handle is ignored for non-system attributes, so we use BLE_CONN_HANDLE_INVALID. - common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo); + bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo); // Check to see if we need to notify or indicate any active connections. for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { bleio_connection_internal_t *connection = &bleio_connections[i]; @@ -255,7 +255,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, } const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); - common_hal_bleio_check_connected(conn_handle); + bleio_check_connected(conn_handle); uint16_t cccd_value = (notify ? BLE_GATT_HVX_NOTIFICATION : 0) | diff --git a/ports/nordic/common-hal/_bleio/Connection.h b/ports/nordic/common-hal/_bleio/Connection.h index 110677dc78b..ea1edf17603 100644 --- a/ports/nordic/common-hal/_bleio/Connection.h +++ b/ports/nordic/common-hal/_bleio/Connection.h @@ -65,6 +65,7 @@ typedef struct { void bleio_connection_clear(bleio_connection_internal_t *self); bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in); +void bleio_check_connected(uint16_t conn_handle); uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection); bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle); diff --git a/ports/nordic/common-hal/_bleio/Descriptor.c b/ports/nordic/common-hal/_bleio/Descriptor.c index 959c8e5c9c0..0d27ca5dc2e 100644 --- a/ports/nordic/common-hal/_bleio/Descriptor.c +++ b/ports/nordic/common-hal/_bleio/Descriptor.c @@ -43,9 +43,9 @@ size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8 if (self->handle != BLE_GATT_HANDLE_INVALID) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { - return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); + return bleio_gattc_read(self->handle, conn_handle, buf, len); } else { - return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); + return bleio_gatts_read(self->handle, conn_handle, buf, len); } } @@ -58,7 +58,7 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { // false means WRITE_REQ, not write-no-response - common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false); + bleio_gattc_write(self->handle, conn_handle, bufinfo, false); } else { // Validate data length for local descriptors only. if (self->fixed_length && bufinfo->len != self->max_length) { @@ -68,7 +68,7 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff mp_raise_ValueError(MP_ERROR_TEXT("Value length > max_length")); } - common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + bleio_gatts_write(self->handle, conn_handle, bufinfo); } } diff --git a/ports/nordic/common-hal/_bleio/__init__.c b/ports/nordic/common-hal/_bleio/__init__.c index 454937dcd35..9dc58d7687c 100644 --- a/ports/nordic/common-hal/_bleio/__init__.c +++ b/ports/nordic/common-hal/_bleio/__init__.c @@ -112,14 +112,14 @@ void bleio_reset(void) { // It currently only has properties and no state. Inited by bleio_reset bleio_adapter_obj_t common_hal_bleio_adapter_obj; -void common_hal_bleio_check_connected(uint16_t conn_handle) { +void bleio_check_connected(uint16_t conn_handle) { if (conn_handle == BLE_CONN_HANDLE_INVALID) { mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); } } // GATTS read of a Characteristic or Descriptor. -size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len) { +size_t bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len) { // conn_handle is ignored unless this is a system attribute. // If we're not connected, that's OK, because we can still read and write the local value. @@ -133,7 +133,7 @@ size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_ return gatts_value.len; } -void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) { +void bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) { // conn_handle is ignored unless this is a system attribute. // If we're not connected, that's OK, because we can still read and write the local value. @@ -188,8 +188,8 @@ static bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { return true; } -size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len) { - common_hal_bleio_check_connected(conn_handle); +size_t bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len) { + bleio_check_connected(conn_handle); read_info_t read_info; read_info.buf = buf; @@ -213,15 +213,15 @@ size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_ RUN_BACKGROUND_TASKS; } // Test if we were disconnected while reading - common_hal_bleio_check_connected(read_info.conn_handle); + bleio_check_connected(read_info.conn_handle); ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info); check_gatt_status(read_info.status); return read_info.final_len; } -void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) { - common_hal_bleio_check_connected(conn_handle); +void bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) { + bleio_check_connected(conn_handle); ble_gattc_write_params_t write_params = { .write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ, diff --git a/ports/nordic/common-hal/alarm/__init__.c b/ports/nordic/common-hal/alarm/__init__.c index 9753b0321fd..026e117b9a6 100644 --- a/ports/nordic/common-hal/alarm/__init__.c +++ b/ports/nordic/common-hal/alarm/__init__.c @@ -240,7 +240,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala #define PRESCALER_VALUE_IN_DEEP_SLEEP (1024) -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep(); diff --git a/ports/nordic/mpconfigport.mk b/ports/nordic/mpconfigport.mk index 48536ec2acd..0316e904b38 100644 --- a/ports/nordic/mpconfigport.mk +++ b/ports/nordic/mpconfigport.mk @@ -9,6 +9,15 @@ CIRCUITPY_BUILD_EXTENSIONS ?= uf2 # Number of USB endpoint pairs. USB_NUM_ENDPOINT_PAIRS = 8 +# The nRF52 USBD implements isochronous transfers only on the fixed, dedicated +# endpoint number 8 (EP_ISO_NUM in TinyUSB's dcd_nrf5x.c); dcd_edpt_open() rejects +# an ISO endpoint on any other number, so a usb_audio mic/speaker placed on a +# sequentially-allocated endpoint would enumerate but never transfer data. Force +# the usb_audio isochronous endpoint onto endpoint 8. (Only read by usb_audio +# code, so it is harmless when CIRCUITPY_USB_AUDIO is off; defined unconditionally +# to stay independent of where that flag gets set in the include order.) +CFLAGS += -DUSB_AUDIO_ISO_EP_NUM=8 + # All nRF ports have longints. LONGINT_IMPL = MPZ @@ -83,6 +92,8 @@ ifeq ($(INTERNAL_FLASH_FILESYSTEM),1) OPTIMIZATION_FLAGS ?= -Os CIRCUITPY_LTO = 1 CIRCUITPY_LTO_PARTITION = balanced +else + CIRCUITPY_USB_AUDIO ?= 1 endif else diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index cef2806c874..d2c550c90fa 100644 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -407,8 +407,7 @@ CFLAGS += \ -msoft-float \ -mfloat-abi=soft -CFLAGS += \ - -DPICO_RP2040 +CFLAGS += -DPICO_RP2040=1 -DPICO_RP2350=0 SRC_SDK_CHIP_VARIANT := \ src/rp2_common/hardware_rtc/rtc.c \ @@ -451,7 +450,7 @@ DOUBLE_EABI = dcp INC += \ -isystem sdk/src/rp2_common/hardware_dcp/include/ -CFLAGS += -DPICO_RP2350=1 +CFLAGS += -DPICO_RP2040=0 -DPICO_RP2350=1 SRC_SDK_CHIP_VARIANT := \ src/rp2_common/hardware_powman/powman.c \ diff --git a/ports/raspberrypi/audio_dma.c b/ports/raspberrypi/audio_dma.c index ae3997a128f..36b86cbf844 100644 --- a/ports/raspberrypi/audio_dma.c +++ b/ports/raspberrypi/audio_dma.c @@ -9,18 +9,23 @@ #include "shared-bindings/audiocore/RawSample.h" #include "shared-bindings/audiocore/WaveFile.h" #include "shared-bindings/microcontroller/__init__.h" -#include "bindings/rp2pio/StateMachine.h" #include "supervisor/background_callback.h" #include "py/mpstate.h" #include "py/runtime.h" #include "hardware/irq.h" -#include "hardware/regs/intctrl.h" // For isr_ macro. #if CIRCUITPY_AUDIOCORE +// audio_dma and rp2pio cooperate on DMA_IRQ_0 using the SDK's shared interrupt +// handlers. We add our handler when we enable our first channel and remove it +// when our last channel is disabled. See the DMA IRQ allocation notes in +// common-hal/microcontroller/__init__.c. +static void audio_dma_enable_irq(uint channel); +static void audio_dma_disable_irq(uint channel); + void audio_dma_reset(void) { for (size_t channel = 0; channel < NUM_DMA_CHANNELS; channel++) { if (MP_STATE_PORT(playing_audio)[channel] == NULL) { @@ -233,7 +238,7 @@ audio_dma_result audio_dma_setup_playback( max_buffer_length /= dma->sample_spacing; } - #ifdef PICO_RP2350 + #if PICO_RP2350 dma->buffer[0] = (uint8_t *)port_realloc(dma->buffer[0], max_buffer_length, true); #else dma->buffer[0] = (uint8_t *)m_realloc(dma->buffer[0], @@ -249,7 +254,7 @@ audio_dma_result audio_dma_setup_playback( } if (!single_buffer) { - #ifdef PICO_RP2350 + #if PICO_RP2350 dma->buffer[1] = (uint8_t *)port_realloc(dma->buffer[1], max_buffer_length, true); #else dma->buffer[1] = (uint8_t *)m_realloc(dma->buffer[1], @@ -335,12 +340,10 @@ audio_dma_result audio_dma_setup_playback( 1, // transaction count false); // trigger } else { - // Clear any latent interrupts so that we don't immediately disable channels. - dma_hw->ints0 |= (1 << dma->channel[0]) | (1 << dma->channel[1]); // Enable our DMA channels on DMA_IRQ_0 to the CPU. This will wake us up when // we're WFI. - dma_hw->inte0 |= (1 << dma->channel[0]) | (1 << dma->channel[1]); - irq_set_mask_enabled(1 << DMA_IRQ_0, true); + audio_dma_enable_irq(dma->channel[0]); + audio_dma_enable_irq(dma->channel[1]); } dma->playing_in_progress = true; @@ -353,16 +356,11 @@ void audio_dma_stop(audio_dma_t *dma) { dma->paused = true; // Disable our interrupts. - uint32_t channel_mask = 0; if (dma->channel[0] < NUM_DMA_CHANNELS) { - channel_mask |= 1 << dma->channel[0]; + audio_dma_disable_irq(dma->channel[0]); } if (dma->channel[1] < NUM_DMA_CHANNELS) { - channel_mask |= 1 << dma->channel[1]; - } - dma_hw->inte0 &= ~channel_mask; - if (!dma_hw->inte0) { - irq_set_mask_enabled(1 << DMA_IRQ_0, false); + audio_dma_disable_irq(dma->channel[1]); } // Run any remaining audio tasks because we remove ourselves from @@ -460,7 +458,7 @@ void audio_dma_init(audio_dma_t *dma) { } void audio_dma_deinit(audio_dma_t *dma) { - #ifdef PICO_RP2350 + #if PICO_RP2350 port_free(dma->buffer[0]); #else #if MICROPY_MALLOC_USES_ALLOCATED_SIZE @@ -472,7 +470,7 @@ void audio_dma_deinit(audio_dma_t *dma) { dma->buffer[0] = NULL; dma->buffer_length[0] = 0; - #ifdef PICO_RP2350 + #if PICO_RP2350 port_free(dma->buffer[1]); #else #if MICROPY_MALLOC_USES_ALLOCATED_SIZE @@ -532,34 +530,59 @@ static void dma_callback_fun(void *arg) { } } -void __not_in_flash_func(isr_dma_0)(void) { +// Shared DMA_IRQ_0 handler for audio. It acknowledges and services only audio +// channels, leaving any other channels' interrupts for the other shared +// handlers (e.g. rp2pio) to acknowledge. +static void __not_in_flash_func(audio_dma_irq_handler)(void) { for (size_t i = 0; i < NUM_DMA_CHANNELS; i++) { uint32_t mask = 1 << i; if ((dma_hw->ints0 & mask) == 0) { continue; } + audio_dma_t *dma = MP_STATE_PORT(playing_audio)[i]; + if (dma == NULL) { + // Not one of our channels; leave it for another shared handler. + continue; + } // acknowledge interrupt early. Doing so late means that you could lose an // interrupt if the buffer is very small and the DMA operation // completed by the time callback_add() / dma_complete() returned. This // affected PIO continuous write more than audio. dma_hw->ints0 = mask; - if (MP_STATE_PORT(playing_audio)[i] != NULL) { - audio_dma_t *dma = MP_STATE_PORT(playing_audio)[i]; - // Record all channels whose DMA has completed; they need loading. - dma->channels_to_load_mask |= mask; - // Disable the channel so that we don't play it without filling it. - dma_hw->ch[i].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS; - // This is a noop if the callback is already queued. - background_callback_add(&dma->callback, dma_callback_fun, (void *)dma); - } - if (MP_STATE_PORT(background_pio_read)[i] != NULL) { - rp2pio_statemachine_obj_t *pio = MP_STATE_PORT(background_pio_read)[i]; - rp2pio_statemachine_dma_complete_read(pio, i); - } - if (MP_STATE_PORT(background_pio_write)[i] != NULL) { - rp2pio_statemachine_obj_t *pio = MP_STATE_PORT(background_pio_write)[i]; - rp2pio_statemachine_dma_complete_write(pio, i); - } + // Record all channels whose DMA has completed; they need loading. + dma->channels_to_load_mask |= mask; + // Disable the channel so that we don't play it without filling it. + dma_hw->ch[i].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS; + // This is a noop if the callback is already queued. + background_callback_add(&dma->callback, dma_callback_fun, (void *)dma); + } +} + +// Channels (bitmask) audio currently has enabled on DMA_IRQ_0. Used to decide +// when to add/remove our shared interrupt handler. +static uint32_t audio_dma_irq0_channel_mask = 0; + +static void audio_dma_enable_irq(uint channel) { + // Clear any latent interrupt so that we don't immediately disable the channel. + dma_hw->ints0 = 1u << channel; + if (audio_dma_irq0_channel_mask == 0) { + irq_add_shared_handler(DMA_IRQ_0, audio_dma_irq_handler, + PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); + } + audio_dma_irq0_channel_mask |= 1u << channel; + dma_irqn_set_channel_enabled(0, channel, true); + irq_set_enabled(DMA_IRQ_0, true); +} + +static void audio_dma_disable_irq(uint channel) { + dma_irqn_set_channel_enabled(0, channel, false); + audio_dma_irq0_channel_mask &= ~(1u << channel); + if (audio_dma_irq0_channel_mask == 0) { + irq_remove_handler(DMA_IRQ_0, audio_dma_irq_handler); + } + // Turn off the IRQ line entirely once no one (audio or rp2pio) needs it. + if (dma_hw->inte0 == 0) { + irq_set_enabled(DMA_IRQ_0, false); } } diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.h b/ports/raspberrypi/bindings/rp2pio/StateMachine.h index 16f884bcfca..3c775a96449 100644 --- a/ports/raspberrypi/bindings/rp2pio/StateMachine.h +++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.h @@ -62,6 +62,18 @@ bool common_hal_rp2pio_statemachine_background_read(rp2pio_statemachine_obj_t *s bool common_hal_rp2pio_statemachine_stop_background_write(rp2pio_statemachine_obj_t *self); bool common_hal_rp2pio_statemachine_stop_background_read(rp2pio_statemachine_obj_t *self); +// Set the once / loop / loop2 read buffers from raw pointers without going +// through an mp_obj_t wrapper. Pass NULL/0 for unused slots. The caller owns +// the memory; it must remain valid until stop_background_read. +void common_hal_rp2pio_statemachine_set_read_buffers_raw(rp2pio_statemachine_obj_t *self, + void *once, size_t once_len, + void *loop, size_t loop_len, + void *loop2, size_t loop2_len); + +// Returns the DMA channel index used by the current background read, or -1 +// if no background read is active. +int common_hal_rp2pio_statemachine_get_read_dma_channel(rp2pio_statemachine_obj_t *self); + mp_int_t common_hal_rp2pio_statemachine_get_pending_write(rp2pio_statemachine_obj_t *self); mp_int_t common_hal_rp2pio_statemachine_get_pending_read(rp2pio_statemachine_obj_t *self); diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2040_adalogger/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_feather_rp2040_adalogger/mpconfigboard.h index 34360169423..4c500366dfc 100644 --- a/ports/raspberrypi/boards/adafruit_feather_rp2040_adalogger/mpconfigboard.h +++ b/ports/raspberrypi/boards/adafruit_feather_rp2040_adalogger/mpconfigboard.h @@ -23,3 +23,11 @@ // #define CIRCUITPY_CONSOLE_UART_RX DEFAULT_UART_BUS_RX // #define CIRCUITPY_CONSOLE_UART_TX DEFAULT_UART_BUS_TX + +// Onboard microSD slot on SPI1. +#define DEFAULT_SD_SCK (&pin_GPIO18) +#define DEFAULT_SD_MOSI (&pin_GPIO19) +#define DEFAULT_SD_MISO (&pin_GPIO20) +#define DEFAULT_SD_CS (&pin_GPIO23) +#define DEFAULT_SD_CARD_DETECT (&pin_GPIO16) +#define DEFAULT_SD_CARD_INSERTED true diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.mk b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.mk index 88cce7c4a4c..6ab89398de7 100644 --- a/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.mk +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.mk @@ -8,3 +8,6 @@ CHIP_PACKAGE = A CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ" + +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/adafruit_floppsy_rp2040/board.c b/ports/raspberrypi/boards/adafruit_floppsy_rp2040/board.c index 882bc9a1a9e..903ed6a9044 100644 --- a/ports/raspberrypi/boards/adafruit_floppsy_rp2040/board.c +++ b/ports/raspberrypi/boards/adafruit_floppsy_rp2040/board.c @@ -36,7 +36,7 @@ void board_init(void) { spi, MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_TFT_DC), MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_TFT_CS), - MP_OBJ_NULL, // TFT_RESET Reset + mp_const_none, // TFT_RESET Reset 40000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/raspberrypi/boards/adafruit_metro_rp2040/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_metro_rp2040/mpconfigboard.h index 4242599354c..fdbd18c0e66 100644 --- a/ports/raspberrypi/boards/adafruit_metro_rp2040/mpconfigboard.h +++ b/ports/raspberrypi/boards/adafruit_metro_rp2040/mpconfigboard.h @@ -20,3 +20,11 @@ #define DEFAULT_UART_BUS_RX (&pin_GPIO1) #define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +// Onboard microSD slot. +#define DEFAULT_SD_SCK (&pin_GPIO18) +#define DEFAULT_SD_MOSI (&pin_GPIO19) +#define DEFAULT_SD_MISO (&pin_GPIO20) +#define DEFAULT_SD_CS (&pin_GPIO23) +#define DEFAULT_SD_CARD_DETECT (&pin_GPIO15) +#define DEFAULT_SD_CARD_INSERTED true diff --git a/ports/raspberrypi/boards/adafruit_tinychad_rp2350/board.c b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/board.c index fddd2572c1f..cfa2308f796 100644 --- a/ports/raspberrypi/boards/adafruit_tinychad_rp2350/board.c +++ b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/board.c @@ -10,7 +10,3 @@ #include "common-hal/picodvi/__init__.h" // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. - -void board_init(void) { - picodvi_autoconstruct(); -} diff --git a/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.mk index 8d2a9c2f527..36359c88fe4 100644 --- a/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.mk @@ -8,3 +8,6 @@ CHIP_PACKAGE = A CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ" + +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.mk b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.mk index d4f2cdb90d0..7663bcfb19d 100644 --- a/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.mk +++ b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.mk @@ -12,5 +12,9 @@ EXTERNAL_FLASH_DEVICES = "W25Q64JVxQ" CIRCUITPY__EVE = 1 CIRCUITPY_ALARM = 0 +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 + + FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.mk b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.mk index ac0bb6d6f27..75d49696a13 100644 --- a/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.mk +++ b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.mk @@ -21,6 +21,9 @@ CIRCUITPY_MDNS = 1 CIRCUITPY_SOCKETPOOL = 1 CIRCUITPY_WIFI = 1 +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 + CFLAGS += \ -DCYW43_PIN_WL_DYNAMIC=0 \ -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ diff --git a/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c b/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c index 53fae76ac1b..dbfc713930b 100644 --- a/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c +++ b/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c @@ -62,6 +62,8 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_VBATT), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, diff --git a/ports/raspberrypi/boards/cytron_motion_2350_pro/mpconfigboard.mk b/ports/raspberrypi/boards/cytron_motion_2350_pro/mpconfigboard.mk index 0ac939ce6a2..9a766f42da7 100644 --- a/ports/raspberrypi/boards/cytron_motion_2350_pro/mpconfigboard.mk +++ b/ports/raspberrypi/boards/cytron_motion_2350_pro/mpconfigboard.mk @@ -11,6 +11,10 @@ EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" CIRCUITPY__EVE = 1 +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 + + # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor diff --git a/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.mk b/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.mk index 1b5c6c5d548..42d747537af 100644 --- a/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.mk +++ b/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.mk @@ -9,5 +9,8 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "GD25Q32C,W25Q32JVxQ" +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 + # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SD diff --git a/ports/raspberrypi/boards/heiafr_picomo_v2/board.c b/ports/raspberrypi/boards/heiafr_picomo_v2/board.c index 3824c5959f5..15324b40ecd 100644 --- a/ports/raspberrypi/boards/heiafr_picomo_v2/board.c +++ b/ports/raspberrypi/boards/heiafr_picomo_v2/board.c @@ -53,7 +53,7 @@ void board_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO16), // TFT_DC Command or data MP_OBJ_FROM_PTR(&pin_GPIO17), // TFT_CS Chip select - MP_OBJ_NULL, // TFT_RST Reset + mp_const_none, // TFT_RST Reset 62500000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/raspberrypi/boards/heiafr_picomo_v3/board.c b/ports/raspberrypi/boards/heiafr_picomo_v3/board.c index 3824c5959f5..15324b40ecd 100644 --- a/ports/raspberrypi/boards/heiafr_picomo_v3/board.c +++ b/ports/raspberrypi/boards/heiafr_picomo_v3/board.c @@ -53,7 +53,7 @@ void board_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO16), // TFT_DC Command or data MP_OBJ_FROM_PTR(&pin_GPIO17), // TFT_CS Chip select - MP_OBJ_NULL, // TFT_RST Reset + mp_const_none, // TFT_RST Reset 62500000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/raspberrypi/boards/lilygo_t_display_rp2040/board.c b/ports/raspberrypi/boards/lilygo_t_display_rp2040/board.c index 67e63daed1d..2e9ccd45d56 100644 --- a/ports/raspberrypi/boards/lilygo_t_display_rp2040/board.c +++ b/ports/raspberrypi/boards/lilygo_t_display_rp2040/board.c @@ -65,7 +65,7 @@ static void display_init(void) { spi, MP_OBJ_FROM_PTR(&pin_GPIO1), // DC MP_OBJ_FROM_PTR(&pin_GPIO5), // CS - MP_OBJ_NULL, // RST (Reset pin tie to 0, do not set here) + mp_const_none, // RST (Reset pin tie to 0, do not set here) 40000000, // baudrate 1, // polarity 0 // phase diff --git a/ports/raspberrypi/boards/mtm_computer/board.c b/ports/raspberrypi/boards/mtm_computer/board.c index e6a868ab212..4fec0cd5b8b 100644 --- a/ports/raspberrypi/boards/mtm_computer/board.c +++ b/ports/raspberrypi/boards/mtm_computer/board.c @@ -5,5 +5,36 @@ // SPDX-License-Identifier: MIT #include "supervisor/board.h" +#include "shared-bindings/mcp4822/MCP4822.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "peripherals/pins.h" +#include "py/runtime.h" +// board.DAC() — factory function that constructs an mcp4822.MCP4822 with +// the MTM Workshop Computer's DAC pins (GP18=SCK, GP19=SDI, GP21=CS). + +static mp_obj_t board_dac_singleton = MP_OBJ_NULL; + +static mp_obj_t board_dac_factory(void) { + if (board_dac_singleton == MP_OBJ_NULL) { + mcp4822_mcp4822_obj_t *dac = mp_obj_malloc_with_finaliser( + mcp4822_mcp4822_obj_t, &mcp4822_mcp4822_type); + common_hal_mcp4822_mcp4822_construct( + dac, + &pin_GPIO18, // clock (SCK) + &pin_GPIO19, // mosi (SDI) + &pin_GPIO21, // cs + 1); // gain 1x + board_dac_singleton = MP_OBJ_FROM_PTR(dac); + } + return board_dac_singleton; +} +MP_DEFINE_CONST_FUN_OBJ_0(board_dac_obj, board_dac_factory); + +void board_deinit(void) { + if (board_dac_singleton != MP_OBJ_NULL) { + common_hal_mcp4822_mcp4822_deinit(MP_OBJ_TO_PTR(board_dac_singleton)); + board_dac_singleton = MP_OBJ_NULL; + } +} // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/mtm_computer/mpconfigboard.mk b/ports/raspberrypi/boards/mtm_computer/mpconfigboard.mk index 718c393d168..45c99711d72 100644 --- a/ports/raspberrypi/boards/mtm_computer/mpconfigboard.mk +++ b/ports/raspberrypi/boards/mtm_computer/mpconfigboard.mk @@ -11,3 +11,4 @@ EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" CIRCUITPY_AUDIOEFFECTS = 1 CIRCUITPY_IMAGECAPTURE = 0 CIRCUITPY_PICODVI = 0 +CIRCUITPY_MCP4822 = 1 diff --git a/ports/raspberrypi/boards/mtm_computer/pins.c b/ports/raspberrypi/boards/mtm_computer/pins.c index 69878182331..ffdf2687702 100644 --- a/ports/raspberrypi/boards/mtm_computer/pins.c +++ b/ports/raspberrypi/boards/mtm_computer/pins.c @@ -6,6 +6,8 @@ #include "shared-bindings/board/__init__.h" +extern const mp_obj_fun_builtin_fixed_t board_dac_obj; + static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS @@ -21,7 +23,6 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_PULSE_2_IN), MP_ROM_PTR(&pin_GPIO3) }, { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, - { MP_ROM_QSTR(MP_QSTR_NORM_PROBE), MP_ROM_PTR(&pin_GPIO4) }, { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, @@ -105,6 +106,9 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + // Factory function: dac = board.DAC() returns a configured mcp4822.MCP4822 + { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&board_dac_obj) }, + // { MP_ROM_QSTR(MP_QSTR_EEPROM_I2C), MP_ROM_PTR(&board_i2c_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/pajenicko_picopad/mpconfigboard.mk b/ports/raspberrypi/boards/pajenicko_picopad/mpconfigboard.mk index 764e41d4d91..1c3801edaac 100644 --- a/ports/raspberrypi/boards/pajenicko_picopad/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pajenicko_picopad/mpconfigboard.mk @@ -12,6 +12,7 @@ EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" CIRCUITPY_KEYPAD = 1 CIRCUITPY_STAGE = 1 CIRCUITPY_AUDIOIO = 1 +CIRCUITPY_AUDIOEFFECTS = 0 CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/board.c b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/board.c new file mode 100644 index 00000000000..1ce23b26459 --- /dev/null +++ b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/board.c @@ -0,0 +1 @@ +#include "shared-bindings/board/__init__.h" diff --git a/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/mpconfigboard.h b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/mpconfigboard.h new file mode 100644 index 00000000000..75deccbc8ed --- /dev/null +++ b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/mpconfigboard.h @@ -0,0 +1,12 @@ +#ifndef MICROPY_INCLUDED_RASPBERRYPI_BOARDS_PCBCUPID_Glyph_Mini_2040 +#define MICROPY_INCLUDED_RASPBERRYPI_BOARDS_PCBCUPID_Glyph_Mini_2040 + +#define MICROPY_HW_BOARD_NAME "PCBCupid Glyph Mini 2040" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define FLASH_SIZE (8 * 1024 * 1024) +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (7 * 1024 * 1024) + +#define MICROPY_HW_LED_STATUS (&pin_GPIO16) + +#endif diff --git a/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/mpconfigboard.mk b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/mpconfigboard.mk new file mode 100644 index 00000000000..415aecd6395 --- /dev/null +++ b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/mpconfigboard.mk @@ -0,0 +1,9 @@ +USB_VID = 0x2E8A +USB_PID = 0x1123 +USB_PRODUCT = "Glyph Mini 2040" +USB_MANUFACTURER = "PCBCupid" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q64JVxQ" diff --git a/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/pico-sdk-configboard.h b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/pico-sdk-configboard.h new file mode 100644 index 00000000000..110195b7794 --- /dev/null +++ b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/pins.c b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/pins.c new file mode 100644 index 00000000000..d2719b1ebea --- /dev/null +++ b/ports/raspberrypi/boards/pcbcupid_glyph_mini_2040/pins.c @@ -0,0 +1,37 @@ +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO16) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/badger2350-shared.h b/ports/raspberrypi/boards/pimoroni_badger2350/badger2350-shared.h new file mode 100644 index 00000000000..4cc67efd4df --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/badger2350-shared.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +extern digitalio_digitalinout_obj_t i2c_power_en_pin_obj; +extern const mp_obj_fun_builtin_fixed_t set_update_speed_obj; +extern const mp_obj_fun_builtin_fixed_t get_reset_state_obj; +extern const mp_obj_fun_builtin_fixed_t on_reset_pressed_obj; diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/board.c b/ports/raspberrypi/boards/pimoroni_badger2350/board.c new file mode 100644 index 00000000000..1da13b80339 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/board.c @@ -0,0 +1,225 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" + +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/board.h" +#include "supervisor/board.h" +#include "badger2350-shared.h" + +#include "hardware/gpio.h" +#include "hardware/structs/iobank0.h" + +digitalio_digitalinout_obj_t i2c_power_en_pin_obj; +static volatile uint32_t reset_button_state = 0; + +// Forward declaration to satisfy -Wmissing-prototypes +static void preinit_button_state(void) __attribute__((constructor(101))); + + +// pin definitions +// Button pin definitions for Badger2350 +#define SW_A_PIN 7 +#define SW_B_PIN 9 +#define SW_C_PIN 10 +#define SW_DOWN_PIN 6 +#define SW_UP_PIN 11 + +static const uint8_t _sw_pin_nrs[] = { + SW_A_PIN, SW_B_PIN, SW_C_PIN, SW_DOWN_PIN, SW_UP_PIN +}; + +// Mask of all front button pins +#define SW_MASK ((1 << SW_A_PIN) | (1 << SW_B_PIN) | (1 << SW_C_PIN) | \ + (1 << SW_DOWN_PIN) | (1 << SW_UP_PIN)) + +// This function runs BEFORE main() via constructor attribute! +// This is the key to fast button state detection. +// Priority 101 = runs very early + +static void preinit_button_state(void) { + // Configure button pins as inputs with pull-downs using direct register access + // This is faster than SDK functions and works before full init + + for (size_t i = 0; i < sizeof(_sw_pin_nrs); i++) { + uint8_t pin_nr = _sw_pin_nrs[i]; + // Set as input + sio_hw->gpio_oe_clr = 1u << pin_nr; + // enable pull-ups + pads_bank0_hw->io[pin_nr] = PADS_BANK0_GPIO0_IE_BITS | + PADS_BANK0_GPIO0_PUE_BITS; + // Set GPIO function + iobank0_hw->io[pin_nr].ctrl = 5; // SIO function + } + + // Small delay for pins to settle (just a few cycles) + for (volatile int i = 0; i < 100; i++) { + __asm volatile ("nop"); + } + + // Capture button states NOW - before anything else runs + reset_button_state = ~sio_hw->gpio_in & SW_MASK; +} + +static mp_obj_t _get_reset_state(void) { + return mp_obj_new_int(reset_button_state); +} +MP_DEFINE_CONST_FUN_OBJ_0(get_reset_state_obj, _get_reset_state); + +static mp_obj_t _on_reset_pressed(mp_obj_t pin_in) { + mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_in); + return mp_obj_new_bool( + (reset_button_state & (1 << pin->number)) != 0); +} +MP_DEFINE_CONST_FUN_OBJ_1(on_reset_pressed_obj, _on_reset_pressed); + +// The display uses an SSD1680 control chip. +uint8_t _start_sequence[] = { + 0x12, 0x80, 0x00, 0x14, // soft reset and wait 20ms + 0x11, 0x00, 0x01, 0x03, // Ram data entry mode + 0x3c, 0x00, 0x01, 0x03, // border color + 0x2c, 0x00, 0x01, 0x28, // Set vcom voltage + 0x03, 0x00, 0x01, 0x17, // Set gate voltage + 0x04, 0x00, 0x03, 0x41, 0xae, 0x32, // Set source voltage + 0x4e, 0x00, 0x01, 0x00, // ram x count + 0x4f, 0x00, 0x02, 0x00, 0x00, // ram y count + 0x01, 0x00, 0x03, 0x07, 0x01, 0x00, // set display size + 0x32, 0x00, 0x99, // Update waveforms + + // offset 44 + 0x40, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L0 + 0xA0, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L1 + 0xA8, 0x65, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L2 + 0xAA, 0x65, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L4 + + // offset 104 + 0x02, 0x00, 0x00, 0x05, 0x0A, 0x00, 0x03, // Group0 (with default speed==0) + // offset 111 + 0x19, 0x19, 0x00, 0x02, 0x00, 0x00, 0x03, // Group1 (with default speed==0) + // offset 118 + 0x05, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x03, // Group2 (with default speed==0) + + // offset 125 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group6 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group11 + 0x44, 0x42, 0x22, 0x22, 0x23, 0x32, 0x00, // Config + 0x00, 0x00, // FR, XON + + 0x22, 0x00, 0x01, 0xc7, // display update mode + +}; + +const uint8_t _stop_sequence[] = { + 0x10, 0x00, 0x01, 0x01 // DSM deep sleep mode 1 +}; + +const uint8_t _refresh_sequence[] = { + 0x20, 0x00, 0x00 // ADUS +}; + +// Change update speed. This changes the repeat-count in the LUTs +// Pimoroni uses: 0 == slow ... 3 == fast +// and calculates the LUT repeat count as 3-speed + +#define SPEED_OFFSET_1 110 +#define SPEED_OFFSET_2 117 +#define SPEED_OFFSET_3 124 + +static mp_obj_t _set_update_speed(mp_obj_t speed_in) { + mp_int_t speed = mp_obj_get_int(speed_in); + uint8_t count = (uint8_t)3 - (uint8_t)(speed & 3); + _start_sequence[SPEED_OFFSET_1] = count; + _start_sequence[SPEED_OFFSET_2] = count; + _start_sequence[SPEED_OFFSET_3] = count; + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_1(set_update_speed_obj, _set_update_speed); + +void board_init(void) { + // Drive the I2C_POWER_EN pin high + i2c_power_en_pin_obj.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct( + &i2c_power_en_pin_obj, &pin_GPIO27); + common_hal_digitalio_digitalinout_switch_to_output( + &i2c_power_en_pin_obj, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_never_reset(&i2c_power_en_pin_obj); + + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, NULL, false); + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO20), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO17), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO21), // EPD_RST Reset + 12000000, // Baudrate + 0, // Polarity + 0); // Phase + + // create and configure display + epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; + display->base.type = &epaperdisplay_epaperdisplay_type; + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = _start_sequence; + args.start_sequence_len = sizeof(_start_sequence); + args.stop_sequence = _stop_sequence; + args.stop_sequence_len = sizeof(_stop_sequence); + args.width = 264; + args.height = 176; + args.ram_width = 250; + args.ram_height = 296; + args.rotation = 270; + args.set_column_window_command = 0x44; + args.set_row_window_command = 0x45; + args.set_current_column_command = 0x4e; + args.set_current_row_command = 0x4f; + args.write_black_ram_command = 0x24; + args.write_color_ram_command = 0x26; + args.color_bits_inverted = true; + args.refresh_sequence = _refresh_sequence; + args.refresh_sequence_len = sizeof(_refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO16; + args.busy_state = true; + args.seconds_per_frame = 3.0; + args.grayscale = true; + args.two_byte_sequence_length = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); +} + +void board_deinit(void) { + epaperdisplay_epaperdisplay_obj_t *display = &displays[0].epaper_display; + if (display->base.type == &epaperdisplay_epaperdisplay_type) { + while (common_hal_epaperdisplay_epaperdisplay_get_busy(display)) { + RUN_BACKGROUND_TASKS; + } + } + common_hal_displayio_release_displays(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/link.ld b/ports/raspberrypi/boards/pimoroni_badger2350/link.ld new file mode 100644 index 00000000000..e814bead4c5 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/link.ld @@ -0,0 +1 @@ +firmware_size = 1532k; diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.h new file mode 100644 index 00000000000..6cffd190ad6 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Bernhard Bablok +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Pimoroni Badger 2350" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) + +#define MICROPY_HW_LED_STATUS (&pin_GPIO0) + +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO4) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO5) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO8) diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.mk new file mode 100644 index 00000000000..58f88af2518 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.mk @@ -0,0 +1,41 @@ +USB_VID = 0x2E8A +USB_PID = 0x1100 +USB_PRODUCT = "Pimoroni Badger 2350" +USB_MANUFACTURER = "Pimoroni" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 + +CIRCUITPY_CYW43 = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 +CIRCUITPY_MDNS = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_WIFI = 1 + +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 + +# PIO clock divider set to 2 (default), consider changing if TM2 gSPI +# becomes unreliable. +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_PIO_CLOCK_DIV_INT=2 \ + -DCYW43_PIO_CLOCK_DIV_FRAC=0 +# Must be accompanied by a linker script change +CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' + +FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-pcf85063a diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/pico-sdk-configboard.h b/ports/raspberrypi/boards/pimoroni_badger2350/pico-sdk-configboard.h new file mode 100644 index 00000000000..42e0612bf8b --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/pins.c b/ports/raspberrypi/boards/pimoroni_badger2350/pins.c new file mode 100644 index 00000000000..1a66961e68f --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/pins.c @@ -0,0 +1,135 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" +#include "badger2350-shared.h" + + +// LUT manipulation +static const mp_rom_map_elem_t lut_update_table[] = { + { MP_ROM_QSTR(MP_QSTR_SET_UPDATE_SPEED), (mp_obj_t)&set_update_speed_obj }, + { MP_ROM_QSTR(MP_QSTR_SPEED_SLOW), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_SPEED_FAST), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_SPEED_FASTER), MP_ROM_INT(2) }, + { MP_ROM_QSTR(MP_QSTR_SPEED_FASTEST), MP_ROM_INT(3) }, +}; +MP_DEFINE_CONST_DICT(lut_update_dict, lut_update_table); + +const mp_obj_module_t display_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&lut_update_dict, +}; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_display), MP_ROM_PTR(&display_module) }, + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_LED0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_LED3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SW_DOWN), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SW_A), MP_ROM_PTR(&pin_GPIO7) }, + + // GP8 is reserved for PSRAM chip select + + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_SW_B), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_SW_C), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_SW_UP), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_RTC_ALARM), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SW_RESET), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SW_INT), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_INKY_BUSY), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_INKY_CS), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_INKY_DC), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_INKY_RST), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_SW_HOME), MP_ROM_PTR(&pin_GPIO22) }, + + // GP23, GP24, GP25, and GP29 are reserved for RM2 gSPI + + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_VBAT_SENSE), MP_ROM_PTR(&pin_GPIO26) }, + + // GP27 is the used for I2C power-enable, driven high by board.c + { MP_ROM_QSTR(MP_QSTR_I2C_POWER_EN), MP_ROM_PTR(&i2c_power_en_pin_obj) }, + + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_SENSE_1V1), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // Pins accessed though the RM2 module (CYW43439) + // CYW0, CYW1 is unconnected + { MP_ROM_QSTR(MP_QSTR_CHARGE_STAT), MP_ROM_PTR(&pin_CYW2) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].epaper_display)}, + + // button-state on reset + // Use `board.RESET_STATE()` to query the state of all buttons at reset. + // To detect individual key-presses, `board.ON_RESET_PRESSED()` + // is simpler. + { MP_ROM_QSTR(MP_QSTR_RESET_STATE), (mp_obj_t)&get_reset_state_obj }, + + // Use `board.ON_RESET_PRESSED(board.SW_A)` to check if `SW_A` was pressed + // during reset. + { MP_ROM_QSTR(MP_QSTR_ON_RESET_PRESSED), (mp_obj_t)&on_reset_pressed_obj }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/board.c b/ports/raspberrypi/boards/pimoroni_explorer2350/board.c new file mode 100644 index 00000000000..d0c6d9a57ce --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/board.c @@ -0,0 +1,145 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/paralleldisplaybus/ParallelBus.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "hardware/gpio.h" + +// Display pins from Pimoroni Explorer parallel bus: {cs=27, dc=28, wr=30, rd=31, d0=32, bl=26} +#define LCD_BACKLIGHT_PIN 26 +#define LCD_CS_PIN 27 +#define LCD_DC_PIN 28 +#define LCD_WR_PIN 30 +#define LCD_RD_PIN 31 +#define LCD_D0_PIN 32 // Data pins are GPIO32-39 (8 consecutive pins) + +#define DELAY 0x80 + +// ST7789V display init sequence for 320x240 parallel bus +// Based on Pimoroni's pimoroni-pico ST7789 driver configuration +uint8_t display_init_sequence[] = { + // Software reset + 0x01, 0 | DELAY, 150, + // Sleep out + 0x11, 0 | DELAY, 255, + // Tearing effect line on (frame sync) + 0x35, 1, 0x00, + // COLMOD: 16-bit color (5-6-5 RGB) + 0x3A, 1, 0x55, + // Porch control (PORCTRL) + 0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33, + // Gate control (GCTRL) - VGH=13.26V, VGL=-10.43V + 0xB7, 1, 0x35, + // VCOM setting (VCOMS) + 0xBB, 1, 0x1F, + // LCM control (LCMCTRL) + 0xC0, 1, 0x2C, + // VDV and VRH command enable (VDVVRHEN) + 0xC2, 1, 0x01, + // VRH set (VRHS) + 0xC3, 1, 0x12, + // VDV set (VDVS) + 0xC4, 1, 0x20, + // Frame rate control (FRCTRL2) + 0xC6, 1, 0x0F, + // Power control 1 (PWCTRL1) + 0xD0, 2, 0xA4, 0xA1, + // RAM control (RAMCTRL) - for proper endianness + 0xB0, 2, 0x00, 0xC0, + // Positive gamma correction + 0xE0, 14, 0xD0, 0x08, 0x11, 0x08, 0x0C, 0x15, 0x39, 0x33, 0x50, 0x36, 0x13, 0x14, 0x29, 0x2D, + // Negative gamma correction + 0xE1, 14, 0xD0, 0x08, 0x10, 0x08, 0x06, 0x06, 0x39, 0x44, 0x51, 0x0B, 0x16, 0x14, 0x2F, 0x31, + // Inversion on + 0x21, 0, + // Normal display mode on + 0x13, 0 | DELAY, 10, + // MADCTL: MX=0, MY=1, MV=1, ML=1 (COL_ORDER | SWAP_XY | SCAN_ORDER) = 0x70 + // This configures the 320x240 display in landscape orientation + 0x36, 1, 0x70, + // Display on + 0x29, 0 | DELAY, 100, +}; + +static void display_init(void) { + paralleldisplaybus_parallelbus_obj_t *bus = &allocate_display_bus()->parallel_bus; + bus->base.type = ¶lleldisplaybus_parallelbus_type; + + common_hal_paralleldisplaybus_parallelbus_construct(bus, + &pin_GPIO32, // Data0 (D0) - data pins are sequential GPIO32-39 + &pin_GPIO28, // Command/Data (DC) + &pin_GPIO27, // Chip select (CS) + &pin_GPIO30, // Write (WR) + &pin_GPIO31, // Read (RD) + NULL, // Reset (directly connected to board reset) + 15000000); // Frequency - ST7789 min clock cycle ~66ns = ~15MHz + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct(display, + bus, + 320, // Width + 240, // Height + 0, // column start + 0, // row start + 0, // rotation + 16, // Color depth + false, // grayscale + false, // pixels_in_byte_share_row + 1, // bytes per cell + false, // reverse_pixels_in_byte + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO26, // Backlight pin (BL) + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void board_init(void) { + // Ensure backlight is on before display init + board_reset_pin_number(LCD_BACKLIGHT_PIN); + display_init(); +} + +// Prevent the backlight pin from being reset, keeping display visible across soft resets +bool board_reset_pin_number(uint8_t pin_number) { + if (pin_number == LCD_BACKLIGHT_PIN) { + // Keep backlight on - set high output without glitching + gpio_put(pin_number, 1); + gpio_set_dir(pin_number, GPIO_OUT); + gpio_set_function(pin_number, GPIO_FUNC_SIO); + return true; + } + return false; +} + +void reset_board(void) { + // Keep backlight on during reset + board_reset_pin_number(LCD_BACKLIGHT_PIN); +} + +void board_deinit(void) { + // Backlight will be handled by board_reset_pin_number +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.h new file mode 100644 index 00000000000..dd269aa6b84 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Pimoroni Explorer" +#define MICROPY_HW_MCU_NAME "rp2350b" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO25) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO21, .sda = &pin_GPIO20}} + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.mk new file mode 100644 index 00000000000..4409dbf57df --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.mk @@ -0,0 +1,13 @@ +USB_VID = 0x2E8A +USB_PID = 0x10C0 +USB_PRODUCT = "Explorer" +USB_MANUFACTURER = "Pimoroni" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = B +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +# GPIO12-19 needed for picodvi, but several are not available. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/pico-sdk-configboard.h b/ports/raspberrypi/boards/pimoroni_explorer2350/pico-sdk-configboard.h new file mode 100644 index 00000000000..66b57dfd13d --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/pico-sdk-configboard.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/pins.c b/ports/raspberrypi/boards/pimoroni_explorer2350/pins.c new file mode 100644 index 00000000000..8154a43de00 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/pins.c @@ -0,0 +1,124 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // User GPIOs (accent connector) + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + + // Servo pins + { MP_ROM_QSTR(MP_QSTR_SERVO1), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_SERVO2), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_SERVO3), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SERVO4), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + + // Audio + { MP_ROM_QSTR(MP_QSTR_AUDIO), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_AMP_EN), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + + // Buttons + { MP_ROM_QSTR(MP_QSTR_SW_C), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SW_B), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SW_A), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_SW_X), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SW_Y), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SW_Z), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + // User button + { MP_ROM_QSTR(MP_QSTR_SW_USER), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + // LED? + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + // Display parallel bus pins (ST7789V 320x240) + // Pins from Pimoroni: {cs=27, dc=28, wr=30, rd=31, d0=32, bl=26} + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_LCD_WR), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_GP30), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RD), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_GP31), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D0), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_GP32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D1), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_GP33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D2), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_GP34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D3), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_GP35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D4), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_GP36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D5), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_GP37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D6), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_GP38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D7), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_GP39), MP_ROM_PTR(&pin_GPIO39) }, + + // ADC pins (RP2350B extended GPIOs) + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_ADC0), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_GP40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_ADC1), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_GP41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_ADC2), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_GP42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_ADC3), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_GP43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_ADC4), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_GP44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_ADC5), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_GP45), MP_ROM_PTR(&pin_GPIO45) }, + + // I2C object + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // Display object + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.mk index 56fd7b641de..52dcd3fbe71 100644 --- a/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.mk @@ -10,3 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" CIRCUITPY__EVE = 1 + +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.mk index 8563f0d0034..cab35965a0f 100644 --- a/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.mk @@ -21,6 +21,9 @@ CIRCUITPY_WIFI = 1 CIRCUITPY_PICODVI = 0 CIRCUITPY_USB_HOST = 0 +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 + CFLAGS += \ -DCYW43_PIN_WL_DYNAMIC=0 \ -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ diff --git a/ports/raspberrypi/boards/pimoroni_tiny2350/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_tiny2350/mpconfigboard.mk index 9ffdf263003..b94022c1f6d 100644 --- a/ports/raspberrypi/boards/pimoroni_tiny2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_tiny2350/mpconfigboard.mk @@ -10,3 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" CIRCUITPY__EVE = 1 + +# GPIO12-19 needed for picodvi, but several are not available. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.mk index d5f866bd89e..f51d5271215 100644 --- a/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.mk @@ -8,3 +8,6 @@ CHIP_PACKAGE = A CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "P25Q16H" + +# GPIO12-19 needed for picodvi, but several are not available. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/sparkfun_pro_micro_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/sparkfun_pro_micro_rp2350/mpconfigboard.mk index e5d6e1b8ff8..53cdf72963f 100644 --- a/ports/raspberrypi/boards/sparkfun_pro_micro_rp2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/sparkfun_pro_micro_rp2350/mpconfigboard.mk @@ -8,3 +8,6 @@ CHIP_PACKAGE = A CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.mk index 6e81a229961..81d7f660473 100644 --- a/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.mk @@ -23,6 +23,8 @@ CIRCUITPY_MDNS = 1 CIRCUITPY_SOCKETPOOL = 1 CIRCUITPY_WIFI = 1 +# GPIO12-19 needed for picodvi, but GPIO14 is used for a NeoPixel. +CIRCUITPY_PICODVI = 0 CFLAGS += \ -DCYW43_PIN_WL_DYNAMIC=0 \ diff --git a/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.mk b/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.mk index eabc2c41e07..7214b36da28 100644 --- a/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.mk +++ b/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.mk @@ -19,6 +19,9 @@ CIRCUITPY_MDNS = 1 CIRCUITPY_SOCKETPOOL = 1 CIRCUITPY_WIFI = 1 +# GPIO12-19 needed for picodvi, but GPIO15 is used for a button. +CIRCUITPY_PICODVI = 0 + CFLAGS += \ -DCYW43_PIN_WL_DYNAMIC=0 \ -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/board.c b/ports/raspberrypi/boards/tinycircuits_thumby/board.c new file mode 100644 index 00000000000..3a306b35f0d --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/board.c @@ -0,0 +1,81 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + + +uint8_t display_init_sequence[] = { + 0xAE, 0, // DISPLAY_OFF + 0x20, 1, 0x00, // Set memory addressing to horizontal mode. + 0x81, 1, 0xcf, // set contrast control + 0xA1, 0, // Column 127 is segment 0 + 0xA6, 0, // Normal display + 0xc8, 0, // Normal display + 0xA8, 1, 0x3f, // Mux ratio is 1/64 + 0xd5, 1, 0x80, // Set divide ratio + 0xd9, 1, 0xf1, // Set pre-charge period + 0xda, 1, 0x12, // Set com configuration + 0xdb, 1, 0x40, // Set vcom configuration + 0x8d, 1, 0x14, // Enable charge pump + 0xAF, 0, // DISPLAY_ON +}; + +void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_OLED_DC), // Command or data + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_OLED_CS), // Chip select + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_OLED_RESET), // Reset + 10000000, // Baudrate + 0, // Polarity + 0); // Phase + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 72, // Width (after rotation) + 40, // Height (after rotation) + 28, // column start + 28, // row start + 0, // rotation + 1, // Color depth + true, // grayscale + false, // pixels in byte share row. only used for depth < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + 0x21, // Set column command + 0x22, // Set row command + 44, // Write memory command + display_init_sequence, + sizeof(display_init_sequence), + NULL, // backlight pin + 0x81, + 1.0f, // brightness + true, // single_byte_bounds + true, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 0); // backlight pwm frequency +} + +void reset_board(void) { +} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.h b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.h new file mode 100644 index 00000000000..cec0fc10f55 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "TinyCircuits Thumby" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) + +#define CIRCUITPY_BOARD_OLED_DC (&pin_GPIO17) +#define CIRCUITPY_BOARD_OLED_CS (&pin_GPIO16) +#define CIRCUITPY_BOARD_OLED_RESET (&pin_GPIO20) + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = DEFAULT_SPI_BUS_SCK, .mosi = DEFAULT_SPI_BUS_MOSI, .miso = NULL}} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.mk b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.mk new file mode 100644 index 00000000000..d8140e6cb0a --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x1209 +USB_PID = 0x3500 +USB_PRODUCT = "Thumby" +USB_MANUFACTURER = "TinyCircuits" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" + +CIRCUITPY_STAGE = 1 +CIRCUITPY_AUDIOIO = 1 +CIRCUITPY_AUDIOPWMIO = 1 +CIRCUITPY_KEYPAD = 1 + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_framebuf +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SSD1306 +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/pico-sdk-configboard.h b/ports/raspberrypi/boards/tinycircuits_thumby/pico-sdk-configboard.h new file mode 100644 index 00000000000..ce5a7645b4e --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/pico-sdk-configboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/pins.c b/ports/raspberrypi/boards/tinycircuits_thumby/pins.c new file mode 100644 index 00000000000..0a087bb8db8 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/pins.c @@ -0,0 +1,48 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Link Cable (ASR00074) + { MP_ROM_QSTR(MP_QSTR_EXT_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_EXT), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_EXT_PU), MP_ROM_PTR(&pin_GPIO1) }, + + // 0.42 inch OLED AST1042 + { MP_ROM_QSTR(MP_QSTR_OLED_CS), MP_ROM_PTR(CIRCUITPY_BOARD_OLED_CS) }, + { MP_ROM_QSTR(MP_QSTR_OLED_DC), MP_ROM_PTR(CIRCUITPY_BOARD_OLED_DC) }, + { MP_ROM_QSTR(MP_QSTR_OLED_RESET), MP_ROM_PTR(CIRCUITPY_BOARD_OLED_RESET) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(DEFAULT_SPI_BUS_SCK) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(DEFAULT_SPI_BUS_MOSI) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, + + // Buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON_LEFT), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_UP), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_DOWN), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_1), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_2), MP_ROM_PTR(&pin_GPIO27) }, + + // Mono PWM Speaker + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO28) }, + + // Hardware revision ID pins + { MP_OBJ_NEW_QSTR(MP_QSTR_ID3), MP_ROM_PTR(&pin_GPIO12) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ID2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ID1), MP_ROM_PTR(&pin_GPIO14) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ID0), MP_ROM_PTR(&pin_GPIO15) }, + + // Power pins + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO26) } +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/board.c b/ports/raspberrypi/boards/tinycircuits_thumby_color/board.c new file mode 100644 index 00000000000..17c512cb2a6 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/board.c @@ -0,0 +1,108 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + + +#define DELAY 0x80 + +// display init sequence according to TinyCircuits-Tiny-Game-Engine +uint8_t display_init_sequence[] = { + 0xFE, 0, // inter register enable 1 + 0xEF, 0, // inter register enable 2 + 0xB0, 1, 0xC0, + 0xB1, 1, 0x80, + 0xB2, 1, 0x2F, + 0xB3, 1, 0x03, + 0xB7, 1, 0x01, + 0xB6, 1, 0x19, + 0xAC, 1, 0xC8, // Complement Principle of RGB 5, 6, 5 + 0xAB, 1, 0x0f, // ? + 0x3A, 1, 0x05, // COLMOD: Pixel Format Set + 0xB4, 1, 0x04, // ? + 0xA8, 1, 0x07, // Frame Rate Set + 0xB8, 1, 0x08, // ? + 0xE7, 1, 0x5A, // VREG_CTL + 0xE8, 1, 0x23, // VGH_SET + 0xE9, 1, 0x47, // VGL_SET + 0xEA, 1, 0x99, // VGH_VGL_CLK + 0xC6, 1, 0x30, // ? + 0xC7, 1, 0x1F, // ? + 0xF0, 14, 0x05, 0x1D, 0x51, 0x2F, 0x85, 0x2A, 0x11, 0x62, 0x00, 0x07, 0x07, 0x0F, 0x08, 0x1F, // SET_GAMMA1 + 0xF1, 14, 0x2E, 0x41, 0x62, 0x56, 0xA5, 0x3A, 0x3f, 0x60, 0x0F, 0x07, 0x0A, 0x18, 0x18, 0x1D, // SET_GAMMA2 + 0x11, 0 | DELAY, 120, + 0x29, 0 | DELAY, 10, // display on +}; + +void board_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct( + spi, + DEFAULT_SPI_BUS_SCK, // CLK + DEFAULT_SPI_BUS_MOSI, // MOSI + NULL, // MISO not connected + false // Not half-duplex + ); + + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_LCD_DC), // DC + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_LCD_CS), // CS + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_LCD_RESET), // RST + 80000000, // baudrate + 0, // polarity + 0 // phase + ); + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 128, // width (after rotation) + 128, // height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + CIRCUITPY_BOARD_LCD_BACKLIGHT, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void reset_board(void) { +} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.h b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.h new file mode 100644 index 00000000000..fc76138bb8a --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "TinyCircuits Thumby Color" +#define MICROPY_HW_MCU_NAME "rp2350" + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO9) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = DEFAULT_I2C_BUS_SCL, .sda = DEFAULT_I2C_BUS_SDA}} + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) + +#define CIRCUITPY_BOARD_LCD_DC (&pin_GPIO16) +#define CIRCUITPY_BOARD_LCD_CS (&pin_GPIO17) +#define CIRCUITPY_BOARD_LCD_RESET (&pin_GPIO4) +#define CIRCUITPY_BOARD_LCD_BACKLIGHT (&pin_GPIO7) + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = DEFAULT_SPI_BUS_SCK, .mosi = DEFAULT_SPI_BUS_MOSI, .miso = NULL}} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.mk b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.mk new file mode 100644 index 00000000000..6159a39ba55 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x1209 +USB_PID = 0x3501 +USB_PRODUCT = "Thumby Color" +USB_MANUFACTURER = "TinyCircuits" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY_STAGE = 1 +CIRCUITPY_AUDIOIO = 1 +CIRCUITPY_AUDIOPWMIO = 1 +CIRCUITPY_KEYPAD = 1 + +# GPIO12-19 needed for picodvi, but many are not available. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/pico-sdk-configboard.h b/ports/raspberrypi/boards/tinycircuits_thumby_color/pico-sdk-configboard.h new file mode 100644 index 00000000000..110195b7794 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/pins.c b/ports/raspberrypi/boards/tinycircuits_thumby_color/pins.c new file mode 100644 index 00000000000..d0e63512d7a --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/pins.c @@ -0,0 +1,58 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON_UP), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_LEFT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_DOWN), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_BUMPER_LEFT), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_BUMPER_RIGHT), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_MENU), MP_ROM_PTR(&pin_GPIO26) }, + + // LED + { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO12) }, + + // Rumble + { MP_ROM_QSTR(MP_QSTR_RUMBLE), MP_ROM_PTR(&pin_GPIO5) }, + + // Mono PWM Speaker + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_GPIO20) }, + + // 0.85 inch TFT GC9107 + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_CS) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_DC) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_RESET) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BACKLIGHT), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_BACKLIGHT) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(DEFAULT_SPI_BUS_SCK) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(DEFAULT_SPI_BUS_MOSI) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // RTC I2C + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(DEFAULT_I2C_BUS_SDA) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(DEFAULT_I2C_BUS_SCL) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // Power pins + { MP_ROM_QSTR(MP_QSTR_CHARGE_STAT), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.mk index 38b69c182c7..e1d89c1fbca 100644 --- a/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.mk +++ b/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.mk @@ -10,3 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" CIRCUITPY__EVE = 1 + +# GPIO12-19 needed for picodvi, but many of the pins are used for other purposes. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.mk index 8f703c5a932..f04b91f8b0d 100644 --- a/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.mk +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.mk @@ -11,6 +11,9 @@ EXTERNAL_FLASH_DEVICES = "P25Q32SH" CIRCUITPY__EVE = 1 +# GPIO12-19 needed for picodvi, but GPIO12 is used for display reset. +CIRCUITPY_PICODVI = 0 + # TODO: Add custom QMI8658 driver # FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython_qmi8658 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.mk index 75398b3269b..bde7153c029 100644 --- a/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.mk +++ b/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.mk @@ -10,3 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" CIRCUITPY__EVE = 1 + +# GPIO12-19 needed for picodvi, but GPIO16 is not broken out and is used for NeoPixel. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.mk index 464c7aff283..79fafbacf5c 100644 --- a/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.mk +++ b/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.mk @@ -10,3 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "P25Q32SH" CIRCUITPY__EVE = 1 + +# GPIO12-19 needed for picodvi, but GPIO16-19 are not available. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.mk index 11e927c7485..0ec6c4ec008 100644 --- a/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.mk +++ b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.mk @@ -11,6 +11,9 @@ EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" CIRCUITPY__EVE = 1 +# GPIO12-19 needed for picodvi, but GPIO12 is used for display reset. +CIRCUITPY_PICODVI = 0 + # TODO: Add custom QMI8658 driver # FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython_qmi8658 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.mk index 444850776a6..7f0a3c71cbb 100644 --- a/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.mk +++ b/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.mk @@ -10,3 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "P25Q32SH" CIRCUITPY__EVE = 1 + +# GPIO12-19 needed for picodvi, but GPIO16 is not broken out and is used for NeoPixel. +CIRCUITPY_PICODVI = 0 diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/board.c b/ports/raspberrypi/boards/weact_studio_rp2350b_core/board.c new file mode 100644 index 00000000000..e6a868ab212 --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.h b/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.h new file mode 100644 index 00000000000..95a81334c73 --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "WeAct Studio RP2350B Core" +#define MICROPY_HW_MCU_NAME "rp2350b" + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.mk b/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.mk new file mode 100644 index 00000000000..d86f28280f3 --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x1209 +USB_PID = 0xDEC1 +USB_PRODUCT = "RP2350B Core" +USB_MANUFACTURER = "WeAct Studio" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = B +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/pico-sdk-configboard.h b/ports/raspberrypi/boards/weact_studio_rp2350b_core/pico-sdk-configboard.h new file mode 100644 index 00000000000..66b57dfd13d --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/pico-sdk-configboard.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/pins.c b/ports/raspberrypi/boards/weact_studio_rp2350b_core/pins.c new file mode 100644 index 00000000000..d6a82becfdd --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/pins.c @@ -0,0 +1,91 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP30), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_GP31), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_GP32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_GP33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_GP34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_GP35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_GP36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_GP37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_GP38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_GP39), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_GP40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO40) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP40_A0), MP_ROM_PTR(&pin_GPIO40) }, + + { MP_ROM_QSTR(MP_QSTR_GP41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO41) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP41_A1), MP_ROM_PTR(&pin_GPIO41) }, + + { MP_ROM_QSTR(MP_QSTR_GP42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO42) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP42_A2), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_GP43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO43) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP43_A3), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_GP44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO44) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP44_A4), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_GP45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO45) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP45_A5), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_ROM_QSTR(MP_QSTR_GP46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO46) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP46_A6), MP_ROM_PTR(&pin_GPIO46) }, + + { MP_ROM_QSTR(MP_QSTR_GP47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO47) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP47_A7), MP_ROM_PTR(&pin_GPIO47) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.mk index 3e3542120e3..d47571e7950 100644 --- a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.mk +++ b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.mk @@ -12,5 +12,8 @@ EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" CIRCUITPY__EVE = 1 CIRCUITPY_SSL = 1 +# GPIO12-19 needed for picodvi, but GPIO16 is used for Wiznet. +CIRCUITPY_PICODVI = 0 + # The default is -O3. Change to -O2 because the build was overflowing. OPTIMIZATION_FLAGS = -O2 diff --git a/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.mk index c10c7aa7eb8..68b621fdf97 100644 --- a/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.mk +++ b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.mk @@ -12,5 +12,8 @@ EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" CIRCUITPY__EVE = 1 CIRCUITPY_SSL = 1 +# GPIO12-19 needed for picodvi, but GPIO16 is used for Wiznet. +CIRCUITPY_PICODVI = 0 + # The default is -O3. Change to -O2 because the build was overflowing. OPTIMIZATION_FLAGS = -O2 diff --git a/ports/raspberrypi/common-hal/alarm/__init__.c b/ports/raspberrypi/common-hal/alarm/__init__.c index c47ddc31505..a72b3a368d4 100644 --- a/ports/raspberrypi/common-hal/alarm/__init__.c +++ b/ports/raspberrypi/common-hal/alarm/__init__.c @@ -197,7 +197,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { bool timealarm_set = alarm_time_timealarm_is_set(); #if CIRCUITPY_CYW43 diff --git a/ports/raspberrypi/common-hal/audioi2sin/I2SIn.c b/ports/raspberrypi/common-hal/audioi2sin/I2SIn.c new file mode 100644 index 00000000000..8bdc4cfeb3b --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/I2SIn.c @@ -0,0 +1,742 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include +#include + +#include "py/mperrno.h" +#include "py/mphal.h" +#include "py/runtime.h" +#include "shared/runtime/interrupt_char.h" +#include "common-hal/audioi2sin/I2SIn.h" +#include "shared-bindings/audioi2sin/I2SIn.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/audioi2sin/__init__.h" +#include "bindings/rp2pio/StateMachine.h" +#include "supervisor/port.h" + +#include "hardware/dma.h" + +#if CIRCUITPY_AUDIOI2SIN + +// 16-bit programs sample a stereo frame of 16+16 = 32 bits and rely on +// auto-push at 32 to deliver one packed (right<<16 | left) word per frame. +// 32-bit programs sample 32 bits per channel and produce two FIFO words per +// frame (right first, then left). Each bit takes 6 PIO clocks (a [2]-delay +// pair). 24-bit recordings reuse the 32-bit programs because most 24-bit +// MEMS mics (SPH0645LM4H, INMP441, ICS-43434) transmit their 24 valid bits +// left-justified inside a 32-bit slot. +// +// `in pins 1` runs on a cycle where side-set drives BCLK high. The slave +// updates the data line on the BCLK falling edge, so by the rising edge it +// has settled and is safe to sample. Sampling at BCLK low (the previous, +// incorrect arrangement) catches the data mid-transition and the result is +// effectively noise. +#define PIO_CLOCKS_PER_BIT (6) + +// Master-mode RX, regular pin order (BCLK = WS - 1), Philips alignment. +static const uint16_t i2sin_program[] = { + 0xb842, // 0: nop side 3 + // .wrap_target + 0xf94e, // 1: set y, 14 side 3 [1] + 0xb242, // 2: nop side 2 [2] + 0x5801, // 3: in pins, 1 side 3 + 0x1982, // 4: jmp y--, 2 side 3 [1] + 0xa242, // 5: nop side 0 [2] + 0x4801, // 6: in pins, 1 side 1 + 0xe94e, // 7: set y, 14 side 1 [1] + 0xa242, // 8: nop side 0 [2] + 0x4801, // 9: in pins, 1 side 1 + 0x0988, // 10: jmp y--, 8 side 1 [1] + 0xb242, // 11: nop side 2 [2] + 0x5801, // 12: in pins, 1 side 3 + // .wrap +}; + +// Master-mode RX, regular pin order, left-justified. +static const uint16_t i2sin_program_left_justified[] = { + 0xa842, // 0: nop side 1 + // .wrap_target + 0xe94e, // 1: set y, 14 side 1 [1] + 0xb242, // 2: nop side 2 [2] + 0x5801, // 3: in pins, 1 side 3 + 0x1982, // 4: jmp y--, 2 side 3 [1] + 0xb242, // 5: nop side 2 [2] + 0x5801, // 6: in pins, 1 side 3 + 0xf94e, // 7: set y, 14 side 3 [1] + 0xa242, // 8: nop side 0 [2] + 0x4801, // 9: in pins, 1 side 1 + 0x0988, // 10: jmp y--, 8 side 1 [1] + 0xa242, // 11: nop side 0 [2] + 0x4801, // 12: in pins, 1 side 1 + // .wrap +}; + +// Master-mode RX, swapped pin order (BCLK = WS + 1), Philips alignment. +static const uint16_t i2sin_program_swap[] = { + 0xb842, // 0: nop side 3 + // .wrap_target + 0xf94e, // 1: set y, 14 side 3 [1] + 0xaa42, // 2: nop side 1 [2] + 0x5801, // 3: in pins, 1 side 3 + 0x1982, // 4: jmp y--, 2 side 3 [1] + 0xa242, // 5: nop side 0 [2] + 0x5001, // 6: in pins, 1 side 2 + 0xf14e, // 7: set y, 14 side 2 [1] + 0xa242, // 8: nop side 0 [2] + 0x5001, // 9: in pins, 1 side 2 + 0x1188, // 10: jmp y--, 8 side 2 [1] + 0xaa42, // 11: nop side 1 [2] + 0x5801, // 12: in pins, 1 side 3 + // .wrap +}; + +// Master-mode RX, swapped pin order, left-justified. +static const uint16_t i2sin_program_left_justified_swap[] = { + 0xb042, // 0: nop side 2 + // .wrap_target + 0xf14e, // 1: set y, 14 side 2 [1] + 0xaa42, // 2: nop side 1 [2] + 0x5801, // 3: in pins, 1 side 3 + 0x1982, // 4: jmp y--, 2 side 3 [1] + 0xaa42, // 5: nop side 1 [2] + 0x5801, // 6: in pins, 1 side 3 + 0xf94e, // 7: set y, 14 side 3 [1] + 0xa242, // 8: nop side 0 [2] + 0x5001, // 9: in pins, 1 side 2 + 0x1188, // 10: jmp y--, 8 side 2 [1] + 0xa242, // 11: nop side 0 [2] + 0x5001, // 12: in pins, 1 side 2 + // .wrap +}; + +// 32-bit-per-channel variants: identical to the 16-bit programs above except +// the loop counter is set to 30 (so each `bitloop` runs 31 in's, plus one +// outside the loop = 32 in's per channel). +static const uint16_t i2sin_program_32[] = { + 0xb842, // 0: nop side 3 + // .wrap_target + 0xf95e, // 1: set y, 30 side 3 [1] + 0xb242, // 2: nop side 2 [2] + 0x5801, // 3: in pins, 1 side 3 + 0x1982, // 4: jmp y--, 2 side 3 [1] + 0xa242, // 5: nop side 0 [2] + 0x4801, // 6: in pins, 1 side 1 + 0xe95e, // 7: set y, 30 side 1 [1] + 0xa242, // 8: nop side 0 [2] + 0x4801, // 9: in pins, 1 side 1 + 0x0988, // 10: jmp y--, 8 side 1 [1] + 0xb242, // 11: nop side 2 [2] + 0x5801, // 12: in pins, 1 side 3 + // .wrap +}; + +static const uint16_t i2sin_program_left_justified_32[] = { + 0xa842, // 0: nop side 1 + // .wrap_target + 0xe95e, // 1: set y, 30 side 1 [1] + 0xb242, // 2: nop side 2 [2] + 0x5801, // 3: in pins, 1 side 3 + 0x1982, // 4: jmp y--, 2 side 3 [1] + 0xb242, // 5: nop side 2 [2] + 0x5801, // 6: in pins, 1 side 3 + 0xf95e, // 7: set y, 30 side 3 [1] + 0xa242, // 8: nop side 0 [2] + 0x4801, // 9: in pins, 1 side 1 + 0x0988, // 10: jmp y--, 8 side 1 [1] + 0xa242, // 11: nop side 0 [2] + 0x4801, // 12: in pins, 1 side 1 + // .wrap +}; + +static const uint16_t i2sin_program_swap_32[] = { + 0xb842, // 0: nop side 3 + // .wrap_target + 0xf95e, // 1: set y, 30 side 3 [1] + 0xaa42, // 2: nop side 1 [2] + 0x5801, // 3: in pins, 1 side 3 + 0x1982, // 4: jmp y--, 2 side 3 [1] + 0xa242, // 5: nop side 0 [2] + 0x5001, // 6: in pins, 1 side 2 + 0xf15e, // 7: set y, 30 side 2 [1] + 0xa242, // 8: nop side 0 [2] + 0x5001, // 9: in pins, 1 side 2 + 0x1188, // 10: jmp y--, 8 side 2 [1] + 0xaa42, // 11: nop side 1 [2] + 0x5801, // 12: in pins, 1 side 3 + // .wrap +}; + +static const uint16_t i2sin_program_left_justified_swap_32[] = { + 0xb042, // 0: nop side 2 + // .wrap_target + 0xf15e, // 1: set y, 30 side 2 [1] + 0xaa42, // 2: nop side 1 [2] + 0x5801, // 3: in pins, 1 side 3 + 0x1982, // 4: jmp y--, 2 side 3 [1] + 0xaa42, // 5: nop side 1 [2] + 0x5801, // 6: in pins, 1 side 3 + 0xf95e, // 7: set y, 30 side 3 [1] + 0xa242, // 8: nop side 0 [2] + 0x5001, // 9: in pins, 1 side 2 + 0x1188, // 10: jmp y--, 8 side 2 [1] + 0xa242, // 11: nop side 0 [2] + 0x5001, // 12: in pins, 1 side 2 + // .wrap +}; + +// Caller validates that pins are free. +void common_hal_audioi2sin_i2sin_construct(audioi2sin_i2sin_obj_t *self, + const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select, + const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, + uint32_t sample_rate, uint8_t bit_depth, uint8_t output_bit_depth, + bool mono, bool left_justified, bool samples_signed) { + + if (main_clock != NULL) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_main_clock); + } + if (bit_depth != 16 && bit_depth != 24 && bit_depth != 32) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be 16, 24, or 32"), MP_QSTR_bit_depth); + } + + // 24- and 32-bit recordings both clock 32 bits per channel; 24-bit MEMS + // mics deliver their data left-justified inside that 32-bit slot. + bool wide = (bit_depth != 16); + uint32_t bits_per_channel = wide ? 32 : 16; + uint32_t pio_clocks_per_frame = bits_per_channel * 2 * PIO_CLOCKS_PER_BIT; + + const mcu_pin_obj_t *sideset_pin = NULL; + const uint16_t *program = NULL; + size_t program_len = 0; + + if (bit_clock->number == word_select->number - 1) { + sideset_pin = bit_clock; + if (left_justified) { + program = wide ? i2sin_program_left_justified_32 : i2sin_program_left_justified; + program_len = wide ? MP_ARRAY_SIZE(i2sin_program_left_justified_32) + : MP_ARRAY_SIZE(i2sin_program_left_justified); + } else { + program = wide ? i2sin_program_32 : i2sin_program; + program_len = wide ? MP_ARRAY_SIZE(i2sin_program_32) + : MP_ARRAY_SIZE(i2sin_program); + } + } else if (bit_clock->number == word_select->number + 1) { + sideset_pin = word_select; + if (left_justified) { + program = wide ? i2sin_program_left_justified_swap_32 : i2sin_program_left_justified_swap; + program_len = wide ? MP_ARRAY_SIZE(i2sin_program_left_justified_swap_32) + : MP_ARRAY_SIZE(i2sin_program_left_justified_swap); + } else { + program = wide ? i2sin_program_swap_32 : i2sin_program_swap; + program_len = wide ? MP_ARRAY_SIZE(i2sin_program_swap_32) + : MP_ARRAY_SIZE(i2sin_program_swap); + } + } else { + mp_raise_ValueError(MP_ERROR_TEXT("Bit clock and word select must be sequential GPIO pins")); + } + + common_hal_rp2pio_statemachine_construct( + &self->state_machine, + program, program_len, + sample_rate * pio_clocks_per_frame, + NULL, 0, // init + NULL, 0, // may_exec + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // out pin + data, 1, // in pins + PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // in pulls + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(0x1f), // set pins + sideset_pin, 2, false, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(0x1f), // sideset pins + false, // No sideset enable + NULL, PULL_NONE, // jump pin + PIO_PINMASK_NONE, // wait gpio pins + true, // exclusive pin use + false, 32, false, // out settings (unused) + false, // Wait for txstall + true, 32, false, // in settings: auto-push at 32 bits, shift left (MSB first) + false, // Not user-interruptible. + 1, -1, // wrap settings + PIO_ANY_OFFSET, + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, + PIO_MOV_N_DEFAULT); + + uint32_t actual_frequency = common_hal_rp2pio_statemachine_get_frequency(&self->state_machine); + self->sample_rate = actual_frequency / pio_clocks_per_frame; + self->bit_depth = bit_depth; + self->mono = mono; + self->samples_signed = samples_signed; + self->left_justified = left_justified; + self->settled = false; + self->ring = NULL; + self->ring_size = 0; + self->half_size = 0; + self->read_pos = 0; + self->dma_channel = -1; + self->overflow = false; + + // Populate the audiosample base so I2SIn can feed the audio pipeline as a + // streaming source. The output depth must be 8 or 16 to actually stream; we + // still fill base here (so sample_rate/bits_per_sample/etc. read back) and + // raise from reset_buffer if a 24/32-bit instance is played. The owned + // conversion buffer is allocated lazily on first reset_buffer(). + uint8_t channel_count = mono ? 1 : 2; + // Report the *nominal* requested rate (not the PIO-derived self->sample_rate, + // which can be off by a fraction of a Hz). audiosample_must_match requires + // exact equality against the consumer, which is configured for the nominal + // rate; the tiny capture-clock difference shows up as the slow drift that the + // underrun silence-pad / overflow-drop paths in fill_buffer absorb. + self->base.sample_rate = sample_rate; + self->base.bits_per_sample = output_bit_depth; + self->base.channel_count = channel_count; + self->base.samples_signed = samples_signed; + self->base.single_buffer = false; + self->base.max_buffer_length = + 2 * AUDIOI2SIN_STREAM_FRAMES * (output_bit_depth / 8) * channel_count; + self->output_buffer = NULL; + self->output_half_bytes = self->base.max_buffer_length / 2; + self->output_index = 0; + + // Each PIO frame produces 4 bytes in the FIFO regardless of bit depth + // (16-bit auto-pushes one packed stereo word, 24/32-bit pushes two + // separate 32-bit words). One stereo frame is therefore either 4 or + // 8 bytes; size the half-buffer for ~40 ms of audio so a slow consumer + // (SD card flush etc.) can complete without overrunning. + size_t bytes_per_frame = (bit_depth == 16) ? 4 : 8; + size_t target = (size_t)self->sample_rate * bytes_per_frame * 40 / 1000; + size_t half_size = (target > 4096) ? target : 4096; + // Round up to a multiple of 8 so 24/32-bit pair reads never straddle + // the half boundary. + half_size = (half_size + 7u) & ~(size_t)7u; + + self->ring = (uint8_t *)port_malloc(2 * half_size, true); + if (self->ring == NULL) { + common_hal_rp2pio_statemachine_deinit(&self->state_machine); + m_malloc_fail(2 * half_size); + } + self->half_size = half_size; + self->ring_size = 2 * half_size; + + common_hal_rp2pio_statemachine_set_read_buffers_raw(&self->state_machine, + NULL, 0, + self->ring, half_size, + self->ring + half_size, half_size); + if (!common_hal_rp2pio_statemachine_background_read(&self->state_machine, 4, false)) { + port_free(self->ring); + self->ring = NULL; + common_hal_rp2pio_statemachine_deinit(&self->state_machine); + mp_raise_OSError(MP_EIO); + } + self->dma_channel = common_hal_rp2pio_statemachine_get_read_dma_channel(&self->state_machine); +} + +bool common_hal_audioi2sin_i2sin_deinited(audioi2sin_i2sin_obj_t *self) { + return common_hal_rp2pio_statemachine_deinited(&self->state_machine); +} + +void common_hal_audioi2sin_i2sin_deinit(audioi2sin_i2sin_obj_t *self) { + if (common_hal_audioi2sin_i2sin_deinited(self)) { + return; + } + common_hal_rp2pio_statemachine_stop_background_read(&self->state_machine); + common_hal_rp2pio_statemachine_deinit(&self->state_machine); + if (self->ring != NULL) { + port_free(self->ring); + self->ring = NULL; + } + if (self->output_buffer != NULL) { + port_free(self->output_buffer); + self->output_buffer = NULL; + } + self->ring_size = 0; + self->half_size = 0; + self->dma_channel = -1; + audiosample_mark_deinit(&self->base); +} + +uint8_t common_hal_audioi2sin_i2sin_get_bit_depth(audioi2sin_i2sin_obj_t *self) { + return self->bit_depth; +} + +uint32_t common_hal_audioi2sin_i2sin_get_sample_rate(audioi2sin_i2sin_obj_t *self) { + return self->sample_rate; +} + +bool common_hal_audioi2sin_i2sin_get_samples_signed(audioi2sin_i2sin_obj_t *self) { + return self->samples_signed; +} + +// In 16-bit mode, each PIO frame produces a single 32-bit FIFO word with bits +// 31..16 = right channel and bits 15..0 = left channel (both MSB-first signed +// 16-bit). In 24/32-bit mode each frame produces two FIFO words: right first, +// then left, each MSB-first in the full 32 bits. For mono we keep the left +// channel; for stereo we emit (left, right) pairs. +// +// `output_buffer_length` is the requested number of samples to write (sample +// width = 2 bytes for bit_depth=16, 4 bytes for bit_depth=24 or 32). Returns +// the number actually written. +// Compute the byte offset inside `ring` that the DMA is currently writing +// (one past the last word it finished). Always lies in [0, ring_size). +static size_t i2sin_write_pos(audioi2sin_i2sin_obj_t *self) { + uintptr_t addr = (uintptr_t)dma_channel_hw_addr(self->dma_channel)->write_addr; + uintptr_t base = (uintptr_t)self->ring; + if (addr < base || addr >= base + self->ring_size) { + // The ISR retargets write_addr to the start of the next half right + // after a transfer completes; it should always be in-range, but if + // we observe it mid-update just report "no new data". + return self->read_pos; + } + return (size_t)(addr - base); +} + +// 24-bit non-left-justified data arrives in the low 24 bits of the FIFO word +// with the sign bit at bit 23 and bits 31..24 zero. To make it decode +// correctly as int32 (array typecode "i"), lift the sign bit to bit 31. +static inline uint32_t movesign24(uint32_t val) { + return ((val & 0x800000u) << 8) | (val & 0x7fffffu); +} + +// Sign-extend a raw FIFO sample to a canonical int32 value. `raw` holds the +// sample as delivered by the PIO program for the given input bit depth and +// alignment. The returned int32 represents the same magnitude with the sign +// bit at bit 31. +static inline int32_t i2sin_normalize_signed(uint32_t raw, uint8_t in_depth, + bool left_justified) { + if (in_depth == 32) { + return (int32_t)raw; + } + if (in_depth == 24) { + if (left_justified) { + // value in bits 31..8, sign at 31; arithmetic shift right 8 + return (int32_t)raw >> 8; + } + // value in bits 23..0, sign at 23 + uint32_t sign_bit = 0x800000u; + return (int32_t)((raw ^ sign_bit) - sign_bit); + } + // 16-bit: low 16 bits, sign at 15 + return (int16_t)(raw & 0xffffu); +} + +// Normalize `raw` (input-depth bits, just-read FIFO sample) for this port's wire +// format, then hand off to the shared converter to rescale `in_depth` -> +// `out_depth` and write it to `buffer` at sample index `idx`. The depth +// conversion + unsigned-WAV flip + container store live in +// `shared_audioi2sin_write_converted` (shared with other ports); see that helper +// for the upscale/downscale semantics. +// +// For signed 24-bit output, the int32 slot holds the sign-extended value +// (range -2^23 .. 2^23-1) — unlike the default `output_bit_depth=bit_depth=24` +// path which uses `movesign24`, the converted path returns proper two's +// complement so the result decodes correctly as int32. +static inline void i2sin_write_converted(void *buffer, uint32_t idx, + uint32_t raw, uint8_t in_depth, uint8_t out_depth, + bool samples_signed, bool left_justified) { + int32_t s = i2sin_normalize_signed(raw, in_depth, left_justified); + shared_audioi2sin_write_converted(buffer, idx, s, in_depth, out_depth, samples_signed); +} + +uint32_t common_hal_audioi2sin_i2sin_record_to_buffer(audioi2sin_i2sin_obj_t *self, + void *buffer, uint32_t output_buffer_length) { + uint32_t output_count = 0; + const size_t ring_size = self->ring_size; + const size_t half_size = self->half_size; + + // I2S delivers signed PCM. When the caller asked for unsigned samples, + // flip the sign bit per sample (XOR with 0x8000 for 16-bit, 0x800000 for + // 24-bit data in a 32-bit slot, 0x80000000 for 32-bit), matching the WAV + // convention. The default (no-conversion) path applies the flip to the + // raw FIFO word before splitting into channels; the conversion path + // applies the flip per output sample at output bit width. + const bool convert = self->base.bits_per_sample != self->bit_depth; + const uint32_t flip16 = (!convert && !self->samples_signed) ? 0x80008000u : 0u; + const uint32_t flip32 = (!convert && !self->samples_signed) + ? (self->bit_depth == 24 ? 0x800000u : 0x80000000u) + : 0u; + const bool fix_sign24 = !convert + && self->bit_depth == 24 + && self->samples_signed + && !self->left_justified; + const uint8_t in_depth = self->bit_depth; + const uint8_t out_depth = self->base.bits_per_sample; + const bool left_justified = self->left_justified; + const bool samples_signed = self->samples_signed; + + if (self->bit_depth == 16) { + // 16-bit mode auto-pushes one stereo frame per FIFO word. The DMA has + // been streaming since construct time, so the ring already contains + // settled data; drop the first 4 bytes once to discard a single + // pre-record frame (matches the prior synchronous behaviour). + uint16_t *output = convert ? NULL : (uint16_t *)buffer; + while (output_count < output_buffer_length) { + size_t write_pos = i2sin_write_pos(self); + size_t avail = (write_pos + ring_size - self->read_pos) % ring_size; + if (avail > half_size) { + // DMA has filled more than one half ahead of us -- we lost + // data. Snap to just behind the DMA on a 4-byte boundary. + self->overflow = true; + self->read_pos = write_pos & ~(size_t)3u; + avail = 0; + } + if (!self->settled && avail >= 4) { + self->read_pos = (self->read_pos + 4) % ring_size; + avail -= 4; + self->settled = true; + } + if (avail < 4) { + RUN_BACKGROUND_TASKS; + if (mp_hal_is_interrupted()) { + return output_count; + } + continue; + } + while (avail >= 4 && output_count < output_buffer_length) { + uint32_t frame = *(volatile uint32_t *)(self->ring + self->read_pos) ^ flip16; + uint16_t left = (uint16_t)(frame & 0xffff); + uint16_t right = (uint16_t)(frame >> 16); + if (!convert) { + if (self->mono) { + output[output_count++] = left; + } else { + output[output_count++] = left; + if (output_count >= output_buffer_length) { + self->read_pos = (self->read_pos + 4) % ring_size; + avail -= 4; + break; + } + output[output_count++] = right; + } + } else { + i2sin_write_converted(buffer, output_count++, left, + in_depth, out_depth, samples_signed, left_justified); + if (!self->mono) { + if (output_count >= output_buffer_length) { + self->read_pos = (self->read_pos + 4) % ring_size; + avail -= 4; + break; + } + i2sin_write_converted(buffer, output_count++, right, + in_depth, out_depth, samples_signed, left_justified); + } + } + self->read_pos = (self->read_pos + 4) % ring_size; + avail -= 4; + } + } + } else { + // 24-/32-bit mode emits two FIFO pushes per stereo frame (right then + // left). The state machine was started at instruction 0 by the + // constructor, so the very first push is the right channel and + // alternation is preserved as long as we never touch the program + // counter and always read an even number of words. half_size is a + // multiple of 8, so reading 8-byte pairs stays aligned across the + // ring wrap. + uint32_t *output = convert ? NULL : (uint32_t *)buffer; + while (output_count < output_buffer_length) { + size_t write_pos = i2sin_write_pos(self); + size_t avail = (write_pos + ring_size - self->read_pos) % ring_size; + if (avail > half_size) { + // Overflow: snap to a frame-aligned position one half behind + // the DMA's current half so we resume on the right channel. + self->overflow = true; + size_t cur_half = (write_pos < half_size) ? 0 : half_size; + self->read_pos = (cur_half + half_size) % ring_size; + self->settled = false; + avail = (write_pos + ring_size - self->read_pos) % ring_size; + } + if (!self->settled && avail >= 8) { + self->read_pos = (self->read_pos + 8) % ring_size; + avail -= 8; + self->settled = true; + } + if (avail < 8) { + RUN_BACKGROUND_TASKS; + if (mp_hal_is_interrupted()) { + return output_count; + } + continue; + } + while (avail >= 8 && output_count < output_buffer_length) { + uint32_t right = *(volatile uint32_t *)(self->ring + self->read_pos) ^ flip32; + size_t next_pos = (self->read_pos + 4) % ring_size; + uint32_t left = *(volatile uint32_t *)(self->ring + next_pos) ^ flip32; + if (fix_sign24) { + right = movesign24(right); + left = movesign24(left); + } + if (!convert) { + if (self->mono) { + output[output_count++] = left; + } else { + output[output_count++] = left; + if (output_count >= output_buffer_length) { + self->read_pos = (self->read_pos + 8) % ring_size; + avail -= 8; + break; + } + output[output_count++] = right; + } + } else { + i2sin_write_converted(buffer, output_count++, left, + in_depth, out_depth, samples_signed, left_justified); + if (!self->mono) { + if (output_count >= output_buffer_length) { + self->read_pos = (self->read_pos + 8) % ring_size; + avail -= 8; + break; + } + i2sin_write_converted(buffer, output_count++, right, + in_depth, out_depth, samples_signed, left_justified); + } + } + self->read_pos = (self->read_pos + 8) % ring_size; + avail -= 8; + } + } + } + + return output_count; +} + +// Write `count` silence samples at output depth starting at sample index `idx`. +// For signed PCM silence is 0; for unsigned (WAV) it is mid-scale. +static void i2sin_fill_silence(void *buffer, uint32_t idx, uint32_t count, + uint8_t out_depth, bool samples_signed) { + if (out_depth == 8) { + uint8_t v = samples_signed ? 0 : 0x80u; + memset((uint8_t *)buffer + idx, v, count); + } else { // 16-bit (the only other streamable width) + uint16_t v = samples_signed ? 0 : 0x8000u; + uint16_t *p = (uint16_t *)buffer + idx; + for (uint32_t i = 0; i < count; i++) { + p[i] = v; + } + } +} + +// Non-blocking fill: convert up to `frames` frames currently available in the +// DMA ring into `buffer` (output depth, interleaved), padding the remainder with +// silence on underrun rather than spinning. Used by get_buffer() from the output +// backend's refill interrupt, so it must never block. `out_depth` is always 8 or +// 16 here (reset_buffer rejects 24/32). Reuses the same per-sample conversion as +// record_to_buffer via i2sin_write_converted. +void common_hal_audioi2sin_i2sin_fill_buffer(audioi2sin_i2sin_obj_t *self, + uint8_t *buffer, uint32_t frames) { + const size_t ring_size = self->ring_size; + const size_t half_size = self->half_size; + const uint8_t in_depth = self->bit_depth; + const uint8_t out_depth = self->base.bits_per_sample; + const bool samples_signed = self->samples_signed; + const bool left_justified = self->left_justified; + const bool stereo = !self->mono; + const uint8_t channel_count = stereo ? 2 : 1; + const size_t frame_bytes = (in_depth == 16) ? 4 : 8; + const uint32_t total_samples = frames * channel_count; + + uint32_t produced = 0; + while (produced < total_samples) { + size_t write_pos = i2sin_write_pos(self); + size_t avail = (write_pos + ring_size - self->read_pos) % ring_size; + if (avail > half_size) { + // The consumer is slower than the mic and the ring is filling up + // (the overflow case record_to_buffer also handles). Drop back to + // just behind the DMA so latency stays bounded; the discarded audio + // shows up as a brief discontinuity, not a hang. + self->overflow = true; + if (in_depth == 16) { + self->read_pos = write_pos & ~(size_t)3u; + } else { + size_t cur_half = (write_pos < half_size) ? 0 : half_size; + self->read_pos = (cur_half + half_size) % ring_size; + self->settled = false; + } + avail = (write_pos + ring_size - self->read_pos) % ring_size; + } + if (!self->settled && avail >= frame_bytes) { + // Drop one frame so playback starts on a settled sample and (for + // 24/32-bit) on the right-channel word the program emits first. + self->read_pos = (self->read_pos + frame_bytes) % ring_size; + avail -= frame_bytes; + self->settled = true; + } + if (avail < frame_bytes) { + break; // underrun: pad the rest with silence below + } + uint32_t left, right; + if (in_depth == 16) { + uint32_t fr = *(volatile uint32_t *)(self->ring + self->read_pos); + left = fr & 0xffffu; + right = fr >> 16; + } else { + right = *(volatile uint32_t *)(self->ring + self->read_pos); + size_t next_pos = (self->read_pos + 4) % ring_size; + left = *(volatile uint32_t *)(self->ring + next_pos); + } + i2sin_write_converted(buffer, produced++, left, + in_depth, out_depth, samples_signed, left_justified); + if (stereo && produced < total_samples) { + i2sin_write_converted(buffer, produced++, right, + in_depth, out_depth, samples_signed, left_justified); + } + self->read_pos = (self->read_pos + frame_bytes) % ring_size; + } + if (produced < total_samples) { + i2sin_fill_silence(buffer, produced, total_samples - produced, + out_depth, samples_signed); + } +} + +void common_hal_audioi2sin_i2sin_reset_buffer(audioi2sin_i2sin_obj_t *self, + bool single_channel_output, uint8_t channel) { + (void)single_channel_output; + (void)channel; + // The audio pipeline only carries 8- or 16-bit samples. 24/32-bit modes can + // still record() but cannot stream; fail clearly the first time playback is + // set up rather than emitting garbage. + if (self->base.bits_per_sample != 8 && self->base.bits_per_sample != 16) { + mp_raise_ValueError_varg( + MP_ERROR_TEXT("%q must be 8 or 16"), MP_QSTR_output_bit_depth); + } + if (self->output_buffer == NULL) { + // The output backend's DMA reads this buffer directly, so it must be + // DMA-capable like the input ring. + self->output_buffer = (uint8_t *)port_malloc(self->base.max_buffer_length, true); + if (self->output_buffer == NULL) { + m_malloc_fail(self->base.max_buffer_length); + } + } + self->output_index = 0; + // Resync to live audio: snap the read cursor just behind the DMA write head + // (frame-aligned) and re-settle so playback begins on fresh samples. + size_t write_pos = i2sin_write_pos(self); + self->read_pos = (self->bit_depth == 16) + ? (write_pos & ~(size_t)3u) + : (write_pos & ~(size_t)7u); + self->settled = false; + self->overflow = false; +} + +audioio_get_buffer_result_t common_hal_audioi2sin_i2sin_get_buffer( + audioi2sin_i2sin_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + uint32_t half = self->output_half_bytes; + uint8_t *out = self->output_buffer + half * self->output_index; + self->output_index = 1 - self->output_index; + + uint32_t bytes_per_sample = self->base.bits_per_sample / 8; + uint32_t frames = half / (bytes_per_sample * self->base.channel_count); + common_hal_audioi2sin_i2sin_fill_buffer(self, out, frames); + + if (single_channel_output) { + out += (channel % self->base.channel_count) * bytes_per_sample; + } + *buffer = out; + *buffer_length = half; + // A live mic is an infinite stream; never report DONE or the backend stops. + return GET_BUFFER_MORE_DATA; +} + +#endif // CIRCUITPY_AUDIOI2SIN diff --git a/ports/raspberrypi/common-hal/audioi2sin/I2SIn.h b/ports/raspberrypi/common-hal/audioi2sin/I2SIn.h new file mode 100644 index 00000000000..bd5cdea577e --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/I2SIn.h @@ -0,0 +1,47 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/microcontroller/Pin.h" +#include "bindings/rp2pio/StateMachine.h" + +#include "py/obj.h" + +#include "shared-module/audiocore/__init__.h" + +// Number of audio frames a single get_buffer() call hands to the output backend +// (one frame = one mono sample, or an L+R pair in stereo). This sets the pull +// granularity and the silence-pad chunk on underrun. Kept independent of the DMA +// half-buffer so the two can be tuned separately. +#define AUDIOI2SIN_STREAM_FRAMES (256) + +typedef struct { + // so I2SIn can be used directly as an audiosample source. + audiosample_base_t base; + uint32_t sample_rate; + uint8_t bit_depth; + bool mono; + bool samples_signed; + bool left_justified; + bool settled; + rp2pio_statemachine_obj_t state_machine; + // Background DMA ring buffer. The state machine alternates DMA writes + // between the two halves so BCLK never stalls between record() calls. + uint8_t *ring; + size_t ring_size; + size_t half_size; + size_t read_pos; + int dma_channel; + bool overflow; + // Owned double-buffer returned to the output backend by get_buffer(), holding + // converted (output-depth, interleaved) samples. Allocated lazily on the first + // reset_buffer() so record()-only use pays no extra RAM. base.max_buffer_length + // is the whole buffer; get_buffer() returns output_half_bytes of it. + uint8_t *output_buffer; + size_t output_half_bytes; + uint8_t output_index; +} audioi2sin_i2sin_obj_t; diff --git a/ports/raspberrypi/common-hal/audioi2sin/README.pio b/ports/raspberrypi/common-hal/audioi2sin/README.pio new file mode 100644 index 00000000000..664c1301a72 --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/README.pio @@ -0,0 +1,14 @@ +.pio files right now are compiled by hand with pico-sdk/tools/pioasm and inserted into I2SIn.c + +i2sin.pio I2S RX, 16 bits/channel, regular pin order, not left_justified +i2sin_left.pio I2S RX, 16 bits/channel, regular pin order, left_justified +i2sin_swap.pio I2S RX, 16 bits/channel, swapped pin order, not left_justified +i2sin_swap_left.pio I2S RX, 16 bits/channel, swapped pin order, left_justified +i2sin_32.pio I2S RX, 32 bits/channel, regular pin order, not left_justified +i2sin_left_32.pio I2S RX, 32 bits/channel, regular pin order, left_justified +i2sin_swap_32.pio I2S RX, 32 bits/channel, swapped pin order, not left_justified +i2sin_swap_left_32.pio I2S RX, 32 bits/channel, swapped pin order, left_justified + +The 32-bit programs are also used for bit_depth=24 because most 24-bit I2S +mics (SPH0645LM4H, INMP441, ICS-43434) place their 24 valid data bits +left-justified inside a 32-bit slot. diff --git a/ports/raspberrypi/common-hal/audioi2sin/__init__.c b/ports/raspberrypi/common-hal/audioi2sin/__init__.c new file mode 100644 index 00000000000..584c821b996 --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT diff --git a/ports/raspberrypi/common-hal/audioi2sin/i2sin.pio b/ports/raspberrypi/common-hal/audioi2sin/i2sin.pio new file mode 100644 index 00000000000..97dc9c7f7e9 --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/i2sin.pio @@ -0,0 +1,34 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2sin +.side_set 2 + +; Master-mode I2S RX. Generates BCLK and LRCLK via side-set and samples the +; data pin. The slave updates `data` on BCLK falling edge, so the master +; samples on the rising edge: every `in pins 1` runs on a side-set value +; with BCLK=1, and the loop/transition instructions hold BCLK=0 so the +; slave has time to settle the next bit. + ; /--- LRCLK + ; |/-- BCLK + ; || + nop side 0b11 +.wrap_target + set y 14 side 0b11 [1] +bitloop1: + nop side 0b10 [2] ; Right channel first + in pins 1 side 0b11 + jmp y-- bitloop1 side 0b11 [1] + nop side 0b00 [2] + in pins 1 side 0b01 + set y 14 side 0b01 [1] +bitloop0: + nop side 0b00 [2] ; Then left channel + in pins 1 side 0b01 + jmp y-- bitloop0 side 0b01 [1] + nop side 0b10 [2] + in pins 1 side 0b11 +.wrap diff --git a/ports/raspberrypi/common-hal/audioi2sin/i2sin_32.pio b/ports/raspberrypi/common-hal/audioi2sin/i2sin_32.pio new file mode 100644 index 00000000000..f09a02a85c2 --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/i2sin_32.pio @@ -0,0 +1,35 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2sin_32 +.side_set 2 + +; Master-mode I2S RX, 32 bits per channel (also used for 24-bit mics that +; transmit data left-justified in a 32-bit slot). Generates BCLK and LRCLK +; via side-set and samples the data pin. The slave updates `data` on BCLK +; falling edge, so the master samples on the rising edge: every `in pins 1` +; runs on a side-set value with BCLK=1, and the preceding nop holds BCLK=0 +; so the slave has time to settle the next bit. + ; /--- LRCLK + ; |/-- BCLK + ; || + nop side 0b11 +.wrap_target + set y 30 side 0b11 [1] +bitloop1: + nop side 0b10 [2] ; Right channel first + in pins 1 side 0b11 + jmp y-- bitloop1 side 0b11 [1] + nop side 0b00 [2] + in pins 1 side 0b01 + set y 30 side 0b01 [1] +bitloop0: + nop side 0b00 [2] ; Then left channel + in pins 1 side 0b01 + jmp y-- bitloop0 side 0b01 [1] + nop side 0b10 [2] + in pins 1 side 0b11 +.wrap diff --git a/ports/raspberrypi/common-hal/audioi2sin/i2sin_left.pio b/ports/raspberrypi/common-hal/audioi2sin/i2sin_left.pio new file mode 100644 index 00000000000..8926d178635 --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/i2sin_left.pio @@ -0,0 +1,30 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2sin_left +.side_set 2 + +; Master-mode I2S RX, left-justified. Mirrors the timing of i2s_left.pio. + ; /--- LRCLK + ; |/-- BCLK + ; || + nop side 0b01 +.wrap_target + set y 14 side 0b01 [1] +bitloop1: + nop side 0b10 [2] ; Right channel first + in pins 1 side 0b11 + jmp y-- bitloop1 side 0b11 [1] + nop side 0b10 [2] + in pins 1 side 0b11 + set y 14 side 0b11 [1] +bitloop0: + nop side 0b00 [2] ; Then left channel + in pins 1 side 0b01 + jmp y-- bitloop0 side 0b01 [1] + nop side 0b00 [2] + in pins 1 side 0b01 +.wrap diff --git a/ports/raspberrypi/common-hal/audioi2sin/i2sin_left_32.pio b/ports/raspberrypi/common-hal/audioi2sin/i2sin_left_32.pio new file mode 100644 index 00000000000..86fcf79a876 --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/i2sin_left_32.pio @@ -0,0 +1,30 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2sin_left_32 +.side_set 2 + +; Master-mode I2S RX, 32 bits per channel, left-justified. + ; /--- LRCLK + ; |/-- BCLK + ; || + nop side 0b01 +.wrap_target + set y 30 side 0b01 [1] +bitloop1: + nop side 0b10 [2] ; Right channel first + in pins 1 side 0b11 + jmp y-- bitloop1 side 0b11 [1] + nop side 0b10 [2] + in pins 1 side 0b11 + set y 30 side 0b11 [1] +bitloop0: + nop side 0b00 [2] ; Then left channel + in pins 1 side 0b01 + jmp y-- bitloop0 side 0b01 [1] + nop side 0b00 [2] + in pins 1 side 0b01 +.wrap diff --git a/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap.pio b/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap.pio new file mode 100644 index 00000000000..8b718ebae65 --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap.pio @@ -0,0 +1,31 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2sin_swap +.side_set 2 + +; Master-mode I2S RX with the LRCLK and BCLK pin order swapped (BCLK is the +; higher-numbered GPIO). + ; /--- BCLK + ; |/-- LRCLK + ; || + nop side 0b11 +.wrap_target + set y 14 side 0b11 [1] +bitloop1: + nop side 0b01 [2] ; Right channel first + in pins 1 side 0b11 + jmp y-- bitloop1 side 0b11 [1] + nop side 0b00 [2] + in pins 1 side 0b10 + set y 14 side 0b10 [1] +bitloop0: + nop side 0b00 [2] ; Then left channel + in pins 1 side 0b10 + jmp y-- bitloop0 side 0b10 [1] + nop side 0b01 [2] + in pins 1 side 0b11 +.wrap diff --git a/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap_32.pio b/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap_32.pio new file mode 100644 index 00000000000..8ac65a20f90 --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap_32.pio @@ -0,0 +1,31 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2sin_swap_32 +.side_set 2 + +; Master-mode I2S RX, 32 bits per channel, with the LRCLK and BCLK pin order +; swapped (BCLK is the higher-numbered GPIO). + ; /--- BCLK + ; |/-- LRCLK + ; || + nop side 0b11 +.wrap_target + set y 30 side 0b11 [1] +bitloop1: + nop side 0b01 [2] ; Right channel first + in pins 1 side 0b11 + jmp y-- bitloop1 side 0b11 [1] + nop side 0b00 [2] + in pins 1 side 0b10 + set y 30 side 0b10 [1] +bitloop0: + nop side 0b00 [2] ; Then left channel + in pins 1 side 0b10 + jmp y-- bitloop0 side 0b10 [1] + nop side 0b01 [2] + in pins 1 side 0b11 +.wrap diff --git a/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap_left.pio b/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap_left.pio new file mode 100644 index 00000000000..f6adc3d5bb8 --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap_left.pio @@ -0,0 +1,31 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2sin_swap_left +.side_set 2 + +; Master-mode I2S RX, left-justified, with the LRCLK and BCLK pin order +; swapped (BCLK is the higher-numbered GPIO). + ; /--- BCLK + ; |/-- LRCLK + ; || + nop side 0b10 +.wrap_target + set y 14 side 0b10 [1] +bitloop1: + nop side 0b01 [2] ; Right channel first + in pins 1 side 0b11 + jmp y-- bitloop1 side 0b11 [1] + nop side 0b01 [2] + in pins 1 side 0b11 + set y 14 side 0b11 [1] +bitloop0: + nop side 0b00 [2] ; Then left channel + in pins 1 side 0b10 + jmp y-- bitloop0 side 0b10 [1] + nop side 0b00 [2] + in pins 1 side 0b10 +.wrap diff --git a/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap_left_32.pio b/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap_left_32.pio new file mode 100644 index 00000000000..ae0ef8b8afb --- /dev/null +++ b/ports/raspberrypi/common-hal/audioi2sin/i2sin_swap_left_32.pio @@ -0,0 +1,31 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2sin_swap_left_32 +.side_set 2 + +; Master-mode I2S RX, 32 bits per channel, left-justified, with the LRCLK and +; BCLK pin order swapped (BCLK is the higher-numbered GPIO). + ; /--- BCLK + ; |/-- LRCLK + ; || + nop side 0b10 +.wrap_target + set y 30 side 0b10 [1] +bitloop1: + nop side 0b01 [2] ; Right channel first + in pins 1 side 0b11 + jmp y-- bitloop1 side 0b11 [1] + nop side 0b01 [2] + in pins 1 side 0b11 + set y 30 side 0b11 [1] +bitloop0: + nop side 0b00 [2] ; Then left channel + in pins 1 side 0b10 + jmp y-- bitloop0 side 0b10 [1] + nop side 0b00 [2] + in pins 1 side 0b10 +.wrap diff --git a/ports/raspberrypi/common-hal/busio/UART.c b/ports/raspberrypi/common-hal/busio/UART.c index 17fcfa17229..074c78c2f4a 100644 --- a/ports/raspberrypi/common-hal/busio/UART.c +++ b/ports/raspberrypi/common-hal/busio/UART.c @@ -50,7 +50,7 @@ static void pin_check(const uint8_t uart, const mcu_pin_obj_t *pin, const uint8_ if (pins_uart != uart) { raise_ValueError_invalid_pins(); } - #ifdef PICO_RP2350 + #if PICO_RP2350 if ((pin_type == 0 && pin->number % 4 == 2) || (pin_type == 1 && pin->number % 4 == 3)) { return; @@ -67,7 +67,7 @@ static uint8_t pin_init(const uint8_t uart, const mcu_pin_obj_t *pin, const uint } claim_pin(pin); gpio_function_t function = GPIO_FUNC_UART; - #ifdef PICO_RP2350 + #if PICO_RP2350 if ((pin_type == 0 && pin->number % 4 == 2) || (pin_type == 1 && pin->number % 4 == 3)) { function = GPIO_FUNC_UART_AUX; diff --git a/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c b/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c index d1c92eea998..a40f6e26608 100644 --- a/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c +++ b/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c @@ -85,6 +85,13 @@ void common_hal_i2ctarget_i2c_target_deinit(i2ctarget_i2c_target_obj_t *self) { } int common_hal_i2ctarget_i2c_target_is_addressed(i2ctarget_i2c_target_obj_t *self, uint8_t *address, bool *is_read, bool *is_restart) { + // Interrupt bits must be cleared by software. Clear the STOP and + // RESTART interrupt bits after an I2C transaction finishes. + if (self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_STOP_DET_BITS) { + self->peripheral->hw->clr_stop_det; + self->peripheral->hw->clr_restart_det; + } + if (!((self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_RX_FULL_BITS) || (self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_RD_REQ_BITS))) { return 0; } @@ -98,12 +105,20 @@ int common_hal_i2ctarget_i2c_target_is_addressed(i2ctarget_i2c_target_obj_t *sel } int common_hal_i2ctarget_i2c_target_read_byte(i2ctarget_i2c_target_obj_t *self, uint8_t *data) { - if (self->peripheral->hw->status & I2C_IC_STATUS_RFNE_BITS) { - *data = (uint8_t)self->peripheral->hw->data_cmd; - return 1; - } else { - return 0; + // Wait for data to arrive or a STOP condition indicating the transfer is over. + // Without this wait, the CPU can drain the FIFO faster than bytes arrive on the + // I2C bus, causing transfers to be split into multiple partial reads. + for (int t = 0; t < 100; t++) { + if (self->peripheral->hw->status & I2C_IC_STATUS_RFNE_BITS) { + *data = (uint8_t)self->peripheral->hw->data_cmd; + return 1; + } + if (self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_STOP_DET_BITS) { + break; + } + mp_hal_delay_us(10); } + return 0; } int common_hal_i2ctarget_i2c_target_write_byte(i2ctarget_i2c_target_obj_t *self, uint8_t data) { diff --git a/ports/raspberrypi/common-hal/mcp4822/MCP4822.c b/ports/raspberrypi/common-hal/mcp4822/MCP4822.c new file mode 100644 index 00000000000..7a8ad7d4df2 --- /dev/null +++ b/ports/raspberrypi/common-hal/mcp4822/MCP4822.c @@ -0,0 +1,286 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT +// +// MCP4822 dual-channel 12-bit SPI DAC audio output. +// Uses PIO + DMA for non-blocking audio playback, mirroring audiobusio.I2SOut. + +#include +#include + +#include "mpconfigport.h" + +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "common-hal/mcp4822/MCP4822.h" +#include "shared-bindings/mcp4822/MCP4822.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/audiocore/__init__.h" +#include "bindings/rp2pio/StateMachine.h" + +// ───────────────────────────────────────────────────────────────────────────── +// PIO program for MCP4822 SPI DAC +// ───────────────────────────────────────────────────────────────────────────── +// +// Pin assignment: +// OUT pin (1) = MOSI — serial data out +// SET pins (N) = MOSI through CS — for CS control & command-bit injection +// SIDE-SET pin (1) = SCK — serial clock +// +// SET PINS bit mapping (bit0=MOSI, ..., bit N=CS): +// 0 = CS low, MOSI low 1 = CS low, MOSI high +// (1 << cs_bit_pos) = CS high, MOSI low +// +// SIDE-SET (1 pin, SCK): side 0 = SCK low, side 1 = SCK high +// +// MCP4822 16-bit command word: +// [15] channel (0=A, 1=B) [14] don't care [13] gain (1=1x, 0=2x) +// [12] output enable (1) [11:0] 12-bit data +// +// DMA feeds unsigned 16-bit audio samples. RP2040 narrow-write replication +// fills both halves of the 32-bit PIO FIFO entry with the same value, +// giving mono→stereo for free. +// +// The PIO pulls 32 bits, then sends two SPI transactions: +// Channel A: cmd nibble, then all 16 sample bits from upper half-word +// Channel B: cmd nibble, then all 16 sample bits from lower half-word +// The MCP4822 captures exactly 16 bits per CS frame (4 cmd + 12 data), +// so only the top 12 of the 16 sample bits become DAC data. The bottom +// 4 sample bits clock out harmlessly after the DAC has latched. +// This gives correct 16-bit → 12-bit scaling (effectively sample >> 4). +// +// PIO instruction encoding with .side_set 1 (no opt): +// [15:13] opcode [12] side-set [11:8] delay [7:0] operands +// +// Total: 26 instructions, 86 PIO clocks per audio sample. +// ───────────────────────────────────────────────────────────────────────────── + +static const uint16_t mcp4822_pio_program[] = { + // side SCK + // 0: pull noblock side 0 ; Get 32 bits or keep X if FIFO empty + 0x8080, + // 1: mov x, osr side 0 ; Save for pull-noblock fallback + 0xA027, + + // ── Channel A: command nibble 0b0011 (1x gain) ──────────────────────── + // 2: set pins, 0 side 0 ; CS low, MOSI=0 (bit15=0: channel A) + 0xE000, + // 3: nop side 1 ; SCK high — latch bit 15 + 0xB042, + // 4: set pins, 0 side 0 ; MOSI=0 (bit14=0: don't care) + 0xE000, + // 5: nop side 1 ; SCK high + 0xB042, + // 6: set pins, 1 side 0 ; MOSI=1 (bit13=1: gain 1x) [patched for 2x] + 0xE001, + // 7: nop side 1 ; SCK high + 0xB042, + // 8: set pins, 1 side 0 ; MOSI=1 (bit12=1: output active) + 0xE001, + // 9: nop side 1 ; SCK high + 0xB042, + // 10: set y, 15 side 0 ; Loop counter: 16 sample bits + 0xE04F, + // 11: out pins, 1 side 0 ; Data bit → MOSI; SCK low (bitloopA) + 0x6001, + // 12: jmp y--, 11 side 1 ; SCK high, loop back + 0x108B, + // 13: set pins, 4 side 0 ; CS high — DAC A latches + 0xE004, + + // ── Channel B: command nibble 0b1011 (1x gain) ──────────────────────── + // 14: set pins, 1 side 0 ; CS low, MOSI=1 (bit15=1: channel B) + 0xE001, + // 15: nop side 1 ; SCK high + 0xB042, + // 16: set pins, 0 side 0 ; MOSI=0 (bit14=0) + 0xE000, + // 17: nop side 1 ; SCK high + 0xB042, + // 18: set pins, 1 side 0 ; MOSI=1 (bit13=1: gain 1x) [patched for 2x] + 0xE001, + // 19: nop side 1 ; SCK high + 0xB042, + // 20: set pins, 1 side 0 ; MOSI=1 (bit12=1: output active) + 0xE001, + // 21: nop side 1 ; SCK high + 0xB042, + // 22: set y, 15 side 0 ; Loop counter: 16 sample bits + 0xE04F, + // 23: out pins, 1 side 0 ; Data bit → MOSI; SCK low (bitloopB) + 0x6001, + // 24: jmp y--, 23 side 1 ; SCK high, loop back + 0x1097, + // 25: set pins, 4 side 0 ; CS high — DAC B latches + 0xE004, +}; + +// Clocks per sample: 2 (pull+mov) + 42 (chanA) + 42 (chanB) = 86 +// Per channel: 8(4 cmd bits × 2 clks) + 1(set y) + 32(16 bits × 2 clks) + 1(cs high) = 42 +#define MCP4822_CLOCKS_PER_SAMPLE 86 + +// MCP4822 gain bit (bit 13) position in the PIO program: +// Instruction 6 = channel A gain bit +// Instruction 18 = channel B gain bit +// 1x gain: set pins, 1 (0xE001) — bit 13 = 1 +// 2x gain: set pins, 0 (0xE000) — bit 13 = 0 +#define MCP4822_PIO_GAIN_INSTR_A 6 +#define MCP4822_PIO_GAIN_INSTR_B 18 +#define MCP4822_PIO_GAIN_1X 0xE001 // set pins, 1 +#define MCP4822_PIO_GAIN_2X 0xE000 // set pins, 0 + +void mcp4822_reset(void) { +} + +// Caller validates that pins are free. +void common_hal_mcp4822_mcp4822_construct(mcp4822_mcp4822_obj_t *self, + const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *cs, uint8_t gain) { + + // The SET pin group spans from MOSI to CS. + // MOSI must have a lower GPIO number than CS, gap at most 4. + if (cs->number <= mosi->number || (cs->number - mosi->number) > 4) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q and %q"), MP_QSTR_CS, MP_QSTR_MOSI); + } + + uint8_t set_count = cs->number - mosi->number + 1; + + // Build a mutable copy of the PIO program and patch the gain bit + uint16_t program[MP_ARRAY_SIZE(mcp4822_pio_program)]; + memcpy(program, mcp4822_pio_program, sizeof(mcp4822_pio_program)); + uint16_t gain_instr = (gain == 2) ? MCP4822_PIO_GAIN_2X : MCP4822_PIO_GAIN_1X; + program[MCP4822_PIO_GAIN_INSTR_A] = gain_instr; + program[MCP4822_PIO_GAIN_INSTR_B] = gain_instr; + + // Initial SET pin state: CS high (bit at CS position), others low + uint32_t cs_bit_position = cs->number - mosi->number; + pio_pinmask32_t initial_set_state = PIO_PINMASK32_FROM_VALUE(1u << cs_bit_position); + pio_pinmask32_t initial_set_dir = PIO_PINMASK32_FROM_VALUE((1u << set_count) - 1); + + common_hal_rp2pio_statemachine_construct( + &self->state_machine, + program, MP_ARRAY_SIZE(mcp4822_pio_program), + 44100 * MCP4822_CLOCKS_PER_SAMPLE, // Initial frequency; play() adjusts + NULL, 0, // No init program + NULL, 0, // No may_exec + mosi, 1, // OUT: MOSI, 1 pin + PIO_PINMASK32_NONE, PIO_PINMASK32_ALL, // OUT state=low, dir=output + NULL, 0, // IN: none + PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // IN pulls: none + mosi, set_count, // SET: MOSI..CS + initial_set_state, initial_set_dir, // SET state (CS high), dir=output + clock, 1, false, // SIDE-SET: SCK, 1 pin, not pindirs + PIO_PINMASK32_NONE, // SIDE-SET state: SCK low + PIO_PINMASK32_FROM_VALUE(0x1), // SIDE-SET dir: output + false, // No sideset enable + NULL, PULL_NONE, // No jump pin + PIO_PINMASK_NONE, // No wait GPIO + true, // Exclusive pin use + false, 32, false, // OUT shift: no autopull, 32-bit, shift left + false, // Don't wait for txstall + false, 32, false, // IN shift (unused) + false, // Not user-interruptible + 0, -1, // Wrap: whole program + PIO_ANY_OFFSET, + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, + PIO_MOV_N_DEFAULT + ); + + self->playing = false; + audio_dma_init(&self->dma); +} + +bool common_hal_mcp4822_mcp4822_deinited(mcp4822_mcp4822_obj_t *self) { + return common_hal_rp2pio_statemachine_deinited(&self->state_machine); +} + +void common_hal_mcp4822_mcp4822_deinit(mcp4822_mcp4822_obj_t *self) { + if (common_hal_mcp4822_mcp4822_deinited(self)) { + return; + } + if (common_hal_mcp4822_mcp4822_get_playing(self)) { + common_hal_mcp4822_mcp4822_stop(self); + } + common_hal_rp2pio_statemachine_deinit(&self->state_machine); + audio_dma_deinit(&self->dma); +} + +void common_hal_mcp4822_mcp4822_play(mcp4822_mcp4822_obj_t *self, + mp_obj_t sample, bool loop) { + + if (common_hal_mcp4822_mcp4822_get_playing(self)) { + common_hal_mcp4822_mcp4822_stop(self); + } + + uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample); + if (bits_per_sample < 16) { + bits_per_sample = 16; + } + + uint32_t sample_rate = audiosample_get_sample_rate(sample); + uint8_t channel_count = audiosample_get_channel_count(sample); + if (channel_count > 2) { + mp_raise_ValueError(MP_ERROR_TEXT("Too many channels in sample.")); + } + + // PIO clock = sample_rate × clocks_per_sample + common_hal_rp2pio_statemachine_set_frequency( + &self->state_machine, + (uint32_t)sample_rate * MCP4822_CLOCKS_PER_SAMPLE); + common_hal_rp2pio_statemachine_restart(&self->state_machine); + + audio_dma_result result = audio_dma_setup_playback( + &self->dma, + sample, + loop, + false, // single_channel_output + 0, // audio_channel + false, // output_signed = false (unsigned for MCP4822) + bits_per_sample, // output_resolution + (uint32_t)&self->state_machine.pio->txf[self->state_machine.state_machine], + self->state_machine.tx_dreq, + false); // swap_channel + + if (result == AUDIO_DMA_DMA_BUSY) { + common_hal_mcp4822_mcp4822_stop(self); + mp_raise_RuntimeError(MP_ERROR_TEXT("No DMA channel found")); + } else if (result == AUDIO_DMA_MEMORY_ERROR) { + common_hal_mcp4822_mcp4822_stop(self); + mp_raise_RuntimeError(MP_ERROR_TEXT("Unable to allocate buffers for signed conversion")); + } else if (result == AUDIO_DMA_SOURCE_ERROR) { + common_hal_mcp4822_mcp4822_stop(self); + mp_raise_RuntimeError(MP_ERROR_TEXT("Audio source error")); + } + + self->playing = true; +} + +void common_hal_mcp4822_mcp4822_pause(mcp4822_mcp4822_obj_t *self) { + audio_dma_pause(&self->dma); +} + +void common_hal_mcp4822_mcp4822_resume(mcp4822_mcp4822_obj_t *self) { + audio_dma_resume(&self->dma); +} + +bool common_hal_mcp4822_mcp4822_get_paused(mcp4822_mcp4822_obj_t *self) { + return audio_dma_get_paused(&self->dma); +} + +void common_hal_mcp4822_mcp4822_stop(mcp4822_mcp4822_obj_t *self) { + audio_dma_stop(&self->dma); + common_hal_rp2pio_statemachine_stop(&self->state_machine); + self->playing = false; +} + +bool common_hal_mcp4822_mcp4822_get_playing(mcp4822_mcp4822_obj_t *self) { + bool playing = audio_dma_get_playing(&self->dma); + if (!playing && self->playing) { + common_hal_mcp4822_mcp4822_stop(self); + } + return playing; +} diff --git a/ports/raspberrypi/common-hal/mcp4822/MCP4822.h b/ports/raspberrypi/common-hal/mcp4822/MCP4822.h new file mode 100644 index 00000000000..53c8e862b63 --- /dev/null +++ b/ports/raspberrypi/common-hal/mcp4822/MCP4822.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/rp2pio/StateMachine.h" + +#include "audio_dma.h" +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + rp2pio_statemachine_obj_t state_machine; + audio_dma_t dma; + bool playing; +} mcp4822_mcp4822_obj_t; + +void mcp4822_reset(void); diff --git a/ports/raspberrypi/common-hal/mcp4822/__init__.c b/ports/raspberrypi/common-hal/mcp4822/__init__.c new file mode 100644 index 00000000000..48981fc88a7 --- /dev/null +++ b/ports/raspberrypi/common-hal/mcp4822/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +// No module-level init needed. diff --git a/ports/raspberrypi/common-hal/memorymap/AddressRange.c b/ports/raspberrypi/common-hal/memorymap/AddressRange.c index 0796a3b860b..a5e860cb40c 100644 --- a/ports/raspberrypi/common-hal/memorymap/AddressRange.c +++ b/ports/raspberrypi/common-hal/memorymap/AddressRange.c @@ -14,7 +14,7 @@ #include "hardware/regs/addressmap.h" // RP2 address map ranges, must be arranged in order by ascending start address -#ifdef PICO_RP2040 +#if PICO_RP2040 addressmap_rp2_range_t rp2_ranges[] = { {(uint8_t *)ROM_BASE, 0x00004000, ROM}, // boot ROM {(uint8_t *)XIP_BASE, 0x00100000, XIP}, // XIP normal cache operation @@ -36,7 +36,7 @@ addressmap_rp2_range_t rp2_ranges[] = { {(uint8_t *)PPB_BASE, 0x00004000, IO} // PPB registers }; #endif -#ifdef PICO_RP2350 +#if PICO_RP2350 addressmap_rp2_range_t rp2_ranges[] = { {(uint8_t *)ROM_BASE, 0x00004000, ROM}, // boot ROM {(uint8_t *)XIP_BASE, 0x00100000, XIP}, // XIP normal cache operation diff --git a/ports/raspberrypi/common-hal/microcontroller/Processor.c b/ports/raspberrypi/common-hal/microcontroller/Processor.c index a3ea890d9af..5a4e7071544 100644 --- a/ports/raspberrypi/common-hal/microcontroller/Processor.c +++ b/ports/raspberrypi/common-hal/microcontroller/Processor.c @@ -20,11 +20,11 @@ #include "hardware/vreg.h" #include "hardware/watchdog.h" -#ifdef PICO_RP2040 +#if PICO_RP2040 #include "hardware/regs/vreg_and_chip_reset.h" #include "hardware/structs/vreg_and_chip_reset.h" #endif -#ifdef PICO_RP2350 +#if PICO_RP2350 #include "hardware/regs/powman.h" #include "hardware/structs/powman.h" #endif @@ -80,7 +80,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { mcu_reset_reason_t reason = RESET_REASON_UNKNOWN; - #ifdef PICO_RP2040 + #if PICO_RP2040 uint32_t chip_reset_reg = vreg_and_chip_reset_hw->chip_reset; if (chip_reset_reg & VREG_AND_CHIP_RESET_CHIP_RESET_HAD_PSM_RESTART_BITS) { @@ -96,7 +96,7 @@ mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { reason = RESET_REASON_POWER_ON; } #endif - #ifdef PICO_RP2350 + #if PICO_RP2350 uint32_t chip_reset_reg = powman_hw->chip_reset; if (chip_reset_reg & POWMAN_CHIP_RESET_HAD_RESCUE_BITS) { diff --git a/ports/raspberrypi/common-hal/microcontroller/__init__.c b/ports/raspberrypi/common-hal/microcontroller/__init__.c index e287e551710..3d8bd381f5e 100644 --- a/ports/raspberrypi/common-hal/microcontroller/__init__.c +++ b/ports/raspberrypi/common-hal/microcontroller/__init__.c @@ -25,12 +25,28 @@ #include "hardware/watchdog.h" #include "hardware/irq.h" +// DMA interrupt (DMA_IRQ_n) allocation for this port: +// +// DMA_IRQ_0 Shared. audiocore (audio_dma.c) and rp2pio (StateMachine.c) each +// register a shared handler with irq_add_shared_handler() and +// service only their own DMA channels. Any new code that needs a +// DMA completion interrupt should do the same: add a shared handler +// on DMA_IRQ_0, check dma_hw->ints0, and acknowledge only its own +// channels. Runs at the default IRQ priority and is masked during +// flash writes (see common_hal_mcu_disable_interrupts below). +// DMA_IRQ_1 Exclusive to picodvi (Framebuffer_RP2040.c / Framebuffer_RP2350.c), +// registered with irq_set_exclusive_handler() at the highest +// priority. On RP2350 it is deliberately kept enabled during flash +// writes via BASEPRI (see below) so the display keeps refreshing. +// DMA_IRQ_2 RP2350 only; currently unused / free. +// DMA_IRQ_3 RP2350 only; currently unused / free. + void common_hal_mcu_delay_us(uint32_t delay) { mp_hal_delay_us(delay); } volatile uint32_t nesting_count = 0; -#ifdef PICO_RP2040 +#if PICO_RP2040 void common_hal_mcu_disable_interrupts(void) { // We don't use save_and_disable_interrupts() from the sdk because we don't want to worry about PRIMASK. // This is what we do on the SAMD21 via CMSIS. diff --git a/ports/raspberrypi/common-hal/picodvi/Framebuffer.h b/ports/raspberrypi/common-hal/picodvi/Framebuffer.h index 50288578590..82c0b189b89 100644 --- a/ports/raspberrypi/common-hal/picodvi/Framebuffer.h +++ b/ports/raspberrypi/common-hal/picodvi/Framebuffer.h @@ -6,7 +6,7 @@ #pragma once -#ifdef PICO_RP2040 +#if PICO_RP2040 #include "Framebuffer_RP2040.h" #else #include "Framebuffer_RP2350.h" diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c index 71050677f22..8e1ea26ab0d 100644 --- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c +++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -68,14 +68,69 @@ static void rp2pio_statemachine_set_pull(pio_pinmask_t pull_pin_up, pio_pinmask_ } } +// audio_dma and rp2pio cooperate on DMA_IRQ_0 using the SDK's shared interrupt +// handlers. We add our handler when we enable our first channel and remove it +// when our last channel is disabled. See the DMA IRQ allocation notes in +// common-hal/microcontroller/__init__.c. + +// Shared DMA_IRQ_0 handler for rp2pio background reads and writes. It +// acknowledges and services only its own channels, leaving any other channels' +// interrupts (e.g. audio) for the other shared handlers to acknowledge. +static void __not_in_flash_func(rp2pio_dma_irq_handler)(void) { + for (size_t i = 0; i < NUM_DMA_CHANNELS; i++) { + uint32_t mask = 1 << i; + if ((dma_hw->ints0 & mask) == 0) { + continue; + } + rp2pio_statemachine_obj_t *read = MP_STATE_PORT(background_pio_read)[i]; + rp2pio_statemachine_obj_t *write = MP_STATE_PORT(background_pio_write)[i]; + if (read == NULL && write == NULL) { + // Not one of our channels; leave it for another shared handler. + continue; + } + // Acknowledge the interrupt early; see the comment in audio_dma.c. + dma_hw->ints0 = mask; + if (read != NULL) { + rp2pio_statemachine_dma_complete_read(read, i); + } + if (write != NULL) { + rp2pio_statemachine_dma_complete_write(write, i); + } + } +} + +// Channels (bitmask) rp2pio currently has enabled on DMA_IRQ_0. Used to decide +// when to add/remove our shared interrupt handler. +static uint32_t rp2pio_dma_irq0_channel_mask = 0; + +static void rp2pio_dma_enable_irq(uint channel) { + // Clear any latent interrupt so that we don't immediately re-trigger. + dma_hw->ints0 = 1u << channel; + if (rp2pio_dma_irq0_channel_mask == 0) { + irq_add_shared_handler(DMA_IRQ_0, rp2pio_dma_irq_handler, + PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); + } + rp2pio_dma_irq0_channel_mask |= 1u << channel; + dma_irqn_set_channel_enabled(0, channel, true); + irq_set_enabled(DMA_IRQ_0, true); +} + +static void rp2pio_dma_disable_irq(uint channel) { + dma_irqn_set_channel_enabled(0, channel, false); + rp2pio_dma_irq0_channel_mask &= ~(1u << channel); + if (rp2pio_dma_irq0_channel_mask == 0) { + irq_remove_handler(DMA_IRQ_0, rp2pio_dma_irq_handler); + } + // Turn off the IRQ line entirely once no one (audio or rp2pio) needs it. + if (dma_hw->inte0 == 0) { + irq_set_enabled(DMA_IRQ_0, false); + } +} + static void rp2pio_statemachine_clear_dma_write(int pio_index, int sm) { if (SM_DMA_ALLOCATED_WRITE(pio_index, sm)) { int channel_write = SM_DMA_GET_CHANNEL_WRITE(pio_index, sm); - uint32_t channel_mask_write = 1u << channel_write; - dma_hw->inte0 &= ~channel_mask_write; - if (!dma_hw->inte0) { - irq_set_mask_enabled(1 << DMA_IRQ_0, false); - } + rp2pio_dma_disable_irq(channel_write); MP_STATE_PORT(background_pio_write)[channel_write] = NULL; dma_channel_abort(channel_write); dma_channel_unclaim(channel_write); @@ -86,11 +141,7 @@ static void rp2pio_statemachine_clear_dma_write(int pio_index, int sm) { static void rp2pio_statemachine_clear_dma_read(int pio_index, int sm) { if (SM_DMA_ALLOCATED_READ(pio_index, sm)) { int channel_read = SM_DMA_GET_CHANNEL_READ(pio_index, sm); - uint32_t channel_mask_read = 1u << channel_read; - dma_hw->inte0 &= ~channel_mask_read; - if (!dma_hw->inte0) { - irq_set_mask_enabled(1 << DMA_IRQ_0, false); - } + rp2pio_dma_disable_irq(channel_read); MP_STATE_PORT(background_pio_read)[channel_read] = NULL; dma_channel_abort(channel_read); dma_channel_unclaim(channel_read); @@ -1274,12 +1325,8 @@ bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t * common_hal_mcu_disable_interrupts(); - // Acknowledge any previous pending interrupt - dma_hw->ints0 |= 1u << channel_write; MP_STATE_PORT(background_pio_write)[channel_write] = self; - dma_hw->inte0 |= 1u << channel_write; - - irq_set_mask_enabled(1 << DMA_IRQ_0, true); + rp2pio_dma_enable_irq(channel_write); dma_start_channel_mask(1u << channel_write); common_hal_mcu_enable_interrupts(); @@ -1438,11 +1485,8 @@ bool common_hal_rp2pio_statemachine_background_read(rp2pio_statemachine_obj_t *s false); common_hal_mcu_disable_interrupts(); - // Acknowledge any previous pending interrupt - dma_hw->ints0 |= 1u << channel_read; MP_STATE_PORT(background_pio_read)[channel_read] = self; - dma_hw->inte0 |= 1u << channel_read; - irq_set_mask_enabled(1 << DMA_IRQ_0, true); + rp2pio_dma_enable_irq(channel_read); dma_start_channel_mask((1u << channel_read)); common_hal_mcu_enable_interrupts(); @@ -1482,6 +1526,36 @@ bool common_hal_rp2pio_statemachine_stop_background_read(rp2pio_statemachine_obj return true; } +void common_hal_rp2pio_statemachine_set_read_buffers_raw(rp2pio_statemachine_obj_t *self, + void *once, size_t once_len, + void *loop, size_t loop_len, + void *loop2, size_t loop2_len) { + memset(&self->once_read_buf_info, 0, sizeof(self->once_read_buf_info)); + memset(&self->loop_read_buf_info, 0, sizeof(self->loop_read_buf_info)); + memset(&self->loop2_read_buf_info, 0, sizeof(self->loop2_read_buf_info)); + if (once && once_len) { + self->once_read_buf_info.info.buf = once; + self->once_read_buf_info.info.len = once_len; + } + if (loop && loop_len) { + self->loop_read_buf_info.info.buf = loop; + self->loop_read_buf_info.info.len = loop_len; + } + if (loop2 && loop2_len) { + self->loop2_read_buf_info.info.buf = loop2; + self->loop2_read_buf_info.info.len = loop2_len; + } +} + +int common_hal_rp2pio_statemachine_get_read_dma_channel(rp2pio_statemachine_obj_t *self) { + uint8_t pio_index = pio_get_index(self->pio); + uint8_t sm = self->state_machine; + if (!SM_DMA_ALLOCATED_READ(pio_index, sm)) { + return -1; + } + return SM_DMA_GET_CHANNEL_READ(pio_index, sm); +} + bool common_hal_rp2pio_statemachine_get_reading(rp2pio_statemachine_obj_t *self) { return !self->dma_completed_read; } diff --git a/ports/raspberrypi/common-hal/usb_host/Port.c b/ports/raspberrypi/common-hal/usb_host/Port.c index b8a49725030..36f255df021 100644 --- a/ports/raspberrypi/common-hal/usb_host/Port.c +++ b/ports/raspberrypi/common-hal/usb_host/Port.c @@ -13,10 +13,10 @@ #include "pico/time.h" #include "hardware/structs/mpu.h" -#ifdef PICO_RP2040 +#if PICO_RP2040 #include "RP2040.h" // (cmsis) #endif -#ifdef PICO_RP2350 +#if PICO_RP2350 #include "RP2350.h" // (cmsis) #endif #include "hardware/dma.h" diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 3c22c3548d1..73e7794ecc2 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -48,7 +48,7 @@ static inline void nw_put_le32(uint8_t *buf, uint32_t x) { buf[3] = x >> 24; } -NORETURN static void ro_attribute(qstr attr) { +MP_NORETURN static void ro_attribute(qstr attr) { mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q is read-only for this board"), attr); } diff --git a/ports/raspberrypi/common-hal/wifi/__init__.c b/ports/raspberrypi/common-hal/wifi/__init__.c index 5fbe3fe58d1..84dba581fbf 100644 --- a/ports/raspberrypi/common-hal/wifi/__init__.c +++ b/ports/raspberrypi/common-hal/wifi/__init__.c @@ -15,6 +15,10 @@ #include "py/mpstate.h" #include "py/runtime.h" +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" +#endif + wifi_radio_obj_t common_hal_wifi_radio_obj; #include "supervisor/port.h" @@ -45,6 +49,15 @@ void common_hal_wifi_init(bool user_initiated) { // set station mode to avoid the default SoftAP common_hal_wifi_radio_start_station(self); + + #if CIRCUITPY_SETTINGS_TOML + // Must be set after station starts. + char hostname[sizeof(self->hostname)]; + if (settings_get_str("CIRCUITPY_WIFI_HOSTNAME", hostname, sizeof(hostname)) == SETTINGS_OK) { + common_hal_wifi_radio_set_hostname(self, hostname); + } + #endif + // start wifi common_hal_wifi_radio_set_enabled(self, true); } diff --git a/ports/raspberrypi/common-hal/wifi/__init__.h b/ports/raspberrypi/common-hal/wifi/__init__.h index 73988e84379..4005c48a3cd 100644 --- a/ports/raspberrypi/common-hal/wifi/__init__.h +++ b/ports/raspberrypi/common-hal/wifi/__init__.h @@ -11,7 +11,7 @@ #include "lwip/ip_addr.h" void wifi_reset(void); -NORETURN void raise_cyw_error(int err); +MP_NORETURN void raise_cyw_error(int err); #define CHECK_CYW_RESULT(x) do { int res = (x); if (res != 0) raise_cyw_error(res); } while (0) void ipaddress_ipaddress_to_lwip(mp_obj_t ip_address, ip_addr_t *lwip_ip_address); diff --git a/ports/raspberrypi/lib/Pico-PIO-USB b/ports/raspberrypi/lib/Pico-PIO-USB index 675543bcc9b..dc9193fed51 160000 --- a/ports/raspberrypi/lib/Pico-PIO-USB +++ b/ports/raspberrypi/lib/Pico-PIO-USB @@ -1 +1 @@ -Subproject commit 675543bcc9baa8170f868ab7ba316d418dbcf41f +Subproject commit dc9193fed510da5f81f4db520e98282f61db9054 diff --git a/ports/raspberrypi/mpconfigport.h b/ports/raspberrypi/mpconfigport.h index 3eb576de39e..d0802b25f00 100644 --- a/ports/raspberrypi/mpconfigport.h +++ b/ports/raspberrypi/mpconfigport.h @@ -8,11 +8,11 @@ #include "hardware/platform_defs.h" -#ifdef PICO_RP2040 +#if PICO_RP2040 #define MICROPY_PY_SYS_PLATFORM "RP2040" #endif -#ifdef PICO_RP2350 +#if PICO_RP2350 #define MICROPY_PY_SYS_PLATFORM "RP2350" // PSRAM can require more stack space for GC. @@ -36,10 +36,8 @@ #define CIRCUITPY_PROCESSOR_COUNT (2) -// For many RP2 boards BOOTSEL is not connected to a GPIO pin. -#ifndef CIRCUITPY_BOOT_BUTTON +// For RP2 boards we use a custom way to read BOOTSEL #define CIRCUITPY_BOOT_BUTTON_NO_GPIO (1) -#endif #if CIRCUITPY_USB_HOST #define CIRCUITPY_USB_HOST_INSTANCE 1 diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index 8401c5d7545..b4d1ed99696 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -11,11 +11,14 @@ CIRCUITPY_FLOPPYIO ?= 1 CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_FULL_BUILD ?= 1 CIRCUITPY_AUDIOMP3 ?= 1 +CIRCUITPY_AUDIOSPEED ?= 1 +CIRCUITPY_AUDIOEFFECTS ?= 1 CIRCUITPY_BITOPS ?= 1 CIRCUITPY_HASHLIB ?= 1 CIRCUITPY_HASHLIB_MBEDTLS ?= 1 CIRCUITPY_IMAGECAPTURE ?= 1 CIRCUITPY_MAX3421E ?= 0 +CIRCUITPY_MCP4822 ?= 0 CIRCUITPY_MEMORYMAP ?= 1 CIRCUITPY_PWMIO ?= 1 CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_DISPLAYIO) @@ -24,6 +27,7 @@ CIRCUITPY_ROTARYIO_SOFTENCODER = 1 CIRCUITPY_SYNTHIO_MAX_CHANNELS = 24 CIRCUITPY_USB_HOST ?= 1 CIRCUITPY_USB_VIDEO ?= 1 +CIRCUITPY_USB_AUDIO ?= 1 # Things that need to be implemented. CIRCUITPY_FREQUENCYIO = 0 @@ -42,6 +46,7 @@ CIRCUITPY_ANALOGBUFIO = 1 # Audio via PWM CIRCUITPY_AUDIOIO = 0 CIRCUITPY_AUDIOBUSIO ?= 1 +CIRCUITPY_AUDIOI2SIN ?= $(CIRCUITPY_AUDIOBUSIO) CIRCUITPY_AUDIOCORE ?= 1 CIRCUITPY_AUDIOPWMIO ?= 1 diff --git a/ports/raspberrypi/supervisor/internal_flash.c b/ports/raspberrypi/supervisor/internal_flash.c index 9d5e13348aa..07b15564c60 100644 --- a/ports/raspberrypi/supervisor/internal_flash.c +++ b/ports/raspberrypi/supervisor/internal_flash.c @@ -23,7 +23,7 @@ #include "supervisor/flash.h" #include "supervisor/usb.h" -#ifdef PICO_RP2350 +#if PICO_RP2350 #include "hardware/structs/qmi.h" #endif #include "hardware/structs/sio.h" diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c index 5cfbdfa66a3..01940acc079 100644 --- a/ports/raspberrypi/supervisor/port.c +++ b/ports/raspberrypi/supervisor/port.c @@ -53,7 +53,7 @@ #include "pico/bootrom.h" #include "hardware/watchdog.h" -#ifdef PICO_RP2350 +#if PICO_RP2350 #include "RP2350.h" // CMSIS #endif @@ -336,10 +336,10 @@ safe_mode_t port_init(void) { // Load from the XIP memory space that doesn't cache. That way we don't // evict anything else. The code we're loading is linked to the RAM address // anyway. - #ifdef PICO_RP2040 + #if PICO_RP2040 size_t nocache = 0x03000000; #endif - #ifdef PICO_RP2350 + #if PICO_RP2350 size_t nocache = 0x04000000; #endif @@ -547,7 +547,7 @@ void port_interrupt_after_ticks(uint32_t ticks) { } void port_idle_until_interrupt(void) { - #ifdef PICO_RP2040 + #if PICO_RP2040 common_hal_mcu_disable_interrupts(); #if CIRCUITPY_USB_HOST if (!background_callback_pending() && !tud_task_event_ready() && !tuh_task_event_ready() && !_woken_up) { @@ -588,7 +588,7 @@ void port_idle_until_interrupt(void) { /** * \brief Default interrupt handler for unused IRQs. */ -extern NORETURN void isr_hardfault(void); // provide a prototype to avoid a missing-prototypes diagnostic +extern MP_NORETURN void isr_hardfault(void); // provide a prototype to avoid a missing-prototypes diagnostic __attribute__((used)) void __not_in_flash_func(isr_hardfault)(void) { // Only safe mode from core 0 which is running CircuitPython. Core 1 faulting // should not be fatal to CP. (Fingers crossed.) @@ -600,7 +600,7 @@ __attribute__((used)) void __not_in_flash_func(isr_hardfault)(void) { } } -void port_yield(void) { +void port_task_yield(void) { #if CIRCUITPY_CYW43 cyw43_arch_poll(); #endif @@ -624,7 +624,7 @@ bool __no_inline_not_in_flash_func(port_boot_button_pressed)(void) { // pressed, return is delayed until the button is released and // a delay has passed in order to debounce the button. const uint32_t CS_PIN_INDEX = 1; - #if defined(PICO_RP2040) + #if PICO_RP2040 const uint32_t CS_BIT = 1u << 1; #else const uint32_t CS_BIT = SIO_GPIO_HI_IN_QSPI_CSN_BITS; diff --git a/ports/renode/supervisor/port.c b/ports/renode/supervisor/port.c index d12ebd2efdd..a40e222d34d 100644 --- a/ports/renode/supervisor/port.c +++ b/ports/renode/supervisor/port.c @@ -210,7 +210,7 @@ __attribute__((used)) void HardFault_Handler(void) { } } -void port_yield(void) { +void port_task_yield(void) { } void port_boot_info(void) { diff --git a/ports/silabs/common-hal/_bleio/Characteristic.c b/ports/silabs/common-hal/_bleio/Characteristic.c index a707b0ef1ac..9ccc6ad9c36 100644 --- a/ports/silabs/common-hal/_bleio/Characteristic.c +++ b/ports/silabs/common-hal/_bleio/Characteristic.c @@ -395,7 +395,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, const uint16_t conn_handle = bleio_connection_get_conn_handle( self->service->connection); - common_hal_bleio_check_connected(conn_handle); + bleio_check_connected(conn_handle); notify = 1; indicate = 0; if (notify) { diff --git a/ports/silabs/common-hal/_bleio/Connection.h b/ports/silabs/common-hal/_bleio/Connection.h index 56872024c93..148caecba11 100644 --- a/ports/silabs/common-hal/_bleio/Connection.h +++ b/ports/silabs/common-hal/_bleio/Connection.h @@ -85,6 +85,7 @@ typedef struct void bleio_connection_clear(bleio_connection_internal_t *self); +void bleio_check_connected(uint16_t conn_handle); uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); mp_obj_t bleio_connection_new_from_internal( diff --git a/ports/silabs/common-hal/_bleio/__init__.c b/ports/silabs/common-hal/_bleio/__init__.c index c6ae8a0b606..4c5ce1f045d 100644 --- a/ports/silabs/common-hal/_bleio/__init__.c +++ b/ports/silabs/common-hal/_bleio/__init__.c @@ -102,7 +102,7 @@ void check_ble_error(int error_code) { } } -void common_hal_bleio_check_connected(uint16_t conn_handle) { +void bleio_check_connected(uint16_t conn_handle) { if (conn_handle == BLEIO_HANDLE_INVALID) { mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); } diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 3d6c4466882..1be8f8dc10d 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -135,7 +135,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_set_wakeup_reason(STM_WAKEUP_UNDEF); alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep(); diff --git a/ports/stm/common-hal/analogio/AnalogOut.h b/ports/stm/common-hal/analogio/AnalogOut.h index 6a8fc2720bf..33c8abc21f8 100644 --- a/ports/stm/common-hal/analogio/AnalogOut.h +++ b/ports/stm/common-hal/analogio/AnalogOut.h @@ -28,3 +28,9 @@ typedef struct { } analogio_analogout_obj_t; void analogout_reset(void); + +// Shared DAC peripheral handle (defined in AnalogOut.c). +// AudioOut reuses this handle for DMA-triggered DAC operation on channel 1. +#if HAS_DAC +extern DAC_HandleTypeDef handle; +#endif diff --git a/ports/stm/common-hal/audioio/AudioOut.c b/ports/stm/common-hal/audioio/AudioOut.c new file mode 100644 index 00000000000..e5dd620521c --- /dev/null +++ b/ports/stm/common-hal/audioio/AudioOut.c @@ -0,0 +1,782 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// DAC-based audio output for STM32F405 / STM32F407. +// +// Architecture: +// TIM6 (basic timer) generates an update event at the sample rate. +// DAC_CHANNEL_1 (PA04) is configured with DAC_TRIGGER_T6_TRGO so each +// TIM6 update latches the next sample from the DMA FIFO. +// DMA1 Stream5 Channel7 operates in circular mode, feeding 16-bit samples +// from a double-buffer. Stereo additionally drives DAC_CHANNEL_2 (PA05) +// via DMA1 Stream6 Channel7, sharing the same TIM6 trigger. +// The DMA half-complete and complete callbacks queue a background_callback +// to refill the idle half from the audio sample source. +// +// The shared DAC handle (declared in AnalogOut.c) is reused here so both +// modules share state consistently and avoid double-init conflicts. Pin +// claims (common_hal_mcu_pin_claim) act as the inter-module mutex: a second +// AudioOut, or an AnalogOut on the same pin, fails at the claim step. + +#include + +#include "py/mperrno.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "common-hal/audioio/AudioOut.h" +#include "shared-bindings/audioio/AudioOut.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/audiocore/__init__.h" +#include "supervisor/background_callback.h" + +#include STM32_HAL_H + +// Shared DAC handle declared in common-hal/analogio/AnalogOut.h. +// AudioOut reconfigures channel 1 (and 2 for stereo) for DMA-triggered +// operation and restores the no-trigger config on deinit so AnalogOut can +// resume use of the channel afterwards. +#include "common-hal/analogio/AnalogOut.h" + +// Highest sample rate accepted by play(). 1 MHz mirrors atmel-samd's SAMD51 +// limit and is comfortably above any reasonable audio rate; the real hardware +// ceiling is TIM6_CLK / 2 (~42 MHz on F405) but rates that high would just +// underrun the DMA refill path. +#define AUDIOOUT_MAX_SAMPLE_RATE 1000000u + +// TIM6 handle: only one instance ever active, so file-scope is fine. +static TIM_HandleTypeDef tim6_handle; + +// Pointer to the currently active AudioOut object, used by IRQ handlers. +// Pin claims prevent two instances from existing simultaneously, but this +// pointer is also used to early-out IRQs after stop(). +static audioio_audioout_obj_t *active_audioout = NULL; + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +// Return the TIM6 input clock frequency in Hz. +// TIM6 sits on APB1. The clock is doubled when the APB1 prescaler != 1 +// (same logic as stm_peripherals_timer_get_source_freq in timers.c but +// applied directly to APB1 since TIM6 is not in mcu_tim_banks[]). +static uint32_t get_tim6_freq(void) { + uint32_t apb1 = HAL_RCC_GetPCLK1Freq(); + uint32_t ppre1 = (RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos; + #if defined(RCC_DCKCFGR_TIMPRE) + uint32_t timpre = RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE; + if (timpre == 0) { + return (ppre1 >= 0b100) ? apb1 * 2 : apb1; + } else { + return (ppre1 > 0b101) ? apb1 * 4 : HAL_RCC_GetHCLKFreq(); + } + #else + return (ppre1 >= 0b100) ? apb1 * 2 : apb1; + #endif +} + +// Gently ramp the given DAC channel output from from_12 to to_12 (both 12-bit, +// 0-4095) to avoid audible clicks. 64 steps × 100 µs/step = ~6.4 ms total; +// shrink the step count and clicks reappear on the F405 output stage. +static void dac_ramp_channel(uint32_t channel, uint32_t from_12, uint32_t to_12) { + if (from_12 == to_12) { + return; + } + int32_t delta = (int32_t)to_12 - (int32_t)from_12; + int32_t step = delta / 64; + if (step == 0) { + step = (delta > 0) ? 1 : -1; + } + int32_t v = (int32_t)from_12; + while (true) { + v += step; + if (step > 0 && v >= (int32_t)to_12) { + v = (int32_t)to_12; + } else if (step < 0 && v <= (int32_t)to_12) { + v = (int32_t)to_12; + } + HAL_DAC_SetValue(&handle, channel, DAC_ALIGN_12B_R, (uint16_t)v); + HAL_DAC_Start(&handle, channel); + mp_hal_delay_us(100); + if (v == (int32_t)to_12) { + break; + } + } +} + +static inline void dac_ramp(uint32_t from_12, uint32_t to_12) { + dac_ramp_channel(DAC_CHANNEL_1, from_12, to_12); +} + +// Convert a buffer of audio samples into 12-bit unsigned DAC values and write +// them into dest[]. Returns the number of DAC samples written; the caller is +// responsible for padding any remaining dest entries with the quiescent value. +// +// NOTE: ports/espressif/common-hal/audioio/AudioOut.c implements the same +// idea with a CONV_MATCH lookup table dispatching to per-format helpers in +// shared-module/audiocore — a more general-purpose pattern. If a future +// refactor lifts a 12-bit DAC variant into shared-module/audiocore, both +// this driver and any other ARM-DAC port could share it. +// +// src - raw sample bytes from audiosample_get_buffer +// src_len - byte length of src +// dest - output array of 12-bit DAC values (uint16_t) +// dest_count - capacity of dest in samples +// bytes_per_sample - 1 or 2 +// samples_signed - true if source samples are signed +// channel_count - 1 (mono) or 2 (stereo) +// channel_offset - 0 for left/mono, 1 for right channel of a stereo stream +static uint32_t convert_to_dac12( + const uint8_t *src, uint32_t src_len, + uint16_t *dest, uint32_t dest_count, + uint8_t bytes_per_sample, bool samples_signed, + uint8_t channel_count, uint8_t channel_offset) { + + // src_stride: bytes between consecutive samples of the same channel + uint32_t src_stride = (uint32_t)bytes_per_sample * channel_count; + // src_offset: byte offset to the desired channel within each frame + uint32_t src_offset = (uint32_t)bytes_per_sample * channel_offset; + uint32_t src_frames = src_len / src_stride; + uint32_t frames = (src_frames < dest_count) ? src_frames : dest_count; + + if (bytes_per_sample == 1) { + for (uint32_t i = 0; i < frames; i++) { + uint8_t u8 = src[i * src_stride + src_offset]; + int32_t s = samples_signed + ? (int32_t)(int8_t)u8 + : (int32_t)u8 - 128; + dest[i] = (uint16_t)((s + 128) & 0xFF) << 4; + } + } else { + for (uint32_t i = 0; i < frames; i++) { + uint16_t u16; + memcpy(&u16, src + i * src_stride + src_offset, 2); + int32_t s = samples_signed + ? (int32_t)(int16_t)u16 + : (int32_t)u16 - 0x8000; + dest[i] = (uint16_t)((s + 0x8000) & 0xFFFF) >> 4; + } + } + return frames; +} + +// Pad [filled, AUDIOOUT_DMA_HALF_SAMPLES) of dest_l (and dest_r if non-NULL) +// with the quiescent value. Used at end-of-stream and on errors so the DAC +// returns smoothly to its resting voltage. +static void pad_quiescent(uint16_t *dest_l, uint16_t *dest_r, + uint32_t filled, uint16_t quiescent_12) { + for (uint32_t i = filled; i < AUDIOOUT_DMA_HALF_SAMPLES; i++) { + dest_l[i] = quiescent_12; + if (dest_r) { + dest_r[i] = quiescent_12; + } + } +} + +// Load one half of the DMA circular buffer from the audio sample source. +// half: 0 = lower half (indices 0..HALF-1), 1 = upper half (HALF..END-1). +// +// Tracks position within the source buffer (src_ptr / src_remaining_len) +// across calls so that large source buffers (e.g. a 1024-sample RawSample) +// are consumed incrementally rather than re-reading from the start each time. +static void load_dma_buffer_half(audioio_audioout_obj_t *self, uint8_t half) { + uint16_t *dest_l = self->dma_buffer + ((uint32_t)half * AUDIOOUT_DMA_HALF_SAMPLES); + uint16_t *dest_r = self->dma_buffer_r + ? self->dma_buffer_r + ((uint32_t)half * AUDIOOUT_DMA_HALF_SAMPLES) + : NULL; + uint16_t quiescent_12 = self->quiescent_value >> 4; + uint32_t src_stride = (uint32_t)self->bytes_per_sample * self->channel_count; + uint32_t filled = 0; + + while (filled < AUDIOOUT_DMA_HALF_SAMPLES) { + // Fetch new source data when the previous buffer is exhausted. + if (self->src_remaining_len == 0) { + // Handle end-of-stream from previous get_buffer call. + if (self->src_done) { + if (self->loop) { + audiosample_reset_buffer(self->sample, + self->channel_count == 1, 0); + self->src_done = false; + } else { + pad_quiescent(dest_l, dest_r, filled, quiescent_12); + self->stopping = true; + return; + } + } + + uint8_t *buf; + uint32_t len; + audioio_get_buffer_result_t result = + audiosample_get_buffer(self->sample, + self->channel_count == 1, 0, &buf, &len); + + if (result == GET_BUFFER_ERROR) { + pad_quiescent(dest_l, dest_r, filled, quiescent_12); + self->stopping = true; + return; + } + + self->src_ptr = buf; + self->src_remaining_len = len; + self->src_done = (result == GET_BUFFER_DONE); + } + + uint32_t written = convert_to_dac12( + self->src_ptr, self->src_remaining_len, + dest_l + filled, AUDIOOUT_DMA_HALF_SAMPLES - filled, + self->bytes_per_sample, self->samples_signed, + self->channel_count, 0); + + if (dest_r) { + uint8_t r_offset = (self->channel_count >= 2) ? 1 : 0; + convert_to_dac12( + self->src_ptr, self->src_remaining_len, + dest_r + filled, AUDIOOUT_DMA_HALF_SAMPLES - filled, + self->bytes_per_sample, self->samples_signed, + self->channel_count, r_offset); + } + + if (written == 0) { + // src had fewer than src_stride bytes left (e.g. a corrupt WAV + // returned an odd byte count for 16-bit data). Drop the partial + // frame so the next loop iteration calls get_buffer for fresh, + // aligned data — without this the loop spins forever because + // neither filled nor src_remaining_len would advance. + self->src_remaining_len = 0; + continue; + } + + // Advance source position by the amount consumed. + uint32_t bytes_consumed = written * src_stride; + self->src_ptr += bytes_consumed; + self->src_remaining_len -= bytes_consumed; + filled += written; + } +} + +// Background callback: called from the main loop after a DMA half/full event. +static void audioout_fill_callback(void *arg) { + audioio_audioout_obj_t *self = (audioio_audioout_obj_t *)arg; + if (!self || active_audioout != self) { + return; + } + if (self->stopping) { + common_hal_audioio_audioout_stop(self); + return; + } + uint8_t mask; + __disable_irq(); + mask = self->halves_to_fill; + self->halves_to_fill = 0; + __enable_irq(); + if (mask & 0x1) { + load_dma_buffer_half(self, 0); + } + if (mask & 0x2) { + load_dma_buffer_half(self, 1); + } +} + +// --------------------------------------------------------------------------- +// IRQ handlers +// +// DMA1 Stream5/6 are claimed exclusively for DAC use here. If a future port +// change wires another peripheral onto either stream the weak-symbol override +// below will collide silently — add a build-time assertion in that file. +// --------------------------------------------------------------------------- + +void DMA1_Stream5_IRQHandler(void) { + if (active_audioout) { + HAL_DMA_IRQHandler(&active_audioout->dma_handle_l); + } +} + +void DMA1_Stream6_IRQHandler(void) { + if (active_audioout && active_audioout->dma_buffer_r) { + HAL_DMA_IRQHandler(&active_audioout->dma_handle_r); + } +} + +// HAL weak-symbol overrides: called from HAL_DMA_IRQHandler context. +// +// Only the Ch1 (left) callbacks are overridden. The Stream6 IRQ for the +// right channel still calls HAL_DACEx_ConvHalfCpltCallbackCh2 / +// HAL_DACEx_ConvCpltCallbackCh2 (the default empty weak implementations) — +// that is intentional. Both DMA streams are clocked by the same TIM6 trigger +// and started together, so their NDTR counters stay in lock-step. Refilling +// from the left-channel IRQ alone is sufficient and avoids redundant work. + +void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef *hdac) { + if (active_audioout && !active_audioout->paused) { + active_audioout->halves_to_fill |= 0x1; + background_callback_add(&active_audioout->callback, + audioout_fill_callback, active_audioout); + } +} + +void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac) { + if (active_audioout && !active_audioout->paused) { + active_audioout->halves_to_fill |= 0x2; + background_callback_add(&active_audioout->callback, + audioout_fill_callback, active_audioout); + } +} + +// --------------------------------------------------------------------------- +// Public API +// --------------------------------------------------------------------------- + +void common_hal_audioio_audioout_construct(audioio_audioout_obj_t *self, + const mcu_pin_obj_t *left_channel, const mcu_pin_obj_t *right_channel, + uint16_t quiescent_value) { + + #if !HAS_DAC + mp_raise_ValueError(MP_ERROR_TEXT("No DAC on chip")); + #else + + // Only PA04 (DAC_CH1) is supported as left channel. + if (left_channel != &pin_PA04) { + raise_ValueError_invalid_pin_name(MP_QSTR_left_channel); + } + + // Right channel must be PA05 (DAC_CH2 / A1) if provided. + if (right_channel != NULL && right_channel != &pin_PA05) { + raise_ValueError_invalid_pin_name(MP_QSTR_right_channel); + } + + // Claim pins first. The pin-claim system is what serialises this driver + // against another AudioOut instance and against AnalogOut on the same + // pins — if either is already using PA04/PA05 the claim raises here, and + // because nothing else is configured yet, no cleanup is needed. + // + // NOTE: ports/atmel-samd/common-hal/audioio/AudioOut.c also claims pins + // first but L242 raises *after* claiming a timer and event channel + // without releasing them on the error path; worth a follow-up there. + common_hal_mcu_pin_claim(left_channel); + if (right_channel != NULL) { + common_hal_mcu_pin_claim(right_channel); + } + + self->left_channel = left_channel; + self->right_channel = right_channel; + self->quiescent_value = quiescent_value; + self->sample = MP_OBJ_NULL; + self->dma_buffer = NULL; + self->dma_buffer_r = NULL; + memset(&self->dma_handle_l, 0, sizeof(self->dma_handle_l)); + memset(&self->dma_handle_r, 0, sizeof(self->dma_handle_r)); + memset(&self->callback, 0, sizeof(self->callback)); + self->stopping = false; + self->paused = false; + self->playing = false; + + // Configure PA04 (and PA05 if stereo) for analog (DAC) mode. + GPIO_InitTypeDef gpio_init = {0}; + gpio_init.Pin = pin_mask(left_channel->number); + gpio_init.Mode = GPIO_MODE_ANALOG; + gpio_init.Pull = GPIO_NOPULL; + HAL_GPIO_Init(pin_port(left_channel->port), &gpio_init); + + if (right_channel != NULL) { + gpio_init.Pin = pin_mask(right_channel->number); + HAL_GPIO_Init(pin_port(right_channel->port), &gpio_init); + } + + // Initialise the shared DAC handle if it hasn't been set up yet + // (i.e. AnalogOut hasn't been used since last reset). __HAL_RCC_DAC_CLK_ENABLE + // is idempotent so calling it unconditionally would be safe too, but + // matching AnalogOut's check keeps the two modules in sync. + if (handle.Instance == NULL || handle.State == HAL_DAC_STATE_RESET) { + __HAL_RCC_DAC_CLK_ENABLE(); + handle.Instance = DAC; + if (HAL_DAC_Init(&handle) != HAL_OK) { + mp_raise_ValueError(MP_ERROR_TEXT("DAC Device Init Error")); + } + } + + // Configure DAC channel 1 with no trigger so the ramp below works + // immediately. play() switches the trigger to TIM6_TRGO. + DAC_ChannelConfTypeDef ch_cfg = {0}; + ch_cfg.DAC_Trigger = DAC_TRIGGER_NONE; + ch_cfg.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; + if (HAL_DAC_ConfigChannel(&handle, &ch_cfg, DAC_CHANNEL_1) != HAL_OK) { + mp_raise_ValueError(MP_ERROR_TEXT("DAC Channel Init Error")); + } + + // Ramp DAC output up to quiescent value to prevent an audible pop. + HAL_DAC_SetValue(&handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0); + HAL_DAC_Start(&handle, DAC_CHANNEL_1); + dac_ramp(0, quiescent_value >> 4); + #endif +} + +bool common_hal_audioio_audioout_deinited(audioio_audioout_obj_t *self) { + return self->left_channel == NULL; +} + +void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t *self) { + if (common_hal_audioio_audioout_deinited(self)) { + return; + } + + common_hal_audioio_audioout_stop(self); + + // Ramp DAC back to zero before disconnecting. + dac_ramp(self->quiescent_value >> 4, 0); + HAL_DAC_Stop(&handle, DAC_CHANNEL_1); + + // Restore channels to no-trigger mode so AnalogOut can use them again. + DAC_ChannelConfTypeDef ch_cfg = {0}; + ch_cfg.DAC_Trigger = DAC_TRIGGER_NONE; + ch_cfg.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; + HAL_DAC_ConfigChannel(&handle, &ch_cfg, DAC_CHANNEL_1); + if (self->right_channel != NULL) { + HAL_DAC_Stop(&handle, DAC_CHANNEL_2); + HAL_DAC_ConfigChannel(&handle, &ch_cfg, DAC_CHANNEL_2); + reset_pin_number(self->right_channel->port, self->right_channel->number); + self->right_channel = NULL; + } + + // Release the left pin. Let AnalogOut manage DAC clock disable. + reset_pin_number(self->left_channel->port, self->left_channel->number); + self->left_channel = NULL; +} + +void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self, + mp_obj_t sample, bool loop) { + // The shared-bindings layer guards every entry point with + // check_for_deinit, so a deinited self can't reach this function. + common_hal_audioio_audioout_stop(self); + + // Extract sample format metadata via the canonical accessors so the + // shared sample-protocol contract is honoured. + audiosample_base_t *base = audiosample_check(sample); + self->bytes_per_sample = audiosample_get_bits_per_sample(base) / 8; + self->samples_signed = base->samples_signed; + self->channel_count = audiosample_get_channel_count(base); + uint32_t sample_rate = audiosample_get_sample_rate(base); + mp_arg_validate_int_min(sample_rate, 1, MP_QSTR_sample_rate); + mp_arg_validate_int_max(sample_rate, AUDIOOUT_MAX_SAMPLE_RATE, MP_QSTR_sample_rate); + + self->sample = sample; + self->loop = loop; + self->stopping = false; + self->paused = false; + self->playing = false; + self->halves_to_fill = 0; + self->src_ptr = NULL; + self->src_remaining_len = 0; + self->src_done = false; + + // Allocate DMA circular buffer(s). m_malloc_without_collect avoids + // triggering a GC cycle while the DAC is mid-configure; m_malloc itself + // raises on failure so no null check is needed. + // + // NOTE: ports/atmel-samd uses plain m_malloc for its audio_dma scratch + // buffers — the same GC-during-fill risk applies and should be migrated + // to m_malloc_without_collect for symmetry with espressif and stm. + self->dma_buffer = (uint16_t *)m_malloc_without_collect( + AUDIOOUT_DMA_BUFFER_SAMPLES * sizeof(uint16_t)); + if (self->right_channel != NULL) { + self->dma_buffer_r = (uint16_t *)m_malloc_without_collect( + AUDIOOUT_DMA_BUFFER_SAMPLES * sizeof(uint16_t)); + } + + // Pre-fill both halves before starting DMA. single_channel_output is + // true when this AudioOut renders only one DAC channel; for stereo + // output we want the audiocore to deliver interleaved frames. + bool single_channel_output = (self->right_channel == NULL); + audiosample_reset_buffer(sample, single_channel_output, 0); + load_dma_buffer_half(self, 0); + load_dma_buffer_half(self, 1); + + // Ramp from quiescent to the first sample so the transition into + // DMA-driven output is glitch-free. The DAC is still in single-mode + // (DAC_TRIGGER_NONE) at this point, set up by construct() / stop(), + // so HAL_DAC_SetValue takes effect immediately. After the ramp the + // pin is sitting at exactly dma_buffer[0], which is also the first + // value the timer-triggered DMA will latch. + uint16_t quiescent_12 = self->quiescent_value >> 4; + dac_ramp_channel(DAC_CHANNEL_1, quiescent_12, self->dma_buffer[0]); + if (self->right_channel != NULL) { + // CH2 was not started in construct(), so it has been outputting + // its reset value (0). Ramp from there. + dac_ramp_channel(DAC_CHANNEL_2, 0, self->dma_buffer_r[0]); + } + + // --- TIM6 setup --- + // TIM6 is a basic timer on APB1. It is not managed by the common timer + // infrastructure (stm_peripherals_find_timer etc.) because it has no GPIO + // pins and is reserved for DAC use (mcu_tim_banks[5] == NULL). + __HAL_RCC_TIM6_CLK_ENABLE(); + + uint32_t tim6_clk = get_tim6_freq(); + // Round to nearest, not truncate, so the realised sample rate is the + // closest TIM6 division to the requested rate. + // NOTE: a sweep audit on atmel-samd (Circuit Playground Express) shows a + // constant -3.4 cent frequency bias across all tones, consistent with a + // truncating period calculation there. The same round-to-nearest fix + // would likely tighten frequency accuracy on that port too. + uint32_t period = (tim6_clk + sample_rate / 2) / sample_rate; + if (period < 2) { + period = 2; + } + period -= 1; + + tim6_handle.Instance = TIM6; + tim6_handle.Init.Prescaler = 0; + tim6_handle.Init.CounterMode = TIM_COUNTERMODE_UP; + tim6_handle.Init.Period = period; + tim6_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + tim6_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&tim6_handle) != HAL_OK) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_TIM6); + } + + // TRGO = Update event → triggers DAC conversion each period. + TIM_MasterConfigTypeDef master_cfg = {0}; + master_cfg.MasterOutputTrigger = TIM_TRGO_UPDATE; + master_cfg.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&tim6_handle, &master_cfg) != HAL_OK) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_TIM6); + } + // NOTE: ports/atmel-samd's audio_dma_setup_playback handles AUDIO_DMA_OK + // and two specific error codes but lets any other non-OK return fall + // through silently — worth tightening there to mirror this raise-on-fail + // pattern. + + // --- DAC channel reconfiguration for DMA-triggered mode --- + // Switch the trigger source to TIM6 *without* disabling the DAC channel. + // HAL_DAC_Stop would disable the channel and momentarily drop the output + // pin to 0 V — audible as a pop between samples. + DAC_ChannelConfTypeDef ch_cfg = {0}; + ch_cfg.DAC_Trigger = DAC_TRIGGER_T6_TRGO; + ch_cfg.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; + HAL_DAC_ConfigChannel(&handle, &ch_cfg, DAC_CHANNEL_1); + if (self->right_channel != NULL) { + HAL_DAC_ConfigChannel(&handle, &ch_cfg, DAC_CHANNEL_2); + } + // Reset HAL state from BUSY (set by Start) back to READY so + // HAL_DAC_Start_DMA below doesn't reject the request. + handle.State = HAL_DAC_STATE_READY; + + // --- DMA1 Stream5 Channel7 setup (DAC CH1, left) --- + __HAL_RCC_DMA1_CLK_ENABLE(); + + DMA_HandleTypeDef *hdma = &self->dma_handle_l; + memset(hdma, 0, sizeof(*hdma)); + hdma->Instance = DMA1_Stream5; + hdma->Init.Channel = DMA_CHANNEL_7; + hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma->Init.PeriphInc = DMA_PINC_DISABLE; + hdma->Init.MemInc = DMA_MINC_ENABLE; + hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma->Init.Mode = DMA_CIRCULAR; + hdma->Init.Priority = DMA_PRIORITY_VERY_HIGH; + hdma->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(hdma) != HAL_OK) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_DMA); + } + __HAL_LINKDMA(&handle, DMA_Handle1, *hdma); + + HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 6, 0); + NVIC_ClearPendingIRQ(DMA1_Stream5_IRQn); + HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); + + // --- DMA1 Stream6 Channel7 setup (DAC CH2, right) --- + if (self->right_channel != NULL) { + DMA_HandleTypeDef *hdma_r = &self->dma_handle_r; + memset(hdma_r, 0, sizeof(*hdma_r)); + hdma_r->Instance = DMA1_Stream6; + hdma_r->Init.Channel = DMA_CHANNEL_7; + hdma_r->Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_r->Init.PeriphInc = DMA_PINC_DISABLE; + hdma_r->Init.MemInc = DMA_MINC_ENABLE; + hdma_r->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_r->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_r->Init.Mode = DMA_CIRCULAR; + hdma_r->Init.Priority = DMA_PRIORITY_VERY_HIGH; + hdma_r->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(hdma_r) != HAL_OK) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_DMA); + } + __HAL_LINKDMA(&handle, DMA_Handle2, *hdma_r); + + HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 6, 0); + NVIC_ClearPendingIRQ(DMA1_Stream6_IRQn); + HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn); + } + + // --- Start DMA transfer(s) then timer --- + active_audioout = self; + + if (HAL_DAC_Start_DMA(&handle, DAC_CHANNEL_1, + (uint32_t *)self->dma_buffer, + AUDIOOUT_DMA_BUFFER_SAMPLES, + DAC_ALIGN_12B_R) != HAL_OK) { + active_audioout = NULL; + HAL_NVIC_DisableIRQ(DMA1_Stream5_IRQn); + if (self->right_channel != NULL) { + HAL_NVIC_DisableIRQ(DMA1_Stream6_IRQn); + m_free(self->dma_buffer_r); + self->dma_buffer_r = NULL; + } + m_free(self->dma_buffer); + self->dma_buffer = NULL; + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_DAC); + } + + if (self->right_channel != NULL) { + if (HAL_DAC_Start_DMA(&handle, DAC_CHANNEL_2, + (uint32_t *)self->dma_buffer_r, + AUDIOOUT_DMA_BUFFER_SAMPLES, + DAC_ALIGN_12B_R) != HAL_OK) { + active_audioout = NULL; + HAL_DAC_Stop_DMA(&handle, DAC_CHANNEL_1); + HAL_NVIC_DisableIRQ(DMA1_Stream5_IRQn); + HAL_NVIC_DisableIRQ(DMA1_Stream6_IRQn); + m_free(self->dma_buffer); + self->dma_buffer = NULL; + m_free(self->dma_buffer_r); + self->dma_buffer_r = NULL; + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_DAC); + } + } + + HAL_TIM_Base_Start(&tim6_handle); + self->playing = true; +} + +void common_hal_audioio_audioout_stop(audioio_audioout_obj_t *self) { + if (active_audioout != self) { + return; + } + + // Stop the sample clock first so no more DMA requests are generated. + TIM6->CR1 &= ~TIM_CR1_CEN; + + // Switch the DAC channels to no-trigger mode while leaving them enabled. + // This is the key to a click-free stop: HAL_DAC_Stop_DMA / HAL_DAC_Stop + // disable the channel, which briefly pulls the output pin to 0 V before + // the ramp can run. Reconfiguring the trigger only keeps the channel + // enabled; the DAC keeps holding its last DHR value while DMA is aborted. + DAC_ChannelConfTypeDef ch_cfg = {0}; + ch_cfg.DAC_Trigger = DAC_TRIGGER_NONE; + ch_cfg.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; + HAL_DAC_ConfigChannel(&handle, &ch_cfg, DAC_CHANNEL_1); + if (self->dma_buffer_r) { + HAL_DAC_ConfigChannel(&handle, &ch_cfg, DAC_CHANNEL_2); + } + + // Capture the last DAC output now that no further DMA writes can land. + uint16_t last_l = (uint16_t)(DAC->DOR1 & 0xFFF); + uint16_t last_r = self->dma_buffer_r ? (uint16_t)(DAC->DOR2 & 0xFFF) : 0; + uint16_t quiescent_12 = self->quiescent_value >> 4; + + // Abort DMA without disabling the DAC channels (HAL_DAC_Stop_DMA would). + HAL_DMA_Abort(&self->dma_handle_l); + HAL_NVIC_DisableIRQ(DMA1_Stream5_IRQn); + NVIC_ClearPendingIRQ(DMA1_Stream5_IRQn); + if (self->dma_buffer_r) { + HAL_DMA_Abort(&self->dma_handle_r); + HAL_NVIC_DisableIRQ(DMA1_Stream6_IRQn); + NVIC_ClearPendingIRQ(DMA1_Stream6_IRQn); + m_free(self->dma_buffer_r); + self->dma_buffer_r = NULL; + } + + // Free the left DMA buffer. + if (self->dma_buffer) { + m_free(self->dma_buffer); + self->dma_buffer = NULL; + } + + // Ramp left channel from last sample back to quiescent. + dac_ramp_channel(DAC_CHANNEL_1, last_l, quiescent_12); + + // Ramp right channel back to 0 (its reset value) before disabling it, + // so the next play() can ramp cleanly from 0 again. + if (self->right_channel != NULL) { + dac_ramp_channel(DAC_CHANNEL_2, last_r, 0); + HAL_DAC_Stop(&handle, DAC_CHANNEL_2); + } + + self->sample = MP_OBJ_NULL; + self->stopping = false; + self->paused = false; + self->playing = false; + active_audioout = NULL; + + __HAL_RCC_TIM6_CLK_DISABLE(); +} + +bool common_hal_audioio_audioout_get_playing(audioio_audioout_obj_t *self) { + return active_audioout == self && self->playing; +} + +void common_hal_audioio_audioout_pause(audioio_audioout_obj_t *self) { + if (active_audioout != self) { + return; + } + self->paused = true; + // Pause the sample clock; DMA remains armed but no new triggers fire. + TIM6->CR1 &= ~TIM_CR1_CEN; +} + +void common_hal_audioio_audioout_resume(audioio_audioout_obj_t *self) { + if (active_audioout != self || !self->paused) { + return; + } + self->paused = false; + // Restart the sample clock. + TIM6->CR1 |= TIM_CR1_CEN; +} + +bool common_hal_audioio_audioout_get_paused(audioio_audioout_obj_t *self) { + // Match espressif's convention: paused only reports true while a play() + // session is active, so a stale flag from a previous session can never + // leak through. + // + // NOTE: ports/atmel-samd delegates to audio_dma_get_paused() and does + // not gate on a "playing" state — it relies on the DMA hardware staying + // quiescent after stop. Worth aligning to the espressif/stm convention. + return self->playing && self->paused; +} + +// --------------------------------------------------------------------------- +// Reset hook +// --------------------------------------------------------------------------- + +void audioout_reset(void) { + if (active_audioout != NULL) { + // Emergency stop: halt timer and DMA without ramping. + TIM6->CR1 &= ~TIM_CR1_CEN; + HAL_DAC_Stop_DMA(&handle, DAC_CHANNEL_1); + HAL_NVIC_DisableIRQ(DMA1_Stream5_IRQn); + if (active_audioout->dma_buffer_r) { + HAL_DAC_Stop_DMA(&handle, DAC_CHANNEL_2); + HAL_NVIC_DisableIRQ(DMA1_Stream6_IRQn); + m_free(active_audioout->dma_buffer_r); + active_audioout->dma_buffer_r = NULL; + } + if (active_audioout->dma_buffer) { + m_free(active_audioout->dma_buffer); + active_audioout->dma_buffer = NULL; + } + active_audioout->sample = MP_OBJ_NULL; + active_audioout->stopping = false; + active_audioout->paused = false; + active_audioout->playing = false; + // Mark the object deinited and drop both pin references so the next + // construct() starts from a fully clean state. reset_all_pins (run + // elsewhere in reset_port) releases the actual pin claims. + active_audioout->left_channel = NULL; + active_audioout->right_channel = NULL; + active_audioout = NULL; + } + __HAL_RCC_TIM6_CLK_DISABLE(); +} diff --git a/ports/stm/common-hal/audioio/AudioOut.h b/ports/stm/common-hal/audioio/AudioOut.h new file mode 100644 index 00000000000..340118819a9 --- /dev/null +++ b/ports/stm/common-hal/audioio/AudioOut.h @@ -0,0 +1,72 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "common-hal/microcontroller/Pin.h" +#include "supervisor/background_callback.h" +#include STM32_HAL_H + +// Total DMA circular buffer size in 16-bit samples. +// Split into two halves; one half plays while the other is refilled. +// 4096-sample halves at 22050 Hz = ~186 ms per half-buffer interrupt, +// giving the background callback enough headroom to absorb SDIO cluster +// reads, NeoPixel updates, and other main-loop stalls without underrun. +#define AUDIOOUT_DMA_BUFFER_SAMPLES 8192 +#define AUDIOOUT_DMA_HALF_SAMPLES (AUDIOOUT_DMA_BUFFER_SAMPLES / 2) + +typedef struct { + mp_obj_base_t base; + + // Left channel pin (PA04 = DAC_CH1). NULL when deinited. + const mcu_pin_obj_t *left_channel; + // Right channel pin (PA05 = DAC_CH2). NULL when mono. + const mcu_pin_obj_t *right_channel; + + // DMA handles. The DAC handle itself is the shared file-scope handle + // from AnalogOut.c; we link these to it via __HAL_LINKDMA. + DMA_HandleTypeDef dma_handle_l; // DMA1 Stream5 Channel7 (DAC CH1, left) + DMA_HandleTypeDef dma_handle_r; // DMA1 Stream6 Channel7 (DAC CH2, right) + + // Circular DMA buffers: AUDIOOUT_DMA_BUFFER_SAMPLES uint16_t elements each, + // allocated on play() and freed on stop(). + uint16_t *dma_buffer; // left (CH1) + uint16_t *dma_buffer_r; // right (CH2), NULL when mono + + // Current audio sample object being played. + mp_obj_t sample; + bool loop; + bool playing; + + // Set from ISR context to request a clean stop via background callback. + volatile bool stopping; + bool paused; + + // Sample format metadata, populated at play() time. + uint8_t bytes_per_sample; // 1 (8-bit) or 2 (16-bit) + bool samples_signed; + uint8_t channel_count; // 1 = mono, 2 = stereo + uint16_t quiescent_value; // 16-bit resting value (default 0x8000) + + // Background callback queued from DMA ISR, processed in main loop. + background_callback_t callback; + + // Bitmask of DMA halves pending refill: bit0 = lower, bit1 = upper. + // Set from half/full IRQ, drained by the background callback. A bitmask + // (not a scalar) so a back-to-back half+full pair queues both fills even + // if the callback hasn't run yet. + volatile uint8_t halves_to_fill; + + // Source buffer position tracking. Allows consuming large source buffers + // (e.g. RawSample > 256 samples) across multiple DMA half-fills. + const uint8_t *src_ptr; // current read position in source buffer + uint32_t src_remaining_len; // bytes remaining in current source buffer + bool src_done; // GET_BUFFER_DONE received for current buffer +} audioio_audioout_obj_t; + +// Called from reset_port() to stop any active playback on soft-reset. +void audioout_reset(void); diff --git a/ports/stm/common-hal/audioio/__init__.c b/ports/stm/common-hal/audioio/__init__.c new file mode 100644 index 00000000000..ebf626832f6 --- /dev/null +++ b/ports/stm/common-hal/audioio/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// No audioio module functions. diff --git a/ports/stm/common-hal/busio/SPI.c b/ports/stm/common-hal/busio/SPI.c index 1b86a9f55d5..24b65fbf54c 100644 --- a/ports/stm/common-hal/busio/SPI.c +++ b/ports/stm/common-hal/busio/SPI.c @@ -136,12 +136,13 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) { + // Ensure the object starts in its deinit state before check_pins sets + // self->sck, self->mosi, and self->miso. + common_hal_busio_spi_mark_deinit(self); + int periph_index = check_pins(self, sck, mosi, miso); SPI_TypeDef *SPIx = mcu_spi_banks[periph_index - 1]; - // Ensure the object starts in its deinit state. - common_hal_busio_spi_mark_deinit(self); - // Start GPIO for each pin GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = pin_mask(sck->number); diff --git a/ports/stm/mpconfigport.mk b/ports/stm/mpconfigport.mk index 96724a52960..bd2b2238eef 100644 --- a/ports/stm/mpconfigport.mk +++ b/ports/stm/mpconfigport.mk @@ -3,6 +3,8 @@ INTERNAL_LIBM ?= 1 ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F405xx STM32F407xx)) CIRCUITPY_ALARM = 1 + # ?= so a board reusing TIM6 / PA04 for something else can opt out. + CIRCUITPY_AUDIOIO ?= 1 CIRCUITPY_CANIO = 1 CIRCUITPY_FRAMEBUFFERIO ?= 1 CIRCUITPY_SDIOIO ?= 1 @@ -19,8 +21,8 @@ ifeq ($(MCU_VARIANT),STM32F407xx) endif ifeq ($(MCU_SERIES),F4) - # Audio via PWM - CIRCUITPY_AUDIOIO = 0 + # Audio via PWM (F405/F407 also supports DAC-based audioio; set above) + CIRCUITPY_AUDIOIO ?= 0 CIRCUITPY_AUDIOCORE ?= 1 CIRCUITPY_AUDIOPWMIO ?= 1 diff --git a/ports/stm/mpconfigport_nanbox.h b/ports/stm/mpconfigport_nanbox.h deleted file mode 100644 index 164850112e0..00000000000 --- a/ports/stm/mpconfigport_nanbox.h +++ /dev/null @@ -1,25 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George -// -// SPDX-License-Identifier: MIT - -#pragma once - -// select nan-boxing object model -#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D) - -// native emitters don't work with nan-boxing -#define MICROPY_EMIT_X86 (0) -#define MICROPY_EMIT_X64 (0) -#define MICROPY_EMIT_THUMB (0) -#define MICROPY_EMIT_ARM (0) - -#include - -typedef int64_t mp_int_t; -typedef uint64_t mp_uint_t; -#define UINT_FMT "%llu" -#define INT_FMT "%lld" - -#include diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index 3820a046fc4..1da862cd886 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -32,6 +32,9 @@ #if CIRCUITPY_RTC #include "shared-bindings/rtc/__init__.h" #endif +#if CIRCUITPY_AUDIOIO +#include "common-hal/audioio/AudioOut.h" +#endif #include "peripherals/clocks.h" #include "peripherals/gpio.h" @@ -39,7 +42,7 @@ #include STM32_HAL_H -void NVIC_SystemReset(void) NORETURN; +void NVIC_SystemReset(void) MP_NORETURN; #if (CPY_STM32H7) || (CPY_STM32F7) #if defined(CIRCUITPY_HW_SDRAM_SIZE) @@ -315,6 +318,9 @@ void reset_port(void) { #if CIRCUITPY_ALARM exti_reset(); #endif + #if CIRCUITPY_AUDIOIO + audioout_reset(); + #endif } void reset_to_bootloader(void) { diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 6461c310eeb..32e3b44b227 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -27,6 +27,9 @@ FROZEN_MANIFEST ?= variants/manifest.py # This should be configured by the mpconfigvariant.mk PROG ?= micropython +# For use in test rules below +ABS_PROG = $(abspath $(BUILD)/$(PROG)) + # qstr definitions (must come before including py.mk) QSTR_DEFS += qstrdefsport.h QSTR_GLOBAL_DEPENDENCIES += $(VARIANT_DIR)/mpconfigvariant.h @@ -46,6 +49,7 @@ INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror +// CIRCUITPY-CHANGE: add -Wno-missing-field-initializers CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Wno-missing-field-initializers CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) @@ -53,6 +57,10 @@ CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EX # This option has no effect on 64-bit builds. CFLAGS += -D_FILE_OFFSET_BITS=64 +# Force the use of 64-bits for time_t in C library functions on 32-bit platforms. +# This option has no effect on 64-bit builds. +CFLAGS += -D_TIME_BITS=64 + # Debugging/Optimization ifdef DEBUG COPT ?= -Og @@ -139,7 +147,11 @@ ifeq ($(MICROPY_PY_SOCKET),1) CFLAGS += -DMICROPY_PY_SOCKET=1 endif ifeq ($(MICROPY_PY_THREAD),1) +ifeq ($(MICROPY_PY_THREAD_GIL),1) +CFLAGS += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=1 +else CFLAGS += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0 +endif LDFLAGS += $(LIBPTHREAD) endif @@ -225,6 +237,7 @@ $(BUILD)/supervisor/shared/translate/translate.o: $(HEADER_BUILD)/qstrdefs.gener SHARED_SRC_C += $(addprefix shared/,\ runtime/gchelper_generic.c \ + runtime/pyexec.c \ timeutils/timeutils.c \ $(SHARED_SRC_C_EXTRA) \ ) @@ -280,7 +293,7 @@ print-failures clean-failures: TEST_ARGS ?= test: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py $(TEST_ARGS) + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py test_full: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) diff --git a/ports/unix/README.md b/ports/unix/README.md index b7aa6e3fef7..ee983a882cc 100644 --- a/ports/unix/README.md +++ b/ports/unix/README.md @@ -72,6 +72,14 @@ To run the complete testsuite, use: $ make test +There are other make targets to interact with the testsuite: + + $ make test//int # Run all tests matching the pattern "int" + $ make test/ports/unix # Run all tests in ports/unix + $ make test-failures # Re-run only the failed tests + $ make print-failures # print the differences for failed tests + $ make clean-failures # delete the .exp and .out files from failed tests + The Unix port comes with a built-in package manager called `mip`, e.g.: $ ./build-standard/micropython -m mip install hmac @@ -155,3 +163,21 @@ The default compiler optimisation level is -Os, or -Og if `DEBUG=1` is set. Setting the variable `COPT` will explicitly set the optimisation level. For example `make [other arguments] COPT=-O0 DEBUG=1` will build a binary with no optimisations, assertions enabled, and debug symbols. + +### Sanitizers + +Sanitizers are extra runtime checks supported by gcc and clang. The CI process +supports building with the "undefined behavior" (UBSan) or "address" (ASan) +sanitizers. The script `tools/ci.sh` is the source of truth about how to build +and run in these modes. + +Several classes of checks are disabled via compiler flags: + +* In the undefined behavior sanitizer, checks based on the presence of the + `non_null` attribute are disabled because the code makes technically incorrect + calls like `memset(NULL, 0, 0)`. A future C standard is likely to permit such + calls. +* In the address sanitizer, `detect_stack_use_after_return` is disabled. This + check is intended to make sure locals in a "returned from" stack frame are not + used. However, this mode interferes with various assumptions that + MicroPython's stack checking, NLR, and GC rely on. diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 7f13f9756f1..49426f0f3e8 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -97,6 +97,7 @@ static const mp_rom_map_elem_t rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write1), MP_ROM_PTR(&mp_stream_write1_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto1), MP_ROM_PTR(&mp_stream_readinto1_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, }; @@ -171,19 +172,34 @@ static void pairheap_test(size_t nops, int *ops) { if (mp_pairheap_is_empty(pairheap_lt, heap)) { mp_printf(&mp_plat_print, " -"); } else { - mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]); + mp_printf(&mp_plat_print, " %d", (int)(mp_pairheap_peek(pairheap_lt, heap) - &node[0])); ; } } mp_printf(&mp_plat_print, "\npop all:"); while (!mp_pairheap_is_empty(pairheap_lt, heap)) { - mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]); + mp_printf(&mp_plat_print, " %d", (int)(mp_pairheap_peek(pairheap_lt, heap) - &node[0])); ; heap = mp_pairheap_pop(pairheap_lt, heap); } mp_printf(&mp_plat_print, "\n"); } +// CIRCUITPY-CHANGE: not turned on in CircuitPython +#if MICROPY_SCHEDULER_STATIC_NODES +static mp_sched_node_t mp_coverage_sched_node; +static bool coverage_sched_function_continue; + +static void coverage_sched_function(mp_sched_node_t *node) { + (void)node; + mp_printf(&mp_plat_print, "scheduled function\n"); + if (coverage_sched_function_continue) { + // Re-scheduling node will cause it to run again next time scheduled functions are run + mp_sched_schedule_node(&mp_coverage_sched_node, coverage_sched_function); + } +} +#endif + // function to run extra tests for things that can't be checked by scripts static mp_obj_t extra_coverage(void) { // mp_printf (used by ports that don't have a native printf) @@ -191,10 +207,22 @@ static mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "# mp_printf\n"); mp_printf(&mp_plat_print, "%d %+d % d\n", -123, 123, 123); // sign mp_printf(&mp_plat_print, "%05d\n", -123); // negative number with zero padding - mp_printf(&mp_plat_print, "%ld\n", 123); // long - mp_printf(&mp_plat_print, "%lx\n", 0x123); // long hex - mp_printf(&mp_plat_print, "%X\n", 0x1abcdef); // capital hex - mp_printf(&mp_plat_print, "%.2s %.3s '%4.4s' '%5.5q' '%.3q'\n", "abc", "abc", "abc", MP_QSTR_True, MP_QSTR_True); // fixed string precision + mp_printf(&mp_plat_print, "%ld\n", 123l); // long + mp_printf(&mp_plat_print, "%lx\n", 0x123fl); // long hex + mp_printf(&mp_plat_print, "%lX\n", 0x123fl); // capital long hex + if (sizeof(mp_int_t) == 8) { + mp_printf(&mp_plat_print, "%llx\n", LLONG_MAX); // long long hex + mp_printf(&mp_plat_print, "%llX\n", LLONG_MAX); // capital long long hex + mp_printf(&mp_plat_print, "%llu\n", ULLONG_MAX); // unsigned long long + } else { + // fake for platforms without narrower mp_int_t + mp_printf(&mp_plat_print, "7fffffffffffffff\n"); + mp_printf(&mp_plat_print, "7FFFFFFFFFFFFFFF\n"); + mp_printf(&mp_plat_print, "18446744073709551615\n"); + } + mp_printf(&mp_plat_print, "%p\n", (void *)0x789f); // pointer + mp_printf(&mp_plat_print, "%P\n", (void *)0x789f); // pointer uppercase + mp_printf(&mp_plat_print, "%.2s %.3s '%4.4s' '%5.5q' '%.3q'\n", "abc", "abc", "abc", (qstr)MP_QSTR_True, (qstr)MP_QSTR_True); // fixed string precision mp_printf(&mp_plat_print, "%.*s\n", -1, "abc"); // negative string precision mp_printf(&mp_plat_print, "%b %b\n", 0, 1); // bools #ifndef NDEBUG @@ -204,10 +232,36 @@ static mp_obj_t extra_coverage(void) { #endif mp_printf(&mp_plat_print, "%d\n", 0x80000000); // should print signed mp_printf(&mp_plat_print, "%u\n", 0x80000000); // should print unsigned - mp_printf(&mp_plat_print, "%x\n", 0x80000000); // should print unsigned - mp_printf(&mp_plat_print, "%X\n", 0x80000000); // should print unsigned - mp_printf(&mp_plat_print, "abc\n%"); // string ends in middle of format specifier + mp_printf(&mp_plat_print, "%x\n", 0x8000000f); // should print unsigned + mp_printf(&mp_plat_print, "%X\n", 0x8000000f); // should print unsigned + // note: storing the string in a variable is enough to prevent the + // format string checker from checking this format string. Otherwise, + // it would be a compile time diagnostic under the format string + // checker. + const char msg[] = "abc\n%"; + mp_printf(&mp_plat_print, msg); // string ends in middle of format specifier mp_printf(&mp_plat_print, "%%\n"); // literal % character + mp_printf(&mp_plat_print, ".%-3s.\n", "a"); // left adjust + + // Check that all kinds of mp_printf arguments are parsed out + // correctly, by having a char argument before and after each main type + // of value that can be formatted. + mp_printf(&mp_plat_print, "%c%%%c\n", '<', '>'); + mp_printf(&mp_plat_print, "%c%p%c\n", '<', (void *)0xaaaa, '>'); + mp_printf(&mp_plat_print, "%c%b%c\n", '<', true, '>'); + mp_printf(&mp_plat_print, "%c%d%c\n", '<', 0xaaaa, '>'); + mp_printf(&mp_plat_print, "%c%ld%c\n", '<', 0xaaaal, '>'); + mp_printf(&mp_plat_print, "%c" INT_FMT "%c\n", '<', (mp_int_t)0xaaaa, '>'); + mp_printf(&mp_plat_print, "%c%s%c\n", '<', "test", '>'); + mp_printf(&mp_plat_print, "%c%f%c\n", '<', MICROPY_FLOAT_CONST(1000.), '>'); + mp_printf(&mp_plat_print, "%c%q%c\n", '<', (qstr)MP_QSTR_True, '>'); + if (sizeof(mp_int_t) == 8) { + mp_printf(&mp_plat_print, "%c%lld%c\n", '<', LLONG_MAX, '>'); + } else { + mp_printf(&mp_plat_print, "<9223372036854775807>\n"); + } + + } // GC @@ -220,11 +274,11 @@ static mp_obj_t extra_coverage(void) { gc_unlock(); // using gc_realloc to resize to 0, which means free the memory - void *p = gc_alloc(4, false); + void *p = gc_alloc(4, 0); mp_printf(&mp_plat_print, "%p\n", gc_realloc(p, 0, false)); // calling gc_nbytes with a non-heap pointer - mp_printf(&mp_plat_print, "%p\n", gc_nbytes(NULL)); + mp_printf(&mp_plat_print, "%d\n", (int)gc_nbytes(NULL)); } // GC initialisation and allocation stress test, to check the logic behind ALLOC_TABLE_GAP_BYTE @@ -285,7 +339,7 @@ static mp_obj_t extra_coverage(void) { } ptrs[i][j] = j; } - mp_printf(&mp_plat_print, "%d %d\n", i, all_zero); + mp_printf(&mp_plat_print, "%d %d\n", (int)i, (int)all_zero); // hide the pointer from the GC and collect ptrs[i] = FLIP_POINTER(ptrs[i]); @@ -301,7 +355,7 @@ static mp_obj_t extra_coverage(void) { break; } } - mp_printf(&mp_plat_print, "%d %d\n", i, correct_contents); + mp_printf(&mp_plat_print, "%d %d\n", (int)i, (int)correct_contents); } // free the memory blocks @@ -400,7 +454,7 @@ static mp_obj_t extra_coverage(void) { // create a bytearray via mp_obj_new_bytearray mp_buffer_info_t bufinfo; mp_get_buffer_raise(mp_obj_new_bytearray(4, "data"), &bufinfo, MP_BUFFER_RW); - mp_printf(&mp_plat_print, "%.*s\n", bufinfo.len, bufinfo.buf); + mp_printf(&mp_plat_print, "%.*s\n", (int)bufinfo.len, bufinfo.buf); } // mpz @@ -464,6 +518,38 @@ static mp_obj_t extra_coverage(void) { mp_int_t value_signed; mpz_as_int_checked(&mpz, &value_signed); mp_printf(&mp_plat_print, "%d\n", (int)value_signed); + + // hash the zero mpz integer + mpz_set_from_int(&mpz, 0); + mp_printf(&mp_plat_print, "%d\n", (int)mpz_hash(&mpz)); + + // convert the mpz zero integer to int + mp_printf(&mp_plat_print, "%d\n", mpz_as_int_checked(&mpz, &value_signed)); + mp_printf(&mp_plat_print, "%d\n", (int)value_signed); + + // mpz_set_from_float with 0 as argument + mpz_set_from_float(&mpz, 0); + mp_printf(&mp_plat_print, "%f\n", mpz_as_float(&mpz)); + + // convert a large integer value (stored in a mpz) to mp_uint_t and to ll; + mp_obj_t obj_bigint = mp_obj_new_int_from_uint((mp_uint_t)0xdeadbeef); + mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint)); + obj_bigint = mp_obj_new_int_from_ll(0xc0ffee777c0ffeell); + long long value_ll = mp_obj_get_ll(obj_bigint); + mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll); + + // convert a large integer value (stored via a struct object) to uint and to ll + // `deadbeef` global is an uctypes.struct defined by extra_coverage.py + obj_bigint = mp_load_global(MP_QSTR_deadbeef); + mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint)); + value_ll = mp_obj_get_ll(obj_bigint); + mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll); + + // convert a smaller integer value to mp_uint_t and to ll + obj_bigint = mp_obj_new_int_from_uint(0xc0ffee); + mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint)); + value_ll = mp_obj_get_ll(obj_bigint); + mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll); } // runtime utils @@ -481,7 +567,7 @@ static mp_obj_t extra_coverage(void) { mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), mp_obj_new_str_from_cstr("abc"), mp_obj_new_str_from_cstr("abc")); // mp_obj_int_get_checked with mp_obj_int_t that has a value that is a small integer - mp_printf(&mp_plat_print, "%d\n", mp_obj_int_get_checked(mp_obj_int_new_mpz())); + mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_checked(MP_OBJ_FROM_PTR(mp_obj_int_new_mpz()))); // mp_obj_int_get_uint_checked with non-negative small-int mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(1))); @@ -506,6 +592,22 @@ static mp_obj_t extra_coverage(void) { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } + // mp_obj_get_uint from a non-int object (should raise exception) + if (nlr_push(&nlr) == 0) { + mp_obj_get_uint(mp_const_none); + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } + + // mp_obj_int_get_ll from a non-int object (should raise exception) + if (nlr_push(&nlr) == 0) { + mp_obj_get_ll(mp_const_none); + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } + // call mp_obj_new_exception_args (it's a part of the public C API and not used in the core) mp_obj_print_exception(&mp_plat_print, mp_obj_new_exception_args(&mp_type_ValueError, 0, NULL)); } @@ -515,26 +617,6 @@ static mp_obj_t extra_coverage(void) { mp_emitter_warning(MP_PASS_CODE_SIZE, "test"); } - // format float - { - mp_printf(&mp_plat_print, "# format float\n"); - - // format with inadequate buffer size - char buf[5]; - mp_format_float(1, buf, sizeof(buf), 'g', 0, '+'); - mp_printf(&mp_plat_print, "%s\n", buf); - - // format with just enough buffer so that precision must be - // set from 0 to 1 twice - char buf2[8]; - mp_format_float(1, buf2, sizeof(buf2), 'g', 0, '+'); - mp_printf(&mp_plat_print, "%s\n", buf2); - - // format where precision is trimmed to avoid buffer overflow - mp_format_float(1, buf2, sizeof(buf2), 'e', 0, '+'); - mp_printf(&mp_plat_print, "%s\n", buf2); - } - // binary { mp_printf(&mp_plat_print, "# binary\n"); @@ -558,14 +640,26 @@ static mp_obj_t extra_coverage(void) { fun_bc.context = &context; fun_bc.child_table = NULL; fun_bc.bytecode = (const byte *)"\x01"; // just needed for n_state + #if MICROPY_PY_SYS_SETTRACE + struct _mp_raw_code_t rc = {}; + fun_bc.rc = &rc; + #endif mp_code_state_t *code_state = m_new_obj_var(mp_code_state_t, state, mp_obj_t, 1); code_state->fun_bc = &fun_bc; code_state->ip = (const byte *)"\x00"; // just needed for an invalid opcode code_state->sp = &code_state->state[0]; code_state->exc_sp_idx = 0; code_state->old_globals = NULL; + #if MICROPY_STACKLESS + code_state->prev = NULL; + #endif + #if MICROPY_PY_SYS_SETTRACE + code_state->prev_state = NULL; + code_state->frame = NULL; + #endif + mp_vm_return_kind_t ret = mp_execute_bytecode(code_state, MP_OBJ_NULL); - mp_printf(&mp_plat_print, "%d %d\n", ret, mp_obj_get_type(code_state->state[0]) == &mp_type_NotImplementedError); + mp_printf(&mp_plat_print, "%d %d\n", (int)ret, mp_obj_get_type(code_state->state[0]) == &mp_type_NotImplementedError); } // scheduler @@ -622,9 +716,25 @@ static mp_obj_t extra_coverage(void) { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } mp_handle_pending(true); + + // CIRCUITPY-CHANGE: not turned on in CircuitPython + #if MICROPY_SCHEDULER_STATIC_NODES + coverage_sched_function_continue = true; + mp_sched_schedule_node(&mp_coverage_sched_node, coverage_sched_function); + for (int i = 0; i < 3; ++i) { + mp_printf(&mp_plat_print, "loop\n"); + mp_handle_pending(true); + } + // Clear this flag to prevent the function scheduling itself again + coverage_sched_function_continue = false; + // Will only run the first time through this loop, then not scheduled again + for (int i = 0; i < 3; ++i) { + mp_handle_pending(true); + } + #endif } - // CIRCUITPY-CHANGE: ringbuf is different + // CIRCUITPY-CHANGE: ringbuf is quite different // ringbuf { #define RINGBUF_SIZE 99 @@ -636,36 +746,36 @@ static mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "# ringbuf\n"); // Single-byte put/get with empty ringbuf. - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); ringbuf_put(&ringbuf, 22); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_get(&ringbuf)); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); // Two-byte put/get with empty ringbuf. ringbuf_put16(&ringbuf, 0xaa55); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); // Two-byte put with full ringbuf. for (int i = 0; i < RINGBUF_SIZE; ++i) { ringbuf_put(&ringbuf, i); } - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb)); // Two-byte put with one byte free. ringbuf_get(&ringbuf); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x3377)); ringbuf_get(&ringbuf); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0xcc99)); for (int i = 0; i < RINGBUF_SIZE - 2; ++i) { ringbuf_get(&ringbuf); } mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); // Two-byte put with wrap around on first byte: ringbuf_clear(&ringbuf); @@ -777,7 +887,7 @@ static mp_obj_t extra_coverage(void) { mp_obj_streamtest_t *s2 = mp_obj_malloc(mp_obj_streamtest_t, &mp_type_stest_textio2); // return a tuple of data for testing on the Python side - mp_obj_t items[] = {(mp_obj_t)&str_no_hash_obj, (mp_obj_t)&bytes_no_hash_obj, MP_OBJ_FROM_PTR(s), MP_OBJ_FROM_PTR(s2)}; + mp_obj_t items[] = {MP_OBJ_FROM_PTR(&str_no_hash_obj), MP_OBJ_FROM_PTR(&bytes_no_hash_obj), MP_OBJ_FROM_PTR(s), MP_OBJ_FROM_PTR(s2)}; return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items); } MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage); diff --git a/ports/unix/coveragecpp.cpp b/ports/unix/coveragecpp.cpp index 377b5acf763..8ba308f6468 100644 --- a/ports/unix/coveragecpp.cpp +++ b/ports/unix/coveragecpp.cpp @@ -1,12 +1,77 @@ extern "C" { -// CIRCUITPY-CHANGE: do not include everything: it causes compilation warnings -#include "py/obj.h" +// Include the complete public API to verify everything compiles as C++. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include } +// Invoke all (except one, see below) public API macros which initialize structs to make sure +// they are C++-compatible, meaning they explicitly initialize all struct members. +mp_obj_t f0(); +MP_DEFINE_CONST_FUN_OBJ_0(f0_obj, f0); +mp_obj_t f1(mp_obj_t); +MP_DEFINE_CONST_FUN_OBJ_1(f1_obj, f1); +mp_obj_t f2(mp_obj_t, mp_obj_t); +MP_DEFINE_CONST_FUN_OBJ_2(f2_obj, f2); +mp_obj_t f3(mp_obj_t, mp_obj_t, mp_obj_t); +MP_DEFINE_CONST_FUN_OBJ_3(f3_obj, f3); +mp_obj_t fvar(size_t, const mp_obj_t *); +MP_DEFINE_CONST_FUN_OBJ_VAR(fvar_obj, 1, fvar); +mp_obj_t fvarbetween(size_t, const mp_obj_t *); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fvarbetween_obj, 1, 2, fvarbetween); +mp_obj_t fkw(size_t, const mp_obj_t *, mp_map_t *); +MP_DEFINE_CONST_FUN_OBJ_KW(fkw_obj, 1, fkw); + +static const mp_rom_map_elem_t table[] = { + { MP_ROM_QSTR(MP_QSTR_f0), MP_ROM_PTR(&f0_obj) }, +}; +MP_DEFINE_CONST_MAP(map, table); +MP_DEFINE_CONST_DICT(dict, table); + +static const qstr attrtuple_fields[] = { + MP_QSTR_f0, +}; +MP_DEFINE_ATTRTUPLE(attrtuple, attrtuple_fields, 1, MP_ROM_PTR(&f0_obj)); + +void nlr_cb(void *); +void nlr_cb(void *){ +} + +// The MP_DEFINE_CONST_OBJ_TYPE macro is not C++-compatible because each of the +// MP_DEFINE_CONST_OBJ_TYPE_NARGS_X macros only initializes some of _mp_obj_type_t's +// .slot_index_xxx members but that cannot be fixed to be done in a deterministic way. + + #if defined(MICROPY_UNIX_COVERAGE) // Just to test building of C++ code. static mp_obj_t extra_cpp_coverage_impl() { + MP_DEFINE_NLR_JUMP_CALLBACK_FUNCTION_1(ctx, nlr_cb, (void *) nlr_cb); + + // To avoid 'error: unused variable [-Werror,-Wunused-const-variable]'. + (void) ctx; + (void) f0_obj; + (void) f1_obj; + (void) f2_obj; + (void) f3_obj; + (void) fvar_obj; + (void) fvarbetween_obj; + (void) fkw_obj; + (void) map; + (void) dict; + (void) attrtuple; return mp_const_none; } diff --git a/ports/unix/input.c b/ports/unix/input.c index 31926a5a8e1..260e9eac8c9 100644 --- a/ports/unix/input.c +++ b/ports/unix/input.c @@ -104,6 +104,9 @@ void prompt_write_history(void) { #if MICROPY_USE_READLINE == 1 char *home = getenv("HOME"); if (home != NULL) { + if (MP_STATE_THREAD(gc_lock_depth) != 0) { + return; + } vstr_t vstr; vstr_init(&vstr, 50); vstr_printf(&vstr, "%s/.micropython.history", home); diff --git a/ports/unix/main.c b/ports/unix/main.c index 259b183eb76..e42400fe5f9 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -54,9 +54,11 @@ #include "extmod/vfs_posix.h" #include "genhdr/mpversion.h" #include "input.h" +#include "stack_size.h" +#include "shared/runtime/pyexec.h" // Command line options, with their defaults -static bool compile_only = false; +bool mp_compile_only = false; static uint emit_opt = MP_EMIT_OPT_NONE; #if MICROPY_ENABLE_GC @@ -90,7 +92,8 @@ static void stderr_print_strn(void *env, const char *str, size_t len) { const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; -#define FORCED_EXIT (0x100) +// CIRCUITPY-CHANGE: be consistent about using PYEXEC_FORCED_EXIT +// #define FORCED_EXIT (0x100) // If exc is SystemExit, return value where FORCED_EXIT bit set, // and lower 8 bits are SystemExit value. For all other exceptions, // return 1. @@ -103,7 +106,8 @@ static int handle_uncaught_exception(mp_obj_base_t *exc) { if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { val = 1; } - return FORCED_EXIT | (val & 255); + // CIRCUITPY-CHANGE: be consistent about using PYEXEC_FORCED_EXIT + return PYEXEC_FORCED_EXIT | (val & 255); } // Report all other exceptions @@ -112,8 +116,6 @@ static int handle_uncaught_exception(mp_obj_base_t *exc) { } #define LEX_SRC_STR (1) -#define LEX_SRC_VSTR (2) -#define LEX_SRC_FILENAME (3) #define LEX_SRC_STDIN (4) // Returns standard error codes: 0 for success, 1 for all other errors, @@ -129,19 +131,13 @@ static int execute_from_lexer(int source_kind, const void *source, mp_parse_inpu if (source_kind == LEX_SRC_STR) { const char *line = source; lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); - } else if (source_kind == LEX_SRC_VSTR) { - const vstr_t *vstr = source; - lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, false); - } else if (source_kind == LEX_SRC_FILENAME) { - const char *filename = (const char *)source; - lex = mp_lexer_new_from_file(qstr_from_str(filename)); } else { // LEX_SRC_STDIN lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); } qstr source_name = lex->source_name; - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ if (input_kind == MP_PARSE_FILE_INPUT) { mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); } @@ -160,7 +156,7 @@ static int execute_from_lexer(int source_kind, const void *source, mp_parse_inpu mp_obj_t module_fun = mp_compile(&parse_tree, source_name, is_repl); - if (!compile_only) { + if (!mp_compile_only) { // execute it mp_call_function_0(module_fun); } @@ -197,92 +193,32 @@ static char *strjoin(const char *s1, int sep_char, const char *s2) { #endif static int do_repl(void) { - mp_hal_stdout_tx_str(MICROPY_BANNER_NAME_AND_VERSION); - mp_hal_stdout_tx_str("; " MICROPY_BANNER_MACHINE); - mp_hal_stdout_tx_str("\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); - #if MICROPY_USE_READLINE == 1 - // use MicroPython supplied readline + // use MicroPython supplied readline-based REPL - vstr_t line; - vstr_init(&line, 16); + int ret = 0; for (;;) { - mp_hal_stdio_mode_raw(); - - input_restart: - vstr_reset(&line); - int ret = readline(&line, mp_repl_get_ps1()); - mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; - - if (ret == CHAR_CTRL_C) { - // cancel input - mp_hal_stdout_tx_str("\r\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // EOF - printf("\n"); - mp_hal_stdio_mode_orig(); - vstr_clear(&line); - return 0; - } else if (ret == CHAR_CTRL_E) { - // paste mode - mp_hal_stdout_tx_str("\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== "); - vstr_reset(&line); - for (;;) { - char c = mp_hal_stdin_rx_chr(); - if (c == CHAR_CTRL_C) { - // cancel everything - mp_hal_stdout_tx_str("\n"); - goto input_restart; - } else if (c == CHAR_CTRL_D) { - // end of input - mp_hal_stdout_tx_str("\n"); - break; - } else { - // add char to buffer and echo - vstr_add_byte(&line, c); - if (c == '\r') { - mp_hal_stdout_tx_str("\n=== "); - } else { - mp_hal_stdout_tx_strn(&c, 1); - } - } - } - parse_input_kind = MP_PARSE_FILE_INPUT; - } else if (line.len == 0) { - if (ret != 0) { - printf("\n"); + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if ((ret = pyexec_raw_repl()) != 0) { + break; } - goto input_restart; } else { - // got a line with non-zero length, see if it needs continuing - while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { - vstr_add_byte(&line, '\n'); - ret = readline(&line, mp_repl_get_ps2()); - if (ret == CHAR_CTRL_C) { - // cancel everything - printf("\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // stop entering compound statement - break; - } + if ((ret = pyexec_friendly_repl()) != 0) { + break; } } - - mp_hal_stdio_mode_orig(); - - ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); - if (ret & FORCED_EXIT) { - return ret; - } } + return ret; #else // use simple readline + mp_hal_stdout_tx_str(MICROPY_BANNER_NAME_AND_VERSION); + mp_hal_stdout_tx_str("; " MICROPY_BANNER_MACHINE); + mp_hal_stdout_tx_str("\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); + for (;;) { char *line = prompt((char *)mp_repl_get_ps1()); if (line == NULL) { @@ -302,7 +238,8 @@ static int do_repl(void) { int ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); free(line); - if (ret & FORCED_EXIT) { + // CIRCUITPY-CHANGE: be consistent about using PYEXEC_FORCED_EXIT + if (ret & PYEXEC_FORCED_EXIT) { return ret; } } @@ -310,12 +247,44 @@ static int do_repl(void) { #endif } +static inline int convert_pyexec_result(int ret) { + #if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING + // With exit code handling enabled: + // pyexec returns exit code with PYEXEC_FORCED_EXIT flag set for SystemExit + // Unix port expects: 0 for success, non-zero for error/exit + if (ret & PYEXEC_FORCED_EXIT) { + // SystemExit: extract exit code from lower bits + return ret & 0xFF; + } + // Normal execution or exception: return as-is (0 for success, 1 for exception) + return ret; + #else + // pyexec returns 1 for success, 0 for exception, PYEXEC_FORCED_EXIT for SystemExit + // Convert to unix port's expected codes: 0 for success, 1 for exception, FORCED_EXIT|val for SystemExit + if (ret == 1) { + return 0; // success + } else if (ret & PYEXEC_FORCED_EXIT) { + return ret; // SystemExit with exit value in lower 8 bits + } else { + return 1; // exception + } + #endif +} + static int do_file(const char *file) { - return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); + // CIRCUITPY-CHANGE: pyexec_file result arg + pyexec_result_t pyexec_result; + return convert_pyexec_result(pyexec_file(file, &pyexec_result)); } static int do_str(const char *str) { - return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); + vstr_t vstr; + vstr.buf = (char *)str; + vstr.len = strlen(str); + // CIRCUITPY-CHANGE: pyexec_vstr result arg + pyexec_result_t pyexec_result; + int ret = pyexec_vstr(&vstr, true, &pyexec_result); + return convert_pyexec_result(ret); } static void print_help(char **argv) { @@ -384,7 +353,7 @@ static void pre_process_options(int argc, char **argv) { } if (0) { } else if (strcmp(argv[a + 1], "compile-only") == 0) { - compile_only = true; + mp_compile_only = true; } else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { emit_opt = MP_EMIT_OPT_BYTECODE; #if MICROPY_EMIT_NATIVE @@ -456,10 +425,13 @@ static void set_sys_argv(char *argv[], int argc, int start_arg) { #if MICROPY_PY_SYS_EXECUTABLE extern mp_obj_str_t mp_sys_executable_obj; -static char executable_path[MICROPY_ALLOC_PATH_MAX]; +static char *executable_path = NULL; static void sys_set_excecutable(char *argv0) { - if (realpath(argv0, executable_path)) { + if (executable_path == NULL) { + executable_path = realpath(argv0, NULL); + } + if (executable_path != NULL) { mp_obj_str_set_data(&mp_sys_executable_obj, (byte *)executable_path, strlen(executable_path)); } } @@ -479,11 +451,7 @@ int main(int argc, char **argv) { #endif // Define a reasonable stack limit to detect stack overflow. - mp_uint_t stack_size = 40000 * (sizeof(void *) / 4); - #if defined(__arm__) && !defined(__thumb2__) - // ARM (non-Thumb) architectures require more stack. - stack_size *= 2; - #endif + mp_uint_t stack_size = 40000 * UNIX_STACK_MULTIPLIER; // We should capture stack top ASAP after start, and it should be // captured guaranteedly before any other stack variables are allocated. @@ -619,19 +587,6 @@ MP_NOINLINE int main_(int argc, char **argv) { } #endif - // Here is some example code to create a class and instance of that class. - // First is the Python, then the C code. - // - // class TestClass: - // pass - // test_obj = TestClass() - // test_obj.attr = 42 - // - // mp_obj_t test_class_type, test_class_instance; - // test_class_type = mp_obj_new_type(qstr_from_str("TestClass"), mp_const_empty_tuple, mp_obj_new_dict(0)); - // mp_store_name(qstr_from_str("test_obj"), test_class_instance = mp_call_function_0(test_class_type)); - // mp_store_attr(test_class_instance, qstr_from_str("attr"), mp_obj_new_int(42)); - /* printf("bytes:\n"); printf(" total %d\n", m_get_total_bytes_allocated()); @@ -685,12 +640,18 @@ MP_NOINLINE int main_(int argc, char **argv) { subpkg_tried = false; reimport: + mp_hal_set_interrupt_char(CHAR_CTRL_C); if (nlr_push(&nlr) == 0) { mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); + mp_hal_set_interrupt_char(-1); + mp_handle_pending(true); nlr_pop(); } else { // uncaught exception - return handle_uncaught_exception(nlr.ret_val) & 0xff; + mp_hal_set_interrupt_char(-1); + mp_handle_pending(false); + ret = handle_uncaught_exception(nlr.ret_val) & 0xff; + break; } // If this module is a package, see if it has a `__main__.py`. @@ -727,11 +688,9 @@ MP_NOINLINE int main_(int argc, char **argv) { return invalid_args(); } } else { - char *pathbuf = malloc(PATH_MAX); - char *basedir = realpath(argv[a], pathbuf); + char *basedir = realpath(argv[a], NULL); if (basedir == NULL) { mp_printf(&mp_stderr_print, "%s: can't open file '%s': [Errno %d] %s\n", argv[0], argv[a], errno, strerror(errno)); - free(pathbuf); // CPython exits with 2 in such case ret = 2; break; @@ -740,7 +699,7 @@ MP_NOINLINE int main_(int argc, char **argv) { // Set base dir of the script as first entry in sys.path. char *p = strrchr(basedir, '/'); mp_obj_list_store(mp_sys_path, MP_OBJ_NEW_SMALL_INT(0), mp_obj_new_str_via_qstr(basedir, p - basedir)); - free(pathbuf); + free(basedir); set_sys_argv(argv, argc, a); ret = do_file(argv[a]); @@ -780,7 +739,7 @@ MP_NOINLINE int main_(int argc, char **argv) { #endif #if MICROPY_PY_BLUETOOTH - void mp_bluetooth_deinit(void); + int mp_bluetooth_deinit(void); mp_bluetooth_deinit(); #endif @@ -806,8 +765,20 @@ MP_NOINLINE int main_(int argc, char **argv) { #endif #endif + #if MICROPY_PY_SYS_EXECUTABLE && !defined(NDEBUG) + // Again, make memory leak detector happy + free(executable_path); + #endif + // printf("total bytes = %d\n", m_get_total_bytes_allocated()); - return ret & 0xff; + + // CIRCUITPY-CHANGE: handle PYEXEC_EXCEPTION + if (ret & PYEXEC_EXCEPTION) { + // Return exit status code 1 so the invoker knows there was an uncaught exception. + return 1; + } else { + return ret & 0xff; + } } void nlr_jump_fail(void *val) { diff --git a/ports/unix/modtime.c b/ports/unix/modtime.c index fbd94b5ecd1..4f0550dbea7 100644 --- a/ports/unix/modtime.c +++ b/ports/unix/modtime.c @@ -34,6 +34,7 @@ #include "py/mphal.h" #include "py/runtime.h" +#include "shared/timeutils/timeutils.h" #ifdef _WIN32 static inline int msec_sleep_tv(struct timeval *tv) { @@ -130,12 +131,7 @@ static mp_obj_t mod_time_gm_local_time(size_t n_args, const mp_obj_t *args, stru if (n_args == 0) { t = time(NULL); } else { - #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE - mp_float_t val = mp_obj_get_float(args[0]); - t = (time_t)MICROPY_FLOAT_C_FUN(trunc)(val); - #else - t = mp_obj_get_int(args[0]); - #endif + t = (time_t)timeutils_obj_get_timestamp(args[0]); } struct tm *tm = time_func(&t); @@ -193,10 +189,10 @@ static mp_obj_t mod_time_mktime(mp_obj_t tuple) { time.tm_isdst = -1; // auto-detect } time_t ret = mktime(&time); - if (ret == -1) { + if (ret == (time_t)-1) { mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("invalid mktime usage")); } - return mp_obj_new_int(ret); + return timeutils_obj_from_timestamp(ret); } MP_DEFINE_CONST_FUN_OBJ_1(mod_time_mktime_obj, mod_time_mktime); diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 4d9fe9f1dc4..815be76b4e9 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -32,6 +32,9 @@ // features to work on Unix-like systems, see mpconfigvariant.h (and // mpconfigvariant_common.h) for feature enabling. +// For time_t, needed by MICROPY_TIMESTAMP_IMPL_TIME_T. +#include + // For size_t and ssize_t #include @@ -41,6 +44,7 @@ // CIRCUITPY-CHANGE #define CIRCUITPY_MICROPYTHON_ADVANCED (1) #define MICROPY_PY_ASYNC_AWAIT (1) +#define MICROPY_PY_DOUBLE_TYPECODE (1) #define MICROPY_PY_UCTYPES (0) #ifndef MICROPY_CONFIG_ROM_LEVEL @@ -78,21 +82,6 @@ #define MICROPY_EMIT_ARM (1) #endif -// Type definitions for the specific machine based on the word size. -#ifndef MICROPY_OBJ_REPR -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless of actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif -#else -// Assume that if we already defined the obj repr then we also defined types. -#endif - // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; @@ -135,6 +124,9 @@ typedef long mp_off_t; // VFS stat functions should return time values relative to 1970/1/1 #define MICROPY_EPOCH_IS_1970 (1) +// port modtime functions use time_t +#define MICROPY_TIMESTAMP_IMPL (MICROPY_TIMESTAMP_IMPL_TIME_T) + // Assume that select() call, interrupted with a signal, and erroring // with EINTR, updates remaining timeout value. #define MICROPY_SELECT_REMAINING_TIME (1) @@ -145,6 +137,9 @@ typedef long mp_off_t; #define MICROPY_STACKLESS_STRICT (0) #endif +// Recursive mutex is needed when threading is enabled, regardless of GIL setting. +#define MICROPY_PY_THREAD_RECURSIVE_MUTEX (MICROPY_PY_THREAD) + // Implementation of the machine module. #define MICROPY_PY_MACHINE_INCLUDEFILE "ports/unix/modmachine.c" @@ -172,6 +167,12 @@ typedef long mp_off_t; // Enable sys.executable. #define MICROPY_PY_SYS_EXECUTABLE (1) +// Enable support for compile-only mode. +#define MICROPY_PYEXEC_COMPILE_ONLY (1) + +// Enable handling of sys.exit() exit codes. +#define MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING (1) + #define MICROPY_PY_SOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128) // Bare-metal ports don't have stderr. Printing debug to stderr may give tests diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index 26c04faf4c5..c836663cd23 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -14,6 +14,7 @@ MICROPY_PY_BTREE = 0 # _thread module using pthreads MICROPY_PY_THREAD = 1 +MICROPY_PY_THREAD_GIL = 0 # Subset of CPython termios module MICROPY_PY_TERMIOS = 1 diff --git a/ports/unix/mphalport.h b/ports/unix/mphalport.h index 7f71217632a..d9cd05b3de8 100644 --- a/ports/unix/mphalport.h +++ b/ports/unix/mphalport.h @@ -25,7 +25,6 @@ */ #include #include -// CIRCUITPY-CHANGE: extra include #include #ifndef CHAR_CTRL_C @@ -38,6 +37,20 @@ #define MICROPY_END_ATOMIC_SECTION(x) (void)x; mp_thread_unix_end_atomic_section() #endif +// In lieu of a WFI(), slow down polling from being a tight loop. +// +// Note that we don't delay for the full TIMEOUT_MS, as execution +// can't be woken from the delay. +#define MICROPY_INTERNAL_WFE(TIMEOUT_MS) \ + do { \ + MP_THREAD_GIL_EXIT(); \ + mp_hal_delay_us(500); \ + MP_THREAD_GIL_ENTER(); \ + } while (0) + +// The port provides `mp_hal_stdio_mode_raw()` and `mp_hal_stdio_mode_orig()`. +#define MICROPY_HAL_HAS_STDIO_MODE_SWITCH (1) + // CIRCUITPY-CHANGE: mp_hal_set_interrupt_char(int) instead of char void mp_hal_set_interrupt_char(int c); bool mp_hal_is_interrupted(void); @@ -110,3 +123,6 @@ enum { void mp_hal_get_mac(int idx, uint8_t buf[6]); #endif + +// Global variable to control compile-only mode. +extern bool mp_compile_only; diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c index 5172645bc14..a41b3ec9f47 100644 --- a/ports/unix/mpthreadport.c +++ b/ports/unix/mpthreadport.c @@ -31,6 +31,7 @@ #include "py/runtime.h" #include "py/mpthread.h" #include "py/gc.h" +#include "stack_size.h" #if MICROPY_PY_THREAD @@ -45,8 +46,14 @@ // potential conflict with other uses of the more commonly used SIGUSR1. #ifdef SIGRTMIN #define MP_THREAD_GC_SIGNAL (SIGRTMIN + 5) +#ifdef __ANDROID__ +#define MP_THREAD_TERMINATE_SIGNAL (SIGRTMIN + 6) +#endif #else #define MP_THREAD_GC_SIGNAL (SIGUSR1) +#ifdef __ANDROID__ +#define MP_THREAD_TERMINATE_SIGNAL (SIGUSR2) +#endif #endif // This value seems to be about right for both 32-bit and 64-bit builds. @@ -107,6 +114,18 @@ static void mp_thread_gc(int signo, siginfo_t *info, void *context) { } } +// On Android, pthread_cancel and pthread_setcanceltype are not implemented. +// To achieve that result a new signal handler responding on either +// (SIGRTMIN + 6) or SIGUSR2 is installed on every child thread. The sole +// purpose of this new signal handler is to terminate the thread in a safe +// asynchronous manner. + +#ifdef __ANDROID__ +static void mp_thread_terminate(int signo, siginfo_t *info, void *context) { + pthread_exit(NULL); +} +#endif + void mp_thread_init(void) { pthread_key_create(&tls_key, NULL); pthread_setspecific(tls_key, &mp_state_ctx.thread); @@ -135,6 +154,14 @@ void mp_thread_init(void) { sa.sa_sigaction = mp_thread_gc; sigemptyset(&sa.sa_mask); sigaction(MP_THREAD_GC_SIGNAL, &sa, NULL); + + // Install a signal handler for asynchronous termination if needed. + #if defined(__ANDROID__) + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = mp_thread_terminate; + sigemptyset(&sa.sa_mask); + sigaction(MP_THREAD_TERMINATE_SIGNAL, &sa, NULL); + #endif } void mp_thread_deinit(void) { @@ -142,7 +169,11 @@ void mp_thread_deinit(void) { while (thread->next != NULL) { mp_thread_t *th = thread; thread = thread->next; + #if defined(__ANDROID__) + pthread_kill(th->id, MP_THREAD_TERMINATE_SIGNAL); + #else pthread_cancel(th->id); + #endif free(th); } mp_thread_unix_end_atomic_section(); @@ -200,7 +231,9 @@ void mp_thread_start(void) { } #endif + #if !defined(__ANDROID__) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + #endif mp_thread_unix_begin_atomic_section(); for (mp_thread_t *th = thread; th != NULL; th = th->next) { if (th->id == pthread_self()) { @@ -212,14 +245,14 @@ void mp_thread_start(void) { } mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { - // default stack size is 8k machine-words + // default stack size if (*stack_size == 0) { - *stack_size = 8192 * sizeof(void *); + *stack_size = 32768 * UNIX_STACK_MULTIPLIER; } // minimum stack size is set by pthreads - if (*stack_size < PTHREAD_STACK_MIN) { - *stack_size = PTHREAD_STACK_MIN; + if (*stack_size < (size_t)PTHREAD_STACK_MIN) { + *stack_size = (size_t)PTHREAD_STACK_MIN; } // ensure there is enough stack to include a stack-overflow margin diff --git a/ports/unix/stack_size.h b/ports/unix/stack_size.h new file mode 100644 index 00000000000..f6159bb69d5 --- /dev/null +++ b/ports/unix/stack_size.h @@ -0,0 +1,54 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2025 Angus Gratton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_UNIX_STACK_SIZE_H +#define MICROPY_INCLUDED_UNIX_STACK_SIZE_H + +#include "py/misc.h" + +// Define scaling factors for the stack size (also applies to main thread) +#ifndef UNIX_STACK_MULTIPLIER + +#if defined(__arm__) && !defined(__thumb2__) +// ARM (non-Thumb) architectures require more stack. +#define UNIX_STACK_MUL_ARM 2 +#else +#define UNIX_STACK_MUL_ARM 1 +#endif + +#if MP_SANITIZER_BUILD +// Sanitizer features consume significant stack in some cases +// This multiplier can probably be removed when using GCC 12 or newer. +#define UNIX_STACK_MUL_SANITIZERS 4 +#else +#define UNIX_STACK_MUL_SANITIZERS 1 +#endif + +// Double the stack size for 64-bit builds, plus additional scaling +#define UNIX_STACK_MULTIPLIER ((sizeof(void *) / 4) * UNIX_STACK_MUL_ARM * UNIX_STACK_MUL_SANITIZERS) + +#endif // UNIX_STACK_MULTIPLIER + +#endif // MICROPY_INCLUDED_UNIX_STACK_SIZE_H diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index ca79d3d0d2b..03f77ec14c6 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -39,11 +39,22 @@ // Enable additional features. #define MICROPY_DEBUG_PARSE_RULE_NAME (1) +// CIRCUITPY-CHANGE: off +#define MICROPY_PY_SYS_SETTRACE (0) #define MICROPY_TRACKED_ALLOC (1) #define MICROPY_WARNINGS_CATEGORY (1) #undef MICROPY_VFS_ROM_IOCTL #define MICROPY_VFS_ROM_IOCTL (1) #define MICROPY_PY_CRYPTOLIB_CTR (1) +// CIRCUITPY-CHANGE: off +#define MICROPY_SCHEDULER_STATIC_NODES (0) + +// Enable os.uname for attrtuple coverage test +#define MICROPY_PY_OS_UNAME (1) +#define MICROPY_HW_BOARD_NAME "a machine" +#define MICROPY_HW_MCU_NAME MICROPY_PY_SYS_PLATFORM +// Keep the standard banner message +#define MICROPY_BANNER_MACHINE MICROPY_PY_SYS_PLATFORM " [" MICROPY_PLATFORM_COMPILER "] version" // CIRCUITPY-CHANGE: Disable things never used in circuitpython #define MICROPY_PY_CRYPTOLIB (0) diff --git a/ports/unix/variants/longlong/mpconfigvariant.h b/ports/unix/variants/longlong/mpconfigvariant.h new file mode 100644 index 00000000000..d50d360b1fe --- /dev/null +++ b/ports/unix/variants/longlong/mpconfigvariant.h @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// This config exists to test that the MICROPY_LONGINT_IMPL_LONGLONG variant +// (i.e. minimal form of "big integer" that's backed by 64-bit int only) builds +// and passes tests. + +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) + +// We build it on top of REPR C, which uses memory-efficient floating point +// objects encoded directly mp_obj_t (30 bits only). +// Therefore this variant should be built using MICROPY_FORCE_32BIT=1 + +#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) + +// Set base feature level. +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" diff --git a/ports/unix/variants/longlong/mpconfigvariant.mk b/ports/unix/variants/longlong/mpconfigvariant.mk new file mode 100644 index 00000000000..2d2c3706469 --- /dev/null +++ b/ports/unix/variants/longlong/mpconfigvariant.mk @@ -0,0 +1,8 @@ +# build interpreter with "bigints" implemented as "longlong" + +# otherwise, small int is essentially 64-bit +MICROPY_FORCE_32BIT := 1 + +MICROPY_PY_FFI := 0 + +MPY_TOOL_FLAGS = -mlongint-impl longlong diff --git a/ports/unix/variants/minimal/mpconfigvariant.h b/ports/unix/variants/minimal/mpconfigvariant.h index 97ed786b8f4..0e280a8f730 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.h +++ b/ports/unix/variants/minimal/mpconfigvariant.h @@ -49,6 +49,7 @@ #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #define MICROPY_ENABLE_COMPILER (1) #define MICROPY_ENABLE_EXTERNAL_IMPORT (1) +#define MICROPY_STACK_CHECK (1) #define MICROPY_FULL_CHECKS (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_KBD_EXCEPTION (1) @@ -61,6 +62,5 @@ #define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) #define MICROPY_PY_GENERATOR_PEND_THROW (1) -// Enable just the sys and os built-in modules. -#define MICROPY_PY_SYS (1) +// Add just the os built-in module. #define MICROPY_PY_OS (1) diff --git a/ports/unix/variants/mpconfigvariant_common.h b/ports/unix/variants/mpconfigvariant_common.h index 9eeed879736..1ac59c95572 100644 --- a/ports/unix/variants/mpconfigvariant_common.h +++ b/ports/unix/variants/mpconfigvariant_common.h @@ -29,7 +29,7 @@ // Send raise KeyboardInterrupt directly from the signal handler rather than // scheduling it into the VM. -#define MICROPY_ASYNC_KBD_INTR (1) +#define MICROPY_ASYNC_KBD_INTR (!MICROPY_PY_THREAD_GIL) // Enable helpers for printing debugging information. #ifndef MICROPY_DEBUG_PRINTERS @@ -104,12 +104,6 @@ #define MICROPY_PY_TIME_CUSTOM_SLEEP (1) #define MICROPY_PY_TIME_INCLUDEFILE "ports/unix/modtime.c" -#if MICROPY_PY_SSL -#define MICROPY_PY_HASHLIB_MD5 (1) -#define MICROPY_PY_HASHLIB_SHA1 (1) -#define MICROPY_PY_CRYPTOLIB (1) -#endif - // The "select" module is enabled by default, but disable select.select(). #define MICROPY_PY_SELECT_POSIX_OPTIMISATIONS (1) #define MICROPY_PY_SELECT_SELECT (0) diff --git a/ports/unix/variants/nanbox/mpconfigvariant.h b/ports/unix/variants/nanbox/mpconfigvariant.h index 7b13b7dc6ce..c9e9c1f63d9 100644 --- a/ports/unix/variants/nanbox/mpconfigvariant.h +++ b/ports/unix/variants/nanbox/mpconfigvariant.h @@ -41,10 +41,3 @@ #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_ARM (0) - -#include - -typedef int64_t mp_int_t; -typedef uint64_t mp_uint_t; -#define UINT_FMT "%llu" -#define INT_FMT "%lld" diff --git a/ports/zephyr-cp/AGENTS.md b/ports/zephyr-cp/AGENTS.md new file mode 100644 index 00000000000..58a3912e2ba --- /dev/null +++ b/ports/zephyr-cp/AGENTS.md @@ -0,0 +1,7 @@ +- Build a board by doing `make BOARD=_`. +- The corresponding configuration files are in `boards//` +- The files (not folders) in `boards/` directory are used by Zephyr. +- To flash it on a board do `make BOARD=_ flash`. +- Zephyr board docs are at `zephyr/boards//`. +- Run zephyr-cp tests with `make test`. +- Do not add new translatable error strings (`MP_ERROR_TEXT`). Instead, use `raise_zephyr_error()` or `CHECK_ZEPHYR_RESULT()` from `bindings/zephyr_kernel/__init__.h` to convert Zephyr errno values into Python exceptions. diff --git a/ports/zephyr-cp/CLAUDE.md b/ports/zephyr-cp/CLAUDE.md new file mode 100644 index 00000000000..43c994c2d36 --- /dev/null +++ b/ports/zephyr-cp/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/ports/zephyr-cp/CMakeLists.txt b/ports/zephyr-cp/CMakeLists.txt index 0ba4a3c48b3..9d115f1e176 100644 --- a/ports/zephyr-cp/CMakeLists.txt +++ b/ports/zephyr-cp/CMakeLists.txt @@ -10,6 +10,10 @@ if(CONFIG_BOARD_NATIVE_SIM) target_sources(app PRIVATE native_sim_i2c_emul_control.c) endif() +if(CONFIG_TRACING_PERFETTO) + zephyr_include_directories(${ZEPHYR_BINARY_DIR}/subsys/tracing/perfetto/proto) +endif() + # From: https://github.com/zephyrproject-rtos/zephyr/blob/main/samples/application_development/external_lib/CMakeLists.txt # The external static library that we are linking with does not know # how to build for this platform so we export all the flags used in diff --git a/ports/zephyr-cp/Kconfig.sysbuild b/ports/zephyr-cp/Kconfig.sysbuild index cd74ff13592..11b49446f42 100644 --- a/ports/zephyr-cp/Kconfig.sysbuild +++ b/ports/zephyr-cp/Kconfig.sysbuild @@ -8,6 +8,7 @@ config NET_CORE_BOARD default "nrf5340dk/nrf5340/cpunet" if $(BOARD) = "nrf5340dk" default "nrf7002dk/nrf5340/cpunet" if $(BOARD) = "nrf7002dk" default "nrf5340_audio_dk/nrf5340/cpunet" if $(BOARD) = "nrf5340_audio_dk" + default "nrf5340bsim/nrf5340/cpunet" if $(BOARD) = "nrf5340bsim" config NET_CORE_IMAGE_HCI_IPC bool "HCI IPC image on network core" diff --git a/ports/zephyr-cp/Makefile b/ports/zephyr-cp/Makefile index 622fe4901a9..ab730a8b339 100644 --- a/ports/zephyr-cp/Makefile +++ b/ports/zephyr-cp/Makefile @@ -8,11 +8,27 @@ BUILD ?= build-$(BOARD) TRANSLATION ?= en_US -.PHONY: $(BUILD)/zephyr-cp/zephyr/zephyr.elf flash debug run clean menuconfig all clean-all test fetch-port-submodules +# Compute shield args once. Command-line SHIELD/SHIELDS values override board defaults from circuitpython.toml. +ifneq ($(strip $(BOARD)),) +WEST_SHIELD_ARGS := $(shell SHIELD_ORIGIN="$(origin SHIELD)" SHIELDS_ORIGIN="$(origin SHIELDS)" SHIELD="$(SHIELD)" SHIELDS="$(SHIELDS)" python cptools/get_west_shield_args.py $(BOARD)) +endif + +WEST_CMAKE_ARGS := -DZEPHYR_BOARD_ALIASES=$(CURDIR)/boards/board_aliases.cmake -Dzephyr-cp_TRANSLATION=$(TRANSLATION) + +# When DEBUG=1, apply additional Kconfig fragments for debug-friendly settings. +DEBUG_CONF_FILE ?= $(CURDIR)/debug.conf +ifeq ($(DEBUG),1) +WEST_CMAKE_ARGS += -Dzephyr-cp_EXTRA_CONF_FILE=$(DEBUG_CONF_FILE) +endif + +.PHONY: $(BUILD)/zephyr-cp/zephyr/zephyr.elf flash recover debug debug-jlink debugserver attach run run-sim clean menuconfig all clean-all sim clean-sim test fetch-port-submodules + +export BSIM_COMPONENTS_PATH := $(CURDIR)/tools/bsim/components +export BSIM_OUT_PATH := $(CURDIR)/tools/bsim $(BUILD)/zephyr-cp/zephyr/zephyr.elf: python cptools/pre_zephyr_build_prep.py $(BOARD) - west build -b $(BOARD) -d $(BUILD) --sysbuild -- -DZEPHYR_BOARD_ALIASES=$(CURDIR)/boards/board_aliases.cmake -Dzephyr-cp_TRANSLATION=$(TRANSLATION) + west build -b $(BOARD) -d $(BUILD) $(WEST_SHIELD_ARGS) --sysbuild -- $(WEST_CMAKE_ARGS) $(BUILD)/firmware.elf: $(BUILD)/zephyr-cp/zephyr/zephyr.elf cp $^ $@ @@ -23,17 +39,42 @@ $(BUILD)/firmware.hex: $(BUILD)/zephyr-cp/zephyr/zephyr.elf $(BUILD)/firmware.exe: $(BUILD)/zephyr-cp/zephyr/zephyr.elf cp $(BUILD)/zephyr-cp/zephyr/zephyr.exe $@ +$(BUILD)/firmware.uf2: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + cp $(BUILD)/zephyr-cp/zephyr/zephyr.uf2 $@ + flash: $(BUILD)/zephyr-cp/zephyr/zephyr.elf west flash -d $(BUILD) +recover: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west flash --recover -d $(BUILD) + debug: $(BUILD)/zephyr-cp/zephyr/zephyr.elf west debug -d $(BUILD) +debug-jlink: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west debug --runner jlink -d $(BUILD) + +debugserver: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west debugserver -d $(BUILD) + +attach: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west attach -d $(BUILD) + run: $(BUILD)/firmware.exe $^ +run-sim: + $(MAKE) BOARD=native_native_sim BUILD=build-native_native_sim build-native_native_sim/firmware.exe + truncate -s 2M build-native_native_sim/flash.bin + mformat -i build-native_native_sim/flash.bin :: + @if [ -d CIRCUITPY ] && [ -n "$$(find CIRCUITPY -mindepth 1 -print -quit)" ]; then \ + echo "Populating build-native_native_sim/flash.bin from ./CIRCUITPY"; \ + mcopy -s -i build-native_native_sim/flash.bin CIRCUITPY/* ::; \ + fi + build-native_native_sim/firmware.exe --flash=build-native_native_sim/flash.bin --flash_rm -wait_uart -rt --i2s_capture=build-native_native_sim/i2s_capture.wav + menuconfig: - west build --sysbuild -d $(BUILD) -t menuconfig + west build $(WEST_SHIELD_ARGS) --sysbuild -d $(BUILD) -t menuconfig -- $(WEST_CMAKE_ARGS) clean: rm -rf $(BUILD) @@ -49,6 +90,13 @@ all: clean-all: rm -rf build build-* +# Build all sim boards concurrently using the same jobserver as `make all`. +sim: + +python cptools/build_all_boards.py --vendor native --continue-on-error + +clean-sim: + rm -rf $(wildcard build-native_*) + test: build-native_native_sim/zephyr-cp/zephyr/zephyr.exe pytest cptools/tests pytest tests/ -v diff --git a/ports/zephyr-cp/README.md b/ports/zephyr-cp/README.md index 1fba1d7d3f7..162ed90bcc8 100644 --- a/ports/zephyr-cp/README.md +++ b/ports/zephyr-cp/README.md @@ -28,6 +28,77 @@ make BOARD=nordic_nrf7002dk This uses Zephyr's cmake to generate Makefiles that then delegate to `tools/cpbuild/build_circuitpython.py` to build the CircuitPython bits in parallel. +## Native simulator build container + +Building the native sim requires `libsdl2-dev:i386` and other 32bit dependencies that +can cause conflicts on 64bit systems resulting in the removal of 64bit versions of critical +software such as the display manager and network manager. A Containerfile and a few scripts +are provided to set up a container to make the native sim build inside without affecting the +host system. + +The container automatically mounts this instance of the circuitpython repo inside at +`/home/dev/circuitpython`. Changes made in the repo inside the container and on the host PC +will sync automatically between host and container. + +To use the container file: + +1. Build the container with `podman build -t zephyr-cp-dev -f native_sim_build_Containerfile .` +2. Run/Start the container by running `./native_sim_build_run_container.sh` on the host PC. + The script will automatically run or start based on whether the container has been run before. +3. Init requirements inside the container with `./native_sim_build_init_container.sh` + +To delete the container and cleanup associated files: +```sh +podman ps -a --filter ancestor=zephyr-cp-dev -q | xargs -r podman rm -f +podman rmi zephyr-cp-dev +podman image prune -f +podman rm -f zcp +``` + +## Running the native simulator + +From `ports/zephyr-cp`, run: + +```sh +make run-sim +``` + +`run-sim` starts the native simulator in realtime. +It prints the PTY path to connect to the simulator REPL. +If a local `./CIRCUITPY/` folder exists, its files are used as the simulator's CIRCUITPY drive. + +Edit files in `./CIRCUITPY` (for example `code.py`) and rerun `make run-sim` to test changes. + +## Shields + +Board defaults can be set in `boards///circuitpython.toml`: + +```toml +SHIELDS = ["shield1", "shield2"] +``` + +For example, `boards/renesas/ek_ra8d1/circuitpython.toml` enables: + +```toml +SHIELDS = ["rtkmipilcdb00000be"] +``` + +You can override shield selection from the command line: + +```sh +# Single shield +make BOARD=renesas_ek_ra8d1 SHIELD=rtkmipilcdb00000be + +# Multiple shields (comma, semicolon, or space separated) +make BOARD=my_vendor_my_board SHIELDS="shield1,shield2" +``` + +Behavior and precedence: + +- If `SHIELD` or `SHIELDS` is explicitly provided, it overrides board defaults. +- If neither is provided, defaults from `circuitpython.toml` are used. +- Use `SHIELD=` (empty) to disable a board default shield for one build. + ## Testing other boards [Any Zephyr board](https://docs.zephyrproject.org/latest/boards/index.html#) can diff --git a/ports/zephyr-cp/background.c b/ports/zephyr-cp/background.c index 1abc034e878..56e9e98f1f2 100644 --- a/ports/zephyr-cp/background.c +++ b/ports/zephyr-cp/background.c @@ -9,17 +9,7 @@ #include "py/runtime.h" #include "supervisor/port.h" -#if CIRCUITPY_DISPLAYIO -#include "shared-module/displayio/__init__.h" -#endif - -#if CIRCUITPY_AUDIOBUSIO -#include "common-hal/audiobusio/I2SOut.h" -#endif - -#if CIRCUITPY_AUDIOPWMIO -#include "common-hal/audiopwmio/PWMAudioOut.h" -#endif +#include void port_start_background_tick(void) { } @@ -28,12 +18,7 @@ void port_finish_background_tick(void) { } void port_background_tick(void) { - #if CIRCUITPY_AUDIOPWMIO - audiopwmout_background(); - #endif - #if CIRCUITPY_AUDIOBUSIO - i2s_background(); - #endif + // No, ticks. We use Zephyr threads instead. } void port_background_task(void) { diff --git a/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.c b/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.c new file mode 100644 index 00000000000..fc0fb9ecc4f --- /dev/null +++ b/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.c @@ -0,0 +1,37 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "bindings/hostnetwork/HostNetwork.h" + +#include "py/runtime.h" + +//| class HostNetwork: +//| """Native networking for the host simulator.""" +//| +//| def __init__(self) -> None: +//| """Create a HostNetwork instance.""" +//| ... +//| +static mp_obj_t hostnetwork_hostnetwork_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + hostnetwork_hostnetwork_obj_t *self = mp_obj_malloc(hostnetwork_hostnetwork_obj_t, &hostnetwork_hostnetwork_type); + common_hal_hostnetwork_hostnetwork_construct(self); + return MP_OBJ_FROM_PTR(self); +} + +static const mp_rom_map_elem_t hostnetwork_hostnetwork_locals_dict_table[] = { +}; +static MP_DEFINE_CONST_DICT(hostnetwork_hostnetwork_locals_dict, hostnetwork_hostnetwork_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + hostnetwork_hostnetwork_type, + MP_QSTR_HostNetwork, + MP_TYPE_FLAG_NONE, + make_new, hostnetwork_hostnetwork_make_new, + locals_dict, &hostnetwork_hostnetwork_locals_dict + ); diff --git a/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.h b/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.h new file mode 100644 index 00000000000..009d8c06087 --- /dev/null +++ b/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; +} hostnetwork_hostnetwork_obj_t; + +extern const mp_obj_type_t hostnetwork_hostnetwork_type; + +void common_hal_hostnetwork_hostnetwork_construct(hostnetwork_hostnetwork_obj_t *self); diff --git a/ports/zephyr-cp/bindings/hostnetwork/__init__.c b/ports/zephyr-cp/bindings/hostnetwork/__init__.c new file mode 100644 index 00000000000..92302b67d0e --- /dev/null +++ b/ports/zephyr-cp/bindings/hostnetwork/__init__.c @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" + +#include "bindings/hostnetwork/__init__.h" +#include "bindings/hostnetwork/HostNetwork.h" + +//| """Host networking support for the native simulator.""" +//| + +static const mp_rom_map_elem_t hostnetwork_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_hostnetwork) }, + { MP_ROM_QSTR(MP_QSTR_HostNetwork), MP_ROM_PTR(&hostnetwork_hostnetwork_type) }, +}; +static MP_DEFINE_CONST_DICT(hostnetwork_module_globals, hostnetwork_module_globals_table); + +const mp_obj_module_t hostnetwork_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&hostnetwork_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_hostnetwork, hostnetwork_module); diff --git a/ports/zephyr-cp/bindings/hostnetwork/__init__.h b/ports/zephyr-cp/bindings/hostnetwork/__init__.h new file mode 100644 index 00000000000..a6731546bde --- /dev/null +++ b/ports/zephyr-cp/bindings/hostnetwork/__init__.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "bindings/hostnetwork/HostNetwork.h" + +extern hostnetwork_hostnetwork_obj_t common_hal_hostnetwork_obj; diff --git a/ports/zephyr-cp/bindings/zephyr_display/Display.c b/ports/zephyr-cp/bindings/zephyr_display/Display.c new file mode 100644 index 00000000000..0923618c50a --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_display/Display.c @@ -0,0 +1,195 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "bindings/zephyr_display/Display.h" + +#include "py/objproperty.h" +#include "py/objtype.h" +#include "py/runtime.h" +#include "shared-bindings/displayio/Group.h" +#include "shared-module/displayio/__init__.h" + +static mp_obj_t zephyr_display_display_make_new(const mp_obj_type_t *type, + size_t n_args, + size_t n_kw, + const mp_obj_t *all_args) { + (void)type; + (void)n_args; + (void)n_kw; + (void)all_args; + mp_raise_NotImplementedError(NULL); + return mp_const_none; +} + +static zephyr_display_display_obj_t *native_display(mp_obj_t display_obj) { + mp_obj_t native = mp_obj_cast_to_native_base(display_obj, &zephyr_display_display_type); + mp_obj_assert_native_inited(native); + return MP_OBJ_TO_PTR(native); +} + +static mp_obj_t zephyr_display_display_obj_show(mp_obj_t self_in, mp_obj_t group_in) { + (void)self_in; + (void)group_in; + mp_raise_AttributeError(MP_ERROR_TEXT(".show(x) removed. Use .root_group = x")); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_show_obj, zephyr_display_display_obj_show); + +static mp_obj_t zephyr_display_display_obj_refresh(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { + ARG_target_frames_per_second, + ARG_minimum_frames_per_second, + }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_target_frames_per_second, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, + { MP_QSTR_minimum_frames_per_second, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + zephyr_display_display_obj_t *self = native_display(pos_args[0]); + + uint32_t maximum_ms_per_real_frame = NO_FPS_LIMIT; + mp_int_t minimum_frames_per_second = args[ARG_minimum_frames_per_second].u_int; + if (minimum_frames_per_second > 0) { + maximum_ms_per_real_frame = 1000 / minimum_frames_per_second; + } + + uint32_t target_ms_per_frame; + if (args[ARG_target_frames_per_second].u_obj == mp_const_none) { + target_ms_per_frame = NO_FPS_LIMIT; + } else { + target_ms_per_frame = 1000 / mp_obj_get_int(args[ARG_target_frames_per_second].u_obj); + } + + return mp_obj_new_bool(common_hal_zephyr_display_display_refresh( + self, + target_ms_per_frame, + maximum_ms_per_real_frame)); +} +MP_DEFINE_CONST_FUN_OBJ_KW(zephyr_display_display_refresh_obj, 1, zephyr_display_display_obj_refresh); + +static mp_obj_t zephyr_display_display_obj_get_auto_refresh(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return mp_obj_new_bool(common_hal_zephyr_display_display_get_auto_refresh(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_auto_refresh_obj, zephyr_display_display_obj_get_auto_refresh); + +static mp_obj_t zephyr_display_display_obj_set_auto_refresh(mp_obj_t self_in, mp_obj_t auto_refresh) { + zephyr_display_display_obj_t *self = native_display(self_in); + common_hal_zephyr_display_display_set_auto_refresh(self, mp_obj_is_true(auto_refresh)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_set_auto_refresh_obj, zephyr_display_display_obj_set_auto_refresh); + +MP_PROPERTY_GETSET(zephyr_display_display_auto_refresh_obj, + (mp_obj_t)&zephyr_display_display_get_auto_refresh_obj, + (mp_obj_t)&zephyr_display_display_set_auto_refresh_obj); + +static mp_obj_t zephyr_display_display_obj_get_brightness(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + mp_float_t brightness = common_hal_zephyr_display_display_get_brightness(self); + if (brightness < 0) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Brightness not adjustable")); + } + return mp_obj_new_float(brightness); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_brightness_obj, zephyr_display_display_obj_get_brightness); + +static mp_obj_t zephyr_display_display_obj_set_brightness(mp_obj_t self_in, mp_obj_t brightness_obj) { + zephyr_display_display_obj_t *self = native_display(self_in); + mp_float_t brightness = mp_obj_get_float(brightness_obj); + if (brightness < 0.0f || brightness > 1.0f) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be %d-%d"), MP_QSTR_brightness, 0, 1); + } + bool ok = common_hal_zephyr_display_display_set_brightness(self, brightness); + if (!ok) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Brightness not adjustable")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_set_brightness_obj, zephyr_display_display_obj_set_brightness); + +MP_PROPERTY_GETSET(zephyr_display_display_brightness_obj, + (mp_obj_t)&zephyr_display_display_get_brightness_obj, + (mp_obj_t)&zephyr_display_display_set_brightness_obj); + +static mp_obj_t zephyr_display_display_obj_get_width(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_zephyr_display_display_get_width(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_width_obj, zephyr_display_display_obj_get_width); +MP_PROPERTY_GETTER(zephyr_display_display_width_obj, (mp_obj_t)&zephyr_display_display_get_width_obj); + +static mp_obj_t zephyr_display_display_obj_get_height(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_zephyr_display_display_get_height(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_height_obj, zephyr_display_display_obj_get_height); +MP_PROPERTY_GETTER(zephyr_display_display_height_obj, (mp_obj_t)&zephyr_display_display_get_height_obj); + +static mp_obj_t zephyr_display_display_obj_get_rotation(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_zephyr_display_display_get_rotation(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_rotation_obj, zephyr_display_display_obj_get_rotation); + +static mp_obj_t zephyr_display_display_obj_set_rotation(mp_obj_t self_in, mp_obj_t value) { + zephyr_display_display_obj_t *self = native_display(self_in); + common_hal_zephyr_display_display_set_rotation(self, mp_obj_get_int(value)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_set_rotation_obj, zephyr_display_display_obj_set_rotation); + +MP_PROPERTY_GETSET(zephyr_display_display_rotation_obj, + (mp_obj_t)&zephyr_display_display_get_rotation_obj, + (mp_obj_t)&zephyr_display_display_set_rotation_obj); + +static mp_obj_t zephyr_display_display_obj_get_root_group(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return common_hal_zephyr_display_display_get_root_group(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_root_group_obj, zephyr_display_display_obj_get_root_group); + +static mp_obj_t zephyr_display_display_obj_set_root_group(mp_obj_t self_in, mp_obj_t group_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + displayio_group_t *group = NULL; + if (group_in != mp_const_none) { + group = MP_OBJ_TO_PTR(native_group(group_in)); + } + + bool ok = common_hal_zephyr_display_display_set_root_group(self, group); + if (!ok) { + mp_raise_ValueError(MP_ERROR_TEXT("Group already used")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_set_root_group_obj, zephyr_display_display_obj_set_root_group); + +MP_PROPERTY_GETSET(zephyr_display_display_root_group_obj, + (mp_obj_t)&zephyr_display_display_get_root_group_obj, + (mp_obj_t)&zephyr_display_display_set_root_group_obj); + +static const mp_rom_map_elem_t zephyr_display_display_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&zephyr_display_display_show_obj) }, + { MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&zephyr_display_display_refresh_obj) }, + + { MP_ROM_QSTR(MP_QSTR_auto_refresh), MP_ROM_PTR(&zephyr_display_display_auto_refresh_obj) }, + { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&zephyr_display_display_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&zephyr_display_display_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&zephyr_display_display_height_obj) }, + { MP_ROM_QSTR(MP_QSTR_rotation), MP_ROM_PTR(&zephyr_display_display_rotation_obj) }, + { MP_ROM_QSTR(MP_QSTR_root_group), MP_ROM_PTR(&zephyr_display_display_root_group_obj) }, +}; +static MP_DEFINE_CONST_DICT(zephyr_display_display_locals_dict, zephyr_display_display_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + zephyr_display_display_type, + MP_QSTR_Display, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, zephyr_display_display_make_new, + locals_dict, &zephyr_display_display_locals_dict); diff --git a/ports/zephyr-cp/bindings/zephyr_display/Display.h b/ports/zephyr-cp/bindings/zephyr_display/Display.h new file mode 100644 index 00000000000..a50dda8fe8b --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_display/Display.h @@ -0,0 +1,37 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/displayio/Group.h" +#include "common-hal/zephyr_display/Display.h" + +extern const mp_obj_type_t zephyr_display_display_type; + +#define NO_FPS_LIMIT 0xffffffff + +void common_hal_zephyr_display_display_construct_from_device(zephyr_display_display_obj_t *self, + const struct device *device, + uint16_t rotation, + bool auto_refresh); + +bool common_hal_zephyr_display_display_refresh(zephyr_display_display_obj_t *self, + uint32_t target_ms_per_frame, + uint32_t maximum_ms_per_real_frame); + +bool common_hal_zephyr_display_display_get_auto_refresh(zephyr_display_display_obj_t *self); +void common_hal_zephyr_display_display_set_auto_refresh(zephyr_display_display_obj_t *self, bool auto_refresh); + +uint16_t common_hal_zephyr_display_display_get_width(zephyr_display_display_obj_t *self); +uint16_t common_hal_zephyr_display_display_get_height(zephyr_display_display_obj_t *self); +uint16_t common_hal_zephyr_display_display_get_rotation(zephyr_display_display_obj_t *self); +void common_hal_zephyr_display_display_set_rotation(zephyr_display_display_obj_t *self, int rotation); + +mp_float_t common_hal_zephyr_display_display_get_brightness(zephyr_display_display_obj_t *self); +bool common_hal_zephyr_display_display_set_brightness(zephyr_display_display_obj_t *self, mp_float_t brightness); + +mp_obj_t common_hal_zephyr_display_display_get_root_group(zephyr_display_display_obj_t *self); +bool common_hal_zephyr_display_display_set_root_group(zephyr_display_display_obj_t *self, displayio_group_t *root_group); diff --git a/ports/zephyr-cp/bindings/zephyr_display/__init__.c b/ports/zephyr-cp/bindings/zephyr_display/__init__.c new file mode 100644 index 00000000000..eecfeeaec58 --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_display/__init__.c @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" + +#include "bindings/zephyr_display/Display.h" + +static const mp_rom_map_elem_t zephyr_display_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_zephyr_display) }, + { MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&zephyr_display_display_type) }, +}; + +static MP_DEFINE_CONST_DICT(zephyr_display_module_globals, zephyr_display_module_globals_table); + +const mp_obj_module_t zephyr_display_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&zephyr_display_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_zephyr_display, zephyr_display_module); diff --git a/ports/zephyr-cp/bindings/zephyr_display/__init__.h b/ports/zephyr-cp/bindings/zephyr_display/__init__.h new file mode 100644 index 00000000000..4256bfac2fe --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_display/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/autogen_board_info.toml new file mode 100644 index 00000000000..d6aca312226 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Adafruit Industries LLC Feather Bluefruit Sense" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/circuitpython.toml new file mode 100644 index 00000000000..eacb0f9607d --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/circuitpython.toml @@ -0,0 +1,4 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] +USB_VID=0x239A +USB_PID=0x8088 +NAME="Feather Bluefruit Sense" diff --git a/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/autogen_board_info.toml new file mode 100644 index 00000000000..dafe7811779 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Adafruit Industries LLC Feather nRF52840 Express" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/circuitpython.toml new file mode 100644 index 00000000000..c4d1099a77e --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/circuitpython.toml @@ -0,0 +1,4 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] +USB_VID=0x239A +USB_PID=0x802A +NAME="Feather nRF52840 Express" diff --git a/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/autogen_board_info.toml new file mode 100644 index 00000000000..cecf8e55a83 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Adafruit Industries LLC Feather RP2040" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/circuitpython.toml new file mode 100644 index 00000000000..9d3c229ed1b --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] diff --git a/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.conf b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.conf new file mode 100644 index 00000000000..20176b34be0 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.conf @@ -0,0 +1,10 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_USE_DT_CODE_PARTITION=y + +CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n diff --git a/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.overlay b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.overlay new file mode 100644 index 00000000000..e01ebd6df1f --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.overlay @@ -0,0 +1,46 @@ +/ { + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + }; +}; + +&zephyr_udc0 { + /delete-node/ board_cdc_acm_uart; +}; + + +&gd25q16 { + /delete-node/ partitions; +}; + +/delete-node/ &storage_partition; +/delete-node/ &code_partition; + +&flash0 { + partitions { + code_partition: partition@26000 { + label = "Application"; + reg = <0x00026000 0x000c4000>; + }; + + storage_partition: partition@ea000 { + label = "storage"; + reg = <0x000ea000 0x00008000>; + }; + + nvm_partition: partition@f2000 { + label = "nvm"; + reg = <0x000f2000 0x00002000>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.conf b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.conf new file mode 100644 index 00000000000..20176b34be0 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.conf @@ -0,0 +1,10 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_USE_DT_CODE_PARTITION=y + +CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n diff --git a/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.overlay b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.overlay new file mode 100644 index 00000000000..e01ebd6df1f --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.overlay @@ -0,0 +1,46 @@ +/ { + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + }; +}; + +&zephyr_udc0 { + /delete-node/ board_cdc_acm_uart; +}; + + +&gd25q16 { + /delete-node/ partitions; +}; + +/delete-node/ &storage_partition; +/delete-node/ &code_partition; + +&flash0 { + partitions { + code_partition: partition@26000 { + label = "Application"; + reg = <0x00026000 0x000c4000>; + }; + + storage_partition: partition@ea000 { + label = "storage"; + reg = <0x000ea000 0x00008000>; + }; + + nvm_partition: partition@f2000 { + label = "nvm"; + reg = <0x000f2000 0x00002000>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/adafruit_feather_rp2040.conf b/ports/zephyr-cp/boards/adafruit_feather_rp2040.conf new file mode 100644 index 00000000000..91c3c15b37d --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_rp2040.conf @@ -0,0 +1 @@ +CONFIG_GPIO=y diff --git a/ports/zephyr-cp/boards/adafruit_feather_rp2040.overlay b/ports/zephyr-cp/boards/adafruit_feather_rp2040.overlay new file mode 100644 index 00000000000..af7295ffe35 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_rp2040.overlay @@ -0,0 +1,34 @@ +&flash0 { + /delete-node/ partitions; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserved memory for the second stage bootloader */ + second_stage_bootloader: partition@0 { + label = "second_stage_bootloader"; + reg = <0x00000000 0x100>; + read-only; + }; + + code_partition: partition@100 { + label = "code-partition"; + reg = <0x100 (0x180000 - 0x100)>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(8) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/board_aliases.cmake b/ports/zephyr-cp/boards/board_aliases.cmake index 954bce0b298..ad0c1b5a57a 100644 --- a/ports/zephyr-cp/boards/board_aliases.cmake +++ b/ports/zephyr-cp/boards/board_aliases.cmake @@ -1,13 +1,53 @@ -set(pca10056_BOARD_ALIAS nrf52840dk/nrf52840) -set(renesas_ek_ra6m5_BOARD_ALIAS ek_ra6m5) -set(renesas_ek_ra8d1_BOARD_ALIAS ek_ra8d1) -set(native_native_sim_BOARD_ALIAS native_sim) -set(nordic_nrf54l15dk_BOARD_ALIAS nrf54l15dk/nrf54l15/cpuapp) -set(nordic_nrf54h20dk_BOARD_ALIAS nrf54h20dk/nrf54h20/cpuapp) -set(nordic_nrf5340dk_BOARD_ALIAS nrf5340dk/nrf5340/cpuapp) -set(nordic_nrf7002dk_BOARD_ALIAS nrf7002dk/nrf5340/cpuapp) -set(nxp_frdm_mcxn947_BOARD_ALIAS frdm_mcxn947/mcxn947/cpu0) -set(nxp_mimxrt1170_evk_BOARD_ALIAS mimxrt1170_evk@A/mimxrt1176/cm7) -set(st_stm32h7b3i_dk_BOARD_ALIAS stm32h7b3i_dk) -set(st_nucleo_u575zi_q_BOARD_ALIAS nucleo_u575zi_q/stm32u575xx) -set(st_nucleo_n657x0_q_BOARD_ALIAS nucleo_n657x0_q/stm32n657xx) +# Workaround for Zephyr alias handling with BOARD_QUALIFIERS in newer Zephyr. +# +# Instead of using _BOARD_ALIAS variables, translate BOARD directly so +# we don't end up with a spurious trailing '/' in BOARD_QUALIFIERS. +macro(cp_board_alias alias target) + if(BOARD STREQUAL "${alias}") + if(NOT "${target}" MATCHES "^([^@/]+)(@[^@/]+)?(/([^@]+))?$") + message(FATAL_ERROR "Invalid alias target '${target}'") + endif() + + set(BOARD_ALIAS "${alias}" CACHE STRING "Board alias, provided by user") + set(BOARD "${CMAKE_MATCH_1}") + + if(CMAKE_MATCH_2) + string(REPLACE "@" "" _rev "${CMAKE_MATCH_2}") + set(BOARD_REVISION "${_rev}") + else() + unset(BOARD_REVISION) + endif() + + if(CMAKE_MATCH_4) + set(BOARD_QUALIFIERS "${CMAKE_MATCH_4}") + else() + unset(BOARD_QUALIFIERS) + endif() + endif() +endmacro() + +cp_board_alias(pca10056 nrf52840dk/nrf52840) +cp_board_alias(adafruit_feather_nrf52840_zephyr adafruit_feather_nrf52840/nrf52840/uf2) +cp_board_alias(adafruit_feather_nrf52840_sense_zephyr adafruit_feather_nrf52840/nrf52840/sense/uf2) +cp_board_alias(adafruit_feather_rp2040_zephyr adafruit_feather_rp2040/rp2040) +cp_board_alias(renesas_ek_ra6m5 ek_ra6m5) +cp_board_alias(renesas_ek_ra8d1 ek_ra8d1) +cp_board_alias(renesas_da14695_dk_usb da14695_dk_usb) +cp_board_alias(native_native_sim native_sim/native) +cp_board_alias(native_nrf5340bsim nrf5340bsim/nrf5340/cpuapp) +cp_board_alias(nordic_nrf54l15dk nrf54l15dk/nrf54l15/cpuapp) +cp_board_alias(nordic_nrf54h20dk nrf54h20dk/nrf54h20/cpuapp) +cp_board_alias(nordic_nrf5340dk nrf5340dk/nrf5340/cpuapp) +cp_board_alias(nordic_nrf7002dk nrf7002dk/nrf5340/cpuapp) +cp_board_alias(nxp_frdm_mcxn947 frdm_mcxn947/mcxn947/cpu0) +cp_board_alias(nxp_frdm_rw612 frdm_rw612) +cp_board_alias(nxp_mimxrt1170_evk mimxrt1170_evk@A/mimxrt1176/cm7) +cp_board_alias(st_stm32h7b3i_dk stm32h7b3i_dk) +cp_board_alias(st_stm32h750b_dk stm32h750b_dk/stm32h750xx/ext_flash_app) +cp_board_alias(st_stm32wba65i_dk1 stm32wba65i_dk1) +cp_board_alias(st_nucleo_u575zi_q nucleo_u575zi_q/stm32u575xx) +cp_board_alias(raspberrypi_rpi_pico_zephyr rpi_pico/rp2040) +cp_board_alias(raspberrypi_rpi_pico_w_zephyr rpi_pico/rp2040/w) +cp_board_alias(raspberrypi_rpi_pico2_zephyr rpi_pico2/rp2350a/m33) +cp_board_alias(raspberrypi_rpi_pico2_w_zephyr rpi_pico2/rp2350a/m33/w) +cp_board_alias(st_nucleo_n657x0_q nucleo_n657x0_q/stm32n657xx) diff --git a/ports/zephyr-cp/boards/da14695_dk_usb.conf b/ports/zephyr-cp/boards/da14695_dk_usb.conf new file mode 100644 index 00000000000..145a9393407 --- /dev/null +++ b/ports/zephyr-cp/boards/da14695_dk_usb.conf @@ -0,0 +1,20 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 diff --git a/ports/zephyr-cp/boards/da14695_dk_usb.overlay b/ports/zephyr-cp/boards/da14695_dk_usb.overlay new file mode 100644 index 00000000000..fbc1817c759 --- /dev/null +++ b/ports/zephyr-cp/boards/da14695_dk_usb.overlay @@ -0,0 +1,10 @@ +&flash0 { + partitions{ + circuitpy_partition: partition@118000 { + label = "circuitpy"; + reg = <0x118000 (DT_SIZE_M(4) - DT_SIZE_K(1120))>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/ek_ra8d1.conf b/ports/zephyr-cp/boards/ek_ra8d1.conf new file mode 100644 index 00000000000..f979d31e751 --- /dev/null +++ b/ports/zephyr-cp/boards/ek_ra8d1.conf @@ -0,0 +1,3 @@ + +# Enable Zephyr display subsystem so DT chosen zephyr,display creates a device. +CONFIG_DISPLAY=y diff --git a/ports/zephyr-cp/boards/frdm_mcxn947_mcxn947_cpu0.conf b/ports/zephyr-cp/boards/frdm_mcxn947_mcxn947_cpu0.conf new file mode 100644 index 00000000000..61f2d18ca3c --- /dev/null +++ b/ports/zephyr-cp/boards/frdm_mcxn947_mcxn947_cpu0.conf @@ -0,0 +1 @@ +CONFIG_DMA_TCD_QUEUE_SIZE=4 diff --git a/ports/zephyr-cp/boards/frdm_rw612.conf b/ports/zephyr-cp/boards/frdm_rw612.conf new file mode 100644 index 00000000000..c06f78ae830 --- /dev/null +++ b/ports/zephyr-cp/boards/frdm_rw612.conf @@ -0,0 +1,42 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_NET_SOCKETS=y + +CONFIG_WIFI=y +CONFIG_NET_L2_WIFI_MGMT=y +CONFIG_NET_MGMT_EVENT=y +CONFIG_NET_MGMT_EVENT_INFO=y + +CONFIG_NET_HOSTNAME_ENABLE=y +CONFIG_NET_HOSTNAME_DYNAMIC=y +CONFIG_NET_HOSTNAME="circuitpython" + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_CIPHERSUITE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256=y +CONFIG_MBEDTLS_ENTROPY_C=y +CONFIG_MBEDTLS_CTR_DRBG_C=y + +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=8 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 + +CONFIG_UDC_WORKQUEUE_STACK_SIZE=1024 diff --git a/ports/zephyr-cp/boards/frdm_rw612.overlay b/ports/zephyr-cp/boards/frdm_rw612.overlay new file mode 100644 index 00000000000..c6a021d9999 --- /dev/null +++ b/ports/zephyr-cp/boards/frdm_rw612.overlay @@ -0,0 +1,11 @@ +&w25q512jvfiq { + partitions { + /delete-node/ partition@620000; + circuitpy_partition: partition@620000 { + label = "circuitpy"; + reg = <0x00620000 (DT_SIZE_M(58) - DT_SIZE_K(128))>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/frdm_rw612_rw612_cpu0.overlay b/ports/zephyr-cp/boards/frdm_rw612_rw612_cpu0.overlay new file mode 100644 index 00000000000..9c517e43255 --- /dev/null +++ b/ports/zephyr-cp/boards/frdm_rw612_rw612_cpu0.overlay @@ -0,0 +1,12 @@ +&w25q512jvfiq { + partitions { + /delete-node/ storage_partition; + circuitpy_partition: partition@620000 { + label = "circuitpy"; + reg = <0x00620000 (DT_SIZE_M(58) - DT_SIZE_K(128))>; + }; + } + +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.conf b/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.conf new file mode 100644 index 00000000000..61f2d18ca3c --- /dev/null +++ b/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.conf @@ -0,0 +1 @@ +CONFIG_DMA_TCD_QUEUE_SIZE=4 diff --git a/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay b/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay index d6f6d4f0c15..ac6fdd8654e 100644 --- a/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay +++ b/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay @@ -1,11 +1,15 @@ &is25wp128 { - partitions{ - /delete-node/ storage_partition; - circuitpy_partition: partition@E20000 { - label = "circuitpy"; - reg = <0x00E20000 (DT_SIZE_M(2) - DT_SIZE_K(128))>; - }; + partitions { + /delete-node/ partition@e20000; + circuitpy_partition: partition@e20000 { + label = "circuitpy"; + reg = <0x00e20000 (DT_SIZE_M(2) - DT_SIZE_K(128))>; + }; }; }; +&sai1 { + mclk-output; +}; + #include "../app.overlay" diff --git a/ports/zephyr-cp/boards/native/native_sim/autogen_board_info.toml b/ports/zephyr-cp/boards/native/native_sim/autogen_board_info.toml index 2cf9d7127d5..b565e8b139f 100644 --- a/ports/zephyr-cp/boards/native/native_sim/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/native/native_sim/autogen_board_info.toml @@ -2,28 +2,29 @@ name = "POSIX/Native Boards Native simulator - native_sim" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false atexit = false -audiobusio = false -audiocore = false -audiodelays = false -audiofilters = false -audiofreeverb = false +audiobusio = true # Zephyr board has audiobusio +audiocore = true # Zephyr board has audiobusio +audiodelays = true # Zephyr board has audiobusio +audiofilters = true # Zephyr board has audiobusio +audiofreeverb = true # Zephyr board has audiobusio audioio = false -audiomixer = false -audiomp3 = false +audiomixer = true # Zephyr board has audiobusio +audiomp3 = true # Zephyr board has audiobusio audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -37,7 +38,7 @@ canio = false codeop = false countio = false digitalio = true -displayio = true # Zephyr board has busio +displayio = true # Zephyr board has displayio dotclockframebuffer = false dualbank = false epaperdisplay = true # Zephyr board has busio @@ -46,31 +47,33 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true # Zephyr networking enabled +hostnetwork = true # Zephyr board has hostnetwork i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false -ipaddress = false +ipaddress = true # Zephyr networking enabled is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false -nvm = false +nvm = true # Zephyr board has nvm onewireio = false os = true paralleldisplaybus = false @@ -78,22 +81,23 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false sharpdisplay = true # Zephyr board has busio -socketpool = false +socketpool = true # Zephyr networking enabled spitarget = false ssl = false -storage = true # Zephyr board has flash +storage = true struct = true supervisor = true -synthio = false +synthio = true # Zephyr board has audiobusio terminalio = true # Zephyr board has busio tilepalettemapper = true # Zephyr board has busio time = true @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = true # Zephyr board has zephyr_display zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/native/native_sim/circuitpython.toml b/ports/zephyr-cp/boards/native/native_sim/circuitpython.toml index 3272dd4c5f3..fbda7c563b8 100644 --- a/ports/zephyr-cp/boards/native/native_sim/circuitpython.toml +++ b/ports/zephyr-cp/boards/native/native_sim/circuitpython.toml @@ -1 +1 @@ -CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "exe"] diff --git a/ports/zephyr-cp/boards/native/nrf5340bsim/autogen_board_info.toml b/ports/zephyr-cp/boards/native/nrf5340bsim/autogen_board_info.toml new file mode 100644 index 00000000000..aa723b53f64 --- /dev/null +++ b/ports/zephyr-cp/boards/native/nrf5340bsim/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "POSIX/Native Boards nRF5340 simulated boards (BabbleSim)" + +[modules] +__future__ = true +_bleio = true # Zephyr board has _bleio +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = false +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/native/nrf5340bsim/circuitpython.toml b/ports/zephyr-cp/boards/native/nrf5340bsim/circuitpython.toml new file mode 100644 index 00000000000..3272dd4c5f3 --- /dev/null +++ b/ports/zephyr-cp/boards/native/nrf5340bsim/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] diff --git a/ports/zephyr-cp/boards/native_sim.conf b/ports/zephyr-cp/boards/native_sim.conf index cc295949d03..00af0d01ac6 100644 --- a/ports/zephyr-cp/boards/native_sim.conf +++ b/ports/zephyr-cp/boards/native_sim.conf @@ -14,7 +14,30 @@ CONFIG_TRACING_GPIO=y # I2C emulation for testing CONFIG_I2C_EMUL=y +# Display emulation for display/terminal golden tests. +CONFIG_DISPLAY=y +CONFIG_SDL_DISPLAY=y + # EEPROM emulation for testing CONFIG_EEPROM=y CONFIG_EEPROM_AT24=y CONFIG_EEPROM_AT2X_EMUL=y + +# I2S SDL emulation for audio testing +CONFIG_I2S_SDL=y + +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_TCP=y +CONFIG_NET_SOCKETS=y +CONFIG_ETH_NATIVE_TAP=n +CONFIG_NET_DRIVERS=y +CONFIG_NET_SOCKETS_OFFLOAD=y +CONFIG_NET_NATIVE_OFFLOADED_SOCKETS=y +CONFIG_HEAP_MEM_POOL_SIZE=1024 + +CONFIG_NET_LOG=y + +CONFIG_MBEDTLS=y +CONFIG_PSA_WANT_ALG_SHA_1=y +CONFIG_PSA_WANT_ALG_SHA_256=y diff --git a/ports/zephyr-cp/boards/native_sim.overlay b/ports/zephyr-cp/boards/native_sim.overlay index 2a07108627f..aee9d17f9d0 100644 --- a/ports/zephyr-cp/boards/native_sim.overlay +++ b/ports/zephyr-cp/boards/native_sim.overlay @@ -31,7 +31,12 @@ circuitpy_partition: partition@0 { label = "circuitpy"; - reg = <0x00000000 DT_SIZE_K(2048)>; + reg = <0x00000000 DT_SIZE_K(2040)>; + }; + + nvm_partition: partition@1fe000 { + label = "nvm"; + reg = <0x001fe000 0x00002000>; }; }; }; diff --git a/ports/zephyr-cp/boards/nordic/nrf5340dk/autogen_board_info.toml b/ports/zephyr-cp/boards/nordic/nrf5340dk/autogen_board_info.toml index 334cf4001eb..ee20efa6fee 100644 --- a/ports/zephyr-cp/boards/nordic/nrf5340dk/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/nordic/nrf5340dk/autogen_board_info.toml @@ -2,28 +2,29 @@ name = "Nordic Semiconductor nRF5340 DK" [modules] -__future__ = false -_bleio = false +__future__ = true +_bleio = true # Zephyr board has _bleio _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false atexit = false -audiobusio = false -audiocore = false -audiodelays = false -audiofilters = false -audiofreeverb = false +audiobusio = true # Zephyr board has audiobusio +audiocore = true # Zephyr board has audiobusio +audiodelays = true # Zephyr board has audiobusio +audiofilters = true # Zephyr board has audiobusio +audiofreeverb = true # Zephyr board has audiobusio audioio = false -audiomixer = false -audiomp3 = false +audiomixer = true # Zephyr board has audiobusio +audiomp3 = true # Zephyr board has audiobusio audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -93,7 +97,7 @@ ssl = false storage = true # Zephyr board has flash struct = true supervisor = true -synthio = false +synthio = true # Zephyr board has audiobusio terminalio = true # Zephyr board has busio tilepalettemapper = true # Zephyr board has busio time = true @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = false zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/nordic/nrf54h20dk/autogen_board_info.toml b/ports/zephyr-cp/boards/nordic/nrf54h20dk/autogen_board_info.toml index 40edb7b7058..ca2c90ceb0b 100644 --- a/ports/zephyr-cp/boards/nordic/nrf54h20dk/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/nordic/nrf54h20dk/autogen_board_info.toml @@ -2,15 +2,15 @@ name = "Nordic Semiconductor nRF54H20 DK" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false @@ -24,6 +24,7 @@ audioio = false audiomixer = false audiomp3 = false audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = false # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = false # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -95,7 +99,7 @@ struct = true supervisor = true synthio = false terminalio = true # Zephyr board has busio -tilepalettemapper = true # Zephyr board has busio +tilepalettemapper = false # Zephyr board has busio time = true touchio = false traceback = true @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = false zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/nordic/nrf54h20dk/circuitpython.toml b/ports/zephyr-cp/boards/nordic/nrf54h20dk/circuitpython.toml index 3272dd4c5f3..415c471b3d4 100644 --- a/ports/zephyr-cp/boards/nordic/nrf54h20dk/circuitpython.toml +++ b/ports/zephyr-cp/boards/nordic/nrf54h20dk/circuitpython.toml @@ -1 +1,2 @@ CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +DISABLED_MODULES=["jpegio", "gifio", "tilepalettemapper"] diff --git a/ports/zephyr-cp/boards/nordic/nrf54l15dk/autogen_board_info.toml b/ports/zephyr-cp/boards/nordic/nrf54l15dk/autogen_board_info.toml index 509f14cd20d..69fdc2da903 100644 --- a/ports/zephyr-cp/boards/nordic/nrf54l15dk/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/nordic/nrf54l15dk/autogen_board_info.toml @@ -2,15 +2,15 @@ name = "Nordic Semiconductor nRF54L15 DK" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false @@ -24,6 +24,7 @@ audioio = false audiomixer = false audiomp3 = false audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = false zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/nordic/nrf7002dk/autogen_board_info.toml b/ports/zephyr-cp/boards/nordic/nrf7002dk/autogen_board_info.toml index 3b0ecedcc63..e0b759e01ce 100644 --- a/ports/zephyr-cp/boards/nordic/nrf7002dk/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/nordic/nrf7002dk/autogen_board_info.toml @@ -2,8 +2,8 @@ name = "Nordic Semiconductor nRF7002 DK" [modules] -__future__ = false -_bleio = false +__future__ = true +_bleio = true # Zephyr board has _bleio _eve = false _pew = false _pixelmap = false @@ -24,6 +24,7 @@ audioio = false audiomixer = false audiomp3 = false audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = false # Zephyr board has busio gnss = false -hashlib = false +hashlib = true # Zephyr networking enabled +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false -ipaddress = false +ipaddress = true # Zephyr networking enabled is31fl3741 = false -jpegio = false +jpegio = false # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -95,7 +99,7 @@ struct = true supervisor = true synthio = false terminalio = true # Zephyr board has busio -tilepalettemapper = true # Zephyr board has busio +tilepalettemapper = false # Zephyr board has busio time = true touchio = false traceback = true @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = true # Zephyr board has wifi +zephyr_display = false zephyr_kernel = false zlib = false diff --git a/ports/zephyr-cp/boards/nordic/nrf7002dk/circuitpython.toml b/ports/zephyr-cp/boards/nordic/nrf7002dk/circuitpython.toml index 76b10578813..761d2631477 100644 --- a/ports/zephyr-cp/boards/nordic/nrf7002dk/circuitpython.toml +++ b/ports/zephyr-cp/boards/nordic/nrf7002dk/circuitpython.toml @@ -2,3 +2,4 @@ CIRCUITPY_BUILD_EXTENSIONS = ["elf"] USB_VID=0x239A USB_PID=0x8168 BLOBS=["nrf_wifi"] +DISABLED_MODULES=["aesio", "adafruit_bus_device", "zlib", "jpegio", "tilepalettemapper", "gifio"] diff --git a/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.conf b/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..57628a61e20 --- /dev/null +++ b/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# Configuration for nrf5340bsim simulated board +# Mirror settings from native_sim.conf for compatibility + +CONFIG_GPIO=y + +# Enable Bluetooth stack - bsim is for BT simulation +CONFIG_BT=y +CONFIG_BT_HCI=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_BROADCASTER=y + +CONFIG_BT_L2CAP_TX_MTU=253 +CONFIG_BT_BUF_CMD_TX_COUNT=2 +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_HCI_VS=y +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 + +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 + +# Ensure the network core image starts when using native simulator +CONFIG_NATIVE_SIMULATOR_AUTOSTART_MCU=y + +CONFIG_TRACING=y +CONFIG_TRACING_PERFETTO=y +CONFIG_TRACING_SYNC=y +CONFIG_TRACING_BACKEND_POSIX=y +CONFIG_TRACING_GPIO=y diff --git a/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.overlay b/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..eeb043c6f3c --- /dev/null +++ b/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.overlay @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/ { + chosen { + zephyr,sram = &sram0; + }; +}; + +&sram0 { + compatible = "zephyr,memory-region", "mmio-sram"; + zephyr,memory-region = "SRAM"; +}; + +&flash0 { + /delete-node/ partitions; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + circuitpy_partition: partition@0 { + label = "circuitpy"; + reg = <0x00000000 DT_SIZE_K(1024)>; + }; + }; +}; + +/* Note: bsim doesn't have USB, so we don't include app.overlay */ diff --git a/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.conf b/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.conf index fa0532e8150..145a9393407 100644 --- a/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -4,3 +4,17 @@ CONFIG_BT_CENTRAL=y CONFIG_BT_BROADCASTER=y CONFIG_BT_OBSERVER=y CONFIG_BT_EXT_ADV=y + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 diff --git a/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.overlay b/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..eb899df8cc9 --- /dev/null +++ b/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +&pinctrl { + i2s0_default_alt: i2s0_default_alt { + group1 { + psels = , + , + , + , + ; + }; + }; +}; + +&clock { + hfclkaudio-frequency = <11289600>; +}; + +i2s_rxtx: &i2s0 { + status = "okay"; + pinctrl-0 = <&i2s0_default_alt>; + pinctrl-names = "default"; + clock-source = "ACLK"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.conf index f7443ecfa33..a55b90c50e7 100644 --- a/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -1 +1,8 @@ CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE=4096 + +# Reduce flash usage for this board. +CONFIG_LOG=y +CONFIG_LOG_MAX_LEVEL=2 +CONFIG_ASSERT=n +CONFIG_FRAME_POINTER=n +CONFIG_HW_STACK_PROTECTION=n diff --git a/ports/zephyr-cp/boards/nrf7002dk_nrf5340_cpuapp.conf b/ports/zephyr-cp/boards/nrf7002dk_nrf5340_cpuapp.conf index c61851fad2d..91c956fa676 100644 --- a/ports/zephyr-cp/boards/nrf7002dk_nrf5340_cpuapp.conf +++ b/ports/zephyr-cp/boards/nrf7002dk_nrf5340_cpuapp.conf @@ -2,7 +2,10 @@ CONFIG_NETWORKING=y CONFIG_WIFI=y CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y -CONFIG_MBEDTLS_USE_PSA_CRYPTO=n + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 CONFIG_BT=y CONFIG_BT_PERIPHERAL=y @@ -10,3 +13,7 @@ CONFIG_BT_CENTRAL=y CONFIG_BT_BROADCASTER=y CONFIG_BT_OBSERVER=y CONFIG_BT_EXT_ADV=y + +CONFIG_LOG=n +CONFIG_ASSERT=n +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/ports/zephyr-cp/boards/nxp/frdm_mcxn947/autogen_board_info.toml b/ports/zephyr-cp/boards/nxp/frdm_mcxn947/autogen_board_info.toml index 7e03594f1d1..b8e2c0601aa 100644 --- a/ports/zephyr-cp/boards/nxp/frdm_mcxn947/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/nxp/frdm_mcxn947/autogen_board_info.toml @@ -2,28 +2,29 @@ name = "NXP Semiconductors FRDM-MCXN947" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false atexit = false -audiobusio = false -audiocore = false -audiodelays = false -audiofilters = false -audiofreeverb = false +audiobusio = true # Zephyr board has audiobusio +audiocore = true # Zephyr board has audiobusio +audiodelays = true # Zephyr board has audiobusio +audiofilters = true # Zephyr board has audiobusio +audiofreeverb = true # Zephyr board has audiobusio audioio = false -audiomixer = false -audiomp3 = false +audiomixer = true # Zephyr board has audiobusio +audiomp3 = true # Zephyr board has audiobusio audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -93,7 +97,7 @@ ssl = false storage = true # Zephyr board has flash struct = true supervisor = true -synthio = false +synthio = true # Zephyr board has audiobusio terminalio = true # Zephyr board has busio tilepalettemapper = true # Zephyr board has busio time = true @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = false zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/nxp/frdm_rw612/autogen_board_info.toml b/ports/zephyr-cp/boards/nxp/frdm_rw612/autogen_board_info.toml new file mode 100644 index 00000000000..557b4f0448f --- /dev/null +++ b/ports/zephyr-cp/boards/nxp/frdm_rw612/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "NXP Semiconductors FRDM-RW612" + +[modules] +__future__ = true +_bleio = true # Zephyr board has _bleio +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true # Zephyr networking enabled +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = true # Zephyr networking enabled +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = true # Zephyr networking enabled +spitarget = false +ssl = true # Zephyr networking enabled +storage = true +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = true # Zephyr board has wifi +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/nxp/frdm_rw612/circuitpython.toml b/ports/zephyr-cp/boards/nxp/frdm_rw612/circuitpython.toml new file mode 100644 index 00000000000..9bceea470ca --- /dev/null +++ b/ports/zephyr-cp/boards/nxp/frdm_rw612/circuitpython.toml @@ -0,0 +1,5 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +BLOBS=["hal_nxp"] + +[blob_fetch_args] +hal_nxp = ["--allow-regex", "^rw61x/"] diff --git a/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/autogen_board_info.toml b/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/autogen_board_info.toml index 4398a38ab87..ee43ef86e8c 100644 --- a/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/autogen_board_info.toml @@ -1,29 +1,30 @@ # This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. -name = "NXP Semiconductors MIMXRT1170-EVK/EVKB" +name = "NXP Semiconductors MIMXRT1170-EVK" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false atexit = false -audiobusio = false -audiocore = false -audiodelays = false -audiofilters = false -audiofreeverb = false +audiobusio = true # Zephyr board has audiobusio +audiocore = true # Zephyr board has audiobusio +audiodelays = true # Zephyr board has audiobusio +audiofilters = true # Zephyr board has audiobusio +audiofreeverb = true # Zephyr board has audiobusio audioio = false -audiomixer = false -audiomp3 = false +audiomixer = true # Zephyr board has audiobusio +audiomp3 = true # Zephyr board has audiobusio audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -90,10 +94,10 @@ sharpdisplay = true # Zephyr board has busio socketpool = false spitarget = false ssl = false -storage = false +storage = true struct = true supervisor = true -synthio = false +synthio = true # Zephyr board has audiobusio terminalio = true # Zephyr board has busio tilepalettemapper = true # Zephyr board has busio time = true @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = false zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/autogen_board_info.toml new file mode 100644 index 00000000000..2215bcf4135 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Raspberry Pi Foundation Raspberry Pi Pico 2" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true # Zephyr networking enabled +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = true # Zephyr networking enabled +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = true # Zephyr networking enabled +spitarget = false +ssl = true # Zephyr networking enabled +storage = true +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = true # Zephyr board has wifi +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/circuitpython.toml new file mode 100644 index 00000000000..0f901d1149e --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/circuitpython.toml @@ -0,0 +1,2 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] +BLOBS=["hal_infineon"] diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/autogen_board_info.toml new file mode 100644 index 00000000000..61324042092 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Raspberry Pi Foundation Raspberry Pi Pico 2" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/circuitpython.toml new file mode 100644 index 00000000000..9d3c229ed1b --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/autogen_board_info.toml new file mode 100644 index 00000000000..203f5fd7048 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Raspberry Pi Foundation Raspberry Pi Pico" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true # Zephyr networking enabled +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = true # Zephyr networking enabled +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = true # Zephyr networking enabled +spitarget = false +ssl = true # Zephyr networking enabled +storage = true +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = true # Zephyr board has wifi +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/circuitpython.toml new file mode 100644 index 00000000000..0f901d1149e --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/circuitpython.toml @@ -0,0 +1,2 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] +BLOBS=["hal_infineon"] diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/autogen_board_info.toml new file mode 100644 index 00000000000..13c77bf2928 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Raspberry Pi Foundation Raspberry Pi Pico" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/circuitpython.toml new file mode 100644 index 00000000000..9d3c229ed1b --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] diff --git a/ports/zephyr-cp/boards/renesas/da14695_dk_usb/autogen_board_info.toml b/ports/zephyr-cp/boards/renesas/da14695_dk_usb/autogen_board_info.toml new file mode 100644 index 00000000000..e596ea1aebc --- /dev/null +++ b/ports/zephyr-cp/boards/renesas/da14695_dk_usb/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Renesas Electronics Corporation DA14695 Development Kit USB" + +[modules] +__future__ = true +_bleio = true # Zephyr board has _bleio +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/renesas/da14695_dk_usb/circuitpython.toml b/ports/zephyr-cp/boards/renesas/da14695_dk_usb/circuitpython.toml new file mode 100644 index 00000000000..f7fad6bc444 --- /dev/null +++ b/ports/zephyr-cp/boards/renesas/da14695_dk_usb/circuitpython.toml @@ -0,0 +1,2 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +BLOBS=["hal_renesas"] diff --git a/ports/zephyr-cp/boards/renesas/ek_ra6m5/autogen_board_info.toml b/ports/zephyr-cp/boards/renesas/ek_ra6m5/autogen_board_info.toml index d60e8eb4b26..7751ec96715 100644 --- a/ports/zephyr-cp/boards/renesas/ek_ra6m5/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/renesas/ek_ra6m5/autogen_board_info.toml @@ -2,15 +2,15 @@ name = "Renesas Electronics Corporation RA6M5 Evaluation Kit" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false @@ -24,6 +24,7 @@ audioio = false audiomixer = false audiomp3 = false audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = false zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/renesas/ek_ra8d1/autogen_board_info.toml b/ports/zephyr-cp/boards/renesas/ek_ra8d1/autogen_board_info.toml index 8743994bbc7..42bef11db0c 100644 --- a/ports/zephyr-cp/boards/renesas/ek_ra8d1/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/renesas/ek_ra8d1/autogen_board_info.toml @@ -2,15 +2,15 @@ name = "Renesas Electronics Corporation RA8D1 Evaluation Kit" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false @@ -24,6 +24,7 @@ audioio = false audiomixer = false audiomp3 = false audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -37,7 +38,7 @@ canio = false codeop = false countio = false digitalio = true -displayio = true # Zephyr board has busio +displayio = true # Zephyr board has displayio dotclockframebuffer = false dualbank = false epaperdisplay = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = true # Zephyr board has zephyr_display zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/renesas/ek_ra8d1/circuitpython.toml b/ports/zephyr-cp/boards/renesas/ek_ra8d1/circuitpython.toml index 3272dd4c5f3..0e19d8d7157 100644 --- a/ports/zephyr-cp/boards/renesas/ek_ra8d1/circuitpython.toml +++ b/ports/zephyr-cp/boards/renesas/ek_ra8d1/circuitpython.toml @@ -1 +1,2 @@ CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +SHIELDS = ["rtkmipilcdb00000be"] diff --git a/ports/zephyr-cp/boards/renesas_da14695_dk_usb.conf b/ports/zephyr-cp/boards/renesas_da14695_dk_usb.conf new file mode 100644 index 00000000000..145a9393407 --- /dev/null +++ b/ports/zephyr-cp/boards/renesas_da14695_dk_usb.conf @@ -0,0 +1,20 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 diff --git a/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33.overlay b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33.overlay new file mode 100644 index 00000000000..eb94fe7de67 --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33.overlay @@ -0,0 +1,25 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + code_partition: partition@0 { + label = "code-partition"; + reg = <0x0 0x180000>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(4) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.conf b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.conf new file mode 100644 index 00000000000..d75b1cd20a9 --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.conf @@ -0,0 +1,19 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_NET_SOCKETS=y + +CONFIG_WIFI=y +CONFIG_NET_L2_WIFI_MGMT=y +CONFIG_NET_MGMT_EVENT=y +CONFIG_NET_MGMT_EVENT_INFO=y + +CONFIG_NET_HOSTNAME_ENABLE=y +CONFIG_NET_HOSTNAME_DYNAMIC=y +CONFIG_NET_HOSTNAME="circuitpython" + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_CIPHERSUITE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256=y +CONFIG_MBEDTLS_ENTROPY_C=y +CONFIG_MBEDTLS_CTR_DRBG_C=y diff --git a/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.overlay b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.overlay new file mode 100644 index 00000000000..eb94fe7de67 --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.overlay @@ -0,0 +1,25 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + code_partition: partition@0 { + label = "code-partition"; + reg = <0x0 0x180000>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(4) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/rpi_pico_rp2040.overlay b/ports/zephyr-cp/boards/rpi_pico_rp2040.overlay new file mode 100644 index 00000000000..ce9083dd62d --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico_rp2040.overlay @@ -0,0 +1,34 @@ +&flash0 { + /delete-node/ partitions; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserved memory for the second stage bootloader */ + second_stage_bootloader: partition@0 { + label = "second_stage_bootloader"; + reg = <0x00000000 0x100>; + read-only; + }; + + code_partition: partition@100 { + label = "code-partition"; + reg = <0x100 (0x180000 - 0x100)>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(2) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/rpi_pico_rp2040_w.conf b/ports/zephyr-cp/boards/rpi_pico_rp2040_w.conf new file mode 100644 index 00000000000..975d6bfd6e1 --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico_rp2040_w.conf @@ -0,0 +1,21 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_NET_SOCKETS=y + +CONFIG_WIFI=y +CONFIG_NET_L2_WIFI_MGMT=y +CONFIG_NET_MGMT_EVENT=y +CONFIG_NET_MGMT_EVENT_INFO=y + +CONFIG_NET_HOSTNAME_ENABLE=y +CONFIG_NET_HOSTNAME_DYNAMIC=y +CONFIG_NET_HOSTNAME="circuitpython" + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_CIPHERSUITE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256=y +CONFIG_MBEDTLS_ENTROPY_C=y +CONFIG_MBEDTLS_CTR_DRBG_C=y + +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/ports/zephyr-cp/boards/rpi_pico_rp2040_w.overlay b/ports/zephyr-cp/boards/rpi_pico_rp2040_w.overlay new file mode 100644 index 00000000000..ce9083dd62d --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico_rp2040_w.overlay @@ -0,0 +1,34 @@ +&flash0 { + /delete-node/ partitions; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserved memory for the second stage bootloader */ + second_stage_bootloader: partition@0 { + label = "second_stage_bootloader"; + reg = <0x00000000 0x100>; + read-only; + }; + + code_partition: partition@100 { + label = "code-partition"; + reg = <0x100 (0x180000 - 0x100)>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(2) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/st/nucleo_n657x0_q/autogen_board_info.toml b/ports/zephyr-cp/boards/st/nucleo_n657x0_q/autogen_board_info.toml index 9b10fbe3c2d..7ad9c4f2111 100644 --- a/ports/zephyr-cp/boards/st/nucleo_n657x0_q/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/st/nucleo_n657x0_q/autogen_board_info.toml @@ -2,15 +2,15 @@ name = "STMicroelectronics Nucleo N657X0-Q" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false @@ -24,6 +24,7 @@ audioio = false audiomixer = false audiomp3 = false audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -90,7 +94,7 @@ sharpdisplay = true # Zephyr board has busio socketpool = false spitarget = false ssl = false -storage = false +storage = true struct = true supervisor = true synthio = false @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = false zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/nucleo_u575zi_q/autogen_board_info.toml b/ports/zephyr-cp/boards/st/nucleo_u575zi_q/autogen_board_info.toml index ef54f4bb0f7..2796f76782f 100644 --- a/ports/zephyr-cp/boards/st/nucleo_u575zi_q/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/st/nucleo_u575zi_q/autogen_board_info.toml @@ -2,15 +2,15 @@ name = "STMicroelectronics Nucleo U575ZI Q" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false @@ -24,6 +24,7 @@ audioio = false audiomixer = false audiomp3 = false audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -90,7 +94,7 @@ sharpdisplay = true # Zephyr board has busio socketpool = false spitarget = false ssl = false -storage = false +storage = true struct = true supervisor = true synthio = false @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = false zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/stm32h750b_dk/autogen_board_info.toml b/ports/zephyr-cp/boards/st/stm32h750b_dk/autogen_board_info.toml new file mode 100644 index 00000000000..2d5385d90b2 --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32h750b_dk/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "STMicroelectronics STM32H750B Discovery Kit" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has displayio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = false +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = true # Zephyr board has zephyr_display +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/stm32h750b_dk/circuitpython.toml b/ports/zephyr-cp/boards/st/stm32h750b_dk/circuitpython.toml new file mode 100644 index 00000000000..83e6bcd39c4 --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32h750b_dk/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["hex"] diff --git a/ports/zephyr-cp/boards/st/stm32h7b3i_dk/autogen_board_info.toml b/ports/zephyr-cp/boards/st/stm32h7b3i_dk/autogen_board_info.toml index 30ac22d00cc..7f158d6f278 100644 --- a/ports/zephyr-cp/boards/st/stm32h7b3i_dk/autogen_board_info.toml +++ b/ports/zephyr-cp/boards/st/stm32h7b3i_dk/autogen_board_info.toml @@ -2,15 +2,15 @@ name = "STMicroelectronics STM32H7B3I Discovery kit" [modules] -__future__ = false +__future__ = true _bleio = false _eve = false _pew = false _pixelmap = false _stage = false -adafruit_bus_device = false +adafruit_bus_device = true adafruit_pixelbuf = false -aesio = false +aesio = true alarm = false analogbufio = false analogio = false @@ -24,6 +24,7 @@ audioio = false audiomixer = false audiomp3 = false audiopwmio = false +audiospeed = false aurora_epaper = false bitbangio = false bitmapfilter = true # Zephyr board has busio @@ -37,7 +38,7 @@ canio = false codeop = false countio = false digitalio = true -displayio = true # Zephyr board has busio +displayio = true # Zephyr board has displayio dotclockframebuffer = false dualbank = false epaperdisplay = true # Zephyr board has busio @@ -46,29 +47,31 @@ fontio = true # Zephyr board has busio fourwire = true # Zephyr board has busio framebufferio = true # Zephyr board has busio frequencyio = false -getpass = false -gifio = false +getpass = true +gifio = true # Zephyr board has busio gnss = false -hashlib = false +hashlib = true +hostnetwork = false i2cdisplaybus = true # Zephyr board has busio i2cioexpander = false i2ctarget = false imagecapture = false ipaddress = false is31fl3741 = false -jpegio = false +jpegio = true # Zephyr board has busio keypad = false keypad_demux = false locale = false lvfontio = true # Zephyr board has busio -math = false +math = true max3421e = false +mcp4822 = false mdns = false memorymap = false memorymonitor = false microcontroller = true mipidsi = false -msgpack = false +msgpack = true neopixel_write = false nvm = false onewireio = false @@ -78,11 +81,12 @@ ps2io = false pulseio = false pwmio = false qrio = false +qspibus = false rainbowio = true random = true rclcpy = false rgbmatrix = false -rotaryio = false +rotaryio = true # Zephyr board has rotaryio rtc = false sdcardio = true # Zephyr board has busio sdioio = false @@ -101,7 +105,7 @@ touchio = false traceback = true uheap = false usb = false -usb_cdc = false +usb_cdc = true usb_hid = false usb_host = false usb_midi = false @@ -111,5 +115,6 @@ vectorio = true # Zephyr board has busio warnings = true watchdog = false wifi = false +zephyr_display = true # Zephyr board has zephyr_display zephyr_kernel = false -zlib = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/stm32wba65i_dk1/autogen_board_info.toml b/ports/zephyr-cp/boards/st/stm32wba65i_dk1/autogen_board_info.toml new file mode 100644 index 00000000000..19141f30065 --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32wba65i_dk1/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "STMicroelectronics STM32WBA65I Discovery kit" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = true +gifio = true # Zephyr board has busio +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = true # Zephyr board has busio +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/stm32wba65i_dk1/circuitpython.toml b/ports/zephyr-cp/boards/st/stm32wba65i_dk1/circuitpython.toml new file mode 100644 index 00000000000..83e6bcd39c4 --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32wba65i_dk1/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["hex"] diff --git a/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.conf b/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.conf new file mode 100644 index 00000000000..24afffb8e88 --- /dev/null +++ b/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.conf @@ -0,0 +1,2 @@ +# Enable Zephyr display subsystem so the built-in LTDC panel is available. +CONFIG_DISPLAY=y diff --git a/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.overlay b/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.overlay new file mode 100644 index 00000000000..fdb4960477b --- /dev/null +++ b/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.overlay @@ -0,0 +1,14 @@ +&ext_flash { + partitions { + /delete-node/ partition@7800000; + + circuitpy_partition: partition@7800000 { + label = "circuitpy"; + reg = <0x7800000 DT_SIZE_M(8)>; + }; + }; +}; + +&rng { + status = "okay"; +}; diff --git a/ports/zephyr-cp/boards/stm32h7b3i_dk.conf b/ports/zephyr-cp/boards/stm32h7b3i_dk.conf new file mode 100644 index 00000000000..24afffb8e88 --- /dev/null +++ b/ports/zephyr-cp/boards/stm32h7b3i_dk.conf @@ -0,0 +1,2 @@ +# Enable Zephyr display subsystem so the built-in LTDC panel is available. +CONFIG_DISPLAY=y diff --git a/ports/zephyr-cp/boards/stm32h7b3i_dk.overlay b/ports/zephyr-cp/boards/stm32h7b3i_dk.overlay index 88ad0415485..c2b5f3129c4 100644 --- a/ports/zephyr-cp/boards/stm32h7b3i_dk.overlay +++ b/ports/zephyr-cp/boards/stm32h7b3i_dk.overlay @@ -2,6 +2,28 @@ /delete-node/ partitions; }; +&sram5 { + status = "disabled"; +}; + &rng { status = "okay"; }; + +&fdcan1 { + status = "disabled"; +}; + +/ { + chosen { + /delete-property/ zephyr,canbus; + }; +}; + +zephyr_udc0: &usbotg_hs { + pinctrl-0 = <&usb_otg_hs_dm_pa11 &usb_otg_hs_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/stm32wba65i_dk1.conf b/ports/zephyr-cp/boards/stm32wba65i_dk1.conf new file mode 100644 index 00000000000..55d951959e6 --- /dev/null +++ b/ports/zephyr-cp/boards/stm32wba65i_dk1.conf @@ -0,0 +1,24 @@ +# USB OTG on STM32WBA requires VOS Range 1. Keep HCLK > 16 MHz. +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=32000000 + +# Bluetooth doesn't start up for some reason. +# CONFIG_BT=y +# CONFIG_BT_PERIPHERAL=y +# CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_STM32WBA_USE_TEMP_BASED_CALIB=n + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 diff --git a/ports/zephyr-cp/boards/stm32wba65i_dk1.overlay b/ports/zephyr-cp/boards/stm32wba65i_dk1.overlay new file mode 100644 index 00000000000..3b72ffc9984 --- /dev/null +++ b/ports/zephyr-cp/boards/stm32wba65i_dk1.overlay @@ -0,0 +1,61 @@ +&flash0 { + /delete-node/ partitions; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(928)>; + }; + + storage_partition: partition@f80000 { + label = "storage"; + reg = <0x001e0000 DT_SIZE_K(64)>; + }; + + circuitpy_partition: partition@108000 { + label = "circuitpy"; + reg = <0x00108000 DT_SIZE_K(992)>; + }; + }; +}; + +&rng { + status = "okay"; +}; + +/* + * USB on STM32WBA requires VOS Range 1. Zephyr selects VOS from HCLK, and + * 16 MHz keeps it in Range 2, which trips an assertion in udc_stm32. + * Run SYSCLK from full 32 MHz HSE so VOS is set to Range 1. + */ +&clk_hse { + /delete-property/ hse-div2; +}; + +&rcc { + clock-frequency = ; + ahb5-prescaler = <1>; +}; + +zephyr_udc0: &usbotg_hs { + status = "okay"; +}; + +&otghs_phy { + /* OTG HS clock source is 32 MHz HSE */ + clocks = <&rcc STM32_CLOCK(AHB2, 15)>, + <&rcc STM32_SRC_HSE OTGHS_SEL(0)>; + clock-reference = "SYSCFG_OTG_HS_PHY_CLK_32MHz"; + status = "okay"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/common-hal/_bleio/Adapter.c b/ports/zephyr-cp/common-hal/_bleio/Adapter.c new file mode 100644 index 00000000000..d1410f02e1b --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Adapter.c @@ -0,0 +1,679 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "py/gc.h" +#include "py/runtime.h" +#include "bindings/zephyr_kernel/__init__.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Address.h" +#include "shared-module/_bleio/Address.h" +#include "shared-module/_bleio/ScanResults.h" +#include "supervisor/shared/tick.h" + +bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; + +static bool scan_callbacks_registered = false; +static bleio_scanresults_obj_t *active_scan_results = NULL; +static struct bt_le_scan_cb scan_callbacks; +static bool ble_advertising = false; +static bool ble_adapter_enabled = true; + +#define BLEIO_ADV_MAX_FIELDS 16 +#define BLEIO_ADV_MAX_DATA_LEN 31 +static struct bt_data adv_data[BLEIO_ADV_MAX_FIELDS]; +static struct bt_data scan_resp_data[BLEIO_ADV_MAX_FIELDS]; +static uint8_t adv_data_storage[BLEIO_ADV_MAX_DATA_LEN]; +static uint8_t scan_resp_storage[BLEIO_ADV_MAX_DATA_LEN]; + +static uint8_t bleio_address_type_from_zephyr(const bt_addr_le_t *addr) { + if (addr == NULL) { + return BLEIO_ADDRESS_TYPE_PUBLIC; + } + + switch (addr->type) { + case BT_ADDR_LE_PUBLIC: + case BT_ADDR_LE_PUBLIC_ID: + return BLEIO_ADDRESS_TYPE_PUBLIC; + case BT_ADDR_LE_RANDOM: + case BT_ADDR_LE_RANDOM_ID: + case BT_ADDR_LE_UNRESOLVED: + if (BT_ADDR_IS_RPA(&addr->a)) { + return BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_RESOLVABLE; + } + if (BT_ADDR_IS_NRPA(&addr->a)) { + return BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE; + } + return BLEIO_ADDRESS_TYPE_RANDOM_STATIC; + default: + return BLEIO_ADDRESS_TYPE_PUBLIC; + } +} + +static uint8_t bleio_address_type_to_zephyr(uint8_t type) { + switch (type) { + case BLEIO_ADDRESS_TYPE_PUBLIC: + return BT_ADDR_LE_PUBLIC; + case BLEIO_ADDRESS_TYPE_RANDOM_STATIC: + case BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_RESOLVABLE: + case BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE: + return BT_ADDR_LE_RANDOM; + default: + return BT_ADDR_LE_PUBLIC; + } +} + +static bleio_connection_internal_t *bleio_connection_find_by_conn(const struct bt_conn *conn) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + if (connection->conn == conn) { + return connection; + } + } + + return NULL; +} + +static bleio_connection_internal_t *bleio_connection_track(struct bt_conn *conn) { + bleio_connection_internal_t *connection = bleio_connection_find_by_conn(conn); + if (connection == NULL) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *candidate = &bleio_connections[i]; + if (candidate->conn == NULL) { + connection = candidate; + break; + } + } + } + + if (connection == NULL) { + return NULL; + } + + if (connection->conn == NULL) { + connection->conn = bt_conn_ref(conn); + } + + return connection; +} + +static void bleio_connection_clear(bleio_connection_internal_t *self) { + if (self == NULL) { + return; + } + + if (self->conn != NULL) { + bt_conn_unref(self->conn); + self->conn = NULL; + } + + self->connection_obj = mp_const_none; +} + +static void bleio_connection_release(bleio_connection_internal_t *connection, uint8_t reason) { + if (connection == NULL) { + return; + } + + if (connection->connection_obj != mp_const_none) { + bleio_connection_obj_t *connection_obj = MP_OBJ_TO_PTR(connection->connection_obj); + connection_obj->connection = NULL; + connection_obj->disconnect_reason = reason; + } + + bleio_connection_clear(connection); + common_hal_bleio_adapter_obj.connection_objs = NULL; +} + +static void bleio_connected_cb(struct bt_conn *conn, uint8_t err) { + if (err != 0) { + return; + } + + if (bleio_connection_track(conn) == NULL) { + bt_conn_disconnect(conn, BT_HCI_ERR_CONN_LIMIT_EXCEEDED); + return; + } + + // When connectable advertising results in a connection, the controller + // auto-stops advertising. Clear our flag to match (we cannot call + // stop_advertising() here because this callback runs in Zephyr's BT + // thread context). + ble_advertising = false; + + common_hal_bleio_adapter_obj.connection_objs = NULL; +} + +static void bleio_disconnected_cb(struct bt_conn *conn, uint8_t reason) { + printk("disconnected %p\n", conn); + bleio_connection_release(bleio_connection_find_by_conn(conn), reason); +} + +BT_CONN_CB_DEFINE(bleio_connection_callbacks) = { + .connected = bleio_connected_cb, + .disconnected = bleio_disconnected_cb, +}; + +static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf) { + if (active_scan_results == NULL || info == NULL || buf == NULL) { + return; + } + + const bool connectable = (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0; + const bool scan_response = (info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0; + const bt_addr_le_t *addr = info->addr; + + uint8_t addr_bytes[NUM_BLEIO_ADDRESS_BYTES] = {0}; + if (addr != NULL) { + memcpy(addr_bytes, addr->a.val, sizeof(addr_bytes)); + } + + shared_module_bleio_scanresults_append(active_scan_results, + supervisor_ticks_ms64(), + connectable, + scan_response, + info->rssi, + addr_bytes, + bleio_address_type_from_zephyr(addr), + buf->data, + buf->len); +} + +static void scan_timeout_cb(void) { + if (active_scan_results == NULL) { + return; + } + shared_module_bleio_scanresults_set_done(active_scan_results, true); + active_scan_results = NULL; +} + +// We need to disassemble the full advertisement packet because the Zephyr takes +// in each ADT in an array. +static size_t bleio_parse_adv_data(const uint8_t *raw, size_t raw_len, struct bt_data *out, + size_t out_len, uint8_t *storage, size_t storage_len) { + size_t count = 0; + size_t offset = 0; + size_t storage_offset = 0; + + while (offset < raw_len) { + uint8_t field_len = raw[offset]; + if (field_len == 0) { + offset++; + continue; + } + uint8_t data_len = field_len - 1; + if (offset + field_len + 1 > raw_len || + count >= out_len || + field_len < 1 || + storage_offset + data_len > storage_len) { + mp_raise_ValueError(MP_ERROR_TEXT("Invalid advertising data")); + } + uint8_t type = raw[offset + 1]; + memcpy(storage + storage_offset, raw + offset + 2, data_len); + out[count].type = type; + out[count].data_len = data_len; + out[count].data = storage + storage_offset; + storage_offset += data_len; + count++; + offset += field_len + 1; + } + + return count; +} + +static uint16_t bleio_validate_and_convert_timeout(mp_float_t timeout) { + mp_arg_validate_float_range(timeout, 0, UINT16_MAX, MP_QSTR_timeout); + + if (timeout <= 0.0f) { + return 0; + } + + const mp_int_t timeout_units = + mp_arg_validate_int_range((mp_int_t)(timeout * 100.0f + 0.5f), 1, UINT16_MAX, MP_QSTR_timeout); + + return (uint16_t)timeout_units; +} + +void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled) { + if (enabled == ble_adapter_enabled) { + return; + } + if (enabled) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_clear(&bleio_connections[i]); + } + if (!bt_is_ready()) { + int err = bt_enable(NULL); + if (err != 0) { + raise_zephyr_error(err); + } + } + ble_adapter_enabled = true; + return; + } + + // On Zephyr bsim + HCI IPC, disabling and immediately re-enabling BLE can + // race endpoint rebinding during soft reload. Keep the controller running, + // but present adapter.enabled=False to CircuitPython code. + common_hal_bleio_adapter_stop_scan(self); + common_hal_bleio_adapter_stop_advertising(self); + ble_adapter_enabled = false; +} + +bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) { + return ble_adapter_enabled; +} + +mp_int_t common_hal_bleio_adapter_get_tx_power(bleio_adapter_obj_t *self) { + struct bt_hci_cp_vs_read_tx_power_level *cp; + struct bt_hci_rp_vs_read_tx_power_level *rp; + struct net_buf *buf, *rsp = NULL; + + buf = bt_hci_cmd_alloc(K_MSEC(1000)); + if (!buf) { + mp_raise_msg(&mp_type_MemoryError, NULL); + } + cp = net_buf_add(buf, sizeof(*cp)); + cp->handle_type = BT_HCI_VS_LL_HANDLE_TYPE_ADV; + cp->handle = 0; + + int err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL, buf, &rsp); + if (err) { + raise_zephyr_error(err); + } + + rp = (void *)rsp->data; + int8_t power = rp->tx_power_level; + net_buf_unref(rsp); + return power; +} + +void common_hal_bleio_adapter_set_tx_power(bleio_adapter_obj_t *self, mp_int_t tx_power) { + struct bt_hci_cp_vs_write_tx_power_level *cp; + struct net_buf *buf, *rsp = NULL; + + buf = bt_hci_cmd_alloc(K_MSEC(3000)); + if (!buf) { + mp_raise_msg(&mp_type_MemoryError, NULL); + } + cp = net_buf_add(buf, sizeof(*cp)); + cp->handle_type = BT_HCI_VS_LL_HANDLE_TYPE_ADV; + cp->handle = 0; + cp->tx_power_level = (int8_t)tx_power; + + int err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL, buf, &rsp); + if (err) { + raise_zephyr_error(err); + } + + net_buf_unref(rsp); +} + +bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) { + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_address_obj_t *address) { + mp_raise_NotImplementedError(NULL); +} + +mp_obj_str_t *common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) { + (void)self; + const char *name = bt_get_name(); + return mp_obj_new_str(name, strlen(name)); +} + +void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char *name) { + (void)self; + size_t len = strlen(name); + int err = 0; + if (len > CONFIG_BT_DEVICE_NAME_MAX) { + char truncated[CONFIG_BT_DEVICE_NAME_MAX + 1]; + memcpy(truncated, name, CONFIG_BT_DEVICE_NAME_MAX); + truncated[CONFIG_BT_DEVICE_NAME_MAX] = '\0'; + err = bt_set_name(truncated); + } else { + err = bt_set_name(name); + } + if (err != 0) { + raise_zephyr_error(err); + } +} + +void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, + bool connectable, bool anonymous, uint32_t timeout, mp_float_t interval, + mp_buffer_info_t *advertising_data_bufinfo, + mp_buffer_info_t *scan_response_data_bufinfo, + mp_int_t tx_power, const bleio_address_obj_t *directed_to) { + (void)directed_to; + (void)interval; + + if (advertising_data_bufinfo->len > BLEIO_ADV_MAX_DATA_LEN || + scan_response_data_bufinfo->len > BLEIO_ADV_MAX_DATA_LEN) { + mp_raise_NotImplementedError(NULL); + } + + if (timeout != 0) { + mp_raise_NotImplementedError(NULL); + } + + if (ble_advertising) { + raise_zephyr_error(-EALREADY); + } + + bt_addr_le_t id_addrs[CONFIG_BT_ID_MAX]; + size_t id_count = CONFIG_BT_ID_MAX; + bt_id_get(id_addrs, &id_count); + if (id_count == 0 || bt_addr_le_eq(&id_addrs[BT_ID_DEFAULT], BT_ADDR_LE_ANY)) { + int id = bt_id_create(NULL, NULL); + if (id < 0) { + printk("Failed to create identity address: %d\n", id); + raise_zephyr_error(id); + } + } + + size_t adv_count = bleio_parse_adv_data(advertising_data_bufinfo->buf, + advertising_data_bufinfo->len, + adv_data, + BLEIO_ADV_MAX_FIELDS, + adv_data_storage, + sizeof(adv_data_storage)); + + size_t scan_resp_count = 0; + if (scan_response_data_bufinfo->len > 0) { + scan_resp_count = bleio_parse_adv_data(scan_response_data_bufinfo->buf, + scan_response_data_bufinfo->len, + scan_resp_data, + BLEIO_ADV_MAX_FIELDS, + scan_resp_storage, + sizeof(scan_resp_storage)); + } + + if (anonymous) { + mp_raise_NotImplementedError(NULL); + } + + struct bt_le_adv_param adv_params; + if (connectable) { + adv_params = (struct bt_le_adv_param)BT_LE_ADV_PARAM_INIT( + BT_LE_ADV_OPT_CONN, + BT_GAP_ADV_FAST_INT_MIN_1, + BT_GAP_ADV_FAST_INT_MAX_1, + NULL); + } else if (scan_resp_count > 0) { + adv_params = (struct bt_le_adv_param)BT_LE_ADV_PARAM_INIT( + BT_LE_ADV_OPT_SCANNABLE, + BT_GAP_ADV_FAST_INT_MIN_2, + BT_GAP_ADV_FAST_INT_MAX_2, + NULL); + } else { + adv_params = (struct bt_le_adv_param)BT_LE_ADV_PARAM_INIT( + 0, + BT_GAP_ADV_FAST_INT_MIN_2, + BT_GAP_ADV_FAST_INT_MAX_2, + NULL); + } + + common_hal_bleio_adapter_set_tx_power(self, tx_power); + + raise_zephyr_error(bt_le_adv_start(&adv_params, + adv_data, + adv_count, + scan_resp_count > 0 ? scan_resp_data : NULL, + scan_resp_count)); + + ble_advertising = true; +} + +void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) { + (void)self; + if (!ble_advertising) { + return; + } + bt_le_adv_stop(); + ble_advertising = false; +} + +bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) { + (void)self; + return ble_advertising; +} + +mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t *prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) { + (void)extended; + + if (self->scan_results != NULL) { + if (!shared_module_bleio_scanresults_get_done(self->scan_results)) { + common_hal_bleio_adapter_stop_scan(self); + } else { + self->scan_results = NULL; + } + } + + int err = 0; + + self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi); + active_scan_results = self->scan_results; + + if (!scan_callbacks_registered) { + scan_callbacks.recv = scan_recv_cb; + scan_callbacks.timeout = scan_timeout_cb; + err = bt_le_scan_cb_register(&scan_callbacks); + if (err != 0) { + self->scan_results = NULL; + active_scan_results = NULL; + raise_zephyr_error(err); + } + scan_callbacks_registered = true; + } + + uint16_t interval_units = (uint16_t)((interval / 0.000625f) + 0.5f); + uint16_t window_units = (uint16_t)((window / 0.000625f) + 0.5f); + uint16_t timeout_units = bleio_validate_and_convert_timeout(timeout); + + struct bt_le_scan_param scan_params = { + .type = active ? BT_LE_SCAN_TYPE_ACTIVE : BT_LE_SCAN_TYPE_PASSIVE, + .options = BT_LE_SCAN_OPT_FILTER_DUPLICATE, + .interval = interval_units, + .window = window_units, + .timeout = (uint16_t)timeout_units, + .interval_coded = 0, + .window_coded = 0, + }; + + err = bt_le_scan_start(&scan_params, NULL); + if (err != 0) { + self->scan_results = NULL; + active_scan_results = NULL; + raise_zephyr_error(err); + } + + return MP_OBJ_FROM_PTR(self->scan_results); +} + +void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) { + if (self->scan_results == NULL) { + return; + } + bt_le_scan_stop(); + shared_module_bleio_scanresults_set_done(self->scan_results, true); + active_scan_results = NULL; + self->scan_results = NULL; +} + +bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { + if (!ble_adapter_enabled) { + return false; + } + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn != NULL) { + return true; + } + } + + return false; +} + +mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) { + if (!ble_adapter_enabled) { + self->connection_objs = NULL; + return mp_const_empty_tuple; + } + + if (self->connection_objs != NULL) { + return self->connection_objs; + } + + size_t total_connected = 0; + mp_obj_t items[BLEIO_TOTAL_CONNECTION_COUNT]; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + if (connection->conn == NULL) { + continue; + } + + if (connection->connection_obj == mp_const_none) { + connection->connection_obj = bleio_connection_new_from_internal(connection); + } + + items[total_connected] = connection->connection_obj; + total_connected++; + } + + self->connection_objs = mp_obj_new_tuple(total_connected, items); + return self->connection_objs; +} + +mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) { + common_hal_bleio_adapter_stop_scan(self); + + const uint16_t timeout_units = bleio_validate_and_convert_timeout(timeout); + + mp_buffer_info_t address_bufinfo; + mp_get_buffer_raise(address->bytes, &address_bufinfo, MP_BUFFER_READ); + + bt_addr_le_t peer = { + .type = bleio_address_type_to_zephyr(address->type), + }; + memcpy(peer.a.val, address_bufinfo.buf, NUM_BLEIO_ADDRESS_BYTES); + + struct bt_conn_le_create_param create_params = BT_CONN_LE_CREATE_PARAM_INIT( + BT_CONN_LE_OPT_NONE, + BT_GAP_SCAN_FAST_INTERVAL, + BT_GAP_SCAN_FAST_INTERVAL); + create_params.timeout = timeout_units; + + struct bt_conn *conn = NULL; + int err = bt_conn_le_create(&peer, &create_params, BT_LE_CONN_PARAM_DEFAULT, &conn); + if (err != 0) { + raise_zephyr_error(err); + } + + while (true) { + struct bt_conn_info info; + err = bt_conn_get_info(conn, &info); + if (err == 0) { + if (info.state == BT_CONN_STATE_CONNECTED) { + break; + } + + if (info.state == BT_CONN_STATE_DISCONNECTED) { + bt_conn_unref(conn); + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Failed to connect: timeout")); + } + } else if (err != -ENOTCONN) { + bt_conn_unref(conn); + raise_zephyr_error(err); + } + + RUN_BACKGROUND_TASKS; + } + + bleio_connection_internal_t *connection = bleio_connection_find_by_conn(conn); + if (connection == NULL) { + connection = bleio_connection_track(conn); + } + + if (connection == NULL) { + bt_conn_unref(conn); + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Failed to connect: internal error")); + } + + // bt_conn_le_create() gave us a ref in `conn`; `connection` keeps its own + // ref via bleio_connection_track(). Drop the create ref now. + bt_conn_unref(conn); + + self->connection_objs = NULL; + return bleio_connection_new_from_internal(connection); +} + +void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) { + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_adapter_is_bonded_to_central(bleio_adapter_obj_t *self) { + return false; +} + +void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) { + gc_collect_root((void **)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t)); + gc_collect_root((void **)bleio_connections, sizeof(bleio_connections) / sizeof(size_t)); +} + +void bleio_adapter_reset(bleio_adapter_obj_t *adapter) { + if (adapter == NULL) { + return; + } + + common_hal_bleio_adapter_stop_scan(adapter); + common_hal_bleio_adapter_stop_advertising(adapter); + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + if (connection->conn != NULL) { + bt_conn_disconnect(connection->conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + } + if (connection->connection_obj != MP_OBJ_NULL && + connection->connection_obj != mp_const_none) { + bleio_connection_obj_t *connection_obj = MP_OBJ_TO_PTR(connection->connection_obj); + connection_obj->connection = NULL; + connection_obj->disconnect_reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN; + } + bleio_connection_clear(connection); + } + + adapter->scan_results = NULL; + adapter->connection_objs = NULL; + active_scan_results = NULL; + ble_advertising = false; + ble_adapter_enabled = bt_is_ready(); +} + +bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void) { + return &common_hal_bleio_adapter_obj; +} + +uint16_t bleio_adapter_get_name(char *buf, uint16_t len) { + const char *name = bt_get_name(); + uint16_t full_len = strlen(name); + if (len > 0) { + uint16_t copy_len = len < full_len ? len : full_len; + memcpy(buf, name, copy_len); + } + return full_len; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Adapter.h b/ports/zephyr-cp/common-hal/_bleio/Adapter.h new file mode 100644 index 00000000000..c15c698e2a5 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Adapter.h @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/objtuple.h" + +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/ScanResults.h" + +#define BLEIO_TOTAL_CONNECTION_COUNT CONFIG_BT_MAX_CONN + +extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; + +typedef struct { + mp_obj_base_t base; + bleio_scanresults_obj_t *scan_results; + mp_obj_t name; + mp_obj_tuple_t *connection_objs; + bool user_advertising; +} bleio_adapter_obj_t; + +void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter); +void bleio_adapter_reset(bleio_adapter_obj_t *adapter); diff --git a/ports/zephyr-cp/common-hal/_bleio/Attribute.c b/ports/zephyr-cp/common-hal/_bleio/Attribute.c new file mode 100644 index 00000000000..6312f3d46b8 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Attribute.c @@ -0,0 +1,8 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Attribute is defined in shared-module, no port-specific implementation needed diff --git a/ports/zephyr-cp/common-hal/_bleio/Attribute.h b/ports/zephyr-cp/common-hal/_bleio/Attribute.h new file mode 100644 index 00000000000..24b0f78a106 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Attribute.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/_bleio/Attribute.h" diff --git a/ports/zephyr-cp/common-hal/_bleio/Characteristic.c b/ports/zephyr-cp/common-hal/_bleio/Characteristic.c new file mode 100644 index 00000000000..386be6004d2 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Characteristic.c @@ -0,0 +1,67 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/Service.h" + +bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self) { + return self->props; +} + +mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { + return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items); +} + +bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) { + return self->service; +} + +bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) { + return self->uuid; +} + +size_t common_hal_bleio_characteristic_get_max_length(bleio_characteristic_obj_t *self) { + return self->max_length; +} + +size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t *buf, size_t len) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo, const char *user_description) { + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return self->service == NULL; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { + // Nothing to do +} + +void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { + mp_raise_NotImplementedError(NULL); +} + +void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer) { + self->observer = observer; +} + +void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self) { + self->observer = mp_const_none; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Characteristic.h b/ports/zephyr-cp/common-hal/_bleio/Characteristic.h new file mode 100644 index 00000000000..b710a9f2662 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Characteristic.h @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/objlist.h" +#include "shared-bindings/_bleio/Attribute.h" +#include "shared-module/_bleio/Characteristic.h" +#include "common-hal/_bleio/Descriptor.h" +#include "common-hal/_bleio/Service.h" +#include "common-hal/_bleio/UUID.h" + +typedef struct _bleio_characteristic_obj { + mp_obj_base_t base; + bleio_service_obj_t *service; + bleio_uuid_obj_t *uuid; + mp_obj_t observer; + uint8_t *current_value; + uint16_t current_value_len; + uint16_t current_value_alloc; + uint16_t max_length; + uint16_t def_handle; + uint16_t handle; + bleio_characteristic_properties_t props; + bleio_attribute_security_mode_t read_perm; + bleio_attribute_security_mode_t write_perm; + mp_obj_list_t *descriptor_list; + uint16_t user_desc_handle; + uint16_t cccd_handle; + uint16_t sccd_handle; + bool fixed_length; +} bleio_characteristic_obj_t; + +void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer); +void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self); diff --git a/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.c b/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.c new file mode 100644 index 00000000000..17e000e905e --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.c @@ -0,0 +1,73 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/mperrno.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/CharacteristicBuffer.h" + +void _common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_float_t timeout, + uint8_t *buffer, size_t buffer_size, + void *static_handler_entry, + bool watch_for_interrupt_char) { + (void)self; + (void)characteristic; + (void)timeout; + (void)buffer; + (void)buffer_size; + (void)static_handler_entry; + (void)watch_for_interrupt_char; + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_float_t timeout, + size_t buffer_size) { + (void)self; + (void)characteristic; + (void)timeout; + (void)buffer_size; + mp_raise_NotImplementedError(NULL); +} + +uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) { + (void)self; + (void)data; + (void)len; + if (errcode != NULL) { + *errcode = MP_EAGAIN; + } + mp_raise_NotImplementedError(NULL); +} + +uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) { + return self->deinited; +} + +void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) { + if (self == NULL) { + return; + } + self->deinited = true; +} + +bool common_hal_bleio_characteristic_buffer_connected(bleio_characteristic_buffer_obj_t *self) { + (void)self; + return false; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.h b/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.h new file mode 100644 index 00000000000..91ea262945a --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" +#include "shared-bindings/_bleio/Characteristic.h" + +typedef struct { + mp_obj_base_t base; + bleio_characteristic_obj_t *characteristic; + bool deinited; +} bleio_characteristic_buffer_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/Connection.c b/ports/zephyr-cp/common-hal/_bleio/Connection.c new file mode 100644 index 00000000000..938359c79ca --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Connection.c @@ -0,0 +1,97 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include +#include + +#include "py/runtime.h" +#include "bindings/zephyr_kernel/__init__.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Connection.h" + +void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) { + if (self == NULL || self->conn == NULL) { + return; + } + + int err = bt_conn_disconnect(self->conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err != 0 && err != -ENOTCONN) { + raise_zephyr_error(err); + } + + // The connection may now be disconnecting; force connections tuple rebuild. + common_hal_bleio_adapter_obj.connection_objs = NULL; +} + +bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) { + if (self == NULL || self->connection == NULL) { + return false; + } + + bleio_connection_internal_t *connection = self->connection; + if (connection->conn == NULL) { + return false; + } + + struct bt_conn_info info; + if (bt_conn_get_info(connection->conn, &info) != 0) { + return false; + } + + return info.state == BT_CONN_STATE_CONNECTED || info.state == BT_CONN_STATE_DISCONNECTING; +} + +mp_int_t common_hal_bleio_connection_get_max_packet_length(bleio_connection_internal_t *self) { + if (self == NULL || self->conn == NULL) { + return 20; + } + + uint16_t mtu = bt_gatt_get_mtu(self->conn); + if (mtu < 3) { + return 20; + } + return mtu - 3; +} + +bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self) { + return false; +} + +mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist) { + mp_raise_NotImplementedError(NULL); +} + +mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_internal_t *self) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval) { + mp_raise_NotImplementedError(NULL); +} + +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection) { + if (connection == NULL) { + return mp_const_none; + } + + if (connection->connection_obj != mp_const_none) { + return connection->connection_obj; + } + + bleio_connection_obj_t *connection_obj = mp_obj_malloc(bleio_connection_obj_t, &bleio_connection_type); + connection_obj->connection = connection; + connection_obj->disconnect_reason = 0; + connection->connection_obj = MP_OBJ_FROM_PTR(connection_obj); + + return connection->connection_obj; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Connection.h b/ports/zephyr-cp/common-hal/_bleio/Connection.h new file mode 100644 index 00000000000..dc14125db5f --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Connection.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" + +struct bt_conn; + +typedef struct { + struct bt_conn *conn; + mp_obj_t connection_obj; +} bleio_connection_internal_t; + +typedef struct { + mp_obj_base_t base; + bleio_connection_internal_t *connection; + uint8_t disconnect_reason; +} bleio_connection_obj_t; + +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection); diff --git a/ports/zephyr-cp/common-hal/_bleio/Descriptor.c b/ports/zephyr-cp/common-hal/_bleio/Descriptor.c new file mode 100644 index 00000000000..a3e65a5e006 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Descriptor.c @@ -0,0 +1,30 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/Characteristic.h" + +void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { + mp_raise_NotImplementedError(NULL); +} + +bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) { + return self->uuid; +} + +bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) { + mp_raise_NotImplementedError(NULL); +} + +size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t *buf, size_t len) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) { + mp_raise_NotImplementedError(NULL); +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Descriptor.h b/ports/zephyr-cp/common-hal/_bleio/Descriptor.h new file mode 100644 index 00000000000..1d29cb27a50 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Descriptor.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/_bleio/Attribute.h" +#include "common-hal/_bleio/UUID.h" + +typedef struct _bleio_descriptor_obj { + mp_obj_base_t base; + bleio_uuid_obj_t *uuid; + uint16_t handle; + bleio_attribute_security_mode_t read_perm; + bleio_attribute_security_mode_t write_perm; + uint16_t max_length; + bool fixed_length; + uint8_t *value; + uint16_t value_length; +} bleio_descriptor_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.c b/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.c new file mode 100644 index 00000000000..82fe8a3d176 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.c @@ -0,0 +1,66 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/PacketBuffer.h" + +void common_hal_bleio_packet_buffer_construct( + bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, + size_t buffer_size, size_t max_packet_size) { + (void)self; + (void)characteristic; + (void)buffer_size; + (void)max_packet_size; + mp_raise_NotImplementedError(NULL); +} + +mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, const uint8_t *data, size_t len, uint8_t *header, size_t header_len) { + (void)self; + (void)data; + (void)len; + (void)header; + (void)header_len; + mp_raise_NotImplementedError(NULL); +} + +mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) { + (void)self; + (void)data; + (void)len; + mp_raise_NotImplementedError(NULL); +} + +mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(bleio_packet_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_packet_buffer_flush(bleio_packet_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) { + return self->deinited; +} + +void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { + if (self == NULL) { + return; + } + self->deinited = true; +} + +bool common_hal_bleio_packet_buffer_connected(bleio_packet_buffer_obj_t *self) { + (void)self; + return false; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.h b/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.h new file mode 100644 index 00000000000..c8cd763fd61 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" + +typedef struct _bleio_characteristic_obj bleio_characteristic_obj_t; + +typedef void *ble_event_handler_t; + +typedef struct { + mp_obj_base_t base; + bool deinited; +} bleio_packet_buffer_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/Service.c b/ports/zephyr-cp/common-hal/_bleio/Service.c new file mode 100644 index 00000000000..cefc85b6df6 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Service.c @@ -0,0 +1,46 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/Characteristic.h" + +uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t *characteristic_list) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_service_deinit(bleio_service_obj_t *self) { + // Nothing to do +} + +void common_hal_bleio_service_from_remote_service(bleio_service_obj_t *self, bleio_connection_obj_t *connection, bleio_uuid_obj_t *uuid, bool is_secondary) { + mp_raise_NotImplementedError(NULL); +} + +bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) { + return self->uuid; +} + +mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self) { + return mp_obj_new_tuple(self->characteristic_list->len, self->characteristic_list->items); +} + +bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) { + return self->is_remote; +} + +bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) { + return self->is_secondary; +} + +void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *initial_value_bufinfo, const char *user_description) { + mp_raise_NotImplementedError(NULL); +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Service.h b/ports/zephyr-cp/common-hal/_bleio/Service.h new file mode 100644 index 00000000000..86727d3b0f7 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Service.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/objlist.h" +#include "common-hal/_bleio/UUID.h" + +typedef struct bleio_service_obj { + mp_obj_base_t base; + bleio_uuid_obj_t *uuid; + mp_obj_t connection; + mp_obj_list_t *characteristic_list; + uint16_t start_handle; + uint16_t end_handle; + bool is_remote; + bool is_secondary; +} bleio_service_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/UUID.c b/ports/zephyr-cp/common-hal/_bleio/UUID.c new file mode 100644 index 00000000000..916eedb2c47 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/UUID.c @@ -0,0 +1,52 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/runtime.h" +#include "shared-bindings/_bleio/UUID.h" + +void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[16]) { + if (uuid16 != 0) { + // 16-bit UUID + self->size = 16; + // Convert 16-bit UUID to 128-bit + // Bluetooth Base UUID: 00000000-0000-1000-8000-00805F9B34FB + const uint8_t base_uuid[16] = {0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + memcpy(self->uuid128, base_uuid, 16); + self->uuid128[12] = (uuid16 & 0xff); + self->uuid128[13] = (uuid16 >> 8) & 0xff; + } else { + // 128-bit UUID + self->size = 128; + memcpy(self->uuid128, uuid128, 16); + } +} + +uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) { + if (self->size == 16) { + return (self->uuid128[13] << 8) | self->uuid128[12]; + } + return 0; +} + +void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) { + memcpy(uuid128, self->uuid128, 16); +} + +uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self) { + return self->size; +} + +void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t *buf) { + if (self->size == 16) { + buf[0] = self->uuid128[12]; + buf[1] = self->uuid128[13]; + } else { + memcpy(buf, self->uuid128, 16); + } +} diff --git a/ports/zephyr-cp/common-hal/_bleio/UUID.h b/ports/zephyr-cp/common-hal/_bleio/UUID.h new file mode 100644 index 00000000000..386f5a7b8b9 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/UUID.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + uint8_t uuid128[16]; + uint8_t size; +} bleio_uuid_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/__init__.c b/ports/zephyr-cp/common-hal/_bleio/__init__.c new file mode 100644 index 00000000000..719564c1cd4 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/__init__.c @@ -0,0 +1,51 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "common-hal/_bleio/Adapter.h" +#include "supervisor/shared/bluetooth/bluetooth.h" + +// The singleton _bleio.Adapter object +bleio_adapter_obj_t common_hal_bleio_adapter_obj; + +void common_hal_bleio_init(void) { + common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type; + bleio_adapter_reset(&common_hal_bleio_adapter_obj); +} + +void bleio_user_reset(void) { + if (common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { + // Stop any user scanning or advertising. + common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); + common_hal_bleio_adapter_stop_advertising(&common_hal_bleio_adapter_obj); + } + + // Maybe start advertising the BLE workflow. + supervisor_bluetooth_background(); +} + +void bleio_reset(void) { + common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type; + if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { + return; + } + + supervisor_stop_bluetooth(); + bleio_adapter_reset(&common_hal_bleio_adapter_obj); + common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false); + supervisor_start_bluetooth(); +} + +void common_hal_bleio_gc_collect(void) { + bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj); +} + +void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist) { + mp_raise_NotImplementedError(NULL); +} diff --git a/ports/zephyr-cp/common-hal/_bleio/__init__.h b/ports/zephyr-cp/common-hal/_bleio/__init__.h new file mode 100644 index 00000000000..1502767c615 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/__init__.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Placeholder for Zephyr-specific BLE defines diff --git a/ports/zephyr-cp/common-hal/audiobusio/I2SOut.c b/ports/zephyr-cp/common-hal/audiobusio/I2SOut.c new file mode 100644 index 00000000000..e858552c524 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/I2SOut.c @@ -0,0 +1,299 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/audiobusio/I2SOut.h" + +#include +#include +#include +#include +#include + +#include "bindings/zephyr_kernel/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/audiocore/__init__.h" +#include "py/runtime.h" + +#if CIRCUITPY_AUDIOBUSIO_I2SOUT + +#define AUDIO_THREAD_STACK_SIZE 2048 +#define AUDIO_THREAD_PRIORITY 5 + +// Forward declarations +static void fill_buffer(audiobusio_i2sout_obj_t *self, uint8_t *buffer, size_t buffer_size); +static void audio_thread_func(void *self_in, void *unused1, void *unused2); + +// Helper function for Zephyr-specific initialization from device tree +mp_obj_t common_hal_audiobusio_i2sout_construct_from_device(audiobusio_i2sout_obj_t *self, const struct device *i2s_device) { + self->base.type = &audiobusio_i2sout_type; + self->i2s_dev = i2s_device; + self->left_justified = false; + self->playing = false; + self->paused = false; + self->sample = NULL; + self->slab_buffer = NULL; + self->thread_stack = NULL; + self->thread_id = NULL; + self->block_size = 0; + + return MP_OBJ_FROM_PTR(self); +} + +// Standard audiobusio construct - not used in Zephyr port (devices come from device tree) +void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self, + const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select, + const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, bool left_justified) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("Use device tree to define %q devices"), MP_QSTR_I2S); +} + +bool common_hal_audiobusio_i2sout_deinited(audiobusio_i2sout_obj_t *self) { + return self->i2s_dev == NULL; +} + +void common_hal_audiobusio_i2sout_deinit(audiobusio_i2sout_obj_t *self) { + if (common_hal_audiobusio_i2sout_deinited(self)) { + return; + } + + // Stop playback (which will free buffers) + common_hal_audiobusio_i2sout_stop(self); + + // Note: Pins and I2S device are managed by Zephyr, not released here + self->i2s_dev = NULL; +} + +static void fill_buffer(audiobusio_i2sout_obj_t *self, uint8_t *buffer, size_t buffer_size) { + if (self->sample == NULL || self->paused || self->stopping) { + // Fill with silence + memset(buffer, 0, buffer_size); + return; + } + + uint32_t bytes_filled = 0; + while (bytes_filled < buffer_size) { + uint8_t *sample_buffer; + uint32_t sample_buffer_length; + + audioio_get_buffer_result_t result = audiosample_get_buffer( + self->sample, false, 0, &sample_buffer, &sample_buffer_length); + + if (result == GET_BUFFER_ERROR) { + // Error getting buffer, stop playback + self->stopping = true; + memset(buffer + bytes_filled, 0, buffer_size - bytes_filled); + return; + } + + if (result == GET_BUFFER_DONE) { + if (self->loop) { + // Reset to beginning + audiosample_reset_buffer(self->sample, false, 0); + } else { + // Done playing, fill rest with silence + self->stopping = true; + i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DRAIN); + memset(buffer + bytes_filled, 0, buffer_size - bytes_filled); + return; + } + } + + // Copy data to buffer + uint32_t bytes_to_copy = sample_buffer_length; + if (bytes_filled + bytes_to_copy > buffer_size) { + bytes_to_copy = buffer_size - bytes_filled; + } + + memcpy(buffer + bytes_filled, sample_buffer, bytes_to_copy); + bytes_filled += bytes_to_copy; + } +} + +static void audio_thread_func(void *self_in, void *unused1, void *unused2) { + audiobusio_i2sout_obj_t *self = (audiobusio_i2sout_obj_t *)self_in; + + while (!self->stopping) { + uint8_t *next_buffer = NULL; + // Wait until I2S has freed the buffer it is sending. + if (k_mem_slab_alloc(&self->mem_slab, (void **)&next_buffer, K_FOREVER) != 0) { + break; + } + if (self->stopping) { + // Stopping so break. + k_mem_slab_free(&self->mem_slab, next_buffer); + break; + } + fill_buffer(self, next_buffer, self->block_size); + + // Write to I2S + int ret = i2s_write(self->i2s_dev, next_buffer, self->block_size); + if (ret < 0) { + printk("i2s_write failed: %d\n", ret); + k_mem_slab_free(&self->mem_slab, next_buffer); + // Error writing, stop playback + self->playing = false; + break; + } + } +} + +void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, + mp_obj_t sample, bool loop) { + // Stop any existing playback + if (self->playing) { + common_hal_audiobusio_i2sout_stop(self); + } + + // Get sample information + uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample); + uint32_t sample_rate = audiosample_get_sample_rate(sample); + uint8_t channel_count = audiosample_get_channel_count(sample); + + // Store sample parameters + self->sample = sample; + self->loop = loop; + self->bytes_per_sample = bits_per_sample / 8; + self->channel_count = channel_count; + self->stopping = false; + + // Get buffer structure from the sample + bool single_buffer, samples_signed; + uint32_t max_buffer_length; + uint8_t sample_spacing; + audiosample_get_buffer_structure(sample, /* single_channel_output */ false, + &single_buffer, &samples_signed, &max_buffer_length, &sample_spacing); + + // Use max_buffer_length from the sample as the block size + self->block_size = max_buffer_length; + if (channel_count == 1) { + // Make room for stereo samples. + self->block_size *= 2; + } + size_t block_size = self->block_size; + uint32_t num_blocks = 4; // Use 4 blocks for buffering + + // Allocate memory slab buffer + self->slab_buffer = m_malloc(self->block_size * num_blocks); + + // Initialize memory slab + int ret = k_mem_slab_init(&self->mem_slab, self->slab_buffer, block_size, num_blocks); + CHECK_ZEPHYR_RESULT(ret); + + // Configure I2S + struct i2s_config config; + config.word_size = bits_per_sample; + config.channels = 2; + config.format = self->left_justified ? I2S_FMT_DATA_FORMAT_LEFT_JUSTIFIED : I2S_FMT_DATA_FORMAT_I2S; + config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER; + config.frame_clk_freq = sample_rate; + config.mem_slab = &self->mem_slab; + config.block_size = block_size; + config.timeout = 1000; // Not a k_timeout_t. In milliseconds. + + // Configure returns EINVAL if the I2S device is not ready. We loop on this + // because it should be ready after it comes to a complete stop. + ret = -EAGAIN; + while (ret == -EAGAIN) { + ret = i2s_configure(self->i2s_dev, I2S_DIR_TX, &config); + } + if (ret != 0) { + common_hal_audiobusio_i2sout_stop(self); + raise_zephyr_error(ret); + } + + // Fill every slab before starting playback to avoid underruns. + for (uint32_t i = 0; i < num_blocks; i++) { + uint8_t *buf = NULL; + k_mem_slab_alloc(&self->mem_slab, (void **)&buf, K_NO_WAIT); + fill_buffer(self, buf, block_size); + ret = i2s_write(self->i2s_dev, buf, block_size); + if (ret < 0) { + printk("i2s_write failed: %d\n", ret); + k_mem_slab_free(&self->mem_slab, buf); + common_hal_audiobusio_i2sout_stop(self); + raise_zephyr_error(ret); + } + } + + // Allocate thread stack with proper MPU alignment for HW stack protection + self->thread_stack = k_thread_stack_alloc(AUDIO_THREAD_STACK_SIZE, 0); + + // Create and start audio processing thread + self->thread_id = k_thread_create(&self->thread, self->thread_stack, + AUDIO_THREAD_STACK_SIZE, + audio_thread_func, + self, NULL, NULL, + AUDIO_THREAD_PRIORITY, 0, K_NO_WAIT); + // Start I2S + ret = i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_START); + if (ret < 0) { + common_hal_audiobusio_i2sout_stop(self); + raise_zephyr_error(ret); + } + + self->playing = true; +} + +void common_hal_audiobusio_i2sout_stop(audiobusio_i2sout_obj_t *self) { + if (!self->playing) { + return; + } + + self->playing = false; + self->paused = false; + self->stopping = true; + + // Stop I2S + i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DROP); + + // Wait for thread to finish + if (self->thread_id != NULL) { + k_thread_join(self->thread_id, K_FOREVER); + self->thread_id = NULL; + } + + // Free thread stack + if (self->thread_stack != NULL) { + k_thread_stack_free(self->thread_stack); + self->thread_stack = NULL; + } + + // Free buffers + if (self->slab_buffer != NULL) { + m_free(self->slab_buffer); + self->slab_buffer = NULL; + } + + self->sample = NULL; +} + +bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t *self) { + return self->playing; +} + +void common_hal_audiobusio_i2sout_pause(audiobusio_i2sout_obj_t *self) { + if (!self->playing || self->paused) { + return; + } + + self->paused = true; + i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_STOP); +} + +void common_hal_audiobusio_i2sout_resume(audiobusio_i2sout_obj_t *self) { + if (!self->playing || !self->paused) { + return; + } + + self->paused = false; + // Thread will automatically resume filling buffers + i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_START); +} + +bool common_hal_audiobusio_i2sout_get_paused(audiobusio_i2sout_obj_t *self) { + return self->paused; +} + +#endif // CIRCUITPY_AUDIOBUSIO_I2SOUT diff --git a/ports/zephyr-cp/common-hal/audiobusio/I2SOut.h b/ports/zephyr-cp/common-hal/audiobusio/I2SOut.h new file mode 100644 index 00000000000..916471fa833 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/I2SOut.h @@ -0,0 +1,47 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "common-hal/microcontroller/Pin.h" +#include "shared-module/audiocore/__init__.h" + +#include +#include +#include + +#if CIRCUITPY_AUDIOBUSIO_I2SOUT + +typedef struct { + mp_obj_base_t base; + const struct device *i2s_dev; + const mcu_pin_obj_t *bit_clock; + const mcu_pin_obj_t *word_select; + const mcu_pin_obj_t *data; + const mcu_pin_obj_t *main_clock; + mp_obj_t sample; + struct k_mem_slab mem_slab; + char *slab_buffer; + struct k_thread thread; + k_thread_stack_t *thread_stack; + k_tid_t thread_id; + size_t block_size; + bool left_justified; + bool playing; + bool paused; + bool loop; + bool stopping; + bool single_buffer; + uint8_t bytes_per_sample; + uint8_t channel_count; +} audiobusio_i2sout_obj_t; + +mp_obj_t common_hal_audiobusio_i2sout_construct_from_device(audiobusio_i2sout_obj_t *self, const struct device *i2s_device); + +void i2sout_reset(void); + +#endif // CIRCUITPY_AUDIOBUSIO_I2SOUT diff --git a/ports/zephyr-cp/common-hal/audiobusio/PDMIn.c b/ports/zephyr-cp/common-hal/audiobusio/PDMIn.c new file mode 100644 index 00000000000..3d3cfef5258 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/PDMIn.c @@ -0,0 +1,39 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/audiobusio/PDMIn.h" + +#include "py/runtime.h" + +#if CIRCUITPY_AUDIOBUSIO_PDMIN + +void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self, + const mcu_pin_obj_t *clock_pin, const mcu_pin_obj_t *data_pin, + uint32_t sample_rate, uint8_t bit_depth, bool mono, uint8_t oversample) { + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_audiobusio_pdmin_deinited(audiobusio_pdmin_obj_t *self) { + return true; +} + +void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t *self) { +} + +uint8_t common_hal_audiobusio_pdmin_get_bit_depth(audiobusio_pdmin_obj_t *self) { + return 0; +} + +uint32_t common_hal_audiobusio_pdmin_get_sample_rate(audiobusio_pdmin_obj_t *self) { + return 0; +} + +uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t *self, + uint16_t *output_buffer, uint32_t output_buffer_length) { + return 0; +} + +#endif // CIRCUITPY_AUDIOBUSIO_PDMIN diff --git a/ports/zephyr-cp/common-hal/audiobusio/PDMIn.h b/ports/zephyr-cp/common-hal/audiobusio/PDMIn.h new file mode 100644 index 00000000000..195a436f3cf --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/PDMIn.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "common-hal/microcontroller/Pin.h" + +#if CIRCUITPY_AUDIOBUSIO_PDMIN + +typedef struct { + mp_obj_base_t base; +} audiobusio_pdmin_obj_t; + +#endif // CIRCUITPY_AUDIOBUSIO_PDMIN diff --git a/ports/zephyr-cp/common-hal/audiobusio/__init__.c b/ports/zephyr-cp/common-hal/audiobusio/__init__.c new file mode 100644 index 00000000000..5d2e802904d --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// No special initialization required for audiobusio diff --git a/ports/zephyr-cp/common-hal/audiobusio/__init__.h b/ports/zephyr-cp/common-hal/audiobusio/__init__.h new file mode 100644 index 00000000000..8ba7882bf94 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/__init__.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// No common definitions needed for audiobusio diff --git a/ports/zephyr-cp/common-hal/busio/UART.h b/ports/zephyr-cp/common-hal/busio/UART.h index 25e767c5b28..be0b7ff83a9 100644 --- a/ports/zephyr-cp/common-hal/busio/UART.h +++ b/ports/zephyr-cp/common-hal/busio/UART.h @@ -27,3 +27,7 @@ mp_obj_t common_hal_busio_uart_construct_from_device(busio_uart_obj_t *self, con // Internal helper for clearing buffer void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self); + +// Zephyr-port-specific write-timeout accessors, used by usb_cdc/Serial.c. +mp_float_t common_hal_busio_uart_get_write_timeout(busio_uart_obj_t *self); +void common_hal_busio_uart_set_write_timeout(busio_uart_obj_t *self, mp_float_t write_timeout); diff --git a/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.c b/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.c new file mode 100644 index 00000000000..494b21cb02d --- /dev/null +++ b/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.c @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "bindings/hostnetwork/HostNetwork.h" + +hostnetwork_hostnetwork_obj_t common_hal_hostnetwork_obj = { + .base = { &hostnetwork_hostnetwork_type }, +}; + +void common_hal_hostnetwork_hostnetwork_construct(hostnetwork_hostnetwork_obj_t *self) { + (void)self; +} diff --git a/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.h b/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.h new file mode 100644 index 00000000000..a6731546bde --- /dev/null +++ b/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "bindings/hostnetwork/HostNetwork.h" + +extern hostnetwork_hostnetwork_obj_t common_hal_hostnetwork_obj; diff --git a/ports/zephyr-cp/common-hal/microcontroller/__init__.c b/ports/zephyr-cp/common-hal/microcontroller/__init__.c index 6ebf5f4c368..be33cd26c9a 100644 --- a/ports/zephyr-cp/common-hal/microcontroller/__init__.c +++ b/ports/zephyr-cp/common-hal/microcontroller/__init__.c @@ -11,7 +11,7 @@ #include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Processor.h" -// #include "shared-bindings/nvm/ByteArray.h" +#include "shared-bindings/nvm/ByteArray.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" @@ -93,14 +93,12 @@ const mcu_processor_obj_t common_hal_mcu_processor_obj = { }, }; -#if CIRCUITPY_NVM && CIRCUITPY_INTERNAL_NVM_SIZE > 0 +#if CIRCUITPY_NVM // The singleton nvm.ByteArray object. const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { .base = { .type = &nvm_bytearray_type, }, - .start_address = (uint8_t *)CIRCUITPY_INTERNAL_NVM_START_ADDR, - .len = CIRCUITPY_INTERNAL_NVM_SIZE, }; #endif diff --git a/ports/zephyr-cp/common-hal/nvm/ByteArray.c b/ports/zephyr-cp/common-hal/nvm/ByteArray.c new file mode 100644 index 00000000000..b8f552d6773 --- /dev/null +++ b/ports/zephyr-cp/common-hal/nvm/ByteArray.c @@ -0,0 +1,103 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "common-hal/nvm/ByteArray.h" +#include "shared-bindings/nvm/ByteArray.h" + +#include + +#include +#include + +#define NVM_PARTITION nvm_partition + +#if FIXED_PARTITION_EXISTS(NVM_PARTITION) + +static const struct flash_area *nvm_area = NULL; +static size_t nvm_erase_size = 0; + +static bool ensure_nvm_open(void) { + if (nvm_area != NULL) { + return true; + } + int rc = flash_area_open(FIXED_PARTITION_ID(NVM_PARTITION), &nvm_area); + if (rc != 0) { + return false; + } + + const struct device *dev = flash_area_get_device(nvm_area); + struct flash_pages_info info; + flash_get_page_info_by_offs(dev, nvm_area->fa_off, &info); + nvm_erase_size = info.size; + + return true; +} + +uint32_t common_hal_nvm_bytearray_get_length(const nvm_bytearray_obj_t *self) { + if (!ensure_nvm_open()) { + return 0; + } + return nvm_area->fa_size; +} + +bool common_hal_nvm_bytearray_set_bytes(const nvm_bytearray_obj_t *self, + uint32_t start_index, uint8_t *values, uint32_t len) { + if (!ensure_nvm_open()) { + return false; + } + + uint32_t address = start_index; + while (len > 0) { + uint32_t page_offset = address % nvm_erase_size; + uint32_t page_start = address - page_offset; + uint32_t write_len = MIN(len, nvm_erase_size - page_offset); + + uint8_t *buffer = m_malloc(nvm_erase_size); + if (buffer == NULL) { + return false; + } + + // Read the full erase page. + int rc = flash_area_read(nvm_area, page_start, buffer, nvm_erase_size); + if (rc != 0) { + m_free(buffer); + return false; + } + + // Modify the relevant bytes. + memcpy(buffer + page_offset, values, write_len); + + // Erase the page. + rc = flash_area_erase(nvm_area, page_start, nvm_erase_size); + if (rc != 0) { + m_free(buffer); + return false; + } + + // Write the page back. + rc = flash_area_write(nvm_area, page_start, buffer, nvm_erase_size); + m_free(buffer); + if (rc != 0) { + return false; + } + + address += write_len; + values += write_len; + len -= write_len; + } + return true; +} + +void common_hal_nvm_bytearray_get_bytes(const nvm_bytearray_obj_t *self, + uint32_t start_index, uint32_t len, uint8_t *values) { + if (!ensure_nvm_open()) { + return; + } + flash_area_read(nvm_area, start_index, values, len); +} + +#endif // FIXED_PARTITION_EXISTS(NVM_PARTITION) diff --git a/ports/zephyr-cp/common-hal/nvm/ByteArray.h b/ports/zephyr-cp/common-hal/nvm/ByteArray.h new file mode 100644 index 00000000000..9c771aaa3a9 --- /dev/null +++ b/ports/zephyr-cp/common-hal/nvm/ByteArray.h @@ -0,0 +1,13 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; +} nvm_bytearray_obj_t; diff --git a/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.c b/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.c new file mode 100644 index 00000000000..d36b571535a --- /dev/null +++ b/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.c @@ -0,0 +1,129 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include "common-hal/rotaryio/IncrementalEncoder.h" +#include "shared-bindings/rotaryio/IncrementalEncoder.h" +#include "shared-module/rotaryio/IncrementalEncoder.h" + +#include "bindings/zephyr_kernel/__init__.h" +#include "py/runtime.h" + +#include +#include +#include +#include + +static void incrementalencoder_gpio_callback(const struct device *port, + struct gpio_callback *cb, gpio_port_pins_t pins) { + (void)port; + (void)pins; + rotaryio_incrementalencoder_gpio_callback_t *callback = + CONTAINER_OF(cb, rotaryio_incrementalencoder_gpio_callback_t, callback); + rotaryio_incrementalencoder_obj_t *self = callback->encoder; + if (self == NULL || self->pin_a == NULL) { + return; + } + + int a = gpio_pin_get(self->pin_a->port, self->pin_a->number); + int b = gpio_pin_get(self->pin_b->port, self->pin_b->number); + if (a < 0 || b < 0) { + return; + } + uint8_t new_state = ((uint8_t)a << 1) | (uint8_t)b; + shared_module_softencoder_state_update(self, new_state); +} + +void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, + const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + + self->pin_a = pin_a; + self->pin_b = pin_b; + self->divisor = 4; + + if (!device_is_ready(pin_a->port) || !device_is_ready(pin_b->port)) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(-ENODEV); + } + + int result = gpio_pin_configure(pin_a->port, pin_a->number, GPIO_INPUT | GPIO_PULL_UP); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + result = gpio_pin_configure(pin_b->port, pin_b->number, GPIO_INPUT | GPIO_PULL_UP); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + self->callback_a.encoder = self; + gpio_init_callback(&self->callback_a.callback, incrementalencoder_gpio_callback, + BIT(pin_a->number)); + result = gpio_add_callback(pin_a->port, &self->callback_a.callback); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + self->callback_b.encoder = self; + gpio_init_callback(&self->callback_b.callback, incrementalencoder_gpio_callback, + BIT(pin_b->number)); + result = gpio_add_callback(pin_b->port, &self->callback_b.callback); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + result = gpio_pin_interrupt_configure(pin_a->port, pin_a->number, GPIO_INT_EDGE_BOTH); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + result = gpio_pin_interrupt_configure(pin_b->port, pin_b->number, GPIO_INT_EDGE_BOTH); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + int a = gpio_pin_get(pin_a->port, pin_a->number); + int b = gpio_pin_get(pin_b->port, pin_b->number); + uint8_t quiescent_state = ((uint8_t)(a > 0) << 1) | (uint8_t)(b > 0); + shared_module_softencoder_state_init(self, quiescent_state); + + claim_pin(pin_a); + claim_pin(pin_b); +} + +bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t *self) { + return self->pin_a == NULL; +} + +void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t *self) { + if (common_hal_rotaryio_incrementalencoder_deinited(self)) { + return; + } + + // Best-effort cleanup. During failed construct(), some of these may not be + // initialized yet. Ignore cleanup errors. + gpio_pin_interrupt_configure(self->pin_a->port, self->pin_a->number, GPIO_INT_DISABLE); + gpio_pin_interrupt_configure(self->pin_b->port, self->pin_b->number, GPIO_INT_DISABLE); + gpio_remove_callback(self->pin_a->port, &self->callback_a.callback); + gpio_remove_callback(self->pin_b->port, &self->callback_b.callback); + + reset_pin(self->pin_a); + reset_pin(self->pin_b); + + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { + self->pin_a = NULL; + self->pin_b = NULL; +} diff --git a/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.h b/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.h new file mode 100644 index 00000000000..a0d2bb392e2 --- /dev/null +++ b/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.h @@ -0,0 +1,31 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +typedef struct rotaryio_incrementalencoder_obj rotaryio_incrementalencoder_obj_t; + +typedef struct { + struct gpio_callback callback; + rotaryio_incrementalencoder_obj_t *encoder; +} rotaryio_incrementalencoder_gpio_callback_t; + +struct rotaryio_incrementalencoder_obj { + mp_obj_base_t base; + const mcu_pin_obj_t *pin_a; + const mcu_pin_obj_t *pin_b; + rotaryio_incrementalencoder_gpio_callback_t callback_a; + rotaryio_incrementalencoder_gpio_callback_t callback_b; + uint8_t state; // + int8_t sub_count; // count intermediate transitions between detents + int8_t divisor; // Number of quadrature edges required per count + mp_int_t position; +}; diff --git a/ports/zephyr-cp/common-hal/rotaryio/__init__.c b/ports/zephyr-cp/common-hal/rotaryio/__init__.c new file mode 100644 index 00000000000..67cae26a8b7 --- /dev/null +++ b/ports/zephyr-cp/common-hal/rotaryio/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// No rotaryio module functions. diff --git a/ports/zephyr-cp/common-hal/socketpool/Socket.c b/ports/zephyr-cp/common-hal/socketpool/Socket.c index 857526a12de..ca8ba419839 100644 --- a/ports/zephyr-cp/common-hal/socketpool/Socket.c +++ b/ports/zephyr-cp/common-hal/socketpool/Socket.c @@ -20,165 +20,104 @@ #include "supervisor/shared/tick.h" #include "supervisor/workflow.h" -#include - -// void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port) { -// // struct addrinfo *result_i; -// // const struct addrinfo hints = { -// // .ai_family = family, -// // .ai_socktype = type, -// // }; -// // int error = socketpool_getaddrinfo_common(hostname, port, &hints, &result_i); -// if (true) { -// common_hal_socketpool_socketpool_raise_gaierror_noname(); -// } -// // memcpy(addr, result_i->ai_addr, sizeof(struct sockaddr_storage)); -// // lwip_freeaddrinfo(result_i); -// } - -// static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) { -// socketpool_resolve_host_or_throw(self->family, self->type, hostname, addr, port); -// } - -// StackType_t socket_select_stack[2 * configMINIMAL_STACK_SIZE]; - -// /* Socket state table: -// * 0 := Closed (unused) -// * 1 := Open -// * 2 := Closing (remove from rfds) -// * Index into socket_fd_state is calculated from actual lwip fd. idx := fd - LWIP_SOCKET_OFFSET -// */ -// #define FDSTATE_CLOSED 0 -// #define FDSTATE_OPEN 1 -// #define FDSTATE_CLOSING 2 -// static uint8_t socket_fd_state[CONFIG_LWIP_MAX_SOCKETS]; +#include +#include +#include +#include +#include -// How long to wait between checks for a socket to connect. -#define SOCKET_CONNECT_POLL_INTERVAL_MS 100 +#include +#include -// static socketpool_socket_obj_t *user_socket[CONFIG_LWIP_MAX_SOCKETS]; -// StaticTask_t socket_select_task_buffer; -// TaskHandle_t socket_select_task_handle; -// static int socket_change_fd = -1; - -// static void socket_select_task(void *arg) { -// uint64_t signal; -// fd_set readfds; -// fd_set excptfds; - -// while (true) { -// FD_ZERO(&readfds); -// FD_ZERO(&excptfds); -// FD_SET(socket_change_fd, &readfds); -// int max_fd = socket_change_fd; -// for (size_t i = 0; i < MP_ARRAY_SIZE(socket_fd_state); i++) { -// if ((socket_fd_state[i] == FDSTATE_OPEN) && (user_socket[i] == NULL)) { -// int sockfd = i + LWIP_SOCKET_OFFSET; -// max_fd = MAX(max_fd, sockfd); -// FD_SET(sockfd, &readfds); -// FD_SET(sockfd, &excptfds); -// } -// } - -// int num_triggered = select(max_fd + 1, &readfds, NULL, &excptfds, NULL); -// // Hard error (or someone closed a socket on another thread) -// if (num_triggered == -1) { -// assert(errno == EBADF); -// continue; -// } - -// assert(num_triggered > 0); - -// // Notice event trigger -// if (FD_ISSET(socket_change_fd, &readfds)) { -// read(socket_change_fd, &signal, sizeof(signal)); -// num_triggered--; -// } - -// // Handle active FDs, close the dead ones -// for (size_t i = 0; i < MP_ARRAY_SIZE(socket_fd_state); i++) { -// int sockfd = i + LWIP_SOCKET_OFFSET; -// if (socket_fd_state[i] != FDSTATE_CLOSED) { -// if (FD_ISSET(sockfd, &readfds) || FD_ISSET(sockfd, &excptfds)) { -// if (socket_fd_state[i] == FDSTATE_CLOSING) { -// socket_fd_state[i] = FDSTATE_CLOSED; -// num_triggered--; -// } -// } -// } -// } - -// if (num_triggered > 0) { -// // Wake up CircuitPython by queuing request -// supervisor_workflow_request_background(); -// ulTaskNotifyTake(pdTRUE, portMAX_DELAY); -// } -// } - -// close(socket_change_fd); -// socket_change_fd = -1; -// vTaskDelete(NULL); -// } +#define SOCKETPOOL_IP_STR_LEN 48 -void socket_user_reset(void) { - // if (socket_change_fd < 0) { - // esp_vfs_eventfd_config_t config = ESP_VFS_EVENTD_CONFIG_DEFAULT(); - // ESP_ERROR_CHECK(esp_vfs_eventfd_register(&config)); - - // // Clear initial socket states - // for (size_t i = 0; i < MP_ARRAY_SIZE(socket_fd_state); i++) { - // socket_fd_state[i] = FDSTATE_CLOSED; - // user_socket[i] = NULL; - // } - // socket_change_fd = eventfd(0, 0); - // // Run this at the same priority as CP so that the web workflow background task can be - // // queued while CP is running. Both tasks can still sleep and, therefore, sleep overall. - // socket_select_task_handle = xTaskCreateStaticPinnedToCore(socket_select_task, - // "socket_select", - // 2 * configMINIMAL_STACK_SIZE, - // NULL, - // uxTaskPriorityGet(NULL), - // socket_select_stack, - // &socket_select_task_buffer, - // xPortGetCoreID()); - // } else { - // // Not init - close open user sockets - // for (size_t i = 0; i < MP_ARRAY_SIZE(socket_fd_state); i++) { - // if ((socket_fd_state[i] == FDSTATE_OPEN) && user_socket[i]) { - // common_hal_socketpool_socket_close(user_socket[i]); - // } - // } - // } +static mp_obj_t _format_address(const struct sockaddr *addr, int family) { + char ip_str[SOCKETPOOL_IP_STR_LEN]; + const struct sockaddr_in *a = (void *)addr; + + switch (family) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + case AF_INET6: + zsock_inet_ntop(family, &((const struct sockaddr_in6 *)a)->sin6_addr, ip_str, sizeof(ip_str)); + break; + #endif + default: + case AF_INET: + zsock_inet_ntop(family, &((const struct sockaddr_in *)a)->sin_addr, ip_str, sizeof(ip_str)); + break; + } + return mp_obj_new_str(ip_str, strlen(ip_str)); } -// Unblock select task (ok if not blocked yet) -void socketpool_socket_poll_resume(void) { - // if (socket_select_task_handle) { - // xTaskNotifyGive(socket_select_task_handle); - // } +static mp_obj_t _sockaddr_to_tuple(const struct sockaddr_storage *sockaddr) { + mp_obj_t args[4] = { + _format_address((const struct sockaddr *)sockaddr, sockaddr->ss_family), + }; + int n = 2; + #if CIRCUITPY_SOCKETPOOL_IPV6 + if (sockaddr->ss_family == AF_INET6) { + const struct sockaddr_in6 *addr6 = (const void *)sockaddr; + args[1] = MP_OBJ_NEW_SMALL_INT(ntohs(addr6->sin6_port)); + args[2] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_flowinfo); + args[3] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_scope_id); + n = 4; + } else + #endif + { + const struct sockaddr_in *addr = (const void *)sockaddr; + args[1] = MP_OBJ_NEW_SMALL_INT(ntohs(addr->sin_port)); + } + return mp_obj_new_tuple(n, args); +} + +static void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port) { + const struct zsock_addrinfo hints = { + .ai_family = family, + .ai_socktype = type, + }; + struct zsock_addrinfo *result_i = NULL; + char service_buf[6]; + + snprintf(service_buf, sizeof(service_buf), "%d", port); + + int error = zsock_getaddrinfo(hostname, service_buf, &hints, &result_i); + if (error != 0 || result_i == NULL) { + common_hal_socketpool_socketpool_raise_gaierror_noname(); + } + + memcpy(addr, result_i->ai_addr, sizeof(struct sockaddr_storage)); + zsock_freeaddrinfo(result_i); } -// The writes below send an event to the socket select task so that it redoes the -// select with the new open socket set. +static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) { + socketpool_resolve_host_or_throw(self->family, self->type, hostname, addr, port); +} -// static bool register_open_socket(int fd) { -// if (fd < FD_SETSIZE) { -// socket_fd_state[fd - LWIP_SOCKET_OFFSET] = FDSTATE_OPEN; -// user_socket[fd - LWIP_SOCKET_OFFSET] = NULL; +// How long to wait between checks for a socket to connect. +#define SOCKET_CONNECT_POLL_INTERVAL_MS 100 -// uint64_t signal = 1; -// write(socket_change_fd, &signal, sizeof(signal)); -// socketpool_socket_poll_resume(); -// return true; -// } -// return false; -// } +void socket_user_reset(void) { + // User sockets are heap objects with __del__ bound to close(). + // During VM shutdown/reset, gc_sweep_all() runs finalizers, so sockets + // are closed there rather than being tracked and closed explicitly here. +} + +static struct k_work_delayable socketpool_poll_work; +static bool socketpool_poll_work_initialized; -// static void mark_user_socket(int fd, socketpool_socket_obj_t *obj) { -// socket_fd_state[fd - LWIP_SOCKET_OFFSET] = FDSTATE_OPEN; -// user_socket[fd - LWIP_SOCKET_OFFSET] = obj; -// // No need to wakeup select task -// } +static void socketpool_poll_work_handler(struct k_work *work) { + (void)work; + supervisor_workflow_request_background(); +} + +// Unblock select task (ok if not blocked yet) +void socketpool_socket_poll_resume(void) { + if (!socketpool_poll_work_initialized) { + k_work_init_delayable(&socketpool_poll_work, socketpool_poll_work_handler); + socketpool_poll_work_initialized = true; + } + k_work_schedule(&socketpool_poll_work, K_MSEC(10)); +} static bool _socketpool_socket(socketpool_socketpool_obj_t *self, socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, @@ -212,16 +151,23 @@ static bool _socketpool_socket(socketpool_socketpool_obj_t *self, sock->pool = self; sock->timeout_ms = (uint)-1; - // Create LWIP socket - // int socknum = -1; - // socknum = lwip_socket(sock->family, sock->type, sock->ipproto); - // if (socknum < 0) { - // return false; - // } + int socknum = zsock_socket(sock->family, sock->type, sock->ipproto); + if (socknum < 0) { + return false; + } - // sock->num = socknum; - // // Sockets should be nonblocking in most cases - // lwip_fcntl(socknum, F_SETFL, O_NONBLOCK); + sock->num = socknum; + + // Enable address reuse by default to avoid bind failures on recently-used ports. + int reuseaddr = 1; + if (zsock_setsockopt(socknum, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) < 0) { + // Ignore if SO_REUSEADDR is unsupported. + } + + // Sockets should be nonblocking in most cases. + if (zsock_fcntl(socknum, F_SETFL, O_NONBLOCK) < 0) { + // Ignore if non-blocking is unsupported. + } return true; } @@ -235,11 +181,6 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self, return false; } - // This shouldn't happen since we have room for the same number of sockets as LWIP. - // if (!register_open_socket(sock->num)) { - // lwip_close(sock->num); - // return false; - // } return true; } @@ -260,13 +201,12 @@ socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_ if (!_socketpool_socket(self, family, type, proto, sock)) { mp_raise_RuntimeError(MP_ERROR_TEXT("Out of sockets")); } - // mark_user_socket(sock->num, sock); return sock; } int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted) { struct sockaddr_storage peer_addr; - // socklen_t socklen = sizeof(peer_addr); + socklen_t socklen = sizeof(peer_addr); int newsoc = -1; bool timed_out = false; uint64_t start_ticks = supervisor_ticks_ms64(); @@ -277,11 +217,23 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; } RUN_BACKGROUND_TASKS; - // newsoc = lwip_accept(self->num, (struct sockaddr *)&peer_addr, &socklen); + #if CIRCUITPY_HOSTNETWORK + if (self->timeout_ms == 0) { + struct zsock_timeval tv = { + .tv_sec = 0, + .tv_usec = 1000, + }; + zsock_setsockopt(self->num, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + } + #endif + newsoc = zsock_accept(self->num, (struct sockaddr *)&peer_addr, &socklen); // In non-blocking mode, fail instead of timing out if (newsoc == -1 && (self->timeout_ms == 0 || mp_hal_is_interrupted())) { return -MP_EAGAIN; } + if (newsoc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { + return -errno; + } } if (timed_out) { @@ -293,18 +245,14 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, } // We got a socket. New client socket will not be non-blocking by default, so make it non-blocking. - // lwip_fcntl(newsoc, F_SETFL, O_NONBLOCK); + if (zsock_fcntl(newsoc, F_SETFL, O_NONBLOCK) < 0) { + // Ignore if non-blocking is unsupported. + } if (accepted != NULL) { // Error if called with open socket object. assert(common_hal_socketpool_socket_get_closed(accepted)); - // Register if system socket - // if (!register_open_socket(newsoc)) { - // lwip_close(newsoc); - // return -MP_EBADF; - // } - // Replace the old accepted socket with the new one. accepted->num = newsoc; accepted->pool = self->pool; @@ -313,7 +261,7 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, } if (peer_out) { - *peer_out = sockaddr_to_tuple(&peer_addr); + *peer_out = _sockaddr_to_tuple(&peer_addr); } return newsoc; @@ -327,7 +275,6 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o if (newsoc > 0) { // Create the socket - // mark_user_socket(newsoc, sock); sock->base.type = &socketpool_socket_type; sock->num = newsoc; sock->pool = self->pool; @@ -343,40 +290,42 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port) { - // struct sockaddr_storage bind_addr; + struct sockaddr_storage bind_addr; const char *broadcast = ""; + uint32_t local_port = port; - // bind_addr.ss_family = self->family; + memset(&bind_addr, 0, sizeof(bind_addr)); + bind_addr.ss_family = self->family; #if CIRCUITPY_SOCKETPOOL_IPV6 if (self->family == AF_INET6) { struct sockaddr_in6 *addr6 = (void *)&bind_addr; - addr6->sin6_port = htons(port); + addr6->sin6_port = htons(local_port); // no ipv6 broadcast if (hostlen == 0) { memset(&addr6->sin6_addr, 0, sizeof(addr6->sin6_addr)); } else { - socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port); + socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, local_port); } } else #endif { - // struct sockaddr_in *addr4 = (void *)&bind_addr; - // addr4->sin_port = htons(port); + struct sockaddr_in *addr4 = (void *)&bind_addr; + addr4->sin_port = htons(local_port); if (hostlen == 0) { - // addr4->sin_addr.s_addr = IPADDR_ANY; + addr4->sin_addr.s_addr = htonl(INADDR_ANY); } else if (hostlen == strlen(broadcast) && memcmp(host, broadcast, strlen(broadcast)) == 0) { - // addr4->sin_addr.s_addr = IPADDR_BROADCAST; + addr4->sin_addr.s_addr = htonl(INADDR_BROADCAST); } else { - // socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port); + socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, local_port); } } - // int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); - // if (result == 0) { - // return 0; - // } + int result = zsock_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); + if (result == 0) { + return 0; + } return errno; } @@ -390,20 +339,11 @@ void socketpool_socket_close(socketpool_socket_obj_t *self) { } #endif self->connected = false; - // int fd = self->num; - // Ignore bogus/closed sockets - // if (fd >= LWIP_SOCKET_OFFSET) { - // if (user_socket[fd - LWIP_SOCKET_OFFSET] == NULL) { - // socket_fd_state[fd - LWIP_SOCKET_OFFSET] = FDSTATE_CLOSING; - // lwip_shutdown(fd, SHUT_RDWR); - // lwip_close(fd); - // } else { - // lwip_shutdown(fd, SHUT_RDWR); - // lwip_close(fd); - // socket_fd_state[fd - LWIP_SOCKET_OFFSET] = FDSTATE_CLOSED; - // user_socket[fd - LWIP_SOCKET_OFFSET] = NULL; - // } - // } + int fd = self->num; + if (fd >= 0) { + zsock_shutdown(fd, ZSOCK_SHUT_RDWR); + zsock_close(fd); + } self->num = -1; } @@ -413,16 +353,11 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) { void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port) { - // struct sockaddr_storage addr; - // resolve_host_or_throw(self, host, &addr, port); - - // Replace above with function call ----- - - // Emulate SO_CONTIMEO, which is not implemented by lwip. - // All our sockets are non-blocking, so we check the timeout ourselves. + (void)hostlen; + struct sockaddr_storage addr; + resolve_host_or_throw(self, host, &addr, port); - int result = -1; - // result = lwip_connect(self->num, (struct sockaddr *)&addr, addr.s2_len); + int result = zsock_connect(self->num, (struct sockaddr *)&addr, sizeof(addr)); if (result == 0) { // Connected immediately. @@ -436,12 +371,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, return; } - // struct timeval timeout = { - // .tv_sec = 0, - // .tv_usec = SOCKET_CONNECT_POLL_INTERVAL_MS * 1000, - // }; - - // Keep checking, using select(), until timeout expires, at short intervals. + // Keep checking, using poll(), until timeout expires, at short intervals. // This allows ctrl-C interrupts to be detected and background tasks to run. mp_uint_t timeout_left = self->timeout_ms; @@ -452,14 +382,22 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, return; } - // fd_set fds; - // FD_ZERO(&fds); - // FD_SET(self->num, &fds); + struct zsock_pollfd fd = { + .fd = self->num, + .events = ZSOCK_POLLOUT, + }; + int poll_timeout = SOCKET_CONNECT_POLL_INTERVAL_MS; + if (self->timeout_ms == (uint)-1) { + poll_timeout = -1; + } else if (timeout_left < SOCKET_CONNECT_POLL_INTERVAL_MS) { + poll_timeout = timeout_left; + } - // result = select(self->num + 1, NULL, &fds, NULL, &timeout); + result = zsock_poll(&fd, 1, poll_timeout); if (result == 0) { - // No change to fd's after waiting for timeout, so try again if some time is still left. - // Don't wrap below 0, because we're using a uint. + if (self->timeout_ms == (uint)-1) { + continue; + } if (timeout_left < SOCKET_CONNECT_POLL_INTERVAL_MS) { timeout_left = 0; } else { @@ -469,16 +407,14 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, } if (result < 0) { - // Some error happened when doing select(); error is in errno. mp_raise_OSError(errno); } - // select() indicated the socket is writable. Check if any connection error occurred. int error_code = 0; - // socklen_t socklen = sizeof(error_code); - // result = getsockopt(self->num, SOL_SOCKET, SO_ERROR, &error_code, &socklen); + socklen_t socklen = sizeof(error_code); + result = zsock_getsockopt(self->num, SOL_SOCKET, SO_ERROR, &error_code, &socklen); if (result < 0 || error_code != 0) { - mp_raise_OSError(errno); + mp_raise_OSError(error_code != 0 ? error_code : errno); } self->connected = true; return; @@ -498,17 +434,15 @@ bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t *self) { } bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int backlog) { - // return lwip_listen(self->num, backlog) == 0; - return false; + return zsock_listen(self->num, backlog) == 0; } mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *self, uint8_t *buf, uint32_t len, mp_obj_t *source_out) { - // struct sockaddr_storage source_addr; - // socklen_t socklen = sizeof(source_addr); + struct sockaddr_storage source_addr; + socklen_t socklen = sizeof(source_addr); - // LWIP Socket uint64_t start_ticks = supervisor_ticks_ms64(); int received = -1; bool timed_out = false; @@ -519,11 +453,18 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; } RUN_BACKGROUND_TASKS; - // received = lwip_recvfrom(self->num, buf, len, 0, (struct sockaddr *)&source_addr, &socklen); + received = zsock_recvfrom(self->num, buf, len, ZSOCK_MSG_DONTWAIT, (struct sockaddr *)&source_addr, &socklen); - // In non-blocking mode, fail instead of looping - if (received == -1 && self->timeout_ms == 0) { - mp_raise_OSError(MP_EAGAIN); + if (received < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { + mp_raise_OSError(errno); + } + + if (received == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + // In non-blocking mode, fail instead of looping + if (self->timeout_ms == 0) { + mp_raise_OSError(MP_EAGAIN); + } + continue; } } @@ -537,7 +478,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se } if (source_out) { - // *source_out = sockaddr_to_tuple(&source_addr); + *source_out = _sockaddr_to_tuple(&source_addr); } return received; @@ -549,7 +490,6 @@ int socketpool_socket_recv_into(socketpool_socket_obj_t *self, bool timed_out = false; if (self->num != -1) { - // LWIP Socket uint64_t start_ticks = supervisor_ticks_ms64(); received = -1; while (received == -1 && @@ -558,7 +498,16 @@ int socketpool_socket_recv_into(socketpool_socket_obj_t *self, timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; } RUN_BACKGROUND_TASKS; - // received = lwip_recv(self->num, (void *)buf, len, 0); + received = zsock_recv(self->num, (void *)buf, len, ZSOCK_MSG_DONTWAIT); + if (received < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { + return -errno; + } + if (received < 1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + if (self->timeout_ms == 0) { + return -MP_EAGAIN; + } + continue; + } // In non-blocking mode, fail instead of looping if (received < 1 && self->timeout_ms == 0) { if ((received == 0) || (errno == ENOTCONN)) { @@ -597,9 +546,7 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t *self, int socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) { int sent = -1; if (self->num != -1) { - // LWIP Socket - // TODO: deal with potential failure/add timeout? - // sent = lwip_send(self->num, buf, len, 0); + sent = zsock_send(self->num, buf, len, 0); } else { sent = -MP_EBADF; } @@ -626,15 +573,15 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) { - // struct sockaddr_storage addr; - // resolve_host_or_throw(self, host, &addr, port); + (void)hostlen; + struct sockaddr_storage addr; + resolve_host_or_throw(self, host, &addr, port); - // int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&addr, addr.s2_len); - // if (bytes_sent < 0) { - // mp_raise_BrokenPipeError(); - // return 0; - // } - int bytes_sent = 0; + int bytes_sent = zsock_sendto(self->num, buf, len, 0, (struct sockaddr *)&addr, sizeof(addr)); + if (bytes_sent < 0) { + mp_raise_BrokenPipeError(); + return 0; + } return bytes_sent; } @@ -648,7 +595,44 @@ mp_int_t common_hal_socketpool_socket_get_type(socketpool_socket_obj_t *self) { int common_hal_socketpool_socket_setsockopt(socketpool_socket_obj_t *self, int level, int optname, const void *value, size_t optlen) { - int err = 0; // lwip_setsockopt(self->num, level, optname, value, optlen); + int zephyr_level = level; + int zephyr_optname = optname; + + switch (level) { + case SOCKETPOOL_SOL_SOCKET: + zephyr_level = SOL_SOCKET; + break; + case SOCKETPOOL_IPPROTO_IP: + zephyr_level = IPPROTO_IP; + break; + case SOCKETPOOL_IPPROTO_TCP: + zephyr_level = IPPROTO_TCP; + break; + case SOCKETPOOL_IPPROTO_UDP: + zephyr_level = IPPROTO_UDP; + break; + #if CIRCUITPY_SOCKETPOOL_IPV6 + case SOCKETPOOL_IPPROTO_IPV6: + zephyr_level = IPPROTO_IPV6; + break; + #endif + } + + if (zephyr_level == SOL_SOCKET) { + switch (optname) { + case SOCKETPOOL_SO_REUSEADDR: + zephyr_optname = SO_REUSEADDR; + break; + } + } else if (zephyr_level == IPPROTO_TCP) { + switch (optname) { + case SOCKETPOOL_TCP_NODELAY: + zephyr_optname = TCP_NODELAY; + break; + } + } + + int err = zsock_setsockopt(self->num, zephyr_level, zephyr_optname, value, optlen); if (err != 0) { return -errno; } @@ -656,29 +640,23 @@ int common_hal_socketpool_socket_setsockopt(socketpool_socket_obj_t *self, int l } bool common_hal_socketpool_readable(socketpool_socket_obj_t *self) { - // struct timeval immediate = {0, 0}; + struct zsock_pollfd fd = { + .fd = self->num, + .events = ZSOCK_POLLIN, + }; - // fd_set fds; - // FD_ZERO(&fds); - // FD_SET(self->num, &fds); - // int num_triggered = select(self->num + 1, &fds, NULL, &fds, &immediate); - - // including returning true in the error case - // return num_triggered != 0; - return false; + int num_triggered = zsock_poll(&fd, 1, 0); + return num_triggered > 0; } bool common_hal_socketpool_writable(socketpool_socket_obj_t *self) { - // struct timeval immediate = {0, 0}; - - // fd_set fds; - // FD_ZERO(&fds); - // FD_SET(self->num, &fds); - // int num_triggered = select(self->num + 1, NULL, &fds, &fds, &immediate); + struct zsock_pollfd fd = { + .fd = self->num, + .events = ZSOCK_POLLOUT, + }; - // including returning true in the error case - // return num_triggered != 0; - return false; + int num_triggered = zsock_poll(&fd, 1, 0); + return num_triggered > 0; } void socketpool_socket_move(socketpool_socket_obj_t *self, socketpool_socket_obj_t *sock) { diff --git a/ports/zephyr-cp/common-hal/socketpool/SocketPool.c b/ports/zephyr-cp/common-hal/socketpool/SocketPool.c index 4531c5bf1b7..c9a3f008321 100644 --- a/ports/zephyr-cp/common-hal/socketpool/SocketPool.c +++ b/ports/zephyr-cp/common-hal/socketpool/SocketPool.c @@ -8,114 +8,116 @@ #include "common-hal/socketpool/Socket.h" #include "py/runtime.h" +#if CIRCUITPY_HOSTNETWORK +#include "bindings/hostnetwork/__init__.h" +#endif +#if CIRCUITPY_WIFI #include "shared-bindings/wifi/__init__.h" +#endif #include "common-hal/socketpool/__init__.h" +#include +#include + +#include + void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *self, mp_obj_t radio) { - if (radio != MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj)) { - mp_raise_ValueError(MP_ERROR_TEXT("SocketPool can only be used with wifi.radio")); + bool is_wifi = false; + #if CIRCUITPY_WIFI + is_wifi = radio == MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj); + #endif + bool is_hostnetwork = false; + #if CIRCUITPY_HOSTNETWORK + is_hostnetwork = mp_obj_is_type(radio, &hostnetwork_hostnetwork_type); + #endif + if (!(is_wifi || is_hostnetwork)) { + mp_raise_ValueError(MP_ERROR_TEXT("SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork")); } } // common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking. -// int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res) { -// // As of 2022, the version of lwip in esp-idf does not handle the -// // trailing-dot syntax of domain names, so emulate it. -// // Remove this once https://github.com/espressif/esp-idf/issues/10013 has -// // been implemented -// if (host) { -// size_t strlen_host = strlen(host); -// if (strlen_host && host[strlen_host - 1] == '.') { -// mp_obj_t nodot = mp_obj_new_str(host, strlen_host - 1); -// host = mp_obj_str_get_str(nodot); -// } -// } - -// // char service_buf[6]; -// // snprintf(service_buf, sizeof(service_buf), "%d", service); - -// // return lwip_getaddrinfo(host, service_buf, hints, res); -// return 0; -// } - -// static mp_obj_t format_address(const struct sockaddr *addr, int family) { -// char ip_str[IPADDR_STRLEN_MAX]; // big enough for any supported address type -// const struct sockaddr_in *a = (void *)addr; - -// switch (family) { -// #if CIRCUITPY_SOCKETPOOL_IPV6 -// case AF_INET6: -// inet_ntop(family, &((const struct sockaddr_in6 *)a)->sin6_addr, ip_str, sizeof(ip_str)); -// break; -// #endif -// default: -// case AF_INET: -// inet_ntop(family, &((const struct sockaddr_in *)a)->sin_addr, ip_str, sizeof(ip_str)); -// break; -// } -// return mp_obj_new_str(ip_str, strlen(ip_str)); -// } - -// static mp_obj_t convert_sockaddr(const struct addrinfo *ai, int port) { -// #if CIRCUITPY_SOCKETPOOL_IPV6 -// mp_int_t n_tuple = ai->ai_family == AF_INET6 ? 4 : 2; -// #else -// mp_int_t n_tuple = 2; -// #endif -// mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_tuple, NULL)); -// result->items[0] = format_address(ai->ai_addr, ai->ai_family); -// result->items[1] = MP_OBJ_NEW_SMALL_INT(port); -// #if CIRCUITPY_SOCKETPOOL_IPV6 -// if (ai->ai_family == AF_INET6) { -// const struct sockaddr_in6 *ai6 = (void *)ai->ai_addr; -// result->items[2] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_flowinfo); -// result->items[3] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_scope_id); -// } -// #endif -// return result; -// } - -// static mp_obj_t convert_addrinfo(const struct addrinfo *ai, int port) { -// MP_STATIC_ASSERT(AF_INET == SOCKETPOOL_AF_INET); -// #if CIRCUITPY_SOCKETPOOL_IPV6 -// MP_STATIC_ASSERT(AF_INET6 == SOCKETPOOL_AF_INET6); -// #endif -// // MP_STATIC_ASSERT(AF_UNSPEC == SOCKETPOOL_AF_UNSPEC); -// mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); -// result->items[0] = MP_OBJ_NEW_SMALL_INT(ai->ai_family); -// result->items[1] = MP_OBJ_NEW_SMALL_INT(ai->ai_socktype); -// result->items[2] = MP_OBJ_NEW_SMALL_INT(ai->ai_protocol); -// result->items[3] = ai->ai_canonname ? mp_obj_new_str(ai->ai_canonname, strlen(ai->ai_canonname)) : MP_OBJ_NEW_QSTR(MP_QSTR_); -// result->items[4] = convert_sockaddr(ai, port); -// return result; -// } +static int socketpool_getaddrinfo_common(const char *host, int service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res) { + char service_buf[6]; + snprintf(service_buf, sizeof(service_buf), "%d", service); + + return zsock_getaddrinfo(host, service_buf, hints, res); +} + +#define SOCKETPOOL_IP_STR_LEN 48 + +static mp_obj_t format_address(const struct sockaddr *addr, int family) { + char ip_str[SOCKETPOOL_IP_STR_LEN]; + const struct sockaddr_in *a = (void *)addr; + + switch (family) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + case AF_INET6: + zsock_inet_ntop(family, &((const struct sockaddr_in6 *)a)->sin6_addr, ip_str, sizeof(ip_str)); + break; + #endif + default: + case AF_INET: + zsock_inet_ntop(family, &((const struct sockaddr_in *)a)->sin_addr, ip_str, sizeof(ip_str)); + break; + } + return mp_obj_new_str(ip_str, strlen(ip_str)); +} + +static mp_obj_t convert_sockaddr(const struct zsock_addrinfo *ai, int port) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + mp_int_t n_tuple = ai->ai_family == AF_INET6 ? 4 : 2; + #else + mp_int_t n_tuple = 2; + #endif + mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_tuple, NULL)); + result->items[0] = format_address(ai->ai_addr, ai->ai_family); + result->items[1] = MP_OBJ_NEW_SMALL_INT(port); + #if CIRCUITPY_SOCKETPOOL_IPV6 + if (ai->ai_family == AF_INET6) { + const struct sockaddr_in6 *ai6 = (void *)ai->ai_addr; + result->items[2] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_flowinfo); + result->items[3] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_scope_id); + } + #endif + return result; +} + +static mp_obj_t convert_addrinfo(const struct zsock_addrinfo *ai, int port) { + mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); + result->items[0] = MP_OBJ_NEW_SMALL_INT(ai->ai_family); + result->items[1] = MP_OBJ_NEW_SMALL_INT(ai->ai_socktype); + result->items[2] = MP_OBJ_NEW_SMALL_INT(ai->ai_protocol); + result->items[3] = ai->ai_canonname ? mp_obj_new_str(ai->ai_canonname, strlen(ai->ai_canonname)) : MP_OBJ_NEW_QSTR(MP_QSTR_); + result->items[4] = convert_sockaddr(ai, port); + return result; +} mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *self, const char *host, int port, int family, int type, int proto, int flags) { - // const struct addrinfo hints = { - // .ai_flags = flags, - // .ai_family = family, - // .ai_protocol = proto, - // .ai_socktype = type, - // }; - - // struct addrinfo *res = NULL; - // int err = socketpool_getaddrinfo_common(host, port, &hints, &res); - if (true) { + const struct zsock_addrinfo hints = { + .ai_flags = flags, + .ai_family = family, + .ai_protocol = proto, + .ai_socktype = type, + }; + + struct zsock_addrinfo *res = NULL; + int err = socketpool_getaddrinfo_common(host, port, &hints, &res); + if (err != 0 || res == NULL) { common_hal_socketpool_socketpool_raise_gaierror_noname(); } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t result = mp_obj_new_list(0, NULL); - // for (struct addrinfo *ai = res; ai; ai = ai->ai_next) { - // mp_obj_list_append(result, convert_addrinfo(ai, port)); - // } + for (struct zsock_addrinfo *ai = res; ai; ai = ai->ai_next) { + mp_obj_list_append(result, convert_addrinfo(ai, port)); + } nlr_pop(); - // lwip_freeaddrinfo(res); + zsock_freeaddrinfo(res); return result; } else { - // lwip_freeaddrinfo(res); + zsock_freeaddrinfo(res); nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); } } diff --git a/ports/zephyr-cp/common-hal/socketpool/SocketPool.h b/ports/zephyr-cp/common-hal/socketpool/SocketPool.h index 64f91e01e1c..7891a8b8e48 100644 --- a/ports/zephyr-cp/common-hal/socketpool/SocketPool.h +++ b/ports/zephyr-cp/common-hal/socketpool/SocketPool.h @@ -6,6 +6,9 @@ #pragma once +#include +#include + #include "py/obj.h" typedef struct { diff --git a/ports/zephyr-cp/common-hal/usb_cdc/Serial.c b/ports/zephyr-cp/common-hal/usb_cdc/Serial.c index 272a78b3141..715955d6e0f 100644 --- a/ports/zephyr-cp/common-hal/usb_cdc/Serial.c +++ b/ports/zephyr-cp/common-hal/usb_cdc/Serial.c @@ -7,6 +7,7 @@ #include "shared/runtime/interrupt_char.h" #include "shared-bindings/usb_cdc/Serial.h" #include "shared-bindings/busio/UART.h" +#include "common-hal/busio/UART.h" #include "supervisor/shared/tick.h" mp_obj_t common_hal_usb_cdc_serial_construct_from_device(usb_cdc_serial_obj_t *self, const struct device *uart_device, uint16_t receiver_buffer_size, byte *receiver_buffer) { diff --git a/ports/zephyr-cp/common-hal/wifi/Radio.c b/ports/zephyr-cp/common-hal/wifi/Radio.c index 726b406b3ca..35a0b76a362 100644 --- a/ports/zephyr-cp/common-hal/wifi/Radio.c +++ b/ports/zephyr-cp/common-hal/wifi/Radio.c @@ -86,13 +86,19 @@ void common_hal_wifi_radio_set_enabled(wifi_radio_obj_t *self, bool enabled) { // mdns_server_deinit_singleton(); // #endif printk("net_if_down\n"); - CHECK_ZEPHYR_RESULT(net_if_down(self->sta_netif)); + int res = net_if_down(self->sta_netif); + if (res < 0 && res != -EALREADY) { + raise_zephyr_error(res); + } self->started = false; return; } if (!self->started && enabled) { printk("net_if_up\n"); - CHECK_ZEPHYR_RESULT(net_if_up(self->sta_netif)); + int res = net_if_up(self->sta_netif); + if (res < 0 && res != -EALREADY) { + raise_zephyr_error(res); + } self->started = true; self->current_scan = NULL; // common_hal_wifi_radio_set_tx_power(self, CIRCUITPY_WIFI_DEFAULT_TX_POWER); diff --git a/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.c b/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.c index 3a6c21c5b83..725bf1fa7cb 100644 --- a/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.c +++ b/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.c @@ -16,6 +16,7 @@ #include "shared-bindings/wifi/Network.h" #include "shared-bindings/wifi/Radio.h" #include "shared-bindings/wifi/ScannedNetworks.h" +#include "bindings/zephyr_kernel/__init__.h" #include #include diff --git a/ports/zephyr-cp/common-hal/wifi/__init__.c b/ports/zephyr-cp/common-hal/wifi/__init__.c index 57f073a9cbb..4b967bc2780 100644 --- a/ports/zephyr-cp/common-hal/wifi/__init__.c +++ b/ports/zephyr-cp/common-hal/wifi/__init__.c @@ -22,6 +22,10 @@ wifi_radio_obj_t common_hal_wifi_radio_obj; #include "supervisor/port.h" #include "supervisor/workflow.h" +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" +#endif + #if CIRCUITPY_STATUS_BAR #include "supervisor/shared/status_bar.h" #endif @@ -29,6 +33,8 @@ wifi_radio_obj_t common_hal_wifi_radio_obj; #include #include +#include + #define MAC_ADDRESS_LENGTH 6 static void schedule_background_on_cp_core(void *arg) { @@ -44,20 +50,23 @@ static void schedule_background_on_cp_core(void *arg) { static struct net_mgmt_event_callback wifi_cb; static struct net_mgmt_event_callback ipv4_cb; -static void _event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface) { +static void _event_handler(struct net_mgmt_event_callback *cb, uint64_t mgmt_event, struct net_if *iface) { wifi_radio_obj_t *self = &common_hal_wifi_radio_obj; - printk("_event_handler cb %p event %08x if %p\n", cb, mgmt_event, iface); + (void)iface; switch (mgmt_event) { - case NET_EVENT_WIFI_SCAN_RESULT: + case NET_EVENT_WIFI_SCAN_RESULT: { printk("NET_EVENT_WIFI_SCAN_RESULT\n"); - struct wifi_scan_result *result = (struct wifi_scan_result *)cb->info; - if (self->current_scan != NULL) { + const struct wifi_scan_result *result = cb->info; + if (result != NULL && self->current_scan != NULL) { wifi_scannednetworks_scan_result(self->current_scan, result); } break; + } case NET_EVENT_WIFI_SCAN_DONE: - printk("NET_EVENT_WIFI_SCAN_DONE\n"); + printk("NET_EVENT_WIFI_SCAN_DONE (thread: %s prio=%d)\n", + k_thread_name_get(k_current_get()), + k_thread_priority_get(k_current_get())); if (self->current_scan != NULL) { k_poll_signal_raise(&self->current_scan->channel_done, 0); } @@ -101,6 +110,9 @@ static void _event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_eve case NET_EVENT_WIFI_AP_STA_DISCONNECTED: printk("NET_EVENT_WIFI_AP_STA_DISCONNECTED\n"); break; + default: + printk("unhandled net event %x\n", mgmt_event); + break; } } @@ -281,6 +293,7 @@ void common_hal_wifi_init(bool user_initiated) { net_mgmt_add_event_callback(&wifi_cb); net_mgmt_add_event_callback(&ipv4_cb); + #if defined(CONFIG_NET_HOSTNAME) // Set the default hostname capped at NET_HOSTNAME_MAX_LEN characters. We trim off // the start of the board name (likely manufacturer) because the end is // often more unique to the board. @@ -291,16 +304,28 @@ void common_hal_wifi_init(bool user_initiated) { board_trim++; } - char cpy_default_hostname[board_len + (MAC_ADDRESS_LENGTH * 2) + 6]; - struct net_linkaddr *mac = net_if_get_link_addr(self->sta_netif); - if (mac->len < MAC_ADDRESS_LENGTH) { - printk("MAC address too short"); + #if CIRCUITPY_SETTINGS_TOML + char hostname[NET_HOSTNAME_MAX_LEN]; + if (settings_get_str("CIRCUITPY_WIFI_HOSTNAME", hostname, sizeof(hostname)) == SETTINGS_OK) { + CHECK_ZEPHYR_RESULT(net_hostname_set(hostname, strlen(hostname))); + } + #else + if (false) { } - snprintf(cpy_default_hostname, sizeof(cpy_default_hostname), "cpy-%s-%02x%02x%02x%02x%02x%02x", CIRCUITPY_BOARD_ID + board_trim, mac->addr[0], mac->addr[1], mac->addr[2], mac->addr[3], mac->addr[4], mac->addr[5]); + #endif + else { + char cpy_default_hostname[board_len + (MAC_ADDRESS_LENGTH * 2) + 6]; + struct net_linkaddr *mac = net_if_get_link_addr(self->sta_netif); + if (mac->len < MAC_ADDRESS_LENGTH) { + printk("MAC address too short"); + } + snprintf(cpy_default_hostname, sizeof(cpy_default_hostname), "cpy-%s-%02x%02x%02x%02x%02x%02x", CIRCUITPY_BOARD_ID + board_trim, mac->addr[0], mac->addr[1], mac->addr[2], mac->addr[3], mac->addr[4], mac->addr[5]); - if (net_hostname_set(cpy_default_hostname, strlen(cpy_default_hostname)) != 0) { - printk("setting hostname failed\n"); + CHECK_ZEPHYR_RESULT(net_hostname_set(cpy_default_hostname, strlen(cpy_default_hostname))); } + #else + printk("Hostname support disabled in Zephyr config\n"); + #endif // set station mode to avoid the default SoftAP common_hal_wifi_radio_start_station(self); // start wifi diff --git a/ports/zephyr-cp/common-hal/zephyr_display/Display.c b/ports/zephyr-cp/common-hal/zephyr_display/Display.c new file mode 100644 index 00000000000..d1585b5f291 --- /dev/null +++ b/ports/zephyr-cp/common-hal/zephyr_display/Display.c @@ -0,0 +1,440 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "bindings/zephyr_display/Display.h" + +#include + +#include "bindings/zephyr_kernel/__init__.h" +#include "py/gc.h" +#include "py/runtime.h" +#include "shared-bindings/time/__init__.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/display.h" +#include "supervisor/shared/tick.h" + +static const displayio_area_t *zephyr_display_get_refresh_areas(zephyr_display_display_obj_t *self) { + if (self->core.full_refresh) { + self->core.area.next = NULL; + return &self->core.area; + } else if (self->core.current_group != NULL) { + return displayio_group_get_refresh_areas(self->core.current_group, NULL); + } + return NULL; +} + +static enum display_pixel_format zephyr_display_select_pixel_format(const struct display_capabilities *caps) { + uint32_t formats = caps->supported_pixel_formats; + + if (formats & PIXEL_FORMAT_RGB_565) { + return PIXEL_FORMAT_RGB_565; + } + if (formats & PIXEL_FORMAT_RGB_888) { + return PIXEL_FORMAT_RGB_888; + } + if (formats & PIXEL_FORMAT_ARGB_8888) { + return PIXEL_FORMAT_ARGB_8888; + } + if (formats & PIXEL_FORMAT_RGB_565X) { + return PIXEL_FORMAT_RGB_565X; + } + if (formats & PIXEL_FORMAT_L_8) { + return PIXEL_FORMAT_L_8; + } + if (formats & PIXEL_FORMAT_AL_88) { + return PIXEL_FORMAT_AL_88; + } + if (formats & PIXEL_FORMAT_MONO01) { + return PIXEL_FORMAT_MONO01; + } + if (formats & PIXEL_FORMAT_MONO10) { + return PIXEL_FORMAT_MONO10; + } + return caps->current_pixel_format; +} + +static void zephyr_display_select_colorspace(zephyr_display_display_obj_t *self, + uint16_t *color_depth, + uint8_t *bytes_per_cell, + bool *grayscale, + bool *pixels_in_byte_share_row, + bool *reverse_pixels_in_byte, + bool *reverse_bytes_in_word) { + *color_depth = 16; + *bytes_per_cell = 2; + *grayscale = false; + *pixels_in_byte_share_row = false; + *reverse_pixels_in_byte = false; + *reverse_bytes_in_word = false; + + if (self->pixel_format == PIXEL_FORMAT_RGB_565X) { + // RGB_565X is big-endian RGB_565, so byte-swap from native LE. + *reverse_bytes_in_word = true; + } else if (self->pixel_format == PIXEL_FORMAT_RGB_888) { + *color_depth = 24; + *bytes_per_cell = 3; + *reverse_bytes_in_word = false; + } else if (self->pixel_format == PIXEL_FORMAT_ARGB_8888) { + *color_depth = 32; + *bytes_per_cell = 4; + *reverse_bytes_in_word = false; + } else if (self->pixel_format == PIXEL_FORMAT_L_8 || + self->pixel_format == PIXEL_FORMAT_AL_88) { + *color_depth = 8; + *bytes_per_cell = 1; + *grayscale = true; + *reverse_bytes_in_word = false; + } else if (self->pixel_format == PIXEL_FORMAT_MONO01 || + self->pixel_format == PIXEL_FORMAT_MONO10) { + bool vtiled = self->capabilities.screen_info & SCREEN_INFO_MONO_VTILED; + bool msb_first = self->capabilities.screen_info & SCREEN_INFO_MONO_MSB_FIRST; + *color_depth = 1; + *bytes_per_cell = 1; + *grayscale = true; + *pixels_in_byte_share_row = !vtiled; + *reverse_pixels_in_byte = msb_first; + *reverse_bytes_in_word = false; + } +} + +void common_hal_zephyr_display_display_construct_from_device(zephyr_display_display_obj_t *self, + const struct device *device, + uint16_t rotation, + bool auto_refresh) { + self->auto_refresh = false; + + if (device == NULL || !device_is_ready(device)) { + raise_zephyr_error(-ENODEV); + } + + self->device = device; + display_get_capabilities(self->device, &self->capabilities); + + self->pixel_format = zephyr_display_select_pixel_format(&self->capabilities); + if (self->pixel_format != self->capabilities.current_pixel_format) { + (void)display_set_pixel_format(self->device, self->pixel_format); + display_get_capabilities(self->device, &self->capabilities); + self->pixel_format = self->capabilities.current_pixel_format; + } + + uint16_t color_depth; + uint8_t bytes_per_cell; + bool grayscale; + bool pixels_in_byte_share_row; + bool reverse_pixels_in_byte; + bool reverse_bytes_in_word; + zephyr_display_select_colorspace(self, &color_depth, &bytes_per_cell, + &grayscale, &pixels_in_byte_share_row, &reverse_pixels_in_byte, + &reverse_bytes_in_word); + + displayio_display_core_construct( + &self->core, + self->capabilities.x_resolution, + self->capabilities.y_resolution, + 0, + color_depth, + grayscale, + pixels_in_byte_share_row, + bytes_per_cell, + reverse_pixels_in_byte, + reverse_bytes_in_word); + + self->native_frames_per_second = 60; + self->native_ms_per_frame = 1000 / self->native_frames_per_second; + self->first_manual_refresh = !auto_refresh; + + if (rotation != 0) { + common_hal_zephyr_display_display_set_rotation(self, rotation); + } + + (void)display_blanking_off(self->device); + + displayio_display_core_set_root_group(&self->core, &circuitpython_splash); + common_hal_zephyr_display_display_set_auto_refresh(self, auto_refresh); +} + +uint16_t common_hal_zephyr_display_display_get_width(zephyr_display_display_obj_t *self) { + return displayio_display_core_get_width(&self->core); +} + +uint16_t common_hal_zephyr_display_display_get_height(zephyr_display_display_obj_t *self) { + return displayio_display_core_get_height(&self->core); +} + +mp_float_t common_hal_zephyr_display_display_get_brightness(zephyr_display_display_obj_t *self) { + (void)self; + return -1; +} + +bool common_hal_zephyr_display_display_set_brightness(zephyr_display_display_obj_t *self, mp_float_t brightness) { + (void)self; + (void)brightness; + return false; +} + +static bool zephyr_display_refresh_area(zephyr_display_display_obj_t *self, const displayio_area_t *area) { + uint16_t buffer_size = CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE / sizeof(uint32_t); + + displayio_area_t clipped; + if (!displayio_display_core_clip_area(&self->core, area, &clipped)) { + return true; + } + + uint16_t rows_per_buffer = displayio_area_height(&clipped); + uint8_t pixels_per_word = (sizeof(uint32_t) * 8) / self->core.colorspace.depth; + // For AL_88, displayio fills at 1 byte/pixel (L_8) but output needs 2 bytes/pixel, + // so halve the effective pixels_per_word for buffer sizing. + uint8_t effective_pixels_per_word = pixels_per_word; + if (self->pixel_format == PIXEL_FORMAT_AL_88) { + effective_pixels_per_word = sizeof(uint32_t) / 2; + } + uint16_t pixels_per_buffer = displayio_area_size(&clipped); + uint16_t subrectangles = 1; + + // When pixels_in_byte_share_row is false (mono vtiled), 8 vertical pixels + // pack into one column byte. The byte layout needs width * ceil(height/8) + // bytes, which can exceed the pixel-count-based buffer size. + bool vtiled = self->core.colorspace.depth < 8 && + !self->core.colorspace.pixels_in_byte_share_row; + + bool needs_subdivision = displayio_area_size(&clipped) > buffer_size * effective_pixels_per_word; + if (vtiled && !needs_subdivision) { + uint16_t width = displayio_area_width(&clipped); + uint16_t height = displayio_area_height(&clipped); + uint32_t vtiled_bytes = (uint32_t)width * ((height + 7) / 8); + needs_subdivision = vtiled_bytes > buffer_size * sizeof(uint32_t); + } + + if (needs_subdivision) { + rows_per_buffer = buffer_size * effective_pixels_per_word / displayio_area_width(&clipped); + if (vtiled) { + rows_per_buffer = (rows_per_buffer / 8) * 8; + if (rows_per_buffer == 0) { + rows_per_buffer = 8; + } + } + if (rows_per_buffer == 0) { + rows_per_buffer = 1; + } + subrectangles = displayio_area_height(&clipped) / rows_per_buffer; + if (displayio_area_height(&clipped) % rows_per_buffer != 0) { + subrectangles++; + } + pixels_per_buffer = rows_per_buffer * displayio_area_width(&clipped); + buffer_size = pixels_per_buffer / pixels_per_word; + if (pixels_per_buffer % pixels_per_word) { + buffer_size += 1; + } + // Ensure buffer is large enough for vtiled packing. + if (vtiled) { + uint16_t width = displayio_area_width(&clipped); + uint16_t vtiled_words = (width * ((rows_per_buffer + 7) / 8) + sizeof(uint32_t) - 1) / sizeof(uint32_t); + if (vtiled_words > buffer_size) { + buffer_size = vtiled_words; + } + } + // Ensure buffer is large enough for AL_88 expansion. + if (self->pixel_format == PIXEL_FORMAT_AL_88) { + uint16_t al88_words = (pixels_per_buffer * 2 + sizeof(uint32_t) - 1) / sizeof(uint32_t); + if (al88_words > buffer_size) { + buffer_size = al88_words; + } + } + } + + uint32_t buffer[buffer_size]; + uint32_t mask_length = (pixels_per_buffer / 32) + 1; + uint32_t mask[mask_length]; + + uint16_t remaining_rows = displayio_area_height(&clipped); + + for (uint16_t j = 0; j < subrectangles; j++) { + displayio_area_t subrectangle = { + .x1 = clipped.x1, + .y1 = clipped.y1 + rows_per_buffer * j, + .x2 = clipped.x2, + .y2 = clipped.y1 + rows_per_buffer * (j + 1), + }; + + if (remaining_rows < rows_per_buffer) { + subrectangle.y2 = subrectangle.y1 + remaining_rows; + } + remaining_rows -= rows_per_buffer; + + memset(mask, 0, mask_length * sizeof(mask[0])); + memset(buffer, 0, buffer_size * sizeof(buffer[0])); + + displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); + + uint16_t width = displayio_area_width(&subrectangle); + uint16_t height = displayio_area_height(&subrectangle); + size_t pixel_count = (size_t)width * (size_t)height; + + if (self->pixel_format == PIXEL_FORMAT_MONO10) { + uint8_t *bytes = (uint8_t *)buffer; + size_t byte_count = (pixel_count + 7) / 8; + for (size_t i = 0; i < byte_count; i++) { + bytes[i] = ~bytes[i]; + } + } + + if (self->pixel_format == PIXEL_FORMAT_AL_88) { + uint8_t *bytes = (uint8_t *)buffer; + for (size_t i = pixel_count; i > 0; i--) { + bytes[(i - 1) * 2 + 1] = 0xFF; + bytes[(i - 1) * 2] = bytes[i - 1]; + } + } + + // Compute buf_size based on the Zephyr pixel format. + uint32_t buf_size_bytes; + if (self->pixel_format == PIXEL_FORMAT_MONO01 || + self->pixel_format == PIXEL_FORMAT_MONO10) { + buf_size_bytes = (pixel_count + 7) / 8; + } else if (self->pixel_format == PIXEL_FORMAT_AL_88) { + buf_size_bytes = pixel_count * 2; + } else { + buf_size_bytes = pixel_count * (self->core.colorspace.depth / 8); + } + + struct display_buffer_descriptor desc = { + .buf_size = buf_size_bytes, + .width = width, + .height = height, + .pitch = width, + .frame_incomplete = false, + }; + + int err = display_write(self->device, subrectangle.x1, subrectangle.y1, &desc, buffer); + if (err < 0) { + return false; + } + + RUN_BACKGROUND_TASKS; + } + + return true; +} + +static void zephyr_display_refresh(zephyr_display_display_obj_t *self) { + if (!displayio_display_core_start_refresh(&self->core)) { + return; + } + + const displayio_area_t *current_area = zephyr_display_get_refresh_areas(self); + while (current_area != NULL) { + if (!zephyr_display_refresh_area(self, current_area)) { + break; + } + current_area = current_area->next; + } + + displayio_display_core_finish_refresh(&self->core); +} + +void common_hal_zephyr_display_display_set_rotation(zephyr_display_display_obj_t *self, int rotation) { + bool transposed = (self->core.rotation == 90 || self->core.rotation == 270); + bool will_transposed = (rotation == 90 || rotation == 270); + if (transposed != will_transposed) { + int tmp = self->core.width; + self->core.width = self->core.height; + self->core.height = tmp; + } + + displayio_display_core_set_rotation(&self->core, rotation); + + if (self == &displays[0].zephyr_display) { + supervisor_stop_terminal(); + supervisor_start_terminal(self->core.width, self->core.height); + } + + if (self->core.current_group != NULL) { + displayio_group_update_transform(self->core.current_group, &self->core.transform); + } +} + +uint16_t common_hal_zephyr_display_display_get_rotation(zephyr_display_display_obj_t *self) { + return self->core.rotation; +} + +bool common_hal_zephyr_display_display_refresh(zephyr_display_display_obj_t *self, + uint32_t target_ms_per_frame, + uint32_t maximum_ms_per_real_frame) { + if (!self->auto_refresh && !self->first_manual_refresh && (target_ms_per_frame != NO_FPS_LIMIT)) { + uint64_t current_time = supervisor_ticks_ms64(); + uint32_t current_ms_since_real_refresh = current_time - self->core.last_refresh; + if (current_ms_since_real_refresh > maximum_ms_per_real_frame) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Below minimum frame rate")); + } + uint32_t current_ms_since_last_call = current_time - self->last_refresh_call; + self->last_refresh_call = current_time; + if (current_ms_since_last_call > target_ms_per_frame) { + return false; + } + uint32_t remaining_time = target_ms_per_frame - (current_ms_since_real_refresh % target_ms_per_frame); + while (supervisor_ticks_ms64() - self->last_refresh_call < remaining_time) { + RUN_BACKGROUND_TASKS; + } + } + self->first_manual_refresh = false; + zephyr_display_refresh(self); + return true; +} + +bool common_hal_zephyr_display_display_get_auto_refresh(zephyr_display_display_obj_t *self) { + return self->auto_refresh; +} + +void common_hal_zephyr_display_display_set_auto_refresh(zephyr_display_display_obj_t *self, bool auto_refresh) { + self->first_manual_refresh = !auto_refresh; + if (auto_refresh != self->auto_refresh) { + if (auto_refresh) { + supervisor_enable_tick(); + } else { + supervisor_disable_tick(); + } + } + self->auto_refresh = auto_refresh; +} + +void zephyr_display_display_background(zephyr_display_display_obj_t *self) { + if (self->auto_refresh && (supervisor_ticks_ms64() - self->core.last_refresh) > self->native_ms_per_frame) { + zephyr_display_refresh(self); + } +} + +void release_zephyr_display(zephyr_display_display_obj_t *self) { + common_hal_zephyr_display_display_set_auto_refresh(self, false); + release_display_core(&self->core); + self->device = NULL; + self->base.type = &mp_type_NoneType; +} + +void zephyr_display_display_collect_ptrs(zephyr_display_display_obj_t *self) { + (void)self; + displayio_display_core_collect_ptrs(&self->core); +} + +void zephyr_display_display_reset(zephyr_display_display_obj_t *self) { + if (self->device != NULL && device_is_ready(self->device)) { + common_hal_zephyr_display_display_set_auto_refresh(self, true); + displayio_display_core_set_root_group(&self->core, &circuitpython_splash); + self->core.full_refresh = true; + } else { + release_zephyr_display(self); + } +} + +mp_obj_t common_hal_zephyr_display_display_get_root_group(zephyr_display_display_obj_t *self) { + if (self->core.current_group == NULL) { + return mp_const_none; + } + return self->core.current_group; +} + +bool common_hal_zephyr_display_display_set_root_group(zephyr_display_display_obj_t *self, displayio_group_t *root_group) { + return displayio_display_core_set_root_group(&self->core, root_group); +} diff --git a/ports/zephyr-cp/common-hal/zephyr_display/Display.h b/ports/zephyr-cp/common-hal/zephyr_display/Display.h new file mode 100644 index 00000000000..bdec1e96ba5 --- /dev/null +++ b/ports/zephyr-cp/common-hal/zephyr_display/Display.h @@ -0,0 +1,31 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" +#include "shared-module/displayio/display_core.h" + +typedef struct { + mp_obj_base_t base; + displayio_display_core_t core; + const struct device *device; + struct display_capabilities capabilities; + enum display_pixel_format pixel_format; + uint64_t last_refresh_call; + uint16_t native_frames_per_second; + uint16_t native_ms_per_frame; + bool auto_refresh; + bool first_manual_refresh; +} zephyr_display_display_obj_t; + +void zephyr_display_display_background(zephyr_display_display_obj_t *self); +void zephyr_display_display_collect_ptrs(zephyr_display_display_obj_t *self); +void zephyr_display_display_reset(zephyr_display_display_obj_t *self); +void release_zephyr_display(zephyr_display_display_obj_t *self); diff --git a/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.c b/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.c index d5e6fd08006..178f33e028d 100644 --- a/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.c +++ b/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.c @@ -9,9 +9,12 @@ #include #include - +#include void raise_zephyr_error(int err) { + if (err == 0) { + return; + } switch (-err) { case EALREADY: printk("EALREADY\n"); @@ -40,7 +43,20 @@ void raise_zephyr_error(int err) { case ENOTSUP: printk("ENOTSUP\n"); break; + case EADDRINUSE: + printk("EADDRINUSE\n"); + break; + case EIO: + printk("EIO\n"); + break; + case ENOSYS: + printk("ENOSYS\n"); + break; + case EINVAL: + printk("EINVAL\n"); + break; default: printk("Zephyr error %d\n", err); } + mp_raise_OSError(-err); } diff --git a/ports/zephyr-cp/cptools/board_tools.py b/ports/zephyr-cp/cptools/board_tools.py index 088b4bb5491..305abab3f19 100644 --- a/ports/zephyr-cp/cptools/board_tools.py +++ b/ports/zephyr-cp/cptools/board_tools.py @@ -1,3 +1,6 @@ +import tomllib + + def find_mpconfigboard(portdir, board_id): next_underscore = board_id.find("_") while next_underscore != -1: @@ -8,3 +11,27 @@ def find_mpconfigboard(portdir, board_id): return p next_underscore = board_id.find("_", next_underscore + 1) return None + + +def load_mpconfigboard(portdir, board_id): + mpconfigboard_path = find_mpconfigboard(portdir, board_id) + if mpconfigboard_path is None or not mpconfigboard_path.exists(): + return None, {} + + with mpconfigboard_path.open("rb") as f: + return mpconfigboard_path, tomllib.load(f) + + +def get_shields(mpconfigboard): + shields = mpconfigboard.get("SHIELDS") + if shields is None: + shields = mpconfigboard.get("SHIELD") + + if shields is None: + return [] + if isinstance(shields, str): + return [shields] + if isinstance(shields, (list, tuple)): + return [str(shield) for shield in shields] + + return [str(shields)] diff --git a/ports/zephyr-cp/cptools/build_all_boards.py b/ports/zephyr-cp/cptools/build_all_boards.py index 8ad6bd05ea9..8505e732efe 100755 --- a/ports/zephyr-cp/cptools/build_all_boards.py +++ b/ports/zephyr-cp/cptools/build_all_boards.py @@ -3,17 +3,113 @@ Build all CircuitPython boards for the Zephyr port. This script discovers all boards by finding circuitpython.toml files -and builds each one sequentially, passing through the jobserver for -parallelism within each build. +and builds them in parallel while sharing a single jobserver across +all builds. + +This is agent generated and works. Don't bother reading too closely because it +is just a tool for us. """ import argparse +import concurrent.futures +import os import pathlib +import shlex import subprocess import sys import time +class Jobserver: + def __init__(self, read_fd, write_fd, jobs=None, owns_fds=False): + self.read_fd = read_fd + self.write_fd = write_fd + self.jobs = jobs + self.owns_fds = owns_fds + + def acquire(self): + while True: + try: + os.read(self.read_fd, 1) + return + except InterruptedError: + continue + + def release(self): + while True: + try: + os.write(self.write_fd, b"+") + return + except InterruptedError: + continue + + def pass_fds(self): + return (self.read_fd, self.write_fd) + + def close(self): + if self.owns_fds: + os.close(self.read_fd) + os.close(self.write_fd) + + +def _parse_makeflags_jobserver(makeflags): + jobserver_auth = None + jobs = None + + for token in shlex.split(makeflags): + if token == "-j" or token == "--jobs": + continue + if token.startswith("-j") and token != "-j": + try: + jobs = int(token[2:]) + except ValueError: + pass + elif token.startswith("--jobs="): + try: + jobs = int(token.split("=", 1)[1]) + except ValueError: + pass + elif token.startswith("--jobserver-auth=") or token.startswith("--jobserver-fds="): + jobserver_auth = token.split("=", 1)[1] + + if not jobserver_auth: + return None, jobs, False + + if jobserver_auth.startswith("fifo:"): + fifo_path = jobserver_auth[len("fifo:") :] + read_fd = os.open(fifo_path, os.O_RDONLY) + write_fd = os.open(fifo_path, os.O_WRONLY) + os.set_inheritable(read_fd, True) + os.set_inheritable(write_fd, True) + return (read_fd, write_fd), jobs, True + + if "," in jobserver_auth: + read_fd, write_fd = jobserver_auth.split(",", 1) + return (int(read_fd), int(write_fd)), jobs, False + + return None, jobs, False + + +def _create_jobserver(jobs): + read_fd, write_fd = os.pipe() + os.set_inheritable(read_fd, True) + os.set_inheritable(write_fd, True) + for _ in range(jobs): + os.write(write_fd, b"+") + return Jobserver(read_fd, write_fd, jobs=jobs, owns_fds=True) + + +def _jobserver_from_env(): + makeflags = os.environ.get("MAKEFLAGS", "") + fds, jobs, owns_fds = _parse_makeflags_jobserver(makeflags) + if not fds: + return None, jobs + read_fd, write_fd = fds + os.set_inheritable(read_fd, True) + os.set_inheritable(write_fd, True) + return Jobserver(read_fd, write_fd, jobs=jobs, owns_fds=owns_fds), jobs + + def discover_boards(port_dir): """ Discover all boards by finding circuitpython.toml files. @@ -35,7 +131,15 @@ def discover_boards(port_dir): return sorted(boards) -def build_board(port_dir, vendor, board, extra_args=None): +def build_board( + port_dir, + vendor, + board, + extra_args=None, + jobserver=None, + env=None, + log_dir=None, +): """ Build a single board using make. @@ -44,12 +148,16 @@ def build_board(port_dir, vendor, board, extra_args=None): vendor: Board vendor name board: Board name extra_args: Additional arguments to pass to make + jobserver: Jobserver instance to limit parallel builds + env: Environment variables for the subprocess + log_dir: Directory to write build logs Returns: - (success: bool, elapsed_time: float) + (success: bool, elapsed_time: float, output: str, log_path: pathlib.Path) """ board_id = f"{vendor}_{board}" start_time = time.time() + log_path = None cmd = ["make", f"BOARD={board_id}"] @@ -57,25 +165,240 @@ def build_board(port_dir, vendor, board, extra_args=None): if extra_args: cmd.extend(extra_args) + if jobserver: + jobserver.acquire() + try: - subprocess.run( + result = subprocess.run( cmd, cwd=port_dir, - check=True, - # Inherit stdin to pass through jobserver file descriptors + # Inherit stdin alongside jobserver file descriptors stdin=sys.stdin, - # Show output in real-time - stdout=None, - stderr=None, - capture_output=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + env=env, + pass_fds=jobserver.pass_fds() if jobserver else (), ) elapsed = time.time() - start_time - return True, elapsed - except subprocess.CalledProcessError: - elapsed = time.time() - start_time - return False, elapsed + output = result.stdout or "" + if log_dir: + log_path = log_dir / f"{board_id}.log" + log_path.write_text(output) + return result.returncode == 0, elapsed, output, log_path except KeyboardInterrupt: raise + finally: + if jobserver: + jobserver.release() + + +def _format_status(status): + state = status["state"] + elapsed = status.get("elapsed") + if state == "queued": + return "QUEUED" + if state == "running": + return f"RUNNING {elapsed:.1f}s" + if state == "success": + return f"SUCCESS {elapsed:.1f}s" + if state == "failed": + return f"FAILED {elapsed:.1f}s" + if state == "skipped": + return "SKIPPED" + return state.upper() + + +def _build_status_table(boards, statuses, start_time, stop_submitting): + from rich.table import Table + from rich.text import Text + + elapsed = time.time() - start_time + title = f"Building {len(boards)} boards | Elapsed: {elapsed:.1f}s" + if stop_submitting: + title += " | STOPPING AFTER FAILURE" + + table = Table(title=title) + table.add_column("#", justify="right") + table.add_column("Board", no_wrap=True) + table.add_column("Status", no_wrap=True) + + for i, (vendor, board) in enumerate(boards): + board_id = f"{vendor}_{board}" + status_text = _format_status(statuses[i]) + state = statuses[i]["state"] + style = None + if state == "success": + style = "green" + elif state == "failed": + style = "red" + table.add_row( + f"{i + 1}/{len(boards)}", + board_id, + Text(status_text, style=style) if style else status_text, + ) + + return table + + +def _run_builds_tui( + port_dir, + boards, + extra_args, + jobserver, + env, + log_dir, + max_workers, + continue_on_error, +): + from rich.live import Live + + statuses = [ + {"state": "queued", "elapsed": 0.0, "start": None, "log_path": None} for _ in boards + ] + results = [] + futures = {} + next_index = 0 + stop_submitting = False + start_time = time.time() + + with Live( + _build_status_table(boards, statuses, start_time, stop_submitting), + refresh_per_second=4, + transient=False, + ) as live: + with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: + while next_index < len(boards) and len(futures) < max_workers: + vendor, board = boards[next_index] + statuses[next_index]["state"] = "running" + statuses[next_index]["start"] = time.time() + future = executor.submit( + build_board, + port_dir, + vendor, + board, + extra_args, + jobserver, + env, + log_dir, + ) + futures[future] = next_index + next_index += 1 + + while futures: + for status in statuses: + if status["state"] == "running": + status["elapsed"] = time.time() - status["start"] + + live.update(_build_status_table(boards, statuses, start_time, stop_submitting)) + + done, _ = concurrent.futures.wait( + futures, + timeout=0.1, + return_when=concurrent.futures.FIRST_COMPLETED, + ) + for future in done: + index = futures.pop(future) + vendor, board = boards[index] + success, elapsed, _output, log_path = future.result() + statuses[index]["elapsed"] = elapsed + statuses[index]["log_path"] = log_path + statuses[index]["state"] = "success" if success else "failed" + results.append((vendor, board, success, elapsed)) + + if not success and not continue_on_error: + stop_submitting = True + + if not stop_submitting and next_index < len(boards): + vendor, board = boards[next_index] + statuses[next_index]["state"] = "running" + statuses[next_index]["start"] = time.time() + future = executor.submit( + build_board, + port_dir, + vendor, + board, + extra_args, + jobserver, + env, + log_dir, + ) + futures[future] = next_index + next_index += 1 + + if stop_submitting: + for index in range(next_index, len(boards)): + if statuses[index]["state"] == "queued": + statuses[index]["state"] = "skipped" + + live.update(_build_status_table(boards, statuses, start_time, stop_submitting)) + + return results, stop_submitting + + +def _run_builds_plain( + port_dir, + boards, + extra_args, + jobserver, + env, + log_dir, + max_workers, + continue_on_error, +): + results = [] + futures = {} + next_index = 0 + stop_submitting = False + + with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: + while next_index < len(boards) and len(futures) < max_workers: + vendor, board = boards[next_index] + future = executor.submit( + build_board, + port_dir, + vendor, + board, + extra_args, + jobserver, + env, + log_dir, + ) + futures[future] = (vendor, board) + next_index += 1 + + while futures: + done, _ = concurrent.futures.wait( + futures, + return_when=concurrent.futures.FIRST_COMPLETED, + ) + for future in done: + vendor, board = futures.pop(future) + success, elapsed, _output, _log_path = future.result() + board_id = f"{vendor}_{board}" + status = "SUCCESS" if success else "FAILURE" + print(f"{board_id}: {status} ({elapsed:.1f}s)") + results.append((vendor, board, success, elapsed)) + + if not success and not continue_on_error: + stop_submitting = True + + if not stop_submitting and next_index < len(boards): + vendor, board = boards[next_index] + future = executor.submit( + build_board, + port_dir, + vendor, + board, + extra_args, + jobserver, + env, + log_dir, + ) + futures[future] = (vendor, board) + next_index += 1 + + return results, stop_submitting def main(): @@ -84,7 +407,7 @@ def main(): formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: - # Build all boards sequentially with 32 parallel jobs per board + # Build all boards in parallel with 32 jobserver slots %(prog)s -j32 # Build all boards using make's jobserver (recommended) @@ -94,70 +417,102 @@ def main(): parser.add_argument( "-j", "--jobs", - type=str, + type=int, default=None, - help="Number of parallel jobs for each board build (passed to make)", + help="Number of shared jobserver slots across all board builds", ) parser.add_argument( "--continue-on-error", action="store_true", help="Continue building remaining boards even if one fails", ) + parser.add_argument( + "--vendor", + type=str, + default=None, + help="Only build boards from this vendor (e.g. 'native' for sim boards)", + ) args = parser.parse_args() + if args.jobs is not None and args.jobs < 1: + print("ERROR: --jobs must be at least 1") + return 2 + # Get the port directory port_dir = pathlib.Path(__file__).parent.resolve().parent # Discover all boards boards = discover_boards(port_dir) + if args.vendor: + boards = [(v, b) for v, b in boards if v == args.vendor] + if not boards: print("ERROR: No boards found!") return 1 - # Prepare extra make arguments + # Prepare jobserver and extra make arguments + jobserver, detected_jobs = _jobserver_from_env() + env = os.environ.copy() + extra_args = [] - if args.jobs: - extra_args.append(f"-j{args.jobs}") + jobserver_jobs = detected_jobs + + if not jobserver: + jobserver_jobs = args.jobs if args.jobs else (os.cpu_count() or 1) + jobserver = _create_jobserver(jobserver_jobs) + env["MAKEFLAGS"] = ( + f"-j{jobserver_jobs} --jobserver-auth={jobserver.read_fd},{jobserver.write_fd}" + ) + + max_workers = jobserver_jobs + if max_workers is None: + max_workers = min(len(boards), os.cpu_count() or 1) + max_workers = max(1, min(len(boards), max_workers)) # Build all boards - start_time = time.time() - results = [] + log_dir = port_dir / "build-logs" + log_dir.mkdir(parents=True, exist_ok=True) try: - for index, (vendor, board) in enumerate(boards): - board_id = f"{vendor}_{board}" - print(f"{index + 1}/{len(boards)} {board_id}: ", end="", flush=True) - - success, elapsed = build_board(port_dir, vendor, board, extra_args) - if success: - print(f"✅ SUCCESS ({elapsed:.1f}s)") - else: - print(f"❌ FAILURE ({elapsed:.1f}s)") - results.append((vendor, board, success, elapsed)) - - if not success and not args.continue_on_error: - print("\nStopping due to build failure.") - break + use_tui = sys.stdout.isatty() + if use_tui: + try: + import rich # noqa: F401 + except ImportError: + use_tui = False + + if use_tui: + results, stop_submitting = _run_builds_tui( + port_dir, + boards, + extra_args, + jobserver, + env, + log_dir, + max_workers, + args.continue_on_error, + ) + else: + results, stop_submitting = _run_builds_plain( + port_dir, + boards, + extra_args, + jobserver, + env, + log_dir, + max_workers, + args.continue_on_error, + ) except KeyboardInterrupt: print("\n\nBuild interrupted by user.") return 130 # Standard exit code for SIGINT + finally: + if jobserver: + jobserver.close() - # Print summary - total_time = time.time() - start_time - print(f"\n{'=' * 80}") - print("Build Summary") - print(f"{'=' * 80}") - - successful = [r for r in results if r[2]] failed = [r for r in results if not r[2]] - - print(f"\nTotal boards: {len(results)}/{len(boards)}") - print(f"Successful: {len(successful)}") - print(f"Failed: {len(failed)}") - print(f"Total time: {total_time:.1f}s") - return 0 if len(failed) == 0 else 1 diff --git a/ports/zephyr-cp/cptools/build_circuitpython.py b/ports/zephyr-cp/cptools/build_circuitpython.py index 5d3c7d7515d..b7334402b74 100644 --- a/ports/zephyr-cp/cptools/build_circuitpython.py +++ b/ports/zephyr-cp/cptools/build_circuitpython.py @@ -43,6 +43,7 @@ ALWAYS_ON_MODULES = ["sys", "collections"] DEFAULT_MODULES = [ + "__future__", "time", "os", "microcontroller", @@ -51,21 +52,42 @@ "json", "random", "digitalio", + "rotaryio", "rainbowio", "traceback", "warnings", "supervisor", "errno", "io", + "math", + "msgpack", + "aesio", + "hashlib", + "zlib", + "adafruit_bus_device", + "getpass", + "storage", ] # Flags that don't match with with a *bindings module. Some used by adafruit_requests -MPCONFIG_FLAGS = ["array", "errno", "io", "json"] +MPCONFIG_FLAGS = ["array", "errno", "io", "json", "math"] # List of other modules (the value) that can be enabled when another one (the key) is. REVERSE_DEPENDENCIES = { + "audiobusio": ["audiocore"], + "audiocore": [ + "audiodelays", + "audiofilters", + "audiofreeverb", + "audiomixer", + "audiomp3", + "synthio", + ], "busio": ["fourwire", "i2cdisplaybus", "sdcardio", "sharpdisplay"], "fourwire": ["displayio", "busdisplay", "epaperdisplay"], "i2cdisplaybus": ["displayio", "busdisplay", "epaperdisplay"], + # Zephyr display backends need displayio and, by extension, terminalio so + # the REPL console appears on the display by default. + "zephyr_display": ["displayio"], "displayio": [ "vectorio", "bitmapfilter", @@ -74,15 +96,43 @@ "lvfontio", "tilepalettemapper", "fontio", + "gifio", + "jpegio", ], "sharpdisplay": ["framebufferio"], "framebufferio": ["displayio"], } # Other flags to set when a module is enabled -EXTRA_FLAGS = {"busio": ["BUSIO_SPI", "BUSIO_I2C"]} +EXTRA_FLAGS = { + "audiobusio": {"AUDIOBUSIO_I2SOUT": 1, "AUDIOBUSIO_PDMIN": 0}, + "busio": {"BUSIO_SPI": 1, "BUSIO_I2C": 1}, + "rotaryio": {"ROTARYIO_SOFTENCODER": 1}, + "synthio": {"SYNTHIO_MAX_CHANNELS": 12}, +} + +# Library sources. Will be globbed from the top level directory +# No QSTR processing or CIRCUITPY specific flags +LIBRARY_SOURCE = { + "audiomp3": ["lib/mp3/src/*.c"], + "zlib": [ + "lib/uzlib/tinflate.c", + "lib/uzlib/tinfzlib.c", + "lib/uzlib/tinfgzip.c", + "lib/uzlib/adler32.c", + "lib/uzlib/crc32.c", + ], + "jpegio": ["lib/tjpgd/src/tjpgd.c"], + "gifio": ["lib/AnimatedGIF/gif.c"], +} + +SHARED_MODULE_AND_COMMON_HAL = ["_bleio", "os", "rotaryio"] -SHARED_MODULE_AND_COMMON_HAL = ["os"] +# Mapping from module directory name to the flag name used in CIRCUITPY_ +MODULE_FLAG_NAMES = { + "__future__": "FUTURE", + "_bleio": "BLEIO", +} async def preprocess_and_split_defs(compiler, source_file, build_path, flags): @@ -217,6 +267,20 @@ async def generate_display_resources(output_path, translation, font, extra_chara ) +async def generate_web_workflow_static(output_path, static_files): + await cpbuild.run_command( + [ + "python", + srcdir / "tools" / "gen_web_workflow_static.py", + "--output_c_file", + output_path, + *static_files, + ], + srcdir, + check_hash=[output_path], + ) + + def determine_enabled_modules(board_info, portdir, srcdir): """Determine which CircuitPython modules should be enabled based on board capabilities. @@ -239,10 +303,18 @@ def determine_enabled_modules(board_info, portdir, srcdir): enabled_modules.add("storage") module_reasons["storage"] = "Zephyr board has flash" - if "wifi" in enabled_modules: + network_enabled = board_info.get("wifi", False) or board_info.get("hostnetwork", False) + + if network_enabled: + enabled_modules.add("ipaddress") + module_reasons["ipaddress"] = "Zephyr networking enabled" enabled_modules.add("socketpool") - enabled_modules.add("ssl") module_reasons["socketpool"] = "Zephyr networking enabled" + enabled_modules.add("hashlib") + module_reasons["hashlib"] = "Zephyr networking enabled" + + if board_info.get("wifi", False) or board_info.get("ethernet", False): + enabled_modules.add("ssl") module_reasons["ssl"] = "Zephyr networking enabled" for port_module in (portdir / "bindings").iterdir(): @@ -289,6 +361,8 @@ async def build_circuitpython(): lto = cmake_args.get("LTO", "n") == "y" circuitpython_flags.append(f"-DCIRCUITPY_ENABLE_MPY_NATIVE={1 if enable_mpy_native else 0}") circuitpython_flags.append(f"-DCIRCUITPY_FULL_BUILD={1 if full_build else 0}") + circuitpython_flags.append(f"-DCIRCUITPY_SETTINGS_TOML={1 if full_build else 0}") + circuitpython_flags.append("-DCIRCUITPY_STATUS_BAR=1") circuitpython_flags.append(f"-DCIRCUITPY_USB_HOST={1 if usb_host else 0}") circuitpython_flags.append(f"-DCIRCUITPY_BOARD_ID='\"{board}\"'") circuitpython_flags.append(f"-DCIRCUITPY_TRANSLATE_OBJECT={1 if lto else 0}") @@ -296,6 +370,9 @@ async def build_circuitpython(): circuitpython_flags.append("-DLONGINT_IMPL_MPZ") circuitpython_flags.append("-DCIRCUITPY_SSL_MBEDTLS") circuitpython_flags.append("-DFFCONF_H='\"lib/oofatfs/ffconf.h\"'") + circuitpython_flags.append( + "-D_DEFAULT_SOURCE" + ) # To get more from picolibc to match newlib such as M_PI circuitpython_flags.extend(("-I", srcdir)) circuitpython_flags.extend(("-I", builddir)) circuitpython_flags.extend(("-I", portdir)) @@ -303,6 +380,11 @@ async def build_circuitpython(): genhdr = builddir / "genhdr" genhdr.mkdir(exist_ok=True, parents=True) version_header = genhdr / "mpversion.h" + mpconfigboard_fn = board_tools.find_mpconfigboard(portdir, board) + mpconfigboard = {"USB_VID": 0x1209, "USB_PID": 0x000C, "USB_INTERFACE_NAME": "CircuitPython"} + if mpconfigboard_fn is not None and mpconfigboard_fn.exists(): + with mpconfigboard_fn.open("rb") as f: + mpconfigboard.update(tomllib.load(f)) async with asyncio.TaskGroup() as tg: tg.create_task( cpbuild.run_command( @@ -320,11 +402,9 @@ async def build_circuitpython(): ) board_autogen_task = tg.create_task( - zephyr_dts_to_cp_board(zephyr_board, portdir, builddir, zephyrbuilddir) + zephyr_dts_to_cp_board(zephyr_board, portdir, builddir, zephyrbuilddir, mpconfigboard) ) board_info = board_autogen_task.result() - mpconfigboard_fn = board_tools.find_mpconfigboard(portdir, board) - mpconfigboard = {"USB_VID": 0x1209, "USB_PID": 0x000C, "USB_INTERFACE_NAME": "CircuitPython"} if mpconfigboard_fn is None: mpconfigboard_fn = ( portdir / "boards" / board_info["vendor_id"] / board / "circuitpython.toml" @@ -332,15 +412,25 @@ async def build_circuitpython(): logging.warning( f"Could not find board config at: boards/{board_info['vendor_id']}/{board}" ) - elif mpconfigboard_fn.exists(): - with mpconfigboard_fn.open("rb") as f: - mpconfigboard.update(tomllib.load(f)) autogen_board_info_fn = mpconfigboard_fn.parent / "autogen_board_info.toml" + creator_id = mpconfigboard.get("CIRCUITPY_CREATOR_ID", mpconfigboard.get("USB_VID", 0x1209)) + creation_id = mpconfigboard.get("CIRCUITPY_CREATION_ID", mpconfigboard.get("USB_PID", 0x000C)) + circuitpython_flags.append(f"-DCIRCUITPY_CREATOR_ID=0x{creator_id:08x}") + circuitpython_flags.append(f"-DCIRCUITPY_CREATION_ID=0x{creation_id:08x}") + + vendor = mpconfigboard.get("VENDOR", board_info["vendor"]) + name = mpconfigboard.get("NAME", board_info["name"]) + enabled_modules, module_reasons = determine_enabled_modules(board_info, portdir, srcdir) + for m in mpconfigboard.get("DISABLED_MODULES", []): + enabled_modules.discard(m) + + web_workflow_enabled = board_info.get("wifi", False) or board_info.get("hostnetwork", False) circuitpython_flags.extend(board_info["cflags"]) + circuitpython_flags.append(f"-DCIRCUITPY_WEB_WORKFLOW={1 if web_workflow_enabled else 0}") supervisor_source = [ "main.c", "extmod/modjson.c", @@ -373,9 +463,11 @@ async def build_circuitpython(): supervisor_source = [pathlib.Path(p) for p in supervisor_source] supervisor_source.extend(board_info["source_files"]) supervisor_source.extend(top.glob("supervisor/shared/*.c")) + if "_bleio" in enabled_modules: + supervisor_source.append(top / "supervisor/shared/bluetooth/bluetooth.c") supervisor_source.append(top / "supervisor/shared/translate/translate.c") - # if web_workflow: - # supervisor_source.extend(top.glob("supervisor/shared/web_workflow/*.c")) + if web_workflow_enabled: + supervisor_source.extend(top.glob("supervisor/shared/web_workflow/*.c")) usb_ok = board_info.get("usb_device", False) circuitpython_flags.append(f"-DCIRCUITPY_USB_DEVICE={1 if usb_ok else 0}") @@ -390,8 +482,8 @@ async def build_circuitpython(): f"-DUSB_INTERFACE_NAME='\"{mpconfigboard['USB_INTERFACE_NAME']}\"'" ) for macro, limit, value in ( - ("USB_PRODUCT", 16, board_info["name"]), - ("USB_MANUFACTURER", 8, board_info["vendor"]), + ("USB_PRODUCT", 16, name), + ("USB_MANUFACTURER", 8, vendor), ): circuitpython_flags.append(f"-D{macro}='\"{value}\"'") circuitpython_flags.append(f"-D{macro}_{limit}='\"{value[:limit]}\"'") @@ -403,10 +495,22 @@ async def build_circuitpython(): (portdir / "supervisor/usb.c", srcdir / "supervisor/shared/usb.c") ) + creator_id = mpconfigboard.get("CIRCUITPY_CREATOR_ID", mpconfigboard.get("USB_VID")) + creation_id = mpconfigboard.get("CIRCUITPY_CREATION_ID", mpconfigboard.get("USB_PID")) + if creator_id is not None: + circuitpython_flags.append(f"-DCIRCUITPY_CREATOR_ID=0x{creator_id:08x}") + if creation_id is not None: + circuitpython_flags.append(f"-DCIRCUITPY_CREATION_ID=0x{creation_id:08x}") + # Always use port serial. It'll switch between USB and UART automatically. circuitpython_flags.append("-DCIRCUITPY_PORT_SERIAL=1") - if "ssl" in enabled_modules: + if "hashlib" in enabled_modules: + circuitpython_flags.append("-DCIRCUITPY_HASHLIB_MBEDTLS=1") + if "ssl" not in enabled_modules: + circuitpython_flags.append("-DCIRCUITPY_HASHLIB_MBEDTLS_ONLY=1") + + if "ssl" in enabled_modules or "hashlib" in enabled_modules: # TODO: Figure out how to get these paths from zephyr circuitpython_flags.append("-DMBEDTLS_CONFIG_FILE='\"config-mbedtls.h\"'") circuitpython_flags.extend( @@ -416,20 +520,34 @@ async def build_circuitpython(): ("-isystem", portdir / "modules" / "crypto" / "mbedtls" / "configs") ) circuitpython_flags.extend( - ("-isystem", portdir / "modules" / "crypto" / "mbedtls" / "include") + ("-isystem", portdir / "modules" / "crypto" / "tf-psa-crypto" / "include") + ) + circuitpython_flags.extend( + ( + "-isystem", + portdir + / "modules" + / "crypto" + / "tf-psa-crypto" + / "drivers" + / "builtin" + / "include", + ) ) circuitpython_flags.extend(("-isystem", zephyrdir / "modules" / "mbedtls" / "configs")) - supervisor_source.append(top / "lib" / "mbedtls_config" / "crt_bundle.c") + if "ssl" in enabled_modules: + supervisor_source.append(top / "lib" / "mbedtls_config" / "crt_bundle.c") # Make sure all modules have a setting by filling in defaults. hal_source = [] + library_sources = [] autogen_board_info = tomlkit.document() autogen_board_info.add( tomlkit.comment( "This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info." ) ) - autogen_board_info.add("name", board_info["vendor"] + " " + board_info["name"]) + autogen_board_info.add("name", vendor + " " + name) autogen_modules = tomlkit.table() autogen_board_info.add("modules", autogen_modules) for module in sorted( @@ -445,12 +563,13 @@ async def build_circuitpython(): if module.name in module_reasons: v.comment(module_reasons[module.name]) autogen_modules.add(module.name, v) - circuitpython_flags.append(f"-DCIRCUITPY_{module.name.upper()}={1 if enabled else 0}") + flag_name = MODULE_FLAG_NAMES.get(module.name, module.name.upper()) + circuitpython_flags.append(f"-DCIRCUITPY_{flag_name}={1 if enabled else 0}") if enabled: if module.name in EXTRA_FLAGS: - for flag in EXTRA_FLAGS[module.name]: - circuitpython_flags.append(f"-DCIRCUITPY_{flag}=1") + for flag, value in EXTRA_FLAGS[module.name].items(): + circuitpython_flags.append(f"-DCIRCUITPY_{flag}={value}") if enabled: hal_source.extend(portdir.glob(f"bindings/{module.name}/*.c")) @@ -458,20 +577,22 @@ async def build_circuitpython(): hal_source.extend(top.glob(f"ports/zephyr-cp/common-hal/{module.name}/*.c")) # Only include shared-module/*.c if no common-hal/*.c files were found if len(hal_source) == len_before or module.name in SHARED_MODULE_AND_COMMON_HAL: - hal_source.extend(top.glob(f"shared-module/{module.name}/*.c")) - hal_source.extend(top.glob(f"shared-bindings/{module.name}/*.c")) + hal_source.extend(top.glob(f"shared-module/{module.name}/**/*.c")) + hal_source.extend(top.glob(f"shared-bindings/{module.name}/**/*.c")) + if module.name in LIBRARY_SOURCE: + for library_source in LIBRARY_SOURCE[module.name]: + library_sources.extend(top.glob(library_source)) if os.environ.get("CI", "false") == "true": - # Fail the build if it isn't up to date. + # Warn if it isn't up to date. if ( not autogen_board_info_fn.exists() or autogen_board_info_fn.read_text() != tomlkit.dumps(autogen_board_info) ): - logger.error("autogen_board_info.toml is out of date.") - raise RuntimeError( + logger.warning( f"autogen_board_info.toml is missing or out of date. Please run `make BOARD={board}` locally and commit {autogen_board_info_fn}." ) - elif autogen_board_info_fn.parent.exists(): + if autogen_board_info_fn.parent.exists(): autogen_board_info_fn.write_text(tomlkit.dumps(autogen_board_info)) for mpflag in MPCONFIG_FLAGS: @@ -535,6 +656,12 @@ async def build_circuitpython(): ) source_files.append(output_path) + if web_workflow_enabled: + output_path = board_build / "autogen_web_workflow_static.c" + static_files = sorted((srcdir / "supervisor/shared/web_workflow/static").glob("*")) + tg.create_task(generate_web_workflow_static(output_path, static_files)) + source_files.append(output_path) + # This file is generated by the QSTR/translation process. source_files.append(builddir / f"translations-{translation}.c") # These files don't include unique QSTRs. They just need to be compiled. @@ -556,6 +683,12 @@ async def build_circuitpython(): objects = [] async with asyncio.TaskGroup() as tg: + for source_file in library_sources: + source_file = top / source_file + build_file = source_file.with_suffix(".o") + object_file = builddir / (build_file.relative_to(top)) + objects.append(object_file) + tg.create_task(compiler.compile(source_file, object_file)) for source_file in source_files: source_file = top / source_file build_file = source_file.with_suffix(".o") diff --git a/ports/zephyr-cp/cptools/compat2driver.py b/ports/zephyr-cp/cptools/compat2driver.py index dff09787b28..7da74ffcf18 100644 --- a/ports/zephyr-cp/cptools/compat2driver.py +++ b/ports/zephyr-cp/cptools/compat2driver.py @@ -15,13 +15,15 @@ "atmel_sam0_adc": "adc", "atmel_sam_adc": "adc", "atmel_sam_afec": "adc", + "bflb_adc": "adc", "ene_kb106x_adc": "adc", "ene_kb1200_adc": "adc", "espressif_esp32_adc": "adc", "gd_gd32_adc": "adc", + "infineon_adc": "adc", "infineon_autanalog_sar_adc": "adc", - "infineon_cat1_adc": "adc", "infineon_hppass_sar_adc": "adc", + "infineon_sar_adc": "adc", "infineon_xmc4xxx_adc": "adc", "ite_it51xxx_adc": "adc", "ite_it8xxx2_adc": "adc", @@ -37,6 +39,7 @@ "maxim_max11117": "adc", "maxim_max11253": "adc", "maxim_max11254": "adc", + "microchip_adc_g1": "adc", "microchip_mcp356xr": "adc", "microchip_xec_adc": "adc", "nordic_nrf_adc": "adc", @@ -53,12 +56,16 @@ "nxp_vf610_adc": "adc", "raspberrypi_pico_adc": "adc", "realtek_rts5912_adc": "adc", - "renesas_ra_adc": "adc", + "renesas_ra_adc12": "adc", + "renesas_ra_adc16": "adc", "renesas_rx_adc": "adc", "renesas_rz_adc": "adc", "renesas_rz_adc_c": "adc", + "renesas_rz_adc_e": "adc", + "renesas_rza2m_adc": "adc", "renesas_smartbond_adc": "adc", "renesas_smartbond_sdadc": "adc", + "sifli_sf32lb_gpadc": "adc", "silabs_gecko_adc": "adc", "silabs_iadc": "adc", "silabs_siwx91x_adc": "adc", @@ -79,6 +86,18 @@ "ti_ads124s08": "adc", "ti_ads131m02": "adc", "ti_ads7052": "adc", + "ti_ads7950": "adc", + "ti_ads7951": "adc", + "ti_ads7952": "adc", + "ti_ads7953": "adc", + "ti_ads7954": "adc", + "ti_ads7955": "adc", + "ti_ads7956": "adc", + "ti_ads7957": "adc", + "ti_ads7958": "adc", + "ti_ads7959": "adc", + "ti_ads7960": "adc", + "ti_ads7961": "adc", "ti_am335x_adc": "adc", "ti_cc13xx_cc26xx_adc": "adc", "ti_cc23x0_adc": "adc", @@ -103,8 +122,10 @@ "cirrus_cs43l22": "audio", "dlg_da7212": "audio", "maxim_max98091": "audio", + "nordic_nrf_pdm": "audio", "nxp_dmic": "audio", "nxp_micfil": "audio", + "sifli_sf32lb_audcodec": "audio", "st_mpxxdtyy": "audio", "ti_pcm1681": "audio", "ti_tas6422dac": "audio", @@ -134,16 +155,22 @@ "st_stm32_bbram": "bbram", "zephyr_bbram_emul": "bbram", # + # biometrics + "adh_tech_gt5x": "biometrics", + "zephyr_biometrics_emul": "biometrics", + "zhiantec_zfm_x0": "biometrics", + # # bluetooth/hci "ambiq_bt_hci_spi": "bluetooth/hci", "espressif_esp32_bt_hci": "bluetooth/hci", - "infineon_cat1_bless_hci": "bluetooth/hci", + "infineon_bless_hci": "bluetooth/hci", + "infineon_bt_hci_uart": "bluetooth/hci", "infineon_cyw208xx_hci": "bluetooth/hci", - "infineon_cyw43xxx_bt_hci": "bluetooth/hci", "nxp_bt_hci_uart": "bluetooth/hci", "nxp_hci_ble": "bluetooth/hci", "renesas_bt_hci_da1453x": "bluetooth/hci", "renesas_bt_hci_da1469x": "bluetooth/hci", + "sifli_sf32lb_mailbox": "bluetooth/hci", "silabs_bt_hci_efr32": "bluetooth/hci", "silabs_siwx91x_bt_hci": "bluetooth/hci", "st_hci_spi_v1": "bluetooth/hci", @@ -195,11 +222,15 @@ "sbs_sbs_charger": "charger", "ti_bq24190": "charger", "ti_bq25180": "charger", + "ti_bq25186": "charger", + "ti_bq25188": "charger", "ti_bq25713": "charger", "x_powers_axp2101_charger": "charger", + "zephyr_charger_gpio": "charger", # # clock_control "adi_max32_gcr": "clock_control", + "alif_clockctrl": "clock_control", "ambiq_clkctrl": "clock_control", "arm_beetle_syscon": "clock_control", "arm_scmi_clock": "clock_control", @@ -210,12 +241,16 @@ "bflb_bl70x_clock_controller": "clock_control", "espressif_esp32_clock": "clock_control", "fixed_clock": "clock_control", + "focaltech_ft9001_cpm": "clock_control", "gd_gd32_cctl": "clock_control", "infineon_fixed_clock": "clock_control", "infineon_fixed_factor_clock": "clock_control", "infineon_peri_div": "clock_control", "intel_agilex5_clock": "clock_control", "ite_it51xxx_ecpm": "clock_control", + "microchip_pic32cm_jh_clock": "clock_control", + "microchip_pic32cm_pl_clock": "clock_control", + "microchip_pic32cz_ca_clock": "clock_control", "microchip_sam_d5x_e5x_clock": "clock_control", "microchip_sam_pmc": "clock_control", "microchip_sama7g5_sckc": "clock_control", @@ -246,6 +281,8 @@ "openisa_rv32m1_pcc": "clock_control", "pwm_clock": "clock_control", "raspberrypi_pico_clock_controller": "clock_control", + "realtek_bee_cctl": "clock_control", + "realtek_rts5817_clock": "clock_control", "realtek_rts5912_sccon": "clock_control", "renesas_r8a7795_cpg_mssr": "clock_control", "renesas_r8a779f0_cpg_mssr": "clock_control", @@ -267,13 +304,17 @@ "st_stm32_clock_mco": "clock_control", "st_stm32_clock_mux": "clock_control", "st_stm32f1_clock_mco": "clock_control", + "ti_k2g_sci_clk": "clock_control", "wch_rcc": "clock_control", # # comparator "ite_it51xxx_vcmp": "comparator", + "microchip_ac_g1_comparator": "comparator", "nordic_nrf_comp": "comparator", "nordic_nrf_lpcomp": "comparator", + "nxp_acomp": "comparator", "nxp_cmp": "comparator", + "nxp_hscmp": "comparator", "renesas_ra_acmphs": "comparator", "renesas_ra_lvd": "comparator", "renesas_rx_lvd": "comparator", @@ -297,16 +338,23 @@ "espressif_esp32_counter": "counter", "espressif_esp32_rtc_timer": "counter", "gd_gd32_timer": "counter", - "infineon_cat1_counter": "counter", + "infineon_counter": "counter", "infineon_tcpwm_counter": "counter", "ite_it51xxx_counter": "counter", "ite_it8xxx2_counter": "counter", "maxim_ds3231": "counter", "microchip_mcp7940n": "counter", + "microchip_sam_pit64b_counter": "counter", + "microchip_tc_g1_counter": "counter", + "microchip_tcc_g1_counter": "counter", "microchip_xec_timer": "counter", + "microcrystal_rv3032_counter": "counter", "neorv32_gptmr": "counter", "nordic_nrf_rtc": "counter", "nordic_nrf_timer": "counter", + "nuvoton_npck_lct": "counter", + "nuvoton_npcx_lct_v1": "counter", + "nuvoton_npcx_lct_v2": "counter", "nxp_ftm": "counter", "nxp_imx_epit": "counter", "nxp_imx_gpt": "counter", @@ -320,9 +368,12 @@ "nxp_mrt": "counter", "nxp_pit": "counter", "nxp_rtc": "counter", + "nxp_rtc_jdp": "counter", "nxp_s32_sys_timer": "counter", "nxp_stm": "counter", "nxp_tpm_timer": "counter", + "raspberrypi_pico_pit": "counter", + "raspberrypi_pico_pit_channel": "counter", "raspberrypi_pico_timer": "counter", "realtek_rts5912_slwtimer": "counter", "realtek_rts5912_timer": "counter", @@ -330,18 +381,22 @@ "renesas_rz_cmtw_counter": "counter", "renesas_rz_gtm_counter": "counter", "renesas_smartbond_timer": "counter", + "silabs_burtc_counter": "counter", "silabs_gecko_rtcc": "counter", + "silabs_timer_counter": "counter", "snps_dw_timers": "counter", "st_stm32_counter": "counter", "ti_cc23x0_lgpt": "counter", "ti_cc23x0_rtc": "counter", "ti_mspm0_timer_counter": "counter", "xlnx_xps_timer_1_00_a": "counter", - "zephyr_native_posix_counter": "counter", "zephyr_native_sim_counter": "counter", # # crc + "nxp_crc": "crc", + "nxp_lpc_crc": "crc", "renesas_ra_crc": "crc", + "sifli_sf32lb_crc": "crc", # # crypto "atmel_ataes132a": "crypto", @@ -351,10 +406,13 @@ "ite_it51xxx_sha": "crypto", "ite_it8xxx2_sha": "crypto", "ite_it8xxx2_sha_v2": "crypto", + "microchip_sha_g1_crypto": "crypto", "microchip_xec_symcr": "crypto", "nordic_nrf_ecb": "crypto", "nuvoton_npcx_sha": "crypto", "nxp_mcux_dcp": "crypto", + "nxp_s32_crypto_hse_mu": "crypto", + "raspberrypi_pico_sha256": "crypto", "realtek_rts5912_sha": "crypto", "renesas_smartbond_crypto": "crypto", "silabs_si32_aes": "crypto", @@ -388,6 +446,7 @@ "atmel_samd5x_dac": "dac", "espressif_esp32_dac": "dac", "gd_gd32_dac": "dac", + "microchip_dac_g1": "dac", "microchip_mcp4725": "dac", "microchip_mcp4728": "dac", "nxp_dac12": "dac", @@ -414,6 +473,9 @@ # dai/intel/ssp "intel_ssp_dai": "dai/intel/ssp", # + # dai/nxp/esai + "nxp_dai_esai": "dai/nxp/esai", + # # dai/nxp/micfil "nxp_dai_micfil": "dai/nxp/micfil", # @@ -462,7 +524,7 @@ "sitronix_st7796s": "display", "solomon_ssd1322": "display", "st_stm32_ltdc": "display", - "waveshare_7inch_dsi_lcd_c": "display", + "waveshare_dsi2dpi": "display", "zephyr_dummy_dc": "display", "zephyr_hub12": "display", "zephyr_sdl_dc": "display", @@ -471,6 +533,7 @@ "adi_max32_dma": "dma", "altr_msgdma": "dma", "andestech_atcdmacx00": "dma", + "arm_dma_pl330": "dma", "atmel_sam0_dmac": "dma", "atmel_sam_xdmac": "dma", "bflb_dma": "dma", @@ -479,7 +542,7 @@ "espressif_esp32_gdma": "dma", "gd_gd32_dma": "dma", "gd_gd32_dma_v1": "dma", - "infineon_cat1_dma": "dma", + "infineon_dma": "dma", "infineon_xmc4xxx_dma": "dma", "intel_adsp_gpdma": "dma", "intel_adsp_hda_host_in": "dma", @@ -488,8 +551,11 @@ "intel_adsp_hda_link_out": "dma", "intel_lpss": "dma", "intel_sedi_dma": "dma", + "microchip_dmac_g1_dma": "dma", "microchip_xec_dmac": "dma", "nuvoton_npcx_gdma": "dma", + "nxp_4ch_dma": "dma", + "nxp_edma": "dma", "nxp_lpc_dma": "dma", "nxp_mcux_edma": "dma", "nxp_pxp": "dma", @@ -525,6 +591,7 @@ # # edac "intel_ibecc": "edac", + "nxp_erm": "edac", "xlnx_zynqmp_ddrc_2_40a": "edac", # # eeprom @@ -547,7 +614,9 @@ "atmel_sam_trng": "entropy", "brcm_iproc_rng200": "entropy", "espressif_esp32_trng": "entropy", + "gd_gd32_trng": "entropy", "litex_prbs": "entropy", + "microchip_trng_g1_entropy": "entropy", "neorv32_trng": "entropy", "nordic_nrf_cracen_ctrdrbg": "entropy", "nordic_nrf_rng": "entropy", @@ -558,16 +627,20 @@ "nxp_kinetis_trng": "entropy", "nxp_lpc_rng": "entropy", "openisa_rv32m1_trng": "entropy", + "raspberrypi_pico_rng": "entropy", "renesas_smartbond_trng": "entropy", "sensry_sy1xx_trng": "entropy", + "sifli_sf32lb_trng": "entropy", "silabs_gecko_semailbox": "entropy", "silabs_gecko_trng": "entropy", "silabs_siwx91x_rng": "entropy", + "st_stm32_rng": "entropy", + "st_stm32_rng_noirq": "entropy", "telink_b91_trng": "entropy", "ti_cc13xx_cc26xx_trng": "entropy", + "ti_mspm0_trng": "entropy", "virtio_device4": "entropy", "zephyr_bt_hci_entropy": "entropy", - "zephyr_native_posix_rng": "entropy", "zephyr_native_sim_rng": "entropy", "zephyr_psa_crypto_rng": "entropy", # @@ -618,7 +691,11 @@ "virtio_net": "ethernet", "vnd_ethernet": "ethernet", "wiznet_w5500": "ethernet", + "wiznet_w6100": "ethernet", "xlnx_axi_ethernet_1_00_a": "ethernet", + "xlnx_gem": "ethernet", + "xlnx_xps_ethernetlite_1_00_a_mac": "ethernet", + "xlnx_xps_ethernetlite_3_00_a_mac": "ethernet", # # ethernet/dsa "microchip_ksz8463": "ethernet/dsa", @@ -637,6 +714,28 @@ "intel_eth_plat": "ethernet/intel", "intel_igc_mac": "ethernet/intel", # + # ethernet/mdio + "adi_adin2111_mdio": "ethernet/mdio", + "atmel_sam_mdio": "ethernet/mdio", + "espressif_esp32_mdio": "ethernet/mdio", + "infineon_xmc4xxx_mdio": "ethernet/mdio", + "intel_igc_mdio": "ethernet/mdio", + "litex_liteeth_mdio": "ethernet/mdio", + "microchip_lan865x_mdio": "ethernet/mdio", + "nxp_enet_mdio": "ethernet/mdio", + "nxp_enet_qos_mdio": "ethernet/mdio", + "nxp_imx_netc_emdio": "ethernet/mdio", + "nxp_s32_gmac_mdio": "ethernet/mdio", + "nxp_s32_netc_emdio": "ethernet/mdio", + "renesas_ra_mdio": "ethernet/mdio", + "sensry_sy1xx_mdio": "ethernet/mdio", + "snps_dwcxgmac_mdio": "ethernet/mdio", + "st_stm32_mdio": "ethernet/mdio", + "xlnx_axi_ethernet_1_00_a_mdio": "ethernet/mdio", + "xlnx_xps_ethernetlite_1_00_a_mdio": "ethernet/mdio", + "xlnx_xps_ethernetlite_3_00_a_mdio": "ethernet/mdio", + "zephyr_mdio_gpio": "ethernet/mdio", + # # ethernet/nxp_imx_netc "nxp_imx_netc_blk_ctrl": "ethernet/nxp_imx_netc", "nxp_imx_netc_psi": "ethernet/nxp_imx_netc", @@ -646,10 +745,13 @@ "adi_adin2111_phy": "ethernet/phy", "davicom_dm8806_phy": "ethernet/phy", "ethernet_phy": "ethernet/phy", + "ethernet_phy_fixed_link": "ethernet/phy", "microchip_ksz8081": "ethernet/phy", "microchip_ksz9131": "ethernet/phy", + "microchip_lan8742": "ethernet/phy", "microchip_t1s_phy": "ethernet/phy", "microchip_vsc8541": "ethernet/phy", + "motorcomm_yt8521": "ethernet/phy", "nxp_tja1103": "ethernet/phy", "nxp_tja11xx": "ethernet/phy", "qca_ar8031": "ethernet/phy", @@ -658,6 +760,7 @@ "ti_dp83867": "ethernet/phy", # # firmware/scmi + "arm_scmi": "firmware/scmi", "arm_scmi_shmem": "firmware/scmi", # # firmware/tisci @@ -673,20 +776,23 @@ "atmel_at45": "flash", "atmel_sam0_nvmctrl": "flash", "atmel_sam_flash_controller": "flash", + "bflb_flash_controller": "flash", "cdns_nand": "flash", "cdns_qspi_nor": "flash", "espressif_esp32_flash_controller": "flash", "gd_gd32_flash_controller": "flash", - "infineon_cat1_flash_controller": "flash", - "infineon_cat1_qspi_flash": "flash", + "infineon_flash_controller": "flash", + "infineon_qspi_flash": "flash", "infineon_xmc4xxx_flash_controller": "flash", "ite_it51xxx_manual_flash_1k": "flash", "ite_it8xxx2_flash_controller": "flash", "jedec_mspi_nor": "flash", + "jedec_spi_nand": "flash", "jedec_spi_nor": "flash", "microchip_nvmctrl_g1_flash": "flash", "mspi_atxp032": "flash", "mspi_is25xx0xx": "flash", + "netsol_s3axx04": "flash", "nordic_mram": "flash", "nordic_nrf51_flash_controller": "flash", "nordic_nrf52_flash_controller": "flash", @@ -699,6 +805,7 @@ "nuvoton_npcx_fiu_qspi": "flash", "nuvoton_numaker_fmc": "flash", "nuvoton_numaker_rmc": "flash", + "nxp_c40_flash_controller": "flash", "nxp_iap_fmc11": "flash", "nxp_iap_fmc54": "flash", "nxp_iap_fmc55": "flash", @@ -707,16 +814,19 @@ "nxp_imx_flexspi_mx25um51345g": "flash", "nxp_imx_flexspi_nor": "flash", "nxp_kinetis_ftfa": "flash", + "nxp_kinetis_ftfc": "flash", "nxp_kinetis_ftfe": "flash", "nxp_kinetis_ftfl": "flash", "nxp_msf1": "flash", "nxp_s32_qspi_hyperflash": "flash", "nxp_s32_qspi_nor": "flash", + "nxp_s32_xspi_hyperram": "flash", "nxp_xspi_nor": "flash", "openisa_rv32m1_ftfe": "flash", "raspberrypi_pico_flash_controller": "flash", "realtek_rts5912_flash_controller": "flash", "renesas_ra_flash_hp_controller": "flash", + "renesas_ra_flash_lp_controller": "flash", "renesas_ra_mram_controller": "flash", "renesas_ra_ospi_b_nor": "flash", "renesas_ra_qspi_nor": "flash", @@ -763,6 +873,9 @@ # fuel_gauge/composite "zephyr_fuel_gauge_composite": "fuel_gauge/composite", # + # fuel_gauge/hy4245 + "hycon_hy4245": "fuel_gauge/hy4245", + # # fuel_gauge/lc709203f "onnn_lc709203f": "fuel_gauge/lc709203f", # @@ -785,10 +898,12 @@ "quectel_lc26g": "gnss", "quectel_lc76g": "gnss", "quectel_lc86g": "gnss", - "u_blox_f9p": "gnss", - "u_blox_m8": "gnss", "zephyr_gnss_emul": "gnss", # + # gnss/u_blox + "u_blox_f9p": "gnss/u_blox", + "u_blox_m8": "gnss/u_blox", + # # gpio "adi_ad559x_gpio": "gpio", "adi_adp5585_gpio": "gpio", @@ -825,7 +940,7 @@ "fcs_fxl6408": "gpio", "gaisler_grgpio": "gpio", "gd_gd32_gpio": "gpio", - "infineon_cat1_gpio": "gpio", + "infineon_gpio": "gpio", "infineon_tle9104_gpio": "gpio", "infineon_xmc4xxx_gpio": "gpio", "intel_gpio": "gpio", @@ -845,12 +960,10 @@ "microchip_mcp23s09": "gpio", "microchip_mcp23s17": "gpio", "microchip_mcp23s18": "gpio", - "microchip_mec5_gpio": "gpio", "microchip_mpfs_gpio": "gpio", "microchip_port_g1_gpio": "gpio", "microchip_sam_pio4": "gpio", "microchip_xec_gpio": "gpio", - "microchip_xec_gpio_v2": "gpio", "neorv32_gpio": "gpio", "nordic_npm1300_gpio": "gpio", "nordic_npm1304_gpio": "gpio", @@ -886,11 +999,14 @@ "nxp_pcal9722": "gpio", "nxp_pcf857x": "gpio", "nxp_sc18im704_gpio": "gpio", + "nxp_sc18is606_gpio": "gpio", "nxp_siul2_gpio": "gpio", "openisa_rv32m1_gpio": "gpio", "quicklogic_eos_s3_gpio": "gpio", "raspberrypi_pico_gpio_port": "gpio", "raspberrypi_rp1_gpio": "gpio", + "realtek_ameba_gpio": "gpio", + "realtek_bee_gpio": "gpio", "realtek_rts5912_gpio": "gpio", "renesas_ra_gpio_ioport": "gpio", "renesas_rcar_gpio": "gpio", @@ -937,8 +1053,11 @@ "zephyr_gpio_emul": "gpio", "zephyr_gpio_emul_sdl": "gpio", # - # haptics - "ti_drv2605": "haptics", + # haptics/cirrus + "cirrus_cs40l5x": "haptics/cirrus", + # + # haptics/ti + "ti_drv2605": "haptics/ti", # # hdlc_rcp_if "nxp_hdlc_rcp_if": "hdlc_rcp_if", @@ -956,7 +1075,9 @@ "nxp_lpc_uid": "hwinfo", # # hwspinlock + "nxp_sema42": "hwspinlock", "sqn_hwspinlock": "hwspinlock", + "vnd_hwspinlock": "hwspinlock", # # i2c "adi_max32_i2c": "i2c", @@ -968,6 +1089,7 @@ "atmel_sam_i2c_twi": "i2c", "atmel_sam_i2c_twihs": "i2c", "atmel_sam_i2c_twim": "i2c", + "bflb_i2c": "i2c", "brcm_iproc_i2c": "i2c", "cdns_i2c": "i2c", "ene_kb1200_i2c": "i2c", @@ -976,8 +1098,7 @@ "gd_gd32_i2c": "i2c", "gpio_i2c": "i2c", "gpio_i2c_switch": "i2c", - "infineon_cat1_i2c": "i2c", - "infineon_cat1_i2c_pdl": "i2c", + "infineon_i2c": "i2c", "infineon_xmc4xxx_i2c": "i2c", "intel_sedi_i2c": "i2c", "ite_enhance_i2c": "i2c", @@ -986,8 +1107,11 @@ "litex_i2c": "i2c", "litex_litei2c": "i2c", "microchip_mpfs_i2c": "i2c", + "microchip_sercom_g1_i2c": "i2c", "microchip_xec_i2c": "i2c", "microchip_xec_i2c_v2": "i2c", + "nordic_nrf_twi": "i2c", + "nordic_nrf_twim": "i2c", "nordic_nrf_twis": "i2c", "nuvoton_npcx_i2c_ctrl": "i2c", "nuvoton_npcx_i2c_port": "i2c", @@ -1007,11 +1131,14 @@ "renesas_rx_i2c": "i2c", "renesas_rz_iic": "i2c", "renesas_rz_riic": "i2c", + "renesas_rza2m_riic": "i2c", "renesas_smartbond_i2c": "i2c", "sensry_sy1xx_i2c": "i2c", "sifive_i2c0": "i2c", + "sifli_sf32lb_i2c": "i2c", "silabs_gecko_i2c": "i2c", "silabs_i2c": "i2c", + "snps_designware_i2c": "i2c", "st_stm32_i2c_v1": "i2c", "st_stm32_i2c_v2": "i2c", "telink_b91_i2c": "i2c", @@ -1032,9 +1159,12 @@ "zephyr_i2c_target_eeprom": "i2c/target", # # i2s + "adi_max32_i2s": "i2s", "ambiq_i2s": "i2s", "atmel_sam_ssc": "i2s", "espressif_esp32_i2s": "i2s", + "infineon_i2s": "i2s", + "nordic_nrf_i2s": "i2s", "nxp_lpc_i2s": "i2s", "nxp_mcux_i2s": "i2s", "renesas_ra_i2s_ssie": "i2s", @@ -1042,6 +1172,7 @@ "st_stm32_i2s": "i2s", "st_stm32_sai": "i2s", "vnd_i2s": "i2s", + "zephyr_i2s_sdl": "i2s", # # i3c "adi_max32_i3c": "i3c", @@ -1075,12 +1206,14 @@ "adc_keys": "input", "analog_axis": "input", "arduino_modulino_buttons": "input", + "bflb_irx": "input", "chipsemi_chsc5x": "input", "chipsemi_chsc6x": "input", "cirque_pinnacle": "input", "cypress_cy8cmbr3xxx": "input", "espressif_esp32_touch": "input", "focaltech_ft5336": "input", + "focaltech_ft6146": "input", "futaba_sbus": "input", "goodix_gt911": "input", "gpio_kbd_matrix": "input", @@ -1096,6 +1229,7 @@ "nintendo_nunchuk": "input", "nuvoton_npcx_kbd": "input", "nxp_mcux_kpp": "input", + "parade_tma525b": "input", "pixart_pat912x": "input", "pixart_paw32xx": "input", "pixart_pmw3610": "input", @@ -1109,11 +1243,13 @@ "st_stm32_tsc": "input", "st_stmpe811": "input", "vishay_vs1838b": "input", + "wch_ch9350l": "input", "xptek_xpt2046": "input", "zephyr_input_sdl_touch": "input", "zephyr_native_linux_evdev": "input", # # interrupt_controller + "adi_max32_rv32_intc": "interrupt_controller", "arm_gic_v1": "interrupt_controller", "arm_gic_v2": "interrupt_controller", "arm_gic_v3": "interrupt_controller", @@ -1132,17 +1268,22 @@ "ite_it8xxx2_wuc": "interrupt_controller", "litex_vexriscv_intc0": "interrupt_controller", "mediatek_adsp_intc": "interrupt_controller", + "microchip_eic_g1_intc": "interrupt_controller", "microchip_xec_ecia": "interrupt_controller", "nuclei_eclic": "interrupt_controller", "nuvoton_npcx_miwu": "interrupt_controller", + "nxp_gint": "interrupt_controller", "nxp_irqsteer_intc": "interrupt_controller", "nxp_pint": "interrupt_controller", "nxp_s32_wkpu": "interrupt_controller", "nxp_siul2_eirq": "interrupt_controller", "openisa_rv32m1_intmux": "interrupt_controller", + "renesas_rx_grp_intc": "interrupt_controller", "renesas_rx_icu": "interrupt_controller", "renesas_rz_ext_irq": "interrupt_controller", + "renesas_rz_tint": "interrupt_controller", "riscv_clic": "interrupt_controller", + "riscv_imsic": "interrupt_controller", "shared_irq": "interrupt_controller", "sifive_plic_1_0_0": "interrupt_controller", "snps_arcv2_intc": "interrupt_controller", @@ -1182,6 +1323,7 @@ "nxp_pca9633": "led", "onnn_ncp5623": "led", "pwm_leds": "led", + "sct_sct2024": "led", "ti_lp3943": "led", "ti_lp5009": "led", "ti_lp5012": "led", @@ -1209,9 +1351,14 @@ # lora "reyax_rylrxxx": "lora", # - # lora/loramac_node - "semtech_sx1272": "lora/loramac_node", - "semtech_sx1276": "lora/loramac_node", + # lora/loramac-node + "semtech_sx1272": "lora/loramac-node", + "semtech_sx1276": "lora/loramac-node", + # + # lora/native/sx126x + "semtech_sx1261": "lora/native/sx126x", + "semtech_sx1262": "lora/native/sx126x", + "st_stm32wl_subghz_radio": "lora/native/sx126x", # # mbox "andestech_mbox_plic_sw": "mbox", @@ -1228,31 +1375,13 @@ "nxp_mbox_imx_mu": "mbox", "nxp_mbox_mailbox": "mbox", "nxp_s32_mru": "mbox", + "raspberrypi_pico_mbox": "mbox", "renesas_ra_ipc_mbox": "mbox", "renesas_rz_mhu_mbox": "mbox", "st_mbox_stm32_hsem": "mbox", "ti_omap_mailbox": "mbox", "ti_secure_proxy": "mbox", - # - # mdio - "adi_adin2111_mdio": "mdio", - "atmel_sam_mdio": "mdio", - "espressif_esp32_mdio": "mdio", - "infineon_xmc4xxx_mdio": "mdio", - "intel_igc_mdio": "mdio", - "litex_liteeth_mdio": "mdio", - "microchip_lan865x_mdio": "mdio", - "nxp_enet_mdio": "mdio", - "nxp_enet_qos_mdio": "mdio", - "nxp_imx_netc_emdio": "mdio", - "nxp_s32_gmac_mdio": "mdio", - "nxp_s32_netc_emdio": "mdio", - "renesas_ra_mdio": "mdio", - "sensry_sy1xx_mdio": "mdio", - "snps_dwcxgmac_mdio": "mdio", - "st_stm32_mdio": "mdio", - "xlnx_axi_ethernet_1_00_a_mdio": "mdio", - "zephyr_mdio_gpio": "mdio", + "xlnx_mbox_versal_ipi_mailbox": "mbox", # # memc "adi_max32_hpb": "memc", @@ -1261,9 +1390,11 @@ "mspi_aps6404l": "memc", "mspi_aps_z8": "memc", "nxp_imx_flexspi": "memc", + "nxp_imx_flexspi_is66wvs8m8": "memc", "nxp_imx_flexspi_s27ks0641": "memc", "nxp_imx_flexspi_w956a8mbya": "memc", "nxp_s32_qspi": "memc", + "nxp_s32_xspi": "memc", "nxp_xspi": "memc", "nxp_xspi_psram": "memc", "renesas_ra_sdram": "memc", @@ -1290,6 +1421,7 @@ "maxim_max20335": "mfd", "maxim_max31790": "mfd", "microchip_sam_flexcom": "mfd", + "microcrystal_rv3032_mfd": "mfd", "motorola_mc146818_mfd": "mfd", "nordic_npm1300": "mfd", "nordic_npm1304": "mfd", @@ -1299,13 +1431,18 @@ "nxp_lp_flexcomm": "mfd", "nxp_pca9422": "mfd", "nxp_pf1550": "mfd", + "nxp_sc18is606": "mfd", "rohm_bd8lb600fs": "mfd", # # mipi_dbi + "bflb_dbi": "mipi_dbi", + "espressif_esp32_lcd_cam_mipi_dbi": "mipi_dbi", "nxp_lcdic": "mipi_dbi", "nxp_mipi_dbi_dcnano_lcdif": "mipi_dbi", "nxp_mipi_dbi_flexio_lcdif": "mipi_dbi", + "raspberrypi_pico_mipi_dbi_pio": "mipi_dbi", "renesas_smartbond_mipi_dbi": "mipi_dbi", + "sifli_sf32lb_lcdc_mipi_dbi": "mipi_dbi", "st_stm32_fmc_mipi_dbi": "mipi_dbi", "zephyr_mipi_dbi_bitbang": "mipi_dbi", "zephyr_mipi_dbi_spi": "mipi_dbi", @@ -1370,6 +1507,7 @@ "intel_timeaware_gpio": "misc/timeaware_gpio", # # mm + "intel_adsp_mtl_tlb": "mm", "intel_adsp_tlb": "mm", # # modem @@ -1381,6 +1519,7 @@ "quectel_eg800q": "modem", "simcom_a76xx": "modem", "sqn_gm02s": "modem", + "st_st87mxx": "modem", "telit_me310g1": "modem", "telit_me910g1": "modem", "u_blox_lara_r6": "modem", @@ -1390,8 +1529,10 @@ # # modem/hl78xx "swir_hl7800": "modem/hl78xx", + "swir_hl7800_gnss": "modem/hl78xx", "swir_hl7800_offload": "modem/hl78xx", "swir_hl7812": "modem/hl78xx", + "swir_hl7812_gnss": "modem/hl78xx", "swir_hl7812_offload": "modem/hl78xx", # # modem/simcom/sim7080 @@ -1400,11 +1541,21 @@ # mspi "ambiq_mspi_controller": "mspi", "snps_designware_ssi": "mspi", + "st_stm32_ospi_controller": "mspi", + "st_stm32_qspi_controller": "mspi", + "st_stm32_xspi_controller": "mspi", "zephyr_mspi_emul_controller": "mspi", # # opamp "nxp_opamp": "opamp", "nxp_opamp_fast": "opamp", + "st_stm32_opamp": "opamp", + # + # otp + "nxp_ocotp": "otp", + "sifli_sf32lb_efuse": "otp", + "st_stm32_bsec": "otp", + "zephyr_otp_emul": "otp", # # pcie/controller "brcm_brcmstb_pcie": "pcie/controller", @@ -1423,11 +1574,12 @@ "nuvoton_npcx_peci": "peci", # # pinctrl + "alif_pinctrl": "pinctrl", + "brcm_bcm2711_pinctrl": "pinctrl", "ene_kb106x_pinctrl": "pinctrl", "ene_kb1200_pinctrl": "pinctrl", "infineon_xmc4xxx_pinctrl": "pinctrl", "ite_it8xxx2_pinctrl_func": "pinctrl", - "microchip_mec5_pinctrl": "pinctrl", "microchip_xec_pinctrl": "pinctrl", "nuvoton_numaker_pinctrl": "pinctrl", "nuvoton_numicro_pinctrl": "pinctrl", @@ -1461,10 +1613,12 @@ "renesas_rzt2m_pinctrl": "pinctrl/renesas/rz", # # pm_cpu_ops + "arm_fvp_pwrc": "pm_cpu_ops", "arm_psci_0_2": "pm_cpu_ops", "arm_psci_1_1": "pm_cpu_ops", # # power_domain + "arm_scmi_power_domain": "power_domain", "intel_adsp_power_domain": "power_domain", "nordic_nrfs_gdpwr": "power_domain", "nordic_nrfs_swext": "power_domain", @@ -1476,6 +1630,7 @@ "ti_sci_pm_domain": "power_domain", # # ps2 + "ite_it51xxx_ps2": "ps2", "microchip_xec_ps2": "ps2", "nuvoton_npcx_ps2_channel": "ps2", "nuvoton_npcx_ps2_ctrl": "ps2", @@ -1494,6 +1649,8 @@ "atmel_sam0_tc_pwm": "pwm", "atmel_sam0_tcc_pwm": "pwm", "atmel_sam_pwm": "pwm", + "bflb_pwm_1": "pwm", + "bflb_pwm_2": "pwm", "ene_kb106x_pwm": "pwm", "ene_kb1200_pwm": "pwm", "espressif_esp32_ledc": "pwm", @@ -1509,10 +1666,12 @@ "ite_it8xxx2_pwm": "pwm", "litex_pwm": "pwm", "maxim_max31790_pwm": "pwm", + "microchip_tc_g1_pwm": "pwm", "microchip_tcc_g1_pwm": "pwm", "microchip_xec_pwm": "pwm", "microchip_xec_pwmbbled": "pwm", "neorv32_pwm": "pwm", + "nordic_nrf_pwm": "pwm", "nordic_nrf_sw_pwm": "pwm", "nuvoton_npcx_pwm": "pwm", "nuvoton_numaker_pwm": "pwm", @@ -1534,7 +1693,10 @@ "renesas_rx_mtu_pwm": "pwm", "renesas_rz_gpt_pwm": "pwm", "renesas_rz_mtu_pwm": "pwm", + "renesas_rza2m_gpt_pwm": "pwm", "sifive_pwm0": "pwm", + "sifli_sf32lb_atim_pwm": "pwm", + "sifli_sf32lb_gpt_pwm": "pwm", "silabs_gecko_pwm": "pwm", "silabs_letimer_pwm": "pwm", "silabs_siwx91x_pwm": "pwm", @@ -1568,10 +1730,13 @@ "regulator_fixed": "regulator", "regulator_gpio": "regulator", "renesas_smartbond_regulator": "regulator", + "st_stm32_vrefbuf": "regulator", + "ti_tps55287": "regulator", "zephyr_fake_regulator": "regulator", # # reset "aspeed_ast10x0_reset": "reset", + "focaltech_ft9001_cpm_rctl": "reset", "gd_gd32_rctl": "reset", "intel_socfpga_reset": "reset", "microchip_mpfs_reset": "reset", @@ -1582,6 +1747,7 @@ "nxp_mrcc_reset": "reset", "nxp_rstctl": "reset", "raspberrypi_pico_reset": "reset", + "realtek_rts5817_reset": "reset", "reset_mmio": "reset", "sifli_sf32lb_rcc_rctl": "reset", "st_stm32_rcc_rctl": "reset", @@ -1593,15 +1759,19 @@ "zephyr_retained_reg": "retained_mem", # # rtc + "adi_max31331": "rtc", "ambiq_am1805": "rtc", "ambiq_rtc": "rtc", "atmel_sam_rtc": "rtc", "epson_rx8130ce_rtc": "rtc", - "infineon_cat1_rtc": "rtc", + "infineon_rtc": "rtc", "infineon_xmc4xxx_rtc": "rtc", + "maxim_ds1302": "rtc", "maxim_ds1307": "rtc", "maxim_ds1337": "rtc", "maxim_ds3231_rtc": "rtc", + "microchip_rtc_g1": "rtc", + "microchip_rtc_g2": "rtc", "microcrystal_rv3028": "rtc", "microcrystal_rv3032": "rtc", "microcrystal_rv8803": "rtc", @@ -1617,6 +1787,7 @@ "realtek_rts5912_rtc": "rtc", "renesas_ra_rtc": "rtc", "renesas_smartbond_rtc": "rtc", + "sifli_sf32lb_rtc": "rtc", "silabs_siwx91x_rtc": "rtc", "st_stm32_rtc": "rtc", "ti_bq32002": "rtc", @@ -1631,7 +1802,7 @@ "atmel_sam_hsmci": "sdhc", "cdns_sdhc": "sdhc", "espressif_esp32_sdhc_slot": "sdhc", - "infineon_cat1_sdhc_sdio": "sdhc", + "infineon_sdhc_sdio": "sdhc", "intel_emmc_host": "sdhc", "microchip_sama7g5_sdmmc": "sdhc", "nxp_imx_usdhc": "sdhc", @@ -1648,6 +1819,9 @@ # sensor/adi/ad2s1210 "adi_ad2s1210": "sensor/adi/ad2s1210", # + # sensor/adi/ade7978 + "adi_ade7978": "sensor/adi/ade7978", + # # sensor/adi/adltc2990 "adi_adltc2990": "sensor/adi/adltc2990", # @@ -1670,6 +1844,9 @@ # sensor/adi/adxl372 "adi_adxl372": "sensor/adi/adxl372", # + # sensor/adi/max30210 + "adi_max30210": "sensor/adi/max30210", + # # sensor/adi/max32664c "maxim_max32664c": "sensor/adi/max32664c", # @@ -1682,6 +1859,9 @@ # sensor/amg88xx "panasonic_amg88xx": "sensor/amg88xx", # + # sensor/ams/ams_as5048 + "ams_as5048": "sensor/ams/ams_as5048", + # # sensor/ams/ams_as5600 "ams_as5600": "sensor/ams/ams_as5600", # @@ -1744,6 +1924,12 @@ # sensor/bosch/bmc150_magn "bosch_bmc150_magn": "sensor/bosch/bmc150_magn", # + # sensor/bosch/bme280 + "bosch_bme280": "sensor/bosch/bme280", + # + # sensor/bosch/bme680 + "bosch_bme680": "sensor/bosch/bme680", + # # sensor/bosch/bmg160 "bosch_bmg160": "sensor/bosch/bmg160", # @@ -1760,6 +1946,12 @@ # sensor/bosch/bmi323 "bosch_bmi323": "sensor/bosch/bmi323", # + # sensor/bosch/bmm150 + "bosch_bmm150": "sensor/bosch/bmm150", + # + # sensor/bosch/bmm350 + "bosch_bmm350": "sensor/bosch/bmm350", + # # sensor/bosch/bmp180 "bosch_bmp180": "sensor/bosch/bmp180", # @@ -1767,6 +1959,9 @@ "bosch_bmp388": "sensor/bosch/bmp388", "bosch_bmp390": "sensor/bosch/bmp388", # + # sensor/bosch/bmp581 + "bosch_bmp581": "sensor/bosch/bmp581", + # # sensor/broadcom/afbr_s50 "brcm_afbr_s50": "sensor/broadcom/afbr_s50", # @@ -1825,6 +2020,9 @@ # sensor/infineon/xmc4xxx_temp "infineon_xmc4xxx_temp": "sensor/infineon/xmc4xxx_temp", # + # sensor/ist8310 + "isentek_ist8310": "sensor/ist8310", + # # sensor/ite/ite_tach_it51xxx "ite_it51xxx_tach": "sensor/ite/ite_tach_it51xxx", # @@ -1837,9 +2035,6 @@ # sensor/jedec/jc42 "jedec_jc_42_4_temp": "sensor/jedec/jc42", # - # sensor/liteon/ltr329 - "liteon_ltr329": "sensor/liteon/ltr329", - # # sensor/liteon/ltrf216a "liteon_ltrf216a": "sensor/liteon/ltrf216a", # @@ -1875,6 +2070,9 @@ # sensor/maxim/max31855 "maxim_max31855": "sensor/maxim/max31855", # + # sensor/maxim/max31865 + "maxim_max31865": "sensor/maxim/max31865", + # # sensor/maxim/max31875 "maxim_max31875": "sensor/maxim/max31875", # @@ -1900,6 +2098,9 @@ # sensor/memsic/mc3419 "memsic_mc3419": "sensor/memsic/mc3419", # + # sensor/memsic/mmc56x3 + "memsic_mmc56x3": "sensor/memsic/mmc56x3", + # # sensor/mhz19b "winsen_mhz19b": "sensor/mhz19b", # @@ -1945,6 +2146,9 @@ # sensor/nuvoton/nuvoton_adc_cmp_npcx "nuvoton_adc_cmp": "sensor/nuvoton/nuvoton_adc_cmp_npcx", # + # sensor/nuvoton/nuvoton_adc_v2t_npcx + "nuvoton_npcx_adc_v2t": "sensor/nuvoton/nuvoton_adc_v2t_npcx", + # # sensor/nuvoton/nuvoton_tach_npcx "nuvoton_npcx_tach": "sensor/nuvoton/nuvoton_tach_npcx", # @@ -1975,6 +2179,9 @@ # sensor/nxp/nxp_tempmon "nxp_tempmon": "sensor/nxp/nxp_tempmon", # + # sensor/nxp/nxp_tempsense + "nxp_tempsense": "sensor/nxp/nxp_tempsense", + # # sensor/nxp/nxp_tmpsns "nxp_tmpsns": "sensor/nxp/nxp_tmpsns", # @@ -2045,6 +2252,9 @@ # sensor/rpi_pico_temp "raspberrypi_pico_temp": "sensor/rpi_pico_temp", # + # sensor/rv3032_temp + "microcrystal_rv3032_temp": "sensor/rv3032_temp", + # # sensor/s11059 "hamamatsu_s11059": "sensor/s11059", # @@ -2074,6 +2284,9 @@ # sensor/sensirion/sts4x "sensirion_sts4x": "sensor/sensirion/sts4x", # + # sensor/sifli/sf32lb_tsen + "sifli_sf32lb_tsen": "sensor/sifli/sf32lb_tsen", + # # sensor/silabs/si7006 "sensirion_sht21": "sensor/silabs/si7006", "silabs_si7006": "sensor/silabs/si7006", @@ -2175,6 +2388,14 @@ # sensor/st/lsm6dsv16x "DT_DRV_COMPAT_LSM6DSV16X": "sensor/st/lsm6dsv16x", "DT_DRV_COMPAT_LSM6DSV32X": "sensor/st/lsm6dsv16x", + "st_lsm6dsv16x": "sensor/st/lsm6dsv16x", + "st_lsm6dsv32x": "sensor/st/lsm6dsv16x", + # + # sensor/st/lsm6dsvxxx + "st_ism6hg256x": "sensor/st/lsm6dsvxxx", + "st_lsm6dsv320x": "sensor/st/lsm6dsvxxx", + "st_lsm6dsv80x": "sensor/st/lsm6dsvxxx", + "st_lsm6dsvxxx": "sensor/st/lsm6dsvxxx", # # sensor/st/lsm9ds0_gyro "st_lsm9ds0_gyro": "sensor/st/lsm9ds0_gyro", @@ -2239,7 +2460,11 @@ "invensense_icm42670s": "sensor/tdk/icm42x70", # # sensor/tdk/icm45686 + "invensense_icm45605": "sensor/tdk/icm45686", + "invensense_icm45605s": "sensor/tdk/icm45686", "invensense_icm45686": "sensor/tdk/icm45686", + "invensense_icm45686s": "sensor/tdk/icm45686", + "invensense_icm45688p": "sensor/tdk/icm45686", # # sensor/tdk/icp101xx "invensense_icp101xx": "sensor/tdk/icp101xx", @@ -2269,6 +2494,7 @@ "ti_ina226": "sensor/ti/ina2xx", "ti_ina228": "sensor/ti/ina2xx", "ti_ina230": "sensor/ti/ina2xx", + "ti_ina232": "sensor/ti/ina2xx", "ti_ina236": "sensor/ti/ina2xx", "ti_ina237": "sensor/ti/ina2xx", # @@ -2281,8 +2507,10 @@ # sensor/ti/lm95234 "national_lm95234": "sensor/ti/lm95234", # - # sensor/ti/opt3001 - "ti_opt3001": "sensor/ti/opt3001", + # sensor/ti/opt300x + "ti_opt3001": "sensor/ti/opt300x", + "ti_opt3004": "sensor/ti/opt300x", + "ti_opt300x": "sensor/ti/opt300x", # # sensor/ti/ti_hdc "ti_hdc": "sensor/ti/ti_hdc", @@ -2301,6 +2529,7 @@ # # sensor/ti/tmp108 "ams_as6212": "sensor/ti/tmp108", + "ams_as6221": "sensor/ti/tmp108", "ti_tmp108": "sensor/ti/tmp108", # # sensor/ti/tmp112 @@ -2388,10 +2617,10 @@ "espressif_esp32_lpuart": "serial", "espressif_esp32_uart": "serial", "espressif_esp32_usb_serial": "serial", + "focaltech_ft9001_usart": "serial", "gaisler_apbuart": "serial", "gd_gd32_usart": "serial", - "infineon_cat1_uart": "serial", - "infineon_cat1_uart_pdl": "serial", + "infineon_uart": "serial", "infineon_xmc4xxx_uart": "serial", "intel_lw_uart": "serial", "intel_sedi_uart": "serial", @@ -2400,7 +2629,6 @@ "litex_uart": "serial", "lowrisc_opentitan_uart": "serial", "microchip_coreuart": "serial", - "microchip_mec5_uart": "serial", "microchip_sercom_g1_uart": "serial", "microchip_xec_uart": "serial", "neorv32_uart": "serial", @@ -2420,6 +2648,8 @@ "openisa_rv32m1_lpuart": "serial", "quicklogic_usbserialport_s3b": "serial", "raspberrypi_pico_uart_pio": "serial", + "realtek_ameba_loguart": "serial", + "realtek_bee_uart": "serial", "realtek_rts5912_uart": "serial", "renesas_ra8_uart_sci_b": "serial", "renesas_ra_sci_uart": "serial", @@ -2458,7 +2688,6 @@ "xen_hvc_consoleio": "serial", "xlnx_xps_uartlite_1_00_a": "serial", "xlnx_xuartps": "serial", - "zephyr_native_posix_uart": "serial", "zephyr_native_pty_uart": "serial", "zephyr_native_tty_uart": "serial", "zephyr_nus_uart": "serial", @@ -2482,14 +2711,14 @@ "arm_pl022": "spi", "atmel_sam0_spi": "spi", "atmel_sam_spi": "spi", + "bflb_spi": "spi", "cdns_spi": "spi", "cypress_psoc6_spi": "spi", "egis_et171_spi": "spi", "espressif_esp32_spi": "spi", "gaisler_spimctrl": "spi", "gd_gd32_spi": "spi", - "infineon_cat1_spi": "spi", - "infineon_cat1_spi_pdl": "spi", + "infineon_spi": "spi", "infineon_xmc4xxx_spi": "spi", "intel_penwell_spi": "spi", "intel_sedi_spi": "spi", @@ -2498,11 +2727,13 @@ "litex_spi": "spi", "litex_spi_litespi": "spi", "lowrisc_opentitan_spi": "spi", - "microchip_mec5_qspi": "spi", "microchip_mpfs_qspi": "spi", "microchip_mpfs_spi": "spi", + "microchip_sercom_g1_spi": "spi", "microchip_xec_qmspi": "spi", "microchip_xec_qmspi_ldma": "spi", + "nordic_nrf_spi": "spi", + "nordic_nrf_spim": "spi", "nuvoton_npcx_spip": "spi", "nuvoton_numaker_spi": "spi", "nxp_dspi": "spi", @@ -2514,13 +2745,18 @@ "opencores_spi_simple": "spi", "openisa_rv32m1_lpspi": "spi", "raspberrypi_pico_spi_pio": "spi", + "realtek_rts5912_spi": "spi", "renesas_ra8_spi_b": "spi", "renesas_ra_spi": "spi", + "renesas_ra_spi_sci": "spi", + "renesas_ra_spi_sci_b": "spi", "renesas_rx_rspi": "spi", "renesas_rz_rspi": "spi", "renesas_rz_spi": "spi", "renesas_smartbond_spi": "spi", + "sensry_sy1xx_spi": "spi", "sifive_spi0": "spi", + "sifli_sf32lb_spi": "spi", "silabs_eusart_spi": "spi", "silabs_gspi": "spi", "silabs_usart_spi": "spi", @@ -2540,16 +2776,29 @@ "nxp_lpspi": "spi/spi_nxp_lpspi", # # stepper - "zephyr_fake_stepper": "stepper", - "zephyr_h_bridge_stepper": "stepper", + "zephyr_fake_stepper_ctrl": "stepper", + "zephyr_fake_stepper_driver": "stepper", + # + # stepper/adi_tmc/tmc22xx + "adi_tmc2209": "stepper/adi_tmc/tmc22xx", + # + # stepper/adi_tmc/tmc50xx + "adi_tmc50xx": "stepper/adi_tmc/tmc50xx", + "adi_tmc50xx_stepper_ctrl": "stepper/adi_tmc/tmc50xx", + "adi_tmc50xx_stepper_driver": "stepper/adi_tmc/tmc50xx", # - # stepper/adi_tmc - "adi_tmc2209": "stepper/adi_tmc", - "adi_tmc50xx": "stepper/adi_tmc", + # stepper/adi_tmc/tmc51xx + "adi_tmc51xx": "stepper/adi_tmc/tmc51xx", + "adi_tmc51xx_stepper_ctrl": "stepper/adi_tmc/tmc51xx", + "adi_tmc51xx_stepper_driver": "stepper/adi_tmc/tmc51xx", # # stepper/allegro "allegro_a4979": "stepper/allegro", # + # stepper/gpio_stepper + "zephyr_gpio_step_dir_stepper_ctrl": "stepper/gpio_stepper", + "zephyr_h_bridge_stepper_ctrl": "stepper/gpio_stepper", + # # stepper/ti "ti_drv84xx": "stepper/ti", # @@ -2561,10 +2810,11 @@ "linaro_optee_tz": "tee/optee", # # timer + "adi_max32_rv32_sys_timer": "timer", "ambiq_stimer": "timer", "atmel_sam0_rtc": "timer", "gaisler_gptimer": "timer", - "infineon_cat1_lp_timer": "timer", + "infineon_lp_timer": "timer", "intel_adsp_timer": "timer", "intel_hpet": "timer", "ite_it51xxx_timer": "timer", @@ -2597,6 +2847,10 @@ # usb/bc12 "diodes_pi3usb9201": "usb/bc12", # + # usb/common/stm32 + "*/": "usb/common/stm32", + "st_stm32u5_otghs_phy": "usb/common/stm32", + # # usb/device "atmel_sam_usbc": "usb/device", "atmel_sam_usbhs": "usb/device", @@ -2607,6 +2861,7 @@ "atmel_sam0_usb": "usb/udc", "ite_it82xx2_usb": "usb/udc", "nordic_nrf_usbd": "usb/udc", + "nuvoton_numaker_hsusbd": "usb/udc", "nuvoton_numaker_usbd": "usb/udc", "nxp_ehci": "usb/udc", "nxp_kinetis_usbd": "usb/udc", @@ -2647,15 +2902,18 @@ # # video "aptina_mt9m114": "video", - "espressif_esp32_lcd_cam": "video", + "espressif_esp32_lcd_cam_dvp": "video", "galaxycore_gc2145": "video", "himax_hm01b0": "video", + "himax_hm0360": "video", "nxp_imx_csi": "video", "nxp_mipi_csi2rx": "video", "nxp_video_smartdma": "video", "ovti_ov2640": "video", "ovti_ov5640": "video", + "ovti_ov5642": "video", "ovti_ov7670": "video", + "ovti_ov7675": "video", "ovti_ov7725": "video", "ovti_ov9655": "video", "renesas_ra_ceu": "video", @@ -2688,19 +2946,21 @@ # # watchdog "adi_max32_watchdog": "watchdog", + "adi_max42500_watchdog": "watchdog", "ambiq_watchdog": "watchdog", "andestech_atcwdt200": "watchdog", "arm_cmsdk_watchdog": "watchdog", "atmel_sam0_watchdog": "watchdog", "atmel_sam4l_watchdog": "watchdog", "atmel_sam_watchdog": "watchdog", + "bflb_wdt": "watchdog", "ene_kb106x_watchdog": "watchdog", "ene_kb1200_watchdog": "watchdog", "espressif_esp32_watchdog": "watchdog", "espressif_esp32_xt_wdt": "watchdog", "gd_gd32_fwdgt": "watchdog", "gd_gd32_wwdgt": "watchdog", - "infineon_cat1_watchdog": "watchdog", + "infineon_watchdog": "watchdog", "infineon_xmc4xxx_watchdog": "watchdog", "intel_adsp_watchdog": "watchdog", "intel_tco_wdt": "watchdog", @@ -2708,11 +2968,13 @@ "ite_it8xxx2_watchdog": "watchdog", "litex_watchdog": "watchdog", "lowrisc_opentitan_aontimer": "watchdog", + "microchip_wdt_g1": "watchdog", "microchip_xec_watchdog": "watchdog", "nordic_npm1300_wdt": "watchdog", "nordic_npm1304_wdt": "watchdog", "nordic_npm2100_wdt": "watchdog", "nordic_npm6001_wdt": "watchdog", + "nordic_nrf_wdt": "watchdog", "nuvoton_npcx_watchdog": "watchdog", "nuvoton_numaker_wwdt": "watchdog", "nxp_cop": "watchdog", @@ -2725,6 +2987,7 @@ "nxp_s32_swt": "watchdog", "nxp_wdog32": "watchdog", "raspberrypi_pico_watchdog": "watchdog", + "realtek_rts5817_watchdog": "watchdog", "realtek_rts5912_watchdog": "watchdog", "renesas_rx_iwdt": "watchdog", "renesas_rz_wdt": "watchdog", @@ -2751,10 +3014,16 @@ # wifi/esp_at "espressif_esp_at": "wifi/esp_at", # + # wifi/esp_hosted + "espressif_esp_hosted": "wifi/esp_hosted", + # # wifi/eswifi "inventek_eswifi": "wifi/eswifi", "inventek_eswifi_uart": "wifi/eswifi", # + # wifi/infineon + "infineon_airoc_wifi": "wifi/infineon", + # # wifi/nrf_wifi/off_raw_tx/src "nordic_wlan": "wifi/nrf_wifi/off_raw_tx/src", # diff --git a/ports/zephyr-cp/cptools/gen_compat2driver.py b/ports/zephyr-cp/cptools/gen_compat2driver.py index 1e529072dab..ffe8da18596 100644 --- a/ports/zephyr-cp/cptools/gen_compat2driver.py +++ b/ports/zephyr-cp/cptools/gen_compat2driver.py @@ -3,7 +3,7 @@ mapping = {} drivers = pathlib.Path("zephyr/drivers") -for p in drivers.glob("**/*.c"): +for p in drivers.glob("**/*.[ch]"): for line in p.open(): if line.startswith("#define DT_DRV_COMPAT"): compat = line.rsplit(None, 1)[-1].strip() diff --git a/ports/zephyr-cp/cptools/get_west_shield_args.py b/ports/zephyr-cp/cptools/get_west_shield_args.py new file mode 100644 index 00000000000..deda6bf5f26 --- /dev/null +++ b/ports/zephyr-cp/cptools/get_west_shield_args.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +"""Resolve shield arguments for west build. + +Priority: +1. SHIELD / SHIELDS make variables (if explicitly provided) +2. SHIELD / SHIELDS from boards///circuitpython.toml +""" + +import argparse +import os +import pathlib +import re +import shlex + +import board_tools + + +def split_shields(raw): + if not raw: + return [] + + return [shield for shield in re.split(r"[,;\s]+", raw.strip()) if shield] + + +def dedupe(values): + deduped = [] + seen = set() + + for value in values: + if value in seen: + continue + seen.add(value) + deduped.append(value) + + return deduped + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("board") + args = parser.parse_args() + + portdir = pathlib.Path(__file__).resolve().parent.parent + + _, mpconfigboard = board_tools.load_mpconfigboard(portdir, args.board) + + shield_origin = os.environ.get("SHIELD_ORIGIN", "undefined") + shields_origin = os.environ.get("SHIELDS_ORIGIN", "undefined") + + shield_override = os.environ.get("SHIELD", "") + shields_override = os.environ.get("SHIELDS", "") + + override_requested = shield_origin != "undefined" or shields_origin != "undefined" + + if override_requested: + shields = split_shields(shield_override) + split_shields(shields_override) + else: + shields = board_tools.get_shields(mpconfigboard) + + shields = dedupe(shields) + + west_shield_args = [] + for shield in shields: + west_shield_args.extend(("--shield", shield)) + + print(shlex.join(west_shield_args)) + + +if __name__ == "__main__": + main() diff --git a/ports/zephyr-cp/cptools/pre_zephyr_build_prep.py b/ports/zephyr-cp/cptools/pre_zephyr_build_prep.py index 0ed280cbc67..f42fc1a3a85 100644 --- a/ports/zephyr-cp/cptools/pre_zephyr_build_prep.py +++ b/ports/zephyr-cp/cptools/pre_zephyr_build_prep.py @@ -2,7 +2,6 @@ import pathlib import subprocess import sys -import tomllib import board_tools @@ -10,14 +9,20 @@ board = sys.argv[-1] -mpconfigboard = board_tools.find_mpconfigboard(portdir, board) -if mpconfigboard is None: +_, mpconfigboard = board_tools.load_mpconfigboard(portdir, board) +if not mpconfigboard: # Assume it doesn't need any prep. sys.exit(0) -with mpconfigboard.open("rb") as f: - mpconfigboard = tomllib.load(f) - blobs = mpconfigboard.get("BLOBS", []) +blob_fetch_args = mpconfigboard.get("blob_fetch_args", {}) for blob in blobs: - subprocess.run(["west", "blobs", "fetch", blob], check=True) + args = blob_fetch_args.get(blob, []) + subprocess.run(["west", "blobs", "fetch", blob, *args], check=True) + +if board.endswith("bsim"): + subprocess.run( + ["make", "everything", "-j", "8"], + cwd=portdir / "tools" / "bsim", + check=True, + ) diff --git a/ports/zephyr-cp/cptools/tests/test_zephyr2cp.py b/ports/zephyr-cp/cptools/tests/test_zephyr2cp.py index 95a07930e98..b147ae0605e 100644 --- a/ports/zephyr-cp/cptools/tests/test_zephyr2cp.py +++ b/ports/zephyr-cp/cptools/tests/test_zephyr2cp.py @@ -313,6 +313,45 @@ def test_memory_region_with_custom_name(self): assert label == "reserved_mem" assert start == "__CUSTOM_REGION_end" + def test_memory_region_requires_sram_or_device_type(self): + """Test memory regions require mmio-sram compatibility or device_type=memory.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 0x40000>; + }; + + reserved_mem: memory@30000000 { + compatible = "zephyr,memory-region"; + reg = <0x30000000 0x10000>; + zephyr,memory-region = "CUSTOM_REGION"; + }; + + external_mem: memory@40000000 { + compatible = "zephyr,memory-region"; + device_type = "memory"; + reg = <0x40000000 0x20000>; + zephyr,memory-region = "EXT_REGION"; + }; + + chosen { + zephyr,sram = &sram0; + }; +}; +""" + dt = parse_dts_string(dts) + result = find_ram_regions(dt) + + assert len(result) == 2 + assert result[0][0] == "sram0" + assert result[1][0] == "external_mem" + def test_disabled_ram_excluded(self): """Test that disabled RAM regions are excluded.""" dts = """ diff --git a/ports/zephyr-cp/cptools/zephyr2cp.py b/ports/zephyr-cp/cptools/zephyr2cp.py index 0f09c21e83f..a9b5ecf6e1d 100644 --- a/ports/zephyr-cp/cptools/zephyr2cp.py +++ b/ports/zephyr-cp/cptools/zephyr2cp.py @@ -20,7 +20,10 @@ "nordic_nrf_uarte": "serial", "nordic_nrf_uart": "serial", "nordic_nrf_twim": "i2c", + "nordic_nrf_twi": "i2c", "nordic_nrf_spim": "spi", + "nordic_nrf_spi": "spi", + "nordic_nrf_i2s": "i2s", } # These are controllers, not the flash devices themselves. @@ -32,6 +35,8 @@ BUSIO_CLASSES = {"serial": "UART", "i2c": "I2C", "spi": "SPI"} +AUDIOBUSIO_CLASSES = {"i2s": "I2SOut"} + CONNECTORS = { "mikro-bus": [ "AN", @@ -94,6 +99,19 @@ "D12", "D13", ], + "nordic,expansion-board-header": [ + "P1_04", + "P1_05", + "P1_06", + "P1_07", + "P1_08", + "P1_09", + "P1_10", + "P1_11", + "P1_12", + "P1_13", + "P1_14", + ], "arducam,dvp-20pin-connector": [ "SCL", "SDA", @@ -143,6 +161,16 @@ "LCD_D14", "LCD_D15", ], + "nxp,lcd-pmod": [ + "LCD_WR", + "TOUCH_SCL", + "LCD_DC", + "TOUCH_SDA", + "LCD_MOSI", + "TOUCH_RESET", + "LCD_CS", + "TOUCH_INT", + ], "raspberrypi,csi-connector": [ "CSI_D0_N", "CSI_D0_P", @@ -220,6 +248,34 @@ "D1", "D0", ], + "raspberrypi,pico-header": [ + "GP0", + "GP1", + "GP2", + "GP3", + "GP4", + "GP5", + "GP6", + "GP7", + "GP8", + "GP9", + "GP10", + "GP11", + "GP12", + "GP13", + "GP14", + "GP15", + "GP16", + "GP17", + "GP18", + "GP19", + "GP20", + "GP21", + "GP22", + ["GP26_A0", "GP26", "A0"], + ["GP27_A1", "GP27", "A1"], + ["GP28_A2", "GP28", "A2"], + ], } EXCEPTIONAL_DRIVERS = ["entropy", "gpio", "led"] @@ -294,6 +350,25 @@ def find_flash_devices(device_tree): ) continue + # Skip soc-nv-flash nodes whose parent is itself a flash device — the + # parent is the real Zephyr device (e.g. nxp,imx-flexspi-nor) and the + # child has no driver-instantiated symbol. + if "soc-nv-flash" in compatible and node.parent is not None: + parent_compat = [] + if "compatible" in node.parent.props: + parent_compat = node.parent.props["compatible"].to_strings() + parent_drivers = [] + for c in parent_compat: + underscored = c.replace(",", "_").replace("-", "_") + d = COMPAT_TO_DRIVER.get(underscored) or MANUAL_COMPAT_TO_DRIVER.get(underscored) + if d: + parent_drivers.append(d) + if "flash" in parent_drivers: + logger.debug( + f" skipping flash {node.labels[0] if node.labels else node.name} (parent is flash device)" + ) + continue + if node.labels: flashes.append(node.labels[0]) @@ -354,6 +429,12 @@ def find_ram_regions(device_tree): if "zephyr,memory-region" not in compatible or "zephyr,memory-region" not in node.props: continue + is_mmio_sram = "mmio-sram" in compatible + device_type = node.props.get("device_type") + has_memory_device_type = device_type and device_type.to_string() == "memory" + if not (is_mmio_sram or has_memory_device_type): + continue + size = node.props["reg"].to_nums()[1] start = "__" + node.props["zephyr,memory-region"].to_string() + "_end" @@ -371,15 +452,35 @@ def find_ram_regions(device_tree): @cpbuild.run_in_thread -def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa: C901 +def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir, mpconfigboard=None): # noqa: C901 board_dir = builddir / "board" # Auto generate board files from device tree. board_info = { "wifi": False, "usb_device": False, + "_bleio": False, + "hostnetwork": board_id in ["native_sim"], + "audiobusio": False, } + config_bt_enabled = False + config_bt_found = False + config_present = True + config = zephyrbuilddir / ".config" + if not config.exists(): + config_present = False + else: + for line in config.read_text().splitlines(): + if line.startswith("CONFIG_BT="): + config_bt_enabled = line.strip().endswith("=y") + config_bt_found = True + break + if line.startswith("# CONFIG_BT is not set"): + config_bt_enabled = False + config_bt_found = True + break + runners = zephyrbuilddir / "runners.yaml" runners = yaml.safe_load(runners.read_text()) zephyr_board_dir = pathlib.Path(runners["config"]["board_dir"]) @@ -404,6 +505,8 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa soc_name = board_yaml["socs"][0]["name"] board_info["soc"] = soc_name board_name = board_yaml["full_name"] + if mpconfigboard and "NAME" in mpconfigboard: + board_name = mpconfigboard["NAME"] board_info["name"] = board_name # board_id_yaml = zephyr_board_dir / (zephyr_board_dir.name + ".yaml") # board_id_yaml = yaml.safe_load(board_id_yaml.read_text()) @@ -433,10 +536,19 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa # Store active Zephyr device labels per-driver so that we can make them available via board. active_zephyr_devices = {} usb_num_endpoint_pairs = 0 + ble_hardware_present = False for k in device_tree.root.nodes["chosen"].props: value = device_tree.root.nodes["chosen"].props[k] path2chosen[value.to_path()] = k chosen2path[k] = value.to_path() + + chosen_display = chosen2path.get("zephyr,display") + if chosen_display is not None: + status = chosen_display.props.get("status", None) + if status is None or status.to_string() == "okay": + board_info["zephyr_display"] = True + board_info["displayio"] = True + remaining_nodes = set([device_tree.root]) while remaining_nodes: node = remaining_nodes.pop() @@ -484,6 +596,15 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa usb_num_endpoint_pairs += min(single_direction_endpoints) elif driver.startswith("wifi"): board_info["wifi"] = True + elif driver == "bluetooth/hci": + ble_hardware_present = True + elif driver in AUDIOBUSIO_CLASSES: + # audiobusio driver (i2s, audio/dmic) + board_info["audiobusio"] = True + logger.info(f"Supported audiobusio driver: {driver}") + if driver not in active_zephyr_devices: + active_zephyr_devices[driver] = [] + active_zephyr_devices[driver].append(node.labels) elif driver in EXCEPTIONAL_DRIVERS: pass elif driver in BUSIO_CLASSES: @@ -504,16 +625,30 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa all_ioports.append(node.labels[0]) if status == "okay": ioports[node.labels[0]] = set(range(0, ngpios)) - if gpio_map and compatible[0] != "gpio-nexus": - i = 0 - for offset, t, label in gpio_map._markers: - if not label: - continue - num = int.from_bytes(gpio_map.value[offset + 4 : offset + 8], "big") - if (label, num) not in board_names: - board_names[(label, num)] = [] - board_names[(label, num)].append(CONNECTORS[compatible[0]][i]) - i += 1 + if gpio_map and compatible and compatible[0] != "gpio-nexus": + connector_pins = CONNECTORS.get(compatible[0], None) + if connector_pins is None: + logger.warning(f"Unsupported connector mapping compatible: {compatible[0]}") + else: + i = 0 + for offset, t, label in gpio_map._markers: + if not label: + continue + if i >= len(connector_pins): + logger.warning( + f"Connector mapping for {compatible[0]} has more pins than names; " + f"stopping at {len(connector_pins)}" + ) + break + num = int.from_bytes(gpio_map.value[offset + 4 : offset + 8], "big") + if (label, num) not in board_names: + board_names[(label, num)] = [] + pin_entry = connector_pins[i] + if isinstance(pin_entry, list): + board_names[(label, num)].extend(pin_entry) + else: + board_names[(label, num)].append(pin_entry) + i += 1 if "gpio-leds" in compatible: for led in node.nodes: led = node.nodes[led] @@ -551,15 +686,18 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa if len(all_ioports) > 1: a, b = all_ioports[:2] i = 0 - while a[i] == b[i]: + max_i = min(len(a), len(b)) + while i < max_i and a[i] == b[i]: i += 1 shared_prefix = a[:i] for ioport in ioports: if not ioport.startswith(shared_prefix): shared_prefix = "" break - else: + elif all_ioports: shared_prefix = all_ioports[0] + else: + shared_prefix = "" pin_defs = [] pin_declarations = ["#pragma once"] @@ -580,7 +718,13 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa board_pin_names = board_names.get((ioport, num), []) for board_pin_name in board_pin_names: - board_pin_name = board_pin_name.upper().replace(" ", "_").replace("-", "_") + board_pin_name = ( + board_pin_name.upper() + .replace(" ", "_") + .replace("-", "_") + .replace("(", "") + .replace(")", "") + ) board_pin_mapping.append( f"{{ MP_ROM_QSTR(MP_QSTR_{board_pin_name}), MP_ROM_PTR(&pin_{pin_object_name}) }}," ) @@ -593,15 +737,25 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa zephyr_binding_headers = [] zephyr_binding_objects = [] zephyr_binding_labels = [] + i2sout_instance_names = [] for driver, instances in active_zephyr_devices.items(): - driverclass = BUSIO_CLASSES[driver] - zephyr_binding_headers.append(f'#include "shared-bindings/busio/{driverclass}.h"') + # Determine if this is busio or audiobusio + if driver in BUSIO_CLASSES: + module = "busio" + driverclass = BUSIO_CLASSES[driver] + elif driver in AUDIOBUSIO_CLASSES: + module = "audiobusio" + driverclass = AUDIOBUSIO_CLASSES[driver] + else: + continue + + zephyr_binding_headers.append(f'#include "shared-bindings/{module}/{driverclass}.h"') - # Designate a main bus such as board.I2C. + # Designate a main device such as board.I2C or board.I2S. if len(instances) == 1: instances[0].append(driverclass) else: - # Check to see if a main bus has already been designated + # Check to see if a main device has already been designated found_main = False for labels in instances: for label in labels: @@ -617,23 +771,28 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa if found_main: break for labels in instances: - instance_name = f"{driver}_{labels[0]}" + instance_name = f"{driver.replace('/', '_')}_{labels[0]}" c_function_name = f"_{instance_name}" singleton_ptr = f"{c_function_name}_singleton" function_object = f"{c_function_name}_obj" - busio_type = f"busio_{driverclass.lower()}" + obj_type = f"{module}_{driverclass.lower()}" - # UART needs a receiver buffer + # Handle special cases for different drivers if driver == "serial": + # UART needs a receiver buffer buffer_decl = f"static byte {instance_name}_buffer[128];" construct_call = f"common_hal_busio_uart_construct_from_device(&{instance_name}_obj, DEVICE_DT_GET(DT_NODELABEL({labels[0]})), 128, {instance_name}_buffer)" else: + # Default case (I2C, SPI, I2S) buffer_decl = "" - construct_call = f"common_hal_busio_{driverclass.lower()}_construct_from_device(&{instance_name}_obj, DEVICE_DT_GET(DT_NODELABEL({labels[0]})))" + construct_call = f"common_hal_{module}_{driverclass.lower()}_construct_from_device(&{instance_name}_obj, DEVICE_DT_GET(DT_NODELABEL({labels[0]})))" + + if driver == "i2s": + i2sout_instance_names.append(instance_name) zephyr_binding_objects.append( f"""{buffer_decl} -static {busio_type}_obj_t {instance_name}_obj; +static {obj_type}_obj_t {instance_name}_obj; static mp_obj_t {singleton_ptr} = mp_const_none; static mp_obj_t {c_function_name}(void) {{ if ({singleton_ptr} != mp_const_none) {{ @@ -652,6 +811,55 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa zephyr_binding_objects = "\n".join(zephyr_binding_objects) zephyr_binding_labels = "\n".join(zephyr_binding_labels) + # Generate i2sout_reset() that stops all board I2SOut instances + if i2sout_instance_names: + stop_calls = "\n ".join( + f"common_hal_audiobusio_i2sout_stop(&{name}_obj);" for name in i2sout_instance_names + ) + i2sout_reset_func = f""" +void i2sout_reset(void) {{ + {stop_calls} +}}""" + else: + i2sout_reset_func = "" + + zephyr_display_header = "" + zephyr_display_object = "" + zephyr_display_board_entry = "" + if board_info.get("zephyr_display", False): + zephyr_display_header = """ +#include +#include +#include "shared-module/displayio/__init__.h" +#include "bindings/zephyr_display/Display.h" + """.strip() + zephyr_display_object = """ +void board_init(void) { +#if CIRCUITPY_ZEPHYR_DISPLAY && DT_HAS_CHOSEN(zephyr_display) + // Always allocate a display slot so board.DISPLAY is at least a valid + // NoneType object even if the underlying Zephyr display is unavailable. + primary_display_t *display_obj = allocate_display(); + if (display_obj == NULL) { + return; + } + + zephyr_display_display_obj_t *display = &display_obj->zephyr_display; + display->base.type = &mp_type_NoneType; + + const struct device *display_dev = device_get_binding(DEVICE_DT_NAME(DT_CHOSEN(zephyr_display))); + if (display_dev == NULL || !device_is_ready(display_dev)) { + return; + } + + display->base.type = &zephyr_display_display_type; + common_hal_zephyr_display_display_construct_from_device(display, display_dev, 0, true); +#endif +} + """.strip() + zephyr_display_board_entry = ( + "{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].zephyr_display) }," + ) + board_dir.mkdir(exist_ok=True, parents=True) header = board_dir / "mpconfigboard.h" if status_led: @@ -669,7 +877,8 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa device, start, end, size, path = ram max_size = max(max_size, size) # We always start at the end of a Zephyr linker section so we need the externs and &. - if board_id in ["native_sim"]: + # Native/simulated boards don't have real memory-mapped RAM, so we allocate static arrays. + if board_id in ["native_sim"] or "bsim" in board_id: ram_externs.append("// This is a native board so we provide all of RAM for our heaps.") ram_externs.append(f"static uint32_t _{device}[{size // 4}]; // {path}") start = f"(const uint32_t *) (_{device})" @@ -699,17 +908,32 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa pins.write_text(pin_declarations) board_c = board_dir / "board.c" + hostnetwork_include = "" + hostnetwork_entry = "" + if board_info.get("hostnetwork", False): + hostnetwork_include = ( + '#if CIRCUITPY_HOSTNETWORK\n#include "bindings/hostnetwork/__init__.h"\n#endif\n' + ) + hostnetwork_entry = ( + "#if CIRCUITPY_HOSTNETWORK\n" + " { MP_ROM_QSTR(MP_QSTR_NETWORK), MP_ROM_PTR(&common_hal_hostnetwork_obj) },\n" + "#endif\n" + ) + new_board_c_content = f""" // This file is autogenerated by build_circuitpython.py #include "shared-bindings/board/__init__.h" +{hostnetwork_include} + #include #include "py/obj.h" #include "py/mphal.h" {zephyr_binding_headers} +{zephyr_display_header} const struct device* const flashes[] = {{ {", ".join(flashes)} }}; const int circuitpy_flash_device_count = {len(flashes)}; @@ -723,6 +947,8 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa {pin_defs} {zephyr_binding_objects} +{zephyr_display_object} +{i2sout_reset_func} static const mp_rom_map_elem_t mcu_pin_globals_table[] = {{ {mcu_pin_mapping} @@ -732,6 +958,8 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa static const mp_rom_map_elem_t board_module_globals_table[] = {{ CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS +{hostnetwork_entry} +{zephyr_display_board_entry} {board_pin_mapping} {zephyr_binding_labels} @@ -741,8 +969,25 @@ def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir): # noqa MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); """ board_c.write_text(new_board_c_content) + if ble_hardware_present: + if not config_present: + raise RuntimeError( + "Missing Zephyr .config; CONFIG_BT must be set explicitly when BLE hardware is present." + ) + if not config_bt_found: + raise RuntimeError( + "CONFIG_BT is missing from Zephyr .config; set it explicitly when BLE hardware is present." + ) + + board_info["_bleio"] = ble_hardware_present and config_bt_enabled board_info["source_files"] = [board_c] board_info["cflags"] = ("-I", board_dir) board_info["flash_count"] = len(flashes) + board_info["rotaryio"] = bool(ioports) board_info["usb_num_endpoint_pairs"] = usb_num_endpoint_pairs + + # Detect NVM partition from the device tree. + nvm_node = device_tree.label2node.get("nvm_partition") + board_info["nvm"] = nvm_node is not None + return board_info diff --git a/ports/zephyr-cp/debug.conf b/ports/zephyr-cp/debug.conf new file mode 100644 index 00000000000..90c1f52d4db --- /dev/null +++ b/ports/zephyr-cp/debug.conf @@ -0,0 +1,15 @@ +CONFIG_DEBUG=y +CONFIG_DEBUG_OPTIMIZATIONS=y +CONFIG_LOG_MAX_LEVEL=4 + +CONFIG_STACK_SENTINEL=y +CONFIG_DEBUG_THREAD_INFO=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y + +CONFIG_ASSERT=y +CONFIG_LOG_BLOCK_IN_THREAD=y +CONFIG_FRAME_POINTER=y + +CONFIG_FLASH_LOG_LEVEL_DBG=y +CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/ports/zephyr-cp/mpconfigport.h b/ports/zephyr-cp/mpconfigport.h index 491b5293e2e..9e7bc62c0fe 100644 --- a/ports/zephyr-cp/mpconfigport.h +++ b/ports/zephyr-cp/mpconfigport.h @@ -17,9 +17,14 @@ #define CIRCUITPY_DEBUG_TINYUSB 0 +// NVM size is determined at runtime from the Zephyr partition table. +#define CIRCUITPY_INTERNAL_NVM_SIZE 1 + // Disable native _Float16 handling for host builds. #define MICROPY_FLOAT_USE_NATIVE_FLT16 (0) +#define MICROPY_NLR_THUMB_USE_LONG_JUMP (1) + //////////////////////////////////////////////////////////////////////////////////////////////////// // This also includes mpconfigboard.h. diff --git a/ports/zephyr-cp/native_sim_build_Containerfile b/ports/zephyr-cp/native_sim_build_Containerfile new file mode 100644 index 00000000000..3cd1a677da3 --- /dev/null +++ b/ports/zephyr-cp/native_sim_build_Containerfile @@ -0,0 +1,40 @@ +FROM ubuntu:24.04 +ENV DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC +ENV PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig + +RUN dpkg --add-architecture i386 && apt-get update && apt-get install -y --no-install-recommends \ + git cmake ninja-build gperf ccache dfu-util device-tree-compiler \ + wget python3 python3-dev python3-pip python3-venv python3-setuptools \ + python3-tk python3-wheel xz-utils file make gcc \ + gcc-multilib g++-multilib libc6-dev-i386 \ + libsdl2-dev:i386 libsdl2-image-dev:i386 \ + libmagic1 mtools pkg-config ca-certificates unzip \ + protobuf-compiler sudo \ + && rm -rf /var/lib/apt/lists/* + +# Remove the default ubuntu:24.04 'ubuntu' user (UID 1000) so 'dev' can take +# UID 1000 — required for --userns=keep-id to map host UID 1000 to 'dev'. +RUN userdel -r ubuntu 2>/dev/null || true \ + && useradd -m -u 1000 -s /bin/bash dev \ + && echo 'dev ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/dev \ + && chmod 440 /etc/sudoers.d/dev +USER dev +WORKDIR /home/dev + +RUN python3 -m venv /home/dev/.venv +ENV PATH="/home/dev/.venv/bin:${PATH}" +RUN pip install --no-cache-dir west pytest pyelftools pyyaml intelhex protobuf grpcio-tools + +# The repo is expected to be bind-mounted here at runtime: +# podman run -v ~/circuitpython:/home/dev/circuitpython:Z --userns=keep-id ... +# On first run, inside the container do: +# cd ~/circuitpython/ports/zephyr-cp +# west init -l zephyr-config +# west update +# west zephyr-export +# pip install -r zephyr/scripts/requirements.txt +# pip install -r ../../requirements-dev.txt +# west sdk install -t x86_64-zephyr-elf +# python ../../tools/ci_fetch_deps.py zephyr-cp +WORKDIR /home/dev/circuitpython/ports/zephyr-cp +CMD ["/bin/bash"] diff --git a/ports/zephyr-cp/native_sim_build_init_container.sh b/ports/zephyr-cp/native_sim_build_init_container.sh new file mode 100755 index 00000000000..19831e1fcc2 --- /dev/null +++ b/ports/zephyr-cp/native_sim_build_init_container.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# One-time setup to run INSIDE the zephyr-cp-dev container on the first +# launch against a fresh bind-mounted circuitpython checkout. +# +# Usage (inside the container): +# cd ~/circuitpython/ports/zephyr-cp +# ./native_sim_build_init_container.sh +# +# Safe to re-run; west/pip/etc. are idempotent. +set -euo pipefail + +git config --global --add safe.directory /home/dev/circuitpython + +cd "$(dirname "${BASH_SOURCE[0]}")" + +echo "==> west init" +if [ ! -d .west ]; then + west init -l zephyr-config +else + echo " (already initialized, skipping)" +fi + +echo "==> west update" +west update + +echo "==> west zephyr-export" +west zephyr-export + +echo "==> pip install Zephyr requirements" +pip install -r zephyr/scripts/requirements.txt + +echo "==> pip install CircuitPython dev requirements" +pip install -r ../../requirements-dev.txt + +echo "==> west sdk install (x86_64-zephyr-elf)" +west sdk install -t x86_64-zephyr-elf + +echo "==> fetch port submodules" +python ../../tools/ci_fetch_deps.py zephyr-cp + +echo +echo "First-run setup complete." +echo "You can now build with: make BOARD=native_native_sim" diff --git a/ports/zephyr-cp/native_sim_build_run_container.sh b/ports/zephyr-cp/native_sim_build_run_container.sh new file mode 100755 index 00000000000..e30aca22b46 --- /dev/null +++ b/ports/zephyr-cp/native_sim_build_run_container.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Launch (or re-attach to) the zephyr-cp-dev container with the enclosing +# circuitpython checkout bind-mounted at /home/dev/circuitpython. Works from +# any CWD — the mount is resolved relative to this script's location. +# +# On first invocation, creates a persistent container named "zcp". On +# subsequent invocations, re-starts the same container so installed state +# (e.g. the Zephyr SDK under /home/dev/zephyr-sdk-*) survives across sessions. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +CONTAINER_NAME="zcp" +IMAGE="zephyr-cp-dev" + +if podman container exists "$CONTAINER_NAME"; then + exec podman start -ai "$CONTAINER_NAME" +else + exec podman run -it --name "$CONTAINER_NAME" \ + -v "$REPO_ROOT:/home/dev/circuitpython:Z" \ + --userns=keep-id \ + "$IMAGE" "$@" +fi diff --git a/ports/zephyr-cp/prj.conf b/ports/zephyr-cp/prj.conf index 485559fe480..765132742bb 100644 --- a/ports/zephyr-cp/prj.conf +++ b/ports/zephyr-cp/prj.conf @@ -1,24 +1,22 @@ -CONFIG_SYS_HEAP_RUNTIME_STATS=y +CONFIG_SYS_HEAP_RUNTIME_STATS=n CONFIG_FLASH=y CONFIG_FLASH_MAP=y -CONFIG_STD_C23=y CONFIG_DYNAMIC_INTERRUPTS=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_FLASH_MAP_LABELS=y CONFIG_MAIN_STACK_SIZE=24288 -CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 -CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_THREAD_STACK_INFO=y -CONFIG_STACK_SENTINEL=y -CONFIG_DEBUG_THREAD_INFO=y -# CONFIG_DEBUG_INFO=y +CONFIG_ARCH_POSIX_UPDATE_STACK_INFO=y +CONFIG_STACK_SENTINEL=n +CONFIG_DEBUG_THREAD_INFO=n +CONFIG_EXCEPTION_STACK_TRACE=n CONFIG_USB_DEVICE_STACK_NEXT=y CONFIG_USBD_CDC_ACM_CLASS=y -CONFIG_USBD_MAX_SPEED=1 +CONFIG_USBD_MSC_STACK_SIZE=1536 CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=n CONFIG_USBD_MSC_CLASS=y @@ -28,8 +26,8 @@ CONFIG_HWINFO=y CONFIG_REBOOT=y CONFIG_ENTROPY_GENERATOR=y -CONFIG_ASSERT=y -CONFIG_LOG_BLOCK_IN_THREAD=y +CONFIG_ASSERT=n +CONFIG_LOG_BLOCK_IN_THREAD=n CONFIG_EVENTS=y @@ -39,3 +37,22 @@ CONFIG_UART_LINE_CTRL=y CONFIG_I2C=y CONFIG_SPI=y CONFIG_SPI_ASYNC=y + +CONFIG_LOG=y +CONFIG_LOG_MAX_LEVEL=2 +CONFIG_FRAME_POINTER=n + +CONFIG_NET_HOSTNAME_ENABLE=y +CONFIG_NET_HOSTNAME_DYNAMIC=y +CONFIG_NET_HOSTNAME="circuitpython" + +CONFIG_I2S=y +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_ALLOC=y +CONFIG_DYNAMIC_THREAD_PREFER_ALLOC=y + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_WANT_ALG_SHA_1=y +CONFIG_PSA_WANT_ALG_SHA_256=y diff --git a/ports/zephyr-cp/socs/nrf5340_cpuapp.conf b/ports/zephyr-cp/socs/nrf5340_cpuapp.conf index bf70997d83f..734d26db8e9 100644 --- a/ports/zephyr-cp/socs/nrf5340_cpuapp.conf +++ b/ports/zephyr-cp/socs/nrf5340_cpuapp.conf @@ -1,4 +1,3 @@ -CONFIG_NRFX_UARTE0=y -CONFIG_NRFX_UARTE1=y +CONFIG_NRFX_UARTE=y CONFIG_NRFX_POWER=y diff --git a/ports/zephyr-cp/socs/stm32h7b3xx.conf b/ports/zephyr-cp/socs/stm32h7b3xx.conf index 3c7daeb753d..14a93b52ce8 100644 --- a/ports/zephyr-cp/socs/stm32h7b3xx.conf +++ b/ports/zephyr-cp/socs/stm32h7b3xx.conf @@ -1,4 +1 @@ -CONFIG_USE_STM32_LL_USB=y -CONFIG_USE_STM32_HAL_PCD=y - CONFIG_MEMC=y diff --git a/ports/zephyr-cp/socs/stm32u575xx.conf b/ports/zephyr-cp/socs/stm32u575xx.conf index 78cefbfef40..e69de29bb2d 100644 --- a/ports/zephyr-cp/socs/stm32u575xx.conf +++ b/ports/zephyr-cp/socs/stm32u575xx.conf @@ -1,2 +0,0 @@ -CONFIG_USE_STM32_LL_USB=y -CONFIG_USE_STM32_HAL_PCD=y diff --git a/ports/zephyr-cp/supervisor/flash.c b/ports/zephyr-cp/supervisor/flash.c index 38f35a5235a..a13bb3cffcb 100644 --- a/ports/zephyr-cp/supervisor/flash.c +++ b/ports/zephyr-cp/supervisor/flash.c @@ -31,15 +31,14 @@ static struct flash_area _dynamic_area; extern const struct device *const flashes[]; extern const int circuitpy_flash_device_count; -// Size of an erase area +// Size of an erase page. static size_t _page_size; -// Size of a write area -static size_t _row_size; +// The value a flash byte has after being erased (usually 0xFF, but can differ). +static uint8_t _erase_value; -// Number of file system blocks in a page. +// Number of FILESYSTEM_BLOCK_SIZE blocks in an erase page. static size_t _blocks_per_page; -static size_t _rows_per_block; static uint32_t _page_mask; #define NO_PAGE_LOADED 0xFFFFFFFF @@ -49,14 +48,41 @@ static uint32_t _current_page_address; static uint32_t _scratch_page_address; -// Track which blocks (up to 32) in the current sector currently live in the -// cache. -static uint32_t _dirty_mask; -static uint32_t _loaded_mask; +// Per-block flags packed into a uint8_t array (one byte per block). +#define ROW_LOADED 0x01 // Block data is present in the cache. +#define ROW_DIRTY 0x02 // Block has been modified since last flush. +#define ROW_ERASED 0x04 // Block is all 0xFF; no need to write after erase. + +static uint8_t *_row_flags = NULL; + +static inline void _clear_row_flags(void) { + if (_row_flags != NULL) { + memset(_row_flags, 0, _blocks_per_page); + } +} + +static inline bool _any_dirty(void) { + for (size_t i = 0; i < _blocks_per_page; i++) { + if (_row_flags[i] & ROW_DIRTY) { + return true; + } + } + return false; +} + +// Check if a buffer is entirely the erase value. +static bool _buffer_is_erased(const uint8_t *buf, size_t len) { + for (size_t i = 0; i < len; i++) { + if (buf[i] != _erase_value) { + return false; + } + } + return true; +} // Table of pointers to each cached block. Should be zero'd after allocation. -#define FLASH_CACHE_TABLE_NUM_ENTRIES (_blocks_per_page * _rows_per_block) -#define FLASH_CACHE_TABLE_SIZE (FLASH_CACHE_TABLE_NUM_ENTRIES * sizeof (uint8_t *)) +#define FLASH_CACHE_TABLE_NUM_ENTRIES (_blocks_per_page) +#define FLASH_CACHE_TABLE_SIZE (FLASH_CACHE_TABLE_NUM_ENTRIES * sizeof(uint8_t *)) static uint8_t **flash_cache_table = NULL; static K_MUTEX_DEFINE(_mutex); @@ -171,52 +197,44 @@ void supervisor_flash_init(void) { return; } - const struct device *d = flash_area_get_device(filesystem_area); - _row_size = flash_get_write_block_size(d); - if (_row_size < 256) { - if (256 % _row_size == 0) { - _row_size = 256; - } else { - size_t new_row_size = _row_size; - while (new_row_size < 256) { - new_row_size += _row_size; - } - _row_size = new_row_size; - } - } struct flash_pages_info first_info; + const struct device *d = flash_area_get_device(filesystem_area); + const struct flash_parameters *fp = flash_get_parameters(d); + _erase_value = fp->erase_value; flash_get_page_info_by_offs(d, filesystem_area->fa_off, &first_info); struct flash_pages_info last_info; - flash_get_page_info_by_offs(d, filesystem_area->fa_off + filesystem_area->fa_size - _row_size, &last_info); + flash_get_page_info_by_offs(d, filesystem_area->fa_off + filesystem_area->fa_size - FILESYSTEM_BLOCK_SIZE, &last_info); _page_size = first_info.size; if (_page_size < FILESYSTEM_BLOCK_SIZE) { _page_size = FILESYSTEM_BLOCK_SIZE; } - printk(" erase page size %d\n", _page_size); - // Makes sure that a cached page has 32 or fewer rows. Our dirty mask is - // only 32 bits. - while (_page_size / _row_size > 32) { - _row_size *= 2; - } - printk(" write row size %d\n", _row_size); _blocks_per_page = _page_size / FILESYSTEM_BLOCK_SIZE; - printk(" blocks per page %d\n", _blocks_per_page); - _rows_per_block = FILESYSTEM_BLOCK_SIZE / _row_size; _page_mask = ~(_page_size - 1); + printk(" erase page size %d\n", _page_size); + printk(" blocks per page %d\n", _blocks_per_page); + + _row_flags = port_malloc(_blocks_per_page, false); + if (_row_flags == NULL) { + printk("Unable to allocate row flags (%d bytes)\n", _blocks_per_page); + filesystem_area = NULL; + return; + } + memset(_row_flags, 0, _blocks_per_page); + // The last page is the scratch sector. - _scratch_page_address = last_info.start_offset; + _scratch_page_address = last_info.start_offset - filesystem_area->fa_off; _current_page_address = NO_PAGE_LOADED; } uint32_t supervisor_flash_get_block_size(void) { - return 512; + return FILESYSTEM_BLOCK_SIZE; } uint32_t supervisor_flash_get_block_count(void) { if (filesystem_area == NULL) { return 0; } - return (_scratch_page_address - filesystem_area->fa_off) / 512; + return _scratch_page_address / FILESYSTEM_BLOCK_SIZE; } @@ -245,10 +263,8 @@ static bool write_flash(uint32_t address, const uint8_t *data, uint32_t data_len static bool block_erased(uint32_t sector_address) { uint8_t short_buffer[4]; if (read_flash(sector_address, short_buffer, 4)) { - for (uint16_t i = 0; i < 4; i++) { - if (short_buffer[i] != 0xff) { - return false; - } + if (!_buffer_is_erased(short_buffer, 4)) { + return false; } } else { return false; @@ -257,10 +273,8 @@ static bool block_erased(uint32_t sector_address) { // Now check the full length. uint8_t full_buffer[FILESYSTEM_BLOCK_SIZE]; if (read_flash(sector_address, full_buffer, FILESYSTEM_BLOCK_SIZE)) { - for (uint16_t i = 0; i < FILESYSTEM_BLOCK_SIZE; i++) { - if (short_buffer[i] != 0xff) { - return false; - } + if (!_buffer_is_erased(full_buffer, FILESYSTEM_BLOCK_SIZE)) { + return false; } } else { return false; @@ -278,17 +292,26 @@ static bool erase_page(uint32_t sector_address) { return res == 0; } -// Sector is really 24 bits. static bool copy_block(uint32_t src_address, uint32_t dest_address) { - // Copy row by row to minimize RAM buffer. - uint8_t buffer[_row_size]; - for (uint32_t i = 0; i < FILESYSTEM_BLOCK_SIZE / _row_size; i++) { - if (!read_flash(src_address + i * _row_size, buffer, _row_size)) { - return false; - } - if (!write_flash(dest_address + i * _row_size, buffer, _row_size)) { - return false; - } + uint8_t buffer[FILESYSTEM_BLOCK_SIZE]; + if (!read_flash(src_address, buffer, FILESYSTEM_BLOCK_SIZE)) { + return false; + } + if (!write_flash(dest_address, buffer, FILESYSTEM_BLOCK_SIZE)) { + return false; + } + return true; +} + +// Load a block into the ram cache and set its flags. Returns false on read error. +static bool _load_block_into_cache(size_t block_index) { + if (!read_flash(_current_page_address + block_index * FILESYSTEM_BLOCK_SIZE, + flash_cache_table[block_index], FILESYSTEM_BLOCK_SIZE)) { + return false; + } + _row_flags[block_index] |= ROW_LOADED; + if (_buffer_is_erased(flash_cache_table[block_index], FILESYSTEM_BLOCK_SIZE)) { + _row_flags[block_index] |= ROW_ERASED; } return true; } @@ -303,12 +326,12 @@ static bool flush_scratch_flash(void) { // cached. bool copy_to_scratch_ok = true; for (size_t i = 0; i < _blocks_per_page; i++) { - if ((_dirty_mask & (1 << i)) == 0) { + if (!(_row_flags[i] & ROW_DIRTY)) { copy_to_scratch_ok = copy_to_scratch_ok && copy_block(_current_page_address + i * FILESYSTEM_BLOCK_SIZE, _scratch_page_address + i * FILESYSTEM_BLOCK_SIZE); } - _loaded_mask |= (1 << i); + _row_flags[i] |= ROW_LOADED; } if (!copy_to_scratch_ok) { // TODO(tannewt): Do more here. We opted to not erase and copy bad data @@ -341,7 +364,7 @@ static void release_ram_cache(void) { port_free(flash_cache_table); flash_cache_table = NULL; _current_page_address = NO_PAGE_LOADED; - _loaded_mask = 0; + _clear_row_flags(); } // Attempts to allocate a new set of page buffers for caching a full sector in @@ -350,7 +373,7 @@ static void release_ram_cache(void) { static bool allocate_ram_cache(void) { flash_cache_table = port_malloc(FLASH_CACHE_TABLE_SIZE, false); if (flash_cache_table == NULL) { - // Not enough space even for the cache table. + printk("Unable to allocate ram cache table\n"); return false; } @@ -359,21 +382,20 @@ static bool allocate_ram_cache(void) { bool success = true; for (size_t i = 0; i < _blocks_per_page && success; i++) { - for (size_t j = 0; j < _rows_per_block && success; j++) { - uint8_t *page_cache = port_malloc(_row_size, false); - if (page_cache == NULL) { - success = false; - break; - } - flash_cache_table[i * _rows_per_block + j] = page_cache; + uint8_t *block_cache = port_malloc(FILESYSTEM_BLOCK_SIZE, false); + if (block_cache == NULL) { + success = false; + break; } + flash_cache_table[i] = block_cache; } // We couldn't allocate enough so give back what we got. if (!success) { + printk("Unable to allocate ram cache pages\n"); release_ram_cache(); } - _loaded_mask = 0; + _clear_row_flags(); _current_page_address = NO_PAGE_LOADED; return success; } @@ -386,7 +408,7 @@ static bool flush_ram_cache(bool keep_cache) { return true; } - if (_current_page_address == NO_PAGE_LOADED || _dirty_mask == 0) { + if (_current_page_address == NO_PAGE_LOADED || !_any_dirty()) { if (!keep_cache) { release_ram_cache(); } @@ -397,21 +419,12 @@ static bool flush_ram_cache(bool keep_cache) { // erase below. bool copy_to_ram_ok = true; for (size_t i = 0; i < _blocks_per_page; i++) { - if ((_loaded_mask & (1 << i)) == 0) { - for (size_t j = 0; j < _rows_per_block; j++) { - copy_to_ram_ok = read_flash( - _current_page_address + (i * _rows_per_block + j) * _row_size, - flash_cache_table[i * _rows_per_block + j], - _row_size); - if (!copy_to_ram_ok) { - break; - } + if (!(_row_flags[i] & ROW_LOADED)) { + if (!_load_block_into_cache(i)) { + copy_to_ram_ok = false; + break; } } - if (!copy_to_ram_ok) { - break; - } - _loaded_mask |= (1 << i); } if (!copy_to_ram_ok) { @@ -421,14 +434,19 @@ static bool flush_ram_cache(bool keep_cache) { erase_page(_current_page_address); // Lastly, write all the data in ram that we've cached. for (size_t i = 0; i < _blocks_per_page; i++) { - for (size_t j = 0; j < _rows_per_block; j++) { - write_flash(_current_page_address + (i * _rows_per_block + j) * _row_size, - flash_cache_table[i * _rows_per_block + j], - _row_size); + // Skip blocks that are entirely erased — the page erase already + // set them to 0xFF so writing would be redundant. + if (_row_flags[i] & ROW_ERASED) { + continue; } + write_flash(_current_page_address + i * FILESYSTEM_BLOCK_SIZE, + flash_cache_table[i], + FILESYSTEM_BLOCK_SIZE); + } + // Nothing is dirty anymore. Clear dirty but keep loaded and erased. + for (size_t i = 0; i < _blocks_per_page; i++) { + _row_flags[i] &= ~ROW_DIRTY; } - // Nothing is dirty anymore. Some may already be in the cache cleanly. - _dirty_mask = 0; // We're done with the cache for now so give it back. if (!keep_cache) { @@ -491,15 +509,10 @@ static bool _flash_read_block(uint8_t *dest, uint32_t block) { // Mask out the lower bits that designate the address within the sector. uint32_t page_address = address & _page_mask; size_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % _blocks_per_page; - uint32_t mask = 1 << (block_index); // We're reading from the currently cached sector. - if (_current_page_address == page_address && (mask & _loaded_mask) > 0) { + if (_current_page_address == page_address && (_row_flags[block_index] & ROW_LOADED)) { if (flash_cache_table != NULL) { - for (int i = 0; i < _rows_per_block; i++) { - memcpy(dest + i * _row_size, - flash_cache_table[block_index * _rows_per_block + i], - _row_size); - } + memcpy(dest, flash_cache_table[block_index], FILESYSTEM_BLOCK_SIZE); return true; } uint32_t scratch_block_address = _scratch_page_address + block_index * FILESYSTEM_BLOCK_SIZE; @@ -518,7 +531,6 @@ static bool _flash_write_block(const uint8_t *data, uint32_t block) { // Mask out the lower bits that designate the address within the sector. uint32_t page_address = address & _page_mask; size_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % _blocks_per_page; - uint32_t mask = 1 << (block_index); // Flush the cache if we're moving onto a different page. if (_current_page_address != page_address) { // Check to see if we'd write to an erased block and aren't writing to @@ -533,19 +545,12 @@ static bool _flash_write_block(const uint8_t *data, uint32_t block) { erase_page(_scratch_page_address); } _current_page_address = page_address; - _dirty_mask = 0; - _loaded_mask = 0; + _clear_row_flags(); } - _dirty_mask |= mask; - _loaded_mask |= mask; - + _row_flags[block_index] = ROW_DIRTY | ROW_LOADED; // Copy the block to the appropriate cache. if (flash_cache_table != NULL) { - for (int i = 0; i < _rows_per_block; i++) { - memcpy(flash_cache_table[block_index * _rows_per_block + i], - data + i * _row_size, - _row_size); - } + memcpy(flash_cache_table[block_index], data, FILESYSTEM_BLOCK_SIZE); return true; } else { uint32_t scratch_block_address = _scratch_page_address + block_index * FILESYSTEM_BLOCK_SIZE; diff --git a/ports/zephyr-cp/supervisor/port.c b/ports/zephyr-cp/supervisor/port.c index 786e6c2f2f5..1ecde0b0141 100644 --- a/ports/zephyr-cp/supervisor/port.c +++ b/ports/zephyr-cp/supervisor/port.c @@ -9,14 +9,39 @@ #include "mpconfigboard.h" #include "supervisor/shared/tick.h" +#if CIRCUITPY_AUDIOBUSIO_I2SOUT +#include "common-hal/audiobusio/I2SOut.h" +#endif + +#include + #include #include #include +#include + +#if defined(CONFIG_ARCH_POSIX) +#include + +#include "cmdline.h" +#include "posix_board_if.h" +#include "posix_native_task.h" +#endif #include "lib/tlsf/tlsf.h" #include +#include + +#if defined(CONFIG_TRACING_PERFETTO) && defined(CONFIG_BOARD_NATIVE_SIM) +#include "perfetto_encoder.h" +#include +#define CIRCUITPY_PERFETTO_TRACK_GROUP_UUID 0x3000ULL +#define CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID 0x3001ULL +#define CIRCUITPY_PERFETTO_OUTER_HEAP_USED_UUID 0x3002ULL +#endif static tlsf_t heap; +static size_t tlsf_heap_used = 0; // Auto generated in pins.c extern const struct device *const rams[]; @@ -24,17 +49,98 @@ extern const uint32_t *const ram_bounds[]; extern const size_t circuitpy_max_ram_size; static pool_t pools[CIRCUITPY_RAM_DEVICE_COUNT]; +static uint8_t valid_pool_count = 0; +static bool zephyr_malloc_active = false; +static void *zephyr_malloc_top = NULL; +static void *zephyr_malloc_bottom = NULL; static K_EVENT_DEFINE(main_needed); static struct k_timer tick_timer; +#if defined(CONFIG_ARCH_POSIX) +// Number of VM runs before exiting. +// <= 0 means run forever. +// INT32_MAX means option was not provided. +static int32_t native_sim_vm_runs = INT32_MAX; +static uint32_t native_sim_reset_port_count = 0; + +static struct args_struct_t native_sim_reset_port_args[] = { + { + .option = "vm-runs", + .name = "count", + .type = 'i', + .dest = &native_sim_vm_runs, + .descript = "Exit native_sim after this many VM runs. " + "Example: --vm-runs=2" + }, + ARG_TABLE_ENDMARKER +}; + +static void native_sim_register_cmdline_opts(void) { + native_add_command_line_opts(native_sim_reset_port_args); +} + +NATIVE_TASK(native_sim_register_cmdline_opts, PRE_BOOT_1, 0); +#endif + +#if defined(CONFIG_TRACING_PERFETTO) && defined(CONFIG_BOARD_NATIVE_SIM) +static bool perfetto_circuitpython_tracks_emitted; + +static void perfetto_emit_outer_heap_stats(void) { + if (!perfetto_start()) { + return; + } + size_t total = tlsf_heap_used; + #if defined(CONFIG_COMMON_LIBC_MALLOC) && defined(CONFIG_SYS_HEAP_RUNTIME_STATS) + extern int malloc_runtime_stats_get(struct sys_memory_stats *stats); + struct sys_memory_stats stats; + if (malloc_runtime_stats_get(&stats) == 0) { + total += stats.allocated_bytes; + } + #endif + perfetto_emit_counter(CIRCUITPY_PERFETTO_OUTER_HEAP_USED_UUID, (int64_t)total); + Z_SPIN_DELAY(1); +} + +static void perfetto_emit_circuitpython_tracks(void) { + if (perfetto_circuitpython_tracks_emitted) { + return; + } + if (!perfetto_start()) { + return; + } + perfetto_emit_track_descriptor(CIRCUITPY_PERFETTO_TRACK_GROUP_UUID, + perfetto_get_process_uuid(), + "CircuitPython"); + perfetto_emit_counter_track_descriptor(CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID, + CIRCUITPY_PERFETTO_TRACK_GROUP_UUID, + "VM Heap Used", + PERFETTO_COUNTER_UNIT_BYTES); + perfetto_emit_counter_track_descriptor(CIRCUITPY_PERFETTO_OUTER_HEAP_USED_UUID, + CIRCUITPY_PERFETTO_TRACK_GROUP_UUID, + "Outer Heap Used", + PERFETTO_COUNTER_UNIT_BYTES); + perfetto_circuitpython_tracks_emitted = true; +} +#else +static inline void perfetto_emit_outer_heap_stats(void) { +} + +static inline void perfetto_emit_circuitpython_tracks(void) { +} +#endif + static void _tick_function(struct k_timer *timer_id) { supervisor_tick(); } safe_mode_t port_init(void) { + // We run CircuitPython at the lowest priority (just higher than idle.) + // This allows networking and USB to preempt us. + k_thread_priority_set(k_current_get(), CONFIG_NUM_PREEMPT_PRIORITIES - 1); k_timer_init(&tick_timer, _tick_function, NULL); + perfetto_emit_circuitpython_tracks(); return SAFE_MODE_NONE; } @@ -50,7 +156,19 @@ void reset_cpu(void) { } void reset_port(void) { + #if CIRCUITPY_AUDIOBUSIO_I2SOUT + i2sout_reset(); + #endif + #if defined(CONFIG_ARCH_POSIX) + native_sim_reset_port_count++; + if (native_sim_vm_runs != INT32_MAX && + native_sim_vm_runs > 0 && + native_sim_reset_port_count >= (uint32_t)(native_sim_vm_runs + 1)) { + printk("posix: exiting after %d VM runs\n", native_sim_vm_runs); + posix_exit(0); + } + #endif } void reset_to_bootloader(void) { @@ -65,10 +183,14 @@ void port_wake_main_task_from_isr(void) { k_event_set(&main_needed, 1); } -void port_yield(void) { +void port_task_yield(void) { k_yield(); } +void port_task_sleep_ms(uint32_t msecs) { + k_msleep(msecs); +} + void port_boot_info(void) { } @@ -135,36 +257,110 @@ void port_idle_until_interrupt(void) { // Zephyr doesn't maintain one multi-heap. So, make our own using TLSF. void port_heap_init(void) { + // Do a test malloc to determine if Zephyr has an outer heap that may + // overlap with a memory region we've identified in ram_bounds. We'll + // corrupt each other if we both use it. + #ifdef CONFIG_COMMON_LIBC_MALLOC + uint32_t *test_malloc = malloc(32); + free(test_malloc); // Free right away so we don't forget. We don't actually write it anyway. + zephyr_malloc_active = test_malloc != NULL; + #endif + for (size_t i = 0; i < CIRCUITPY_RAM_DEVICE_COUNT; i++) { uint32_t *heap_bottom = ram_bounds[2 * i]; uint32_t *heap_top = ram_bounds[2 * i + 1]; size_t size = (heap_top - heap_bottom) * sizeof(uint32_t); + // The linker script may fill up a region we thought we could use at + // build time. (The ram_bounds values are sometimes determined by the + // linker.) So, we need to guard against regions that aren't actually + // free. + if (size < 1024) { + printk("Skipping region because the linker filled it up.\n"); + continue; + } + #ifdef CONFIG_COMMON_LIBC_MALLOC + // Skip a ram region if our test malloc is within it. We'll use Zephyr's + // malloc to share that space with Zephyr. + if (heap_bottom <= test_malloc && test_malloc < heap_top) { + zephyr_malloc_top = heap_top; + zephyr_malloc_bottom = heap_bottom; + printk("Skipping region because Zephyr malloc is within bounds\n"); + pools[i] = NULL; + continue; + } + #endif printk("Init heap at %p - %p with size %d\n", heap_bottom, heap_top, size); // If this crashes, then make sure you've enabled all of the Kconfig needed for the drivers. - if (i == 0) { + if (valid_pool_count == 0) { heap = tlsf_create_with_pool(heap_bottom, size, circuitpy_max_ram_size); pools[i] = tlsf_get_pool(heap); } else { pools[i] = tlsf_add_pool(heap, heap_bottom + 1, size - sizeof(uint32_t)); } + valid_pool_count++; } + perfetto_emit_outer_heap_stats(); #if !DT_HAS_CHOSEN(zephyr_sram) #error "No SRAM!" #endif } void *port_malloc(size_t size, bool dma_capable) { - void *block = tlsf_malloc(heap, size); + void *block = NULL; + if (valid_pool_count > 0) { + block = tlsf_malloc(heap, size); + } + if (block != NULL) { + tlsf_heap_used += tlsf_block_size(block); + } + #ifdef CONFIG_COMMON_LIBC_MALLOC + if (block == NULL) { + block = malloc(size); + } + #endif + if (block != NULL) { + perfetto_emit_outer_heap_stats(); + } return block; } void port_free(void *ptr) { - tlsf_free(heap, ptr); + if (ptr == NULL) { + return; + } + if (valid_pool_count > 0 && !(ptr >= zephyr_malloc_bottom && ptr < zephyr_malloc_top)) { + tlsf_heap_used -= tlsf_block_size(ptr); + tlsf_free(heap, ptr); + } else { + #ifdef CONFIG_COMMON_LIBC_MALLOC + free(ptr); + #endif + } + perfetto_emit_outer_heap_stats(); } void *port_realloc(void *ptr, size_t size, bool dma_capable) { - return tlsf_realloc(heap, ptr, size); + if (ptr == NULL) { + return port_malloc(size, dma_capable); + } + if (valid_pool_count > 0 && !(ptr >= zephyr_malloc_bottom && ptr < zephyr_malloc_top)) { + size_t old_size = tlsf_block_size(ptr); + void *new_block = tlsf_realloc(heap, ptr, size); + if (new_block != NULL) { + tlsf_heap_used = tlsf_heap_used - old_size + tlsf_block_size(new_block); + perfetto_emit_outer_heap_stats(); + } + return new_block; + } + #ifdef CONFIG_COMMON_LIBC_MALLOC + void *new_block = realloc(ptr, size); + if (new_block != NULL) { + perfetto_emit_outer_heap_stats(); + } + return new_block; + #endif + return NULL; } static bool max_size_walker(void *ptr, size_t size, int used, void *user) { @@ -177,15 +373,21 @@ static bool max_size_walker(void *ptr, size_t size, int used, void *user) { size_t port_heap_get_largest_free_size(void) { size_t max_size = 0; - for (size_t i = 0; i < CIRCUITPY_RAM_DEVICE_COUNT; i++) { - tlsf_walk_pool(pools[i], max_size_walker, &max_size); + if (valid_pool_count > 0) { + for (size_t i = 0; i < CIRCUITPY_RAM_DEVICE_COUNT; i++) { + if (pools[i] == NULL) { + continue; + } + tlsf_walk_pool(pools[i], max_size_walker, &max_size); + } + // IDF does this. Not sure why. + return tlsf_fit_size(heap, max_size); } - // IDF does this. Not sure why. - return tlsf_fit_size(heap, max_size); + return 64 * 1024; } void assert_post_action(const char *file, unsigned int line) { - printk("Assertion failed at %s:%u\n", file, line); + // printk("Assertion failed at %s:%u\n", file, line); // Check that this is arm #if defined(__arm__) __asm__ ("bkpt"); diff --git a/ports/zephyr-cp/supervisor/usb.c b/ports/zephyr-cp/supervisor/usb.c index 844d4fae759..a42a5192f4f 100644 --- a/ports/zephyr-cp/supervisor/usb.c +++ b/ports/zephyr-cp/supervisor/usb.c @@ -22,7 +22,7 @@ #include "supervisor/shared/reload.h" #include -LOG_MODULE_REGISTER(usb, LOG_LEVEL_INF); +LOG_MODULE_REGISTER(cpusb, CONFIG_LOG_DEFAULT_LEVEL); #define USB_DEVICE DT_NODELABEL(zephyr_udc0) @@ -191,6 +191,20 @@ int _zephyr_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) { static void _msg_cb(struct usbd_context *const ctx, const struct usbd_msg *msg) { LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); + + if (usbd_can_detect_vbus(ctx)) { + if (msg->type == USBD_MSG_VBUS_READY) { + if (usbd_enable(ctx)) { + LOG_ERR("Failed to enable device support"); + } + } + + if (msg->type == USBD_MSG_VBUS_REMOVED) { + if (usbd_disable(ctx)) { + LOG_ERR("Failed to disable device support"); + } + } + } } void usb_init(void) { @@ -341,12 +355,14 @@ void usb_init(void) { printk("USB initialized\n"); - err = usbd_enable(&main_usbd); - if (err) { - LOG_ERR("Failed to enable device support"); - return; + if (!usbd_can_detect_vbus(&main_usbd)) { + err = usbd_enable(&main_usbd); + if (err) { + LOG_ERR("Failed to enable device support"); + return; + } + printk("usbd enabled\n"); } - printk("usbd enabled\n"); } bool usb_connected(void) { diff --git a/ports/zephyr-cp/sysbuild.cmake b/ports/zephyr-cp/sysbuild.cmake index f0968e05b5c..3c3acf0a803 100644 --- a/ports/zephyr-cp/sysbuild.cmake +++ b/ports/zephyr-cp/sysbuild.cmake @@ -18,4 +18,6 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) + native_simulator_set_final_executable(${DEFAULT_IMAGE}) endif() diff --git a/ports/zephyr-cp/tests/__init__.py b/ports/zephyr-cp/tests/__init__.py new file mode 100644 index 00000000000..e9039dd88b3 --- /dev/null +++ b/ports/zephyr-cp/tests/__init__.py @@ -0,0 +1,162 @@ +from pathlib import Path + +import serial +import subprocess +import threading +import time + + +class StdSerial: + def __init__(self, stdin, stdout): + self.stdin = stdin + self.stdout = stdout + + def read(self, amount=None): + data = self.stdout.read(amount) + if data == b"": + raise EOFError("stdout closed") + return data + + def write(self, buf): + if self.stdin is None: + return + self.stdin.write(buf) + self.stdin.flush() + + def close(self): + if self.stdin is not None: + self.stdin.close() + self.stdout.close() + + @property + def in_waiting(self): + if self.stdout is None: + return 0 + return len(self.stdout.peek()) + + +class SerialSaver: + """Capture serial output in a background thread so output isn't missed.""" + + def __init__(self, serial_obj, name="serial"): + self.all_output = "" + self.all_input = "" + self.serial = serial_obj + self.name = name + + self._stop = threading.Event() + self._lock = threading.Lock() + self._cv = threading.Condition(self._lock) + self._reader = threading.Thread(target=self._reader_loop, daemon=True) + self._reader.start() + + def _reader_loop(self): + while not self._stop.is_set(): + try: + read = self.serial.read(1) + except Exception: + # Serial port closed or device disconnected. + break + + if read == b"": + # Timeout with no data — keep waiting. Only a real + # exception or an explicit stop should end the loop. + continue + + text = read.decode("utf-8", errors="replace") + with self._cv: + self.all_output += text + self._cv.notify_all() + in_waiting = 0 + try: + in_waiting = self.serial.in_waiting + except OSError: + pass + if in_waiting > 0: + self.all_output += self.serial.read().decode("utf-8", errors="replace") + + def wait_for(self, text, timeout=10): + with self._cv: + while text not in self.all_output and self._reader.is_alive(): + if not self._cv.wait(timeout=timeout): + break + if text not in self.all_output: + tail = self.all_output[-400:] + raise TimeoutError( + f"Timed out waiting for {text!r} on {self.name}. Output tail:\n{tail}" + ) + + def read(self, amount=None): + # Kept for compatibility with existing callers. + return + + def close(self): + if not self.serial: + return + + self._stop.set() + self._reader.join(timeout=1.0) + try: + self.serial.close() + except Exception: + pass + self.serial = None + + def write(self, text): + self.all_input += text + self.serial.write(text.encode("utf-8")) + + +class NativeSimProcess: + def __init__(self, cmd, timeout=5, trace_file=None, env=None, flash_file=None): + if trace_file: + cmd.append(f"--trace-file={trace_file}") + + self._timeout = timeout + self.trace_file = trace_file + self.flash_file = flash_file + print("Running", " ".join(cmd)) + self._proc = subprocess.Popen( + cmd, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=None, + env=env, + ) + if self._proc.stdout is None: + raise RuntimeError("Failed to capture simulator stdout") + + # Discard the test warning + uart_pty_line = self._proc.stdout.readline().decode("utf-8") + if "connected to pseudotty:" not in uart_pty_line: + raise RuntimeError("Failed to connect to UART") + pty_path = uart_pty_line.strip().rsplit(":", maxsplit=1)[1].strip() + self.serial = SerialSaver( + serial.Serial(pty_path, baudrate=115200, timeout=0.05, write_timeout=0), + name="uart0", + ) + self.debug_serial = SerialSaver( + StdSerial(self._proc.stdin, self._proc.stdout), name="debug" + ) + + def shutdown(self): + if self._proc.poll() is None: + self._proc.terminate() + self._proc.wait(timeout=self._timeout) + + self.serial.close() + self.debug_serial.close() + + def display_capture_paths(self) -> list[Path]: + """Return paths to numbered PNG capture files produced by trace-driven capture.""" + pattern = getattr(self, "_capture_png_pattern", None) + count = getattr(self, "_capture_count", 0) + if not pattern or count == 0: + return [] + return [Path(pattern % i) for i in range(count)] + + def wait_until_done(self): + start_time = time.monotonic() + while self._proc.poll() is None and time.monotonic() - start_time < self._timeout: + time.sleep(0.01) + self.shutdown() diff --git a/ports/zephyr-cp/tests/bsim/__init__.py b/ports/zephyr-cp/tests/bsim/__init__.py new file mode 100644 index 00000000000..75136bccf43 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/__init__.py @@ -0,0 +1,3 @@ +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") diff --git a/ports/zephyr-cp/tests/bsim/conftest.py b/ports/zephyr-cp/tests/bsim/conftest.py new file mode 100644 index 00000000000..493f4c92b3b --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/conftest.py @@ -0,0 +1,227 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Pytest fixtures for CircuitPython bsim testing.""" + +import logging +import os +import shutil +import subprocess +from pathlib import Path + +import pytest + +from .. import SerialSaver, StdSerial + +logger = logging.getLogger(__name__) + +ZEPHYR_CP = Path(__file__).resolve().parents[2] +BSIM_BUILD_DIR = ZEPHYR_CP / "build-native_nrf5340bsim" +BSIM_SYSBUILD_BINARY = BSIM_BUILD_DIR / "zephyr/zephyr.exe" +BSIM_BINARY = BSIM_BUILD_DIR / "zephyr-cp/zephyr/zephyr.exe" +BSIM_ROOT = ZEPHYR_CP / "tools/bsim" +BSIM_PHY_BINARY = BSIM_ROOT / "bin/bs_2G4_phy_v1" + + +@pytest.fixture +def native_sim_env() -> dict[str, str]: + env = os.environ.copy() + env["BSIM_OUT_PATH"] = str(BSIM_ROOT) + env["BSIM_COMPONENTS_PATH"] = str(BSIM_ROOT / "components") + lib_path = str(BSIM_ROOT / "lib") + existing = env.get("LD_LIBRARY_PATH", "") + env["LD_LIBRARY_PATH"] = f"{lib_path}:{existing}" if existing else lib_path + return env + + +@pytest.fixture +def bsim_binary(): + """Return path to nrf5340bsim binary, skip if not built.""" + if BSIM_SYSBUILD_BINARY.exists(): + return BSIM_SYSBUILD_BINARY + if not BSIM_BINARY.exists(): + pytest.skip(f"nrf5340bsim not built: {BSIM_BINARY}") + return BSIM_BINARY + + +@pytest.fixture +def bsim_phy_binary(): + """Return path to BabbleSim PHY binary, skip if not present.""" + if not BSIM_PHY_BINARY.exists(): + pytest.skip(f"bs_2G4_phy_v1 not found: {BSIM_PHY_BINARY}") + return BSIM_PHY_BINARY + + +class BsimPhyInstance: + def __init__(self, proc: subprocess.Popen, serial: SerialSaver, timeout: float): + self.proc = proc + self.serial = serial + self.timeout = timeout + + def finish_sim(self) -> None: + self.serial.wait_for("Cleaning up", timeout=self.timeout + 5) + + def shutdown(self) -> None: + if self.proc.poll() is None: + self.proc.terminate() + self.proc.wait(timeout=2) + self.serial.close() + + +class ZephyrSampleProcess: + def __init__(self, proc: subprocess.Popen, timeout: float): + self._proc = proc + self._timeout = timeout + if proc.stdout is None: + raise RuntimeError("Failed to capture Zephyr sample stdout") + self.serial = SerialSaver(StdSerial(None, proc.stdout), name="zephyr sample") + + def shutdown(self) -> None: + if self._proc.poll() is None: + self._proc.terminate() + self._proc.wait(timeout=self._timeout) + self.serial.close() + + +@pytest.fixture +def bsim_phy(request, bsim_phy_binary, native_sim_env, sim_id): + duration_marker = request.node.get_closest_marker("duration") + duration = float(duration_marker.args[0]) if duration_marker else 20.0 + + devices = 1 + if "circuitpython2" in request.fixturenames or "zephyr_sample" in request.fixturenames: + devices = 2 + + sample_marker = request.node.get_closest_marker("zephyr_sample") + if sample_marker is not None: + sample_device_id = int(sample_marker.kwargs.get("device_id", 1)) + devices = max(devices, sample_device_id + 1) + + # Do not pass -sim_length: if the PHY exits on simulated time, device 0 can + # still be flushing UART output and test output can get truncated. Instead, + # let pytest own process lifetime and terminate the PHY at fixture teardown. + cmd = [ + "stdbuf", + "-oL", + str(bsim_phy_binary), + "-v=9", # Cleaning up level is on 9. Connecting is 7. + f"-s={sim_id}", + f"-D={devices}", + "-argschannel", + "-at=40", # 40 dB attenuation (default 60) so RSSI ~ -40 dBm + ] + print("Running:", " ".join(cmd)) + proc = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=native_sim_env, + cwd=BSIM_ROOT / "bin", + ) + if proc.stdout is None: + raise RuntimeError("Failed to capture bsim phy stdout") + + # stdbuf -oL forces line-buffered stdout so SerialSaver can + # stream-read PHY output in real time. Wrapping in StdSerial + # ensures the reader thread exits on EOF when the PHY process + # terminates, rather than spinning on empty timeout reads. + phy_output = SerialSaver(StdSerial(None, proc.stdout), name="bsim phy") + try: + phy_output.wait_for("Connecting", timeout=2) + except TimeoutError: + if proc.poll() is not None: + print(phy_output.all_output) + raise RuntimeError("bsim PHY exited immediately") + # Assume bsim is running + + phy = BsimPhyInstance(proc, phy_output, timeout=duration) + yield phy + phy.shutdown() + + print("bsim phy output:") + print(phy_output.all_output) + + +def _build_zephyr_sample(build_dir: Path, source_dir: Path, board: str) -> Path: + if shutil.which("west") is None: + raise RuntimeError("west not found") + + cmd = [ + "west", + "build", + "-b", + board, + "-d", + str(build_dir), + "-p=auto", + str(source_dir), + ] + logger.info("Building Zephyr sample: %s", " ".join(cmd)) + subprocess.run(cmd, check=True, cwd=ZEPHYR_CP) + + return build_dir / "zephyr/zephyr.exe" + + +@pytest.fixture +def zephyr_sample(request, bsim_phy, native_sim_env, sim_id): + marker = request.node.get_closest_marker("zephyr_sample") + if marker is None or len(marker.args) != 1: + raise RuntimeError( + "zephyr_sample fixture requires @pytest.mark.zephyr_sample('')" + ) + + sample = marker.args[0] + board = marker.kwargs.get("board", "nrf52_bsim") + device_id = int(marker.kwargs.get("device_id", 1)) + timeout = float(marker.kwargs.get("timeout", 10.0)) + + sample_rel = str(sample).removeprefix("zephyr/samples/") + source_dir = ZEPHYR_CP / "zephyr/samples" / sample_rel + if not source_dir.exists(): + pytest.skip(f"Zephyr sample not found: {source_dir}") + + build_name = f"build-bsim-sample-{sample_rel.replace('/', '_')}-{board}" + build_dir = ZEPHYR_CP / build_name + binary = build_dir / "zephyr/zephyr.exe" + + if not binary.exists(): + try: + binary = _build_zephyr_sample(build_dir, source_dir, board) + except (subprocess.CalledProcessError, RuntimeError) as exc: + pytest.skip(f"Failed to build Zephyr sample {sample_rel}: {exc}") + + if not binary.exists(): + pytest.skip(f"Zephyr sample binary not found: {binary}") + + cmd = [ + str(binary), + f"-s={sim_id}", + f"-d={device_id}", + "-disconnect_on_exit=1", + ] + logger.info("Running: %s", " ".join(cmd)) + proc = subprocess.Popen( + cmd, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=native_sim_env, + ) + sample_proc = ZephyrSampleProcess(proc, timeout=timeout) + yield sample_proc + sample_proc.shutdown() + + print("Zephyr sample output:") + print(sample_proc.serial.all_output) + + +# pytest markers are defined inside out meaning the bottom one is first in the +# list and the top is last. So use negative indices to reverse them. +@pytest.fixture +def circuitpython1(circuitpython): + return circuitpython[-1] + + +@pytest.fixture +def circuitpython2(circuitpython): + return circuitpython[-2] diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_basics.py b/ports/zephyr-cp/tests/bsim/test_bsim_basics.py new file mode 100644 index 00000000000..477292ddd54 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_basics.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Basic BabbleSim connectivity tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_CODE = """\ +print("bsim ready") +""" + + +@pytest.mark.circuitpy_drive({"code.py": BSIM_CODE}) +@pytest.mark.circuitpy_drive({"code.py": BSIM_CODE}) +@pytest.mark.duration(3) +def test_bsim_dual_instance_connect(bsim_phy, circuitpython1, circuitpython2): + """Run two bsim instances on the same sim id and verify UART output.""" + + # Wait for both devices to complete before checking output. + circuitpython1.wait_until_done() + circuitpython2.wait_until_done() + + output0 = circuitpython1.serial.all_output + output1 = circuitpython2.serial.all_output + + assert "Board ID:native_nrf5340bsim" in output0 + assert "Board ID:native_nrf5340bsim" in output1 + assert "bsim ready" in output0 + assert "bsim ready" in output1 diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_advertising.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_advertising.py new file mode 100644 index 00000000000..33680fe2506 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_advertising.py @@ -0,0 +1,174 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE advertising tests for nrf5340bsim.""" + +import logging +import re + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +logger = logging.getLogger(__name__) + +BSIM_ADV_CODE = """\ +import _bleio +import time + +name = b"CPADV" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +adapter = _bleio.adapter +print("adv start") +adapter.start_advertising(advertisement, connectable=False) +print("adv started") +time.sleep(4) +adapter.stop_advertising() +print("adv stop") +""" + +BSIM_ADV_INTERRUPT_RELOAD_CODE = """\ +import _bleio +import time + +name = b"CPADV" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +adapter = _bleio.adapter +print("adv run start") +adapter.start_advertising(advertisement, connectable=False) +print("adv running") +time.sleep(10) +adapter.stop_advertising() +print("adv run done") +""" + + +BSIM_TX_POWER_DEFAULT_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +name = b"CPTXPWR" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +print("advertising default") +adapter.start_advertising(advertisement) +time.sleep(4) +adapter.stop_advertising() +print("done") +""" + +BSIM_TX_POWER_LOW_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +name = b"CPTXPWR" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +print("advertising low") +adapter.start_advertising(advertisement, tx_power=-20) +time.sleep(4) +adapter.stop_advertising() +print("done") +""" + + +@pytest.mark.zephyr_sample("bluetooth/observer") +@pytest.mark.circuitpy_drive({"code.py": BSIM_ADV_CODE}) +def test_bsim_advertise_and_scan(bsim_phy, circuitpython, zephyr_sample): + """Advertise from CircuitPython and verify Zephyr observer sees traffic.""" + observer = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + observer_output = observer.serial.all_output + assert "adv start" in cp_output + assert "adv started" in cp_output + assert "adv stop" in cp_output + assert "Device found:" in observer_output + assert "AD data len 10" in observer_output + + +@pytest.mark.zephyr_sample("bluetooth/observer") +@pytest.mark.code_py_runs(2) +@pytest.mark.duration(25) +@pytest.mark.circuitpy_drive({"code.py": BSIM_ADV_INTERRUPT_RELOAD_CODE}) +def test_bsim_advertise_ctrl_c_reload(bsim_phy, circuitpython, zephyr_sample): + """Ensure advertising resumes after Ctrl-C and a reload.""" + observer = zephyr_sample + + circuitpython.serial.wait_for("adv running") + observer.serial.wait_for("Device found:") + observer_count_before = observer.serial.all_output.count("Device found:") + + circuitpython.serial.write("\x03") + circuitpython.serial.wait_for("KeyboardInterrupt") + + circuitpython.serial.write("\x04") + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + observer_output = observer.serial.all_output + logger.info(observer_output) + logger.info(cp_output) + + assert "adv run start" in cp_output + assert "KeyboardInterrupt" in cp_output + assert cp_output.count("adv running") >= 2 + assert cp_output.count("adv run done") >= 1 + assert observer_output.count("Device found:") >= observer_count_before + 1 + assert "Already advertising" not in cp_output + + +@pytest.mark.zephyr_sample("bluetooth/observer") +@pytest.mark.circuitpy_drive({"code.py": BSIM_TX_POWER_DEFAULT_CODE}) +def test_bsim_tx_power_default_rssi(bsim_phy, circuitpython, zephyr_sample): + """Verify default TX power produces expected RSSI.""" + observer = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + obs_output = observer.serial.all_output + + assert "advertising default" in cp_output + assert "done" in cp_output + + # Observer: "Device found: (RSSI ), type , AD data len " + # Advertisement is 12 bytes: flags (3) + name (9). + # With 40 dB channel attenuation and 0 dBm TX → RSSI ~ -39 + rssi_pattern = re.compile(r"RSSI (-?\d+)\), type \d+, AD data len 12") + all_rssi = [int(m.group(1)) for m in rssi_pattern.finditer(obs_output)] + logger.info("RSSI values: %s", all_rssi) + + assert len(all_rssi) > 0, "Observer saw no advertisements" + assert all_rssi[0] == -39, f"Expected RSSI -39 (0 dBm TX), got {all_rssi[0]}" + + +@pytest.mark.zephyr_sample("bluetooth/observer") +@pytest.mark.circuitpy_drive({"code.py": BSIM_TX_POWER_LOW_CODE}) +def test_bsim_tx_power_low_rssi(bsim_phy, circuitpython, zephyr_sample): + """Verify low TX power reduces RSSI.""" + observer = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + obs_output = observer.serial.all_output + + assert "advertising low" in cp_output + assert "done" in cp_output + + # With 40 dB channel attenuation and -20 dBm TX → RSSI ~ -59 + rssi_pattern = re.compile(r"RSSI (-?\d+)\), type \d+, AD data len 12") + all_rssi = [int(m.group(1)) for m in rssi_pattern.finditer(obs_output)] + logger.info("RSSI values: %s", all_rssi) + + assert len(all_rssi) > 0, "Observer saw no advertisements" + assert all_rssi[0] < -39, f"Expected lower RSSI with -20 dBm TX, got {all_rssi[0]}" diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_connect.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_connect.py new file mode 100644 index 00000000000..21cfeaf79da --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_connect.py @@ -0,0 +1,119 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE central connection tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_CONNECT_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("connect start") +target = None +for entry in adapter.start_scan(timeout=6.0, active=True): + if entry.connectable: + target = entry.address + print("found target") + break +adapter.stop_scan() +print("have target", target is not None) + +if target is None: + raise RuntimeError("No connectable target found") + +connection = adapter.connect(target, timeout=5.0) +print("connected", connection.connected, adapter.connected, len(adapter.connections)) +connection.disconnect() + +for _ in range(40): + if not connection.connected and not adapter.connected: + break + time.sleep(0.1) + +print("disconnected", connection.connected, adapter.connected, len(adapter.connections)) +""" + +BSIM_RECONNECT_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("run start") +target = None +for entry in adapter.start_scan(timeout=6.0, active=True): + if entry.connectable: + target = entry.address + print("run found target") + break +adapter.stop_scan() +print("run have target", target is not None) + +if target is None: + raise RuntimeError("No connectable target found") + +connection = adapter.connect(target, timeout=5.0) +print("run connected", connection.connected, adapter.connected, len(adapter.connections)) +connection.disconnect() + +for _ in range(50): + if not connection.connected and not adapter.connected and len(adapter.connections) == 0: + break + time.sleep(0.1) + +print("run disconnected", connection.connected, adapter.connected, len(adapter.connections)) +""" + + +@pytest.mark.zephyr_sample("bluetooth/peripheral") +@pytest.mark.duration(14) +@pytest.mark.circuitpy_drive({"code.py": BSIM_CONNECT_CODE}) +def test_bsim_connect_zephyr_peripheral(bsim_phy, circuitpython, zephyr_sample): + """Connect to the Zephyr peripheral sample and disconnect cleanly.""" + peripheral = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + peripheral_output = peripheral.serial.all_output + + assert "connect start" in cp_output + assert "found target" in cp_output + assert "have target True" in cp_output + assert "connected True True 1" in cp_output + assert "disconnected False False 0" in cp_output + + assert "Advertising successfully started" in peripheral_output + assert "Connected" in peripheral_output + + +@pytest.mark.zephyr_sample("bluetooth/peripheral_sc_only") +@pytest.mark.code_py_runs(2) +@pytest.mark.duration(26) +@pytest.mark.circuitpy_drive({"code.py": BSIM_RECONNECT_CODE}) +def test_bsim_reconnect_zephyr_peripheral(bsim_phy, circuitpython, zephyr_sample): + """Connect/disconnect, soft reload, then connect/disconnect again.""" + peripheral = zephyr_sample + + circuitpython.serial.wait_for("run disconnected") + circuitpython.serial.wait_for("Press any key to enter the REPL") + circuitpython.serial.write("\x04") + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + peripheral_output = peripheral.serial.all_output + + assert cp_output.count("run start") >= 2 + assert cp_output.count("run found target") >= 2 + assert cp_output.count("run have target True") >= 2 + assert cp_output.count("run connected True True 1") >= 2 + assert cp_output.count("run disconnected False False 0") >= 2 + + assert "Advertising successfully started" in peripheral_output + assert peripheral_output.count("Connected") >= 2 diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_name.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_name.py new file mode 100644 index 00000000000..69435d38256 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_name.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE name tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_NAME_CODE = """\ +import _bleio + +adapter = _bleio.adapter +adapter.enabled = True +adapter.name = "CPNAME" +print("name", adapter.name) +""" + + +@pytest.mark.circuitpy_drive({"code.py": BSIM_NAME_CODE}) +def test_bsim_set_name(bsim_phy, circuitpython): + """Set the BLE name and read it back on bsim.""" + circuitpython.wait_until_done() + + assert "name CPNAME" in circuitpython.serial.all_output diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_peripheral.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_peripheral.py new file mode 100644 index 00000000000..7a4bbfaecd9 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_peripheral.py @@ -0,0 +1,120 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE peripheral connection tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_PERIPHERAL_CODE = """\ +import _bleio +import time +import sys + +adapter = _bleio.adapter + +name = b"CPPERIPH" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +print("peripheral start") +adapter.start_advertising(advertisement, connectable=True) +print("advertising", adapter.advertising) + +was_connected = False +timeout = time.monotonic() + 8.0 +while not was_connected and time.monotonic() < timeout: + time.sleep(0.01) + was_connected = adapter.connected + +if not was_connected: + print("connect timed out") + sys.exit(-1) + +print("connected", was_connected, "advertising", adapter.advertising) + +if was_connected: + timeout = time.monotonic() + 8.0 + while adapter.connected and time.monotonic() < timeout: + time.sleep(0.1) + +print("disconnected", adapter.connected, len(adapter.connections)) +""" + +BSIM_CENTRAL_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("central start") +target = None +for entry in adapter.start_scan(timeout=6.0, active=True): + if entry.connectable and b"CPPERIPH" in entry.advertisement_bytes: + target = entry.address + print("found peripheral") + break +adapter.stop_scan() +print("have target", target is not None) + +if target is None: + raise RuntimeError("No connectable peripheral found") + +connection = adapter.connect(target, timeout=5.0) +print("connected", connection.connected, adapter.connected, len(adapter.connections)) +connection.disconnect() + +timeout = time.monotonic() + 4.0 +while (connection.connected or adapter.connected) and time.monotonic() < timeout: + time.sleep(0.1) + +print("disconnected", connection.connected, adapter.connected, len(adapter.connections)) +""" + + +@pytest.mark.zephyr_sample("bluetooth/central") +@pytest.mark.duration(14) +@pytest.mark.circuitpy_drive({"code.py": BSIM_PERIPHERAL_CODE}) +def test_bsim_peripheral_zephyr_central(bsim_phy, circuitpython, zephyr_sample): + """Advertise as connectable from CP; Zephyr central connects and disconnects.""" + central = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + central_output = central.serial.all_output + + assert "peripheral start" in cp_output + assert "advertising True" in cp_output + assert "connected True advertising False" in cp_output + assert "disconnected False 0" in cp_output + + assert "Scanning successfully started" in central_output + assert "Connected:" in central_output + assert "Disconnected:" in central_output + + +@pytest.mark.duration(14) +@pytest.mark.circuitpy_drive({"code.py": BSIM_PERIPHERAL_CODE}) +@pytest.mark.circuitpy_drive({"code.py": BSIM_CENTRAL_CODE}) +def test_bsim_peripheral_cp_central(bsim_phy, circuitpython1, circuitpython2): + """Two CP instances: device 0 peripheral, device 1 central.""" + peripheral = circuitpython1 + central = circuitpython2 + + central.wait_until_done() + peripheral.wait_until_done() + + periph_output = peripheral.serial.all_output + central_output = central.serial.all_output + + assert "peripheral start" in periph_output + assert "advertising True" in periph_output + assert "connected True advertising False" in periph_output + assert "disconnected False 0" in periph_output + + assert "central start" in central_output + assert "found peripheral" in central_output + assert "have target True" in central_output + assert "connected True True 1" in central_output + assert "disconnected False False 0" in central_output diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_scan.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_scan.py new file mode 100644 index 00000000000..19455b7bfa3 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_scan.py @@ -0,0 +1,112 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE scanning tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_SCAN_CODE = """\ +import _bleio + +adapter = _bleio.adapter +print("scan start") +scan = adapter.start_scan(timeout=4.0, active=True) +found = False +for entry in scan: + if b"zephyrproject" in entry.advertisement_bytes: + print("found beacon") + found = True + break +adapter.stop_scan() +print("scan done", found) +""" + +BSIM_SCAN_RELOAD_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("scan run start") +found = False +for entry in adapter.start_scan(active=True): + if b"zephyrproject" in entry.advertisement_bytes: + print("found beacon run") + found = True + break +adapter.stop_scan() +print("scan run done", found) +""" + +BSIM_SCAN_RELOAD_NO_STOP_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("scan run start") +found = False +for entry in adapter.start_scan(active=True): + if b"zephyrproject" in entry.advertisement_bytes: + print("found beacon run") + found = True + break +print("scan run done", found) +""" + + +@pytest.mark.zephyr_sample("bluetooth/beacon") +@pytest.mark.circuitpy_drive({"code.py": BSIM_SCAN_CODE}) +def test_bsim_scan_zephyr_beacon(bsim_phy, circuitpython, zephyr_sample): + """Scan for Zephyr beacon sample advertisement using bsim.""" + _ = zephyr_sample + + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "scan start" in output + assert "found beacon" in output + assert "scan done True" in output + + +@pytest.mark.zephyr_sample("bluetooth/beacon") +@pytest.mark.code_py_runs(2) +@pytest.mark.duration(4) +@pytest.mark.circuitpy_drive({"code.py": BSIM_SCAN_RELOAD_CODE}) +def test_bsim_scan_zephyr_beacon_reload(bsim_phy, circuitpython, zephyr_sample): + """Scan for Zephyr beacon, soft reload, and scan again.""" + _ = zephyr_sample + + circuitpython.serial.wait_for("scan run done") + circuitpython.serial.wait_for("Press any key to enter the REPL") + circuitpython.serial.write("\x04") + + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert output.count("scan run start") >= 2 + assert output.count("found beacon run") >= 2 + assert output.count("scan run done True") >= 2 + + +@pytest.mark.xfail(strict=False, reason="scan without stop_scan may fail on reload") +@pytest.mark.zephyr_sample("bluetooth/beacon") +@pytest.mark.code_py_runs(2) +@pytest.mark.duration(8) +@pytest.mark.circuitpy_drive({"code.py": BSIM_SCAN_RELOAD_NO_STOP_CODE}) +def test_bsim_scan_zephyr_beacon_reload_no_stop(bsim_phy, circuitpython, zephyr_sample): + """Scan for Zephyr beacon without explicit stop, soft reload, and scan again.""" + _ = zephyr_sample + + circuitpython.serial.wait_for("scan run done") + circuitpython.serial.wait_for("Press any key to enter the REPL") + circuitpython.serial.write("\x04") + + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert output.count("scan run start") >= 2 + assert output.count("found beacon run") >= 2 + assert output.count("scan run done True") >= 2 diff --git a/ports/zephyr-cp/tests/conftest.py b/ports/zephyr-cp/tests/conftest.py index f26c7f0f45f..03451048324 100644 --- a/ports/zephyr-cp/tests/conftest.py +++ b/ports/zephyr-cp/tests/conftest.py @@ -5,67 +5,83 @@ import logging import os -import re -import select import subprocess -import time -from dataclasses import dataclass from pathlib import Path import pytest -from perfetto.trace_processor import TraceProcessor - -logger = logging.getLogger(__name__) - -ZEPHYR_CP = Path(__file__).parent.parent -BUILD_DIR = ZEPHYR_CP / "build-native_native_sim" -BINARY = BUILD_DIR / "zephyr-cp/zephyr/zephyr.exe" - +import serial -@dataclass -class InputTrigger: - """A trigger for sending input to the simulator. +from .perfetto_input_trace import write_input_trace - Attributes: - trigger: Text to match in output to trigger input, or None for immediate send. - data: Bytes to send when triggered. - sent: Whether this trigger has been sent (set internally). - """ +from perfetto.trace_processor import TraceProcessor - trigger: str | None - data: bytes - sent: bool = False +from . import NativeSimProcess +logger = logging.getLogger(__name__) -@dataclass -class SimulatorResult: - """Result from running CircuitPython on the simulator.""" - output: str - trace_file: Path +def pytest_addoption(parser): + parser.addoption( + "--update-goldens", + action="store_true", + default=False, + help="Overwrite golden images with captured output instead of comparing.", + ) -def parse_gpio_trace(trace_file: Path, pin_name: str = "gpio_emul.00") -> list[tuple[int, int]]: - """Parse GPIO trace from Perfetto trace file. +def pytest_configure(config): + config.addinivalue_line( + "markers", "circuitpy_drive(files): run CircuitPython with files in the flash image" + ) + config.addinivalue_line( + "markers", "disable_i2c_devices(*names): disable native_sim I2C emulator devices" + ) + config.addinivalue_line( + "markers", "circuitpython_board(board_id): which board id to use in the test" + ) + config.addinivalue_line( + "markers", + "zephyr_sample(sample, board='nrf52_bsim', device_id=1): build and run a Zephyr sample for bsim tests", + ) + config.addinivalue_line( + "markers", + "duration(seconds): native_sim timeout and bsim PHY simulation duration", + ) + config.addinivalue_line( + "markers", + "code_py_runs(count): stop native_sim after count code.py runs (default: 1)", + ) + config.addinivalue_line( + "markers", + "input_trace(trace): inject input signal trace data into native_sim", + ) + config.addinivalue_line( + "markers", + "native_sim_rt: run native_sim in realtime mode (-rt instead of -no-rt)", + ) + config.addinivalue_line( + "markers", + "display(capture_times_ns=None): run test with SDL display; " + "capture_times_ns is a list of nanosecond timestamps for trace-triggered captures", + ) + config.addinivalue_line( + "markers", + "display_pixel_format(format): override the display pixel format " + "(e.g. 'RGB_565', 'ARGB_8888')", + ) + config.addinivalue_line( + "markers", + "display_mono_vtiled(value): override the mono vtiled screen_info flag (True or False)", + ) + config.addinivalue_line( + "markers", + "flash_config(erase_block_size=N, total_size=N): override flash simulator parameters", + ) - Args: - trace_file: Path to the Perfetto trace file. - pin_name: Name of the GPIO pin track (e.g., "gpio_emul.00"). - Returns: - List of (timestamp_ns, value) tuples for the specified GPIO pin. - """ - tp = TraceProcessor(file_path=str(trace_file)) - result = tp.query( - f''' - SELECT c.ts, c.value - FROM counter c - JOIN track t ON c.track_id = t.id - WHERE t.name = "{pin_name}" - ORDER BY c.ts - ''' - ) - return [(row.ts, int(row.value)) for row in result] +ZEPHYR_CP = Path(__file__).parent.parent +BUILD_DIR = ZEPHYR_CP / "build-native_native_sim" +BINARY = BUILD_DIR / "zephyr-cp/zephyr/zephyr.exe" def _iter_uart_tx_slices(trace_file: Path) -> list[tuple[int, int, str, str]]: @@ -134,179 +150,232 @@ def log_uart_trace_output(trace_file: Path) -> None: @pytest.fixture -def native_sim_binary(): +def board(request): + board = request.node.get_closest_marker("circuitpython_board") + if board is not None: + board = board.args[0] + else: + board = "native_native_sim" + return board + + +@pytest.fixture +def native_sim_binary(request, board): """Return path to native_sim binary, skip if not built.""" - if not BINARY.exists(): - pytest.skip(f"native_sim not built: {BINARY}") - return BINARY + build_dir = ZEPHYR_CP / f"build-{board}" + binary = build_dir / "zephyr-cp/zephyr/zephyr.exe" + + if not binary.exists(): + pytest.skip(f"binary not built: {binary}") + return binary @pytest.fixture -def create_flash_image(tmp_path): - """Factory fixture to create FAT flash images.""" +def native_sim_env() -> dict[str, str]: + return {} - def _create(files: dict[str, str]) -> Path: - flash = tmp_path / "flash.bin" - # Create 2MB empty file - flash.write_bytes(b"\x00" * (2 * 1024 * 1024)) +PIXEL_FORMAT_BITMASK = { + "RGB_888": 1 << 0, + "MONO01": 1 << 1, + "MONO10": 1 << 2, + "ARGB_8888": 1 << 3, + "RGB_565": 1 << 4, + "BGR_565": 1 << 5, + "L_8": 1 << 6, + "AL_88": 1 << 7, +} - # Format as FAT (mformat) - subprocess.run(["mformat", "-i", str(flash), "::"], check=True) - # Copy files (mcopy) - for name, content in files.items(): - src = tmp_path / name - src.write_text(content) - subprocess.run(["mcopy", "-i", str(flash), str(src), f"::{name}"], check=True) +@pytest.fixture +def pixel_format(request) -> str: + """Indirect-parametrize fixture: adds display_pixel_format marker.""" + fmt = request.param + request.node.add_marker(pytest.mark.display_pixel_format(fmt)) + return fmt - return flash - return _create +@pytest.fixture +def sim_id(request) -> str: + return request.node.nodeid.replace("/", "_") @pytest.fixture -def run_circuitpython(native_sim_binary, create_flash_image, tmp_path): - """Run CircuitPython with given code string and return output from PTY. - - Args: - code: Python code to write to code.py, or None for no code.py. - timeout: Timeout in seconds for the simulation. - erase_flash: If True, erase flash before running. - input_sequence: List of InputTrigger objects. When trigger text is seen - in output, the corresponding data is written to the PTY. If trigger - is None, the data is sent immediately when PTY is opened. - """ - - def _run( - code: str | None, - timeout: float = 5.0, - erase_flash: bool = False, - input_sequence: list[InputTrigger] | None = None, - disabled_i2c_devices: list[str] | None = None, - ) -> SimulatorResult: - files = {"code.py": code} if code is not None else {} - flash = create_flash_image(files) - triggers = list(input_sequence) if input_sequence else [] - trace_file = tmp_path / "trace.perfetto" - - cmd = [ - str(native_sim_binary), - f"--flash={flash}", - "--flash_rm", - "-no-rt", - "-wait_uart", - f"-stop_at={timeout}", - f"--trace-file={trace_file}", - ] - if erase_flash: - cmd.append("--flash_erase") - if disabled_i2c_devices: - for device in disabled_i2c_devices: +def circuitpython(request, board, sim_id, native_sim_binary, native_sim_env, tmp_path): + """Run CircuitPython with given code string and return PTY output.""" + + instance_count = 1 + if "circuitpython1" in request.fixturenames and "circuitpython2" in request.fixturenames: + instance_count = 2 + + drives = list(request.node.iter_markers_with_node("circuitpy_drive")) + if len(drives) != instance_count: + raise RuntimeError(f"not enough drives for {instance_count} instances") + + input_trace_markers = list(request.node.iter_markers_with_node("input_trace")) + if len(input_trace_markers) > 1: + raise RuntimeError("expected at most one input_trace marker") + + input_trace = None + if input_trace_markers and len(input_trace_markers[0][1].args) == 1: + input_trace = input_trace_markers[0][1].args[0] + + input_trace_file = None + if input_trace is not None: + input_trace_file = tmp_path / "input.perfetto" + write_input_trace(input_trace_file, input_trace) + + marker = request.node.get_closest_marker("duration") + if marker is None: + timeout = 10 + else: + timeout = marker.args[0] + + runs_marker = request.node.get_closest_marker("code_py_runs") + if runs_marker is None: + code_py_runs = 1 + else: + code_py_runs = int(runs_marker.args[0]) + + display_marker = request.node.get_closest_marker("display") + if display_marker is None: + display_marker = request.node.get_closest_marker("display_capture") + + capture_times_ns = None + if display_marker is not None: + capture_times_ns = display_marker.kwargs.get("capture_times_ns", None) + + pixel_format_marker = request.node.get_closest_marker("display_pixel_format") + pixel_format = None + if pixel_format_marker is not None and pixel_format_marker.args: + pixel_format = pixel_format_marker.args[0] + + mono_vtiled_marker = request.node.get_closest_marker("display_mono_vtiled") + mono_vtiled = None + if mono_vtiled_marker is not None and mono_vtiled_marker.args: + mono_vtiled = mono_vtiled_marker.args[0] + + # If capture_times_ns is set, merge display_capture track into input trace. + if capture_times_ns is not None: + if input_trace is None: + input_trace = {} + else: + input_trace = dict(input_trace) + input_trace["display_capture"] = list(capture_times_ns) + if input_trace_file is None: + input_trace_file = tmp_path / "input.perfetto" + write_input_trace(input_trace_file, input_trace) + + use_realtime = request.node.get_closest_marker("native_sim_rt") is not None + + flash_config_marker = request.node.get_closest_marker("flash_config") + flash_total_size = 2 * 1024 * 1024 # default 2MB + flash_erase_block_size = None + flash_write_block_size = None + if flash_config_marker: + flash_total_size = flash_config_marker.kwargs.get("total_size", flash_total_size) + flash_erase_block_size = flash_config_marker.kwargs.get("erase_block_size", None) + flash_write_block_size = flash_config_marker.kwargs.get("write_block_size", None) + + procs = [] + for i in range(instance_count): + flash = tmp_path / f"flash-{i}.bin" + flash.write_bytes(b"\xff" * flash_total_size) + files = None + if len(drives[i][1].args) == 1: + files = drives[i][1].args[0] + if files is not None: + subprocess.run(["mformat", "-i", str(flash), "::"], check=True) + tmp_drive = tmp_path / f"drive{i}" + tmp_drive.mkdir(exist_ok=True) + + for name, content in files.items(): + src = tmp_drive / name + if isinstance(content, bytes): + src.write_bytes(content) + else: + src.write_text(content) + subprocess.run(["mcopy", "-i", str(flash), str(src), f"::{name}"], check=True) + + trace_file = tmp_path / f"trace-{i}.perfetto" + + if "bsim" in board: + cmd = [str(native_sim_binary), f"--flash_app={flash}"] + if instance_count > 1: + cmd.append("-disconnect_on_exit=1") + cmd.extend( + ( + f"-s={sim_id}", + f"-d={i}", + "-uart0_pty", + "-uart0_pty_wait_for_readers", + "-uart_pty_wait", + f"--vm-runs={code_py_runs + 1}", + ) + ) + else: + cmd = [str(native_sim_binary), f"--flash={flash}"] + # native_sim vm-runs includes the boot VM setup run. + realtime_flag = "-rt" if use_realtime else "-no-rt" + cmd.extend( + ( + realtime_flag, + "-display_headless", + "-i2s_earless", + "-wait_uart", + f"--vm-runs={code_py_runs + 1}", + ) + ) + + if flash_erase_block_size is not None: + cmd.append(f"--flash_erase_block_size={flash_erase_block_size}") + if flash_write_block_size is not None: + cmd.append(f"--flash_write_block_size={flash_write_block_size}") + if flash_config_marker and "total_size" in flash_config_marker.kwargs: + cmd.append(f"--flash_total_size={flash_total_size}") + + if input_trace_file is not None: + cmd.append(f"--input-trace={input_trace_file}") + + marker = request.node.get_closest_marker("disable_i2c_devices") + if marker and len(marker.args) > 0: + for device in marker.args: cmd.append(f"--disable-i2c={device}") - logger.info("Running: %s", " ".join(cmd)) - # Start the process - proc = subprocess.Popen( - cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - ) - - pty_path = None - pty_fd = None - output = [] - stdout_lines = [] - - try: - # Read stdout to find the PTY path - start_time = time.time() - while time.time() - start_time < timeout + 5: - if proc.poll() is not None: - # Process exited - break - - # Check if stdout has data - ready, _, _ = select.select([proc.stdout], [], [], 0.1) - if ready: - line = proc.stdout.readline() - if not line: - break - - stdout_lines.append(line.rstrip()) - - # Look for PTY path - match = re.search(r"uart connected to pseudotty: (/dev/pts/\d+)", line) - if match: - pty_path = match.group(1) - # Open the PTY for reading and writing - pty_fd = os.open(pty_path, os.O_RDWR | os.O_NONBLOCK) - - # Send any immediate triggers (trigger=None) - for t in triggers: - if t.trigger is None and not t.sent: - os.write(pty_fd, t.data) - logger.info("PTY input (immediate): %r", t.data) - t.sent = True - break - - if pty_fd is None: - raise RuntimeError("Failed to find PTY path in output") - - def check_triggers(accumulated_output: str) -> None: - """Check accumulated output against triggers and send input.""" - for t in triggers: - if t.trigger is not None and not t.sent: - if t.trigger in accumulated_output: - os.write(pty_fd, t.data) - logger.info("PTY input (trigger %r): %r", t.trigger, t.data) - t.sent = True - - # Read from PTY until process exits or timeout - while time.time() - start_time < timeout + 1: - if proc.poll() is not None: - # Process exited, do one final read - try: - ready, _, _ = select.select([pty_fd], [], [], 0.1) - if ready: - data = os.read(pty_fd, 4096) - if data: - output.append(data.decode("utf-8", errors="replace")) - except (OSError, BlockingIOError): - pass - break - - # Check if PTY has data - try: - ready, _, _ = select.select([pty_fd], [], [], 0.1) - if ready: - data = os.read(pty_fd, 4096) - if data: - output.append(data.decode("utf-8", errors="replace")) - check_triggers("".join(output)) - except (OSError, BlockingIOError): - pass - - # Read any remaining stdout - remaining_stdout = proc.stdout.read() - if remaining_stdout: - stdout_lines.extend(remaining_stdout.rstrip().split("\n")) - - # Log stdout - for line in stdout_lines: - logger.info("stdout: %s", line) - - pty_output = "".join(output) - for line in pty_output.split("\n"): - logger.info("PTY output: %s", repr(line.strip())) - log_uart_trace_output(trace_file) - return SimulatorResult(output=pty_output, trace_file=trace_file) - - finally: - if pty_fd is not None: - os.close(pty_fd) - proc.terminate() - proc.wait(timeout=1) - - return _run + if pixel_format is not None: + cmd.append(f"--display_pixel_format={PIXEL_FORMAT_BITMASK[pixel_format]}") + + if mono_vtiled is not None: + cmd.append(f"--display_mono_vtiled={'true' if mono_vtiled else 'false'}") + + env = os.environ.copy() + env.update(native_sim_env) + + capture_png_pattern = None + if capture_times_ns is not None: + if instance_count == 1: + capture_png_pattern = str(tmp_path / "frame_%d.png") + else: + capture_png_pattern = str(tmp_path / f"frame-{i}_%d.png") + cmd.append(f"--display_capture_png={capture_png_pattern}") + + logger.info("Running: %s", " ".join(cmd)) + proc = NativeSimProcess(cmd, timeout, trace_file, env, flash_file=flash) + proc.display_dump = None + proc._capture_png_pattern = capture_png_pattern + proc._capture_count = len(capture_times_ns) if capture_times_ns is not None else 0 + procs.append(proc) + if instance_count == 1: + yield procs[0] + else: + yield procs + for i, proc in enumerate(procs): + if instance_count > 1: + print(f"---------- Instance {i} -----------") + proc.shutdown() + + print("All serial output:") + print(proc.serial.all_output) + print() + print("All debug serial output:") + print(proc.debug_serial.all_output) diff --git a/ports/zephyr-cp/tests/docs/babblesim.md b/ports/zephyr-cp/tests/docs/babblesim.md new file mode 100644 index 00000000000..75d45079b2e --- /dev/null +++ b/ports/zephyr-cp/tests/docs/babblesim.md @@ -0,0 +1,81 @@ +# BabbleSim testing + +This document describes how to build and run CircuitPython tests against the +BabbleSim (bsim) nRF5340 board. + +## Board target + +We use the Zephyr BabbleSim board for the nRF5340 application core: + +- Zephyr board: `nrf5340bsim/nrf5340/cpuapp` +- CircuitPython board alias: `native_nrf5340bsim` + +The tests expect two bsim instances to run in the same simulation, which allows +future BLE/802.15.4 multi-node tests. + +## Prerequisites + +BabbleSim needs to be available to Zephyr. Either: + +- Use the repo-provided `tools/bsim` checkout (if present) +- Or set environment variables: + +``` +export BSIM_COMPONENTS_PATH=/path/to/bsim/components +export BSIM_OUT_PATH=/path/to/bsim +``` + +## Build + +``` +CCACHE_TEMPDIR=/tmp/ccache-tmp make -j BOARD=native_nrf5340bsim +``` + +If you do not use ccache, you can omit `CCACHE_TEMPDIR`. + +## Run the bsim test + +``` +pytest tests/test_bsim_basics.py -v +``` + +## BLE scan + advertising tests + +The BLE tests run multiple bsim instances and build Zephyr samples on-demand: + +- `tests/test_bsim_ble_scan.py` scans for the Zephyr beacon sample +- `tests/test_bsim_ble_advertising.py` advertises from CircuitPython while the + Zephyr observer sample scans + +The fixtures build the Zephyr samples if missing: + +- Beacon: `zephyr/samples/bluetooth/beacon` (board `nrf52_bsim`) +- Observer: `zephyr/samples/bluetooth/observer` (board `nrf52_bsim`) + +Run the tests with: + +``` +pytest tests/test_bsim_ble_scan.py -v +pytest tests/test_bsim_ble_advertising.py -v +``` + +## Pytest markers + +For bsim-specific test tuning: + +- `@pytest.mark.duration(seconds)` controls simulation runtime/timeout. + +Example: + +```py +pytestmark = pytest.mark.duration(30.0) +``` + +## Notes + +- The bsim test spawns two instances that share a sim id. It only checks UART + output for now, but is the base for BLE/Thread multi-node tests. +- The BLE tests rely on the sysbuild HCI IPC net-core image for the nRF5340 + simulator (enabled via `sysbuild.conf`). +- The board uses a custom devicetree overlay to provide the SRAM region and + CircuitPython flash partition expected by the port. diff --git a/ports/zephyr-cp/tests/docs/web_workflow.md b/ports/zephyr-cp/tests/docs/web_workflow.md new file mode 100644 index 00000000000..eb6742b8a3e --- /dev/null +++ b/ports/zephyr-cp/tests/docs/web_workflow.md @@ -0,0 +1,37 @@ +# Web Workflow native_sim Tests + +These tests validate CircuitPython's web workflow support in the Zephyr native_sim port, including filesystem write behavior with and without USB-style write protection. + +## Coverage + +- `test_web_workflow_hostnetwork`: Verifies the web workflow HTTP server responds and enforces authentication (`/edit/` returns `401 Unauthorized`). +- `test_web_workflow_write_code_py_conflict`: Exercises a write attempt while the filesystem is protected (no `boot.py` remount). The DELETE request should return `409 Conflict`. +- `test_web_workflow_write_code_py_remount`: Uses a `boot.py` remount to allow CircuitPython to write. A PUT request updates `code.py`, and a subsequent GET verifies the contents. + +## Filesystem Setup + +The tests create a flash image with: + +- `settings.toml` containing `CIRCUITPY_WEB_API_PASSWORD="testpass"` so the web workflow starts using the on-device settings file. +- `boot.py` (for the remount test only) with: + ```python + import storage + storage.remount("/", readonly=False) + ``` + This disables concurrent write protection so the web workflow can write to CIRCUITPY. + +## Running the Tests + +Build native_sim (if needed): + +```bash +make BOARD=native_native_sim +``` + +Run the tests: + +```bash +pytest -q ports/zephyr-cp/tests/test_web_workflow.py::test_web_workflow_hostnetwork -vv +pytest -q ports/zephyr-cp/tests/test_web_workflow.py::test_web_workflow_write_code_py_conflict -vv +pytest -q ports/zephyr-cp/tests/test_web_workflow.py::test_web_workflow_write_code_py_remount -vv +``` diff --git a/ports/zephyr-cp/tests/perfetto_input_trace.py b/ports/zephyr-cp/tests/perfetto_input_trace.py new file mode 100644 index 00000000000..494c9cdcadf --- /dev/null +++ b/ports/zephyr-cp/tests/perfetto_input_trace.py @@ -0,0 +1,159 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries LLC +# SPDX-License-Identifier: MIT + +"""Utilities for creating Perfetto input trace files for native_sim tests. + +This module can be used directly from Python or from the command line: + + python -m tests.perfetto_input_trace input_trace.json output.perfetto + +Input JSON format — counter tracks use [timestamp, value] pairs, instant +tracks use bare timestamps: + +{ + "gpio_emul.01": [[8000000000, 0], [9000000000, 1], [10000000000, 0]], + "display_capture": [500000000, 1000000000] +} +""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path +from typing import Mapping, Sequence + +# Counter tracks: list of (timestamp, value) pairs. +# Instant tracks: list of timestamps (bare ints). +InputTraceData = Mapping[str, Sequence[tuple[int, int] | int]] + + +def _load_perfetto_pb2(): + from perfetto.protos.perfetto.trace import perfetto_trace_pb2 as perfetto_pb2 + + return perfetto_pb2 + + +def _is_instant_track(events: Sequence) -> bool: + """Return True if *events* is a list of bare timestamps (instant track).""" + if not events: + return False + return isinstance(events[0], int) + + +def build_input_trace(trace_data: InputTraceData, *, sequence_id: int = 1): + """Build a Perfetto Trace protobuf for input replay counter and instant tracks.""" + perfetto_pb2 = _load_perfetto_pb2() + trace = perfetto_pb2.Trace() + + seq_incremental_state_cleared = 1 + seq_needs_incremental_state = 2 + + for idx, (track_name, events) in enumerate(trace_data.items()): + track_uuid = 1001 + idx + instant = _is_instant_track(events) + + desc_packet = trace.packet.add() + desc_packet.timestamp = 0 + desc_packet.trusted_packet_sequence_id = sequence_id + if idx == 0: + desc_packet.sequence_flags = seq_incremental_state_cleared + desc_packet.track_descriptor.uuid = track_uuid + desc_packet.track_descriptor.name = track_name + if not instant: + desc_packet.track_descriptor.counter.unit = ( + perfetto_pb2.CounterDescriptor.Unit.UNIT_COUNT + ) + + if instant: + for ts in events: + event_packet = trace.packet.add() + event_packet.timestamp = ts + event_packet.trusted_packet_sequence_id = sequence_id + event_packet.sequence_flags = seq_needs_incremental_state + event_packet.track_event.type = perfetto_pb2.TrackEvent.Type.TYPE_INSTANT + event_packet.track_event.track_uuid = track_uuid + else: + for ts, value in events: + event_packet = trace.packet.add() + event_packet.timestamp = ts + event_packet.trusted_packet_sequence_id = sequence_id + event_packet.sequence_flags = seq_needs_incremental_state + event_packet.track_event.type = perfetto_pb2.TrackEvent.Type.TYPE_COUNTER + event_packet.track_event.track_uuid = track_uuid + event_packet.track_event.counter_value = value + + return trace + + +def write_input_trace( + trace_file: Path, trace_data: InputTraceData, *, sequence_id: int = 1 +) -> None: + """Write input replay data to a Perfetto trace file.""" + trace = build_input_trace(trace_data, sequence_id=sequence_id) + trace_file.parent.mkdir(parents=True, exist_ok=True) + trace_file.write_bytes(trace.SerializeToString()) + + +def _parse_trace_json(data: object) -> dict[str, list[tuple[int, int]] | list[int]]: + if not isinstance(data, dict): + raise ValueError("top-level JSON value must be an object") + + parsed: dict[str, list[tuple[int, int]] | list[int]] = {} + for track_name, events in data.items(): + if not isinstance(track_name, str): + raise ValueError("track names must be strings") + if not isinstance(events, list): + raise ValueError(f"track {track_name!r} must map to a list of events") + + if not events: + parsed[track_name] = [] + continue + + # Distinguish instant (bare ints) vs counter ([ts, value] pairs). + if isinstance(events[0], (int, float)): + parsed[track_name] = [int(ts) for ts in events] + else: + parsed_events: list[tuple[int, int]] = [] + for event in events: + if not isinstance(event, (list, tuple)) or len(event) != 2: + raise ValueError( + f"track {track_name!r} events must be [timestamp, value] pairs " + "or bare timestamps" + ) + timestamp_ns, value = event + parsed_events.append((int(timestamp_ns), int(value))) + parsed[track_name] = parsed_events + + return parsed + + +def _build_arg_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + description="Generate a Perfetto input trace file used by native_sim --input-trace" + ) + parser.add_argument("input_json", type=Path, help="Path to input trace JSON") + parser.add_argument("output_trace", type=Path, help="Output .perfetto file path") + parser.add_argument( + "--sequence-id", + type=int, + default=1, + help="trusted_packet_sequence_id to use (default: 1)", + ) + return parser + + +def main(argv: Sequence[str] | None = None) -> int: + parser = _build_arg_parser() + args = parser.parse_args(argv) + + trace_json = json.loads(args.input_json.read_text()) + trace_data = _parse_trace_json(trace_json) + write_input_trace(args.output_trace, trace_data, sequence_id=args.sequence_id) + + print(f"Wrote {args.output_trace} ({len(trace_data)} tracks)") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/ports/zephyr-cp/tests/test_adafruit_bus_device.py b/ports/zephyr-cp/tests/test_adafruit_bus_device.py new file mode 100644 index 00000000000..3022838506e --- /dev/null +++ b/ports/zephyr-cp/tests/test_adafruit_bus_device.py @@ -0,0 +1,236 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test adafruit_bus_device.i2c_device.I2CDevice against the AT24 EEPROM emulator.""" + +import pytest + + +PROBE_OK_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) +print(f"device created: {type(device).__name__}") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": PROBE_OK_CODE}) +def test_i2cdevice_probe_success(circuitpython): + """Constructing I2CDevice with probe=True succeeds when AT24 is present at 0x50.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "device created: I2CDevice" in output + assert "done" in output + + +PROBE_FAIL_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +try: + device = I2CDevice(i2c, 0x51) + print("unexpected_success") +except ValueError as e: + print(f"probe_failed: {e}") +except OSError as e: + print(f"probe_failed: {e}") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": PROBE_FAIL_CODE}) +def test_i2cdevice_probe_failure(circuitpython): + """Constructing I2CDevice with probe=True raises when no device responds.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "probe_failed" in output + assert "unexpected_success" not in output + assert "done" in output + + +PROBE_DISABLED_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +# probe=False should not raise even without a device at this address +device = I2CDevice(i2c, 0x51, probe=False) +print(f"device created: {type(device).__name__}") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": PROBE_DISABLED_CODE}) +def test_i2cdevice_probe_disabled(circuitpython): + """Constructing I2CDevice with probe=False succeeds regardless of device presence.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "device created: I2CDevice" in output + assert "done" in output + + +READ_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) + +# Read first byte by writing the memory address, then reading. +buf = bytearray(1) +with device: + device.write(bytes([0x00])) + device.readinto(buf) +print(f"AT24 byte 0: 0x{buf[0]:02X}") +if buf[0] == 0xFF: + print("eeprom_valid") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": READ_CODE}) +def test_i2cdevice_write_then_readinto_separate(circuitpython): + """write() followed by readinto() inside a single context manager block reads EEPROM data.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "AT24 byte 0: 0xFF" in output + assert "eeprom_valid" in output + assert "done" in output + + +WRITE_THEN_READINTO_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) + +out_buf = bytes([0x00]) +in_buf = bytearray(4) +with device: + device.write_then_readinto(out_buf, in_buf) +print(f"first 4 bytes: {[hex(b) for b in in_buf]}") +if all(b == 0xFF for b in in_buf): + print("eeprom_valid") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_THEN_READINTO_CODE}) +def test_i2cdevice_write_then_readinto_atomic(circuitpython): + """write_then_readinto() performs an atomic write+read against the EEPROM.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "first 4 bytes:" in output + assert "eeprom_valid" in output + assert "done" in output + + +WRITE_READBACK_CODE = """\ +import board +import time +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) + +# Write four bytes starting at EEPROM address 0x10. +payload = bytes([0xDE, 0xAD, 0xBE, 0xEF]) +with device: + device.write(bytes([0x10]) + payload) + +# EEPROM needs a moment to commit the write internally. +time.sleep(0.01) + +readback = bytearray(4) +with device: + device.write_then_readinto(bytes([0x10]), readback) +print(f"readback: {[hex(b) for b in readback]}") +if bytes(readback) == payload: + print("readback_ok") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_READBACK_CODE}) +def test_i2cdevice_write_then_read_roundtrip(circuitpython): + """Writing bytes to the EEPROM and reading them back returns the written values.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "readback_ok" in output + assert "done" in output + + +SLICE_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) + +# Use start/end kwargs to send only a slice of the outgoing buffer. +out = bytearray([0xAA, 0x00, 0xBB]) +dest = bytearray(4) +with device: + # Only send the middle byte (the memory address 0x00). + device.write_then_readinto(out, dest, out_start=1, out_end=2, in_start=0, in_end=2) +print(f"partial read: {[hex(b) for b in dest]}") +# Only the first two entries should have been written by the read. +if dest[0] == 0xFF and dest[1] == 0xFF and dest[2] == 0x00 and dest[3] == 0x00: + print("slice_ok") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": SLICE_CODE}) +def test_i2cdevice_buffer_slices(circuitpython): + """write_then_readinto honors out_start/out_end and in_start/in_end bounds.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "slice_ok" in output + assert "done" in output + + +DISABLED_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +try: + device = I2CDevice(i2c, 0x50) + print("unexpected_success") +except (ValueError, OSError) as e: + print(f"probe_failed: {e}") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": DISABLED_CODE}) +@pytest.mark.disable_i2c_devices("eeprom@50") +def test_i2cdevice_probe_fails_when_device_disabled(circuitpython): + """Probe fails when the AT24 emulator device is disabled on the bus.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "probe_failed" in output + assert "unexpected_success" not in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_aesio.py b/ports/zephyr-cp/tests/test_aesio.py new file mode 100644 index 00000000000..3ae016ac8e3 --- /dev/null +++ b/ports/zephyr-cp/tests/test_aesio.py @@ -0,0 +1,223 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the aesio module.""" + +import pytest + +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + + +KEY = b"Sixteen byte key" +PLAINTEXT = b"CircuitPython!!!" # 16 bytes + + +ECB_CODE = """\ +import aesio + +key = b'Sixteen byte key' +inp = b'CircuitPython!!!' +outp = bytearray(len(inp)) +cipher = aesio.AES(key, aesio.MODE_ECB) +cipher.encrypt_into(inp, outp) +print(f"ciphertext_hex: {outp.hex()}") + +decrypted = bytearray(len(outp)) +cipher.decrypt_into(bytes(outp), decrypted) +print(f"decrypted: {bytes(decrypted)}") +print(f"match: {bytes(decrypted) == inp}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": ECB_CODE}) +def test_aesio_ecb(circuitpython): + """AES-ECB round-trips and matches CPython cryptography's output.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + encryptor = Cipher(algorithms.AES(KEY), modes.ECB()).encryptor() + expected_hex = (encryptor.update(PLAINTEXT) + encryptor.finalize()).hex() + assert f"ciphertext_hex: {expected_hex}" in output + assert "match: True" in output + assert "done" in output + + +IV = b"InitializationVe" # 16 bytes +CBC_PLAINTEXT = b"CircuitPython!!!" * 2 # 32 bytes, multiple of 16 +CTR_PLAINTEXT = b"CircuitPython is fun to use!" # 28 bytes, arbitrary length + + +CBC_CODE = """\ +import aesio + +key = b'Sixteen byte key' +iv = b'InitializationVe' +inp = b'CircuitPython!!!' * 2 +outp = bytearray(len(inp)) +cipher = aesio.AES(key, aesio.MODE_CBC, iv) +print(f"mode: {cipher.mode}") +cipher.encrypt_into(inp, outp) +print(f"ciphertext_hex: {outp.hex()}") + +# Re-create cipher to reset IV state for decryption. +cipher2 = aesio.AES(key, aesio.MODE_CBC, iv) +decrypted = bytearray(len(outp)) +cipher2.decrypt_into(bytes(outp), decrypted) +print(f"match: {bytes(decrypted) == inp}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": CBC_CODE}) +def test_aesio_cbc(circuitpython): + """AES-CBC round-trips and matches CPython cryptography's output.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + encryptor = Cipher(algorithms.AES(KEY), modes.CBC(IV)).encryptor() + expected_hex = (encryptor.update(CBC_PLAINTEXT) + encryptor.finalize()).hex() + assert "mode: 2" in output + assert f"ciphertext_hex: {expected_hex}" in output + assert "match: True" in output + assert "done" in output + + +CTR_CODE = """\ +import aesio + +key = b'Sixteen byte key' +iv = b'InitializationVe' +inp = b'CircuitPython is fun to use!' +outp = bytearray(len(inp)) +cipher = aesio.AES(key, aesio.MODE_CTR, iv) +print(f"mode: {cipher.mode}") +cipher.encrypt_into(inp, outp) +print(f"ciphertext_hex: {outp.hex()}") + +cipher2 = aesio.AES(key, aesio.MODE_CTR, iv) +decrypted = bytearray(len(outp)) +cipher2.decrypt_into(bytes(outp), decrypted) +print(f"decrypted: {bytes(decrypted)}") +print(f"match: {bytes(decrypted) == inp}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": CTR_CODE}) +def test_aesio_ctr(circuitpython): + """AES-CTR handles arbitrary-length buffers and matches CPython output.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + encryptor = Cipher(algorithms.AES(KEY), modes.CTR(IV)).encryptor() + expected_hex = (encryptor.update(CTR_PLAINTEXT) + encryptor.finalize()).hex() + assert "mode: 6" in output + assert f"ciphertext_hex: {expected_hex}" in output + assert "match: True" in output + assert "done" in output + + +REKEY_CODE = """\ +import aesio + +key1 = b'Sixteen byte key' +key2 = b'Another 16 byte!' +inp = b'CircuitPython!!!' + +cipher = aesio.AES(key1, aesio.MODE_ECB) +out1 = bytearray(16) +cipher.encrypt_into(inp, out1) +print(f"ct1_hex: {out1.hex()}") + +cipher.rekey(key2) +out2 = bytearray(16) +cipher.encrypt_into(inp, out2) +print(f"ct2_hex: {out2.hex()}") +print(f"different: {bytes(out1) != bytes(out2)}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": REKEY_CODE}) +def test_aesio_rekey(circuitpython): + """rekey() switches the active key; ciphertexts match CPython for both keys.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + enc1 = Cipher(algorithms.AES(b"Sixteen byte key"), modes.ECB()).encryptor() + ct1 = (enc1.update(PLAINTEXT) + enc1.finalize()).hex() + enc2 = Cipher(algorithms.AES(b"Another 16 byte!"), modes.ECB()).encryptor() + ct2 = (enc2.update(PLAINTEXT) + enc2.finalize()).hex() + assert f"ct1_hex: {ct1}" in output + assert f"ct2_hex: {ct2}" in output + assert "different: True" in output + assert "done" in output + + +MODE_PROPERTY_CODE = """\ +import aesio + +key = b'Sixteen byte key' +iv = b'InitializationVe' +cipher = aesio.AES(key, aesio.MODE_ECB) +print(f"initial: {cipher.mode}") +print(f"ECB={aesio.MODE_ECB} CBC={aesio.MODE_CBC} CTR={aesio.MODE_CTR}") + +for name, m in (("ECB", aesio.MODE_ECB), ("CBC", aesio.MODE_CBC), ("CTR", aesio.MODE_CTR)): + cipher.mode = m + print(f"set_{name}: {cipher.mode}") + +try: + cipher.mode = 99 +except NotImplementedError as e: + print(f"bad_mode: NotImplementedError") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": MODE_PROPERTY_CODE}) +def test_aesio_mode_property(circuitpython): + """The mode property is readable, writable, and rejects unsupported values.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "initial: 1" in output + assert "ECB=1 CBC=2 CTR=6" in output + assert "set_ECB: 1" in output + assert "set_CBC: 2" in output + assert "set_CTR: 6" in output + assert "bad_mode: NotImplementedError" in output + assert "done" in output + + +KEY_LENGTHS_CODE = """\ +import aesio + +inp = b'CircuitPython!!!' +for key in (b'A' * 16, b'B' * 24, b'C' * 32): + cipher = aesio.AES(key, aesio.MODE_ECB) + out = bytearray(16) + cipher.encrypt_into(inp, out) + print(f"len{len(key)}: {out.hex()}") + +try: + aesio.AES(b'too short', aesio.MODE_ECB) +except ValueError: + print("bad_key: ValueError") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": KEY_LENGTHS_CODE}) +def test_aesio_key_lengths(circuitpython): + """AES-128/192/256 keys all work and match CPython; bad key length raises.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + for key in (b"A" * 16, b"B" * 24, b"C" * 32): + encryptor = Cipher(algorithms.AES(key), modes.ECB()).encryptor() + expected = (encryptor.update(PLAINTEXT) + encryptor.finalize()).hex() + assert f"len{len(key)}: {expected}" in output + assert "bad_key: ValueError" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_audiobusio.py b/ports/zephyr-cp/tests/test_audiobusio.py new file mode 100644 index 00000000000..5a899139c22 --- /dev/null +++ b/ports/zephyr-cp/tests/test_audiobusio.py @@ -0,0 +1,216 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries LLC +# SPDX-License-Identifier: MIT + +"""Test audiobusio I2SOut functionality on native_sim.""" + +from pathlib import Path + +import pytest +from perfetto.trace_processor import TraceProcessor + + +I2S_PLAY_CODE = """\ +import array +import math +import audiocore +import board +import time + +# Generate a 440 Hz sine wave, 16-bit signed stereo at 16000 Hz +sample_rate = 16000 +length = sample_rate // 440 # ~36 samples per period +values = [] +for i in range(length): + v = int(math.sin(math.pi * 2 * i / length) * 30000) + values.append(v) # left + values.append(v) # right + +sample = audiocore.RawSample( + array.array("h", values), + sample_rate=sample_rate, + channel_count=2, +) + +dac = board.I2S0() +print("playing") +dac.play(sample, loop=True) +time.sleep(0.5) +dac.stop() +print("stopped") +print("done") +""" + + +def parse_i2s_trace(trace_file: Path, track_name: str) -> list[tuple[int, int]]: + """Parse I2S counter trace from Perfetto trace file.""" + tp = TraceProcessor(file_path=str(trace_file)) + result = tp.query( + f""" + SELECT c.ts, c.value + FROM counter c + JOIN track t ON c.track_id = t.id + WHERE t.name LIKE "%{track_name}" + ORDER BY c.ts + """ + ) + return [(int(row.ts), int(row.value)) for row in result] + + +@pytest.mark.duration(10) +@pytest.mark.circuitpy_drive({"code.py": I2S_PLAY_CODE}) +def test_i2s_play_and_stop(circuitpython): + """Test I2SOut play and stop produce expected output and correct waveform traces.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "playing" in output + assert "stopped" in output + assert "done" in output + + # Check that Perfetto trace has I2S counter tracks with data + left_trace = parse_i2s_trace(circuitpython.trace_file, "Left") + right_trace = parse_i2s_trace(circuitpython.trace_file, "Right") + + # Should have counter events (initial zero + audio data) + assert len(left_trace) > 10, f"Expected many Left channel events, got {len(left_trace)}" + assert len(right_trace) > 10, f"Expected many Right channel events, got {len(right_trace)}" + + # Verify timestamps are spread out (not all the same) + left_timestamps = [ts for ts, _ in left_trace] + assert left_timestamps[-1] > left_timestamps[1], "Timestamps should increase over time" + time_span_ns = left_timestamps[-1] - left_timestamps[1] + # We play for 0.5s, so span should be at least 100ms + assert time_span_ns > 100_000_000, f"Expected >100ms time span, got {time_span_ns / 1e6:.1f}ms" + + # Audio data should contain non-zero values (sine wave) + # Skip the initial zero value + left_values = [v for _, v in left_trace if v != 0] + right_values = [v for _, v in right_trace if v != 0] + assert len(left_values) > 5, "Left channel has too few non-zero values" + assert len(right_values) > 5, "Right channel has too few non-zero values" + + # Sine wave should have both positive and negative values + assert any(v > 0 for v in left_values), "Left channel has no positive values" + assert any(v < 0 for v in left_values), "Left channel has no negative values" + + # Verify amplitude is in the expected range (we generate with amplitude 30000) + max_left = max(left_values) + min_left = min(left_values) + assert max_left > 20000, f"Left max {max_left} too low, expected >20000" + assert min_left < -20000, f"Left min {min_left} too high, expected <-20000" + + # Left and right should match (we write the same value to both channels) + # Compare a subset of matching timestamps + left_by_ts = dict(left_trace) + right_by_ts = dict(right_trace) + common_ts = sorted(set(left_by_ts.keys()) & set(right_by_ts.keys())) + mismatches = 0 + for ts in common_ts[:100]: + if left_by_ts[ts] != right_by_ts[ts]: + mismatches += 1 + assert mismatches == 0, ( + f"{mismatches} L/R mismatches in first {min(100, len(common_ts))} common timestamps" + ) + + +I2S_PLAY_NO_STOP_CODE = """\ +import array +import math +import audiocore +import board +import time + +sample_rate = 16000 +length = sample_rate // 440 +values = [] +for i in range(length): + v = int(math.sin(math.pi * 2 * i / length) * 30000) + values.append(v) + values.append(v) + +sample = audiocore.RawSample( + array.array("h", values), + sample_rate=sample_rate, + channel_count=2, +) + +dac = board.I2S0() +dac.play(sample, loop=True) +print("playing") +time.sleep(0.2) +# Exit without calling dac.stop() — reset_port should clean up +print("exiting") +""" + + +@pytest.mark.duration(15) +@pytest.mark.code_py_runs(2) +@pytest.mark.circuitpy_drive({"code.py": I2S_PLAY_NO_STOP_CODE}) +def test_i2s_stops_on_code_exit(circuitpython): + """Test I2S is stopped by reset_port when code.py exits without explicit stop.""" + # First run: plays audio then exits without stopping + circuitpython.serial.wait_for("exiting") + circuitpython.serial.wait_for("Press any key to enter the REPL") + # Trigger soft reload + circuitpython.serial.write("\x04") + + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + # Should see "playing" and "exiting" at least twice (once per run) + assert output.count("playing") >= 2 + assert output.count("exiting") >= 2 + + +I2S_PAUSE_RESUME_CODE = """\ +import array +import math +import audiocore +import board +import time + +sample_rate = 16000 +length = sample_rate // 440 +values = [] +for i in range(length): + v = int(math.sin(math.pi * 2 * i / length) * 30000) + values.append(v) + values.append(v) + +sample = audiocore.RawSample( + array.array("h", values), + sample_rate=sample_rate, + channel_count=2, +) + +dac = board.I2S0() +dac.play(sample, loop=True) +print("playing") +time.sleep(0.2) + +dac.pause() +print("paused") +assert dac.paused +time.sleep(0.1) + +dac.resume() +print("resumed") +assert not dac.paused +time.sleep(0.2) + +dac.stop() +print("done") +""" + + +@pytest.mark.duration(10) +@pytest.mark.circuitpy_drive({"code.py": I2S_PAUSE_RESUME_CODE}) +def test_i2s_pause_resume(circuitpython): + """Test I2SOut pause and resume work correctly.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "playing" in output + assert "paused" in output + assert "resumed" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_basics.py b/ports/zephyr-cp/tests/test_basics.py index 9abb7f451b7..84b31849a8e 100644 --- a/ports/zephyr-cp/tests/test_basics.py +++ b/ports/zephyr-cp/tests/test_basics.py @@ -1,105 +1,22 @@ # SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries # SPDX-License-Identifier: MIT -"""Test LED blink functionality on native_sim.""" +"""Test basic native_sim functionality.""" -from conftest import InputTrigger, parse_gpio_trace +import pytest -def test_blank_flash_hello_world(run_circuitpython): +@pytest.mark.circuitpy_drive(None) +def test_blank_flash_hello_world(circuitpython): """Test that an erased flash shows code.py output header.""" - result = run_circuitpython(None, timeout=4, erase_flash=True) + circuitpython.wait_until_done() - assert "Board ID:native_native_sim" in result.output - assert "UID:" in result.output - assert "code.py output:" in result.output - assert "Hello World" in result.output - assert "done" in result.output - - -BLINK_CODE = """\ -import time -import board -import digitalio - -led = digitalio.DigitalInOut(board.LED) -led.direction = digitalio.Direction.OUTPUT - -for i in range(3): - print(f"LED on {i}") - led.value = True - time.sleep(0.1) - print(f"LED off {i}") - led.value = False - time.sleep(0.1) - -print("done") -""" - - -def test_blink_output(run_circuitpython): - """Test blink program produces expected output and GPIO traces.""" - result = run_circuitpython(BLINK_CODE, timeout=5) - - # Check serial output - assert "LED on 0" in result.output - assert "LED off 0" in result.output - assert "LED on 2" in result.output - assert "LED off 2" in result.output - assert "done" in result.output - - # Check GPIO traces - LED is on gpio_emul.00 - gpio_trace = parse_gpio_trace(result.trace_file, "gpio_emul.00") - - # Deduplicate by timestamp (keep last value at each timestamp) - by_timestamp = {} - for ts, val in gpio_trace: - by_timestamp[ts] = val - sorted_trace = sorted(by_timestamp.items()) - - # Find transition points (where value changes), skipping initialization at ts=0 - transitions = [] - for i in range(1, len(sorted_trace)): - prev_ts, prev_val = sorted_trace[i - 1] - curr_ts, curr_val = sorted_trace[i] - if prev_val != curr_val and curr_ts > 0: - transitions.append((curr_ts, curr_val)) - - # We expect at least 6 transitions (3 on + 3 off) from the blink loop - assert len(transitions) >= 6, f"Expected at least 6 transitions, got {len(transitions)}" - - # Verify timing between consecutive transitions - # Each sleep is 0.1s = 100ms = 100,000,000 ns - expected_interval_ns = 100_000_000 - tolerance_ns = 20_000_000 # 20ms tolerance - - # Find a sequence of 6 consecutive transitions with ~100ms intervals (the blink loop) - # This filters out initialization and cleanup noise - blink_transitions = [] - for i in range(len(transitions) - 1): - interval = transitions[i + 1][0] - transitions[i][0] - if abs(interval - expected_interval_ns) < tolerance_ns: - if not blink_transitions: - blink_transitions.append(transitions[i]) - blink_transitions.append(transitions[i + 1]) - elif blink_transitions: - # Found end of blink sequence - break - - assert len(blink_transitions) >= 6, ( - f"Expected at least 6 blink transitions with ~100ms intervals, got {len(blink_transitions)}" - ) - - # Verify timing between blink transitions - for i in range(1, min(6, len(blink_transitions))): - prev_ts = blink_transitions[i - 1][0] - curr_ts = blink_transitions[i][0] - interval = curr_ts - prev_ts - assert abs(interval - expected_interval_ns) < tolerance_ns, ( - f"Transition interval {interval / 1_000_000:.1f}ms deviates from " - f"expected {expected_interval_ns / 1_000_000:.1f}ms by more than " - f"{tolerance_ns / 1_000_000:.1f}ms tolerance" - ) + output = circuitpython.serial.all_output + assert "Board ID:native_native_sim" in output + assert "UID:" in output + assert "code.py output:" in output + assert "Hello World" in output + assert "done" in output # --- PTY Input Tests --- @@ -115,17 +32,17 @@ def test_blink_output(run_circuitpython): """ -def test_basic_serial_input(run_circuitpython): +@pytest.mark.circuitpy_drive({"code.py": INPUT_CODE}) +def test_basic_serial_input(circuitpython): """Test reading single character from serial via PTY write.""" - result = run_circuitpython( - INPUT_CODE, - timeout=5.0, - input_sequence=[InputTrigger(trigger="ready", data=b"A")], - ) + circuitpython.serial.wait_for("ready") + circuitpython.serial.write("A") + circuitpython.wait_until_done() - assert "ready" in result.output - assert "received: 'A'" in result.output - assert "done" in result.output + output = circuitpython.serial.all_output + assert "ready" in output + assert "received: 'A'" in output + assert "done" in output INPUT_FUNC_CODE = """\ @@ -136,18 +53,18 @@ def test_basic_serial_input(run_circuitpython): """ -def test_input_function(run_circuitpython): +@pytest.mark.circuitpy_drive({"code.py": INPUT_FUNC_CODE}) +def test_input_function(circuitpython): """Test the built-in input() function with PTY input.""" - result = run_circuitpython( - INPUT_FUNC_CODE, - timeout=5.0, - input_sequence=[InputTrigger(trigger="Enter name:", data=b"World\r")], - ) + circuitpython.serial.wait_for("Enter name:") + circuitpython.serial.write("World\r") + circuitpython.wait_until_done() - assert "ready" in result.output - assert "Enter name:" in result.output - assert "hello World" in result.output - assert "done" in result.output + output = circuitpython.serial.all_output + assert "ready" in output + assert "Enter name:" in output + assert "hello World" in output + assert "done" in output INTERRUPT_CODE = """\ @@ -161,18 +78,18 @@ def test_input_function(run_circuitpython): """ -def test_ctrl_c_interrupt(run_circuitpython): +@pytest.mark.circuitpy_drive({"code.py": INTERRUPT_CODE}) +def test_ctrl_c_interrupt(circuitpython): """Test sending Ctrl+C (0x03) to interrupt running code.""" - result = run_circuitpython( - INTERRUPT_CODE, - timeout=15.0, - input_sequence=[InputTrigger(trigger="loop 5", data=b"\x03")], - ) + circuitpython.serial.wait_for("loop 5") + circuitpython.serial.write("\x03") + circuitpython.wait_until_done() - assert "starting" in result.output - assert "loop 5" in result.output - assert "KeyboardInterrupt" in result.output - assert "completed" not in result.output + output = circuitpython.serial.all_output + assert "starting" in output + assert "loop 5" in output + assert "KeyboardInterrupt" in output + assert "completed" not in output RELOAD_CODE = """\ @@ -183,17 +100,18 @@ def test_ctrl_c_interrupt(run_circuitpython): """ -def test_ctrl_d_soft_reload(run_circuitpython): +@pytest.mark.circuitpy_drive({"code.py": RELOAD_CODE}) +@pytest.mark.code_py_runs(2) +def test_ctrl_d_soft_reload(circuitpython): """Test sending Ctrl+D (0x04) to trigger soft reload.""" - result = run_circuitpython( - RELOAD_CODE, - timeout=10.0, - input_sequence=[InputTrigger(trigger="first run", data=b"\x04")], - ) + circuitpython.serial.wait_for("first run") + circuitpython.serial.write("\x04") + circuitpython.wait_until_done() # Should see "first run" appear multiple times due to reload # or see a soft reboot message - assert "first run" in result.output + output = circuitpython.serial.all_output + assert "first run" in output # The soft reload should restart the code before "done" is printed - assert "done" in result.output - assert result.output.count("first run") > 1 + assert "done" in output + assert output.count("first run") > 1 diff --git a/ports/zephyr-cp/tests/test_digitalio.py b/ports/zephyr-cp/tests/test_digitalio.py new file mode 100644 index 00000000000..22c64f7b83f --- /dev/null +++ b/ports/zephyr-cp/tests/test_digitalio.py @@ -0,0 +1,171 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries LLC +# SPDX-License-Identifier: MIT + +"""Test digitalio functionality on native_sim.""" + +import re +from pathlib import Path + +import pytest +from perfetto.trace_processor import TraceProcessor + + +DIGITALIO_INPUT_TRACE_READ_CODE = """\ +import time +import digitalio +import microcontroller + +pin = digitalio.DigitalInOut(microcontroller.pin.P_01) +pin.direction = digitalio.Direction.INPUT + +start = time.monotonic() +last = pin.value +print(f"t_abs={time.monotonic():.3f} initial={last}") + +# Poll long enough to observe a high pulse injected through input trace. +while time.monotonic() - start < 8.0: + value = pin.value + if value != last: + print(f"t_abs={time.monotonic():.3f} edge={value}") + last = value + time.sleep(0.05) + +print(f"t_abs={time.monotonic():.3f} done") +""" + + +DIGITALIO_INPUT_TRACE = { + "gpio_emul.01": [ + (8_000_000_000, 0), + (9_000_000_000, 1), + (10_000_000_000, 0), + ], +} + + +@pytest.mark.duration(14.0) +@pytest.mark.circuitpy_drive({"code.py": DIGITALIO_INPUT_TRACE_READ_CODE}) +@pytest.mark.input_trace(DIGITALIO_INPUT_TRACE) +def test_digitalio_reads_input_trace(circuitpython): + """Test DigitalInOut input reads values injected via input trace.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + + initial_match = re.search(r"t_abs=([0-9]+\.[0-9]+) initial=False", output) + edge_match = re.search(r"t_abs=([0-9]+\.[0-9]+) edge=True", output) + done_match = re.search(r"t_abs=([0-9]+\.[0-9]+) done", output) + + assert initial_match is not None + assert edge_match is not None + assert done_match is not None + + initial_abs = float(initial_match.group(1)) + edge_abs = float(edge_match.group(1)) + done_abs = float(done_match.group(1)) + + # Input trace edge is at 9.0s for gpio_emul.01. + assert 8.5 <= edge_abs <= 9.5 + assert initial_abs <= edge_abs <= done_abs + + +BLINK_CODE = """\ +import time +import board +import digitalio + +led = digitalio.DigitalInOut(board.LED) +led.direction = digitalio.Direction.OUTPUT + +for i in range(3): + print(f"LED on {i}") + led.value = True + time.sleep(0.1) + print(f"LED off {i}") + led.value = False + time.sleep(0.1) + +print("done") +""" + + +def parse_gpio_trace(trace_file: Path, pin_name: str = "gpio_emul.00") -> list[tuple[int, int]]: + """Parse GPIO trace from Perfetto trace file.""" + tp = TraceProcessor(file_path=str(trace_file)) + result = tp.query( + f''' + SELECT c.ts, c.value + FROM counter c + JOIN track t ON c.track_id = t.id + WHERE t.name = "{pin_name}" + ORDER BY c.ts + ''' + ) + return [(row.ts, int(row.value)) for row in result] + + +@pytest.mark.circuitpy_drive({"code.py": BLINK_CODE}) +def test_digitalio_blink_output(circuitpython): + """Test blink program produces expected output and GPIO traces.""" + circuitpython.wait_until_done() + + # Check serial output + output = circuitpython.serial.all_output + assert "LED on 0" in output + assert "LED off 0" in output + assert "LED on 2" in output + assert "LED off 2" in output + assert "done" in output + + # Check GPIO traces - LED is on gpio_emul.00 + gpio_trace = parse_gpio_trace(circuitpython.trace_file, "gpio_emul.00") + + # Deduplicate by timestamp (keep last value at each timestamp) + by_timestamp = {} + for ts, val in gpio_trace: + by_timestamp[ts] = val + sorted_trace = sorted(by_timestamp.items()) + + # Find transition points (where value changes), skipping initialization at ts=0 + transitions = [] + for i in range(1, len(sorted_trace)): + prev_ts, prev_val = sorted_trace[i - 1] + curr_ts, curr_val = sorted_trace[i] + if prev_val != curr_val and curr_ts > 0: + transitions.append((curr_ts, curr_val)) + + # We expect at least 6 transitions (3 on + 3 off) from the blink loop + assert len(transitions) >= 6, f"Expected at least 6 transitions, got {len(transitions)}" + + # Verify timing between consecutive transitions + # Each sleep is 0.1s = 100ms = 100,000,000 ns + expected_interval_ns = 100_000_000 + tolerance_ns = 20_000_000 # 20ms tolerance + + # Find a sequence of 6 consecutive transitions with ~100ms intervals (the blink loop) + # This filters out initialization and cleanup noise + blink_transitions = [] + for i in range(len(transitions) - 1): + interval = transitions[i + 1][0] - transitions[i][0] + if abs(interval - expected_interval_ns) < tolerance_ns: + if not blink_transitions: + blink_transitions.append(transitions[i]) + blink_transitions.append(transitions[i + 1]) + elif blink_transitions: + # Found end of blink sequence + break + + assert len(blink_transitions) >= 6, ( + f"Expected at least 6 blink transitions with ~100ms intervals, got {len(blink_transitions)}" + ) + + # Verify timing between blink transitions + for i in range(1, min(6, len(blink_transitions))): + prev_ts = blink_transitions[i - 1][0] + curr_ts = blink_transitions[i][0] + interval = curr_ts - prev_ts + assert abs(interval - expected_interval_ns) < tolerance_ns, ( + f"Transition interval {interval / 1_000_000:.1f}ms deviates from " + f"expected {expected_interval_ns / 1_000_000:.1f}ms by more than " + f"{tolerance_ns / 1_000_000:.1f}ms tolerance" + ) diff --git a/ports/zephyr-cp/tests/test_flash.py b/ports/zephyr-cp/tests/test_flash.py new file mode 100644 index 00000000000..e2e5f4de14f --- /dev/null +++ b/ports/zephyr-cp/tests/test_flash.py @@ -0,0 +1,171 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test flash filesystem with various erase block sizes.""" + +import subprocess + +import pytest + + +def read_file_from_flash(flash_file, path): + """Extract a file from the FAT filesystem in the flash image.""" + result = subprocess.run( + ["mcopy", "-i", str(flash_file), f"::{path}", "-"], + capture_output=True, + ) + if result.returncode != 0: + raise FileNotFoundError( + f"Failed to read ::{path} from {flash_file}: {result.stderr.decode()}" + ) + return result.stdout.decode() + + +WRITE_READ_CODE = """\ +import storage +storage.remount("/", readonly=False) +with open("/test.txt", "w") as f: + f.write("hello flash") +with open("/test.txt", "r") as f: + content = f.read() +print(f"content: {content}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_READ_CODE}) +def test_flash_default_erase_size(circuitpython): + """Test filesystem write/read with default 4KB erase blocks.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "content: hello flash" in output + assert "done" in output + + content = read_file_from_flash(circuitpython.flash_file, "test.txt") + assert content == "hello flash" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_READ_CODE}) +@pytest.mark.flash_config(erase_block_size=65536) +def test_flash_64k_erase_blocks(circuitpython): + """Test filesystem write/read with 64KB erase blocks (128 blocks per page).""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "content: hello flash" in output + assert "done" in output + + content = read_file_from_flash(circuitpython.flash_file, "test.txt") + assert content == "hello flash" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_READ_CODE}) +@pytest.mark.flash_config(erase_block_size=262144, total_size=4 * 1024 * 1024) +def test_flash_256k_erase_blocks(circuitpython): + """Test filesystem write/read with 256KB erase blocks (like RA8D1 OSPI).""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "content: hello flash" in output + assert "done" in output + + content = read_file_from_flash(circuitpython.flash_file, "test.txt") + assert content == "hello flash" + + +MULTI_FILE_CODE = """\ +import storage +storage.remount("/", readonly=False) +for i in range(5): + name = f"/file{i}.txt" + with open(name, "w") as f: + f.write(f"data{i}" * 100) +print("multi_file_ok") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": MULTI_FILE_CODE}) +@pytest.mark.flash_config(erase_block_size=262144, total_size=4 * 1024 * 1024) +def test_flash_256k_multi_file(circuitpython): + """Test multiple file writes with 256KB erase blocks to exercise cache flushing.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "multi_file_ok" in output + + for i in range(5): + content = read_file_from_flash(circuitpython.flash_file, f"file{i}.txt") + assert content == f"data{i}" * 100, f"file{i}.txt mismatch" + + +EXISTING_DATA_CODE = """\ +import storage +storage.remount("/", readonly=False) + +# Write a file to populate the erase page. +original_data = "A" * 4000 +with open("/original.txt", "w") as f: + f.write(original_data) + +# Force a flush so the data is written to flash. +storage.remount("/", readonly=True) +storage.remount("/", readonly=False) + +# Now write a small new file. This updates FAT metadata and directory +# entries that share an erase page with original.txt, exercising the +# read-modify-write cycle on the cached page. +with open("/small.txt", "w") as f: + f.write("tiny") + +# Read back original to check it survived. +with open("/original.txt", "r") as f: + readback = f.read() +if readback == original_data: + print("existing_data_ok") +else: + print(f"MISMATCH: got {len(readback)} bytes") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": EXISTING_DATA_CODE}) +@pytest.mark.flash_config(erase_block_size=262144, total_size=4 * 1024 * 1024) +def test_flash_256k_existing_data_survives(circuitpython): + """Test that existing data in an erase page survives when new data is written. + + With 256KB erase blocks (512 blocks per page), writing to any block in + the page triggers an erase-rewrite of the entire page. Existing blocks + must be preserved through the read-modify-write cycle. + """ + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "existing_data_ok" in output + + # Verify both files survived on the actual flash image. + original = read_file_from_flash(circuitpython.flash_file, "original.txt") + assert original == "A" * 4000, f"original.txt corrupted: got {len(original)} bytes" + + small = read_file_from_flash(circuitpython.flash_file, "small.txt") + assert small == "tiny" + + +OVERWRITE_CODE = """\ +import storage +storage.remount("/", readonly=False) +with open("/overwrite.txt", "w") as f: + f.write("first version") +with open("/overwrite.txt", "w") as f: + f.write("second version") +print("overwrite_ok") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": OVERWRITE_CODE}) +@pytest.mark.flash_config(erase_block_size=262144, total_size=4 * 1024 * 1024) +def test_flash_256k_overwrite(circuitpython): + """Test overwriting a file with 256KB erase blocks to exercise erase-rewrite cycle.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "overwrite_ok" in output + + content = read_file_from_flash(circuitpython.flash_file, "overwrite.txt") + assert content == "second version" diff --git a/ports/zephyr-cp/tests/test_getpass.py b/ports/zephyr-cp/tests/test_getpass.py new file mode 100644 index 00000000000..541d91078b3 --- /dev/null +++ b/ports/zephyr-cp/tests/test_getpass.py @@ -0,0 +1,182 @@ +# SPDX-FileCopyrightText: 2026 Tim Cocks for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the getpass core module.""" + +import pytest + + +DEFAULT_PROMPT_CODE = """\ +import getpass + +print("ready") +pw = getpass.getpass() +print(f"got: {pw}") +print(f"length: {len(pw)}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": DEFAULT_PROMPT_CODE}) +def test_getpass_default_prompt(circuitpython): + """getpass() with no args prints 'Password: ' and returns the typed string.""" + circuitpython.serial.wait_for("ready") + circuitpython.serial.wait_for("Password:") + circuitpython.serial.write("hunter2\r") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "Password:" in output + assert "got: hunter2" in output + assert "length: 7" in output + assert "done" in output + + +CUSTOM_PROMPT_CODE = """\ +import getpass + +print("ready") +pw = getpass.getpass("Enter secret: ") +print(f"got: {pw}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": CUSTOM_PROMPT_CODE}) +def test_getpass_custom_prompt(circuitpython): + """A user-supplied prompt string is written before reading input.""" + circuitpython.serial.wait_for("Enter secret:") + circuitpython.serial.write("s3cr3t\r") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "Enter secret:" in output + assert "got: s3cr3t" in output + assert "done" in output + + +NO_ECHO_CODE = """\ +import getpass + +print("ready") +pw = getpass.getpass("Pwd: ") +print("---boundary---") +print(f"got: {pw}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": NO_ECHO_CODE}) +def test_getpass_does_not_echo(circuitpython): + """Characters typed during getpass are not echoed back to the terminal.""" + circuitpython.serial.wait_for("Pwd:") + secret = "TopSecret123" + circuitpython.serial.write(secret + "\r") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + # Split around the boundary: nothing typed should appear before it, + # but the printed value appears after. + pre, _, post = output.partition("---boundary---") + assert secret not in pre + assert f"got: {secret}" in post + assert "done" in post + + +BACKSPACE_CODE = """\ +import getpass + +print("ready") +pw = getpass.getpass("P: ") +print(f"got: {pw}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": BACKSPACE_CODE}) +def test_getpass_backspace(circuitpython): + """Backspace (0x7f) removes the previous character from the buffer.""" + circuitpython.serial.wait_for("P:") + # Type "abcX", then backspace, then "d" -> "abcd" + circuitpython.serial.write("abcX\x7fd\r") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "got: abcd" in output + assert "done" in output + + +CTRL_C_CODE = """\ +import getpass + +print("ready") +try: + getpass.getpass("Pwd: ") + print("no exception") +except KeyboardInterrupt: + print("interrupted") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": CTRL_C_CODE}) +def test_getpass_ctrl_c_raises_keyboard_interrupt(circuitpython): + """Sending Ctrl+C while getpass is reading raises KeyboardInterrupt.""" + circuitpython.serial.wait_for("Pwd:") + circuitpython.serial.write("\x03") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "interrupted" in output + assert "no exception" not in output + assert "done" in output + + +CTRL_D_EMPTY_CODE = """\ +import getpass + +print("ready") +try: + getpass.getpass("Pwd: ") + print("no exception") +except EOFError: + print("eof") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": CTRL_D_EMPTY_CODE}) +def test_getpass_ctrl_d_empty_raises_eof(circuitpython): + """Ctrl+D with an empty buffer raises EOFError.""" + circuitpython.serial.wait_for("Pwd:") + circuitpython.serial.write("\x04") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "eof" in output + assert "no exception" not in output + assert "done" in output + + +EMPTY_INPUT_CODE = """\ +import getpass + +print("ready") +pw = getpass.getpass("Pwd: ") +print(f"length: {len(pw)}") +print(f"empty: {pw == ''}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": EMPTY_INPUT_CODE}) +def test_getpass_empty_input(circuitpython): + """Pressing return immediately yields an empty string.""" + circuitpython.serial.wait_for("Pwd:") + circuitpython.serial.write("\r") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "length: 0" in output + assert "empty: True" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_hashlib.py b/ports/zephyr-cp/tests/test_hashlib.py new file mode 100644 index 00000000000..94463ba1e99 --- /dev/null +++ b/ports/zephyr-cp/tests/test_hashlib.py @@ -0,0 +1,152 @@ +# SPDX-FileCopyrightText: 2026 Tim Cocks for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the hashlib module against CPython hashlib.""" + +import hashlib + +import pytest + + +SHORT_DATA = b"CircuitPython!" +CHUNK_A = b"Hello, " +CHUNK_B = b"CircuitPython world!" +LONG_DATA = b"The quick brown fox jumps over the lazy dog." * 64 + + +SHA256_CODE = """\ +import hashlib + +h = hashlib.new("sha256", b"CircuitPython!") +print(f"digest_size: {h.digest_size}") +print(f"digest_hex: {h.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": SHA256_CODE}) +def test_hashlib_sha256_basic(circuitpython): + """sha256 digest on a small buffer matches CPython hashlib.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + expected = hashlib.sha256(SHORT_DATA).hexdigest() + assert "digest_size: 32" in output + assert f"digest_hex: {expected}" in output + assert "done" in output + + +SHA1_CODE = """\ +import hashlib + +h = hashlib.new("sha1", b"CircuitPython!") +print(f"digest_size: {h.digest_size}") +print(f"digest_hex: {h.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": SHA1_CODE}) +def test_hashlib_sha1_basic(circuitpython): + """sha1 digest on a small buffer matches CPython hashlib.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + expected = hashlib.sha1(SHORT_DATA).hexdigest() + assert "digest_size: 20" in output + assert f"digest_hex: {expected}" in output + assert "done" in output + + +UPDATE_CODE = """\ +import hashlib + +h = hashlib.new("sha256") +h.update(b"Hello, ") +h.update(b"CircuitPython world!") +print(f"chunked_hex: {h.digest().hex()}") + +h2 = hashlib.new("sha256", b"Hello, CircuitPython world!") +print(f"oneshot_hex: {h2.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": UPDATE_CODE}) +def test_hashlib_sha256_update_chunks(circuitpython): + """Multiple update() calls produce the same digest as a single buffer, and match CPython.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + expected = hashlib.sha256(CHUNK_A + CHUNK_B).hexdigest() + assert f"chunked_hex: {expected}" in output + assert f"oneshot_hex: {expected}" in output + assert "done" in output + + +LONG_CODE = """\ +import hashlib + +data = b"The quick brown fox jumps over the lazy dog." * 64 +h = hashlib.new("sha256", data) +print(f"sha256_hex: {h.digest().hex()}") + +h1 = hashlib.new("sha1", data) +print(f"sha1_hex: {h1.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": LONG_CODE}) +def test_hashlib_long_input(circuitpython): + """Digests of a multi-block input match CPython for both sha1 and sha256.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"sha256_hex: {hashlib.sha256(LONG_DATA).hexdigest()}" in output + assert f"sha1_hex: {hashlib.sha1(LONG_DATA).hexdigest()}" in output + assert "done" in output + + +EMPTY_CODE = """\ +import hashlib + +h = hashlib.new("sha256", b"") +print(f"empty256: {h.digest().hex()}") + +h = hashlib.new("sha1", b"") +print(f"empty1: {h.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": EMPTY_CODE}) +def test_hashlib_empty_input(circuitpython): + """Empty-input digests match CPython well-known values.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"empty256: {hashlib.sha256(b'').hexdigest()}" in output + assert f"empty1: {hashlib.sha1(b'').hexdigest()}" in output + assert "done" in output + + +BAD_ALGO_CODE = """\ +import hashlib + +try: + hashlib.new("md5", b"data") +except ValueError: + print("bad_algo: ValueError") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": BAD_ALGO_CODE}) +def test_hashlib_unsupported_algorithm(circuitpython): + """Unsupported algorithm names raise ValueError.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "bad_algo: ValueError" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_i2c.py b/ports/zephyr-cp/tests/test_i2c.py index 594dfcc8f4d..ec5229faa2f 100644 --- a/ports/zephyr-cp/tests/test_i2c.py +++ b/ports/zephyr-cp/tests/test_i2c.py @@ -3,6 +3,8 @@ """Test I2C functionality on native_sim.""" +import pytest + I2C_SCAN_CODE = """\ import board @@ -17,18 +19,20 @@ """ -def test_i2c_scan(run_circuitpython): +@pytest.mark.circuitpy_drive({"code.py": I2C_SCAN_CODE}) +def test_i2c_scan(circuitpython): """Test I2C bus scanning finds emulated devices. The AT24 EEPROM emulator responds to zero-length probe writes, so it should appear in scan results at address 0x50. """ - result = run_circuitpython(I2C_SCAN_CODE, timeout=5.0) + circuitpython.wait_until_done() - assert "I2C devices:" in result.output + output = circuitpython.serial.all_output + assert "I2C devices:" in output # AT24 EEPROM should be at address 0x50 - assert "0x50" in result.output - assert "done" in result.output + assert "0x50" in output + assert "done" in output AT24_READ_CODE = """\ @@ -61,38 +65,38 @@ def test_i2c_scan(run_circuitpython): """ -def test_i2c_at24_read(run_circuitpython): +@pytest.mark.circuitpy_drive({"code.py": AT24_READ_CODE}) +def test_i2c_at24_read(circuitpython): """Test reading from AT24 EEPROM emulator.""" - result = run_circuitpython(AT24_READ_CODE, timeout=5.0) + circuitpython.wait_until_done() - assert "AT24 byte 0: 0xFF" in result.output - assert "eeprom_valid" in result.output - assert "done" in result.output + output = circuitpython.serial.all_output + assert "AT24 byte 0: 0xFF" in output + assert "eeprom_valid" in output + assert "done" in output -def test_i2c_device_disabled(run_circuitpython): +@pytest.mark.circuitpy_drive({"code.py": I2C_SCAN_CODE}) +@pytest.mark.disable_i2c_devices("eeprom@50") +def test_i2c_device_disabled(circuitpython): """Test that disabled I2C device doesn't appear in scan.""" - result = run_circuitpython( - I2C_SCAN_CODE, - timeout=5.0, - disabled_i2c_devices=["eeprom@50"], - ) + circuitpython.wait_until_done() - assert "I2C devices:" in result.output + output = circuitpython.serial.all_output + assert "I2C devices:" in output # AT24 at 0x50 should NOT appear when disabled - assert "0x50" not in result.output - assert "done" in result.output + assert "0x50" not in output + assert "done" in output -def test_i2c_device_disabled_communication_fails(run_circuitpython): +@pytest.mark.circuitpy_drive({"code.py": AT24_READ_CODE}) +@pytest.mark.disable_i2c_devices("eeprom@50") +def test_i2c_device_disabled_communication_fails(circuitpython): """Test that communication with disabled I2C device fails.""" - result = run_circuitpython( - AT24_READ_CODE, - timeout=5.0, - disabled_i2c_devices=["eeprom@50"], - ) + circuitpython.wait_until_done() + output = circuitpython.serial.all_output # Should get an I2C error when trying to communicate - assert "I2C error" in result.output - assert "eeprom_valid" not in result.output - assert "done" in result.output + assert "I2C error" in output + assert "eeprom_valid" not in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_msgpack.py b/ports/zephyr-cp/tests/test_msgpack.py new file mode 100644 index 00000000000..09bed35209c --- /dev/null +++ b/ports/zephyr-cp/tests/test_msgpack.py @@ -0,0 +1,137 @@ +# SPDX-FileCopyrightText: 2026 Tim Cocks for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the msgpack module.""" + +import pytest + + +ROUNDTRIP_CODE = """\ +import msgpack +from io import BytesIO + +obj = {"list": [True, False, None, 1, 3.125], "str": "blah"} +b = BytesIO() +msgpack.pack(obj, b) +encoded = b.getvalue() +print(f"encoded_len: {len(encoded)}") +print(f"encoded_hex: {encoded.hex()}") + +b.seek(0) +decoded = msgpack.unpack(b) +print(f"decoded: {decoded}") +print(f"match: {decoded == obj}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": ROUNDTRIP_CODE}) +def test_msgpack_roundtrip(circuitpython): + """Pack and unpack a dict containing the basic msgpack types.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "match: True" in output + assert "done" in output + + +USE_LIST_CODE = """\ +import msgpack +from io import BytesIO + +b = BytesIO() +msgpack.pack([1, 2, 3], b) + +b.seek(0) +as_list = msgpack.unpack(b) +print(f"as_list: {as_list} type={type(as_list).__name__}") + +b.seek(0) +as_tuple = msgpack.unpack(b, use_list=False) +print(f"as_tuple: {as_tuple} type={type(as_tuple).__name__}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": USE_LIST_CODE}) +def test_msgpack_use_list(circuitpython): + """use_list=False should return a tuple instead of a list.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "as_list: [1, 2, 3] type=list" in output + assert "as_tuple: (1, 2, 3) type=tuple" in output + assert "done" in output + + +EXTTYPE_CODE = """\ +from msgpack import pack, unpack, ExtType +from io import BytesIO + +class MyClass: + def __init__(self, val): + self.value = val + +data = MyClass(b"my_value") + +def encoder(obj): + if isinstance(obj, MyClass): + return ExtType(1, obj.value) + return f"no encoder for {obj}" + +def decoder(code, data): + if code == 1: + return MyClass(data) + return f"no decoder for type {code}" + +buf = BytesIO() +pack(data, buf, default=encoder) +buf.seek(0) +decoded = unpack(buf, ext_hook=decoder) +print(f"decoded_type: {type(decoded).__name__}") +print(f"decoded_value: {decoded.value}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": EXTTYPE_CODE}) +def test_msgpack_exttype(circuitpython): + """ExtType with a custom encoder/decoder should round-trip.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "decoded_type: MyClass" in output + assert "decoded_value: b'my_value'" in output + assert "done" in output + + +EXTTYPE_PROPS_CODE = """\ +from msgpack import ExtType + +e = ExtType(5, b"hello") +print(f"code: {e.code}") +print(f"data: {e.data}") + +e.code = 10 +print(f"new_code: {e.code}") + +try: + ExtType(128, b"x") +except (ValueError, OverflowError) as ex: + print(f"range_error: {type(ex).__name__}") + +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": EXTTYPE_PROPS_CODE}) +def test_msgpack_exttype_properties(circuitpython): + """ExtType exposes code/data as read/write properties and rejects out-of-range codes.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "code: 5" in output + assert "data: b'hello'" in output + assert "new_code: 10" in output + assert "range_error:" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_nvm.py b/ports/zephyr-cp/tests/test_nvm.py new file mode 100644 index 00000000000..5de304afc1b --- /dev/null +++ b/ports/zephyr-cp/tests/test_nvm.py @@ -0,0 +1,73 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test NVM functionality on native_sim.""" + +import pytest + + +NVM_BASIC_CODE = """\ +import microcontroller + +nvm = microcontroller.nvm +print(f"nvm length: {len(nvm)}") + +# Write some bytes +nvm[0] = 42 +nvm[1] = 99 +print(f"nvm[0]: {nvm[0]}") +print(f"nvm[1]: {nvm[1]}") + +# Write a slice +nvm[2:5] = b"\\x01\\x02\\x03" +print(f"nvm[2:5]: {list(nvm[2:5])}") + +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": NVM_BASIC_CODE}) +def test_nvm_read_write(circuitpython): + """Test basic NVM read and write operations.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "nvm length: 8192" in output + assert "nvm[0]: 42" in output + assert "nvm[1]: 99" in output + assert "nvm[2:5]: [1, 2, 3]" in output + assert "done" in output + + +NVM_PERSIST_CODE = """\ +import microcontroller + +nvm = microcontroller.nvm +value = nvm[0] +print(f"nvm[0]: {value}") + +if value == 255: + # First run: write a marker + nvm[0] = 123 + print("wrote marker") +else: + print(f"marker found: {value}") + +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": NVM_PERSIST_CODE}) +@pytest.mark.code_py_runs(2) +def test_nvm_persists_across_reload(circuitpython): + """Test that NVM data persists across soft reloads.""" + circuitpython.serial.wait_for("wrote marker") + # Trigger soft reload + circuitpython.serial.write("\x04") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "nvm[0]: 255" in output + assert "wrote marker" in output + assert "marker found: 123" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_rotaryio.py b/ports/zephyr-cp/tests/test_rotaryio.py new file mode 100644 index 00000000000..e9a5c1913cb --- /dev/null +++ b/ports/zephyr-cp/tests/test_rotaryio.py @@ -0,0 +1,132 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries LLC +# SPDX-License-Identifier: MIT + +"""Test rotaryio functionality on native_sim.""" + +import pytest + + +ROTARY_CODE_5S = """\ +import time +import microcontroller +import rotaryio + +encoder = rotaryio.IncrementalEncoder(microcontroller.pin.P_01, microcontroller.pin.P_02) + +time.sleep(5.0) # Sleep long enough for trace events to complete +print(f"position={encoder.position}") +print("done") +""" + + +ROTARY_CODE_7S = """\ +import time +import microcontroller +import rotaryio + +encoder = rotaryio.IncrementalEncoder(microcontroller.pin.P_01, microcontroller.pin.P_02) + +time.sleep(7.0) # Sleep long enough for trace events to complete +print(f"position={encoder.position}") +print("done") +""" + + +CLOCKWISE_TRACE = { + "gpio_emul.01": [ + (4_000_000_000, 0), # 4.0s: initial state (low) + (4_100_000_000, 1), # 4.1s: A goes high (A leads) + (4_300_000_000, 0), # 4.3s: A goes low + ], + "gpio_emul.02": [ + (4_000_000_000, 0), # 4.0s: initial state (low) + (4_200_000_000, 1), # 4.2s: B goes high (B follows) + (4_400_000_000, 0), # 4.4s: B goes low + ], +} + +COUNTERCLOCKWISE_TRACE = { + "gpio_emul.01": [ + (4_000_000_000, 0), # 4.0s: initial state (low) + (4_200_000_000, 1), # 4.2s: A goes high (A follows) + (4_400_000_000, 0), # 4.4s: A goes low + ], + "gpio_emul.02": [ + (4_000_000_000, 0), # 4.0s: initial state (low) + (4_100_000_000, 1), # 4.1s: B goes high (B leads) + (4_300_000_000, 0), # 4.3s: B goes low + ], +} + +BOTH_DIRECTIONS_TRACE = { + "gpio_emul.01": [ + (4_000_000_000, 0), # Initial state + # First clockwise detent + (4_100_000_000, 1), # A rises (leads) + (4_300_000_000, 0), # A falls + # Second clockwise detent + (4_500_000_000, 1), # A rises (leads) + (4_700_000_000, 0), # A falls + # First counter-clockwise detent + (5_000_000_000, 1), # A rises (follows) + (5_200_000_000, 0), # A falls + # Second counter-clockwise detent + (5_400_000_000, 1), # A rises (follows) + (5_600_000_000, 0), # A falls + # Third counter-clockwise detent + (5_800_000_000, 1), # A rises (follows) + (6_000_000_000, 0), # A falls + ], + "gpio_emul.02": [ + (4_000_000_000, 0), # Initial state + # First clockwise detent + (4_200_000_000, 1), # B rises (follows) + (4_400_000_000, 0), # B falls + # Second clockwise detent + (4_600_000_000, 1), # B rises (follows) + (4_800_000_000, 0), # B falls + # First counter-clockwise detent + (4_900_000_000, 1), # B rises (leads) + (5_100_000_000, 0), # B falls + # Second counter-clockwise detent + (5_300_000_000, 1), # B rises (leads) + (5_500_000_000, 0), # B falls + # Third counter-clockwise detent + (5_700_000_000, 1), # B rises (leads) + (5_900_000_000, 0), # B falls + ], +} + + +@pytest.mark.circuitpy_drive({"code.py": ROTARY_CODE_5S}) +@pytest.mark.input_trace(CLOCKWISE_TRACE) +def test_rotaryio_incrementalencoder_clockwise(circuitpython): + """Test clockwise rotation increments position.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "position=1" in output + assert "done" in output + + +@pytest.mark.circuitpy_drive({"code.py": ROTARY_CODE_5S}) +@pytest.mark.input_trace(COUNTERCLOCKWISE_TRACE) +def test_rotaryio_incrementalencoder_counterclockwise(circuitpython): + """Test counter-clockwise rotation decrements position.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "position=-1" in output + assert "done" in output + + +@pytest.mark.duration(12.0) +@pytest.mark.circuitpy_drive({"code.py": ROTARY_CODE_7S}) +@pytest.mark.input_trace(BOTH_DIRECTIONS_TRACE) +def test_rotaryio_incrementalencoder_both_directions(circuitpython): + """Test rotation in both directions: 2 clockwise, then 3 counter-clockwise.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "position=-1" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_storage.py b/ports/zephyr-cp/tests/test_storage.py new file mode 100644 index 00000000000..33e63e5ea85 --- /dev/null +++ b/ports/zephyr-cp/tests/test_storage.py @@ -0,0 +1,162 @@ +# SPDX-FileCopyrightText: 2026 Tim Cocks for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the `storage` core module on native_sim.""" + +import pytest + + +REMOUNT_READWRITE_CODE = """\ +import storage +storage.remount("/", readonly=False) +with open("/rw.txt", "w") as f: + f.write("writable") +with open("/rw.txt", "r") as f: + print(f"content: {f.read()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": REMOUNT_READWRITE_CODE}) +def test_storage_remount_readwrite(circuitpython): + """remount with readonly=False allows writes to /.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "content: writable" in output + assert "done" in output + + +REMOUNT_READONLY_CODE = """\ +import storage +storage.remount("/", readonly=True) +try: + with open("/should_fail.txt", "w") as f: + f.write("nope") + print("unexpected: write succeeded") +except OSError as e: + print(f"caught OSError: errno={e.errno}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": REMOUNT_READONLY_CODE}) +def test_storage_remount_readonly_blocks_writes(circuitpython): + """remount with readonly=True prevents writes to /.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "caught OSError" in output + assert "unexpected: write succeeded" not in output + assert "done" in output + + +GETMOUNT_CODE = """\ +import storage +mount = storage.getmount("/") +print(f"type: {type(mount).__name__}") +print(f"readonly: {mount.readonly}") +# label attribute should be accessible +print(f"label: {mount.label!r}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": GETMOUNT_CODE}) +def test_storage_getmount(circuitpython): + """getmount('/') returns the VfsFat object for the root mount.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "type: VfsFat" in output + assert "readonly:" in output + assert "label:" in output + assert "done" in output + + +GETMOUNT_MISSING_CODE = """\ +import storage +try: + storage.getmount("/does_not_exist") + print("unexpected: getmount succeeded") +except OSError as e: + print(f"caught OSError: errno={e.errno}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": GETMOUNT_MISSING_CODE}) +def test_storage_getmount_missing(circuitpython): + """getmount on an unmounted path raises OSError.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "caught OSError" in output + assert "unexpected: getmount succeeded" not in output + assert "done" in output + + +REMOUNT_PERSISTS_CODE = """\ +import storage +storage.remount("/", readonly=False) +with open("/persist.txt", "w") as f: + f.write("across-reload") +print("wrote persist.txt") +""" + +REMOUNT_PERSISTS_READ_CODE = """\ +with open("/persist.txt", "r") as f: + print(f"readback: {f.read()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": REMOUNT_PERSISTS_CODE}) +@pytest.mark.code_py_runs(2) +def test_storage_remount_persists_across_reload(circuitpython): + """Data written after remount(readonly=False) persists across soft reload.""" + circuitpython.serial.wait_for("wrote persist.txt") + # Replace code.py via raw REPL-style approach: write new file then reload. + # Simpler: just trigger a soft reload and check the file is still there. + circuitpython.serial.write("\x04") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "wrote persist.txt" in output + + +LABEL_CODE = """\ +import storage +storage.remount("/", readonly=False) +mount = storage.getmount("/") +mount.label = "CIRCUITPY" +print(f"label: {mount.label!r}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": LABEL_CODE}) +def test_storage_set_label(circuitpython): + """VfsFat.label can be set when mounted read-write.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "label: 'CIRCUITPY'" in output + assert "done" in output + + +UMOUNT_MISSING_CODE = """\ +import storage +# Unmounting an unmounted path should raise. +try: + storage.umount("/not_mounted") + print("unexpected: umount succeeded") +except OSError as e: + print(f"umount OSError: errno={e.errno}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": UMOUNT_MISSING_CODE}) +def test_storage_umount_missing(circuitpython): + """umount on an unmounted path raises OSError.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "umount OSError" in output + assert "unexpected:" not in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_web_workflow.py b/ports/zephyr-cp/tests/test_web_workflow.py new file mode 100644 index 00000000000..d3a00782a33 --- /dev/null +++ b/ports/zephyr-cp/tests/test_web_workflow.py @@ -0,0 +1,142 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Tests for web workflow on native_sim.""" + +from __future__ import annotations + +import json +import re + +import pytest +import requests + + +pytestmark = pytest.mark.native_sim_rt + +WEB_WORKFLOW_PORT = 8090 +WEB_WORKFLOW_PASSWORD = "testpass" + +WEB_WORKFLOW_CODE = """\ +import time + +# Keep the VM alive while the web workflow starts. +time.sleep(3) +""" + +WEB_WORKFLOW_UPDATED_CODE = """\ +print("updated") +""" + +WEB_WORKFLOW_SETTINGS = f"""\ +CIRCUITPY_WEB_API_PASSWORD="{WEB_WORKFLOW_PASSWORD}" +CIRCUITPY_WEB_API_PORT={WEB_WORKFLOW_PORT} +""" + +WEB_WORKFLOW_SETTINGS_PORT_80 = f"""\ +CIRCUITPY_WEB_API_PASSWORD="{WEB_WORKFLOW_PASSWORD}" +CIRCUITPY_WEB_API_PORT=80 +""" + +WEB_WORKFLOW_BOOT = """\ +import storage + +storage.remount("/", readonly=False) +""" + + +@pytest.mark.circuitpy_drive( + { + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS, + } +) +def test_web_workflow_hostnetwork(circuitpython): + """Ensure web workflow responds over hostnetwork.""" + circuitpython.serial.wait_for(f"127.0.0.1:{WEB_WORKFLOW_PORT}") + response = requests.get(f"http://127.0.0.1:{WEB_WORKFLOW_PORT}/edit/", timeout=1.0) + + assert response.status_code == 401 + + +@pytest.mark.circuitpy_drive( + { + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS, + } +) +def test_web_workflow_version_json_hostnetwork_ip_and_port(circuitpython): + """Ensure /cp/version.json reports hostnetwork endpoint with configured port.""" + circuitpython.serial.wait_for(f"127.0.0.1:{WEB_WORKFLOW_PORT}") + response = requests.get( + f"http://127.0.0.1:{WEB_WORKFLOW_PORT}/cp/version.json", + auth=("", WEB_WORKFLOW_PASSWORD), + timeout=1.0, + ) + + assert response.status_code == 200 + + payload = json.loads(response.text) + assert payload["ip"] == "127.0.0.1" + assert payload["port"] == WEB_WORKFLOW_PORT + + +@pytest.mark.circuitpy_drive( + { + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS, + } +) +def test_web_workflow_status_line_hostnetwork_non_default_port(circuitpython): + """Status line should include hostnetwork IP and non-default port.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + + # Remove ANSI control sequences before matching. + output = re.sub(r"\x1b\[[0-9;]*[A-Za-z]", "", output) + assert "127.0.0.1:8090" in output + + +@pytest.mark.circuitpy_drive( + { + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS_PORT_80, + } +) +def test_web_workflow_status_line_hostnetwork_default_port(circuitpython): + """Status line should show IP without :80 for default HTTP port.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + + output = re.sub(r"\x1b\[[0-9;]*[A-Za-z]", "", output) + assert "127.0.0.1" in output + assert "127.0.0.1:80" not in output + + +@pytest.mark.circuitpy_drive( + { + "boot.py": WEB_WORKFLOW_BOOT, + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS, + } +) +def test_web_workflow_write_code_py_remount(circuitpython): + """Ensure web workflow can update code.py after remounting.""" + circuitpython.serial.wait_for(f"127.0.0.1:{WEB_WORKFLOW_PORT}") + body = WEB_WORKFLOW_UPDATED_CODE.encode("utf-8") + + response = requests.put( + f"http://127.0.0.1:{WEB_WORKFLOW_PORT}/fs/code.py", + auth=("", WEB_WORKFLOW_PASSWORD), + data=body, + timeout=1.0, + ) + assert response.status_code in (201, 204) + + response = requests.get( + f"http://127.0.0.1:{WEB_WORKFLOW_PORT}/fs/code.py", + auth=("", WEB_WORKFLOW_PASSWORD), + timeout=1.0, + ) + assert response.status_code == 200 + assert WEB_WORKFLOW_UPDATED_CODE in response.text diff --git a/ports/zephyr-cp/tests/test_zlib.py b/ports/zephyr-cp/tests/test_zlib.py new file mode 100644 index 00000000000..bd89d8e1c25 --- /dev/null +++ b/ports/zephyr-cp/tests/test_zlib.py @@ -0,0 +1,110 @@ +# SPDX-FileCopyrightText: 2026 Tim Cocks for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the zlib module against CPython zlib. + +CircuitPython's zlib only implements ``decompress``; these tests compress data +with CPython and verify the zephyr-cp port decodes it back to the same bytes. +""" + +import zlib + +import pytest + + +PLAIN_TEXT = b"CircuitPython running on Zephyr says hello!" +REPEATED_TEXT = b"The quick brown fox jumps over the lazy dog. " * 32 +BINARY_BLOB = bytes(range(256)) * 4 + + +def _make_code(compressed: bytes, wbits: int, expected_len: int) -> str: + return ( + "import zlib\n" + f"compressed = {compressed!r}\n" + f"out = zlib.decompress(compressed, {wbits})\n" + f'print(f"out_len: {{len(out)}}")\n' + f'print(f"expected_len: {expected_len}")\n' + 'print(f"out_hex: {out.hex()}")\n' + 'print("done")\n' + ) + + +ZLIB_COMPRESSED = zlib.compress(PLAIN_TEXT) +ZLIB_CODE = _make_code(ZLIB_COMPRESSED, wbits=15, expected_len=len(PLAIN_TEXT)) + + +@pytest.mark.circuitpy_drive({"code.py": ZLIB_CODE}) +def test_zlib_decompress_zlib_format(circuitpython): + """Data produced by CPython zlib.compress() round-trips through CircuitPython zlib.decompress().""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(PLAIN_TEXT)}" in output + assert f"out_hex: {PLAIN_TEXT.hex()}" in output + assert "done" in output + + +REPEATED_COMPRESSED = zlib.compress(REPEATED_TEXT) +REPEATED_CODE = _make_code(REPEATED_COMPRESSED, wbits=15, expected_len=len(REPEATED_TEXT)) + + +@pytest.mark.circuitpy_drive({"code.py": REPEATED_CODE}) +def test_zlib_decompress_repeated(circuitpython): + """Highly-compressible repeated input decompresses correctly (back-references).""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(REPEATED_TEXT)}" in output + # Repeated text has many back-references; shrinks a lot. + assert len(REPEATED_COMPRESSED) < len(REPEATED_TEXT) // 4 + assert f"out_hex: {REPEATED_TEXT.hex()}" in output + assert "done" in output + + +BINARY_COMPRESSED = zlib.compress(BINARY_BLOB) +BINARY_CODE = _make_code(BINARY_COMPRESSED, wbits=15, expected_len=len(BINARY_BLOB)) + + +@pytest.mark.circuitpy_drive({"code.py": BINARY_CODE}) +def test_zlib_decompress_binary_bytes(circuitpython): + """Decompression preserves every byte value (0x00-0xFF).""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(BINARY_BLOB)}" in output + assert f"out_hex: {BINARY_BLOB.hex()}" in output + assert "done" in output + + +# Raw DEFLATE stream (no zlib header/trailer). +_raw_compressor = zlib.compressobj(wbits=-15) +RAW_COMPRESSED = _raw_compressor.compress(PLAIN_TEXT) + _raw_compressor.flush() +RAW_CODE = _make_code(RAW_COMPRESSED, wbits=-15, expected_len=len(PLAIN_TEXT)) + + +@pytest.mark.circuitpy_drive({"code.py": RAW_CODE}) +def test_zlib_decompress_raw_deflate(circuitpython): + """Raw DEFLATE streams (wbits=-15) decompress to the original bytes.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(PLAIN_TEXT)}" in output + assert f"out_hex: {PLAIN_TEXT.hex()}" in output + assert "done" in output + + +# Gzip wrapper (wbits=31). +_gzip_compressor = zlib.compressobj(wbits=31) +GZIP_COMPRESSED = _gzip_compressor.compress(PLAIN_TEXT) + _gzip_compressor.flush() +GZIP_CODE = _make_code(GZIP_COMPRESSED, wbits=31, expected_len=len(PLAIN_TEXT)) + + +@pytest.mark.circuitpy_drive({"code.py": GZIP_CODE}) +def test_zlib_decompress_gzip_format(circuitpython): + """Gzip-wrapped streams (wbits=31) decompress to the original bytes.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(PLAIN_TEXT)}" in output + assert f"out_hex: {PLAIN_TEXT.hex()}" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/zephyr_display/README.md b/ports/zephyr-cp/tests/zephyr_display/README.md new file mode 100644 index 00000000000..6b502021543 --- /dev/null +++ b/ports/zephyr-cp/tests/zephyr_display/README.md @@ -0,0 +1,45 @@ +# Zephyr Display Golden Tests + +This directory contains native_sim golden-image tests for the Zephyr-specific `zephyr_display` path. + +## What is tested + +- `board.DISPLAY` is present and usable. +- CircuitPython terminal/console tilegrids are attached to the default display root group. +- Deterministic console terminal output matches a checked-in golden image. +- `zephyr_display` pixel format constants are exposed. +- `displayio` rendering produces expected stripe colors at sampled pixel locations. + +## Files + +- `test_zephyr_display.py` – pytest tests. +- `golden/terminal_console_output_320x240.png` – console terminal output golden reference image. + +## How capture works + +These tests use trace-driven SDL display capture triggered by Perfetto instant events: + +- `--input-trace=` provides a Perfetto trace containing a `"display_capture"` track + with instant events at the desired capture timestamps. +- `--display_capture_png=` specifies the output PNG pattern (may contain `%d` for + a sequence number). +- `--display_headless` runs SDL in headless/hidden-window mode (always enabled for native_sim tests). + +The test harness sets these flags automatically when tests use +`@pytest.mark.display(capture_times_ns=[...])`. + +## Regenerating the console golden image + +```bash +rm -rf /tmp/zephyr-display-golden +pytest -q ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py::test_console_output_golden \ + --basetemp=/tmp/zephyr-display-golden +cp /tmp/zephyr-display-golden/test_console_output_golden0/frame_0.png \ + ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.png +``` + +## Running the tests + +```bash +pytest -q ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py +``` diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240.png new file mode 100644 index 00000000000..5739b8ee156 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_AL_88.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_AL_88.png new file mode 100644 index 00000000000..6bdb72b802c Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_AL_88.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_ARGB_8888.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_ARGB_8888.png new file mode 100644 index 00000000000..90b422792db Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_ARGB_8888.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_BGR_565.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_BGR_565.png new file mode 100644 index 00000000000..5739b8ee156 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_BGR_565.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_L_8.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_L_8.png new file mode 100644 index 00000000000..6bdb72b802c Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_L_8.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO01.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO01.png new file mode 100644 index 00000000000..b22de4417ab Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO01.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO10.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO10.png new file mode 100644 index 00000000000..b22de4417ab Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO10.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_565.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_565.png new file mode 100644 index 00000000000..5739b8ee156 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_565.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_888.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_888.png new file mode 100644 index 00000000000..c4301da47c5 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_888.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_00_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_00_320x240.png new file mode 100644 index 00000000000..8f7fc051365 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_00_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_01_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_01_320x240.png new file mode 100644 index 00000000000..67d17856c7d Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_01_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_02_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_02_320x240.png new file mode 100644 index 00000000000..99c832b68ec Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_02_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_03_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_03_320x240.png new file mode 100644 index 00000000000..38f403a2ad3 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_03_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_04_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_04_320x240.png new file mode 100644 index 00000000000..2a6649a0014 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_04_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_05_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_05_320x240.png new file mode 100644 index 00000000000..507a9290937 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_05_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_06_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_06_320x240.png new file mode 100644 index 00000000000..217b98f680b Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_06_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_07_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_07_320x240.png new file mode 100644 index 00000000000..507a9290937 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_07_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_08_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_08_320x240.png new file mode 100644 index 00000000000..2a6649a0014 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_08_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_09_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_09_320x240.png new file mode 100644 index 00000000000..38f403a2ad3 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_09_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_10_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_10_320x240.png new file mode 100644 index 00000000000..99c832b68ec Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_10_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_11_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_11_320x240.png new file mode 100644 index 00000000000..67d17856c7d Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_11_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_12_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_12_320x240.png new file mode 100644 index 00000000000..8f7fc051365 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/gifio_frame_12_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/jpegio_test_pattern_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/jpegio_test_pattern_320x240.png new file mode 100644 index 00000000000..4987b76ff80 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/jpegio_test_pattern_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.mask.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.mask.png new file mode 100644 index 00000000000..c675e2e5fa7 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.mask.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.png new file mode 100644 index 00000000000..77577a65601 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_AL_88.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_AL_88.png new file mode 100644 index 00000000000..f9ceedebe4a Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_AL_88.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_ARGB_8888.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_ARGB_8888.png new file mode 100644 index 00000000000..90b422792db Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_ARGB_8888.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_BGR_565.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_BGR_565.png new file mode 100644 index 00000000000..77577a65601 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_BGR_565.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_L_8.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_L_8.png new file mode 100644 index 00000000000..f9ceedebe4a Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_L_8.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01.png new file mode 100644 index 00000000000..59928bcd107 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01_no_vtiled.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01_no_vtiled.png new file mode 100644 index 00000000000..59928bcd107 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01_no_vtiled.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10.png new file mode 100644 index 00000000000..59928bcd107 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10_no_vtiled.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10_no_vtiled.png new file mode 100644 index 00000000000..59928bcd107 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10_no_vtiled.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_565.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_565.png new file mode 100644 index 00000000000..77577a65601 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_565.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_888.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_888.png new file mode 100644 index 00000000000..28d51925cae Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_888.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/test.gif b/ports/zephyr-cp/tests/zephyr_display/test.gif new file mode 100644 index 00000000000..4f96816a1f0 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/test.gif differ diff --git a/ports/zephyr-cp/tests/zephyr_display/test.jpg b/ports/zephyr-cp/tests/zephyr_display/test.jpg new file mode 100644 index 00000000000..488357f506a Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/test.jpg differ diff --git a/ports/zephyr-cp/tests/zephyr_display/test_gifio.py b/ports/zephyr-cp/tests/zephyr_display/test_gifio.py new file mode 100644 index 00000000000..d4a665e2d44 --- /dev/null +++ b/ports/zephyr-cp/tests/zephyr_display/test_gifio.py @@ -0,0 +1,201 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +import shutil +from pathlib import Path + +import pytest +from PIL import Image + + +_TEST_GIF_PATH = Path(__file__).parent / "test.gif" +_TEST_GIF_BYTES = _TEST_GIF_PATH.read_bytes() + + +def _read_image(path: Path) -> tuple[int, int, bytes]: + with Image.open(path) as img: + rgb = img.convert("RGB") + return rgb.width, rgb.height, rgb.tobytes() + + +def _golden_compare_or_update(request, captures, golden_path): + if not captures or not captures[0].exists(): + pytest.skip("display capture was not produced") + + if request.config.getoption("--update-goldens"): + golden_path.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(captures[0], golden_path) + return + + gw, gh, gpx = _read_image(golden_path) + dw, dh, dpx = _read_image(captures[0]) + assert (dw, dh) == (gw, gh) + assert gpx == dpx + + +GIFIO_METADATA_CODE = """\ +import gifio + +odg = gifio.OnDiskGif('/test.gif') +print('size', odg.width, odg.height) +print('frame_count', odg.frame_count) +print('duration', round(odg.duration, 3)) +print('min_delay', round(odg.min_delay, 3)) +print('max_delay', round(odg.max_delay, 3)) + +delay = odg.next_frame() +print('delay', round(delay, 3)) + +bitmap = odg.bitmap +print('bitmap_size', bitmap.width, bitmap.height) + +for i in range(min(odg.width, 8)): + print('px', i, hex(bitmap[i, 0])) + +odg.deinit() +print('deinited') + +try: + odg.next_frame() +except Exception as e: + print('after_deinit', type(e).__name__) + +print('done') +""" + + +GIFIO_DECODE_CODE = """\ +import board +import displayio +import time +from gifio import OnDiskGif + +odg = OnDiskGif('/test.gif') +print('size', odg.width, odg.height) +print('frame_count', odg.frame_count) + +scale = 10 +tg = displayio.TileGrid( + odg.bitmap, + pixel_shader=displayio.ColorConverter( + input_colorspace=displayio.Colorspace.RGB565_SWAPPED + ), +) +g = displayio.Group(scale=scale) +g.x = (board.DISPLAY.width - odg.width * scale) // 2 +g.y = (board.DISPLAY.height - odg.height * scale) // 2 +g.append(tg) + +board.DISPLAY.auto_refresh = False +board.DISPLAY.root_group = g + +# Pin the render loop to a known point in simulated time so that the +# capture_times_ns schedule below lands on each GIF frame while it is on screen. +LOOP_START = 10.0 +FRAME_HOLD = 2.0 +while time.monotonic() < LOOP_START: + time.sleep(0.05) +print('loop_start', round(time.monotonic(), 3)) + +for frame_index in range(odg.frame_count): + odg.next_frame() + board.DISPLAY.refresh() + print('rendered', frame_index, round(time.monotonic(), 3)) + # Hold this frame on screen; the capture for this frame is scheduled + # for the middle of this window. + target = LOOP_START + (frame_index + 1) * FRAME_HOLD + while time.monotonic() < target: + time.sleep(0.05) + +print('done') +while True: + time.sleep(1) +""" + + +# Keep these in sync with LOOP_START / FRAME_HOLD in GIFIO_DECODE_CODE. +_DECODE_LOOP_START_S = 10.0 +_DECODE_FRAME_HOLD_S = 2.0 +_DECODE_FRAME_COUNT = 13 +# Capture at the midpoint of each frame's hold window. +_DECODE_CAPTURE_TIMES_NS = [ + int( + (_DECODE_LOOP_START_S + i * _DECODE_FRAME_HOLD_S + _DECODE_FRAME_HOLD_S / 2) + * 1_000_000_000 + ) + for i in range(_DECODE_FRAME_COUNT) +] + + +GIFIO_WRITER_CODE = """\ +import displayio +import gifio +import os + +width, height = 8, 4 +buf = bytearray(width * height * 2) +for i in range(width * height): + # RGB565 gradient + value = (i * 0x0841) & 0xFFFF + buf[2 * i] = (value >> 8) & 0xFF + buf[2 * i + 1] = value & 0xFF + +path = '/out.gif' +with gifio.GifWriter(path, width, height, displayio.Colorspace.RGB565, loop=True) as writer: + writer.add_frame(buf, 0.1) + writer.add_frame(buf, 0.2) + +size = os.stat(path)[6] +print('wrote_size', size) + +with open(path, 'rb') as f: + header = f.read(6) +print('header', header) + +print('done') +""" + + +_GIFIO_METADATA_DRIVE = {"code.py": GIFIO_METADATA_CODE, "test.gif": _TEST_GIF_BYTES} +_GIFIO_DECODE_DRIVE = {"code.py": GIFIO_DECODE_CODE, "test.gif": _TEST_GIF_BYTES} +_GIFIO_WRITER_DRIVE = {"code.py": GIFIO_WRITER_CODE} + + +@pytest.mark.circuitpy_drive(_GIFIO_METADATA_DRIVE) +def test_gifio_metadata(circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "size 16 16" in output + assert "frame_count 13" in output + assert "bitmap_size 16 16" in output + assert "min_delay 0.08" in output + assert "max_delay 0.08" in output + # 13 frames * 0.08s = 1.04s + assert "duration 1.04" in output + assert "delay 0.08" in output + assert "deinited" in output + # Using a deinited OnDiskGif should raise an exception. + assert "after_deinit" in output + assert "done" in output + + +@pytest.mark.circuitpy_drive(_GIFIO_DECODE_DRIVE) +@pytest.mark.display(capture_times_ns=_DECODE_CAPTURE_TIMES_NS) +@pytest.mark.duration(60) +def test_gifio_decode(request, circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "size 16 16" in output + assert "frame_count 13" in output + for frame_index in range(_DECODE_FRAME_COUNT): + assert f"rendered {frame_index}" in output + assert "done" in output + + captures = circuitpython.display_capture_paths() + assert len(captures) == _DECODE_FRAME_COUNT + golden_dir = Path(__file__).parent / "golden" + for frame_index, capture in enumerate(captures): + golden = golden_dir / f"gifio_frame_{frame_index:02d}_320x240.png" + _golden_compare_or_update(request, [capture], golden) diff --git a/ports/zephyr-cp/tests/zephyr_display/test_jpegio.py b/ports/zephyr-cp/tests/zephyr_display/test_jpegio.py new file mode 100644 index 00000000000..6368be7a5cf --- /dev/null +++ b/ports/zephyr-cp/tests/zephyr_display/test_jpegio.py @@ -0,0 +1,87 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +import shutil +from pathlib import Path + +import pytest +from PIL import Image + + +_TEST_JPG_PATH = Path(__file__).parent / "test.jpg" +_TEST_JPG_BYTES = _TEST_JPG_PATH.read_bytes() + + +def _read_image(path: Path) -> tuple[int, int, bytes]: + with Image.open(path) as img: + rgb = img.convert("RGB") + return rgb.width, rgb.height, rgb.tobytes() + + +def _golden_compare_or_update(request, captures, golden_path): + if not captures or not captures[0].exists(): + pytest.skip("display capture was not produced") + + if request.config.getoption("--update-goldens"): + golden_path.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(captures[0], golden_path) + return + + gw, gh, gpx = _read_image(golden_path) + dw, dh, dpx = _read_image(captures[0]) + assert (dw, dh) == (gw, gh) + assert gpx == dpx + + +JPEGIO_DECODE_CODE = """\ +import board +import displayio +import time +from jpegio import JpegDecoder + +decoder = JpegDecoder() +width, height = decoder.open("/test.jpg") +print('size', width, height) + +bitmap = displayio.Bitmap(width, height, 65535) +decoder.decode(bitmap) + +for i in range(min(width, 8)): + print('px', i, hex(bitmap[i, 0])) + +scale = 10 +tg = displayio.TileGrid( + bitmap, + pixel_shader=displayio.ColorConverter( + input_colorspace=displayio.Colorspace.RGB565_SWAPPED + ), +) +g = displayio.Group(scale=scale) +g.x = (board.DISPLAY.width - width * scale) // 2 +g.y = (board.DISPLAY.height - height * scale) // 2 +g.append(tg) + +board.DISPLAY.auto_refresh = False +board.DISPLAY.root_group = g +board.DISPLAY.refresh() +print('rendered') +while True: + time.sleep(1) +""" + + +_JPEGIO_DRIVE = {"code.py": JPEGIO_DECODE_CODE, "test.jpg": _TEST_JPG_BYTES} + + +@pytest.mark.circuitpy_drive(_JPEGIO_DRIVE) +@pytest.mark.display(capture_times_ns=[14_000_000_000]) +@pytest.mark.duration(18) +def test_jpegio_decode(request, circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "size 20 20" in output + assert "rendered" in output + + golden = Path(__file__).parent / "golden" / "jpegio_test_pattern_320x240.png" + _golden_compare_or_update(request, circuitpython.display_capture_paths(), golden) diff --git a/ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py b/ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py new file mode 100644 index 00000000000..6700c42ec4a --- /dev/null +++ b/ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py @@ -0,0 +1,365 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +import colorsys +import shutil +import struct +from pathlib import Path + +import pytest +from PIL import Image + + +def _read_image(path: Path) -> tuple[int, int, bytes]: + """Read an image file and return (width, height, RGB bytes).""" + with Image.open(path) as img: + rgb = img.convert("RGB") + return rgb.width, rgb.height, rgb.tobytes() + + +def _read_mask(golden_path: Path) -> bytes | None: + """Load the companion mask PNG for a golden image, if it exists. + + Non-zero pixels are masked (skipped during comparison). + """ + mask_path = golden_path.with_suffix(".mask.png") + if not mask_path.exists(): + return None + with Image.open(mask_path) as img: + return img.convert("L").tobytes() + + +def _assert_pixels_equal_masked( + golden_pixels: bytes, actual_pixels: bytes, mask: bytes | None = None +): + """Assert pixels match, skipping positions where the mask is non-zero.""" + assert len(golden_pixels) == len(actual_pixels) + for i in range(0, len(golden_pixels), 3): + if mask is not None and mask[i // 3] != 0: + continue + if golden_pixels[i : i + 3] != actual_pixels[i : i + 3]: + pixel = i // 3 + assert False, ( + f"Pixel {pixel} mismatch: " + f"golden={tuple(golden_pixels[i : i + 3])} " + f"actual={tuple(actual_pixels[i : i + 3])}" + ) + + +BOARD_DISPLAY_AVAILABLE_CODE = """\ +import board +print(hasattr(board, 'DISPLAY')) +print(type(board.DISPLAY).__name__) +print(board.DISPLAY.width, board.DISPLAY.height) +print('done') +""" + + +@pytest.mark.circuitpy_drive({"code.py": BOARD_DISPLAY_AVAILABLE_CODE}) +@pytest.mark.display +@pytest.mark.duration(8) +def test_board_display_available(circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "True" in output + assert "Display" in output + assert "320 240" in output + assert "done" in output + + +CONSOLE_TERMINAL_PRESENT_CODE = """\ +import board + +root = board.DISPLAY.root_group +has_terminal_tilegrids = ( + type(root).__name__ == 'Group' and + len(root) >= 2 and + type(root[0]).__name__ == 'TileGrid' and + type(root[-1]).__name__ == 'TileGrid' +) +print('has_terminal_tilegrids:', has_terminal_tilegrids) +print('done') +""" + + +@pytest.mark.circuitpy_drive({"code.py": CONSOLE_TERMINAL_PRESENT_CODE}) +@pytest.mark.display +@pytest.mark.duration(8) +def test_console_terminal_present_by_default(circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "has_terminal_tilegrids: True" in output + assert "done" in output + + +CONSOLE_OUTPUT_GOLDEN_CODE = """\ +import time +time.sleep(0.25) +print('done') +while True: + time.sleep(1) +""" + + +def _golden_compare_or_update(request, captures, golden_path, mask_path=None): + """Compare captured PNG against golden, or update golden if --update-goldens. + + mask_path overrides the default companion mask lookup (golden.mask.png). + """ + if not captures or not captures[0].exists(): + pytest.skip("display capture was not produced") + + if request.config.getoption("--update-goldens"): + golden_path.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(captures[0], golden_path) + return + + gw, gh, gpx = _read_image(golden_path) + dw, dh, dpx = _read_image(captures[0]) + if mask_path is not None: + mask = _read_mask(mask_path) + else: + mask = _read_mask(golden_path) + + assert (dw, dh) == (gw, gh) + _assert_pixels_equal_masked(gpx, dpx, mask) + + +@pytest.mark.circuitpy_drive({"code.py": CONSOLE_OUTPUT_GOLDEN_CODE}) +@pytest.mark.display(capture_times_ns=[4_000_000_000]) +@pytest.mark.duration(8) +def test_console_output_golden(request, circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "done" in output + + golden = Path(__file__).parent / "golden" / "terminal_console_output_320x240.png" + _golden_compare_or_update(request, circuitpython.display_capture_paths(), golden) + + +PIXEL_FORMATS = ["ARGB_8888", "RGB_888", "RGB_565", "BGR_565", "L_8", "AL_88", "MONO01", "MONO10"] + +# Shared mask: the same screen regions vary regardless of pixel format. +_CONSOLE_GOLDEN_MASK = Path(__file__).parent / "golden" / "terminal_console_output_320x240.png" + + +@pytest.mark.circuitpy_drive({"code.py": CONSOLE_OUTPUT_GOLDEN_CODE}) +@pytest.mark.display(capture_times_ns=[4_000_000_000]) +@pytest.mark.duration(8) +@pytest.mark.parametrize( + "pixel_format", + PIXEL_FORMATS, + indirect=True, +) +def test_console_output_golden_pixel_format(pixel_format, request, circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "done" in output + + golden_name = f"terminal_console_output_320x240_{pixel_format}.png" + golden = Path(__file__).parent / "golden" / golden_name + _golden_compare_or_update( + request, circuitpython.display_capture_paths(), golden, _CONSOLE_GOLDEN_MASK + ) + + +MONO_NO_VTILED_FORMATS = ["MONO01", "MONO10"] + + +@pytest.mark.circuitpy_drive({"code.py": CONSOLE_OUTPUT_GOLDEN_CODE}) +@pytest.mark.display(capture_times_ns=[4_000_000_000]) +@pytest.mark.display_mono_vtiled(False) +@pytest.mark.duration(8) +@pytest.mark.parametrize( + "pixel_format", + MONO_NO_VTILED_FORMATS, + indirect=True, +) +def test_console_output_golden_mono_no_vtiled(pixel_format, request, circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "done" in output + + golden_name = f"terminal_console_output_320x240_{pixel_format}_no_vtiled.png" + golden = Path(__file__).parent / "golden" / golden_name + _golden_compare_or_update( + request, circuitpython.display_capture_paths(), golden, _CONSOLE_GOLDEN_MASK + ) + + +def _generate_gradient_bmp(width, height): + """Generate a 24-bit BMP with HSL color gradient. + + Hue sweeps left to right, lightness goes from black (bottom) to white (top), + saturation is 1.0. + """ + row_size = width * 3 + row_padding = (4 - (row_size % 4)) % 4 + padded_row_size = row_size + row_padding + pixel_data_size = padded_row_size * height + file_size = 14 + 40 + pixel_data_size + + header = struct.pack( + "<2sIHHI", + b"BM", + file_size, + 0, + 0, + 14 + 40, + ) + info = struct.pack( + "stack_adjust < 0x100) { emit_al(as, asm_arm_op_sub_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust)); } else { - asm_arm_mov_reg_i32_optimised(as, ASM_ARM_REG_R8, as->stack_adjust); - emit_al(as, asm_arm_op_sub_reg(ASM_ARM_REG_SP, ASM_ARM_REG_SP, ASM_ARM_REG_R8)); + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, as->stack_adjust); + emit_al(as, asm_arm_op_sub_reg(ASM_ARM_REG_SP, ASM_ARM_REG_SP, REG_TEMP)); } } } @@ -182,8 +182,8 @@ void asm_arm_exit(asm_arm_t *as) { if (as->stack_adjust < 0x100) { emit_al(as, asm_arm_op_add_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust)); } else { - asm_arm_mov_reg_i32_optimised(as, ASM_ARM_REG_R8, as->stack_adjust); - emit_al(as, asm_arm_op_add_reg(ASM_ARM_REG_SP, ASM_ARM_REG_SP, ASM_ARM_REG_R8)); + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, as->stack_adjust); + emit_al(as, asm_arm_op_add_reg(ASM_ARM_REG_SP, ASM_ARM_REG_SP, REG_TEMP)); } } @@ -293,10 +293,10 @@ void asm_arm_orr_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { void asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num) { if (local_num >= 0x40) { - // mov r8, #local_num*4 - // add rd, sp, r8 - asm_arm_mov_reg_i32_optimised(as, ASM_ARM_REG_R8, local_num << 2); - emit_al(as, asm_arm_op_add_reg(rd, ASM_ARM_REG_SP, ASM_ARM_REG_R8)); + // mov temp, #local_num*4 + // add rd, sp, temp + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, local_num << 2); + emit_al(as, asm_arm_op_add_reg(rd, ASM_ARM_REG_SP, REG_TEMP)); } else { // add rd, sp, #local_num*4 emit_al(as, asm_arm_op_add_imm(rd, ASM_ARM_REG_SP, local_num << 2)); @@ -333,14 +333,22 @@ void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs) { emit_al(as, 0x1a00050 | (rd << 12) | (rs << 8) | rd); } -void asm_arm_ldr_reg_reg(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { - // ldr rd, [rn, #off] - emit_al(as, 0x5900000 | (rn << 16) | (rd << 12) | byte_offset); +void asm_arm_ldr_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { + if (byte_offset < 0x1000) { + // ldr rd, [rn, #off] + emit_al(as, 0x5900000 | (rn << 16) | (rd << 12) | byte_offset); + } else { + // mov temp, #off + // ldr rd, [rn, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x7900000 | (rn << 16) | (rd << 12) | REG_TEMP); + } } -void asm_arm_ldrh_reg_reg(asm_arm_t *as, uint rd, uint rn) { - // ldrh rd, [rn] - emit_al(as, 0x1d000b0 | (rn << 16) | (rd << 12)); +void asm_arm_ldrh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { + // ldrh doesn't support scaled register index + emit_al(as, 0x1a00080 | (REG_TEMP << 12) | rn); // mov temp, rn, lsl #1 + emit_al(as, 0x19000b0 | (rm << 16) | (rd << 12) | REG_TEMP); // ldrh rd, [rm, temp]; } void asm_arm_ldrh_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { @@ -348,31 +356,69 @@ void asm_arm_ldrh_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offs // ldrh rd, [rn, #off] emit_al(as, 0x1d000b0 | (rn << 16) | (rd << 12) | ((byte_offset & 0xf0) << 4) | (byte_offset & 0xf)); } else { - // mov r8, #off - // ldrh rd, [rn, r8] - asm_arm_mov_reg_i32_optimised(as, ASM_ARM_REG_R8, byte_offset); - emit_al(as, 0x19000b0 | (rn << 16) | (rd << 12) | ASM_ARM_REG_R8); + // mov temp, #off + // ldrh rd, [rn, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x19000b0 | (rn << 16) | (rd << 12) | REG_TEMP); } } -void asm_arm_ldrb_reg_reg(asm_arm_t *as, uint rd, uint rn) { - // ldrb rd, [rn] - emit_al(as, 0x5d00000 | (rn << 16) | (rd << 12)); +void asm_arm_ldrb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { + // ldrb rd, [rm, rn] + emit_al(as, 0x7d00000 | (rm << 16) | (rd << 12) | rn); +} + +void asm_arm_ldrb_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { + if (byte_offset < 0x1000) { + // ldrb rd, [rn, #off] + emit_al(as, 0x5d00000 | (rn << 16) | (rd << 12) | byte_offset); + } else { + // mov temp, #off + // ldrb rd, [rn, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x7d00000 | (rn << 16) | (rd << 12) | REG_TEMP); + } } -void asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm, uint byte_offset) { - // str rd, [rm, #off] - emit_al(as, 0x5800000 | (rm << 16) | (rd << 12) | byte_offset); +void asm_arm_ldr_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { + // ldr rd, [rm, rn, lsl #2] + emit_al(as, 0x7900100 | (rm << 16) | (rd << 12) | rn); } -void asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm) { - // strh rd, [rm] - emit_al(as, 0x1c000b0 | (rm << 16) | (rd << 12)); +void asm_arm_str_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset) { + if (byte_offset < 0x1000) { + // str rd, [rm, #off] + emit_al(as, 0x5800000 | (rm << 16) | (rd << 12) | byte_offset); + } else { + // mov temp, #off + // str rd, [rm, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x7800000 | (rm << 16) | (rd << 12) | REG_TEMP); + } } -void asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm) { - // strb rd, [rm] - emit_al(as, 0x5c00000 | (rm << 16) | (rd << 12)); +void asm_arm_strh_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { + if (byte_offset < 0x100) { + // strh rd, [rn, #off] + emit_al(as, 0x1c000b0 | (rn << 16) | (rd << 12) | ((byte_offset & 0xf0) << 4) | (byte_offset & 0xf)); + } else { + // mov temp, #off + // strh rd, [rn, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x18000b0 | (rn << 16) | (rd << 12) | REG_TEMP); + } +} + +void asm_arm_strb_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset) { + if (byte_offset < 0x1000) { + // strb rd, [rm, #off] + emit_al(as, 0x5c00000 | (rm << 16) | (rd << 12) | byte_offset); + } else { + // mov temp, #off + // strb rd, [rm, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x7c00000 | (rm << 16) | (rd << 12) | REG_TEMP); + } } void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { @@ -382,8 +428,8 @@ void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { void asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { // strh doesn't support scaled register index - emit_al(as, 0x1a00080 | (ASM_ARM_REG_R8 << 12) | rn); // mov r8, rn, lsl #1 - emit_al(as, 0x18000b0 | (rm << 16) | (rd << 12) | ASM_ARM_REG_R8); // strh rd, [rm, r8] + emit_al(as, 0x1a00080 | (REG_TEMP << 12) | rn); // mov temp, rn, lsl #1 + emit_al(as, 0x18000b0 | (rm << 16) | (rd << 12) | REG_TEMP); // strh rd, [rm, temp] } void asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { @@ -398,7 +444,7 @@ void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label) { rel -= 8; // account for instruction prefetch, PC is 8 bytes ahead of this instruction rel >>= 2; // in ARM mode the branch target is 32-bit aligned, so the 2 LSB are omitted - if (SIGNED_FIT24(rel)) { + if (MP_FIT_SIGNED(24, rel)) { emit(as, cond | 0xa000000 | (rel & 0xffffff)); } else { printf("asm_arm_bcc: branch does not fit in 24 bits\n"); diff --git a/py/asmarm.h b/py/asmarm.h index a0e057fce44..f3fd586a375 100644 --- a/py/asmarm.h +++ b/py/asmarm.h @@ -109,13 +109,18 @@ void asm_arm_lsr_reg_reg(asm_arm_t *as, uint rd, uint rs); void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs); // memory -void asm_arm_ldr_reg_reg(asm_arm_t *as, uint rd, uint rn, uint byte_offset); -void asm_arm_ldrh_reg_reg(asm_arm_t *as, uint rd, uint rn); +void asm_arm_ldr_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset); void asm_arm_ldrh_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset); -void asm_arm_ldrb_reg_reg(asm_arm_t *as, uint rd, uint rn); -void asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm, uint byte_offset); -void asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm); -void asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm); +void asm_arm_ldrb_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset); +void asm_arm_str_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset); +void asm_arm_strh_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset); +void asm_arm_strb_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset); + +// load from array +void asm_arm_ldr_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); +void asm_arm_ldrh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); +void asm_arm_ldrb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); + // store to array void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); void asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); @@ -160,12 +165,12 @@ void asm_arm_bx_reg(asm_arm_t *as, uint reg_src); // Holds a pointer to mp_fun_table #define REG_FUN_TABLE ASM_ARM_REG_FUN_TABLE -#define ASM_T asm_arm_t -#define ASM_END_PASS asm_arm_end_pass -#define ASM_ENTRY asm_arm_entry -#define ASM_EXIT asm_arm_exit +#define ASM_T asm_arm_t +#define ASM_END_PASS asm_arm_end_pass +#define ASM_ENTRY(as, num_locals, name) asm_arm_entry((as), (num_locals)) +#define ASM_EXIT asm_arm_exit -#define ASM_JUMP asm_arm_b_label +#define ASM_JUMP asm_arm_b_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ asm_arm_cmp_reg_i8(as, reg, 0); \ @@ -203,18 +208,28 @@ void asm_arm_bx_reg(asm_arm_t *as, uint reg_src); #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_arm_sub_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_arm_mul_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_arm_ldrb_reg_reg((as), (reg_dest), (reg_base)) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_arm_ldrh_reg_reg((as), (reg_dest), (reg_base)) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_arm_ldrh_reg_reg_offset((as), (reg_dest), (reg_base), 2 * (uint16_offset)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 0) - -#define ASM_STORE_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base), 0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_str_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_value, reg_base) asm_arm_strb_reg_reg((as), (reg_value), (reg_base)) -#define ASM_STORE16_REG_REG(as, reg_value, reg_base) asm_arm_strh_reg_reg((as), (reg_value), (reg_base)) -#define ASM_STORE32_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (word_offset)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_arm_ldrb_reg_reg_offset((as), (reg_dest), (reg_base), (byte_offset)) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, halfword_offset) asm_arm_ldrh_reg_reg_offset((as), (reg_dest), (reg_base), 2 * (halfword_offset)) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_ldr_reg_reg_offset((as), (reg_dest), (reg_base), 4 * (word_offset)) + +#define ASM_STORE_REG_REG_OFFSET(as, reg_value, reg_base, word_offset) ASM_STORE32_REG_REG_OFFSET((as), (reg_value), (reg_base), (word_offset)) +#define ASM_STORE8_REG_REG(as, reg_value, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_value), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_value, reg_base, byte_offset) asm_arm_strb_reg_reg_offset((as), (reg_value), (reg_base), (byte_offset)) +#define ASM_STORE16_REG_REG(as, reg_value, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_value), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_value, reg_base, halfword_offset) asm_arm_strh_reg_reg_offset((as), (reg_value), (reg_base), 2 * (halfword_offset)) +#define ASM_STORE32_REG_REG(as, reg_value, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_value), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_value, reg_base, word_offset) asm_arm_str_reg_reg_offset((as), (reg_value), (reg_base), 4 * (word_offset)) + +#define ASM_LOAD8_REG_REG_REG(as, reg_dest, reg_base, reg_index) asm_arm_ldrb_reg_reg_reg((as), (reg_dest), (reg_base), (reg_index)) +#define ASM_LOAD16_REG_REG_REG(as, reg_dest, reg_base, reg_index) asm_arm_ldrh_reg_reg_reg((as), (reg_dest), (reg_base), (reg_index)) +#define ASM_LOAD32_REG_REG_REG(as, reg_dest, reg_base, reg_index) asm_arm_ldr_reg_reg_reg((as), (reg_dest), (reg_base), (reg_index)) +#define ASM_STORE8_REG_REG_REG(as, reg_val, reg_base, reg_index) asm_arm_strb_reg_reg_reg((as), (reg_val), (reg_base), (reg_index)) +#define ASM_STORE16_REG_REG_REG(as, reg_val, reg_base, reg_index) asm_arm_strh_reg_reg_reg((as), (reg_val), (reg_base), (reg_index)) +#define ASM_STORE32_REG_REG_REG(as, reg_val, reg_base, reg_index) asm_arm_str_reg_reg_reg((as), (reg_val), (reg_base), (reg_index)) #endif // GENERIC_ASM_API diff --git a/py/asmbase.c b/py/asmbase.c index 3fce543a7f4..07dbf4430f9 100644 --- a/py/asmbase.c +++ b/py/asmbase.c @@ -53,7 +53,7 @@ void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) { } else { // allocating executable RAM is platform specific MP_PLAT_ALLOC_EXEC(as->code_offset, (void **)&as->code_base, &as->code_size); - assert(as->code_base != NULL); + assert(as->code_size == 0 || as->code_base != NULL); } as->pass = pass; as->suppress = false; @@ -102,7 +102,7 @@ void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) { // align must be a multiple of 2 void mp_asm_base_align(mp_asm_base_t *as, unsigned int align) { - as->code_offset = (as->code_offset + align - 1) & (~(align - 1)); + as->code_offset = (as->code_offset + align - 1) & (~(size_t)(align - 1)); } // this function assumes a little endian machine diff --git a/py/asmrv32.c b/py/asmrv32.c index c24d05a1384..1d0cea6c026 100644 --- a/py/asmrv32.c +++ b/py/asmrv32.c @@ -36,6 +36,8 @@ #if MICROPY_EMIT_RV32 #include "py/asmrv32.h" +#include "py/mpstate.h" +#include "py/persistentcode.h" #if MICROPY_DEBUG_VERBOSE #define DEBUG_PRINT (1) @@ -450,18 +452,24 @@ void asm_rv32_emit_mov_reg_local_addr(asm_rv32_t *state, mp_uint_t rd, mp_uint_t asm_rv32_opcode_cadd(state, rd, ASM_RV32_REG_SP); } -void asm_rv32_emit_load_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { - mp_int_t scaled_offset = offset * sizeof(ASM_WORD_SIZE); +static const uint8_t RV32_LOAD_OPCODE_TABLE[3] = { + 0x04, 0x05, 0x02 +}; - if (scaled_offset >= 0 && RV32_IS_IN_C_REGISTER_WINDOW(rd) && RV32_IS_IN_C_REGISTER_WINDOW(rs) && FIT_UNSIGNED(scaled_offset, 6)) { +void asm_rv32_emit_load_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, int32_t offset, mp_uint_t operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); + + int32_t scaled_offset = offset << operation_size; + + if (scaled_offset >= 0 && operation_size == 2 && RV32_IS_IN_C_REGISTER_WINDOW(rd) && RV32_IS_IN_C_REGISTER_WINDOW(rs) && MP_FIT_UNSIGNED(6, scaled_offset)) { // c.lw rd', offset(rs') asm_rv32_opcode_clw(state, RV32_MAP_IN_C_REGISTER_WINDOW(rd), RV32_MAP_IN_C_REGISTER_WINDOW(rs), scaled_offset); return; } - if (FIT_SIGNED(scaled_offset, 12)) { - // lw rd, offset(rs) - asm_rv32_opcode_lw(state, rd, rs, scaled_offset); + if (MP_FIT_SIGNED(12, scaled_offset)) { + // lbu|lhu|lw rd, offset(rs) + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, RV32_LOAD_OPCODE_TABLE[operation_size], rd, rs, scaled_offset)); return; } @@ -469,12 +477,12 @@ void asm_rv32_emit_load_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_ mp_uint_t lower = 0; split_immediate(scaled_offset, &upper, &lower); - // lui rd, HI(offset) ; Or c.lui if possible - // c.add rd, rs - // lw rd, LO(offset)(rd) + // lui rd, HI(offset) ; Or c.lui if possible + // c.add rd, rs + // lbu|lhu|lw rd, LO(offset)(rd) load_upper_immediate(state, rd, upper); asm_rv32_opcode_cadd(state, rd, rs); - asm_rv32_opcode_lw(state, rd, rd, lower); + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, RV32_LOAD_OPCODE_TABLE[operation_size], rd, rd, lower)); } void asm_rv32_emit_jump(asm_rv32_t *state, mp_uint_t label) { @@ -497,12 +505,20 @@ void asm_rv32_emit_jump(asm_rv32_t *state, mp_uint_t label) { asm_rv32_opcode_jalr(state, ASM_RV32_REG_ZERO, REG_TEMP2, lower); } -void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { - mp_int_t scaled_offset = offset * ASM_WORD_SIZE; +void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, int32_t offset, mp_uint_t operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); - if (FIT_SIGNED(scaled_offset, 12)) { - // sw rd, offset(rs) - asm_rv32_opcode_sw(state, rd, rs, scaled_offset); + int32_t scaled_offset = offset << operation_size; + + if (scaled_offset >= 0 && operation_size == 2 && RV32_IS_IN_C_REGISTER_WINDOW(rd) && RV32_IS_IN_C_REGISTER_WINDOW(rs) && MP_FIT_UNSIGNED(6, scaled_offset)) { + // c.sw rd', offset(rs') + asm_rv32_opcode_csw(state, RV32_MAP_IN_C_REGISTER_WINDOW(rd), RV32_MAP_IN_C_REGISTER_WINDOW(rs), scaled_offset); + return; + } + + if (MP_FIT_SIGNED(12, scaled_offset)) { + // sb|sh|sw rd, offset(rs) + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, operation_size, rs, rd, scaled_offset)); return; } @@ -510,12 +526,12 @@ void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint mp_uint_t lower = 0; split_immediate(scaled_offset, &upper, &lower); - // lui temporary, HI(offset) ; Or c.lui if possible - // c.add temporary, rs - // sw rd, LO(offset)(temporary) + // lui temporary, HI(offset) ; Or c.lui if possible + // c.add temporary, rs + // sb|sh|sw rd, LO(offset)(temporary) load_upper_immediate(state, REG_TEMP2, upper); asm_rv32_opcode_cadd(state, REG_TEMP2, rs); - asm_rv32_opcode_sw(state, rd, REG_TEMP2, lower); + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, operation_size, REG_TEMP2, rd, lower)); } void asm_rv32_emit_mov_reg_pcrel(asm_rv32_t *state, mp_uint_t rd, mp_uint_t label) { @@ -530,27 +546,6 @@ void asm_rv32_emit_mov_reg_pcrel(asm_rv32_t *state, mp_uint_t rd, mp_uint_t labe asm_rv32_opcode_addi(state, rd, rd, lower); } -void asm_rv32_emit_load16_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { - mp_int_t scaled_offset = offset * sizeof(uint16_t); - - if (FIT_SIGNED(scaled_offset, 12)) { - // lhu rd, offset(rs) - asm_rv32_opcode_lhu(state, rd, rs, scaled_offset); - return; - } - - mp_uint_t upper = 0; - mp_uint_t lower = 0; - split_immediate(scaled_offset, &upper, &lower); - - // lui rd, HI(offset) ; Or c.lui if possible - // c.add rd, rs - // lhu rd, LO(offset)(rd) - load_upper_immediate(state, rd, upper); - asm_rv32_opcode_cadd(state, rd, rs); - asm_rv32_opcode_lhu(state, rd, rd, lower); -} - void asm_rv32_emit_optimised_xor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) { if (rs == rd) { // c.li rd, 0 @@ -562,14 +557,39 @@ void asm_rv32_emit_optimised_xor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) asm_rv32_opcode_xor(state, rd, rd, rs); } +static bool asm_rv32_allow_zba_opcodes(void) { + return asm_rv32_allowed_extensions() & RV32_EXT_ZBA; +} + +static void asm_rv32_fix_up_scaled_reg_reg_reg(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); + + if (operation_size > 0 && asm_rv32_allow_zba_opcodes()) { + // sh{1,2}add rs1, rs2, rs1 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 1 << operation_size, 0x10, rs1, rs2, rs1)); + } else { + if (operation_size > 0) { + asm_rv32_opcode_cslli(state, rs2, operation_size); + } + asm_rv32_opcode_cadd(state, rs1, rs2); + } +} + +void asm_rv32_emit_load_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size) { + asm_rv32_fix_up_scaled_reg_reg_reg(state, rs1, rs2, operation_size); + asm_rv32_emit_load_reg_reg_offset(state, rd, rs1, 0, operation_size); +} + +void asm_rv32_emit_store_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size) { + asm_rv32_fix_up_scaled_reg_reg_reg(state, rs1, rs2, operation_size); + asm_rv32_emit_store_reg_reg_offset(state, rd, rs1, 0, operation_size); +} + void asm_rv32_meta_comparison_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd) { - // c.li rd, 1 ; - // beq rs1, rs2, 6 ; PC + 0 - // c.li rd, 0 ; PC + 4 - // ... ; PC + 6 - asm_rv32_opcode_cli(state, rd, 1); - asm_rv32_opcode_beq(state, rs1, rs2, 6); - asm_rv32_opcode_cli(state, rd, 0); + // sub rd, rs1, rs2 + // sltiu rd, rd, 1 + asm_rv32_opcode_sub(state, rd, rs1, rs2); + asm_rv32_opcode_sltiu(state, rd, rd, 1); } void asm_rv32_meta_comparison_ne(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd) { @@ -580,26 +600,15 @@ void asm_rv32_meta_comparison_ne(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2 } void asm_rv32_meta_comparison_lt(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd, bool unsigned_comparison) { - // slt(u) rd, rs1, rs2 - if (unsigned_comparison) { - asm_rv32_opcode_sltu(state, rd, rs1, rs2); - } else { - asm_rv32_opcode_slt(state, rd, rs1, rs2); - } + // slt|sltu rd, rs1, rs2 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, (0x02 | (unsigned_comparison ? 1 : 0)), 0x00, rd, rs1, rs2)); } void asm_rv32_meta_comparison_le(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd, bool unsigned_comparison) { - // c.li rd, 1 ; - // beq rs1, rs2, 8 ; PC + 0 - // slt(u) rd, rs1, rs2 ; PC + 4 - // ... ; PC + 8 - asm_rv32_opcode_cli(state, rd, 1); - asm_rv32_opcode_beq(state, rs1, rs2, 8); - if (unsigned_comparison) { - asm_rv32_opcode_sltu(state, rd, rs1, rs2); - } else { - asm_rv32_opcode_slt(state, rd, rs1, rs2); - } + // slt[u] rd, rs2, rs1 + // xori rd, rd, 1 + asm_rv32_meta_comparison_lt(state, rs2, rs1, rd, unsigned_comparison); + asm_rv32_opcode_xori(state, rd, rd, 1); } #endif // MICROPY_EMIT_RV32 diff --git a/py/asmrv32.h b/py/asmrv32.h index b09f48eb12f..6f709daa11b 100644 --- a/py/asmrv32.h +++ b/py/asmrv32.h @@ -122,6 +122,18 @@ typedef struct _asm_rv32_t { mp_uint_t locals_stack_offset; } asm_rv32_t; +enum { + RV32_EXT_NONE = 0, + RV32_EXT_ZBA = 1 << 0, + + RV32_EXT_ALL = RV32_EXT_ZBA +}; + +typedef struct _asm_rv32_backend_options_t { + // This is a bitmask holding a combination of RV32_EXT_* entries. + uint8_t allowed_extensions; +} asm_rv32_backend_options_t; + void asm_rv32_entry(asm_rv32_t *state, mp_uint_t locals); void asm_rv32_exit(asm_rv32_t *state); void asm_rv32_end_pass(asm_rv32_t *state); @@ -583,6 +595,24 @@ static inline void asm_rv32_opcode_remu(asm_rv32_t *state, mp_uint_t rd, mp_uint asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x07, 0x01, rd, rs1, rs2)); } +// SH1ADD RD, RS1, RS2 +static inline void asm_rv32_opcode_sh1add(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0010000 ..... ..... 010 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x02, 0x10, rd, rs1, rs2)); +} + +// SH2ADD RD, RS1, RS2 +static inline void asm_rv32_opcode_sh2add(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0010000 ..... ..... 100 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x04, 0x10, rd, rs1, rs2)); +} + +// SH3ADD RD, RS1, RS2 +static inline void asm_rv32_opcode_sh3add(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0010000 ..... ..... 110 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x06, 0x10, rd, rs1, rs2)); +} + // SLL RD, RS1, RS2 static inline void asm_rv32_opcode_sll(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { // R: 0000000 ..... ..... 001 ..... 0110011 @@ -679,6 +709,19 @@ static inline void asm_rv32_opcode_xori(asm_rv32_t *state, mp_uint_t rd, mp_uint asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x04, rd, rs, immediate)); } +#define MICROPY_RV32_EXTENSIONS \ + (MICROPY_EMIT_RV32_ZBA ? RV32_EXT_ZBA : 0) + +static inline uint8_t asm_rv32_allowed_extensions(void) { + uint8_t extensions = MICROPY_RV32_EXTENSIONS; + #if MICROPY_DYNAMIC_COMPILER + if (mp_dynamic_compiler.backend_options != NULL) { + extensions |= ((asm_rv32_backend_options_t *)mp_dynamic_compiler.backend_options)->allowed_extensions; + } + #endif + return extensions; +} + #define ASM_WORD_SIZE (4) #define ASM_HALFWORD_SIZE (2) @@ -702,6 +745,8 @@ void asm_rv32_meta_comparison_lt(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2 void asm_rv32_meta_comparison_le(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd, bool unsigned_comparison); void asm_rv32_emit_optimised_load_immediate(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate); +void asm_rv32_emit_load_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size); +void asm_rv32_emit_store_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size); #ifdef GENERIC_ASM_API @@ -709,17 +754,16 @@ void asm_rv32_emit_call_ind(asm_rv32_t *state, mp_uint_t index); void asm_rv32_emit_jump(asm_rv32_t *state, mp_uint_t label); void asm_rv32_emit_jump_if_reg_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t label); void asm_rv32_emit_jump_if_reg_nonzero(asm_rv32_t *state, mp_uint_t rs, mp_uint_t label); -void asm_rv32_emit_load16_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset); -void asm_rv32_emit_load_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset); +void asm_rv32_emit_load_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, int32_t offset, mp_uint_t operation_size); void asm_rv32_emit_mov_local_reg(asm_rv32_t *state, mp_uint_t local, mp_uint_t rs); void asm_rv32_emit_mov_reg_local_addr(asm_rv32_t *state, mp_uint_t rd, mp_uint_t local); void asm_rv32_emit_mov_reg_local(asm_rv32_t *state, mp_uint_t rd, mp_uint_t local); void asm_rv32_emit_mov_reg_pcrel(asm_rv32_t *state, mp_uint_t rd, mp_uint_t label); void asm_rv32_emit_optimised_xor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs); -void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t source, mp_uint_t base, mp_int_t offset); +void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t source, mp_uint_t base, int32_t offset, mp_uint_t operation_size); #define ASM_T asm_rv32_t -#define ASM_ENTRY(state, labels) asm_rv32_entry(state, labels) +#define ASM_ENTRY(state, labels, name) asm_rv32_entry(state, labels) #define ASM_EXIT(state) asm_rv32_exit(state) #define ASM_END_PASS(state) asm_rv32_end_pass(state) @@ -732,12 +776,13 @@ void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t source, mp_ #define ASM_JUMP_IF_REG_NONZERO(state, rs, label, bool_test) asm_rv32_emit_jump_if_reg_nonzero(state, rs, label) #define ASM_JUMP_IF_REG_ZERO(state, rs, label, bool_test) asm_rv32_emit_jump_if_reg_eq(state, rs, ASM_RV32_REG_ZERO, label) #define ASM_JUMP_REG(state, rs) asm_rv32_opcode_cjr(state, rs) -#define ASM_LOAD16_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load16_reg_reg_offset(state, rd, rs, offset) -#define ASM_LOAD16_REG_REG(state, rd, rs) asm_rv32_opcode_lhu(state, rd, rs, 0) -#define ASM_LOAD32_REG_REG(state, rd, rs) ASM_LOAD_REG_REG_OFFSET(state, rd, rs, 0) -#define ASM_LOAD8_REG_REG(state, rd, rs) asm_rv32_opcode_lbu(state, rd, rs, 0) -#define ASM_LOAD_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load_reg_reg_offset(state, rd, rs, offset) -#define ASM_LOAD_REG_REG(state, rd, rs) ASM_LOAD32_REG_REG(state, rd, rs) +#define ASM_LOAD_REG_REG_OFFSET(state, rd, rs, offset) ASM_LOAD32_REG_REG_OFFSET(state, rd, rs, offset) +#define ASM_LOAD8_REG_REG(state, rd, rs) ASM_LOAD8_REG_REG_OFFSET(state, rd, rs, 0) +#define ASM_LOAD16_REG_REG(state, rd, rs) ASM_LOAD16_REG_REG_OFFSET(state, rd, rs, 0) +#define ASM_LOAD32_REG_REG(state, rd, rs) ASM_LOAD32_REG_REG_OFFSET(state, rd, rs, 0) +#define ASM_LOAD8_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load_reg_reg_offset(state, rd, rs, offset, 0) +#define ASM_LOAD16_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load_reg_reg_offset(state, rd, rs, offset, 1) +#define ASM_LOAD32_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load_reg_reg_offset(state, rd, rs, offset, 2) #define ASM_LSL_REG_REG(state, rd, rs) asm_rv32_opcode_sll(state, rd, rd, rs) #define ASM_LSR_REG_REG(state, rd, rs) asm_rv32_opcode_srl(state, rd, rd, rs) #define ASM_MOV_LOCAL_REG(state, local, rs) asm_rv32_emit_mov_local_reg(state, local, rs) @@ -750,14 +795,22 @@ void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t source, mp_ #define ASM_NEG_REG(state, rd) asm_rv32_opcode_sub(state, rd, ASM_RV32_REG_ZERO, rd) #define ASM_NOT_REG(state, rd) asm_rv32_opcode_xori(state, rd, rd, -1) #define ASM_OR_REG_REG(state, rd, rs) asm_rv32_opcode_or(state, rd, rd, rs) -#define ASM_STORE16_REG_REG(state, rs1, rs2) asm_rv32_opcode_sh(state, rs1, rs2, 0) -#define ASM_STORE32_REG_REG(state, rs1, rs2) ASM_STORE_REG_REG_OFFSET(state, rs1, rs2, 0) -#define ASM_STORE8_REG_REG(state, rs1, rs2) asm_rv32_opcode_sb(state, rs1, rs2, 0) -#define ASM_STORE_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_store_reg_reg_offset(state, rd, rs, offset) -#define ASM_STORE_REG_REG(state, rs1, rs2) ASM_STORE32_REG_REG(state, rs1, rs2) +#define ASM_STORE_REG_REG_OFFSET(state, rd, rs, offset) ASM_STORE32_REG_REG_OFFSET(state, rd, rs, offset) +#define ASM_STORE8_REG_REG(state, rs1, rs2) ASM_STORE8_REG_REG_OFFSET(state, rs1, rs2, 0) +#define ASM_STORE16_REG_REG(state, rs1, rs2) ASM_STORE16_REG_REG_OFFSET(state, rs1, rs2, 0) +#define ASM_STORE32_REG_REG(state, rs1, rs2) ASM_STORE32_REG_REG_OFFSET(state, rs1, rs2, 0) +#define ASM_STORE8_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_store_reg_reg_offset(state, rd, rs, offset, 0) +#define ASM_STORE16_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_store_reg_reg_offset(state, rd, rs, offset, 1) +#define ASM_STORE32_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_store_reg_reg_offset(state, rd, rs, offset, 2) #define ASM_SUB_REG_REG(state, rd, rs) asm_rv32_opcode_sub(state, rd, rd, rs) #define ASM_XOR_REG_REG(state, rd, rs) asm_rv32_emit_optimised_xor(state, rd, rs) #define ASM_CLR_REG(state, rd) +#define ASM_LOAD8_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_load_reg_reg_reg(state, rd, rs1, rs2, 0) +#define ASM_LOAD16_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_load_reg_reg_reg(state, rd, rs1, rs2, 1) +#define ASM_LOAD32_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_load_reg_reg_reg(state, rd, rs1, rs2, 2) +#define ASM_STORE8_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_store_reg_reg_reg(state, rd, rs1, rs2, 0) +#define ASM_STORE16_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_store_reg_reg_reg(state, rd, rs1, rs2, 1) +#define ASM_STORE32_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_store_reg_reg_reg(state, rd, rs1, rs2, 2) #endif diff --git a/py/asmthumb.c b/py/asmthumb.c index 420815e8026..58cc7aea880 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -37,7 +37,6 @@ #include "py/asmthumb.h" #include "py/misc.h" -#define UNSIGNED_FIT5(x) ((uint32_t)(x) < 32) #define UNSIGNED_FIT7(x) ((uint32_t)(x) < 128) #define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0) #define UNSIGNED_FIT16(x) (((x) & 0xffff0000) == 0) @@ -52,12 +51,6 @@ #define OP_SUB_W_RRI_HI(reg_src) (0xf2a0 | (reg_src)) #define OP_SUB_W_RRI_LO(reg_dest, imm11) ((imm11 << 4 & 0x7000) | reg_dest << 8 | (imm11 & 0xff)) -#define OP_LDR_W_HI(reg_base) (0xf8d0 | (reg_base)) -#define OP_LDR_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12)) - -#define OP_LDRH_W_HI(reg_base) (0xf8b0 | (reg_base)) -#define OP_LDRH_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12)) - static inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) { return mp_asm_base_get_cur_to_write_bytes(&as->base, n); } @@ -274,9 +267,8 @@ bool asm_thumb_b_n_label(asm_thumb_t *as, uint label) { #define OP_BCC_N(cond, byte_offset) (0xd000 | ((cond) << 8) | (((byte_offset) >> 1) & 0x00ff)) -// all these bit-arithmetic operations need coverage testing! -#define OP_BCC_W_HI(cond, byte_offset) (0xf000 | ((cond) << 6) | (((byte_offset) >> 10) & 0x0400) | (((byte_offset) >> 14) & 0x003f)) -#define OP_BCC_W_LO(byte_offset) (0x8000 | ((byte_offset) & 0x2000) | (((byte_offset) >> 1) & 0x0fff)) +#define OP_BCC_W_HI(cond, byte_offset) (0xf000 | ((cond) << 6) | (((byte_offset) >> 10) & 0x0400) | (((byte_offset) >> 12) & 0x003f)) +#define OP_BCC_W_LO(byte_offset) (0x8000 | (((byte_offset) >> 5) & 0x2000) | (((byte_offset) >> 8) & 0x0800) | (((byte_offset) >> 1) & 0x07ff)) bool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide) { mp_uint_t dest = get_label_dest(as, label); @@ -432,11 +424,6 @@ void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label) { asm_thumb_add_reg_reg(as, rlo_dest, ASM_THUMB_REG_R15); // 2 bytes } -// ARMv7-M only -static inline void asm_thumb_ldr_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) { - asm_thumb_op32(as, OP_LDR_W_HI(reg_base), OP_LDR_W_LO(reg_dest, word_offset * 4)); -} - // emits code for: reg_dest = reg_base + offset << offset_shift static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint offset_shift) { if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8) { @@ -450,12 +437,12 @@ static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint re asm_thumb_lsl_rlo_rlo_i5(as, reg_dest, reg_dest, offset_shift); asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base); } else if (reg_dest != reg_base) { - asm_thumb_mov_rlo_i16(as, reg_dest, offset << offset_shift); - asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_dest); + asm_thumb_mov_reg_i32_optimised(as, reg_dest, offset << offset_shift); + asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base); } else { uint reg_other = reg_dest ^ 7; asm_thumb_op16(as, OP_PUSH_RLIST((1 << reg_other))); - asm_thumb_mov_rlo_i16(as, reg_other, offset << offset_shift); + asm_thumb_mov_reg_i32_optimised(as, reg_other, offset << offset_shift); asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_other); asm_thumb_op16(as, OP_POP_RLIST((1 << reg_other))); } @@ -464,30 +451,50 @@ static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint re } } -void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) { - if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(word_offset)) { - asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_base, word_offset); - } else if (asm_thumb_allow_armv7m(as)) { - asm_thumb_ldr_reg_reg_i12(as, reg_dest, reg_base, word_offset); +#define OP_LDR_STR_W_HI(operation_size, reg) ((0xf880 | (operation_size) << 5) | (reg)) +#define OP_LDR_STR_W_LO(reg, imm12) (((reg) << 12) | (imm12)) + +#define OP_LDR 0x01 +#define OP_STR 0x00 + +#define OP_LDR_W 0x10 +#define OP_STR_W 0x00 + +static const uint8_t OP_LDR_STR_TABLE[3] = { + 0x0E, 0x10, 0x0C +}; + +void asm_thumb_load_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size) { + assert(operation_size <= 2 && "Operation size out of range."); + + if (MP_FIT_UNSIGNED(5, offset) && (reg_dest < ASM_THUMB_REG_R8) && (reg_base < ASM_THUMB_REG_R8)) { + // Can use T1 encoding + asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_LDR) << 11) | (offset << 6) | (reg_base << 3) | reg_dest); + } else if (asm_thumb_allow_armv7m(as) && MP_FIT_UNSIGNED(12, offset << operation_size)) { + // Can use T3 encoding + asm_thumb_op32(as, (OP_LDR_STR_W_HI(operation_size, reg_base) | OP_LDR_W), OP_LDR_STR_W_LO(reg_dest, (offset << operation_size))); } else { - asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, word_offset - 31, 2); - asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_dest, 31); + // Must use the generic sequence + asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, offset - 31, operation_size); + asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_LDR) << 11) | (31 << 6) | (reg_dest << 3) | (reg_dest)); } } -// ARMv7-M only -static inline void asm_thumb_ldrh_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) { - asm_thumb_op32(as, OP_LDRH_W_HI(reg_base), OP_LDRH_W_LO(reg_dest, uint16_offset * 2)); -} +void asm_thumb_store_reg_reg_offset(asm_thumb_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size) { + assert(operation_size <= 2 && "Operation size out of range."); -void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) { - if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(uint16_offset)) { - asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_base, uint16_offset); - } else if (asm_thumb_allow_armv7m(as)) { - asm_thumb_ldrh_reg_reg_i12(as, reg_dest, reg_base, uint16_offset); + if (MP_FIT_UNSIGNED(5, offset) && (reg_src < ASM_THUMB_REG_R8) && (reg_base < ASM_THUMB_REG_R8)) { + // Can use T1 encoding + asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_STR) << 11) | (offset << 6) | (reg_base << 3) | reg_src); + } else if (asm_thumb_allow_armv7m(as) && MP_FIT_UNSIGNED(12, offset << operation_size)) { + // Can use T3 encoding + asm_thumb_op32(as, (OP_LDR_STR_W_HI(operation_size, reg_base) | OP_STR_W), OP_LDR_STR_W_LO(reg_src, (offset << operation_size))); } else { - asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, uint16_offset - 31, 1); - asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_dest, 31); + // Must use the generic sequence + asm_thumb_op16(as, OP_PUSH_RLIST(1 << reg_base)); + asm_thumb_add_reg_reg_offset(as, reg_base, reg_base, offset - 31, operation_size); + asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_STR) << 11) | (31 << 6) | (reg_base << 3) | reg_src); + asm_thumb_op16(as, OP_POP_RLIST(1 << reg_base)); } } @@ -495,6 +502,7 @@ void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint r #define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff)) #define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff)) +// In Thumb1 mode, this may clobber r1. void asm_thumb_b_label(asm_thumb_t *as, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; @@ -514,19 +522,40 @@ void asm_thumb_b_label(asm_thumb_t *as, uint label) { if (asm_thumb_allow_armv7m(as)) { asm_thumb_op32(as, OP_BW_HI(rel), OP_BW_LO(rel)); } else { + // this code path has to be the same instruction size irrespective of the value of rel + bool need_align = as->base.code_offset & 2u; if (SIGNED_FIT12(rel)) { - // this code path has to be the same number of instructions irrespective of rel asm_thumb_op16(as, OP_B_N(rel)); - } else { asm_thumb_op16(as, ASM_THUMB_OP_NOP); - if (dest != (mp_uint_t)-1) { - // we have an actual branch > 12 bits; this is not handled yet - mp_raise_NotImplementedError(MP_ERROR_TEXT("native method too big")); + asm_thumb_op16(as, ASM_THUMB_OP_NOP); + asm_thumb_op16(as, ASM_THUMB_OP_NOP); + if (need_align) { + asm_thumb_op16(as, ASM_THUMB_OP_NOP); + } + } else { + // do a large jump using: + // (nop) + // ldr r1, [pc, _data] + // add pc, r1 + // _data: .word rel + // + // note: can't use r0 as a temporary because native code can have the return value + // in that register and use a large jump to get to the exit point of the function + + rel -= 2; // account for the "ldr r1, [pc, _data]" + if (need_align) { + asm_thumb_op16(as, ASM_THUMB_OP_NOP); + rel -= 2; // account for this nop } + asm_thumb_ldr_rlo_pcrel_i8(as, ASM_THUMB_REG_R1, 0); + asm_thumb_add_reg_reg(as, ASM_THUMB_REG_R15, ASM_THUMB_REG_R1); + asm_thumb_op16(as, rel & 0xffff); + asm_thumb_op16(as, rel >> 16); } } } +// In Thumb1 mode, this may clobber r1. void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; @@ -547,8 +576,15 @@ void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) { asm_thumb_op32(as, OP_BCC_W_HI(cond, rel), OP_BCC_W_LO(rel)); } else { // reverse the sense of the branch to jump over a longer branch - asm_thumb_op16(as, OP_BCC_N(cond ^ 1, 0)); + size_t code_offset_start = as->base.code_offset; + byte *c = asm_thumb_get_cur_to_write_bytes(as, 2); asm_thumb_b_label(as, label); + size_t bytes_to_skip = as->base.code_offset - code_offset_start; + uint16_t op = OP_BCC_N(cond ^ 1, bytes_to_skip - 4); + if (c != NULL) { + c[0] = op; + c[1] = op >> 8; + } } } @@ -569,7 +605,7 @@ void asm_thumb_b_rel12(asm_thumb_t *as, int rel) { void asm_thumb_bl_ind(asm_thumb_t *as, uint fun_id, uint reg_temp) { // Load ptr to function from table, indexed by fun_id, then call it - asm_thumb_ldr_reg_reg_i12_optimised(as, reg_temp, ASM_THUMB_REG_FUN_TABLE, fun_id); + asm_thumb_load_reg_reg_offset(as, reg_temp, ASM_THUMB_REG_FUN_TABLE, fun_id, 2); asm_thumb_op16(as, OP_BLX(reg_temp)); } diff --git a/py/asmthumb.h b/py/asmthumb.h index 0584ed3227a..cb786694f0b 100644 --- a/py/asmthumb.h +++ b/py/asmthumb.h @@ -251,6 +251,50 @@ static inline void asm_thumb_bx_reg(asm_thumb_t *as, uint r_src) { asm_thumb_format_5(as, ASM_THUMB_FORMAT_5_BX, 0, r_src); } +// FORMAT 7: load/store with register offset +// FORMAT 8: load/store sign-extended byte/halfword + +#define ASM_THUMB_FORMAT_7_LDR (0x5800) +#define ASM_THUMB_FORMAT_7_STR (0x5000) +#define ASM_THUMB_FORMAT_7_WORD_TRANSFER (0x0000) +#define ASM_THUMB_FORMAT_7_BYTE_TRANSFER (0x0400) +#define ASM_THUMB_FORMAT_8_LDRH (0x5A00) +#define ASM_THUMB_FORMAT_8_STRH (0x5200) + +#define ASM_THUMB_FORMAT_7_8_ENCODE(op, rlo_dest, rlo_base, rlo_index) \ + ((op) | ((rlo_index) << 6) | ((rlo_base) << 3) | ((rlo_dest))) + +static inline void asm_thumb_format_7_8(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_base, uint rlo_index) { + assert(rlo_dest < ASM_THUMB_REG_R8); + assert(rlo_base < ASM_THUMB_REG_R8); + assert(rlo_index < ASM_THUMB_REG_R8); + asm_thumb_op16(as, ASM_THUMB_FORMAT_7_8_ENCODE(op, rlo_dest, rlo_base, rlo_index)); +} + +static inline void asm_thumb_ldrb_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_7_LDR | ASM_THUMB_FORMAT_7_BYTE_TRANSFER, rlo_dest, rlo_base, rlo_index); +} + +static inline void asm_thumb_ldrh_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_8_LDRH, rlo_dest, rlo_base, rlo_index); +} + +static inline void asm_thumb_ldr_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_7_LDR | ASM_THUMB_FORMAT_7_WORD_TRANSFER, rlo_dest, rlo_base, rlo_index); +} + +static inline void asm_thumb_strb_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_7_STR | ASM_THUMB_FORMAT_7_BYTE_TRANSFER, rlo_src, rlo_base, rlo_index); +} + +static inline void asm_thumb_strh_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_8_STRH, rlo_dest, rlo_base, rlo_index); +} + +static inline void asm_thumb_str_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_7_STR | ASM_THUMB_FORMAT_7_WORD_TRANSFER, rlo_src, rlo_base, rlo_index); +} + // FORMAT 9: load/store with immediate offset // For word transfers the offset must be aligned, and >>2 @@ -273,24 +317,6 @@ static inline void asm_thumb_format_9_10(asm_thumb_t *as, uint op, uint rlo_dest asm_thumb_op16(as, ASM_THUMB_FORMAT_9_10_ENCODE(op, rlo_dest, rlo_base, offset)); } -static inline void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_src, rlo_base, word_offset); -} -static inline void asm_thumb_strb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint byte_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER, rlo_src, rlo_base, byte_offset); -} -static inline void asm_thumb_strh_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint uint16_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_10_STRH, rlo_src, rlo_base, uint16_offset); -} -static inline void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_dest, rlo_base, word_offset); -} -static inline void asm_thumb_ldrb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint byte_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER, rlo_dest, rlo_base, byte_offset); -} -static inline void asm_thumb_ldrh_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint uint16_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_10_LDRH, rlo_dest, rlo_base, uint16_offset); -} static inline void asm_thumb_lsl_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_src, uint shift) { asm_thumb_format_1(as, ASM_THUMB_FORMAT_1_LSL, rlo_dest, rlo_src, shift); } @@ -338,8 +364,10 @@ void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num); // void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label); -void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset); // convenience -void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset); // convenience +// Generate optimised load dest, [src, #offset] sequence +void asm_thumb_load_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size); +// Generate optimised store src, [dest, #offset] sequence +void asm_thumb_store_reg_reg_offset(asm_thumb_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size); void asm_thumb_b_label(asm_thumb_t *as, uint label); // convenience: picks narrow or wide branch void asm_thumb_bcc_label(asm_thumb_t *as, int cc, uint label); // convenience: picks narrow or wide branch @@ -376,12 +404,12 @@ void asm_thumb_b_rel12(asm_thumb_t *as, int rel); #define REG_FUN_TABLE ASM_THUMB_REG_FUN_TABLE -#define ASM_T asm_thumb_t -#define ASM_END_PASS asm_thumb_end_pass -#define ASM_ENTRY asm_thumb_entry -#define ASM_EXIT asm_thumb_exit +#define ASM_T asm_thumb_t +#define ASM_END_PASS asm_thumb_end_pass +#define ASM_ENTRY(as, num_locals, name) asm_thumb_entry((as), (num_locals)) +#define ASM_EXIT asm_thumb_exit -#define ASM_JUMP asm_thumb_b_label +#define ASM_JUMP asm_thumb_b_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ asm_thumb_cmp_rlo_i8(as, reg, 0); \ @@ -419,18 +447,44 @@ void asm_thumb_b_rel12(asm_thumb_t *as, int rel); #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_thumb_sub_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_MUL, (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_thumb_ldr_reg_reg_i12_optimised((as), (reg_dest), (reg_base), (word_offset)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrb_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrh_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_thumb_ldrh_reg_reg_i12_optimised((as), (reg_dest), (reg_base), (uint16_offset)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) - -#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_thumb_strb_rlo_rlo_i5((as), (reg_src), (reg_base), 0) -#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_thumb_strh_rlo_rlo_i5((as), (reg_src), (reg_base), 0) -#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (word_offset)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_thumb_load_reg_reg_offset((as), (reg_dest), (reg_base), (byte_offset), 0) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, halfword_offset) asm_thumb_load_reg_reg_offset((as), (reg_dest), (reg_base), (halfword_offset), 1) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_thumb_load_reg_reg_offset((as), (reg_dest), (reg_base), (word_offset), 2) + +#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), (word_offset)) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_src, reg_base, byte_offset) asm_thumb_store_reg_reg_offset((as), (reg_src), (reg_base), (byte_offset), 0) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_src, reg_base, halfword_offset) asm_thumb_store_reg_reg_offset((as), (reg_src), (reg_base), (halfword_offset), 1) +#define ASM_STORE32_REG_REG(as, reg_src, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_thumb_store_reg_reg_offset((as), (reg_src), (reg_base), (word_offset), 2) + +#define ASM_LOAD8_REG_REG_REG(as, reg_dest, reg_base, reg_index) asm_thumb_ldrb_rlo_rlo_rlo((as), (reg_dest), (reg_base), (reg_index)) +#define ASM_LOAD16_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 1); \ + asm_thumb_ldrh_rlo_rlo_rlo((as), (reg_dest), (reg_base), (reg_index)); \ + } while (0) +#define ASM_LOAD32_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 2); \ + asm_thumb_ldr_rlo_rlo_rlo((as), (reg_dest), (reg_base), (reg_index)); \ + } while (0) +#define ASM_STORE8_REG_REG_REG(as, reg_val, reg_base, reg_index) asm_thumb_strb_rlo_rlo_rlo((as), (reg_val), (reg_base), (reg_index)) +#define ASM_STORE16_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 1); \ + asm_thumb_strh_rlo_rlo_rlo((as), (reg_val), (reg_base), (reg_index)); \ + } while (0) +#define ASM_STORE32_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 2); \ + asm_thumb_str_rlo_rlo_rlo((as), (reg_val), (reg_base), (reg_index)); \ + } while (0) #endif // GENERIC_ASM_API diff --git a/py/asmx64.h b/py/asmx64.h index 03070b5f63d..1e8cb0c905f 100644 --- a/py/asmx64.h +++ b/py/asmx64.h @@ -155,12 +155,12 @@ void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r32); // Holds a pointer to mp_fun_table #define REG_FUN_TABLE ASM_X64_REG_FUN_TABLE -#define ASM_T asm_x64_t -#define ASM_END_PASS asm_x64_end_pass -#define ASM_ENTRY asm_x64_entry -#define ASM_EXIT asm_x64_exit +#define ASM_T asm_x64_t +#define ASM_END_PASS asm_x64_end_pass +#define ASM_ENTRY(as, num_locals, name) asm_x64_entry((as), (num_locals)) +#define ASM_EXIT asm_x64_exit -#define ASM_JUMP asm_x64_jmp_label +#define ASM_JUMP asm_x64_jmp_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ if (bool_test) { \ @@ -206,18 +206,21 @@ void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r32); #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x64_sub_r64_r64((as), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_x64_mul_r64_r64((as), (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem64_to_r64((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x64_mov_mem64_to_r64((as), (reg_base), 8 * (word_offset), (reg_dest)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem8_to_r64zx((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 2 * (uint16_offset), (reg_dest)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem32_to_r64zx((as), (reg_base), 0, (reg_dest)) - -#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 8 * (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x64_mov_r8_to_mem8((as), (reg_src), (reg_base), 0) -#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x64_mov_r16_to_mem16((as), (reg_src), (reg_base), 0) -#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x64_mov_r32_to_mem32((as), (reg_src), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, qword_offset) asm_x64_mov_mem64_to_r64((as), (reg_base), 8 * (qword_offset), (reg_dest)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_x64_mov_mem8_to_r64zx((as), (reg_base), (byte_offset), (reg_dest)) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 2 * (word_offset), (reg_dest)) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, dword_offset) asm_x64_mov_mem32_to_r64zx((as), (reg_base), 4 * (dword_offset), (reg_dest)) + +#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, qword_offset) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 8 * (qword_offset)) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_src, reg_base, byte_offset) asm_x64_mov_r8_to_mem8((as), (reg_src), (reg_base), (byte_offset)) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x64_mov_r16_to_mem16((as), (reg_src), (reg_base), 2 * (word_offset)) +#define ASM_STORE32_REG_REG(as, reg_src, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_src, reg_base, dword_offset) asm_x64_mov_r32_to_mem32((as), (reg_src), (reg_base), 4 * (dword_offset)) #endif // GENERIC_ASM_API diff --git a/py/asmx86.h b/py/asmx86.h index 7796d697626..f5d37228a2f 100644 --- a/py/asmx86.h +++ b/py/asmx86.h @@ -150,12 +150,12 @@ void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r // Holds a pointer to mp_fun_table #define REG_FUN_TABLE ASM_X86_REG_FUN_TABLE -#define ASM_T asm_x86_t -#define ASM_END_PASS asm_x86_end_pass -#define ASM_ENTRY asm_x86_entry -#define ASM_EXIT asm_x86_exit +#define ASM_T asm_x86_t +#define ASM_END_PASS asm_x86_end_pass +#define ASM_ENTRY(as, num_locals, name) asm_x86_entry((as), (num_locals)) +#define ASM_EXIT asm_x86_exit -#define ASM_JUMP asm_x86_jmp_label +#define ASM_JUMP asm_x86_jmp_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ if (bool_test) { \ @@ -201,18 +201,21 @@ void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x86_sub_r32_r32((as), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_x86_mul_r32_r32((as), (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x86_mov_mem32_to_r32((as), (reg_base), 4 * (word_offset), (reg_dest)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem8_to_r32zx((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 2 * (uint16_offset), (reg_dest)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest)) - -#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 4 * (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x86_mov_r8_to_mem8((as), (reg_src), (reg_base), 0) -#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x86_mov_r16_to_mem16((as), (reg_src), (reg_base), 0) -#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, dword_offset) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (dword_offset)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_x86_mov_mem8_to_r32zx((as), (reg_base), (byte_offset), (reg_dest)) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 2 * (word_offset), (reg_dest)) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, dword_offset) asm_x86_mov_mem32_to_r32((as), (reg_base), 4 * (dword_offset), (reg_dest)) + +#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, dword_offset) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), (dword_offset)) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_src, reg_base, byte_offset) asm_x86_mov_r8_to_mem8((as), (reg_src), (reg_base), (byte_offset)) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x86_mov_r16_to_mem16((as), (reg_src), (reg_base), 2 * (word_offset)) +#define ASM_STORE32_REG_REG(as, reg_src, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_src, reg_base, dword_offset) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 4 * (dword_offset)) #endif // GENERIC_ASM_API diff --git a/py/asmxtensa.c b/py/asmxtensa.c index 0fbe351dcf3..bc3e717d9f3 100644 --- a/py/asmxtensa.c +++ b/py/asmxtensa.c @@ -34,9 +34,20 @@ #include "py/asmxtensa.h" +#if N_XTENSAWIN +#define REG_TEMP ASM_XTENSA_REG_TEMPORARY_WIN +#else +#define REG_TEMP ASM_XTENSA_REG_TEMPORARY +#endif + #define WORD_SIZE (4) +#define SIGNED_FIT6(x) ((((x) & 0xffffffe0) == 0) || (((x) & 0xffffffe0) == 0xffffffe0)) #define SIGNED_FIT8(x) ((((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)) #define SIGNED_FIT12(x) ((((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)) +#define SIGNED_FIT18(x) ((((x) & 0xfffe0000) == 0) || (((x) & 0xfffe0000) == 0xfffe0000)) + +#define ET_OUT_OF_RANGE MP_ERROR_TEXT("ERROR: xtensa %q out of range") +#define ET_NOT_ALIGNED MP_ERROR_TEXT("ERROR: %q %q not word-aligned") void asm_xtensa_end_pass(asm_xtensa_t *as) { as->num_const = as->cur_const; @@ -47,9 +58,9 @@ void asm_xtensa_end_pass(asm_xtensa_t *as) { if (as->base.pass == MP_ASM_PASS_EMIT) { uint8_t *d = as->base.code_base; printf("XTENSA ASM:"); - for (int i = 0; i < ((as->base.code_size + 15) & ~15); ++i) { + for (size_t i = 0; i < ((as->base.code_size + 15) & ~15); ++i) { if (i % 16 == 0) { - printf("\n%08x:", (uint32_t)&d[i]); + printf("\n%p:", &d[i]); } if (i % 2 == 0) { printf(" "); @@ -62,10 +73,12 @@ void asm_xtensa_end_pass(asm_xtensa_t *as) { } void asm_xtensa_entry(asm_xtensa_t *as, int num_locals) { - // jump over the constants - asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4); - mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // padding/alignment byte - as->const_table = (uint32_t *)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4); + if (as->num_const > 0) { + // jump over the constants + asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4); + mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // padding/alignment byte + as->const_table = (uint32_t *)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4); + } // adjust the stack-pointer to store a0, a12, a13, a14, a15 and locals, 16-byte aligned as->stack_adjust = (((ASM_XTENSA_NUM_REGS_SAVED + num_locals) * WORD_SIZE) + 15) & ~15; @@ -146,22 +159,60 @@ void asm_xtensa_j_label(asm_xtensa_t *as, uint label) { asm_xtensa_op_j(as, rel); } +static bool calculate_branch_displacement(asm_xtensa_t *as, uint label, ptrdiff_t *displacement) { + assert(displacement != NULL && "Displacement pointer is NULL"); + + uint32_t label_offset = get_label_dest(as, label); + *displacement = (ptrdiff_t)(label_offset - as->base.code_offset - 4); + return (label_offset != (uint32_t)-1) && (*displacement < 0); +} + void asm_xtensa_bccz_reg_label(asm_xtensa_t *as, uint cond, uint reg, uint label) { - uint32_t dest = get_label_dest(as, label); - int32_t rel = dest - as->base.code_offset - 4; - if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT12(rel)) { - printf("ERROR: xtensa bccz out of range\n"); + ptrdiff_t rel = 0; + bool can_emit_short_jump = calculate_branch_displacement(as, label, &rel); + + if (can_emit_short_jump && SIGNED_FIT12(rel)) { + // Backwards BCCZ opcodes with an offset that fits in 12 bits can + // be emitted without any change. + asm_xtensa_op_bccz(as, cond, reg, rel); + return; } - asm_xtensa_op_bccz(as, cond, reg, rel); + + // Range is effectively extended to 18 bits, as a more complex jump code + // sequence is emitted. + if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT18(rel - 6)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_bccz); + } + + // ~BCCZ skip ; +0 <- Condition is flipped here (EQ -> NE, etc.) + // J addr ; +3 + // skip: ; +6 + asm_xtensa_op_bccz(as, cond ^ 1, reg, 6 - 4); + asm_xtensa_op_j(as, rel - 3); } void asm_xtensa_bcc_reg_reg_label(asm_xtensa_t *as, uint cond, uint reg1, uint reg2, uint label) { - uint32_t dest = get_label_dest(as, label); - int32_t rel = dest - as->base.code_offset - 4; - if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT8(rel)) { - printf("ERROR: xtensa bcc out of range\n"); + ptrdiff_t rel = 0; + bool can_emit_short_jump = calculate_branch_displacement(as, label, &rel); + + if (can_emit_short_jump && SIGNED_FIT8(rel)) { + // Backwards BCC opcodes with an offset that fits in 8 bits can + // be emitted without any change. + asm_xtensa_op_bcc(as, cond, reg1, reg2, rel); + return; + } + + // Range is effectively extended to 18 bits, as a more complex jump code + // sequence is emitted. + if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT18(rel - 6)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_bcc); } - asm_xtensa_op_bcc(as, cond, reg1, reg2, rel); + + // ~BCC skip ; +0 <- Condition is flipped here (EQ -> NE, etc.) + // J addr ; +3 + // skip: ; +6 + asm_xtensa_op_bcc(as, cond ^ 8, reg1, reg2, 6 - 4); + asm_xtensa_op_j(as, rel - 3); } // convenience function; reg_dest must be different from reg_src[12] @@ -179,6 +230,8 @@ size_t asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32) { // store the constant in the table if (as->const_table != NULL) { as->const_table[as->cur_const] = i32; + } else { + assert((as->base.pass != MP_ASM_PASS_EMIT) && "Constants table was not built."); } ++as->cur_const; return loc; @@ -240,17 +293,53 @@ void asm_xtensa_l32i_optimised(asm_xtensa_t *as, uint reg_dest, uint reg_base, u } else if (word_offset < 256) { asm_xtensa_op_l32i(as, reg_dest, reg_base, word_offset); } else { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("asm overflow")); + asm_xtensa_mov_reg_i32_optimised(as, reg_dest, word_offset * 4); + asm_xtensa_op_add_n(as, reg_dest, reg_base, reg_dest); + asm_xtensa_op_l32i_n(as, reg_dest, reg_dest, 0); } } -void asm_xtensa_s32i_optimised(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset) { - if (word_offset < 16) { - asm_xtensa_op_s32i_n(as, reg_src, reg_base, word_offset); - } else if (word_offset < 256) { - asm_xtensa_op_s32i(as, reg_src, reg_base, word_offset); +void asm_xtensa_load_reg_reg_offset(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); + + if (operation_size == 2 && MP_FIT_UNSIGNED(4, offset)) { + asm_xtensa_op_l32i_n(as, reg_dest, reg_base, offset); + return; + } + + if (MP_FIT_UNSIGNED(8, offset)) { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, operation_size, reg_base, reg_dest, offset)); + return; + } + + asm_xtensa_mov_reg_i32_optimised(as, reg_dest, offset << operation_size); + asm_xtensa_op_add_n(as, reg_dest, reg_base, reg_dest); + if (operation_size == 2) { + asm_xtensa_op_l32i_n(as, reg_dest, reg_dest, 0); } else { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("asm overflow")); + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, operation_size, reg_dest, reg_dest, 0)); + } +} + +void asm_xtensa_store_reg_reg_offset(asm_xtensa_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); + + if (operation_size == 2 && MP_FIT_UNSIGNED(4, offset)) { + asm_xtensa_op_s32i_n(as, reg_src, reg_base, offset); + return; + } + + if (MP_FIT_UNSIGNED(8, offset)) { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 0x04 | operation_size, reg_base, reg_src, offset)); + return; + } + + asm_xtensa_mov_reg_i32_optimised(as, REG_TEMP, offset << operation_size); + asm_xtensa_op_add_n(as, REG_TEMP, reg_base, REG_TEMP); + if (operation_size == 2) { + asm_xtensa_op_s32i_n(as, reg_src, REG_TEMP, 0); + } else { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 0x04 | operation_size, REG_TEMP, reg_src, 0)); } } @@ -264,4 +353,47 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) { asm_xtensa_op_callx8(as, ASM_XTENSA_REG_A8); } +void asm_xtensa_bit_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t bit, mp_uint_t label, mp_uint_t condition) { + uint32_t dest = get_label_dest(as, label); + int32_t rel = dest - as->base.code_offset - 4; + if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT8(rel)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_bit_branch); + } + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(7, condition | ((bit >> 4) & 0x01), reg, bit & 0x0F, rel & 0xFF)); +} + +void asm_xtensa_call0(asm_xtensa_t *as, mp_uint_t label) { + uint32_t dest = get_label_dest(as, label); + int32_t rel = dest - as->base.code_offset - 3; + if (as->base.pass == MP_ASM_PASS_EMIT) { + if ((dest & 0x03) != 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_call0, MP_QSTR_target); + } + if ((rel & 0x03) != 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_call0, MP_QSTR_location); + } + if (!SIGNED_FIT18(rel)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_call0); + } + } + asm_xtensa_op_call0(as, rel); +} + +void asm_xtensa_l32r(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t label) { + uint32_t dest = get_label_dest(as, label); + int32_t rel = dest - as->base.code_offset; + if (as->base.pass == MP_ASM_PASS_EMIT) { + if ((dest & 0x03) != 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_l32r, MP_QSTR_target); + } + if ((rel & 0x03) != 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_l32r, MP_QSTR_location); + } + if (!SIGNED_FIT18(rel) || (rel >= 0)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_l32r); + } + } + asm_xtensa_op_l32r(as, reg, as->base.code_offset, dest); +} + #endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN diff --git a/py/asmxtensa.h b/py/asmxtensa.h index a8c39206bd0..ed98c9d7305 100644 --- a/py/asmxtensa.h +++ b/py/asmxtensa.h @@ -64,9 +64,11 @@ #define ASM_XTENSA_REG_A14 (14) #define ASM_XTENSA_REG_A15 (15) -// for bccz +// for bccz and bcci #define ASM_XTENSA_CCZ_EQ (0) #define ASM_XTENSA_CCZ_NE (1) +#define ASM_XTENSA_CCZ_LT (2) +#define ASM_XTENSA_CCZ_GE (3) // for bcc and setcc #define ASM_XTENSA_CC_NONE (0) @@ -291,15 +293,24 @@ void asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src); void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num); void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num); void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label); -void asm_xtensa_l32i_optimised(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset); -void asm_xtensa_s32i_optimised(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset); +void asm_xtensa_load_reg_reg_offset(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size); +void asm_xtensa_store_reg_reg_offset(asm_xtensa_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size); void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx); void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); +void asm_xtensa_bit_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t bit, mp_uint_t label, mp_uint_t condition); +void asm_xtensa_immediate_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t immediate, mp_uint_t label, mp_uint_t cond); +void asm_xtensa_call0(asm_xtensa_t *as, mp_uint_t label); +void asm_xtensa_l32r(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t label); // Holds a pointer to mp_fun_table #define ASM_XTENSA_REG_FUN_TABLE ASM_XTENSA_REG_A15 #define ASM_XTENSA_REG_FUN_TABLE_WIN ASM_XTENSA_REG_A7 +// Internal temporary register (currently aliased to REG_ARG_5 for xtensa, +// and to REG_TEMP2 for xtensawin). +#define ASM_XTENSA_REG_TEMPORARY ASM_XTENSA_REG_A6 +#define ASM_XTENSA_REG_TEMPORARY_WIN ASM_XTENSA_REG_A12 + // CIRCUITPY-CHANGE: prevent #if warning #if defined(GENERIC_ASM_API) && GENERIC_ASM_API @@ -330,9 +341,9 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); #define ASM_NUM_REGS_SAVED ASM_XTENSA_NUM_REGS_SAVED #define REG_FUN_TABLE ASM_XTENSA_REG_FUN_TABLE -#define ASM_ENTRY(as, nlocal) asm_xtensa_entry((as), (nlocal)) -#define ASM_EXIT(as) asm_xtensa_exit((as)) -#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind((as), (idx)) +#define ASM_ENTRY(as, nlocal, name) asm_xtensa_entry((as), (nlocal)) +#define ASM_EXIT(as) asm_xtensa_exit((as)) +#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind((as), (idx)) #else // Configuration for windowed calls with window size 8 @@ -360,9 +371,9 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); #define ASM_NUM_REGS_SAVED ASM_XTENSA_NUM_REGS_SAVED_WIN #define REG_FUN_TABLE ASM_XTENSA_REG_FUN_TABLE_WIN -#define ASM_ENTRY(as, nlocal) asm_xtensa_entry_win((as), (nlocal)) -#define ASM_EXIT(as) asm_xtensa_exit_win((as)) -#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind_win((as), (idx)) +#define ASM_ENTRY(as, nlocal, name) asm_xtensa_entry_win((as), (nlocal)) +#define ASM_EXIT(as) asm_xtensa_exit_win((as)) +#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind_win((as), (idx)) #endif @@ -408,16 +419,51 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_sub((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mull((as), (reg_dest), (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_l32i_optimised((as), (reg_dest), (reg_base), (word_offset)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l8ui((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), (uint16_offset)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (word_offset)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_xtensa_load_reg_reg_offset((as), (reg_dest), (reg_base), (byte_offset), 0) +#define ASM_LOAD8_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_xtensa_op_add_n((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_l8ui((as), (reg_dest), (reg_base), 0); \ + } while (0) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, halfword_offset) asm_xtensa_load_reg_reg_offset((as), (reg_dest), (reg_base), (halfword_offset), 1) +#define ASM_LOAD16_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_xtensa_op_addx2((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), 0); \ + } while (0) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_load_reg_reg_offset((as), (reg_dest), (reg_base), (word_offset), 2) +#define ASM_LOAD32_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_xtensa_op_addx4((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), 0); \ + } while (0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_s32i_optimised((as), (reg_dest), (reg_base), (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s8i((as), (reg_src), (reg_base), 0) -#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s16i((as), (reg_src), (reg_base), 0) -#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s32i_n((as), (reg_src), (reg_base), 0) +#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) ASM_STORE32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (word_offset)) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_src, reg_base, byte_offset) asm_xtensa_store_reg_reg_offset((as), (reg_src), (reg_base), (byte_offset), 0) +#define ASM_STORE8_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_xtensa_op_add_n((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_s8i((as), (reg_val), (reg_base), 0); \ + } while (0) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_src, reg_base, halfword_offset) asm_xtensa_store_reg_reg_offset((as), (reg_src), (reg_base), (halfword_offset), 1) +#define ASM_STORE16_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_xtensa_op_addx2((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_s16i((as), (reg_val), (reg_base), 0); \ + } while (0) +#define ASM_STORE32_REG_REG(as, reg_src, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_store_reg_reg_offset((as), (reg_dest), (reg_base), (word_offset), 2) +#define ASM_STORE32_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_xtensa_op_addx4((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_s32i_n((as), (reg_val), (reg_base), 0); \ + } while (0) #endif // GENERIC_ASM_API diff --git a/py/bc.c b/py/bc.c index c2956030e38..4caa022e3d8 100644 --- a/py/bc.c +++ b/py/bc.c @@ -88,7 +88,7 @@ const byte *mp_decode_uint_skip(const byte *ptr) { return ptr; } -static NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) { +static MP_NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE // generic message, used also for other argument issues (void)f; diff --git a/py/bc.h b/py/bc.h index 7658f66414f..3b7a6fe1c96 100644 --- a/py/bc.h +++ b/py/bc.h @@ -226,6 +226,7 @@ typedef struct _mp_compiled_module_t { bool has_native; size_t n_qstr; size_t n_obj; + size_t arch_flags; #endif } mp_compiled_module_t; @@ -303,7 +304,7 @@ static inline void mp_module_context_alloc_tables(mp_module_context_t *context, size_t nq = (n_qstr * sizeof(qstr_short_t) + sizeof(mp_uint_t) - 1) / sizeof(mp_uint_t); size_t no = n_obj; // CIRCUITPY-CHANGE - mp_uint_t *mem = m_malloc_items(nq + no); + mp_uint_t *mem = (mp_uint_t *)m_malloc_items(nq + no); context->constants.qstr_table = (qstr_short_t *)mem; context->constants.obj_table = (mp_obj_t *)(mem + nq); #else @@ -316,25 +317,35 @@ static inline void mp_module_context_alloc_tables(mp_module_context_t *context, #endif } +typedef struct _mp_code_lineinfo_t { + size_t bc_increment; + size_t line_increment; +} mp_code_lineinfo_t; + +static inline mp_code_lineinfo_t mp_bytecode_decode_lineinfo(const byte **line_info) { + mp_code_lineinfo_t result; + size_t c = (*line_info)[0]; + if ((c & 0x80) == 0) { + // 0b0LLBBBBB encoding + result.bc_increment = c & 0x1f; + result.line_increment = c >> 5; + *line_info += 1; + } else { + // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) + result.bc_increment = c & 0xf; + result.line_increment = ((c << 4) & 0x700) | (*line_info)[1]; + *line_info += 2; + } + return result; +} + static inline size_t mp_bytecode_get_source_line(const byte *line_info, const byte *line_info_top, size_t bc_offset) { size_t source_line = 1; while (line_info < line_info_top) { - size_t c = *line_info; - size_t b, l; - if ((c & 0x80) == 0) { - // 0b0LLBBBBB encoding - b = c & 0x1f; - l = c >> 5; - line_info += 1; - } else { - // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) - b = c & 0xf; - l = ((c << 4) & 0x700) | line_info[1]; - line_info += 2; - } - if (bc_offset >= b) { - bc_offset -= b; - source_line += l; + mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo(&line_info); + if (bc_offset >= decoded.bc_increment) { + bc_offset -= decoded.bc_increment; + source_line += decoded.line_increment; } else { // found source line corresponding to bytecode offset break; diff --git a/py/binary.c b/py/binary.c index 728f29815cd..180a13beec7 100644 --- a/py/binary.c +++ b/py/binary.c @@ -71,8 +71,7 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) { case 'Q': size = 8; break; - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'P': case 'O': case 'S': @@ -128,8 +127,7 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) { align = alignof(long long); size = sizeof(long long); break; - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'P': case 'O': case 'S': @@ -208,7 +206,7 @@ static float mp_decode_half_float(uint16_t hf) { ++e; } - fpu.i = ((hf & 0x8000) << 16) | (e << 23) | (m << 13); + fpu.i = ((hf & 0x8000u) << 16) | (e << 23) | (m << 13); return fpu.f; } @@ -289,20 +287,17 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index) { #if MICROPY_PY_BUILTINS_FLOAT case 'f': return mp_obj_new_float_from_f(((float *)p)[index]); - #if MICROPY_PY_DOUBLE_TYPECODE case 'd': return mp_obj_new_float_from_d(((double *)p)[index]); #endif - #endif - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES - // Extension to CPython: array of objects + // Extension to CPython: array of objects + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'O': return ((mp_obj_t *)p)[index]; // Extension to CPython: array of pointers case 'P': return mp_obj_new_int((mp_int_t)(uintptr_t)((void **)p)[index]); - #endif + #endif } return MP_OBJ_NEW_SMALL_INT(val); } @@ -352,14 +347,11 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte * long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p); - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - if (MICROPY_NONSTANDARD_TYPECODES && (val_type == 'O')) { + if (MICROPY_PY_STRUCT_UNSAFE_TYPECODES && val_type == 'O') { return (mp_obj_t)(mp_uint_t)val; - #if MICROPY_NONSTANDARD_TYPECODES - } else if (val_type == 'S') { + } else if (MICROPY_PY_STRUCT_UNSAFE_TYPECODES && val_type == 'S') { const char *s_val = (const char *)(uintptr_t)(mp_uint_t)val; return mp_obj_new_str_from_cstr(s_val); - #endif #if MICROPY_PY_BUILTINS_FLOAT } else if (val_type == 'e') { return mp_obj_new_float_from_f(mp_decode_half_float(val)); @@ -369,7 +361,6 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte * float f; } fpu = {val}; return mp_obj_new_float_from_f(fpu.f); - #if MICROPY_PY_DOUBLE_TYPECODE } else if (val_type == 'd') { union { uint64_t i; @@ -377,7 +368,6 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte * } fpu = {val}; return mp_obj_new_float_from_d(fpu.f); #endif - #endif } else if (is_signed(val_type)) { if ((long long)MP_SMALL_INT_MIN <= val && val <= (long long)MP_SMALL_INT_MAX) { return mp_obj_new_int((mp_int_t)val); @@ -430,8 +420,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p mp_uint_t val; switch (val_type) { - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'O': val = (mp_uint_t)val_in; break; @@ -449,6 +438,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p val = fp_sp.i; break; } + // CIRCUITPY-CHANGE #if MICROPY_PY_DOUBLE_TYPECODE case 'd': { union { @@ -507,14 +497,11 @@ void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_ case 'f': ((float *)p)[index] = mp_obj_get_float_to_f(val_in); break; - #if MICROPY_PY_DOUBLE_TYPECODE case 'd': ((double *)p)[index] = mp_obj_get_float_to_d(val_in); break; #endif - #endif - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES // Extension to CPython: array of objects case 'O': ((mp_obj_t *)p)[index] = val_in; @@ -582,18 +569,15 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, size_t index, mp_i case 'f': ((float *)p)[index] = (float)val; break; - #if MICROPY_PY_DOUBLE_TYPECODE case 'd': ((double *)p)[index] = (double)val; break; #endif - #endif - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES - // Extension to CPython: array of pointers + // Extension to CPython: array of pointers + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'P': ((void **)p)[index] = (void *)(uintptr_t)val; break; - #endif + #endif } } diff --git a/py/builtin.h b/py/builtin.h index 6efe3e8faca..388bc847005 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -138,6 +138,7 @@ extern const mp_obj_module_t mp_module_sys; extern const mp_obj_module_t mp_module_errno; extern const mp_obj_module_t mp_module_uctypes; extern const mp_obj_module_t mp_module_machine; +extern const mp_obj_module_t mp_module_math; extern const char MICROPY_PY_BUILTINS_HELP_TEXT[]; diff --git a/py/builtinhelp.c b/py/builtinhelp.c index d041d6915a6..9ab2a12d214 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -162,9 +162,8 @@ static void mp_help_print_obj(const mp_obj_t obj) { } if (map != NULL) { for (uint i = 0; i < map->alloc; i++) { - mp_obj_t key = map->table[i].key; - if (key != MP_OBJ_NULL) { - mp_help_print_info_about_object(key, map->table[i].value); + if (mp_map_slot_is_filled(map, i)) { + mp_help_print_info_about_object(map->table[i].key, map->table[i].value); } } } diff --git a/py/builtinimport.c b/py/builtinimport.c index e4e06d8e2cc..5d77ac42859 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -105,7 +105,26 @@ static mp_import_stat_t stat_module(vstr_t *path) { mp_import_stat_t stat = stat_path(path); DEBUG_printf("stat %s: %d\n", vstr_str(path), stat); if (stat == MP_IMPORT_STAT_DIR) { - return stat; + // CIRCUITPY-CHANGE: match CPython import precedence. A regular + // package (directory with __init__.py/.mpy) takes precedence, then a + // sibling .py/.mpy module, and only then a namespace package + // (directory without __init__). See + // https://docs.python.org/3/reference/import.html#regular-packages + size_t orig_len = path->len; + vstr_add_str(path, PATH_SEP_CHAR "__init__.py"); + mp_import_stat_t init_stat = stat_file_py_or_mpy(path); + path->len = orig_len; + if (init_stat == MP_IMPORT_STAT_FILE) { + return MP_IMPORT_STAT_DIR; + } + + vstr_add_str(path, ".py"); + mp_import_stat_t file_stat = stat_file_py_or_mpy(path); + if (file_stat == MP_IMPORT_STAT_FILE) { + return file_stat; + } + path->len = orig_len; + return MP_IMPORT_STAT_DIR; } // Not a directory, add .py and try as a file. @@ -118,7 +137,7 @@ static mp_import_stat_t stat_module(vstr_t *path) { // path (i.e. "/mod_name(.py)"). static mp_import_stat_t stat_top_level(qstr mod_name, vstr_t *dest) { DEBUG_printf("stat_top_level: '%s'\n", qstr_str(mod_name)); - #if MICROPY_PY_SYS + #if MICROPY_PY_SYS && MICROPY_PY_SYS_PATH size_t path_num; mp_obj_t *path_items; mp_obj_get_array(mp_sys_path, &path_num, &path_items); @@ -155,7 +174,7 @@ static mp_import_stat_t stat_top_level(qstr mod_name, vstr_t *dest) { #if MICROPY_MODULE_FROZEN_STR || MICROPY_ENABLE_COMPILER static void do_load_from_lexer(mp_module_context_t *context, mp_lexer_t *lex) { - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ qstr source_name = lex->source_name; mp_store_attr(MP_OBJ_FROM_PTR(&context->module), MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); #endif @@ -168,7 +187,7 @@ static void do_load_from_lexer(mp_module_context_t *context, mp_lexer_t *lex) { #if (MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD) || MICROPY_MODULE_FROZEN_MPY static void do_execute_proto_fun(const mp_module_context_t *context, mp_proto_fun_t proto_fun, qstr source_name) { - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ mp_store_attr(MP_OBJ_FROM_PTR(&context->module), MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); #else (void)source_name; @@ -227,7 +246,7 @@ static void do_load(mp_module_context_t *module_obj, vstr_t *file) { if (frozen_type == MP_FROZEN_MPY) { const mp_frozen_module_t *frozen = modref; module_obj->constants = frozen->constants; - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ qstr frozen_file_qstr = qstr_from_str(file_str + frozen_path_prefix_len); #else qstr frozen_file_qstr = MP_QSTRnull; @@ -270,7 +289,7 @@ static void do_load(mp_module_context_t *module_obj, vstr_t *file) { // Convert a relative (to the current module) import, going up "level" levels, // into an absolute import. -static void evaluate_relative_import(mp_int_t level, const char **module_name, size_t *module_name_len) { +static void evaluate_relative_import(mp_int_t level, const char **module_name, size_t *module_name_len, mp_obj_t globals) { // What we want to do here is to take the name of the current module, // remove trailing components, and concatenate the passed-in // module name. @@ -279,7 +298,7 @@ static void evaluate_relative_import(mp_int_t level, const char **module_name, s // module's position in the package hierarchy." // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name - mp_obj_t current_module_name_obj = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___name__)); + mp_obj_t current_module_name_obj = mp_obj_dict_get(globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__)); assert(current_module_name_obj != MP_OBJ_NULL); #if MICROPY_MODULE_OVERRIDE_MAIN_IMPORT && MICROPY_CPYTHON_COMPAT @@ -287,12 +306,12 @@ static void evaluate_relative_import(mp_int_t level, const char **module_name, s // This is a module loaded by -m command-line switch (e.g. unix port), // and so its __name__ has been set to "__main__". Get its real name // that we stored during import in the __main__ attribute. - current_module_name_obj = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); + current_module_name_obj = mp_obj_dict_get(globals, MP_OBJ_NEW_QSTR(MP_QSTR___main__)); } #endif // If we have a __path__ in the globals dict, then we're a package. - bool is_pkg = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP); + bool is_pkg = mp_map_lookup(mp_obj_dict_get_map(globals), MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP); #if DEBUG_PRINT DEBUG_printf("Current module/package: "); @@ -370,7 +389,7 @@ static mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, // Immediately return if the module at this level is already loaded. mp_map_elem_t *elem; - #if MICROPY_PY_SYS + #if MICROPY_PY_SYS && MICROPY_PY_SYS_PATH // If sys.path is empty, the intention is to force using a built-in. This // means we should also ignore any loaded modules with the same name // which may have come from the filesystem. @@ -406,6 +425,7 @@ static mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, // all the locations in sys.path. stat = stat_top_level(level_mod_name, &path); + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES // If filesystem failed, now try and see if it matches an extensible // built-in module. if (stat == MP_IMPORT_STAT_NO_EXIST) { @@ -414,6 +434,7 @@ static mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, return module_obj; } } + #endif } else { DEBUG_printf("Searching for sub-module\n"); @@ -577,10 +598,19 @@ mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) { const char *module_name = mp_obj_str_get_data(module_name_obj, &module_name_len); if (level != 0) { + // This is the dict with all global symbols. + mp_obj_t globals = MP_OBJ_FROM_PTR(mp_globals_get()); + if (n_args >= 2 && args[1] != mp_const_none) { + globals = args[1]; + if (!mp_obj_is_type(globals, &mp_type_dict)) { + mp_raise_TypeError(NULL); + } + } + // Turn "foo.bar" with level=3 into ".foo.bar". // Current module name is extracted from globals().__name__. - evaluate_relative_import(level, &module_name, &module_name_len); // module_name is now an absolute module path. + evaluate_relative_import(level, &module_name, &module_name_len, globals); } if (module_name_len == 0) { @@ -656,11 +686,13 @@ mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) { if (module_obj != MP_OBJ_NULL) { return module_obj; } + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES // Now try as an extensible built-in (e.g. `time`). module_obj = mp_module_get_builtin(module_name_qstr, true); if (module_obj != MP_OBJ_NULL) { return module_obj; } + #endif // Couldn't find the module, so fail #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index d8c95d18a79..4c91ed102c2 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -122,6 +122,9 @@ endif ifeq ($(CIRCUITPY_AUDIOBUSIO),1) SRC_PATTERNS += audiobusio/% endif +ifeq ($(CIRCUITPY_AUDIOI2SIN),1) +SRC_PATTERNS += audioi2sin/% +endif ifeq ($(CIRCUITPY_AUDIOIO),1) SRC_PATTERNS += audioio/% endif @@ -146,6 +149,9 @@ endif ifeq ($(CIRCUITPY_AUDIOMP3),1) SRC_PATTERNS += audiomp3/% endif +ifeq ($(CIRCUITPY_AUDIOSPEED),1) +SRC_PATTERNS += audiospeed/% +endif ifeq ($(CIRCUITPY_AURORA_EPAPER),1) SRC_PATTERNS += aurora_epaper/% endif @@ -201,6 +207,9 @@ endif ifeq ($(CIRCUITPY_DISPLAYIO),1) SRC_PATTERNS += displayio/% endif +ifeq ($(CIRCUITPY_DOTCLOCKFRAMEBUFFER),1) +SRC_PATTERNS += dotclockframebuffer/% +endif ifeq ($(CIRCUITPY_DUALBANK),1) SRC_PATTERNS += dualbank/% endif @@ -285,6 +294,9 @@ endif ifeq ($(CIRCUITPY_MAX3421E),1) SRC_PATTERNS += max3421e/% endif +ifeq ($(CIRCUITPY_MCP4822),1) +SRC_PATTERNS += mcp4822/% +endif ifeq ($(CIRCUITPY_MDNS),1) SRC_PATTERNS += mdns/% endif @@ -354,8 +366,8 @@ endif ifeq ($(CIRCUITPY_RGBMATRIX),1) SRC_PATTERNS += rgbmatrix/% endif -ifeq ($(CIRCUITPY_DOTCLOCKFRAMEBUFFER),1) -SRC_PATTERNS += dotclockframebuffer/% +ifeq ($(CIRCUITPY_QSPIBUS),1) +SRC_PATTERNS += qspibus/% endif ifeq ($(CIRCUITPY_RP2PIO),1) SRC_PATTERNS += rp2pio/% @@ -438,6 +450,9 @@ endif ifeq ($(CIRCUITPY_USB_VIDEO),1) SRC_PATTERNS += usb_video/% endif +ifeq ($(CIRCUITPY_USB_AUDIO),1) +SRC_PATTERNS += usb_audio/% +endif ifeq ($(CIRCUITPY_USB_HOST),1) SRC_PATTERNS += usb_host/% endif @@ -496,6 +511,8 @@ SRC_COMMON_HAL_ALL = \ audiobusio/I2SOut.c \ audiobusio/PDMIn.c \ audiobusio/__init__.c \ + audioi2sin/I2SIn.c \ + audioi2sin/__init__.c \ audioio/AudioOut.c \ audioio/__init__.c \ audiopwmio/PWMAudioOut.c \ @@ -529,6 +546,8 @@ SRC_COMMON_HAL_ALL = \ i2ctarget/I2CTarget.c \ i2ctarget/__init__.c \ max3421e/Max3421E.c \ + mcp4822/__init__.c \ + mcp4822/MCP4822.c \ memorymap/__init__.c \ memorymap/AddressRange.c \ microcontroller/__init__.c \ @@ -552,6 +571,8 @@ SRC_COMMON_HAL_ALL = \ pulseio/__init__.c \ pwmio/PWMOut.c \ pwmio/__init__.c \ + qspibus/QSPIBus.c \ + qspibus/__init__.c \ rclcpy/__init__.c \ rclcpy/Node.c \ rclcpy/Publisher.c \ @@ -683,6 +704,9 @@ SRC_SHARED_MODULE_ALL = \ audiocore/RawSample.c \ audiocore/WaveFile.c \ audiocore/__init__.c \ + audiospeed/Resampler.c \ + audiospeed/SpeedChanger.c \ + audiospeed/__init__.c \ audiodelays/Echo.c \ audiodelays/Chorus.c \ audiodelays/PitchShift.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index f6310dfaf68..381cb9538e4 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -17,6 +17,10 @@ // Always 1: defined in circuitpy_mpconfig.mk // #define CIRCUITPY (1) +#ifndef MP_SSIZE_MAX +#define MP_SSIZE_MAX (0x7fffffff) +#endif + // REPR_C encodes qstrs, 31-bit ints, and 30-bit floats in a single 32-bit word. #ifndef MICROPY_OBJ_REPR #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C) @@ -42,10 +46,14 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_PY_BLUETOOTH (0) #define MICROPY_PY_LWIP_SLIP (0) #define MICROPY_PY_OS_DUPTERM (0) +#define MICROPY_PYEXEC_COMPILE_ONLY (0) #define MICROPY_ROM_TEXT_COMPRESSION (0) #define MICROPY_VFS_LFS1 (0) #define MICROPY_VFS_LFS2 (0) +// Always turn on exit code handling +#define MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING (1) + #ifndef MICROPY_GCREGS_SETJMP #define MICROPY_GCREGS_SETJMP (0) #endif @@ -88,7 +96,6 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_MEM_STATS (0) #define MICROPY_MODULE_BUILTIN_INIT (1) #define MICROPY_MODULE_BUILTIN_SUBPACKAGES (1) -#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_OPT_COMPUTED_GOTO (1) #define MICROPY_OPT_COMPUTED_GOTO_SAVE_SPACE (CIRCUITPY_COMPUTED_GOTO_SAVE_SPACE) #define MICROPY_OPT_LOAD_ATTR_FAST_PATH (CIRCUITPY_OPT_LOAD_ATTR_FAST_PATH) @@ -141,6 +148,7 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_PY_RE (CIRCUITPY_RE) // Supplanted by shared-bindings/struct #define MICROPY_PY_STRUCT (0) +#define MICROPY_PY_STRUCT_UNSAFE_TYPECODES (0) #define MICROPY_PY_SYS (CIRCUITPY_SYS) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_STDFILES (1) @@ -193,21 +201,6 @@ extern void common_hal_mcu_enable_interrupts(void); // Track stack usage. Expose results via ustack module. #define MICROPY_MAX_STACK_USAGE (0) -#define UINT_FMT "%u" -#define INT_FMT "%d" -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless of actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif -#if __GNUC__ >= 10 // on recent gcc versions we can check that this is so -_Static_assert(sizeof(mp_int_t) == sizeof(void *)); -_Static_assert(sizeof(mp_uint_t) == sizeof(void *)); -#endif typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) @@ -269,6 +262,10 @@ typedef long mp_off_t; #define MICROPY_PY_COLLECTIONS_DEQUE_SUBSCR (CIRCUITPY_FULL_BUILD) #endif +#ifndef MICROPY_PY_DELATTR_SETATTR +#define MICROPY_PY_DELATTR_SETATTR (CIRCUITPY_FULL_BUILD) +#endif + #ifndef MICROPY_PY_DOUBLE_TYPECODE #define MICROPY_PY_DOUBLE_TYPECODE (CIRCUITPY_FULL_BUILD ? 1 : 0) #endif @@ -303,12 +300,10 @@ typedef long mp_off_t; #ifdef LONGINT_IMPL_MPZ #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MP_SSIZE_MAX (0x7fffffff) #endif #ifdef LONGINT_IMPL_LONGLONG #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) -#define MP_SSIZE_MAX (0x7fffffff) #endif #ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS @@ -394,9 +389,11 @@ typedef long mp_off_t; #define CIRCUITPY_DISPLAY_LIMIT (1) #endif -// Framebuffer area size in bytes. Rounded down to power of four for alignment. +// Display area buffer size in bytes for _refresh_area() VLA. +// Allocated on stack; boards with larger displays can override per-board. +// Default 512 bytes = 128 uint32_t words. #ifndef CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE -#define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (128) +#define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (512) #endif #else diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 56fc6957421..4f5a4bbd64d 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -135,6 +135,10 @@ CFLAGS += -DCIRCUITPY_AUDIOBUSIO_I2SOUT=$(CIRCUITPY_AUDIOBUSIO_I2SOUT) CIRCUITPY_AUDIOBUSIO_PDMIN ?= $(CIRCUITPY_AUDIOBUSIO) CFLAGS += -DCIRCUITPY_AUDIOBUSIO_PDMIN=$(CIRCUITPY_AUDIOBUSIO_PDMIN) +# I2S audio input (separate core module `audioi2sin`). +CIRCUITPY_AUDIOI2SIN ?= 0 +CFLAGS += -DCIRCUITPY_AUDIOI2SIN=$(CIRCUITPY_AUDIOI2SIN) + CIRCUITPY_AUDIOIO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_AUDIOIO=$(CIRCUITPY_AUDIOIO) @@ -155,6 +159,9 @@ CFLAGS += -DCIRCUITPY_AUDIOCORE_DEBUG=$(CIRCUITPY_AUDIOCORE_DEBUG) CIRCUITPY_AUDIOMP3 ?= $(call enable-if-all,$(CIRCUITPY_FULL_BUILD) $(CIRCUITPY_AUDIOCORE)) CFLAGS += -DCIRCUITPY_AUDIOMP3=$(CIRCUITPY_AUDIOMP3) +CIRCUITPY_AUDIOSPEED ?= 0 +CFLAGS += -DCIRCUITPY_AUDIOSPEED=$(CIRCUITPY_AUDIOSPEED) + CIRCUITPY_AUDIOEFFECTS ?= 0 CIRCUITPY_AUDIODELAYS ?= $(CIRCUITPY_AUDIOEFFECTS) CFLAGS += -DCIRCUITPY_AUDIODELAYS=$(CIRCUITPY_AUDIODELAYS) @@ -262,6 +269,10 @@ CFLAGS += -DCIRCUITPY_BUSDISPLAY=$(CIRCUITPY_BUSDISPLAY) CIRCUITPY_FOURWIRE ?= $(CIRCUITPY_DISPLAYIO) CFLAGS += -DCIRCUITPY_FOURWIRE=$(CIRCUITPY_FOURWIRE) +# QSPI bus protocol for quad-SPI displays (like RM690B0) +CIRCUITPY_QSPIBUS ?= 0 +CFLAGS += -DCIRCUITPY_QSPIBUS=$(CIRCUITPY_QSPIBUS) + CIRCUITPY_EPAPERDISPLAY ?= $(CIRCUITPY_DISPLAYIO) CFLAGS += -DCIRCUITPY_EPAPERDISPLAY=$(CIRCUITPY_EPAPERDISPLAY) @@ -346,6 +357,9 @@ CFLAGS += -DCIRCUITPY_HASHLIB_MBEDTLS=$(CIRCUITPY_HASHLIB_MBEDTLS) CIRCUITPY_HASHLIB_MBEDTLS_ONLY ?= $(call enable-if-all,$(CIRCUITPY_HASHLIB_MBEDTLS) $(call enable-if-not,$(CIRCUITPY_SSL))) CFLAGS += -DCIRCUITPY_HASHLIB_MBEDTLS_ONLY=$(CIRCUITPY_HASHLIB_MBEDTLS_ONLY) +# Always zero because it is for Zephyr only +CFLAGS += -DCIRCUITPY_HOSTNETWORK=0 + CIRCUITPY_I2CTARGET ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_I2CTARGET=$(CIRCUITPY_I2CTARGET) @@ -660,6 +674,9 @@ CFLAGS += -DCIRCUITPY_USB_HID_ENABLED_DEFAULT=$(CIRCUITPY_USB_HID_ENABLED_DEFAUL CIRCUITPY_USB_VIDEO ?= 0 CFLAGS += -DCIRCUITPY_USB_VIDEO=$(CIRCUITPY_USB_VIDEO) +CIRCUITPY_USB_AUDIO ?= 0 +CFLAGS += -DCIRCUITPY_USB_AUDIO=$(CIRCUITPY_USB_AUDIO) + CIRCUITPY_USB_HOST ?= 0 CFLAGS += -DCIRCUITPY_USB_HOST=$(CIRCUITPY_USB_HOST) @@ -703,6 +720,9 @@ CFLAGS += -DCIRCUITPY_USB_KEYBOARD_WORKFLOW=$(CIRCUITPY_USB_KEYBOARD_WORKFLOW) CIRCUITPY_USTACK ?= 0 CFLAGS += -DCIRCUITPY_USTACK=$(CIRCUITPY_USTACK) +# Zephyr display integration is only built by ports/zephyr-cp. +CFLAGS += -DCIRCUITPY_ZEPHYR_DISPLAY=0 + # for decompressing utilities CIRCUITPY_ZLIB ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_ZLIB=$(CIRCUITPY_ZLIB) diff --git a/py/compile.c b/py/compile.c index c7dd2fd4761..c8704131234 100644 --- a/py/compile.c +++ b/py/compile.c @@ -103,6 +103,7 @@ static const emit_method_table_t *emit_native_table[] = { &emit_native_xtensa_method_table, &emit_native_xtensawin_method_table, &emit_native_rv32_method_table, + NULL, &emit_native_debug_method_table, }; @@ -3295,7 +3296,9 @@ static void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind } // check structure of parse node - assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0])); + if (!MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0])) { + goto not_an_instruction; + } if (!MP_PARSE_NODE_IS_NULL(pns2->nodes[1])) { goto not_an_instruction; } @@ -3587,6 +3590,13 @@ void mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool case MP_EMIT_OPT_NATIVE_PYTHON: case MP_EMIT_OPT_VIPER: if (emit_native == NULL) { + // The check looks like this to work around a false + // warning in GCC 13 (and possibly later), where it + // assumes that the check will always fail. + if ((uintptr_t)NATIVE_EMITTER_TABLE == (uintptr_t)NULL) { + comp->compile_error = mp_obj_new_exception_msg(&mp_type_NotImplementedError, MP_ERROR_TEXT("cannot emit native code for this architecture")); + goto emit_finished; + } emit_native = NATIVE_EMITTER(new)(&comp->emit_common, &comp->compile_error, &comp->next_label, max_num_labels); } comp->emit_method_table = NATIVE_EMITTER_TABLE; @@ -3619,6 +3629,10 @@ void mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool } } + #if MICROPY_EMIT_NATIVE +emit_finished: + #endif + if (comp->compile_error != MP_OBJ_NULL) { // if there is no line number for the error then use the line // number for the start of this scope diff --git a/py/cstack.h b/py/cstack.h index b12a18e13fc..bcd919d31f9 100644 --- a/py/cstack.h +++ b/py/cstack.h @@ -35,7 +35,7 @@ void mp_cstack_init_with_sp_here(size_t stack_size); -inline static void mp_cstack_init_with_top(void *top, size_t stack_size) { +static inline void mp_cstack_init_with_top(void *top, size_t stack_size) { MP_STATE_THREAD(stack_top) = (char *)top; #if MICROPY_STACK_CHECK @@ -54,7 +54,7 @@ void mp_cstack_check(void); #else -inline static void mp_cstack_check(void) { +static inline void mp_cstack_check(void) { // No-op when stack checking is disabled } diff --git a/py/dynruntime.h b/py/dynruntime.h index e87cf6591c4..ab155a13875 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -70,7 +70,7 @@ #define m_realloc(ptr, new_num_bytes) (m_realloc_dyn((ptr), (new_num_bytes))) #define m_realloc_maybe(ptr, new_num_bytes, allow_move) (m_realloc_maybe_dyn((ptr), (new_num_bytes), (allow_move))) -static NORETURN inline void m_malloc_fail_dyn(size_t num_bytes) { +static MP_NORETURN inline void m_malloc_fail_dyn(size_t num_bytes) { mp_fun_table.raise_msg( mp_fun_table.load_global(MP_QSTR_MemoryError), "memory allocation failed"); @@ -289,7 +289,7 @@ static inline void *mp_obj_malloc_helper_dyn(size_t num_bytes, const mp_obj_type #define nlr_raise(o) (mp_raise_dyn(o)) #define mp_raise_type_arg(type, arg) (mp_raise_dyn(mp_obj_new_exception_arg1_dyn((type), (arg)))) -// CIRCUITPY-CHANGE: use str +// CIRCUITPY-CHANGE: use mp_raise_msg_str #define mp_raise_msg(type, msg) (mp_fun_table.raise_msg_str((type), (msg))) #define mp_raise_OSError(er) (mp_raise_OSError_dyn(er)) #define mp_raise_NotImplementedError(msg) (mp_raise_msg(&mp_type_NotImplementedError, (msg))) @@ -301,14 +301,14 @@ static inline mp_obj_t mp_obj_new_exception_arg1_dyn(const mp_obj_type_t *exc_ty return mp_call_function_n_kw(MP_OBJ_FROM_PTR(exc_type), 1, 0, &args[0]); } -static NORETURN inline void mp_raise_dyn(mp_obj_t o) { +static MP_NORETURN inline void mp_raise_dyn(mp_obj_t o) { mp_fun_table.raise(o); for (;;) { } } // CIRCUITPY-CHANGE: new routine -static NORETURN inline void mp_raise_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { +static MP_NORETURN inline void mp_raise_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { mp_fun_table.raise(mp_obj_new_exception_arg1_dyn(exc_type, arg)); for (;;) { } diff --git a/py/dynruntime.mk b/py/dynruntime.mk index 807befb464a..030728cfc9a 100644 --- a/py/dynruntime.mk +++ b/py/dynruntime.mk @@ -63,14 +63,14 @@ else ifeq ($(ARCH),armv6m) # thumb CROSS = arm-none-eabi- CFLAGS_ARCH += -mthumb -mcpu=cortex-m0 -MICROPY_FLOAT_IMPL ?= none +MICROPY_FLOAT_IMPL ?= float else ifeq ($(ARCH),armv7m) # thumb CROSS = arm-none-eabi- CFLAGS_ARCH += -mthumb -mcpu=cortex-m3 -MICROPY_FLOAT_IMPL ?= none +MICROPY_FLOAT_IMPL ?= float else ifeq ($(ARCH),armv7emsp) @@ -124,6 +124,10 @@ else $(error architecture '$(ARCH)' not supported) endif +ifneq ($(findstring -musl,$(shell $(CROSS)gcc -dumpmachine)),) +USE_MUSL := 1 +endif + MICROPY_FLOAT_IMPL_UPPER = $(shell echo $(MICROPY_FLOAT_IMPL) | tr '[:lower:]' '[:upper:]') CFLAGS += $(CFLAGS_ARCH) -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_$(MICROPY_FLOAT_IMPL_UPPER) @@ -147,6 +151,8 @@ ifeq ($(LINK_RUNTIME),1) # distribution. ifeq ($(USE_PICOLIBC),1) LIBM_NAME := libc.a +else ifeq ($(USE_MUSL),1) +LIBM_NAME := libc.a else LIBM_NAME := libm.a endif @@ -166,6 +172,9 @@ endif endif MPY_LD_FLAGS += $(addprefix -l, $(LIBGCC_PATH) $(LIBM_PATH)) endif +ifneq ($(MPY_EXTERN_SYM_FILE),) +MPY_LD_FLAGS += --externs "$(realpath $(MPY_EXTERN_SYM_FILE))" +endif CFLAGS += $(CFLAGS_EXTRA) diff --git a/py/emitcommon.c b/py/emitcommon.c index a9eb6e2021f..1369c544c54 100644 --- a/py/emitcommon.c +++ b/py/emitcommon.c @@ -25,6 +25,7 @@ */ #include +#include #include "py/emit.h" #include "py/nativeglue.h" @@ -72,7 +73,25 @@ static bool strictly_equal(mp_obj_t a, mp_obj_t b) { } return true; } else { - return mp_obj_equal(a, b); + if (!mp_obj_equal(a, b)) { + return false; + } + #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_COMP_CONST_FLOAT + if (a_type == &mp_type_float) { + mp_float_t a_val = mp_obj_float_get(a); + // CIRCUITPY-CHANGE: ignore float equal warning + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + if (a_val == (mp_float_t)0.0) { + // Although 0.0 == -0.0, they are not strictly_equal and + // must be stored as two different constants in .mpy files + mp_float_t b_val = mp_obj_float_get(b); + return signbit(a_val) == signbit(b_val); + } + #pragma GCC diagnostic pop + } + #endif + return true; } } diff --git a/py/emitglue.c b/py/emitglue.c index 8cc14bdc54e..c6ad3e3bc38 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -32,6 +32,7 @@ #include #include "py/emitglue.h" +#include "py/mphal.h" #include "py/runtime0.h" #include "py/bc.h" #include "py/objfun.h" @@ -133,6 +134,9 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, cons "mcr p15, 0, r0, c7, c7, 0\n" // invalidate I-cache and D-cache : : : "r0", "cc"); #endif + #elif (MICROPY_EMIT_RV32 || MICROPY_EMIT_INLINE_RV32) && defined(MP_HAL_CLEAN_DCACHE) + // Flush the D-cache. + MP_HAL_CLEAN_DCACHE(fun_data, fun_len); #endif rc->kind = kind; diff --git a/py/emitinlinerv32.c b/py/emitinlinerv32.c index a539242b84d..e81b152087d 100644 --- a/py/emitinlinerv32.c +++ b/py/emitinlinerv32.c @@ -196,7 +196,6 @@ typedef enum { CALL_R, // Opcode Register CALL_RL, // Opcode Register, Label CALL_N, // Opcode - CALL_I, // Opcode Immediate CALL_RII, // Opcode Register, Register, Immediate CALL_RIR, // Opcode Register, Immediate(Register) CALL_COUNT @@ -210,7 +209,6 @@ typedef enum { #define U (1 << 2) // Unsigned immediate #define Z (1 << 3) // Non-zero -typedef void (*call_l_t)(asm_rv32_t *state, mp_uint_t label_index); typedef void (*call_ri_t)(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate); typedef void (*call_rri_t)(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_int_t immediate); typedef void (*call_rii_t)(asm_rv32_t *state, mp_uint_t rd, mp_uint_t immediate1, mp_int_t immediate2); @@ -225,7 +223,7 @@ typedef struct _opcode_t { uint16_t argument1_mask : 4; uint16_t argument2_mask : 4; uint16_t argument3_mask : 4; - uint16_t arguments_count : 2; + uint16_t parse_nodes : 2; // 2 bits available here uint32_t calling_convention : 4; uint32_t argument1_kind : 4; @@ -234,7 +232,8 @@ typedef struct _opcode_t { uint32_t argument2_shift : 4; uint32_t argument3_kind : 4; uint32_t argument3_shift : 4; - // 4 bits available here + uint32_t required_extensions : 1; + // 3 bits available here void *emitter; } opcode_t; @@ -297,88 +296,91 @@ static const uint32_t OPCODE_MASKS[] = { }; static const opcode_t OPCODES[] = { - { MP_QSTR_add, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_add }, - { MP_QSTR_addi, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, asm_rv32_opcode_addi }, - { MP_QSTR_and_, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_and }, - { MP_QSTR_andi, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, asm_rv32_opcode_andi }, - { MP_QSTR_auipc, MASK_FFFFFFFF, MASK_FFFFF000, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 12, N, 0, asm_rv32_opcode_auipc }, - { MP_QSTR_beq, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, asm_rv32_opcode_beq }, - { MP_QSTR_bge, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, asm_rv32_opcode_bge }, - { MP_QSTR_bgeu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, asm_rv32_opcode_bgeu }, - { MP_QSTR_blt, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, asm_rv32_opcode_blt }, - { MP_QSTR_bltu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, asm_rv32_opcode_bltu }, - { MP_QSTR_bne, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, asm_rv32_opcode_bne }, - { MP_QSTR_csrrc, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, IU, 0, asm_rv32_opcode_csrrc }, - { MP_QSTR_csrrs, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, IU, 0, asm_rv32_opcode_csrrs }, - { MP_QSTR_csrrw, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, IU, 0, asm_rv32_opcode_csrrw }, - { MP_QSTR_csrrci, MASK_FFFFFFFF, MASK_00000FFF, MASK_0000001F, 3, CALL_RII, R, 0, IU, 0, IU, 0, asm_rv32_opcode_csrrci }, - { MP_QSTR_csrrsi, MASK_FFFFFFFF, MASK_00000FFF, MASK_0000001F, 3, CALL_RII, R, 0, IU, 0, IU, 0, asm_rv32_opcode_csrrsi }, - { MP_QSTR_csrrwi, MASK_FFFFFFFF, MASK_00000FFF, MASK_0000001F, 3, CALL_RII, R, 0, IU, 0, IU, 0, asm_rv32_opcode_csrrwi }, - { MP_QSTR_c_add, MASK_FFFFFFFE, MASK_FFFFFFFE, MASK_NOT_USED, 2, CALL_RR, R, 0, R, 0, N, 0, asm_rv32_opcode_cadd }, - { MP_QSTR_c_addi, MASK_FFFFFFFE, MASK_0000003F, MASK_NOT_USED, 2, CALL_RI, R, 0, IZ, 0, N, 0, asm_rv32_opcode_caddi }, - { MP_QSTR_c_addi4spn, MASK_0000FF00, MASK_000003FC, MASK_NOT_USED, 2, CALL_RI, R, 0, IUZ, 0, N, 0, asm_rv32_opcode_caddi4spn }, - { MP_QSTR_c_and, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, asm_rv32_opcode_cand }, - { MP_QSTR_c_andi, MASK_0000FF00, MASK_0000003F, MASK_NOT_USED, 2, CALL_RI, RC, 0, I, 0, N, 0, asm_rv32_opcode_candi }, - { MP_QSTR_c_beqz, MASK_0000FF00, MASK_000001FE, MASK_NOT_USED, 2, CALL_RL, RC, 0, L, 0, N, 0, asm_rv32_opcode_cbeqz }, - { MP_QSTR_c_bnez, MASK_0000FF00, MASK_000001FE, MASK_NOT_USED, 2, CALL_RL, RC, 0, L, 0, N, 0, asm_rv32_opcode_cbnez }, - { MP_QSTR_c_ebreak, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, asm_rv32_opcode_cebreak }, - { MP_QSTR_c_j, MASK_00000FFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_L, L, 0, N, 0, N, 0, asm_rv32_opcode_cj }, - { MP_QSTR_c_jal, MASK_00000FFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_L, L, 0, N, 0, N, 0, asm_rv32_opcode_cjal }, - { MP_QSTR_c_jalr, MASK_FFFFFFFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_R, R, 0, N, 0, N, 0, asm_rv32_opcode_cjalr }, - { MP_QSTR_c_jr, MASK_FFFFFFFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_R, R, 0, N, 0, N, 0, asm_rv32_opcode_cjr }, - { MP_QSTR_c_li, MASK_FFFFFFFE, MASK_0000003F, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, asm_rv32_opcode_cli }, - { MP_QSTR_c_lui, MASK_FFFFFFFA, MASK_0001F800, MASK_NOT_USED, 2, CALL_RI, R, 0, IUZ, 12, N, 0, asm_rv32_opcode_clui }, - { MP_QSTR_c_lw, MASK_0000FF00, MASK_0000007C, MASK_0000FF00, 3, CALL_RIR, RC, 0, I, 0, RC, 0, asm_rv32_opcode_clw }, - { MP_QSTR_c_lwsp, MASK_FFFFFFFE, MASK_000000FC, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, asm_rv32_opcode_clwsp }, - { MP_QSTR_c_mv, MASK_FFFFFFFE, MASK_FFFFFFFE, MASK_NOT_USED, 2, CALL_RR, R, 0, R, 0, N, 0, asm_rv32_opcode_cmv }, - { MP_QSTR_c_nop, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, asm_rv32_opcode_cnop }, - { MP_QSTR_c_or, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, asm_rv32_opcode_cor }, - { MP_QSTR_c_slli, MASK_FFFFFFFE, MASK_0000001F, MASK_NOT_USED, 2, CALL_RI, R, 0, IU, 0, N, 0, asm_rv32_opcode_cslli }, - { MP_QSTR_c_srai, MASK_0000FF00, MASK_0000001F, MASK_NOT_USED, 2, CALL_RI, RC, 0, IU, 0, N, 0, asm_rv32_opcode_csrai }, - { MP_QSTR_c_srli, MASK_0000FF00, MASK_0000001F, MASK_NOT_USED, 2, CALL_RI, RC, 0, IU, 0, N, 0, asm_rv32_opcode_csrli }, - { MP_QSTR_c_sub, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, asm_rv32_opcode_csub }, - { MP_QSTR_c_sw, MASK_0000FF00, MASK_0000007C, MASK_0000FF00, 3, CALL_RIR, RC, 0, I, 0, RC, 0, asm_rv32_opcode_csw }, - { MP_QSTR_c_swsp, MASK_FFFFFFFF, MASK_000000FC, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, asm_rv32_opcode_cswsp }, - { MP_QSTR_c_xor, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, asm_rv32_opcode_cxor }, - { MP_QSTR_div, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_div }, - { MP_QSTR_divu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_divu }, - { MP_QSTR_ebreak, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, asm_rv32_opcode_ebreak }, - { MP_QSTR_ecall, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, asm_rv32_opcode_ecall }, - { MP_QSTR_jal, MASK_FFFFFFFF, MASK_001FFFFE, MASK_NOT_USED, 2, CALL_RL, R, 0, L, 0, N, 0, asm_rv32_opcode_jal }, - { MP_QSTR_jalr, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, asm_rv32_opcode_jalr }, - { MP_QSTR_la, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_NOT_USED, 2, CALL_RL, R, 0, L, 0, N, 0, opcode_la }, - { MP_QSTR_lb, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 3, CALL_RIR, R, 0, I, 0, R, 0, asm_rv32_opcode_lb }, - { MP_QSTR_lbu, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 3, CALL_RIR, R, 0, I, 0, R, 0, asm_rv32_opcode_lbu }, - { MP_QSTR_lh, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 3, CALL_RIR, R, 0, I, 0, R, 0, asm_rv32_opcode_lh }, - { MP_QSTR_lhu, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 3, CALL_RIR, R, 0, I, 0, R, 0, asm_rv32_opcode_lhu }, - { MP_QSTR_li, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, opcode_li }, - { MP_QSTR_lui, MASK_FFFFFFFF, MASK_FFFFF000, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 12, N, 0, asm_rv32_opcode_lui }, - { MP_QSTR_lw, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 3, CALL_RIR, R, 0, I, 0, R, 0, asm_rv32_opcode_lw }, - { MP_QSTR_mv, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_NOT_USED, 2, CALL_RR, R, 0, R, 0, N, 0, asm_rv32_opcode_cmv }, - { MP_QSTR_mul, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_mul }, - { MP_QSTR_mulh, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_mulh }, - { MP_QSTR_mulhsu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_mulhsu }, - { MP_QSTR_mulhu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_mulhu }, - { MP_QSTR_or_, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_or }, - { MP_QSTR_ori, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, asm_rv32_opcode_ori }, - { MP_QSTR_rem, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_rem }, - { MP_QSTR_remu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_remu }, - { MP_QSTR_sb, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 3, CALL_RIR, R, 0, I, 0, R, 0, asm_rv32_opcode_sb }, - { MP_QSTR_sh, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 3, CALL_RIR, R, 0, I, 0, R, 0, asm_rv32_opcode_sh }, - { MP_QSTR_sll, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_sll }, - { MP_QSTR_slli, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_0000001F, 3, CALL_RRI, R, 0, R, 0, IU, 0, asm_rv32_opcode_slli }, - { MP_QSTR_slt, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_slt }, - { MP_QSTR_slti, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, asm_rv32_opcode_slti }, - { MP_QSTR_sltiu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, asm_rv32_opcode_sltiu }, - { MP_QSTR_sltu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_sltu }, - { MP_QSTR_sra, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_sra }, - { MP_QSTR_srai, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_0000001F, 3, CALL_RRI, R, 0, R, 0, IU, 0, asm_rv32_opcode_srai }, - { MP_QSTR_srl, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_srl }, - { MP_QSTR_srli, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_0000001F, 3, CALL_RRI, R, 0, R, 0, IU, 0, asm_rv32_opcode_srli }, - { MP_QSTR_sub, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_sub }, - { MP_QSTR_sw, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 3, CALL_RIR, R, 0, I, 0, R, 0, asm_rv32_opcode_sw }, - { MP_QSTR_xor, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, asm_rv32_opcode_xor }, - { MP_QSTR_xori, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, asm_rv32_opcode_xori }, + { MP_QSTR_add, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_add }, + { MP_QSTR_addi, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_addi }, + { MP_QSTR_and_, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_and }, + { MP_QSTR_andi, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_andi }, + { MP_QSTR_auipc, MASK_FFFFFFFF, MASK_FFFFF000, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 12, N, 0, RV32_EXT_NONE, asm_rv32_opcode_auipc }, + { MP_QSTR_beq, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_beq }, + { MP_QSTR_bge, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_bge }, + { MP_QSTR_bgeu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_bgeu }, + { MP_QSTR_blt, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_blt }, + { MP_QSTR_bltu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_bltu }, + { MP_QSTR_bne, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_bne }, + { MP_QSTR_csrrc, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrc }, + { MP_QSTR_csrrs, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrs }, + { MP_QSTR_csrrw, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrw }, + { MP_QSTR_csrrci, MASK_FFFFFFFF, MASK_00000FFF, MASK_0000001F, 3, CALL_RII, R, 0, IU, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrci }, + { MP_QSTR_csrrsi, MASK_FFFFFFFF, MASK_00000FFF, MASK_0000001F, 3, CALL_RII, R, 0, IU, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrsi }, + { MP_QSTR_csrrwi, MASK_FFFFFFFF, MASK_00000FFF, MASK_0000001F, 3, CALL_RII, R, 0, IU, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrwi }, + { MP_QSTR_c_add, MASK_FFFFFFFE, MASK_FFFFFFFE, MASK_NOT_USED, 2, CALL_RR, R, 0, R, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cadd }, + { MP_QSTR_c_addi, MASK_FFFFFFFE, MASK_0000003F, MASK_NOT_USED, 2, CALL_RI, R, 0, IZ, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_caddi }, + { MP_QSTR_c_addi4spn, MASK_0000FF00, MASK_000003FC, MASK_NOT_USED, 2, CALL_RI, R, 0, IUZ, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_caddi4spn }, + { MP_QSTR_c_and, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cand }, + { MP_QSTR_c_andi, MASK_0000FF00, MASK_0000003F, MASK_NOT_USED, 2, CALL_RI, RC, 0, I, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_candi }, + { MP_QSTR_c_beqz, MASK_0000FF00, MASK_000001FE, MASK_NOT_USED, 2, CALL_RL, RC, 0, L, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cbeqz }, + { MP_QSTR_c_bnez, MASK_0000FF00, MASK_000001FE, MASK_NOT_USED, 2, CALL_RL, RC, 0, L, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cbnez }, + { MP_QSTR_c_ebreak, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cebreak }, + { MP_QSTR_c_j, MASK_00000FFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_L, L, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cj }, + { MP_QSTR_c_jal, MASK_00000FFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_L, L, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cjal }, + { MP_QSTR_c_jalr, MASK_FFFFFFFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_R, R, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cjalr }, + { MP_QSTR_c_jr, MASK_FFFFFFFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_R, R, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cjr }, + { MP_QSTR_c_li, MASK_FFFFFFFE, MASK_0000003F, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cli }, + { MP_QSTR_c_lui, MASK_FFFFFFFA, MASK_0001F800, MASK_NOT_USED, 2, CALL_RI, R, 0, IUZ, 12, N, 0, RV32_EXT_NONE, asm_rv32_opcode_clui }, + { MP_QSTR_c_lw, MASK_0000FF00, MASK_0000007C, MASK_0000FF00, 2, CALL_RIR, RC, 0, I, 0, RC, 0, RV32_EXT_NONE, asm_rv32_opcode_clw }, + { MP_QSTR_c_lwsp, MASK_FFFFFFFE, MASK_000000FC, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_clwsp }, + { MP_QSTR_c_mv, MASK_FFFFFFFE, MASK_FFFFFFFE, MASK_NOT_USED, 2, CALL_RR, R, 0, R, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cmv }, + { MP_QSTR_c_nop, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cnop }, + { MP_QSTR_c_or, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cor }, + { MP_QSTR_c_slli, MASK_FFFFFFFE, MASK_0000001F, MASK_NOT_USED, 2, CALL_RI, R, 0, IU, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cslli }, + { MP_QSTR_c_srai, MASK_0000FF00, MASK_0000001F, MASK_NOT_USED, 2, CALL_RI, RC, 0, IU, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_csrai }, + { MP_QSTR_c_srli, MASK_0000FF00, MASK_0000001F, MASK_NOT_USED, 2, CALL_RI, RC, 0, IU, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_csrli }, + { MP_QSTR_c_sub, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_csub }, + { MP_QSTR_c_sw, MASK_0000FF00, MASK_0000007C, MASK_0000FF00, 2, CALL_RIR, RC, 0, I, 0, RC, 0, RV32_EXT_NONE, asm_rv32_opcode_csw }, + { MP_QSTR_c_swsp, MASK_FFFFFFFF, MASK_000000FC, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cswsp }, + { MP_QSTR_c_xor, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cxor }, + { MP_QSTR_div, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_div }, + { MP_QSTR_divu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_divu }, + { MP_QSTR_ebreak, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_ebreak }, + { MP_QSTR_ecall, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_ecall }, + { MP_QSTR_jal, MASK_FFFFFFFF, MASK_001FFFFE, MASK_NOT_USED, 2, CALL_RL, R, 0, L, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_jal }, + { MP_QSTR_jalr, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_jalr }, + { MP_QSTR_la, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_NOT_USED, 2, CALL_RL, R, 0, L, 0, N, 0, RV32_EXT_NONE, opcode_la }, + { MP_QSTR_lb, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lb }, + { MP_QSTR_lbu, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lbu }, + { MP_QSTR_lh, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lh }, + { MP_QSTR_lhu, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lhu }, + { MP_QSTR_li, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, RV32_EXT_NONE, opcode_li }, + { MP_QSTR_lui, MASK_FFFFFFFF, MASK_FFFFF000, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 12, N, 0, RV32_EXT_NONE, asm_rv32_opcode_lui }, + { MP_QSTR_lw, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lw }, + { MP_QSTR_mv, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_NOT_USED, 2, CALL_RR, R, 0, R, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cmv }, + { MP_QSTR_mul, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_mul }, + { MP_QSTR_mulh, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_mulh }, + { MP_QSTR_mulhsu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_mulhsu }, + { MP_QSTR_mulhu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_mulhu }, + { MP_QSTR_or_, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_or }, + { MP_QSTR_ori, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_ori }, + { MP_QSTR_rem, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_rem }, + { MP_QSTR_remu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_remu }, + { MP_QSTR_sb, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sb }, + { MP_QSTR_sh, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sh }, + { MP_QSTR_sh1add, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_ZBA, asm_rv32_opcode_sh1add }, + { MP_QSTR_sh2add, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_ZBA, asm_rv32_opcode_sh2add }, + { MP_QSTR_sh3add, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_ZBA, asm_rv32_opcode_sh3add }, + { MP_QSTR_sll, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sll }, + { MP_QSTR_slli, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_0000001F, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_slli }, + { MP_QSTR_slt, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_slt }, + { MP_QSTR_slti, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_slti }, + { MP_QSTR_sltiu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_sltiu }, + { MP_QSTR_sltu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sltu }, + { MP_QSTR_sra, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sra }, + { MP_QSTR_srai, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_0000001F, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_srai }, + { MP_QSTR_srl, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_srl }, + { MP_QSTR_srli, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_0000001F, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_srli }, + { MP_QSTR_sub, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sub }, + { MP_QSTR_sw, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sw }, + { MP_QSTR_xor, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_xor }, + { MP_QSTR_xori, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_xori }, }; #undef RC @@ -388,9 +390,9 @@ static const opcode_t OPCODES[] = { // These two checks assume the bitmasks are contiguous. -static bool is_in_signed_mask(mp_uint_t mask, mp_uint_t value) { - mp_uint_t leading_zeroes = mp_clz(mask); - if (leading_zeroes == 0 || leading_zeroes > 32) { +static bool is_in_signed_mask(uint32_t mask, mp_uint_t value) { + uint32_t leading_zeroes = mp_clz(mask); + if (leading_zeroes == 0) { return true; } mp_uint_t positive_mask = ~(mask & ~(1U << (31 - leading_zeroes))); @@ -435,9 +437,9 @@ static bool validate_integer(mp_uint_t value, mp_uint_t mask, mp_uint_t flags) { #define ET_WRONG_ARGUMENTS_COUNT MP_ERROR_TEXT("opcode '%q': expecting %d arguments") #define ET_OUT_OF_RANGE MP_ERROR_TEXT("opcode '%q' argument %d: out of range") -static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr, - const opcode_t *opcode, mp_parse_node_t node, mp_uint_t node_index) { +static bool serialise_argument(emit_inline_asm_t *emit, const opcode_t *opcode, mp_parse_node_t node, mp_uint_t node_index, mp_uint_t *serialised) { assert((node_index < 3) && "Invalid argument node number."); + assert(serialised && "Serialised value pointer is NULL."); uint32_t kind = 0; uint32_t shift = 0; @@ -466,17 +468,19 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr, break; } + mp_uint_t serialised_value = 0; + switch (kind & 0x03) { case N: assert(mask == OPCODE_MASKS[MASK_NOT_USED] && "Invalid mask index for missing operand."); - return true; + break; case R: { mp_uint_t register_index; if (!parse_register_node(node, ®ister_index, false)) { emit_inline_rv32_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - ET_WRONG_ARGUMENT_KIND, opcode_qstr, node_index + 1, MP_QSTR_register)); + ET_WRONG_ARGUMENT_KIND, opcode->qstring, node_index + 1, MP_QSTR_register)); return false; } @@ -484,11 +488,11 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr, emit_inline_rv32_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("opcode '%q' argument %d: unknown register"), - opcode_qstr, node_index + 1)); + opcode->qstring, node_index + 1)); return false; } - return true; + serialised_value = (kind & C) ? RV32_MAP_IN_C_REGISTER_WINDOW(register_index) : register_index; } break; @@ -497,7 +501,7 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr, if (!mp_parse_node_get_int_maybe(node, &object)) { emit_inline_rv32_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - ET_WRONG_ARGUMENT_KIND, opcode_qstr, node_index + 1, MP_QSTR_integer)); + ET_WRONG_ARGUMENT_KIND, opcode->qstring, node_index + 1, MP_QSTR_integer)); return false; } @@ -516,7 +520,7 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr, goto zero_immediate; } - return true; + serialised_value = immediate; } break; @@ -524,7 +528,7 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr, if (!MP_PARSE_NODE_IS_ID(node)) { emit_inline_rv32_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - ET_WRONG_ARGUMENT_KIND, opcode_qstr, node_index + 1, MP_QSTR_label)); + ET_WRONG_ARGUMENT_KIND, opcode->qstring, node_index + 1, MP_QSTR_label)); return false; } @@ -534,7 +538,7 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr, emit_inline_rv32_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("opcode '%q' argument %d: undefined label '%q'"), - opcode_qstr, node_index + 1, qstring)); + opcode->qstring, node_index + 1, qstring)); return false; } @@ -548,43 +552,45 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr, goto out_of_range; } } - return true; + + serialised_value = displacement; } break; default: assert(!"Unknown argument kind"); + MP_UNREACHABLE; break; } - return false; + *serialised = serialised_value; + return true; out_of_range: emit_inline_rv32_error_exc(emit, - mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_OUT_OF_RANGE, opcode_qstr, node_index + 1)); + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_OUT_OF_RANGE, opcode->qstring, node_index + 1)); return false; zero_immediate: emit_inline_rv32_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("opcode '%q' argument %d: must not be zero"), - opcode_qstr, node_index + 1)); + opcode->qstring, node_index + 1)); return false; } -static bool parse_register_offset_node(emit_inline_asm_t *emit, qstr opcode_qstr, const opcode_t *opcode_data, mp_parse_node_t node, mp_uint_t node_index, mp_parse_node_t *register_node, mp_parse_node_t *offset_node, bool *negative) { - assert(register_node != NULL && "Register node pointer is NULL."); - assert(offset_node != NULL && "Offset node pointer is NULL."); - assert(negative != NULL && "Negative pointer is NULL."); +static bool serialise_register_offset_node(emit_inline_asm_t *emit, const opcode_t *opcode_data, mp_parse_node_t node, mp_uint_t node_index, mp_uint_t *offset, mp_uint_t *base) { + assert(offset && "Attempting to store the offset value into NULL."); + assert(base && "Attempting to store the base register into NULL."); if (!MP_PARSE_NODE_IS_STRUCT_KIND(node, PN_atom_expr_normal) && !MP_PARSE_NODE_IS_STRUCT_KIND(node, PN_factor_2)) { goto invalid_structure; } mp_parse_node_struct_t *node_struct = (mp_parse_node_struct_t *)node; - *negative = false; + bool negative = false; if (MP_PARSE_NODE_IS_STRUCT_KIND(node, PN_factor_2)) { if (MP_PARSE_NODE_IS_TOKEN_KIND(node_struct->nodes[0], MP_TOKEN_OP_MINUS)) { - *negative = true; + negative = true; } else { if (!MP_PARSE_NODE_IS_TOKEN_KIND(node_struct->nodes[0], MP_TOKEN_OP_PLUS)) { goto invalid_structure; @@ -596,186 +602,97 @@ static bool parse_register_offset_node(emit_inline_asm_t *emit, qstr opcode_qstr node_struct = (mp_parse_node_struct_t *)node_struct->nodes[1]; } - if (*negative) { + if (negative) { // If the value is negative, RULE_atom_expr_normal's first token will be the // offset stripped of its negative marker; range check will then fail if the // default method is used, so a custom check is used instead. mp_obj_t object; if (!mp_parse_node_get_int_maybe(node_struct->nodes[0], &object)) { emit_inline_rv32_error_exc(emit, - mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_WRONG_ARGUMENT_KIND, opcode_qstr, 2, MP_QSTR_integer)); + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_WRONG_ARGUMENT_KIND, opcode_data->qstring, 2, MP_QSTR_integer)); return false; } mp_uint_t value = mp_obj_get_int_truncated(object); value = (~value + 1) & (mp_uint_t)-1; if (!validate_integer(value << opcode_data->argument2_shift, OPCODE_MASKS[opcode_data->argument2_mask], opcode_data->argument2_kind)) { emit_inline_rv32_error_exc(emit, - mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_OUT_OF_RANGE, opcode_qstr, 2)); + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_OUT_OF_RANGE, opcode_data->qstring, 2)); return false; } + *offset = value; } else { - if (!validate_argument(emit, opcode_qstr, opcode_data, node_struct->nodes[0], 1)) { + if (!serialise_argument(emit, opcode_data, node_struct->nodes[0], 1, offset)) { return false; } } - *offset_node = node_struct->nodes[0]; node_struct = (mp_parse_node_struct_t *)node_struct->nodes[1]; - if (!validate_argument(emit, opcode_qstr, opcode_data, node_struct->nodes[0], 2)) { + if (!serialise_argument(emit, opcode_data, node_struct->nodes[0], 2, base)) { return false; } - *register_node = node_struct->nodes[0]; return true; invalid_structure: emit_inline_rv32_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - ET_WRONG_ARGUMENT_KIND, opcode_qstr, node_index + 1, MP_QSTR_offset)); + ET_WRONG_ARGUMENT_KIND, opcode_data->qstring, node_index + 1, MP_QSTR_offset)); return false; } -static void handle_opcode(emit_inline_asm_t *emit, qstr opcode, const opcode_t *opcode_data, mp_parse_node_t *arguments) { - mp_uint_t rd = 0; - mp_uint_t rs1 = 0; - mp_uint_t rs2 = 0; - +static void handle_opcode(emit_inline_asm_t *emit, const opcode_t *opcode_data, mp_uint_t *arguments) { switch (opcode_data->calling_convention) { - case CALL_RRR: { - parse_register_node(arguments[0], &rd, opcode_data->argument1_kind & C); - parse_register_node(arguments[1], &rs1, opcode_data->argument2_kind & C); - parse_register_node(arguments[2], &rs2, opcode_data->argument3_kind & C); - ((call_rrr_t)opcode_data->emitter)(&emit->as, rd, rs1, rs2); + case CALL_RRR: + ((call_rrr_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1], arguments[2]); break; - } - case CALL_RR: { - parse_register_node(arguments[0], &rd, opcode_data->argument1_kind & C); - parse_register_node(arguments[1], &rs1, opcode_data->argument2_kind & C); - ((call_rr_t)opcode_data->emitter)(&emit->as, rd, rs1); + case CALL_RR: + ((call_rr_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1]); break; - } - case CALL_RRI: { - parse_register_node(arguments[0], &rd, opcode_data->argument1_kind & C); - parse_register_node(arguments[1], &rs1, opcode_data->argument2_kind & C); - mp_obj_t object; - mp_parse_node_get_int_maybe(arguments[2], &object); - mp_uint_t immediate = mp_obj_get_int_truncated(object) << opcode_data->argument3_shift; - ((call_rri_t)opcode_data->emitter)(&emit->as, rd, rs1, immediate); + case CALL_RRI: + ((call_rri_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1], arguments[2]); break; - } - case CALL_RI: { - parse_register_node(arguments[0], &rd, opcode_data->argument1_kind & C); - mp_obj_t object; - mp_parse_node_get_int_maybe(arguments[1], &object); - mp_uint_t immediate = mp_obj_get_int_truncated(object) << opcode_data->argument2_shift; - ((call_ri_t)opcode_data->emitter)(&emit->as, rd, immediate); + case CALL_RI: + ((call_ri_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1]); break; - } - case CALL_R: { - parse_register_node(arguments[0], &rd, opcode_data->argument1_kind & C); - ((call_r_t)opcode_data->emitter)(&emit->as, rd); + case CALL_R: + ((call_r_t)opcode_data->emitter)(&emit->as, arguments[0]); break; - } - case CALL_RRL: { - parse_register_node(arguments[0], &rd, opcode_data->argument1_kind & C); - parse_register_node(arguments[1], &rs1, opcode_data->argument2_kind & C); - qstr qstring; - mp_uint_t label_index = lookup_label(emit, arguments[2], &qstring); - ptrdiff_t displacement = label_code_offset(emit, label_index); - ((call_rri_t)opcode_data->emitter)(&emit->as, rd, rs1, displacement); + case CALL_RRL: + ((call_rri_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1], (ptrdiff_t)arguments[2]); break; - } - case CALL_RL: { - parse_register_node(arguments[0], &rd, opcode_data->argument1_kind & C); - qstr qstring; - mp_uint_t label_index = lookup_label(emit, arguments[1], &qstring); - ptrdiff_t displacement = label_code_offset(emit, label_index); - ((call_ri_t)opcode_data->emitter)(&emit->as, rd, displacement); + case CALL_RL: + ((call_ri_t)opcode_data->emitter)(&emit->as, arguments[0], (ptrdiff_t)arguments[1]); break; - } - case CALL_L: { - qstr qstring; - mp_uint_t label_index = lookup_label(emit, arguments[0], &qstring); - ptrdiff_t displacement = label_code_offset(emit, label_index); - ((call_i_t)opcode_data->emitter)(&emit->as, displacement); + case CALL_L: + ((call_i_t)opcode_data->emitter)(&emit->as, (ptrdiff_t)arguments[0]); break; - } case CALL_N: ((call_n_t)opcode_data->emitter)(&emit->as); break; - case CALL_I: { - mp_obj_t object; - mp_parse_node_get_int_maybe(arguments[0], &object); - mp_uint_t immediate = mp_obj_get_int_truncated(object) << opcode_data->argument1_shift; - ((call_i_t)opcode_data->emitter)(&emit->as, immediate); + case CALL_RII: + ((call_rii_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1], arguments[2]); break; - } - - case CALL_RII: { - parse_register_node(arguments[0], &rd, opcode_data->argument1_kind & C); - mp_obj_t object; - mp_parse_node_get_int_maybe(arguments[1], &object); - mp_uint_t immediate1 = mp_obj_get_int_truncated(object) << opcode_data->argument2_shift; - mp_parse_node_get_int_maybe(arguments[2], &object); - mp_uint_t immediate2 = mp_obj_get_int_truncated(object) << opcode_data->argument3_shift; - ((call_rii_t)opcode_data->emitter)(&emit->as, rd, immediate1, immediate2); - break; - } case CALL_RIR: - assert(!"Should not get here."); + // The last two arguments indices are swapped on purpose. + ((call_rri_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[2], arguments[1]); break; default: assert(!"Unhandled call convention."); + MP_UNREACHABLE; break; } } -static bool handle_load_store_opcode_with_offset(emit_inline_asm_t *emit, qstr opcode, const opcode_t *opcode_data, mp_parse_node_t *argument_nodes) { - mp_parse_node_t nodes[3] = {0}; - if (!validate_argument(emit, opcode, opcode_data, argument_nodes[0], 0)) { - return false; - } - nodes[0] = argument_nodes[0]; - bool negative = false; - if (!parse_register_offset_node(emit, opcode, opcode_data, argument_nodes[1], 1, &nodes[1], &nodes[2], &negative)) { - return false; - } - - mp_uint_t rd = 0; - mp_uint_t rs1 = 0; - if (!parse_register_node(nodes[0], &rd, opcode_data->argument1_kind & C)) { - return false; - } - if (!parse_register_node(nodes[1], &rs1, opcode_data->argument3_kind & C)) { - return false; - } - - mp_obj_t object; - mp_parse_node_get_int_maybe(nodes[2], &object); - mp_uint_t immediate = mp_obj_get_int_truncated(object) << opcode_data->argument2_shift; - if (negative) { - immediate = (~immediate + 1) & (mp_uint_t)-1; - } - if (!is_in_signed_mask(OPCODE_MASKS[opcode_data->argument2_mask], immediate)) { - emit_inline_rv32_error_exc(emit, - mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_OUT_OF_RANGE, opcode, 2)); - return false; - } - - ((call_rri_t)opcode_data->emitter)(&emit->as, rd, rs1, immediate); - return true; -} - static void emit_inline_rv32_opcode(emit_inline_asm_t *emit, qstr opcode, mp_uint_t arguments_count, mp_parse_node_t *argument_nodes) { const opcode_t *opcode_data = NULL; for (mp_uint_t index = 0; index < MP_ARRAY_SIZE(OPCODES); index++) { @@ -785,10 +702,9 @@ static void emit_inline_rv32_opcode(emit_inline_asm_t *emit, qstr opcode, mp_uin } } - if (!opcode_data) { - emit_inline_rv32_error_exc(emit, - mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - MP_ERROR_TEXT("unknown RV32 instruction '%q'"), opcode)); + if (!opcode_data || (asm_rv32_allowed_extensions() & opcode_data->required_extensions) != opcode_data->required_extensions) { + emit_inline_rv32_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + MP_ERROR_TEXT("invalid RV32 instruction '%q'"), opcode)); return; } @@ -796,36 +712,36 @@ static void emit_inline_rv32_opcode(emit_inline_asm_t *emit, qstr opcode, mp_uin assert((opcode_data->argument2_mask < MP_ARRAY_SIZE(OPCODE_MASKS)) && "Argument #2 opcode mask index out of bounds."); assert((opcode_data->argument3_mask < MP_ARRAY_SIZE(OPCODE_MASKS)) && "Argument #3 opcode mask index out of bounds."); assert((opcode_data->calling_convention < CALL_COUNT) && "Calling convention index out of bounds."); - if (opcode_data->calling_convention != CALL_RIR) { - if (opcode_data->arguments_count != arguments_count) { - emit_inline_rv32_error_exc(emit, - mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - ET_WRONG_ARGUMENTS_COUNT, opcode, opcode_data->arguments_count)); - return; - } - if (opcode_data->arguments_count >= 1 && !validate_argument(emit, opcode, opcode_data, argument_nodes[0], 0)) { + mp_uint_t serialised_arguments[3] = { 0 }; + if (arguments_count != opcode_data->parse_nodes) { + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + ET_WRONG_ARGUMENTS_COUNT, opcode, opcode_data->parse_nodes)); + return; + } + + if (opcode_data->parse_nodes >= 1 && !serialise_argument(emit, opcode_data, argument_nodes[0], 0, &serialised_arguments[0])) { + return; + } + if (opcode_data->calling_convention == CALL_RIR) { + // "register, offset(base)" calls require some preprocessing to + // split the offset and base nodes - not to mention that if the offset + // is negative, the parser won't see the offset as a single node but as + // a sequence of the minus sign token followed by the number itself. + + if (!serialise_register_offset_node(emit, opcode_data, argument_nodes[1], 1, &serialised_arguments[1], &serialised_arguments[2])) { return; } - if (opcode_data->arguments_count >= 2 && !validate_argument(emit, opcode, opcode_data, argument_nodes[1], 1)) { + } else { + if (opcode_data->parse_nodes >= 2 && !serialise_argument(emit, opcode_data, argument_nodes[1], 1, &serialised_arguments[1])) { return; } - if (opcode_data->arguments_count >= 3 && !validate_argument(emit, opcode, opcode_data, argument_nodes[2], 2)) { + if (opcode_data->parse_nodes >= 3 && !serialise_argument(emit, opcode_data, argument_nodes[2], 2, &serialised_arguments[2])) { return; } - handle_opcode(emit, opcode, opcode_data, argument_nodes); - return; - } - - assert((opcode_data->argument2_kind & U) == 0 && "Offset must not be unsigned."); - assert((opcode_data->argument2_kind & Z) == 0 && "Offset can be zero."); - - if (arguments_count != 2) { - emit_inline_rv32_error_exc(emit, - mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_WRONG_ARGUMENTS_COUNT, opcode, 2)); - return; } - handle_load_store_opcode_with_offset(emit, opcode, opcode_data, argument_nodes); + handle_opcode(emit, opcode_data, serialised_arguments); } #undef N diff --git a/py/emitinlinextensa.c b/py/emitinlinextensa.c index fed259cfc6b..d0eb3d566fc 100644 --- a/py/emitinlinextensa.c +++ b/py/emitinlinextensa.c @@ -173,7 +173,7 @@ static int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_ #define RRI8_B (2) typedef struct _opcode_table_3arg_t { - uint16_t name; // actually a qstr, which should fit in 16 bits + qstr_short_t name; uint8_t type; uint8_t a0 : 4; uint8_t a1 : 4; @@ -187,6 +187,13 @@ static const opcode_table_3arg_t opcode_table_3arg[] = { {MP_QSTR_add, RRR, 0, 8}, {MP_QSTR_sub, RRR, 0, 12}, {MP_QSTR_mull, RRR, 2, 8}, + {MP_QSTR_addx2, RRR, 0, 9}, + {MP_QSTR_addx4, RRR, 0, 10}, + {MP_QSTR_addx8, RRR, 0, 11}, + {MP_QSTR_subx2, RRR, 0, 13}, + {MP_QSTR_subx4, RRR, 0, 14}, + {MP_QSTR_subx8, RRR, 0, 15}, + {MP_QSTR_src, RRR, 1, 8}, // load/store/addi opcodes: reg, reg, imm // upper nibble of type encodes the range of the immediate arg @@ -208,21 +215,62 @@ static const opcode_table_3arg_t opcode_table_3arg[] = { {MP_QSTR_bge, RRI8_B, ASM_XTENSA_CC_GE, 0}, {MP_QSTR_bgeu, RRI8_B, ASM_XTENSA_CC_GEU, 0}, {MP_QSTR_blt, RRI8_B, ASM_XTENSA_CC_LT, 0}, + {MP_QSTR_bltu, RRI8_B, ASM_XTENSA_CC_LTU, 0}, {MP_QSTR_bnall, RRI8_B, ASM_XTENSA_CC_NALL, 0}, {MP_QSTR_bne, RRI8_B, ASM_XTENSA_CC_NE, 0}, {MP_QSTR_bnone, RRI8_B, ASM_XTENSA_CC_NONE, 0}, }; +// The index of the first four qstrs matches the CCZ condition value to be +// embedded into the opcode. +static const qstr_short_t BCCZ_OPCODES[] = { + MP_QSTR_beqz, MP_QSTR_bnez, MP_QSTR_bltz, MP_QSTR_bgez, + MP_QSTR_beqz_n, MP_QSTR_bnez_n +}; + +#if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES +typedef struct _single_opcode_t { + qstr_short_t name; + uint16_t value; +} single_opcode_t; + +static const single_opcode_t NOARGS_OPCODES[] = { + {MP_QSTR_dsync, 0x2030}, + {MP_QSTR_esync, 0x2020}, + {MP_QSTR_extw, 0x20D0}, + {MP_QSTR_ill, 0x0000}, + {MP_QSTR_isync, 0x2000}, + {MP_QSTR_memw, 0x20C0}, + {MP_QSTR_rsync, 0x2010}, +}; +#endif + static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) { size_t op_len; const char *op_str = (const char *)qstr_data(op, &op_len); if (n_args == 0) { - if (op == MP_QSTR_ret_n) { + if (op == MP_QSTR_ret_n || op == MP_QSTR_ret) { asm_xtensa_op_ret_n(&emit->as); - } else { - goto unknown_op; + return; + } else if (op == MP_QSTR_nop) { + asm_xtensa_op24(&emit->as, 0x20F0); + return; + } else if (op == MP_QSTR_nop_n) { + asm_xtensa_op16(&emit->as, 0xF03D); + return; } + #if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES + for (size_t index = 0; index < MP_ARRAY_SIZE(NOARGS_OPCODES); index++) { + const single_opcode_t *opcode = &NOARGS_OPCODES[index]; + if (op == opcode->name) { + asm_xtensa_op24(&emit->as, opcode->value); + return; + } + } + #endif + + goto unknown_op; } else if (n_args == 1) { if (op == MP_QSTR_callx0) { @@ -234,19 +282,45 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_ } else if (op == MP_QSTR_jx) { uint r0 = get_arg_reg(emit, op_str, pn_args[0]); asm_xtensa_op_jx(&emit->as, r0); + } else if (op == MP_QSTR_ssl) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + asm_xtensa_op_ssl(&emit->as, r0); + } else if (op == MP_QSTR_ssr) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + asm_xtensa_op_ssr(&emit->as, r0); + } else if (op == MP_QSTR_ssai) { + mp_uint_t sa = get_arg_i(emit, op_str, pn_args[0], 0, 31); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 4, sa & 0x0F, (sa >> 4) & 0x01)); + } else if (op == MP_QSTR_ssa8b) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 3, r0, 0)); + } else if (op == MP_QSTR_ssa8l) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 2, r0, 0)); + } else if (op == MP_QSTR_call0) { + mp_uint_t label = get_arg_label(emit, op_str, pn_args[0]); + asm_xtensa_call0(&emit->as, label); + #if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES + } else if (op == MP_QSTR_fsync) { + mp_uint_t imm3 = get_arg_i(emit, op_str, pn_args[0], 0, 7); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 0, 2, 8 | imm3, 0)); + } else if (op == MP_QSTR_ill_n) { + asm_xtensa_op16(&emit->as, 0xF06D); + #endif } else { goto unknown_op; } } else if (n_args == 2) { uint r0 = get_arg_reg(emit, op_str, pn_args[0]); - if (op == MP_QSTR_beqz) { - int label = get_arg_label(emit, op_str, pn_args[1]); - asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_EQ, r0, label); - } else if (op == MP_QSTR_bnez) { - int label = get_arg_label(emit, op_str, pn_args[1]); - asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_NE, r0, label); - } else if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) { + for (size_t index = 0; index < MP_ARRAY_SIZE(BCCZ_OPCODES); index++) { + if (op == BCCZ_OPCODES[index]) { + mp_uint_t label = get_arg_label(emit, op_str, pn_args[1]); + asm_xtensa_bccz_reg_label(&emit->as, index & 0x03, r0, label); + return; + } + } + if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) { // we emit mov.n for both "mov" and "mov_n" opcodes uint r1 = get_arg_reg(emit, op_str, pn_args[1]); asm_xtensa_op_mov_n(&emit->as, r0, r1); @@ -254,7 +328,53 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_ // for convenience we emit l32r if the integer doesn't fit in movi uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0); asm_xtensa_mov_reg_i32(&emit->as, r0, imm); - } else { + } else if (op == MP_QSTR_abs_) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 6, r0, 1, r1)); + } else if (op == MP_QSTR_neg) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 6, r0, 0, r1)); + } else if (op == MP_QSTR_sll) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 10, r0, r1, 0)); + } else if (op == MP_QSTR_sra) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 11, r0, 0, r1)); + } else if (op == MP_QSTR_srl) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 9, r0, 0, r1)); + } else if (op == MP_QSTR_nsa) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 14, r1, r0)); + } else if (op == MP_QSTR_nsau) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 15, r1, r0)); + } else if (op == MP_QSTR_l32r) { + mp_uint_t label = get_arg_label(emit, op_str, pn_args[1]); + asm_xtensa_l32r(&emit->as, r0, label); + } else if (op == MP_QSTR_movi_n) { + mp_int_t imm = get_arg_i(emit, op_str, pn_args[1], -32, 95); + asm_xtensa_op_movi_n(&emit->as, r0, imm); + } else + #if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES + if (op == MP_QSTR_rsr) { + mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 3, 0, sr, r0)); + } else if (op == MP_QSTR_rur) { + mp_uint_t imm8 = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 3, 14, r0, (imm8 >> 4) & 0x0F, imm8 & 0x0F)); + } else if (op == MP_QSTR_wsr) { + mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 3, 1, sr, r0)); + } else if (op == MP_QSTR_wur) { + mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 3, 15, sr, r0)); + } else if (op == MP_QSTR_xsr) { + mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 1, 6, sr, r0)); + } else + #endif + { goto unknown_op; } @@ -288,7 +408,72 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_ return; } } - goto unknown_op; + + if (op == MP_QSTR_add_n) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t r2 = get_arg_reg(emit, op_str, pn_args[2]); + asm_xtensa_op16(&emit->as, ASM_XTENSA_ENCODE_RRRN(10, r0, r1, r2)); + } else if (op == MP_QSTR_addi_n) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_int_t imm4 = get_arg_i(emit, op_str, pn_args[2], -1, 15); + asm_xtensa_op16(&emit->as, ASM_XTENSA_ENCODE_RRRN(11, r0, r1, (imm4 != 0 ? imm4 : -1))); + } else if (op == MP_QSTR_addmi) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_int_t imm8 = get_arg_i(emit, op_str, pn_args[2], -128 * 256, 127 * 256); + if ((imm8 & 0xFF) != 0) { + emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a multiple of %d"), imm8, 256)); + } else { + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRI8(2, 13, r1, r0, imm8 >> 8)); + } + } else if (op == MP_QSTR_bbci) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t bit = get_arg_i(emit, op_str, pn_args[1], 0, 31); + mp_int_t label = get_arg_label(emit, op_str, pn_args[2]); + asm_xtensa_bit_branch(&emit->as, r0, bit, label, 6); + } else if (op == MP_QSTR_bbsi) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t bit = get_arg_i(emit, op_str, pn_args[1], 0, 31); + mp_uint_t label = get_arg_label(emit, op_str, pn_args[2]); + asm_xtensa_bit_branch(&emit->as, r0, bit, label, 14); + } else if (op == MP_QSTR_slli) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t bits = 32 - get_arg_i(emit, op_str, pn_args[2], 1, 31); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 0 | ((bits >> 4) & 0x01), r0, r1, bits & 0x0F)); + } else if (op == MP_QSTR_srai) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t bits = get_arg_i(emit, op_str, pn_args[2], 0, 31); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 2 | ((bits >> 4) & 0x01), r0, bits & 0x0F, r1)); + } else if (op == MP_QSTR_srli) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t bits = get_arg_i(emit, op_str, pn_args[2], 0, 15); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 4, r0, bits, r1)); + } else if (op == MP_QSTR_l32i_n) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t imm = get_arg_i(emit, op_str, pn_args[2], 0, 60); + if ((imm & 0x03) != 0) { + emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a multiple of %d"), imm, 4)); + } else { + asm_xtensa_op_l32i_n(&emit->as, r0, r1, imm >> 2); + } + } else if (op == MP_QSTR_s32i_n) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t imm = get_arg_i(emit, op_str, pn_args[2], 0, 60); + if ((imm & 0x03) != 0) { + emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a multiple of %d"), imm, 4)); + } else { + asm_xtensa_op_s32i_n(&emit->as, r0, r1, imm >> 2); + } + } else { + goto unknown_op; + } } else { goto unknown_op; diff --git a/py/emitnative.c b/py/emitnative.c index a888418e5df..6f12200f7e1 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -222,12 +222,6 @@ static const uint8_t reg_local_table[MAX_REGS_FOR_LOCAL_VARS] = {REG_LOCAL_1, RE *emit->error_slot = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, __VA_ARGS__); \ } while (0) -#if N_RV32 -#define FIT_SIGNED(value, bits) \ - ((((value) & ~((1U << ((bits) - 1)) - 1)) == 0) || \ - (((value) & ~((1U << ((bits) - 1)) - 1)) == ~((1U << ((bits) - 1)) - 1))) -#endif - typedef enum { STACK_VALUE, STACK_REG, @@ -335,12 +329,27 @@ struct _emit_t { #define ASM_CLR_REG(state, rd) ASM_XOR_REG_REG(state, rd, rd) #endif +#if N_RV32 +#define ASM_MOV_LOCAL_MP_OBJ_NULL(as, local_num, reg_temp) \ + ASM_MOV_LOCAL_REG(as, local_num, REG_ZERO) +#else +#define ASM_MOV_LOCAL_MP_OBJ_NULL(as, local_num, reg_temp) \ + ASM_MOV_REG_IMM(as, reg_temp, (mp_uint_t)MP_OBJ_NULL); \ + ASM_MOV_LOCAL_REG(as, local_num, reg_temp) +#endif + static void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj); static void emit_native_global_exc_entry(emit_t *emit); static void emit_native_global_exc_exit(emit_t *emit); static void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj); emit_t *EXPORT_FUN(new)(mp_emit_common_t * emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels) { + // Generated code performing exception handling assumes that MP_OBJ_NULL + // equals to 0 to simplify some checks, leveraging dedicated opcodes for + // comparisons against 0. If this assumption does not hold true anymore + // then generated code won't work correctly. + MP_STATIC_ASSERT(MP_OBJ_NULL == 0); + emit_t *emit = m_new0(emit_t, 1); emit->emit_common = emit_common; emit->error_slot = error_slot; @@ -467,6 +476,30 @@ static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop emit->stack_info[i].vtype = VTYPE_UNBOUND; } + char *qualified_name = NULL; + + #if N_DEBUG + scope_t *current_scope = scope; + vstr_t *qualified_name_vstr = vstr_new(qstr_len(current_scope->simple_name)); + size_t fragment_length = 0; + const byte *fragment_pointer; + for (;;) { + fragment_pointer = qstr_data(current_scope->simple_name, &fragment_length); + vstr_hint_size(qualified_name_vstr, fragment_length); + memmove(qualified_name_vstr->buf + fragment_length, qualified_name_vstr->buf, qualified_name_vstr->len); + memcpy(qualified_name_vstr->buf, fragment_pointer, fragment_length); + qualified_name_vstr->len += fragment_length; + if (current_scope->parent == NULL || current_scope->parent->simple_name == MP_QSTR__lt_module_gt_) { + break; + } + vstr_ins_char(qualified_name_vstr, 0, '.'); + current_scope = current_scope->parent; + } + qualified_name = vstr_null_terminated_str(qualified_name_vstr); + #else + (void)qualified_name; + #endif + mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE); // generate code for entry to function @@ -513,7 +546,7 @@ static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop } // Entry to function - ASM_ENTRY(emit->as, emit->stack_start + emit->n_state - num_locals_in_regs); + ASM_ENTRY(emit->as, emit->stack_start + emit->n_state - num_locals_in_regs, qualified_name); #if N_X86 asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1); @@ -584,7 +617,7 @@ static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->start_offset); - ASM_ENTRY(emit->as, emit->code_state_start); + ASM_ENTRY(emit->as, emit->code_state_start, qualified_name); // Reset the state size for the state pointed to by REG_GENERATOR_STATE emit->code_state_start = 0; @@ -616,7 +649,7 @@ static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop emit->stack_start = emit->code_state_start + SIZEOF_CODE_STATE; // Allocate space on C-stack for code_state structure, which includes state - ASM_ENTRY(emit->as, emit->stack_start + emit->n_state); + ASM_ENTRY(emit->as, emit->stack_start + emit->n_state, qualified_name); // Prepare incoming arguments for call to mp_setup_code_state @@ -682,6 +715,10 @@ static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop } } } + + #if N_DEBUG + vstr_free(qualified_name_vstr); + #endif } static inline void emit_native_write_code_info_byte(emit_t *emit, byte val) { @@ -1311,8 +1348,7 @@ static void emit_native_global_exc_entry(emit_t *emit) { // Check LOCAL_IDX_THROW_VAL for any injected value ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_THROW_VAL(emit)); - ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL); - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2); + ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2); emit_call(emit, MP_F_NATIVE_RAISE); } } @@ -1579,87 +1615,50 @@ static void emit_native_load_subscr(emit_t *emit) { switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory - // TODO optimise to use thumb ldrb r1, [r2, r3] + #ifdef ASM_LOAD8_REG_REG_OFFSET + ASM_LOAD8_REG_REG_OFFSET(emit->as, REG_RET, reg_base, index_value); + #else if (index_value != 0) { // index is non-zero - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_ldrb_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value); - break; - } - #elif N_RV32 - if (FIT_SIGNED(index_value, 12)) { - asm_rv32_opcode_lbu(emit->as, REG_RET, reg_base, index_value); - break; - } - #elif N_XTENSA || N_XTENSAWIN - if (index_value > 0 && index_value < 256) { - asm_xtensa_op_l8ui(emit->as, REG_RET, reg_base, index_value); - break; - } - #endif need_reg_single(emit, reg_index, 0); ASM_MOV_REG_IMM(emit->as, reg_index, index_value); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base reg_base = reg_index; } ASM_LOAD8_REG_REG(emit->as, REG_RET, reg_base); // load from (base+index) + #endif break; } case VTYPE_PTR16: { // pointer to 16-bit memory + #ifdef ASM_LOAD16_REG_REG_OFFSET + ASM_LOAD16_REG_REG_OFFSET(emit->as, REG_RET, reg_base, index_value); + #else if (index_value != 0) { // index is a non-zero immediate - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_ldrh_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value); - break; - } - #elif N_RV32 - if (FIT_SIGNED(index_value, 11)) { - asm_rv32_opcode_lhu(emit->as, REG_RET, reg_base, index_value << 1); - break; - } - #elif N_XTENSA || N_XTENSAWIN - if (index_value > 0 && index_value < 256) { - asm_xtensa_op_l16ui(emit->as, REG_RET, reg_base, index_value); - break; - } - #endif need_reg_single(emit, reg_index, 0); ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base reg_base = reg_index; } ASM_LOAD16_REG_REG(emit->as, REG_RET, reg_base); // load from (base+2*index) + #endif break; } case VTYPE_PTR32: { // pointer to 32-bit memory + #ifdef ASM_LOAD32_REG_REG_OFFSET + ASM_LOAD32_REG_REG_OFFSET(emit->as, REG_RET, reg_base, index_value); + #else if (index_value != 0) { // index is a non-zero immediate - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_ldr_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value); - break; - } - #elif N_RV32 - if (FIT_SIGNED(index_value, 10)) { - asm_rv32_opcode_lw(emit->as, REG_RET, reg_base, index_value << 2); - break; - } - #elif N_XTENSA || N_XTENSAWIN - if (index_value > 0 && index_value < 256) { - asm_xtensa_l32i_optimised(emit->as, REG_RET, reg_base, index_value); - break; - } - #endif need_reg_single(emit, reg_index, 0); ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base reg_base = reg_index; } ASM_LOAD32_REG_REG(emit->as, REG_RET, reg_base); // load from (base+4*index) + #endif break; } default: @@ -1680,40 +1679,36 @@ static void emit_native_load_subscr(emit_t *emit) { switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory - // TODO optimise to use thumb ldrb r1, [r2, r3] + #ifdef ASM_LOAD8_REG_REG_REG + ASM_LOAD8_REG_REG_REG(emit->as, REG_RET, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_LOAD8_REG_REG(emit->as, REG_RET, REG_ARG_1); // store value to (base+index) + #endif break; } case VTYPE_PTR16: { // pointer to 16-bit memory - #if N_XTENSA || N_XTENSAWIN - asm_xtensa_op_addx2(emit->as, REG_ARG_1, reg_index, REG_ARG_1); - asm_xtensa_op_l16ui(emit->as, REG_RET, REG_ARG_1, 0); - break; - #endif + #ifdef ASM_LOAD16_REG_REG_REG + ASM_LOAD16_REG_REG_REG(emit->as, REG_RET, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_LOAD16_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+2*index) + #endif break; } case VTYPE_PTR32: { // pointer to word-size memory - #if N_RV32 - asm_rv32_opcode_slli(emit->as, REG_TEMP2, reg_index, 2); - asm_rv32_opcode_cadd(emit->as, REG_ARG_1, REG_TEMP2); - asm_rv32_opcode_lw(emit->as, REG_RET, REG_ARG_1, 0); - break; - #elif N_XTENSA || N_XTENSAWIN - asm_xtensa_op_addx4(emit->as, REG_ARG_1, reg_index, REG_ARG_1); - asm_xtensa_op_l32i_n(emit->as, REG_RET, REG_ARG_1, 0); - break; - #endif + #ifdef ASM_LOAD32_REG_REG_REG + ASM_LOAD32_REG_REG_REG(emit->as, REG_RET, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_LOAD32_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+4*index) + #endif break; } default: @@ -1856,92 +1851,47 @@ static void emit_native_store_subscr(emit_t *emit) { switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory - // TODO optimise to use thumb strb r1, [r2, r3] + #ifdef ASM_STORE8_REG_REG_OFFSET + ASM_STORE8_REG_REG_OFFSET(emit->as, reg_value, reg_base, index_value); + #else if (index_value != 0) { // index is non-zero - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_strb_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); - break; - } - #elif N_RV32 - if (FIT_SIGNED(index_value, 12)) { - asm_rv32_opcode_sb(emit->as, reg_value, reg_base, index_value); - break; - } - #elif N_XTENSA || N_XTENSAWIN - if (index_value > 0 && index_value < 256) { - asm_xtensa_op_s8i(emit->as, REG_RET, reg_base, index_value); - break; - } - #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value); - #if N_ARM - asm_arm_strb_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); - return; - #endif ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base reg_base = reg_index; } ASM_STORE8_REG_REG(emit->as, reg_value, reg_base); // store value to (base+index) + #endif break; } case VTYPE_PTR16: { // pointer to 16-bit memory + #ifdef ASM_STORE16_REG_REG_OFFSET + ASM_STORE16_REG_REG_OFFSET(emit->as, reg_value, reg_base, index_value); + #else if (index_value != 0) { // index is a non-zero immediate - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_strh_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); - break; - } - #elif N_RV32 - if (FIT_SIGNED(index_value, 11)) { - asm_rv32_opcode_sh(emit->as, reg_value, reg_base, index_value << 1); - break; - } - #elif N_XTENSA || N_XTENSAWIN - if (index_value > 0 && index_value < 256) { - asm_xtensa_op_s16i(emit->as, REG_RET, reg_base, index_value); - break; - } - #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base reg_base = reg_index; } ASM_STORE16_REG_REG(emit->as, reg_value, reg_base); // store value to (base+2*index) + #endif break; } case VTYPE_PTR32: { // pointer to 32-bit memory + #ifdef ASM_STORE32_REG_REG_OFFSET + ASM_STORE32_REG_REG_OFFSET(emit->as, reg_value, reg_base, index_value); + #else if (index_value != 0) { // index is a non-zero immediate - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_str_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); - break; - } - #elif N_RV32 - if (FIT_SIGNED(index_value, 10)) { - asm_rv32_opcode_sw(emit->as, reg_value, reg_base, index_value << 2); - break; - } - #elif N_XTENSA || N_XTENSAWIN - if (index_value > 0 && index_value < 256) { - asm_xtensa_s32i_optimised(emit->as, REG_RET, reg_base, index_value); - break; - } - #elif N_ARM - ASM_MOV_REG_IMM(emit->as, reg_index, index_value); - asm_arm_str_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); - return; - #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base reg_base = reg_index; } ASM_STORE32_REG_REG(emit->as, reg_value, reg_base); // store value to (base+4*index) + #endif break; } default: @@ -1972,50 +1922,36 @@ static void emit_native_store_subscr(emit_t *emit) { switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory - // TODO optimise to use thumb strb r1, [r2, r3] - #if N_ARM - asm_arm_strb_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); - break; - #endif + #ifdef ASM_STORE8_REG_REG_REG + ASM_STORE8_REG_REG_REG(emit->as, reg_value, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE8_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+index) + #endif break; } case VTYPE_PTR16: { // pointer to 16-bit memory - #if N_ARM - asm_arm_strh_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); - break; - #elif N_XTENSA || N_XTENSAWIN - asm_xtensa_op_addx2(emit->as, REG_ARG_1, reg_index, REG_ARG_1); - asm_xtensa_op_s16i(emit->as, reg_value, REG_ARG_1, 0); - break; - #endif + #ifdef ASM_STORE16_REG_REG_REG + ASM_STORE16_REG_REG_REG(emit->as, reg_value, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE16_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+2*index) + #endif break; } case VTYPE_PTR32: { // pointer to 32-bit memory - #if N_ARM - asm_arm_str_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); - break; - #elif N_RV32 - asm_rv32_opcode_slli(emit->as, REG_TEMP2, reg_index, 2); - asm_rv32_opcode_cadd(emit->as, REG_ARG_1, REG_TEMP2); - asm_rv32_opcode_sw(emit->as, reg_value, REG_ARG_1, 0); - break; - #elif N_XTENSA || N_XTENSAWIN - asm_xtensa_op_addx4(emit->as, REG_ARG_1, reg_index, REG_ARG_1); - asm_xtensa_op_s32i_n(emit->as, reg_value, REG_ARG_1, 0); - break; - #endif + #ifdef ASM_STORE32_REG_REG_REG + ASM_STORE32_REG_REG_REG(emit->as, reg_value, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE32_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+4*index) + #endif break; } default: @@ -2328,8 +2264,7 @@ static void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) { // Replace exception with MP_OBJ_NULL. emit_native_label_assign(emit, *emit->label_slot); - ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL); - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); + ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); // end of with cleanup nlr_catch block emit_native_label_assign(emit, *emit->label_slot + 1); @@ -2436,8 +2371,7 @@ static void emit_native_for_iter_end(emit_t *emit) { static void emit_native_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { if (within_exc_handler) { // Cancel any active exception so subsequent handlers don't see it - ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL); - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); + ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); } else { emit_native_leave_exc_stack(emit, false); } @@ -3122,8 +3056,7 @@ static void emit_native_yield(emit_t *emit, int kind) { if (kind == MP_EMIT_YIELD_VALUE) { // Check LOCAL_IDX_THROW_VAL for any injected value ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_THROW_VAL(emit)); - ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL); - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2); + ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2); emit_call(emit, MP_F_NATIVE_RAISE); } else { // Label loop entry diff --git a/py/emitndebug.c b/py/emitndebug.c index bd896a75c8d..e49c5cdbffa 100644 --- a/py/emitndebug.c +++ b/py/emitndebug.c @@ -108,8 +108,8 @@ static void asm_debug_end_pass(asm_debug_t *as) { (void)as; } -static void asm_debug_entry(asm_debug_t *as, int num_locals) { - asm_debug_printf(as, "ENTRY(num_locals=%d)\n", num_locals); +static void asm_debug_entry(asm_debug_t *as, int num_locals, char *name) { + asm_debug_printf(as, "ENTRY(%s, num_locals=%d)\n", name != NULL ? name : "?", num_locals); } static void asm_debug_exit(asm_debug_t *as) { @@ -195,8 +195,8 @@ static void asm_debug_setcc_reg_reg_reg(asm_debug_t *as, int op, int reg1, int r #define ASM_T asm_debug_t #define ASM_END_PASS asm_debug_end_pass -#define ASM_ENTRY(as, num_locals) \ - asm_debug_entry(as, num_locals) +#define ASM_ENTRY(as, num_locals, name) \ + asm_debug_entry(as, num_locals, name) #define ASM_EXIT(as) \ asm_debug_exit(as) @@ -251,8 +251,6 @@ static void asm_debug_setcc_reg_reg_reg(asm_debug_t *as, int op, int reg1, int r #define ASM_MUL_REG_REG(as, reg_dest, reg_src) \ asm_debug_reg_reg(as, "mul", reg_dest, reg_src) -#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) \ - asm_debug_reg_reg(as, "load", reg_dest, reg_base) #define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) \ asm_debug_reg_reg_offset(as, "load", reg_dest, reg_base, word_offset) #define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) \ @@ -264,8 +262,6 @@ static void asm_debug_setcc_reg_reg_reg(asm_debug_t *as, int op, int reg1, int r #define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) \ asm_debug_reg_reg(as, "load32", reg_dest, reg_base) -#define ASM_STORE_REG_REG(as, reg_src, reg_base) \ - asm_debug_reg_reg(as, "store", reg_src, reg_base) #define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) \ asm_debug_reg_reg_offset(as, "store", reg_src, reg_base, word_offset) #define ASM_STORE8_REG_REG(as, reg_src, reg_base) \ diff --git a/py/formatfloat.c b/py/formatfloat.c index b4348122ff4..1ea34f84bf7 100644 --- a/py/formatfloat.c +++ b/py/formatfloat.c @@ -33,394 +33,537 @@ #include #include #include "py/formatfloat.h" +#include "py/parsenum.h" /*********************************************************************** Routine for converting a arbitrary floating point number into a string. - The code in this function was inspired from Fred Bayer's pdouble.c. - Since pdouble.c was released as Public Domain, I'm releasing this - code as public domain as well. + The code in this function was inspired from Dave Hylands's previous + version, which was itself inspired from Fred Bayer's pdouble.c. The original code can be found in https://github.com/dhylands/format-float - Dave Hylands - ***********************************************************************/ -#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT -// 1 sign bit, 8 exponent bits, and 23 mantissa bits. -// exponent values 0 and 255 are reserved, exponent can be 1 to 254. -// exponent is stored with a bias of 127. -// The min and max floats are on the order of 1x10^37 and 1x10^-37 - -#define FPTYPE float -#define FPCONST(x) x##F -#define FPROUND_TO_ONE 0.9999995F -#define FPDECEXP 32 -#define FPMIN_BUF_SIZE 6 // +9e+99 +// Float formatting debug code is intended for use in ports/unix only, +// as it uses the libc float printing function as a reference. +#define DEBUG_FLOAT_FORMATTING 0 + +#if DEBUG_FLOAT_FORMATTING +#define DEBUG_PRINTF(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + +#if MICROPY_FLOAT_FORMAT_IMPL == MICROPY_FLOAT_FORMAT_IMPL_EXACT || MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#define MP_FFUINT_FMT "%lu" +#else +#define MP_FFUINT_FMT "%u" +#endif + +static inline int fp_expval(mp_float_t x) { + mp_float_union_t fb = { x }; + return (int)fb.p.exp - MP_FLOAT_EXP_OFFSET; +} -#define FLT_SIGN_MASK 0x80000000 +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE -static inline int fp_signbit(float x) { - mp_float_union_t fb = {x}; - return fb.i & FLT_SIGN_MASK; +static inline int fp_isless1(mp_float_t x) { + return x < 1.0; } -#define fp_isnan(x) isnan(x) -#define fp_isinf(x) isinf(x) -static inline int fp_iszero(float x) { - mp_float_union_t fb = {x}; - return fb.i == 0; + +static inline int fp_iszero(mp_float_t x) { + return x == 0.0; } -static inline int fp_isless1(float x) { - mp_float_union_t fb = {x}; + +#if MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_APPROX +static inline int fp_equal(mp_float_t x, mp_float_t y) { + return x == y; +} +#else +static inline mp_float_t fp_diff(mp_float_t x, mp_float_t y) { + return x - y; +} +#endif + +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT + +// The functions below are roughly equivalent to the ones above, +// but they are optimized to reduce code footprint by skipping +// handling for special values such as nan, inf, +/-0.0 +// for ports where FP support is done in software. +// +// They also take into account lost bits of REPR_C as needed. + +static inline int fp_isless1(mp_float_t x) { + mp_float_union_t fb = { x }; return fb.i < 0x3f800000; } -#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +static inline int fp_iszero(mp_float_t x) { + mp_float_union_t x_check = { x }; + return !x_check.i; // this is valid for REPR_C as well +} -// CIRCUITPY-CHANGE: prevent warnings -#pragma GCC diagnostic ignored "-Wfloat-equal" -#define FPTYPE double -#define FPCONST(x) x -#define FPROUND_TO_ONE 0.999999999995 -#define FPDECEXP 256 -#define FPMIN_BUF_SIZE 7 // +9e+199 -#define fp_signbit(x) signbit(x) -#define fp_isnan(x) isnan(x) -#define fp_isinf(x) isinf(x) -#define fp_iszero(x) (x == 0) -#define fp_isless1(x) (x < 1.0) +#if MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_APPROX +static inline int fp_equal(mp_float_t x, mp_float_t y) { + mp_float_union_t x_check = { x }; + mp_float_union_t y_check = { y }; + #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C + return (x_check.i & ~3) == (y_check.i & ~3); + #else + return x_check.i == y_check.i; + #endif +} +#else +static inline mp_float_t fp_diff(mp_float_t x, mp_float_t y) { + #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C + mp_float_union_t x_check = { x }; + mp_float_union_t y_check = { y }; + x_check.i &= ~3; + y_check.i &= ~3; + return x_check.f - y_check.f; + #else + return x - y; + #endif +} +#endif -#endif // MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT/DOUBLE +#endif -static inline int fp_expval(FPTYPE x) { - mp_float_union_t fb = {x}; - return (int)((fb.i >> MP_FLOAT_FRAC_BITS) & (~(0xFFFFFFFF << MP_FLOAT_EXP_BITS))) - MP_FLOAT_EXP_OFFSET; +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +#define FPMIN_BUF_SIZE 6 // +9e+99 +#define MAX_MANTISSA_DIGITS (9) +#define SAFE_MANTISSA_DIGITS (6) +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#define FPMIN_BUF_SIZE 7 // +9e+199 +#define MAX_MANTISSA_DIGITS (19) +#define SAFE_MANTISSA_DIGITS (16) +#endif + +// Internal formatting flags +#define FMT_MODE_E 0x01 // render using scientific notation (%e) +#define FMT_MODE_G 0x02 // render using general format (%g) +#define FMT_MODE_F 0x04 // render using using expanded fixed-point format (%f) +#define FMT_E_CASE 0x20 // don't change this value (used for case conversion!) + +static char *mp_prepend_zeros(char *s, int cnt) { + *s++ = '0'; + *s++ = '.'; + while (cnt > 0) { + *s++ = '0'; + cnt--; + } + return s; } -int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) { +// Helper to convert a decimal mantissa (provided as an mp_large_float_uint_t) to string +static int mp_format_mantissa(mp_large_float_uint_t mantissa, mp_large_float_uint_t mantissa_cap, char *buf, char *s, + int num_digits, int max_exp_zeros, int trailing_zeros, int dec, int e, int fmt_flags) { - char *s = buf; + DEBUG_PRINTF("mantissa=" MP_FFUINT_FMT " exp=%d (cap=" MP_FFUINT_FMT "):\n", mantissa, e, mantissa_cap); - if (buf_size <= FPMIN_BUF_SIZE) { - // FPMIN_BUF_SIZE is the minimum size needed to store any FP number. - // If the buffer does not have enough room for this (plus null terminator) - // then don't try to format the float. + if (mantissa) { + // If rounding/searching created an extra digit or removed too many, fix mantissa first + if (mantissa >= mantissa_cap) { + if (fmt_flags & FMT_MODE_F) { + assert(e >= 0); + num_digits++; + dec++; + } else { + mantissa /= 10; + e++; + } + } + } - if (buf_size >= 2) { - *s++ = '?'; + // When 'g' format is used, replace small exponents by explicit zeros + if ((fmt_flags & FMT_MODE_G) && e != 0) { + if (e >= 0) { + // If 0 < e < max_exp_zeros, expand positive exponent into trailing zeros + if (e < max_exp_zeros) { + dec += e; + if (dec >= num_digits) { + trailing_zeros = dec - (num_digits - 1); + } + e = 0; + } + } else { + // If -4 <= e < 0, expand negative exponent without losing significant digits + if (e >= -4) { + int cnt = 0; + while (e < 0 && !(mantissa % 10)) { + mantissa /= 10; + cnt++; + e++; + } + num_digits -= cnt; + s = mp_prepend_zeros(s, cnt - e - 1); + dec = 255; + e = 0; + } } - if (buf_size >= 1) { - *s = '\0'; + } + + // Convert the integer mantissa to string + for (int digit = num_digits - 1; digit >= 0; digit--) { + int digit_ofs = (digit > dec ? digit + 1 : digit); + s[digit_ofs] = '0' + (int)(mantissa % 10); + mantissa /= 10; + } + int dot = (dec >= 255); + if (dec + 1 < num_digits) { + dot = 1; + s++; + s[dec] = '.'; + } + s += num_digits; + #if DEBUG_FLOAT_FORMATTING + *s = 0; + DEBUG_PRINTF(" = %s exp=%d num_digits=%d zeros=%d dec=%d\n", buf, e, num_digits, trailing_zeros, dec); + #endif + + // Append or remove trailing zeros, as required by format + if (trailing_zeros) { + dec -= num_digits - 1; + while (trailing_zeros--) { + if (!dec--) { + *s++ = '.'; + dot = 1; + } + *s++ = '0'; } - return buf_size >= 2; } - if (fp_signbit(f) && !fp_isnan(f)) { - *s++ = '-'; - f = -f; - } else { - if (sign) { - *s++ = sign; + if (fmt_flags & FMT_MODE_G) { + // 'g' format requires to remove trailing zeros after decimal point + if (dot) { + while (s[-1] == '0') { + s--; + } + if (s[-1] == '.') { + s--; + } + } + } + + // Append the exponent if needed + if (((e != 0) || (fmt_flags & FMT_MODE_E)) && !(fmt_flags & FMT_MODE_F)) { + *s++ = 'E' | (fmt_flags & FMT_E_CASE); + if (e >= 0) { + *s++ = '+'; + } else { + *s++ = '-'; + e = -e; } + if (e >= 100) { + *s++ = '0' + (e / 100); + } + *s++ = '0' + ((e / 10) % 10); + *s++ = '0' + (e % 10); } + *s = '\0'; + DEBUG_PRINTF(" ===> %s\n", buf); - // buf_remaining contains bytes available for digits and exponent. - // It is buf_size minus room for the sign and null byte. - int buf_remaining = buf_size - 1 - (s - buf); + return s - buf; +} +// minimal value expected for buf_size, to avoid checking everywhere for overflow +#define MIN_BUF_SIZE (MAX_MANTISSA_DIGITS + 10) + +int mp_format_float(mp_float_t f_entry, char *buf_entry, size_t buf_size, char fmt, int prec, char sign) { + assert(buf_size >= MIN_BUF_SIZE); + + // Handle sign + mp_float_t f = f_entry; + char *buf = buf_entry; + if (signbit(f_entry) && !isnan(f_entry)) { + f = -f; + sign = '-'; + } + if (sign) { + *buf++ = sign; + buf_size--; + } + + // Handle inf/nan + char uc = fmt & 0x20; { - char uc = fmt & 0x20; - if (fp_isinf(f)) { + char *s = buf; + if (isinf(f)) { *s++ = 'I' ^ uc; *s++ = 'N' ^ uc; *s++ = 'F' ^ uc; goto ret; - } else if (fp_isnan(f)) { + } else if (isnan(f)) { *s++ = 'N' ^ uc; *s++ = 'A' ^ uc; *s++ = 'N' ^ uc; ret: *s = '\0'; - return s - buf; + return s - buf_entry; } } + // Decode format character + int fmt_flags = (unsigned char)uc; // setup FMT_E_CASE, clear all other bits + char lofmt = (char)(fmt | 0x20); // fmt in lowercase + if (lofmt == 'f') { + fmt_flags |= FMT_MODE_F; + } else if (lofmt == 'g') { + fmt_flags |= FMT_MODE_G; + } else { + fmt_flags |= FMT_MODE_E; + } + + // When precision is unspecified, default to 6 if (prec < 0) { prec = 6; } - char e_char = 'E' | (fmt & 0x20); // e_char will match case of fmt - fmt |= 0x20; // Force fmt to be lowercase - char org_fmt = fmt; - if (fmt == 'g' && prec == 0) { - prec = 1; + // Use high precision for `repr`, but switch to exponent mode + // after 16 digits in any case to match CPython behaviour + int max_exp_zeros = (prec < (int)buf_size - 3 ? prec : (int)buf_size - 3); + if (prec == MP_FLOAT_REPR_PREC) { + prec = MAX_MANTISSA_DIGITS; + max_exp_zeros = 16; } - int e; - int dec = 0; - char e_sign = '\0'; - int num_digits = 0; - int signed_e = 0; - // Approximate power of 10 exponent from binary exponent. - // abs(e_guess) is lower bound on abs(power of 10 exponent). - int e_guess = (int)(fp_expval(f) * FPCONST(0.3010299956639812)); // 1/log2(10). - if (fp_iszero(f)) { - e = 0; - if (fmt == 'f') { - // Truncate precision to prevent buffer overflow - if (prec + 2 > buf_remaining) { - prec = buf_remaining - 2; - } - num_digits = prec + 1; - } else { - // Truncate precision to prevent buffer overflow - if (prec + 6 > buf_remaining) { - prec = buf_remaining - 6; - } - if (fmt == 'e') { - e_sign = '+'; - } + // Precompute the exact decimal exponent of f, such that + // abs(e) is lower bound on abs(power of 10 exponent). + int e = 0; + if (!fp_iszero(f)) { + // Approximate power of 10 exponent from binary exponent. + e = (int)(fp_expval(f) * MICROPY_FLOAT_CONST(0.3010299956639812)); // 1/log2(10). + int positive_exp = !fp_isless1(f); + mp_float_t u_base = (mp_float_t)mp_decimal_exp((mp_large_float_t)1.0, e + positive_exp); + while ((f >= u_base) == positive_exp) { + e += (positive_exp ? 1 : -1); + u_base = (mp_float_t)mp_decimal_exp((mp_large_float_t)1.0, e + positive_exp); } - } else if (fp_isless1(f)) { - FPTYPE f_entry = f; // Save f in case we go to 'f' format. - // Build negative exponent - e = -e_guess; - FPTYPE u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e); - while (u_base > f) { - ++e; - u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e); - } - // Normalize out the inferred unit. Use divide because - // pow(10, e) * pow(10, -e) is slightly < 1 for some e in float32 - // (e.g. print("%.12f" % ((1e13) * (1e-13)))) - f /= u_base; - - // If the user specified 'g' format, and e is <= 4, then we'll switch - // to the fixed format ('f') - - if (fmt == 'f' || (fmt == 'g' && e <= 4)) { - fmt = 'f'; - dec = 0; + } - if (org_fmt == 'g') { - prec += (e - 1); - } + // For 'e' format, prec is # digits after the decimal + // For 'f' format, prec is # digits after the decimal + // For 'g' format, prec is the max number of significant digits + // + // For 'e' & 'g' format, there will be a single digit before the decimal + // For 'f' format, zeros must be expanded instead of using an exponent. + // Make sure there is enough room in the buffer for them, or switch to format 'g'. + if ((fmt_flags & FMT_MODE_F) && e > 0) { + int req_size = e + prec + 2; + if (req_size > (int)buf_size) { + fmt_flags ^= FMT_MODE_F; + fmt_flags |= FMT_MODE_G; + prec++; + } + } - // truncate precision to prevent buffer overflow - if (prec + 2 > buf_remaining) { - prec = buf_remaining - 2; + // To work independently of the format, we precompute: + // - the max number of significant digits to produce + // - the number of leading zeros to prepend (mode f only) + // - the number of trailing zeros to append + int max_digits = prec; + int lead_zeros = 0; + int trail_zeros = 0; + if (fmt_flags & FMT_MODE_F) { + if (max_digits > (int)buf_size - 3) { + // cannot satisfy requested number of decimals given buf_size, sorry + max_digits = (int)buf_size - 3; + } + if (e < 0) { + if (max_digits > 2 && e < -2) { + // Insert explicit leading zeros + lead_zeros = (-e < max_digits ? -e : max_digits) - 2; + max_digits -= lead_zeros; + } else { + max_digits++; } - - num_digits = prec; - signed_e = 0; - f = f_entry; - ++num_digits; } else { - // For e & g formats, we'll be printing the exponent, so set the - // sign. - e_sign = '-'; - dec = 0; - - if (prec > (buf_remaining - FPMIN_BUF_SIZE)) { - prec = buf_remaining - FPMIN_BUF_SIZE; - if (fmt == 'g') { - prec++; - } - } - signed_e = -e; + max_digits += e + 1; } } else { - // Build positive exponent. - // We don't modify f at this point to avoid inaccuracies from - // scaling it. Instead, we find the product of powers of 10 - // that is not greater than it, and use that to start the - // mantissa. - e = e_guess; - FPTYPE next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1); - while (f >= next_u) { - ++e; - next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1); + if (!(fmt_flags & FMT_MODE_G) || max_digits == 0) { + max_digits++; } + } + if (max_digits > MAX_MANTISSA_DIGITS) { + // use trailing zeros to avoid overflowing the mantissa + trail_zeros = max_digits - MAX_MANTISSA_DIGITS; + max_digits = MAX_MANTISSA_DIGITS; + } + int overhead = (fmt_flags & FMT_MODE_F ? 3 : FPMIN_BUF_SIZE + 1); + if (trail_zeros > (int)buf_size - max_digits - overhead) { + // cannot satisfy requested number of decimals given buf_size, sorry + trail_zeros = (int)buf_size - max_digits - overhead; + } - // If the user specified fixed format (fmt == 'f') and e makes the - // number too big to fit into the available buffer, then we'll - // switch to the 'e' format. - - if (fmt == 'f') { - if (e >= buf_remaining) { - fmt = 'e'; - } else if ((e + prec + 2) > buf_remaining) { - prec = buf_remaining - e - 2; - if (prec < 0) { - // This means no decimal point, so we can add one back - // for the decimal. - prec++; - } - } - } - if (fmt == 'e' && prec > (buf_remaining - FPMIN_BUF_SIZE)) { - prec = buf_remaining - FPMIN_BUF_SIZE; - } - if (fmt == 'g') { - // Truncate precision to prevent buffer overflow - if (prec + (FPMIN_BUF_SIZE - 1) > buf_remaining) { - prec = buf_remaining - (FPMIN_BUF_SIZE - 1); - } - } - // If the user specified 'g' format, and e is < prec, then we'll switch - // to the fixed format. + // When the caller asks for more precision than available for sure, + // Look for a shorter (rounded) representation first, and only dig + // into more digits if there is no short representation. + int num_digits = (SAFE_MANTISSA_DIGITS < max_digits ? SAFE_MANTISSA_DIGITS : max_digits); +try_again: + ; - if (fmt == 'g' && e < prec) { - fmt = 'f'; - prec -= (e + 1); - } - if (fmt == 'f') { - dec = e; - num_digits = prec + e + 1; + char *s = buf; + int extra_zeros = trail_zeros + (max_digits - num_digits); + int decexp; + int dec = 0; + + if (fp_iszero(f)) { + // no need for scaling 0.0 + decexp = 0; + } else if (fmt_flags & FMT_MODE_F) { + decexp = num_digits - 1; + if (e < 0) { + // Negative exponent: we keep a single leading zero in the mantissa, + // as using more would waste precious digits needed for accuracy. + if (lead_zeros > 0) { + // We are using leading zeros + s = mp_prepend_zeros(s, lead_zeros); + decexp += lead_zeros + 1; + dec = 255; // no decimal dot + } else { + // Small negative exponent, work directly on the mantissa + dec = 0; + } } else { - e_sign = '+'; + // Positive exponent: we will add trailing zeros separately + decexp -= e; + dec = e; } - signed_e = e; + } else { + decexp = num_digits - e - 1; } - if (prec < 0) { - // This can happen when the prec is trimmed to prevent buffer overflow - prec = 0; + DEBUG_PRINTF("input=%.19g e=%d fmt=%c max_d=%d num_d=%d decexp=%d dec=%d l0=%d r0=%d\n", + (double)f, e, lofmt, max_digits, num_digits, decexp, dec, lead_zeros, extra_zeros); + + // At this point, + // - buf points to beginning of output buffer for the unsigned representation + // - num_digits == the number of mantissa digits to add + // - (dec + 1) == the number of digits to print before adding a decimal point + // - decexp == the power of 10 exponent to apply to f to get the decimal mantissa + // - e == the power of 10 exponent to append ('e' or 'g' format) + mp_large_float_uint_t mantissa_cap = 10; + for (int n = 1; n < num_digits; n++) { + mantissa_cap *= 10; } - // At this point e contains the absolute value of the power of 10 exponent. - // (dec + 1) == the number of dgits before the decimal. - - // For e, prec is # digits after the decimal - // For f, prec is # digits after the decimal - // For g, prec is the max number of significant digits - // - // For e & g there will be a single digit before the decimal - // for f there will be e digits before the decimal - - if (fmt == 'e') { - num_digits = prec + 1; - } else if (fmt == 'g') { - if (prec == 0) { - prec = 1; + // Build the decimal mantissa into a large uint + mp_large_float_uint_t mantissa = 1; + if (sizeof(mp_large_float_t) == sizeof(mp_float_t) && num_digits > SAFE_MANTISSA_DIGITS && decexp > 1) { + // if we don't have large floats, use integer multiply to produce the last digits + if (num_digits > SAFE_MANTISSA_DIGITS + 1 && decexp > 2) { + mantissa = 100; + decexp -= 2; + } else { + mantissa = 10; + decexp -= 1; } - num_digits = prec; } - - int d = 0; - for (int digit_index = signed_e; num_digits >= 0; --digit_index) { - FPTYPE u_base = FPCONST(1.0); - if (digit_index > 0) { - // Generate 10^digit_index for positive digit_index. - u_base = MICROPY_FLOAT_C_FUN(pow)(10, digit_index); - } - for (d = 0; d < 9; ++d) { - if (f < u_base) { - break; - } - f -= u_base; - } - // We calculate one more digit than we display, to use in rounding - // below. So only emit the digit if it's one that we display. - if (num_digits > 0) { - // Emit this number (the leading digit). - *s++ = '0' + d; - if (dec == 0 && prec > 0) { - *s++ = '.'; - } - } - --dec; - --num_digits; - if (digit_index <= 0) { - // Once we get below 1.0, we scale up f instead of calculating - // negative powers of 10 in u_base. This provides better - // renditions of exact decimals like 1/16 etc. - f *= FPCONST(10.0); + mp_large_float_t mantissa_f = mp_decimal_exp((mp_large_float_t)f, decexp); + mantissa *= (mp_large_float_uint_t)(mantissa_f + (mp_large_float_t)0.5); + DEBUG_PRINTF("input=%.19g fmt=%c num_digits=%d dec=%d mantissa=" MP_FFUINT_FMT " r0=%d\n", (double)f, lofmt, num_digits, dec, mantissa, extra_zeros); + + // Finally convert the decimal mantissa to a floating-point string, according to formatting rules + int reprlen = mp_format_mantissa(mantissa, mantissa_cap, buf, s, num_digits, max_exp_zeros, extra_zeros, dec, e, fmt_flags); + assert(reprlen + 1 <= (int)buf_size); + + #if MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_APPROX + + if (num_digits < max_digits) { + // The initial precision might not be sufficient for an exact representation + // for all numbers. If the result is not exact, restart using next precision. + // parse the resulting number and compare against the original + mp_float_t check; + DEBUG_PRINTF("input=%.19g, compare to float('%s')\n", (double)f, buf); + mp_parse_float_internal(buf, reprlen, &check); + if (!fp_equal(check, f)) { + num_digits++; + DEBUG_PRINTF("Not perfect, retry using more digits (%d)\n", num_digits); + goto try_again; } } - // Rounding. If the next digit to print is >= 5, round up. - if (d >= 5) { - char *rs = s; - rs--; - while (1) { - if (*rs == '.') { - rs--; - continue; - } - if (*rs < '0' || *rs > '9') { - // + or - - rs++; // So we sit on the digit to the right of the sign - break; + + #else + + // The initial decimal mantissa might not have been be completely accurate due + // to the previous loating point operations. The best way to verify this is to + // parse the resulting number and compare against the original + mp_float_t check; + DEBUG_PRINTF("input=%.19g, compare to float('%s')\n", (double)f, buf); + mp_parse_float_internal(buf, reprlen, &check); + mp_float_t diff = fp_diff(check, f); + mp_float_t best_diff = diff; + mp_large_float_uint_t best_mantissa = mantissa; + + if (fp_iszero(diff)) { + // we have a perfect match + DEBUG_PRINTF(MP_FFUINT_FMT ": perfect match (direct)\n", mantissa); + } else { + // In order to get the best possible representation, we will perform a + // dichotomic search for a reversible representation. + // This will also provide optimal rounding on the fly. + unsigned err_range = 1; + if (num_digits > SAFE_MANTISSA_DIGITS) { + err_range <<= 3 * (num_digits - SAFE_MANTISSA_DIGITS); + } + int maxruns = 3 + 3 * (MAX_MANTISSA_DIGITS - SAFE_MANTISSA_DIGITS); + while (maxruns-- > 0) { + // update mantissa according to dichotomic search + if (signbit(diff)) { + mantissa += err_range; + } else { + // mantissa is expected to always have more significant digits than err_range + assert(mantissa >= err_range); + mantissa -= err_range; } - if (*rs < '9') { - (*rs)++; + // retry conversion + reprlen = mp_format_mantissa(mantissa, mantissa_cap, buf, s, num_digits, max_exp_zeros, extra_zeros, dec, e, fmt_flags); + assert(reprlen + 1 <= (int)buf_size); + DEBUG_PRINTF("input=%.19g, compare to float('%s')\n", (double)f, buf); + mp_parse_float_internal(buf, reprlen, &check); + DEBUG_PRINTF("check=%.19g num_digits=%d e=%d mantissa=" MP_FFUINT_FMT "\n", (double)check, num_digits, e, mantissa); + diff = fp_diff(check, f); + if (fp_iszero(diff)) { + // we have a perfect match + DEBUG_PRINTF(MP_FFUINT_FMT ": perfect match\n", mantissa); break; } - *rs = '0'; - if (rs == buf) { - break; + // keep track of our best estimate + mp_float_t delta = MICROPY_FLOAT_C_FUN(fabs)(diff) - MICROPY_FLOAT_C_FUN(fabs)(best_diff); + if (signbit(delta) || (fp_iszero(delta) && !(mantissa % 10u))) { + best_diff = diff; + best_mantissa = mantissa; } - rs--; - } - if (*rs == '0') { - // We need to insert a 1 - if (rs[1] == '.' && fmt != 'f') { - // We're going to round 9.99 to 10.00 - // Move the decimal point - rs[0] = '.'; - rs[1] = '0'; - if (e_sign == '-') { - e--; - if (e == 0) { - e_sign = '+'; - } - } else { - e++; - } + // string repr is not perfect: continue a dichotomic improvement + DEBUG_PRINTF(MP_FFUINT_FMT ": %.19g, err_range=%d\n", mantissa, (double)check, err_range); + if (err_range > 1) { + err_range >>= 1; } else { - // Need at extra digit at the end to make room for the leading '1' - // but if we're at the buffer size limit, just drop the final digit. - if ((size_t)(s + 1 - buf) < buf_size) { - s++; + // We have tried all possible mantissa, without finding a reversible repr. + // Check if we have an alternate precision to try. + if (num_digits < max_digits) { + num_digits++; + DEBUG_PRINTF("Failed to find a perfect match, try with more digits (%d)\n", num_digits); + goto try_again; } + // Otherwise, keep the closest one, which is either the first one or the last one. + if (mantissa == best_mantissa) { + // Last guess is the best one + DEBUG_PRINTF(MP_FFUINT_FMT ": last guess was the best one\n", mantissa); + } else { + // We had a better guess earlier + DEBUG_PRINTF(MP_FFUINT_FMT ": use best guess\n", mantissa); + reprlen = mp_format_mantissa(best_mantissa, mantissa_cap, buf, s, num_digits, max_exp_zeros, extra_zeros, dec, e, fmt_flags); + } + break; } - char *ss = s; - while (ss > rs) { - *ss = ss[-1]; - ss--; - } - *rs = '1'; } } + #endif - // verify that we did not overrun the input buffer so far - assert((size_t)(s + 1 - buf) <= buf_size); - - if (org_fmt == 'g' && prec > 0) { - // Remove trailing zeros and a trailing decimal point - while (s[-1] == '0') { - s--; - } - if (s[-1] == '.') { - s--; - } - } - // Append the exponent - if (e_sign) { - *s++ = e_char; - *s++ = e_sign; - if (FPMIN_BUF_SIZE == 7 && e >= 100) { - *s++ = '0' + (e / 100); - } - *s++ = '0' + ((e / 10) % 10); - *s++ = '0' + (e % 10); - } - *s = '\0'; - - // verify that we did not overrun the input buffer - assert((size_t)(s + 1 - buf) <= buf_size); - - return s - buf; + return buf + reprlen - buf_entry; } #endif // MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE diff --git a/py/formatfloat.h b/py/formatfloat.h index 9a1643b4ddf..7b1414672b7 100644 --- a/py/formatfloat.h +++ b/py/formatfloat.h @@ -29,6 +29,7 @@ #include "py/mpconfig.h" #if MICROPY_PY_BUILTINS_FLOAT +#define MP_FLOAT_REPR_PREC (99) // magic `prec` value for optimal `repr` behaviour int mp_format_float(mp_float_t f, char *buf, size_t bufSize, char fmt, int prec, char sign); #endif diff --git a/py/gc.c b/py/gc.c index c6da81d495c..757c27e3de6 100644 --- a/py/gc.c +++ b/py/gc.c @@ -32,6 +32,12 @@ #include "py/gc.h" #include "py/runtime.h" +#if defined(__ZEPHYR__) +#include +#include +#include +#endif + #if MICROPY_DEBUG_VALGRIND #include #endif @@ -45,6 +51,12 @@ #include "shared-module/memorymonitor/__init__.h" #endif +#if defined(__ZEPHYR__) && defined(CONFIG_TRACING_PERFETTO) && defined(CONFIG_BOARD_NATIVE_SIM) +#include "perfetto_encoder.h" +#define CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID 0x3001ULL +#define CIRCUITPY_PERFETTO_VM_HEAP_MAX_FREE_UUID 0x3002ULL +#endif + #if MICROPY_ENABLE_GC #if MICROPY_DEBUG_VERBOSE // print debugging info @@ -158,6 +170,32 @@ void __attribute__ ((noinline)) gc_log_change(uint32_t start_block, uint32_t len #pragma GCC pop_options #endif +#if defined(__ZEPHYR__) && defined(CONFIG_TRACING_PERFETTO) && defined(CONFIG_BOARD_NATIVE_SIM) +static void gc_perfetto_emit_heap_stats(void) { + if (!perfetto_start()) { + return; + } + gc_info_t info; + gc_info(&info); + perfetto_emit_counter(CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID, (int64_t)info.used); + Z_SPIN_DELAY(1); +} + +static void gc_perfetto_emit_heap_stopped(void) { + if (!perfetto_start()) { + return; + } + perfetto_emit_counter(CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID, 0); + Z_SPIN_DELAY(1); +} +#else +static inline void gc_perfetto_emit_heap_stats(void) { +} + +static inline void gc_perfetto_emit_heap_stopped(void) { +} +#endif + // Static functions for individual steps of the GC mark/sweep sequence static void gc_collect_start_common(void); static void *gc_get_ptr(void **ptrs, int i); @@ -284,6 +322,7 @@ void gc_init(void *start, void *end) { #endif GC_MUTEX_INIT(); + gc_perfetto_emit_heap_stats(); } #if MICROPY_GC_SPLIT_HEAP @@ -425,6 +464,7 @@ void gc_deinit(void) { // Run any finalisers before we stop using the heap. This will also free // any additional heap areas (but not the first.) gc_sweep_all(); + gc_perfetto_emit_heap_stopped(); memset(&MP_STATE_MEM(area), 0, sizeof(MP_STATE_MEM(area))); } @@ -654,6 +694,7 @@ void gc_collect_end(void) { } MP_STATE_THREAD(gc_lock_depth) &= ~GC_COLLECT_FLAG; GC_EXIT(); + gc_perfetto_emit_heap_stats(); } static void gc_deal_with_stack_overflow(void) { @@ -1069,6 +1110,8 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { memorymonitor_track_allocation(end_block - start_block + 1); #endif + gc_perfetto_emit_heap_stats(); + return ret_ptr; } @@ -1150,6 +1193,7 @@ void gc_free(void *ptr) { } while (ATB_GET_KIND(area, block) == AT_TAIL); GC_EXIT(); + gc_perfetto_emit_heap_stats(); #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(&mp_plat_print); @@ -1290,6 +1334,8 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { memorymonitor_track_allocation(new_blocks); #endif + gc_perfetto_emit_heap_stats(); + return ptr_in; } @@ -1327,6 +1373,8 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { memorymonitor_track_allocation(new_blocks); #endif + gc_perfetto_emit_heap_stats(); + return ptr_in; } @@ -1399,7 +1447,7 @@ void gc_dump_alloc_table(const mp_print_t *print) { } if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) { // there are at least 2 lines containing only free blocks, so abbreviate their printing - mp_printf(print, "\n (%u lines all free)", (uint)(bl2 - bl) / DUMP_BYTES_PER_LINE); + mp_printf(print, "\n (%u lines all free)", (uint)((bl2 - bl) / DUMP_BYTES_PER_LINE)); bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1)); if (bl >= area->gc_alloc_table_byte_len * BLOCKS_PER_ATB) { // got to end of heap @@ -1442,7 +1490,7 @@ void gc_dump_alloc_table(const mp_print_t *print) { break; } */ - /* this prints the uPy object type of the head block */ + /* this prints the MicroPython object type of the head block */ case AT_HEAD: { // CIRCUITPY-CHANGE: compiler warning avoidance #pragma GCC diagnostic push diff --git a/py/gc.h b/py/gc.h index 0752478d1f2..f9028d637c5 100644 --- a/py/gc.h +++ b/py/gc.h @@ -71,6 +71,11 @@ bool gc_alloc_possible(void); // Use this function to sweep the whole heap and run all finalisers void gc_sweep_all(void); +// These functions are used to manage weakrefs. +void gc_weakref_mark(void *ptr); +void gc_weakref_about_to_be_freed(void *ptr); +void gc_weakref_sweep(void); + enum { GC_ALLOC_FLAG_HAS_FINALISER = 1, // CIRCUITPY-CHANGE diff --git a/py/make_root_pointers.py b/py/make_root_pointers.py index efe398b8227..5da343c1270 100644 --- a/py/make_root_pointers.py +++ b/py/make_root_pointers.py @@ -6,8 +6,6 @@ "struct _mp_state_vm_t" in py/mpstate.h """ -from __future__ import print_function - import argparse import io import re diff --git a/py/makecompresseddata.py b/py/makecompresseddata.py index 1bce3e8e837..a6fa7db00b2 100644 --- a/py/makecompresseddata.py +++ b/py/makecompresseddata.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import collections import re import sys diff --git a/py/makemoduledefs.py b/py/makemoduledefs.py index 29162ab387c..c8fdc21f6fb 100644 --- a/py/makemoduledefs.py +++ b/py/makemoduledefs.py @@ -14,8 +14,6 @@ the built-in version. """ -from __future__ import print_function - import sys import re import io @@ -87,19 +85,25 @@ def generate_module_table_header(modules): ) ) + # There should always be at least one module (__main__ in runtime.c) + assert mod_defs + print("\n#define MICROPY_REGISTERED_MODULES \\") for mod_def in sorted(mod_defs): print(" {mod_def} \\".format(mod_def=mod_def)) - print("// MICROPY_REGISTERED_MODULES") - print("\n#define MICROPY_REGISTERED_EXTENSIBLE_MODULES \\") + # There are not necessarily any extensible modules (e.g., bare-arm or minimal x86) + print("\n#define MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES ", len(extensible_mod_defs)) - for mod_def in sorted(extensible_mod_defs): - print(" {mod_def} \\".format(mod_def=mod_def)) + if extensible_mod_defs: + print("\n#define MICROPY_REGISTERED_EXTENSIBLE_MODULES \\") + + for mod_def in sorted(extensible_mod_defs): + print(" {mod_def} \\".format(mod_def=mod_def)) - print("// MICROPY_REGISTERED_EXTENSIBLE_MODULES") + print("// MICROPY_REGISTERED_EXTENSIBLE_MODULES") def generate_module_delegations(delegations): diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 998328bf1d2..3fdb2d5476b 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -1,31 +1,13 @@ """ Process raw qstr file and output qstr data with length, hash and data bytes. -This script works with Python 2.7, 3.3 and 3.4. - -CIRCUITPY-CHANGE: -For documentation about the format of compressed translated strings, see -supervisor/shared/translate/translate.h +This script works with Python 3.3+. """ -from __future__ import print_function - - import re import sys -# CIRCUITPY-CHANGE -if hasattr(sys.stdout, "reconfigure"): - sys.stdout.reconfigure(encoding="utf-8") - sys.stderr.reconfigure(errors="backslashreplace") - -# Python 2/3 compatibility: -# - iterating through bytes is different -# - codepoint2name from html.entities is hard-coded -if sys.version_info[0] == 2: - bytes_cons = lambda val, enc=None: bytearray(val) -elif sys.version_info[0] == 3: # Also handles MicroPython - bytes_cons = bytes +bytes_cons = bytes # fmt: off codepoint2name = { @@ -67,7 +49,6 @@ 253: "yacute", 165: "yen", 255: "yuml", 950: "zeta", 8205: "zwj", 8204: "zwnj" } # fmt: on -# end compatibility code codepoint2name[ord("-")] = "hyphen" diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index a4039857694..8c07899baf8 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -2,11 +2,9 @@ This script processes the output from the C preprocessor and extracts all qstr. Each qstr is transformed into a qstr definition of the form 'Q(...)'. -This script works with Python 3.x (CIRCUITPY-CHANGE: not 2.x) +This script works with Python 3.3+. """ -from __future__ import print_function - import io import os import re @@ -139,6 +137,7 @@ def qstr_unescape(qstr): return qstr +# CIRCUITPY-CHANGE: output_filename as an arg def process_file(f, output_filename=None): # match gcc-like output (# n "file") and msvc-like output (#line n "file") re_line = re.compile(r"^#(?:line)?\s+\d+\s\"([^\"]+)\"") @@ -292,6 +291,7 @@ class Args: args.input_filename = sys.argv[3] # Unused for command=cat args.output_dir = sys.argv[4] args.output_file = None if len(sys.argv) == 5 else sys.argv[5] # Unused for command=split + # CIRCUITPY-CHANGE if args.output_file == "_": args.output_file = None @@ -306,6 +306,7 @@ class Args: if args.command == "split": with io.open(args.input_filename, encoding="utf-8") as infile: + # CIRCUITPY-CHANGE: pass output_file process_file(infile, args.output_file) if args.command == "cat": diff --git a/py/maketranslationdata.py b/py/maketranslationdata.py index 3933387b645..c3c3442e311 100644 --- a/py/maketranslationdata.py +++ b/py/maketranslationdata.py @@ -527,11 +527,23 @@ def esc_char(m): def parse_qstrs(infile): r = {} - rx = re.compile(r'QDEF[01]\([A-Za-z0-9_]+,\s*\d+,\s*\d+,\s*(?P"(?:[^"\\\\]*|\\.)")\)') + rx = re.compile( + r'QDEF(?P[01])\([A-Za-z0-9_]+,\s*\d+,\s*\d+,\s*(?P"(?:[^"\\\\]|\\.)*")\)' + ) content = infile.read() - for i, mat in enumerate(rx.findall(content, re.M)): - mat = eval(mat) - r[mat] = i + matches = rx.finditer(content) + qdef0_qstrs = [] + qdef1_qstrs = [] + for match in matches: + qstr = eval(match.group("cstr")) + if match.group("pool") == "0": + qdef0_qstrs.append(qstr) + else: + qdef1_qstrs.append(qstr) + for i, qstr in enumerate(qdef0_qstrs): + r[qstr] = i + for i, qstr in enumerate(qdef1_qstrs, start=len(qdef0_qstrs)): + r[qstr] = i return r diff --git a/py/makeversionhdr.py b/py/makeversionhdr.py index 307bfac1e9a..94321ef0bad 100644 --- a/py/makeversionhdr.py +++ b/py/makeversionhdr.py @@ -5,8 +5,6 @@ This script works with Python 3.7 and newer """ -from __future__ import print_function - import argparse import sys import os diff --git a/py/malloc.c b/py/malloc.c index fcf930ecfaa..fc9795043a8 100644 --- a/py/malloc.c +++ b/py/malloc.c @@ -54,9 +54,11 @@ // freely accessed - for interfacing with system and 3rd-party libs for // example. On the other hand, some (e.g. bare-metal) ports may use GC // heap as system heap, so, to avoid warnings, we do undef's first. -// CIRCUITPY-CHANGE: Add selective collect support to malloc to optimize GC for large buffers +#undef malloc #undef free #undef realloc +#define malloc(b) gc_alloc((b), false) +#define malloc_with_finaliser(b) gc_alloc((b), true) #define free gc_free #define realloc(ptr, n) gc_realloc(ptr, n, true) #define realloc_ext(ptr, n, mv) gc_realloc(ptr, n, mv) @@ -68,6 +70,7 @@ #error MICROPY_ENABLE_FINALISER requires MICROPY_ENABLE_GC #endif +// CIRCUITPY-CHANGE: Add selective collect support to malloc to optimize GC for large buffers #if MICROPY_ENABLE_SELECTIVE_COLLECT #error MICROPY_ENABLE_SELECTIVE_COLLECT requires MICROPY_ENABLE_GC #endif @@ -85,7 +88,7 @@ static void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) { #endif // MICROPY_ENABLE_GC -// CIRCUITPY-CHANGE: Add malloc helper with flags instead of a list of bools. +// CIRCUITPY-CHANGE: Add malloc helper to factor out flag handling and allow combinations. void *m_malloc_helper(size_t num_bytes, uint8_t flags) { void *ptr; #if MICROPY_ENABLE_GC @@ -112,7 +115,6 @@ void *m_malloc_helper(size_t num_bytes, uint8_t flags) { MP_STATE_MEM(current_bytes_allocated) += num_bytes; UPDATE_PEAK(); #endif - // CIRCUITPY-CHANGE // If this config is set then the GC clears all memory, so we don't need to. #if !MICROPY_GC_CONSERVATIVE_CLEAR if (flags & M_MALLOC_ENSURE_ZEROED) { @@ -124,26 +126,37 @@ void *m_malloc_helper(size_t num_bytes, uint8_t flags) { } void *m_malloc(size_t num_bytes) { - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: use helper return m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT); } void *m_malloc_maybe(size_t num_bytes) { - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: use helper return m_malloc_helper(num_bytes, M_MALLOC_COLLECT); } +#if MICROPY_ENABLE_FINALISER +void *m_malloc_with_finaliser(size_t num_bytes) { + // CIRCUITPY-CHANGE: use helper + return m_malloc_helper(num_bytes, M_MALLOC_COLLECT | M_MALLOC_WITH_FINALISER); +} +#endif + void *m_malloc0(size_t num_bytes) { - return m_malloc_helper(num_bytes, M_MALLOC_ENSURE_ZEROED | M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT); + // CIRCUITPY-CHANGE: use helper + return m_malloc_helper(num_bytes, + (MICROPY_GC_CONSERVATIVE_CLEAR ? 0 : M_MALLOC_ENSURE_ZEROED) + | M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT); } +// CIRCUITPY-CHANGE: add selective collect void *m_malloc_without_collect(size_t num_bytes) { - // CIRCUITPY-CHANGE return m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR); } +// CIRCUITPY-CHANGE: add selective collect void *m_malloc_maybe_without_collect(size_t num_bytes) { - // CIRCUITPY-CHANGE + return m_malloc_helper(num_bytes, 0); } @@ -224,6 +237,31 @@ void m_free(void *ptr) #if MICROPY_TRACKED_ALLOC +#if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL +// If there's no GIL, use the GC recursive mutex to protect the tracked node linked list +// under m_tracked_head. +// +// (For ports with GIL, the expectation is to only call tracked alloc functions +// while holding the GIL.) + +static inline void m_tracked_node_lock(void) { + mp_thread_recursive_mutex_lock(&MP_STATE_MEM(gc_mutex), 1); +} + +static inline void m_tracked_node_unlock(void) { + mp_thread_recursive_mutex_unlock(&MP_STATE_MEM(gc_mutex)); +} + +#else + +static inline void m_tracked_node_lock(void) { +} + +static inline void m_tracked_node_unlock(void) { +} + +#endif + #define MICROPY_TRACKED_ALLOC_STORE_SIZE (!MICROPY_ENABLE_GC) typedef struct _m_tracked_node_t { @@ -237,6 +275,7 @@ typedef struct _m_tracked_node_t { #if MICROPY_DEBUG_VERBOSE static size_t m_tracked_count_links(size_t *nb) { + m_tracked_node_lock(); m_tracked_node_t *node = MP_STATE_VM(m_tracked_head); size_t n = 0; *nb = 0; @@ -249,6 +288,7 @@ static size_t m_tracked_count_links(size_t *nb) { #endif node = node->next; } + m_tracked_node_unlock(); return n; } #endif @@ -263,12 +303,14 @@ void *m_tracked_calloc(size_t nmemb, size_t size) { size_t n = m_tracked_count_links(&nb); DEBUG_printf("m_tracked_calloc(%u, %u) -> (%u;%u) %p\n", (int)nmemb, (int)size, (int)n, (int)nb, node); #endif + m_tracked_node_lock(); if (MP_STATE_VM(m_tracked_head) != NULL) { MP_STATE_VM(m_tracked_head)->prev = node; } node->prev = NULL; node->next = MP_STATE_VM(m_tracked_head); MP_STATE_VM(m_tracked_head) = node; + m_tracked_node_unlock(); #if MICROPY_TRACKED_ALLOC_STORE_SIZE node->size = nmemb * size; #endif @@ -294,7 +336,8 @@ void m_tracked_free(void *ptr_in) { size_t nb; size_t n = m_tracked_count_links(&nb); DEBUG_printf("m_tracked_free(%p, [%p, %p], nbytes=%u, links=%u;%u)\n", node, node->prev, node->next, (int)data_bytes, (int)n, (int)nb); - #endif + #endif // MICROPY_DEBUG_VERBOSE + m_tracked_node_lock(); if (node->next != NULL) { node->next->prev = node->prev; } @@ -303,6 +346,7 @@ void m_tracked_free(void *ptr_in) { } else { MP_STATE_VM(m_tracked_head) = node->next; } + m_tracked_node_unlock(); m_free(node #if MICROPY_MALLOC_USES_ALLOCATED_SIZE #if MICROPY_TRACKED_ALLOC_STORE_SIZE diff --git a/py/misc.h b/py/misc.h index 22f32147124..d5d7950574f 100644 --- a/py/misc.h +++ b/py/misc.h @@ -26,6 +26,8 @@ #ifndef MICROPY_INCLUDED_PY_MISC_H #define MICROPY_INCLUDED_PY_MISC_H +#include "py/mpconfig.h" + // a mini library of useful types and functions /** types *******************************************************/ @@ -33,13 +35,25 @@ #include #include #include - -// CIRCUITPY-CHANGE: include directly instead of depending on previous includes -#include "mpconfig.h" +// CIRCUITPY-CHANGE: #ifdef instead of #if +#ifdef __cplusplus // Required on at least one compiler to get ULLONG_MAX +#include +#else +#include +#endif typedef unsigned char byte; typedef unsigned int uint; +#ifndef __has_builtin +#define __has_builtin(x) (0) +#endif +#ifndef __has_feature +// This macro is supported by Clang and gcc>=14 +#define __has_feature(x) (0) +#endif + + /** generic ops *************************************************/ #ifndef MIN @@ -54,6 +68,7 @@ typedef unsigned int uint; #define MP_STRINGIFY(x) MP_STRINGIFY_HELPER(x) // Static assertion macro +// CIRCUITPY-CHANGE: defined() #if defined(__cplusplus) #define MP_STATIC_ASSERT(cond) static_assert((cond), #cond) #elif __GNUC__ >= 5 || __STDC_VERSION__ >= 201112L @@ -70,6 +85,7 @@ typedef unsigned int uint; #if defined(_MSC_VER) || defined(__cplusplus) #define MP_STATIC_ASSERT_NONCONSTEXPR(cond) ((void)1) #else +// CIRCUITPY-CHANGE: defined() #if defined(__clang__) #pragma GCC diagnostic ignored "-Wgnu-folding-constant" #endif @@ -98,9 +114,9 @@ typedef unsigned int uint; #define m_new0(type, num) ((type *)(m_malloc0(sizeof(type) * (num)))) #define m_new_obj(type) (m_new(type, 1)) #define m_new_obj_maybe(type) (m_new_maybe(type, 1)) -#define m_new_obj_var(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_helper(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num), M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT)) -#define m_new_obj_var0(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_helper(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num), M_MALLOC_ENSURE_ZEROED | M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT)) -#define m_new_obj_var_maybe(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_helper(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num), M_MALLOC_COLLECT)) +#define m_new_obj_var(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) +#define m_new_obj_var0(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc0(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) +#define m_new_obj_var_maybe(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_maybe(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) #if MICROPY_MALLOC_USES_ALLOCATED_SIZE #define m_renew(type, ptr, old_num, new_num) ((type *)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num)))) #define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type *)(m_realloc_maybe((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num), (allow_move)))) @@ -126,9 +142,13 @@ typedef unsigned int uint; void *m_malloc_helper(size_t num_bytes, uint8_t flags); void *m_malloc(size_t num_bytes); void *m_malloc_maybe(size_t num_bytes); +void *m_malloc_with_finaliser(size_t num_bytes); void *m_malloc0(size_t num_bytes); + +// CIRCUITPY-CHANGE: _without_collect void *m_malloc_without_collect(size_t num_bytes); void *m_malloc_maybe_without_collect(size_t num_bytes); + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes); void *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes, bool allow_move); @@ -138,7 +158,7 @@ void *m_realloc(void *ptr, size_t new_num_bytes); void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move); void m_free(void *ptr); #endif -NORETURN void m_malloc_fail(size_t num_bytes); +MP_NORETURN void m_malloc_fail(size_t num_bytes); #if MICROPY_TRACKED_ALLOC // These alloc/free functions track the pointers in a linked list so the GC does not reclaim @@ -161,7 +181,7 @@ size_t m_get_peak_bytes_allocated(void); // align ptr to the nearest multiple of "alignment" #define MP_ALIGN(ptr, alignment) (void *)(((uintptr_t)(ptr) + ((alignment) - 1)) & ~((alignment) - 1)) -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: addition #define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) /** unichar / UTF-8 *********************************************/ @@ -308,6 +328,25 @@ typedef union _mp_float_union_t { mp_float_uint_t i; } mp_float_union_t; +#if MICROPY_FLOAT_FORMAT_IMPL == MICROPY_FLOAT_FORMAT_IMPL_EXACT + +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +// Exact float conversion requires using internally a bigger sort of floating point +typedef double mp_large_float_t; +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +typedef long double mp_large_float_t; +#endif +// Always use a 64 bit mantissa for formatting and parsing +typedef uint64_t mp_large_float_uint_t; + +#else // MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_EXACT + +// No bigger floating points +typedef mp_float_t mp_large_float_t; +typedef mp_float_uint_t mp_large_float_uint_t; + +#endif + #endif // MICROPY_PY_BUILTINS_FLOAT /** ROM string compression *************/ @@ -413,26 +452,28 @@ static inline bool mp_check(bool value) { static inline uint32_t mp_popcount(uint32_t x) { return __popcnt(x); } -#else +#else // _MSC_VER #define mp_clz(x) __builtin_clz(x) #define mp_clzl(x) __builtin_clzl(x) #define mp_clzll(x) __builtin_clzll(x) #define mp_ctz(x) __builtin_ctz(x) #define mp_check(x) (x) -#if defined __has_builtin #if __has_builtin(__builtin_popcount) #define mp_popcount(x) __builtin_popcount(x) -#endif -#endif -#if !defined(mp_popcount) +#else static inline uint32_t mp_popcount(uint32_t x) { x = x - ((x >> 1) & 0x55555555); x = (x & 0x33333333) + ((x >> 2) & 0x33333333); x = (x + (x >> 4)) & 0x0F0F0F0F; - return x * 0x01010101; + return (x * 0x01010101) >> 24; } -#endif -#endif +#endif // __has_builtin(__builtin_popcount) +#endif // _MSC_VER + +#define MP_FIT_UNSIGNED(bits, value) (((value) & (~0U << (bits))) == 0) +#define MP_FIT_SIGNED(bits, value) \ + (MP_FIT_UNSIGNED(((bits) - 1), (value)) || \ + (((value) & (~0U << ((bits) - 1))) == (~0U << ((bits) - 1)))) // mp_int_t can be larger than long, i.e. Windows 64-bit, nan-box variants static inline uint32_t mp_clz_mpi(mp_int_t x) { @@ -448,16 +489,107 @@ static inline uint32_t mp_clz_mpi(mp_int_t x) { } return zeroes; #else - MP_STATIC_ASSERT(sizeof(mp_int_t) == sizeof(long long) - || sizeof(mp_int_t) == sizeof(long)); + #if MP_INT_MAX == INT_MAX + return mp_clz((unsigned)x); + #elif MP_INT_MAX == LONG_MAX + return mp_clzl((unsigned long)x); + #elif MP_INT_MAX == LLONG_MAX + return mp_clzll((unsigned long long)x); + #else + #error Unexpected MP_INT_MAX value + #endif + #endif +} - // ugly, but should compile to single intrinsic unless O0 is set - if (mp_check(sizeof(mp_int_t) == sizeof(long))) { - return mp_clzl((unsigned long)x); +// Overflow-checked operations + +// Integer overflow builtins were added to GCC 5, but __has_builtin only in GCC 10 +// +// Note that the builtins has a defined result when overflow occurs, whereas the custom +// functions below don't update the result if an overflow would occur (to avoid UB). +#define MP_GCC_HAS_BUILTIN_OVERFLOW (__GNUC__ >= 5) + +#if MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC + +#define mp_mul_ull_overflow __builtin_umulll_overflow +#define mp_mul_ll_overflow __builtin_smulll_overflow +static inline bool mp_mul_mp_int_t_overflow(mp_int_t x, mp_int_t y, mp_int_t *res) { + // __builtin_mul_overflow is a type-generic function, this inline ensures the argument + // types are checked to match mp_int_t. + return __builtin_mul_overflow(x, y, res); +} + +#else + +bool mp_mul_ll_overflow(long long int x, long long int y, long long int *res); +bool mp_mul_mp_int_t_overflow(mp_int_t x, mp_int_t y, mp_int_t *res); +static inline bool mp_mul_ull_overflow(unsigned long long int x, unsigned long long int y, unsigned long long int *res) { + if (y > 0 && x > (ULLONG_MAX / y)) { + return true; // overflow + } + *res = x * y; + return false; +} + +#endif + +#if __has_builtin(__builtin_saddll_overflow) || MP_GCC_HAS_BUILTIN_OVERFLOW +#define mp_add_ll_overflow __builtin_saddll_overflow +#else +static inline bool mp_add_ll_overflow(long long int lhs, long long int rhs, long long int *res) { + bool overflow; + + if (rhs > 0) { + overflow = (lhs > LLONG_MAX - rhs); } else { - return mp_clzll((unsigned long long)x); + overflow = (lhs < LLONG_MIN - rhs); } - #endif + + if (!overflow) { + *res = lhs + rhs; + } + + return overflow; +} +#endif + +#if __has_builtin(__builtin_ssubll_overflow) || MP_GCC_HAS_BUILTIN_OVERFLOW +#define mp_sub_ll_overflow __builtin_ssubll_overflow +#else +static inline bool mp_sub_ll_overflow(long long int lhs, long long int rhs, long long int *res) { + bool overflow; + + if (rhs > 0) { + overflow = (lhs < LLONG_MIN + rhs); + } else { + overflow = (lhs > LLONG_MAX + rhs); + } + + if (!overflow) { + *res = lhs - rhs; + } + + return overflow; } +#endif + + +// Helper macros for detecting if sanitizers are enabled +// +// Use sparingly, not for masking issues reported by sanitizers! +// +// Can be detected automatically in Clang and gcc>=14, need to be +// set manually otherwise. +#ifndef MP_UBSAN +#define MP_UBSAN __has_feature(undefined_behavior_sanitizer) +#endif + +#ifndef MP_ASAN +#define MP_ASAN __has_feature(address_sanitizer) +#endif + +#ifndef MP_SANITIZER_BUILD +#define MP_SANITIZER_BUILD (MP_UBSAN || MP_ASAN) +#endif #endif // MICROPY_INCLUDED_PY_MISC_H diff --git a/py/mkrules.cmake b/py/mkrules.cmake index 4374b8b4da3..e3d769cc59b 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -14,6 +14,9 @@ set(MICROPY_MODULEDEFS "${MICROPY_GENHDR_DIR}/moduledefs.h") set(MICROPY_ROOT_POINTERS_SPLIT "${MICROPY_GENHDR_DIR}/root_pointers.split") set(MICROPY_ROOT_POINTERS_COLLECTED "${MICROPY_GENHDR_DIR}/root_pointers.collected") set(MICROPY_ROOT_POINTERS "${MICROPY_GENHDR_DIR}/root_pointers.h") +set(MICROPY_COMPRESSED_SPLIT "${MICROPY_GENHDR_DIR}/compressed.split") +set(MICROPY_COMPRESSED_COLLECTED "${MICROPY_GENHDR_DIR}/compressed.collected") +set(MICROPY_COMPRESSED_DATA "${MICROPY_GENHDR_DIR}/compressed.data.h") if(NOT MICROPY_PREVIEW_VERSION_2) set(MICROPY_PREVIEW_VERSION_2 0) @@ -32,6 +35,13 @@ if(MICROPY_BOARD) ) endif() +# Need to do this before extracting MICROPY_CPP_DEF below. +if(MICROPY_ROM_TEXT_COMPRESSION) + target_compile_definitions(${MICROPY_TARGET} PUBLIC + MICROPY_ROM_TEXT_COMPRESSION=\(1\) + ) +endif() + # Need to do this before extracting MICROPY_CPP_DEF below. Rest of frozen # manifest handling is at the end of this file. if(MICROPY_FROZEN_MANIFEST) @@ -84,6 +94,18 @@ target_sources(${MICROPY_TARGET} PRIVATE ${MICROPY_ROOT_POINTERS} ) +if(MICROPY_ROM_TEXT_COMPRESSION) + target_sources(${MICROPY_TARGET} PRIVATE + ${MICROPY_COMPRESSED_DATA} + ) +endif() + +# Ensure genhdr directory is removed on clean + +set_property(TARGET ${MICROPY_TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES + "${MICROPY_GENHDR_DIR}" +) + # Command to force the build of another command # Generate mpversion.h @@ -197,11 +219,41 @@ add_custom_command( DEPENDS ${MICROPY_ROOT_POINTERS_COLLECTED} ${MICROPY_PY_DIR}/make_root_pointers.py ) +# Generate compressed.data.h + +add_custom_command( + OUTPUT ${MICROPY_COMPRESSED_SPLIT} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py split compress ${MICROPY_QSTRDEFS_LAST} ${MICROPY_GENHDR_DIR}/compress _ + COMMAND touch ${MICROPY_COMPRESSED_SPLIT} + DEPENDS ${MICROPY_QSTRDEFS_LAST} + VERBATIM + COMMAND_EXPAND_LISTS +) + +add_custom_command( + OUTPUT ${MICROPY_COMPRESSED_COLLECTED} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py cat compress _ ${MICROPY_GENHDR_DIR}/compress ${MICROPY_COMPRESSED_COLLECTED} + BYPRODUCTS "${MICROPY_COMPRESSED_COLLECTED}.hash" + DEPENDS ${MICROPY_COMPRESSED_SPLIT} + VERBATIM + COMMAND_EXPAND_LISTS +) + +add_custom_command( + OUTPUT ${MICROPY_COMPRESSED_DATA} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makecompresseddata.py ${MICROPY_COMPRESSED_COLLECTED} > ${MICROPY_COMPRESSED_DATA} + DEPENDS ${MICROPY_COMPRESSED_COLLECTED} ${MICROPY_PY_DIR}/makecompresseddata.py +) + # Build frozen code if enabled if(MICROPY_FROZEN_MANIFEST) set(MICROPY_FROZEN_CONTENT "${CMAKE_BINARY_DIR}/frozen_content.c") + set_property(TARGET ${MICROPY_TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES + "${CMAKE_BINARY_DIR}/frozen_mpy" + ) + target_sources(${MICROPY_TARGET} PRIVATE ${MICROPY_FROZEN_CONTENT} ) diff --git a/py/mkrules.mk b/py/mkrules.mk index f364297f0f2..03988996c71 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -11,6 +11,7 @@ ifeq ($(MICROPY_PREVIEW_VERSION_2),1) CFLAGS += -DMICROPY_PREVIEW_VERSION_2=1 endif +# CIRCUITPY-CHANGE: point to CircuitPython documentation HELP_BUILD_ERROR ?= "See \033[1;31mhttps://learn.adafruit.com/building-circuitpython; Adafruit Discord \#circuitpython-dev\033[0m" HELP_MPY_LIB_SUBMODULE ?= "\033[1;31mError: micropython-lib submodule is not initialized.\033[0m Run 'make submodules'" @@ -112,6 +113,14 @@ $(BUILD)/%.pp: %.c $(STEPECHO) "PreProcess $<" $(Q)$(CPP) $(CFLAGS) -Wp,-C,-dD,-dI -o $@ $< +.PHONY: $(BUILD)/%.sz +$(BUILD)/%.sz: $(BUILD)/%.o + $(Q)$(SIZE) $< + +# Special case for compiling auto-generated source files. +$(BUILD)/%.o: $(BUILD)/%.c + $(call compile_c) + # The following rule uses | to create an order only prerequisite. Order only # prerequisites only get built if they don't exist. They don't cause timestamp # checking to be performed. @@ -179,7 +188,7 @@ $(HEADER_BUILD)/compressed.collected: $(HEADER_BUILD)/compressed.split # will be created if they don't exist. OBJ_DIRS = $(sort $(dir $(OBJ))) $(OBJ): | $(OBJ_DIRS) -// CIRCUITPY-CHANGE: use $(Q) +# CIRCUITPY-CHANGE: use $(Q) $(OBJ_DIRS): $(Q)$(MKDIR) -p $@ @@ -260,7 +269,7 @@ submodules: $(ECHO) "Updating submodules: $(GIT_SUBMODULES)" ifneq ($(GIT_SUBMODULES),) $(Q)cd $(TOP) && git submodule sync $(GIT_SUBMODULES) - $(Q)cd $(TOP) && git submodule update --init --filter=blob:none $(GIT_SUBMODULES) || \ + $(Q)cd $(TOP) && git submodule update --init --filter=blob:none $(GIT_SUBMODULES) 2>/dev/null || \ git submodule update --init $(GIT_SUBMODULES) endif .PHONY: submodules diff --git a/py/modio.c b/py/modio.c index d3e563dbcf4..9aeb42d30aa 100644 --- a/py/modio.c +++ b/py/modio.c @@ -169,12 +169,13 @@ static mp_obj_t bufwriter_flush(mp_obj_t self_in) { int err; mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->len, &err); (void)out_sz; - // TODO: try to recover from a case of non-blocking stream, e.g. move - // remaining chunk to the beginning of buffer. - assert(out_sz == self->len); - self->len = 0; if (err != 0) { mp_raise_OSError(err); + } else { + // TODO: try to recover from a case of non-blocking stream, e.g. move + // remaining chunk to the beginning of buffer. + assert(out_sz == self->len); + self->len = 0; } } diff --git a/py/modmath.c b/py/modmath.c index 2b41bbcd7d1..2a9ed1b7f22 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -37,7 +37,7 @@ #define MP_PI_4 MICROPY_FLOAT_CONST(0.78539816339744830962) #define MP_3_PI_4 MICROPY_FLOAT_CONST(2.35619449019234492885) -static NORETURN void math_error(void) { +static MP_NORETURN void math_error(void) { mp_raise_ValueError(MP_ERROR_TEXT("math domain error")); } @@ -99,12 +99,16 @@ mp_float_t MICROPY_FLOAT_C_FUN(log2)(mp_float_t x) { MATH_FUN_1(sqrt, sqrt) // pow(x, y): returns x to the power of y #if MICROPY_PY_MATH_POW_FIX_NAN -mp_float_t pow_func(mp_float_t x, mp_float_t y) { +mp_float_t MICROPY_FLOAT_C_FUN(pow_func)(mp_float_t x, mp_float_t y) { // pow(base, 0) returns 1 for any base, even when base is NaN // pow(+1, exponent) returns 1 for any exponent, even when exponent is NaN if (x == MICROPY_FLOAT_CONST(1.0) || y == MICROPY_FLOAT_CONST(0.0)) { return MICROPY_FLOAT_CONST(1.0); } + // pow(base, NaN) returns NaN for any other value of base + if (isnan(y)) { + return y; + } return MICROPY_FLOAT_C_FUN(pow)(x, y); } MATH_FUN_2(pow, pow_func) @@ -161,6 +165,11 @@ MATH_FUN_2(atan2, atan2) MATH_FUN_1_TO_INT(ceil, ceil) // copysign(x, y) static mp_float_t MICROPY_FLOAT_C_FUN(copysign_func)(mp_float_t x, mp_float_t y) { + #if MICROPY_PY_MATH_COPYSIGN_FIX_NAN + if (isnan(y)) { + y = 0.0; + } + #endif return MICROPY_FLOAT_C_FUN(copysign)(x, y); } MATH_FUN_2(copysign, copysign_func) diff --git a/py/modmicropython.c b/py/modmicropython.c index ff25af8ff7e..67bb32626c3 100644 --- a/py/modmicropython.c +++ b/py/modmicropython.c @@ -100,7 +100,7 @@ static mp_obj_t mp_micropython_qstr_info(size_t n_args, const mp_obj_t *args) { size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); mp_printf(&mp_plat_print, "qstr pool: n_pool=%u, n_qstr=%u, n_str_data_bytes=%u, n_total_bytes=%u\n", - n_pool, n_qstr, n_str_data_bytes, n_total_bytes); + (uint)n_pool, (uint)n_qstr, (uint)n_str_data_bytes, (uint)n_total_bytes); if (n_args == 1) { // arg given means dump qstr data qstr_dump_data(); diff --git a/py/modsys.c b/py/modsys.c index 2adbc0b7bd6..bbae93d0c3f 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -95,8 +95,16 @@ static const MP_DEFINE_STR_OBJ(mp_sys_implementation_machine_obj, MICROPY_BANNER MP_ROM_PTR(&mp_sys_implementation_machine_obj) #if MICROPY_PERSISTENT_CODE_LOAD +// Note: Adding architecture flags to _mpy will break if the flags information +// takes up more bits than what is available in a small-int value. +#if MICROPY_EMIT_RV32 +#include "py/asmrv32.h" +#define MPY_FILE_ARCH_FLAGS (MICROPY_RV32_EXTENSIONS << 16) +#else +#define MPY_FILE_ARCH_FLAGS (0) +#endif #define SYS_IMPLEMENTATION_ELEMS__MPY \ - , MP_ROM_INT(MPY_FILE_HEADER_INT) + , MP_ROM_INT(MPY_FILE_HEADER_INT | MPY_FILE_ARCH_FLAGS) #else #define SYS_IMPLEMENTATION_ELEMS__MPY #endif @@ -113,6 +121,18 @@ static const MP_DEFINE_STR_OBJ(mp_sys_implementation__build_obj, MICROPY_BOARD_B #define SYS_IMPLEMENTATION_ELEMS__BUILD #endif +#if MICROPY_PY_THREAD +#if MICROPY_PY_THREAD_GIL +#define SYS_IMPLEMENTATION_ELEMS__THREAD \ + , MP_ROM_QSTR(MP_QSTR_GIL) +#else +#define SYS_IMPLEMENTATION_ELEMS__THREAD \ + , MP_ROM_QSTR(MP_QSTR_unsafe) +#endif +#else +#define SYS_IMPLEMENTATION_ELEMS__THREAD +#endif + #if MICROPY_PREVIEW_VERSION_2 #define SYS_IMPLEMENTATION_ELEMS__V2 \ , MP_ROM_TRUE @@ -130,6 +150,9 @@ static const qstr impl_fields[] = { #if defined(MICROPY_BOARD_BUILD_NAME) MP_QSTR__build, #endif + #if MICROPY_PY_THREAD + MP_QSTR__thread, + #endif #if MICROPY_PREVIEW_VERSION_2 MP_QSTR__v2, #endif @@ -137,20 +160,21 @@ static const qstr impl_fields[] = { static MP_DEFINE_ATTRTUPLE( mp_sys_implementation_obj, impl_fields, - 3 + MICROPY_PERSISTENT_CODE_LOAD + MICROPY_BOARD_BUILD + MICROPY_PREVIEW_VERSION_2, + 3 + MICROPY_PERSISTENT_CODE_LOAD + MICROPY_BOARD_BUILD + MICROPY_PY_THREAD + MICROPY_PREVIEW_VERSION_2, SYS_IMPLEMENTATION_ELEMS_BASE SYS_IMPLEMENTATION_ELEMS__MPY SYS_IMPLEMENTATION_ELEMS__BUILD + SYS_IMPLEMENTATION_ELEMS__THREAD SYS_IMPLEMENTATION_ELEMS__V2 ); #else static const mp_rom_obj_tuple_t mp_sys_implementation_obj = { {&mp_type_tuple}, 3 + MICROPY_PERSISTENT_CODE_LOAD, - // Do not include SYS_IMPLEMENTATION_ELEMS__BUILD or SYS_IMPLEMENTATION_ELEMS__V2 - // because SYS_IMPLEMENTATION_ELEMS__MPY may be empty if + // Do not include SYS_IMPLEMENTATION_ELEMS__BUILD, SYS_IMPLEMENTATION_ELEMS__THREAD + // or SYS_IMPLEMENTATION_ELEMS__V2 because SYS_IMPLEMENTATION_ELEMS__MPY may be empty if // MICROPY_PERSISTENT_CODE_LOAD is disabled, which means they'll share - // the same index. Cannot query _build or _v2 if MICROPY_PY_ATTRTUPLE is + // the same index. Cannot query _build, _thread or _v2 if MICROPY_PY_ATTRTUPLE is // disabled. { SYS_IMPLEMENTATION_ELEMS_BASE diff --git a/py/mpconfig.h b/py/mpconfig.h index a4895820061..0e440066d78 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -26,6 +26,15 @@ #ifndef MICROPY_INCLUDED_PY_MPCONFIG_H #define MICROPY_INCLUDED_PY_MPCONFIG_H +#include +#include + +#if defined(__cplusplus) // Required on at least one compiler to get ULLONG_MAX +#include +#else +#include +#endif + // CIRCUITPY-CHANGE // Is this a CircuitPython build? #ifndef CIRCUITPY @@ -40,7 +49,7 @@ // as well as a fallback to generate MICROPY_GIT_TAG if the git repo or tags // are unavailable. #define MICROPY_VERSION_MAJOR 1 -#define MICROPY_VERSION_MINOR 25 +#define MICROPY_VERSION_MINOR 27 #define MICROPY_VERSION_MICRO 0 #define MICROPY_VERSION_PRERELEASE 0 @@ -173,6 +182,81 @@ #define MICROPY_OBJ_IMMEDIATE_OBJS (MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D) #endif +// Definition of the `mp_int_t` and `mp_uint_t` types and associated macros. +// Normally, it suffices for the platform to do nothing: A type as wide +// as a pointer is chosen, unless nanboxing (REPR_D) is selected, in +// which case a 64-bit type is chosen to match the assumed size of +// double-precision floats. +// +// In the case of exceptions, the port, board, or variant must define +// MP_INT_TYPE as MP_INT_TYPE_OTHER and provide all the typedefs and +// defines. +#define MP_INT_TYPE_INTPTR (0) +#define MP_INT_TYPE_INT64 (1) +#define MP_INT_TYPE_OTHER (2) + +#if !defined(MP_INT_TYPE) +#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D +#define MP_INT_TYPE (MP_INT_TYPE_INT64) +#else +#define MP_INT_TYPE (MP_INT_TYPE_INTPTR) +#endif +#endif + +#if MP_INT_TYPE == MP_INT_TYPE_INTPTR +typedef intptr_t mp_int_t; +// Use size_t so kw-function signatures and other size-typed APIs match without +// triggering -Wincompatible-pointer-types under newer GCCs where size_t and +// uintptr_t are distinct types of the same width (e.g. picolibc on 32-bit ARM). +typedef size_t mp_uint_t; +#define MP_INT_MAX INTPTR_MAX +#define MP_INT_MIN INTPTR_MIN +#define MP_UINT_MAX SIZE_MAX +#elif MP_INT_TYPE == MP_INT_TYPE_INT64 +typedef int64_t mp_int_t; +typedef uint64_t mp_uint_t; +#define MP_INT_MAX INT64_MAX +#define MP_INT_MIN INT64_MIN +#define MP_UINT_MAX INT64_UMAX +#endif + +// mp_printf format support for mp_int_t. In the unusual case that MP_INT_MAX doesn't +// match any of the standard C types (int/long/long long), provide all 3 +// macros. Otherwise, rely on these automatic definitions. +#if !defined(INT_FMT) +#if MP_INT_MAX == INT_MAX +#define INT_FMT "%d" +#define UINT_FMT "%u" +#define HEX_FMT "%x" +#elif MP_INT_MAX == LONG_MAX +#define INT_FMT "%ld" +#define UINT_FMT "%lu" +#define HEX_FMT "%lx" +#elif MP_INT_MAX == LLONG_MAX +#define INT_FMT "%lld" +#define UINT_FMT "%llu" +#define HEX_FMT "%llx" +#else +#error Unexpected MP_INT_MAX value +#endif +#endif + +// mp_printf format support for size_t. In the unusual case that SIZE_MAX doesn't +// match any of the standard C types (int/long/long long), provide a +// macro. Otherwise, rely on these automatic definitions. +#if !defined(SIZE_FMT) +#if SIZE_MAX == UINT_MAX +#define SIZE_FMT "%u" +#elif SIZE_MAX == ULONG_MAX +#define SIZE_FMT "%lu" +#elif SIZE_MAX == ULLONG_MAX +#define SIZE_FMT "%llu" +#else +#error Unexpected SIZE_MAX value +#endif +#endif + + /*****************************************************************************/ /* Memory allocation policy */ @@ -418,6 +502,11 @@ #define MICROPY_EMIT_INLINE_XTENSA (0) #endif +// Whether to support uncommon Xtensa inline assembler opcodes +#ifndef MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES +#define MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES (0) +#endif + // Whether to emit Xtensa-Windowed native code #ifndef MICROPY_EMIT_XTENSAWIN #define MICROPY_EMIT_XTENSAWIN (0) @@ -428,9 +517,9 @@ #define MICROPY_EMIT_RV32 (0) #endif -// CIRCUITPY-CHANGE: make sure MICROPY_EMIT_NATIVE_DEBUG is defined -#ifndef MICROPY_EMIT_NATIVE_DEBUG -#define MICROPY_EMIT_NATIVE_DEBUG (0) +// Whether to emit RISC-V RV32 Zba opcodes in native code +#ifndef MICROPY_EMIT_RV32_ZBA +#define MICROPY_EMIT_RV32_ZBA (0) #endif // Whether to enable the RISC-V RV32 inline assembler @@ -438,6 +527,11 @@ #define MICROPY_EMIT_INLINE_RV32 (0) #endif +// Whether to enable the human-readable native instructions emitter +#ifndef MICROPY_EMIT_NATIVE_DEBUG +#define MICROPY_EMIT_NATIVE_DEBUG (0) +#endif + // Convenience definition for whether any native emitter is enabled #define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN || MICROPY_EMIT_RV32 || MICROPY_EMIT_NATIVE_DEBUG) @@ -497,6 +591,13 @@ #define MICROPY_COMP_CONST (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif +// Whether to enable float constant folding like 1.2+3.4 (when MICROPY_COMP_CONST_FOLDING is also enabled) +// and constant optimisation like id = const(1.2) (when MICROPY_COMP_CONST is also enabled) +// and constant lookup like math.inf (when MICROPY_COMP_MODULE_CONST is also enabled) +#ifndef MICROPY_COMP_CONST_FLOAT +#define MICROPY_COMP_CONST_FLOAT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) +#endif + // Whether to enable optimisation of: a, b = c, d // Costs 124 bytes (Thumb2) #ifndef MICROPY_COMP_DOUBLE_TUPLE_ASSIGN @@ -727,6 +828,13 @@ #define MICROPY_STACK_CHECK_MARGIN (0) #endif +// The size of a separate stack used for hard IRQ handlers, which should be +// checked instead of the main stack when running a hard callback. 0 implies +// there is no separate ISR stack to check. +#ifndef MICROPY_STACK_SIZE_HARD_IRQ +#define MICROPY_STACK_SIZE_HARD_IRQ (0) +#endif + // Whether to have an emergency exception buffer #ifndef MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) @@ -896,8 +1004,25 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT) #endif -#ifndef MICROPY_PY_DOUBLE_TYPECODE -#define MICROPY_PY_DOUBLE_TYPECODE (MICROPY_PY_BUILTINS_FLOAT) +// Float to string conversion implementations +// +// Note that the EXACT method is only available if the compiler supports +// floating points larger than mp_float_t: +// - with MICROPY_FLOAT_IMPL_FLOAT, the compiler needs to support `double` +// - with MICROPY_FLOAT_IMPL_DOUBLE, the compiler needs to support `long double` +// +#define MICROPY_FLOAT_FORMAT_IMPL_BASIC (0) // smallest code, but inexact +#define MICROPY_FLOAT_FORMAT_IMPL_APPROX (1) // slightly bigger, almost perfect +#define MICROPY_FLOAT_FORMAT_IMPL_EXACT (2) // bigger code, and 100% exact repr + +#ifndef MICROPY_FLOAT_FORMAT_IMPL +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +#define MICROPY_FLOAT_FORMAT_IMPL (MICROPY_FLOAT_FORMAT_IMPL_APPROX) +#elif defined(__SIZEOF_LONG_DOUBLE__) && __SIZEOF_LONG_DOUBLE__ > __SIZEOF_DOUBLE__ +#define MICROPY_FLOAT_FORMAT_IMPL (MICROPY_FLOAT_FORMAT_IMPL_EXACT) +#else +#define MICROPY_FLOAT_FORMAT_IMPL (MICROPY_FLOAT_FORMAT_IMPL_APPROX) +#endif #endif // Whether to use the native _Float16 for 16-bit float support @@ -932,6 +1057,64 @@ typedef double mp_float_t; #define MICROPY_FULL_CHECKS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif +// Ports can choose to use timestamps based on 2000-01-01 or 1970-01-01 +// Default is timestamps based on 2000-01-01 +#if !defined(MICROPY_EPOCH_IS_2000) && !defined(MICROPY_EPOCH_IS_1970) +#define MICROPY_EPOCH_IS_2000 (1) +#define MICROPY_EPOCH_IS_1970 (0) +#elif !defined(MICROPY_EPOCH_IS_1970) +#define MICROPY_EPOCH_IS_1970 (1 - (MICROPY_EPOCH_IS_2000)) +#elif !defined(MICROPY_EPOCH_IS_2000) +#define MICROPY_EPOCH_IS_2000 (1 - (MICROPY_EPOCH_IS_1970)) +#endif + +// To maintain reasonable compatibility with CPython on embedded systems, +// and avoid breaking anytime soon, time functions are defined to work +// at least between 1970 and 2099 (included) on any machine. +// +// Specific ports can enable extended date support +// - after 2099 using MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND +// - before 1970 using MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE +// The largest possible range is year 1600 to year 3000 +// +// By default, extended date support is only enabled for machines using 64 bit pointers, +// but it can be enabled by specific ports +#ifndef MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE +#if MP_SSIZE_MAX > 2147483647 +#define MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE (1) +#else +#define MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE (0) +#endif +#endif + +// When support for dates <1970 is enabled, supporting >=2100 does not cost anything +#ifndef MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND +#define MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND (MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE) +#endif + +// The type to be used to represent platform-specific timestamps depends on the choices above +#define MICROPY_TIMESTAMP_IMPL_LONG_LONG (0) +#define MICROPY_TIMESTAMP_IMPL_UINT (1) +#define MICROPY_TIMESTAMP_IMPL_TIME_T (2) + +#ifndef MICROPY_TIMESTAMP_IMPL +#if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE || MICROPY_EPOCH_IS_2000 +#define MICROPY_TIMESTAMP_IMPL (MICROPY_TIMESTAMP_IMPL_LONG_LONG) +#else +#define MICROPY_TIMESTAMP_IMPL (MICROPY_TIMESTAMP_IMPL_UINT) +#endif +#endif + +// `mp_timestamp_t` is the type that should be used by the port +// to represent timestamps, and is referenced to the platform epoch +#if MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_LONG_LONG +typedef long long mp_timestamp_t; +#elif MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_UINT +typedef mp_uint_t mp_timestamp_t; +#elif MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_TIME_T +typedef time_t mp_timestamp_t; +#endif + // Whether POSIX-semantics non-blocking streams are supported #ifndef MICROPY_STREAMS_NON_BLOCK #define MICROPY_STREAMS_NON_BLOCK (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -943,6 +1126,16 @@ typedef double mp_float_t; #define MICROPY_STREAMS_POSIX_API (0) #endif +// Whether to process __all__ when importing all public symbols from a module. +#ifndef MICROPY_MODULE___ALL__ +#define MICROPY_MODULE___ALL__ (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_BASIC_FEATURES) +#endif + +// Whether to set __file__ on imported modules. +#ifndef MICROPY_MODULE___FILE__ +#define MICROPY_MODULE___FILE__ (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) +#endif + // Whether modules can use MP_REGISTER_MODULE_DELEGATION() to delegate failed // attribute lookups to a custom handler function. #ifndef MICROPY_MODULE_ATTR_DELEGATION @@ -1030,6 +1223,16 @@ typedef double mp_float_t; #define MICROPY_ENABLE_VM_ABORT (0) #endif +// Whether to handle abort behavior in pyexec code +#ifndef MICROPY_PYEXEC_ENABLE_VM_ABORT +#define MICROPY_PYEXEC_ENABLE_VM_ABORT (0) +#endif + +// Whether to set exit codes according to the exit reason (keyboard interrupt, crash, normal exit, ...) +#ifndef MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING +#define MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING (0) +#endif + // Support for internal scheduler #ifndef MICROPY_ENABLE_SCHEDULER #define MICROPY_ENABLE_SCHEDULER (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -1065,6 +1268,11 @@ typedef double mp_float_t; #define MICROPY_VFS_POSIX (0) #endif +// Whether to include support for writable POSIX filesystems. +#ifndef MICROPY_VFS_POSIX_WRITABLE +#define MICROPY_VFS_POSIX_WRITABLE (1) +#endif + // Support for VFS FAT component, to mount a FAT filesystem within VFS #ifndef MICROPY_VFS_FAT #define MICROPY_VFS_FAT (0) @@ -1105,7 +1313,15 @@ typedef double mp_float_t; #define MICROPY_PY_FUNCTION_ATTRS_CODE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_FULL_FEATURES) #endif -// Whether to support the descriptors __get__, __set__, __delete__ +// Whether bound_method can just use == (feature disabled), or requires a call to +// mp_obj_equal (feature enabled), to test equality of the self and meth entities. +// This is only needed if objects and functions can be identical without being the +// same thing, eg when using an object proxy. +#ifndef MICROPY_PY_BOUND_METHOD_FULL_EQUALITY_CHECK +#define MICROPY_PY_BOUND_METHOD_FULL_EQUALITY_CHECK (0) +#endif + +// Whether to support the descriptors __get__, __set__, __delete__, __set_name__ // This costs some code size and makes load/store/delete of instance // attributes slower for the classes that use this feature #ifndef MICROPY_PY_DESCRIPTORS @@ -1362,11 +1578,6 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_HELP_MODULES (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif -// Whether to set __file__ for imported modules -#ifndef MICROPY_PY___FILE__ -#define MICROPY_PY___FILE__ (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) -#endif - // Whether to provide mem-info related functions in micropython module #ifndef MICROPY_PY_MICROPYTHON_MEM_INFO #define MICROPY_PY_MICROPYTHON_MEM_INFO (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -1482,6 +1693,7 @@ typedef double mp_float_t; #endif // Whether to provide fix for pow(1, NaN) and pow(NaN, 0), which both should be 1 not NaN. +// Also fixes pow(base, NaN) to return NaN for other values of base. #ifndef MICROPY_PY_MATH_POW_FIX_NAN #define MICROPY_PY_MATH_POW_FIX_NAN (0) #endif @@ -1518,7 +1730,7 @@ typedef double mp_float_t; // Whether to provide "io.IOBase" class to support user streams #ifndef MICROPY_PY_IO_IOBASE -#define MICROPY_PY_IO_IOBASE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) +#define MICROPY_PY_IO_IOBASE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif // Whether to provide "io.BytesIO" class @@ -1536,15 +1748,16 @@ typedef double mp_float_t; #define MICROPY_PY_STRUCT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif -// CIRCUITPY-CHANGE -// Whether to provide non-standard typecodes in "struct" module -#ifndef MICROPY_NONSTANDARD_TYPECODES -#define MICROPY_NONSTANDARD_TYPECODES (1) +// Whether struct module provides unsafe and non-standard typecodes O, P, S. +// These typecodes are not in CPython and can cause crashes by accessing arbitrary +// memory. +#ifndef MICROPY_PY_STRUCT_UNSAFE_TYPECODES +#define MICROPY_PY_STRUCT_UNSAFE_TYPECODES (1) #endif // Whether to provide "sys" module #ifndef MICROPY_PY_SYS -#define MICROPY_PY_SYS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) +#define MICROPY_PY_SYS (1) #endif // Whether to initialise "sys.path" and "sys.argv" to their defaults in mp_init() @@ -1800,11 +2013,11 @@ typedef double mp_float_t; #endif #ifndef MICROPY_PY_HASHLIB_MD5 -#define MICROPY_PY_HASHLIB_MD5 (0) +#define MICROPY_PY_HASHLIB_MD5 (MICROPY_PY_SSL) #endif #ifndef MICROPY_PY_HASHLIB_SHA1 -#define MICROPY_PY_HASHLIB_SHA1 (0) +#define MICROPY_PY_HASHLIB_SHA1 (MICROPY_PY_SSL) #endif #ifndef MICROPY_PY_HASHLIB_SHA256 @@ -1812,7 +2025,7 @@ typedef double mp_float_t; #endif #ifndef MICROPY_PY_CRYPTOLIB -#define MICROPY_PY_CRYPTOLIB (0) +#define MICROPY_PY_CRYPTOLIB (MICROPY_PY_SSL) #endif // Depends on MICROPY_PY_CRYPTOLIB @@ -1935,6 +2148,11 @@ typedef double mp_float_t; #define MICROPY_PY_SSL_MBEDTLS_NEED_ACTIVE_CONTEXT (MICROPY_PY_SSL_ECDSA_SIGN_ALT) #endif +// Whether to support DTLS protocol (non-CPython feature) +#ifndef MICROPY_PY_SSL_DTLS +#define MICROPY_PY_SSL_DTLS (MICROPY_SSL_MBEDTLS && MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) +#endif + // Whether to provide the "vfs" module #ifndef MICROPY_PY_VFS #define MICROPY_PY_VFS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES && MICROPY_VFS) @@ -2027,7 +2245,7 @@ typedef double mp_float_t; /*****************************************************************************/ /* Miscellaneous settings */ -// All uPy objects in ROM must be aligned on at least a 4 byte boundary +// All MicroPython objects in ROM must be aligned on at least a 4 byte boundary // so that the small-int/qstr/pointer distinction can be made. For machines // that don't do this (eg 16-bit CPU), define the following macro to something // like __attribute__((aligned(4))). @@ -2166,25 +2384,13 @@ typedef double mp_float_t; #define MP_SSIZE_MAX SSIZE_MAX #endif -// printf format spec to use for mp_int_t and friends -#ifndef INT_FMT -#if defined(__LP64__) -// Archs where mp_int_t == long, long != int -#define UINT_FMT "%lu" -#define INT_FMT "%ld" -#elif defined(_WIN64) -#define UINT_FMT "%llu" -#define INT_FMT "%lld" -#else -// Archs where mp_int_t == int -#define UINT_FMT "%u" -#define INT_FMT "%d" +// Modifier for function which doesn't return +#ifndef MP_NORETURN +#define MP_NORETURN __attribute__((noreturn)) #endif -#endif // INT_FMT -// Modifier for function which doesn't return -#ifndef NORETURN -#define NORETURN __attribute__((noreturn)) +#if !MICROPY_PREVIEW_VERSION_2 +#define NORETURN MP_NORETURN #endif // Modifier for weak functions @@ -2205,6 +2411,12 @@ typedef double mp_float_t; #define MP_INLINE inline MP_NO_INSTRUMENT #endif +// CIRCUITPY-CHANGE +// Modifier for functions whose return value should not be ignored +#ifndef MP_WARN_UNUSED_RESULT +#define MP_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#endif + // Modifier for functions which should be never inlined #ifndef MP_NOINLINE #define MP_NOINLINE __attribute__((noinline)) @@ -2279,4 +2491,23 @@ typedef double mp_float_t; #define MP_WARN_CAT(x) (NULL) #endif +// If true, use __builtin_mul_overflow (a gcc intrinsic supported by clang) for +// overflow checking when multiplying two small ints. Otherwise, use a portable +// algorithm. +// +// Most MCUs have a 32x32->64 bit multiply instruction, in which case the +// intrinsic is likely to be faster and generate smaller code. The main exception is +// cortex-m0 with __ARM_ARCH_ISA_THUMB == 1. +// +// The intrinsic is in GCC starting with version 5. +#ifndef MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC +#if defined(__ARM_ARCH_ISA_THUMB) && (__GNUC__ >= 5) +#define MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC (__ARM_ARCH_ISA_THUMB >= 2) +#elif (__GNUC__ >= 5) +#define MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC (1) +#else +#define MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC (0) +#endif +#endif + #endif // MICROPY_INCLUDED_PY_MPCONFIG_H diff --git a/py/mphal.h b/py/mphal.h index 95289ac856c..3907641be83 100644 --- a/py/mphal.h +++ b/py/mphal.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_PY_MPHAL_H #include +#include #include "py/mpconfig.h" #ifdef MICROPY_MPHALPORT_H diff --git a/py/mpprint.c b/py/mpprint.c index e4e25f5a82e..62e80d1e8e8 100644 --- a/py/mpprint.c +++ b/py/mpprint.c @@ -40,8 +40,20 @@ #include "py/formatfloat.h" #endif -static const char pad_spaces[] = " "; -static const char pad_zeroes[] = "0000000000000000"; +static const char pad_spaces[16] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; +#define pad_spaces_size (sizeof(pad_spaces)) +static const char pad_common[23] = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '_', '0', '0', '0', ',', '0', '0'}; +// The contents of pad_common is arranged to provide the following padding +// strings with minimal flash size: +// 0000000000000000 <- pad_zeroes +// 0000_000 <- pad_zeroes_underscore (offset: 12, size 5) +// 000,00 <- pad_zeroes_comma (offset: 17, size 4) +#define pad_zeroes (pad_common + 0) +#define pad_zeroes_size (16) +#define pad_zeroes_underscore (pad_common + 12) +#define pad_zeroes_underscore_size (5) +#define pad_zeroes_comma (pad_common + 17) +#define pad_zeroes_comma_size (4) static void plat_print_strn(void *env, const char *str, size_t len) { (void)env; @@ -58,20 +70,37 @@ int mp_print_str(const mp_print_t *print, const char *str) { return len; } -int mp_print_strn(const mp_print_t *print, const char *str, size_t len, int flags, char fill, int width) { +int mp_print_strn(const mp_print_t *print, const char *str, size_t len, unsigned int flags, char fill, int width) { int left_pad = 0; int right_pad = 0; int pad = width - len; int pad_size; int total_chars_printed = 0; const char *pad_chars; + char grouping = flags >> PF_FLAG_SEP_POS; if (!fill || fill == ' ') { pad_chars = pad_spaces; - pad_size = sizeof(pad_spaces) - 1; - } else if (fill == '0') { + pad_size = pad_spaces_size; + } else if (fill == '0' && !grouping) { pad_chars = pad_zeroes; - pad_size = sizeof(pad_zeroes) - 1; + pad_size = pad_zeroes_size; + } else if (fill == '0') { + if (grouping == '_') { + pad_chars = pad_zeroes_underscore; + pad_size = pad_zeroes_underscore_size; + } else { + pad_chars = pad_zeroes_comma; + pad_size = pad_zeroes_comma_size; + } + // The result will never start with a grouping character. An extra leading zero is added. + // width is dead after this so we can use it in calculation + if (width % pad_size == 0) { + pad++; + width++; + } + // position the grouping character correctly within the pad repetition + pad_chars += pad_size - 1 - width % pad_size; } else { // Other pad characters are fairly unusual, so we'll take the hit // and output them 1 at a time. @@ -201,7 +230,7 @@ static int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, return len; } -int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec) { +int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, unsigned int base, int base_char, int flags, char fill, int width, int prec) { // These are the only values for "base" that are required to be supported by this // function, since Python only allows the user to format integers in these bases. // If needed this function could be generalised to handle other values. @@ -248,10 +277,7 @@ int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char int prefix_len = prefix - prefix_buf; prefix = prefix_buf; - char comma = '\0'; - if (flags & PF_FLAG_SHOW_COMMA) { - comma = ','; - } + char comma = flags >> PF_FLAG_SEP_POS; // The size of this buffer is rather arbitrary. If it's not large // enough, a dynamic one will be allocated. @@ -340,8 +366,8 @@ int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char } #if MICROPY_PY_BUILTINS_FLOAT -int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec) { - char buf[32]; +int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, unsigned int flags, char fill, int width, int prec) { + char buf[36]; char sign = '\0'; int chrs = 0; @@ -352,11 +378,17 @@ int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, c sign = ' '; } - int len = mp_format_float(f, buf, sizeof(buf), fmt, prec, sign); + int len = mp_format_float(f, buf, sizeof(buf) - 3, fmt, prec, sign); char *s = buf; - if ((flags & PF_FLAG_ADD_PERCENT) && (size_t)(len + 1) < sizeof(buf)) { + if ((flags & PF_FLAG_ALWAYS_DECIMAL) && strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) { + buf[len++] = '.'; + buf[len++] = '0'; + buf[len] = '\0'; + } + + if (flags & PF_FLAG_ADD_PERCENT) { buf[len++] = '%'; buf[len] = '\0'; } @@ -376,14 +408,6 @@ int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, c } #endif -// CIRCUITPY-CHANGE -static int print_str_common(const mp_print_t *print, const char *str, int prec, size_t len, int flags, int fill, int width) { - if (prec >= 0 && (size_t)prec < len) { - len = prec; - } - return mp_print_strn(print, str, len, flags, fill, width); -} - int mp_printf(const mp_print_t *print, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -424,8 +448,6 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { flags |= PF_FLAG_SHOW_SIGN; } else if (*fmt == ' ') { flags |= PF_FLAG_SPACE_SIGN; - } else if (*fmt == '!') { - flags |= PF_FLAG_NO_TRAILZ; } else if (*fmt == '0') { flags |= PF_FLAG_PAD_AFTER_SIGN; fill = '0'; @@ -459,16 +481,36 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { } } - // parse long specifiers (only for LP64 model where they make a difference) - #ifndef __LP64__ - const + // parse long and long long specifiers (only where they make a difference) + #if (MP_INT_MAX > INT_MAX && MP_INT_MAX == LONG_MAX) || defined(MICROPY_UNIX_COVERAGE) + #define SUPPORT_L_FORMAT (1) + #else + #define SUPPORT_L_FORMAT (0) #endif + #if SUPPORT_L_FORMAT bool long_arg = false; + #endif + + #if (MP_INT_MAX > LONG_MAX) || defined(MICROPY_UNIX_COVERAGE) + #define SUPPORT_LL_FORMAT (1) + #else + #define SUPPORT_LL_FORMAT (0) + #endif + #if SUPPORT_LL_FORMAT + bool long_long_arg = false; + #endif + if (*fmt == 'l') { ++fmt; - #ifdef __LP64__ + #if SUPPORT_L_FORMAT long_arg = true; #endif + #if SUPPORT_LL_FORMAT + if (*fmt == 'l') { + ++fmt; + long_long_arg = true; + } + #endif } if (*fmt == '\0') { @@ -492,27 +534,19 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { qstr qst = va_arg(args, qstr); size_t len; const char *str = (const char *)qstr_data(qst, &len); - // CIRCUITPY-CHANGE - chrs += print_str_common(print, str, prec, len, flags, fill, width); - break; - } - // CIRCUITPY-CHANGE: new code to print compressed strings - case 'S': { - mp_rom_error_text_t arg = va_arg(args, mp_rom_error_text_t); - size_t len_with_nul = decompress_length(arg); - size_t len = len_with_nul - 1; - char str[len_with_nul]; - decompress(arg, str); - chrs += print_str_common(print, str, prec, len, flags, fill, width); + if (prec >= 0 && (size_t)prec < len) { + len = prec; + } + chrs += mp_print_strn(print, str, len, flags, fill, width); break; } case 's': { const char *str = va_arg(args, const char *); #ifndef NDEBUG // With debugging enabled, catch printing of null string pointers - if (str == NULL) { - // CIRCUITPY-CHANGE - str = "(null)"; + if (prec != 0 && str == NULL) { + chrs += mp_print_strn(print, "(null)", 6, flags, fill, width); + break; } #endif size_t len = strlen(str); @@ -522,41 +556,58 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { chrs += mp_print_strn(print, str, len, flags, fill, width); break; } - case 'd': { - mp_int_t val; - if (long_arg) { - val = va_arg(args, long int); - } else { - val = va_arg(args, int); - } - chrs += mp_print_int(print, val, 1, 10, 'a', flags, fill, width); - break; - } + case 'd': + case 'p': + case 'P': case 'u': case 'x': case 'X': { - int base = 16 - ((*fmt + 1) & 6); // maps char u/x/X to base 10/16/16 - char fmt_c = (*fmt & 0xf0) - 'P' + 'A'; // maps char u/x/X to char a/a/A + char fmt_chr = *fmt; mp_uint_t val; - if (long_arg) { - val = va_arg(args, unsigned long int); + if (fmt_chr == 'p' || fmt_chr == 'P') { + val = va_arg(args, uintptr_t); + } + #if SUPPORT_LL_FORMAT + else if (long_long_arg) { + val = va_arg(args, unsigned long long); + } + #endif + #if SUPPORT_L_FORMAT + else if (long_arg) { + if (sizeof(long) != sizeof(mp_uint_t) && fmt_chr == 'd') { + val = va_arg(args, long); + } else { + val = va_arg(args, unsigned long); + } + } + #endif + else { + if (sizeof(int) != sizeof(mp_uint_t) && fmt_chr == 'd') { + val = va_arg(args, int); + } else { + val = va_arg(args, unsigned); + } + } + int base; + // Map format char x/p/X/P to a/a/A/A for hex letters. + // It doesn't matter what d/u map to. + char fmt_c = (fmt_chr & 0xf0) - 'P' + 'A'; + if (fmt_chr == 'd' || fmt_chr == 'u') { + base = 10; } else { - val = va_arg(args, unsigned int); + base = 16; + } + // CIRCUITPY-CHANGE: include "0x" for 'p' and 'P'. + if (fmt_chr == 'p' || fmt_chr == 'P') { + #if SUPPORT_INT_BASE_PREFIX + chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags | PF_FLAG_SHOW_PREFIX, fill, width); + #else + chrs += mp_print_strn(print, "0x", 2, flags, fill, width); + #endif } - chrs += mp_print_int(print, val, 0, base, fmt_c, flags, fill, width); + chrs += mp_print_int(print, val, fmt_chr == 'd', base, fmt_c, flags, fill, width); break; } - case 'p': - case 'P': // don't bother to handle upcase for 'P' - // Use unsigned long int to work on both ILP32 and LP64 systems - // CIRCUITPY-CHANGE: print 0x prefix - #if SUPPORT_INT_BASE_PREFIX - chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags | PF_FLAG_SHOW_PREFIX, fill, width); - #else - print->print_strn(print->data, "0x", 2); - chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags, fill, width) + 2; - #endif - break; #if MICROPY_PY_BUILTINS_FLOAT case 'e': case 'E': @@ -573,18 +624,21 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { break; } #endif - // Because 'l' is eaten above, another 'l' means %ll. We need to support - // this length specifier for OBJ_REPR_D (64-bit NaN boxing). - // TODO Either enable this unconditionally, or provide a specific config var. - #if (MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D) || defined(_WIN64) - case 'l': { - unsigned long long int arg_value = va_arg(args, unsigned long long int); - ++fmt; - assert(*fmt == 'u' || *fmt == 'd' || !"unsupported fmt char"); - chrs += mp_print_int(print, arg_value, *fmt == 'd', 10, 'a', flags, fill, width); + + // CIRCUITPY-CHANGE: new format code to print compressed strings + case 'S': { + mp_rom_error_text_t arg = va_arg(args, mp_rom_error_text_t); + size_t len_with_nul = decompress_length(arg); + size_t len = len_with_nul - 1; + char str[len_with_nul]; + decompress(arg, str); + if (prec >= 0 && (size_t)prec < len) { + len = prec; + } + chrs += mp_print_strn(print, str, len, flags, fill, width); break; } - #endif + default: // if it's not %% then it's an unsupported format character assert(*fmt == '%' || !"unsupported fmt char"); diff --git a/py/mpprint.h b/py/mpprint.h index e883cc27047..614c61ea415 100644 --- a/py/mpprint.h +++ b/py/mpprint.h @@ -31,13 +31,13 @@ #define PF_FLAG_LEFT_ADJUST (0x001) #define PF_FLAG_SHOW_SIGN (0x002) #define PF_FLAG_SPACE_SIGN (0x004) -#define PF_FLAG_NO_TRAILZ (0x008) -#define PF_FLAG_SHOW_PREFIX (0x010) -#define PF_FLAG_SHOW_COMMA (0x020) -#define PF_FLAG_PAD_AFTER_SIGN (0x040) -#define PF_FLAG_CENTER_ADJUST (0x080) -#define PF_FLAG_ADD_PERCENT (0x100) -#define PF_FLAG_SHOW_OCTAL_LETTER (0x200) +#define PF_FLAG_SHOW_PREFIX (0x008) +#define PF_FLAG_PAD_AFTER_SIGN (0x010) +#define PF_FLAG_CENTER_ADJUST (0x020) +#define PF_FLAG_ADD_PERCENT (0x040) +#define PF_FLAG_SHOW_OCTAL_LETTER (0x080) +#define PF_FLAG_ALWAYS_DECIMAL (0x100) +#define PF_FLAG_SEP_POS (9) // must be above all the above PF_FLAGs #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES #define MP_PYTHON_PRINTER &mp_sys_stdout_print @@ -69,9 +69,9 @@ extern const mp_print_t mp_sys_stdout_print; #endif int mp_print_str(const mp_print_t *print, const char *str); -int mp_print_strn(const mp_print_t *print, const char *str, size_t len, int flags, char fill, int width); +int mp_print_strn(const mp_print_t *print, const char *str, size_t len, unsigned int flags, char fill, int width); #if MICROPY_PY_BUILTINS_FLOAT -int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec); +int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, unsigned int flags, char fill, int width, int prec); #endif int mp_printf(const mp_print_t *print, const char *fmt, ...); diff --git a/py/mpstate.h b/py/mpstate.h index e5e5f8d9fa3..7934e843f06 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -71,6 +71,12 @@ enum { // This structure contains dynamic configuration for the compiler. #if MICROPY_DYNAMIC_COMPILER typedef struct mp_dynamic_compiler_t { + // This is used to let mpy-cross pass options to the emitter chosen with + // `native_arch`. The main use case for the time being is to give the + // RV32 emitter extended information about which extensions can be + // optionally used, in order to generate code that's better suited for the + // hardware platform the code will run on. + void *backend_options; uint8_t small_int_bits; // must be <= host small_int_bits uint8_t native_arch; uint8_t nlr_buf_num_regs; diff --git a/py/mpz.c b/py/mpz.c index 7d8bc03ca86..74fd1754636 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -1541,7 +1541,8 @@ mp_int_t mpz_hash(const mpz_t *z) { mp_uint_t val = 0; mpz_dig_t *d = z->dig + z->len; - while (d-- > z->dig) { + while (d > z->dig) { + d--; val = (val << DIG_SIZE) | *d; } @@ -1556,11 +1557,12 @@ bool mpz_as_int_checked(const mpz_t *i, mp_int_t *value) { mp_uint_t val = 0; mpz_dig_t *d = i->dig + i->len; - while (d-- > i->dig) { + while (d > i->dig) { if (val > (~(MP_OBJ_WORD_MSBIT_HIGH) >> DIG_SIZE)) { // will overflow return false; } + d--; val = (val << DIG_SIZE) | *d; } @@ -1581,11 +1583,12 @@ bool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) { mp_uint_t val = 0; mpz_dig_t *d = i->dig + i->len; - while (d-- > i->dig) { + while (d > i->dig) { if (val > (~(MP_OBJ_WORD_MSBIT_HIGH) >> (DIG_SIZE - 1))) { // will overflow return false; } + d--; val = (val << DIG_SIZE) | *d; } @@ -1646,7 +1649,8 @@ mp_float_t mpz_as_float(const mpz_t *i) { mp_float_t val = 0; mpz_dig_t *d = i->dig + i->len; - while (d-- > i->dig) { + while (d > i->dig) { + d--; val = val * DIG_BASE + *d; } @@ -1676,6 +1680,8 @@ size_t mpz_as_str_inpl(const mpz_t *i, unsigned int base, const char *prefix, ch size_t ilen = i->len; + int n_comma = (base == 10) ? 3 : 4; + char *s = str; if (ilen == 0) { if (prefix) { @@ -1721,7 +1727,7 @@ size_t mpz_as_str_inpl(const mpz_t *i, unsigned int base, const char *prefix, ch break; } } - if (!done && comma && (s - last_comma) == 3) { + if (!done && comma && (s - last_comma) == n_comma) { *s++ = comma; last_comma = s; } diff --git a/py/nativeglue.h b/py/nativeglue.h index 00ed9f3f4fc..01825ac60ed 100644 --- a/py/nativeglue.h +++ b/py/nativeglue.h @@ -143,7 +143,7 @@ typedef struct _mp_fun_table_t { int (*printf_)(const mp_print_t *print, const char *fmt, ...); int (*vprintf_)(const mp_print_t *print, const char *fmt, va_list args); #if defined(__GNUC__) - NORETURN // Only certain compilers support no-return attributes in function pointer declarations + MP_NORETURN // Only certain compilers support no-return attributes in function pointer declarations #endif // CIRCUITPY-CHANGE: raise_msg_str instead of raise_msg void (*raise_msg_str)(const mp_obj_type_t *exc_type, const char *msg); diff --git a/py/nlr.c b/py/nlr.c index 7ab0c0955a2..de2a38ceff3 100644 --- a/py/nlr.c +++ b/py/nlr.c @@ -81,7 +81,7 @@ void nlr_call_jump_callbacks(nlr_buf_t *nlr) { } #if MICROPY_ENABLE_VM_ABORT -NORETURN void nlr_jump_abort(void) { +MP_NORETURN void nlr_jump_abort(void) { MP_STATE_THREAD(nlr_top) = MP_STATE_VM(nlr_abort); nlr_jump(NULL); } diff --git a/py/nlr.h b/py/nlr.h index 340627b7aa1..446e78c7ebb 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -233,18 +233,18 @@ unsigned int nlr_push(nlr_buf_t *); unsigned int nlr_push_tail(nlr_buf_t *top); void nlr_pop(void); -NORETURN void nlr_jump(void *val); +MP_NORETURN void nlr_jump(void *val); #if MICROPY_ENABLE_VM_ABORT #define nlr_set_abort(buf) MP_STATE_VM(nlr_abort) = buf #define nlr_get_abort() MP_STATE_VM(nlr_abort) -NORETURN void nlr_jump_abort(void); +MP_NORETURN void nlr_jump_abort(void); #endif // This must be implemented by a port. It's called by nlr_jump // if no nlr buf has been pushed. It must not return, but rather // should bail out with a fatal error. -NORETURN void nlr_jump_fail(void *val); +MP_NORETURN void nlr_jump_fail(void *val); // use nlr_raise instead of nlr_jump so that debugging is easier #ifndef MICROPY_DEBUG_NLR diff --git a/py/nlraarch64.c b/py/nlraarch64.c index d6d87ebc50d..3318004b5e0 100644 --- a/py/nlraarch64.c +++ b/py/nlraarch64.c @@ -56,7 +56,7 @@ __asm( #endif ); -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) MP_STATIC_ASSERT(offsetof(nlr_buf_t, regs) == 16); // asm assumes it diff --git a/py/nlrmips.c b/py/nlrmips.c index cba52b16a26..5c55db7e268 100644 --- a/py/nlrmips.c +++ b/py/nlrmips.c @@ -57,7 +57,7 @@ __asm( ".end nlr_push \n" ); -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm( "move $4, %0 \n" diff --git a/py/nlrpowerpc.c b/py/nlrpowerpc.c index 8a69fe1eeca..cf140400e68 100644 --- a/py/nlrpowerpc.c +++ b/py/nlrpowerpc.c @@ -78,7 +78,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { return 0; } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm__ volatile ( @@ -167,7 +167,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { return 0; } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm__ volatile ( diff --git a/py/nlrrv32.c b/py/nlrrv32.c index 9a12ede400d..565a8629db5 100644 --- a/py/nlrrv32.c +++ b/py/nlrrv32.c @@ -50,7 +50,7 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { ); } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "add x10, x0, %0 \n" // Load nlr_buf address. diff --git a/py/nlrrv64.c b/py/nlrrv64.c index e7ba79797b8..b7d1467b8f6 100644 --- a/py/nlrrv64.c +++ b/py/nlrrv64.c @@ -50,7 +50,7 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { ); } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "add x10, x0, %0 \n" // Load nlr_buf address. diff --git a/py/nlrthumb.c b/py/nlrthumb.c index 265052568ff..1791d8b4929 100644 --- a/py/nlrthumb.c +++ b/py/nlrthumb.c @@ -104,7 +104,7 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { #endif } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( diff --git a/py/nlrx64.c b/py/nlrx64.c index d1ad91ff7d7..51224729fc9 100644 --- a/py/nlrx64.c +++ b/py/nlrx64.c @@ -100,7 +100,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { #endif } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( diff --git a/py/nlrx86.c b/py/nlrx86.c index 085e30d2034..26bf0dc6ccb 100644 --- a/py/nlrx86.c +++ b/py/nlrx86.c @@ -78,7 +78,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { #endif } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( diff --git a/py/nlrxtensa.c b/py/nlrxtensa.c index ff7af6edeef..2d1bf35e381 100644 --- a/py/nlrxtensa.c +++ b/py/nlrxtensa.c @@ -55,7 +55,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { return 0; // needed to silence compiler warning } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( diff --git a/py/obj.c b/py/obj.c index 29ae76557f8..ba3e6a9a996 100644 --- a/py/obj.c +++ b/py/obj.c @@ -157,7 +157,7 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t if (MP_OBJ_TYPE_HAS_SLOT(type, print)) { MP_OBJ_TYPE_GET_SLOT(type, print)((mp_print_t *)print, o_in, kind); } else { - mp_printf(print, "<%q>", type->name); + mp_printf(print, "<%q>", (qstr)type->name); } } @@ -417,6 +417,36 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { return val; } +#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE +mp_uint_t mp_obj_get_uint(mp_const_obj_t arg) { + if (!mp_obj_is_exact_type(arg, &mp_type_int)) { + mp_obj_t as_int = mp_unary_op(MP_UNARY_OP_INT_MAYBE, (mp_obj_t)arg); + if (as_int == MP_OBJ_NULL) { + mp_raise_TypeError_int_conversion(arg); + } + arg = as_int; + } + return mp_obj_int_get_uint_checked(arg); +} + +long long mp_obj_get_ll(mp_const_obj_t arg) { + if (!mp_obj_is_exact_type(arg, &mp_type_int)) { + mp_obj_t as_int = mp_unary_op(MP_UNARY_OP_INT_MAYBE, (mp_obj_t)arg); + if (as_int == MP_OBJ_NULL) { + mp_raise_TypeError_int_conversion(arg); + } + arg = as_int; + } + if (mp_obj_is_small_int(arg)) { + return MP_OBJ_SMALL_INT_VALUE(arg); + } else { + long long res; + mp_obj_int_to_bytes_impl((mp_obj_t)arg, MP_ENDIANNESS_BIG, sizeof(res), (byte *)&res); + return res; + } +} +#endif + mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg) { if (mp_obj_is_int(arg)) { return mp_obj_int_get_truncated(arg); diff --git a/py/obj.h b/py/obj.h index 38db17cba44..eb7143bd43f 100644 --- a/py/obj.h +++ b/py/obj.h @@ -184,13 +184,15 @@ static inline bool mp_obj_is_small_int(mp_const_obj_t o) { #define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 1) | 1)) #if MICROPY_PY_BUILTINS_FLOAT -#define MP_OBJ_NEW_CONST_FLOAT(f) MP_ROM_PTR((mp_obj_t)((((((uint64_t)f) & ~3) | 2) + 0x80800000) & 0xffffffff)) +#include +// note: MP_OBJ_NEW_CONST_FLOAT should be a MP_ROM_PTR but that macro isn't available yet +#define MP_OBJ_NEW_CONST_FLOAT(f) ((mp_obj_t)((((((uint64_t)f) & ~3) | 2) + 0x80800000) & 0xffffffff)) #define mp_const_float_e MP_OBJ_NEW_CONST_FLOAT(0x402df854) #define mp_const_float_pi MP_OBJ_NEW_CONST_FLOAT(0x40490fdb) +#define mp_const_float_nan MP_OBJ_NEW_CONST_FLOAT(0x7fc00000) #if MICROPY_PY_MATH_CONSTANTS #define mp_const_float_tau MP_OBJ_NEW_CONST_FLOAT(0x40c90fdb) #define mp_const_float_inf MP_OBJ_NEW_CONST_FLOAT(0x7f800000) -#define mp_const_float_nan MP_OBJ_NEW_CONST_FLOAT(0xffc00000) #endif static inline bool mp_obj_is_float(mp_const_obj_t o) { @@ -204,9 +206,17 @@ static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { mp_float_t f; mp_uint_t u; } num = {.u = ((mp_uint_t)o - 0x80800000u) & ~3u}; + // Rather than always truncating toward zero, which creates a strong + // bias, copy the two previous bits to fill in the two missing bits. + // This appears to be a pretty good heuristic. + num.u |= (num.u >> 2) & 3u; return num.f; } static inline mp_obj_t mp_obj_new_float(mp_float_t f) { + if (isnan(f)) { + // prevent creation of bad nanboxed pointers via array.array or struct + return mp_const_float_nan; + } union { mp_float_t f; mp_uint_t u; @@ -257,8 +267,10 @@ static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) { #error MICROPY_OBJ_REPR_D requires MICROPY_FLOAT_IMPL_DOUBLE #endif +#include #define mp_const_float_e {((mp_obj_t)((uint64_t)0x4005bf0a8b145769 + 0x8004000000000000))} #define mp_const_float_pi {((mp_obj_t)((uint64_t)0x400921fb54442d18 + 0x8004000000000000))} +#define mp_const_float_nan {((mp_obj_t)((uint64_t)0x7ff8000000000000 + 0x8004000000000000))} #if MICROPY_PY_MATH_CONSTANTS #define mp_const_float_tau {((mp_obj_t)((uint64_t)0x401921fb54442d18 + 0x8004000000000000))} #define mp_const_float_inf {((mp_obj_t)((uint64_t)0x7ff0000000000000 + 0x8004000000000000))} @@ -276,6 +288,13 @@ static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { return num.f; } static inline mp_obj_t mp_obj_new_float(mp_float_t f) { + if (isnan(f)) { + // prevent creation of bad nanboxed pointers via array.array or struct + struct { + uint64_t r; + } num = mp_const_float_nan; + return num.r; + } union { mp_float_t f; uint64_t r; @@ -371,25 +390,25 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; #define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ - {{&mp_type_fun_builtin_0}, .fun._0 = fun_name} + {.base = {.type = &mp_type_fun_builtin_0}, .fun = {._0 = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ - {{&mp_type_fun_builtin_1}, .fun._1 = fun_name} + {.base = {.type = &mp_type_fun_builtin_1}, .fun = {._1 = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ - {{&mp_type_fun_builtin_2}, .fun._2 = fun_name} + {.base = {.type = &mp_type_fun_builtin_2}, .fun = {._2 = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ - {{&mp_type_fun_builtin_3}, .fun._3 = fun_name} + {.base = {.type = &mp_type_fun_builtin_3}, .fun = {._3 = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) \ const mp_obj_fun_builtin_var_t obj_name = \ - {{&mp_type_fun_builtin_var}, MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, false), .fun.var = fun_name} + {.base = {.type = &mp_type_fun_builtin_var}, .sig = MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, false), .fun = {.var = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) \ const mp_obj_fun_builtin_var_t obj_name = \ - {{&mp_type_fun_builtin_var}, MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, false), .fun.var = fun_name} + {.base = {.type = &mp_type_fun_builtin_var}, .sig = MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, false), .fun = {.var = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) \ const mp_obj_fun_builtin_var_t obj_name = \ - {{&mp_type_fun_builtin_var}, MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, true), .fun.kw = fun_name} + {.base = {.type = &mp_type_fun_builtin_var}, .sig = MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, true), .fun = {.kw = fun_name}} // CIRCUITPY-CHANGE #define MP_DEFINE_CONST_PROP_GET(obj_name, fun_name) \ @@ -516,9 +535,7 @@ static inline bool mp_map_slot_is_filled(const mp_map_t *map, size_t pos) { void mp_map_init(mp_map_t *map, size_t n); void mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table); -mp_map_t *mp_map_new(size_t n); void mp_map_deinit(mp_map_t *map); -void mp_map_free(mp_map_t *map); mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind); void mp_map_clear(mp_map_t *map); void mp_map_dump(mp_map_t *map); @@ -555,6 +572,10 @@ typedef mp_obj_t (*mp_fun_var_t)(size_t n, const mp_obj_t *); typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); // Flags for type behaviour (mp_obj_type_t.flags) +// If MP_TYPE_FLAG_IS_SUBCLASSED is set, then subclasses of this class have been created. +// Mutations to this class that would require updating all subclasses must be rejected. +// If MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS is set, then attribute lookups involving this +// class need to additionally check for special accessor methods, such as from descriptors. // If MP_TYPE_FLAG_EQ_NOT_REFLEXIVE is clear then __eq__ is reflexive (A==A returns True). // If MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE is clear then the type can't be equal to an // instance of any different class that also clears this flag. If this flag is set @@ -572,6 +593,8 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); // If MP_TYPE_FLAG_ITER_IS_STREAM is set then the type implicitly gets a "return self" // getiter, and mp_stream_unbuffered_iter for iternext. // If MP_TYPE_FLAG_INSTANCE_TYPE is set then this is an instance type (i.e. defined in Python). +// If MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE is set then the "subscr" slot allows a stack +// allocated slice to be passed in (no references to it will be retained after the call). #define MP_TYPE_FLAG_NONE (0x0000) #define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001) #define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) @@ -585,8 +608,9 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); #define MP_TYPE_FLAG_ITER_IS_CUSTOM (0x0100) #define MP_TYPE_FLAG_ITER_IS_STREAM (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM) #define MP_TYPE_FLAG_INSTANCE_TYPE (0x0200) +#define MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE (0x0400) // CIRCUITPY-CHANGE: check for valid types in json dumps -#define MP_TYPE_FLAG_PRINT_JSON (0x0400) +#define MP_TYPE_FLAG_PRINT_JSON (0x0800) typedef enum { PRINT_STR = 0, @@ -827,7 +851,7 @@ typedef struct _mp_obj_full_type_t { #define MP_DEFINE_CONST_OBJ_TYPE_NARGS(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, N, ...) MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N // This macros is used to define a object type in ROM. -// Invoke as MP_DEFINE_CONST_OBJ_TYPE(_typename, _name, _flags, _make_new [, slot, func]*) +// Invoke as MP_DEFINE_CONST_OBJ_TYPE(_typename, _name, _flags, [, slot, func]*) // It uses the number of arguments to select which MP_DEFINE_CONST_OBJ_TYPE_* // macro to use based on the number of arguments. It works by shifting the // numeric values 12, 11, ... 0 by the number of arguments, such that the @@ -847,7 +871,7 @@ extern const mp_obj_type_t mp_type_bytearray; extern const mp_obj_type_t mp_type_memoryview; extern const mp_obj_type_t mp_type_float; extern const mp_obj_type_t mp_type_complex; -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: add traceback support extern const mp_obj_type_t mp_type_traceback; extern const mp_obj_type_t mp_type_tuple; extern const mp_obj_type_t mp_type_list; @@ -909,7 +933,7 @@ extern const mp_obj_type_t mp_type_ImportError; extern const mp_obj_type_t mp_type_IndentationError; extern const mp_obj_type_t mp_type_IndexError; extern const mp_obj_type_t mp_type_KeyboardInterrupt; -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: add ReloadException extern const mp_obj_type_t mp_type_ReloadException; extern const mp_obj_type_t mp_type_KeyError; extern const mp_obj_type_t mp_type_LookupError; @@ -917,9 +941,9 @@ extern const mp_obj_type_t mp_type_MemoryError; extern const mp_obj_type_t mp_type_NameError; extern const mp_obj_type_t mp_type_NotImplementedError; extern const mp_obj_type_t mp_type_OSError; -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: add ConnectionError extern const mp_obj_type_t mp_type_ConnectionError; -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: add BrokenPipeError extern const mp_obj_type_t mp_type_BrokenPipeError; extern const mp_obj_type_t mp_type_OverflowError; extern const mp_obj_type_t mp_type_RuntimeError; @@ -927,6 +951,7 @@ extern const mp_obj_type_t mp_type_StopAsyncIteration; extern const mp_obj_type_t mp_type_StopIteration; extern const mp_obj_type_t mp_type_SyntaxError; extern const mp_obj_type_t mp_type_SystemExit; +// CIRCUITPY-CHANGE: add TimeoutError extern const mp_obj_type_t mp_type_TimeoutError; extern const mp_obj_type_t mp_type_TypeError; extern const mp_obj_type_t mp_type_UnicodeError; @@ -991,11 +1016,11 @@ void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); // Object allocation macros for allocating objects that have a finaliser. #if MICROPY_ENABLE_FINALISER #define mp_obj_malloc_with_finaliser(struct_type, obj_type) ((struct_type *)mp_obj_malloc_with_finaliser_helper(sizeof(struct_type), obj_type)) -#define mp_obj_malloc_var_with_finaliser(struct_type, var_type, var_num, obj_type) ((struct_type *)mp_obj_malloc_with_finaliser_helper(sizeof(struct_type) + sizeof(var_type) * (var_num), obj_type)) +#define mp_obj_malloc_var_with_finaliser(struct_type, var_field, var_type, var_num, obj_type) ((struct_type *)mp_obj_malloc_with_finaliser_helper(offsetof(struct_type, var_field) + sizeof(var_type) * (var_num), obj_type)) void *mp_obj_malloc_with_finaliser_helper(size_t num_bytes, const mp_obj_type_t *type); #else #define mp_obj_malloc_with_finaliser(struct_type, obj_type) mp_obj_malloc(struct_type, obj_type) -#define mp_obj_malloc_var_with_finaliser(struct_type, var_type, var_num, obj_type) mp_obj_malloc_var(struct_type, var_type, var_num, obj_type) +#define mp_obj_malloc_var_with_finaliser(struct_type, var_field, var_type, var_num, obj_type) mp_obj_malloc_var(struct_type, var_field, var_type, var_num, obj_type) #endif // These macros are derived from more primitive ones and are used to @@ -1032,7 +1057,6 @@ bool mp_obj_is_dict_or_ordereddict(mp_obj_t o); // type check is done on iter method to allow tuple, namedtuple, attrtuple #define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), iter) == mp_obj_tuple_getiter) -mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); static inline mp_obj_t mp_obj_new_bool(mp_int_t x) { return x ? mp_const_true : mp_const_false; } @@ -1053,10 +1077,10 @@ mp_obj_t mp_obj_new_str_from_utf8_vstr(vstr_t *vstr); // input data must be vali #endif mp_obj_t mp_obj_new_bytes_from_vstr(vstr_t *vstr); mp_obj_t mp_obj_new_bytes(const byte *data, size_t len); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine mp_obj_t mp_obj_new_bytes_of_zeros(size_t len); mp_obj_t mp_obj_new_bytearray(size_t n, const void *items); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine mp_obj_t mp_obj_new_bytearray_of_zeros(size_t n); mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items); #if MICROPY_PY_BUILTINS_FLOAT @@ -1092,7 +1116,7 @@ mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items); const mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in); const char *mp_obj_get_type_str(mp_const_obj_t o_in); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine #define mp_obj_get_type_qstr(o_in) (mp_obj_get_type((o_in))->name) bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects mp_obj_t mp_obj_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type); @@ -1100,7 +1124,7 @@ mp_obj_t mp_obj_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); void mp_obj_print(mp_obj_t o, mp_print_kind_t kind); void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine void mp_obj_print_exception_with_limit(const mp_print_t *print, mp_obj_t exc, mp_int_t limit); bool mp_obj_is_true(mp_obj_t arg); @@ -1114,6 +1138,8 @@ static inline bool mp_obj_is_integer(mp_const_obj_t o) { } mp_int_t mp_obj_get_int(mp_const_obj_t arg); +mp_uint_t mp_obj_get_uint(mp_const_obj_t arg); +long long mp_obj_get_ll(mp_const_obj_t arg); mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg); bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value); #if MICROPY_PY_BUILTINS_FLOAT @@ -1163,7 +1189,7 @@ bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type); void mp_obj_exception_clear_traceback(mp_obj_t self_in); void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block); void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine mp_obj_t mp_obj_exception_get_traceback_obj(mp_obj_t self_in); mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in); mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args); @@ -1240,7 +1266,7 @@ void mp_obj_tuple_del(mp_obj_t self_in); mp_int_t mp_obj_tuple_hash(mp_obj_t self_in); // list -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: public routine mp_obj_t mp_obj_list_clear(mp_obj_t self_in); mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg); mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value); @@ -1336,7 +1362,7 @@ typedef struct _mp_rom_obj_static_class_method_t { } mp_rom_obj_static_class_method_t; // property -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: extra args const mp_obj_t *mp_obj_property_get(mp_obj_t self_in, size_t *n_proxy); // sequence helpers diff --git a/py/objarray.c b/py/objarray.c index 0be1947167d..1e259a20ac8 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -126,6 +126,19 @@ static mp_obj_array_t *array_new(char typecode, size_t n) { #endif #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY +static void array_extend_impl(mp_obj_array_t *array, mp_obj_t arg, char typecode, size_t len) { + mp_obj_t iterable = mp_getiter(arg, NULL); + mp_obj_t item; + size_t i = 0; + while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (len == 0) { + array_append(MP_OBJ_FROM_PTR(array), item); + } else { + mp_binary_set_val_array(typecode, array->items, i++, item); + } + } +} + static mp_obj_t array_construct(char typecode, mp_obj_t initializer) { // bytearrays can be raw-initialised from anything with the buffer protocol // other arrays can only be raw-initialised from bytes and bytearray objects @@ -158,18 +171,7 @@ static mp_obj_t array_construct(char typecode, mp_obj_t initializer) { } mp_obj_array_t *array = array_new(typecode, len); - - mp_obj_t iterable = mp_getiter(initializer, NULL); - mp_obj_t item; - size_t i = 0; - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - if (len == 0) { - array_append(MP_OBJ_FROM_PTR(array), item); - } else { - mp_binary_set_val_array(typecode, array->items, i++, item); - } - } - + array_extend_impl(array, initializer, typecode, len); return MP_OBJ_FROM_PTR(array); } #endif @@ -298,7 +300,7 @@ static void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); dest[0] = MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL)); } - // CIRCUITPY-CHANGE: prevent warning + // CIRCUITPY-CHANGE: add MICROPY_CPYTHON_COMPAT #if MICROPY_PY_BUILTINS_BYTES_HEX || MICROPY_CPYTHON_COMPAT else { // Need to forward to locals dict. @@ -493,39 +495,42 @@ static mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { // allow to extend by anything that has the buffer protocol (extension to CPython) mp_buffer_info_t arg_bufinfo; - // CIRCUITPY-CHANGE: allow appending an iterable - if (mp_get_buffer(arg_in, &arg_bufinfo, MP_BUFFER_READ)) { - size_t sz = mp_binary_get_size('@', self->typecode, NULL); - - // convert byte count to element count - size_t len = arg_bufinfo.len / sz; - - // make sure we have enough room to extend - // TODO: alloc policy; at the moment we go conservative - if (self->free < len) { - self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz); - self->free = 0; - } else { - self->free -= len; - } + if (!mp_get_buffer(arg_in, &arg_bufinfo, MP_BUFFER_READ)) { + array_extend_impl(self, arg_in, 0, 0); + return mp_const_none; + } - // extend - mp_seq_copy((byte *)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte); - self->len += len; - } else { - // Otherwise argument must be an iterable of items to append - mp_obj_t iterable = mp_getiter(arg_in, NULL); - mp_obj_t item; - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - array_append(self_in, item); + size_t sz = mp_binary_get_size('@', self->typecode, NULL); + + // convert byte count to element count + size_t len = arg_bufinfo.len / sz; + + // make sure we have enough room to extend + // TODO: alloc policy; at the moment we go conservative + if (self->free < len) { + self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz); + self->free = 0; + + if (self_in == arg_in) { + // Get arg_bufinfo again in case self->items has moved + // + // (Note not possible to handle case that arg_in is a memoryview into self) + mp_get_buffer_raise(arg_in, &arg_bufinfo, MP_BUFFER_READ); } + } else { + self->free -= len; } + + // extend + mp_seq_copy((byte *)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte); + self->len += len; + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(mp_obj_array_extend_obj, array_extend); #endif -// CIRCUITPY-CHANGE: buffer_finder used belo +// CIRCUITPY-CHANGE: buffer_finder used below #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_CPYTHON_COMPAT static mp_obj_t buffer_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) { mp_check_self(mp_obj_is_type(args[0], &mp_type_bytearray)); @@ -564,7 +569,6 @@ static mp_obj_t buffer_finder(size_t n_args, const mp_obj_t *args, int direction } return MP_OBJ_NEW_SMALL_INT(p - (const byte *)haystack_bufinfo.buf); } - // CIRCUITPY-CHANGE: provides find, rfind, index static mp_obj_t buffer_find(size_t n_args, const mp_obj_t *args) { return buffer_finder(n_args, args, 1, false); @@ -667,7 +671,7 @@ static mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value mp_seq_replace_slice_no_grow(dest_items, o->len, slice.start, slice.stop, src_items + src_offs, src_len, item_sz); // CIRCUITPY-CHANGE - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES // Clear "freed" elements at the end of list // TODO: This is actually only needed for typecode=='O' mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz); @@ -803,7 +807,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_DEFINE_CONST_OBJ_TYPE( mp_type_bytearray, MP_QSTR_bytearray, - MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE, make_new, bytearray_make_new, print, array_print, iter, array_iterator_new, @@ -842,7 +846,7 @@ MP_DEFINE_CONST_DICT(memoryview_locals_dict, memoryview_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_memoryview, MP_QSTR_memoryview, - MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE, make_new, memoryview_make_new, iter, array_iterator_new, unary_op, array_unary_op, diff --git a/py/objboundmeth.c b/py/objboundmeth.c index e3503ff154a..6df67f7bf9e 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -102,7 +102,11 @@ static mp_obj_t bound_meth_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_ } mp_obj_bound_meth_t *lhs = MP_OBJ_TO_PTR(lhs_in); mp_obj_bound_meth_t *rhs = MP_OBJ_TO_PTR(rhs_in); + #if MICROPY_PY_BOUND_METHOD_FULL_EQUALITY_CHECK + return mp_obj_new_bool(mp_obj_equal(lhs->self, rhs->self) && mp_obj_equal(lhs->meth, rhs->meth)); + #else return mp_obj_new_bool(lhs->self == rhs->self && lhs->meth == rhs->meth); + #endif } #if MICROPY_PY_FUNCTION_ATTRS diff --git a/py/objcell.c b/py/objcell.c index 95966c7917c..5c030c7405a 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -30,7 +30,7 @@ static void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_cell_t *o = MP_OBJ_TO_PTR(o_in); - mp_printf(print, "obj); + mp_printf(print, "obj); if (o->obj == MP_OBJ_NULL) { mp_print_str(print, "(nil)"); } else { diff --git a/py/objcode.c b/py/objcode.c index 9b98a696798..09904f10f36 100644 --- a/py/objcode.c +++ b/py/objcode.c @@ -69,6 +69,7 @@ static mp_obj_tuple_t *code_consts(const mp_module_context_t *context, const mp_ return consts; } +#if !MICROPY_PREVIEW_VERSION_2 static mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) { // const mp_bytecode_prelude_t *prelude = &rc->prelude; uint start = 0; @@ -106,6 +107,68 @@ static mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) { m_del(byte, buffer, buffer_size); return o; } +#endif + +static mp_obj_t code_colines_iter(mp_obj_t); +static mp_obj_t code_colines_next(mp_obj_t); +typedef struct _mp_obj_colines_iter_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + const mp_raw_code_t *rc; + mp_uint_t bc; + mp_uint_t source_line; + const byte *ci; +} mp_obj_colines_iter_t; + +static mp_obj_t code_colines_iter(mp_obj_t self_in) { + mp_obj_code_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_colines_iter_t *iter = mp_obj_malloc(mp_obj_colines_iter_t, &mp_type_polymorph_iter); + iter->iternext = code_colines_next; + iter->rc = self->rc; + iter->bc = 0; + iter->source_line = 1; + iter->ci = self->rc->prelude.line_info; + return MP_OBJ_FROM_PTR(iter); +} +static MP_DEFINE_CONST_FUN_OBJ_1(code_colines_obj, code_colines_iter); + +static mp_obj_t code_colines_next(mp_obj_t iter_in) { + mp_obj_colines_iter_t *iter = MP_OBJ_TO_PTR(iter_in); + const byte *ci_end = iter->rc->prelude.line_info_top; + + mp_uint_t start = iter->bc; + mp_uint_t line_no = iter->source_line; + bool another = true; + + while (another && iter->ci < ci_end) { + another = false; + mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo(&iter->ci); + iter->bc += decoded.bc_increment; + iter->source_line += decoded.line_increment; + + if (decoded.bc_increment == 0) { + line_no = iter->source_line; + another = true; + } else if (decoded.line_increment == 0) { + another = true; + } + } + + if (another) { + mp_uint_t prelude_size = (iter->rc->prelude.opcodes - (const byte *)iter->rc->fun_data); + mp_uint_t bc_end = iter->rc->fun_data_len - prelude_size; + if (iter->bc >= bc_end) { + return MP_OBJ_STOP_ITERATION; + } else { + iter->bc = bc_end; + } + } + + mp_uint_t end = iter->bc; + mp_obj_t next[3] = {MP_OBJ_NEW_SMALL_INT(start), MP_OBJ_NEW_SMALL_INT(end), MP_OBJ_NEW_SMALL_INT(line_no)}; + + return mp_obj_new_tuple(MP_ARRAY_SIZE(next), next); +} static void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { @@ -137,12 +200,18 @@ static void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { case MP_QSTR_co_names: dest[0] = MP_OBJ_FROM_PTR(o->dict_locals); break; + #if !MICROPY_PREVIEW_VERSION_2 case MP_QSTR_co_lnotab: if (!o->lnotab) { o->lnotab = raw_code_lnotab(rc); } dest[0] = o->lnotab; break; + #endif + case MP_QSTR_co_lines: + dest[0] = MP_OBJ_FROM_PTR(&code_colines_obj); + dest[1] = self_in; + break; } } @@ -168,7 +237,9 @@ mp_obj_t mp_obj_new_code(const mp_module_context_t *context, const mp_raw_code_t o->context = context; o->rc = rc; o->dict_locals = mp_locals_get(); // this is a wrong! how to do this properly? + #if !MICROPY_PREVIEW_VERSION_2 o->lnotab = MP_OBJ_NULL; + #endif return MP_OBJ_FROM_PTR(o); } diff --git a/py/objcode.h b/py/objcode.h index 8db9a34b6e1..7be15e23f52 100644 --- a/py/objcode.h +++ b/py/objcode.h @@ -72,15 +72,16 @@ static inline const void *mp_code_get_proto_fun(mp_obj_code_t *self) { #include "py/emitglue.h" -#define MP_CODE_QSTR_MAP(context, idx) (context->constants.qstr_table[idx]) +#define MP_CODE_QSTR_MAP(context, idx) ((qstr)(context->constants.qstr_table[idx])) typedef struct _mp_obj_code_t { - // TODO this was 4 words mp_obj_base_t base; const mp_module_context_t *context; const mp_raw_code_t *rc; mp_obj_dict_t *dict_locals; + #if !MICROPY_PREVIEW_VERSION_2 mp_obj_t lnotab; + #endif } mp_obj_code_t; mp_obj_t mp_obj_new_code(const mp_module_context_t *context, const mp_raw_code_t *rc, bool result_required); diff --git a/py/objcomplex.c b/py/objcomplex.c index d7287efdc13..88f4444f09e 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -49,29 +49,18 @@ typedef struct _mp_obj_complex_t { static void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in); - #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT - char buf[16]; - #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C - const int precision = 6; - #else - const int precision = 7; - #endif - #else - char buf[32]; - const int precision = 16; - #endif - if (o->real == 0) { - mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\0'); - mp_printf(print, "%sj", buf); + const char *suffix; + int flags = 0; + if (o->real != 0) { + mp_print_str(print, "("); + mp_print_float(print, o->real, 'g', 0, '\0', -1, MP_FLOAT_REPR_PREC); + flags = PF_FLAG_SHOW_SIGN; + suffix = "j)"; } else { - mp_format_float(o->real, buf, sizeof(buf), 'g', precision, '\0'); - mp_printf(print, "(%s", buf); - if (o->imag >= 0 || isnan(o->imag)) { - mp_print_str(print, "+"); - } - mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\0'); - mp_printf(print, "%sj)", buf); + suffix = "j"; } + mp_print_float(print, o->imag, 'g', flags, '\0', -1, MP_FLOAT_REPR_PREC); + mp_print_str(print, suffix); } static mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { diff --git a/py/objdict.c b/py/objdict.c index 79a606f0970..d459d1ae486 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -101,7 +101,7 @@ static void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ #endif } if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) { - mp_printf(print, "%q(", self->base.type->name); + mp_printf(print, "%q(", (qstr)self->base.type->name); } mp_print_str(print, "{"); size_t cur = 0; @@ -616,7 +616,8 @@ static mp_obj_t dict_view_unary_op(mp_unary_op_t op, mp_obj_t o_in) { if (op == MP_UNARY_OP_HASH && o->kind == MP_DICT_VIEW_VALUES) { return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in); } - return MP_OBJ_NULL; + // delegate all other ops to dict unary op handler + return dict_unary_op(op, o->dict); } static mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { diff --git a/py/objfloat.c b/py/objfloat.c index 3610c2b8586..ecc0f61a6ab 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -34,6 +34,11 @@ #if MICROPY_PY_BUILTINS_FLOAT +// Workaround a bug in Windows SDK version 10.0.26100.0, where NAN is no longer constant. +#if defined(_MSC_VER) && !defined(_UCRT_NOISY_NAN) +#define _UCRT_NOISY_NAN +#endif + #include #include "py/formatfloat.h" @@ -51,13 +56,6 @@ #define M_PI (3.14159265358979323846) #endif -// Workaround a bug in recent MSVC where NAN is no longer constant. -// (By redefining back to the previous MSVC definition of NAN) -#if defined(_MSC_VER) && _MSC_VER >= 1942 -#undef NAN -#define NAN (-(float)(((float)(1e+300 * 1e+300)) * 0.0F)) -#endif - typedef struct _mp_obj_float_t { mp_obj_base_t base; mp_float_t value; @@ -116,23 +114,7 @@ mp_int_t mp_float_hash(mp_float_t src) { static void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_float_t o_val = mp_obj_float_get(o_in); - #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT - char buf[16]; - #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C - const int precision = 6; - #else - const int precision = 7; - #endif - #else - char buf[32]; - const int precision = 16; - #endif - mp_format_float(o_val, buf, sizeof(buf), 'g', precision, '\0'); - mp_print_str(print, buf); - if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) { - // Python floats always have decimal point (unless inf or nan) - mp_print_str(print, ".0"); - } + mp_print_float(print, o_val, 'g', PF_FLAG_ALWAYS_DECIMAL, '\0', -1, MP_FLOAT_REPR_PREC); } static mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { @@ -324,6 +306,10 @@ mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t lhs_val = MICROPY_FLOAT_CONST(1.0); break; } + if (isnan(rhs_val)) { + lhs_val = rhs_val; + break; + } #endif lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val); break; diff --git a/py/objfun.c b/py/objfun.c index e6a923d59e8..34565cf6336 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -184,7 +184,8 @@ static mp_obj_t fun_bc_make_new(const mp_obj_type_t *type, size_t n_args, size_t static void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_fun_bc_t *o = MP_OBJ_TO_PTR(o_in); - mp_printf(print, "", mp_obj_fun_get_name(o_in), o); + // CIRCUITPY-CHANGE: %p already prints "0x", so don't include it explicitly. + mp_printf(print, "", mp_obj_fun_get_name(o_in), o); } #endif diff --git a/py/objint.c b/py/objint.c index b12f09c9d38..cabbd7b8f0e 100644 --- a/py/objint.c +++ b/py/objint.c @@ -117,9 +117,15 @@ static mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) { } // 8 * sizeof(uintptr_t) counts the number of bits for a small int // TODO provide a way to configure this properly + #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B + if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 4) << MP_FLOAT_EXP_SHIFT_I32)) { + return MP_FP_CLASS_FIT_SMALLINT; + } + #else if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 3) << MP_FLOAT_EXP_SHIFT_I32)) { return MP_FP_CLASS_FIT_SMALLINT; } + #endif #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG if (e <= (((sizeof(long long) * MP_BITS_PER_BYTE) + MP_FLOAT_EXP_BIAS - 2) << MP_FLOAT_EXP_SHIFT_I32)) { return MP_FP_CLASS_FIT_LONGINT; @@ -211,7 +217,7 @@ static const uint8_t log_base2_floor[] = { size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma) { assert(2 <= base && base <= 16); size_t num_digits = num_bits / log_base2_floor[base - 1] + 1; - size_t num_commas = comma ? num_digits / 3 : 0; + size_t num_commas = comma ? (base == 10 ? num_digits / 3 : num_digits / 4): 0; size_t prefix_len = prefix ? strlen(prefix) : 0; return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte } @@ -249,10 +255,11 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co char sign = '\0'; if (num < 0) { - num = -num; + num = -(fmt_uint_t)num; sign = '-'; } + int n_comma = (base == 10) ? 3 : 4; size_t needed_size = mp_int_format_size(sizeof(fmt_int_t) * 8, base, prefix, comma); if (needed_size > *buf_size) { *buf = m_new(char, needed_size); @@ -277,7 +284,7 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co c += '0'; } *(--b) = c; - if (comma && num != 0 && b > str && (last_comma - b) == 3) { + if (comma && num != 0 && b > str && (last_comma - b) == n_comma) { *(--b) = comma; last_comma = b; } diff --git a/py/objint_longlong.c b/py/objint_longlong.c index 0fad693c7ad..f24aa0cc186 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -43,6 +43,10 @@ const mp_obj_int_t mp_sys_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX}; #endif +static void raise_long_long_overflow(void) { + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("result overflows long long storage")); +} + // CIRCUITPY-CHANGE: bit_length mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_int)); @@ -132,7 +136,6 @@ mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { // small int if the value fits without truncation case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_int_t)o->val); - case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: @@ -159,6 +162,8 @@ mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { long long lhs_val; long long rhs_val; + bool overflow = false; + long long result; if (mp_obj_is_small_int(lhs_in)) { lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in); @@ -171,21 +176,41 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs_in); } else if (mp_obj_is_exact_type(rhs_in, &mp_type_int)) { rhs_val = ((mp_obj_int_t *)rhs_in)->val; + #if MICROPY_PY_BUILTINS_FLOAT + } else if (mp_obj_is_float(rhs_in)) { + return mp_obj_float_binary_op(op, (mp_float_t)lhs_val, rhs_in); + #endif + #if MICROPY_PY_BUILTINS_COMPLEX + } else if (mp_obj_is_type(rhs_in, &mp_type_complex)) { + return mp_obj_complex_binary_op(op, (mp_float_t)lhs_val, 0, rhs_in); + #endif } else { // delegate to generic function to check for extra cases return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in); } + #if MICROPY_PY_BUILTINS_FLOAT + if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) { + if (rhs_val == 0) { + goto zero_division; + } + return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val); + } + #endif + switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: - return mp_obj_new_int_from_ll(lhs_val + rhs_val); + overflow = mp_add_ll_overflow(lhs_val, rhs_val, &result); + break; case MP_BINARY_OP_SUBTRACT: case MP_BINARY_OP_INPLACE_SUBTRACT: - return mp_obj_new_int_from_ll(lhs_val - rhs_val); + overflow = mp_sub_ll_overflow(lhs_val, rhs_val, &result); + break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: - return mp_obj_new_int_from_ll(lhs_val * rhs_val); + overflow = mp_mul_ll_overflow(lhs_val, rhs_val, &result); + break; case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: if (rhs_val == 0) { @@ -211,9 +236,21 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i case MP_BINARY_OP_LSHIFT: case MP_BINARY_OP_INPLACE_LSHIFT: - return mp_obj_new_int_from_ll(lhs_val << (int)rhs_val); + if (rhs_val < 0) { + // negative shift not allowed + mp_raise_ValueError(MP_ERROR_TEXT("negative shift count")); + } + overflow = rhs_val >= (sizeof(long long) * MP_BITS_PER_BYTE) + || lhs_val > (LLONG_MAX >> rhs_val) + || lhs_val < (LLONG_MIN >> rhs_val); + result = (unsigned long long)lhs_val << rhs_val; + break; case MP_BINARY_OP_RSHIFT: case MP_BINARY_OP_INPLACE_RSHIFT: + if ((int)rhs_val < 0) { + // negative shift not allowed + mp_raise_ValueError(MP_ERROR_TEXT("negative shift count")); + } return mp_obj_new_int_from_ll(lhs_val >> (int)rhs_val); case MP_BINARY_OP_POWER: @@ -225,18 +262,18 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mp_raise_ValueError(MP_ERROR_TEXT("negative power with no float support")); #endif } - long long ans = 1; - while (rhs_val > 0) { + result = 1; + while (rhs_val > 0 && !overflow) { if (rhs_val & 1) { - ans *= lhs_val; + overflow = mp_mul_ll_overflow(result, lhs_val, &result); } - if (rhs_val == 1) { + if (rhs_val == 1 || overflow) { break; } rhs_val /= 2; - lhs_val *= lhs_val; + overflow = mp_mul_ll_overflow(lhs_val, lhs_val, &lhs_val); } - return mp_obj_new_int_from_ll(ans); + break; } case MP_BINARY_OP_LESS: @@ -254,8 +291,14 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return MP_OBJ_NULL; // op not supported } + if (overflow) { + raise_long_long_overflow(); + } + + return mp_obj_new_int_from_ll(result); + zero_division: - mp_raise_ZeroDivisionError(); + mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("divide by zero")); } mp_obj_t mp_obj_new_int(mp_int_t value) { @@ -277,22 +320,12 @@ mp_obj_t mp_obj_new_int_from_ll(long long val) { } mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) { - // TODO raise an exception if the unsigned long long won't fit if (val >> (sizeof(unsigned long long) * 8 - 1) != 0) { - mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ulonglong too large")); + raise_long_long_overflow(); } return mp_obj_new_int_from_ll(val); } -mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) { - // TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated - // TODO check overflow - char *endptr; - mp_obj_t result = mp_obj_new_int_from_ll(strtoll(*str, &endptr, base)); - *str = endptr; - return result; -} - mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) { if (mp_obj_is_small_int(self_in)) { return MP_OBJ_SMALL_INT_VALUE(self_in); @@ -303,8 +336,33 @@ mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) { } mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { - // TODO: Check overflow - return mp_obj_int_get_truncated(self_in); + if (mp_obj_is_small_int(self_in)) { + return MP_OBJ_SMALL_INT_VALUE(self_in); + } else { + const mp_obj_int_t *self = self_in; + long long value = self->val; + mp_int_t truncated = (mp_int_t)value; + if ((long long)truncated == value) { + return truncated; + } + } + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("overflow converting long int to machine word")); +} + +mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) { + if (mp_obj_is_small_int(self_in)) { + if (MP_OBJ_SMALL_INT_VALUE(self_in) >= 0) { + return MP_OBJ_SMALL_INT_VALUE(self_in); + } + } else { + const mp_obj_int_t *self = self_in; + long long value = self->val; + mp_uint_t truncated = (mp_uint_t)value; + if (value >= 0 && (long long)truncated == value) { + return truncated; + } + } + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("overflow converting long int to machine word")); } #if MICROPY_PY_BUILTINS_FLOAT diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 111f53009fb..1bede811a4a 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -364,9 +364,10 @@ static mpz_t *mp_mpz_for_int(mp_obj_t arg, mpz_t *temp) { mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus) { if (!mp_obj_is_int(base) || !mp_obj_is_int(exponent) || !mp_obj_is_int(modulus)) { mp_raise_TypeError(MP_ERROR_TEXT("pow() with 3 arguments requires integers")); + } else if (modulus == MP_OBJ_NEW_SMALL_INT(0)) { + mp_raise_ValueError(MP_ERROR_TEXT("divide by zero")); } else { - mp_obj_t result = mp_obj_new_int_from_ull(0); // Use the _from_ull version as this forces an mpz int - mp_obj_int_t *res_p = (mp_obj_int_t *)MP_OBJ_TO_PTR(result); + mp_obj_int_t *res_p = mp_obj_int_new_mpz(); mpz_t l_temp, r_temp, m_temp; mpz_t *lhs = mp_mpz_for_int(base, &l_temp); @@ -389,7 +390,7 @@ mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus) { if (mod == &m_temp) { mpz_deinit(mod); } - return result; + return MP_OBJ_FROM_PTR(res_p); } } #endif diff --git a/py/objlist.c b/py/objlist.c index 3137e9fa534..a29fc51b104 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -118,7 +118,7 @@ static mp_obj_t list_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } static mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: allow subclassing mp_obj_list_t *o = native_list(lhs); switch (op) { case MP_BINARY_OP_ADD: { @@ -142,7 +142,7 @@ static mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { if (n < 0) { n = 0; } - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: overflow check (PR#1279) size_t new_len = mp_seq_multiply_len(o->len, n); mp_obj_list_t *s = list_new(new_len); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); @@ -171,76 +171,66 @@ static mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { } static mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { - // CIRCUITPY-CHANGE - mp_obj_list_t *self = native_list(self_in); - if (value == MP_OBJ_NULL) { - // delete - #if MICROPY_PY_BUILTINS_SLICE - if (mp_obj_is_type(index, &mp_type_slice)) { - mp_bound_slice_t slice; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { - mp_raise_NotImplementedError(NULL); + #if MICROPY_PY_BUILTINS_SLICE + if (mp_obj_is_type(index, &mp_type_slice)) { + // CIRCUITPY-CHANGE: handle subclassing + mp_obj_list_t *self = native_list(self_in); + mp_bound_slice_t slice; + bool fast = mp_seq_get_fast_slice_indexes(self->len, index, &slice); + if (value == MP_OBJ_SENTINEL) { + // load + if (!fast) { + return mp_seq_extract_slice(self->items, &slice); } - - mp_int_t len_adj = slice.start - slice.stop; - assert(len_adj <= 0); - mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items /*NULL*/, 0, sizeof(*self->items)); + mp_obj_list_t *res = list_new(slice.stop - slice.start); + mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); + return MP_OBJ_FROM_PTR(res); + } + // assign/delete + if (value == MP_OBJ_NULL) { + // delete is equivalent to slice assignment of an empty sequence + value = mp_const_empty_tuple; + } + if (!fast) { + mp_raise_NotImplementedError(NULL); + } + size_t value_len; + mp_obj_t *value_items; + mp_obj_get_array(value, &value_len, &value_items); + mp_int_t len_adj = value_len - (slice.stop - slice.start); + if (len_adj > 0) { + if (self->len + len_adj > self->alloc) { + // TODO: Might optimize memory copies here by checking if block can + // be grown inplace or not + self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj); + self->alloc = self->len + len_adj; + } + mp_seq_replace_slice_grow_inplace(self->items, self->len, + slice.start, slice.stop, value_items, value_len, len_adj, sizeof(*self->items)); + } else { + mp_seq_replace_slice_no_grow(self->items, self->len, + slice.start, slice.stop, value_items, value_len, sizeof(*self->items)); // Clear "freed" elements at the end of list mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); - self->len += len_adj; - return mp_const_none; + // TODO: apply allocation policy re: alloc_size } - #endif - // CIRCUITPY-CHANGE - mp_obj_t args[2] = {MP_OBJ_FROM_PTR(self), index}; + self->len += len_adj; + return mp_const_none; + } + #endif + if (value == MP_OBJ_NULL) { + // delete + // CIRCUITPY-CHANGE: handle subclassing + mp_obj_t args[2] = {MP_OBJ_FROM_PTR(self_in), index}; list_pop(2, args); return mp_const_none; } else if (value == MP_OBJ_SENTINEL) { // load - #if MICROPY_PY_BUILTINS_SLICE - if (mp_obj_is_type(index, &mp_type_slice)) { - mp_bound_slice_t slice; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { - return mp_seq_extract_slice(self->items, &slice); - } - mp_obj_list_t *res = list_new(slice.stop - slice.start); - mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); - return MP_OBJ_FROM_PTR(res); - } - #endif + // CIRCUITPY-CHANGE: handle subclassing + mp_obj_list_t *self = native_list(self_in); size_t index_val = mp_get_index(self->base.type, self->len, index, false); return self->items[index_val]; } else { - #if MICROPY_PY_BUILTINS_SLICE - if (mp_obj_is_type(index, &mp_type_slice)) { - size_t value_len; - mp_obj_t *value_items; - mp_obj_get_array(value, &value_len, &value_items); - mp_bound_slice_t slice_out; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) { - mp_raise_NotImplementedError(NULL); - } - mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start); - if (len_adj > 0) { - if (self->len + len_adj > self->alloc) { - // TODO: Might optimize memory copies here by checking if block can - // be grown inplace or not - self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj); - self->alloc = self->len + len_adj; - } - mp_seq_replace_slice_grow_inplace(self->items, self->len, - slice_out.start, slice_out.stop, value_items, value_len, len_adj, sizeof(*self->items)); - } else { - mp_seq_replace_slice_no_grow(self->items, self->len, - slice_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items)); - // Clear "freed" elements at the end of list - mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); - // TODO: apply allocation policy re: alloc_size - } - self->len += len_adj; - return mp_const_none; - } - #endif mp_obj_list_store(self_in, index, value); return mp_const_none; } @@ -252,7 +242,7 @@ static mp_obj_t list_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); if (self->len >= self->alloc) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2); @@ -266,7 +256,7 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { static mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); if (mp_obj_is_type(arg_in, &mp_type_list)) { - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); mp_obj_list_t *arg = native_list(arg_in); @@ -285,7 +275,7 @@ static mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { return mp_const_none; // return None, as per CPython } -// CIRCUITPY-CHANGE: used elsewhere so not static; impl is different +// CIRCUITPY-CHANGE: provide version for C use outside this file inline mp_obj_t mp_obj_list_pop(mp_obj_list_t *self, size_t index) { if (self->len == 0) { // CIRCUITPY-CHANGE: more specific mp_raise @@ -303,18 +293,28 @@ inline mp_obj_t mp_obj_list_pop(mp_obj_list_t *self, size_t index) { return ret; } -// CIRCUITPY-CHANGE static mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_type(args[0], &mp_type_list)); mp_obj_list_t *self = native_list(args[0]); size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false); + // CIRCUITPY-CHANGE: use factored-out pop code return mp_obj_list_pop(self, index); } +// "head" is actually the *exclusive lower bound* of the range to sort. That is, +// the first element to be sorted is `head[1]`, not `head[0]`. Similarly `tail` +// is an *inclusive upper bound* of the range to sort. That is, the final +// element to sort is `tail[0]`, not `tail[-1]`. +// +// The pivot element is always chosen as `tail[0]`. +// +// These unusual choices allows structuring the partitioning +// process as a do/while loop, which generates smaller code than the equivalent +// code with usual C bounds & a while or for loop. static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, mp_obj_t binop_less_result) { mp_cstack_check(); - while (head < tail) { - mp_obj_t *h = head - 1; + while (tail - head > 1) { // So long as at least 2 elements remain + mp_obj_t *h = head; mp_obj_t *t = tail; mp_obj_t v = key_fn == MP_OBJ_NULL ? tail[0] : mp_call_function_1(key_fn, tail[0]); // get pivot using key_fn for (;;) { @@ -325,19 +325,21 @@ static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, mp_obj if (h >= t) { break; } + // A pair of objects must be swapped to the other side of the partition mp_obj_t x = h[0]; h[0] = t[0]; t[0] = x; } + // Place the pivot element in the proper position mp_obj_t x = h[0]; h[0] = tail[0]; tail[0] = x; // do the smaller recursive call first, to keep stack within O(log(N)) - if (t - head < tail - h - 1) { + if (t - head < tail - h) { mp_quicksort(head, t, key_fn, binop_less_result); - head = h + 1; + head = h; } else { - mp_quicksort(h + 1, tail, key_fn, binop_less_result); + mp_quicksort(h, tail, key_fn, binop_less_result); tail = t; } } @@ -362,7 +364,7 @@ mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ mp_obj_list_t *self = native_list(pos_args[0]); if (self->len > 1) { - mp_quicksort(self->items, self->items + self->len - 1, + mp_quicksort(self->items - 1, self->items + self->len - 1, args.key.u_obj == mp_const_none ? MP_OBJ_NULL : args.key.u_obj, args.reverse.u_bool ? mp_const_false : mp_const_true); } @@ -370,10 +372,10 @@ mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ return mp_const_none; } -// CIRCUITPY-CHANGE: used elsewhere so not static +// CIRCUITPY-CHANGE: rename and make not static for use elsewhere mp_obj_t mp_obj_list_clear(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); self->len = 0; self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC); @@ -384,27 +386,28 @@ mp_obj_t mp_obj_list_clear(mp_obj_t self_in) { static mp_obj_t list_copy(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); return mp_obj_new_list(self->len, self->items); } static mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); return mp_seq_count_obj(self->items, self->len, value); } static mp_obj_t list_index(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_type(args[0], &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(args[0]); return mp_seq_index_obj(self->items, self->len, n_args, args); } -// CIRCUITPY-CHANGE: used elsewhere so not static -inline void mp_obj_list_insert(mp_obj_list_t *self, size_t index, mp_obj_t obj) { +// CIRCUITPY-CHANGE: factor out for C use elsewhere; not meant to emulate Python API +inline void mp_obj_list_insert(mp_obj_list_t *self_in, size_t index, mp_obj_t obj) { + mp_obj_list_t *self = native_list(self_in); mp_obj_list_append(MP_OBJ_FROM_PTR(self), mp_const_none); for (size_t i = self->len - 1; i > index; --i) { @@ -428,7 +431,7 @@ static mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) { if ((size_t)index > self->len) { index = self->len; } - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: use factored-out insert code mp_obj_list_insert(self, index, obj); return mp_const_none; } diff --git a/py/objmodule.c b/py/objmodule.c index a5c1dee968e..84b6a10f9ab 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -34,11 +34,6 @@ #include "py/runtime.h" #include "py/builtin.h" -// CIRCUITPY-CHANGE -#if CIRCUITPY_WARNINGS -#include "shared-module/warnings/__init__.h" -#endif - static void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); @@ -49,7 +44,7 @@ static void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin module_name = mp_obj_str_get_str(elem->value); } - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ // If we store __file__ to imported modules then try to lookup this // symbol to give more information about the module. elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP); @@ -157,11 +152,13 @@ static const mp_rom_map_elem_t mp_builtin_module_table[] = { }; MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table); +#if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES static const mp_rom_map_elem_t mp_builtin_extensible_module_table[] = { // built-in modules declared with MP_REGISTER_EXTENSIBLE_MODULE() MICROPY_REGISTERED_EXTENSIBLE_MODULES }; MP_DEFINE_CONST_MAP(mp_builtin_extensible_module_map, mp_builtin_extensible_module_table); +#endif #if MICROPY_MODULE_ATTR_DELEGATION && defined(MICROPY_MODULE_DELEGATIONS) typedef struct _mp_module_delegation_entry_t { @@ -178,13 +175,13 @@ static const mp_module_delegation_entry_t mp_builtin_module_delegation_table[] = // Attempts to find (and initialise) a built-in, otherwise returns // MP_OBJ_NULL. mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible) { - // CIRCUITPY-CHANGE - #if CIRCUITPY_PARALLELDISPLAYBUS && CIRCUITPY_WARNINGS - if (module_name == MP_QSTR_paralleldisplay) { - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q renamed %q"), MP_QSTR_paralleldisplay, MP_QSTR_paralleldisplaybus); - } + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES + const mp_map_t *map = extensible ? &mp_builtin_extensible_module_map : &mp_builtin_module_map; + #else + const mp_map_t *map = &mp_builtin_module_map; #endif - mp_map_elem_t *elem = mp_map_lookup((mp_map_t *)(extensible ? &mp_builtin_extensible_module_map : &mp_builtin_module_map), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); + mp_map_elem_t *elem = mp_map_lookup((mp_map_t *)map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); + if (!elem) { #if MICROPY_PY_SYS // Special case for sys, which isn't extensible but can always be @@ -194,6 +191,7 @@ mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible) { } #endif + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES if (extensible) { // At this point we've already tried non-extensible built-ins, the // filesystem, and now extensible built-ins. No match, so fail @@ -210,6 +208,7 @@ mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible) { // the old behaviour of the u-prefix being used to force a built-in // import. // CIRCUITPY-CHANGE: Don't look for `ufoo`. + #endif return MP_OBJ_NULL; } diff --git a/py/objmodule.h b/py/objmodule.h index 8b14cd9fc3d..221392ccce4 100644 --- a/py/objmodule.h +++ b/py/objmodule.h @@ -32,10 +32,16 @@ // Only include module definitions when not doing qstr extraction, because the // qstr extraction stage also generates this module definition header file. #include "genhdr/moduledefs.h" +// CIRCUITPY-CHANGE: avoid undef warning +#else +#define MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES (0) #endif extern const mp_map_t mp_builtin_module_map; + +#if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES extern const mp_map_t mp_builtin_extensible_module_map; +#endif mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible); diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index b6bbe6e05d8..d687dbfda59 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -73,7 +73,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(namedtuple_asdict_obj, namedtuple_asdict); void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_namedtuple_t *o = MP_OBJ_TO_PTR(o_in); - mp_printf(print, "%q", o->tuple.base.type->name); + mp_printf(print, "%q", (qstr)o->tuple.base.type->name); const qstr *fields = ((mp_obj_namedtuple_type_t *)o->tuple.base.type)->fields; mp_obj_attrtuple_print_helper(print, fields, &o->tuple); } diff --git a/py/objrange.c b/py/objrange.c index bde2ebaabb4..dea9fe5f296 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -41,9 +41,9 @@ typedef struct _mp_obj_range_it_t { static mp_obj_t range_it_iternext(mp_obj_t o_in) { mp_obj_range_it_t *o = MP_OBJ_TO_PTR(o_in); if ((o->step > 0 && o->cur < o->stop) || (o->step < 0 && o->cur > o->stop)) { - mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(o->cur); + mp_int_t cur = o->cur; o->cur += o->step; - return o_out; + return mp_obj_new_int(cur); } else { return MP_OBJ_STOP_ITERATION; } @@ -133,7 +133,7 @@ static mp_obj_t range_unary_op(mp_unary_op_t op, mp_obj_t self_in) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len > 0); case MP_UNARY_OP_LEN: - return MP_OBJ_NEW_SMALL_INT(len); + return mp_obj_new_int(len); default: return MP_OBJ_NULL; // op not supported } @@ -165,20 +165,16 @@ static mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_bound_slice_t slice; - mp_seq_get_fast_slice_indexes(len, index, &slice); + mp_obj_slice_indices(index, len, &slice); mp_obj_range_t *o = mp_obj_malloc(mp_obj_range_t, &mp_type_range); o->start = self->start + slice.start * self->step; o->stop = self->start + slice.stop * self->step; o->step = slice.step * self->step; - if (slice.step < 0) { - // Negative slice steps have inclusive stop, so adjust for exclusive - o->stop -= self->step; - } return MP_OBJ_FROM_PTR(o); } #endif size_t index_val = mp_get_index(self->base.type, len, index, false); - return MP_OBJ_NEW_SMALL_INT(self->start + index_val * self->step); + return mp_obj_new_int(self->start + index_val * self->step); } else { return MP_OBJ_NULL; // op not supported } diff --git a/py/objringio.c b/py/objringio.c index ba1ec25307e..0025b26be3b 100644 --- a/py/objringio.c +++ b/py/objringio.c @@ -39,22 +39,19 @@ typedef struct _micropython_ringio_obj_t { static mp_obj_t micropython_ringio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); - mp_int_t buff_size = -1; mp_buffer_info_t bufinfo = {NULL, 0, 0}; if (!mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) { - buff_size = mp_obj_get_int(args[0]); + bufinfo.len = mp_obj_get_int(args[0]) + 1; + bufinfo.buf = m_new(uint8_t, bufinfo.len); } - micropython_ringio_obj_t *self = mp_obj_malloc(micropython_ringio_obj_t, type); - if (bufinfo.buf != NULL) { - // buffer passed in, use it directly for ringbuffer. - self->ringbuffer.buf = bufinfo.buf; - self->ringbuffer.size = bufinfo.len; - self->ringbuffer.iget = self->ringbuffer.iput = 0; - } else { - // Allocate new buffer, add one extra to buff_size as ringbuf consumes one byte for tracking. - ringbuf_alloc(&(self->ringbuffer), buff_size + 1); + if (bufinfo.len < 2 || bufinfo.len > UINT16_MAX) { + mp_raise_ValueError(NULL); } + micropython_ringio_obj_t *self = mp_obj_malloc(micropython_ringio_obj_t, type); + self->ringbuffer.buf = bufinfo.buf; + self->ringbuffer.size = bufinfo.len; + self->ringbuffer.iget = self->ringbuffer.iput = 0; return MP_OBJ_FROM_PTR(self); } diff --git a/py/objstr.c b/py/objstr.c index 1874cdb01d0..bd650bbe18a 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -33,6 +33,7 @@ #include "py/objlist.h" #include "py/runtime.h" #include "py/cstack.h" +#include "py/objtuple.h" // CIRCUITPY-CHANGE const char nibble_to_hex_upper[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', @@ -46,7 +47,7 @@ static mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ #endif static mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); -static NORETURN void bad_implicit_conversion(mp_obj_t self_in); +static MP_NORETURN void bad_implicit_conversion(mp_obj_t self_in); static mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); @@ -372,8 +373,7 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mp_obj_t *args = &rhs_in; size_t n_args = 1; mp_obj_t dict = MP_OBJ_NULL; - if (mp_obj_is_type(rhs_in, &mp_type_tuple)) { - // TODO: Support tuple subclasses? + if (mp_obj_is_tuple_compatible(rhs_in)) { mp_obj_tuple_get(rhs_in, &n_args, &args); } else if (mp_obj_is_type(rhs_in, &mp_type_dict)) { dict = rhs_in; @@ -1018,7 +1018,7 @@ static mp_obj_t arg_as_int(mp_obj_t arg) { #endif #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE -static NORETURN void terse_str_format_value_error(void) { +static MP_NORETURN void terse_str_format_value_error(void) { mp_raise_ValueError(MP_ERROR_TEXT("bad format string")); } #else @@ -1205,7 +1205,7 @@ static vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar int width = -1; int precision = -1; char type = '\0'; - int flags = 0; + unsigned int flags = 0; if (format_spec) { // The format specifier (from http://docs.python.org/2/library/string.html#formatspec) @@ -1250,8 +1250,9 @@ static vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } } s = str_to_int(s, stop, &width); - if (*s == ',') { - flags |= PF_FLAG_SHOW_COMMA; + if (*s == ',' || *s == '_') { + MP_STATIC_ASSERT((unsigned)'_' << PF_FLAG_SEP_POS >> PF_FLAG_SEP_POS == '_'); + flags |= (unsigned)*s << PF_FLAG_SEP_POS; s++; } if (*s == '.') { @@ -1324,7 +1325,7 @@ static vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } case '\0': // No explicit format type implies 'd' - case 'n': // I don't think we support locales in uPy so use 'd' + case 'n': // I don't think we support locales in MicroPython so use 'd' case 'd': mp_print_mp_int(&print, arg, 10, 'a', flags, fill, width, 0); continue; @@ -2395,7 +2396,7 @@ bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) { } } -static NORETURN void bad_implicit_conversion(mp_obj_t self_in) { +static MP_NORETURN void bad_implicit_conversion(mp_obj_t self_in) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("can't convert to str implicitly")); #else diff --git a/py/objtuple.c b/py/objtuple.c index e0b31edaf23..b2ccbbb2990 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -31,9 +31,6 @@ #include "py/objtuple.h" #include "py/runtime.h" -// type check is done on getiter method to allow tuple, namedtuple, attrtuple -#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), iter) == mp_obj_tuple_getiter) - /******************************************************************************/ /* tuple */ diff --git a/py/objtuple.h b/py/objtuple.h index e2d010e6c5a..783522a6222 100644 --- a/py/objtuple.h +++ b/py/objtuple.h @@ -57,7 +57,7 @@ extern const mp_obj_type_t mp_type_attrtuple; #define MP_DEFINE_ATTRTUPLE(tuple_obj_name, fields, nitems, ...) \ const mp_rom_obj_tuple_t tuple_obj_name = { \ - .base = {&mp_type_attrtuple}, \ + .base = {.type = &mp_type_attrtuple}, \ .len = nitems, \ .items = { __VA_ARGS__, MP_ROM_PTR((void *)fields) } \ } @@ -68,4 +68,7 @@ void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *items); +// type check is done on getiter method to allow tuple, namedtuple, attrtuple +#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), iter) == mp_obj_tuple_getiter) + #endif // MICROPY_INCLUDED_PY_OBJTUPLE_H diff --git a/py/objtype.c b/py/objtype.c index 074d6f39293..b1a984b50e0 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -44,6 +44,7 @@ #define ENABLE_SPECIAL_ACCESSORS \ (MICROPY_PY_DESCRIPTORS || MICROPY_PY_DELATTR_SETATTR || MICROPY_PY_BUILTINS_PROPERTY) +static mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); static mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo); static mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); @@ -690,8 +691,8 @@ static void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des // try __getattr__ if (attr != MP_QSTR___getattr__) { #if MICROPY_PY_DESCRIPTORS - // With descriptors enabled, don't delegate lookups of __get__/__set__/__delete__. - if (attr == MP_QSTR___get__ || attr == MP_QSTR___set__ || attr == MP_QSTR___delete__) { + // With descriptors enabled, don't delegate lookups of __get__/__set__/__delete__/__set_name__. + if (attr == MP_QSTR___get__ || attr == MP_QSTR___set__ || attr == MP_QSTR___delete__ || attr == MP_QSTR___set_name__) { return; } #endif @@ -996,7 +997,7 @@ static bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) { #endif #if MICROPY_PY_DESCRIPTORS static const uint8_t to_check[] = { - MP_QSTR___get__, MP_QSTR___set__, MP_QSTR___delete__, + MP_QSTR___get__, MP_QSTR___set__, MP_QSTR___delete__, // not needed for MP_QSTR___set_name__ though }; for (size_t i = 0; i < MP_ARRAY_SIZE(to_check); ++i) { mp_obj_t dest_temp[2]; @@ -1010,10 +1011,52 @@ static bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) { } #endif +#if MICROPY_PY_DESCRIPTORS +// Shared data layout for the __set_name__ call and a linked list of calls to be made. +typedef union _setname_list_t setname_list_t; +union _setname_list_t { + mp_obj_t call[4]; + struct { + mp_obj_t _meth; + mp_obj_t _self; + setname_list_t *next; // can use the "owner" argument position temporarily for the linked list + mp_obj_t _name; + }; +}; + +// Append any `__set_name__` method on `value` to the setname list, with its per-attr args +static setname_list_t *setname_maybe_bind_append(setname_list_t *tail, mp_obj_t name, mp_obj_t value) { + // make certain our type-punning is safe: + MP_STATIC_ASSERT_NONCONSTEXPR(offsetof(setname_list_t, next) == offsetof(setname_list_t, call[2])); + + // tail is a blank list entry + mp_load_method_maybe(value, MP_QSTR___set_name__, tail->call); + if (tail->call[1] != MP_OBJ_NULL) { + // Each time a __set_name__ is found, leave it in-place in the former tail and allocate a new tail + tail->next = m_new_obj(setname_list_t); + tail->next->next = NULL; + tail->call[3] = name; + return tail->next; + } else { + return tail; + } +} + +// Execute the captured `__set_name__` calls, destroying the setname list in the process. +static inline void setname_consume_call_all(setname_list_t *head, mp_obj_t owner) { + setname_list_t *next; + while ((next = head->next) != NULL) { + head->call[2] = owner; + mp_call_method_n_kw(2, 0, head->call); + head = next; + } +} +#endif + static void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "", self->name); + mp_printf(print, "", (qstr)self->name); } static mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { @@ -1043,7 +1086,7 @@ static mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp if (!MP_OBJ_TYPE_HAS_SLOT(self, make_new)) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE - mp_raise_TypeError(MP_ERROR_TEXT("cannot create instance")); + mp_raise_TypeError(MP_ERROR_TEXT("can't create instance")); #else // CIRCUITPY-CHANGE: more specific mp_raise mp_raise_TypeError_varg(MP_ERROR_TEXT("can't create '%q' instances"), self->name); @@ -1159,7 +1202,7 @@ MP_DEFINE_CONST_OBJ_TYPE( attr, type_attr ); -mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { +static mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { // Verify input objects have expected type if (!mp_obj_is_type(bases_tuple, &mp_type_tuple)) { mp_raise_TypeError(NULL); @@ -1252,20 +1295,38 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) } } + #if MICROPY_PY_DESCRIPTORS + // To avoid any dynamic allocations when no __set_name__ exists, + // the head of this list is kept on the stack (marked blank with `next = NULL`). + setname_list_t setname_list = { .next = NULL }; + setname_list_t *setname_tail = &setname_list; + #endif + #if ENABLE_SPECIAL_ACCESSORS - // Check if the class has any special accessor methods - if (!(o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { - for (size_t i = 0; i < locals_ptr->map.alloc; i++) { - if (mp_map_slot_is_filled(&locals_ptr->map, i)) { - const mp_map_elem_t *elem = &locals_ptr->map.table[i]; - if (check_for_special_accessors(elem->key, elem->value)) { - o->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; - break; - } + // Check if the class has any special accessor methods, + // and accumulate bound __set_name__ methods that need to be called + for (size_t i = 0; i < locals_ptr->map.alloc; i++) { + #if !MICROPY_PY_DESCRIPTORS + // __set_name__ needs to scan the entire locals map, can't early-terminate + if (o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS) { + break; + } + #endif + + if (mp_map_slot_is_filled(&locals_ptr->map, i)) { + const mp_map_elem_t *elem = &locals_ptr->map.table[i]; + + if (!(o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS) // elidable when the early-termination check is enabled + && check_for_special_accessors(elem->key, elem->value)) { + o->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; } + + #if MICROPY_PY_DESCRIPTORS + setname_tail = setname_maybe_bind_append(setname_tail, elem->key, elem->value); + #endif } } - #endif + #endif // ENABLE_SPECIAL_ACCESSORS const mp_obj_type_t *native_base; size_t num_native_bases = instance_count_native_bases(o, &native_base); @@ -1273,8 +1334,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) mp_raise_TypeError(MP_ERROR_TEXT("multiple bases have instance lay-out conflict")); } - mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(o, locals_dict)->map; - mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP); + mp_map_elem_t *elem = mp_map_lookup(&locals_ptr->map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP); if (elem != NULL) { // __new__ slot exists; check if it is a function if (mp_obj_is_fun(elem->value)) { @@ -1283,6 +1343,10 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) } } + #if MICROPY_PY_DESCRIPTORS + setname_consume_call_all(&setname_list, MP_OBJ_FROM_PTR(o)); + #endif + return MP_OBJ_FROM_PTR(o); } diff --git a/py/parse.c b/py/parse.c index a393b0ee8c1..36150ef468b 100644 --- a/py/parse.c +++ b/py/parse.c @@ -341,18 +341,34 @@ static uint8_t peek_rule(parser_t *parser, size_t n) { } #endif -bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) { +#if MICROPY_COMP_CONST_FOLDING || MICROPY_EMIT_INLINE_ASM +static bool mp_parse_node_get_number_maybe(mp_parse_node_t pn, mp_obj_t *o) { if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { *o = MP_OBJ_NEW_SMALL_INT(MP_PARSE_NODE_LEAF_SMALL_INT(pn)); return true; } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_const_object)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn; *o = mp_parse_node_extract_const_object(pns); - return mp_obj_is_int(*o); + return mp_obj_is_int(*o) + #if MICROPY_COMP_CONST_FLOAT + || mp_obj_is_float(*o) + #endif + ; } else { return false; } } +#endif + +#if MICROPY_EMIT_INLINE_ASM +bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) { + return mp_parse_node_get_number_maybe(pn, o) + #if MICROPY_COMP_CONST_FLOAT + && mp_obj_is_int(*o) + #endif + ; +} +#endif #if MICROPY_COMP_CONST_TUPLE || MICROPY_COMP_CONST static bool mp_parse_node_is_const(mp_parse_node_t pn) { @@ -647,12 +663,32 @@ static const mp_rom_map_elem_t mp_constants_table[] = { #if MICROPY_PY_UCTYPES { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) }, #endif + #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH && MICROPY_COMP_CONST_FLOAT + { MP_ROM_QSTR(MP_QSTR_math), MP_ROM_PTR(&mp_module_math) }, + #endif // Extra constants as defined by a port MICROPY_PORT_CONSTANTS }; static MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table); #endif +static bool binary_op_maybe(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs, mp_obj_t *res) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t tmp = mp_binary_op(op, lhs, rhs); + nlr_pop(); + #if MICROPY_PY_BUILTINS_COMPLEX + if (mp_obj_is_type(tmp, &mp_type_complex)) { + return false; + } + #endif + *res = tmp; + return true; + } else { + return false; + } +} + static bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *num_args) { if (rule_id == RULE_or_test || rule_id == RULE_and_test) { @@ -711,7 +747,7 @@ static bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *nu } static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { - // this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4 + // this code does folding of arbitrary numeric expressions, eg 1 + 2 * 3 + 4 // it does not do partial folding, eg 1 + 2 + x -> 3 + x mp_obj_t arg0; @@ -721,7 +757,7 @@ static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { || rule_id == RULE_power) { // folding for binary ops: | ^ & ** mp_parse_node_t pn = peek_result(parser, num_args - 1); - if (!mp_parse_node_get_int_maybe(pn, &arg0)) { + if (!mp_parse_node_get_number_maybe(pn, &arg0)) { return false; } mp_binary_op_t op; @@ -737,58 +773,45 @@ static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { for (ssize_t i = num_args - 2; i >= 0; --i) { pn = peek_result(parser, i); mp_obj_t arg1; - if (!mp_parse_node_get_int_maybe(pn, &arg1)) { + if (!mp_parse_node_get_number_maybe(pn, &arg1)) { return false; } - if (op == MP_BINARY_OP_POWER && mp_obj_int_sign(arg1) < 0) { - // ** can't have negative rhs + if (!binary_op_maybe(op, arg0, arg1, &arg0)) { return false; } - arg0 = mp_binary_op(op, arg0, arg1); } } else if (rule_id == RULE_shift_expr || rule_id == RULE_arith_expr || rule_id == RULE_term) { // folding for binary ops: << >> + - * @ / % // mp_parse_node_t pn = peek_result(parser, num_args - 1); - if (!mp_parse_node_get_int_maybe(pn, &arg0)) { + if (!mp_parse_node_get_number_maybe(pn, &arg0)) { return false; } for (ssize_t i = num_args - 2; i >= 1; i -= 2) { pn = peek_result(parser, i - 1); mp_obj_t arg1; - if (!mp_parse_node_get_int_maybe(pn, &arg1)) { + if (!mp_parse_node_get_number_maybe(pn, &arg1)) { return false; } mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, i)); - if (tok == MP_TOKEN_OP_AT || tok == MP_TOKEN_OP_SLASH) { - // Can't fold @ or / - return false; - } mp_binary_op_t op = MP_BINARY_OP_LSHIFT + (tok - MP_TOKEN_OP_DBL_LESS); - int rhs_sign = mp_obj_int_sign(arg1); - if (op <= MP_BINARY_OP_RSHIFT) { - // << and >> can't have negative rhs - if (rhs_sign < 0) { - return false; - } - } else if (op >= MP_BINARY_OP_FLOOR_DIVIDE) { - // % and // can't have zero rhs - if (rhs_sign == 0) { - return false; - } + if (!binary_op_maybe(op, arg0, arg1, &arg0)) { + return false; } - arg0 = mp_binary_op(op, arg0, arg1); } } else if (rule_id == RULE_factor_2) { // folding for unary ops: + - ~ mp_parse_node_t pn = peek_result(parser, 0); - if (!mp_parse_node_get_int_maybe(pn, &arg0)) { + if (!mp_parse_node_get_number_maybe(pn, &arg0)) { return false; } mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, 1)); mp_unary_op_t op; if (tok == MP_TOKEN_OP_TILDE) { + if (!mp_obj_is_int(arg0)) { + return false; + } op = MP_UNARY_OP_INVERT; } else { assert(tok == MP_TOKEN_OP_PLUS || tok == MP_TOKEN_OP_MINUS); // should be @@ -860,7 +883,7 @@ static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { return false; } // id1.id2 - // look it up in constant table, see if it can be replaced with an integer + // look it up in constant table, see if it can be replaced with an integer or a float mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pn1; assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); qstr q_base = MP_PARSE_NODE_LEAF_ARG(pn0); @@ -871,7 +894,7 @@ static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { } mp_obj_t dest[2]; mp_load_method_maybe(elem->value, q_attr, dest); - if (!(dest[0] != MP_OBJ_NULL && mp_obj_is_int(dest[0]) && dest[1] == MP_OBJ_NULL)) { + if (!(dest[0] != MP_OBJ_NULL && (mp_obj_is_int(dest[0]) || mp_obj_is_float(dest[0])) && dest[1] == MP_OBJ_NULL)) { return false; } arg0 = dest[0]; diff --git a/py/parsenum.c b/py/parsenum.c index 874216f08d0..c52f040e1a2 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -28,6 +28,7 @@ #include #include "py/runtime.h" +#include "py/misc.h" #include "py/parsenumbase.h" #include "py/parsenum.h" #include "py/smallint.h" @@ -36,7 +37,7 @@ #include #endif -static NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) { +static MP_NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) { // if lex!=NULL then the parser called us and we need to convert the // exception's type from ValueError to SyntaxError and add traceback info if (lex != NULL) { @@ -46,6 +47,27 @@ static NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) { nlr_raise(exc); } +#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_LONGLONG +// For the common small integer parsing case, we parse directly to mp_int_t and +// check that the value doesn't overflow a smallint (in which case we fail over +// to bigint parsing if supported) +typedef mp_int_t parsed_int_t; + +#define PARSED_INT_MUL_OVERFLOW mp_mul_mp_int_t_overflow +#define PARSED_INT_FITS MP_SMALL_INT_FITS +#else +// In the special case where bigint support is long long, we save code size by +// parsing directly to long long and then return either a bigint or smallint +// from the same result. +// +// To avoid pulling in (slow) signed 64-bit math routines we do the initial +// parsing to an unsigned long long and only convert to signed at the end. +typedef unsigned long long parsed_int_t; + +#define PARSED_INT_MUL_OVERFLOW mp_mul_ull_overflow +#define PARSED_INT_FITS(I) ((I) <= (unsigned long long)LLONG_MAX + 1) +#endif + mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, mp_lexer_t *lex) { const byte *restrict str = (const byte *)str_; const byte *restrict top = str + len; @@ -77,7 +99,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m str += mp_parse_num_base((const char *)str, top - str, &base); // string should be an integer number - mp_int_t int_val = 0; + parsed_int_t parsed_val = 0; const byte *restrict str_val_start = str; for (; str < top; str++) { // get next digit as a value @@ -99,25 +121,32 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m break; } - // add next digi and check for overflow - if (mp_small_int_mul_overflow(int_val, base)) { + // add next digit and check for overflow + if (PARSED_INT_MUL_OVERFLOW(parsed_val, base, &parsed_val)) { goto overflow; } - int_val = int_val * base + dig; - if (!MP_SMALL_INT_FITS(int_val)) { + parsed_val += dig; + if (!PARSED_INT_FITS(parsed_val)) { goto overflow; } } - // negate value if needed - if (neg) { - int_val = -int_val; + #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_LONGLONG + // The PARSED_INT_FITS check above ensures parsed_val fits in small int representation + ret_val = MP_OBJ_NEW_SMALL_INT(neg ? (-parsed_val) : parsed_val); +have_ret_val: + #else + // The PARSED_INT_FITS check above ensures parsed_val won't overflow signed long long + long long signed_val = -parsed_val; + if (!neg) { + if (signed_val == LLONG_MIN) { + goto overflow; + } + signed_val = -signed_val; } + ret_val = mp_obj_new_int_from_ll(signed_val); // Could be large or small int + #endif - // create the small int - ret_val = MP_OBJ_NEW_SMALL_INT(int_val); - -have_ret_val: // check we parsed something if (str == str_val_start) { goto value_error; @@ -136,6 +165,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m return ret_val; overflow: + #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_LONGLONG // reparse using long int { const char *s2 = (const char *)str_val_start; @@ -143,6 +173,9 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m str = (const byte *)s2; goto have_ret_val; } + #else + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("result overflows long long storage")); + #endif value_error: { @@ -167,6 +200,8 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m } } +#if MICROPY_PY_BUILTINS_FLOAT + enum { REAL_IMAG_STATE_START = 0, REAL_IMAG_STATE_HAVE_REAL = 1, @@ -179,27 +214,81 @@ typedef enum { PARSE_DEC_IN_EXP, } parse_dec_in_t; -#if MICROPY_PY_BUILTINS_FLOAT // MANTISSA_MAX is used to retain precision while not overflowing mantissa -// SMALL_NORMAL_VAL is the smallest power of 10 that is still a normal float -// EXACT_POWER_OF_10 is the largest value of x so that 10^x can be stored exactly in a float -// Note: EXACT_POWER_OF_10 is at least floor(log_5(2^mantissa_length)). Indeed, 10^n = 2^n * 5^n -// so we only have to store the 5^n part in the mantissa (the 2^n part will go into the float's -// exponent). +#define MANTISSA_MAX (sizeof(mp_large_float_uint_t) == 8 ? 0x1999999999999998ULL : 0x19999998U) + +// MAX_EXACT_POWER_OF_5 is the largest value of x so that 5^x can be stored exactly in a float #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT -#define MANTISSA_MAX 0x19999998U -#define SMALL_NORMAL_VAL (1e-37F) -#define SMALL_NORMAL_EXP (-37) -#define EXACT_POWER_OF_10 (9) +#define MAX_EXACT_POWER_OF_5 (10) #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE -#define MANTISSA_MAX 0x1999999999999998ULL -#define SMALL_NORMAL_VAL (1e-307) -#define SMALL_NORMAL_EXP (-307) -#define EXACT_POWER_OF_10 (22) +#define MAX_EXACT_POWER_OF_5 (22) #endif +// Helper to compute `num * (10.0 ** dec_exp)` +mp_large_float_t mp_decimal_exp(mp_large_float_t num, int dec_exp) { + // CIRCUITPY-CHANGE: ignore float equal warning + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + if (dec_exp == 0 || num == (mp_large_float_t)(0.0)) { + return num; + } + #pragma GCC diagnostic pop + + #if MICROPY_FLOAT_FORMAT_IMPL == MICROPY_FLOAT_FORMAT_IMPL_EXACT + + // If the assert below fails, it means you have chosen MICROPY_FLOAT_FORMAT_IMPL_EXACT + // manually on a platform where `larger floats` are not supported, which would + // result in inexact conversions. To fix this issue, change your `mpconfigport.h` + // and select MICROPY_FLOAT_FORMAT_IMPL_APPROX instead + assert(sizeof(mp_large_float_t) > sizeof(mp_float_t)); + + // Perform power using simple multiplications, to avoid + // dependency to higher-precision pow() function + int neg_exp = (dec_exp < 0); + if (neg_exp) { + dec_exp = -dec_exp; + } + mp_large_float_t res = num; + mp_large_float_t expo = (mp_large_float_t)10.0; + while (dec_exp) { + if (dec_exp & 1) { + if (neg_exp) { + res /= expo; + } else { + res *= expo; + } + } + dec_exp >>= 1; + if (dec_exp) { + expo *= expo; + } + } + return res; + + #else + // MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_EXACT + + mp_float_union_t res = {num}; + // Multiply first by (2.0 ** dec_exp) via the exponent + // - this will ensure that the result of `pow()` is always in mp_float_t range + // when the result is expected to be in mp_float_t range (e.g. during format) + // - we don't need to care about p.exp overflow, as (5.0 ** dec_exp) will anyway + // force the final result toward the proper edge if needed (0.0 or inf) + res.p.exp += dec_exp; + // Use positive exponents when they are more precise then negative + if (dec_exp < 0 && dec_exp >= -MAX_EXACT_POWER_OF_5) { + res.f /= MICROPY_FLOAT_C_FUN(pow)(5, -dec_exp); + } else { + res.f *= MICROPY_FLOAT_C_FUN(pow)(5, dec_exp); + } + return (mp_large_float_t)res.f; + + #endif +} + + // Break out inner digit accumulation routine to ease trailing zero deferral. -static mp_float_uint_t accept_digit(mp_float_uint_t p_mantissa, unsigned int dig, int *p_exp_extra, int in) { +static mp_large_float_uint_t accept_digit(mp_large_float_uint_t p_mantissa, unsigned int dig, int *p_exp_extra, int in) { // Core routine to ingest an additional digit. if (p_mantissa < MANTISSA_MAX) { // dec_val won't overflow so keep accumulating @@ -216,6 +305,85 @@ static mp_float_uint_t accept_digit(mp_float_uint_t p_mantissa, unsigned int dig return p_mantissa; } } + +// Helper to parse an unsigned decimal number into a mp_float_t +const char *mp_parse_float_internal(const char *str, size_t len, mp_float_t *res) { + const char *top = str + len; + + parse_dec_in_t in = PARSE_DEC_IN_INTG; + bool exp_neg = false; + mp_large_float_uint_t mantissa = 0; + int exp_val = 0; + int exp_extra = 0; + int trailing_zeros_intg = 0, trailing_zeros_frac = 0; + while (str < top) { + unsigned int dig = *str++; + if ('0' <= dig && dig <= '9') { + dig -= '0'; + if (in == PARSE_DEC_IN_EXP) { + // don't overflow exp_val when adding next digit, instead just truncate + // it and the resulting float will still be correct, either inf or 0.0 + // (use INT_MAX/2 to allow adding exp_extra at the end without overflow) + if (exp_val < (INT_MAX / 2 - 9) / 10) { + exp_val = 10 * exp_val + dig; + } + } else { + if (dig == 0 || mantissa >= MANTISSA_MAX) { + // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them. + // Also, once we reach MANTISSA_MAX, treat every additional digit as a trailing zero. + if (in == PARSE_DEC_IN_INTG) { + ++trailing_zeros_intg; + } else { + ++trailing_zeros_frac; + } + } else { + // Time to un-defer any trailing zeros. Intg zeros first. + while (trailing_zeros_intg) { + mantissa = accept_digit(mantissa, 0, &exp_extra, PARSE_DEC_IN_INTG); + --trailing_zeros_intg; + } + while (trailing_zeros_frac) { + mantissa = accept_digit(mantissa, 0, &exp_extra, PARSE_DEC_IN_FRAC); + --trailing_zeros_frac; + } + mantissa = accept_digit(mantissa, dig, &exp_extra, in); + } + } + } else if (in == PARSE_DEC_IN_INTG && dig == '.') { + in = PARSE_DEC_IN_FRAC; + } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) { + in = PARSE_DEC_IN_EXP; + if (str < top) { + if (str[0] == '+') { + str++; + } else if (str[0] == '-') { + str++; + exp_neg = true; + } + } + if (str == top) { + return NULL; + } + } else if (dig == '_') { + continue; + } else { + // unknown character + str--; + break; + } + } + + // work out the exponent + if (exp_neg) { + exp_val = -exp_val; + } + exp_val += exp_extra + trailing_zeros_intg; + + // At this point, we just need to multiply the mantissa by its base 10 exponent. + *res = (mp_float_t)mp_decimal_exp(mantissa, exp_val); + + return str; +} #endif // MICROPY_PY_BUILTINS_FLOAT #if MICROPY_PY_BUILTINS_COMPLEX @@ -253,111 +421,23 @@ parse_start:; const char *str_val_start = str; // determine what the string is - if (str < top && (str[0] | 0x20) == 'i') { - // string starts with 'i', should be 'inf' or 'infinity' (case insensitive) - if (str + 2 < top && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'f') { - // inf - str += 3; - dec_val = (mp_float_t)INFINITY; - if (str + 4 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'i' && (str[3] | 0x20) == 't' && (str[4] | 0x20) == 'y') { - // infinity - str += 5; - } - } - } else if (str < top && (str[0] | 0x20) == 'n') { - // string starts with 'n', should be 'nan' (case insensitive) - if (str + 2 < top && (str[1] | 0x20) == 'a' && (str[2] | 0x20) == 'n') { - // NaN - str += 3; - dec_val = MICROPY_FLOAT_C_FUN(nan)(""); + if (str + 2 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'f') { + // 'inf' or 'infinity' (case insensitive) + str += 3; + dec_val = (mp_float_t)INFINITY; + if (str + 4 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'i' && (str[3] | 0x20) == 't' && (str[4] | 0x20) == 'y') { + // infinity + str += 5; } + } else if (str + 2 < top && (str[0] | 0x20) == 'n' && (str[1] | 0x20) == 'a' && (str[2] | 0x20) == 'n') { + // 'nan' (case insensitive) + str += 3; + dec_val = MICROPY_FLOAT_C_FUN(nan)(""); } else { // string should be a decimal number - parse_dec_in_t in = PARSE_DEC_IN_INTG; - bool exp_neg = false; - mp_float_uint_t mantissa = 0; - int exp_val = 0; - int exp_extra = 0; - int trailing_zeros_intg = 0, trailing_zeros_frac = 0; - while (str < top) { - unsigned int dig = *str++; - if ('0' <= dig && dig <= '9') { - dig -= '0'; - if (in == PARSE_DEC_IN_EXP) { - // don't overflow exp_val when adding next digit, instead just truncate - // it and the resulting float will still be correct, either inf or 0.0 - // (use INT_MAX/2 to allow adding exp_extra at the end without overflow) - if (exp_val < (INT_MAX / 2 - 9) / 10) { - exp_val = 10 * exp_val + dig; - } - } else { - if (dig == 0 || mantissa >= MANTISSA_MAX) { - // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them. - // Also, once we reach MANTISSA_MAX, treat every additional digit as a trailing zero. - if (in == PARSE_DEC_IN_INTG) { - ++trailing_zeros_intg; - } else { - ++trailing_zeros_frac; - } - } else { - // Time to un-defer any trailing zeros. Intg zeros first. - while (trailing_zeros_intg) { - mantissa = accept_digit(mantissa, 0, &exp_extra, PARSE_DEC_IN_INTG); - --trailing_zeros_intg; - } - while (trailing_zeros_frac) { - mantissa = accept_digit(mantissa, 0, &exp_extra, PARSE_DEC_IN_FRAC); - --trailing_zeros_frac; - } - mantissa = accept_digit(mantissa, dig, &exp_extra, in); - } - } - } else if (in == PARSE_DEC_IN_INTG && dig == '.') { - in = PARSE_DEC_IN_FRAC; - } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) { - in = PARSE_DEC_IN_EXP; - if (str < top) { - if (str[0] == '+') { - str++; - } else if (str[0] == '-') { - str++; - exp_neg = true; - } - } - if (str == top) { - goto value_error; - } - } else if (dig == '_') { - continue; - } else { - // unknown character - str--; - break; - } - } - - // work out the exponent - if (exp_neg) { - exp_val = -exp_val; - } - - // apply the exponent, making sure it's not a subnormal value - exp_val += exp_extra + trailing_zeros_intg; - dec_val = (mp_float_t)mantissa; - if (exp_val < SMALL_NORMAL_EXP) { - exp_val -= SMALL_NORMAL_EXP; - dec_val *= SMALL_NORMAL_VAL; - } - - // At this point, we need to multiply the mantissa by its base 10 exponent. If possible, - // we would rather manipulate numbers that have an exact representation in IEEE754. It - // turns out small positive powers of 10 do, whereas small negative powers of 10 don't. - // So in that case, we'll yield a division of exact values rather than a multiplication - // of slightly erroneous values. - if (exp_val < 0 && exp_val >= -EXACT_POWER_OF_10) { - dec_val /= MICROPY_FLOAT_C_FUN(pow)(10, -exp_val); - } else { - dec_val *= MICROPY_FLOAT_C_FUN(pow)(10, exp_val); + str = mp_parse_float_internal(str, top - str, &dec_val); + if (!str) { + goto value_error; } } diff --git a/py/parsenum.h b/py/parsenum.h index f444632d230..d532cb194a5 100644 --- a/py/parsenum.h +++ b/py/parsenum.h @@ -34,6 +34,11 @@ mp_obj_t mp_parse_num_integer(const char *restrict str, size_t len, int base, mp_lexer_t *lex); +#if MICROPY_PY_BUILTINS_FLOAT +mp_large_float_t mp_decimal_exp(mp_large_float_t num, int dec_exp); +const char *mp_parse_float_internal(const char *str, size_t len, mp_float_t *res); +#endif + #if MICROPY_PY_BUILTINS_COMPLEX mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex); diff --git a/py/persistentcode.c b/py/persistentcode.c index 93f4c33deb4..5c3de3174bc 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -63,6 +63,10 @@ typedef struct _bytecode_prelude_t { uint code_info_size; } bytecode_prelude_t; +#if MICROPY_EMIT_RV32 +#include "py/asmrv32.h" +#endif + #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE #if MICROPY_PERSISTENT_CODE_LOAD @@ -72,6 +76,8 @@ typedef struct _bytecode_prelude_t { static int read_byte(mp_reader_t *reader); static size_t read_uint(mp_reader_t *reader); +#if MICROPY_EMIT_MACHINE_CODE + #if MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA || MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA // An mp_obj_list_t that tracks native text/BSS/rodata to prevent the GC from reclaiming them. @@ -86,8 +92,6 @@ static void track_root_pointer(void *ptr) { #endif -#if MICROPY_EMIT_MACHINE_CODE - typedef struct _reloc_info_t { mp_reader_t *reader; mp_module_context_t *context; @@ -422,15 +426,17 @@ static mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co // Relocate and commit code to executable address space reloc_info_t ri = {reader, context, rodata, bss}; + #if MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA + if (native_scope_flags & MP_SCOPE_FLAG_VIPERRELOC) { + // Track the function data memory so it's not reclaimed by the GC. + track_root_pointer(fun_data); + } + #endif #if defined(MP_PLAT_COMMIT_EXEC) void *opt_ri = (native_scope_flags & MP_SCOPE_FLAG_VIPERRELOC) ? &ri : NULL; fun_data = MP_PLAT_COMMIT_EXEC(fun_data, fun_data_len, opt_ri); #else if (native_scope_flags & MP_SCOPE_FLAG_VIPERRELOC) { - #if MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA - // Track the function data memory so it's not reclaimed by the GC. - track_root_pointer(fun_data); - #endif // Do the relocations. mp_native_relocate(&ri, fun_data, (uintptr_t)fun_data); } @@ -480,7 +486,7 @@ void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) { || header[3] > MP_SMALL_INT_BITS) { mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file")); } - if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE) { + if (arch != MP_NATIVE_ARCH_NONE) { if (!MPY_FEATURE_ARCH_TEST(arch)) { if (MPY_FEATURE_ARCH_TEST(MP_NATIVE_ARCH_NONE)) { // On supported ports this can be resolved by enabling feature, eg @@ -492,6 +498,23 @@ void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) { } } + size_t arch_flags = 0; + if (MPY_FEATURE_ARCH_FLAGS_TEST(header[2])) { + #if MICROPY_EMIT_RV32 + arch_flags = read_uint(reader); + + if (MPY_FEATURE_ARCH_TEST(MP_NATIVE_ARCH_RV32IMC)) { + if ((arch_flags & (size_t)asm_rv32_allowed_extensions()) != arch_flags) { + mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file")); + } + } else + #endif + { + (void)arch_flags; + mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file")); + } + } + size_t n_qstr = read_uint(reader); size_t n_obj = read_uint(reader); mp_module_context_alloc_tables(cm->context, n_qstr, n_obj); @@ -513,6 +536,7 @@ void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) { cm->has_native = MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE; cm->n_qstr = n_qstr; cm->n_obj = n_obj; + cm->arch_flags = arch_flags; #endif // Deregister exception handler and close the reader. @@ -682,7 +706,7 @@ void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print) { byte header[4] = { 'C', MPY_VERSION, - cm->has_native ? MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC) : 0, + (cm->arch_flags != 0 ? MPY_FEATURE_ARCH_FLAGS : 0) | (cm->has_native ? MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC) : 0), #if MICROPY_DYNAMIC_COMPILER mp_dynamic_compiler.small_int_bits, #else @@ -691,6 +715,10 @@ void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print) { }; mp_print_bytes(print, header, sizeof(header)); + if (cm->arch_flags) { + mp_print_uint(print, cm->arch_flags); + } + // Number of entries in constant table. mp_print_uint(print, cm->n_qstr); mp_print_uint(print, cm->n_obj); @@ -769,7 +797,7 @@ static void bit_vector_clear(bit_vector_t *self) { static bool bit_vector_is_set(bit_vector_t *self, size_t index) { const size_t bits_size = sizeof(*self->bits) * MP_BITS_PER_BYTE; return index / bits_size < self->alloc - && (self->bits[index / bits_size] & (1 << (index % bits_size))) != 0; + && (self->bits[index / bits_size] & ((uintptr_t)1 << (index % bits_size))) != 0; } static void bit_vector_set(bit_vector_t *self, size_t index) { @@ -780,7 +808,7 @@ static void bit_vector_set(bit_vector_t *self, size_t index) { self->bits = m_renew(uintptr_t, self->bits, self->alloc, new_alloc); self->alloc = new_alloc; } - self->bits[index / bits_size] |= 1 << (index % bits_size); + self->bits[index / bits_size] |= (uintptr_t)1 << (index % bits_size); } typedef struct _mp_opcode_t { diff --git a/py/persistentcode.h b/py/persistentcode.h index 46b474e57f7..85668e608c8 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -50,7 +50,7 @@ // Macros to encode/decode native architecture to/from the feature byte #define MPY_FEATURE_ENCODE_ARCH(arch) ((arch) << 2) -#define MPY_FEATURE_DECODE_ARCH(feat) ((feat) >> 2) +#define MPY_FEATURE_DECODE_ARCH(feat) (((feat) >> 2) & 0x2F) // Define the host architecture #if MICROPY_EMIT_X86 @@ -90,6 +90,10 @@ #define MPY_FILE_HEADER_INT (MPY_VERSION \ | (MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH)) << 8) +// Architecture-specific flags are present in the .mpy file +#define MPY_FEATURE_ARCH_FLAGS (0x40) +#define MPY_FEATURE_ARCH_FLAGS_TEST(x) (((x) & MPY_FEATURE_ARCH_FLAGS) == MPY_FEATURE_ARCH_FLAGS) + enum { MP_NATIVE_ARCH_NONE = 0, MP_NATIVE_ARCH_X86, @@ -103,6 +107,7 @@ enum { MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN, MP_NATIVE_ARCH_RV32IMC, + MP_NATIVE_ARCH_RV64IMC, MP_NATIVE_ARCH_DEBUG, // this entry should always be last }; diff --git a/py/profile.c b/py/profile.c index 397d0291f9f..b5a0c54728c 100644 --- a/py/profile.c +++ b/py/profile.c @@ -80,7 +80,7 @@ static void frame_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t "", frame, MP_CODE_QSTR_MAP(code->context, 0), - frame->lineno, + (int)frame->lineno, MP_CODE_QSTR_MAP(code->context, prelude->qstr_block_name_idx) ); } diff --git a/py/py.cmake b/py/py.cmake index 6c180ae53e6..b99d2d24b5d 100644 --- a/py/py.cmake +++ b/py/py.cmake @@ -58,6 +58,7 @@ set(MICROPY_SOURCE_PY ${MICROPY_PY_DIR}/mpz.c ${MICROPY_PY_DIR}/nativeglue.c ${MICROPY_PY_DIR}/nlr.c + ${MICROPY_PY_DIR}/nlraarch64.c ${MICROPY_PY_DIR}/nlrmips.c ${MICROPY_PY_DIR}/nlrpowerpc.c ${MICROPY_PY_DIR}/nlrrv32.c diff --git a/py/py.mk b/py/py.mk index c05327bf81d..21be07c794f 100644 --- a/py/py.mk +++ b/py/py.mk @@ -191,6 +191,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ objnamedtuple.o \ objrange.o \ objreversed.o \ + objringio.o \ objset.o \ objsingleton.o \ objslice.o \ @@ -289,7 +290,7 @@ $(HEADER_BUILD)/compressed_translations.generated.h: $(PY_SRC)/maketranslationda PY_CORE_O += $(PY_BUILD)/translations-$(TRANSLATION).o # build a list of registered modules for py/objmodule.c. -$(HEADER_BUILD)/moduledefs.h: $(HEADER_BUILD)/moduledefs.collected +$(HEADER_BUILD)/moduledefs.h: $(HEADER_BUILD)/moduledefs.collected $(PY_SRC)/makemoduledefs.py @$(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makemoduledefs.py $< > $@ diff --git a/py/repl.c b/py/repl.c index c9a20305c79..bbfdd2ea6a6 100644 --- a/py/repl.c +++ b/py/repl.c @@ -181,8 +181,11 @@ static bool test_qstr(mp_obj_t obj, qstr name) { return dest[0] != MP_OBJ_NULL; } else { // try builtin module - return mp_map_lookup((mp_map_t *)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP) || - mp_map_lookup((mp_map_t *)&mp_builtin_extensible_module_map, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP); + return mp_map_lookup((mp_map_t *)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP) + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES + || mp_map_lookup((mp_map_t *)&mp_builtin_extensible_module_map, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP) + #endif + ; } } @@ -237,6 +240,10 @@ static void print_completions(const mp_print_t *print, for (qstr q = q_first; q <= q_last; ++q) { size_t d_len; const char *d_str = (const char *)qstr_data(q, &d_len); + // filter out words that begin with underscore unless there's already a partial match + if (s_len == 0 && d_str[0] == '_') { + continue; + } if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { if (test_qstr(obj, q)) { int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len; diff --git a/py/runtime.c b/py/runtime.c index 9def98380fa..81abc3de875 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -134,7 +134,7 @@ void mp_init(void) { MP_STATE_VM(mp_module_builtins_override_dict) = NULL; #endif - #if MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA || MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA + #if MICROPY_EMIT_MACHINE_CODE && (MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA || MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA) MP_STATE_VM(persistent_code_root_pointers) = MP_OBJ_NULL; #endif @@ -446,7 +446,7 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs // Operations that can overflow: // + result always fits in mp_int_t, then handled by SMALL_INT check // - result always fits in mp_int_t, then handled by SMALL_INT check - // * checked explicitly + // * checked explicitly for fit in mp_int_t, then handled by SMALL_INT check // / if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check // % if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check // << checked explicitly @@ -505,30 +505,16 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: { - - // If long long type exists and is larger than mp_int_t, then - // we can use the following code to perform overflow-checked multiplication. - // Otherwise (eg in x64 case) we must use mp_small_int_mul_overflow. - #if 0 - // compute result using long long precision - long long res = (long long)lhs_val * (long long)rhs_val; - if (res > MP_SMALL_INT_MAX || res < MP_SMALL_INT_MIN) { - // result overflowed SMALL_INT, so return higher precision integer - return mp_obj_new_int_from_ll(res); - } else { - // use standard precision - lhs_val = (mp_int_t)res; - } - #endif - - if (mp_small_int_mul_overflow(lhs_val, rhs_val)) { + mp_int_t int_res; + if (mp_mul_mp_int_t_overflow(lhs_val, rhs_val, &int_res)) { // use higher precision lhs = mp_obj_new_int_from_ll(lhs_val); goto generic_binary_op; } else { // use standard precision - return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val); + lhs_val = int_res; } + break; } case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: @@ -568,19 +554,19 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs mp_int_t ans = 1; while (rhs_val > 0) { if (rhs_val & 1) { - if (mp_small_int_mul_overflow(ans, lhs_val)) { + if (mp_mul_mp_int_t_overflow(ans, lhs_val, &ans)) { goto power_overflow; } - ans *= lhs_val; } if (rhs_val == 1) { break; } rhs_val /= 2; - if (mp_small_int_mul_overflow(lhs_val, lhs_val)) { + mp_int_t int_res; + if (mp_mul_mp_int_t_overflow(lhs_val, lhs_val, &int_res)) { goto power_overflow; } - lhs_val *= lhs_val; + lhs_val = int_res; } lhs_val = ans; } @@ -976,7 +962,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ob // unpacked items are stored in reverse order into the array pointed to by items // CIRCUITPY-CHANGE: noline -void __attribute__((noinline, )) mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) { +MP_NOINLINE void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) { size_t seq_len; if (mp_obj_is_type(seq_in, &mp_type_tuple) || mp_obj_is_type(seq_in, &mp_type_list)) { mp_obj_t *seq_items; @@ -1301,6 +1287,19 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { mp_raise_msg_varg(&mp_type_AttributeError, MP_ERROR_TEXT("type object '%q' has no attribute '%q'"), ((mp_obj_type_t *)MP_OBJ_TO_PTR(base))->name, attr); + #if MICROPY_MODULE___ALL__ && MICROPY_ERROR_REPORTING >= MICROPY_ERROR_REPORTING_DETAILED + } else if (mp_obj_is_type(base, &mp_type_module)) { + // report errors in __all__ as done by CPython + mp_obj_t dest_name[2]; + qstr module_name = MP_QSTR_; + mp_load_method_maybe(base, MP_QSTR___name__, dest_name); + if (mp_obj_is_qstr(dest_name[0])) { + module_name = mp_obj_str_get_qstr(dest_name[0]); + } + mp_raise_msg_varg(&mp_type_AttributeError, + MP_ERROR_TEXT("module '%q' has no attribute '%q'"), + module_name, attr); + #endif } else { mp_raise_msg_varg(&mp_type_AttributeError, MP_ERROR_TEXT("'%s' object has no attribute '%q'"), @@ -1619,7 +1618,7 @@ mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) { // build args array mp_obj_t args[5]; args[0] = MP_OBJ_NEW_QSTR(name); - args[1] = mp_const_none; // TODO should be globals + args[1] = MP_OBJ_FROM_PTR(mp_globals_get()); // globals of the current context args[2] = mp_const_none; // TODO should be locals args[3] = fromlist; args[4] = level; @@ -1639,20 +1638,17 @@ mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) { } // CIRCUITPY-CHANGE: noinline -mp_obj_t __attribute__((noinline, )) mp_import_from(mp_obj_t module, qstr name) { +MP_NOINLINE mp_obj_t mp_import_from(mp_obj_t module, qstr name) { DEBUG_printf("import from %p %s\n", module, qstr_str(name)); mp_obj_t dest[2]; mp_load_method_maybe(module, name, dest); - if (dest[1] != MP_OBJ_NULL) { - // Hopefully we can't import bound method from an object - import_error: - mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("can't import name %q"), name); - } - - if (dest[0] != MP_OBJ_NULL) { + // Importing a bound method from a class instance. + return mp_obj_new_bound_meth(dest[0], dest[1]); + } else if (dest[0] != MP_OBJ_NULL) { + // Importing a function or attribute. return dest[0]; } @@ -1685,13 +1681,36 @@ mp_obj_t __attribute__((noinline, )) mp_import_from(mp_obj_t module, qstr name) goto import_error; #endif + +import_error: + mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("can't import name %q"), name); } void mp_import_all(mp_obj_t module) { DEBUG_printf("import all %p\n", module); - // TODO: Support __all__ mp_map_t *map = &mp_obj_module_get_globals(module)->map; + + #if MICROPY_MODULE___ALL__ + mp_map_elem_t *elem = mp_map_lookup(map, MP_OBJ_NEW_QSTR(MP_QSTR___all__), MP_MAP_LOOKUP); + if (elem != NULL) { + // When __all__ is defined, we must explicitly load all specified + // symbols, possibly invoking the module __getattr__ function + size_t len; + mp_obj_t *items; + mp_obj_get_array(elem->value, &len, &items); + for (size_t i = 0; i < len; i++) { + qstr qname = mp_obj_str_get_qstr(items[i]); + mp_obj_t dest[2]; + mp_load_method(module, qname, dest); + mp_store_name(qname, dest[0]); + } + return; + } + #endif + + // By default, the set of public names includes all names found in the module's + // namespace which do not begin with an underscore character ('_') for (size_t i = 0; i < map->alloc; i++) { if (mp_map_slot_is_filled(map, i)) { // Entry in module global scope may be generated programmatically @@ -1747,7 +1766,7 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i #endif // MICROPY_ENABLE_COMPILER // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void m_malloc_fail(size_t num_bytes) { +MP_COLD MP_NORETURN void m_malloc_fail(size_t num_bytes) { DEBUG_printf("memory allocation failed, allocating %u bytes\n", (uint)num_bytes); #if MICROPY_ENABLE_GC if (gc_is_locked()) { @@ -1761,29 +1780,29 @@ NORETURN MP_COLD void m_malloc_fail(size_t num_bytes) { #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NONE // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_type(const mp_obj_type_t *exc_type) { +MP_COLD MP_NORETURN void mp_raise_type(const mp_obj_type_t *exc_type) { nlr_raise(mp_obj_new_exception(exc_type)); } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_ValueError_no_msg(void) { +MP_COLD MP_NORETURN void mp_raise_ValueError_no_msg(void) { mp_raise_type(&mp_type_ValueError); } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_TypeError_no_msg(void) { +MP_COLD MP_NORETURN void mp_raise_TypeError_no_msg(void) { mp_raise_type(&mp_type_TypeError); } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_NotImplementedError_no_msg(void) { +MP_COLD MP_NORETURN void mp_raise_NotImplementedError_no_msg(void) { mp_raise_type(&mp_type_NotImplementedError); } #else // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg) { if (msg == NULL) { nlr_raise(mp_obj_new_exception(exc_type)); } else { @@ -1792,24 +1811,24 @@ NORETURN MP_COLD void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_t } // CIRCUITPY-CHANGE: new function for use below. -NORETURN MP_COLD void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, va_list argptr) { +MP_COLD MP_NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, va_list argptr) { mp_obj_t exception = mp_obj_new_exception_msg_vlist(exc_type, fmt, argptr); nlr_raise(exception); } // CIRCUITPY-CHANGE: MP_COLD and use mp_raise_msg_vlist() -NORETURN MP_COLD void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(exc_type, fmt, argptr); va_end(argptr); } -NORETURN MP_COLD void mp_raise_ValueError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_ValueError, msg); } -NORETURN MP_COLD void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char *msg) { +MP_COLD MP_NORETURN void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char *msg) { if (msg == NULL) { nlr_raise(mp_obj_new_exception(exc_type)); } else { @@ -1818,17 +1837,17 @@ NORETURN MP_COLD void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_AttributeError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_AttributeError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_AttributeError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_RuntimeError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_RuntimeError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_RuntimeError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_RuntimeError, fmt, argptr); @@ -1836,17 +1855,17 @@ NORETURN MP_COLD void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_ImportError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_ImportError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_ImportError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_IndexError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_IndexError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_IndexError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_IndexError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_IndexError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_IndexError, fmt, argptr); @@ -1854,7 +1873,7 @@ NORETURN MP_COLD void mp_raise_IndexError_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_ValueError, fmt, argptr); @@ -1862,12 +1881,12 @@ NORETURN MP_COLD void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_TypeError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_TypeError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_TypeError, fmt, argptr); @@ -1875,12 +1894,12 @@ NORETURN MP_COLD void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_OSError_msg(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_OSError_msg(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_OSError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_OSError_errno_str(int errno_, mp_obj_t str) { +MP_COLD MP_NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str) { mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(errno_), str, @@ -1889,7 +1908,7 @@ NORETURN MP_COLD void mp_raise_OSError_errno_str(int errno_, mp_obj_t str) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_OSError, fmt, argptr); @@ -1897,21 +1916,23 @@ NORETURN MP_COLD void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_ConnectionError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_ConnectionError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_ConnectionError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_BrokenPipeError(void) { +MP_COLD MP_NORETURN void mp_raise_BrokenPipeError(void) { mp_raise_type_arg(&mp_type_BrokenPipeError, MP_OBJ_NEW_SMALL_INT(MP_EPIPE)); } -NORETURN MP_COLD void mp_raise_NotImplementedError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_NotImplementedError, msg); } +#endif + // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_NotImplementedError, fmt, argptr); @@ -1919,7 +1940,7 @@ NORETURN MP_COLD void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_OverflowError, fmt, argptr); @@ -1927,11 +1948,11 @@ NORETURN MP_COLD void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...) } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg) { +MP_COLD MP_NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg) { nlr_raise(mp_obj_new_exception_arg1(exc_type, arg)); } -NORETURN void mp_raise_StopIteration(mp_obj_t arg) { +MP_NORETURN void mp_raise_StopIteration(mp_obj_t arg) { if (arg == MP_OBJ_NULL) { mp_raise_type(&mp_type_StopIteration); } else { @@ -1939,7 +1960,7 @@ NORETURN void mp_raise_StopIteration(mp_obj_t arg) { } } -NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg) { +MP_NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE (void)arg; mp_raise_TypeError(MP_ERROR_TEXT("can't convert to int")); @@ -1950,12 +1971,12 @@ NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg) { } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_OSError(int errno_) { +MP_COLD MP_NORETURN void mp_raise_OSError(int errno_) { mp_raise_type_arg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_)); } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_OSError_with_filename(int errno_, const char *filename) { +MP_COLD MP_NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename) { vstr_t vstr; vstr_init(&vstr, 32); vstr_printf(&vstr, "can't open %s", filename); @@ -1965,13 +1986,12 @@ NORETURN MP_COLD void mp_raise_OSError_with_filename(int errno_, const char *fil } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_ZeroDivisionError(void) { +MP_COLD MP_NORETURN void mp_raise_ZeroDivisionError(void) { mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("division by zero")); } #if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_recursion_depth(void) { +MP_COLD MP_NORETURN void mp_raise_recursion_depth(void) { mp_raise_RuntimeError(MP_ERROR_TEXT("maximum recursion depth exceeded")); } #endif -#endif diff --git a/py/runtime.h b/py/runtime.h index a2d69638ffc..22ed9c3eaf9 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -37,11 +37,12 @@ #include "supervisor/shared/translate/translate.h" // For use with mp_call_function_1_from_nlr_jump_callback. +// Initialize an nlr_jump_callback_node_call_function_1_t struct for use with +// nlr_push_jump_callback(&ctx.callback, mp_call_function_1_from_nlr_jump_callback); #define MP_DEFINE_NLR_JUMP_CALLBACK_FUNCTION_1(ctx, f, a) \ - nlr_jump_callback_node_call_function_1_t ctx = { \ - .func = (void (*)(void *))(f), \ - .arg = (a), \ - } + nlr_jump_callback_node_call_function_1_t ctx; \ + ctx.func = (void (*)(void *))(f); \ + ctx.arg = (a) typedef enum { MP_VM_RETURN_NORMAL, @@ -58,6 +59,12 @@ typedef enum { MP_ARG_KW_ONLY = 0x200, } mp_arg_flag_t; +typedef enum { + MP_HANDLE_PENDING_CALLBACKS_ONLY, + MP_HANDLE_PENDING_CALLBACKS_AND_EXCEPTIONS, + MP_HANDLE_PENDING_CALLBACKS_AND_CLEAR_EXCEPTIONS, +} mp_handle_pending_behaviour_t; + typedef union _mp_arg_val_t { bool u_bool; mp_int_t u_int; @@ -106,7 +113,14 @@ void mp_sched_keyboard_interrupt(void); #if MICROPY_ENABLE_VM_ABORT void mp_sched_vm_abort(void); #endif -void mp_handle_pending(bool raise_exc); + +void mp_handle_pending_internal(mp_handle_pending_behaviour_t behavior); + +static inline void mp_handle_pending(bool raise_exc) { + mp_handle_pending_internal(raise_exc ? + MP_HANDLE_PENDING_CALLBACKS_AND_EXCEPTIONS : + MP_HANDLE_PENDING_CALLBACKS_AND_CLEAR_EXCEPTIONS); +} #if MICROPY_ENABLE_SCHEDULER void mp_sched_lock(void); @@ -134,7 +148,7 @@ void mp_event_wait_indefinite(void); void mp_event_wait_ms(mp_uint_t timeout_ms); // extra printing method specifically for mp_obj_t's which are integral type -int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec); +int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, unsigned base, int base_char, int flags, char fill, int width, int prec); void mp_arg_check_num_sig(size_t n_args, size_t n_kw, uint32_t sig); static inline void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) { @@ -142,11 +156,11 @@ static inline void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_mi } void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); -NORETURN void mp_arg_error_terse_mismatch(void); -NORETURN void mp_arg_error_unimpl_kw(void); +MP_NORETURN void mp_arg_error_terse_mismatch(void); +MP_NORETURN void mp_arg_error_unimpl_kw(void); // CIRCUITPY-CHANGE: arg validation routines -NORETURN void mp_arg_error_invalid(qstr arg_name); +MP_NORETURN void mp_arg_error_invalid(qstr arg_name); mp_int_t mp_arg_validate_int(mp_int_t i, mp_int_t required_i, qstr arg_name); mp_int_t mp_arg_validate_int_min(mp_int_t i, mp_int_t min, qstr arg_name); mp_int_t mp_arg_validate_int_max(mp_int_t i, mp_int_t j, qstr arg_name); @@ -194,9 +208,16 @@ static inline void mp_thread_init_state(mp_state_thread_t *ts, size_t stack_size ts->gc_lock_depth = 0; // There are no pending jump callbacks or exceptions yet + ts->nlr_top = NULL; ts->nlr_jump_callback_top = NULL; ts->mp_pending_exception = MP_OBJ_NULL; + #if MICROPY_PY_SYS_SETTRACE + ts->prof_trace_callback = MP_OBJ_NULL; + ts->prof_callback_is_executing = false; + ts->current_code_state = NULL; + #endif + // If locals/globals are not given, inherit from main thread if (locals == NULL) { locals = mp_state_ctx.thread.dict_locals; @@ -274,10 +295,10 @@ mp_obj_t mp_import_from(mp_obj_t module, qstr name); void mp_import_all(mp_obj_t module); #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NONE -NORETURN void mp_raise_type(const mp_obj_type_t *exc_type); -NORETURN void mp_raise_ValueError_no_msg(void); -NORETURN void mp_raise_TypeError_no_msg(void); -NORETURN void mp_raise_NotImplementedError_no_msg(void); +MP_NORETURN void mp_raise_type(const mp_obj_type_t *exc_type); +MP_NORETURN void mp_raise_ValueError_no_msg(void); +MP_NORETURN void mp_raise_TypeError_no_msg(void); +MP_NORETURN void mp_raise_NotImplementedError_no_msg(void); #define mp_raise_msg(exc_type, msg) mp_raise_type(exc_type) #define mp_raise_msg_varg(exc_type, ...) mp_raise_type(exc_type) #define mp_raise_ValueError(msg) mp_raise_ValueError_no_msg() @@ -285,46 +306,46 @@ NORETURN void mp_raise_NotImplementedError_no_msg(void); #define mp_raise_NotImplementedError(msg) mp_raise_NotImplementedError_no_msg() #else #define mp_raise_type(exc_type) mp_raise_msg(exc_type, NULL) -NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg); -NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg); -NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg); -NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg); #endif // CIRCUITPY-CHANGE: new mp_raise routines -NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg); -NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg); -NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt +MP_NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg); +MP_NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt , ...); -NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, va_list argptr); +MP_NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, va_list argptr); // Only use this string version in native mpy files. Otherwise, use the compressed string version. -NORETURN void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char *msg); - -NORETURN void mp_raise_AttributeError(mp_rom_error_text_t msg); -NORETURN void mp_raise_BrokenPipeError(void); -NORETURN void mp_raise_ConnectionError(mp_rom_error_text_t msg); -NORETURN void mp_raise_ImportError(mp_rom_error_text_t msg); -NORETURN void mp_raise_IndexError(mp_rom_error_text_t msg); -NORETURN void mp_raise_IndexError_varg(mp_rom_error_text_t msg, ...); -NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg); -NORETURN void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str); -NORETURN void mp_raise_OSError(int errno_); -NORETURN void mp_raise_OSError_msg(mp_rom_error_text_t msg); -NORETURN void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename); -NORETURN void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_recursion_depth(void); -NORETURN void mp_raise_RuntimeError(mp_rom_error_text_t msg); -NORETURN void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_StopIteration(mp_obj_t arg); -NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg); -NORETURN void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg); -NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg); -NORETURN void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_ZeroDivisionError(void); +MP_NORETURN void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char *msg); + +MP_NORETURN void mp_raise_AttributeError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_BrokenPipeError(void); +MP_NORETURN void mp_raise_ConnectionError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_ImportError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_IndexError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_IndexError_varg(mp_rom_error_text_t msg, ...); +MP_NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str); +MP_NORETURN void mp_raise_OSError(int errno_); +MP_NORETURN void mp_raise_OSError_msg(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename); +MP_NORETURN void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_recursion_depth(void); +MP_NORETURN void mp_raise_RuntimeError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_StopIteration(mp_obj_t arg); +MP_NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg); +MP_NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_ZeroDivisionError(void); #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG #undef mp_check_self diff --git a/py/runtime_utils.c b/py/runtime_utils.c index 98252c31220..33da558e30f 100644 --- a/py/runtime_utils.c +++ b/py/runtime_utils.c @@ -53,3 +53,59 @@ mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2 return MP_OBJ_NULL; } } + +#if !MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC +bool mp_mul_ll_overflow(long long int x, long long int y, long long int *res) { + bool overflow; + + // Check for multiply overflow; see CERT INT32-C + if (x > 0) { // x is positive + if (y > 0) { // x and y are positive + overflow = (x > (LLONG_MAX / y)); + } else { // x positive, y nonpositive + overflow = (y < (LLONG_MIN / x)); + } // x positive, y nonpositive + } else { // x is nonpositive + if (y > 0) { // x is nonpositive, y is positive + overflow = (x < (LLONG_MIN / y)); + } else { // x and y are nonpositive + overflow = (x != 0 && y < (LLONG_MAX / x)); + } // End if x and y are nonpositive + } // End if x is nonpositive + + if (!overflow) { + *res = x * y; + } + + return overflow; +} + +bool mp_mul_mp_int_t_overflow(mp_int_t x, mp_int_t y, mp_int_t *res) { + // Check for multiply overflow; see CERT INT32-C + if (x > 0) { // x is positive + if (y > 0) { // x and y are positive + if (x > (MP_INT_MAX / y)) { + return true; + } + } else { // x positive, y nonpositive + if (y < (MP_INT_MIN / x)) { + return true; + } + } // x positive, y nonpositive + } else { // x is nonpositive + if (y > 0) { // x is nonpositive, y is positive + if (x < (MP_INT_MIN / y)) { + return true; + } + } else { // x and y are nonpositive + if (x != 0 && y < (MP_INT_MAX / x)) { + return true; + } + } // End if x and y are nonpositive + } // End if x is nonpositive + + // Result doesn't overflow + *res = x * y; + return false; +} +#endif diff --git a/py/scheduler.c b/py/scheduler.c index 92e5af6b31b..ee9cd96b331 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -97,17 +97,21 @@ static inline void mp_sched_run_pending(void) { #if MICROPY_SCHEDULER_STATIC_NODES // Run all pending C callbacks. - while (MP_STATE_VM(sched_head) != NULL) { - mp_sched_node_t *node = MP_STATE_VM(sched_head); - MP_STATE_VM(sched_head) = node->next; - if (MP_STATE_VM(sched_head) == NULL) { - MP_STATE_VM(sched_tail) = NULL; - } - mp_sched_callback_t callback = node->callback; - node->callback = NULL; - MICROPY_END_ATOMIC_SECTION(atomic_state); - callback(node); - atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + mp_sched_node_t *original_tail = MP_STATE_VM(sched_tail); + if (original_tail != NULL) { + mp_sched_node_t *node; + do { + node = MP_STATE_VM(sched_head); + MP_STATE_VM(sched_head) = node->next; + if (MP_STATE_VM(sched_head) == NULL) { + MP_STATE_VM(sched_tail) = NULL; + } + mp_sched_callback_t callback = node->callback; + node->callback = NULL; + MICROPY_END_ATOMIC_SECTION(atomic_state); + callback(node); + atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + } while (node != original_tail); // Don't execute any callbacks scheduled during this run } #endif @@ -218,24 +222,27 @@ MP_REGISTER_ROOT_POINTER(mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH]); // Called periodically from the VM or from "waiting" code (e.g. sleep) to // process background tasks and pending exceptions (e.g. KeyboardInterrupt). -void mp_handle_pending(bool raise_exc) { +void mp_handle_pending_internal(mp_handle_pending_behaviour_t behavior) { + bool handle_exceptions = (behavior != MP_HANDLE_PENDING_CALLBACKS_ONLY); + bool raise_exceptions = (behavior == MP_HANDLE_PENDING_CALLBACKS_AND_EXCEPTIONS); + // Handle pending VM abort. #if MICROPY_ENABLE_VM_ABORT - if (MP_STATE_VM(vm_abort) && mp_thread_is_main_thread()) { + if (handle_exceptions && MP_STATE_VM(vm_abort) && mp_thread_is_main_thread()) { MP_STATE_VM(vm_abort) = false; - if (raise_exc && nlr_get_abort() != NULL) { + if (raise_exceptions && nlr_get_abort() != NULL) { nlr_jump_abort(); } } #endif // Handle any pending exception. - if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) { + if (handle_exceptions && MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); if (obj != MP_OBJ_NULL) { MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - if (raise_exc) { + if (raise_exceptions) { MICROPY_END_ATOMIC_SECTION(atomic_state); nlr_raise(obj); } diff --git a/py/sequence.c b/py/sequence.c index ac7ad5368b9..6bbc62f0f7f 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -34,18 +34,13 @@ #define SWAP(type, var1, var2) { type t = var2; var2 = var1; var1 = t; } // CIRCUITPY-CHANGE: detect sequence overflow -#if __GNUC__ < 5 -// n.b. does not actually detect overflow! -#define __builtin_mul_overflow(a, b, x) (*(x) = (a) * (b), false) -#endif - // Detect when a multiply causes an overflow. size_t mp_seq_multiply_len(size_t item_sz, size_t len) { - size_t new_len; - if (__builtin_mul_overflow(item_sz, len, &new_len)) { + mp_int_t new_len; + if (mp_mul_mp_int_t_overflow(item_sz, len, &new_len)) { mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow")); } - return new_len; + return (size_t)new_len; } // Implements backend of sequence * integer operation. Assumes elements are diff --git a/py/showbc.c b/py/showbc.c index 6913d18c1ca..792fccd0133 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -144,17 +144,9 @@ void mp_bytecode_print(const mp_print_t *print, const mp_raw_code_t *rc, size_t mp_uint_t source_line = 1; mp_printf(print, " bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line); for (const byte *ci = code_info; ci < line_info_top;) { - if ((ci[0] & 0x80) == 0) { - // 0b0LLBBBBB encoding - bc += ci[0] & 0x1f; - source_line += ci[0] >> 5; - ci += 1; - } else { - // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) - bc += ci[0] & 0xf; - source_line += ((ci[0] << 4) & 0x700) | ci[1]; - ci += 2; - } + mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo(&ci); + bc += decoded.bc_increment; + source_line += decoded.line_increment; mp_printf(print, " bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line); } } diff --git a/py/smallint.c b/py/smallint.c index aa542ca7bf2..eb99b58667a 100644 --- a/py/smallint.c +++ b/py/smallint.c @@ -26,32 +26,6 @@ #include "py/smallint.h" -bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) { - // Check for multiply overflow; see CERT INT32-C - if (x > 0) { // x is positive - if (y > 0) { // x and y are positive - if (x > (MP_SMALL_INT_MAX / y)) { - return true; - } - } else { // x positive, y nonpositive - if (y < (MP_SMALL_INT_MIN / x)) { - return true; - } - } // x positive, y nonpositive - } else { // x is nonpositive - if (y > 0) { // x is nonpositive, y is positive - if (x < (MP_SMALL_INT_MIN / y)) { - return true; - } - } else { // x and y are nonpositive - if (x != 0 && y < (MP_SMALL_INT_MAX / x)) { - return true; - } - } // End if x and y are nonpositive - } // End if x is nonpositive - return false; -} - mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor) { // Python specs require that mod has same sign as second operand dividend %= divisor; diff --git a/py/smallint.h b/py/smallint.h index 584e0018d1b..ec5b0af3b28 100644 --- a/py/smallint.h +++ b/py/smallint.h @@ -68,7 +68,6 @@ // The number of bits in a MP_SMALL_INT including the sign bit. #define MP_SMALL_INT_BITS (MP_IMAX_BITS(MP_SMALL_INT_MAX) + 1) -bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y); mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor); mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom); diff --git a/py/stream.c b/py/stream.c index fbf7fd878a1..520422cc92f 100644 --- a/py/stream.c +++ b/py/stream.c @@ -260,9 +260,14 @@ void mp_stream_write_adaptor(void *self, const char *buf, size_t len) { mp_stream_write(MP_OBJ_FROM_PTR(self), buf, len, MP_STREAM_RW_WRITE); } -static mp_obj_t stream_write_method(size_t n_args, const mp_obj_t *args) { +static mp_obj_t stream_readinto_write_generic(size_t n_args, const mp_obj_t *args, byte flags) { mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &bufinfo, (flags & MP_STREAM_RW_WRITE) ? MP_BUFFER_READ : MP_BUFFER_WRITE); + + // CPython extension, allow optional maximum length and offset: + // - stream.operation(buf, max_len) + // - stream.operation(buf, off, max_len) + // Similar to https://docs.python.org/3/library/socket.html#socket.socket.recv_into size_t max_len = (size_t)-1; size_t off = 0; if (n_args == 3) { @@ -275,45 +280,31 @@ static mp_obj_t stream_write_method(size_t n_args, const mp_obj_t *args) { } } bufinfo.len -= off; - return mp_stream_write(args[0], (byte *)bufinfo.buf + off, MIN(bufinfo.len, max_len), MP_STREAM_RW_WRITE); + + // Perform the readinto or write operation. + return mp_stream_write(args[0], (byte *)bufinfo.buf + off, MIN(bufinfo.len, max_len), flags); +} + +static mp_obj_t stream_write_method(size_t n_args, const mp_obj_t *args) { + return stream_readinto_write_generic(n_args, args, MP_STREAM_RW_WRITE); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj, 2, 4, stream_write_method); -static mp_obj_t stream_write1_method(mp_obj_t self_in, mp_obj_t arg) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); - return mp_stream_write(self_in, bufinfo.buf, bufinfo.len, MP_STREAM_RW_WRITE | MP_STREAM_RW_ONCE); +static mp_obj_t stream_write1_method(size_t n_args, const mp_obj_t *args) { + return stream_readinto_write_generic(n_args, args, MP_STREAM_RW_WRITE | MP_STREAM_RW_ONCE); } -MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write1_obj, stream_write1_method); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write1_obj, 2, 4, stream_write1_method); static mp_obj_t stream_readinto(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); - - // CPython extension: if 2nd arg is provided, that's max len to read, - // instead of full buffer. Similar to - // https://docs.python.org/3/library/socket.html#socket.socket.recv_into - mp_uint_t len = bufinfo.len; - if (n_args > 2) { - len = mp_obj_get_int(args[2]); - if (len > bufinfo.len) { - len = bufinfo.len; - } - } - - int error; - mp_uint_t out_sz = mp_stream_read_exactly(args[0], bufinfo.buf, len, &error); - if (error != 0) { - if (mp_is_nonblocking_error(error)) { - return mp_const_none; - } - mp_raise_OSError(error); - } else { - return MP_OBJ_NEW_SMALL_INT(out_sz); - } + return stream_readinto_write_generic(n_args, args, MP_STREAM_RW_READ); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj, 2, 3, stream_readinto); +static mp_obj_t stream_readinto1(size_t n_args, const mp_obj_t *args) { + return stream_readinto_write_generic(n_args, args, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto1_obj, 2, 3, stream_readinto1); + static mp_obj_t stream_readall(mp_obj_t self_in) { const mp_stream_p_t *stream_p = mp_get_stream(self_in); diff --git a/py/stream.h b/py/stream.h index 5e1cd5d4413..6e60e849b5f 100644 --- a/py/stream.h +++ b/py/stream.h @@ -87,10 +87,11 @@ typedef struct _mp_stream_p_t { MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read1_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto1_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj); -MP_DECLARE_CONST_FUN_OBJ_2(mp_stream_write1_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write1_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_close_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream___exit___obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj); diff --git a/py/vm.c b/py/vm.c index 6fd17782619..860aa36e397 100644 --- a/py/vm.c +++ b/py/vm.c @@ -205,6 +205,22 @@ static mp_obj_t get_active_exception(mp_exc_stack_t *exc_sp, mp_exc_stack_t *exc return MP_OBJ_NULL; } +#if MICROPY_PY_BUILTINS_SLICE +// This function is marked "no inline" so it doesn't increase the C stack usage of the main VM function. +MP_NOINLINE static mp_obj_t *build_slice_stack_allocated(byte op, mp_obj_t *sp, mp_obj_t step) { + mp_obj_t stop = sp[2]; + mp_obj_t start = sp[1]; + mp_obj_slice_t slice = { .base = { .type = &mp_type_slice }, .start = start, .stop = stop, .step = step }; + if (op == MP_BC_LOAD_SUBSCR) { + SET_TOP(mp_obj_subscr(TOP(), MP_OBJ_FROM_PTR(&slice), MP_OBJ_SENTINEL)); + } else { // MP_BC_STORE_SUBSCR + mp_obj_subscr(TOP(), MP_OBJ_FROM_PTR(&slice), sp[-1]); + sp -= 2; + } + return sp; +} +#endif + // fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc) // sp points to bottom of stack which grows up // returns: @@ -871,9 +887,20 @@ unwind_jump:; // 3-argument slice includes step step = POP(); } - mp_obj_t stop = POP(); - mp_obj_t start = TOP(); - SET_TOP(mp_obj_new_slice(start, stop, step)); + if ((*ip == MP_BC_LOAD_SUBSCR || *ip == MP_BC_STORE_SUBSCR) + && (mp_obj_get_type(sp[-2])->flags & MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE)) { + // Fast path optimisation for when the BUILD_SLICE is immediately followed + // by a LOAD/STORE_SUBSCR for an accepting type, to avoid needing to allocate + // the slice on the heap. In some cases (e.g. a[1:3] = x) this can result + // in no allocations at all. We can't do this for instance types because + // the get/set/delattr implementation may keep a reference to the slice. + byte op = *ip++; + sp = build_slice_stack_allocated(op, sp - 2, step); + } else { + mp_obj_t stop = POP(); + mp_obj_t start = TOP(); + SET_TOP(mp_obj_new_slice(start, stop, step)); + } DISPATCH(); } #endif diff --git a/py/vstr.c b/py/vstr.c index 00972edf897..522509d0d05 100644 --- a/py/vstr.c +++ b/py/vstr.c @@ -51,7 +51,7 @@ void vstr_init(vstr_t *vstr, size_t alloc) { // Init the vstr so it allocs exactly enough ram to hold a null-terminated // string of the given length, and set the length. void vstr_init_len(vstr_t *vstr, size_t len) { - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: check for invalid length if (len == SIZE_MAX) { m_malloc_fail(len); } diff --git a/pyproject.toml b/pyproject.toml index 7003a6af9ae..5f84ca104ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,35 +1,26 @@ -# SPDX-FileCopyrightText: 2024 Scott Shawcroft for Adafruit Industries -# -# SPDX-License-Identifier: MIT - -[tool.setuptools_scm] # can be empty if no extra settings are needed, presence enables setuptools-scm - -# Codespell settings copied from MicroPython - [tool.ruff] -target-version = "py37" - +target-version = "py312" line-length = 99 -# Exclude third-party code from linting and formatting. Ruff doesn't know how to ignore submodules. -# Exclude the following tests: -# repl_: not real python files -# viper_args: uses f(*) +# Include Python source files that don't end with .py +extend-include = [ "tools/cc1" ] +# Exclude third-party code from linting and formatting extend-exclude = [ + # CIRCUITPY-CHANGES "extmod/ulab", "frozen", "lib", "ports/analog/msdk", "ports/atmel-samd/asf4", "ports/broadcom/peripherals", + "ports/espress/tools", "ports/espressif/esp-idf", "ports/espressif/esp-protocols", "ports/raspberrypi/sdk", "ports/silabs/gecko_sdk", "ports/silabs/tools/slc_cli_linux", "ports/stm/st_driver", - "tests/*/repl_*.py", - "tests/micropython/viper_args.py", + "tests/cpydiff/syntax_assign_expr.py", # intentionally incorrect CPython code "tools/adabot", "tools/bitmap_font", "tools/cc1", @@ -40,9 +31,32 @@ extend-exclude = [ ] # Exclude third-party code, and exclude the following tests: # basics: needs careful attention before applying automatic formatting -format.exclude = [ "tests/basics/*.py" ] +# repl_: not real python files +# viper_args: uses f(*) +format.exclude = [ + "tests/*/repl_*.py", + "tests/basics/*.py", + "tests/cmdline/cmd_compile_only_error.py", + "tests/micropython/test_normalize_newlines.py", + "tests/micropython/viper_args.py", +] lint.extend-select = [ "C9", "PLC" ] -lint.ignore = [ +lint.exclude = [ + # Ruff finds Python SyntaxError in these files + "tests/cmdline/cmd_compile_only_error.py", + "tests/cmdline/repl_autocomplete.py", + "tests/cmdline/repl_autocomplete_underscore.py", + "tests/cmdline/repl_autoindent.py", + "tests/cmdline/repl_basic.py", + "tests/cmdline/repl_cont.py", + "tests/cmdline/repl_emacs_keys.py", + "tests/cmdline/repl_paste.py", + "tests/cmdline/repl_words_move.py", + "tests/feature_check/repl_emacs_check.py", + "tests/feature_check/repl_words_move_check.py", + "tests/micropython/viper_args.py", +] +lint.extend-ignore = [ "E401", "E402", "E722", @@ -51,35 +65,27 @@ lint.ignore = [ "F401", "F403", "F405", - "PLC1901", + "PLC0206", + "PLC0415", # conditional imports are common in MicroPython ] # manifest.py files are evaluated with some global names pre-defined lint.per-file-ignores."**/manifest.py" = [ "F821" ] lint.per-file-ignores."ports/**/boards/**/manifest_*.py" = [ "F821" ] -# Exclude all tests from linting (does not apply to formatting). +lint.per-file-ignores."ports/cc3200/tools/uniflash.py" = [ "E711" ] +# Exclude all tests from linting. lint.per-file-ignores."tests/**/*.py" = [ "ALL" ] +# Uses assignment expressions. +lint.per-file-ignores."tests/cpydiff/syntax_assign_expr.py" = [ "F821" ] lint.mccabe.max-complexity = 40 [tool.codespell] count = "" -ignore-regex = '\b[A-Z]{3}\b' -ignore-words-list = "ans,asend,aranges,deques,dout,emac,extint,hsi,iput,mis,notin,numer,ser,shft,synopsys,technic,ure,curren" +ignore-regex = "\\b[A-Z]{3}\\b" +# CIRCUITPY-CHANGE: aranges +ignore-words-list = "ans,aranges,asend,deques,dout,emac,extint,hsi,iput,mis,notin,numer,ser,shft,synopsys,technic,ure,curren" quiet-level = 3 -skip = """ -*/build*,\ -./.git,\ -./drivers/cc3100,\ -./lib,\ -./ports/cc3200/FreeRTOS,\ -./ports/cc3200/bootmgr/sl,\ -./ports/cc3200/hal,\ -./ports/cc3200/simplelink,\ -./ports/cc3200/telnet,\ -./ports/esp32/managed_components,\ -./ports/nrf/drivers/bluetooth/s1*,\ -./ports/stm32/usbhost,\ -./tests,\ -ACKNOWLEDGEMENTS,\ -""" - -# Ruff settings copied from MicroPython +skip = """\ + */build*,./.git,./drivers/cc3100,./lib,./ports/cc3200/FreeRTOS,./ports/cc3200/bootmgr/sl,./ports/cc3200/hal,./ports/c\ + c3200/simplelink,./ports/cc3200/telnet,./ports/esp32/managed_components,./ports/nrf/drivers/bluetooth/s1*,./ports/stm\ + 32/usbhost,./tests,ACKNOWLEDGEMENTS,\ + """ diff --git a/requirements-dev.txt b/requirements-dev.txt index 6505a982906..6a33c49daec 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -25,8 +25,7 @@ intelhex # for building & testing natmods pyelftools -# newer versions break ESP-IDF now -cryptography<45 +cryptography # for web workflow minify minify_html @@ -42,4 +41,5 @@ setuptools # For zephyr port tomlkit pytest +pytest-rerunfailures perfetto diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 839b8b19add..a1f81a063fd 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -215,7 +215,7 @@ static mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT); } - const mp_float_t interval = mp_obj_get_float(args[ARG_interval].u_obj); + const mp_float_t interval = mp_arg_validate_type_float(args[ARG_interval].u_obj, MP_QSTR_interval); if (interval < ADV_INTERVAL_MIN || interval > ADV_INTERVAL_MAX) { mp_raise_ValueError_varg(MP_ERROR_TEXT("interval must be in range %s-%s"), ADV_INTERVAL_MIN_STRING, ADV_INTERVAL_MAX_STRING); @@ -223,7 +223,7 @@ static mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t bool connectable = args[ARG_connectable].u_bool; bool anonymous = args[ARG_anonymous].u_bool; - uint32_t timeout = args[ARG_timeout].u_int; + const uint32_t timeout = (uint32_t)mp_arg_validate_int_min(args[ARG_timeout].u_int, 0, MP_QSTR_timeout); if (data_bufinfo.len > 31 && connectable && scan_response_bufinfo.len > 0) { mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Cannot have scan responses for extended, connectable advertisements.")); } @@ -306,7 +306,7 @@ static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args mp_float_t timeout = 0.0f; if (args[ARG_timeout].u_obj != mp_const_none) { - timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + timeout = mp_arg_validate_obj_float_non_negative(args[ARG_timeout].u_obj, 0.0f, MP_QSTR_timeout); } if (args[ARG_interval].u_obj == MP_OBJ_NULL) { @@ -317,7 +317,7 @@ static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args args[ARG_window].u_obj = mp_obj_new_float(WINDOW_DEFAULT); } - const mp_float_t interval = mp_obj_get_float(args[ARG_interval].u_obj); + const mp_float_t interval = mp_arg_validate_type_float(args[ARG_interval].u_obj, MP_QSTR_interval); if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { mp_raise_ValueError_varg(MP_ERROR_TEXT("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING); } @@ -329,7 +329,7 @@ static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args } #pragma GCC diagnostic pop - const mp_float_t window = mp_obj_get_float(args[ARG_window].u_obj); + const mp_float_t window = mp_arg_validate_type_float(args[ARG_window].u_obj, MP_QSTR_window); if (window > interval) { mp_raise_ValueError(MP_ERROR_TEXT("window must be <= interval")); } @@ -344,7 +344,9 @@ static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args } } - return common_hal_bleio_adapter_start_scan(self, prefix_bufinfo.buf, prefix_bufinfo.len, args[ARG_extended].u_bool, args[ARG_buffer_size].u_int, timeout, interval, window, args[ARG_minimum_rssi].u_int, args[ARG_active].u_bool); + const mp_int_t buffer_size = mp_arg_validate_int_min(args[ARG_buffer_size].u_int, 1, MP_QSTR_buffer_size); + + return common_hal_bleio_adapter_start_scan(self, prefix_bufinfo.buf, prefix_bufinfo.len, args[ARG_extended].u_bool, buffer_size, timeout, interval, window, args[ARG_minimum_rssi].u_int, args[ARG_active].u_bool); } static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_scan_obj, 1, bleio_adapter_start_scan); @@ -416,7 +418,8 @@ static mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); bleio_address_obj_t *address = mp_arg_validate_type(args[ARG_address].u_obj, &bleio_address_type, MP_QSTR_address); - mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + const mp_float_t timeout = + mp_arg_validate_obj_float_non_negative(args[ARG_timeout].u_obj, 0.0f, MP_QSTR_timeout); return common_hal_bleio_adapter_connect(self, address, timeout); } diff --git a/shared-bindings/_bleio/Address.c b/shared-bindings/_bleio/Address.c index 58f8a8adc1e..10500bec9cb 100644 --- a/shared-bindings/_bleio/Address.c +++ b/shared-bindings/_bleio/Address.c @@ -37,20 +37,18 @@ static mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args, mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - bleio_address_obj_t *self = mp_obj_malloc(bleio_address_obj_t, &bleio_address_type); - const mp_obj_t address = args[ARG_address].u_obj; mp_buffer_info_t buf_info; mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ); - if (buf_info.len != NUM_BLEIO_ADDRESS_BYTES) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("Address must be %d bytes long"), NUM_BLEIO_ADDRESS_BYTES); - } + mp_arg_validate_length(buf_info.len, NUM_BLEIO_ADDRESS_BYTES, MP_QSTR_address); - const mp_int_t address_type = args[ARG_address_type].u_int; - if (address_type < BLEIO_ADDRESS_TYPE_MIN || address_type > BLEIO_ADDRESS_TYPE_MAX) { - mp_arg_error_invalid(MP_QSTR_address_type); - } + const mp_int_t address_type = + mp_arg_validate_int_range(args[ARG_address_type].u_int, + BLEIO_ADDRESS_TYPE_MIN, + BLEIO_ADDRESS_TYPE_MAX, + MP_QSTR_address_type); + bleio_address_obj_t *self = mp_obj_malloc(bleio_address_obj_t, &bleio_address_type); common_hal_bleio_address_construct(self, buf_info.buf, address_type); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index 8d6ac43e487..0ed4c2b7eaa 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -116,9 +116,10 @@ static mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ } mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ); - if (initial_value_bufinfo.len > max_length || - (fixed_length && initial_value_bufinfo.len != max_length)) { - mp_raise_ValueError(MP_ERROR_TEXT("initial_value length is wrong")); + if (fixed_length) { + mp_arg_validate_length(initial_value_bufinfo.len, max_length, MP_QSTR_initial_value); + } else { + mp_arg_validate_length_max(initial_value_bufinfo.len, max_length, MP_QSTR_initial_value); } const char *user_description = NULL; diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c index 5ffff0dcba7..07394256933 100644 --- a/shared-bindings/_bleio/CharacteristicBuffer.c +++ b/shared-bindings/_bleio/CharacteristicBuffer.c @@ -118,7 +118,7 @@ static mp_uint_t bleio_characteristic_buffer_write(mp_obj_t self_in, const void return 0; } -static mp_uint_t bleio_characteristic_buffer_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +static mp_uint_t bleio_characteristic_buffer_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); raise_error_if_not_connected(self); diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c index 57cc605029f..9e29f57d8dd 100644 --- a/shared-bindings/_bleio/Descriptor.c +++ b/shared-bindings/_bleio/Descriptor.c @@ -99,9 +99,10 @@ static mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_o } } mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ); - if (initial_value_bufinfo.len > max_length || - (fixed_length && initial_value_bufinfo.len != max_length)) { - mp_raise_ValueError(MP_ERROR_TEXT("initial_value length is wrong")); + if (fixed_length) { + mp_arg_validate_length(initial_value_bufinfo.len, max_length, MP_QSTR_initial_value); + } else { + mp_arg_validate_length_max(initial_value_bufinfo.len, max_length, MP_QSTR_initial_value); } bleio_descriptor_obj_t *descriptor = mp_obj_malloc(bleio_descriptor_obj_t, &bleio_descriptor_type); diff --git a/shared-bindings/_bleio/PacketBuffer.c b/shared-bindings/_bleio/PacketBuffer.c index 47d71ebd55a..aa1e6e8645a 100644 --- a/shared-bindings/_bleio/PacketBuffer.c +++ b/shared-bindings/_bleio/PacketBuffer.c @@ -57,7 +57,10 @@ static mp_obj_t bleio_packet_buffer_make_new(const mp_obj_type_t *type, size_t n size_t max_packet_size = common_hal_bleio_characteristic_get_max_length(characteristic); if (args[ARG_max_packet_size].u_obj != mp_const_none) { - max_packet_size = mp_obj_get_int(args[ARG_max_packet_size].u_obj); + const mp_int_t max_packet_size_int = + mp_arg_validate_type_int(args[ARG_max_packet_size].u_obj, MP_QSTR_max_packet_size); + max_packet_size = + (size_t)mp_arg_validate_int_min(max_packet_size_int, 1, MP_QSTR_max_packet_size); } bleio_packet_buffer_obj_t *self = mp_obj_malloc(bleio_packet_buffer_obj_t, &bleio_packet_buffer_type); diff --git a/shared-bindings/_bleio/PacketBuffer.h b/shared-bindings/_bleio/PacketBuffer.h index dd0c1ae9e25..24fb24bce78 100644 --- a/shared-bindings/_bleio/PacketBuffer.h +++ b/shared-bindings/_bleio/PacketBuffer.h @@ -6,6 +6,7 @@ #pragma once +#include "shared-bindings/_bleio/Characteristic.h" #include "common-hal/_bleio/PacketBuffer.h" extern const mp_obj_type_t bleio_packet_buffer_type; diff --git a/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c index 2d28d5a9b61..eef8546e253 100644 --- a/shared-bindings/_bleio/UUID.c +++ b/shared-bindings/_bleio/UUID.c @@ -34,20 +34,18 @@ static mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); - bleio_uuid_obj_t *self = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type); - const mp_obj_t value = all_args[0]; uint8_t uuid128[16]; if (mp_obj_is_int(value)) { - mp_int_t uuid16 = mp_obj_get_int(value); - if (uuid16 < 0 || uuid16 > 0xffff) { - mp_raise_ValueError(MP_ERROR_TEXT("UUID integer value must be 0-0xffff")); - } + const mp_int_t uuid16 = + mp_arg_validate_int_range(mp_obj_get_int(value), 0, 0xffff, MP_QSTR_value); // NULL means no 128-bit value. + bleio_uuid_obj_t *self = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type); common_hal_bleio_uuid_construct(self, uuid16, NULL); + return MP_OBJ_FROM_PTR(self); } else { if (mp_obj_is_str(value)) { // 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' @@ -82,9 +80,7 @@ static mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, si mp_raise_ValueError(MP_ERROR_TEXT("UUID value is not str, int or byte buffer")); } - if (bufinfo.len != 16) { - mp_raise_ValueError(MP_ERROR_TEXT("Byte buffer must be 16 bytes.")); - } + mp_arg_validate_length(bufinfo.len, 16, MP_QSTR_value); memcpy(uuid128, bufinfo.buf, 16); } @@ -93,10 +89,12 @@ static mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, si uint32_t uuid16 = (uuid128[13] << 8) | uuid128[12]; uuid128[12] = 0; uuid128[13] = 0; + + bleio_uuid_obj_t *self = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type); common_hal_bleio_uuid_construct(self, uuid16, uuid128); - } - return MP_OBJ_FROM_PTR(self); + return MP_OBJ_FROM_PTR(self); + } } //| uuid16: int @@ -171,12 +169,12 @@ static mp_obj_t bleio_uuid_pack_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE); - size_t offset = args[ARG_offset].u_int; - if (offset + common_hal_bleio_uuid_get_size(self) / 8 > bufinfo.len) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer + offset too small %d %d %d")); - } + const mp_int_t offset = + mp_arg_validate_int_range(args[ARG_offset].u_int, 0, (mp_int_t)bufinfo.len, MP_QSTR_offset); + const size_t packed_len = common_hal_bleio_uuid_get_size(self) / 8; + mp_arg_validate_length_min(bufinfo.len - (size_t)offset, packed_len, MP_QSTR_buffer); - common_hal_bleio_uuid_pack_into(self, bufinfo.buf + offset); + common_hal_bleio_uuid_pack_into(self, (uint8_t *)bufinfo.buf + (size_t)offset); return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_uuid_pack_into_obj, 1, bleio_uuid_pack_into); diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c index 3bf8c1a2c9c..1ec9fd96e76 100644 --- a/shared-bindings/_bleio/__init__.c +++ b/shared-bindings/_bleio/__init__.c @@ -56,7 +56,7 @@ //| //| MP_DEFINE_BLEIO_EXCEPTION(BluetoothError, Exception) -NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t fmt, ...) { +MP_NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_bleio_BluetoothError, fmt, argptr); @@ -72,7 +72,7 @@ NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t fmt, ...) { //| //| MP_DEFINE_BLEIO_EXCEPTION(RoleError, bleio_BluetoothError) -NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg) { +MP_NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_bleio_RoleError, msg); } @@ -83,7 +83,7 @@ NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg) { //| //| MP_DEFINE_BLEIO_EXCEPTION(SecurityError, bleio_BluetoothError) -NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t fmt, ...) { +MP_NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_bleio_SecurityError, fmt, argptr); diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h index faf11ea1d06..0c5a5fec06b 100644 --- a/shared-bindings/_bleio/__init__.h +++ b/shared-bindings/_bleio/__init__.h @@ -45,19 +45,11 @@ void common_hal_bleio_init(void); extern mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj); -NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t msg, ...); -NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg); -NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t msg, ...); +MP_NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t msg, ...); +MP_NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t msg, ...); bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void); -void common_hal_bleio_check_connected(uint16_t conn_handle); - -uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist); -size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len); -void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo); -size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len); -void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response); - void common_hal_bleio_gc_collect(void); diff --git a/shared-bindings/_stage/Layer.c b/shared-bindings/_stage/Layer.c index de4861a70ee..0d7a1bfbd5e 100644 --- a/shared-bindings/_stage/Layer.c +++ b/shared-bindings/_stage/Layer.c @@ -38,38 +38,38 @@ static mp_obj_t layer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 4, 5, false); - layer_obj_t *self = mp_obj_malloc(layer_obj_t, type); - - self->width = mp_obj_get_int(args[0]); - self->height = mp_obj_get_int(args[1]); - self->x = 0; - self->y = 0; - self->frame = 0; - self->rotation = false; + mp_uint_t width = mp_arg_validate_int_min(mp_obj_get_int(args[0]), 0, MP_QSTR_width); + mp_uint_t height = mp_arg_validate_int_min(mp_obj_get_int(args[1]), 0, MP_QSTR_height); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); - self->graphic = bufinfo.buf; - if (bufinfo.len != 2048) { - mp_raise_ValueError(MP_ERROR_TEXT("graphic must be 2048 bytes long")); - } + mp_buffer_info_t graphic_bufinfo; + mp_get_buffer_raise(args[2], &graphic_bufinfo, MP_BUFFER_READ); + mp_arg_validate_length(graphic_bufinfo.len, 2048, MP_QSTR_graphic); - mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); - self->palette = bufinfo.buf; - if (bufinfo.len != 32) { - mp_raise_ValueError(MP_ERROR_TEXT("palette must be 32 bytes long")); - } + mp_buffer_info_t palette_bufinfo; + mp_get_buffer_raise(args[3], &palette_bufinfo, MP_BUFFER_READ); + mp_arg_validate_length(palette_bufinfo.len, 32, MP_QSTR_palette); + mp_buffer_info_t map_bufinfo = { .buf = NULL }; if (n_args > 4) { - mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ); - self->map = bufinfo.buf; - if (bufinfo.len < (self->width * self->height) / 2) { + mp_get_buffer_raise(args[4], &map_bufinfo, MP_BUFFER_READ); + if (map_bufinfo.len < (width * height) / 2) { mp_raise_ValueError(MP_ERROR_TEXT("map buffer too small")); } - } else { - self->map = NULL; } + // Only allocate after validation is finished. + layer_obj_t *self = mp_obj_malloc(layer_obj_t, type); + + self->width = width; + self->height = height; + self->x = 0; + self->y = 0; + self->frame = 0; + self->rotation = false; + self->graphic = graphic_bufinfo.buf; + self->palette = palette_bufinfo.buf; + self->map = map_bufinfo.buf; + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/_stage/Text.c b/shared-bindings/_stage/Text.c index ecd4f644a78..0013ffb6697 100644 --- a/shared-bindings/_stage/Text.c +++ b/shared-bindings/_stage/Text.c @@ -38,32 +38,32 @@ static mp_obj_t text_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 5, 5, false); - text_obj_t *self = mp_obj_malloc(text_obj_t, type); + mp_uint_t width = mp_arg_validate_int_min(mp_obj_get_int(args[0]), 0, MP_QSTR_width); + mp_uint_t height = mp_arg_validate_int_min(mp_obj_get_int(args[1]), 0, MP_QSTR_height); - self->width = mp_obj_get_int(args[0]); - self->height = mp_obj_get_int(args[1]); - self->x = 0; - self->y = 0; - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); - self->font = bufinfo.buf; - if (bufinfo.len != 2048) { - mp_raise_ValueError(MP_ERROR_TEXT("font must be 2048 bytes long")); - } + mp_buffer_info_t font_bufinfo; + mp_get_buffer_raise(args[2], &font_bufinfo, MP_BUFFER_READ); + mp_arg_validate_length(font_bufinfo.len, 2048, MP_QSTR_font); - mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); - self->palette = bufinfo.buf; - if (bufinfo.len != 32) { - mp_raise_ValueError(MP_ERROR_TEXT("palette must be 32 bytes long")); - } + mp_buffer_info_t palette_bufinfo; + mp_get_buffer_raise(args[3], &palette_bufinfo, MP_BUFFER_READ); + mp_arg_validate_length(palette_bufinfo.len, 32, MP_QSTR_palette); - mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ); - self->chars = bufinfo.buf; - if (bufinfo.len < self->width * self->height) { + mp_buffer_info_t chars_bufinfo; + mp_get_buffer_raise(args[4], &chars_bufinfo, MP_BUFFER_READ); + if (chars_bufinfo.len < width * height) { mp_raise_ValueError(MP_ERROR_TEXT("chars buffer too small")); } + text_obj_t *self = mp_obj_malloc(text_obj_t, type); + self->width = width; + self->height = height; + self->x = 0; + self->y = 0; + self->font = font_bufinfo.buf; + self->palette = palette_bufinfo.buf; + self->chars = chars_bufinfo.buf; + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c b/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c index 32d418923fb..5fb821ceade 100644 --- a/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c +++ b/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c @@ -47,8 +47,6 @@ //| ... //| static mp_obj_t adafruit_bus_device_i2cdevice_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - adafruit_bus_device_i2cdevice_obj_t *self = - mp_obj_malloc(adafruit_bus_device_i2cdevice_obj_t, &adafruit_bus_device_i2cdevice_type); enum { ARG_i2c, ARG_device_address, ARG_probe }; static const mp_arg_t allowed_args[] = { { MP_QSTR_i2c, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -60,12 +58,14 @@ static mp_obj_t adafruit_bus_device_i2cdevice_make_new(const mp_obj_type_t *type mp_obj_t *i2c = args[ARG_i2c].u_obj; + adafruit_bus_device_i2cdevice_obj_t *self = + mp_obj_malloc(adafruit_bus_device_i2cdevice_obj_t, &adafruit_bus_device_i2cdevice_type); common_hal_adafruit_bus_device_i2cdevice_construct(MP_OBJ_TO_PTR(self), i2c, args[ARG_device_address].u_int); if (args[ARG_probe].u_bool == true) { common_hal_adafruit_bus_device_i2cdevice_probe_for_device(self); } - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } //| def __enter__(self) -> I2CDevice: diff --git a/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c b/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c index f62aedc47e3..2f4895e38ce 100644 --- a/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c +++ b/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c @@ -59,8 +59,6 @@ //| ... //| static mp_obj_t adafruit_bus_device_spidevice_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - adafruit_bus_device_spidevice_obj_t *self = - mp_obj_malloc(adafruit_bus_device_spidevice_obj_t, &adafruit_bus_device_spidevice_type); enum { ARG_spi, ARG_chip_select, ARG_cs_active_value, ARG_baudrate, ARG_polarity, ARG_phase, ARG_extra_clocks }; static const mp_arg_t allowed_args[] = { { MP_QSTR_spi, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -78,12 +76,11 @@ static mp_obj_t adafruit_bus_device_spidevice_make_new(const mp_obj_type_t *type mp_arg_validate_type_or_none(args[ARG_chip_select].u_obj, &digitalio_digitalinout_type, MP_QSTR_chip_select); - common_hal_adafruit_bus_device_spidevice_construct(MP_OBJ_TO_PTR(self), spi, args[ARG_chip_select].u_obj, args[ARG_cs_active_value].u_bool, args[ARG_baudrate].u_int, args[ARG_polarity].u_int, - args[ARG_phase].u_int, args[ARG_extra_clocks].u_int); - if (args[ARG_chip_select].u_obj != mp_const_none) { - digitalinout_result_t result = common_hal_digitalio_digitalinout_switch_to_output(MP_OBJ_TO_PTR(args[ARG_chip_select].u_obj), - true, DRIVE_MODE_PUSH_PULL); + digitalinout_result_t result = + common_hal_digitalio_digitalinout_switch_to_output(MP_OBJ_TO_PTR(args[ARG_chip_select].u_obj), + true, + DRIVE_MODE_PUSH_PULL); #if CIRCUITPY_DIGITALIO_HAVE_INPUT_ONLY if (result == DIGITALINOUT_INPUT_ONLY) { mp_raise_NotImplementedError(MP_ERROR_TEXT("Pin is input only")); @@ -93,7 +90,19 @@ static mp_obj_t adafruit_bus_device_spidevice_make_new(const mp_obj_type_t *type #endif } - return (mp_obj_t)self; + adafruit_bus_device_spidevice_obj_t *self = + mp_obj_malloc(adafruit_bus_device_spidevice_obj_t, &adafruit_bus_device_spidevice_type); + common_hal_adafruit_bus_device_spidevice_construct(MP_OBJ_TO_PTR(self), + spi, + args[ARG_chip_select].u_obj, + args[ARG_cs_active_value].u_bool, + args[ARG_baudrate].u_int, + args[ARG_polarity].u_int, + args[ARG_phase].u_int, + args[ARG_extra_clocks].u_int); + + + return MP_OBJ_FROM_PTR(self); } //| def __enter__(self) -> busio.SPI: diff --git a/shared-bindings/adafruit_pixelbuf/PixelBuf.c b/shared-bindings/adafruit_pixelbuf/PixelBuf.c index cdffbfa627a..4144f086b98 100644 --- a/shared-bindings/adafruit_pixelbuf/PixelBuf.c +++ b/shared-bindings/adafruit_pixelbuf/PixelBuf.c @@ -24,7 +24,7 @@ #include "extmod/ulab/code/ndarray.h" #endif -static NORETURN void invalid_byteorder(void) { +static MP_NORETURN void invalid_byteorder(void) { mp_arg_error_invalid(MP_QSTR_byteorder); } diff --git a/shared-bindings/aesio/aes.c b/shared-bindings/aesio/aes.c index a6916042fda..75f2850a7ef 100644 --- a/shared-bindings/aesio/aes.c +++ b/shared-bindings/aesio/aes.c @@ -55,8 +55,6 @@ static mp_obj_t aesio_aes_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - aesio_aes_obj_t *self = mp_obj_malloc(aesio_aes_obj_t, &aesio_aes_type); - enum { ARG_key, ARG_mode, ARG_IV, ARG_counter, ARG_segment_size }; static const mp_arg_t allowed_args[] = { {MP_QSTR_key, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, @@ -100,8 +98,10 @@ static mp_obj_t aesio_aes_make_new(const mp_obj_type_t *type, size_t n_args, iv = bufinfo.buf; } + aesio_aes_obj_t *self = mp_obj_malloc(aesio_aes_obj_t, &aesio_aes_type); common_hal_aesio_aes_construct(self, key, key_length, iv, mode, args[ARG_counter].u_int); + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/alarm/SleepMemory.c b/shared-bindings/alarm/SleepMemory.c index e6d65de4555..383c2a4e613 100644 --- a/shared-bindings/alarm/SleepMemory.c +++ b/shared-bindings/alarm/SleepMemory.c @@ -12,9 +12,11 @@ #include "shared-bindings/alarm/SleepMemory.h" //| class SleepMemory: -//| """Store raw bytes in RAM that persists during deep sleep. +//| """Store raw bytes in RAM that persists across deep sleep and software resets. //| The class acts as a ``bytearray``. -//| If power is lost, the memory contents are lost. +//| Contents are preserved across ``microcontroller.reset()``, watchdog resets, +//| and deep sleep wake. Contents are lost when power is removed and restored, +//| or on brown-out reset. //| //| Note that this class can't be imported and used directly. The sole //| instance of :class:`SleepMemory` is available at diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index e9f2db324d5..d229246e781 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -122,6 +122,9 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_light_sleep_until_alarms_obj, 1, MP_OB //| //| If no alarms are specified, the microcontroller will deep sleep until reset. //| +//| You cannot initiate a deep sleep from the REPL. +//| You must call `exit_and_deep_sleep_until_alarms()` from a program file. +//| //| :param circuitpython_typing.Alarm alarms: the alarms that can wake the microcontroller. //| :param Sequence[digitalio.DigitalInOut] preserve_dios: A sequence of `DigitalInOut` objects //| whose state should be preserved during deep sleep. diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index af92b381137..37bfd9c51b7 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -24,7 +24,7 @@ extern mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const // it will exit idle as if deep sleep was exited extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms, size_t n_dios, digitalio_digitalinout_obj_t **preserve_dios); -extern NORETURN void common_hal_alarm_enter_deep_sleep(void); +extern MP_NORETURN void common_hal_alarm_enter_deep_sleep(void); // May be used to re-initialize peripherals like GPIO, if the VM reset returned // them to a default state diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index 8d93ca8d0de..4633fdb233c 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -42,7 +42,6 @@ //| ... //| static mp_obj_t alarm_pin_pinalarm_make_new(const mp_obj_type_t *type, mp_uint_t n_args, size_t n_kw, const mp_obj_t *all_args) { - alarm_pin_pinalarm_obj_t *self = mp_obj_malloc(alarm_pin_pinalarm_obj_t, &alarm_pin_pinalarm_type); enum { ARG_pin, ARG_value, ARG_edge, ARG_pull }; static const mp_arg_t allowed_args[] = { { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -55,6 +54,7 @@ static mp_obj_t alarm_pin_pinalarm_make_new(const mp_obj_type_t *type, mp_uint_t const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); + alarm_pin_pinalarm_obj_t *self = mp_obj_malloc(alarm_pin_pinalarm_obj_t, &alarm_pin_pinalarm_type); common_hal_alarm_pin_pinalarm_construct(self, pin, args[ARG_value].u_bool, diff --git a/shared-bindings/alarm/time/TimeAlarm.c b/shared-bindings/alarm/time/TimeAlarm.c index 0277c22fc44..a3df6ddf7fd 100644 --- a/shared-bindings/alarm/time/TimeAlarm.c +++ b/shared-bindings/alarm/time/TimeAlarm.c @@ -46,8 +46,6 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) { //| static mp_obj_t alarm_time_timealarm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - alarm_time_timealarm_obj_t *self = mp_obj_malloc(alarm_time_timealarm_obj_t, &alarm_time_timealarm_type); - enum { ARG_monotonic_time, ARG_epoch_time }; static const mp_arg_t allowed_args[] = { { MP_QSTR_monotonic_time, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -92,6 +90,7 @@ static mp_obj_t alarm_time_timealarm_make_new(const mp_obj_type_t *type, mp_raise_ValueError(MP_ERROR_TEXT("Time is in the past.")); } + alarm_time_timealarm_obj_t *self = mp_obj_malloc(alarm_time_timealarm_obj_t, &alarm_time_timealarm_type); common_hal_alarm_time_timealarm_construct(self, monotonic_time); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/alarm/touch/TouchAlarm.c b/shared-bindings/alarm/touch/TouchAlarm.c index f25e826cff0..eac3f37b8f4 100644 --- a/shared-bindings/alarm/touch/TouchAlarm.c +++ b/shared-bindings/alarm/touch/TouchAlarm.c @@ -21,13 +21,12 @@ //| may be limited due to hardware restrictions, particularly for deep-sleep alarms. //| //| **Limitations:** Not available on SAMD, Nordic, or RP2040. +//| On Espressif, only available on ESP32, ESP32-S2, ESP32-S3, and ESP32-P4. //| """ //| ... //| static mp_obj_t alarm_touch_touchalarm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - alarm_touch_touchalarm_obj_t *self = mp_obj_malloc(alarm_touch_touchalarm_obj_t, &alarm_touch_touchalarm_type); - enum { ARG_pin }; static const mp_arg_t allowed_args[] = { { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -38,6 +37,7 @@ static mp_obj_t alarm_touch_touchalarm_make_new(const mp_obj_type_t *type, const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); + alarm_touch_touchalarm_obj_t *self = mp_obj_malloc(alarm_touch_touchalarm_obj_t, &alarm_touch_touchalarm_type); common_hal_alarm_touch_touchalarm_construct(self, pin); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/analogbufio/BufferedIn.c b/shared-bindings/analogbufio/BufferedIn.c index a25610207b4..2c42ee1f325 100644 --- a/shared-bindings/analogbufio/BufferedIn.c +++ b/shared-bindings/analogbufio/BufferedIn.c @@ -60,10 +60,8 @@ static mp_obj_t analogbufio_bufferedin_make_new(const mp_obj_type_t *type, size_ // Validate Pin const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); - // Create local object - analogbufio_bufferedin_obj_t *self = mp_obj_malloc_with_finaliser(analogbufio_bufferedin_obj_t, &analogbufio_bufferedin_type); - - // Call local interface in ports/common-hal/analogbufio + analogbufio_bufferedin_obj_t *self = + mp_obj_malloc_with_finaliser(analogbufio_bufferedin_obj_t, &analogbufio_bufferedin_type); common_hal_analogbufio_bufferedin_construct(self, pin, args[ARG_sample_rate].u_int); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c index 9aaf7421c65..952a00e2903 100644 --- a/shared-bindings/audiobusio/I2SOut.c +++ b/shared-bindings/audiobusio/I2SOut.c @@ -144,6 +144,8 @@ static void check_for_deinit(audiobusio_i2sout_obj_t *self) { //| //| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`. //| +//| Mono samples will be converted to stereo by copying value to both the left channel and the right channel. +//| //| The sample itself should consist of 8 bit or 16 bit samples.""" //| ... //| diff --git a/shared-bindings/audiobusio/PDMIn.c b/shared-bindings/audiobusio/PDMIn.c index 2890afda0fd..aba8a019f35 100644 --- a/shared-bindings/audiobusio/PDMIn.c +++ b/shared-bindings/audiobusio/PDMIn.c @@ -48,7 +48,7 @@ //| //| **Limitations:** On SAMD and RP2040, supports only 8 or 16 bit mono input, with 64x oversampling. //| On nRF52840, supports only 16 bit mono input at 16 kHz; oversampling is fixed at 64x. Not provided -//| on nRF52833 for space reasons. Not available on Espressif. +//| on nRF52833 for space reasons. On Espressif, only available on ESP32, ESP32-S3, and ESP32-P4. //| //| For example, to record 8-bit unsigned samples to a buffer:: //| @@ -96,9 +96,6 @@ static mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar const mcu_pin_obj_t *clock_pin = validate_obj_is_free_pin(args[ARG_clock_pin].u_obj, MP_QSTR_clock_pin); const mcu_pin_obj_t *data_pin = validate_obj_is_free_pin(args[ARG_data_pin].u_obj, MP_QSTR_data_pin); - // create PDMIn object from the given pin - audiobusio_pdmin_obj_t *self = mp_obj_malloc_with_finaliser(audiobusio_pdmin_obj_t, &audiobusio_pdmin_type); - uint32_t sample_rate = args[ARG_sample_rate].u_int; uint8_t bit_depth = args[ARG_bit_depth].u_int; if (bit_depth % 8 != 0) { @@ -115,6 +112,7 @@ static mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar : mp_obj_get_float(args[ARG_startup_delay].u_obj); mp_arg_validate_float_range(startup_delay, 0.0f, 1.0f, MP_QSTR_startup_delay); + audiobusio_pdmin_obj_t *self = mp_obj_malloc_with_finaliser(audiobusio_pdmin_obj_t, &audiobusio_pdmin_type); common_hal_audiobusio_pdmin_construct(self, clock_pin, data_pin, sample_rate, bit_depth, mono, oversample); diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c index 30c1d1ad600..8dc57903286 100644 --- a/shared-bindings/audiocore/RawSample.c +++ b/shared-bindings/audiocore/RawSample.c @@ -90,7 +90,6 @@ static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_a mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - audioio_rawsample_obj_t *self = mp_obj_malloc(audioio_rawsample_obj_t, &audioio_rawsample_type); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); uint8_t bytes_per_sample = 1; @@ -103,9 +102,16 @@ static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_a if (!args[ARG_single_buffer].u_bool && bufinfo.len % (bytes_per_sample * args[ARG_channel_count].u_int * 2) != 0) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Length of %q must be an even multiple of channel_count * type_size"), MP_QSTR_buffer); } - common_hal_audioio_rawsample_construct(self, ((uint8_t *)bufinfo.buf), bufinfo.len, - bytes_per_sample, signed_samples, args[ARG_channel_count].u_int, - args[ARG_sample_rate].u_int, args[ARG_single_buffer].u_bool); + + audioio_rawsample_obj_t *self = mp_obj_malloc(audioio_rawsample_obj_t, &audioio_rawsample_type); + common_hal_audioio_rawsample_construct(self, + ((uint8_t *)bufinfo.buf), + bufinfo.len, + bytes_per_sample, + signed_samples, + args[ARG_channel_count].u_int, + args[ARG_sample_rate].u_int, + args[ARG_single_buffer].u_bool); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c index 4ba7d24bfd2..c93bedd4213 100644 --- a/shared-bindings/audiocore/WaveFile.c +++ b/shared-bindings/audiocore/WaveFile.c @@ -60,7 +60,6 @@ static mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_ar arg = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), arg, MP_ROM_QSTR(MP_QSTR_rb)); } - audioio_wavefile_obj_t *self = mp_obj_malloc(audioio_wavefile_obj_t, &audioio_wavefile_type); if (!mp_obj_is_type(arg, &mp_type_vfs_fat_fileio)) { mp_raise_TypeError(MP_ERROR_TEXT("file must be a file opened in byte mode")); } @@ -72,6 +71,8 @@ static mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_ar buffer = bufinfo.buf; buffer_size = mp_arg_validate_length_range(bufinfo.len, 8, 1024, MP_QSTR_buffer); } + + audioio_wavefile_obj_t *self = mp_obj_malloc(audioio_wavefile_obj_t, &audioio_wavefile_type); common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(arg), buffer, buffer_size); diff --git a/shared-bindings/audiodelays/PitchShift.c b/shared-bindings/audiodelays/PitchShift.c index b94df7d9edd..ee3bf5afdd7 100644 --- a/shared-bindings/audiodelays/PitchShift.c +++ b/shared-bindings/audiodelays/PitchShift.c @@ -94,8 +94,18 @@ static mp_obj_t audiodelays_pitch_shift_make_new(const mp_obj_type_t *type, size mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); } - audiodelays_pitch_shift_obj_t *self = mp_obj_malloc(audiodelays_pitch_shift_obj_t, &audiodelays_pitch_shift_type); - common_hal_audiodelays_pitch_shift_construct(self, args[ARG_semitones].u_obj, args[ARG_mix].u_obj, args[ARG_window].u_int, args[ARG_overlap].u_int, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); + audiodelays_pitch_shift_obj_t *self = + mp_obj_malloc(audiodelays_pitch_shift_obj_t, &audiodelays_pitch_shift_type); + common_hal_audiodelays_pitch_shift_construct(self, + args[ARG_semitones].u_obj, + args[ARG_mix].u_obj, + args[ARG_window].u_int, + args[ARG_overlap].u_int, + args[ARG_buffer_size].u_int, + bits_per_sample, + args[ARG_samples_signed].u_bool, + channel_count, + sample_rate); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audiofilters/Distortion.c b/shared-bindings/audiofilters/Distortion.c index 8de4c1d1ea3..bed28f5ed49 100644 --- a/shared-bindings/audiofilters/Distortion.c +++ b/shared-bindings/audiofilters/Distortion.c @@ -145,8 +145,21 @@ static mp_obj_t audiofilters_distortion_make_new(const mp_obj_type_t *type, size mode = validate_distortion_mode(args[ARG_mode].u_obj, MP_QSTR_mode); } - audiofilters_distortion_obj_t *self = mp_obj_malloc(audiofilters_distortion_obj_t, &audiofilters_distortion_type); - common_hal_audiofilters_distortion_construct(self, args[ARG_drive].u_obj, args[ARG_pre_gain].u_obj, args[ARG_post_gain].u_obj, mode, args[ARG_soft_clip].u_obj, args[ARG_mix].u_obj, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); + audiofilters_distortion_obj_t *self = + mp_obj_malloc(audiofilters_distortion_obj_t, &audiofilters_distortion_type); + common_hal_audiofilters_distortion_construct(self, + args[ARG_drive].u_obj, + args[ARG_pre_gain].u_obj, + args[ARG_post_gain].u_obj, + mode, + args[ARG_soft_clip].u_obj, + args[ARG_mix].u_obj, + args[ARG_buffer_size].u_int, + bits_per_sample, + args[ARG_samples_signed].u_bool, + channel_count, + sample_rate); + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audiofilters/Filter.c b/shared-bindings/audiofilters/Filter.c index 426fff22616..2d0d12b226a 100644 --- a/shared-bindings/audiofilters/Filter.c +++ b/shared-bindings/audiofilters/Filter.c @@ -91,7 +91,14 @@ static mp_obj_t audiofilters_filter_make_new(const mp_obj_type_t *type, size_t n } audiofilters_filter_obj_t *self = mp_obj_malloc(audiofilters_filter_obj_t, &audiofilters_filter_type); - common_hal_audiofilters_filter_construct(self, args[ARG_filter].u_obj, args[ARG_mix].u_obj, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); + common_hal_audiofilters_filter_construct(self, + args[ARG_filter].u_obj, + args[ARG_mix].u_obj, + args[ARG_buffer_size].u_int, + bits_per_sample, + args[ARG_samples_signed].u_bool, + channel_count, + sample_rate); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audiofilters/Phaser.c b/shared-bindings/audiofilters/Phaser.c index 9f713afce5f..2aed9623b72 100644 --- a/shared-bindings/audiofilters/Phaser.c +++ b/shared-bindings/audiofilters/Phaser.c @@ -91,7 +91,16 @@ static mp_obj_t audiofilters_phaser_make_new(const mp_obj_type_t *type, size_t n } audiofilters_phaser_obj_t *self = mp_obj_malloc(audiofilters_phaser_obj_t, &audiofilters_phaser_type); - common_hal_audiofilters_phaser_construct(self, args[ARG_frequency].u_obj, args[ARG_feedback].u_obj, args[ARG_mix].u_obj, args[ARG_stages].u_int, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); + common_hal_audiofilters_phaser_construct(self, + args[ARG_frequency].u_obj, + args[ARG_feedback].u_obj, + args[ARG_mix].u_obj, + args[ARG_stages].u_int, + args[ARG_buffer_size].u_int, + bits_per_sample, + args[ARG_samples_signed].u_bool, + channel_count, + sample_rate); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audioi2sin/I2SIn.c b/shared-bindings/audioi2sin/I2SIn.c new file mode 100644 index 00000000000..056aa859abe --- /dev/null +++ b/shared-bindings/audioi2sin/I2SIn.c @@ -0,0 +1,314 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "extmod/vfs_fat.h" +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/mphal.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/audioi2sin/I2SIn.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-module/audiocore/__init__.h" +#include "shared-bindings/util.h" + +//| class I2SIn: +//| """Record an input I2S audio stream from an external I2S source such as a MEMS microphone.""" +//| +//| def __init__( +//| self, +//| bit_clock: microcontroller.Pin, +//| word_select: microcontroller.Pin, +//| data: microcontroller.Pin, +//| *, +//| main_clock: Optional[microcontroller.Pin] = None, +//| sample_rate: int = 16000, +//| bit_depth: int = 16, +//| output_bit_depth: Optional[int] = None, +//| mono: bool = True, +//| left_justified: bool = False, +//| samples_signed: bool = True, +//| ) -> None: +//| """Create an I2SIn object associated with the given pins. This allows you to +//| record audio signals from an external I2S source (e.g. an I2S MEMS microphone +//| like the SPH0645LM4H or INMP441). +//| +//| The pin signature mirrors `audiobusio.I2SOut` so users can swap classes; +//| recording parameters mirror `audiobusio.PDMIn`. +//| +//| :param ~microcontroller.Pin bit_clock: The bit clock (or serial clock) pin +//| :param ~microcontroller.Pin word_select: The word select (or left/right clock) pin +//| :param ~microcontroller.Pin data: The data input pin +//| :param ~microcontroller.Pin main_clock: The main clock pin. Not all ports support this. +//| :param int sample_rate: Target sample rate of the resulting samples. Check `sample_rate` for actual value. +//| :param int bit_depth: Number of bits per sample on the I2S bus. Must be 8, 16, 24, or +//| 32. 8-bit only supported on espressif. The destination buffer typecode is determined +//| by ``output_bit_depth`` (or ``bit_depth`` when ``output_bit_depth`` is ``None``): +//| +//| +----------------+------------------+----------------------+ +//| | samples_signed | output_bit_depth | Required typecode(s) | +//| +================+==================+======================+ +//| | True | 24 or 32 | ``'i'`` | +//| +----------------+------------------+----------------------+ +//| | True | 16 | ``'h'`` | +//| +----------------+------------------+----------------------+ +//| | True | 8 | ``'b'`` or BYTEARRAY | +//| +----------------+------------------+----------------------+ +//| | False | 24 or 32 | ``'I'`` | +//| +----------------+------------------+----------------------+ +//| | False | 16 | ``'H'`` | +//| +----------------+------------------+----------------------+ +//| | False | 8 | ``'B'`` or BYTEARRAY | +//| +----------------+------------------+----------------------+ +//| +//| Note that 24-bit samples from mics like the SPH0645LM4H / INMP441 are +//| transported in 32-bit slots, so use ``bit_depth=32`` and an ``'I'`` buffer. +//| :param int output_bit_depth: If set, recorded samples are rescaled from +//| ``bit_depth`` to this width before being written to the destination buffer +//| (8, 16, 24, or 32). Widening bit-replicates so full-scale input maps to +//| full-scale output (e.g. 16-bit ``0xFFFF`` -> 24-bit ``0xFFFFFF``); narrowing +//| arithmetic-shifts the value right (sign-preserving when ``samples_signed`` is +//| True). When ``None`` (the default) the destination buffer holds samples at +//| ``bit_depth`` (a 24-bit sample still occupies a 32-bit ``'i'``/``'I'`` slot, +//| sign-extended without rescaling). +//| :param bool mono: True when capturing a single channel of audio, captures two channels otherwise. +//| :param bool left_justified: True when data bits are aligned with the word select clock. False +//| when they are shifted by one to match classic I2S protocol. Set True for mics like the SPH0645LM4H. +//| :param bool samples_signed: Samples are signed (True) or unsigned (False). I2S mics deliver signed +//| two's-complement PCM natively; set False to have the recorded samples converted to unsigned PCM +//| (the top/sign bit is flipped, matching the WAV convention for unsigned samples). +//| +//| Example, recording 16-bit mono samples from an INMP441:: +//| +//| import array +//| import audioi2sin +//| import board +//| +//| buf = array.array("h", [0] * 16000) +//| with audioi2sin.I2SIn(board.D9, board.D10, board.D11, +//| sample_rate=16000, bit_depth=16) as mic: +//| mic.record(buf, len(buf)) +//| +//| """ +//| ... +//| +static mp_obj_t audioi2sin_i2sin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + #if !CIRCUITPY_AUDIOI2SIN + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_I2SIn); + return NULL; // Not reachable. + #else + enum { ARG_bit_clock, ARG_word_select, ARG_data, ARG_main_clock, + ARG_sample_rate, ARG_bit_depth, ARG_output_bit_depth, + ARG_mono, ARG_left_justified, ARG_samples_signed }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bit_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_word_select, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_main_clock, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_sample_rate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16000} }, + { MP_QSTR_bit_depth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} }, + { MP_QSTR_output_bit_depth, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_mono, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_left_justified, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_samples_signed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mcu_pin_obj_t *bit_clock = validate_obj_is_free_pin(args[ARG_bit_clock].u_obj, MP_QSTR_bit_clock); + const mcu_pin_obj_t *word_select = validate_obj_is_free_pin(args[ARG_word_select].u_obj, MP_QSTR_word_select); + const mcu_pin_obj_t *data = validate_obj_is_free_pin(args[ARG_data].u_obj, MP_QSTR_data); + const mcu_pin_obj_t *main_clock = validate_obj_is_free_pin_or_none(args[ARG_main_clock].u_obj, MP_QSTR_main_clock); + + uint32_t sample_rate = args[ARG_sample_rate].u_int; + uint8_t bit_depth = args[ARG_bit_depth].u_int; + if (bit_depth != 8 && bit_depth != 16 && bit_depth != 24 && bit_depth != 32) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be 8, 16, 24, or 32"), MP_QSTR_bit_depth); + } + uint8_t output_bit_depth; + mp_obj_t output_bit_depth_obj = args[ARG_output_bit_depth].u_obj; + if (output_bit_depth_obj == mp_const_none) { + output_bit_depth = bit_depth; + } else { + mp_int_t v = mp_obj_get_int(output_bit_depth_obj); + if (v != 8 && v != 16 && v != 24 && v != 32) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be 8, 16, 24, or 32"), MP_QSTR_output_bit_depth); + } + output_bit_depth = (uint8_t)v; + } + bool mono = args[ARG_mono].u_bool; + bool left_justified = args[ARG_left_justified].u_bool; + bool samples_signed = args[ARG_samples_signed].u_bool; + + audioi2sin_i2sin_obj_t *self = mp_obj_malloc_with_finaliser(audioi2sin_i2sin_obj_t, &audioi2sin_i2sin_type); + common_hal_audioi2sin_i2sin_construct(self, bit_clock, word_select, data, main_clock, + sample_rate, bit_depth, output_bit_depth, mono, left_justified, samples_signed); + + return MP_OBJ_FROM_PTR(self); + #endif +} + +#if CIRCUITPY_AUDIOI2SIN +//| def deinit(self) -> None: +//| """Deinitialises the I2SIn and releases any hardware resources for reuse.""" +//| ... +//| +static mp_obj_t audioi2sin_i2sin_deinit(mp_obj_t self_in) { + audioi2sin_i2sin_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audioi2sin_i2sin_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audioi2sin_i2sin_deinit_obj, audioi2sin_i2sin_deinit); + +static void check_for_deinit(audioi2sin_i2sin_obj_t *self) { + if (common_hal_audioi2sin_i2sin_deinited(self)) { + raise_deinited_error(); + } +} + +//| def __enter__(self) -> I2SIn: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + +//| def record(self, destination: WriteableBuffer, destination_length: int) -> int: +//| """Records destination_length samples to destination. This is blocking. +//| +//| :return: The number of samples recorded. If this is less than ``destination_length``, +//| some samples were missed due to processing time.""" +//| ... +//| +static mp_obj_t audioi2sin_i2sin_obj_record(mp_obj_t self_obj, mp_obj_t destination, mp_obj_t destination_length) { + audioi2sin_i2sin_obj_t *self = MP_OBJ_TO_PTR(self_obj); + check_for_deinit(self); + uint32_t length = mp_arg_validate_type_int(destination_length, MP_QSTR_length); + mp_arg_validate_length_min(length, 0, MP_QSTR_length); + + mp_buffer_info_t bufinfo; + if (mp_obj_is_type(destination, &mp_type_fileio)) { + mp_raise_NotImplementedError(MP_ERROR_TEXT("Cannot record to a file")); + } + mp_get_buffer_raise(destination, &bufinfo, MP_BUFFER_WRITE); + if (bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL) < length) { + mp_raise_ValueError(MP_ERROR_TEXT("Destination capacity is smaller than destination_length.")); + } + uint8_t output_bit_depth = self->base.bits_per_sample; + char error_type = ' '; + bool samples_signed = common_hal_audioi2sin_i2sin_get_samples_signed(self); + if (samples_signed) { + if ((output_bit_depth == 24 || output_bit_depth == 32) && bufinfo.typecode != 'i') { + error_type = 'i'; + } else if (output_bit_depth == 16 && bufinfo.typecode != 'h') { + error_type = 'h'; + } else if (output_bit_depth == 8 && bufinfo.typecode != 'b' && bufinfo.typecode != BYTEARRAY_TYPECODE) { + error_type = 'b'; // NOTE: Not identifying as bytearray + } + } else { + if ((output_bit_depth == 24 || output_bit_depth == 32) && bufinfo.typecode != 'I') { + error_type = 'I'; + } else if (output_bit_depth == 16 && bufinfo.typecode != 'H') { + error_type = 'H'; + } else if (output_bit_depth == 8 && bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE) { + error_type = 'B'; + } + } + if (error_type != ' ') { + mp_raise_TypeError_varg( + MP_ERROR_TEXT("invalid destination buffer, must be an array of type: %c"), + error_type + ); + } + uint32_t length_written = + common_hal_audioi2sin_i2sin_record_to_buffer(self, bufinfo.buf, length); + return MP_OBJ_NEW_SMALL_INT(length_written); +} +MP_DEFINE_CONST_FUN_OBJ_3(audioi2sin_i2sin_record_obj, audioi2sin_i2sin_obj_record); + +//| sample_rate: int +//| """The configured (nominal) sample rate, in Hz. This is the rate reported to +//| the audio pipeline so it matches the output/consumer it is played into. The +//| true capture rate may differ from this by a fraction of a Hz due to internal +//| clock limitations.""" +//| +//| bits_per_sample: int +//| """The number of bits per sample as it is streamed through the audio pipeline. +//| (read-only)""" +//| +//| channel_count: int +//| """The number of channels (1 for mono, 2 for stereo). (read-only)""" +//| + +//| bit_depth: int +//| """The actual bit depth of the recording. (read-only)""" +//| +//| +static mp_obj_t audioi2sin_i2sin_obj_get_bit_depth(mp_obj_t self_in) { + audioi2sin_i2sin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_audioi2sin_i2sin_get_bit_depth(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audioi2sin_i2sin_get_bit_depth_obj, audioi2sin_i2sin_obj_get_bit_depth); + +MP_PROPERTY_GETTER(audioi2sin_i2sin_bit_depth_obj, + (mp_obj_t)&audioi2sin_i2sin_get_bit_depth_obj); + + +//| samples_signed: bool +//| """True if recorded samples are signed PCM, False for unsigned. (read-only)""" +//| +//| +static mp_obj_t audioi2sin_i2sin_obj_get_samples_signed(mp_obj_t self_in) { + audioi2sin_i2sin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audioi2sin_i2sin_get_samples_signed(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audioi2sin_i2sin_get_samples_signed_obj, audioi2sin_i2sin_obj_get_samples_signed); + +MP_PROPERTY_GETTER(audioi2sin_i2sin_samples_signed_obj, + (mp_obj_t)&audioi2sin_i2sin_get_samples_signed_obj); + +static const mp_rom_map_elem_t audioi2sin_i2sin_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&audioi2sin_i2sin_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioi2sin_i2sin_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_record), MP_ROM_PTR(&audioi2sin_i2sin_record_obj) }, + // sample_rate / bits_per_sample / channel_count come from the audiosample + // protocol's shared property getters. + AUDIOSAMPLE_FIELDS, + { MP_ROM_QSTR(MP_QSTR_bit_depth), MP_ROM_PTR(&audioi2sin_i2sin_bit_depth_obj) }, + { MP_ROM_QSTR(MP_QSTR_samples_signed), MP_ROM_PTR(&audioi2sin_i2sin_samples_signed_obj) }, +}; +static MP_DEFINE_CONST_DICT(audioi2sin_i2sin_locals_dict, audioi2sin_i2sin_locals_dict_table); + +static const audiosample_p_t audioi2sin_i2sin_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)common_hal_audioi2sin_i2sin_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)common_hal_audioi2sin_i2sin_get_buffer, +}; +#endif // CIRCUITPY_AUDIOI2SIN + +MP_DEFINE_CONST_OBJ_TYPE( + audioi2sin_i2sin_type, + MP_QSTR_I2SIn, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audioi2sin_i2sin_make_new + #if CIRCUITPY_AUDIOI2SIN + , locals_dict, &audioi2sin_i2sin_locals_dict + , protocol, &audioi2sin_i2sin_proto + #endif + ); diff --git a/shared-bindings/audioi2sin/I2SIn.h b/shared-bindings/audioi2sin/I2SIn.h new file mode 100644 index 00000000000..c0fc48a6d09 --- /dev/null +++ b/shared-bindings/audioi2sin/I2SIn.h @@ -0,0 +1,42 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-bindings/microcontroller/Pin.h" + +#if CIRCUITPY_AUDIOI2SIN +#include "common-hal/audioi2sin/I2SIn.h" +#include "shared-module/audiocore/__init__.h" +#endif + +extern const mp_obj_type_t audioi2sin_i2sin_type; + +#if CIRCUITPY_AUDIOI2SIN +void common_hal_audioi2sin_i2sin_construct(audioi2sin_i2sin_obj_t *self, + const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select, + const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, + uint32_t sample_rate, uint8_t bit_depth, uint8_t output_bit_depth, + bool mono, bool left_justified, bool samples_signed); +void common_hal_audioi2sin_i2sin_deinit(audioi2sin_i2sin_obj_t *self); +bool common_hal_audioi2sin_i2sin_deinited(audioi2sin_i2sin_obj_t *self); +uint32_t common_hal_audioi2sin_i2sin_record_to_buffer(audioi2sin_i2sin_obj_t *self, + void *buffer, uint32_t length); +uint8_t common_hal_audioi2sin_i2sin_get_bit_depth(audioi2sin_i2sin_obj_t *self); +uint32_t common_hal_audioi2sin_i2sin_get_sample_rate(audioi2sin_i2sin_obj_t *self); +bool common_hal_audioi2sin_i2sin_get_samples_signed(audioi2sin_i2sin_obj_t *self); + +// audiosample protocol: streaming source support. fill_buffer converts the +// frames currently available from the live mic into `buffer` (output depth, +// interleaved), padding with silence on underrun; it never blocks. +void common_hal_audioi2sin_i2sin_fill_buffer(audioi2sin_i2sin_obj_t *self, + uint8_t *buffer, uint32_t frames); +void common_hal_audioi2sin_i2sin_reset_buffer(audioi2sin_i2sin_obj_t *self, + bool single_channel_output, uint8_t channel); +audioio_get_buffer_result_t common_hal_audioi2sin_i2sin_get_buffer( + audioi2sin_i2sin_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length); +#endif diff --git a/shared-bindings/audioi2sin/__init__.c b/shared-bindings/audioi2sin/__init__.c new file mode 100644 index 00000000000..45ba16cb01a --- /dev/null +++ b/shared-bindings/audioi2sin/__init__.c @@ -0,0 +1,38 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/audioi2sin/__init__.h" +#include "shared-bindings/audioi2sin/I2SIn.h" + +//| """Support for recording audio from an I2S input source. +//| +//| The `audioi2sin` module contains the `I2SIn` class for recording audio +//| from an external I2S source such as a MEMS microphone (e.g. SPH0645LM4H +//| or INMP441). +//| +//| All classes change hardware state and should be deinitialized when they +//| are no longer needed. To do so, either call :py:meth:`!deinit` or use a +//| context manager.""" + +static const mp_rom_map_elem_t audioi2sin_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audioi2sin) }, + { MP_ROM_QSTR(MP_QSTR_I2SIn), MP_ROM_PTR(&audioi2sin_i2sin_type) }, +}; + +static MP_DEFINE_CONST_DICT(audioi2sin_module_globals, audioi2sin_module_globals_table); + +const mp_obj_module_t audioi2sin_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&audioi2sin_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_audioi2sin, audioi2sin_module); diff --git a/shared-bindings/audioi2sin/__init__.h b/shared-bindings/audioi2sin/__init__.h new file mode 100644 index 00000000000..779b49ffd8d --- /dev/null +++ b/shared-bindings/audioi2sin/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c index 82aecefa370..8ea068ceb8f 100644 --- a/shared-bindings/audioio/AudioOut.c +++ b/shared-bindings/audioio/AudioOut.c @@ -103,7 +103,10 @@ static mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar // create AudioOut object from the given pin audioio_audioout_obj_t *self = mp_obj_malloc_with_finaliser(audioio_audioout_obj_t, &audioio_audioout_type); - common_hal_audioio_audioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int); + common_hal_audioio_audioout_construct(self, + left_channel_pin, + right_channel_pin, + args[ARG_quiescent_value].u_int); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audiomixer/MixerVoice.c b/shared-bindings/audiomixer/MixerVoice.c index 128c214d447..4957fab3884 100644 --- a/shared-bindings/audiomixer/MixerVoice.c +++ b/shared-bindings/audiomixer/MixerVoice.c @@ -29,8 +29,8 @@ // TODO: support mono or stereo voices static mp_obj_t audiomixer_mixervoice_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_check_num(n_args, n_kw, 0, 0, false); - audiomixer_mixervoice_obj_t *self = mp_obj_malloc(audiomixer_mixervoice_obj_t, &audiomixer_mixervoice_type); + audiomixer_mixervoice_obj_t *self = mp_obj_malloc(audiomixer_mixervoice_obj_t, &audiomixer_mixervoice_type); common_hal_audiomixer_mixervoice_construct(self); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/audiomp3/MP3Decoder.c b/shared-bindings/audiomp3/MP3Decoder.c index ff6c77e8572..433b308c156 100644 --- a/shared-bindings/audiomp3/MP3Decoder.c +++ b/shared-bindings/audiomp3/MP3Decoder.c @@ -91,8 +91,6 @@ static mp_obj_t audiomp3_mp3file_make_new(const mp_obj_type_t *type, size_t n_ar stream = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), stream, MP_ROM_QSTR(MP_QSTR_rb)); } - audiomp3_mp3file_obj_t *self = mp_obj_malloc_with_finaliser(audiomp3_mp3file_obj_t, &audiomp3_mp3file_type); - const mp_stream_p_t *stream_p = mp_get_stream_raise(stream, MP_STREAM_OP_READ); if (stream_p->is_text) { @@ -106,6 +104,8 @@ static mp_obj_t audiomp3_mp3file_make_new(const mp_obj_type_t *type, size_t n_ar buffer = bufinfo.buf; buffer_size = bufinfo.len; } + + audiomp3_mp3file_obj_t *self = mp_obj_malloc_with_finaliser(audiomp3_mp3file_obj_t, &audiomp3_mp3file_type); common_hal_audiomp3_mp3file_construct(self, stream, buffer, buffer_size); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/audiopwmio/PWMAudioOut.c b/shared-bindings/audiopwmio/PWMAudioOut.c index 3c961433641..5b8d071924b 100644 --- a/shared-bindings/audiopwmio/PWMAudioOut.c +++ b/shared-bindings/audiopwmio/PWMAudioOut.c @@ -100,8 +100,10 @@ static mp_obj_t audiopwmio_pwmaudioout_make_new(const mp_obj_type_t *type, size_ // create AudioOut object from the given pin // The object is created with a finaliser as some ports use these (rather than 'reset' functions) // to ensure resources are collected at interpreter shutdown. - audiopwmio_pwmaudioout_obj_t *self = mp_obj_malloc_with_finaliser(audiopwmio_pwmaudioout_obj_t, &audiopwmio_pwmaudioout_type); - common_hal_audiopwmio_pwmaudioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int); + audiopwmio_pwmaudioout_obj_t *self = + mp_obj_malloc_with_finaliser(audiopwmio_pwmaudioout_obj_t, &audiopwmio_pwmaudioout_type); + common_hal_audiopwmio_pwmaudioout_construct(self, + left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audiospeed/Resampler.c b/shared-bindings/audiospeed/Resampler.c new file mode 100644 index 00000000000..8abf52905d4 --- /dev/null +++ b/shared-bindings/audiospeed/Resampler.c @@ -0,0 +1,113 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared/runtime/context_manager_helpers.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/audiospeed/Resampler.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-bindings/util.h" +#include "shared-module/audiospeed/Resampler.h" + +//| class Resampler: +//| """Wraps an audio sample to match it to the destination sample rate.""" +//| +//| def __init__(self) -> None: +//| """Create a Resampler that wraps ``source``. +//| +//| :param audiosample source: The audio source to resample. +//| +//| Playing a wave file through a mixer with half the sample rate:: +//| +//| import board +//| import audiocore +//| import audiomixer +//| import audiospeed +//| import audioio +//| +//| wav = audiocore.WaveFile("sample.wav") +//| resampler = audiospeed.Resampler(wav) +//| mixer = audiomixer.Mixer( +//| channel_count=wav.channel_count, +//| bits_per_sample=wav.bits_per_sample, +//| sample_rate=wav.sample_rate // 2, +//| ) +//| audio = audioio.AudioOut(board.A0) +//| audio.play(mixer) +//| mixer.play(resampler) +//| """ +//| ... +//| +static mp_obj_t audiospeed_resampler_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_source }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_source, MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Validate source implements audiosample protocol + mp_obj_t source = args[ARG_source].u_obj; + audiosample_check(source); + + audiospeed_resampler_obj_t *self = mp_obj_malloc(audiospeed_resampler_obj_t, &audiospeed_resampler_type); + common_hal_audiospeed_resampler_construct(self, source); + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the Resampler and releases all memory resources for reuse.""" +//| ... +//| +static mp_obj_t audiospeed_resampler_deinit(mp_obj_t self_in) { + audiospeed_resampler_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiospeed_resampler_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiospeed_resampler_deinit_obj, audiospeed_resampler_deinit); + +//| rate: float +//| """Playback speed multiplier.""" +//| +static mp_obj_t audiospeed_resampler_obj_get_rate(mp_obj_t self_in) { + audiospeed_resampler_obj_t *self = MP_OBJ_TO_PTR(self_in); + audiosample_check_for_deinit(&self->base.base); + return common_hal_audiospeed_resampler_get_rate(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiospeed_resampler_get_rate_obj, audiospeed_resampler_obj_get_rate); + +MP_PROPERTY_GETTER(audiospeed_resampler_rate_obj, + (mp_obj_t)&audiospeed_resampler_get_rate_obj); + +static const mp_rom_map_elem_t audiospeed_resampler_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiospeed_resampler_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_rate), MP_ROM_PTR(&audiospeed_resampler_rate_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiospeed_resampler_locals_dict, audiospeed_resampler_locals_dict_table); + +static const audiosample_p_t audiospeed_resampler_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiospeed_resampler_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiospeed_resampler_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiospeed_resampler_type, + MP_QSTR_Resampler, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiospeed_resampler_make_new, + locals_dict, &audiospeed_resampler_locals_dict, + protocol, &audiospeed_resampler_proto + ); diff --git a/shared-bindings/audiospeed/Resampler.h b/shared-bindings/audiospeed/Resampler.h new file mode 100644 index 00000000000..7a744474bd1 --- /dev/null +++ b/shared-bindings/audiospeed/Resampler.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiospeed/Resampler.h" + +extern const mp_obj_type_t audiospeed_resampler_type; + +void common_hal_audiospeed_resampler_construct(audiospeed_resampler_obj_t *self, mp_obj_t source); +void common_hal_audiospeed_resampler_deinit(audiospeed_resampler_obj_t *self); + +mp_obj_t common_hal_audiospeed_resampler_get_rate(audiospeed_resampler_obj_t *self); + +void audiospeed_resampler_set_sample_rate(audiospeed_resampler_obj_t *self, uint32_t sample_rate); diff --git a/shared-bindings/audiospeed/SpeedChanger.c b/shared-bindings/audiospeed/SpeedChanger.c new file mode 100644 index 00000000000..bcac6b7ff20 --- /dev/null +++ b/shared-bindings/audiospeed/SpeedChanger.c @@ -0,0 +1,123 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared/runtime/context_manager_helpers.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/audiospeed/SpeedChanger.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-bindings/util.h" +#include "shared-module/audiospeed/__init__.h" +#include "shared-module/audiospeed/SpeedChanger.h" + +//| class SpeedChanger: +//| """Wraps an audio sample to play it back at a different speed. +//| +//| Uses nearest-neighbor resampling with a fixed-point phase accumulator +//| for CPU-efficient variable-speed playback.""" +//| +//| def __init__(self, source: circuitpython_typing.AudioSample, rate: float = 1.0) -> None: +//| """Create a SpeedChanger that wraps ``source``. +//| +//| :param audiosample source: The audio source to resample. +//| :param float rate: Playback speed multiplier. 1.0 = normal, 2.0 = double speed, +//| 0.5 = half speed. Must be positive. +//| +//| Playing a wave file at 1.5x speed:: +//| +//| import board +//| import audiocore +//| import audiospeed +//| import audioio +//| +//| wav = audiocore.WaveFile("drum.wav") +//| fast = audiospeed.SpeedChanger(wav, rate=1.5) +//| audio = audioio.AudioOut(board.A0) +//| audio.play(fast) +//| +//| # Change speed during playback: +//| fast.rate = 2.0 # double speed +//| fast.rate = 0.5 # half speed +//| """ +//| ... +//| +static mp_obj_t audiospeed_speedchanger_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_source, ARG_rate }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_source, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_rate, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Validate source implements audiosample protocol + mp_obj_t source = args[ARG_source].u_obj; + audiosample_check(source); + + audiospeed_speedchanger_obj_t *self = mp_obj_malloc(audiospeed_speedchanger_obj_t, &audiospeed_speedchanger_type); + common_hal_audiospeed_speedchanger_construct(self, source, args[ARG_rate].u_obj); + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the SpeedChanger and releases all memory resources for reuse.""" +//| ... +//| +static mp_obj_t audiospeed_speedchanger_deinit(mp_obj_t self_in) { + audiospeed_speedchanger_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiospeed_speedchanger_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiospeed_speedchanger_deinit_obj, audiospeed_speedchanger_deinit); + +//| rate: float +//| """Playback speed multiplier. Can be changed during playback.""" +//| +static mp_obj_t audiospeed_speedchanger_obj_get_rate(mp_obj_t self_in) { + audiospeed_speedchanger_obj_t *self = MP_OBJ_TO_PTR(self_in); + audiosample_check_for_deinit(&self->base); + return common_hal_audiospeed_speedchanger_get_rate(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiospeed_speedchanger_get_rate_obj, audiospeed_speedchanger_obj_get_rate); + +static mp_obj_t audiospeed_speedchanger_obj_set_rate(mp_obj_t self_in, mp_obj_t rate_obj) { + audiospeed_speedchanger_obj_t *self = MP_OBJ_TO_PTR(self_in); + audiosample_check_for_deinit(&self->base); + common_hal_audiospeed_speedchanger_set_rate(self, rate_obj); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiospeed_speedchanger_set_rate_obj, audiospeed_speedchanger_obj_set_rate); + +MP_PROPERTY_GETSET(audiospeed_speedchanger_rate_obj, + (mp_obj_t)&audiospeed_speedchanger_get_rate_obj, + (mp_obj_t)&audiospeed_speedchanger_set_rate_obj); + +static const mp_rom_map_elem_t audiospeed_speedchanger_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiospeed_speedchanger_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_rate), MP_ROM_PTR(&audiospeed_speedchanger_rate_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiospeed_speedchanger_locals_dict, audiospeed_speedchanger_locals_dict_table); + +static const audiosample_p_t audiospeed_speedchanger_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiospeed_speedchanger_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiospeed_speedchanger_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiospeed_speedchanger_type, + MP_QSTR_SpeedChanger, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiospeed_speedchanger_make_new, + locals_dict, &audiospeed_speedchanger_locals_dict, + protocol, &audiospeed_speedchanger_proto + ); diff --git a/shared-bindings/audiospeed/SpeedChanger.h b/shared-bindings/audiospeed/SpeedChanger.h new file mode 100644 index 00000000000..bc0b166b612 --- /dev/null +++ b/shared-bindings/audiospeed/SpeedChanger.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiospeed/SpeedChanger.h" + +extern const mp_obj_type_t audiospeed_speedchanger_type; + +void common_hal_audiospeed_speedchanger_construct(audiospeed_speedchanger_obj_t *self, + mp_obj_t source, mp_obj_t rate_obj); +void common_hal_audiospeed_speedchanger_deinit(audiospeed_speedchanger_obj_t *self); + +void common_hal_audiospeed_speedchanger_set_rate(audiospeed_speedchanger_obj_t *self, mp_obj_t rate_obj); +mp_obj_t common_hal_audiospeed_speedchanger_get_rate(audiospeed_speedchanger_obj_t *self); diff --git a/shared-bindings/audiospeed/__init__.c b/shared-bindings/audiospeed/__init__.c new file mode 100644 index 00000000000..3eca41e6467 --- /dev/null +++ b/shared-bindings/audiospeed/__init__.c @@ -0,0 +1,30 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/audiospeed/Resampler.h" +#include "shared-bindings/audiospeed/SpeedChanger.h" + +//| """Audio processing tools""" + +static const mp_rom_map_elem_t audiospeed_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiospeed) }, + { MP_ROM_QSTR(MP_QSTR_Resampler), MP_ROM_PTR(&audiospeed_resampler_type) }, + { MP_ROM_QSTR(MP_QSTR_SpeedChanger), MP_ROM_PTR(&audiospeed_speedchanger_type) }, +}; + +static MP_DEFINE_CONST_DICT(audiospeed_module_globals, audiospeed_module_globals_table); + +const mp_obj_module_t audiospeed_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&audiospeed_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_audiospeed, audiospeed_module); diff --git a/shared-bindings/audiospeed/__init__.h b/shared-bindings/audiospeed/__init__.h new file mode 100644 index 00000000000..c4a52e5819d --- /dev/null +++ b/shared-bindings/audiospeed/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c index ddd8824eb58..e1413392699 100644 --- a/shared-bindings/bitbangio/I2C.c +++ b/shared-bindings/bitbangio/I2C.c @@ -59,7 +59,8 @@ static mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, bitbangio_i2c_obj_t *self = mp_obj_malloc_with_finaliser(bitbangio_i2c_obj_t, &bitbangio_i2c_type); shared_module_bitbangio_i2c_construct(self, args[ARG_scl].u_obj, args[ARG_sda].u_obj, args[ARG_frequency].u_int, args[ARG_timeout].u_int); - return (mp_obj_t)self; + + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c index f2e635b47bb..de021867f3c 100644 --- a/shared-bindings/bitbangio/SPI.c +++ b/shared-bindings/bitbangio/SPI.c @@ -67,7 +67,7 @@ static mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t n_args, bitbangio_spi_obj_t *self = mp_obj_malloc(bitbangio_spi_obj_t, &bitbangio_spi_type); shared_module_bitbangio_spi_construct(self, args[ARG_clock].u_obj, args[ARG_MOSI].u_obj, args[ARG_MISO].u_obj); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index f3aad1b67b0..a56075344e8 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -206,9 +206,9 @@ static mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap - displayio_bitmap_t *source = MP_OBJ_TO_PTR(args[ARG_source_bitmap].u_obj); // the source bitmap + displayio_bitmap_t *source = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_source_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap)); // the source bitmap // ensure that the destination bitmap has at least as many `bits_per_value` as the source if (destination->bits_per_value < source->bits_per_value) { @@ -311,6 +311,7 @@ MAKE_ENUM_TYPE(bitmaptools, BlendMode, bitmaptools_blendmode); //| blendmode: Optional[BlendMode] = BlendMode.Normal, //| skip_source1_index: Union[int, None] = None, //| skip_source2_index: Union[int, None] = None, +//| mask: Optional[displayio.Bitmap] = None, //| ) -> None: //| """Alpha blend the two source bitmaps into the destination. //| @@ -326,6 +327,11 @@ MAKE_ENUM_TYPE(bitmaptools, BlendMode, bitmaptools_blendmode); //| :param bitmaptools.BlendMode blendmode: The blend mode to use. Default is Normal. //| :param int skip_source1_index: Bitmap palette or luminance index in source_bitmap_1 that will not be blended, set to None to blend all pixels //| :param int skip_source2_index: Bitmap palette or luminance index in source_bitmap_2 that will not be blended, set to None to blend all pixels +//| :param displayio.Bitmap mask: Optional 8-bits-per-value grayscale mask bitmap controlling per-pixel opacity of ``source_bitmap_2``. +//| The mask must have the same width and height as the other bitmaps and a ``bits_per_value`` of 8. A mask value of 0 +//| means ``source_bitmap_2`` is fully transparent at that pixel (only ``source_bitmap_1`` contributes); a value of 255 means +//| ``source_bitmap_2`` is fully opaque at that pixel (subject to ``factor2``). Intermediate values scale ``factor2`` linearly. +//| Pass ``None`` to disable per-pixel masking. //| //| For the L8 colorspace, the bitmaps must have a bits-per-value of 8. //| For the RGB colorspaces, they must have a bits-per-value of 16.""" @@ -333,7 +339,7 @@ MAKE_ENUM_TYPE(bitmaptools, BlendMode, bitmaptools_blendmode); //| static mp_obj_t bitmaptools_alphablend(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum {ARG_dest_bitmap, ARG_source_bitmap_1, ARG_source_bitmap_2, ARG_colorspace, ARG_factor_1, ARG_factor_2, ARG_blendmode, ARG_skip_source1_index, ARG_skip_source2_index}; + enum {ARG_dest_bitmap, ARG_source_bitmap_1, ARG_source_bitmap_2, ARG_colorspace, ARG_factor_1, ARG_factor_2, ARG_blendmode, ARG_skip_source1_index, ARG_skip_source2_index, ARG_mask}; static const mp_arg_t allowed_args[] = { {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = NULL}}, @@ -345,6 +351,7 @@ static mp_obj_t bitmaptools_alphablend(size_t n_args, const mp_obj_t *pos_args, {MP_QSTR_blendmode, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = (void *)&bitmaptools_blendmode_Normal_obj}}, {MP_QSTR_skip_source1_index, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, {MP_QSTR_skip_source2_index, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + {MP_QSTR_mask, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -411,8 +418,19 @@ static mp_obj_t bitmaptools_alphablend(size_t n_args, const mp_obj_t *pos_args, skip_source2_index_none = false; } + displayio_bitmap_t *mask = NULL; + if (args[ARG_mask].u_obj != mp_const_none) { + mask = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_mask].u_obj, &displayio_bitmap_type, MP_QSTR_mask)); + if (mask->width != destination->width || mask->height != destination->height) { + mp_raise_ValueError(MP_ERROR_TEXT("Mask bitmap size must match the other bitmaps")); + } + if (mask->bits_per_value != 8) { + mp_raise_ValueError(MP_ERROR_TEXT("Mask bitmap must have 8 bits per pixel")); + } + } + common_hal_bitmaptools_alphablend(destination, source1, source2, colorspace, factor1, factor2, blendmode, skip_source1_index, - skip_source1_index_none, skip_source2_index, skip_source2_index_none); + skip_source1_index_none, skip_source2_index, skip_source2_index_none, mask); return mp_const_none; } @@ -485,7 +503,7 @@ static mp_obj_t bitmaptools_obj_fill_region(size_t n_args, const mp_obj_t *pos_a mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap uint32_t value, color_depth; value = args[ARG_value].u_int; @@ -598,7 +616,7 @@ static mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap uint32_t value, color_depth; value = args[ARG_value].u_int; @@ -684,7 +702,7 @@ static mp_obj_t bitmaptools_obj_draw_polygon(size_t n_args, const mp_obj_t *pos_ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap mp_buffer_info_t xs_buf, ys_buf; mp_get_buffer_raise(args[ARG_xs].u_obj, &xs_buf, MP_BUFFER_READ); @@ -1017,7 +1035,7 @@ static mp_obj_t bitmaptools_obj_draw_circle(size_t n_args, const mp_obj_t *pos_a mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap uint32_t value, color_depth; value = args[ARG_value].u_int; diff --git a/shared-bindings/bitmaptools/__init__.h b/shared-bindings/bitmaptools/__init__.h index f193ef6d952..20236983bac 100644 --- a/shared-bindings/bitmaptools/__init__.h +++ b/shared-bindings/bitmaptools/__init__.h @@ -69,7 +69,8 @@ void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int void common_hal_bitmaptools_dither(displayio_bitmap_t *dest_bitmap, displayio_bitmap_t *source_bitmap, displayio_colorspace_t colorspace, bitmaptools_dither_algorithm_t algorithm); void common_hal_bitmaptools_alphablend(displayio_bitmap_t *destination, displayio_bitmap_t *source1, displayio_bitmap_t *source2, displayio_colorspace_t colorspace, mp_float_t factor1, mp_float_t factor2, - bitmaptools_blendmode_t blendmode, uint32_t skip_source1_index, bool skip_source1_index_none, uint32_t skip_source2_index, bool skip_source2_index_none); + bitmaptools_blendmode_t blendmode, uint32_t skip_source1_index, bool skip_source1_index_none, uint32_t skip_source2_index, bool skip_source2_index_none, + displayio_bitmap_t *mask); typedef struct { union { diff --git a/shared-bindings/busdisplay/BusDisplay.c b/shared-bindings/busdisplay/BusDisplay.c index 297a8690577..0bf171a5d08 100644 --- a/shared-bindings/busdisplay/BusDisplay.c +++ b/shared-bindings/busdisplay/BusDisplay.c @@ -122,7 +122,6 @@ //| :param int native_frames_per_second: Number of display refreshes per second that occur with the given init_sequence. //| :param bool backlight_on_high: If True, pulling the backlight pin high turns the backlight on. //| :param bool SH1107_addressing: Special quirk for SH1107, use upper/lower column set and page set -//| :param int set_vertical_scroll: This parameter is accepted but ignored for backwards compatibility. It will be removed in a future release. //| :param int backlight_pwm_frequency: The frequency to use to drive the PWM for backlight brightness control. Default is 50000. //| """ //| ... @@ -133,7 +132,7 @@ static mp_obj_t busdisplay_busdisplay_make_new(const mp_obj_type_t *type, size_t ARG_rotation, ARG_color_depth, ARG_grayscale, ARG_pixels_in_byte_share_row, ARG_bytes_per_cell, ARG_reverse_pixels_in_byte, ARG_reverse_bytes_in_word, ARG_set_column_command, ARG_set_row_command, ARG_write_ram_command, - ARG_set_vertical_scroll, ARG_backlight_pin, ARG_brightness_command, + ARG_backlight_pin, ARG_brightness_command, ARG_brightness, ARG_single_byte_bounds, ARG_data_as_commands, ARG_auto_refresh, ARG_native_frames_per_second, ARG_backlight_on_high, ARG_SH1107_addressing, ARG_backlight_pwm_frequency }; @@ -154,7 +153,6 @@ static mp_obj_t busdisplay_busdisplay_make_new(const mp_obj_type_t *type, size_t { MP_QSTR_set_column_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2a} }, { MP_QSTR_set_row_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2b} }, { MP_QSTR_write_ram_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2c} }, - { MP_QSTR_set_vertical_scroll, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x0} }, { MP_QSTR_backlight_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, { MP_QSTR_brightness_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = NO_BRIGHTNESS_COMMAND} }, { MP_QSTR_brightness, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(1)} }, diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index a2724e60c34..5fa62f9df38 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -67,7 +67,7 @@ static mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz busio_i2c_obj_t *self = mp_obj_malloc_with_finaliser(busio_i2c_obj_t, &busio_i2c_type); common_hal_busio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); #else mp_raise_NotImplementedError(NULL); #endif // CIRCUITPY_BUSIO_I2C @@ -112,7 +112,7 @@ static void check_lock(busio_i2c_obj_t *self) { } } -//| def probe(self, address: int) -> List[int]: +//| def probe(self, address: int) -> bool: //| """Check if a device at the specified address responds. //| //| :param int address: 7-bit device address diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index 24c02a16e63..6ff74880266 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -9,17 +9,17 @@ #include +#include "py/binary.h" +#include "py/mperrno.h" +#include "py/objproperty.h" +#include "py/runtime.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/util.h" - #include "shared/runtime/buffer_helper.h" #include "shared/runtime/context_manager_helpers.h" -#include "py/binary.h" -#include "py/mperrno.h" -#include "py/objproperty.h" -#include "py/runtime.h" - +#include "shared/runtime/interrupt_char.h" +#include "supervisor/shared/tick.h" //| class SPI: //| """A 3-4 wire serial protocol @@ -88,7 +88,6 @@ // TODO(tannewt): Support LSB SPI. static mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_BUSIO_SPI - busio_spi_obj_t *self = mp_obj_malloc_with_finaliser(busio_spi_obj_t, &busio_spi_type); enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_half_duplex }; static const mp_arg_t allowed_args[] = { { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -107,6 +106,7 @@ static mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, siz mp_raise_ValueError(MP_ERROR_TEXT("Must provide MISO or MOSI pin")); } + busio_spi_obj_t *self = mp_obj_malloc_with_finaliser(busio_spi_obj_t, &busio_spi_type); common_hal_busio_spi_construct(self, clock, mosi, miso, args[ARG_half_duplex].u_bool); return MP_OBJ_FROM_PTR(self); #else @@ -157,9 +157,12 @@ static void check_for_deinit(busio_spi_obj_t *self) { //| ) -> None: //| """Configures the SPI bus. The SPI object must be locked. //| -//| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower -//| due to the granularity of available clock settings. +//| :param int baudrate: the desired clock rate in Hertz. The value is treated as a ceiling: +//| the actual clock rate may be lower due to the granularity of available clock settings, +//| but it will not exceed the given value. //| Check the `frequency` attribute for the actual clock rate. +//| **Limitations**: On Zephyr, the ceiling behavior may be violated, and +//| the `frequency` value does not reflect the actual baudrate. //| :param int polarity: the base state of the clock line (0 or 1) //| :param int phase: the edge of the clock that data is captured. First (0) //| or second (1). Rising or falling depends on clock polarity. @@ -168,13 +171,7 @@ static void check_for_deinit(busio_spi_obj_t *self) { //| .. note:: On the SAMD21, it is possible to set the baudrate to 24 MHz, but that //| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is //| within spec for the SAMD21. -//| -//| .. note:: On the nRF52840, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz, -//| and 8MHz. -//| If you pick a a baudrate other than one of these, the nearest lower -//| baudrate will be chosen, with a minimum of 125kHz. -//| Two SPI objects may be created, except on the Circuit Playground Bluefruit, -//| which allows only one (to allow for an additional I2C object).""" +//| """ //| ... //| @@ -445,9 +442,14 @@ static mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 1, busio_spi_write_readinto); //| frequency: int -//| """The actual SPI bus frequency. This may not match the frequency requested -//| due to internal limitations.""" +//| """The actual SPI bus frequency. This may be lower than the frequency requested +//| due to internal limitations, but it will not be higher. //| +//| **Limitations**: On Zephyr, the returned value does not reflect the actual baudrate, +//| because there is `no way to fetch the actual chosen frequency +//| `_. +//| In addition, on Zephyr, the ceiling behavior described in `configure` may be violated. +//| """ //| static mp_obj_t busio_spi_obj_get_frequency(mp_obj_t self_in) { @@ -494,3 +496,17 @@ MP_DEFINE_CONST_OBJ_TYPE( busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj, qstr arg_name) { return mp_arg_validate_type(obj, &busio_spi_type, arg_name); } + +// Wait as long as needed for the lock. This is used by SD card access from USB. +// The default implementation is to busy-wait while running the background tasks. espressif is different. +bool common_hal_busio_spi_wait_for_lock(busio_spi_obj_t *self, uint32_t timeout_ms) { + uint64_t deadline = supervisor_ticks_ms64() + timeout_ms; + while (supervisor_ticks_ms64() < deadline && + !mp_hal_is_interrupted()) { + if (common_hal_busio_spi_try_lock(self)) { + return true; + } + RUN_BACKGROUND_TASKS; + } + return false; +} diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h index 34f34c927f6..76ed697d665 100644 --- a/shared-bindings/busio/SPI.h +++ b/shared-bindings/busio/SPI.h @@ -54,3 +54,7 @@ uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t *self); extern void common_hal_busio_spi_never_reset(busio_spi_obj_t *self); extern busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj_in, qstr arg_name); + +// Wait as long as needed for the lock. This is used by SD card access from USB. +// For most ports, busy-wait while running the background tasks. +MP_WEAK bool common_hal_busio_spi_wait_for_lock(busio_spi_obj_t *self, uint32_t timeout_ms); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index 4714c3ee073..81e970a98f4 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -157,7 +157,7 @@ static mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, si common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485_dir, rs485_invert, args[ARG_baudrate].u_int, bits, parity, stop, timeout, buffer_size, NULL, false); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); #else mp_raise_NotImplementedError(NULL); #endif // CIRCUITPY_BUSIO_UART @@ -277,7 +277,7 @@ static mp_uint_t busio_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_ return common_hal_busio_uart_write(self, buf, size, errcode); } -static mp_uint_t busio_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +static mp_uint_t busio_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { busio_uart_obj_t *self = native_uart(self_in); check_for_deinit(self); mp_uint_t ret; diff --git a/shared-bindings/camera/Camera.c b/shared-bindings/camera/Camera.c index 6f42fa08bcf..f0991082e50 100644 --- a/shared-bindings/camera/Camera.c +++ b/shared-bindings/camera/Camera.c @@ -41,10 +41,10 @@ //| ... //| static mp_obj_t camera_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - camera_obj_t *self = mp_obj_malloc(camera_obj_t, &camera_type); // No arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); + camera_obj_t *self = mp_obj_malloc(camera_obj_t, &camera_type); common_hal_camera_construct(self); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/canio/Match.c b/shared-bindings/canio/Match.c index 5e44a7ce4ed..e7c3dba42aa 100644 --- a/shared-bindings/canio/Match.c +++ b/shared-bindings/canio/Match.c @@ -47,7 +47,8 @@ static mp_obj_t canio_match_make_new(const mp_obj_type_t *type, size_t n_args, s canio_match_obj_t *self = mp_obj_malloc(canio_match_obj_t, &canio_match_type); common_hal_canio_match_construct(self, id, mask, args[ARG_extended].u_bool); - return self; + + return MP_OBJ_FROM_PTR(self); } //| id: int diff --git a/shared-bindings/canio/Message.c b/shared-bindings/canio/Message.c index c40892b5edb..848b5b15e43 100644 --- a/shared-bindings/canio/Message.c +++ b/shared-bindings/canio/Message.c @@ -41,7 +41,8 @@ static mp_obj_t canio_message_make_new(const mp_obj_type_t *type, size_t n_args, canio_message_obj_t *self = mp_obj_malloc(canio_message_obj_t, &canio_message_type); common_hal_canio_message_construct(self, args[ARG_id].u_int, data.buf, data.len, args[ARG_extended].u_bool); - return self; + + return MP_OBJ_FROM_PTR(self); } //| id: int diff --git a/shared-bindings/canio/RemoteTransmissionRequest.c b/shared-bindings/canio/RemoteTransmissionRequest.c index 966fee71215..bdc91c494a4 100644 --- a/shared-bindings/canio/RemoteTransmissionRequest.c +++ b/shared-bindings/canio/RemoteTransmissionRequest.c @@ -42,7 +42,8 @@ static mp_obj_t canio_remote_transmission_request_make_new(const mp_obj_type_t * canio_remote_transmission_request_obj_t *self = mp_obj_malloc(canio_remote_transmission_request_obj_t, &canio_remote_transmission_request_type); common_hal_canio_remote_transmission_request_construct(self, args[ARG_id].u_int, length, args[ARG_extended].u_bool); - return self; + + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/countio/Counter.c b/shared-bindings/countio/Counter.c index c2e3ddc7404..9f8bd00645c 100644 --- a/shared-bindings/countio/Counter.c +++ b/shared-bindings/countio/Counter.c @@ -66,8 +66,8 @@ static mp_obj_t countio_counter_make_new(const mp_obj_type_t *type, size_t n_arg const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); const countio_edge_t edge = validate_edge(args[ARG_edge].u_obj, MP_QSTR_edge); const digitalio_pull_t pull = validate_pull(args[ARG_pull].u_obj, MP_QSTR_pull); - countio_counter_obj_t *self = mp_obj_malloc_with_finaliser(countio_counter_obj_t, &countio_counter_type); + countio_counter_obj_t *self = mp_obj_malloc_with_finaliser(countio_counter_obj_t, &countio_counter_type); common_hal_countio_counter_construct(self, pin, edge, pull); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/digitalio/DigitalInOut.c b/shared-bindings/digitalio/DigitalInOut.c index c868ca7d443..58f90b0b141 100644 --- a/shared-bindings/digitalio/DigitalInOut.c +++ b/shared-bindings/digitalio/DigitalInOut.c @@ -71,9 +71,9 @@ static mp_obj_t digitalio_digitalinout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); - digitalio_digitalinout_obj_t *self = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); - const mcu_pin_obj_t *pin = common_hal_digitalio_validate_pin(args[0]); + + digitalio_digitalinout_obj_t *self = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(self, pin); return MP_OBJ_FROM_PTR(self); @@ -191,9 +191,9 @@ static mp_obj_t digitalio_digitalinout_obj_get_direction(mp_obj_t self_in) { check_for_deinit(self); digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self); if (direction == DIRECTION_INPUT) { - return (mp_obj_t)&digitalio_direction_input_obj; + return MP_OBJ_FROM_PTR(&digitalio_direction_input_obj); } - return (mp_obj_t)&digitalio_direction_output_obj; + return MP_OBJ_FROM_PTR(&digitalio_direction_output_obj); } MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_get_direction_obj, digitalio_digitalinout_obj_get_direction); @@ -255,9 +255,9 @@ static mp_obj_t digitalio_digitalinout_obj_get_drive_mode(mp_obj_t self_in) { } digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self); if (drive_mode == DRIVE_MODE_PUSH_PULL) { - return (mp_obj_t)&digitalio_drive_mode_push_pull_obj; + return MP_OBJ_FROM_PTR(&digitalio_drive_mode_push_pull_obj); } - return (mp_obj_t)&digitalio_drive_mode_open_drain_obj; + return MP_OBJ_FROM_PTR(&digitalio_drive_mode_open_drain_obj); } MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_get_drive_mode_obj, digitalio_digitalinout_obj_get_drive_mode); diff --git a/shared-bindings/displayio/ColorConverter.c b/shared-bindings/displayio/ColorConverter.c index e2721cfdef2..bfd037016d4 100644 --- a/shared-bindings/displayio/ColorConverter.c +++ b/shared-bindings/displayio/ColorConverter.c @@ -39,7 +39,6 @@ static mp_obj_t displayio_colorconverter_make_new(const mp_obj_type_t *type, siz mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); displayio_colorconverter_t *self = mp_obj_malloc(displayio_colorconverter_t, &displayio_colorconverter_type); - common_hal_displayio_colorconverter_construct(self, args[ARG_dither].u_bool, (displayio_colorspace_t)cp_enum_value(&displayio_colorspace_type, args[ARG_input_colorspace].u_obj, MP_QSTR_input_colorspace)); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c index 560fb66a675..fb5cabf05bf 100644 --- a/shared-bindings/displayio/TileGrid.c +++ b/shared-bindings/displayio/TileGrid.c @@ -17,7 +17,7 @@ #include "shared-bindings/displayio/ColorConverter.h" #include "shared-bindings/displayio/OnDiskBitmap.h" #include "shared-bindings/displayio/Palette.h" -#ifdef CIRCUITPY_TILEPALETTEMAPPER +#if CIRCUITPY_TILEPALETTEMAPPER #include "shared-bindings/tilepalettemapper/TilePaletteMapper.h" #endif @@ -133,6 +133,7 @@ static mp_obj_t displayio_tilegrid_make_new(const mp_obj_type_t *type, size_t n_ bitmap_width / tile_width, bitmap_height / tile_height, pixel_shader, args[ARG_width].u_int, args[ARG_height].u_int, tile_width, tile_height, x, y, args[ARG_default_tile].u_int); + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/displayio/__init__.c b/shared-bindings/displayio/__init__.c index e0c35d3bce4..970c4826476 100644 --- a/shared-bindings/displayio/__init__.c +++ b/shared-bindings/displayio/__init__.c @@ -79,7 +79,12 @@ //| afterwards. This may take seconds to complete if an active EPaperDisplay is refreshing. //| //| Use this once in your code.py if you initialize a display. Place it right before the -//| initialization so the display is active as long as possible.""" +//| initialization so the display is active as long as possible. +//| +//| Once you release a builtin display (one that is initialized automatically, not by user code), +//| the display will remain released even if you restart the CircuitPython VM, for instance by typing ctrl-D. +//| The display is not re-initialized until you do a hard reset or manually initialize it again. +//| """ //| ... //| //| diff --git a/shared-bindings/displayio/__init__.h b/shared-bindings/displayio/__init__.h index 88e9650cf44..583f6b217fa 100644 --- a/shared-bindings/displayio/__init__.h +++ b/shared-bindings/displayio/__init__.h @@ -49,4 +49,5 @@ typedef bool (*display_bus_begin_transaction)(mp_obj_t bus); typedef void (*display_bus_send)(mp_obj_t bus, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length); typedef void (*display_bus_end_transaction)(mp_obj_t bus); +typedef void (*display_bus_flush)(mp_obj_t bus); typedef void (*display_bus_collect_ptrs)(mp_obj_t bus); diff --git a/shared-bindings/dotclockframebuffer/__init__.c b/shared-bindings/dotclockframebuffer/__init__.c index b8dbf8c1897..700cd067178 100644 --- a/shared-bindings/dotclockframebuffer/__init__.c +++ b/shared-bindings/dotclockframebuffer/__init__.c @@ -104,7 +104,7 @@ static mp_obj_t ioexpander_send_init_sequence(size_t n_args, const mp_obj_t *pos mp_arg_validate_int_range(cs_bit, 0, max_bit, MP_QSTR_cs_bit); mp_arg_validate_int_range(mosi_bit, 0, max_bit, MP_QSTR_mosi_bit); mp_arg_validate_int_range(clk_bit, 0, max_bit, MP_QSTR_clk_bit); - mp_arg_validate_int_range(gpio_data, 0, (1 << (max_bit * 8)) - 1, MP_QSTR_gpio_data); + mp_arg_validate_int_range(gpio_data, 0, (1 << (gpio_data_len * 8)) - 1, MP_QSTR_gpio_data); mp_int_t reset_mask = 0; if (args[ARG_reset_bit].u_obj != MP_ROM_NONE) { mp_int_t reset_bit = mp_arg_validate_int_range(mp_arg_validate_type_int(args[ARG_reset_bit].u_obj, MP_QSTR_reset_bit), 0, max_bit, MP_QSTR_reset_bit); diff --git a/shared-bindings/gnss/GNSS.c b/shared-bindings/gnss/GNSS.c index 95c3ed975d5..3df23979c9e 100644 --- a/shared-bindings/gnss/GNSS.c +++ b/shared-bindings/gnss/GNSS.c @@ -38,7 +38,6 @@ //| ... //| static mp_obj_t gnss_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - gnss_obj_t *self = mp_obj_malloc(gnss_obj_t, &gnss_type); enum { ARG_system }; static const mp_arg_t allowed_args[] = { { MP_QSTR_system, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -63,7 +62,9 @@ static mp_obj_t gnss_make_new(const mp_obj_type_t *type, size_t n_args, size_t n mp_raise_TypeError(MP_ERROR_TEXT("System entry must be gnss.SatelliteSystem")); } + gnss_obj_t *self = mp_obj_malloc(gnss_obj_t, &gnss_type); common_hal_gnss_construct(self, selection); + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/i2cioexpander/IOExpander.c b/shared-bindings/i2cioexpander/IOExpander.c index c828c6dc5c7..3efa0fd1868 100644 --- a/shared-bindings/i2cioexpander/IOExpander.c +++ b/shared-bindings/i2cioexpander/IOExpander.c @@ -72,8 +72,6 @@ static mp_obj_t i2cioexpander_ioexpander_make_new(const mp_obj_type_t *type, siz mp_raise_ValueError(MP_ERROR_TEXT("num_pins must be 8 or 16")); } - i2cioexpander_ioexpander_obj_t *self = mp_obj_malloc(i2cioexpander_ioexpander_obj_t, &i2cioexpander_ioexpander_type); - // Convert and validate register parameters uint16_t set_value_reg = NO_REGISTER; if (args[ARG_set_value_reg].u_obj != mp_const_none) { @@ -96,6 +94,8 @@ static mp_obj_t i2cioexpander_ioexpander_make_new(const mp_obj_type_t *type, siz set_direction_reg = reg; } + i2cioexpander_ioexpander_obj_t *self = + mp_obj_malloc(i2cioexpander_ioexpander_obj_t, &i2cioexpander_ioexpander_type); common_hal_i2cioexpander_ioexpander_construct( self, i2c, diff --git a/shared-bindings/i2ctarget/I2CTarget.c b/shared-bindings/i2ctarget/I2CTarget.c index 8586d1843cc..94dbf4e8be4 100644 --- a/shared-bindings/i2ctarget/I2CTarget.c +++ b/shared-bindings/i2ctarget/I2CTarget.c @@ -26,7 +26,8 @@ static mp_obj_t mp_obj_new_i2ctarget_i2c_target_request(i2ctarget_i2c_target_obj self->address = address; self->is_read = is_read; self->is_restart = is_restart; - return (mp_obj_t)self; + + return MP_OBJ_FROM_PTR(self); } //| class I2CTarget: @@ -50,7 +51,6 @@ static mp_obj_t mp_obj_new_i2ctarget_i2c_target_request(i2ctarget_i2c_target_obj //| ... //| static mp_obj_t i2ctarget_i2c_target_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - i2ctarget_i2c_target_obj_t *self = mp_obj_malloc_with_finaliser(i2ctarget_i2c_target_obj_t, &i2ctarget_i2c_target_type); enum { ARG_scl, ARG_sda, ARG_addresses, ARG_smbus }; static const mp_arg_t allowed_args[] = { { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -78,8 +78,10 @@ static mp_obj_t i2ctarget_i2c_target_make_new(const mp_obj_type_t *type, size_t mp_raise_ValueError(MP_ERROR_TEXT("addresses is empty")); } + i2ctarget_i2c_target_obj_t *self = mp_obj_malloc_with_finaliser(i2ctarget_i2c_target_obj_t, &i2ctarget_i2c_target_type); common_hal_i2ctarget_i2c_target_construct(self, scl, sda, addresses, i, args[ARG_smbus].u_bool); - return (mp_obj_t)self; + + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: diff --git a/shared-bindings/imagecapture/ParallelImageCapture.c b/shared-bindings/imagecapture/ParallelImageCapture.c index 866edb489ce..427eaeb3793 100644 --- a/shared-bindings/imagecapture/ParallelImageCapture.c +++ b/shared-bindings/imagecapture/ParallelImageCapture.c @@ -58,7 +58,6 @@ static mp_obj_t imagecapture_parallelimagecapture_make_new(const mp_obj_type_t * imagecapture_parallelimagecapture_obj_t *self = mp_obj_malloc(imagecapture_parallelimagecapture_obj_t, &imagecapture_parallelimagecapture_type); - common_hal_imagecapture_parallelimagecapture_construct(self, pins, pin_count, clock, vsync, href); return self; diff --git a/shared-bindings/ipaddress/IPv4Address.c b/shared-bindings/ipaddress/IPv4Address.c index 5aab02e9f5c..7705e500e7e 100644 --- a/shared-bindings/ipaddress/IPv4Address.c +++ b/shared-bindings/ipaddress/IPv4Address.c @@ -59,7 +59,6 @@ static mp_obj_t ipaddress_ipv4address_make_new(const mp_obj_type_t *type, size_t ipaddress_ipv4address_obj_t *self = mp_obj_malloc(ipaddress_ipv4address_obj_t, &ipaddress_ipv4address_type); - common_hal_ipaddress_ipv4address_construct(self, buf, 4); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/is31fl3741/IS31FL3741.c b/shared-bindings/is31fl3741/IS31FL3741.c index 0c6b3479b04..71c4437a1d2 100644 --- a/shared-bindings/is31fl3741/IS31FL3741.c +++ b/shared-bindings/is31fl3741/IS31FL3741.c @@ -38,7 +38,6 @@ static mp_obj_t is31fl3741_IS31FL3741_make_new(const mp_obj_type_t *type, size_t mp_obj_t i2c = mp_arg_validate_type(args[ARG_i2c].u_obj, &busio_i2c_type, MP_QSTR_i2c_bus); is31fl3741_IS31FL3741_obj_t *self = mp_obj_malloc(is31fl3741_IS31FL3741_obj_t, &is31fl3741_IS31FL3741_type); - common_hal_is31fl3741_IS31FL3741_construct(self, MP_OBJ_TO_PTR(i2c), args[ARG_addr].u_int diff --git a/shared-bindings/jpegio/JpegDecoder.c b/shared-bindings/jpegio/JpegDecoder.c index 13287a23650..d55de7b67e0 100644 --- a/shared-bindings/jpegio/JpegDecoder.c +++ b/shared-bindings/jpegio/JpegDecoder.c @@ -23,13 +23,18 @@ //| Example:: //| //| from jpegio import JpegDecoder -//| from displayio import Bitmap +//| from displayio import Bitmap, TileGrid, ColorConverter, Colorspace +//| import supervisor //| //| decoder = JpegDecoder() //| width, height = decoder.open("/sd/example.jpg") //| bitmap = Bitmap(width, height, 65535) //| decoder.decode(bitmap) -//| # .. do something with bitmap +//| tg = TileGrid(bitmap, pixel_shader=ColorConverter(input_colorspace=Colorspace.RGB565_SWAPPED)) +//| supervisor.runtime.display.root_group = tg +//| while True: +//| pass +//| //| """ //| //| def __init__(self) -> None: @@ -43,7 +48,6 @@ static mp_obj_t jpegio_jpegdecoder_make_new(const mp_obj_type_t *type, size_t n_ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); jpegio_jpegdecoder_obj_t *self = mp_obj_malloc(jpegio_jpegdecoder_obj_t, &jpegio_jpegdecoder_type); - self->base.type = &jpegio_jpegdecoder_type; common_hal_jpegio_jpegdecoder_construct(self); return MP_OBJ_FROM_PTR(self); @@ -137,7 +141,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(jpegio_jpegdecoder_open_obj, jpegio_jpegdecoder_open); //| """ //| //| -static mp_obj_t jpegio_jpegdecoder_decode(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t jpegio_jpegdecoder_decode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { jpegio_jpegdecoder_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); enum { ARG_bitmap, ARG_scale, ARG_x, ARG_y, ARGS_X1_Y1_X2_Y2, ARG_skip_source_index, ARG_skip_dest_index }; diff --git a/shared-bindings/keypad/Event.c b/shared-bindings/keypad/Event.c index 51e446e8362..f83e01e785e 100644 --- a/shared-bindings/keypad/Event.c +++ b/shared-bindings/keypad/Event.c @@ -26,7 +26,6 @@ //| ... //| static mp_obj_t keypad_event_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - keypad_event_obj_t *self = mp_obj_malloc(keypad_event_obj_t, &keypad_event_type); enum { ARG_key_number, ARG_pressed, ARG_timestamp }; static const mp_arg_t allowed_args[] = { { MP_QSTR_key_number, MP_ARG_INT, {.u_int = 0} }, @@ -45,7 +44,9 @@ static mp_obj_t keypad_event_make_new(const mp_obj_type_t *type, size_t n_args, } (void)mp_obj_get_int_truncated(timestamp); // ensure that timestamp is an integer + keypad_event_obj_t *self = mp_obj_malloc(keypad_event_obj_t, &keypad_event_type); common_hal_keypad_event_construct(self, key_number, args[ARG_pressed].u_bool, timestamp); + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/keypad/KeyMatrix.c b/shared-bindings/keypad/KeyMatrix.c index edb32c2c5c7..01416a2f8a1 100644 --- a/shared-bindings/keypad/KeyMatrix.c +++ b/shared-bindings/keypad/KeyMatrix.c @@ -81,7 +81,6 @@ static mp_obj_t keypad_keymatrix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_KEYPAD_KEYMATRIX - keypad_keymatrix_obj_t *self = mp_obj_malloc(keypad_keymatrix_obj_t, &keypad_keymatrix_type); enum { ARG_row_pins, ARG_column_pins, ARG_columns_to_anodes, ARG_interval, ARG_max_events, ARG_debounce_threshold }; static const mp_arg_t allowed_args[] = { { MP_QSTR_row_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -123,7 +122,9 @@ static mp_obj_t keypad_keymatrix_make_new(const mp_obj_type_t *type, size_t n_ar column_pins_array[column] = pin; } + keypad_keymatrix_obj_t *self = mp_obj_malloc(keypad_keymatrix_obj_t, &keypad_keymatrix_type); common_hal_keypad_keymatrix_construct(self, num_row_pins, row_pins_array, num_column_pins, column_pins_array, args[ARG_columns_to_anodes].u_bool, interval, max_events, debounce_threshold); + return MP_OBJ_FROM_PTR(self); #else mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_KeyMatrix); diff --git a/shared-bindings/keypad/Keys.c b/shared-bindings/keypad/Keys.c index 64e8e51a67d..5fd065fc627 100644 --- a/shared-bindings/keypad/Keys.c +++ b/shared-bindings/keypad/Keys.c @@ -81,7 +81,6 @@ static mp_obj_t keypad_keys_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_KEYPAD_KEYS - keypad_keys_obj_t *self = mp_obj_malloc(keypad_keys_obj_t, &keypad_keys_type); enum { ARG_pins, ARG_value_when_pressed, ARG_pull, ARG_interval, ARG_max_events, ARG_debounce_threshold }; static const mp_arg_t allowed_args[] = { { MP_QSTR_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -112,6 +111,7 @@ static mp_obj_t keypad_keys_make_new(const mp_obj_type_t *type, size_t n_args, s validate_obj_is_free_pin(mp_obj_subscr(pins, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL), MP_QSTR_pin); } + keypad_keys_obj_t *self = mp_obj_malloc(keypad_keys_obj_t, &keypad_keys_type); common_hal_keypad_keys_construct(self, num_pins, pins_array, value_when_pressed, args[ARG_pull].u_bool, interval, max_events, debounce_threshold); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/keypad/ShiftRegisterKeys.c b/shared-bindings/keypad/ShiftRegisterKeys.c index 1347735b5d2..7f89a11ecf1 100644 --- a/shared-bindings/keypad/ShiftRegisterKeys.c +++ b/shared-bindings/keypad/ShiftRegisterKeys.c @@ -88,8 +88,6 @@ static mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS - keypad_shiftregisterkeys_obj_t *self = - mp_obj_malloc(keypad_shiftregisterkeys_obj_t, &keypad_shiftregisterkeys_type); enum { ARG_clock, ARG_data, ARG_latch, ARG_value_to_latch, ARG_key_count, ARG_value_when_pressed, ARG_interval, ARG_max_events, ARG_debounce_threshold }; static const mp_arg_t allowed_args[] = { { MP_QSTR_clock, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -160,6 +158,8 @@ static mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, siz const size_t max_events = (size_t)mp_arg_validate_int_min(args[ARG_max_events].u_int, 1, MP_QSTR_max_events); const uint8_t debounce_threshold = (uint8_t)mp_arg_validate_int_range(args[ARG_debounce_threshold].u_int, 1, 127, MP_QSTR_debounce_threshold); + keypad_shiftregisterkeys_obj_t *self = + mp_obj_malloc(keypad_shiftregisterkeys_obj_t, &keypad_shiftregisterkeys_type); common_hal_keypad_shiftregisterkeys_construct( self, clock, num_data_pins, data_pins_array, latch, value_to_latch, num_key_counts, key_count_array, value_when_pressed, interval, max_events, debounce_threshold); diff --git a/shared-bindings/keypad_demux/DemuxKeyMatrix.c b/shared-bindings/keypad_demux/DemuxKeyMatrix.c index f1b5ecae9ce..554e461c228 100644 --- a/shared-bindings/keypad_demux/DemuxKeyMatrix.c +++ b/shared-bindings/keypad_demux/DemuxKeyMatrix.c @@ -80,7 +80,6 @@ //| static mp_obj_t keypad_demux_demuxkeymatrix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - keypad_demux_demuxkeymatrix_obj_t *self = mp_obj_malloc(keypad_demux_demuxkeymatrix_obj_t, &keypad_demux_demuxkeymatrix_type); enum { ARG_row_addr_pins, ARG_column_pins, ARG_columns_to_anodes, ARG_transpose, ARG_interval, ARG_max_events, ARG_debounce_threshold }; static const mp_arg_t allowed_args[] = { { MP_QSTR_row_addr_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -123,8 +122,10 @@ static mp_obj_t keypad_demux_demuxkeymatrix_make_new(const mp_obj_type_t *type, column_pins_array[column] = pin; } + keypad_demux_demuxkeymatrix_obj_t *self = mp_obj_malloc(keypad_demux_demuxkeymatrix_obj_t, &keypad_demux_demuxkeymatrix_type); // Last arg is use_gc_allocator, true during VM use. common_hal_keypad_demux_demuxkeymatrix_construct(self, num_row_addr_pins, row_addr_pins_array, num_column_pins, column_pins_array, args[ARG_columns_to_anodes].u_bool, args[ARG_transpose].u_bool, interval, max_events, debounce_threshold, true); + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/math/__init__.c b/shared-bindings/math/__init__.c index 54fe53280ca..49ca2958d8c 100644 --- a/shared-bindings/math/__init__.c +++ b/shared-bindings/math/__init__.c @@ -26,7 +26,7 @@ //| """ //| -static NORETURN void math_error(void) { +static MP_NORETURN void math_error(void) { mp_raise_ValueError(MP_ERROR_TEXT("math domain error")); } diff --git a/shared-bindings/mcp4822/MCP4822.c b/shared-bindings/mcp4822/MCP4822.c new file mode 100644 index 00000000000..f192caf4052 --- /dev/null +++ b/shared-bindings/mcp4822/MCP4822.c @@ -0,0 +1,243 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/mcp4822/MCP4822.h" +#include "shared-bindings/util.h" + +//| class MCP4822: +//| """Output audio to an MCP4822 dual-channel 12-bit SPI DAC.""" +//| +//| def __init__( +//| self, +//| clock: microcontroller.Pin, +//| mosi: microcontroller.Pin, +//| cs: microcontroller.Pin, +//| *, +//| gain: int = 1, +//| ) -> None: +//| """Create an MCP4822 object associated with the given SPI pins. +//| +//| :param ~microcontroller.Pin clock: The SPI clock (SCK) pin +//| :param ~microcontroller.Pin mosi: The SPI data (SDI/MOSI) pin +//| :param ~microcontroller.Pin cs: The chip select (CS) pin +//| :param int gain: DAC output gain, 1 for 1x (0-2.048V) or 2 for 2x (0-4.096V). Default 1. +//| +//| Simple 8ksps 440 Hz sine wave:: +//| +//| import mcp4822 +//| import audiocore +//| import board +//| import array +//| import time +//| import math +//| +//| length = 8000 // 440 +//| sine_wave = array.array("H", [0] * length) +//| for i in range(length): +//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15) +//| +//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000) +//| dac = mcp4822.MCP4822(clock=board.GP18, mosi=board.GP19, cs=board.GP21) +//| dac.play(sine_wave, loop=True) +//| time.sleep(1) +//| dac.stop() +//| +//| Playing a wave file from flash:: +//| +//| import board +//| import audiocore +//| import mcp4822 +//| +//| f = open("sound.wav", "rb") +//| wav = audiocore.WaveFile(f) +//| +//| dac = mcp4822.MCP4822(clock=board.GP18, mosi=board.GP19, cs=board.GP21) +//| dac.play(wav) +//| while dac.playing: +//| pass""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_clock, ARG_mosi, ARG_cs, ARG_gain }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_mosi, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_cs, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_gain, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock); + const mcu_pin_obj_t *mosi = validate_obj_is_free_pin(args[ARG_mosi].u_obj, MP_QSTR_mosi); + const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); + const mp_int_t gain = mp_arg_validate_int_range(args[ARG_gain].u_int, 1, 2, MP_QSTR_gain); + + mcp4822_mcp4822_obj_t *self = mp_obj_malloc_with_finaliser(mcp4822_mcp4822_obj_t, &mcp4822_mcp4822_type); + common_hal_mcp4822_mcp4822_construct(self, clock, mosi, cs, (uint8_t)gain); + + return MP_OBJ_FROM_PTR(self); +} + +static void check_for_deinit(mcp4822_mcp4822_obj_t *self) { + if (common_hal_mcp4822_mcp4822_deinited(self)) { + raise_deinited_error(); + } +} + +//| def deinit(self) -> None: +//| """Deinitialises the MCP4822 and releases any hardware resources for reuse.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_deinit(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_mcp4822_mcp4822_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_deinit_obj, mcp4822_mcp4822_deinit); + +//| def __enter__(self) -> MCP4822: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`. +//| +//| The sample itself should consist of 8 bit or 16 bit samples.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_mcp4822_mcp4822_play(self, sample, args[ARG_loop].u_bool); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mcp4822_mcp4822_play_obj, 1, mcp4822_mcp4822_obj_play); + +//| def stop(self) -> None: +//| """Stops playback.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_obj_stop(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_mcp4822_mcp4822_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_stop_obj, mcp4822_mcp4822_obj_stop); + +//| playing: bool +//| """True when the audio sample is being output. (read-only)""" +//| +static mp_obj_t mcp4822_mcp4822_obj_get_playing(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_mcp4822_mcp4822_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_get_playing_obj, mcp4822_mcp4822_obj_get_playing); + +MP_PROPERTY_GETTER(mcp4822_mcp4822_playing_obj, + (mp_obj_t)&mcp4822_mcp4822_get_playing_obj); + +//| def pause(self) -> None: +//| """Stops playback temporarily while remembering the position. Use `resume` to resume playback.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_obj_pause(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + if (!common_hal_mcp4822_mcp4822_get_playing(self)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Not playing")); + } + common_hal_mcp4822_mcp4822_pause(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_pause_obj, mcp4822_mcp4822_obj_pause); + +//| def resume(self) -> None: +//| """Resumes sample playback after :py:func:`pause`.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_obj_resume(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + if (common_hal_mcp4822_mcp4822_get_paused(self)) { + common_hal_mcp4822_mcp4822_resume(self); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_resume_obj, mcp4822_mcp4822_obj_resume); + +//| paused: bool +//| """True when playback is paused. (read-only)""" +//| +//| +static mp_obj_t mcp4822_mcp4822_obj_get_paused(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_mcp4822_mcp4822_get_paused(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_get_paused_obj, mcp4822_mcp4822_obj_get_paused); + +MP_PROPERTY_GETTER(mcp4822_mcp4822_paused_obj, + (mp_obj_t)&mcp4822_mcp4822_get_paused_obj); + +static const mp_rom_map_elem_t mcp4822_mcp4822_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mcp4822_mcp4822_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mcp4822_mcp4822_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&mcp4822_mcp4822_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mcp4822_mcp4822_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&mcp4822_mcp4822_pause_obj) }, + { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&mcp4822_mcp4822_resume_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&mcp4822_mcp4822_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_paused), MP_ROM_PTR(&mcp4822_mcp4822_paused_obj) }, +}; +static MP_DEFINE_CONST_DICT(mcp4822_mcp4822_locals_dict, mcp4822_mcp4822_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + mcp4822_mcp4822_type, + MP_QSTR_MCP4822, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, mcp4822_mcp4822_make_new, + locals_dict, &mcp4822_mcp4822_locals_dict + ); diff --git a/shared-bindings/mcp4822/MCP4822.h b/shared-bindings/mcp4822/MCP4822.h new file mode 100644 index 00000000000..b129aec3061 --- /dev/null +++ b/shared-bindings/mcp4822/MCP4822.h @@ -0,0 +1,25 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/mcp4822/MCP4822.h" +#include "common-hal/microcontroller/Pin.h" + +extern const mp_obj_type_t mcp4822_mcp4822_type; + +void common_hal_mcp4822_mcp4822_construct(mcp4822_mcp4822_obj_t *self, + const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *cs, uint8_t gain); + +void common_hal_mcp4822_mcp4822_deinit(mcp4822_mcp4822_obj_t *self); +bool common_hal_mcp4822_mcp4822_deinited(mcp4822_mcp4822_obj_t *self); +void common_hal_mcp4822_mcp4822_play(mcp4822_mcp4822_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_mcp4822_mcp4822_stop(mcp4822_mcp4822_obj_t *self); +bool common_hal_mcp4822_mcp4822_get_playing(mcp4822_mcp4822_obj_t *self); +void common_hal_mcp4822_mcp4822_pause(mcp4822_mcp4822_obj_t *self); +void common_hal_mcp4822_mcp4822_resume(mcp4822_mcp4822_obj_t *self); +bool common_hal_mcp4822_mcp4822_get_paused(mcp4822_mcp4822_obj_t *self); diff --git a/shared-bindings/mcp4822/__init__.c b/shared-bindings/mcp4822/__init__.c new file mode 100644 index 00000000000..bac2136d9e7 --- /dev/null +++ b/shared-bindings/mcp4822/__init__.c @@ -0,0 +1,36 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/mcp4822/__init__.h" +#include "shared-bindings/mcp4822/MCP4822.h" + +//| """Audio output via MCP4822 dual-channel 12-bit SPI DAC. +//| +//| The `mcp4822` module provides the `MCP4822` class for non-blocking +//| audio playback through the Microchip MCP4822 SPI DAC using PIO and DMA. +//| +//| All classes change hardware state and should be deinitialized when they +//| are no longer needed. To do so, either call :py:meth:`!deinit` or use a +//| context manager.""" + +static const mp_rom_map_elem_t mcp4822_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mcp4822) }, + { MP_ROM_QSTR(MP_QSTR_MCP4822), MP_ROM_PTR(&mcp4822_mcp4822_type) }, +}; + +static MP_DEFINE_CONST_DICT(mcp4822_module_globals, mcp4822_module_globals_table); + +const mp_obj_module_t mcp4822_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mcp4822_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_mcp4822, mcp4822_module); diff --git a/shared-bindings/mcp4822/__init__.h b/shared-bindings/mcp4822/__init__.h new file mode 100644 index 00000000000..c4a52e5819d --- /dev/null +++ b/shared-bindings/mcp4822/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/memorymap/AddressRange.c b/shared-bindings/memorymap/AddressRange.c index efc55ad37d7..5f7ee0deb95 100644 --- a/shared-bindings/memorymap/AddressRange.c +++ b/shared-bindings/memorymap/AddressRange.c @@ -92,7 +92,6 @@ static mp_obj_t memorymap_addressrange_make_new(const mp_obj_type_t *type, size_ } memorymap_addressrange_obj_t *self = mp_obj_malloc(memorymap_addressrange_obj_t, &memorymap_addressrange_type); - common_hal_memorymap_addressrange_construct(self, (uint8_t *)start, length); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/memorymonitor/AllocationAlarm.c b/shared-bindings/memorymonitor/AllocationAlarm.c index 5475e2d7db4..00cfbbd9fe1 100644 --- a/shared-bindings/memorymonitor/AllocationAlarm.c +++ b/shared-bindings/memorymonitor/AllocationAlarm.c @@ -48,7 +48,6 @@ static mp_obj_t memorymonitor_allocationalarm_make_new(const mp_obj_type_t *type memorymonitor_allocationalarm_obj_t *self = mp_obj_malloc(memorymonitor_allocationalarm_obj_t, &memorymonitor_allocationalarm_type); - common_hal_memorymonitor_allocationalarm_construct(self, minimum_block_count); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/memorymonitor/__init__.c b/shared-bindings/memorymonitor/__init__.c index 64d0140ff79..e364344b363 100644 --- a/shared-bindings/memorymonitor/__init__.c +++ b/shared-bindings/memorymonitor/__init__.c @@ -25,7 +25,7 @@ //| MP_DEFINE_MEMORYMONITOR_EXCEPTION(AllocationError, Exception) -NORETURN void mp_raise_memorymonitor_AllocationError(mp_rom_error_text_t fmt, ...) { +MP_NORETURN void mp_raise_memorymonitor_AllocationError(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_memorymonitor_AllocationError, fmt, argptr); diff --git a/shared-bindings/memorymonitor/__init__.h b/shared-bindings/memorymonitor/__init__.h index 28480bea7b5..5f141b924d0 100644 --- a/shared-bindings/memorymonitor/__init__.h +++ b/shared-bindings/memorymonitor/__init__.h @@ -23,4 +23,4 @@ void memorymonitor_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr extern const mp_obj_type_t mp_type_memorymonitor_AllocationError; -NORETURN void mp_raise_memorymonitor_AllocationError(mp_rom_error_text_t msg, ...); +MP_NORETURN void mp_raise_memorymonitor_AllocationError(mp_rom_error_text_t msg, ...); diff --git a/shared-bindings/microcontroller/Pin.c b/shared-bindings/microcontroller/Pin.c index e74d54b0770..1fcde50e060 100644 --- a/shared-bindings/microcontroller/Pin.c +++ b/shared-bindings/microcontroller/Pin.c @@ -175,14 +175,14 @@ void validate_pins(qstr what, uint8_t *pin_nos, mp_int_t max_pins, mp_obj_t seq, } } -NORETURN void raise_ValueError_invalid_pin(void) { +MP_NORETURN void raise_ValueError_invalid_pin(void) { mp_arg_error_invalid(MP_QSTR_pin); } -NORETURN void raise_ValueError_invalid_pins(void) { +MP_NORETURN void raise_ValueError_invalid_pins(void) { mp_arg_error_invalid(MP_QSTR_pins); } -NORETURN void raise_ValueError_invalid_pin_name(qstr pin_name) { +MP_NORETURN void raise_ValueError_invalid_pin_name(qstr pin_name) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q pin"), pin_name); } diff --git a/shared-bindings/microcontroller/Pin.h b/shared-bindings/microcontroller/Pin.h index 1245b5f23e4..8ddca71bfbb 100644 --- a/shared-bindings/microcontroller/Pin.h +++ b/shared-bindings/microcontroller/Pin.h @@ -21,9 +21,9 @@ void validate_no_duplicate_pins(mp_obj_t seq, qstr arg_name); void validate_no_duplicate_pins_2(mp_obj_t seq1, mp_obj_t seq2, qstr arg_name1, qstr arg_name2); void validate_list_is_free_pins(qstr what, const mcu_pin_obj_t **pins_out, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out); void validate_pins(qstr what, uint8_t *pin_nos, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out); -NORETURN void raise_ValueError_invalid_pin(void); -NORETURN void raise_ValueError_invalid_pins(void); -NORETURN void raise_ValueError_invalid_pin_name(qstr pin_name); +MP_NORETURN void raise_ValueError_invalid_pin(void); +MP_NORETURN void raise_ValueError_invalid_pins(void); +MP_NORETURN void raise_ValueError_invalid_pin_name(qstr pin_name); void assert_pin_free(const mcu_pin_obj_t *pin); diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h index 2a4a9732781..5c5902ff965 100644 --- a/shared-bindings/microcontroller/__init__.h +++ b/shared-bindings/microcontroller/__init__.h @@ -20,7 +20,7 @@ extern void common_hal_mcu_disable_interrupts(void); extern void common_hal_mcu_enable_interrupts(void); extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode); -NORETURN extern void common_hal_mcu_reset(void); +MP_NORETURN extern void common_hal_mcu_reset(void); extern const mp_obj_dict_t mcu_pin_globals; diff --git a/shared-bindings/msgpack/ExtType.c b/shared-bindings/msgpack/ExtType.c index f66abda8fa2..c69416f9773 100644 --- a/shared-bindings/msgpack/ExtType.c +++ b/shared-bindings/msgpack/ExtType.c @@ -18,7 +18,6 @@ //| :param bytes data: representation.""" //| static mp_obj_t mod_msgpack_exttype_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - mod_msgpack_extype_obj_t *self = mp_obj_malloc(mod_msgpack_extype_obj_t, &mod_msgpack_exttype_type); enum { ARG_code, ARG_data }; static const mp_arg_t allowed_args[] = { { MP_QSTR_code, MP_ARG_INT | MP_ARG_REQUIRED }, @@ -28,11 +27,12 @@ static mp_obj_t mod_msgpack_exttype_make_new(const mp_obj_type_t *type, size_t n mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); int code = mp_arg_validate_int_range(args[ARG_code].u_int, 0, 127, MP_QSTR_code); + mp_obj_t data = args[ARG_data].u_obj; + mod_msgpack_extype_obj_t *self = mp_obj_malloc(mod_msgpack_extype_obj_t, &mod_msgpack_exttype_type); self->code = code; - - mp_obj_t data = args[ARG_data].u_obj; self->data = data; + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/onewireio/OneWire.c b/shared-bindings/onewireio/OneWire.c index a3750ae5e07..2f69424cc23 100644 --- a/shared-bindings/onewireio/OneWire.c +++ b/shared-bindings/onewireio/OneWire.c @@ -43,8 +43,8 @@ static mp_obj_t onewireio_onewire_make_new(const mp_obj_type_t *type, size_t n_a const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); onewireio_onewire_obj_t *self = mp_obj_malloc(onewireio_onewire_obj_t, &onewireio_onewire_type); - common_hal_onewireio_onewire_construct(self, pin); + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/os/__init__.c b/shared-bindings/os/__init__.c index 65bc90fbf86..bbf5a5025c1 100644 --- a/shared-bindings/os/__init__.c +++ b/shared-bindings/os/__init__.c @@ -67,7 +67,7 @@ static MP_DEFINE_ATTRTUPLE( ); static mp_obj_t os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; + return MP_OBJ_FROM_PTR(&os_uname_info_obj); } static MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); diff --git a/shared-bindings/paralleldisplaybus/ParallelBus.c b/shared-bindings/paralleldisplaybus/ParallelBus.c index dfe363bdcb7..7f8749501fb 100644 --- a/shared-bindings/paralleldisplaybus/ParallelBus.c +++ b/shared-bindings/paralleldisplaybus/ParallelBus.c @@ -85,14 +85,16 @@ static mp_obj_t paralleldisplaybus_parallelbus_make_new(const mp_obj_type_t *typ mp_raise_ValueError(MP_ERROR_TEXT("Specify exactly one of data0 or data_pins")); } + uint32_t frequency = (uint32_t)mp_arg_validate_int_min(args[ARG_frequency].u_int, 1, MP_QSTR_frequency); + if (specified_data0) { const mcu_pin_obj_t *data0 = validate_obj_is_free_pin(args[ARG_data0].u_obj, MP_QSTR_data0); - common_hal_paralleldisplaybus_parallelbus_construct(self, data0, command, chip_select, write, read, reset, args[ARG_frequency].u_int); + common_hal_paralleldisplaybus_parallelbus_construct(self, data0, command, chip_select, write, read, reset, frequency); } else { uint8_t num_pins; const mcu_pin_obj_t *data_pins[16]; validate_list_is_free_pins(MP_QSTR_data_pins, data_pins, (mp_int_t)MP_ARRAY_SIZE(data_pins), args[ARG_data_pins].u_obj, &num_pins); - common_hal_paralleldisplaybus_parallelbus_construct_nonsequential(self, num_pins, data_pins, command, chip_select, write, read, reset, args[ARG_frequency].u_int); + common_hal_paralleldisplaybus_parallelbus_construct_nonsequential(self, num_pins, data_pins, command, chip_select, write, read, reset, frequency); } return self; } diff --git a/shared-bindings/paralleldisplaybus/__init__.c b/shared-bindings/paralleldisplaybus/__init__.c index 24d968c9e31..19a381570ba 100644 --- a/shared-bindings/paralleldisplaybus/__init__.c +++ b/shared-bindings/paralleldisplaybus/__init__.c @@ -29,6 +29,3 @@ const mp_obj_module_t paralleldisplaybus_module = { }; MP_REGISTER_MODULE(MP_QSTR_paralleldisplaybus, paralleldisplaybus_module); - -// Remove in CircuitPython 10 -MP_REGISTER_MODULE(MP_QSTR_paralleldisplay, paralleldisplaybus_module); diff --git a/shared-bindings/ps2io/Ps2.c b/shared-bindings/ps2io/Ps2.c index 8766ea7a2a1..90e6b0b6045 100644 --- a/shared-bindings/ps2io/Ps2.c +++ b/shared-bindings/ps2io/Ps2.c @@ -58,7 +58,6 @@ static mp_obj_t ps2io_ps2_make_new(const mp_obj_type_t *type, size_t n_args, siz const mcu_pin_obj_t *data_pin = validate_obj_is_free_pin(args[ARG_data_pin].u_obj, MP_QSTR_data_pin); ps2io_ps2_obj_t *self = mp_obj_malloc(ps2io_ps2_obj_t, &ps2io_ps2_type); - common_hal_ps2io_ps2_construct(self, data_pin, clock_pin); return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/pulseio/PulseIn.c b/shared-bindings/pulseio/PulseIn.c index d9e6bfd7aec..830f7b7c62c 100644 --- a/shared-bindings/pulseio/PulseIn.c +++ b/shared-bindings/pulseio/PulseIn.c @@ -69,7 +69,6 @@ static mp_obj_t pulseio_pulsein_make_new(const mp_obj_type_t *type, size_t n_arg const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); pulseio_pulsein_obj_t *self = mp_obj_malloc_with_finaliser(pulseio_pulsein_obj_t, &pulseio_pulsein_type); - common_hal_pulseio_pulsein_construct(self, pin, args[ARG_maxlen].u_int, args[ARG_idle_state].u_bool); diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c index 947aa4b518e..58c98b8e2cc 100644 --- a/shared-bindings/pulseio/PulseOut.c +++ b/shared-bindings/pulseio/PulseOut.c @@ -62,6 +62,7 @@ static mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_ar pulseio_pulseout_obj_t *self = mp_obj_malloc_with_finaliser(pulseio_pulseout_obj_t, &pulseio_pulseout_type); common_hal_pulseio_pulseout_construct(self, pin, frequency, duty_cycle); + return MP_OBJ_FROM_PTR(self); #else mp_raise_NotImplementedError(NULL); diff --git a/shared-bindings/qrio/QRDecoder.c b/shared-bindings/qrio/QRDecoder.c index 6a36d8b0265..e8977bc1efe 100644 --- a/shared-bindings/qrio/QRDecoder.c +++ b/shared-bindings/qrio/QRDecoder.c @@ -34,7 +34,7 @@ static mp_obj_t qrio_qrdecoder_make_new(const mp_obj_type_t *type, size_t n_args qrio_qrdecoder_obj_t *self = mp_obj_malloc(qrio_qrdecoder_obj_t, &qrio_qrdecoder_type_obj); shared_module_qrio_qrdecoder_construct(self, args[ARG_width].u_int, args[ARG_height].u_int); - return self; + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/qspibus/QSPIBus.c b/shared-bindings/qspibus/QSPIBus.c new file mode 100644 index 00000000000..24c3089213f --- /dev/null +++ b/shared-bindings/qspibus/QSPIBus.c @@ -0,0 +1,199 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/qspibus/QSPIBus.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "shared-module/displayio/__init__.h" + +#include "py/binary.h" +#include "py/obj.h" +#include "py/runtime.h" + +static void check_for_deinit(qspibus_qspibus_obj_t *self) { + if (common_hal_qspibus_qspibus_deinited(self)) { + raise_deinited_error(); + } +} + +//| class QSPIBus: +//| """QSPI bus for quad-SPI displays.""" +//| +//| def __init__( +//| self, +//| *, +//| clock: microcontroller.Pin, +//| data0: microcontroller.Pin, +//| data1: microcontroller.Pin, +//| data2: microcontroller.Pin, +//| data3: microcontroller.Pin, +//| cs: microcontroller.Pin, +//| dcx: Optional[microcontroller.Pin] = None, +//| reset: Optional[microcontroller.Pin] = None, +//| frequency: int = 80_000_000, +//| ) -> None: +//| """Create a QSPIBus object for quad-SPI display communication. +//| +//| :param ~microcontroller.Pin clock: QSPI clock pin +//| :param ~microcontroller.Pin data0: QSPI data line 0 +//| :param ~microcontroller.Pin data1: QSPI data line 1 +//| :param ~microcontroller.Pin data2: QSPI data line 2 +//| :param ~microcontroller.Pin data3: QSPI data line 3 +//| :param ~microcontroller.Pin cs: Chip select pin +//| :param ~microcontroller.Pin dcx: Optional data/command select pin. +//| Reserved for future hardware paths. Current ESP32-S3 implementation +//| uses encoded QSPI command words and does not require explicit DCX. +//| :param ~microcontroller.Pin reset: Optional reset pin +//| :param int frequency: Bus frequency in Hz (1-80MHz) +//| """ +//| ... +//| +static mp_obj_t qspibus_qspibus_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *all_args) { + + enum { ARG_clock, ARG_data0, ARG_data1, ARG_data2, ARG_data3, ARG_cs, ARG_dcx, ARG_reset, ARG_frequency }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data0, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data1, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data2, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data3, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_dcx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_reset, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 80000000} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock); + const mcu_pin_obj_t *data0 = validate_obj_is_free_pin(args[ARG_data0].u_obj, MP_QSTR_data0); + const mcu_pin_obj_t *data1 = validate_obj_is_free_pin(args[ARG_data1].u_obj, MP_QSTR_data1); + const mcu_pin_obj_t *data2 = validate_obj_is_free_pin(args[ARG_data2].u_obj, MP_QSTR_data2); + const mcu_pin_obj_t *data3 = validate_obj_is_free_pin(args[ARG_data3].u_obj, MP_QSTR_data3); + const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); + const mcu_pin_obj_t *dcx = validate_obj_is_free_pin_or_none(args[ARG_dcx].u_obj, MP_QSTR_dcx); + const mcu_pin_obj_t *reset = validate_obj_is_free_pin_or_none(args[ARG_reset].u_obj, MP_QSTR_reset); + + uint32_t frequency = (uint32_t)mp_arg_validate_int_range(args[ARG_frequency].u_int, 1, 80000000, MP_QSTR_frequency); + + qspibus_qspibus_obj_t *self = &allocate_display_bus_or_raise()->qspi_bus; + self->base.type = &qspibus_qspibus_type; + common_hal_qspibus_qspibus_construct(self, clock, data0, data1, data2, data3, cs, dcx, reset, frequency); + + return MP_OBJ_FROM_PTR(self); +} + +//| def reset(self) -> None: +//| """Perform a hardware reset using the reset pin. +//| +//| :raises RuntimeError: if no reset pin was provided at construction. +//| """ +//| ... +//| +static mp_obj_t qspibus_qspibus_obj_reset(mp_obj_t self_in) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (!common_hal_qspibus_qspibus_reset(MP_OBJ_FROM_PTR(self))) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("No %q pin"), MP_QSTR_reset); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(qspibus_qspibus_reset_obj, qspibus_qspibus_obj_reset); + +//| def send( +//| self, command: int, data: ReadableBuffer, *, toggle_every_byte: bool = False +//| ) -> None: +//| """Sends the given command value followed by the full set of data. Display state, such as +//| vertical scroll, set via ``send`` may or may not be reset once the code is done.""" +//| ... +//| +static mp_obj_t qspibus_qspibus_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_command, ARG_data }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_command, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_data, MP_ARG_OBJ | MP_ARG_REQUIRED }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + + uint8_t command = (uint8_t)mp_arg_validate_int_range(args[ARG_command].u_int, 0, 255, MP_QSTR_command); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_data].u_obj, &bufinfo, MP_BUFFER_READ); + + // Flush any pending command from a prior write_command() call. + // begin_transaction() returns false while has_pending_command is set, + // so entering the wait loop without flushing would spin forever. + if (self->has_pending_command) { + common_hal_qspibus_qspibus_write_data(self, NULL, 0); + } + + // Wait for display bus to be available, then acquire transaction. + while (!common_hal_qspibus_qspibus_begin_transaction(MP_OBJ_FROM_PTR(self))) { + RUN_BACKGROUND_TASKS; + } + common_hal_qspibus_qspibus_send(MP_OBJ_FROM_PTR(self), DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, &command, 1); + common_hal_qspibus_qspibus_send(MP_OBJ_FROM_PTR(self), DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, ((uint8_t *)bufinfo.buf), bufinfo.len); + common_hal_qspibus_qspibus_end_transaction(MP_OBJ_FROM_PTR(self)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(qspibus_qspibus_send_obj, 1, qspibus_qspibus_send); + +//| def write_command(self, command: int) -> None: +//| """Stage a command byte for subsequent :py:meth:`write_data`. +//| +//| If a previously staged command had no data, it is sent as +//| a command-only transaction before staging the new one. +//| """ +//| ... +//| +static mp_obj_t qspibus_qspibus_write_command(mp_obj_t self_in, mp_obj_t command_obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + uint8_t command = (uint8_t)mp_arg_validate_int_range(mp_obj_get_int(command_obj), 0, 255, MP_QSTR_command); + common_hal_qspibus_qspibus_write_command(self, command); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(qspibus_qspibus_write_command_obj, qspibus_qspibus_write_command); + +//| def write_data(self, data: ReadableBuffer) -> None: +//| """Send payload bytes for the most recently staged command.""" +//| ... +//| +static mp_obj_t qspibus_qspibus_write_data(mp_obj_t self_in, mp_obj_t data_obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ); + common_hal_qspibus_qspibus_write_data(self, (const uint8_t *)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(qspibus_qspibus_write_data_obj, qspibus_qspibus_write_data); + +static const mp_rom_map_elem_t qspibus_qspibus_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&qspibus_qspibus_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&qspibus_qspibus_send_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_command), MP_ROM_PTR(&qspibus_qspibus_write_command_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_data), MP_ROM_PTR(&qspibus_qspibus_write_data_obj) }, +}; +static MP_DEFINE_CONST_DICT(qspibus_qspibus_locals_dict, qspibus_qspibus_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + qspibus_qspibus_type, + MP_QSTR_QSPIBus, + MP_TYPE_FLAG_NONE, + make_new, qspibus_qspibus_make_new, + locals_dict, &qspibus_qspibus_locals_dict + ); diff --git a/shared-bindings/qspibus/QSPIBus.h b/shared-bindings/qspibus/QSPIBus.h new file mode 100644 index 00000000000..140b639279d --- /dev/null +++ b/shared-bindings/qspibus/QSPIBus.h @@ -0,0 +1,53 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" + +#include "shared-bindings/displayio/__init__.h" + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/qspibus/QSPIBus.h" + +extern const mp_obj_type_t qspibus_qspibus_type; + +void common_hal_qspibus_qspibus_construct( + qspibus_qspibus_obj_t *self, + const mcu_pin_obj_t *clock, + const mcu_pin_obj_t *data0, + const mcu_pin_obj_t *data1, + const mcu_pin_obj_t *data2, + const mcu_pin_obj_t *data3, + const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *dcx, + const mcu_pin_obj_t *reset, + uint32_t frequency); + +void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self); +bool common_hal_qspibus_qspibus_deinited(qspibus_qspibus_obj_t *self); + +void common_hal_qspibus_qspibus_write_command( + qspibus_qspibus_obj_t *self, + uint8_t command); +void common_hal_qspibus_qspibus_write_data( + qspibus_qspibus_obj_t *self, + const uint8_t *data, + size_t len); + +bool common_hal_qspibus_qspibus_reset(mp_obj_t obj); +bool common_hal_qspibus_qspibus_bus_free(mp_obj_t obj); +bool common_hal_qspibus_qspibus_begin_transaction(mp_obj_t obj); +void common_hal_qspibus_qspibus_send( + mp_obj_t obj, + display_byte_type_t data_type, + display_chip_select_behavior_t chip_select, + const uint8_t *data, + uint32_t data_length); +void common_hal_qspibus_qspibus_end_transaction(mp_obj_t obj); +void common_hal_qspibus_qspibus_flush(mp_obj_t obj); +void common_hal_qspibus_qspibus_collect_ptrs(mp_obj_t obj); diff --git a/shared-bindings/qspibus/__init__.c b/shared-bindings/qspibus/__init__.c new file mode 100644 index 00000000000..0281c41c804 --- /dev/null +++ b/shared-bindings/qspibus/__init__.c @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/qspibus/__init__.h" +#include "shared-bindings/qspibus/QSPIBus.h" + +//| """QSPI bus protocol for quad-SPI displays +//| +//| The `qspibus` module provides a low-level QSPI bus interface for displays +//| that use four data lines. It is analogous to `fourwire` for standard SPI. +//| +//| Use :class:`qspibus.QSPIBus` to create a bus instance. +//| +//| Example usage:: +//| +//| import board +//| import qspibus +//| import displayio +//| +//| displayio.release_displays() +//| +//| bus = qspibus.QSPIBus( +//| clock=board.LCD_CLK, +//| data0=board.LCD_D0, +//| data1=board.LCD_D1, +//| data2=board.LCD_D2, +//| data3=board.LCD_D3, +//| cs=board.LCD_CS, +//| reset=board.LCD_RESET, +//| frequency=80_000_000, +//| ) +//| """ + +static const mp_rom_map_elem_t qspibus_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_qspibus) }, + { MP_ROM_QSTR(MP_QSTR_QSPIBus), MP_ROM_PTR(&qspibus_qspibus_type) }, +}; + +static MP_DEFINE_CONST_DICT(qspibus_module_globals, qspibus_module_globals_table); + +const mp_obj_module_t qspibus_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&qspibus_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_qspibus, qspibus_module); diff --git a/shared-bindings/qspibus/__init__.h b/shared-bindings/qspibus/__init__.h new file mode 100644 index 00000000000..9b4ca243327 --- /dev/null +++ b/shared-bindings/qspibus/__init__.h @@ -0,0 +1,8 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/qspibus/QSPIBus.h" diff --git a/shared-bindings/rclcpy/Node.c b/shared-bindings/rclcpy/Node.c index a2fa9bd36a6..4097fbc1515 100644 --- a/shared-bindings/rclcpy/Node.c +++ b/shared-bindings/rclcpy/Node.c @@ -50,7 +50,8 @@ static mp_obj_t rclcpy_node_make_new(const mp_obj_type_t *type, size_t n_args, s rclcpy_node_obj_t *self = mp_obj_malloc_with_finaliser(rclcpy_node_obj_t, &rclcpy_node_type); common_hal_rclcpy_node_construct(self, node_name, namespace); - return (mp_obj_t)self; + + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: @@ -90,7 +91,7 @@ static mp_obj_t rclcpy_node_create_publisher(mp_obj_t self_in, mp_obj_t topic) { rclcpy_publisher_obj_t *publisher = mp_obj_malloc_with_finaliser(rclcpy_publisher_obj_t, &rclcpy_publisher_type); common_hal_rclcpy_publisher_construct(publisher, self, topic_name); - return (mp_obj_t)publisher; + return MP_OBJ_FROM_PTR(publisher); } static MP_DEFINE_CONST_FUN_OBJ_2(rclcpy_node_create_publisher_obj, rclcpy_node_create_publisher); diff --git a/shared-bindings/rclcpy/__init__.c b/shared-bindings/rclcpy/__init__.c index a6631642ea7..e195294cde6 100644 --- a/shared-bindings/rclcpy/__init__.c +++ b/shared-bindings/rclcpy/__init__.c @@ -112,7 +112,8 @@ static mp_obj_t rclcpy_create_node(size_t n_args, const mp_obj_t *pos_args, mp_m rclcpy_node_obj_t *self = mp_obj_malloc_with_finaliser(rclcpy_node_obj_t, &rclcpy_node_type); common_hal_rclcpy_node_construct(self, node_name, namespace); - return (mp_obj_t)self; + + return MP_OBJ_FROM_PTR(self); } static MP_DEFINE_CONST_FUN_OBJ_KW(rclcpy_create_node_obj, 2, rclcpy_create_node); diff --git a/shared-bindings/sdcardio/SDCard.c b/shared-bindings/sdcardio/SDCard.c index 65c5f80b52b..506009f64d6 100644 --- a/shared-bindings/sdcardio/SDCard.c +++ b/shared-bindings/sdcardio/SDCard.c @@ -25,7 +25,10 @@ //| with ``storage.VfsFat`` to allow file I/O to an SD card.""" //| //| def __init__( -//| self, bus: busio.SPI, cs: microcontroller.Pin, baudrate: int = 8000000 +//| self, +//| bus: busio.SPI, +//| cs: Union[microcontroller.Pin, digitalio.DigitalInOutProtocol], +//| baudrate: int = 8000000 //| ) -> None: //| """Construct an SPI SD Card object with the given properties //| @@ -38,10 +41,18 @@ //| the microcontroller) //| //| .. important:: -//| If the same SPI bus is shared with other peripherals, it is important that -//| the SD card be initialized before accessing any other peripheral on the bus. -//| Failure to do so can prevent the SD card from being recognized until it is -//| powered off or re-inserted. +//| When the SPI bus is shared with other peripherals, every CS pin on +//| the bus must be in a known HIGH (deselected) state before any SPI +//| transaction occurs. This is normally guaranteed by a hardware +//| pull-up on each CS line, but on boards where a co-resident +//| peripheral's CS floats (for example the Feather RP2040 RFM, whose +//| ``RFM_CS`` has no pull-up), that CS must be driven HIGH in +//| software before the SD card is initialized. If any CS is allowed +//| to float low, the SPI bus can be corrupted during SD card init +//| and the card may not be recognized until it is powered off or +//| re-inserted. The order in which peripherals are constructed is +//| secondary; what matters is that all CS lines are HIGH (deselected) +//| before any SPI transaction. //| //| Example usage: //| @@ -79,13 +90,11 @@ static mp_obj_t sdcardio_sdcard_make_new(const mp_obj_type_t *type, size_t n_arg mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); busio_spi_obj_t *spi = validate_obj_is_spi_bus(args[ARG_spi].u_obj, MP_QSTR_spi); - const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); sdcardio_sdcard_obj_t *self = mp_obj_malloc_with_finaliser(sdcardio_sdcard_obj_t, &sdcardio_SDCard_type); + common_hal_sdcardio_sdcard_construct(self, spi, args[ARG_cs].u_obj, args[ARG_baudrate].u_int); - common_hal_sdcardio_sdcard_construct(self, spi, cs, args[ARG_baudrate].u_int); - - return self; + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/sdcardio/SDCard.h b/shared-bindings/sdcardio/SDCard.h index d0cb8206c34..4251575f8fd 100644 --- a/shared-bindings/sdcardio/SDCard.h +++ b/shared-bindings/sdcardio/SDCard.h @@ -12,7 +12,7 @@ extern const mp_obj_type_t sdcardio_SDCard_type; -void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *cs, int baudrate); +void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, mp_obj_t cs, int baudrate); void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self); bool common_hal_sdcardio_sdcard_deinited(sdcardio_sdcard_obj_t *self); void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self); diff --git a/shared-bindings/sdioio/SDCard.c b/shared-bindings/sdioio/SDCard.c index 892cecd3fb4..baf1e1660e8 100644 --- a/shared-bindings/sdioio/SDCard.c +++ b/shared-bindings/sdioio/SDCard.c @@ -67,7 +67,6 @@ //| static mp_obj_t sdioio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - sdioio_sdcard_obj_t *self = mp_obj_malloc(sdioio_sdcard_obj_t, &sdioio_SDCard_type); enum { ARG_clock, ARG_command, ARG_data, ARG_frequency, NUM_ARGS }; static const mp_arg_t allowed_args[] = { { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ }, @@ -86,6 +85,7 @@ static mp_obj_t sdioio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, uint8_t num_data; validate_list_is_free_pins(MP_QSTR_data, data_pins, MP_ARRAY_SIZE(data_pins), args[ARG_data].u_obj, &num_data); + sdioio_sdcard_obj_t *self = mp_obj_malloc(sdioio_sdcard_obj_t, &sdioio_SDCard_type); common_hal_sdioio_sdcard_construct(self, clock, command, num_data, data_pins, args[ARG_frequency].u_int); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/socketpool/Socket.c b/shared-bindings/socketpool/Socket.c index 5dac9d150e8..35adb20bbfb 100644 --- a/shared-bindings/socketpool/Socket.c +++ b/shared-bindings/socketpool/Socket.c @@ -446,7 +446,7 @@ static mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, return ret; } -static mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +static mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c index e139e3a077a..1fc9e2c3335 100644 --- a/shared-bindings/socketpool/SocketPool.c +++ b/shared-bindings/socketpool/SocketPool.c @@ -24,21 +24,20 @@ //| a pool of sockets provided by the underlying OS. //| """ //| -//| def __init__(self, radio: wifi.Radio) -> None: +//| def __init__(self, radio: Union[wifi.Radio, hostnetwork.HostNetwork]) -> None: //| """Create a new SocketPool object for the provided radio //| -//| :param wifi.Radio radio: The (connected) network hardware to associate -//| with this SocketPool; currently, this will always be the object -//| returned by :py:attr:`wifi.radio` +//| :param radio: The (connected) network interface to associate with this +//| SocketPool, such as :py:attr:`wifi.radio` or :py:attr:`board.NETWORK`. //| """ //| ... //| static mp_obj_t socketpool_socketpool_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); - socketpool_socketpool_obj_t *s = mp_obj_malloc_with_finaliser(socketpool_socketpool_obj_t, &socketpool_socketpool_type); mp_obj_t radio = args[0]; + socketpool_socketpool_obj_t *s = mp_obj_malloc_with_finaliser(socketpool_socketpool_obj_t, &socketpool_socketpool_type); common_hal_socketpool_socketpool_construct(s, radio); return MP_OBJ_FROM_PTR(s); @@ -190,7 +189,7 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &socketpool_socketpool_locals_dict ); -MP_WEAK NORETURN +MP_WEAK MP_NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void) { vstr_t vstr; mp_print_t print; diff --git a/shared-bindings/socketpool/SocketPool.h b/shared-bindings/socketpool/SocketPool.h index 36035ed00e1..60d58372b91 100644 --- a/shared-bindings/socketpool/SocketPool.h +++ b/shared-bindings/socketpool/SocketPool.h @@ -25,6 +25,6 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self, socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, int proto, socketpool_socket_obj_t *sock); -NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void); +MP_NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void); mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *self, const char *host, int port, int family, int type, int proto, int flags); diff --git a/shared-bindings/spitarget/SPITarget.c b/shared-bindings/spitarget/SPITarget.c index eca92d80027..08f6d554f3a 100644 --- a/shared-bindings/spitarget/SPITarget.c +++ b/shared-bindings/spitarget/SPITarget.c @@ -33,7 +33,6 @@ //| ... //| static mp_obj_t spitarget_spi_target_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - spitarget_spi_target_obj_t *self = mp_obj_malloc(spitarget_spi_target_obj_t, &spitarget_spi_target_type); enum { ARG_sck, ARG_mosi, ARG_miso, ARG_ss }; static const mp_arg_t allowed_args[] = { { MP_QSTR_sck, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -49,7 +48,9 @@ static mp_obj_t spitarget_spi_target_make_new(const mp_obj_type_t *type, size_t const mcu_pin_obj_t *miso = validate_obj_is_free_pin(args[ARG_miso].u_obj, MP_QSTR_miso); const mcu_pin_obj_t *ss = validate_obj_is_free_pin(args[ARG_ss].u_obj, MP_QSTR_ss); + spitarget_spi_target_obj_t *self = mp_obj_malloc(spitarget_spi_target_obj_t, &spitarget_spi_target_type); common_hal_spitarget_spi_target_construct(self, sck, mosi, miso, ss); + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/ssl/SSLContext.c b/shared-bindings/ssl/SSLContext.c index 078a716cdb8..9546c50ed7c 100644 --- a/shared-bindings/ssl/SSLContext.c +++ b/shared-bindings/ssl/SSLContext.c @@ -26,7 +26,6 @@ static mp_obj_t ssl_sslcontext_make_new(const mp_obj_type_t *type, size_t n_args mp_arg_check_num(n_args, n_kw, 0, 1, false); ssl_sslcontext_obj_t *s = mp_obj_malloc(ssl_sslcontext_obj_t, &ssl_sslcontext_type); - common_hal_ssl_sslcontext_construct(s); return MP_OBJ_FROM_PTR(s); diff --git a/shared-bindings/ssl/SSLSocket.c b/shared-bindings/ssl/SSLSocket.c index 4418a8e48d9..98f67878d04 100644 --- a/shared-bindings/ssl/SSLSocket.c +++ b/shared-bindings/ssl/SSLSocket.c @@ -291,7 +291,7 @@ static mp_uint_t sslsocket_write(mp_obj_t self_in, const void *buf, mp_uint_t si return readwrite_common(self_in, common_hal_ssl_sslsocket_send, buf, size, errorcode); } -static mp_uint_t sslsocket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +static mp_uint_t sslsocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { diff --git a/shared-bindings/ssl/__init__.c b/shared-bindings/ssl/__init__.c index 0d10090e9cb..51a3ad3cfc4 100644 --- a/shared-bindings/ssl/__init__.c +++ b/shared-bindings/ssl/__init__.c @@ -27,9 +27,9 @@ static mp_obj_t ssl_create_default_context(void) { ssl_sslcontext_obj_t *s = mp_obj_malloc(ssl_sslcontext_obj_t, &ssl_sslcontext_type); - common_hal_ssl_create_default_context(s); - return s; + + return MP_OBJ_FROM_PTR(s); } MP_DEFINE_CONST_FUN_OBJ_0(ssl_create_default_context_obj, ssl_create_default_context); diff --git a/shared-bindings/storage/__init__.h b/shared-bindings/storage/__init__.h index ed3e8d44e4a..6df60426295 100644 --- a/shared-bindings/storage/__init__.h +++ b/shared-bindings/storage/__init__.h @@ -16,7 +16,7 @@ void common_hal_storage_umount_path(const char *path); void common_hal_storage_umount_object(mp_obj_t vfs_obj); void common_hal_storage_remount(const char *path, bool readonly, bool disable_concurrent_write_protection); mp_obj_t common_hal_storage_getmount(const char *path); -NORETURN void common_hal_storage_erase_filesystem(bool extended); +MP_NORETURN void common_hal_storage_erase_filesystem(bool extended); bool common_hal_storage_disable_usb_drive(void); bool common_hal_storage_enable_usb_drive(void); diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index a0a01f124f7..a331249998a 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -364,13 +364,13 @@ static mp_obj_t supervisor_set_usb_identification(size_t n_args, const mp_obj_t } MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_set_usb_identification_obj, 0, supervisor_set_usb_identification); -//| def get_setting(key: str, default: object=None) -> int | str | bool: +//| def get_setting(key: str, default: object=None) -> int | float | str | bool: //| """ //| Get and parse the value for the given ``key`` from the ``/settings.toml`` file. //| If ``key`` is not found or ``settings.toml`` is not present, return the ``default`` value. //| //| :param str key: The setting key to retrieve -//| :return: The setting value as an ``int``, ``str``, or ``bool`` depending on the value in the file +//| :return: The setting value as an ``int``, ``float``, ``str``, or ``bool`` depending on the value in the file //| //| :raises ValueError: If the value cannot be parsed as a valid TOML value. //| @@ -379,9 +379,10 @@ MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_set_usb_identification_obj, 0, supervisor_ //| - ``str``: Double-quoted string. //| The string may include Unicode characters, and ``\\u`` Unicode escapes. Backslash-escaped characters //| ``\\b``, ``\\r``, ``\\n``, ``\\t``, ``\\v``, ``\\v`` are also allowed. -//| - ``int``: signed or unsigned integer -//| - lower-case boolean words ``true`` and ``false``. +//| - ``int``: signed or unsigned integer. +//| - ``bool``: lower-case ``true`` or ``false``. //| The values are returned as Python ``True`` or ``False`` values. +//| - ``float``: signed or unsigned decimal number with a ``.`` or exponent, or ``inf``, ``inf``, ``nan``. //| //| Example:: //| @@ -389,11 +390,13 @@ MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_set_usb_identification_obj, 0, supervisor_ //| WIDTH = 42 //| color = "red" //| DEBUG = true +//| RATIO = 1.5 //| //| import supervisor //| print(supervisor.get_setting("WIDTH")) # prints 42 //| print(supervisor.get_setting("color")) # prints 'red' //| print(supervisor.get_setting("DEBUG")) # prints True +//| print(supervisor.get_setting("RATIO")) # prints 1.5 //| """ //| ... //| diff --git a/shared-bindings/synthio/LFO.c b/shared-bindings/synthio/LFO.c index ee2d67d3089..2dfae22a577 100644 --- a/shared-bindings/synthio/LFO.c +++ b/shared-bindings/synthio/LFO.c @@ -103,17 +103,17 @@ static mp_obj_t synthio_lfo_make_new(const mp_obj_type_t *type_in, size_t n_args } self->waveform_obj = args[ARG_waveform].u_obj; - mp_obj_t result = MP_OBJ_FROM_PTR(self); - properties_construct_helper(result, lfo_properties + 1, args + 1, MP_ARRAY_SIZE(lfo_properties) - 1); + mp_obj_t self_obj = MP_OBJ_FROM_PTR(self); + properties_construct_helper(self_obj, lfo_properties + 1, args + 1, MP_ARRAY_SIZE(lfo_properties) - 1); // Force computation of the LFO's initial output synthio_global_rate_scale = 0; self->base.last_tick = synthio_global_tick - 1; synthio_block_slot_t slot; - synthio_block_assign_slot(MP_OBJ_FROM_PTR(result), &slot, MP_QSTR_self); + synthio_block_assign_slot(self_obj, &slot, MP_QSTR_self); (void)synthio_block_slot_get(&slot); - return result; + return self_obj; }; //| waveform: Optional[ReadableBuffer] diff --git a/shared-bindings/synthio/Math.c b/shared-bindings/synthio/Math.c index 5e943b44d0f..96857fb3513 100644 --- a/shared-bindings/synthio/Math.c +++ b/shared-bindings/synthio/Math.c @@ -157,10 +157,10 @@ static mp_obj_t synthio_math_make_new_common(mp_arg_val_t args[MP_ARRAY_SIZE(mat self->base.last_tick = synthio_global_tick; - mp_obj_t result = MP_OBJ_FROM_PTR(self); - properties_construct_helper(result, math_properties, args, MP_ARRAY_SIZE(math_properties)); + mp_obj_t self_obj = MP_OBJ_FROM_PTR(self); + properties_construct_helper(self_obj, math_properties, args, MP_ARRAY_SIZE(math_properties)); - return result; + return self_obj; }; //| a: BlockInput diff --git a/shared-bindings/synthio/MidiTrack.c b/shared-bindings/synthio/MidiTrack.c index db75a543c61..0304df12a81 100644 --- a/shared-bindings/synthio/MidiTrack.c +++ b/shared-bindings/synthio/MidiTrack.c @@ -70,7 +70,6 @@ static mp_obj_t synthio_miditrack_make_new(const mp_obj_type_t *type, size_t n_a mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); synthio_miditrack_obj_t *self = mp_obj_malloc(synthio_miditrack_obj_t, &synthio_miditrack_type); - common_hal_synthio_miditrack_construct(self, (uint8_t *)bufinfo.buf, bufinfo.len, args[ARG_tempo].u_int, diff --git a/shared-bindings/synthio/Note.c b/shared-bindings/synthio/Note.c index 95dd51fe6b0..183c59d5fbd 100644 --- a/shared-bindings/synthio/Note.c +++ b/shared-bindings/synthio/Note.c @@ -61,11 +61,11 @@ static mp_obj_t synthio_note_make_new(const mp_obj_type_t *type_in, size_t n_arg mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(note_properties), note_properties, args); synthio_note_obj_t *self = mp_obj_malloc(synthio_note_obj_t, &synthio_note_type); + mp_obj_t self_obj = MP_OBJ_FROM_PTR(self); - mp_obj_t result = MP_OBJ_FROM_PTR(self); - properties_construct_helper(result, note_properties, args, MP_ARRAY_SIZE(note_properties)); + properties_construct_helper(self_obj, note_properties, args, MP_ARRAY_SIZE(note_properties)); - return result; + return self_obj; }; //| frequency: float diff --git a/shared-bindings/synthio/Synthesizer.c b/shared-bindings/synthio/Synthesizer.c index fb39e8ef50e..35cc42a2037 100644 --- a/shared-bindings/synthio/Synthesizer.c +++ b/shared-bindings/synthio/Synthesizer.c @@ -62,7 +62,6 @@ static mp_obj_t synthio_synthesizer_make_new(const mp_obj_type_t *type, size_t n mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); synthio_synthesizer_obj_t *self = mp_obj_malloc(synthio_synthesizer_obj_t, &synthio_synthesizer_type); - common_hal_synthio_synthesizer_construct(self, args[ARG_sample_rate].u_int, args[ARG_channel_count].u_int, diff --git a/shared-bindings/synthio/__init__.c b/shared-bindings/synthio/__init__.c index 6d42880541d..6a21834751b 100644 --- a/shared-bindings/synthio/__init__.c +++ b/shared-bindings/synthio/__init__.c @@ -252,7 +252,6 @@ static mp_obj_t synthio_from_file(size_t n_args, const mp_obj_t *pos_args, mp_ma } synthio_miditrack_obj_t *result = mp_obj_malloc(synthio_miditrack_obj_t, &synthio_miditrack_type); - common_hal_synthio_miditrack_construct(result, buffer, track_size, tempo, args[ARG_sample_rate].u_int, args[ARG_waveform].u_obj, mp_const_none, diff --git a/shared-bindings/terminalio/Terminal.c b/shared-bindings/terminalio/Terminal.c index 199128e56e9..320d4cc667a 100644 --- a/shared-bindings/terminalio/Terminal.c +++ b/shared-bindings/terminalio/Terminal.c @@ -176,8 +176,8 @@ static mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n mp_arg_validate_int_min(scroll_area->width_in_tiles * scroll_area->height_in_tiles, 2, MP_QSTR_scroll_area_area); terminalio_terminal_obj_t *self = mp_obj_malloc(terminalio_terminal_obj_t, &terminalio_terminal_type); - common_hal_terminalio_terminal_construct(self, scroll_area, font, status_bar); + return MP_OBJ_FROM_PTR(self); } @@ -222,7 +222,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(terminalio_terminal_get_cursor_y_obj, terminalio_termi MP_PROPERTY_GETTER(terminalio_terminal_cursor_y_obj, (mp_obj_t)&terminalio_terminal_get_cursor_y_obj); -static mp_uint_t terminalio_terminal_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +static mp_uint_t terminalio_terminal_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { terminalio_terminal_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { diff --git a/shared-bindings/tilepalettemapper/TilePaletteMapper.c b/shared-bindings/tilepalettemapper/TilePaletteMapper.c index ed3e928957f..c22ea47bf26 100644 --- a/shared-bindings/tilepalettemapper/TilePaletteMapper.c +++ b/shared-bindings/tilepalettemapper/TilePaletteMapper.c @@ -45,7 +45,6 @@ static mp_obj_t tilepalettemapper_tilepalettemapper_make_new(const mp_obj_type_t mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_pixel_shader); } - tilepalettemapper_tilepalettemapper_t *self = mp_obj_malloc(tilepalettemapper_tilepalettemapper_t, &tilepalettemapper_tilepalettemapper_type); common_hal_tilepalettemapper_tilepalettemapper_construct(self, pixel_shader, args[ARG_input_color_count].u_int); diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index e19d97251bc..b6d36baeb5f 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -206,7 +206,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); //| def monotonic_ns() -> int: //| """Return the time of the monotonic clock, which cannot go backward, in nanoseconds. //| Not available on boards without long integer support. -//| Only use it to compare against other values from `time.monotonic()` +//| Only use it to compare against other values from `time.monotonic_ns()` //| during a single code run. //| //| :return: the current time diff --git a/shared-bindings/touchio/TouchIn.c b/shared-bindings/touchio/TouchIn.c index 19d97bd9d7c..2250e88f599 100644 --- a/shared-bindings/touchio/TouchIn.c +++ b/shared-bindings/touchio/TouchIn.c @@ -56,7 +56,7 @@ static mp_obj_t touchio_touchin_make_new(const mp_obj_type_t *type, touchio_touchin_obj_t *self = mp_obj_malloc(touchio_touchin_obj_t, &touchio_touchin_type); common_hal_touchio_touchin_construct(self, pin, pull); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: diff --git a/shared-bindings/usb/core/__init__.c b/shared-bindings/usb/core/__init__.c index 545e182ea99..29dab285084 100644 --- a/shared-bindings/usb/core/__init__.c +++ b/shared-bindings/usb/core/__init__.c @@ -30,7 +30,7 @@ //| //| MP_DEFINE_USB_CORE_EXCEPTION(USBError, OSError) -NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...) { +MP_NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...) { mp_obj_t exception; if (fmt == NULL) { exception = mp_obj_new_exception(&mp_type_usb_core_USBError); @@ -50,7 +50,7 @@ NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...) { //| //| MP_DEFINE_USB_CORE_EXCEPTION(USBTimeoutError, usb_core_USBError) -NORETURN void mp_raise_usb_core_USBTimeoutError(void) { +MP_NORETURN void mp_raise_usb_core_USBTimeoutError(void) { mp_raise_type(&mp_type_usb_core_USBTimeoutError); } @@ -90,9 +90,10 @@ static mp_obj_t _next_device(usb_core_devices_obj_t *iter) { // We passed the filters. Now make a properly allocated object to // return to the user. usb_core_device_obj_t *self = mp_obj_malloc(usb_core_device_obj_t, &usb_core_device_type); - common_hal_usb_core_device_construct(self, i); + iter->next_index = i + 1; + return MP_OBJ_FROM_PTR(self); } // Iter is done. diff --git a/shared-bindings/usb/core/__init__.h b/shared-bindings/usb/core/__init__.h index 0dc08fae532..adb8430a6c3 100644 --- a/shared-bindings/usb/core/__init__.h +++ b/shared-bindings/usb/core/__init__.h @@ -25,8 +25,8 @@ void usb_core_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_k extern const mp_obj_type_t mp_type_usb_core_USBError; extern const mp_obj_type_t mp_type_usb_core_USBTimeoutError; -NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_usb_core_USBTimeoutError(void); +MP_NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_usb_core_USBTimeoutError(void); // Find is all Python object oriented so we don't need a separate common-hal API // for it. It uses the device common-hal instead. diff --git a/shared-bindings/usb_audio/USBMicrophone.c b/shared-bindings/usb_audio/USBMicrophone.c new file mode 100644 index 00000000000..ff53d812e49 --- /dev/null +++ b/shared-bindings/usb_audio/USBMicrophone.c @@ -0,0 +1,177 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared/runtime/context_manager_helpers.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/usb_audio/USBMicrophone.h" +#include "shared-bindings/util.h" +#include "shared-module/usb_audio/__init__.h" + +//| class USBMicrophone: +//| """Streams an audio sample to the host computer as a USB Audio Class microphone. +//| +//| A ``USBMicrophone`` is a *consumer* of an audio sample, exactly like +//| `audioio.AudioOut`, `audiobusio.I2SOut` and `audiopwmio.PWMAudioOut`. The +//| samples it pulls are streamed to the host PC over USB rather than to a pin, +//| so the board appears as a microphone. +//| +//| You cannot create an instance of `usb_audio.USBMicrophone`. +//| +//| There is a single shared instance, available as ``usb_audio.usb_microphone`` +//| once ``usb_audio.enable()`` has configured an input (microphone) stream in +//| ``boot.py``. Until then ``usb_audio.usb_microphone`` is ``None``.""" +//| + + + +static mp_obj_t usb_audio_usbmicrophone_deinit(mp_obj_t self_in) { + usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_usb_audio_usbmicrophone_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_deinit_obj, usb_audio_usbmicrophone_deinit); + +static void check_for_deinit(usb_audio_usbmicrophone_obj_t *self) { + if (common_hal_usb_audio_usbmicrophone_deinited(self)) { + raise_deinited_error(); + } +} + +//| def __enter__(self) -> USBMicrophone: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| """Streams the sample to the host once when loop=False and continuously when +//| loop=True. Does not block. Use `playing` to block. +//| +//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer`, +//| `audiomp3.MP3Decoder` or `synthio.Synthesizer`.""" +//| ... +//| +static mp_obj_t usb_audio_usbmicrophone_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + common_hal_usb_audio_usbmicrophone_play(self, args[ARG_sample].u_obj, args[ARG_loop].u_bool); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(usb_audio_usbmicrophone_play_obj, 1, usb_audio_usbmicrophone_obj_play); + +//| def stop(self) -> None: +//| """Stops streaming and resets to the start of the sample.""" +//| ... +//| +static mp_obj_t usb_audio_usbmicrophone_obj_stop(mp_obj_t self_in) { + usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_usb_audio_usbmicrophone_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_stop_obj, usb_audio_usbmicrophone_obj_stop); + +//| playing: bool +//| """True when an audio sample is being streamed even if `paused`. (read-only)""" +//| +static mp_obj_t usb_audio_usbmicrophone_obj_get_playing(mp_obj_t self_in) { + usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_usb_audio_usbmicrophone_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_get_playing_obj, usb_audio_usbmicrophone_obj_get_playing); + +MP_PROPERTY_GETTER(usb_audio_usbmicrophone_playing_obj, + (mp_obj_t)&usb_audio_usbmicrophone_get_playing_obj); + +//| def pause(self) -> None: +//| """Stops streaming temporarily while remembering the position. Use `resume` to resume.""" +//| ... +//| +static mp_obj_t usb_audio_usbmicrophone_obj_pause(mp_obj_t self_in) { + usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + if (!common_hal_usb_audio_usbmicrophone_get_playing(self)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Not playing")); + } + common_hal_usb_audio_usbmicrophone_pause(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_pause_obj, usb_audio_usbmicrophone_obj_pause); + +//| def resume(self) -> None: +//| """Resumes streaming after :py:func:`pause`.""" +//| ... +//| +static mp_obj_t usb_audio_usbmicrophone_obj_resume(mp_obj_t self_in) { + usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + if (common_hal_usb_audio_usbmicrophone_get_paused(self)) { + common_hal_usb_audio_usbmicrophone_resume(self); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_resume_obj, usb_audio_usbmicrophone_obj_resume); + +//| paused: bool +//| """True when streaming is paused. (read-only)""" +//| +//| +static mp_obj_t usb_audio_usbmicrophone_obj_get_paused(mp_obj_t self_in) { + usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_usb_audio_usbmicrophone_get_paused(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_get_paused_obj, usb_audio_usbmicrophone_obj_get_paused); + +MP_PROPERTY_GETTER(usb_audio_usbmicrophone_paused_obj, + (mp_obj_t)&usb_audio_usbmicrophone_get_paused_obj); + +static const mp_rom_map_elem_t usb_audio_usbmicrophone_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&usb_audio_usbmicrophone_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&usb_audio_usbmicrophone_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&usb_audio_usbmicrophone_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&usb_audio_usbmicrophone_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&usb_audio_usbmicrophone_pause_obj) }, + { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&usb_audio_usbmicrophone_resume_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&usb_audio_usbmicrophone_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_paused), MP_ROM_PTR(&usb_audio_usbmicrophone_paused_obj) }, +}; +static MP_DEFINE_CONST_DICT(usb_audio_usbmicrophone_locals_dict, usb_audio_usbmicrophone_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + usb_audio_USBMicrophone_type, + MP_QSTR_USBMicrophone, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + locals_dict, &usb_audio_usbmicrophone_locals_dict + ); diff --git a/shared-bindings/usb_audio/USBMicrophone.h b/shared-bindings/usb_audio/USBMicrophone.h new file mode 100644 index 00000000000..4fe096778bc --- /dev/null +++ b/shared-bindings/usb_audio/USBMicrophone.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/usb_audio/USBMicrophone.h" + +extern const mp_obj_type_t usb_audio_USBMicrophone_type; + +void common_hal_usb_audio_usbmicrophone_construct(usb_audio_usbmicrophone_obj_t *self); +void common_hal_usb_audio_usbmicrophone_deinit(usb_audio_usbmicrophone_obj_t *self); +bool common_hal_usb_audio_usbmicrophone_deinited(usb_audio_usbmicrophone_obj_t *self); +void common_hal_usb_audio_usbmicrophone_play(usb_audio_usbmicrophone_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_usb_audio_usbmicrophone_stop(usb_audio_usbmicrophone_obj_t *self); +bool common_hal_usb_audio_usbmicrophone_get_playing(usb_audio_usbmicrophone_obj_t *self); +void common_hal_usb_audio_usbmicrophone_pause(usb_audio_usbmicrophone_obj_t *self); +void common_hal_usb_audio_usbmicrophone_resume(usb_audio_usbmicrophone_obj_t *self); +bool common_hal_usb_audio_usbmicrophone_get_paused(usb_audio_usbmicrophone_obj_t *self); diff --git a/shared-bindings/usb_audio/USBSpeaker.c b/shared-bindings/usb_audio/USBSpeaker.c new file mode 100644 index 00000000000..d9302886c64 --- /dev/null +++ b/shared-bindings/usb_audio/USBSpeaker.c @@ -0,0 +1,167 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared/runtime/context_manager_helpers.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/usb_audio/USBSpeaker.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-bindings/util.h" +#include "shared-module/usb_audio/__init__.h" + +//| class USBSpeaker: +//| """Plays audio streamed from the host computer as a USB Audio Class speaker. +//| +//| A ``USBSpeaker`` is a *source* of audio samples, exactly like +//| `audiocore.RawSample` or `audiocore.WaveFile`. The host PC streams audio to +//| the board over USB, and the ``USBSpeaker`` hands that audio to a consumer +//| such as `audiobusio.I2SOut`, `audiopwmio.PWMAudioOut` or `audioio.AudioOut` +//| (optionally through the effect modules), so the board appears as a speaker. +//| +//| You cannot create an instance of `usb_audio.USBSpeaker`. +//| +//| There is a single shared instance, available as ``usb_audio.usb_speaker`` +//| once ``usb_audio.enable()`` has configured an output (speaker) stream in +//| ``boot.py``. Until then ``usb_audio.usb_speaker`` is ``None``. +//| +//| .. code-block:: py +//| +//| # boot.py +//| import usb_audio +//| usb_audio.enable(sample_rate=16000, channel_count=1, bits_per_sample=16, +//| microphone=False, speaker=True) +//| +//| .. code-block:: py +//| +//| # code.py +//| import board +//| import usb_audio +//| import audiobusio +//| +//| spk = usb_audio.usb_speaker +//| out = audiobusio.I2SOut(board.I2S_BIT_CLOCK, board.I2S_WORD_SELECT, board.I2S_DATA) +//| out.play(spk, loop=True) +//| while True: +//| pass +//| +//| """ + +static mp_obj_t usb_audio_usbspeaker_deinit(mp_obj_t self_in) { + usb_audio_usbspeaker_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_usb_audio_usbspeaker_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbspeaker_deinit_obj, usb_audio_usbspeaker_deinit); + +static void check_for_deinit(usb_audio_usbspeaker_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + +//| def read(self, destination: circuitpython_typing.WriteableBuffer, destination_length: int) -> int: +//| """Copies up to ``destination_length`` of the most recent samples streamed +//| from the host into ``destination``, for analysis such as an audio-reactive +//| effect or VU meter. This does not block: it returns whatever the host has +//| delivered so far, which may be fewer than ``destination_length`` samples +//| (or zero when the host is not streaming). +//| +//| ``destination`` must be an ``array.array`` of 16-bit signed samples +//| (typecode ``"h"``), matching the negotiated speaker format. +//| +//| Reading consumes the samples, so a ``USBSpeaker`` being read this way +//| should not also be passed to an output backend's ``play()`` at the same +//| time. +//| +//| :return: The number of samples copied into ``destination``.""" +//| ... +//| +static mp_obj_t usb_audio_usbspeaker_obj_read(mp_obj_t self_in, mp_obj_t destination, mp_obj_t destination_length) { + usb_audio_usbspeaker_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + uint32_t length = mp_arg_validate_type_int(destination_length, MP_QSTR_length); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(destination, &bufinfo, MP_BUFFER_WRITE); + // The negotiated speaker format is 16-bit signed PCM, so require a matching + // 'h' array. This keeps the copy a straight memcpy with no conversion. + if (bufinfo.typecode != 'h') { + mp_raise_TypeError(MP_ERROR_TEXT("destination must be an array of type 'h'")); + } + size_t capacity = bufinfo.len / sizeof(int16_t); + if (capacity < length) { + length = capacity; + } + + uint32_t length_read = common_hal_usb_audio_usbspeaker_read(self, bufinfo.buf, length); + return MP_OBJ_NEW_SMALL_INT(length_read); +} +static MP_DEFINE_CONST_FUN_OBJ_3(usb_audio_usbspeaker_read_obj, usb_audio_usbspeaker_obj_read); + +//| def __enter__(self) -> USBSpeaker: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + +//| connected: bool +//| """True while the host is streaming audio to this speaker. (read-only)""" +//| +//| +static mp_obj_t usb_audio_usbspeaker_obj_get_connected(mp_obj_t self_in) { + usb_audio_usbspeaker_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_usb_audio_usbspeaker_get_connected(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbspeaker_get_connected_obj, usb_audio_usbspeaker_obj_get_connected); + +MP_PROPERTY_GETTER(usb_audio_usbspeaker_connected_obj, + (mp_obj_t)&usb_audio_usbspeaker_get_connected_obj); + +//| sample_rate: int +//| """The sample rate negotiated with the host in ``boot.py``. (read-only)""" +//| +//| bits_per_sample: int +//| """The bit depth negotiated with the host in ``boot.py``. (read-only)""" +//| +//| channel_count: int +//| """The number of channels negotiated with the host in ``boot.py``. (read-only)""" +//| +//| +static const mp_rom_map_elem_t usb_audio_usbspeaker_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&usb_audio_usbspeaker_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&usb_audio_usbspeaker_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&usb_audio_usbspeaker_read_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&usb_audio_usbspeaker_connected_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(usb_audio_usbspeaker_locals_dict, usb_audio_usbspeaker_locals_dict_table); + +static const audiosample_p_t usb_audio_usbspeaker_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)usb_audio_usbspeaker_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)usb_audio_usbspeaker_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + usb_audio_USBSpeaker_type, + MP_QSTR_USBSpeaker, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + locals_dict, &usb_audio_usbspeaker_locals_dict, + protocol, &usb_audio_usbspeaker_proto + ); diff --git a/shared-bindings/usb_audio/USBSpeaker.h b/shared-bindings/usb_audio/USBSpeaker.h new file mode 100644 index 00000000000..30d2b0862a3 --- /dev/null +++ b/shared-bindings/usb_audio/USBSpeaker.h @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/usb_audio/USBSpeaker.h" + +extern const mp_obj_type_t usb_audio_USBSpeaker_type; + +void common_hal_usb_audio_usbspeaker_construct(usb_audio_usbspeaker_obj_t *self); +void common_hal_usb_audio_usbspeaker_deinit(usb_audio_usbspeaker_obj_t *self); +bool common_hal_usb_audio_usbspeaker_deinited(usb_audio_usbspeaker_obj_t *self); +bool common_hal_usb_audio_usbspeaker_get_connected(usb_audio_usbspeaker_obj_t *self); +uint32_t common_hal_usb_audio_usbspeaker_read(usb_audio_usbspeaker_obj_t *self, void *buffer, uint32_t length); diff --git a/shared-bindings/usb_audio/__init__.c b/shared-bindings/usb_audio/__init__.c new file mode 100644 index 00000000000..49eaa9716f2 --- /dev/null +++ b/shared-bindings/usb_audio/__init__.c @@ -0,0 +1,160 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/usb_audio/__init__.h" +#include "shared-bindings/usb_audio/USBMicrophone.h" +#include "shared-bindings/usb_audio/USBSpeaker.h" +#include "shared-module/usb_audio/__init__.h" +#include "shared-module/usb_audio/usb_audio_descriptors.h" + +//| """Stream audio to a host computer via USB +//| +//| This makes your CircuitPython device identify to the host computer as a USB +//| Audio Class (UAC2) microphone: the board is the audio *source* and streams +//| samples to the host over a USB isochronous IN endpoint. +//| +//| This mode requires 1 IN endpoint and 2 interfaces. Generally, microcontrollers +//| have a limit on the number of endpoints. If you exceed the number of endpoints, +//| CircuitPython will automatically enter Safe Mode. Even in this case, you may be +//| able to enable USB audio by also disabling other USB functions, such as +//| `usb_hid` or `usb_midi`. +//| +//| To enable this mode, you must configure the audio format in ``boot.py`` and then +//| use the `usb_microphone` singleton instance in ``code.py``. +//| +//| .. code-block:: py +//| +//| # boot.py +//| import usb_audio +//| usb_audio.enable(sample_rate=16000, channel_count=1, bits_per_sample=16) +//| +//| .. code-block:: py +//| +//| # code.py +//| import time +//| import usb_audio +//| import synthio +//| +//| # usb_audio.usb_microphone is a singleton instance (created by enable() above), +//| # not a class you construct. It is a consumer of an audio sample, just like +//| # audioio.AudioOut: the samples it pulls are streamed to the host PC instead +//| # of to a pin. +//| mic = usb_audio.usb_microphone +//| synth = synthio.Synthesizer(sample_rate=16000, channel_count=1) +//| mic.play(synth, loop=True) +//| +//| c_major_scale = [60, 62, 64, 65, 67, 69, 71, 72] +//| try: +//| while True: +//| for note in c_major_scale: +//| synth.press(note) +//| time.sleep(0.1) +//| synth.release(note) +//| time.sleep(0.05) +//| except KeyboardInterrupt: +//| pass +//| mic.stop() +//| +//| The ``sample_rate`` and ``channel_count`` of the sample played must match the +//| values passed to `enable`, and the sample must be 16-bit signed; otherwise +//| ``play`` raises a ``ValueError``. +//| +//| This interface is experimental and may change without notice even in stable +//| versions of CircuitPython.""" +//| +//| + +//| usb_microphone: Optional[USBMicrophone] +//| """The shared `USBMicrophone` singleton instance, or ``None`` until +//| ``usb_audio.enable()`` has configured an input (microphone) stream in ``boot.py``. +//| `USBMicrophone` is exposed only as a type; you do not construct it.""" +//| +//| usb_speaker: Optional[USBSpeaker] +//| """The shared `USBSpeaker` singleton instance, or ``None`` until +//| ``usb_audio.enable()`` has configured an output (speaker) stream in ``boot.py``. +//| `USBSpeaker` is exposed only as a type; you do not construct it.""" +//| + +//| def enable( +//| sample_rate: int = 16000, +//| channel_count: int = 1, +//| bits_per_sample: int = 16, +//| microphone: bool = True, +//| speaker: bool = False, +//| ) -> None: +//| """Enable the USB audio interface with the given PCM format. +//| +//| This function may only be used from ``boot.py``. +//| +//| :param int sample_rate: Samples per second of the streamed audio. +//| :param int channel_count: Number of channels. Only mono (1) is supported initially. +//| :param int bits_per_sample: Bits per signed PCM sample. Only 16 is supported initially. +//| :param bool microphone: Present a microphone (audio flows board -> host). Enabled by default. +//| :param bool speaker: Present a speaker (audio flows host -> board). +//| +//| Enabling both ``microphone`` and ``speaker`` presents a combined headset. At +//| least one of the two must be enabled.""" +//| +//| +static mp_obj_t usb_audio_enable(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample_rate, ARG_channel_count, ARG_bits_per_sample, ARG_microphone, ARG_speaker }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample_rate, MP_ARG_INT, { .u_int = 16000 } }, + { MP_QSTR_channel_count, MP_ARG_INT, { .u_int = 1 } }, + { MP_QSTR_bits_per_sample, MP_ARG_INT, { .u_int = 16 } }, + { MP_QSTR_microphone, MP_ARG_BOOL, { .u_bool = true } }, + { MP_QSTR_speaker, MP_ARG_BOOL, { .u_bool = false } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t sample_rate = mp_arg_validate_int_range(args[ARG_sample_rate].u_int, 1, USB_AUDIO_MAX_SAMPLE_RATE, MP_QSTR_sample_rate); + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, USB_AUDIO_N_CHANNELS, MP_QSTR_channel_count); + mp_int_t bits_per_sample = mp_arg_validate_int(args[ARG_bits_per_sample].u_int, USB_AUDIO_BITS_PER_SAMPLE, MP_QSTR_bits_per_sample); + bool microphone = args[ARG_microphone].u_bool; + bool speaker = args[ARG_speaker].u_bool; + + if (!microphone && !speaker) { + mp_raise_ValueError(MP_ERROR_TEXT("At least one of microphone and speaker must be enabled")); + } + + if (!shared_module_usb_audio_enable(sample_rate, channel_count, bits_per_sample, microphone, speaker)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot change USB devices now")); + } + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_KW(usb_audio_enable_obj, 0, usb_audio_enable); + +mp_map_elem_t usb_audio_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_audio) }, + // USBMicrophone and USBSpeaker are the classes, exposed only for typing and + // isinstance() checks; you do not construct them. The usable objects are the + // pre-made singleton instances installed at the usb_microphone / usb_speaker + // attributes below. + { MP_ROM_QSTR(MP_QSTR_USBMicrophone), MP_OBJ_FROM_PTR(&usb_audio_USBMicrophone_type) }, + { MP_ROM_QSTR(MP_QSTR_USBSpeaker), MP_OBJ_FROM_PTR(&usb_audio_USBSpeaker_type) }, + // usb_microphone and usb_speaker are the singleton instances, like + // usb_midi.ports. usb_audio_setup_singletons() replaces these None + // placeholders with the real instances at the start of each VM when the + // matching direction was enabled in boot.py. + { MP_ROM_QSTR(MP_QSTR_usb_microphone), MP_ROM_NONE }, + { MP_ROM_QSTR(MP_QSTR_usb_speaker), MP_ROM_NONE }, + { MP_ROM_QSTR(MP_QSTR_enable), MP_OBJ_FROM_PTR(&usb_audio_enable_obj) }, +}; + +// This isn't const so the singleton instances can be installed dynamically. +MP_DEFINE_MUTABLE_DICT(usb_audio_module_globals, usb_audio_module_globals_table); + +const mp_obj_module_t usb_audio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&usb_audio_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_usb_audio, usb_audio_module); diff --git a/shared-bindings/usb_audio/__init__.h b/shared-bindings/usb_audio/__init__.h new file mode 100644 index 00000000000..f9ad0eeeb78 --- /dev/null +++ b/shared-bindings/usb_audio/__init__.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +#include "shared-module/usb_audio/__init__.h" + +// The module globals dict is mutable so the USBMicrophone and USBSpeaker +// singleton instances can be installed at runtime (see usb_audio_setup_singletons). +extern mp_obj_dict_t usb_audio_module_globals; diff --git a/shared-bindings/usb_cdc/Serial.c b/shared-bindings/usb_cdc/Serial.c index eb526615927..9bbc2b78f35 100644 --- a/shared-bindings/usb_cdc/Serial.c +++ b/shared-bindings/usb_cdc/Serial.c @@ -100,7 +100,7 @@ static mp_uint_t usb_cdc_serial_write_stream(mp_obj_t self_in, const void *buf_i return common_hal_usb_cdc_serial_write(self, buf, size, errcode); } -static mp_uint_t usb_cdc_serial_ioctl_stream(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +static mp_uint_t usb_cdc_serial_ioctl_stream(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret = 0; switch (request) { diff --git a/shared-bindings/usb_hid/Device.c b/shared-bindings/usb_hid/Device.c index a4a0e8680e5..66c9c01ad6e 100644 --- a/shared-bindings/usb_hid/Device.c +++ b/shared-bindings/usb_hid/Device.c @@ -75,7 +75,6 @@ //| static mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - usb_hid_device_obj_t *self = mp_obj_malloc(usb_hid_device_obj_t, &usb_hid_device_type); enum { ARG_report_descriptor, ARG_usage_page, ARG_usage, ARG_report_ids, ARG_in_report_lengths, ARG_out_report_lengths }; static const mp_arg_t allowed_args[] = { { MP_QSTR_report_descriptor, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -141,9 +140,10 @@ static mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args mp_raise_ValueError_varg(MP_ERROR_TEXT("%q length must be %d"), MP_QSTR_report_id_space_0, 1); } + usb_hid_device_obj_t *self = mp_obj_malloc(usb_hid_device_obj_t, &usb_hid_device_type); common_hal_usb_hid_device_construct( self, descriptor, usage_page, usage, report_ids_count, report_ids_array, in_report_lengths_array, out_report_lengths_array); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/usb_host/Port.c b/shared-bindings/usb_host/Port.c index 41e8513a1e8..2c61e641a05 100644 --- a/shared-bindings/usb_host/Port.c +++ b/shared-bindings/usb_host/Port.c @@ -42,7 +42,7 @@ static mp_obj_t usb_host_port_make_new(const mp_obj_type_t *type, usb_host_port_obj_t *self = common_hal_usb_host_port_construct(dp, dm); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } static const mp_rom_map_elem_t usb_host_port_locals_dict_table[] = { diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c index d62d0b53af1..3f4b19fdec2 100644 --- a/shared-bindings/usb_midi/PortIn.c +++ b/shared-bindings/usb_midi/PortIn.c @@ -60,7 +60,7 @@ static mp_uint_t usb_midi_portin_read(mp_obj_t self_in, void *buf_in, mp_uint_t return common_hal_usb_midi_portin_read(self, buf, size, errcode); } -static mp_uint_t usb_midi_portin_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +static mp_uint_t usb_midi_portin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { usb_midi_portin_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c index 89c83810188..35856ff25fa 100644 --- a/shared-bindings/usb_midi/PortOut.c +++ b/shared-bindings/usb_midi/PortOut.c @@ -42,7 +42,7 @@ static mp_uint_t usb_midi_portout_write(mp_obj_t self_in, const void *buf_in, mp return common_hal_usb_midi_portout_write(self, buf, size, errcode); } -static mp_uint_t usb_midi_portout_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +static mp_uint_t usb_midi_portout_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { usb_midi_portout_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { diff --git a/shared-bindings/util.h b/shared-bindings/util.h index d53e5c6e8da..11f0a00db71 100644 --- a/shared-bindings/util.h +++ b/shared-bindings/util.h @@ -9,7 +9,7 @@ #include "py/mpprint.h" #include "py/runtime.h" -NORETURN void raise_deinited_error(void); +MP_NORETURN void raise_deinited_error(void); void properties_print_helper(const mp_print_t *print, mp_obj_t self_in, const mp_arg_t *properties, size_t n_properties); void properties_construct_helper(mp_obj_t self_in, const mp_arg_t *args, const mp_arg_val_t *vals, size_t n_properties); bool path_exists(const char *path); diff --git a/shared-bindings/vectorio/VectorShape.c b/shared-bindings/vectorio/VectorShape.c index ff29609fc4e..834f1fbff50 100644 --- a/shared-bindings/vectorio/VectorShape.c +++ b/shared-bindings/vectorio/VectorShape.c @@ -69,7 +69,7 @@ mp_obj_t vectorio_vector_shape_make_new(const mp_obj_t shape, const mp_obj_t pix } else if (mp_obj_is_type(shape, &vectorio_circle_type)) { common_hal_vectorio_circle_set_on_dirty(self->ishape.shape, on_dirty); } else { - mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_shape); + // Already excluded due to previous else-if chain. } return MP_OBJ_FROM_PTR(self); diff --git a/shared-module/audiocore/__init__.c b/shared-module/audiocore/__init__.c index 2ee683d75e1..3a80d6b6f42 100644 --- a/shared-module/audiocore/__init__.c +++ b/shared-module/audiocore/__init__.c @@ -13,6 +13,10 @@ #include "shared-module/audiocore/RawSample.h" #include "shared-module/audiocore/WaveFile.h" +#if CIRCUITPY_AUDIOSPEED +#include "shared-bindings/audiospeed/Resampler.h" +#endif + #include "shared-bindings/audiomixer/Mixer.h" #include "shared-module/audiomixer/Mixer.h" @@ -198,7 +202,11 @@ void audiosample_convert_s16s_u8s(uint8_t *buffer_out, const int16_t *buffer_in, void audiosample_must_match(audiosample_base_t *self, mp_obj_t other_in, bool allow_mono_to_stereo) { const audiosample_base_t *other = audiosample_check(other_in); + #if !CIRCUITPY_AUDIOSPEED if (other->sample_rate != self->sample_rate) { + #else + if (other->sample_rate != self->sample_rate && !mp_obj_is_type(other_in, &audiospeed_resampler_type)) { + #endif mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_sample_rate); } if ((!allow_mono_to_stereo || (allow_mono_to_stereo && self->channel_count != 2)) && other->channel_count != self->channel_count) { @@ -210,4 +218,11 @@ void audiosample_must_match(audiosample_base_t *self, mp_obj_t other_in, bool al if (other->samples_signed != self->samples_signed) { mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness); } + + #if CIRCUITPY_AUDIOSPEED + if (mp_obj_is_type(other_in, &audiospeed_resampler_type)) { + audiospeed_resampler_obj_t *other_resampler = MP_OBJ_TO_PTR(other_in); + audiospeed_resampler_set_sample_rate(other_resampler, self->sample_rate); + } + #endif } diff --git a/shared-module/audiofilters/Filter.c b/shared-module/audiofilters/Filter.c index 4cedc810aba..f9c899e2995 100644 --- a/shared-module/audiofilters/Filter.c +++ b/shared-module/audiofilters/Filter.c @@ -40,8 +40,8 @@ void common_hal_audiofilters_filter_construct(audiofilters_filter_obj_t *self, self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 // This buffer will be used to process samples through the biquad filter - self->filter_buffer = m_malloc_without_collect(SYNTHIO_MAX_DUR * sizeof(int32_t)); - memset(self->filter_buffer, 0, SYNTHIO_MAX_DUR * sizeof(int32_t)); + self->filter_buffer = m_malloc_without_collect(SYNTHIO_MAX_DUR * self->base.channel_count * sizeof(int32_t)); + memset(self->filter_buffer, 0, SYNTHIO_MAX_DUR * self->base.channel_count * sizeof(int32_t)); // Initialize other values most effects will need. self->sample = NULL; // The current playing sample @@ -106,9 +106,9 @@ void common_hal_audiofilters_filter_set_filter(audiofilters_filter_obj_t *self, self->filter_objs = filter_objs; self->filter_states = m_renew(biquad_filter_state, self->filter_states, - self->filter_states_len, - n_items); - self->filter_states_len = n_items; + self->filter_objs_len * self->base.channel_count, + n_items * self->base.channel_count); + self->filter_objs_len = n_items; } mp_obj_t common_hal_audiofilters_filter_get_filter(audiofilters_filter_obj_t *self) { @@ -129,10 +129,10 @@ void audiofilters_filter_reset_buffer(audiofilters_filter_obj_t *self, memset(self->buffer[0], 0, self->buffer_len); memset(self->buffer[1], 0, self->buffer_len); - memset(self->filter_buffer, 0, SYNTHIO_MAX_DUR * sizeof(int32_t)); + memset(self->filter_buffer, 0, SYNTHIO_MAX_DUR * self->base.channel_count * sizeof(int32_t)); if (self->filter_states) { - for (uint8_t i = 0; i < self->filter_states_len; i++) { + for (uint8_t i = 0; i < self->filter_objs_len * self->base.channel_count; i++) { synthio_biquad_filter_reset(&self->filter_states[i]); } } @@ -207,7 +207,7 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o (void)synthio_block_slot_get(&self->mix); // Tick biquad filters - for (uint8_t j = 0; j < self->filter_states_len; j++) { + for (uint8_t j = 0; j < self->filter_objs_len; j++) { common_hal_synthio_biquad_tick(self->filter_objs[j]); } if (self->base.samples_signed) { @@ -248,46 +248,52 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o } else { uint32_t i = 0; while (i < n) { - uint32_t n_samples = MIN(SYNTHIO_MAX_DUR, n - i); + uint32_t n_samples = MIN(SYNTHIO_MAX_DUR, (n - i) >> (self->base.channel_count - 1)); // Fill filter buffer with samples - for (uint32_t j = 0; j < n_samples; j++) { + for (uint32_t j = 0; j < n_samples * self->base.channel_count; j++) { + bool buf_offset = (j % self->base.channel_count) == 1; + uint32_t k = j / self->base.channel_count; if (MP_LIKELY(self->base.bits_per_sample == 16)) { - self->filter_buffer[j] = sample_src[i + j]; + self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] = sample_src[i + j]; } else { if (self->base.samples_signed) { - self->filter_buffer[j] = sample_hsrc[i + j]; + self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] = sample_hsrc[i + j]; } else { // Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed - self->filter_buffer[j] = (int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80); + self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] = (int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80); } } } // Process biquad filters - for (uint8_t j = 0; j < self->filter_states_len; j++) { + for (uint8_t j = 0; j < self->filter_objs_len; j++) { mp_obj_t filter_obj = self->filter_objs[j]; common_hal_synthio_biquad_tick(filter_obj); - synthio_biquad_filter_samples(filter_obj, &self->filter_states[j], self->filter_buffer, n_samples); + for (uint8_t k = 0; k < self->base.channel_count; k++) { + synthio_biquad_filter_samples(filter_obj, &self->filter_states[j * self->base.channel_count + k], self->filter_buffer + k * SYNTHIO_MAX_DUR, n_samples); + } } // Mix processed signal with original sample and transfer to output buffer - for (uint32_t j = 0; j < n_samples; j++) { + for (uint32_t j = 0; j < n_samples * self->base.channel_count; j++) { + bool buf_offset = (j % self->base.channel_count) == 1; + uint32_t k = j / self->base.channel_count; if (MP_LIKELY(self->base.bits_per_sample == 16)) { - word_buffer[i + j] = synthio_mix_down_sample((int32_t)((sample_src[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)), SYNTHIO_MIX_DOWN_SCALE(2)); + word_buffer[i + j] = synthio_mix_down_sample((int32_t)((sample_src[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] * mix)), SYNTHIO_MIX_DOWN_SCALE(2)); if (!self->base.samples_signed) { word_buffer[i + j] ^= 0x8000; } } else { if (self->base.samples_signed) { - hword_buffer[i + j] = (int8_t)((sample_hsrc[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)); + hword_buffer[i + j] = (int8_t)((sample_hsrc[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] * mix)); } else { - hword_buffer[i + j] = (uint8_t)(((int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80) * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)) ^ 0x80; + hword_buffer[i + j] = (uint8_t)(((int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80) * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] * mix)) ^ 0x80; } } } - i += n_samples; + i += n_samples * self->base.channel_count; } } diff --git a/shared-module/audiofilters/Filter.h b/shared-module/audiofilters/Filter.h index 4447f8a2988..e24827e44a8 100644 --- a/shared-module/audiofilters/Filter.h +++ b/shared-module/audiofilters/Filter.h @@ -21,7 +21,7 @@ typedef struct { synthio_block_slot_t mix; mp_obj_t *filter_objs; - size_t filter_states_len; + size_t filter_objs_len; biquad_filter_state *filter_states; int8_t *buffer[2]; diff --git a/shared-module/audioi2sin/__init__.h b/shared-module/audioi2sin/__init__.h new file mode 100644 index 00000000000..852616ee3a7 --- /dev/null +++ b/shared-module/audioi2sin/__init__.h @@ -0,0 +1,71 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +// Rescale an already-normalized signed sample and write it to `buffer` at sample +// index `idx`. `s` is the sign-extended int32 value of the sample at `in_depth` +// scale (the per-port `i2sin_normalize_signed` produces it from the raw FIFO +// word, handling wire-format details like left-justification). This helper does +// the depth conversion + unsigned-WAV flip + container store, which is identical +// across ports. +// +// This path runs only when the caller set `output_bit_depth`, i.e. asked for a +// real bit-depth rescale: upscaling bit-replicates so full-scale input maps to +// full-scale output (e.g. 16-bit 0xFFFF -> 24-bit 0xFFFFFF) and downscaling +// arithmetic-shifts right. This is distinct from the implicit container width +// set by the array typecode (e.g. a 24-bit sample carried in a 32-bit 'i' slot), +// which only sign-extends and is handled by the default (non-converting) path. +// Output element size follows `out_depth`: 1 byte at 8, 2 bytes at 16, 4 bytes +// at 24 or 32. +static inline void shared_audioi2sin_write_converted(void *buffer, uint32_t idx, + int32_t s, uint8_t in_depth, uint8_t out_depth, bool samples_signed) { + int32_t shifted; + if (out_depth > in_depth) { + // Explicit upscale: left-justify the in_depth-bit sample at the top of a + // 32-bit word and replicate the pattern downward so full-scale input + // maps to full-scale output (e.g. 16-bit 0xFFFF -> 24-bit 0xFFFFFF). Two + // steps cover every supported ratio (widest is 8 -> 32); the guard skips + // the second step (and the resulting shift-by->=32 UB) when one suffices. + uint32_t top = (uint32_t)s << (32 - in_depth); + top |= top >> in_depth; + if (in_depth * 2 < out_depth) { + top |= top >> (in_depth * 2); + } + // Arithmetic-shift the high out_depth bits down, sign-extending to int32 + // so a 24-bit value in a 32-bit slot decodes correctly (no-op at 32). + shifted = (int32_t)top >> (32 - out_depth); + } else if (out_depth == in_depth) { + shifted = s; + } else { + shifted = s >> (in_depth - out_depth); + } + uint32_t u = (uint32_t)shifted; + if (!samples_signed) { + // I2S delivers signed PCM; flip the sign bit to match the WAV unsigned + // convention, at the output bit width. + if (out_depth >= 32) { + u ^= 0x80000000u; + } else { + uint32_t mask = (1u << out_depth) - 1u; + u = (u & mask) ^ (1u << (out_depth - 1)); + } + } + switch (out_depth) { + case 8: + ((uint8_t *)buffer)[idx] = (uint8_t)(u & 0xffu); + break; + case 16: + ((uint16_t *)buffer)[idx] = (uint16_t)(u & 0xffffu); + break; + default: // 24 or 32 + ((uint32_t *)buffer)[idx] = u; + break; + } +} diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index b27eafb71a9..b6cb3318e54 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -92,23 +92,23 @@ static inline uint32_t add16signed(uint32_t a, uint32_t b) { } __attribute__((always_inline)) -static inline uint32_t mult16signed(uint32_t val, int32_t mul[2]) { +static inline uint32_t mult16signed(uint32_t val, int32_t lomul, int32_t himul) { #if (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) - mul[0] <<= 16; - mul[1] <<= 16; + lomul <<= 16; + himul <<= 16; int32_t hi, lo; enum { bits = 16 }; // saturate to 16 bits enum { shift = 15 }; // shift is done automatically - asm volatile ("smulwb %0, %1, %2" : "=r" (lo) : "r" (mul[0]), "r" (val)); - asm volatile ("smulwt %0, %1, %2" : "=r" (hi) : "r" (mul[1]), "r" (val)); - asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (lo) : "I" (bits), "r" (lo), "I" (shift)); - asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (hi) : "I" (bits), "r" (hi), "I" (shift)); - asm volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack + __asm__ volatile ("smulwb %0, %1, %2" : "=r" (lo) : "r" (lomul), "r" (val)); + __asm__ volatile ("smulwt %0, %1, %2" : "=r" (hi) : "r" (himul), "r" (val)); + __asm__ volatile ("ssat %0, %1, %2, asr %3" : "=r" (lo) : "I" (bits), "r" (lo), "I" (shift)); + __asm__ volatile ("ssat %0, %1, %2, asr %3" : "=r" (hi) : "I" (bits), "r" (hi), "I" (shift)); + __asm__ volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack return val; #else uint32_t result = 0; for (int8_t i = 0; i < 2; i++) { - float mod_mul = (float)mul[i] / (float)((1 << 15) - 1); + float mod_mul = (float)(i ? himul : lomul) / (float)((1 << 15) - 1); int16_t ai = (val >> (sizeof(uint16_t) * 8 * i)); int32_t intermediate = (int32_t)(ai * mod_mul); if (intermediate > SHRT_MAX) { @@ -156,23 +156,21 @@ static inline uint32_t pack8(uint32_t val) { } static inline uint32_t copy16lsb(uint32_t val) { + #if (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) + return __PKHBT(val, val, 16); + #else val &= 0x0000ffff; return val | (val << 16); + #endif } static inline uint32_t copy16msb(uint32_t val) { + #if (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) + return __PKHTB(val, val, 16); + #else val &= 0xffff0000; return val | (val >> 16); -} - -static inline uint32_t copy8lsb(uint32_t val) { - val &= 0x00ff; - return val | (val << 8); -} - -static inline uint32_t copy8msb(uint32_t val) { - val &= 0xff00; - return val | (val >> 8); + #endif } #define ALMOST_ONE (MICROPY_FLOAT_CONST(32767.) / 32768) @@ -228,16 +226,17 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, uint16_t left_panning_scaled = 32768, right_panning_scaled = 32768; if (MP_LIKELY(self->base.channel_count == 2)) { if (panning >= 0) { - right_panning_scaled = 32767 - panning; + left_panning_scaled = 32767 - panning; } else { - left_panning_scaled = 32767 + panning; + right_panning_scaled = 32767 + panning; } } - int32_t loudness[2] = { level, level }; + int32_t lo_level = level; + int32_t hi_level = level; if (MP_LIKELY(self->base.channel_count == 2)) { - loudness[0] = (left_panning_scaled * loudness[0]) >> 15; - loudness[1] = (right_panning_scaled * loudness[1]) >> 15; + lo_level = (left_panning_scaled * lo_level) >> 15; + hi_level = (right_panning_scaled * hi_level) >> 15; } // First active voice gets copied over verbatim. @@ -247,13 +246,13 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { for (uint32_t i = 0; i < n; i++) { uint32_t v = src[i]; - word_buffer[i] = mult16signed(v, loudness); + word_buffer[i] = mult16signed(v, lo_level, hi_level); } } else { for (uint32_t i = 0; i < n; i += 2) { uint32_t v = src[i >> 1]; - word_buffer[i] = mult16signed(copy16lsb(v), loudness); - word_buffer[i + 1] = mult16signed(copy16msb(v), loudness); + word_buffer[i] = mult16signed(copy16lsb(v), lo_level, hi_level); + word_buffer[i + 1] = mult16signed(copy16msb(v), lo_level, hi_level); } } } else { @@ -261,14 +260,14 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, for (uint32_t i = 0; i < n; i++) { uint32_t v = src[i]; v = tosigned16(v); - word_buffer[i] = mult16signed(v, loudness); + word_buffer[i] = mult16signed(v, lo_level, hi_level); } } else { for (uint32_t i = 0; i + 1 < n; i += 2) { uint32_t v = src[i >> 1]; v = tosigned16(v); - word_buffer[i] = mult16signed(copy16lsb(v), loudness); - word_buffer[i + 1] = mult16signed(copy16msb(v), loudness); + word_buffer[i] = mult16signed(copy16lsb(v), lo_level, hi_level); + word_buffer[i + 1] = mult16signed(copy16msb(v), lo_level, hi_level); } } } @@ -281,7 +280,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, if (MP_LIKELY(!self->base.samples_signed)) { word = tosigned16(word); } - word = mult16signed(word, loudness); + word = mult16signed(word, lo_level, hi_level); hword_buffer[i] = pack8(word); } } else { @@ -290,8 +289,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, if (MP_LIKELY(!self->base.samples_signed)) { word = tosigned16(word); } - hword_buffer[i] = pack8(mult16signed(copy16lsb(word), loudness)); - hword_buffer[i + 1] = pack8(mult16signed(copy16msb(word), loudness)); + hword_buffer[i] = pack8(mult16signed(copy16lsb(word), lo_level, hi_level)); + hword_buffer[i + 1] = pack8(mult16signed(copy16msb(word), lo_level, hi_level)); } } } @@ -301,13 +300,13 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { for (uint32_t i = 0; i < n; i++) { uint32_t word = src[i]; - word_buffer[i] = add16signed(mult16signed(word, loudness), word_buffer[i]); + word_buffer[i] = add16signed(mult16signed(word, lo_level, hi_level), word_buffer[i]); } } else { for (uint32_t i = 0; i + 1 < n; i += 2) { uint32_t word = src[i >> 1]; - word_buffer[i] = add16signed(mult16signed(copy16lsb(word), loudness), word_buffer[i]); - word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), loudness), word_buffer[i + 1]); + word_buffer[i] = add16signed(mult16signed(copy16lsb(word), lo_level, hi_level), word_buffer[i]); + word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), lo_level, hi_level), word_buffer[i + 1]); } } } else { @@ -315,14 +314,14 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, for (uint32_t i = 0; i < n; i++) { uint32_t word = src[i]; word = tosigned16(word); - word_buffer[i] = add16signed(mult16signed(word, loudness), word_buffer[i]); + word_buffer[i] = add16signed(mult16signed(word, lo_level, hi_level), word_buffer[i]); } } else { for (uint32_t i = 0; i + 1 < n; i += 2) { uint32_t word = src[i >> 1]; word = tosigned16(word); - word_buffer[i] = add16signed(mult16signed(copy16lsb(word), loudness), word_buffer[i]); - word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), loudness), word_buffer[i + 1]); + word_buffer[i] = add16signed(mult16signed(copy16lsb(word), lo_level, hi_level), word_buffer[i]); + word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), lo_level, hi_level), word_buffer[i + 1]); } } } @@ -335,7 +334,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, if (MP_LIKELY(!self->base.samples_signed)) { word = tosigned16(word); } - word = mult16signed(word, loudness); + word = mult16signed(word, lo_level, hi_level); word = add16signed(word, unpack8(hword_buffer[i])); hword_buffer[i] = pack8(word); } @@ -345,8 +344,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, if (MP_LIKELY(!self->base.samples_signed)) { word = tosigned16(word); } - hword_buffer[i] = pack8(add16signed(mult16signed(copy16lsb(word), loudness), unpack8(hword_buffer[i]))); - hword_buffer[i + 1] = pack8(add16signed(mult16signed(copy16msb(word), loudness), unpack8(hword_buffer[i + 1]))); + hword_buffer[i] = pack8(add16signed(mult16signed(copy16lsb(word), lo_level, hi_level), unpack8(hword_buffer[i]))); + hword_buffer[i + 1] = pack8(add16signed(mult16signed(copy16msb(word), lo_level, hi_level), unpack8(hword_buffer[i + 1]))); } } } diff --git a/shared-module/audiomixer/MixerVoice.c b/shared-module/audiomixer/MixerVoice.c index 6c23a39215c..3a598516e7c 100644 --- a/shared-module/audiomixer/MixerVoice.c +++ b/shared-module/audiomixer/MixerVoice.c @@ -51,7 +51,7 @@ void common_hal_audiomixer_mixervoice_set_panning(audiomixer_mixervoice_obj_t *s #if CIRCUITPY_SYNTHIO synthio_block_assign_slot(arg, &self->panning, MP_QSTR_panning); #else - self->panning = (uint16_t)(mp_arg_validate_obj_float_range(arg, -1, 1, MP_QSTR_panning) * ((1 << 15) - 1)); + self->panning = (int16_t)(mp_arg_validate_obj_float_range(arg, -1, 1, MP_QSTR_panning) * ((1 << 15) - 1)); #endif } diff --git a/shared-module/audiospeed/Resampler.c b/shared-module/audiospeed/Resampler.c new file mode 100644 index 00000000000..cd1ac681246 --- /dev/null +++ b/shared-module/audiospeed/Resampler.c @@ -0,0 +1,44 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/audiospeed/Resampler.h" + +static void calculate_rate(audiospeed_base_t *self, uint32_t sample_rate) { + if (self->source != NULL && sample_rate) { + self->speed.rate_fp = (uint32_t)((mp_float_t)self->base.sample_rate / sample_rate * (1 << SPEED_SHIFT)); + } else { + audiospeed_set_rate(&self->speed, mp_const_none); + } +} + +void common_hal_audiospeed_resampler_construct(audiospeed_resampler_obj_t *self, mp_obj_t source) { + audiospeed_construct(&self->base, source, mp_const_none); // default rate 1.0 + self->sample_rate = 0; +} + +void common_hal_audiospeed_resampler_deinit(audiospeed_resampler_obj_t *self) { + audiospeed_deinit(&self->base); +} + +mp_obj_t common_hal_audiospeed_resampler_get_rate(audiospeed_resampler_obj_t *self) { + return audiospeed_get_rate(&self->base.speed); +} + +void audiospeed_resampler_set_sample_rate(audiospeed_resampler_obj_t *self, uint32_t sample_rate) { + self->sample_rate = sample_rate; + calculate_rate(&self->base, self->sample_rate); +} + +void audiospeed_resampler_reset_buffer(audiospeed_resampler_obj_t *self, + bool single_channel_output, uint8_t channel) { + audiospeed_reset_buffer(&self->base, single_channel_output, channel); +} + +audioio_get_buffer_result_t audiospeed_resampler_get_buffer(audiospeed_resampler_obj_t *self, + bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + return audiospeed_get_buffer(&self->base, single_channel_output, channel, buffer, buffer_length); +} diff --git a/shared-module/audiospeed/Resampler.h b/shared-module/audiospeed/Resampler.h new file mode 100644 index 00000000000..a105c5c2ab9 --- /dev/null +++ b/shared-module/audiospeed/Resampler.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-module/audiocore/__init__.h" +#include "shared-module/audiospeed/__init__.h" + +typedef struct { + audiospeed_base_t base; + uint32_t sample_rate; +} audiospeed_resampler_obj_t; + +void audiospeed_resampler_reset_buffer(audiospeed_resampler_obj_t *self, + bool single_channel_output, uint8_t channel); +audioio_get_buffer_result_t audiospeed_resampler_get_buffer(audiospeed_resampler_obj_t *self, + bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length); diff --git a/shared-module/audiospeed/SpeedChanger.c b/shared-module/audiospeed/SpeedChanger.c new file mode 100644 index 00000000000..1bf21dfab7a --- /dev/null +++ b/shared-module/audiospeed/SpeedChanger.c @@ -0,0 +1,42 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/audiospeed/SpeedChanger.h" + +#include +#include "py/runtime.h" +#include "py/gc.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-bindings/audiocore/__init__.h" + +void common_hal_audiospeed_speedchanger_construct(audiospeed_speedchanger_obj_t *self, + mp_obj_t source, mp_obj_t rate_obj) { + audiospeed_construct(self, source, rate_obj); +} + +void common_hal_audiospeed_speedchanger_deinit(audiospeed_speedchanger_obj_t *self) { + audiospeed_deinit(self); +} + +void common_hal_audiospeed_speedchanger_set_rate(audiospeed_speedchanger_obj_t *self, mp_obj_t rate_obj) { + audiospeed_set_rate(&self->speed, rate_obj); +} + +mp_obj_t common_hal_audiospeed_speedchanger_get_rate(audiospeed_speedchanger_obj_t *self) { + return audiospeed_get_rate(&self->speed); +} + +void audiospeed_speedchanger_reset_buffer(audiospeed_speedchanger_obj_t *self, + bool single_channel_output, uint8_t channel) { + audiospeed_reset_buffer(self, single_channel_output, channel); +} + +audioio_get_buffer_result_t audiospeed_speedchanger_get_buffer(audiospeed_speedchanger_obj_t *self, + bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + return audiospeed_get_buffer(self, single_channel_output, channel, buffer, buffer_length); +} diff --git a/shared-module/audiospeed/SpeedChanger.h b/shared-module/audiospeed/SpeedChanger.h new file mode 100644 index 00000000000..34969e42bd6 --- /dev/null +++ b/shared-module/audiospeed/SpeedChanger.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-module/audiocore/__init__.h" +#include "shared-module/audiospeed/__init__.h" + +typedef audiospeed_base_t audiospeed_speedchanger_obj_t; + +void audiospeed_speedchanger_reset_buffer(audiospeed_speedchanger_obj_t *self, + bool single_channel_output, uint8_t channel); +audioio_get_buffer_result_t audiospeed_speedchanger_get_buffer(audiospeed_speedchanger_obj_t *self, + bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length); diff --git a/shared-module/audiospeed/__init__.c b/shared-module/audiospeed/__init__.c new file mode 100644 index 00000000000..19c4c9bf20d --- /dev/null +++ b/shared-module/audiospeed/__init__.c @@ -0,0 +1,176 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/gc.h" +#include "py/objproperty.h" +#include "py/runtime.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-module/audiospeed/__init__.h" +#include "shared-bindings/audiocore/__init__.h" + +// Convert a Python float to 16.16 fixed-point rate +uint32_t audiospeed_rate_to_fp(mp_obj_t rate_obj) { + mp_float_t rate = mp_arg_validate_obj_float_range(rate_obj, 0.001, 1000.0, MP_QSTR_rate); + return (uint32_t)(rate * (1 << SPEED_SHIFT)); +} + +// Convert 16.16 fixed-point rate to Python float +mp_obj_t audiospeed_fp_to_rate(uint32_t rate_fp) { + return mp_obj_new_float((mp_float_t)rate_fp / (1 << SPEED_SHIFT)); +} + +void audiospeed_construct(audiospeed_base_t *self, mp_obj_t source, mp_obj_t rate_obj) { + audiosample_base_t *src_base = audiosample_check(source); + + self->source = source; + self->src_buffer = NULL; + self->src_buffer_length = 0; + self->src_sample_count = 0; + self->source_done = false; + self->source_exhausted = false; + + + // Copy format from source + self->base.sample_rate = src_base->sample_rate; + self->base.channel_count = src_base->channel_count; + self->base.bits_per_sample = src_base->bits_per_sample; + self->base.samples_signed = src_base->samples_signed; + self->base.single_buffer = false; + + audiospeed_set_rate(&self->speed, rate_obj); + audiospeed_reset_phase(&self->speed); + + uint8_t bytes_per_frame = (src_base->bits_per_sample / 8) * src_base->channel_count; + self->output_buffer_length = OUTPUT_BUFFER_FRAMES * bytes_per_frame; + self->base.max_buffer_length = self->output_buffer_length; + + self->output_buffer = m_malloc_without_collect(self->output_buffer_length); + if (self->output_buffer == NULL) { + m_malloc_fail(self->output_buffer_length); + } +} + +void audiospeed_deinit(audiospeed_base_t *self) { + self->output_buffer = NULL; + self->source = MP_OBJ_NULL; + audiosample_mark_deinit(&self->base); +} + +// Fetch the next buffer from the source. Returns false if no data available. +bool audiospeed_fetch_source_buffer(audiospeed_base_t *self) { + if (self->source_exhausted || self->source == NULL) { + return false; + } + uint8_t *buf = NULL; + uint32_t len = 0; + audioio_get_buffer_result_t result = audiosample_get_buffer(self->source, false, 0, &buf, &len); + if (result == GET_BUFFER_ERROR) { + self->source_exhausted = true; + return false; + } + if (len == 0) { + self->source_exhausted = true; + return false; + } + self->src_buffer = buf; + self->src_buffer_length = len; + uint8_t bytes_per_frame = (self->base.bits_per_sample / 8) * self->base.channel_count; + self->src_sample_count = len / bytes_per_frame; + self->source_done = (result == GET_BUFFER_DONE); + // Reset phase to index within this new buffer + audiospeed_reset_phase(&self->speed); + return true; +} + +void audiospeed_reset_buffer(audiospeed_base_t *self, bool single_channel_output, uint8_t channel) { + if (single_channel_output && channel == 1) { + return; + } + audiosample_reset_buffer(self->source, false, 0); + audiospeed_reset_phase(&self->speed); + self->src_buffer = NULL; + self->src_buffer_length = 0; + self->src_sample_count = 0; + self->source_done = false; + self->source_exhausted = false; +} + +audioio_get_buffer_result_t audiospeed_get_buffer(audiospeed_base_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + + // Ensure we have a source buffer + if (self->src_buffer == NULL) { + if (!audiospeed_fetch_source_buffer(self)) { + *buffer = NULL; + *buffer_length = 0; + return GET_BUFFER_DONE; + } + } + + uint8_t bytes_per_sample = self->base.bits_per_sample / 8; + uint8_t channels = self->base.channel_count; + uint8_t bytes_per_frame = bytes_per_sample * channels; + uint32_t out_frames = 0; + uint32_t max_out_frames = self->output_buffer_length / bytes_per_frame; + + if (bytes_per_sample == 1) { + // 8-bit samples + uint8_t *out = self->output_buffer; + while (out_frames < max_out_frames) { + uint32_t src_index = audiospeed_get_index(&self->speed); + // Advance to next source buffer if needed + if (src_index >= self->src_sample_count) { + if (self->source_done) { + self->source_exhausted = true; + break; + } + if (!audiospeed_fetch_source_buffer(self)) { + break; + } + src_index = 0; // phase was reset by fetch + } + uint8_t *src = self->src_buffer + src_index * bytes_per_frame; + for (uint8_t c = 0; c < channels; c++) { + *out++ = src[c]; + } + out_frames++; + audiospeed_increment_phase(&self->speed); + } + } else { + // 16-bit samples + int16_t *out = (int16_t *)self->output_buffer; + while (out_frames < max_out_frames) { + uint32_t src_index = audiospeed_get_index(&self->speed); + if (src_index >= self->src_sample_count) { + if (self->source_done) { + self->source_exhausted = true; + break; + } + if (!audiospeed_fetch_source_buffer(self)) { + break; + } + src_index = 0; + } + int16_t *src = (int16_t *)(self->src_buffer + src_index * bytes_per_frame); + for (uint8_t c = 0; c < channels; c++) { + *out++ = src[c]; + } + out_frames++; + audiospeed_increment_phase(&self->speed); + } + } + + *buffer = self->output_buffer; + *buffer_length = out_frames * bytes_per_frame; + + if (out_frames == 0) { + return GET_BUFFER_DONE; + } + return self->source_exhausted ? GET_BUFFER_DONE : GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiospeed/__init__.h b/shared-module/audiospeed/__init__.h new file mode 100644 index 00000000000..4a36a8b79b7 --- /dev/null +++ b/shared-module/audiospeed/__init__.h @@ -0,0 +1,72 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/objproperty.h" +#include "shared-module/audiocore/__init__.h" + +// Fixed-point 16.16 format +#define SPEED_SHIFT 16 +#define SPEED_DEFAULT (1 << SPEED_SHIFT) // default 1.0 + +typedef struct { + // Phase accumulator and rate in 16.16 fixed-point (units: source frames) + uint32_t phase; + uint32_t rate_fp; // 16.16 fixed-point rate +} audiospeed_speed_t; + +uint32_t audiospeed_rate_to_fp(mp_obj_t rate_obj); +mp_obj_t audiospeed_fp_to_rate(uint32_t rate_fp); + +static inline void audiospeed_set_rate(audiospeed_speed_t *self, mp_obj_t rate_obj) { + if (rate_obj != mp_const_none) { + self->rate_fp = audiospeed_rate_to_fp(rate_obj); + } else { + self->rate_fp = SPEED_DEFAULT; + } +} + +static inline mp_obj_t audiospeed_get_rate(audiospeed_speed_t *self) { + return audiospeed_fp_to_rate(self->rate_fp); +} + +static inline void audiospeed_reset_phase(audiospeed_speed_t *self) { + self->phase = 0; +} + +static inline void audiospeed_increment_phase(audiospeed_speed_t *self) { + self->phase += self->rate_fp; +} + +static inline uint32_t audiospeed_get_index(audiospeed_speed_t *self) { + return self->phase >> SPEED_SHIFT; +} + +#define OUTPUT_BUFFER_FRAMES 128 + +typedef struct { + audiosample_base_t base; + mp_obj_t source; + uint8_t *output_buffer; + uint32_t output_buffer_length; // in bytes, allocated size + // Source buffer cache + uint8_t *src_buffer; + uint32_t src_buffer_length; // in bytes + uint32_t src_sample_count; // in frames + audiospeed_speed_t speed; + bool source_done; // source returned DONE on last get_buffer + bool source_exhausted; // source DONE and we consumed all of it +} audiospeed_base_t; + +void audiospeed_construct(audiospeed_base_t *self, mp_obj_t source, mp_obj_t rate_obj); +void audiospeed_deinit(audiospeed_base_t *self); +bool audiospeed_fetch_source_buffer(audiospeed_base_t *self); +void audiospeed_reset_buffer(audiospeed_base_t *self, bool single_channel_output, uint8_t channel); +audioio_get_buffer_result_t audiospeed_get_buffer(audiospeed_base_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length); diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index 2f2b7aaf475..e51881aa5bb 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -857,12 +857,15 @@ void common_hal_bitmaptools_dither(displayio_bitmap_t *dest_bitmap, displayio_bi } void common_hal_bitmaptools_alphablend(displayio_bitmap_t *dest, displayio_bitmap_t *source1, displayio_bitmap_t *source2, displayio_colorspace_t colorspace, mp_float_t factor1, mp_float_t factor2, - bitmaptools_blendmode_t blendmode, uint32_t skip_source1_index, bool skip_source1_index_none, uint32_t skip_source2_index, bool skip_source2_index_none) { + bitmaptools_blendmode_t blendmode, uint32_t skip_source1_index, bool skip_source1_index_none, uint32_t skip_source2_index, bool skip_source2_index_none, + displayio_bitmap_t *mask) { displayio_area_t a = {0, 0, dest->width, dest->height, NULL}; displayio_bitmap_set_dirty_area(dest, &a); - int ifactor1 = (int)(factor1 * 256); - int ifactor2 = (int)(factor2 * 256); + int ifactor1_base = (int)(factor1 * 256); + int ifactor2_base = (int)(factor2 * 256); + int ifactor1 = ifactor1_base; + int ifactor2 = ifactor2_base; bool blend_source1, blend_source2; if (colorspace == DISPLAYIO_COLORSPACE_L8) { @@ -870,10 +873,20 @@ void common_hal_bitmaptools_alphablend(displayio_bitmap_t *dest, displayio_bitma uint8_t *dptr = (uint8_t *)(dest->data + y * dest->stride); uint8_t *sptr1 = (uint8_t *)(source1->data + y * source1->stride); uint8_t *sptr2 = (uint8_t *)(source2->data + y * source2->stride); + uint8_t *mptr = mask ? (uint8_t *)(mask->data + y * mask->stride) : NULL; int pixel; for (int x = 0; x < dest->width; x++) { blend_source1 = skip_source1_index_none || *sptr1 != (uint8_t)skip_source1_index; blend_source2 = skip_source2_index_none || *sptr2 != (uint8_t)skip_source2_index; + if (mptr) { + uint8_t m = *mptr; + // Scale source2's contribution by the mask (0..255) + ifactor2 = (ifactor2_base * m + 127) / 255; + if (m == 0) { + // Mask says fully transparent: drop source2 entirely + blend_source2 = false; + } + } if (blend_source1 && blend_source2) { // Premultiply by the alpha factor int sda = *sptr1++ *ifactor1; @@ -886,7 +899,8 @@ void common_hal_bitmaptools_alphablend(displayio_bitmap_t *dest, displayio_bitma blend = sca + sda * (256 - ifactor2) / 256; } // Divide by the alpha factor - pixel = (blend / (ifactor1 + ifactor2 - ifactor1 * ifactor2 / 256)); + int denom = ifactor1 + ifactor2 - ifactor1 * ifactor2 / 256; + pixel = (denom > 0) ? (blend / denom) : 0; } else if (blend_source1) { // Apply iFactor1 to source1 only pixel = *sptr1++ *ifactor1 / 256; @@ -898,6 +912,9 @@ void common_hal_bitmaptools_alphablend(displayio_bitmap_t *dest, displayio_bitma pixel = *dptr; } *dptr++ = MIN(255, MAX(0, pixel)); + if (mptr) { + mptr++; + } } } } else { @@ -907,6 +924,7 @@ void common_hal_bitmaptools_alphablend(displayio_bitmap_t *dest, displayio_bitma uint16_t *dptr = (uint16_t *)(dest->data + y * dest->stride); uint16_t *sptr1 = (uint16_t *)(source1->data + y * source1->stride); uint16_t *sptr2 = (uint16_t *)(source2->data + y * source2->stride); + uint8_t *mptr = mask ? (uint8_t *)(mask->data + y * mask->stride) : NULL; for (int x = 0; x < dest->width; x++) { int spix1 = *sptr1++; int spix2 = *sptr2++; @@ -922,11 +940,24 @@ void common_hal_bitmaptools_alphablend(displayio_bitmap_t *dest, displayio_bitma blend_source1 = skip_source1_index_none || spix1 != (int)skip_source1_index; blend_source2 = skip_source2_index_none || spix2 != (int)skip_source2_index; + if (mptr) { + uint8_t m = *mptr++; + ifactor2 = (ifactor2_base * m + 127) / 255; + if (m == 0) { + blend_source2 = false; + } + } + if (blend_source1 && blend_source2) { // Blend based on the SVG alpha compositing specs // https://dev.w3.org/SVG/modules/compositing/master/#alphaCompositing int ifactor_blend = ifactor1 + ifactor2 - ifactor1 * ifactor2 / 256; + if (ifactor_blend <= 0) { + // Both factors are zero at this pixel; keep destination. + dptr++; + continue; + } // Premultiply the colors by the alpha factor int red_dca = ((spix1 & r_mask) >> 8) * ifactor1; diff --git a/shared-module/busdisplay/BusDisplay.c b/shared-module/busdisplay/BusDisplay.c index 6ef1c4c7f66..01e0f7a7896 100644 --- a/shared-module/busdisplay/BusDisplay.c +++ b/shared-module/busdisplay/BusDisplay.c @@ -6,6 +6,7 @@ #include "shared-bindings/busdisplay/BusDisplay.h" +#include "py/mphal.h" #include "py/runtime.h" #if CIRCUITPY_FOURWIRE #include "shared-bindings/fourwire/FourWire.h" @@ -16,6 +17,7 @@ #if CIRCUITPY_PARALLELDISPLAYBUS #include "shared-bindings/paralleldisplaybus/ParallelBus.h" #endif +#include "shared/runtime/interrupt_char.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/__init__.h" @@ -73,6 +75,9 @@ void common_hal_busdisplay_busdisplay_construct(busdisplay_busdisplay_obj_t *sel uint8_t *data = cmd + 2; while (!displayio_display_bus_begin_transaction(&self->bus)) { RUN_BACKGROUND_TASKS; + if (mp_hal_is_interrupted()) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_display); + } } if (self->bus.data_as_commands) { uint8_t full_command[data_size + 1]; @@ -214,7 +219,7 @@ static void _send_pixels(busdisplay_busdisplay_obj_t *self, uint8_t *pixels, uin } static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_area_t *area) { - uint16_t buffer_size = 128; // In uint32_ts + uint16_t buffer_size = CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE / sizeof(uint32_t); // In uint32_ts displayio_area_t clipped; // Clip the area to the display by overlapping the areas. If there is no overlap then we're done. @@ -256,9 +261,10 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are // Allocated and shared as a uint32_t array so the compiler knows the // alignment everywhere. - uint32_t buffer[buffer_size]; uint32_t mask_length = (pixels_per_buffer / 32) + 1; + uint32_t buffer[buffer_size]; uint32_t mask[mask_length]; + uint16_t remaining_rows = displayio_area_height(&clipped); for (uint16_t j = 0; j < subrectangles; j++) { @@ -273,8 +279,6 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are } remaining_rows -= rows_per_buffer; - displayio_display_bus_set_region_to_update(&self->bus, &self->core, &subrectangle); - uint16_t subrectangle_size_bytes; if (self->core.colorspace.depth >= 8) { subrectangle_size_bytes = displayio_area_size(&subrectangle) * (self->core.colorspace.depth / 8); @@ -287,12 +291,12 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); + displayio_display_bus_set_region_to_update(&self->bus, &self->core, &subrectangle); + // Can't acquire display bus; skip the rest of the data. - if (!displayio_display_bus_is_free(&self->bus)) { + if (!displayio_display_bus_begin_transaction(&self->bus)) { return false; } - - displayio_display_bus_begin_transaction(&self->bus); _send_pixels(self, (uint8_t *)buffer, subrectangle_size_bytes); displayio_display_bus_end_transaction(&self->bus); @@ -305,6 +309,10 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are usb_background(); #endif } + + // Drain any remaining asynchronous transfers. + displayio_display_bus_flush(&self->bus); + return true; } diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index e325a7857f4..c1309ee0972 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -45,6 +45,9 @@ #if CIRCUITPY_MIPIDSI #include "shared-bindings/mipidsi/Display.h" #endif +#if CIRCUITPY_ZEPHYR_DISPLAY +#include "bindings/zephyr_display/Display.h" +#endif #ifdef BOARD_USE_INTERNAL_SPI #include "supervisor/spi_flash_api.h" @@ -112,6 +115,10 @@ void displayio_background(void) { } else if (display_type == &epaperdisplay_epaperdisplay_type) { epaperdisplay_epaperdisplay_background(&displays[i].epaper_display); #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + } else if (display_type == &zephyr_display_display_type) { + zephyr_display_display_background(&displays[i].zephyr_display); + #endif } } @@ -142,10 +149,17 @@ static void common_hal_displayio_release_displays_impl(bool keep_primary) { } else if (display_type == &framebufferio_framebufferdisplay_type) { release_framebufferdisplay(&displays[i].framebuffer_display); #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + } else if (display_type == &zephyr_display_display_type) { + release_zephyr_display(&displays[i].zephyr_display); + #endif } displays[i].display_base.type = &mp_type_NoneType; } for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { + if (i == primary_display_number) { + continue; + } mp_const_obj_t bus_type = display_buses[i].bus_base.type; if (bus_type == NULL || bus_type == &mp_type_NoneType) { continue; @@ -189,11 +203,17 @@ static void common_hal_displayio_release_displays_impl(bool keep_primary) { } else if (bus_type == &mipidsi_display_type) { common_hal_mipidsi_display_deinit(&display_buses[i].mipidsi); #endif + #if CIRCUITPY_QSPIBUS + } else if (bus_type == &qspibus_qspibus_type) { + common_hal_qspibus_qspibus_deinit(&display_buses[i].qspi_bus); + #endif } display_buses[i].bus_base.type = &mp_type_NoneType; } - supervisor_stop_terminal(); + if (!keep_primary) { + supervisor_stop_terminal(); + } } void common_hal_displayio_release_displays(void) { @@ -201,8 +221,9 @@ void common_hal_displayio_release_displays(void) { } void reset_displays(void) { - // In CircuitPython 10, release secondary displays before doing anything else: - // common_hal_displayio_release_displays_impl(true); + // TODO: In CircuitPython 11, uncomment the call. + // Release secondary displays. + // common_hal_displayio_release_displays_impl(/*keep_primary*/ true); // The SPI buses used by FourWires may be allocated on the heap so we need to move them inline. for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { @@ -352,6 +373,10 @@ void reset_displays(void) { } else if (display_type == &framebufferio_framebufferdisplay_type) { framebufferio_framebufferdisplay_reset(&displays[i].framebuffer_display); #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + } else if (display_type == &zephyr_display_display_type) { + zephyr_display_display_reset(&displays[i].zephyr_display); + #endif } } } @@ -403,6 +428,10 @@ void displayio_gc_collect(void) { } else if (display_type == &epaperdisplay_epaperdisplay_type) { epaperdisplay_epaperdisplay_collect_ptrs(&displays[i].epaper_display); #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + } else if (display_type == &zephyr_display_display_type) { + zephyr_display_display_collect_ptrs(&displays[i].zephyr_display); + #endif } } } diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h index f2f4691b313..eabff662782 100644 --- a/shared-module/displayio/__init__.h +++ b/shared-module/displayio/__init__.h @@ -41,6 +41,12 @@ #if CIRCUITPY_MIPIDSI #include "shared-bindings/mipidsi/Display.h" #endif +#if CIRCUITPY_QSPIBUS +#include "shared-bindings/qspibus/QSPIBus.h" +#endif +#if CIRCUITPY_ZEPHYR_DISPLAY +#include "bindings/zephyr_display/Display.h" +#endif // Port unique frame buffers. #if CIRCUITPY_VIDEOCORE #include "bindings/videocore/Framebuffer.h" @@ -87,6 +93,9 @@ typedef struct { #if CIRCUITPY_MIPIDSI mipidsi_display_obj_t mipidsi; #endif + #if CIRCUITPY_QSPIBUS + qspibus_qspibus_obj_t qspi_bus; + #endif }; } primary_display_bus_t; @@ -102,6 +111,9 @@ typedef struct { #if CIRCUITPY_FRAMEBUFFERIO framebufferio_framebufferdisplay_obj_t framebuffer_display; #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + zephyr_display_display_obj_t zephyr_display; + #endif }; } primary_display_t; diff --git a/shared-module/displayio/bus_core.c b/shared-module/displayio/bus_core.c index e01b9d9eef6..9b3fb426217 100644 --- a/shared-module/displayio/bus_core.c +++ b/shared-module/displayio/bus_core.c @@ -17,6 +17,9 @@ #if CIRCUITPY_PARALLELDISPLAYBUS #include "shared-bindings/paralleldisplaybus/ParallelBus.h" #endif +#if CIRCUITPY_QSPIBUS +#include "shared-bindings/qspibus/QSPIBus.h" +#endif #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/__init__.h" @@ -49,6 +52,8 @@ void displayio_display_bus_construct(displayio_display_bus_t *self, self->SH1107_addressing = SH1107_addressing; self->address_little_endian = address_little_endian; + self->flush = NULL; + #if CIRCUITPY_PARALLELDISPLAYBUS if (mp_obj_is_type(bus, ¶lleldisplaybus_parallelbus_type)) { self->bus_reset = common_hal_paralleldisplaybus_parallelbus_reset; @@ -79,17 +84,33 @@ void displayio_display_bus_construct(displayio_display_bus_t *self, self->collect_ptrs = common_hal_i2cdisplaybus_i2cdisplaybus_collect_ptrs; } else #endif + #if CIRCUITPY_QSPIBUS + if (mp_obj_is_type(bus, &qspibus_qspibus_type)) { + self->bus_reset = common_hal_qspibus_qspibus_reset; + self->bus_free = common_hal_qspibus_qspibus_bus_free; + self->begin_transaction = common_hal_qspibus_qspibus_begin_transaction; + self->send = common_hal_qspibus_qspibus_send; + self->end_transaction = common_hal_qspibus_qspibus_end_transaction; + self->flush = common_hal_qspibus_qspibus_flush; + self->collect_ptrs = common_hal_qspibus_qspibus_collect_ptrs; + } else + #endif { mp_raise_ValueError(MP_ERROR_TEXT("Unsupported display bus type")); } self->bus = bus; } +// This is just a hint, and is not a reliable result, since the bus could be grabbed in between this called +// and the attempt to use the bus. Use displayio_display_bus_begin_transaction(), which is atomic. bool displayio_display_bus_is_free(displayio_display_bus_t *self) { return !self->bus || self->bus_free(self->bus); } -bool displayio_display_bus_begin_transaction(displayio_display_bus_t *self) { +MP_WARN_UNUSED_RESULT bool displayio_display_bus_begin_transaction(displayio_display_bus_t *self) { + if (!self->bus) { + return false; + } mp_obj_base_t *bus_base = MP_OBJ_TO_PTR(self->bus); if (bus_base->type == &mp_type_NoneType) { return false; @@ -128,7 +149,9 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d } // Set column. - displayio_display_bus_begin_transaction(self); + if (!displayio_display_bus_begin_transaction(self)) { + return; + } uint8_t data[5]; data[0] = self->column_command; uint8_t data_length = 1; @@ -167,7 +190,9 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d if (self->set_current_column_command != NO_COMMAND) { uint8_t command = self->set_current_column_command; - displayio_display_bus_begin_transaction(self); + if (!displayio_display_bus_begin_transaction(self)) { + return; + } self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1); // Only send the first half of data because it is the first coordinate. self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2); @@ -176,7 +201,9 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d // Set row. - displayio_display_bus_begin_transaction(self); + if (!displayio_display_bus_begin_transaction(self)) { + return; + } data[0] = self->row_command; data_length = 1; if (!self->data_as_commands) { @@ -211,7 +238,9 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d if (self->set_current_row_command != NO_COMMAND) { uint8_t command = self->set_current_row_command; - displayio_display_bus_begin_transaction(self); + if (!displayio_display_bus_begin_transaction(self)) { + return; + } self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1); // Only send the first half of data because it is the first coordinate. self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2); @@ -219,6 +248,12 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d } } +void displayio_display_bus_flush(displayio_display_bus_t *self) { + if (self->flush != NULL) { + self->flush(self->bus); + } +} + void displayio_display_bus_collect_ptrs(displayio_display_bus_t *self) { self->collect_ptrs(self->bus); } diff --git a/shared-module/displayio/bus_core.h b/shared-module/displayio/bus_core.h index 838454c92e6..75d03d7f284 100644 --- a/shared-module/displayio/bus_core.h +++ b/shared-module/displayio/bus_core.h @@ -21,6 +21,7 @@ typedef struct { display_bus_begin_transaction begin_transaction; display_bus_send send; display_bus_end_transaction end_transaction; + display_bus_flush flush; display_bus_collect_ptrs collect_ptrs; uint16_t ram_width; uint16_t ram_height; @@ -49,6 +50,10 @@ void displayio_display_bus_end_transaction(displayio_display_bus_t *self); void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area); +// Drain any pending asynchronous transfers on the bus. +// No-op for synchronous buses (FourWire, I2C, ParallelBus). +void displayio_display_bus_flush(displayio_display_bus_t *self); + void release_display_bus(displayio_display_bus_t *self); void displayio_display_bus_collect_ptrs(displayio_display_bus_t *self); diff --git a/shared-module/epaperdisplay/EPaperDisplay.c b/shared-module/epaperdisplay/EPaperDisplay.c index 655ae103071..d34be9d5c7c 100644 --- a/shared-module/epaperdisplay/EPaperDisplay.c +++ b/shared-module/epaperdisplay/EPaperDisplay.c @@ -153,7 +153,10 @@ static void send_command_sequence(epaperdisplay_epaperdisplay_obj_t *self, data_size = ((data_size & ~DELAY) << 8) + *(cmd + 2); data = cmd + 3; } - displayio_display_bus_begin_transaction(&self->bus); + while (!displayio_display_bus_begin_transaction(&self->bus) && + !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + } self->bus.send(self->bus.bus, DISPLAY_COMMAND, self->chip_select, cmd, 1); self->bus.send(self->bus.bus, DISPLAY_DATA, self->chip_select, data, data_size); displayio_display_bus_end_transaction(&self->bus); @@ -311,7 +314,10 @@ static bool epaperdisplay_epaperdisplay_refresh_area(epaperdisplay_epaperdisplay if (pass == 1) { write_command = self->write_color_ram_command; } - displayio_display_bus_begin_transaction(&self->bus); + if (!displayio_display_bus_begin_transaction(&self->bus)) { + // Display bus not available now. + return false; + } self->bus.send(self->bus.bus, DISPLAY_COMMAND, self->chip_select, &write_command, 1); displayio_display_bus_end_transaction(&self->bus); @@ -388,7 +394,9 @@ static bool _clean_area(epaperdisplay_epaperdisplay_obj_t *self) { memset(buffer, 0x77, width / 2); uint8_t write_command = self->write_black_ram_command; - displayio_display_bus_begin_transaction(&self->bus); + if (displayio_display_bus_begin_transaction(&self->bus)) { + return false; + } self->bus.send(self->bus.bus, DISPLAY_COMMAND, self->chip_select, &write_command, 1); displayio_display_bus_end_transaction(&self->bus); diff --git a/shared-module/hashlib/Hash.c b/shared-module/hashlib/Hash.c index b7e966e951b..64fcf2d941f 100644 --- a/shared-module/hashlib/Hash.c +++ b/shared-module/hashlib/Hash.c @@ -7,14 +7,55 @@ #include "shared-bindings/hashlib/Hash.h" #include "shared-module/hashlib/__init__.h" +#include "mbedtls/version.h" + +#if MBEDTLS_VERSION_MAJOR >= 4 + +#include "psa/crypto.h" + +void common_hal_hashlib_hash_update(hashlib_hash_obj_t *self, const uint8_t *data, size_t datalen) { + psa_hash_update(&self->hash_op, data, datalen); +} + +void common_hal_hashlib_hash_digest(hashlib_hash_obj_t *self, uint8_t *data, size_t datalen) { + if (datalen < common_hal_hashlib_hash_get_digest_size(self)) { + return; + } + // Clone the operation so we can continue to update or get digest again. + psa_hash_operation_t clone = PSA_HASH_OPERATION_INIT; + psa_hash_clone(&self->hash_op, &clone); + size_t hash_len; + psa_hash_finish(&clone, data, datalen, &hash_len); +} + +size_t common_hal_hashlib_hash_get_digest_size(hashlib_hash_obj_t *self) { + return PSA_HASH_LENGTH(self->hash_alg); +} + +#else + #include "mbedtls/ssl.h" +// In mbedtls 2.x, the _ret suffix functions are the recommended API. +// In mbedtls 3.x, the _ret suffix was removed and the base names return int. +#if MBEDTLS_VERSION_MAJOR < 3 +#define SHA1_UPDATE mbedtls_sha1_update_ret +#define SHA1_FINISH mbedtls_sha1_finish_ret +#define SHA256_UPDATE mbedtls_sha256_update_ret +#define SHA256_FINISH mbedtls_sha256_finish_ret +#else +#define SHA1_UPDATE mbedtls_sha1_update +#define SHA1_FINISH mbedtls_sha1_finish +#define SHA256_UPDATE mbedtls_sha256_update +#define SHA256_FINISH mbedtls_sha256_finish +#endif + void common_hal_hashlib_hash_update(hashlib_hash_obj_t *self, const uint8_t *data, size_t datalen) { if (self->hash_type == MBEDTLS_SSL_HASH_SHA1) { - mbedtls_sha1_update_ret(&self->sha1, data, datalen); + SHA1_UPDATE(&self->sha1, data, datalen); return; } else if (self->hash_type == MBEDTLS_SSL_HASH_SHA256) { - mbedtls_sha256_update_ret(&self->sha256, data, datalen); + SHA256_UPDATE(&self->sha256, data, datalen); return; } } @@ -28,12 +69,12 @@ void common_hal_hashlib_hash_digest(hashlib_hash_obj_t *self, uint8_t *data, siz // the digest a second time. mbedtls_sha1_context copy; mbedtls_sha1_clone(©, &self->sha1); - mbedtls_sha1_finish_ret(&self->sha1, data); + SHA1_FINISH(&self->sha1, data); mbedtls_sha1_clone(&self->sha1, ©); } else if (self->hash_type == MBEDTLS_SSL_HASH_SHA256) { mbedtls_sha256_context copy; mbedtls_sha256_clone(©, &self->sha256); - mbedtls_sha256_finish_ret(&self->sha256, data); + SHA256_FINISH(&self->sha256, data); mbedtls_sha256_clone(&self->sha256, ©); } } @@ -46,3 +87,5 @@ size_t common_hal_hashlib_hash_get_digest_size(hashlib_hash_obj_t *self) { } return 0; } + +#endif diff --git a/shared-module/hashlib/Hash.h b/shared-module/hashlib/Hash.h index f3c2979e59c..035368e7c2f 100644 --- a/shared-module/hashlib/Hash.h +++ b/shared-module/hashlib/Hash.h @@ -6,6 +6,20 @@ #pragma once +#include "mbedtls/version.h" + +#if MBEDTLS_VERSION_MAJOR >= 4 + +#include "psa/crypto.h" + +typedef struct { + mp_obj_base_t base; + psa_hash_operation_t hash_op; + psa_algorithm_t hash_alg; +} hashlib_hash_obj_t; + +#else + #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" @@ -18,3 +32,5 @@ typedef struct { // Of MBEDTLS_SSL_HASH_* uint8_t hash_type; } hashlib_hash_obj_t; + +#endif diff --git a/shared-module/hashlib/__init__.c b/shared-module/hashlib/__init__.c index f9bc787d49f..d2a19386431 100644 --- a/shared-module/hashlib/__init__.c +++ b/shared-module/hashlib/__init__.c @@ -7,20 +7,52 @@ #include "shared-bindings/hashlib/__init__.h" #include "shared-module/hashlib/__init__.h" +#include "mbedtls/version.h" + +#if MBEDTLS_VERSION_MAJOR >= 4 + +#include "psa/crypto.h" + +bool common_hal_hashlib_new(hashlib_hash_obj_t *self, const char *algorithm) { + if (strcmp(algorithm, "sha1") == 0) { + self->hash_alg = PSA_ALG_SHA_1; + } else if (strcmp(algorithm, "sha256") == 0) { + self->hash_alg = PSA_ALG_SHA_256; + } else { + return false; + } + self->hash_op = psa_hash_operation_init(); + psa_hash_setup(&self->hash_op, self->hash_alg); + return true; +} + +#else + #include "mbedtls/ssl.h" +// In mbedtls 2.x, the _ret suffix functions are the recommended API. +// In mbedtls 3.x, the _ret suffix was removed and the base names return int. +#if MBEDTLS_VERSION_MAJOR < 3 +#define SHA1_STARTS mbedtls_sha1_starts_ret +#define SHA256_STARTS mbedtls_sha256_starts_ret +#else +#define SHA1_STARTS mbedtls_sha1_starts +#define SHA256_STARTS mbedtls_sha256_starts +#endif bool common_hal_hashlib_new(hashlib_hash_obj_t *self, const char *algorithm) { if (strcmp(algorithm, "sha1") == 0) { self->hash_type = MBEDTLS_SSL_HASH_SHA1; mbedtls_sha1_init(&self->sha1); - mbedtls_sha1_starts_ret(&self->sha1); + SHA1_STARTS(&self->sha1); return true; } else if (strcmp(algorithm, "sha256") == 0) { self->hash_type = MBEDTLS_SSL_HASH_SHA256; mbedtls_sha256_init(&self->sha256); - mbedtls_sha256_starts_ret(&self->sha256, 0); + SHA256_STARTS(&self->sha256, 0); return true; } return false; } + +#endif diff --git a/shared-module/lvfontio/OnDiskFont.c b/shared-module/lvfontio/OnDiskFont.c index 368bd381475..efffed63074 100644 --- a/shared-module/lvfontio/OnDiskFont.c +++ b/shared-module/lvfontio/OnDiskFont.c @@ -48,6 +48,7 @@ static inline void free_memory(lvfontio_ondiskfont_t *self, void *ptr) { // Forward declarations for helper functions static int16_t find_codepoint_slot(lvfontio_ondiskfont_t *self, uint32_t codepoint); +static bool slot_has_active_full_width_partner(lvfontio_ondiskfont_t *self, uint16_t slot); static uint16_t find_free_slot(lvfontio_ondiskfont_t *self, uint32_t codepoint); static FRESULT read_bits(FIL *file, size_t num_bits, uint8_t *byte_val, uint8_t *remaining_bits, uint32_t *result); static FRESULT read_glyph_dimensions(FIL *file, lvfontio_ondiskfont_t *self, uint32_t *advance_width, int32_t *bbox_x, int32_t *bbox_y, uint32_t *bbox_w, uint32_t *bbox_h, uint8_t *byte_val, uint8_t *remaining_bits); @@ -224,7 +225,12 @@ static bool load_font_header(lvfontio_ondiskfont_t *self, FIL *file, size_t *max // Throw away the bitmap bits. read_bits(file, self->header.bits_per_pixel * bbox_w * bbox_h, &byte_val, &remaining_bits, NULL); - if (advances[0] == glyph_advance) { + + if (glyph_advance == 0) { + // Ignore zero-advance glyphs when inferring the terminal cell width. + // Some fonts include placeholders/control glyphs with zero advance, + // which would otherwise skew default_advance_width too small. + } else if (advances[0] == glyph_advance) { advance_count[0]++; } else if (advances[1] == glyph_advance) { advance_count[1]++; @@ -257,6 +263,12 @@ static bool load_font_header(lvfontio_ondiskfont_t *self, FIL *file, size_t *max *max_slots = advance_count[0] + advance_count[1]; } + if (self->header.default_advance_width == 0) { + self->header.default_advance_width = 1; + } + if (*max_slots == 0) { + *max_slots = 1; + } found_glyf = true; } @@ -344,8 +356,9 @@ static int32_t get_char_id(lvfontio_ondiskfont_t *self, uint32_t codepoint) { for (size_t j = 0; j < self->cmap_ranges[i].entries_count; j++) { // Read code point at the index uint16_t candidate_codepoint_delta; - res = f_read(&self->file, &candidate_codepoint_delta, 2, NULL); - if (res != FR_OK) { + UINT bytes_read; + res = f_read(&self->file, &candidate_codepoint_delta, 2, &bytes_read); + if (res != FR_OK || bytes_read < 2) { return -1; } @@ -574,18 +587,20 @@ int16_t common_hal_lvfontio_ondiskfont_cache_glyph(lvfontio_ondiskfont_t *self, // Check if already cached int16_t existing_slot = find_codepoint_slot(self, codepoint); if (existing_slot >= 0) { - // Glyph is already cached, increment reference count + // Glyph is already cached, increment reference count(s). self->reference_counts[existing_slot]++; // Check if this is a full-width character by looking for a second slot - // with the same codepoint right after this one + // with the same codepoint right after this one, wrapping at the end. + uint16_t next_slot = (existing_slot + 1) % self->max_glyphs; + bool cached_is_full_width = self->codepoints[next_slot] == codepoint; + + if (cached_is_full_width) { + self->reference_counts[next_slot]++; + } + if (is_full_width != NULL) { - if (existing_slot + 1 < self->max_glyphs && - self->codepoints[existing_slot + 1] == codepoint) { - *is_full_width = true; - } else { - *is_full_width = false; - } + *is_full_width = cached_is_full_width; } return existing_slot; @@ -722,12 +737,37 @@ static int16_t find_codepoint_slot(lvfontio_ondiskfont_t *self, uint32_t codepoi for (uint16_t i = 0; i < self->max_glyphs; i++) { int16_t slot = (i + offset) % self->max_glyphs; if (self->codepoints[slot] == codepoint) { + // If this is the second slot of a full-width glyph pair, return the + // first slot so callers always get a canonical index. + if (slot > 0 && self->codepoints[slot - 1] == codepoint) { + return slot - 1; + } return slot; } } return -1; } +static bool slot_has_active_full_width_partner(lvfontio_ondiskfont_t *self, uint16_t slot) { + uint32_t codepoint = self->codepoints[slot]; + if (codepoint == LVFONTIO_INVALID_CODEPOINT) { + return false; + } + + // Don't evict one half of a full-width pair while the other half is still in use. + uint16_t prev_slot = (slot + self->max_glyphs - 1) % self->max_glyphs; + uint16_t next_slot = (slot + 1) % self->max_glyphs; + + if (self->codepoints[prev_slot] == codepoint && self->reference_counts[prev_slot] > 0) { + return true; + } + if (self->codepoints[next_slot] == codepoint && self->reference_counts[next_slot] > 0) { + return true; + } + + return false; +} + static uint16_t find_free_slot(lvfontio_ondiskfont_t *self, uint32_t codepoint) { size_t offset = codepoint % self->max_glyphs; @@ -739,10 +779,11 @@ static uint16_t find_free_slot(lvfontio_ondiskfont_t *self, uint32_t codepoint) } } - // If none found, look for slots with zero reference count, starting at the offset + // If none found, look for slots with zero reference count, starting at the offset. + // Avoid reusing one half of an active full-width glyph pair. for (uint16_t i = 0; i < self->max_glyphs; i++) { int16_t slot = (i + offset) % self->max_glyphs; - if (self->reference_counts[slot] == 0) { + if (self->reference_counts[slot] == 0 && !slot_has_active_full_width_partner(self, slot)) { return slot; } } diff --git a/shared-module/msgpack/__init__.c b/shared-module/msgpack/__init__.c index a98fb02de39..7c3e664bb6c 100644 --- a/shared-module/msgpack/__init__.c +++ b/shared-module/msgpack/__init__.c @@ -394,7 +394,9 @@ static mp_obj_t unpack(msgpack_stream_t *s, mp_obj_t ext_hook, bool use_list) { size_t len = code & 0b1111; mp_obj_dict_t *d = MP_OBJ_TO_PTR(mp_obj_new_dict(len)); for (size_t i = 0; i < len; i++) { - mp_obj_dict_store(d, unpack(s, ext_hook, use_list), unpack(s, ext_hook, use_list)); + mp_obj_t key = unpack(s, ext_hook, use_list); + mp_obj_t value = unpack(s, ext_hook, use_list); + mp_obj_dict_store(d, key, value); } return MP_OBJ_FROM_PTR(d); } @@ -462,7 +464,9 @@ static mp_obj_t unpack(msgpack_stream_t *s, mp_obj_t ext_hook, bool use_list) { size_t len = read_size(s, code - 0xde + 1); mp_obj_dict_t *d = MP_OBJ_TO_PTR(mp_obj_new_dict(len)); for (size_t i = 0; i < len; i++) { - mp_obj_dict_store(d, unpack(s, ext_hook, use_list), unpack(s, ext_hook, use_list)); + mp_obj_t key = unpack(s, ext_hook, use_list); + mp_obj_t value = unpack(s, ext_hook, use_list); + mp_obj_dict_store(d, key, value); } return MP_OBJ_FROM_PTR(d); } diff --git a/shared-module/sdcardio/SDCard.c b/shared-module/sdcardio/SDCard.c index 878fed7a13c..40d09aa99ca 100644 --- a/shared-module/sdcardio/SDCard.c +++ b/shared-module/sdcardio/SDCard.c @@ -7,15 +7,18 @@ // This implementation largely follows the structure of adafruit_sdcard.py #include "extmod/vfs.h" - #include "shared-bindings/busio/SPI.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/sdcardio/SDCard.h" #include "shared-bindings/time/__init__.h" #include "shared-bindings/util.h" #include "shared-module/sdcardio/SDCard.h" +#include "supervisor/shared/tick.h" #include "py/mperrno.h" +#include "py/mphal.h" +#include "py/gc.h" +#include "supervisor/port.h" #if 0 #define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print,##__VA_ARGS__)) @@ -23,7 +26,17 @@ #define DEBUG_PRINT(...) ((void)0) #endif -#define CMD_TIMEOUT (200) +// https://nodeloop.org/guides/sd-card-spi-init-guide/ is an excellent source of info for SPI card use. + +// https://www.taterli.com/wp-content/uploads/2017/05/Physical-Layer-Simplified-SpecificationV6.0.pdf +// specifies timeouts for read (100 ms), write (250 ms), erase (depends on size), and other operations. +// cmd timeout was 250, but did not work on some cards. +// See https://github.com/adafruit/circuitpython/issues/10954 +#define CMD_TIMEOUT_MS (500) +#define SPI_TIMEOUT_MS (250) +// Init ready timeout. +#define READY_TIMEOUT_MS (300) + #define R1_IDLE_STATE (1 << 0) #define R1_ILLEGAL_COMMAND (1 << 2) @@ -54,9 +67,8 @@ static bool lock_and_configure_bus(sdcardio_sdcard_obj_t *self) { if (common_hal_sdcardio_sdcard_deinited(self)) { return false; } - common_hal_sdcardio_check_for_deinit(self); - if (!common_hal_busio_spi_try_lock(self->bus)) { + if (!common_hal_busio_spi_wait_for_lock(self->bus, SPI_TIMEOUT_MS)) { return false; } @@ -68,7 +80,7 @@ static bool lock_and_configure_bus(sdcardio_sdcard_obj_t *self) { } common_hal_busio_spi_configure(self->bus, self->baudrate, 0, 0, 8); - common_hal_digitalio_digitalinout_set_value(&self->cs, false); + digitalinout_protocol_set_value(self->cs, false); return true; } @@ -79,11 +91,10 @@ static void lock_bus_or_throw(sdcardio_sdcard_obj_t *self) { } static void clock_card(sdcardio_sdcard_obj_t *self, int bytes) { - uint8_t buf[] = {0xff}; - common_hal_digitalio_digitalinout_set_value(&self->cs, true); - for (int i = 0; i < bytes; i++) { - common_hal_busio_spi_write(self->bus, buf, 1); - } + uint8_t buf[bytes]; + memset(buf, 0xff, bytes); + digitalinout_protocol_set_value(self->cs, true); + common_hal_busio_spi_write(self->bus, buf, bytes); } static void extraclock_and_unlock_bus(sdcardio_sdcard_obj_t *self) { @@ -106,21 +117,35 @@ static uint8_t CRC7(const uint8_t *data, uint8_t n) { return (crc << 1) | 1; } -#define READY_TIMEOUT_NS (300 * 1000 * 1000) // 300ms -static int wait_for_ready(sdcardio_sdcard_obj_t *self) { - uint64_t deadline = common_hal_time_monotonic_ns() + READY_TIMEOUT_NS; - while (common_hal_time_monotonic_ns() < deadline) { +// Assumes that the spi lock has been acquired. +// +// Mask the incoming value with mask. Use 0xff to not mask. +// if not_match is true, wait for something NOT matching the value. +// Return the response as an int32_t (which is always >= 0), or -1 if timed out. +static int32_t wait_for_masked_response(sdcardio_sdcard_obj_t *self, uint8_t mask, uint8_t response, bool not_match, uint32_t timeout_ms) { + uint64_t deadline = supervisor_ticks_ms64() + timeout_ms; + while (supervisor_ticks_ms64() < deadline) { uint8_t b; common_hal_busio_spi_read(self->bus, &b, 1, 0xff); - if (b == 0xff) { - return 0; + if (((b & mask) == response) ^ not_match) { + return b; } } - return -ETIMEDOUT; + return -1; +} + +// Wait for the given response byte. +static bool wait_for_response(sdcardio_sdcard_obj_t *self, uint8_t response) { + return wait_for_masked_response(self, 0xff, response, false, CMD_TIMEOUT_MS) != -1; +} + +// Wait for 0xff, with a specific timeout. +static bool wait_for_ready(sdcardio_sdcard_obj_t *self) { + return wait_for_masked_response(self, 0xff, 0xff, false, READY_TIMEOUT_MS) != -1; } // Note: this is never called while "in cmd25" (in fact, it's only used by `exit_cmd25`) -static int cmd_nodata(sdcardio_sdcard_obj_t *self, int cmd, int response) { +static mp_negative_errno_t cmd_nodata(sdcardio_sdcard_obj_t *self, int cmd, int response) { uint8_t cmdbuf[2] = {cmd, 0xff}; assert(!self->in_cmd25); @@ -128,17 +153,14 @@ static int cmd_nodata(sdcardio_sdcard_obj_t *self, int cmd, int response) { common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf)); // Wait for the response (response[7] == response) - for (int i = 0; i < CMD_TIMEOUT; i++) { - common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff); - if (cmdbuf[0] == response) { - return 0; - } + if (wait_for_response(self, response)) { + return 0; } return -MP_EIO; } -static int exit_cmd25(sdcardio_sdcard_obj_t *self) { +static mp_negative_errno_t exit_cmd25(sdcardio_sdcard_obj_t *self) { if (self->in_cmd25) { DEBUG_PRINT("exit cmd25\n"); self->in_cmd25 = false; @@ -149,7 +171,7 @@ static int exit_cmd25(sdcardio_sdcard_obj_t *self) { // In Python API, defaults are response=None, data_block=True, wait=True static int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf, size_t response_len, bool data_block, bool wait) { - int r = exit_cmd25(self); + mp_negative_errno_t r = exit_cmd25(self); if (r < 0) { return r; } @@ -164,25 +186,17 @@ static int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf cmdbuf[5] = CRC7(cmdbuf, 5); if (wait) { - r = wait_for_ready(self); - if (r < 0) { - return r; + if (!wait_for_ready(self)) { + return -MP_ETIMEDOUT; } } common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf)); // Wait for the response (response[7] == 0) - bool response_received = false; - for (int i = 0; i < CMD_TIMEOUT; i++) { - common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff); - if ((cmdbuf[0] & 0x80) == 0) { - response_received = true; - break; - } - } - - if (!response_received) { + // Now wait for cmd response, which is the high bit being 0. + int32_t response = wait_for_masked_response(self, 0x80, 0, false, CMD_TIMEOUT_MS); + if (response == -1) { return -MP_EIO; } @@ -190,22 +204,25 @@ static int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf if (data_block) { cmdbuf[1] = 0xff; - do { - // Wait for the start block byte - common_hal_busio_spi_read(self->bus, cmdbuf + 1, 1, 0xff); - } while (cmdbuf[1] != 0xfe); + if (!wait_for_response(self, 0xfe)) { + return -MP_EIO; + } } - common_hal_busio_spi_read(self->bus, response_buf, response_len, 0xff); + if (!common_hal_busio_spi_read(self->bus, response_buf, response_len, 0xff)) { + return -MP_EIO; + } if (data_block) { // Read and discard the CRC-CCITT checksum - common_hal_busio_spi_read(self->bus, cmdbuf + 1, 2, 0xff); + if (!common_hal_busio_spi_read(self->bus, cmdbuf + 1, 2, 0xff)) { + return -MP_EIO; + } } } - return cmdbuf[0]; + return response; } static int block_cmd(sdcardio_sdcard_obj_t *self, int cmd_, int block, void *response_buf, size_t response_len, bool data_block, bool wait) { @@ -213,7 +230,8 @@ static int block_cmd(sdcardio_sdcard_obj_t *self, int cmd_, int block, void *res } static mp_rom_error_text_t init_card_v1(sdcardio_sdcard_obj_t *self) { - for (int i = 0; i < CMD_TIMEOUT; i++) { + uint64_t deadline = supervisor_ticks_ms64() + CMD_TIMEOUT_MS; + while (supervisor_ticks_ms64() < deadline) { if (cmd(self, 41, 0, NULL, 0, true, true) == 0) { return NULL; } @@ -222,7 +240,8 @@ static mp_rom_error_text_t init_card_v1(sdcardio_sdcard_obj_t *self) { } static mp_rom_error_text_t init_card_v2(sdcardio_sdcard_obj_t *self) { - for (int i = 0; i < CMD_TIMEOUT; i++) { + uint64_t deadline = supervisor_ticks_ms64() + CMD_TIMEOUT_MS; + while (supervisor_ticks_ms64() < deadline) { uint8_t ocr[4]; common_hal_time_delay_ms(50); cmd(self, 58, 0, ocr, sizeof(ocr), false, true); @@ -239,9 +258,11 @@ static mp_rom_error_text_t init_card_v2(sdcardio_sdcard_obj_t *self) { } static mp_rom_error_text_t init_card(sdcardio_sdcard_obj_t *self) { + // https://nodeloop.org/guides/sd-card-spi-init-guide/ recommends at least 74 bit clocks + // and says 80 bit clocks(10*8) is common. Value below is bytes, not bits. clock_card(self, 10); - common_hal_digitalio_digitalinout_set_value(&self->cs, false); + digitalinout_protocol_set_value(self->cs, false); assert(!self->in_cmd25); self->in_cmd25 = false; // should be false already @@ -317,11 +338,15 @@ static mp_rom_error_text_t init_card(sdcardio_sdcard_obj_t *self) { return NULL; } -mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate, bool persistent_mount) { +mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, mp_obj_t cs, int baudrate, bool persistent_mount) { self->bus = bus; self->persistent_mount = persistent_mount; - common_hal_digitalio_digitalinout_construct(&self->cs, cs); - common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL); + + // Allocate the pins in the same place as self. + bool use_port_allocation = !gc_alloc_possible() || !gc_ptr_on_heap(self); + + self->cs = digitalinout_protocol_from_pin(cs, MP_QSTR_cs, false, use_port_allocation, &self->own_cs); + digitalinout_protocol_switch_to_output(self->cs, true, DRIVE_MODE_PUSH_PULL); self->cdv = 512; self->sectors = 0; @@ -334,7 +359,10 @@ mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio extraclock_and_unlock_bus(self); if (result != NULL) { - common_hal_digitalio_digitalinout_deinit(&self->cs); + if (self->own_cs) { + digitalinout_protocol_deinit(self->cs); + circuitpy_free_obj(self->cs); + } return result; } @@ -343,7 +371,7 @@ mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio } -void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) { +void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, mp_obj_t cs, int baudrate) { // User mounted, so persistent_mount=false. mp_rom_error_text_t result = sdcardio_sdcard_construct(self, bus, cs, baudrate, false); if (result != NULL) { @@ -357,7 +385,10 @@ void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) { } common_hal_sdcardio_sdcard_sync(self); common_hal_sdcardio_sdcard_mark_deinit(self); - common_hal_digitalio_digitalinout_deinit(&self->cs); + if (self->own_cs) { + digitalinout_protocol_deinit(self->cs); + circuitpy_free_obj(self->cs); + } } int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self) { @@ -366,23 +397,25 @@ int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self) { } static int readinto(sdcardio_sdcard_obj_t *self, void *buf, size_t size) { - uint8_t aux[2] = {0, 0}; - while (aux[0] != 0xfe) { - common_hal_busio_spi_read(self->bus, aux, 1, 0xff); + + if (!wait_for_response(self, 0xfe)) { + return -MP_EIO; } common_hal_busio_spi_read(self->bus, buf, size, 0xff); // Read checksum and throw it away - common_hal_busio_spi_read(self->bus, aux, sizeof(aux), 0xff); + uint8_t checksum[2]; + common_hal_busio_spi_read(self->bus, checksum, sizeof(checksum), 0xff); return 0; } +// The mp_uint_t is misleading; negative errors can be returned. mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) { // deinit check is in lock_and_configure_bus() sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!lock_and_configure_bus(self)) { - return MP_EAGAIN; + return -MP_ETIMEDOUT; } int r = 0; size_t buflen = 512 * nblocks; @@ -415,6 +448,7 @@ mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t st } } extraclock_and_unlock_bus(self); + // No caller actually uses this value. return r; } @@ -427,7 +461,9 @@ int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t } static int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) { - wait_for_ready(self); + if (!wait_for_ready(self)) { + return -MP_ETIMEDOUT; + } uint8_t cmd[2]; cmd[0] = token; @@ -450,9 +486,9 @@ static int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t // with STATUS 010 indicating "data accepted", and other status bit // combinations indicating failure. // In practice, I was seeing cmd[0] as 0xe5, indicating success - for (int i = 0; i < CMD_TIMEOUT; i++) { + uint64_t deadline = supervisor_ticks_ms64() + CMD_TIMEOUT_MS; + while (supervisor_ticks_ms64() < deadline) { common_hal_busio_spi_read(self->bus, cmd, 1, 0xff); - DEBUG_PRINT("i=%02d cmd[0] = 0x%02x\n", i, cmd[0]); if ((cmd[0] & 0b00010001) == 0b00000001) { if ((cmd[0] & 0x1f) != 0x5) { return -MP_EIO; @@ -463,9 +499,11 @@ static int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t } // Wait for the write to finish - do { - common_hal_busio_spi_read(self->bus, cmd, 1, 0xff); - } while (cmd[0] == 0); + + // Wait for a non-zero value. + if (wait_for_masked_response(self, 0xff /*mask*/, 0, true /*not_match*/, CMD_TIMEOUT_MS) == -1) { + return -MP_EIO; + } // Success return 0; @@ -475,7 +513,7 @@ mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t s // deinit check is in lock_and_configure_bus() sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!lock_and_configure_bus(self)) { - return MP_EAGAIN; + return -MP_ETIMEDOUT; } if (!self->in_cmd25 || start_block != self->next_block) { @@ -507,15 +545,17 @@ mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t s return 0; } -int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self) { +mp_negative_errno_t common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self) { // deinit check is in lock_and_configure_bus() - lock_and_configure_bus(self); + if (!lock_and_configure_bus(self)) { + return -MP_ETIMEDOUT; + } int r = exit_cmd25(self); extraclock_and_unlock_bus(self); return r; } -int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { +mp_negative_errno_t common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { if (buf->len % 512 != 0) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); } diff --git a/shared-module/sdcardio/SDCard.h b/shared-module/sdcardio/SDCard.h index 35a9ed1bf3c..6af68c274cd 100644 --- a/shared-module/sdcardio/SDCard.h +++ b/shared-module/sdcardio/SDCard.h @@ -17,7 +17,7 @@ typedef struct { mp_obj_base_t base; busio_spi_obj_t *bus; - digitalio_digitalinout_obj_t cs; + mp_obj_t cs; int cdv; int baudrate; uint32_t sectors; @@ -26,6 +26,7 @@ typedef struct { // Automounted SD cards are usually persistent across VM's. Note this as needed to allow access // when the VM is not running. bool persistent_mount; + bool own_cs; } sdcardio_sdcard_obj_t; -mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate, bool persistent_mount); +mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, mp_obj_t cs, int baudrate, bool persistent_mount); diff --git a/shared-module/sdcardio/__init__.c b/shared-module/sdcardio/__init__.c index 4a7a4d500cc..751e6f58127 100644 --- a/shared-module/sdcardio/__init__.c +++ b/shared-module/sdcardio/__init__.c @@ -6,8 +6,11 @@ #include "shared-module/sdcardio/__init__.h" +#include "py/obj.h" + #include "extmod/vfs_fat.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/sdcardio/SDCard.h" @@ -81,7 +84,8 @@ void automount_sd_card(void) { common_hal_busio_spi_never_reset(spi_obj); #endif sdcard.base.type = &sdcardio_SDCard_type; - mp_rom_error_text_t error = sdcardio_sdcard_construct(&sdcard, spi_obj, DEFAULT_SD_CS, 25000000, true); + mp_obj_t cs_obj = MP_OBJ_FROM_PTR(DEFAULT_SD_CS); + mp_rom_error_text_t error = sdcardio_sdcard_construct(&sdcard, spi_obj, cs_obj, 25000000, true); if (error != NULL) { // Failed to communicate with the card. _automounted = false; @@ -91,8 +95,9 @@ void automount_sd_card(void) { #endif return; } - common_hal_digitalio_digitalinout_never_reset(&sdcard.cs); - + if (mp_obj_is_type(cs_obj, &mcu_pin_type)) { + common_hal_digitalio_digitalinout_never_reset(MP_OBJ_TO_PTR(sdcard.cs)); + } fs_user_mount_t *vfs = &_sdcard_usermount; vfs->base.type = &mp_fat_vfs_type; vfs->fatfs.drv = vfs; diff --git a/shared-module/ssl/SSLSocket.c b/shared-module/ssl/SSLSocket.c index 8911fa2f454..70275945803 100644 --- a/shared-module/ssl/SSLSocket.c +++ b/shared-module/ssl/SSLSocket.c @@ -44,7 +44,7 @@ static void mbedtls_debug(void *ctx, int level, const char *file, int line, cons #define DEBUG_PRINT(...) do {} while (0) #endif -static NORETURN void mbedtls_raise_error(int err) { +static MP_NORETURN void mbedtls_raise_error(int err) { // _mbedtls_ssl_send and _mbedtls_ssl_recv (below) turn positive error codes from the // underlying socket into negative codes to pass them through mbedtls. Here we turn them // positive again so they get interpreted as the OSError they really are. The @@ -200,7 +200,7 @@ static int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) { } -#if MBEDTLS_VERSION_MAJOR >= 3 +#if MBEDTLS_VERSION_MAJOR == 3 static int urandom_adapter(void *unused, unsigned char *buf, size_t n) { int result = common_hal_os_urandom(buf, n); if (result) { @@ -238,18 +238,24 @@ ssl_sslsocket_obj_t *common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t mbedtls_x509_crt_init(&o->cacert); mbedtls_x509_crt_init(&o->cert); mbedtls_pk_init(&o->pkey); + #if MBEDTLS_VERSION_MAJOR < 4 mbedtls_ctr_drbg_init(&o->ctr_drbg); + #endif #ifdef MBEDTLS_DEBUG_C // Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose mbedtls_debug_set_threshold(4); #endif + #if MBEDTLS_VERSION_MAJOR < 4 mbedtls_entropy_init(&o->entropy); const byte seed[] = "upy"; int ret = mbedtls_ctr_drbg_seed(&o->ctr_drbg, mbedtls_entropy_func, &o->entropy, seed, sizeof(seed)); if (ret != 0) { goto cleanup; } + #else + int ret; + #endif ret = mbedtls_ssl_config_defaults(&o->conf, server_side ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, @@ -273,7 +279,9 @@ ssl_sslsocket_obj_t *common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t } else { mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE); } + #if MBEDTLS_VERSION_MAJOR < 4 mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg); + #endif #ifdef MBEDTLS_DEBUG_C mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL); #endif @@ -293,7 +301,9 @@ ssl_sslsocket_obj_t *common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t mbedtls_ssl_set_bio(&o->ssl, o, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL); if (self->cert_buf.buf != NULL) { - #if MBEDTLS_VERSION_MAJOR >= 3 + #if MBEDTLS_VERSION_MAJOR >= 4 + ret = mbedtls_pk_parse_key(&o->pkey, self->key_buf.buf, self->key_buf.len + 1, NULL, 0); + #elif MBEDTLS_VERSION_MAJOR >= 3 ret = mbedtls_pk_parse_key(&o->pkey, self->key_buf.buf, self->key_buf.len + 1, NULL, 0, urandom_adapter, NULL); #else ret = mbedtls_pk_parse_key(&o->pkey, self->key_buf.buf, self->key_buf.len + 1, NULL, 0); @@ -318,8 +328,10 @@ ssl_sslsocket_obj_t *common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t mbedtls_x509_crt_free(&o->cacert); mbedtls_ssl_free(&o->ssl); mbedtls_ssl_config_free(&o->conf); + #if MBEDTLS_VERSION_MAJOR < 4 mbedtls_ctr_drbg_free(&o->ctr_drbg); mbedtls_entropy_free(&o->entropy); + #endif if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) { mp_raise_type(&mp_type_MemoryError); @@ -382,8 +394,10 @@ void common_hal_ssl_sslsocket_close(ssl_sslsocket_obj_t *self) { mbedtls_x509_crt_free(&self->cacert); mbedtls_ssl_free(&self->ssl); mbedtls_ssl_config_free(&self->conf); + #if MBEDTLS_VERSION_MAJOR < 4 mbedtls_ctr_drbg_free(&self->ctr_drbg); mbedtls_entropy_free(&self->entropy); + #endif } static void do_handshake(ssl_sslsocket_obj_t *self) { @@ -408,8 +422,10 @@ static void do_handshake(ssl_sslsocket_obj_t *self) { mbedtls_x509_crt_free(&self->cacert); mbedtls_ssl_free(&self->ssl); mbedtls_ssl_config_free(&self->conf); + #if MBEDTLS_VERSION_MAJOR < 4 mbedtls_ctr_drbg_free(&self->ctr_drbg); mbedtls_entropy_free(&self->entropy); + #endif if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) { mp_raise_type(&mp_type_MemoryError); diff --git a/shared-module/ssl/SSLSocket.h b/shared-module/ssl/SSLSocket.h index f7f3d1ae83c..9373734d27c 100644 --- a/shared-module/ssl/SSLSocket.h +++ b/shared-module/ssl/SSLSocket.h @@ -15,15 +15,20 @@ #include "mbedtls/ssl.h" #include "mbedtls/x509_crt.h" #include "mbedtls/pk.h" +#include "mbedtls/version.h" +#if MBEDTLS_VERSION_MAJOR < 4 #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" +#endif typedef struct ssl_sslsocket_obj { mp_obj_base_t base; mp_obj_t sock_obj; ssl_sslcontext_obj_t *ssl_context; + #if MBEDTLS_VERSION_MAJOR < 4 mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; + #endif mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; diff --git a/shared-module/struct/__init__.c b/shared-module/struct/__init__.c index 715b5043021..4b6b2b589ef 100644 --- a/shared-module/struct/__init__.c +++ b/shared-module/struct/__init__.c @@ -14,7 +14,8 @@ #include "shared-bindings/struct/__init__.h" static void struct_validate_format(char fmt) { - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES + if (fmt == 'S' || fmt == 'O') { mp_raise_RuntimeError(MP_ERROR_TEXT("'S' and 'O' are not supported format types")); } diff --git a/shared-module/usb_audio/USBMicrophone.c b/shared-module/usb_audio/USBMicrophone.c new file mode 100644 index 00000000000..fd5309abeb9 --- /dev/null +++ b/shared-module/usb_audio/USBMicrophone.c @@ -0,0 +1,149 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/misc.h" +#include "py/runtime.h" + +#include "shared-bindings/usb_audio/USBMicrophone.h" +#include "shared-module/usb_audio/__init__.h" +#include "shared-module/audiocore/__init__.h" + +// Only one microphone may feed the single USB IN endpoint at a time. This points +// at the USBMicrophone whose play() was called most recently, or NULL when none +// is streaming. The USB background task pulls from it via +// usb_audio_usbmicrophone_background_fill(). +static usb_audio_usbmicrophone_obj_t *active_microphone = NULL; + +void common_hal_usb_audio_usbmicrophone_construct(usb_audio_usbmicrophone_obj_t *self) { + self->sample = MP_OBJ_NULL; + self->buffer = NULL; + self->buffer_length = 0; + self->loop = false; + self->playing = false; + self->paused = false; + self->deinited = false; + self->more_data = false; +} + +void common_hal_usb_audio_usbmicrophone_deinit(usb_audio_usbmicrophone_obj_t *self) { + common_hal_usb_audio_usbmicrophone_stop(self); + self->deinited = true; +} + +bool common_hal_usb_audio_usbmicrophone_deinited(usb_audio_usbmicrophone_obj_t *self) { + return self->deinited; +} + +void common_hal_usb_audio_usbmicrophone_play(usb_audio_usbmicrophone_obj_t *self, mp_obj_t sample, bool loop) { + // The negotiated USB format is fixed 16-bit signed LE PCM at the rate/channel + // count chosen by usb_audio.enable() in boot.py. Resampling and format + // conversion are out of scope, so the source must already match exactly. This + // mirrors how audiocore's audiosample_must_match() validates an output's input + // (and reuses its error messages), but checks against the USB format rather + // than another audiosample. + audiosample_base_t *sample_base = audiosample_check(sample); + if (audiosample_get_sample_rate(sample_base) != usb_audio_sample_rate) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_sample_rate); + } + if (audiosample_get_channel_count(sample_base) != usb_audio_channel_count) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_channel_count); + } + if (audiosample_get_bits_per_sample(sample_base) != usb_audio_bits_per_sample) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_bits_per_sample); + } + if (!sample_base->samples_signed) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness); + } + + // Start at the beginning and arm the pull loop to request the first chunk. + audiosample_reset_buffer(sample, false, 0); + self->sample = sample; + self->buffer = NULL; + self->buffer_length = 0; + self->loop = loop; + self->playing = true; + self->paused = false; + self->more_data = true; + // Take over the single USB IN endpoint from any other microphone. + active_microphone = self; +} + +void common_hal_usb_audio_usbmicrophone_stop(usb_audio_usbmicrophone_obj_t *self) { + self->sample = MP_OBJ_NULL; + self->buffer = NULL; + self->buffer_length = 0; + self->playing = false; + self->paused = false; + self->more_data = false; + if (active_microphone == self) { + active_microphone = NULL; + } +} + +bool common_hal_usb_audio_usbmicrophone_get_playing(usb_audio_usbmicrophone_obj_t *self) { + return self->playing && !self->paused; +} + +void common_hal_usb_audio_usbmicrophone_pause(usb_audio_usbmicrophone_obj_t *self) { + self->paused = true; +} + +void common_hal_usb_audio_usbmicrophone_resume(usb_audio_usbmicrophone_obj_t *self) { + self->paused = false; +} + +bool common_hal_usb_audio_usbmicrophone_get_paused(usb_audio_usbmicrophone_obj_t *self) { + return self->playing && self->paused; +} + +size_t usb_audio_usbmicrophone_background_fill(uint8_t *out, size_t max_bytes) { + usb_audio_usbmicrophone_obj_t *self = active_microphone; + if (self == NULL || !self->playing || self->paused || self->sample == MP_OBJ_NULL) { + return 0; + } + + // The negotiated USB format is 16-bit signed mono PCM. For this step the + // bound sample is assumed to already be in that format (e.g. a 16-bit signed + // mono audiocore.RawSample), so its bytes are copied straight through. + size_t filled = 0; + while (filled < max_bytes) { + if (self->buffer_length == 0) { + if (!self->more_data) { + // The previous chunk was the sample's last and we've played it + // out. Loop back to the start or stop. + if (self->loop) { + audiosample_reset_buffer(self->sample, false, 0); + self->more_data = true; + } else { + common_hal_usb_audio_usbmicrophone_stop(self); + break; + } + } + audioio_get_buffer_result_t result = + audiosample_get_buffer(self->sample, false, 0, &self->buffer, &self->buffer_length); + if (result == GET_BUFFER_ERROR) { + common_hal_usb_audio_usbmicrophone_stop(self); + break; + } + self->more_data = (result == GET_BUFFER_MORE_DATA); + if (self->buffer_length == 0) { + // No samples available right now (underrun); the caller fills the + // rest of the frame with silence and we retry next tick. + break; + } + } + + size_t n = MIN(self->buffer_length, max_bytes - filled); + memcpy(out + filled, self->buffer, n); + self->buffer += n; + self->buffer_length -= n; + filled += n; + } + + return filled; +} diff --git a/shared-module/usb_audio/USBMicrophone.h b/shared-module/usb_audio/USBMicrophone.h new file mode 100644 index 00000000000..74f167e8e43 --- /dev/null +++ b/shared-module/usb_audio/USBMicrophone.h @@ -0,0 +1,33 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +typedef struct usb_audio_usbmicrophone_obj { + mp_obj_base_t base; + // The audiosample currently bound for streaming, or MP_OBJ_NULL. + mp_obj_t sample; + // Cursor into the chunk last returned by audiosample_get_buffer(): the next + // unread byte and the number of bytes still unread in that chunk. + uint8_t *buffer; + uint32_t buffer_length; + bool loop; + bool playing; + bool paused; + bool deinited; + // False once audiosample_get_buffer() reported GET_BUFFER_DONE for the + // current chunk; the chunk is still played out, then we loop or stop. + bool more_data; +} usb_audio_usbmicrophone_obj_t; + +// Pull up to max_bytes of audio (in the negotiated USB PCM format) from whichever +// USBMicrophone is currently playing, writing it into out. Returns the number of +// bytes written, which is < max_bytes (possibly 0) when nothing is streaming or +// the source underruns; the caller pads the remainder with silence. Called from +// the USB background task in shared-module/usb_audio/__init__.c. +size_t usb_audio_usbmicrophone_background_fill(uint8_t *out, size_t max_bytes); diff --git a/shared-module/usb_audio/USBSpeaker.c b/shared-module/usb_audio/USBSpeaker.c new file mode 100644 index 00000000000..12921430bc3 --- /dev/null +++ b/shared-module/usb_audio/USBSpeaker.c @@ -0,0 +1,227 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/misc.h" + +#include "shared-bindings/usb_audio/USBSpeaker.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-module/usb_audio/__init__.h" + +#include "tusb.h" + +// The ring is sized independently of the TinyUSB headers (see USBSpeaker.h); +// check it still matches the OUT endpoint's software FIFO so the push side can be +// reasoned about against the USB plumbing. +MP_STATIC_ASSERT(USB_AUDIO_SPEAKER_RING_SIZE == CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ); + +// Only one speaker can be fed by the single USB OUT endpoint at a time. This +// points at the most recently constructed USBSpeaker, or NULL when none exists, +// mirroring active_microphone in USBMicrophone.c. The USB background task pushes +// received bytes into it via usb_audio_usbspeaker_background_drain(). +static usb_audio_usbspeaker_obj_t *active_speaker = NULL; + +void common_hal_usb_audio_usbspeaker_construct(usb_audio_usbspeaker_obj_t *self) { + // The pipeline treats the speaker as an ordinary audiosample source, so + // populate base from the format negotiated by usb_audio.enable(). The UAC2 + // format we present is 16-bit signed LE PCM, which is exactly what the + // CircuitPython audio pipeline carries, so no conversion is needed. + self->base.sample_rate = usb_audio_sample_rate; + self->base.bits_per_sample = usb_audio_bits_per_sample; + self->base.channel_count = usb_audio_channel_count; + self->base.samples_signed = true; + self->base.single_buffer = false; + self->base.max_buffer_length = USB_AUDIO_SPEAKER_OUTPUT_BUFFER_SIZE; + + self->ring_head = 0; + self->ring_tail = 0; + self->ring_count = 0; + self->output_index = 0; + + // The most recently created speaker receives the host's OUT stream. + active_speaker = self; +} + +void common_hal_usb_audio_usbspeaker_deinit(usb_audio_usbspeaker_obj_t *self) { + // Stop directing USB OUT data at this object. The producer (drain) and this + // deinit both run in non-interrupt context, so the pointer swap needs no + // interrupt guard. + if (active_speaker == self) { + active_speaker = NULL; + } + audiosample_mark_deinit(&self->base); +} + +bool common_hal_usb_audio_usbspeaker_deinited(usb_audio_usbspeaker_obj_t *self) { + return audiosample_deinited(&self->base); +} + +bool common_hal_usb_audio_usbspeaker_get_connected(usb_audio_usbspeaker_obj_t *self) { + (void)self; + // True while the host has opened the OUT streaming interface, i.e. it is + // actively sending audio. Speaker-specific so it stays correct when a mic + // shares the same headset function. + return usb_audio_speaker_streaming(); +} + +// --------------------------------------------------------------------+ +// Receive ring (push side, producer = USB background task) +// --------------------------------------------------------------------+ +// +// The ring decouples the two independently clocked stages from +// usb_audio_output_plan.md: USB push (paced by the host's SOF clock, in the +// background task) and the audiosample pull (paced by the output backend's +// sample clock, in its refill interrupt). It is a single-producer/ +// single-consumer ring across an interrupt boundary: +// +// * Producer: usb_audio_usbspeaker_background_drain(), task context. +// * Consumer: usb_audio_usbspeaker_get_buffer(), output DMA/refill ISR. +// +// The consumer is an interrupt, so it can never be preempted by the producer and +// needs no guard of its own. The producer can be preempted by the consumer, and +// its drop-oldest overrun handling touches both cursors, so it does its whole +// read-modify-write with interrupts disabled. + +void usb_audio_usbspeaker_streaming_reset(void) { + usb_audio_usbspeaker_obj_t *self = active_speaker; + if (self == NULL) { + return; + } + common_hal_mcu_disable_interrupts(); + self->ring_head = 0; + self->ring_tail = 0; + self->ring_count = 0; + common_hal_mcu_enable_interrupts(); +} + +void usb_audio_usbspeaker_background_drain(const uint8_t *in, size_t n) { + usb_audio_usbspeaker_obj_t *self = active_speaker; + if (self == NULL || n == 0) { + return; + } + if (n >= USB_AUDIO_SPEAKER_RING_SIZE) { + // A single chunk larger than the whole ring can only contribute its + // newest tail. (Cannot happen with USB packets << ring size, but keep + // the copies provably in-bounds.) + in += n - USB_AUDIO_SPEAKER_RING_SIZE; + n = USB_AUDIO_SPEAKER_RING_SIZE; + } + + common_hal_mcu_disable_interrupts(); + + size_t free_space = USB_AUDIO_SPEAKER_RING_SIZE - self->ring_count; + if (n > free_space) { + // Overrun: advance the read cursor past the oldest bytes we're about to + // overwrite, keeping latency bounded and following the newest host audio. + size_t drop = n - free_space; + self->ring_tail = (self->ring_tail + drop) % USB_AUDIO_SPEAKER_RING_SIZE; + self->ring_count -= drop; + } + + // Copy in one or two segments, wrapping at the end of the ring. + size_t first = MIN(n, USB_AUDIO_SPEAKER_RING_SIZE - self->ring_head); + memcpy(&self->ring[self->ring_head], in, first); + if (n > first) { + memcpy(&self->ring[0], in + first, n - first); + } + self->ring_head = (self->ring_head + n) % USB_AUDIO_SPEAKER_RING_SIZE; + self->ring_count += n; + + common_hal_mcu_enable_interrupts(); +} + +uint32_t common_hal_usb_audio_usbspeaker_read(usb_audio_usbspeaker_obj_t *self, + void *buffer, uint32_t length) { + // Hand the most recent host audio to Python so it can be analysed (e.g. an + // audio-reactive effect or VU meter). This drains the ring just like the + // output backend's get_buffer() does, so it is an alternative *consumer*: + // a USBSpeaker being read this way must not also be play()ed to an output + // backend at the same time, or the two consumers would race on the single + // SPSC ring. + // + // Unlike get_buffer() (which runs in the output refill ISR and so needs no + // guard) this runs in VM/task context and can be preempted by the USB + // producer, so it brackets its read-modify-write with interrupts disabled, + // mirroring usb_audio_usbspeaker_background_drain(). + size_t bytes_per_frame = (self->base.bits_per_sample / 8) * self->base.channel_count; + size_t want = (size_t)length * bytes_per_frame; + + common_hal_mcu_disable_interrupts(); + size_t to_copy = MIN(self->ring_count, want); + // Never split a frame across calls (the ring always holds whole UAC2 frames, + // but stay defensive so the returned count is always a whole number). + to_copy -= to_copy % bytes_per_frame; + + size_t first = MIN(to_copy, USB_AUDIO_SPEAKER_RING_SIZE - self->ring_tail); + memcpy(buffer, &self->ring[self->ring_tail], first); + if (to_copy > first) { + memcpy((uint8_t *)buffer + first, &self->ring[0], to_copy - first); + } + self->ring_tail = (self->ring_tail + to_copy) % USB_AUDIO_SPEAKER_RING_SIZE; + self->ring_count -= to_copy; + common_hal_mcu_enable_interrupts(); + + return to_copy / bytes_per_frame; +} + +// --------------------------------------------------------------------+ +// audiosample protocol (pull side, consumer = output backend) +// --------------------------------------------------------------------+ + +void usb_audio_usbspeaker_reset_buffer(usb_audio_usbspeaker_obj_t *self, + bool single_channel_output, uint8_t channel) { + (void)single_channel_output; + (void)channel; + // Begin playback from live audio rather than whatever was buffered before: + // drop the ring and restart the double-buffer. Guarded because some ports may + // call reset_buffer outside the initial setup. + common_hal_mcu_disable_interrupts(); + self->ring_head = 0; + self->ring_tail = 0; + self->ring_count = 0; + common_hal_mcu_enable_interrupts(); + self->output_index = 0; +} + +audioio_get_buffer_result_t usb_audio_usbspeaker_get_buffer(usb_audio_usbspeaker_obj_t *self, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) { + + uint32_t half = self->base.max_buffer_length / 2; + uint8_t *out = self->output_buffer + half * self->output_index; + self->output_index = 1 - self->output_index; + + // Consumer side of the SPSC ring (runs in the output backend's refill ISR). + // It is never preempted by the producer, so no interrupt guard is required. + size_t to_copy = MIN(self->ring_count, (size_t)half); + + size_t first = MIN(to_copy, USB_AUDIO_SPEAKER_RING_SIZE - self->ring_tail); + memcpy(out, &self->ring[self->ring_tail], first); + if (to_copy > first) { + memcpy(out + first, &self->ring[0], to_copy - first); + } + self->ring_tail = (self->ring_tail + to_copy) % USB_AUDIO_SPEAKER_RING_SIZE; + self->ring_count -= to_copy; + + if (to_copy < half) { + // Underrun: pad the remainder with silence. Samples are signed, so + // silence is 0. This is the consume-side of the pacing failure mode + // tracked in the usb-audio-artifact-pacing memory: we never spin. + memset(out + to_copy, 0, half - to_copy); + } + + // Mono only for v1, so the single-channel offset is always 0; computed the + // same way as audiocore.RawSample so stereo (interleaved ring) can extend it. + if (single_channel_output) { + out += (channel % self->base.channel_count) * (self->base.bits_per_sample / 8); + } + + *buffer = out; + *buffer_length = half; + // A live USB stream is infinite; never report DONE or the backend would stop. + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/usb_audio/USBSpeaker.h b/shared-module/usb_audio/USBSpeaker.h new file mode 100644 index 00000000000..8c06cff519d --- /dev/null +++ b/shared-module/usb_audio/USBSpeaker.h @@ -0,0 +1,73 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-module/usb_audio/usb_audio_descriptors.h" + +// One half-buffer of the audiosample double-buffer holds this many frames. The +// output backend pulls a half each get_buffer() call, so this sets the pull +// granularity and the silence-pad chunk on underrun. It is deliberately +// independent of the USB OUT software FIFO (the ring below) so the push and pull +// stages can be tuned separately, and small enough that two halves sit +// comfortably inside the ring. +#define USB_AUDIO_SPEAKER_FRAMES_PER_BUFFER (128) + +// Bytes per audio frame in the negotiated UAC2 format (mono 16-bit for v1). +#define USB_AUDIO_SPEAKER_BYTES_PER_FRAME (USB_AUDIO_N_BYTES_PER_SAMPLE * USB_AUDIO_N_CHANNELS) + +// Full owned double-buffer: two halves of FRAMES_PER_BUFFER frames each. Matches +// audiocore.RawSample's convention where base.max_buffer_length is the whole +// buffer and get_buffer() returns half of it. +#define USB_AUDIO_SPEAKER_OUTPUT_BUFFER_SIZE (2 * USB_AUDIO_SPEAKER_FRAMES_PER_BUFFER * USB_AUDIO_SPEAKER_BYTES_PER_FRAME) + +// Host -> board receive ring size. Mirrors CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ +// (16 * the full-speed OUT wMaxPacketSize) but is spelled out from the format +// constants so this struct definition stays free of the TinyUSB headers. A +// MP_STATIC_ASSERT in USBSpeaker.c checks the two stay equal. +#define USB_AUDIO_SPEAKER_OUT_PACKET_SIZE ((USB_AUDIO_MAX_SAMPLE_RATE / 1000 + 1) * USB_AUDIO_SPEAKER_BYTES_PER_FRAME) +#define USB_AUDIO_SPEAKER_RING_SIZE (16 * USB_AUDIO_SPEAKER_OUT_PACKET_SIZE) + +typedef struct usb_audio_usbspeaker_obj { + // First member so the object can be used directly as an audiosample source. + audiosample_base_t base; + + // Host -> board receive ring (the "push" stage). Filled by the USB + // background task via usb_audio_usbspeaker_background_drain() and drained by + // get_buffer(). Single producer (task), single consumer (output DMA ISR); + // see the concurrency notes in USBSpeaker.c. + uint8_t ring[USB_AUDIO_SPEAKER_RING_SIZE]; + size_t ring_head; // next write offset + size_t ring_tail; // next read offset + size_t ring_count; // valid bytes currently in the ring + + // Owned double-buffer returned to the output backend by get_buffer(). + uint8_t output_buffer[USB_AUDIO_SPEAKER_OUTPUT_BUFFER_SIZE]; + uint8_t output_index; // 0 or 1: which half get_buffer() fills next +} usb_audio_usbspeaker_obj_t; + +// audiosample protocol implementation. Not exposed to Python because get_buffer() +// runs in the output backend's refill interrupt. +void usb_audio_usbspeaker_reset_buffer(usb_audio_usbspeaker_obj_t *self, + bool single_channel_output, uint8_t channel); +audioio_get_buffer_result_t usb_audio_usbspeaker_get_buffer(usb_audio_usbspeaker_obj_t *self, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); + +// Push n bytes received on the USB OUT endpoint into the active speaker's ring. +// Called from the USB background task (see usb_audio_task()). No-op when no +// speaker is active. Overrun policy: drop the oldest buffered bytes. +void usb_audio_usbspeaker_background_drain(const uint8_t *in, size_t n); + +// Drop anything buffered in the active speaker's ring so a (re)opened stream +// starts from live audio. Called when the host opens/closes the OUT streaming +// interface. +void usb_audio_usbspeaker_streaming_reset(void); diff --git a/shared-module/usb_audio/__init__.c b/shared-module/usb_audio/__init__.c new file mode 100644 index 00000000000..5964b8acf78 --- /dev/null +++ b/shared-module/usb_audio/__init__.c @@ -0,0 +1,623 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/usb_audio/__init__.h" +#include "shared-bindings/usb_audio/USBMicrophone.h" +#include "shared-bindings/usb_audio/USBSpeaker.h" +#include "shared-module/usb_audio/__init__.h" +#include "shared-module/usb_audio/USBMicrophone.h" +#include "shared-module/usb_audio/USBSpeaker.h" +#include "shared-module/usb_audio/usb_audio_descriptors.h" + +#include + +#include "py/misc.h" +#include "py/mphal.h" +#include "py/runtime.h" +#include "supervisor/shared/tick.h" +#include "tusb.h" + +static bool usb_audio_is_enabled = false; + +// The host opens each AudioStreaming interface independently (alt 0 = idle, alt 1 +// = streaming), so the two directions of a headset are tracked separately. For +// the single-direction microphone/speaker only the matching flag is ever set. +static bool usb_audio_mic_streaming = false; +static bool usb_audio_spk_streaming = false; + +// AudioStreaming interface numbers assigned when the descriptor is built, used to +// route the host's set-interface requests to the right direction. 0xff until a +// descriptor that includes that direction has been emitted. +static uint8_t usb_audio_mic_as_itf = 0xff; +static uint8_t usb_audio_spk_as_itf = 0xff; + +uint32_t usb_audio_sample_rate; +uint8_t usb_audio_channel_count; +uint8_t usb_audio_bits_per_sample; +bool usb_audio_microphone_enabled; +bool usb_audio_speaker_enabled; + +// Audio control state surfaced to the host. One extra entry for the master channel 0. +static int8_t usb_audio_mute[USB_AUDIO_N_CHANNELS + 1]; +static int16_t usb_audio_volume[USB_AUDIO_N_CHANNELS + 1]; + +bool shared_module_usb_audio_enable(mp_int_t sample_rate, mp_int_t channel_count, mp_int_t bits_per_sample, bool microphone, bool speaker) { + if (tud_connected()) { + return false; + } + + usb_audio_sample_rate = sample_rate; + usb_audio_channel_count = channel_count; + usb_audio_bits_per_sample = bits_per_sample; + usb_audio_microphone_enabled = microphone; + usb_audio_speaker_enabled = speaker; + usb_audio_is_enabled = true; + + return true; +} + +bool shared_module_usb_audio_disable(void) { + if (tud_connected()) { + return false; + } + usb_audio_is_enabled = false; + return true; +} + +bool usb_audio_enabled(void) { + return usb_audio_is_enabled; +} + +bool usb_audio_streaming(void) { + return usb_audio_mic_streaming || usb_audio_spk_streaming; +} + +// True while the host has the speaker (OUT) stream open, i.e. it is actively +// sending audio. Used by USBSpeaker.connected so it reflects the speaker +// direction specifically even when a mic shares the same headset function. +bool usb_audio_speaker_streaming(void) { + return usb_audio_spk_streaming; +} + +void usb_audio_setup_singletons(void) { + // USBMicrophone and USBSpeaker are singletons rather than constructible + // classes (like usb_midi.ports). The host-facing format and direction are + // fixed by usb_audio.enable() in boot.py and persist in C globals, but the + // instances themselves live on the GC heap, which is reset between boot.py + // and code.py, so they are rebuilt here once per VM. Each is created only + // when its direction was enabled; otherwise it is left as None. + // + // The objects are held in MP_STATE_VM root pointers so the GC keeps them + // alive for the whole VM (the module globals table is static data and is not + // a GC root, so a reference from there alone would be swept). Rooting the + // microphone also traces its bound audiosample (self->sample). They are then + // installed in the module globals so they are reachable as the + // usb_audio.usb_microphone / usb_audio.usb_speaker attributes. + mp_obj_t microphone = mp_const_none; + mp_obj_t speaker = mp_const_none; + + if (usb_audio_is_enabled) { + const bool has_input = usb_audio_microphone_enabled; + const bool has_output = usb_audio_speaker_enabled; + + if (has_input) { + usb_audio_usbmicrophone_obj_t *self = + mp_obj_malloc_with_finaliser(usb_audio_usbmicrophone_obj_t, &usb_audio_USBMicrophone_type); + common_hal_usb_audio_usbmicrophone_construct(self); + microphone = MP_OBJ_FROM_PTR(self); + } + if (has_output) { + usb_audio_usbspeaker_obj_t *self = + mp_obj_malloc_with_finaliser(usb_audio_usbspeaker_obj_t, &usb_audio_USBSpeaker_type); + common_hal_usb_audio_usbspeaker_construct(self); + speaker = MP_OBJ_FROM_PTR(self); + } + } + + MP_STATE_VM(usb_audio_microphone_singleton) = microphone; + MP_STATE_VM(usb_audio_speaker_singleton) = speaker; + + mp_map_lookup(&usb_audio_module_globals.map, MP_ROM_QSTR(MP_QSTR_usb_microphone), MP_MAP_LOOKUP)->value = + microphone; + mp_map_lookup(&usb_audio_module_globals.map, MP_ROM_QSTR(MP_QSTR_usb_speaker), MP_MAP_LOOKUP)->value = + speaker; +} + +// Hand-rolled UAC2 mono speaker (host -> board) descriptor WITHOUT an async +// feedback endpoint. This mirrors TinyUSB's TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR +// (lib/tinyusb/src/device/usbd.h) but drops the trailing feedback endpoint, so +// the streaming alt-setting declares a single OUT endpoint (_nEPs = 0x01). The +// entity IDs match the mic descriptor (see usb_audio_descriptors.h); only the +// terminal roles reverse: the input terminal is the USB-streaming side and the +// output terminal is the desktop speaker, and the AS interface links the input +// terminal (0x01). Async feedback for true clock matching is a later step. +#define USB_AUDIO_SPEAKER_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize) \ + /* Standard Interface Association Descriptor (IAD) */ \ + TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00), \ + /* Standard AC Interface Descriptor(4.7.1) */ \ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx), \ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */ \ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN + TUD_AUDIO_DESC_INPUT_TERM_LEN + TUD_AUDIO_DESC_OUTPUT_TERM_LEN + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS), \ + /* Clock Source Descriptor(4.7.2.1) */ \ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ USB_AUDIO_ENTITY_CLOCK_SOURCE, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ USB_AUDIO_ENTITY_INPUT_TERMINAL, /*_stridx*/ 0x00), \ + /* Input Terminal Descriptor(4.7.2.4) -- USB streaming in from the host */ \ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ USB_AUDIO_ENTITY_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ USB_AUDIO_ENTITY_CLOCK_SOURCE, /*_nchannelslogical*/ USB_AUDIO_N_CHANNELS, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00), \ + /* Output Terminal Descriptor(4.7.2.5) -- desktop speaker */ \ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ USB_AUDIO_ENTITY_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ USB_AUDIO_ENTITY_INPUT_TERMINAL, /*_srcid*/ USB_AUDIO_ENTITY_FEATURE_UNIT, /*_clkid*/ USB_AUDIO_ENTITY_CLOCK_SOURCE, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00), \ + /* Feature Unit Descriptor(4.7.2.8) */ \ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ USB_AUDIO_ENTITY_FEATURE_UNIT, /*_srcid*/ USB_AUDIO_ENTITY_INPUT_TERMINAL, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00), \ + /* Standard AS Interface Descriptor(4.9.1) -- alt 0, zero bandwidth */ \ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00), \ + /* Standard AS Interface Descriptor(4.9.1) -- alt 1, one OUT endpoint */ \ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00), \ + /* Class-Specific AS Interface Descriptor(4.9.2) -- linked to the input terminal */ \ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ USB_AUDIO_ENTITY_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ USB_AUDIO_N_CHANNELS, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00), \ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ \ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample), \ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ \ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t)((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01), \ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ \ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + +// Hand-rolled UAC2 mono headset (microphone + speaker both enabled): one audio function +// presenting both a speaker (host -> board OUT) and a microphone (board -> host +// IN) at once. This combines USB_AUDIO_SPEAKER_DESCRIPTOR's speaker chain with +// TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR's mic chain under a single IAD. The two chains +// must use distinct entity IDs (USB_AUDIO_HS_ENTITY_*; see usb_audio_descriptors.h) +// because they live in the same AudioControl interface, and they share one clock +// source. The function spans three interfaces: AudioControl (_itfnum), the +// speaker AudioStreaming interface (_itfnum + 1, OUT endpoint), and the mic +// AudioStreaming interface (_itfnum + 2, IN endpoint). Neither stream has an +// async feedback endpoint, matching the single-direction descriptors. +#define USB_AUDIO_HEADSET_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epin, _epsize) \ + /* Standard Interface Association Descriptor (IAD) -- 3 interfaces */ \ + TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x03, /*_stridx*/ 0x00), \ + /* Standard AC Interface Descriptor(4.7.1) */ \ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx), \ + /* Class-Specific AC Interface Header Descriptor(4.7.2) -- clock + both chains */ \ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN + 2 * (TUD_AUDIO_DESC_INPUT_TERM_LEN + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN + TUD_AUDIO_DESC_OUTPUT_TERM_LEN), /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS), \ + /* Clock Source Descriptor(4.7.2.1) -- shared by both chains */ \ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ USB_AUDIO_HS_ENTITY_CLOCK_SOURCE, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ + /* --- Speaker chain (host -> board) --- */ \ + /* Input Terminal Descriptor(4.7.2.4) -- USB streaming in from the host */ \ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ USB_AUDIO_HS_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ USB_AUDIO_HS_ENTITY_CLOCK_SOURCE, /*_nchannelslogical*/ USB_AUDIO_N_CHANNELS, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00), \ + /* Feature Unit Descriptor(4.7.2.8) */ \ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ USB_AUDIO_HS_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ USB_AUDIO_HS_ENTITY_SPK_INPUT_TERMINAL, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00), \ + /* Output Terminal Descriptor(4.7.2.5) -- desktop speaker */ \ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ USB_AUDIO_HS_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x00, /*_srcid*/ USB_AUDIO_HS_ENTITY_SPK_FEATURE_UNIT, /*_clkid*/ USB_AUDIO_HS_ENTITY_CLOCK_SOURCE, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00), \ + /* --- Mic chain (board -> host) --- */ \ + /* Input Terminal Descriptor(4.7.2.4) -- generic microphone */ \ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ USB_AUDIO_HS_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ USB_AUDIO_HS_ENTITY_CLOCK_SOURCE, /*_nchannelslogical*/ USB_AUDIO_N_CHANNELS, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00), \ + /* Feature Unit Descriptor(4.7.2.8) */ \ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ USB_AUDIO_HS_ENTITY_MIC_FEATURE_UNIT, /*_srcid*/ USB_AUDIO_HS_ENTITY_MIC_INPUT_TERMINAL, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00), \ + /* Output Terminal Descriptor(4.7.2.5) -- USB streaming out to the host */ \ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ USB_AUDIO_HS_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_srcid*/ USB_AUDIO_HS_ENTITY_MIC_FEATURE_UNIT, /*_clkid*/ USB_AUDIO_HS_ENTITY_CLOCK_SOURCE, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00), \ + /* --- Speaker AudioStreaming interface (_itfnum + 1) --- */ \ + /* Standard AS Interface Descriptor(4.9.1) -- alt 0, zero bandwidth */ \ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00), \ + /* Standard AS Interface Descriptor(4.9.1) -- alt 1, one OUT endpoint */ \ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00), \ + /* Class-Specific AS Interface Descriptor(4.9.2) -- linked to the speaker input terminal */ \ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ USB_AUDIO_HS_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ USB_AUDIO_N_CHANNELS, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00), \ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ \ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample), \ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ \ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t)((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01), \ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ \ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000), \ + /* --- Mic AudioStreaming interface (_itfnum + 2) --- */ \ + /* Standard AS Interface Descriptor(4.9.1) -- alt 0, zero bandwidth */ \ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 2), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00), \ + /* Standard AS Interface Descriptor(4.9.1) -- alt 1, one IN endpoint */ \ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 2), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00), \ + /* Class-Specific AS Interface Descriptor(4.9.2) -- linked to the mic output terminal */ \ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ USB_AUDIO_HS_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ USB_AUDIO_N_CHANNELS, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00), \ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ \ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample), \ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ \ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t)((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01), \ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ \ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + +// Combined headset: both a microphone (board -> host IN) and a speaker +// (host -> board OUT) under one audio function. +static bool usb_audio_direction_is_input_output(void) { + return usb_audio_microphone_enabled && usb_audio_speaker_enabled; +} + +// Speaker only (host -> board OUT), no microphone. +static bool usb_audio_direction_is_output(void) { + return usb_audio_speaker_enabled && !usb_audio_microphone_enabled; +} + +size_t usb_audio_descriptor_length(void) { + if (usb_audio_direction_is_input_output()) { + return USB_AUDIO_HEADSET_DESC_LEN; + } + if (usb_audio_direction_is_output()) { + return USB_AUDIO_SPEAKER_DESC_LEN; + } + return TUD_AUDIO_MIC_ONE_CH_DESC_LEN; +} + +size_t usb_audio_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string) { + // Pick the isochronous endpoint number. By default it follows the same + // sequential allocation as every other interface. On ports that pin ISO to a + // fixed, dedicated endpoint (USB_AUDIO_ISO_EP_NUM != 0; see the header for the + // nRF52 case), we use that number instead and leave the sequential counters + // untouched: the dedicated ISO endpoint is a separate hardware resource, so + // it must not consume one of the regular endpoint numbers the other + // interfaces draw from. + const bool forced_iso_ep = (USB_AUDIO_ISO_EP_NUM != 0); + const uint8_t iso_ep_num = forced_iso_ep ? USB_AUDIO_ISO_EP_NUM : descriptor_counts->current_endpoint; + + if (usb_audio_direction_is_input_output()) { + // Combined headset: a speaker AudioStreaming interface (OUT) and a mic + // AudioStreaming interface (IN) under one AudioControl interface. This + // needs two isochronous endpoints, so it cannot be served by ports that + // pin ISO to a single dedicated endpoint number (forced_iso_ep, e.g. + // nRF52, which has only one ISO-capable endpoint). On those ports the + // sequential numbers below will not match the hardware's required ISO + // endpoint and the stream will not open; INPUT_OUTPUT is effectively + // unsupported there. The sequential-allocation ports (e.g. RP2) take a + // distinct number for each direction. + const uint8_t ep_out = descriptor_counts->current_endpoint; + const uint8_t ep_in = descriptor_counts->current_endpoint + 1; + + usb_add_interface_string(*current_interface_string, "CircuitPython Headset"); + const uint8_t usb_audio_descriptor[] = { + USB_AUDIO_HEADSET_DESCRIPTOR( + /*_itfnum*/ descriptor_counts->current_interface, + /*_stridx*/ *current_interface_string, + /*_nBytesPerSample*/ USB_AUDIO_N_BYTES_PER_SAMPLE, + /*_nBitsUsedPerSample*/ USB_AUDIO_BITS_PER_SAMPLE, + /*_epout*/ ep_out, + /*_epin*/ ep_in | 0x80, + /*_epsize*/ CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX) + }; + + // Speaker AS is the first interface after AudioControl, mic AS the second. + usb_audio_spk_as_itf = descriptor_counts->current_interface + 1; + usb_audio_mic_as_itf = descriptor_counts->current_interface + 2; + + (*current_interface_string)++; + // One IAD wrapping an AudioControl + two AudioStreaming interfaces, plus + // one OUT and one IN endpoint. + descriptor_counts->current_interface += 3; + descriptor_counts->num_out_endpoints++; + descriptor_counts->num_in_endpoints++; + descriptor_counts->current_endpoint += 2; + + memcpy(descriptor_buf, usb_audio_descriptor, sizeof(usb_audio_descriptor)); + + return sizeof(usb_audio_descriptor); + } + + if (usb_audio_direction_is_output()) { + usb_add_interface_string(*current_interface_string, "CircuitPython Speaker"); + const uint8_t usb_audio_descriptor[] = { + USB_AUDIO_SPEAKER_DESCRIPTOR( + /*_itfnum*/ descriptor_counts->current_interface, + /*_stridx*/ *current_interface_string, + /*_nBytesPerSample*/ USB_AUDIO_N_BYTES_PER_SAMPLE, + /*_nBitsUsedPerSample*/ USB_AUDIO_BITS_PER_SAMPLE, + /*_epout*/ iso_ep_num, + /*_epsize*/ CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX) + }; + + // The AudioStreaming interface follows the AudioControl interface. + usb_audio_spk_as_itf = descriptor_counts->current_interface + 1; + + (*current_interface_string)++; + // One IAD wrapping an AudioControl + an AudioStreaming interface, plus one OUT endpoint. + descriptor_counts->current_interface += 2; + if (!forced_iso_ep) { + descriptor_counts->num_out_endpoints++; + descriptor_counts->current_endpoint++; + } + + memcpy(descriptor_buf, usb_audio_descriptor, sizeof(usb_audio_descriptor)); + + return sizeof(usb_audio_descriptor); + } + + usb_add_interface_string(*current_interface_string, "CircuitPython Microphone"); + const uint8_t usb_audio_descriptor[] = { + TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR( + /*_itfnum*/ descriptor_counts->current_interface, + /*_stridx*/ *current_interface_string, + /*_nBytesPerSample*/ USB_AUDIO_N_BYTES_PER_SAMPLE, + /*_nBitsUsedPerSample*/ USB_AUDIO_BITS_PER_SAMPLE, + /*_epin*/ iso_ep_num | 0x80, + /*_epsize*/ CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX) + }; + + // The AudioStreaming interface follows the AudioControl interface. + usb_audio_mic_as_itf = descriptor_counts->current_interface + 1; + + (*current_interface_string)++; + // One IAD wrapping an AudioControl + an AudioStreaming interface, plus one IN endpoint. + descriptor_counts->current_interface += 2; + if (!forced_iso_ep) { + descriptor_counts->num_in_endpoints++; + descriptor_counts->current_endpoint++; + } + + memcpy(descriptor_buf, usb_audio_descriptor, sizeof(usb_audio_descriptor)); + + return sizeof(usb_audio_descriptor); +} + +// --------------------------------------------------------------------+ +// Speaker (host -> board) receive task +// --------------------------------------------------------------------+ + +// Drain everything the host has delivered to the OUT endpoint since the last +// pass into the active USBSpeaker's ring. TinyUSB's weak rx-done handler has +// already moved the isochronous data into ep_out_ff; we copy it out here, in +// task (non-ISR) context, matching the project's "defer ISR work" rule. The ring +// itself, and the overrun/underrun handling, live in USBSpeaker.c so the data +// sits in the audiosample source the output backend pulls from. +static void usb_audio_speaker_task(void) { + // One USB packet of scratch; we loop until ep_out_ff is empty. + static uint8_t chunk[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; + + while (tud_audio_available() > 0) { + uint16_t got = tud_audio_read(chunk, sizeof(chunk)); + if (got == 0) { + break; + } + // tud_audio_read() never returns more than the buffer it was given, but + // clamp so the compiler can prove the drain copies stay within chunk[] + // once this loop is inlined into it. + if (got > sizeof(chunk)) { + got = sizeof(chunk); + } + usb_audio_usbspeaker_background_drain(chunk, got); + } +} + +// --------------------------------------------------------------------+ +// Microphone (board -> host) transmit task +// --------------------------------------------------------------------+ + +static void usb_audio_microphone_task(void) { + // Pace production by the IN FIFO level. Each pass we top the software FIFO + // back up to its half-full setpoint, generating only the samples the host has + // actually drained since the last pass. This limits our production rate to the + // host's true consumption rate (its USB SOF / audio clock), keeps the FIFO + // around the level TinyUSB's flow control targets so it can send steady + // nominal-size packets, and automatically catches up after any scheduling gap + // (GCpause, other background work) in a single pass instead of underrunning. + // Underruns here showed up to the host as discrete sample-drop/insert splices, + // i.e. the erratic ticking on a held tone. + tu_fifo_t *ep_in_ff = tud_audio_get_ep_in_ff(); + uint16_t const target = tu_fifo_depth(ep_in_ff) / 2; + + // One scratch chunk (1 ms at the max rate); we loop until the FIFO reaches + // the setpoint. Sized for the highest rate enable() accepts. + static int16_t samples[USB_AUDIO_MAX_SAMPLE_RATE / 1000 * USB_AUDIO_N_CHANNELS]; + + uint16_t count; + while ((count = tu_fifo_count(ep_in_ff)) < target) { + size_t want = target - count; + if (want > sizeof(samples)) { + want = sizeof(samples); + } + + // Pull the next chunk from whichever USBMicrophone is playing. + bool underran = false; + size_t filled = usb_audio_usbmicrophone_background_fill((uint8_t *)samples, want); + if (filled == 0) { + // No source attached, paused, or fully drained: keep the endpoint + // alive with silence so the host never sees a starved stream. + memset((uint8_t *)samples, 0, want); + } else if (filled < want) { + // The source momentarily underran. Send just what it produced and + // let the FIFO cushion ride until it catches up next pass, rather + // than flooding the stream with a burst of silence. + want = filled; + underran = true; + } + + if (tud_audio_write((uint8_t *)samples, (uint16_t)want) == 0) { + break; // FIFO unexpectedly full / host not ready + } + if (underran) { + break; + } + } +} + +void usb_audio_task(void) { + // Each direction is gated on the host having opened its AudioStreaming + // interface. For a headset both run in the same pass: drain the host's + // speaker audio and refill the mic stream independently. The single-direction + // modes simply never have the other flag set. + if (usb_audio_spk_streaming) { + usb_audio_speaker_task(); + } + if (usb_audio_mic_streaming) { + usb_audio_microphone_task(); + } +} + +// --------------------------------------------------------------------+ +// TinyUSB audio class callbacks (weak symbols overridden here) +// --------------------------------------------------------------------+ + +// Host opened/closed the AudioStreaming alternate setting. The host selects each +// direction's interface independently (a headset has two), so route by interface +// number to the matching streaming flag rather than assuming a single stream. +bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void)rhport; + uint8_t const itf = (uint8_t)tu_u16_low(p_request->wIndex); + bool const streaming = (tu_u16_low(p_request->wValue) != 0); + + if (itf == usb_audio_spk_as_itf) { + usb_audio_spk_streaming = streaming; + // Start each speaker streaming session from live audio: drop anything + // left in the OUT FIFO/ring from a previous session. + tud_audio_clear_ep_out_ff(); + usb_audio_usbspeaker_streaming_reset(); + } else if (itf == usb_audio_mic_as_itf) { + usb_audio_mic_streaming = streaming; + } + return true; +} + +bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void)rhport; + uint8_t const itf = (uint8_t)tu_u16_low(p_request->wIndex); + + if (itf == usb_audio_spk_as_itf) { + usb_audio_spk_streaming = false; + tud_audio_clear_ep_out_ff(); + usb_audio_usbspeaker_streaming_reset(); + } else if (itf == usb_audio_mic_as_itf) { + usb_audio_mic_streaming = false; + } + return true; +} + +// Class-specific SET requests for an entity (we accept mute/volume on the feature unit). +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { + (void)rhport; + + uint8_t const channelNum = (uint8_t)tu_u16_low(p_request->wValue); + uint8_t const ctrlSel = (uint8_t)tu_u16_high(p_request->wValue); + uint8_t const entityID = (uint8_t)tu_u16_high(p_request->wIndex); + + // Only current-value requests are supported. + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // A headset exposes a feature unit per direction; the speaker's id matches the + // single-direction USB_AUDIO_ENTITY_FEATURE_UNIT, the mic adds a second one. + // Mute/volume state is shared across them (mono, cosmetic for now). + if (entityID == USB_AUDIO_ENTITY_FEATURE_UNIT || + entityID == USB_AUDIO_HS_ENTITY_MIC_FEATURE_UNIT) { + if (channelNum > USB_AUDIO_N_CHANNELS) { + return false; + } + switch (ctrlSel) { + case AUDIO_FU_CTRL_MUTE: + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + usb_audio_mute[channelNum] = ((audio_control_cur_1_t *)pBuff)->bCur; + return true; + + case AUDIO_FU_CTRL_VOLUME: + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + usb_audio_volume[channelNum] = ((audio_control_cur_2_t *)pBuff)->bCur; + return true; + + default: + return false; + } + } + return false; +} + +// Class-specific GET requests for an entity (clock source, feature unit, input terminal). +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void)rhport; + + uint8_t const channelNum = (uint8_t)tu_u16_low(p_request->wValue); + uint8_t const ctrlSel = (uint8_t)tu_u16_high(p_request->wValue); + uint8_t const entityID = (uint8_t)tu_u16_high(p_request->wIndex); + + // Input terminal connector control. The single-mic descriptor uses + // USB_AUDIO_ENTITY_INPUT_TERMINAL; the headset's microphone input terminal is + // a distinct id. (The USB-streaming input terminals don't advertise a readable + // connector control, so the host won't query them here.) + if (entityID == USB_AUDIO_ENTITY_INPUT_TERMINAL || + entityID == USB_AUDIO_HS_ENTITY_MIC_INPUT_TERMINAL) { + switch (ctrlSel) { + case AUDIO_TE_CTRL_CONNECTOR: { + audio_desc_channel_cluster_t ret; + ret.bNrChannels = USB_AUDIO_N_CHANNELS; + ret.bmChannelConfig = (audio_channel_config_t)0; + ret.iChannelNames = 0; + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &ret, sizeof(ret)); + } + default: + return false; + } + } + + // Feature unit (mute/volume) for either the speaker or mic chain. + if (entityID == USB_AUDIO_ENTITY_FEATURE_UNIT || + entityID == USB_AUDIO_HS_ENTITY_MIC_FEATURE_UNIT) { + if (channelNum > USB_AUDIO_N_CHANNELS) { + return false; + } + switch (ctrlSel) { + case AUDIO_FU_CTRL_MUTE: + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &usb_audio_mute[channelNum], sizeof(usb_audio_mute[channelNum])); + + case AUDIO_FU_CTRL_VOLUME: + switch (p_request->bRequest) { + case AUDIO_CS_REQ_CUR: + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &usb_audio_volume[channelNum], sizeof(usb_audio_volume[channelNum])); + + case AUDIO_CS_REQ_RANGE: { + audio_control_range_2_n_t(1) ret; + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = -90 * 256; // -90 dB + ret.subrange[0].bMax = 90 * 256; // +90 dB + ret.subrange[0].bRes = 256; // 1 dB steps + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &ret, sizeof(ret)); + } + + default: + return false; + } + + default: + return false; + } + } + + // Clock source (sample rate set in usb_audio.enable()). + if (entityID == USB_AUDIO_ENTITY_CLOCK_SOURCE) { + switch (ctrlSel) { + case AUDIO_CS_CTRL_SAM_FREQ: + switch (p_request->bRequest) { + case AUDIO_CS_REQ_CUR: { + audio_control_cur_4_t cur = { .bCur = (int32_t)usb_audio_sample_rate }; + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &cur, sizeof(cur)); + } + + case AUDIO_CS_REQ_RANGE: { + audio_control_range_4_n_t(1) ret; + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = (int32_t)usb_audio_sample_rate; + ret.subrange[0].bMax = (int32_t)usb_audio_sample_rate; + ret.subrange[0].bRes = 0; + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &ret, sizeof(ret)); + } + + default: + return false; + } + + case AUDIO_CS_CTRL_CLK_VALID: { + audio_control_cur_1_t cur = { .bCur = 1 }; + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &cur, sizeof(cur)); + } + + default: + return false; + } + } + + return false; +} + +// Keep the per-VM singleton instances (and, for the microphone, its bound +// audiosample) alive for the GC. Installed in the module globals by +// usb_audio_setup_singletons() and reset to NULL at each VM start. +MP_REGISTER_ROOT_POINTER(mp_obj_t usb_audio_microphone_singleton); +MP_REGISTER_ROOT_POINTER(mp_obj_t usb_audio_speaker_singleton); diff --git a/shared-module/usb_audio/__init__.h b/shared-module/usb_audio/__init__.h new file mode 100644 index 00000000000..8ec13f90853 --- /dev/null +++ b/shared-module/usb_audio/__init__.h @@ -0,0 +1,60 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include + +#include "py/obj.h" +#include "supervisor/usb.h" + +// Enable/disable the USB Audio Class (UAC2) interface. These may only be +// called before USB is connected (i.e. from boot.py); they return false +// otherwise. At least one of microphone/speaker must be true; enabling both +// presents a combined headset. +bool shared_module_usb_audio_enable(mp_int_t sample_rate, mp_int_t channel_count, mp_int_t bits_per_sample, bool microphone, bool speaker); +bool shared_module_usb_audio_disable(void); + +// True once enable() has been called successfully. +bool usb_audio_enabled(void); + +// True while the host has opened either AudioStreaming alternate setting, i.e. it +// is actively listening or sending. This is the real "stream the audio now" +// signal. +bool usb_audio_streaming(void); + +// True while the host has the speaker (host -> board OUT) stream open. Distinct +// from usb_audio_streaming() so USBSpeaker can report its own direction even when +// it shares a headset function with a microphone. +bool usb_audio_speaker_streaming(void); + +// Negotiated audio format, valid when usb_audio_enabled() is true. +extern uint32_t usb_audio_sample_rate; +extern uint8_t usb_audio_channel_count; +extern uint8_t usb_audio_bits_per_sample; + +// Which streams were requested in enable(), valid when usb_audio_enabled() is +// true. Both true presents a combined headset. +extern bool usb_audio_microphone_enabled; +extern bool usb_audio_speaker_enabled; + +// Descriptor injection hooks, called from supervisor/shared/usb/usb_desc.c. +size_t usb_audio_descriptor_length(void); +size_t usb_audio_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string); + +// Background task that streams samples to the host, called from +// supervisor/shared/usb/usb.c. +void usb_audio_task(void); + +// (Re)create the USBMicrophone and USBSpeaker singleton instances for the +// current VM and install them as the usb_audio.usb_microphone and +// usb_audio.usb_speaker module attributes (or None when that direction was not +// enabled in boot.py). Called once per VM from usb_setup_with_vm(), mirroring +// usb_midi_setup_ports(): the instances live on the GC heap, which is reset +// between boot.py and code.py, so they must be rebuilt each time. +void usb_audio_setup_singletons(void); diff --git a/shared-module/usb_audio/tusb_config.h b/shared-module/usb_audio/tusb_config.h new file mode 100644 index 00000000000..d7bfb65b148 --- /dev/null +++ b/shared-module/usb_audio/tusb_config.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-module/usb_audio/usb_audio_descriptors.h b/shared-module/usb_audio/usb_audio_descriptors.h new file mode 100644 index 00000000000..1313e198959 --- /dev/null +++ b/shared-module/usb_audio/usb_audio_descriptors.h @@ -0,0 +1,127 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +// Fixed audio format for the UAC2 microphone profile. These must have no other +// dependencies because this header is included from the TinyUSB tusb_config.h +// (to size the IN endpoint) as well as from the descriptor/binding code. + +// Actual length, in bytes, of the audio function descriptor emitted for the +// current direction (mic, speaker, or headset). Declared here -- in the +// dependency-free header tusb_config.h already includes -- because TinyUSB's +// audio class driver reads CFG_TUD_AUDIO_FUNC_1_DESC_LEN at enumeration time and +// returns it to the device core as the number of configuration-descriptor bytes +// the function owns. That value MUST equal the descriptor we actually emitted: +// the three directions differ in length, so a compile-time maximum would over- +// report for the shorter ones and make the core swallow the interfaces that +// follow audio (CDC/MSC), breaking their enumeration. The full definition lives +// in __init__.c (also declared in __init__.h for the descriptor builder). +size_t usb_audio_descriptor_length(void); + +// The isochronous IN endpoint's wMaxPacketSize in the USB descriptor is computed +// for this rate, so it is the highest rate usb_audio.enable() will accept. +#define USB_AUDIO_MAX_SAMPLE_RATE (48000) + +// 16-bit signed LE PCM, mono. +#define USB_AUDIO_N_BYTES_PER_SAMPLE (2) +#define USB_AUDIO_N_CHANNELS (1) +#define USB_AUDIO_BITS_PER_SAMPLE (USB_AUDIO_N_BYTES_PER_SAMPLE * 8) + +// Endpoint number for the single isochronous audio data endpoint. Most device +// controllers accept an ISO endpoint on any number, so the descriptor builder +// just takes the next sequential one (signalled by 0 here). The nRF52 USBD, +// however, implements isochronous transfers only on a fixed, dedicated endpoint +// number (8): its dcd_edpt_open() rejects any other number for an ISO endpoint, +// so the stream silently never opens and the host sees a mic/speaker that +// transfers no data. Such ports override this (e.g. -DUSB_AUDIO_ISO_EP_NUM=8 in +// the port's mpconfigport.mk) to force the audio endpoint onto that number. +#ifndef USB_AUDIO_ISO_EP_NUM +#define USB_AUDIO_ISO_EP_NUM (0) +#endif + +// Fixed UAC2 entity IDs baked into TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR and the +// hand-rolled speaker descriptor (USB_AUDIO_SPEAKER_DESCRIPTOR in __init__.c). +// The speaker reuses the same IDs as the mic; only the terminal roles reverse +// (input terminal = USB streaming, output terminal = desktop speaker). +#define USB_AUDIO_ENTITY_INPUT_TERMINAL (0x01) +#define USB_AUDIO_ENTITY_FEATURE_UNIT (0x02) +#define USB_AUDIO_ENTITY_OUTPUT_TERMINAL (0x03) +#define USB_AUDIO_ENTITY_CLOCK_SOURCE (0x04) + +// Combined headset (microphone + speaker both enabled) topology. A single audio function +// carries both a speaker chain (host -> board) and a mic chain (board -> host), +// so every unit/terminal needs an ID unique across the whole function -- unlike +// the single-direction descriptors above, which can reuse the same small set. +// The clock source is shared by both chains. (USB_AUDIO_HEADSET_DESCRIPTOR in +// __init__.c bakes these in.) +#define USB_AUDIO_HS_ENTITY_CLOCK_SOURCE (0x04) +#define USB_AUDIO_HS_ENTITY_SPK_INPUT_TERMINAL (0x01) // USB streaming in from host +#define USB_AUDIO_HS_ENTITY_SPK_FEATURE_UNIT (0x02) +#define USB_AUDIO_HS_ENTITY_SPK_OUTPUT_TERMINAL (0x03) // desktop speaker +#define USB_AUDIO_HS_ENTITY_MIC_INPUT_TERMINAL (0x05) // generic microphone +#define USB_AUDIO_HS_ENTITY_MIC_FEATURE_UNIT (0x06) +#define USB_AUDIO_HS_ENTITY_MIC_OUTPUT_TERMINAL (0x07) // USB streaming out to host + +// Length of the no-feedback mono speaker descriptor. It uses the same set of +// sub-descriptors as TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR (one isochronous data +// endpoint, no feedback endpoint), so this is identical to +// TUD_AUDIO_MIC_ONE_CH_DESC_LEN -- but spell it out independently so the two +// can diverge later (e.g. stereo) without silently mis-sizing the descriptor. +// These TUD_AUDIO_DESC_*_LEN macros come from TinyUSB's usbd.h; this expression +// is only expanded where that header is already included (never at the point +// tusb_config.h includes us), so the header stays dependency-free. +#define USB_AUDIO_SPEAKER_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN \ + + TUD_AUDIO_DESC_STD_AC_LEN \ + + TUD_AUDIO_DESC_CS_AC_LEN \ + + TUD_AUDIO_DESC_CLK_SRC_LEN \ + + TUD_AUDIO_DESC_INPUT_TERM_LEN \ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN \ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN \ + + TUD_AUDIO_DESC_STD_AS_INT_LEN \ + + TUD_AUDIO_DESC_STD_AS_INT_LEN \ + + TUD_AUDIO_DESC_CS_AS_INT_LEN \ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN \ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN \ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + +// Length of the combined headset descriptor (microphone + speaker both enabled): one IAD +// wrapping a single AudioControl interface plus two AudioStreaming interfaces +// (speaker OUT + mic IN). The AC interface declares one shared clock, plus an +// input terminal / feature unit / output terminal for each of the two chains; +// each AS interface contributes a zero-bandwidth alt 0 and a streaming alt 1 +// with one isochronous data endpoint (no feedback endpoint, matching the +// single-direction descriptors). See USB_AUDIO_HEADSET_DESCRIPTOR in __init__.c. +// Expanded only where TinyUSB's usbd.h is already included (never at the point +// tusb_config.h includes us), so this header stays dependency-free. +#define USB_AUDIO_HEADSET_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN \ + + TUD_AUDIO_DESC_STD_AC_LEN \ + + TUD_AUDIO_DESC_CS_AC_LEN \ + + TUD_AUDIO_DESC_CLK_SRC_LEN \ + /* speaker chain: USB-streaming input terminal -> feature unit -> speaker */ \ + + TUD_AUDIO_DESC_INPUT_TERM_LEN \ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN \ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN \ + /* mic chain: microphone input terminal -> feature unit -> USB-streaming out */ \ + + TUD_AUDIO_DESC_INPUT_TERM_LEN \ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN \ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN \ + /* speaker AudioStreaming interface (alt 0 + alt 1 with OUT endpoint) */ \ + + TUD_AUDIO_DESC_STD_AS_INT_LEN \ + + TUD_AUDIO_DESC_STD_AS_INT_LEN \ + + TUD_AUDIO_DESC_CS_AS_INT_LEN \ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN \ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN \ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN \ + /* mic AudioStreaming interface (alt 0 + alt 1 with IN endpoint) */ \ + + TUD_AUDIO_DESC_STD_AS_INT_LEN \ + + TUD_AUDIO_DESC_STD_AS_INT_LEN \ + + TUD_AUDIO_DESC_CS_AS_INT_LEN \ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN \ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN \ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) diff --git a/shared/libc/abort_.c b/shared/libc/abort_.c index 3051eae81e0..54eab67d3fb 100644 --- a/shared/libc/abort_.c +++ b/shared/libc/abort_.c @@ -1,7 +1,7 @@ #include -NORETURN void abort_(void); +MP_NORETURN void abort_(void); -NORETURN void abort_(void) { +MP_NORETURN void abort_(void) { mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("abort() called")); } diff --git a/shared/memzip/make-memzip.py b/shared/memzip/make-memzip.py index 92a5d6168bb..e406c55a43c 100755 --- a/shared/memzip/make-memzip.py +++ b/shared/memzip/make-memzip.py @@ -7,8 +7,6 @@ # This is somewhat like frozen modules in python, but allows arbitrary files # to be used. -from __future__ import print_function - import argparse import os import subprocess diff --git a/shared/netutils/trace.c b/shared/netutils/trace.c index a6dfb42c28f..24af4d5ca31 100644 --- a/shared/netutils/trace.c +++ b/shared/netutils/trace.c @@ -56,7 +56,7 @@ static const char *ethertype_str(uint16_t type) { } void netutils_ethernet_trace(const mp_print_t *print, size_t len, const uint8_t *buf, unsigned int flags) { - mp_printf(print, "[% 8d] ETH%cX len=%u", mp_hal_ticks_ms(), flags & NETUTILS_TRACE_IS_TX ? 'T' : 'R', len); + mp_printf(print, "[% 8u] ETH%cX len=%u", (unsigned)mp_hal_ticks_ms(), flags & NETUTILS_TRACE_IS_TX ? 'T' : 'R', len); mp_printf(print, " dst=%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); mp_printf(print, " src=%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); diff --git a/shared/runtime/gchelper_generic.c b/shared/runtime/gchelper_generic.c index 464aeaa9981..230a2444005 100644 --- a/shared/runtime/gchelper_generic.c +++ b/shared/runtime/gchelper_generic.c @@ -42,6 +42,7 @@ // stack already by the caller. #if defined(__x86_64__) +// CIRCUITPY-CHANGE: use __asm__ instead of asm static void gc_helper_get_regs(gc_helper_regs_t arr) { register long rbx __asm__ ("rbx"); register long rbp __asm__ ("rbp"); diff --git a/shared/runtime/interrupt_char.c b/shared/runtime/interrupt_char.c index 5cec1988f41..1f270201719 100644 --- a/shared/runtime/interrupt_char.c +++ b/shared/runtime/interrupt_char.c @@ -31,6 +31,7 @@ #if MICROPY_KBD_EXCEPTION +// CIRCUITPY-CHANGE #ifdef __ZEPHYR__ #include diff --git a/shared/runtime/interrupt_char.h b/shared/runtime/interrupt_char.h index c4a465456a8..44fd4b45a61 100644 --- a/shared/runtime/interrupt_char.h +++ b/shared/runtime/interrupt_char.h @@ -29,6 +29,7 @@ // CIRCUITPY-CHANGE #include +// CIRCUITPY-CHANGE #ifdef __ZEPHYR__ #include diff --git a/shared/runtime/mpirq.c b/shared/runtime/mpirq.c deleted file mode 100644 index 6111b9b10cf..00000000000 --- a/shared/runtime/mpirq.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Daniel Campora - * 2018 Tobias Badertscher - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include - -#include "py/runtime.h" -#include "py/gc.h" -#include "shared/runtime/mpirq.h" - -#if MICROPY_ENABLE_SCHEDULER - -/****************************************************************************** - DECLARE PUBLIC DATA - ******************************************************************************/ - -const mp_arg_t mp_irq_init_args[] = { - { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_trigger, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, -}; - -/****************************************************************************** - DECLARE PRIVATE DATA - ******************************************************************************/ - -/****************************************************************************** - DEFINE PUBLIC FUNCTIONS - ******************************************************************************/ - -mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent) { - mp_irq_obj_t *self = m_new0(mp_irq_obj_t, 1); - mp_irq_init(self, methods, parent); - return self; -} - -void mp_irq_init(mp_irq_obj_t *self, const mp_irq_methods_t *methods, mp_obj_t parent) { - self->base.type = &mp_irq_type; - self->methods = (mp_irq_methods_t *)methods; - self->parent = parent; - self->handler = mp_const_none; - self->ishard = false; -} - -void mp_irq_handler(mp_irq_obj_t *self) { - if (self->handler != mp_const_none) { - if (self->ishard) { - // When executing code within a handler we must lock the scheduler to - // prevent any scheduled callbacks from running, and lock the GC to - // prevent any memory allocations. - mp_sched_lock(); - gc_lock(); - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_call_function_1(self->handler, self->parent); - nlr_pop(); - } else { - // Uncaught exception; disable the callback so that it doesn't run again - self->methods->trigger(self->parent, 0); - self->handler = mp_const_none; - mp_printf(MICROPY_ERROR_PRINTER, "Uncaught exception in IRQ callback handler\n"); - mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val)); - } - gc_unlock(); - mp_sched_unlock(); - } else { - // Schedule call to user function - mp_sched_schedule(self->handler, self->parent); - } - } -} - -/******************************************************************************/ -// MicroPython bindings - -static mp_obj_t mp_irq_flags(mp_obj_t self_in) { - mp_irq_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_FLAGS)); -} -static MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags); - -static mp_obj_t mp_irq_trigger(size_t n_args, const mp_obj_t *args) { - mp_irq_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_obj_t ret_obj = mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_TRIGGERS)); - if (n_args == 2) { - // Set trigger - self->methods->trigger(self->parent, mp_obj_get_int(args[1])); - } - return ret_obj; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_irq_trigger_obj, 1, 2, mp_irq_trigger); - -static mp_obj_t mp_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 0, false); - mp_irq_handler(MP_OBJ_TO_PTR(self_in)); - return mp_const_none; -} - -static const mp_rom_map_elem_t mp_irq_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_flags), MP_ROM_PTR(&mp_irq_flags_obj) }, - { MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&mp_irq_trigger_obj) }, -}; -static MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - mp_irq_type, - MP_QSTR_irq, - MP_TYPE_FLAG_NONE, - call, mp_irq_call, - locals_dict, &mp_irq_locals_dict - ); - -#endif // MICROPY_ENABLE_SCHEDULER diff --git a/shared/runtime/mpirq.h b/shared/runtime/mpirq.h deleted file mode 100644 index dd423c01011..00000000000 --- a/shared/runtime/mpirq.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Daniel Campora - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H -#define MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H - -#include "py/runtime.h" - -/****************************************************************************** - DEFINE CONSTANTS - ******************************************************************************/ - -enum { - MP_IRQ_ARG_INIT_handler = 0, - MP_IRQ_ARG_INIT_trigger, - MP_IRQ_ARG_INIT_hard, - MP_IRQ_ARG_INIT_NUM_ARGS, -}; - -/****************************************************************************** - DEFINE TYPES - ******************************************************************************/ - -typedef mp_uint_t (*mp_irq_trigger_fun_t)(mp_obj_t self, mp_uint_t trigger); -typedef mp_uint_t (*mp_irq_info_fun_t)(mp_obj_t self, mp_uint_t info_type); - -enum { - MP_IRQ_INFO_FLAGS, - MP_IRQ_INFO_TRIGGERS, -}; - -typedef struct _mp_irq_methods_t { - mp_irq_trigger_fun_t trigger; - mp_irq_info_fun_t info; -} mp_irq_methods_t; - -typedef struct _mp_irq_obj_t { - mp_obj_base_t base; - mp_irq_methods_t *methods; - mp_obj_t parent; - mp_obj_t handler; - bool ishard; -} mp_irq_obj_t; - -/****************************************************************************** - DECLARE EXPORTED DATA - ******************************************************************************/ - -extern const mp_arg_t mp_irq_init_args[]; -extern const mp_obj_type_t mp_irq_type; - -/****************************************************************************** - DECLARE PUBLIC FUNCTIONS - ******************************************************************************/ - -mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent); -void mp_irq_init(mp_irq_obj_t *self, const mp_irq_methods_t *methods, mp_obj_t parent); -void mp_irq_handler(mp_irq_obj_t *self); - -#endif // MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index 06680ff2dd1..bc5f89bdc81 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -38,15 +38,12 @@ #include "py/gc.h" #include "py/frozenmod.h" #include "py/mphal.h" -#if MICROPY_HW_ENABLE_USB -#include "irq.h" -#include "usb.h" -#endif #include "shared/readline/readline.h" #include "shared/runtime/pyexec.h" +#include "extmod/modplatform.h" #include "genhdr/mpversion.h" -// CIRCUITPY-CHANGE: atexit support +// CIRCUITPY-CHANGE: add atexit support #if CIRCUITPY_ATEXIT #include "shared-module/atexit/__init__.h" #endif @@ -87,57 +84,71 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input nlr_buf_t nlr; nlr.ret_val = NULL; if (nlr_push(&nlr) == 0) { - // CIRCUITPY-CHANGE - mp_obj_t module_fun = mp_const_none; - // CIRCUITPY-CHANGE + #if MICROPY_PYEXEC_ENABLE_VM_ABORT + nlr_set_abort(&nlr); + #endif + + // CIRCUITPY-CHANGE: move declaration for easier handling of atexit #if. + // Also make it possible to determine if module_fun was set. + mp_obj_t module_fun = NULL; + + // CIRCUITPY-CHANGE: add atexit support #if CIRCUITPY_ATEXIT - if (!(exec_flags & EXEC_FLAG_SOURCE_IS_ATEXIT)) + if (exec_flags & EXEC_FLAG_SOURCE_IS_ATEXIT) { + atexit_callback_t *callback = (atexit_callback_t *)source; + mp_call_function_n_kw(callback->func, callback->n_pos, callback->n_kw, callback->args); + } else #endif - // CIRCUITPY-CHANGE: multiple code changes - { - #if MICROPY_MODULE_FROZEN_MPY - if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) { - // source is a raw_code object, create the function - const mp_frozen_module_t *frozen = source; - mp_module_context_t *ctx = m_new_obj(mp_module_context_t); - ctx->module.globals = mp_globals_get(); - ctx->constants = frozen->constants; - module_fun = mp_make_function_from_proto_fun(frozen->proto_fun, ctx, NULL); - } else - #endif - { - #if MICROPY_ENABLE_COMPILER - mp_lexer_t *lex; - if (exec_flags & EXEC_FLAG_SOURCE_IS_VSTR) { - const vstr_t *vstr = source; - lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, 0); - } else if (exec_flags & EXEC_FLAG_SOURCE_IS_READER) { - lex = mp_lexer_new(MP_QSTR__lt_stdin_gt_, *(mp_reader_t *)source); - } else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) { - lex = mp_lexer_new_from_file(qstr_from_str(source)); - } else { - lex = (mp_lexer_t *)source; - } - // source is a lexer, parse and compile the script - qstr source_name = lex->source_name; - // CIRCUITPY-CHANGE - #if MICROPY_PY___FILE__ - if (input_kind == MP_PARSE_FILE_INPUT) { - mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); - } - #endif - mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - module_fun = mp_compile(&parse_tree, source_name, exec_flags & EXEC_FLAG_IS_REPL); - #else - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("script compilation not supported")); - #endif + #if MICROPY_MODULE_FROZEN_MPY + if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) { + // source is a raw_code object, create the function + const mp_frozen_module_t *frozen = source; + mp_module_context_t *ctx = m_new_obj(mp_module_context_t); + ctx->module.globals = mp_globals_get(); + ctx->constants = frozen->constants; + module_fun = mp_make_function_from_proto_fun(frozen->proto_fun, ctx, NULL); + } else + #endif + { + #if MICROPY_ENABLE_COMPILER + mp_lexer_t *lex; + if (exec_flags & EXEC_FLAG_SOURCE_IS_VSTR) { + const vstr_t *vstr = source; + lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, 0); + } else if (exec_flags & EXEC_FLAG_SOURCE_IS_READER) { + lex = mp_lexer_new(MP_QSTR__lt_stdin_gt_, *(mp_reader_t *)source); + } else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) { + lex = mp_lexer_new_from_file(qstr_from_str(source)); + } else { + lex = (mp_lexer_t *)source; } - - // If the code was loaded from a file, collect any garbage before running. + // source is a lexer, parse and compile the script + qstr source_name = lex->source_name; + #if MICROPY_MODULE___FILE__ if (input_kind == MP_PARSE_FILE_INPUT) { - gc_collect(); + mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); } + #endif + mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); + #if defined(MICROPY_UNIX_COVERAGE) + // allow to print the parse tree in the coverage build + if (mp_verbose_flag >= 3) { + printf("----------------\n"); + mp_parse_node_print(&mp_plat_print, parse_tree.root, 0); + printf("----------------\n"); + } + #endif + module_fun = mp_compile(&parse_tree, source_name, exec_flags & EXEC_FLAG_IS_REPL); + #else + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("script compilation not supported")); + #endif + } + + // CIRCUITPY-CHANGE: garbage collect after loading + // If the code was loaded from a file, collect any garbage before running. + if (input_kind == MP_PARSE_FILE_INPUT) { + gc_collect(); } // execute code @@ -147,22 +158,19 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input #if MICROPY_REPL_INFO start = mp_hal_ticks_ms(); #endif - // CIRCUITPY-CHANGE - #if CIRCUITPY_ATEXIT - if (exec_flags & EXEC_FLAG_SOURCE_IS_ATEXIT) { - atexit_callback_t *callback = (atexit_callback_t *)source; - mp_call_function_n_kw(callback->func, callback->n_pos, callback->n_kw, callback->args); - } else + #if MICROPY_PYEXEC_COMPILE_ONLY + if (!mp_compile_only) #endif - // CIRCUITPY-CHANGE - if (module_fun != mp_const_none) { - mp_call_function_0(module_fun); + { + // CIRCUITPY-CHANGE: if atexit function was called, there is nothing to call. + if (module_fun != NULL) { + mp_call_function_0(module_fun); + } } mp_hal_set_interrupt_char(-1); // disable interrupt mp_handle_pending(true); // handle any pending exceptions (and any callbacks) nlr_pop(); - // CIRCUITPY-CHANGE - ret = 0; + ret = PYEXEC_NORMAL_EXIT; if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } @@ -181,36 +189,65 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input mp_hal_stdout_tx_strn("\x04", 1); } - // check for SystemExit - - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: Name and use some values. // nlr.ret_val is an exception object. mp_obj_t exception_obj = (mp_obj_t)nlr.ret_val; + const mp_obj_type_t *exception_obj_type = mp_obj_get_type(exception_obj); - if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(exception_obj)), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { - // at the moment, the value of SystemExit is unused + #if MICROPY_PYEXEC_ENABLE_VM_ABORT + if (nlr.ret_val == NULL) { // abort + ret = PYEXEC_ABORT; + } else + #endif + + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exception_obj_type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // system exit + #if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING + // None is an exit value of 0; an int is its value; anything else is 1 + mp_obj_t val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); + if (val != mp_const_none) { + if (mp_obj_is_int(val)) { + ret = (int)mp_obj_int_get_truncated(val); + } else { + mp_obj_print_helper(MICROPY_ERROR_PRINTER, val, PRINT_STR); + mp_print_str(MICROPY_ERROR_PRINTER, "\n"); + ret = PYEXEC_UNHANDLED_EXCEPTION; + } + } else { + ret = PYEXEC_NORMAL_EXIT; + } + // Set PYEXEC_FORCED_EXIT flag so REPL knows to exit + ret |= PYEXEC_FORCED_EXIT; + #else ret = PYEXEC_FORCED_EXIT; - // CIRCUITPY-CHANGE + #endif + // CIRCUITPY-CHANGE: support DeepSleepRequest #if CIRCUITPY_ALARM - } else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(exception_obj)), MP_OBJ_FROM_PTR(&mp_type_DeepSleepRequest))) { + } else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exception_obj_type), MP_OBJ_FROM_PTR(&mp_type_DeepSleepRequest))) { ret = PYEXEC_DEEP_SLEEP; #endif + // CIRCUITPY-CHANGE: support ReloadException } else if (exception_obj == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { ret = PYEXEC_RELOAD; - } else { - mp_obj_print_exception(&mp_plat_print, exception_obj); - ret = PYEXEC_EXCEPTION; + } else { // other exception + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + ret = PYEXEC_UNHANDLED_EXCEPTION; + #if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_KeyboardInterrupt))) { // keyboard interrupt + ret = PYEXEC_KEYBOARD_INTERRUPT; + } + #endif } - } + + // CIRCUITPY_CHANGE: Fill in result out argument. if (result != NULL) { result->return_code = ret; - #if CIRCUITPY_ALARM // Don't set the exception object if we exited for deep sleep. - if (ret != 0 && ret != PYEXEC_DEEP_SLEEP) { - #else - if (ret != 0) { + if (ret != 0 + #if CIRCUITPY_ALARM + && ret != PYEXEC_DEEP_SLEEP #endif + ) { mp_obj_t return_value = (mp_obj_t)nlr.ret_val; result->exception = return_value; result->exception_line = -1; @@ -227,6 +264,10 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input } } + #if MICROPY_PYEXEC_ENABLE_VM_ABORT + nlr_set_abort(NULL); + #endif + #if MICROPY_REPL_INFO // display debugging info if wanted if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { @@ -484,7 +525,10 @@ static int pyexec_friendly_repl_process_char(int c) { // CIRCUITPY-CHANGE: print CircuitPython-style banner. mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO); mp_hal_stdout_tx_str("\r\n"); + #if MICROPY_PY_BUILTINS_HELP + // CIRCUITPY-CHANGE: don't print help info // mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); + #endif goto input_restart; } else if (ret == CHAR_CTRL_C) { // break @@ -570,10 +614,21 @@ MP_REGISTER_ROOT_POINTER(vstr_t * repl_line); #else // MICROPY_REPL_EVENT_DRIVEN +// CIRCUITPY-CHANGE: avoid warnings +#if !defined(MICROPY_HAL_HAS_STDIO_MODE_SWITCH) || !MICROPY_HAL_HAS_STDIO_MODE_SWITCH +// If the port doesn't need any stdio mode switching calls then provide trivial ones. +static inline void mp_hal_stdio_mode_raw(void) { +} +static inline void mp_hal_stdio_mode_orig(void) { +} +#endif + int pyexec_raw_repl(void) { vstr_t line; vstr_init(&line, 32); + mp_hal_stdio_mode_raw(); + raw_repl_reset: mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n"); @@ -587,6 +642,7 @@ int pyexec_raw_repl(void) { if (vstr_len(&line) == 2 && vstr_str(&line)[0] == CHAR_CTRL_E) { int ret = do_reader_stdin(vstr_str(&line)[1]); if (ret & PYEXEC_FORCED_EXIT) { + mp_hal_stdio_mode_orig(); return ret; } vstr_reset(&line); @@ -599,6 +655,7 @@ int pyexec_raw_repl(void) { mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; + mp_hal_stdio_mode_orig(); return 0; } else if (c == CHAR_CTRL_C) { // clear line @@ -619,14 +676,18 @@ int pyexec_raw_repl(void) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); + mp_hal_stdio_mode_orig(); return PYEXEC_FORCED_EXIT; } + // Switch to original terminal mode to execute code, eg to support keyboard interrupt (SIGINT). + mp_hal_stdio_mode_orig(); // CIRCUITPY-CHANGE: add last arg, handle reload int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR, NULL); if (ret & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) { return ret; } + mp_hal_stdio_mode_raw(); } } @@ -634,6 +695,8 @@ int pyexec_friendly_repl(void) { vstr_t line; vstr_init(&line, 32); + mp_hal_stdio_mode_raw(); + friendly_repl_reset: // CIRCUITPY-CHANGE: CircuitPython-style banner. mp_hal_stdout_tx_str("\r\n"); @@ -661,20 +724,6 @@ int pyexec_friendly_repl(void) { for (;;) { input_restart: - - #if MICROPY_HW_ENABLE_USB - if (usb_vcp_is_enabled()) { - // If the user gets to here and interrupts are disabled then - // they'll never see the prompt, traceback etc. The USB REPL needs - // interrupts to be enabled or no transfers occur. So we try to - // do the user a favor and re-enable interrupts. - if (query_irq() == IRQ_STATE_DISABLED) { - enable_irq(IRQ_STATE_ENABLED); - mp_hal_stdout_tx_str("MPY: enabling IRQs\r\n"); - } - } - #endif - // If the GC is locked at this point there is no way out except a reset, // so force the GC to be unlocked to help the user debug what went wrong. if (MP_STATE_THREAD(gc_lock_depth) != 0) { @@ -705,6 +754,7 @@ int pyexec_friendly_repl(void) { mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_RAW_REPL; + mp_hal_stdio_mode_orig(); return 0; } else if (ret == CHAR_CTRL_B) { // reset friendly REPL @@ -718,6 +768,7 @@ int pyexec_friendly_repl(void) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); + mp_hal_stdio_mode_orig(); return PYEXEC_FORCED_EXIT; } else if (ret == CHAR_CTRL_E) { // paste mode @@ -762,11 +813,14 @@ int pyexec_friendly_repl(void) { } } + // Switch to original terminal mode to execute code, eg to support keyboard interrupt (SIGINT). + mp_hal_stdio_mode_orig(); // CIRCUITPY-CHANGE: add last arg ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR, NULL); if (ret & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) { return ret; } + mp_hal_stdio_mode_raw(); } } diff --git a/shared/runtime/pyexec.h b/shared/runtime/pyexec.h index 55a3003791c..9d1ef2a3cb0 100644 --- a/shared/runtime/pyexec.h +++ b/shared/runtime/pyexec.h @@ -51,6 +51,17 @@ extern pyexec_mode_kind_t pyexec_mode_kind; #define PYEXEC_DEEP_SLEEP (0x400) #define PYEXEC_RELOAD (0x800) +#if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING +#define PYEXEC_NORMAL_EXIT (0) +#define PYEXEC_UNHANDLED_EXCEPTION (1) +#define PYEXEC_KEYBOARD_INTERRUPT (128 + 2) // same as SIG INT exit code +#define PYEXEC_ABORT (128 + 9) // same as SIG KILL exit code +#else +#define PYEXEC_NORMAL_EXIT (1) +#define PYEXEC_UNHANDLED_EXCEPTION (0) +#define PYEXEC_ABORT PYEXEC_FORCED_EXIT +#endif + int pyexec_raw_repl(void); int pyexec_friendly_repl(void); // CIRCUITPY-CHANGE: result out argument diff --git a/shared/timeutils/timeutils.c b/shared/timeutils/timeutils.c index 4282a0178dd..0c6916e06dd 100644 --- a/shared/timeutils/timeutils.c +++ b/shared/timeutils/timeutils.c @@ -29,12 +29,27 @@ #include "shared/timeutils/timeutils.h" -// LEAPOCH corresponds to 2000-03-01, which is a mod-400 year, immediately -// after Feb 29. We calculate seconds as a signed integer relative to that. +// To maintain reasonable compatibility with CPython on embedded systems, +// and avoid breaking anytime soon, timeutils functions are required to +// work properly between 1970 and 2099 on all ports. // -// Our timebase is relative to 2000-01-01. - -#define LEAPOCH ((31 + 29) * 86400) +// During that period of time, leap years occur every 4 years without +// exception, so we can keep the code short for 32 bit machines. + +// The last leap day before the required period is Feb 29, 1968. +// This is the number of days to add to get to that date. +#define PREV_LEAP_DAY ((mp_uint_t)(365 + 366 - (31 + 29))) +#define PREV_LEAP_YEAR 1968 + +// On ports where either MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND or +// MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE is enabled, we include extra +// code to support leap years outside of the 'easy' period. +// Computation is then made based on 1600 (a mod-400 year). +// This is the number of days between 1600 and 1968. +#define QC_BASE_DAY 134409 +#define QC_LEAP_YEAR 1600 +// This is the number of leap days between 1600 and 1970 +#define QC_LEAP_DAYS 89 #define DAYS_PER_400Y (365 * 400 + 97) #define DAYS_PER_100Y (365 * 100 + 24) @@ -42,8 +57,20 @@ static const uint16_t days_since_jan1[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; +// type used internally to count small integers relative to epoch +// (using uint when possible produces smaller code on some platforms) +#if MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE +typedef mp_int_t relint_t; +#else +typedef mp_uint_t relint_t; +#endif + bool timeutils_is_leap_year(mp_uint_t year) { + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; + #else + return year % 4 == 0; + #endif } // month is one based @@ -65,67 +92,67 @@ mp_uint_t timeutils_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date) { return yday; } -void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t, timeutils_struct_time_t *tm) { - // The following algorithm was adapted from musl's __secs_to_tm and adapted - // for differences in MicroPython's timebase. - - mp_int_t seconds = t - LEAPOCH; +void timeutils_seconds_since_1970_to_struct_time(timeutils_timestamp_t seconds, timeutils_struct_time_t *tm) { + // The following algorithm was inspired from musl's __secs_to_tm + // and simplified to reduce code footprint in the simple case - mp_int_t days = seconds / 86400; + relint_t days = seconds / 86400; seconds %= 86400; + #if MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE if (seconds < 0) { seconds += 86400; days -= 1; } + #endif tm->tm_hour = seconds / 3600; tm->tm_min = seconds / 60 % 60; tm->tm_sec = seconds % 60; - mp_int_t wday = (days + 2) % 7; // Mar 1, 2000 was a Wednesday (2) + relint_t wday = (days + 3) % 7; // Jan 1, 1970 was a Thursday (3) + #if MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE if (wday < 0) { wday += 7; } + #endif tm->tm_wday = wday; - mp_int_t qc_cycles = days / DAYS_PER_400Y; + days += PREV_LEAP_DAY; + + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE + // rebase day to the oldest supported date (=> always positive) + mp_uint_t base_year = QC_LEAP_YEAR; + days += QC_BASE_DAY; + mp_uint_t qc_cycles = days / DAYS_PER_400Y; days %= DAYS_PER_400Y; - if (days < 0) { - days += DAYS_PER_400Y; - qc_cycles--; - } - mp_int_t c_cycles = days / DAYS_PER_100Y; + mp_uint_t c_cycles = days / DAYS_PER_100Y; if (c_cycles == 4) { c_cycles--; } days -= (c_cycles * DAYS_PER_100Y); - - mp_int_t q_cycles = days / DAYS_PER_4Y; + #else + mp_uint_t base_year = PREV_LEAP_YEAR; + mp_uint_t qc_cycles = 0; + mp_uint_t c_cycles = 0; + #endif + + mp_uint_t q_cycles = days / DAYS_PER_4Y; + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE if (q_cycles == 25) { q_cycles--; } + #endif days -= q_cycles * DAYS_PER_4Y; - mp_int_t years = days / 365; + relint_t years = days / 365; if (years == 4) { years--; } days -= (years * 365); - /* We will compute tm_yday at the very end - mp_int_t leap = !years && (q_cycles || !c_cycles); - - tm->tm_yday = days + 31 + 28 + leap; - if (tm->tm_yday >= 365 + leap) { - tm->tm_yday -= 365 + leap; - } - - tm->tm_yday++; // Make one based - */ - - tm->tm_year = 2000 + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles; + tm->tm_year = base_year + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles; // Note: days_in_month[0] corresponds to March - static const int8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29}; + static const uint8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29}; mp_int_t month; for (month = 0; days_in_month[month] <= days; month++) { @@ -144,21 +171,28 @@ void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t, timeutils_struct_t } // returns the number of seconds, as an integer, since 2000-01-01 -mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month, +timeutils_timestamp_t timeutils_seconds_since_1970(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { - return - second - + minute * 60 - + hour * 3600 - + (timeutils_year_day(year, month, date) - 1 - + ((year - 2000 + 3) / 4) // add a day each 4 years starting with 2001 - - ((year - 2000 + 99) / 100) // subtract a day each 100 years starting with 2001 - + ((year - 2000 + 399) / 400) // add a day each 400 years starting with 2001 - ) * 86400 - + (year - 2000) * 31536000; + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE + mp_uint_t ref_year = QC_LEAP_YEAR; + #else + mp_uint_t ref_year = PREV_LEAP_YEAR; + #endif + timeutils_timestamp_t res; + res = ((relint_t)year - 1970) * 365; + res += (year - (ref_year + 1)) / 4; // add a day each 4 years + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE + res -= (year - (ref_year + 1)) / 100; // subtract a day each 100 years + res += (year - (ref_year + 1)) / 400; // add a day each 400 years + res -= QC_LEAP_DAYS; + #endif + res += timeutils_year_day(year, month, date) - 1; + res *= 86400; + res += hour * 3600 + minute * 60 + second; + return res; } -mp_uint_t timeutils_mktime_2000(mp_uint_t year, mp_int_t month, mp_int_t mday, +timeutils_timestamp_t timeutils_mktime_1970(mp_uint_t year, mp_int_t month, mp_int_t mday, mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { // Normalize the tuple. This allows things like: @@ -211,12 +245,16 @@ mp_uint_t timeutils_mktime_2000(mp_uint_t year, mp_int_t month, mp_int_t mday, year++; } } - return timeutils_seconds_since_2000(year, month, mday, hours, minutes, seconds); + return timeutils_seconds_since_1970(year, month, mday, hours, minutes, seconds); } // Calculate the weekday from the date. // The result is zero based with 0 = Monday. // by Michael Keith and Tom Craver, 1990. int timeutils_calc_weekday(int y, int m, int d) { - return ((d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 - y / 100 + y / 400) + 6) % 7; + return ((d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE + - y / 100 + y / 400 + #endif + ) + 6) % 7; } diff --git a/shared/timeutils/timeutils.h b/shared/timeutils/timeutils.h index b41903d3b27..35356b462aa 100644 --- a/shared/timeutils/timeutils.h +++ b/shared/timeutils/timeutils.h @@ -27,12 +27,23 @@ #ifndef MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H #define MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H -// CIRCUITPY-CHANGE: MICROPY_EPOCH_IS_1970 -#include "mpconfigport.h" +#include "py/obj.h" +#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#include // required for trunc() +#endif + +// `timeutils_timestamp_t` is the type used internally by timeutils to +// represent timestamps, and is always referenced to 1970. +// It may not match the platform-specific `mp_timestamp_t`. +#if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE +typedef long long timeutils_timestamp_t; +#else +typedef mp_uint_t timeutils_timestamp_t; +#endif // The number of seconds between 1970/1/1 and 2000/1/1 is calculated using: // time.mktime((2000,1,1,0,0,0,0,0,0)) - time.mktime((1970,1,1,0,0,0,0,0,0)) -#define TIMEUTILS_SECONDS_1970_TO_2000 (946684800ULL) +#define TIMEUTILS_SECONDS_1970_TO_2000 (946684800LL) typedef struct _timeutils_struct_time_t { uint16_t tm_year; // i.e. 2014 @@ -48,66 +59,116 @@ typedef struct _timeutils_struct_time_t { bool timeutils_is_leap_year(mp_uint_t year); mp_uint_t timeutils_days_in_month(mp_uint_t year, mp_uint_t month); mp_uint_t timeutils_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date); +int timeutils_calc_weekday(int y, int m, int d); -void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t, +void timeutils_seconds_since_1970_to_struct_time(timeutils_timestamp_t t, timeutils_struct_time_t *tm); // Year is absolute, month/date are 1-based, hour/minute/second are 0-based. -mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month, +timeutils_timestamp_t timeutils_seconds_since_1970(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second); // Year is absolute, month/mday are 1-based, hours/minutes/seconds are 0-based. -mp_uint_t timeutils_mktime_2000(mp_uint_t year, mp_int_t month, mp_int_t mday, +timeutils_timestamp_t timeutils_mktime_1970(mp_uint_t year, mp_int_t month, mp_int_t mday, mp_int_t hours, mp_int_t minutes, mp_int_t seconds); +static inline mp_timestamp_t timeutils_obj_get_timestamp(mp_obj_t o_in) { + #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE + mp_float_t val = mp_obj_get_float(o_in); + return (mp_timestamp_t)MICROPY_FLOAT_C_FUN(trunc)(val); + #elif MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_UINT + return mp_obj_get_uint(o_in); + #else + return mp_obj_get_ll(o_in); + #endif +} + +static inline mp_obj_t timeutils_obj_from_timestamp(mp_timestamp_t t) { + #if MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_UINT + return mp_obj_new_int_from_uint(t); + #else + return mp_obj_new_int_from_ll(t); + #endif +} + +static inline void timeutils_seconds_since_2000_to_struct_time(mp_timestamp_t t, timeutils_struct_time_t *tm) { + timeutils_seconds_since_1970_to_struct_time((timeutils_timestamp_t)(t + TIMEUTILS_SECONDS_1970_TO_2000), tm); +} + +// Year is absolute, month/date are 1-based, hour/minute/second are 0-based. +static inline mp_timestamp_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t date, + mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { + return (mp_timestamp_t)timeutils_seconds_since_1970(year, month, date, hour, minute, second) - TIMEUTILS_SECONDS_1970_TO_2000; +} + +// Year is absolute, month/mday are 1-based, hours/minutes/seconds are 0-based. +static inline mp_timestamp_t timeutils_mktime_2000(mp_uint_t year, mp_int_t month, mp_int_t mday, + mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { + return (mp_timestamp_t)timeutils_mktime_1970(year, month, mday, hours, minutes, seconds) - TIMEUTILS_SECONDS_1970_TO_2000; +} + + // Select the Epoch used by the port. #if MICROPY_EPOCH_IS_1970 -static inline void timeutils_seconds_since_epoch_to_struct_time(uint64_t t, timeutils_struct_time_t *tm) { - // TODO this will give incorrect results for dates before 2000/1/1 - timeutils_seconds_since_2000_to_struct_time((mp_uint_t)(t - TIMEUTILS_SECONDS_1970_TO_2000), tm); +static inline void timeutils_seconds_since_epoch_to_struct_time(mp_timestamp_t t, timeutils_struct_time_t *tm) { + timeutils_seconds_since_1970_to_struct_time(t, tm); +} + +// Year is absolute, month/date are 1-based, hour/minute/second are 0-based. +static inline mp_timestamp_t timeutils_seconds_since_epoch(mp_uint_t year, mp_uint_t month, mp_uint_t date, + mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { + return timeutils_seconds_since_1970(year, month, date, hour, minute, second); } // Year is absolute, month/mday are 1-based, hours/minutes/seconds are 0-based. -static inline uint64_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday, mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { - return timeutils_mktime_2000(year, month, mday, hours, minutes, seconds) + TIMEUTILS_SECONDS_1970_TO_2000; +static inline mp_timestamp_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday, + mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { + return timeutils_mktime_1970(year, month, mday, hours, minutes, seconds); } -// Year is absolute, month/date are 1-based, hour/minute/second are 0-based. -static inline uint64_t timeutils_seconds_since_epoch(mp_uint_t year, mp_uint_t month, - mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { - // TODO this will give incorrect results for dates before 2000/1/1 - return timeutils_seconds_since_2000(year, month, date, hour, minute, second) + TIMEUTILS_SECONDS_1970_TO_2000; +static inline mp_timestamp_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(int64_t ns) { + return (mp_timestamp_t)(ns / 1000000000LL); } -static inline mp_uint_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(uint64_t ns) { - return (mp_uint_t)(ns / 1000000000ULL); +static inline int64_t timeutils_seconds_since_epoch_to_nanoseconds_since_1970(mp_timestamp_t s) { + return (int64_t)s * 1000000000LL; } -static inline uint64_t timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(uint64_t ns) { +static inline int64_t timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(int64_t ns) { return ns; } #else // Epoch is 2000 -#define timeutils_seconds_since_epoch_to_struct_time timeutils_seconds_since_2000_to_struct_time -#define timeutils_seconds_since_epoch timeutils_seconds_since_2000 -#define timeutils_mktime timeutils_mktime_2000 +static inline void timeutils_seconds_since_epoch_to_struct_time(mp_timestamp_t t, timeutils_struct_time_t *tm) { + timeutils_seconds_since_2000_to_struct_time(t, tm); +} -static inline uint64_t timeutils_seconds_since_epoch_to_nanoseconds_since_1970(mp_uint_t s) { - return ((uint64_t)s + TIMEUTILS_SECONDS_1970_TO_2000) * 1000000000ULL; +// Year is absolute, month/date are 1-based, hour/minute/second are 0-based. +static inline mp_timestamp_t timeutils_seconds_since_epoch(mp_uint_t year, mp_uint_t month, mp_uint_t date, + mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { + return timeutils_seconds_since_2000(year, month, date, hour, minute, second); } -static inline mp_uint_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(uint64_t ns) { - return ns / 1000000000ULL - TIMEUTILS_SECONDS_1970_TO_2000; +// Year is absolute, month/mday are 1-based, hours/minutes/seconds are 0-based. +static inline mp_timestamp_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday, + mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { + return timeutils_mktime_2000(year, month, mday, hours, minutes, seconds); +} + +static inline mp_timestamp_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(int64_t ns) { + return (mp_timestamp_t)(ns / 1000000000LL - TIMEUTILS_SECONDS_1970_TO_2000); +} + +static inline int64_t timeutils_seconds_since_epoch_to_nanoseconds_since_1970(mp_timestamp_t s) { + return ((int64_t)s + TIMEUTILS_SECONDS_1970_TO_2000) * 1000000000LL; } static inline int64_t timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(int64_t ns) { - return ns + TIMEUTILS_SECONDS_1970_TO_2000 * 1000000000ULL; + return ns + TIMEUTILS_SECONDS_1970_TO_2000 * 1000000000LL; } #endif -int timeutils_calc_weekday(int y, int m, int d); - #endif // MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H diff --git a/supervisor/port.h b/supervisor/port.h index 192307a5f57..f0e13e167cc 100644 --- a/supervisor/port.h +++ b/supervisor/port.h @@ -24,13 +24,13 @@ extern uint32_t _ebss; safe_mode_t port_init(void); // Reset the microcontroller completely. -void reset_cpu(void) NORETURN; +void reset_cpu(void) MP_NORETURN; // Reset the microcontroller state. void reset_port(void); // Reset to the bootloader -void reset_to_bootloader(void) NORETURN; +void reset_to_bootloader(void) MP_NORETURN; // Get stack limit address uint32_t *port_stack_get_limit(void); @@ -92,9 +92,17 @@ void port_wake_main_task(void); void port_wake_main_task_from_isr(void); // Some ports may use real RTOS tasks besides the background task framework of -// CircuitPython. Calling this will yield to other tasks and then return to the -// CircuitPython task when others are done. -void port_yield(void); +// CircuitPython. Calling this will yield to other tasks at the same priority level +// (or higher priority level if pre-emption is not immediate in the RTOS) +// and then return to the CircuitPython task when others are done. +// Note that this does NOT yield to lower priority tasks. Use port_task_sleep_ms() instead. +void port_task_yield(void); + +// On ports using real RTOS tasks, yield to other tasks for at least msecs. +// This will allow lower priority tasks to run. +// On non-RTOS implementations, this just sleeps for msecs and will run CircuitPython +// background tasks. +void port_task_sleep_ms(uint32_t msecs); // Some ports want to add information to boot_out.txt. // A default weak implementation is provided that does nothing. diff --git a/supervisor/shared/filesystem.c b/supervisor/shared/filesystem.c index eb4b6548d11..1d2a6180a94 100644 --- a/supervisor/shared/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -219,6 +219,13 @@ bool filesystem_init(bool create_allowed, bool force_create) { #if CIRCUITPY_SDCARDIO sdcardio_init(); + #if defined(DEFAULT_SD_CARD_DETECT) && CIRCUITPY_SDCARD_USB + // Mount the SD card now so it's ready when USB enumerates. + // Lazy mount from tud_msc_test_unit_ready_cb can lose races with + // macOS's probe timing. Gated on CIRCUITPY_SDCARD_USB to match the + // existing call site in usb_msc_flash.c (guarded by SDCARD_LUN). + automount_sd_card(); + #endif #endif return true; @@ -320,12 +327,23 @@ bool filesystem_lock(fs_user_mount_t *fs_mount) { return false; } fs_mount->lock_count += 1; + // CIRCUITPY-CHANGE: while a non-USB-MSC writer (BLE file transfer, web + // workflow, storage.remount) holds the filesystem lock, allow the + // FatFS f_open(FA_WRITE) path to bypass STA_PROTECT. Without this, the + // disk_ioctl(IOCTL_STATUS) -> filesystem_is_writable_by_python() check + // added by #10659 always sets STA_PROTECT on USB-device-capable boards, + // so even after the lock is held, f_open returns FR_WRITE_PROTECTED. + // USB MSC takes the lock via blockdev_lock() directly, NOT via + // filesystem_lock(), so this flag is never set on its behalf. + fs_mount->blockdev.flags |= MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION; return true; } void filesystem_unlock(fs_user_mount_t *fs_mount) { fs_mount->lock_count -= 1; if (fs_mount->lock_count == 0) { + // CIRCUITPY-CHANGE: clear the bypass when releasing the lock. + fs_mount->blockdev.flags &= ~MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION; blockdev_unlock(fs_mount); } } diff --git a/supervisor/shared/port.c b/supervisor/shared/port.c index f908e3f0bd8..3c95f2b7409 100644 --- a/supervisor/shared/port.c +++ b/supervisor/shared/port.c @@ -8,6 +8,7 @@ #include +#include "py/mphal.h" #include "py/runtime.h" #include "py/gc.h" @@ -26,7 +27,11 @@ MP_WEAK void port_wake_main_task(void) { MP_WEAK void port_wake_main_task_from_isr(void) { } -MP_WEAK void port_yield(void) { +MP_WEAK void port_task_yield(void) { +} + +MP_WEAK void port_task_sleep_ms(uint32_t msecs) { + mp_hal_delay_ms(msecs); } MP_WEAK void port_boot_info(void) { diff --git a/supervisor/shared/safe_mode.c b/supervisor/shared/safe_mode.c index 3860de6621f..da528d27df7 100644 --- a/supervisor/shared/safe_mode.c +++ b/supervisor/shared/safe_mode.c @@ -18,6 +18,10 @@ #include "supervisor/shared/translate/translate.h" #include "supervisor/shared/tick.h" +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" +#endif + #ifdef __ZEPHYR__ #include #endif @@ -65,10 +69,22 @@ safe_mode_t wait_for_safe_mode_reset(void) { #if CIRCUITPY_STATUS_LED status_led_init(); #endif + + uint32_t safe_mode_delay_msecs = 1000; + + #if CIRCUITPY_SETTINGS_TOML + mp_float_t safe_mode_delay_secs = 1.0f; + // Will update delay_secs if setting is present. + settings_get_float("CIRCUITPY_SAFE_MODE_DELAY", &safe_mode_delay_secs); + if (safe_mode_delay_secs >= 0.0f && safe_mode_delay_secs <= (mp_float_t)UINT32_MAX) { + safe_mode_delay_msecs = safe_mode_delay_secs * 1000; + } + #endif + uint64_t start_ticks = supervisor_ticks_ms64(); uint64_t diff = 0; bool boot_in_safe_mode = false; - while (diff < 1000) { + while (diff < safe_mode_delay_msecs) { #if CIRCUITPY_STATUS_LED // Blink on for 100, off for 100 bool led_on = (diff % 250) < 125; diff --git a/supervisor/shared/safe_mode.h b/supervisor/shared/safe_mode.h index 8f4037cbe20..87f65d867ea 100644 --- a/supervisor/shared/safe_mode.h +++ b/supervisor/shared/safe_mode.h @@ -38,6 +38,6 @@ void set_safe_mode(safe_mode_t safe_mode); safe_mode_t wait_for_safe_mode_reset(void); void safe_mode_on_next_reset(safe_mode_t reason); -void reset_into_safe_mode(safe_mode_t reason) NORETURN; +void reset_into_safe_mode(safe_mode_t reason) MP_NORETURN; void print_safe_mode_message(safe_mode_t reason); diff --git a/supervisor/shared/settings.c b/supervisor/shared/settings.c index d1b05a5da9d..1414195411e 100644 --- a/supervisor/shared/settings.c +++ b/supervisor/shared/settings.c @@ -5,6 +5,7 @@ // // SPDX-License-Identifier: MIT +#include #include #include #include @@ -419,6 +420,57 @@ settings_err_t settings_get_bool(const char *key, bool *value) { return result; } +#if MICROPY_PY_BUILTINS_FLOAT +static settings_err_t get_float(const char *key, mp_float_t *value) { + char buf[48]; + bool quoted; + settings_err_t result = settings_get_buf_terminated(key, buf, sizeof(buf), "ed); + if (result != SETTINGS_OK) { + return result; + } + if (quoted) { + return SETTINGS_ERR_BAD_VALUE; + } + + const char *str = buf; + const char *end = buf + strlen(buf); + bool neg = false; + + if (str < end && (*str == '+' || *str == '-')) { + neg = (*str == '-'); + str++; + } + + mp_float_t val; + if (end - str >= 3 && str[0] == 'i' && str[1] == 'n' && str[2] == 'f') { + str += 3; + val = (mp_float_t)INFINITY; + } else if (end - str >= 3 && str[0] == 'n' && str[1] == 'a' && str[2] == 'n') { + str += 3; + val = MICROPY_FLOAT_C_FUN(nan)(""); + } else { + const char *num_start = str; + str = mp_parse_float_internal(str, end - str, &val); + if (str == NULL || str == num_start) { + return SETTINGS_ERR_BAD_VALUE; + } + } + + if (str != end) { + return SETTINGS_ERR_BAD_VALUE; + } + + *value = neg ? -val : val; + return SETTINGS_OK; +} + +settings_err_t settings_get_float(const char *key, mp_float_t *value) { + settings_err_t result = get_float(key, value); + print_error(key, result); + return result; +} +#endif + // Get the raw value as a vstr, whether quoted or bare. Value may be an invalid TOML value. settings_err_t settings_get_raw_vstr(const char *key, vstr_t *vstr) { bool quoted; @@ -457,6 +509,16 @@ settings_err_t settings_get_obj(const char *key, mp_obj_t *value) { return SETTINGS_OK; } + // Not an integer, try float + #if MICROPY_PY_BUILTINS_FLOAT + mp_float_t float_val; + result = get_float(key, &float_val); + if (result == SETTINGS_OK) { + *value = mp_obj_new_float(float_val); + return SETTINGS_OK; + } + #endif + return SETTINGS_ERR_BAD_VALUE; } diff --git a/supervisor/shared/settings.h b/supervisor/shared/settings.h index eafa9962e95..6d92d45d79a 100644 --- a/supervisor/shared/settings.h +++ b/supervisor/shared/settings.h @@ -10,6 +10,7 @@ typedef enum { SETTINGS_OK = 0, + // The settings file could not be opened. SETTINGS_ERR_OPEN, SETTINGS_ERR_UNICODE, SETTINGS_ERR_LENGTH, @@ -20,7 +21,7 @@ typedef enum { // Read a string value from the settings file. // If it fits, the return value is 0-terminated. The passed-in buffer // may be modified even if an error is returned. Allocation free. -// An error that is not 'open' or 'not found' is printed on the repl. +// An error that is not SETTINGS_ERR_OPEN or SETTINGS_ERR_NOT_FOUND is printed on the repl. // Returns an error if the value is not a quoted string. settings_err_t settings_get_str(const char *key, char *value, size_t value_len); @@ -38,13 +39,23 @@ settings_err_t settings_get_int(const char *key, mp_int_t *value); // An error that is not 'open' or 'not found' is printed on the repl. settings_err_t settings_get_bool(const char *key, bool *value); +#if MICROPY_PY_BUILTINS_FLOAT +// Read a float value from the settings file. +// Returns SETTINGS_OK and sets value to the read value. Returns +// SETTINGS_ERR_... if the value was not a float. allocation-free. +// If any error code is returned, value is guaranteed not modified. +// An error that is not SETTINGS_ERR_OPEN or SETTINGS_ERR_NOT_FOUND is printed on the repl. +settings_err_t settings_get_float(const char *key, mp_float_t *value); +#endif + // Read a value from the settings file and return as parsed Python object. // Returns SETTINGS_OK and sets value to a parsed Python object from the RHS value: // - Quoted strings return as str // - Bare "true" or "false" return as bool // - Valid integers return as int +// - Valid floats (containing '.' or 'e'/'E') return as float // Returns SETTINGS_ERR_... if the value is not parseable as one of these types. -// An error that is not 'open' or 'not found' is printed on the repl. +// An error that is not SETTINGS_ERR_OPEN or SETTINGS_ERR_NOT_FOUND is printed on the repl. settings_err_t settings_get_obj(const char *key, mp_obj_t *value); // Read the raw value as a string, whether quoted or bare. diff --git a/supervisor/shared/translate/translate.c b/supervisor/shared/translate/translate.c index 958e0a2144f..b590b385a71 100644 --- a/supervisor/shared/translate/translate.c +++ b/supervisor/shared/translate/translate.c @@ -114,7 +114,7 @@ static void decompress_vstr(mp_rom_error_text_t compressed, vstr_t *decompressed } int v = values[searched_length + bits - max_code]; if (v == 1) { - qstr q = get_nbits(&b, translation_qstr_bits) + 1; // honestly no idea why "+1"... + qstr q = get_nbits(&b, translation_qstr_bits); vstr_add_str(decompressed, qstr_str(q)); } else { put_utf8(decompressed, v); diff --git a/supervisor/shared/usb.c b/supervisor/shared/usb.c index ff0dd1f8467..3aa24e62675 100644 --- a/supervisor/shared/usb.c +++ b/supervisor/shared/usb.c @@ -25,6 +25,10 @@ #include "shared-module/usb_midi/__init__.h" #endif +#if CIRCUITPY_USB_AUDIO +#include "shared-module/usb_audio/__init__.h" +#endif + #if CIRCUITPY_USB_VIDEO #include "shared-module/usb_video/__init__.h" #endif @@ -61,5 +65,9 @@ void usb_setup_with_vm(void) { #if CIRCUITPY_USB_MIDI usb_midi_setup_ports(); #endif + + #if CIRCUITPY_USB_AUDIO + usb_audio_setup_singletons(); + #endif #endif } diff --git a/supervisor/shared/usb/tusb_config.h b/supervisor/shared/usb/tusb_config.h index f2d800b9912..a10cd712226 100644 --- a/supervisor/shared/usb/tusb_config.h +++ b/supervisor/shared/usb/tusb_config.h @@ -115,8 +115,52 @@ extern "C" { #define CFG_TUD_HID CIRCUITPY_USB_HID #define CFG_TUD_MIDI CIRCUITPY_USB_MIDI #define CFG_TUD_VENDOR CIRCUITPY_USB_VENDOR +#define CFG_TUD_AUDIO CIRCUITPY_USB_AUDIO #define CFG_TUD_CUSTOM_CLASS 0 +// ------------- AUDIO CLASS (UAC2 microphone) -------------// +#if CIRCUITPY_USB_AUDIO +#include "shared-module/usb_audio/usb_audio_descriptors.h" + +// Single audio function. The emitted descriptor is chosen at boot from the +// stored direction: a mic (1 AS interface, IN endpoint), a speaker (1 AS +// interface, OUT endpoint), or a combined headset (2 AS interfaces, one IN and +// one OUT endpoint). The class driver returns this length to the device core as +// the span of config descriptor the function owns, so it must equal the +// descriptor we actually emitted -- the three directions differ in length, so a +// compile-time maximum would over-report for the shorter ones and make the core +// skip the interfaces that follow audio. usb_audio_descriptor_length() returns +// the live length for the stored direction; it is only read at enumeration time +// (audiod_open), by which point usb_audio.enable() has fixed the direction. +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN usb_audio_descriptor_length() +// The headset presents two AudioStreaming interfaces; the single-direction +// descriptors use only the first. The class driver sizes its per-interface alt +// tracking from this, so it must cover the largest case. +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 2 +// EP0 buffer for class-specific control requests (sample-freq range, volume range, ...). +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 + +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX USB_AUDIO_N_BYTES_PER_SAMPLE +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX USB_AUDIO_N_CHANNELS +// wMaxPacketSize, sized for the highest supported sample rate. +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TUD_AUDIO_EP_SIZE(USB_AUDIO_MAX_SAMPLE_RATE, USB_AUDIO_N_BYTES_PER_SAMPLE, USB_AUDIO_N_CHANNELS) +// Deep software FIFO so the 1 ms refill keeps clear of the underrun floor. +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (16 * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX) + +// OUT endpoint (host -> board speaker). Compiled into the class driver +// unconditionally; whether it actually enumerates is decided by the emitted +// descriptor (still mic-only until the speaker descriptor lands). Mirrors the +// IN sizing above. +#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX USB_AUDIO_N_BYTES_PER_SAMPLE +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX USB_AUDIO_N_CHANNELS +// wMaxPacketSize, sized for the highest supported sample rate. +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TUD_AUDIO_EP_SIZE(USB_AUDIO_MAX_SAMPLE_RATE, USB_AUDIO_N_BYTES_PER_SAMPLE, USB_AUDIO_N_CHANNELS) +// Deep software FIFO so the 1 ms drain keeps clear of the overrun ceiling. +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ (16 * CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX) +#endif + /*------------------------------------------------------------------*/ /* CLASS DRIVER *------------------------------------------------------------------*/ diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c index fbe8be97882..e8a4422bb36 100644 --- a/supervisor/shared/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -7,6 +7,7 @@ #include "py/objstr.h" #include "supervisor/background_callback.h" #include "supervisor/linker.h" +#include "supervisor/port.h" #include "supervisor/shared/tick.h" #include "supervisor/usb.h" #include "shared/readline/readline.h" @@ -38,6 +39,10 @@ #include "shared-module/usb_video/__init__.h" #endif +#if CIRCUITPY_USB_AUDIO +#include "shared-module/usb_audio/__init__.h" +#endif + #endif #include "tusb.h" @@ -160,9 +165,8 @@ void usb_background(void) { tuh_task(); #endif #elif CFG_TUSB_OS == OPT_OS_FREERTOS - // Yield to FreeRTOS in case TinyUSB runs in a separate task. Don't use - // port_yield() because it has a longer delay. - vTaskDelay(0); + // TinyUSB may run in a separate task, at the same priority as CircuitPython. + port_task_yield(); #endif // No need to flush if there's no REPL. #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_CDC @@ -174,6 +178,9 @@ void usb_background(void) { #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VIDEO usb_video_task(); #endif + #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_AUDIO + usb_audio_task(); + #endif } } diff --git a/supervisor/shared/usb/usb_desc.c b/supervisor/shared/usb/usb_desc.c index 9427171fe9b..7a0bc4686bb 100644 --- a/supervisor/shared/usb/usb_desc.c +++ b/supervisor/shared/usb/usb_desc.c @@ -32,6 +32,10 @@ #include "shared-module/usb_video/__init__.h" #endif +#if CIRCUITPY_USB_AUDIO +#include "shared-module/usb_audio/__init__.h" +#endif + #include "shared-bindings/microcontroller/Processor.h" @@ -170,6 +174,12 @@ static bool usb_build_configuration_descriptor(void) { } #endif + #if CIRCUITPY_USB_AUDIO + if (usb_audio_enabled()) { + total_descriptor_length += usb_audio_descriptor_length(); + } + #endif + // Now we know how big the configuration descriptor will be, so we can allocate space for it. configuration_descriptor = (uint8_t *)port_malloc(total_descriptor_length, @@ -259,6 +269,13 @@ static bool usb_build_configuration_descriptor(void) { descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string); } #endif + + #if CIRCUITPY_USB_AUDIO + if (usb_audio_enabled()) { + descriptor_buf_remaining += usb_audio_add_descriptor( + descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string); + } + #endif // Now we know how many interfaces have been used. configuration_descriptor[CONFIG_NUM_INTERFACES_INDEX] = descriptor_counts.current_interface; diff --git a/supervisor/shared/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c index 5ea457ef328..6f15b508095 100644 --- a/supervisor/shared/usb/usb_msc_flash.c +++ b/supervisor/shared/usb/usb_msc_flash.c @@ -18,6 +18,7 @@ #include "shared-module/storage/__init__.h" #include "supervisor/filesystem.h" #include "supervisor/shared/reload.h" +#include "supervisor/shared/settings.h" #define MSC_FLASH_BLOCK_SIZE 512 @@ -204,20 +205,25 @@ uint8_t tud_msc_get_maxlun_cb(void) { return LUN_COUNT; } +// PREVENT ALLOW MEDIUM REMOVAL: TinyUSB routes this to its own dedicated callback, +// NOT tud_msc_scsi_cb. Reply unsupported on all LUNs so the host keeps TUR polling +// on every LUN — eject/storage.remount() works uniformly across CIRCUITPY, SAVES, SD. +bool tud_msc_prevent_allow_medium_removal_cb(uint8_t lun, uint8_t prohibit_removal, uint8_t control) { + (void)prohibit_removal; + (void)control; + tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + return false; +} + // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE -// - READ10 and WRITE10 have their own callbacks +// - PREVENT_ALLOW_MEDIUM_REMOVAL, READ10, WRITE10 have their own callbacks int32_t tud_msc_scsi_cb(uint8_t lun, const uint8_t scsi_cmd[16], void *buffer, uint16_t bufsize) { // Note that no command uses a response right now. const void *response = NULL; int32_t resplen = 0; switch (scsi_cmd[0]) { - case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: - // Host is about to read/write etc ... better not to disconnect disk - resplen = 0; - break; - default: // Set Sense = Invalid Command Operation tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); @@ -360,6 +366,32 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16 memcpy(product_rev, CFG_TUD_MSC_PRODUCT_REV, strlen(CFG_TUD_MSC_PRODUCT_REV)); } +#ifdef SDCARD_LUN +#if CIRCUITPY_SETTINGS_TOML +typedef enum { + SDCARD_USB_SETTING_NOT_YET_READ = 0, + SDCARD_USB_SETTING_TRUE, + SDCARD_USB_SETTING_FALSE, +} sdcard_usb_setting_state_t; + +static sdcard_usb_setting_state_t _sdcard_usb_setting_state = SDCARD_USB_SETTING_NOT_YET_READ; + +// Read only once to save file access time. +static bool sdcard_usb_enabled(void) { + if (_sdcard_usb_setting_state == SDCARD_USB_SETTING_NOT_YET_READ) { + bool setting = true; + (void)settings_get_bool("CIRCUITPY_SDCARD_USB", &setting); + _sdcard_usb_setting_state = setting ? SDCARD_USB_SETTING_TRUE : SDCARD_USB_SETTING_FALSE; + } + return _sdcard_usb_setting_state == SDCARD_USB_SETTING_TRUE; +} +#else +static bool sdcard_usb_enabled(void) { + return CIRCUITPY_SDCARD_USB; +} +#endif +#endif + // Invoked when received Test Unit Ready command. // return true allowing host to read/write this LUN e.g SD card inserted bool tud_msc_test_unit_ready_cb(uint8_t lun) { @@ -367,17 +399,16 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) { return false; } - #ifdef SDCARD_LUN - if (lun == SDCARD_LUN) { - automount_sd_card(); - } - #endif - fs_user_mount_t *current_mount = get_vfs(lun); if (current_mount == NULL) { return false; } - if (ejected[lun] || eject_once[lun]) { + + if (ejected[lun] || eject_once[lun] + #ifdef SDCARD_LUN + || (lun == SDCARD_LUN && !sdcard_usb_enabled()) + #endif + ) { eject_once[lun] = false; // Set 0x3a for media not present. tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 74e4fed5759..8da8dcc5184 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -8,6 +8,8 @@ #define _GNU_SOURCE #include +#include +#include #include #include "extmod/vfs.h" @@ -42,6 +44,10 @@ #include "shared-bindings/socketpool/Socket.h" #include "shared-bindings/socketpool/SocketPool.h" +#if CIRCUITPY_HOSTNETWORK +#include "bindings/hostnetwork/__init__.h" +#endif + #if CIRCUITPY_WIFI #include "shared-bindings/wifi/__init__.h" #endif @@ -84,12 +90,18 @@ typedef struct { char websocket_key[24 + 1]; } _request; +#if CIRCUITPY_WIFI static wifi_radio_error_t _wifi_status = WIFI_RADIO_ERROR_NONE; +#endif -#if CIRCUITPY_STATUS_BAR +#if CIRCUITPY_STATUS_BAR && (CIRCUITPY_WIFI || CIRCUITPY_HOSTNETWORK) // Store various last states to compute if status bar needs an update. static bool _last_enabled = false; static uint32_t _last_ip = 0; +static mp_int_t _last_web_api_port = 80; +#endif + +#if CIRCUITPY_STATUS_BAR && CIRCUITPY_WIFI static wifi_radio_error_t _last_wifi_status = WIFI_RADIO_ERROR_NONE; #endif @@ -171,11 +183,7 @@ static bool _base64_in_place(char *buf, size_t in_len, size_t out_len) { return true; } -static void _update_encoded_ip(void) { - uint32_t ipv4_address = 0; - if (common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) { - ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj); - } +static void _update_encoded_ip(uint32_t ipv4_address) { if (_encoded_ip != ipv4_address) { uint8_t *octets = (uint8_t *)&ipv4_address; snprintf(_our_ip_encoded, sizeof(_our_ip_encoded), "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]); @@ -183,66 +191,118 @@ static void _update_encoded_ip(void) { } } +static bool _get_web_workflow_ip(uint32_t *ipv4_address) { + *ipv4_address = 0; + #if CIRCUITPY_WIFI + if (!common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) { + return false; + } + *ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj); + return true; + #elif CIRCUITPY_HOSTNETWORK + // hostnetwork uses the host network namespace and is reachable via localhost. + *ipv4_address = 0x0100007f; // 127.0.0.1 + return true; + #else + return false; + #endif +} + +#if CIRCUITPY_STATUS_BAR +static void _print_web_workflow_endpoint(void) { + mp_printf(&mp_plat_print, "%s", _our_ip_encoded); + if (web_api_port != 80) { + mp_printf(&mp_plat_print, ":%d", web_api_port); + } +} +#endif + mdns_server_obj_t *supervisor_web_workflow_mdns(mp_obj_t network_interface) { - #if CIRCUITPY_MDNS + #if CIRCUITPY_MDNS && CIRCUITPY_WIFI if (network_interface == &common_hal_wifi_radio_obj && mdns.base.type == &mdns_server_type) { return &mdns; } #endif + (void)network_interface; return NULL; } #if CIRCUITPY_STATUS_BAR bool supervisor_web_workflow_status_dirty(void) { - return common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) != _last_enabled || - _encoded_ip != _last_ip || - _last_wifi_status != _wifi_status; + #if CIRCUITPY_WIFI || CIRCUITPY_HOSTNETWORK + uint32_t ipv4_address = 0; + bool enabled = _get_web_workflow_ip(&ipv4_address); + if (enabled != _last_enabled || ipv4_address != _last_ip || web_api_port != _last_web_api_port) { + return true; + } + #if CIRCUITPY_WIFI + if (_last_wifi_status != _wifi_status) { + return true; + } + #endif + return false; + #else + return false; + #endif } #endif #if CIRCUITPY_STATUS_BAR void supervisor_web_workflow_status(void) { - _last_enabled = common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj); + #if CIRCUITPY_WIFI || CIRCUITPY_HOSTNETWORK + uint32_t ipv4_address = 0; + _last_enabled = _get_web_workflow_ip(&ipv4_address); + _last_web_api_port = web_api_port; + if (_last_enabled) { - uint32_t ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj); + _update_encoded_ip(ipv4_address); + _last_ip = _encoded_ip; + if (ipv4_address != 0) { - _update_encoded_ip(); - _last_ip = _encoded_ip; - mp_printf(&mp_plat_print, "%s", _our_ip_encoded); - if (web_api_port != 80) { - mp_printf(&mp_plat_print, ":%d", web_api_port); - } + _print_web_workflow_endpoint(); // TODO: Use these unicode to show signal strength: ▂▄▆█ return; } - serial_write_compressed(MP_ERROR_TEXT("Wi-Fi: ")); - _last_wifi_status = _wifi_status; - if (_wifi_status == WIFI_RADIO_ERROR_AUTH_EXPIRE || - _wifi_status == WIFI_RADIO_ERROR_AUTH_FAIL) { - serial_write_compressed(MP_ERROR_TEXT("Authentication failure")); - } else if (_wifi_status != WIFI_RADIO_ERROR_NONE) { - mp_printf(&mp_plat_print, "%d", _wifi_status); - } else if (ipv4_address == 0) { - _last_ip = 0; - serial_write_compressed(MP_ERROR_TEXT("No IP")); - } else { - } - } else { - // Keep Wi-Fi print separate so its data can be matched with the one above. - serial_write_compressed(MP_ERROR_TEXT("Wi-Fi: ")); + } + + #if CIRCUITPY_WIFI + serial_write_compressed(MP_ERROR_TEXT("Wi-Fi: ")); + _last_wifi_status = _wifi_status; + if (!_last_enabled) { serial_write_compressed(MP_ERROR_TEXT("off")); + } else if (_wifi_status == WIFI_RADIO_ERROR_AUTH_EXPIRE || + _wifi_status == WIFI_RADIO_ERROR_AUTH_FAIL) { + serial_write_compressed(MP_ERROR_TEXT("Authentication failure")); + } else if (_wifi_status != WIFI_RADIO_ERROR_NONE) { + mp_printf(&mp_plat_print, "%d", _wifi_status); + } else { + _last_ip = 0; + serial_write_compressed(MP_ERROR_TEXT("No IP")); } + #endif + #else + return; + #endif } #endif bool supervisor_start_web_workflow(void) { - #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_SETTINGS_TOML + #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_SETTINGS_TOML && (CIRCUITPY_WIFI || CIRCUITPY_HOSTNETWORK) + + #if CIRCUITPY_WIFI + mp_obj_t socketpool_radio = MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj); + #else + mp_obj_t socketpool_radio = MP_OBJ_FROM_PTR(&common_hal_hostnetwork_obj); + #endif + + settings_err_t result; + #if CIRCUITPY_WIFI char ssid[33]; char password[64]; - settings_err_t result = settings_get_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); + result = settings_get_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); if (result != SETTINGS_OK || strlen(ssid) < 1) { return false; } @@ -275,6 +335,7 @@ bool supervisor_start_web_workflow(void) { common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, false); return false; } + #endif // Skip starting the workflow if we're not starting from power on or reset. const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); @@ -307,7 +368,7 @@ bool supervisor_start_web_workflow(void) { } pool.base.type = &socketpool_socketpool_type; - common_hal_socketpool_socketpool_construct(&pool, &common_hal_wifi_radio_obj); + common_hal_socketpool_socketpool_construct(&pool, socketpool_radio); socketpool_socket_reset(&listening); socketpool_socket_reset(&active); @@ -373,7 +434,7 @@ void web_workflow_send_raw(socketpool_socket_obj_t *socket, bool flush, const ui total_sent += sent; if (total_sent < len) { // Yield so that network code can run. - port_yield(); + port_task_sleep_ms(4); } } } @@ -847,7 +908,9 @@ static void _reply_with_version_json(socketpool_socket_obj_t *socket, _request * instance_name = common_hal_mdns_server_get_instance_name(&mdns); } #endif - _update_encoded_ip(); + uint32_t ipv4_address = 0; + (void)_get_web_workflow_ip(&ipv4_address); + _update_encoded_ip(ipv4_address); // Note: this leverages the fact that C concats consecutive string literals together. mp_printf(&_socket_print, "{\"web_api_version\": 4, " @@ -977,7 +1040,7 @@ static void _write_file_and_reply(socketpool_socket_obj_t *socket, _request *req if (result == FR_NO_FILE) { new_file = true; result = f_open(fs, &active_file, path, FA_WRITE | FA_OPEN_ALWAYS); - } else { + } else if (result == FR_OK) { old_length = f_size(&active_file); } @@ -988,6 +1051,18 @@ static void _write_file_and_reply(socketpool_socket_obj_t *socket, _request *req _reply_missing(socket, request); return; } + if (result == FR_WRITE_PROTECTED) { + // The filesystem is held by something else with write access (most + // commonly USB-MSC: the host has CIRCUITPY mounted, so CircuitPython + // can't write through FatFS). Match the mkdir/move/delete paths and + // reply 409 Conflict so clients can show an actionable message + // ("eject CIRCUITPY / disable USB MSC") instead of a generic 500. + override_fattime(0); + filesystem_unlock(fs_mount); + _discard_incoming(socket, request->content_length); + _reply_conflict(socket, request); + return; + } if (result != FR_OK) { override_fattime(0); filesystem_unlock(fs_mount); diff --git a/supervisor/shared/web_workflow/web_workflow.h b/supervisor/shared/web_workflow/web_workflow.h index 439964dd333..9ec15a14ddc 100644 --- a/supervisor/shared/web_workflow/web_workflow.h +++ b/supervisor/shared/web_workflow/web_workflow.h @@ -8,7 +8,12 @@ #include +#if CIRCUITPY_MDNS #include "shared-bindings/mdns/Server.h" +#else +typedef struct mdns_server_obj mdns_server_obj_t; +#endif + #include "shared-bindings/socketpool/Socket.h" // This background function should be called repeatedly. It cannot be done based diff --git a/supervisor/shared/workflow.c b/supervisor/shared/workflow.c index c1999b4a7b6..28ce682efd9 100644 --- a/supervisor/shared/workflow.c +++ b/supervisor/shared/workflow.c @@ -23,8 +23,10 @@ #endif #endif -#if CIRCUITPY_TINYUSB || CIRCUITPY_USB_KEYBOARD_WORKFLOW +#if CIRCUITPY_USB_DEVICE || CIRCUITPY_USB_KEYBOARD_WORKFLOW #include "supervisor/usb.h" +#endif +#if CIRCUITPY_TINYUSB #include "tusb.h" #endif @@ -43,10 +45,12 @@ void supervisor_workflow_reset(void) { #if CIRCUITPY_WEB_WORKFLOW bool result = supervisor_start_web_workflow(); - if (workflow_background_cb.fun) { - if (result) { - supervisor_workflow_request_background(); + if (result) { + if (!workflow_background_cb.fun) { + // Enable background callbacks if web_workflow startup successful. + workflow_background_cb.fun = supervisor_web_workflow_background; } + supervisor_workflow_request_background(); } #endif } @@ -68,8 +72,8 @@ void supervisor_workflow_request_background(void) { bool supervisor_workflow_active(void) { #if CIRCUITPY_USB_DEVICE // Eventually there might be other non-USB workflows, such as BLE. - // tud_ready() checks for usb mounted and not suspended. - if (tud_ready()) { + // usb_connected() checks for usb mounted and not suspended. + if (usb_connected()) { return true; } #endif @@ -105,9 +109,10 @@ void supervisor_workflow_start(void) { #if CIRCUITPY_WEB_WORKFLOW if (supervisor_start_web_workflow()) { - // Enable background callbacks if web_workflow startup successful - memset(&workflow_background_cb, 0, sizeof(workflow_background_cb)); + // Enable background callbacks if web_workflow startup successful. workflow_background_cb.fun = supervisor_web_workflow_background; + // Kick the first background run now that the callback is installed. + supervisor_workflow_request_background(); } #endif diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index bce47353f57..1f40cebd0d2 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -182,6 +182,20 @@ ifeq ($(CIRCUITPY_TINYUSB),1) CFLAGS += -DCFG_TUD_VIDEO=1 -DCFG_TUD_VIDEO_STREAMING=1 -DCFG_TUD_VIDEO_STREAMING_EP_BUFSIZE=256 -DCFG_TUD_VIDEO_STREAMING_BULK=1 endif + ifeq ($(CIRCUITPY_USB_AUDIO), 1) + SRC_SUPERVISOR += \ + shared-bindings/usb_audio/__init__.c \ + shared-module/usb_audio/__init__.c \ + shared-bindings/usb_audio/USBMicrophone.c \ + shared-module/usb_audio/USBMicrophone.c \ + shared-bindings/usb_audio/USBSpeaker.c \ + shared-module/usb_audio/USBSpeaker.c \ + lib/tinyusb/src/class/audio/audio_device.c \ + + # The CFG_TUD_AUDIO_* class driver settings are defined in + # supervisor/shared/usb/tusb_config.h, gated on CIRCUITPY_USB_AUDIO. + endif + ifeq ($(CIRCUITPY_USB_VENDOR), 1) SRC_SUPERVISOR += \ diff --git a/tests/README.md b/tests/README.md index 21e14eee5e1..534e7e0a059 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,6 +1,7 @@ # MicroPython Test Suite -This directory contains tests for most parts of MicroPython. +This directory contains tests for most parts of MicroPython. To run it you will need +CPython 3.8.2 or newer, which is used to validate MicroPython's behaviour. To run all stable tests, run the "run-tests.py" script in this directory. By default that will run the test suite against the unix port of MicroPython. @@ -67,16 +68,14 @@ for a full list of command line options. ### Benchmarking a target -To run tests on a firmware target using `pyboard.py`, run the command line like +To run tests on a firmware target using a serial port, run the command line like this: ``` -./run-perfbench.py -p -d /dev/ttyACM0 168 100 +./run-perfbench.py -t /dev/ttyACM0 168 100 ``` -* `-p` indicates running on a remote target via pyboard.py, not the host. -* `-d PORTNAME` is the serial port, `/dev/ttyACM0` is the default if not - provided. +* `-t PORTNAME` is the serial port to use (and it supports shorthand like `a0`). * `168` is value `N`, the approximate CPU frequency in MHz (in this case Pyboard V1.1 is 168MHz). It's possible to choose other values as well: lower values like `10` will run much the tests much quicker, higher values like `1000` will @@ -136,11 +135,11 @@ Usually you want to know if something is faster or slower than a reference. To do this, copy the output of each `run-perfbench.py` run to a text file. This can be done multiple ways, but one way on Linux/macOS is with the `tee` -utility: `./run-perfbench.py -p 168 100 | tee pyb-run1.txt` +utility: `./run-perfbench.py -t a0 168 100 | tee pyb-run1.txt` Once you have two files with output from two different runs (maybe with different code or configuration), compare the runtimes with `./run-perfbench.py --t pybv-run1.txt pybv-run2.txt` or compare scores with `./run-perfbench.py -s +-m pybv-run1.txt pybv-run2.txt` or compare scores with `./run-perfbench.py -s pybv-run1.txt pybv-run2.txt`: ``` @@ -204,6 +203,18 @@ internal_bench/bytebuf: 1 tests performed (3 individual testcases) ``` +## Serial reliability and performance test + +Serial port reliability and performance can be tested using the `serial_test.py` script. +Pass the name of the port to test against, for example: + + $ ./serial_test.py -t /dev/ttyACM0 + +If no port is specified then `/dev/ttyACM0` is used as the default. + +The test will send data out to the target, and receive data from the target, in various +chunk sizes. The throughput of the serial connection will be reported for each sub-test. + ## Test key/certificates SSL/TLS tests in `multi_net` and `net_inet` use self-signed key/cert pairs diff --git a/tests/basics/annotate_var.py.exp b/tests/basics/annotate_var.py.exp deleted file mode 100644 index 9b6536e966b..00000000000 --- a/tests/basics/annotate_var.py.exp +++ /dev/null @@ -1,5 +0,0 @@ -False -1 -(1, 2) -NameError -1 diff --git a/tests/basics/array_add.py b/tests/basics/array_add.py index 76ce59f761e..e78615541c3 100644 --- a/tests/basics/array_add.py +++ b/tests/basics/array_add.py @@ -14,3 +14,9 @@ a1.extend(array.array('I', [5])) print(a1) + +a1.extend([6, 7]) +print(a1) + +a1.extend(i for i in (8, 9)) +print(a1) diff --git a/tests/basics/assign_expr.py.exp b/tests/basics/assign_expr.py.exp deleted file mode 100644 index 47da56b80d4..00000000000 --- a/tests/basics/assign_expr.py.exp +++ /dev/null @@ -1,16 +0,0 @@ -4 -True -2 -4 5 -5 -1 5 5 -5 -2 1 -1 0 -any True -8 -123 -any True -8 -[(1, 0), (2, 2), (3, 6), (4, 12)] -4 diff --git a/tests/basics/assign_expr_scope.py.exp b/tests/basics/assign_expr_scope.py.exp deleted file mode 100644 index 5c780b38221..00000000000 --- a/tests/basics/assign_expr_scope.py.exp +++ /dev/null @@ -1,23 +0,0 @@ -scope0 -1 -None -scope1 -[1] -1 -None -scope2 -[0, 1] -1 -1 -scope3 -[0, 1] -None -None -scope4 -[0, 1] -1 -1 -scope5 -[0, 1] -1 -None diff --git a/tests/basics/async_await.py.exp b/tests/basics/async_await.py.exp deleted file mode 100644 index b51c388a933..00000000000 --- a/tests/basics/async_await.py.exp +++ /dev/null @@ -1,32 +0,0 @@ -4 -3 -2 -1 -0 -0 -1 -0 -0 -2 -1 -0 -0 -1 -0 -0 -3 -2 -1 -0 -0 -1 -0 -0 -2 -1 -0 -0 -1 -0 -0 -finished diff --git a/tests/basics/async_await2.py.exp b/tests/basics/async_await2.py.exp deleted file mode 100644 index fc9ff0aa535..00000000000 --- a/tests/basics/async_await2.py.exp +++ /dev/null @@ -1,5 +0,0 @@ -wait value: 1 -return from send: message from wait(1) -wait got back: message from main -x = 100 -got StopIteration diff --git a/tests/basics/async_def.py.exp b/tests/basics/async_def.py.exp deleted file mode 100644 index f555ace99ab..00000000000 --- a/tests/basics/async_def.py.exp +++ /dev/null @@ -1,3 +0,0 @@ -decorator -foo -StopIteration diff --git a/tests/basics/async_for.py.exp b/tests/basics/async_for.py.exp deleted file mode 100644 index 6f59979c065..00000000000 --- a/tests/basics/async_for.py.exp +++ /dev/null @@ -1,51 +0,0 @@ -== start == -init -aiter -init -anext -a -anext -b -anext -c -anext -== finish == -== start == -init -aiter -init -anext -d -anext -e -anext -f -anext -AsyncIteratorWrapper-def -== finish == -init -== start == -aiter -init -anext -g -anext -h -anext -i -anext -AsyncIteratorWrapper-ghi -== finish == -init -== start == -aiter -init -anext -j -anext -k -anext -l -anext -AsyncIteratorWrapper-jkl -== finish == diff --git a/tests/basics/async_for2.py b/tests/basics/async_for2.py index bbdb02c49b2..82232d52fc2 100644 --- a/tests/basics/async_for2.py +++ b/tests/basics/async_for2.py @@ -1,7 +1,7 @@ # test waiting within "async for" __anext__ function # CIRCUITPY-CHANGE -# uPy allows normal generators to be awaitables. +# MicroPython allows normal generators to be awaitables. # CircuitPython does not. # In CircuitPython you need to have an __await__ method on an awaitable like in CPython; # and like in CPython, generators do not have __await__. diff --git a/tests/basics/async_for2.py.exp b/tests/basics/async_for2.py.exp deleted file mode 100644 index 52bbe90c853..00000000000 --- a/tests/basics/async_for2.py.exp +++ /dev/null @@ -1,32 +0,0 @@ -init -aiter -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -x 0 -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -x 1 -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -x 2 -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -x 3 -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -finished diff --git a/tests/basics/async_syntaxerror.py.exp b/tests/basics/async_syntaxerror.py.exp deleted file mode 100644 index 5275689b413..00000000000 --- a/tests/basics/async_syntaxerror.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -SyntaxError -SyntaxError diff --git a/tests/basics/async_with.py.exp b/tests/basics/async_with.py.exp deleted file mode 100644 index 6bbf84cb4b5..00000000000 --- a/tests/basics/async_with.py.exp +++ /dev/null @@ -1,11 +0,0 @@ -enter -body -exit None None -finished -enter -1 -exit error -ValueError -enter -exit -BaseException diff --git a/tests/basics/async_with2.py b/tests/basics/async_with2.py index 5bac38236fe..b18fa6bdee1 100644 --- a/tests/basics/async_with2.py +++ b/tests/basics/async_with2.py @@ -1,7 +1,7 @@ # test waiting within async with enter/exit functions # CIRCUITPY-CHANGE -# uPy allows normal generators to be awaitables. +# MicroPython allows normal generators to be awaitables. # CircuitPython does not. # In CircuitPython you need to have an __await__ method on an awaitable like in CPython; # and like in CPython, generators do not have __await__. diff --git a/tests/basics/async_with2.py.exp b/tests/basics/async_with2.py.exp deleted file mode 100644 index 76b173b4c24..00000000000 --- a/tests/basics/async_with2.py.exp +++ /dev/null @@ -1,17 +0,0 @@ -enter -f start: 10 -coro yielded: 11 -coro yielded: 12 -f returned: 13 -body start -f start: 30 -coro yielded: 31 -coro yielded: 32 -body f returned: 33 -body end -exit None None -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -finished diff --git a/tests/basics/async_with_break.py.exp b/tests/basics/async_with_break.py.exp deleted file mode 100644 index d077a88fad0..00000000000 --- a/tests/basics/async_with_break.py.exp +++ /dev/null @@ -1,15 +0,0 @@ -enter -body -exit None None -finished -enter -body -exit None None -finally -finished -enter -body -exit None None -finally inner -finally outer -finished diff --git a/tests/basics/async_with_return.py.exp b/tests/basics/async_with_return.py.exp deleted file mode 100644 index d077a88fad0..00000000000 --- a/tests/basics/async_with_return.py.exp +++ /dev/null @@ -1,15 +0,0 @@ -enter -body -exit None None -finished -enter -body -exit None None -finally -finished -enter -body -exit None None -finally inner -finally outer -finished diff --git a/tests/basics/attrtuple2.py b/tests/basics/attrtuple2.py new file mode 100644 index 00000000000..081d24b6ae9 --- /dev/null +++ b/tests/basics/attrtuple2.py @@ -0,0 +1,25 @@ +# test os.uname() attrtuple, if available +try: + import os +except ImportError: + print("SKIP") + raise SystemExit + +try: + u = os.uname() +except AttributeError: + print("SKIP") + raise SystemExit + +# test printing of attrtuple +print(str(u).find("machine=") > 0) + +# test read attr +print(isinstance(u.machine, str)) + +# test str modulo operator for attrtuple +impl_str = ("%s " * len(u)) % u +test_str = "" +for val in u: + test_str += val + " " +print(impl_str == test_str) diff --git a/tests/basics/boundmeth1.py b/tests/basics/boundmeth1.py index fe1b454688d..9f08d9bbb25 100644 --- a/tests/basics/boundmeth1.py +++ b/tests/basics/boundmeth1.py @@ -1,6 +1,6 @@ # tests basics of bound methods -# uPy and CPython differ when printing a bound method, so just print the type +# MicroPython and CPython differ when printing a bound method, so just print the type print(type(repr([].append))) diff --git a/tests/basics/builtin_help.py b/tests/basics/builtin_help.py index 6ec39653fe9..3d4e4f26bd2 100644 --- a/tests/basics/builtin_help.py +++ b/tests/basics/builtin_help.py @@ -14,4 +14,10 @@ help(micropython) # help for a module help('modules') # list available modules +class A: + x = 1 + y = 2 + del x +help(A) + print('done') # so last bit of output is predictable diff --git a/tests/basics/builtin_pow3_intbig.py b/tests/basics/builtin_pow3_intbig.py index bedc8b36b7e..41d2acbc0cc 100644 --- a/tests/basics/builtin_pow3_intbig.py +++ b/tests/basics/builtin_pow3_intbig.py @@ -20,3 +20,8 @@ print(hex(pow(y, x-1, x))) # Should be 1, since x is prime print(hex(pow(y, y-1, x))) # Should be a 'big value' print(hex(pow(y, y-1, y))) # Should be a 'big value' + +try: + print(pow(1, 2, 0)) +except ValueError: + print("ValueError") diff --git a/tests/basics/builtin_range.py b/tests/basics/builtin_range.py index 66226bad16a..9608a816310 100644 --- a/tests/basics/builtin_range.py +++ b/tests/basics/builtin_range.py @@ -32,13 +32,29 @@ print(range(1, 4)[0:]) print(range(1, 4)[1:]) print(range(1, 4)[:-1]) +print(range(4, 1)[:]) +print(range(4, 1)[0:]) +print(range(4, 1)[1:]) +print(range(4, 1)[:-1]) print(range(7, -2, -4)[:]) print(range(1, 100, 5)[5:15:3]) print(range(1, 100, 5)[15:5:-3]) print(range(100, 1, -5)[5:15:3]) print(range(100, 1, -5)[15:5:-3]) +print(range(1, 100, 5)[5:15:-3]) +print(range(1, 100, 5)[15:5:3]) +print(range(100, 1, -5)[5:15:-3]) +print(range(100, 1, -5)[15:5:3]) +print(range(1, 100, 5)[5:15:3]) +print(range(1, 100, 5)[15:5:-3]) +print(range(1, 100, -5)[5:15:3]) +print(range(1, 100, -5)[15:5:-3]) +print(range(1, 100, 5)[5:15:-3]) +print(range(1, 100, 5)[15:5:3]) +print(range(1, 100, -5)[5:15:-3]) +print(range(1, 100, -5)[15:5:3]) -# for this case uPy gives a different stop value but the listed elements are still correct +# for this case MicroPython gives a different stop value but the listed elements are still correct print(list(range(7, -2, -4)[2:-2:])) # zero step diff --git a/tests/basics/builtin_range_maxsize.py b/tests/basics/builtin_range_maxsize.py new file mode 100644 index 00000000000..b0f3a5e5129 --- /dev/null +++ b/tests/basics/builtin_range_maxsize.py @@ -0,0 +1,38 @@ +try: + from sys import maxsize +except ImportError: + print("SKIP") + raise SystemExit + +# Test the range builtin at extreme values. (https://github.com/micropython/micropython/issues/17684) +# +# This is written using asserts instead of prints because the value of `maxsize` differs. +# +# Numbers & counts right up against the max of mp_int_t also cause overflows, such as +# objrange.c:115:14: runtime error: signed integer overflow: 9223372036854775807 + 1 cannot be represented in type 'long int' +# so just avoid them for the purposes of this test. + +r = range(-maxsize + 1, -1) +assert r.start == -maxsize + 1 +assert r.stop == -1 +assert r[0] == -maxsize + 1 +assert r[1] == -maxsize + 2 +assert r[-1] == -2 +assert r[-2] == -3 + +ir = iter(r) +assert next(ir) == -maxsize + 1 +assert next(ir) == -maxsize + 2 + +r = range(0, maxsize - 1) +assert len(r) == maxsize - 1 +assert r.stop == maxsize - 1 + +r = range(maxsize, 0, -1) +assert len(r) == maxsize +assert r.start == maxsize +assert r[0] == maxsize +assert r[1] == maxsize - 1 +ir = iter(r) +assert next(ir) == maxsize +assert next(ir) == maxsize - 1 diff --git a/tests/basics/builtin_setattr.py b/tests/basics/builtin_setattr.py index e4acb14cac3..2c9a452c327 100644 --- a/tests/basics/builtin_setattr.py +++ b/tests/basics/builtin_setattr.py @@ -21,5 +21,5 @@ def __init__(self): try: setattr(int, 'to_bytes', 1) except (AttributeError, TypeError): - # uPy raises AttributeError, CPython raises TypeError + # MicroPython raises AttributeError, CPython raises TypeError print('AttributeError/TypeError') diff --git a/tests/basics/builtin_slice.py b/tests/basics/builtin_slice.py index 3ff3c3dd04d..cbce3d14ed6 100644 --- a/tests/basics/builtin_slice.py +++ b/tests/basics/builtin_slice.py @@ -1,11 +1,44 @@ # test builtin slice +# ensures that slices passed to user types are heap-allocated and can be +# safely stored as well as not overridden by subsequent slices. + # print slice class A: def __getitem__(self, idx): - print(idx) + print("get", idx) + print("abc"[1:]) + print("get", idx) + return idx + + def __setitem__(self, idx, value): + print("set", idx) + print("abc"[1:]) + print("set", idx) + self.saved_idx = idx + return idx + + def __delitem__(self, idx): + print("del", idx) + print("abc"[1:]) + print("del", idx) return idx -s = A()[1:2:3] + + +a = A() +s = a[1:2:3] +a[4:5:6] = s +del a[7:8:9] + +print(a.saved_idx) + +# nested slicing +print(A()[1 : A()[A()[2:3:4] : 5]]) + +# tuple slicing +a[1:2, 4:5, 7:8] +a[1, 4:5, 7:8, 2] +a[1:2, a[3:4], 5:6] # check type print(type(s) is slice) diff --git a/tests/basics/bytes_format_modulo.py.exp b/tests/basics/bytes_format_modulo.py.exp deleted file mode 100644 index 782b7f91fcb..00000000000 --- a/tests/basics/bytes_format_modulo.py.exp +++ /dev/null @@ -1,5 +0,0 @@ -b'%' -b'=1=' -b'=1=2=' -b'=str=' -b"=b'str'=" diff --git a/tests/basics/class_bind_self.py b/tests/basics/class_bind_self.py index 813f876446e..8bece902ca2 100644 --- a/tests/basics/class_bind_self.py +++ b/tests/basics/class_bind_self.py @@ -52,7 +52,7 @@ def f4(self, arg): # generator print(C.f8(13)) print(C.f9(14)) -# not working in uPy +# not working in MicroPython #class C(list): # # this acts like a method and binds self # f1 = list.extend diff --git a/tests/basics/class_descriptor.py b/tests/basics/class_descriptor.py index 83d31674301..feaed2fbb2a 100644 --- a/tests/basics/class_descriptor.py +++ b/tests/basics/class_descriptor.py @@ -1,22 +1,28 @@ class Descriptor: def __get__(self, obj, cls): - print('get') + print("get") print(type(obj) is Main) print(cls is Main) - return 'result' + return "result" def __set__(self, obj, val): - print('set') + print("set") print(type(obj) is Main) print(val) def __delete__(self, obj): - print('delete') + print("delete") print(type(obj) is Main) + def __set_name__(self, owner, name): + print("set_name", name) + print(owner.__name__ == "Main") + + class Main: Forward = Descriptor() + m = Main() try: m.__class__ @@ -26,15 +32,15 @@ class Main: raise SystemExit r = m.Forward -if 'Descriptor' in repr(r.__class__): +if "Descriptor" in repr(r.__class__): # Target doesn't support descriptors. - print('SKIP') + print("SKIP") raise SystemExit # Test assignment and deletion. print(r) -m.Forward = 'a' +m.Forward = "a" del m.Forward # Test that lookup of descriptors like __get__ are not passed into __getattr__. diff --git a/tests/basics/class_inplace_op2.py.exp b/tests/basics/class_inplace_op2.py.exp deleted file mode 100644 index 8c323b5178e..00000000000 --- a/tests/basics/class_inplace_op2.py.exp +++ /dev/null @@ -1,12 +0,0 @@ -__imul__ -__imatmul__ -__ifloordiv__ -__itruediv__ -__imod__ -__ipow__ -__ior__ -__ixor__ -__iand__ -__ilshift__ -__irshift__ -TypeError diff --git a/tests/basics/class_ordereddict.py.exp b/tests/basics/class_ordereddict.py.exp deleted file mode 100644 index b723e327515..00000000000 --- a/tests/basics/class_ordereddict.py.exp +++ /dev/null @@ -1 +0,0 @@ -['a', 'b', 'c', 'd', 'e'] diff --git a/tests/basics/class_setname_hazard.py b/tests/basics/class_setname_hazard.py new file mode 100644 index 00000000000..77c04093462 --- /dev/null +++ b/tests/basics/class_setname_hazard.py @@ -0,0 +1,182 @@ +# Test that __set_name__ can access and mutate its owner argument. + + +def skip_if_no_descriptors(): + class Descriptor: + def __get__(self, obj, cls): + return + + class TestClass: + Forward = Descriptor() + + a = TestClass() + try: + a.__class__ + except AttributeError: + # Target doesn't support __class__. + print("SKIP") + raise SystemExit + + b = a.Forward + if "Descriptor" in repr(b.__class__): + # Target doesn't support descriptors. + print("SKIP") + raise SystemExit + + +skip_if_no_descriptors() + + +# Test basic accesses and mutations. + + +class GetSibling: + def __set_name__(self, owner, name): + print(getattr(owner, name + "_sib")) + + +class GetSiblingTest: + desc = GetSibling() + desc_sib = 111 + + +t110 = GetSiblingTest() + + +class SetSibling: + def __set_name__(self, owner, name): + setattr(owner, name + "_sib", 121) + + +class SetSiblingTest: + desc = SetSibling() + + +t120 = SetSiblingTest() + +print(t120.desc_sib) + + +class DelSibling: + def __set_name__(self, owner, name): + delattr(owner, name + "_sib") + + +class DelSiblingTest: + desc = DelSibling() + desc_sib = 131 + + +t130 = DelSiblingTest() + +try: + print(t130.desc_sib) +except AttributeError: + print("AttributeError") + + +class GetSelf: + x = 211 + + def __set_name__(self, owner, name): + print(getattr(owner, name).x) + + +class GetSelfTest: + desc = GetSelf() + + +t210 = GetSelfTest() + + +class SetSelf: + def __set_name__(self, owner, name): + setattr(owner, name, 221) + + +class SetSelfTest: + desc = SetSelf() + + +t220 = SetSelfTest() + +print(t220.desc) + + +class DelSelf: + def __set_name__(self, owner, name): + delattr(owner, name) + + +class DelSelfTest: + desc = DelSelf() + + +t230 = DelSelfTest() + +try: + print(t230.desc) +except AttributeError: + print("AttributeError") + + +# Test exception behavior. + + +class Raise: + def __set_name__(self, owner, name): + raise Exception() + + +try: + + class RaiseTest: + desc = Raise() +except Exception as e: # CPython raises RuntimeError, MicroPython propagates the original exception + print("Exception") + + +# Ensure removed/overwritten class members still get __set_name__ called. + + +class SetSpecific: + def __init__(self, sib_name, sib_replace): + self.sib_name = sib_name + self.sib_replace = sib_replace + + def __set_name__(self, owner, name): + setattr(owner, self.sib_name, self.sib_replace) + + +class SetReplaceTest: + a = SetSpecific("b", 312) # one of these is changed first + b = SetSpecific("a", 311) + + +t310 = SetReplaceTest() +print(t310.a) +print(t310.b) + + +class DelSpecific: + def __init__(self, sib_name): + self.sib_name = sib_name + + def __set_name__(self, owner, name): + delattr(owner, self.sib_name) + + +class DelReplaceTest: + a = DelSpecific("b") # one of these is removed first + b = DelSpecific("a") + + +t320 = DelReplaceTest() +try: + print(t320.a) +except AttributeError: + print("AttributeError") +try: + print(t320.b) +except AttributeError: + print("AttributeError") diff --git a/tests/basics/class_setname_hazard_rand.py b/tests/basics/class_setname_hazard_rand.py new file mode 100644 index 00000000000..4c9934c3bf0 --- /dev/null +++ b/tests/basics/class_setname_hazard_rand.py @@ -0,0 +1,111 @@ +# Test to make sure there's no sequence hazard even when a __set_name__ implementation +# mutates and reorders the namespace of its owner class. +# VERY hard bug to prove out except via a stochastic test. + + +try: + from random import choice + import re +except ImportError: + print("SKIP") + raise SystemExit + + +def skip_if_no_descriptors(): + class Descriptor: + def __get__(self, obj, cls): + return + + class TestClass: + Forward = Descriptor() + + a = TestClass() + try: + a.__class__ + except AttributeError: + # Target doesn't support __class__. + print("SKIP") + raise SystemExit + + b = a.Forward + if "Descriptor" in repr(b.__class__): + # Target doesn't support descriptors. + print("SKIP") + raise SystemExit + + +skip_if_no_descriptors() + +letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +# Would be r"[A-Z]{5}", but not all ports support the {n} quantifier. +junk_re = re.compile(r"[A-Z][A-Z][A-Z][A-Z][A-Z]") + + +def junk_fill(obj, n=10): # Add randomly-generated attributes to an object. + for i in range(n): + name = "".join(choice(letters) for j in range(5)) + setattr(obj, name, object()) + + +def junk_clear(obj): # Remove attributes added by junk_fill. + to_del = [name for name in dir(obj) if junk_re.match(name)] + for name in to_del: + delattr(obj, name) + + +def junk_sequencer(): + global runs + try: + while True: + owner, name = yield + runs[name] = runs.get(name, 0) + 1 + junk_fill(owner) + finally: + junk_clear(owner) + + +class JunkMaker: + def __set_name__(self, owner, name): + global seq + seq.send((owner, name)) + + +runs = {} +seq = junk_sequencer() +next(seq) + + +class Main: + a = JunkMaker() + b = JunkMaker() + c = JunkMaker() + d = JunkMaker() + e = JunkMaker() + f = JunkMaker() + g = JunkMaker() + h = JunkMaker() + i = JunkMaker() + j = JunkMaker() + k = JunkMaker() + l = JunkMaker() + m = JunkMaker() + n = JunkMaker() + o = JunkMaker() + p = JunkMaker() + q = JunkMaker() + r = JunkMaker() + s = JunkMaker() + t = JunkMaker() + u = JunkMaker() + v = JunkMaker() + w = JunkMaker() + x = JunkMaker() + y = JunkMaker() + z = JunkMaker() + + +seq.close() + +for k in letters.lower(): + print(k, runs.get(k, 0)) diff --git a/tests/basics/del_attr.py b/tests/basics/del_attr.py index 8487b97e311..90a8a5a6f83 100644 --- a/tests/basics/del_attr.py +++ b/tests/basics/del_attr.py @@ -35,5 +35,5 @@ def f(): try: del int.to_bytes except (AttributeError, TypeError): - # uPy raises AttributeError, CPython raises TypeError + # MicroPython raises AttributeError, CPython raises TypeError print('AttributeError/TypeError') diff --git a/tests/basics/del_global.py b/tests/basics/del_global.py index d740357b033..e1aa074b97a 100644 --- a/tests/basics/del_global.py +++ b/tests/basics/del_global.py @@ -14,7 +14,7 @@ def do_del(): try: do_del() except: # NameError: - # FIXME uPy returns KeyError for this + # FIXME MicroPython returns KeyError for this print("NameError") # delete globals using a list diff --git a/tests/basics/del_name.py b/tests/basics/del_name.py index c92be54d3b6..8393b2df92a 100644 --- a/tests/basics/del_name.py +++ b/tests/basics/del_name.py @@ -10,7 +10,7 @@ try: del x except: # NameError: - # FIXME uPy returns KeyError for this + # FIXME MicroPython returns KeyError for this print("NameError") class C: diff --git a/tests/basics/dict_views.py b/tests/basics/dict_views.py index a82f47b6be2..45f3238f1c6 100644 --- a/tests/basics/dict_views.py +++ b/tests/basics/dict_views.py @@ -6,6 +6,11 @@ # print a view with more than one item print({1:1, 2:1}.values()) +# `bool` and `len` unary ops +for d in ({}, {1: 2}, {1: 2, 3: 4}): + for op in (bool, len): + print(op(d.keys()), op(d.values()), op(d.items())) + # unsupported binary op on a dict values view try: {1:1}.values() + 1 diff --git a/tests/basics/exception_chain.py b/tests/basics/exception_chain.py index 579756c85fa..96c06c847ab 100644 --- a/tests/basics/exception_chain.py +++ b/tests/basics/exception_chain.py @@ -1,5 +1,12 @@ # CIRCUITPY-CHANGE: exception chaining is supported +import sys + +# The unix minimal build doesn't enable MICROPY_WARNINGS (required for this test). +if getattr(sys.implementation, "_build", None) == "minimal": + print("SKIP") + raise SystemExit + try: Exception().__cause__ except AttributeError: diff --git a/tests/basics/frozenset_set.py b/tests/basics/frozenset_set.py index 3bf456acfd7..2b3c6832609 100644 --- a/tests/basics/frozenset_set.py +++ b/tests/basics/frozenset_set.py @@ -8,5 +8,5 @@ # "Instances of set are compared to instances of frozenset based on their # members. For example:" print(set('abc') == frozenset('abc')) -# This doesn't work in uPy +# This doesn't work in MicroPython #print(set('abc') in set([frozenset('abc')])) diff --git a/tests/basics/fun_code_colines.py b/tests/basics/fun_code_colines.py new file mode 100644 index 00000000000..a8867770edd --- /dev/null +++ b/tests/basics/fun_code_colines.py @@ -0,0 +1,81 @@ +# Check that we have sensical bytecode offsets in function.__code__.co_lines + +def f1(x, y, obj, obj2, obj3): + a = x + y # line 4: bc+4 line+4 + b = x - y # line 5: bc+4 line+1 + # line 6 + # line 7 + # line 8 + # line 9 + # line 10 + # line 11 + # line 12 + # line 13 + # line 14 + # line 15 + # line 16 + # line 17 + # line 18 + # line 19 + c = a * b # line 20: bc+4 line+15 + obj.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.fun() # line 21: bc+31 line+1; bc+27 line+0 + # line 22 + # line 23 + # line 24: bc+0 line+3 + # line 25 + # line 26 + # line 27: bc+0 line+3 + # line 28 + # line 29 + obj2.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.fun() # line 30: bc+31 line+3; bc+27 line+0 + # line 31 + # line 32 + # line 33: bc+0 line+3 + # line 34 + # line 35 + # line 36 + # line 37 + # line 38 + # line 39 + # line 40 + # line 41 + # line 42 + # line 43 + # line 44 + # line 45 + # line 46 + # line 47 + # line 48 + # line 49 + # line 50 + # line 51 + # line 52 + # line 53 + # line 54 + # line 55 + # line 56 + # line 57 + # line 58 + # line 59 + return obj3.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.fun() # line 60: bc+31 line+27; bc+27 line+0 + +def f2(x, y): + a = x + y # line 63 + b = x - y # line 64 + return a * b # line 65 + +try: + f1.__code__.co_lines +except AttributeError: + print("SKIP") + raise SystemExit + +print("f1") +for start, end, line_no in f1.__code__.co_lines(): + print("line {} start: {}".format(line_no, start)) + print("line {} end: {}".format(line_no, end)) + +print("f2") +for start, end, line_no in f2.__code__.co_lines(): + print("line {} start: {}".format(line_no, start)) + print("line {} end: {}".format(line_no, end)) diff --git a/tests/basics/fun_code_colines.py.exp b/tests/basics/fun_code_colines.py.exp new file mode 100644 index 00000000000..19bd4ef6e2a --- /dev/null +++ b/tests/basics/fun_code_colines.py.exp @@ -0,0 +1,20 @@ +f1 +line 4 start: 0 +line 4 end: 4 +line 5 start: 4 +line 5 end: 8 +line 20 start: 8 +line 20 end: 12 +line 21 start: 12 +line 21 end: 70 +line 30 start: 70 +line 30 end: 128 +line 60 start: 128 +line 60 end: 186 +f2 +line 63 start: 0 +line 63 end: 4 +line 64 start: 4 +line 64 end: 8 +line 65 start: 8 +line 65 end: 12 diff --git a/tests/basics/fun_code_full.py b/tests/basics/fun_code_full.py new file mode 100644 index 00000000000..538863631a6 --- /dev/null +++ b/tests/basics/fun_code_full.py @@ -0,0 +1,38 @@ +# Test function.__code__ attributes not available with MICROPY_PY_BUILTINS_CODE <= MICROPY_PY_BUILTINS_CODE_BASIC + +try: + (lambda: 0).__code__.co_code +except AttributeError: + print("SKIP") + raise SystemExit + +def f(x, y): + a = x + y + b = x - y + return a * b + +code = f.__code__ + +print(type(code.co_code)) # both bytes (but mpy and cpy have different instruction sets) +print(code.co_consts) # (not necessarily the same set, but in this function they are) +print(code.co_filename.rsplit('/')[-1]) # same terminal filename but might be different paths on other ports +print(type(code.co_firstlineno)) # both ints (but mpy points to first line inside, cpy points to declaration) +print(code.co_name) +print(iter(code.co_names) is not None) # both iterable (but mpy returns dict with names as keys, cpy only the names; and not necessarily the same set) + +co_lines = code.co_lines() + +l = list(co_lines) +first_start = l[0][0] +last_end = l[-1][1] +print(first_start) # co_lines should start at the start of the bytecode +print(len(code.co_code) - last_end) # and end at the end of the bytecode + +prev_end = 0 +for start, end, line_no in l: + if end != prev_end: + print("non-contiguous") + break # the offset ranges should be contiguous + prev_end = end +else: + print("contiguous") diff --git a/tests/basics/fun_code_full.py.exp b/tests/basics/fun_code_full.py.exp new file mode 100644 index 00000000000..830effadfc6 --- /dev/null +++ b/tests/basics/fun_code_full.py.exp @@ -0,0 +1,9 @@ + +(None,) +fun_code_full.py + +f +True +0 +0 +non-contiguous diff --git a/tests/basics/fun_code_lnotab.py b/tests/basics/fun_code_lnotab.py new file mode 100644 index 00000000000..9223e5730f0 --- /dev/null +++ b/tests/basics/fun_code_lnotab.py @@ -0,0 +1,34 @@ +# Test deprecation of co_lnotab + +try: + (lambda: 0).__code__.co_code +except AttributeError: + print("SKIP") + raise SystemExit + + +import unittest +import sys + + +mpy_is_v2 = getattr(sys.implementation, '_v2', False) + + +def f(): + pass + + +class Test(unittest.TestCase): + + @unittest.skipIf(mpy_is_v2, "Removed in MicroPython v2 and later.") + def test_co_lnotab_exists(self): + self.assertIsInstance(f.__code__.co_lnotab, bytes) + + @unittest.skipUnless(mpy_is_v2, "Not removed before MicroPython v2.") + def test_co_lnotab_removed(self): + with self.assertRaises(AttributeError): + f.__code__.co_lnotab + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/basics/fun_name.py b/tests/basics/fun_name.py index b2642280a2a..8aac35eeafa 100644 --- a/tests/basics/fun_name.py +++ b/tests/basics/fun_name.py @@ -16,7 +16,7 @@ def Fun(self): print('SKIP') raise SystemExit -# __name__ of a bound native method is not implemented in uPy +# __name__ of a bound native method is not implemented in MicroPython # the test here is to make sure it doesn't crash try: str((1).to_bytes.__name__) diff --git a/tests/basics/gc1.py b/tests/basics/gc1.py index 332bf9744c0..dff9538b14b 100644 --- a/tests/basics/gc1.py +++ b/tests/basics/gc1.py @@ -15,13 +15,13 @@ gc.collect() if hasattr(gc, 'mem_free'): - # uPy has these extra functions + # MicroPython has these extra functions # just test they execute and return an int assert type(gc.mem_free()) is int assert type(gc.mem_alloc()) is int if hasattr(gc, 'threshold'): - # uPy has this extra function + # MicroPython has this extra function # check execution and returns assert(gc.threshold(1) is None) assert(gc.threshold() == 0) diff --git a/tests/basics/import_instance_method.py b/tests/basics/import_instance_method.py new file mode 100644 index 00000000000..d25b70ac5f0 --- /dev/null +++ b/tests/basics/import_instance_method.py @@ -0,0 +1,38 @@ +# Test importing a method from a class instance. +# This is not a common thing to do, but ensures MicroPython has the same semantics as CPython. + +import sys + +if not hasattr(sys, "modules"): + print("SKIP") + raise SystemExit + + +class A: + def __init__(self, value): + self.value = value + + def meth(self): + return self.value + + def meth_with_arg(self, a): + return [self.value, a] + + +# Register a class instance as the module "mod". +sys.modules["mod"] = A(1) + +# Try importing it as a module. +import mod + +print(mod.meth()) +print(mod.meth_with_arg(2)) + +# Change the module. +sys.modules["mod"] = A(3) + +# Try importing it using "from ... import". +from mod import meth, meth_with_arg + +print(meth()) +print(meth_with_arg(4)) diff --git a/tests/basics/int_64_basics.py b/tests/basics/int_64_basics.py new file mode 100644 index 00000000000..ef76793317e --- /dev/null +++ b/tests/basics/int_64_basics.py @@ -0,0 +1,161 @@ +# test support for 64-bit long integers +# (some ports don't support arbitrary precision but do support these) + +# this test is adapted from int_big1.py with numbers kept within 64-bit signed range + +# to test arbitrary precision integers + +x = 1000000000000000000 +xn = -1000000000000000000 +y = 2000000000000000000 + +# printing +print(x) +print(y) +print('%#X' % (x - x)) # print prefix +print('{:#,}'.format(x)) # print with commas + +# construction +print(int(x)) + +# addition +print(x + 1) +print(x + y) +print(x + xn == 0) +print(bool(x + xn)) + +# subtraction +print(x - 1) +print(x - y) +print(y - x) +print(x - x == 0) +print(bool(x - x)) + +# multiplication +print(x * 2) +print(1090511627776 * 1048500) + +# integer division +print(x // 2) +print(y // x) + +# bit inversion +print(~x) +print(~(-x)) + +# left shift +print("left shift positive") +x = 0x40000000 +for i in range(32): + x = x << 1 + print(x) + +# right shift +print("right shift positive") +x = 0x2000000000000000 # TODO: why can't second-tip bit be set? +for i in range(64): + x = x >> 1 + print(x) + +# left shift of a negative number +print("left shift negative") +for i in range(8): + print(-10000000000000000 << i) + print(-10000000000000001 << i) + print(-10000000000000002 << i) + print(-10000000000000003 << i) + print(-10000000000000004 << i) + + +# right shift of a negative number +print("right shift negative") +for i in range(8): + print(-1000000000000000000 >> i) + print(-1000000000000000001 >> i) + print(-1000000000000000002 >> i) + print(-1000000000000000003 >> i) + print(-1000000000000000004 >> i) + +# conversion from string +print(int("1234567890123456789")) +print(int("-1234567890123456789")) +print(int("1234567890abcdef", 16)) +print(int("1234567890ABCDEF", 16)) +print(int("-1234567890ABCDEF", 16)) +print(int("ijklmnopqrsz", 36)) + +# numbers close to 64-bit limits +print(int("-9111222333444555666")) +print(int("9111222333444555666")) + +# numbers with preceding 0s +print(int("-00000000000000000000009111222333444555666")) +print(int("0000000000000000000000009111222333444555666")) + +# invalid characters in string +try: + print(int("1234567890abcdef")) +except ValueError: + print('ValueError'); +try: + print(int("123456789\x01")) +except ValueError: + print('ValueError'); + +# test parsing ints just on threshold of small to big +# for 32 bit archs +x = 1073741823 # small +x = -1073741823 # small +x = 1073741824 # big +x = -1073741824 # big +# for 64 bit archs +x = 4611686018427387903 # small +x = -4611686018427387903 # small +x = 4611686018427387904 # big +x = -4611686018427387904 # big + +# sys.maxsize is a constant bigint, so test it's compatible with dynamic ones +import sys +if hasattr(sys, "maxsize"): + print(sys.maxsize - 1 + 1 == sys.maxsize) +else: + print(True) # No maxsize property in this config + +# test extraction of big int value via mp_obj_get_int_maybe +x = 1 << 62 +print('a' * (x + 4 - x)) + +# test overflow check in mp_obj_get_int_maybe +x = 1 << 32 +r = None +try: + r = range(0, x) +except OverflowError: + # 32-bit target, correctly handled the overflow of x + print("ok") +if r is not None: + if len(r) == x: + # 64-bit target, everything is just a small-int + print("ok") + else: + # 32-bit target that did not handle the overflow of x + print("unhandled overflow") + +# negative shifts are invalid +try: + print((1 << 48) >> -4) +except ValueError as e: + print(e) + +try: + print((1 << 48) << -6) +except ValueError as e: + print(e) + +# Test that the most extreme 64 bit integer values all parse with int() +print(int("-9223372036854775807")) +print(int("-9223372036854775808")) +print(int("9223372036854775807")) + +# Test that the most negative 64 bit integer can be formed via arithmetic +print(-9223372036854775807-1) diff --git a/tests/basics/int_big_to_small.py b/tests/basics/int_big_to_small.py index 64280d0c635..c92d263fc28 100644 --- a/tests/basics/int_big_to_small.py +++ b/tests/basics/int_big_to_small.py @@ -5,6 +5,17 @@ print("SKIP") raise SystemExit +# Skip this test on "REPR B" where (1<<29 + 1) is not a small int. +k = 1 << 29 +micropython.heap_lock() +try: + k = k + 1 +except MemoryError: + print("SKIP") + raise SystemExit +finally: + micropython.heap_unlock() + # All less than small int max. for d in (0, 27, 1<<29, -1861, -(1<<29)): i = 1<<70 diff --git a/tests/basics/int_big_to_small_int29.py b/tests/basics/int_big_to_small_int29.py new file mode 100644 index 00000000000..438a74d2bc6 --- /dev/null +++ b/tests/basics/int_big_to_small_int29.py @@ -0,0 +1,22 @@ +try: + import micropython + micropython.heap_lock +except: + print("SKIP") + raise SystemExit + +# All less than small int max. +for d in (0, 27, 1<<28, -1861, -(1<<28)): + i = 1<<70 + print(i) + j = (1<<70) + d + print(j) + # k should now be a small int. + k = j - i + print(k) + + # Now verify that working with k doesn't allocate (i.e. it's a small int). + micropython.heap_lock() + print(k + 20) + print(k // 20) + micropython.heap_unlock() diff --git a/tests/basics/int_big_to_small_int29.py.exp b/tests/basics/int_big_to_small_int29.py.exp new file mode 100644 index 00000000000..0920101924a --- /dev/null +++ b/tests/basics/int_big_to_small_int29.py.exp @@ -0,0 +1,25 @@ +1180591620717411303424 +1180591620717411303424 +0 +20 +0 +1180591620717411303424 +1180591620717411303451 +27 +47 +1 +1180591620717411303424 +1180591620717679738880 +268435456 +268435476 +13421772 +1180591620717411303424 +1180591620717411301563 +-1861 +-1841 +-94 +1180591620717411303424 +1180591620717142867968 +-268435456 +-268435436 +-13421773 diff --git a/tests/basics/io_buffered_writer.py b/tests/basics/io_buffered_writer.py index 11df0324e24..3cfee0103f7 100644 --- a/tests/basics/io_buffered_writer.py +++ b/tests/basics/io_buffered_writer.py @@ -1,10 +1,10 @@ -import io - try: + import io + io.BytesIO io.BufferedWriter -except AttributeError: - print("SKIP") +except (AttributeError, ImportError): + print('SKIP') raise SystemExit bts = io.BytesIO() @@ -28,3 +28,27 @@ # hashing a BufferedWriter print(type(hash(buf))) + +# Test failing flush() +class MyIO(io.IOBase): + def __init__(self): + self.count = 0 + + def write(self, buf): + self.count += 1 + if self.count < 3: + return None + print("writing", buf) + return len(buf) + + +buf = io.BufferedWriter(MyIO(), 8) + +buf.write(b"foobar") + +for _ in range(4): + try: + buf.flush() + print("flushed") + except OSError: + print("OSError") diff --git a/tests/basics/io_buffered_writer.py.exp b/tests/basics/io_buffered_writer.py.exp index 2209348f5af..d61eb148b45 100644 --- a/tests/basics/io_buffered_writer.py.exp +++ b/tests/basics/io_buffered_writer.py.exp @@ -4,3 +4,8 @@ b'foobarfoobar' b'foobarfoobar' b'foo' +OSError +OSError +writing bytearray(b'foobar') +flushed +flushed diff --git a/tests/basics/io_bytesio_cow.py b/tests/basics/io_bytesio_cow.py index 2edb7136a96..543c12ad42a 100644 --- a/tests/basics/io_bytesio_cow.py +++ b/tests/basics/io_bytesio_cow.py @@ -1,6 +1,12 @@ # Make sure that write operations on io.BytesIO don't # change original object it was constructed from. -import io + +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + b = b"foobar" a = io.BytesIO(b) diff --git a/tests/basics/io_bytesio_ext.py b/tests/basics/io_bytesio_ext.py index 4d4c60c1363..92e71517811 100644 --- a/tests/basics/io_bytesio_ext.py +++ b/tests/basics/io_bytesio_ext.py @@ -1,5 +1,11 @@ # Extended stream operations on io.BytesIO -import io + +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + a = io.BytesIO(b"foobar") a.seek(10) print(a.read(10)) diff --git a/tests/basics/io_bytesio_ext2.py b/tests/basics/io_bytesio_ext2.py index 414ac90a3b0..f60a6a9a604 100644 --- a/tests/basics/io_bytesio_ext2.py +++ b/tests/basics/io_bytesio_ext2.py @@ -1,4 +1,9 @@ -import io +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + a = io.BytesIO(b"foobar") try: a.seek(-10) diff --git a/tests/basics/io_iobase.py b/tests/basics/io_iobase.py index b2ee5cd63a6..31f2616310e 100644 --- a/tests/basics/io_iobase.py +++ b/tests/basics/io_iobase.py @@ -1,15 +1,17 @@ import io try: + import io + io.IOBase -except AttributeError: +except (AttributeError, ImportError): print("SKIP") raise SystemExit class MyIO(io.IOBase): def write(self, buf): - # CPython and uPy pass in different types for buf (str vs bytearray) - print("write", len(buf)) + # CPython and MicroPython pass in different types for buf (str vs bytearray) + print('write', len(buf)) return len(buf) -print("test", file=MyIO()) +print('test', file=MyIO()) diff --git a/tests/basics/io_stringio1.py b/tests/basics/io_stringio1.py index 7d355930f5a..889e3ce6973 100644 --- a/tests/basics/io_stringio1.py +++ b/tests/basics/io_stringio1.py @@ -1,4 +1,9 @@ -import io +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + a = io.StringIO() print('io.StringIO' in repr(a)) print(a.getvalue()) diff --git a/tests/basics/io_stringio_base.py b/tests/basics/io_stringio_base.py index 0f65fb3fabc..c8890dab73a 100644 --- a/tests/basics/io_stringio_base.py +++ b/tests/basics/io_stringio_base.py @@ -1,7 +1,11 @@ # Checks that an instance type inheriting from a native base that uses # MP_TYPE_FLAG_ITER_IS_STREAM will still have a getiter. -import io +try: + import io +except ImportError: + print("SKIP") + raise SystemExit a = io.StringIO() a.write("hello\nworld\nmicro\npython\n") diff --git a/tests/basics/io_stringio_with.py b/tests/basics/io_stringio_with.py index a3aa6ec84e0..0155ad5382d 100644 --- a/tests/basics/io_stringio_with.py +++ b/tests/basics/io_stringio_with.py @@ -1,4 +1,9 @@ -import io +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + # test __enter__/__exit__ with io.StringIO() as b: b.write("foo") diff --git a/tests/basics/io_write_ext.py b/tests/basics/io_write_ext.py index 79f7450954e..5af1de7a6c3 100644 --- a/tests/basics/io_write_ext.py +++ b/tests/basics/io_write_ext.py @@ -1,11 +1,12 @@ # This tests extended (MicroPython-specific) form of write: # write(buf, len) and write(buf, offset, len) -import io try: + import io + io.BytesIO -except AttributeError: - print("SKIP") +except (AttributeError, ImportError): + print('SKIP') raise SystemExit buf = io.BytesIO() diff --git a/tests/basics/list_pop.py b/tests/basics/list_pop.py index 87ed456f851..58bcdd91e41 100644 --- a/tests/basics/list_pop.py +++ b/tests/basics/list_pop.py @@ -10,7 +10,7 @@ else: raise AssertionError("No IndexError raised") -# popping such that list storage shrinks (tests implementation detail of uPy) +# popping such that list storage shrinks (tests implementation detail of MicroPython) l = list(range(20)) for i in range(len(l)): l.pop() diff --git a/tests/basics/module2.py b/tests/basics/module2.py index a135601579c..d1dc18930f0 100644 --- a/tests/basics/module2.py +++ b/tests/basics/module2.py @@ -1,4 +1,4 @@ -# uPy behaviour only: builtin modules are read-only +# MicroPython behaviour only: builtin modules are read-only import sys try: sys.x = 1 diff --git a/tests/basics/namedtuple1.py b/tests/basics/namedtuple1.py index 362c60583ec..b9689b58423 100644 --- a/tests/basics/namedtuple1.py +++ b/tests/basics/namedtuple1.py @@ -21,6 +21,9 @@ print(isinstance(t, tuple)) + # a NamedTuple can be used as a tuple + print("(%d, %d)" % t) + # Check tuple can compare equal to namedtuple with same elements print(t == (t[0], t[1]), (t[0], t[1]) == t) diff --git a/tests/basics/parser.py b/tests/basics/parser.py index 626b67ad7a9..6ae5f05ba45 100644 --- a/tests/basics/parser.py +++ b/tests/basics/parser.py @@ -7,7 +7,7 @@ raise SystemExit # completely empty string -# uPy and CPy differ for this case +# MPy and CPy differ for this case #try: # compile("", "stdin", "single") #except SyntaxError: diff --git a/tests/basics/python34.py b/tests/basics/python34.py index 922234d22db..3071b55eff8 100644 --- a/tests/basics/python34.py +++ b/tests/basics/python34.py @@ -28,7 +28,7 @@ def test_syntax(code): test_syntax("del ()") # can't delete empty tuple (in 3.6 we can) # from basics/sys1.py -# uPy prints version 3.4 +# MicroPython prints version 3.4 import sys print(sys.version[:3]) print(sys.version_info[0], sys.version_info[1]) diff --git a/tests/basics/python36.py.exp b/tests/basics/python36.py.exp deleted file mode 100644 index 4b65daafa18..00000000000 --- a/tests/basics/python36.py.exp +++ /dev/null @@ -1,5 +0,0 @@ -100000 -165 -65535 -123 -83 diff --git a/tests/basics/self_type_check.py b/tests/basics/self_type_check.py index 3bd5b3eed60..5f6f6f2ca65 100644 --- a/tests/basics/self_type_check.py +++ b/tests/basics/self_type_check.py @@ -3,6 +3,14 @@ import skip_if skip_if.board_in("gemma_m0", "trinket_m0") +import sys + +# Minimal builds usually don't enable MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG, +# which is required for this test. +if getattr(sys.implementation, "_build", None) == "minimal": + print("SKIP") + raise SystemExit + list.append try: diff --git a/tests/basics/slice_optimise.py b/tests/basics/slice_optimise.py new file mode 100644 index 00000000000..f663e16b8c2 --- /dev/null +++ b/tests/basics/slice_optimise.py @@ -0,0 +1,23 @@ +# Test that the slice-on-stack optimisation does not break various uses of slice +# (see MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE type option). +# +# Note: this test has a corresponding .py.exp file because hashing slice objects +# was not allowed in CPython until 3.12. + +try: + from collections import OrderedDict +except ImportError: + print("SKIP") + raise SystemExit + +# Attempt to index with a slice, error should contain the slice (failed key). +try: + dict()[:] +except KeyError as e: + print("KeyError", e.args) + +# Put a slice and another object into an OrderedDict, and retrieve them. +x = OrderedDict() +x[:"a"] = 1 +x["b"] = 2 +print(list(x.keys()), list(x.values())) diff --git a/tests/basics/slice_optimise.py.exp b/tests/basics/slice_optimise.py.exp new file mode 100644 index 00000000000..3fa59aae15a --- /dev/null +++ b/tests/basics/slice_optimise.py.exp @@ -0,0 +1,2 @@ +KeyError (slice(None, None, None),) +[slice(None, 'a', None), 'b'] [1, 2] diff --git a/tests/basics/special_methods2.py.exp b/tests/basics/special_methods2.py.exp deleted file mode 100644 index a9ae75be55c..00000000000 --- a/tests/basics/special_methods2.py.exp +++ /dev/null @@ -1,19 +0,0 @@ -__pos__ called -__pos__ called -__neg__ called -__invert__ called -__mul__ called -__matmul__ called -__truediv__ called -__floordiv__ called -__iadd__ called -__isub__ called -__mod__ called -__pow__ called -__or__ called -__and__ called -__xor__ called -__lshift__ called -__rshift__ called -['a', 'b', 'c'] -False diff --git a/tests/basics/string_format.py b/tests/basics/string_format.py index e8600f58361..11e7836a73e 100644 --- a/tests/basics/string_format.py +++ b/tests/basics/string_format.py @@ -22,7 +22,17 @@ def test(fmt, *args): test("{:4x}", 123) test("{:4X}", 123) +test("{:4,d}", 1) +test("{:4_d}", 1) +test("{:4_o}", 1) +test("{:4_b}", 1) +test("{:4_x}", 1) + test("{:4,d}", 12345678) +test("{:4_d}", 12345678) +test("{:4_o}", 12345678) +test("{:4_b}", 12345678) +test("{:4_x}", 12345678) test("{:#4b}", 10) test("{:#4o}", 123) diff --git a/tests/basics/string_format_sep.py b/tests/basics/string_format_sep.py new file mode 100644 index 00000000000..de131fdaf33 --- /dev/null +++ b/tests/basics/string_format_sep.py @@ -0,0 +1,9 @@ +try: + "%d" % 1 +except TypeError: + print("SKIP") + raise SystemExit + +for v in (0, 0x10, 0x1000, -0x10, -0x1000): + for sz in range(1, 12): print(("{:0%d,d}" % sz).format(v)) + for sz in range(1, 12): print(("{:0%d_x}" % sz).format(v)) diff --git a/tests/basics/string_fstring_debug.py.exp b/tests/basics/string_fstring_debug.py.exp deleted file mode 100644 index f0309e1c98a..00000000000 --- a/tests/basics/string_fstring_debug.py.exp +++ /dev/null @@ -1,9 +0,0 @@ -x=1 -x=00000001 -a x=1 b 2 c -a x=00000001 b 2 c -a f() + g("foo") + h()=15 b -a f() + g("foo") + h()=0000000f b -a 1,=(1,) b -a x,y,=(1, 2) b -a x,1=(1, 1) b diff --git a/tests/basics/subclass_native_init.py b/tests/basics/subclass_native_init.py index 64167fa037e..102befd551f 100644 --- a/tests/basics/subclass_native_init.py +++ b/tests/basics/subclass_native_init.py @@ -1,5 +1,9 @@ # test subclassing a native type and overriding __init__ +if not hasattr(object, "__init__"): + print("SKIP") + raise SystemExit + # overriding list.__init__() class L(list): def __init__(self, a, b): diff --git a/tests/basics/syntaxerror.py b/tests/basics/syntaxerror.py index c0702cb2452..7b6ef9b7550 100644 --- a/tests/basics/syntaxerror.py +++ b/tests/basics/syntaxerror.py @@ -86,7 +86,7 @@ def test_syntax(code): test_syntax("nonlocal a") test_syntax("await 1") -# error on uPy, warning on CPy +# error on MPy, warning on CPy #test_syntax("def f():\n a = 1\n global a") # default except must be last @@ -98,7 +98,7 @@ def test_syntax(code): # non-keyword after keyword test_syntax("f(a=1, 2)") -# doesn't error on uPy but should +# doesn't error on MPy but should #test_syntax("f(1, i for i in i)") # all elements of dict/set must be pairs or singles diff --git a/tests/basics/sys1.py b/tests/basics/sys1.py index 7f261aa9645..02946abc220 100644 --- a/tests/basics/sys1.py +++ b/tests/basics/sys1.py @@ -31,6 +31,12 @@ # Effectively skip subtests print(str) +if hasattr(sys.implementation, '_thread'): + print(sys.implementation._thread in ("GIL", "unsafe")) +else: + # Effectively skip subtests + print(True) + try: print(sys.intern('micropython') == 'micropython') has_intern = True diff --git a/tests/basics/sys_tracebacklimit.py b/tests/basics/sys_tracebacklimit.py index 3ae372b8d52..6f575fde654 100644 --- a/tests/basics/sys_tracebacklimit.py +++ b/tests/basics/sys_tracebacklimit.py @@ -30,7 +30,7 @@ def print_exc(e): if l.startswith(" File "): l = l.split('"') print(l[0], l[2]) - # uPy and CPy tracebacks differ in that CPy prints a source line for + # MPy and CPy tracebacks differ in that CPy prints a source line for # each traceback entry. In this case, we know that offending line # has 4-space indent, so filter it out. elif not l.startswith(" "): diff --git a/tests/basics/sys_tracebacklimit.py.native.exp b/tests/basics/sys_tracebacklimit.py.native.exp new file mode 100644 index 00000000000..f9d30c05856 --- /dev/null +++ b/tests/basics/sys_tracebacklimit.py.native.exp @@ -0,0 +1,22 @@ +ValueError: value + +limit 4 +ValueError: value + +limit 3 +ValueError: value + +limit 2 +ValueError: value + +limit 1 +ValueError: value + +limit 0 +ValueError: value + +limit -1 +ValueError: value + +True +False diff --git a/tests/basics/try_finally_continue.py.exp b/tests/basics/try_finally_continue.py.exp deleted file mode 100644 index 2901997b1aa..00000000000 --- a/tests/basics/try_finally_continue.py.exp +++ /dev/null @@ -1,9 +0,0 @@ -4 0 -continue -4 1 -continue -4 2 -continue -4 3 -continue -None diff --git a/tests/basics/tuple1.py b/tests/basics/tuple1.py index 72bb3f01bff..70ae071898e 100644 --- a/tests/basics/tuple1.py +++ b/tests/basics/tuple1.py @@ -17,7 +17,7 @@ x += (10, 11, 12) print(x) -# construction of tuple from large iterator (tests implementation detail of uPy) +# construction of tuple from large iterator (tests implementation detail of MicroPython) print(tuple(range(20))) # unsupported unary operation diff --git a/tests/circuitpython-manual/alarm/sleep_memory_persist.py b/tests/circuitpython-manual/alarm/sleep_memory_persist.py new file mode 100644 index 00000000000..39e6baafca7 --- /dev/null +++ b/tests/circuitpython-manual/alarm/sleep_memory_persist.py @@ -0,0 +1,100 @@ +"""Reproducer for https://github.com/adafruit/circuitpython/issues/10896 + +Copy to code.py. Sequences through test steps using sleep_memory to +track state. + +The test scoreboard is printed to the magtag e-ink display after every +run so the final display shows cumulative results. +""" + +import alarm +import binascii +import microcontroller +import struct +import supervisor +import time + +# Safe mode avoidance +# On boot CircuitPython writes a SAFE_MODE_USER guard to an RTC register, +# If a second boot occurs before 1000ms elapses then we enter safe mode. +# So, wait for 1000+1ms before calling microcontroller.reset(). +_SAFE_MODE_WINDOW_MS = 1000 + + +def _wait_for_safe_mode_window(): + elapsed_ms = time.monotonic() * 1000 + remaining = _SAFE_MODE_WINDOW_MS + 1 - elapsed_ms + if remaining > 0: + time.sleep(remaining / 1000) + + +# Test result enum +_UNTESTED = 0 +_PASS = 1 +_FAIL = 2 +_LABEL = {_UNTESTED: "-", _PASS: "PASS", _FAIL: "FAIL"} + +# CRC32-protected state in sleep_memory +# [magic:2][step:1][r_reset:1][r_reload:1][pad:1][crc32:4] +_MAGIC = 0xBE01 +_FMT = " board.D5 +# mic LRCL -> board.D6 +# mic DOUT -> board.D9 +# neopixel -> board.D10 +# +# The mic's 24-bit samples ride in 32-bit slots, so we use bit_depth=32 and +# an array.array("I", ...). For SPH0645 set left_justified=True. + +import array +import math +import time + +import board +import audioi2sin +import neopixel + +NUM_PIXELS = 30 +PIXEL_PIN = board.D10 + +SAMPLE_RATE = 16000 +SAMPLES_PER_FRAME = 512 # ~32 ms windows + +pixels = neopixel.NeoPixel(PIXEL_PIN, NUM_PIXELS, brightness=0.3, auto_write=False) + +mic = audioi2sin.I2SIn( + bit_clock=board.D5, + word_select=board.D6, + data=board.D9, + sample_rate=SAMPLE_RATE, + bit_depth=32, + mono=True, + left_justified=False, # set True for SPH0645LM4H +) + +buf = array.array("i", [0] * SAMPLES_PER_FRAME) + + +def wheel(pos): + pos = pos % 256 + if pos < 85: + return (pos * 3, 255 - pos * 3, 0) + if pos < 170: + pos -= 85 + return (255 - pos * 3, 0, pos * 3) + pos -= 170 + return (0, pos * 3, 255 - pos * 3) + + +# Smoothed noise floor + peak so the effect adapts to the room. +noise_floor = 2000.0 +peak = 20000.0 +hue = 0 +smoothed_level = 0.0 + +while True: + mic.record(buf, len(buf)) + + # Compute RMS of the window. + acc = 0 + for s in buf: + acc += s * s + rms = math.sqrt(acc / len(buf)) + + # Track a slow noise floor and a decaying peak for auto-gain. + noise_floor = 0.995 * noise_floor + 0.005 * rms + if rms > peak: + peak = rms + else: + peak *= 0.995 + if peak < noise_floor + 1000: + peak = noise_floor + 1000 + + level = (rms - noise_floor) / (peak - noise_floor) + if level < 0: + level = 0.0 + elif level > 1: + level = 1.0 + + # Smooth the bar so it doesn't jitter on every frame. + smoothed_level = 0.6 * smoothed_level + 0.4 * level + + lit = int(smoothed_level * NUM_PIXELS) + hue = (hue + 2) % 256 + + for i in range(NUM_PIXELS): + if i < lit: + r, g, b = wheel((hue + i * (256 // NUM_PIXELS)) % 256) + pixels[i] = (r, g, b) + else: + pixels[i] = (0, 0, 0) + pixels.show() + + time.sleep(0.005) diff --git a/tests/circuitpython-manual/audioi2sin/i2sin_record_sdcard.py b/tests/circuitpython-manual/audioi2sin/i2sin_record_sdcard.py new file mode 100644 index 00000000000..c381e272bf7 --- /dev/null +++ b/tests/circuitpython-manual/audioi2sin/i2sin_record_sdcard.py @@ -0,0 +1,105 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +# Record a longer I2S audio capture to a WAV file on an SD card. +# +# Produces /sd/recording.wav. Set left_justified=True for SPH0645LM4H mics. + +import array +import struct +import time + +import ulab.numpy as np +import board +import busio +import sdcardio +import storage +import audioi2sin + +# ---- Recording config ------------------------------------------------------ +SAMPLE_RATE = 16000 +RECORD_SECONDS = 10 +CHUNK_SAMPLES = 1024 # samples captured per record() call +OUTPUT_PATH = "/sd/talk.wav" + +# ---- Mount SD -------------------------------------------------------------- +spi = board.SPI() +sdcard = sdcardio.SDCard(spi, cs=board.D10, baudrate=24_000_000) +vfs = storage.VfsFat(sdcard) +storage.mount(vfs, "/sd") + +# ---- Mic ------------------------------------------------------------------- +# 24-bit MEMS mics ride in 32-bit slots. Downconvert each slot to a +# signed 16-bit PCM sample before writing. +mic = audioi2sin.I2SIn( + bit_clock=board.D5, + word_select=board.D6, + data=board.D9, + sample_rate=SAMPLE_RATE, + bit_depth=32, + mono=True, + left_justified=False, # True for SPH0645LM4H +) + +actual_rate = mic.sample_rate +print("Recording at", actual_rate, "Hz for", RECORD_SECONDS, "s ->", OUTPUT_PATH) + +raw = array.array("i", [0] * CHUNK_SAMPLES) +pcm16 = array.array("h", [0] * CHUNK_SAMPLES) + + +def write_wav_header(f, sample_rate, num_samples, bits_per_sample=16, channels=1): + byte_rate = sample_rate * channels * bits_per_sample // 8 + block_align = channels * bits_per_sample // 8 + data_size = num_samples * block_align + f.write(b"RIFF") + f.write(struct.pack("> 16 # take top 16 bits + pcm16[i] = s + # Write only the valid portion. + f.write(memoryview(pcm16)[:n]) + written += n + + elapsed = time.monotonic() - start + # Rewrite header now that we know the true sample count. + f.seek(0) + write_wav_header(f, actual_rate, written) + +storage.umount("/sd") + +print("Done. Wrote", written, "samples in", round(elapsed, 2), "s") diff --git a/tests/circuitpython-manual/audioi2sin/i2sin_record_sdcard_output_bit_depth.py b/tests/circuitpython-manual/audioi2sin/i2sin_record_sdcard_output_bit_depth.py new file mode 100644 index 00000000000..cc2d2e78c29 --- /dev/null +++ b/tests/circuitpython-manual/audioi2sin/i2sin_record_sdcard_output_bit_depth.py @@ -0,0 +1,100 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +# Record a longer I2S audio capture to a WAV file on an SD card, using the +# `output_bit_depth` argument to have the driver downconvert each 32-bit slot +# to signed 16-bit PCM. Compared to `i2sin_record_sdcard.py`, this avoids the +# Python-side shift loop and writes directly from the recording buffer. +# +# Produces /sd/talk.wav. Set left_justified=True for SPH0645LM4H mics. + +import array +import struct +import time + +import board +import sdcardio +import storage +import audioi2sin + +# ---- Recording config ------------------------------------------------------ +SAMPLE_RATE = 16000 +RECORD_SECONDS = 10 +CHUNK_SAMPLES = 1024 # samples captured per record() call +OUTPUT_PATH = "/sd/talk.wav" + +# ---- Mount SD -------------------------------------------------------------- +spi = board.SPI() +sdcard = sdcardio.SDCard(spi, cs=board.D10, baudrate=24_000_000) +vfs = storage.VfsFat(sdcard) +storage.mount(vfs, "/sd") + +# ---- Mic ------------------------------------------------------------------- +# 24-bit MEMS mics ride in 32-bit slots. Ask the driver to downconvert each +# slot to a signed 16-bit PCM sample, so `record()` writes straight into a +# WAV-ready 'h' buffer. +mic = audioi2sin.I2SIn( + bit_clock=board.D5, + word_select=board.D6, + data=board.D9, + sample_rate=SAMPLE_RATE, + bit_depth=32, + output_bit_depth=16, + mono=True, + left_justified=False, # True for SPH0645LM4H +) + +actual_rate = mic.sample_rate +print("Recording at", actual_rate, "Hz for", RECORD_SECONDS, "s ->", OUTPUT_PATH) + +pcm16 = array.array("h", [0] * CHUNK_SAMPLES) + + +def write_wav_header(f, sample_rate, num_samples, bits_per_sample=16, channels=1): + byte_rate = sample_rate * channels * bits_per_sample // 8 + block_align = channels * bits_per_sample // 8 + data_size = num_samples * block_align + f.write(b"RIFF") + f.write(struct.pack(" **If using `run_serial_tests.py`** this step is done automatically — skip ahead. + +Copy the WAV test samples onto the board's `CIRCUITPY` drive root: + +``` +cp \ + tests/circuitpython-manual/audiocore/jeplayer-splash-8000-8bit-mono-unsigned.wav \ + tests/circuitpython-manual/audiocore/jeplayer-splash-8000-16bit-mono-signed.wav \ + tests/circuitpython-manual/audiocore/jeplayer-splash-44100-16bit-mono-signed.wav \ + tests/circuitpython-manual/audiocore/jeplayer-splash-8000-16bit-stereo-signed.wav \ + tests/circuitpython-manual/audiocore/jeplayer-splash-44100-16bit-stereo-signed.wav \ + /Volumes/CIRCUITPY/ +``` + +These five files cover every exercised code path: +- `8000-8bit-mono-unsigned` — 8-bit unsigned decode path, audibly lo-fi +- `8000-16bit-mono-signed` — 16-bit signed decode path at lowest sample rate +- `44100-16bit-mono-signed` — 16-bit at highest sample rate (DMA reconfiguration, audible quality difference) +- `8000-16bit-stereo-signed` — stereo decode path, left→A0, right→A1 +- `44100-16bit-stereo-signed` — stereo at 44.1 kHz + +The 16 kHz files in the audiocore test set are skipped because they exercise +no code paths beyond 8 kHz and 44.1 kHz. 24-bit WAVs are not supported by +`audiocore.WaveFile` and will raise `OSError` if loaded — they are omitted on +purpose. + +Copy the test scripts to the board as well (or paste them into the REPL): + +``` +cp tests/circuitpython-manual/audioio/wavefile_playback.py /Volumes/CIRCUITPY/ +cp tests/circuitpython-manual/audioio/wavefile_pause_resume.py /Volumes/CIRCUITPY/ +cp tests/circuitpython-manual/audioio/single_buffer_loop.py /Volumes/CIRCUITPY/ +cp tests/circuitpython-manual/audioio/stereo_playback.py /Volumes/CIRCUITPY/ +``` + +## Test 1 — WAV File Playback (`wavefile_playback.py`) *(automated)* + +Verifies that `AudioOut(board.A0)` can play WAV files at 8 kHz and 44.1 kHz +with 8-bit unsigned and 16-bit signed encodings. Stereo WAVs are played here +through the mono `AudioOut` (only the left channel is mixed to A0); the +stereo path is exercised separately in Test 5. + +**Note:** 24-bit WAV files are not supported by `audiocore.WaveFile` and will +print an `OSError` if any are present on the filesystem. That is expected. + +**Run from the REPL:** + +```python +import os +os.chdir("/") +exec(open("wavefile_playback.py").read()) +``` + +**Expected output (order may vary by filename sort):** + +``` +playing jeplayer-splash-44100-16bit-mono-signed.wav +playing jeplayer-splash-8000-16bit-mono-signed.wav +playing jeplayer-splash-8000-8bit-mono-unsigned.wav +done +``` + +**What to listen for:** + +- Each supported WAV plays the "jeplayer splash" jingle to completion before the next starts. +- No loud pops at the start or end of each file (the DAC ramp-in / ramp-out should suppress them). +- Audio pitch should match the sample rate: the 44100 Hz file sounds the most natural; the 8000 Hz file sounds lower fidelity. + +## Test 2 — Pause and Resume (`wavefile_pause_resume.py`) *(automated)* + +Verifies `AudioOut.pause()` / `AudioOut.resume()` by toggling every 100 ms during playback. The audio will sound choppy — that is intentional. + +**Run from the REPL:** + +```python +exec(open("wavefile_pause_resume.py").read()) +``` + +**Expected output (repeating for each WAV):** + +``` +playing with pause/resume: jeplayer-splash-44100-16bit-mono-signed.wav + paused + resumed + ... +playing with pause/resume: jeplayer-splash-8000-16bit-mono-signed.wav + paused + resumed + ... +playing with pause/resume: jeplayer-splash-8000-8bit-mono-unsigned.wav + paused + resumed + ... +done +``` + +**What to verify:** + +- The REPL prints alternating "paused" / "resumed" lines. +- Audio cuts in and out in sync with the prints. +- Playback eventually completes (the `while dac.playing` loop exits normally). +- No hard fault or hang. + +## Test 3 — Looping Sine Wave (`single_buffer_loop.py`) *(automated)* + +Verifies `RawSample` with `loop=True` and tests all four sample formats: +`unsigned 8-bit`, `signed 8-bit`, `unsigned 16-bit`, `signed 16-bit`. + +Each sample generates one cycle of a 440 Hz sine wave and loops for 1 second. + +**Run from the REPL:** + +```python +exec(open("single_buffer_loop.py").read()) +``` + +**Expected output:** + +``` +unsigned 8 bit + +signed 8 bit + +unsigned 16 bit + +signed 16 bit + +done +``` + +**What to listen for:** + +- A 440 Hz tone (concert A) for approximately 1 second for each format. +- All four formats use the same 8 kHz sample rate and should sound + essentially identical in pitch and volume — the test is comparing + format-conversion paths, not playback rates. +- No pops or glitches during the loop. +- Clean silence between tones (quiescent DAC value holds between `stop()` calls). + +## Test 4 — `deinit` and Re-init *(automated)* + +Verifies that `AudioOut` can be deconstructed and reconstructed without rebooting, and that pin A0 is properly released. + +```python +import audioio, analogio, board + +# Construct and immediately deinit AudioOut +dac = audioio.AudioOut(board.A0) +dac.deinit() + +# PA04 should now be free for AnalogOut +aout = analogio.AnalogOut(board.A0) +aout.value = 32768 # mid-scale +aout.deinit() + +# Re-create AudioOut on the same pin +dac2 = audioio.AudioOut(board.A0) +dac2.deinit() +print("pass") +``` + +**Expected output:** `pass` with no exceptions. + +## Test 5 — Stereo Playback (`stereo_playback.py`) *(automated)* + +Verifies that `AudioOut(board.A0, right_channel=board.A1)` drives both DAC +channels independently: left on **A0 (PA04, DAC_CH1)**, right on +**A1 (PA05, DAC_CH2)**, both clocked by TIM6. + +The script runs four phases in order: + +1. **Left-only 440 Hz tone** (~1 s) — only A0 should produce audio. +2. **Right-only 440 Hz tone** (~1 s) — only A1 should produce audio. +3. **Both-channel 440 Hz tone** (~1 s) — equal amplitude on both pins. +4. **Pan sweep L → R** (~3 s) — continuous equal-power (cos/sin) crossfade from A0 to A1 in a single non-looped buffer. +5. Then plays each stereo WAV (`44100` and `8000` Hz) in full. + +**Hardware required:** connect a stereo headphone/amp to A0 (left) and A1 +(right) with common ground, or scope-probe each pin separately. + +**Run from the REPL:** + +```python +import os +os.chdir("/") +exec(open("stereo_playback.py").read()) +``` + +**Expected output:** + +``` +channel test: left only +channel test: right only +channel test: both channels +pan sweep: left to right +playing stereo: jeplayer-splash-44100-16bit-stereo-signed.wav +playing stereo: jeplayer-splash-8000-16bit-stereo-signed.wav +done +``` + +**What to listen / look for:** + +- "left only" → tone in left ear, silence in right. +- "right only" → tone in right ear, silence in left. +- "both channels" → centered tone in both ears. +- "pan sweep" → tone smoothly travels left → right over ~3 s. +- Stereo WAVs play with proper L/R separation; no cross-contamination. +- On a scope: probing A0 and A1 simultaneously during phases 1 and 2 should + show one channel idle (mid-scale DC) while the other carries the sine. + +## Oscilloscope Checks (Optional) + +Each test script drives `board.D4` (pin D4) low at the start of each playback and high when it ends. This provides a clean trigger edge for a scope. + +- **Test 1:** Probe A0 — should show a sampled waveform at the correct sample rate. Probe D4 for a gate signal that spans the file duration. +- **Test 3:** Probe A0 — should show a 440 Hz staircase-sine at the DAC output (12-bit steps visible at 44.1 kHz; fewer at 8 kHz). A simple RC low-pass filter (1 kΩ + 100 nF) on the A0 output will smooth the staircase significantly. + +## Known Limitations + +- **Left channel must be A0 (PA04)**. Any other pin raises `ValueError: AudioOut requires pin A0 (PA04)`. +- **Right channel must be A1 (PA05)** when used. Any other pin raises `ValueError: AudioOut right channel requires pin A1 (PA05)`. +- **24-bit WAV files** are not supported by `audiocore.WaveFile` and will raise `OSError` when opened. +- Only one `AudioOut` instance can be active at a time. diff --git a/tests/circuitpython-manual/audioio/run_serial_tests.py b/tests/circuitpython-manual/audioio/run_serial_tests.py new file mode 100644 index 00000000000..9fbbe555592 --- /dev/null +++ b/tests/circuitpython-manual/audioio/run_serial_tests.py @@ -0,0 +1,582 @@ +#!/usr/bin/env python3 +""" +run_serial_tests.py — Automated REPL-based tests for STM32F405 audioio. + +Automates Tests 1–5 from README.md by: + 1. Copying WAV files and test scripts to the board via mpremote. + 2. Running each test on the device via the CircuitPython REPL. + 3. Comparing captured output to expected patterns and reporting PASS/FAIL. + +Usage: + python3 run_serial_tests.py + python3 run_serial_tests.py --port /dev/cu.usbmodemXXX + python3 run_serial_tests.py --circuitpy /Volumes/CIRCUITPY # macOS + python3 run_serial_tests.py --circuitpy /media/user/CIRCUITPY # Linux + python3 run_serial_tests.py --circuitpy D:\\ # Windows + python3 run_serial_tests.py --no-copy --tests 3,4 + +Requirements: + pip install mpremote +""" + +from __future__ import annotations + +import argparse +import os +import shutil +import subprocess +import sys +import time + +# --------------------------------------------------------------------------- +# Paths +# --------------------------------------------------------------------------- +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +REPO_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, "../../..")) +AUDIOCORE_DIR = os.path.join(REPO_ROOT, "tests", "circuitpython-manual", "audiocore") + +WAV_FILES = [ + "jeplayer-splash-8000-8bit-mono-unsigned.wav", + "jeplayer-splash-8000-16bit-mono-signed.wav", + "jeplayer-splash-44100-16bit-mono-signed.wav", + "jeplayer-splash-8000-16bit-stereo-signed.wav", + "jeplayer-splash-44100-16bit-stereo-signed.wav", +] + +TEST_SCRIPTS = [ + "wavefile_playback.py", + "wavefile_pause_resume.py", + "single_buffer_loop.py", + "stereo_playback.py", +] + +DEINIT_TEST_CODE = ( + "import audioio, analogio, board\n" + "dac = audioio.AudioOut(board.A0)\n" + "dac.deinit()\n" + "aout = analogio.AnalogOut(board.A0)\n" + "aout.value = 32768\n" + "aout.deinit()\n" + "dac2 = audioio.AudioOut(board.A0)\n" + "dac2.deinit()\n" + 'print("pass")\n' +) + +# --------------------------------------------------------------------------- +# mpremote helpers +# --------------------------------------------------------------------------- + + +def _mpremote(args: list, timeout: float = 30.0): + """Run an mpremote command, return (stdout, stderr). Raises on timeout.""" + try: + result = subprocess.run( + ["mpremote"] + args, + capture_output=True, + text=True, + timeout=timeout, + ) + return result.stdout, result.stderr + except subprocess.TimeoutExpired: + raise TimeoutError(f"mpremote timed out after {timeout}s") + except FileNotFoundError: + sys.exit("mpremote not found. Run: pip install mpremote") + + +# stderr substrings that indicate a transient host/USB issue worth retrying. +# Matched case-insensitively. CircuitPython USB-CDC briefly disappears during +# soft-reset and after some heavy DMA activity; mpremote's next invocation then +# either can't open the port or sees the kernel still holding the previous +# descriptor. +_RETRYABLE_STDERR = ( + "could not enter raw repl", + "failed to access", + "device not configured", + "errno 6", + "errno 16", + "resource busy", + "could not open", + "no such file or directory", + "serialexception", + "device disconnected", + "could not exclusively lock", +) + + +def _is_retryable(stderr: str) -> bool: + s = stderr.lower() + return any(needle in s for needle in _RETRYABLE_STDERR) + + +def _port_holders(port: str) -> list[str]: + """Return a human-readable list of processes holding *port* (Unix only). + + macOS / Linux only — uses `lsof`. Returns lines like "Code Helper (51298)". + Empty list when nothing holds the port or `lsof` is unavailable. + """ + if not port.startswith("/"): + return [] + holders: list[str] = [] + # Both /dev/cu.* (callout) and /dev/tty.* (dial-in) refer to the same UART + # on macOS — VS Code typically opens /dev/tty.* while we ask for /dev/cu.*, + # so check both. + candidates = {port} + if "/cu." in port: + candidates.add(port.replace("/cu.", "/tty.", 1)) + elif "/tty." in port: + candidates.add(port.replace("/tty.", "/cu.", 1)) + for path in candidates: + if not os.path.exists(path): + continue + try: + result = subprocess.run( + ["lsof", "-Fcp", path], + capture_output=True, + text=True, + timeout=5, + ) + except (FileNotFoundError, subprocess.TimeoutExpired): + return [] + pid = command = None + for line in result.stdout.splitlines(): + if line.startswith("p"): + pid = line[1:] + elif line.startswith("c"): + command = line[1:] + if pid: + holders.append(f"{command} (PID {pid}) on {path}") + pid = command = None + return holders + + +def _wait_for_port(port: str, timeout: float = 10.0) -> bool: + """Block until *port* exists in the filesystem, or *timeout* elapses. + + macOS / Linux expose serial ports as /dev nodes; Windows uses COMx which is + not a filesystem path, so on Windows we just sleep briefly and trust the + next mpremote call to surface the real error. + """ + if not port.startswith("/"): + time.sleep(0.5) + return True + deadline = time.time() + timeout + while time.time() < deadline: + if os.path.exists(port): + return True + time.sleep(0.1) + return False + + +def _interrupt_running_code(port: str, soft_reset: bool = False) -> None: + """Halt any code running on the device so mpremote can enter raw REPL. + + Strategy: + 1. Ctrl-C burst — usually breaks a busy print loop. + 2. Optional Ctrl-D soft reset, followed by a Ctrl-C flood through the + reboot window so code.py is interrupted *before* it gets busy again. + """ + try: + import serial # type: ignore[import-not-found] + except ImportError: + return + try: + with serial.Serial(port, 115200, timeout=0.1) as ser: + for _ in range(5): + ser.write(b"\x03") + ser.flush() + time.sleep(0.05) + if soft_reset: + ser.write(b"\x04") # Ctrl-D → soft reboot + ser.flush() + # Flood Ctrl-C while CircuitPython reboots so code.py can't + # get past its first iteration before we break in. + deadline = time.time() + 3.0 + while time.time() < deadline: + ser.write(b"\x03") + ser.flush() + time.sleep(0.05) + time.sleep(0.3) + ser.reset_input_buffer() + except (serial.SerialException, OSError): + pass + + +def find_port() -> str: + """Return the port of the first Adafruit device found by mpremote devs.""" + stdout, _ = _mpremote(["devs"]) + for line in stdout.splitlines(): + parts = line.split() + if not parts: + continue + # mpremote devs output: + # Filter for Adafruit VID (239a) + if any("239a" in p for p in parts): + return parts[0] + # Fall back to any USB serial port that isn't Bluetooth/wlan + for line in stdout.splitlines(): + parts = line.split() + if ( + parts + and parts[0].startswith("/dev/") + and "Bluetooth" not in line + and "wlan" not in line + ): + return parts[0] + raise RuntimeError( + "No board detected. Connect the board and/or pass --port.\n" + f"mpremote devs output:\n{stdout}" + ) + + +def find_circuitpy() -> str | None: + """Return the path to the mounted CIRCUITPY volume, or None if not found.""" + import platform + + system = platform.system() + + if system == "Darwin": + # Glob so a second CIRCUITPY volume (mounted as "CIRCUITPY 1") is found. + import glob + + candidates = sorted(glob.glob("/Volumes/CIRCUITPY*")) + elif system == "Windows": + # Scan all drive letters for a CIRCUITPY volume label. + import string + import ctypes + + candidates = [] + kernel32 = ctypes.windll.kernel32 # type: ignore[attr-defined] + buf = ctypes.create_unicode_buffer(256) + for letter in string.ascii_uppercase: + root = f"{letter}:\\" + if kernel32.GetVolumeInformationW(root, buf, 256, None, None, None, None, 0): + if buf.value == "CIRCUITPY": + candidates.append(root) + else: + # Linux: common udev/udisks mount points + candidates = ["/media/CIRCUITPY", "/run/media/CIRCUITPY"] + try: + import pwd + + user = pwd.getpwuid(os.getuid()).pw_name + candidates.insert(0, f"/run/media/{user}/CIRCUITPY") + candidates.insert(0, f"/media/{user}/CIRCUITPY") + except Exception: + pass + + for path in candidates: + if os.path.isdir(path): + return path + return None + + +def copy_files(port: str, circuitpy: str | None = None): + """Copy WAV samples and test scripts to the board.""" + mount = circuitpy or find_circuitpy() + if mount: + print(f"Copying files to board via {mount} ...") + else: + print("Copying files to board via mpremote ...") + files = [(os.path.join(AUDIOCORE_DIR, w), w) for w in WAV_FILES] + [ + (os.path.join(SCRIPT_DIR, s), s) for s in TEST_SCRIPTS + ] + # Check if device has enough space for test files + if mount: + needed = 0 + for src, dst in files: + if not os.path.exists(src): + continue + needed += os.path.getsize(src) + dest_path = os.path.join(mount, dst) + if os.path.exists(dest_path): + needed -= os.path.getsize(dest_path) + free = shutil.disk_usage(mount).free + if needed > free: + short = needed - free + print(f"ERROR: not enough space on {mount}.") + print(f" need: {needed / 1024:.1f} KiB") + print(f" free: {free / 1024:.1f} KiB") + print(f" short: {short / 1024:.1f} KiB") + print(f" Delete unrelated files (e.g. an old code.py or stale WAVs) and re-run.") + sys.exit(1) + missing = [] + for src, dst in files: + if not os.path.exists(src): + missing.append(src) + continue + if mount: + dest_path = os.path.join(mount, dst) + shutil.copy2(src, dest_path) + print(f" {dst} (copied)") + else: + stdout, stderr = _mpremote(["connect", port, "fs", "cp", src, f":/{dst}"], timeout=30) + if stderr and "Error" in stderr: + print(f" {dst} (FAILED: {stderr.strip()})") + else: + status = "up to date" if "Up to date" in stdout else "copied" + print(f" {dst} ({status})") + if missing: + print("WARNING: source files not found:") + for m in missing: + print(f" {m}") + print() + + +# --------------------------------------------------------------------------- +# Test runner +# --------------------------------------------------------------------------- + +PASS_TAG = "PASS" +FAIL_TAG = "FAIL" + + +def _check(condition: bool, message: str) -> bool: + print(f" [{PASS_TAG if condition else FAIL_TAG}] {message}") + return condition + + +def _run_exec(port: str, code: str, label: str, timeout: float, retries: int = 3): + """Execute *code* on the device via mpremote exec and print the output. + + Retries cover three failure modes: + * raw-REPL handshake blocked by a running code.py → Ctrl-C burst. + * Persistent handshake failure → soft-reset + Ctrl-C flood. + * Host-side serial drop ("device in use", "Errno 6", etc.) → wait for the + port node to re-appear, then retry. CircuitPython's USB-CDC can briefly + vanish after heavy DMA traffic or soft-reset. + """ + print(f"\n{'=' * 60}") + print(f" {label}") + print("=" * 60) + stdout = "" + stderr = "" + for attempt in range(retries + 1): + if not _wait_for_port(port, timeout=10.0): + print(f" [retry {attempt}/{retries}] port {port} not present — waited 10s") + continue + try: + stdout, stderr = _mpremote(["connect", port, "exec", code], timeout=timeout) + except TimeoutError as exc: + print(f" [FAIL] {exc}") + return False, "", "" + if not _is_retryable(stderr): + break + if attempt < retries: + handshake = "could not enter raw repl" in stderr.lower() + # Soft-reset only on persistent raw-REPL failures, not on host drops + # (a soft-reset there just makes the disconnect window longer). + escalate = handshake and attempt >= 1 + if handshake: + tactic = "soft-reset + Ctrl-C flood" if escalate else "Ctrl-C burst" + else: + tactic = f"port-drop recovery ({stderr.strip().splitlines()[-1] if stderr.strip() else '?'})" + print(f" [retry {attempt + 1}/{retries}] {tactic}") + _wait_for_port(port, timeout=10.0) + _interrupt_running_code(port, soft_reset=escalate) + time.sleep(0.5) + print("Output:") + for line in stdout.splitlines(): + print(f" {line}") + if stderr: + print("Stderr:") + for line in stderr.splitlines(): + print(f" {line}") + return True, stdout, stderr + + +def _settle_between_tests(port: str) -> None: + """Drain any lingering REPL output and wait for the port to be ready. + + CircuitPython occasionally re-enumerates its USB-CDC after a heavy test; + next mpremote call then races the kernel re-binding the tty. Polling for + the port node and then sending a Ctrl-C burst gives the host a clean + starting state before the next exec. + """ + _wait_for_port(port, timeout=10.0) + _interrupt_running_code(port, soft_reset=False) + time.sleep(0.3) + + +# --------------------------------------------------------------------------- +# Individual tests +# --------------------------------------------------------------------------- + + +def test1_wavefile_playback(port: str) -> bool: + code = 'exec(open("/wavefile_playback.py").read())' + ok, stdout, stderr = _run_exec( + port, code, "Test 1 — WAV File Playback (wavefile_playback.py)", timeout=180 + ) + if not ok: + return False + passed = True + for wav in sorted(WAV_FILES): + passed &= _check(f"playing {wav}" in stdout, f"played {wav}") + passed &= _check("OSError" not in stdout, "No OSError reported during playback") + passed &= _check("done" in stdout, "Script completed with 'done'") + passed &= _check(not stderr, f"No exceptions (stderr={stderr!r})") + return passed + + +def test2_pause_resume(port: str) -> bool: + code = 'exec(open("/wavefile_pause_resume.py").read())' + ok, stdout, stderr = _run_exec( + port, code, "Test 2 — Pause / Resume (wavefile_pause_resume.py)", timeout=180 + ) + if not ok: + return False + passed = True + for wav in sorted(WAV_FILES): + passed &= _check( + f"playing with pause/resume: {wav}" in stdout, f"pause/resume header for {wav}" + ) + passed &= _check("paused" in stdout, "At least one 'paused' line printed") + passed &= _check("resumed" in stdout, "At least one 'resumed' line printed") + passed &= _check("TIMEOUT" not in stdout, "No pause/resume hang timeout") + passed &= _check("OSError" not in stdout, "No OSError reported during playback") + passed &= _check("done" in stdout, "Script completed with 'done'") + passed &= _check(not stderr, f"No exceptions (stderr={stderr!r})") + return passed + + +def test3_single_buffer_loop(port: str) -> bool: + code = 'exec(open("/single_buffer_loop.py").read())' + ok, stdout, stderr = _run_exec( + port, code, "Test 3 — Looping Sine Wave (single_buffer_loop.py)", timeout=30 + ) + if not ok: + return False + passed = True + for label in ("unsigned 8 bit", "signed 8 bit", "unsigned 16 bit", "signed 16 bit"): + passed &= _check(label in stdout, f"'{label}' label printed") + passed &= _check("done" in stdout, "Script completed with 'done'") + passed &= _check(not stderr, f"No exceptions (stderr={stderr!r})") + return passed + + +def test5_stereo_playback(port: str) -> bool: + code = 'exec(open("/stereo_playback.py").read())' + ok, stdout, stderr = _run_exec( + port, code, "Test 5 — Stereo Playback (stereo_playback.py)", timeout=180 + ) + if not ok: + return False + passed = True + passed &= _check("channel test: left only" in stdout, "Left-only channel tone played") + passed &= _check("channel test: right only" in stdout, "Right-only channel tone played") + passed &= _check("channel test: both channels" in stdout, "Both-channel tone played") + passed &= _check("pan sweep: left to right" in stdout, "Pan sweep played") + passed &= _check( + "playing stereo: jeplayer-splash-44100-16bit-stereo-signed.wav" in stdout, + "44100 Hz 16-bit stereo WAV played", + ) + passed &= _check( + "playing stereo: jeplayer-splash-8000-16bit-stereo-signed.wav" in stdout, + "8000 Hz 16-bit stereo WAV played", + ) + passed &= _check("done" in stdout, "Script completed with 'done'") + passed &= _check(not stderr, f"No exceptions (stderr={stderr!r})") + return passed + + +def test4_deinit(port: str) -> bool: + ok, stdout, stderr = _run_exec( + port, DEINIT_TEST_CODE, "Test 4 — deinit and Re-init (inline)", timeout=10 + ) + if not ok: + return False + passed = True + passed &= _check("pass" in stdout, "Script printed 'pass'") + passed &= _check(not stderr, f"No exceptions (stderr={stderr!r})") + return passed + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + + +def main(): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument("--port", help="Serial port (auto-detected if omitted)") + parser.add_argument( + "--circuitpy", + metavar="PATH", + help="Path to mounted CIRCUITPY volume (auto-detected if omitted)", + ) + parser.add_argument( + "--no-copy", + action="store_true", + help="Skip copying files to the board (assume they are already present)", + ) + parser.add_argument( + "--tests", + default="1,2,3,4,5", + help="Comma-separated list of test numbers to run (default: 1,2,3,4,5)", + ) + args = parser.parse_args() + + selected = set(args.tests.split(",")) + + port = args.port or find_port() + print(f"Using port: {port}\n") + + # Surface the common "VS Code has the serial monitor open" pitfall up front + # — otherwise every test fails with the opaque "in use by another program". + holders = _port_holders(port) + if holders: + print("ERROR: port is held by another process:") + for h in holders: + print(f" {h}") + print( + "Close the offending app (e.g. VS Code Serial Monitor, screen, tio)\n" + "and re-run. mpremote needs exclusive access." + ) + sys.exit(2) + + if not args.no_copy: + copy_files(port, circuitpy=args.circuitpy) + + # Halt any running code.py so the first test gets a clean raw-REPL entry. + _interrupt_running_code(port) + + test_runners = [ + ("1", "Test 1 — WAV Playback", test1_wavefile_playback), + ("2", "Test 2 — Pause/Resume", test2_pause_resume), + ("3", "Test 3 — Looping Sine", test3_single_buffer_loop), + ("4", "Test 4 — deinit/Re-init", test4_deinit), + ("5", "Test 5 — Stereo Playback", test5_stereo_playback), + ] + results: dict[str, bool] = {} + first = True + for key, name, runner in test_runners: + if key not in selected: + continue + if not first: + _settle_between_tests(port) + first = False + results[name] = runner(port) + + print(f"\n{'=' * 60}") + print("SUMMARY") + print("=" * 60) + all_passed = True + for name, passed in results.items(): + print(f" [{'PASS' if passed else 'FAIL'}] {name}") + all_passed = all_passed and passed + + print() + if all_passed: + print("All automated tests passed.") + print("Remaining manual step: audio/oscilloscope verification.") + sys.exit(0) + else: + print("One or more tests FAILED — see details above.") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/tests/circuitpython-manual/audioio/single_buffer_loop.py b/tests/circuitpython-manual/audioio/single_buffer_loop.py new file mode 100644 index 00000000000..4a4c4304275 --- /dev/null +++ b/tests/circuitpython-manual/audioio/single_buffer_loop.py @@ -0,0 +1,62 @@ +import audiocore +import audioio +import board +import digitalio +import array +import time +import math + +# Optional trigger pin for oscilloscope synchronisation. +try: + trigger = digitalio.DigitalInOut(board.D4) + trigger.switch_to_output(True) +except AttributeError: + trigger = None + +# Generate one period of a 440 Hz sine wave. All four samples use the same +# sample rate so each plays the same audible pitch — the test is comparing +# the four format-conversion paths, not playback rates. +sample_rate = 8000 +length = sample_rate // 440 # samples per cycle + +sample_names = ["unsigned 8 bit", "signed 8 bit", "unsigned 16 bit", "signed 16 bit"] + +# unsigned 8 bit +u8 = array.array("B", [0] * length) +for i in range(length): + u8[i] = int(math.sin(math.pi * 2 * i / length) * 127 + 128) +samples = [audiocore.RawSample(u8, sample_rate=sample_rate)] + +# signed 8 bit +s8 = array.array("b", [0] * length) +for i in range(length): + s8[i] = int(math.sin(math.pi * 2 * i / length) * 127) +samples.append(audiocore.RawSample(s8, sample_rate=sample_rate)) + +# unsigned 16 bit +u16 = array.array("H", [0] * length) +for i in range(length): + u16[i] = int(math.sin(math.pi * 2 * i / length) * 32767 + 32768) +samples.append(audiocore.RawSample(u16, sample_rate=sample_rate)) + +# signed 16 bit +s16 = array.array("h", [0] * length) +for i in range(length): + s16[i] = int(math.sin(math.pi * 2 * i / length) * 32767) +samples.append(audiocore.RawSample(s16, sample_rate=sample_rate)) + +dac = audioio.AudioOut(board.A0) +for sample, name in zip(samples, sample_names): + print(name) + if trigger: + trigger.value = False + dac.play(sample, loop=True) + time.sleep(1) + dac.stop() + time.sleep(0.1) + if trigger: + trigger.value = True + print() + +dac.deinit() +print("done") diff --git a/tests/circuitpython-manual/audioio/stereo_playback.py b/tests/circuitpython-manual/audioio/stereo_playback.py new file mode 100644 index 00000000000..cfdb4d39540 --- /dev/null +++ b/tests/circuitpython-manual/audioio/stereo_playback.py @@ -0,0 +1,128 @@ +import audiocore +import audioio +import board +import digitalio +import array +import gc +import math +import time +import os + +# Optional trigger pin for oscilloscope synchronisation. +try: + trigger = digitalio.DigitalInOut(board.D4) + trigger.switch_to_output(True) +except AttributeError: + trigger = None + +dac = audioio.AudioOut(board.A0, right_channel=board.A1) + +# --------------------------------------------------------------------------- +# Channel-isolation tones: prove each DAC channel can be driven independently. +# Listener should hear the 440 Hz tone shift between ears. +# --------------------------------------------------------------------------- +sample_rate = 8000 +freq = 440 +length = sample_rate // freq +sine = [int(math.sin(2 * math.pi * i / length) * 16000) for i in range(length)] +silence = [0] * length + + +def stereo_buffer(left, right): + buf = array.array("h", [0] * (len(left) * 2)) + for i in range(len(left)): + buf[2 * i] = left[i] + buf[2 * i + 1] = right[i] + return buf + + +channel_tests = ( + ("left only", sine, silence), + ("right only", silence, sine), + ("both channels", sine, sine), +) + +for label, left, right in channel_tests: + print("channel test:", label) + sample = audiocore.RawSample( + stereo_buffer(left, right), channel_count=2, sample_rate=sample_rate + ) + if trigger: + trigger.value = False + dac.play(sample, loop=True) + time.sleep(1.0) + dac.stop() + if trigger: + trigger.value = True + time.sleep(0.2) + del sample + print() + +del channel_tests, sine, silence + +# --------------------------------------------------------------------------- +# Pan sweep: continuous equal-power L→R over 2 s. Single non-looped buffer, +# played once for a smooth crossfade with no DMA restart clicks. +# +# Linear amplitude pan sounds like centred stereo at the midpoint because both +# channels are equally loud. Equal-power (cos/sin) pan keeps total energy +# constant so the source is perceived as moving rather than collapsing inwards. +# +# 2 s @ 4 kHz stereo 8-bit signed = 16000 bytes. Halving the sample rate keeps +# the buffer small while doubling perceived motion duration; 220 Hz at 4 kHz +# has the same samples-per-cycle as the earlier 440 Hz @ 8 kHz tones. +# --------------------------------------------------------------------------- +gc.collect() +pan_sr = sample_rate // 2 +pan_freq = freq // 2 +pan_seconds = 3 +pan_frames = pan_sr * pan_seconds +pan_buf = array.array("b", bytes(pan_frames * 2)) +two_pi_freq_over_sr = 2 * math.pi * pan_freq / pan_sr +half_pi = math.pi / 2 +for i in range(pan_frames): + s = math.sin(two_pi_freq_over_sr * i) + t = i / pan_frames # 0 → 1 + l_gain = math.cos(t * half_pi) + r_gain = math.sin(t * half_pi) + pan_buf[2 * i] = int(s * l_gain * 120) + pan_buf[2 * i + 1] = int(s * r_gain * 120) + +print("pan sweep: left to right") +pan_sample = audiocore.RawSample(pan_buf, channel_count=2, sample_rate=pan_sr) +if trigger: + trigger.value = False +dac.play(pan_sample) +while dac.playing: + time.sleep(0.05) +if trigger: + trigger.value = True +time.sleep(0.2) +print() + +# --------------------------------------------------------------------------- +# Stereo WAV files: full-content check. +# --------------------------------------------------------------------------- +sample_prefix = "jeplayer-splash" +wavs = sorted(fn for fn in os.listdir("/") if fn.startswith(sample_prefix) and "stereo" in fn) + +for filename in wavs: + print("playing stereo:", filename) + with open(filename, "rb") as sample_file: + try: + sample = audiocore.WaveFile(sample_file) + except OSError as e: + print(e) + continue + if trigger: + trigger.value = False + dac.play(sample) + while dac.playing: + time.sleep(0.1) + if trigger: + trigger.value = True + time.sleep(0.1) + print() + +dac.deinit() +print("done") diff --git a/tests/circuitpython-manual/audioio/wavefile_pause_resume.py b/tests/circuitpython-manual/audioio/wavefile_pause_resume.py new file mode 100644 index 00000000000..7661a828b26 --- /dev/null +++ b/tests/circuitpython-manual/audioio/wavefile_pause_resume.py @@ -0,0 +1,66 @@ +import audiocore +import audioio +import board +import digitalio +import time +import os + +# Optional trigger pin for oscilloscope synchronisation. +try: + trigger = digitalio.DigitalInOut(board.D4) + trigger.switch_to_output(True) +except AttributeError: + trigger = None + +sample_prefix = "jeplayer-splash" + +samples = [] +for fn in os.listdir("/"): + if fn.startswith(sample_prefix): + samples.append(fn) + +if not samples: + print( + "No sample files found. Copy *.wav files from tests/circuitpython-manual/audiocore/ to the board." + ) + +dac = audioio.AudioOut(board.A0) +for filename in sorted(samples): + print("playing with pause/resume:", filename) + with open(filename, "rb") as sample_file: + try: + sample = audiocore.WaveFile(sample_file) + except OSError as e: + print(e) + continue + if trigger: + trigger.value = False + dac.play(sample) + # Deliberately toggle pause/resume every 100 ms to stress-test the + # pause/resume cycle. Audio will sound choppy — that is expected. + # The wall-clock guard makes the test fail loudly instead of hanging + # if pause() ever leaves the driver in a state where playing never + # clears. 30 s is enough for the longest 44.1 kHz mono WAV in the + # set even with pause-doubling. + deadline = time.monotonic() + 30.0 + while dac.playing: + if time.monotonic() > deadline: + print(" TIMEOUT waiting for playback to finish") + dac.stop() + break + time.sleep(0.1) + if not dac.playing: # may have finished during sleep + break + if not dac.paused: + dac.pause() + print(" paused") + else: + dac.resume() + print(" resumed") + if trigger: + trigger.value = True + time.sleep(0.1) + print() + +dac.deinit() +print("done") diff --git a/tests/circuitpython-manual/audioio/wavefile_playback.py b/tests/circuitpython-manual/audioio/wavefile_playback.py new file mode 100644 index 00000000000..a7800c54ddc --- /dev/null +++ b/tests/circuitpython-manual/audioio/wavefile_playback.py @@ -0,0 +1,49 @@ +import audiocore +import audioio +import board +import digitalio +import time +import os + +# Optional trigger pin for oscilloscope synchronisation. +try: + trigger = digitalio.DigitalInOut(board.D4) + trigger.switch_to_output(True) +except AttributeError: + trigger = None + +# List WAV files from the audiocore test samples directory on the device. +# Copy tests/circuitpython-manual/audiocore/*.wav to the board's filesystem. +sample_prefix = "jeplayer-splash" + +samples = [] +for fn in os.listdir("/"): + if fn.startswith(sample_prefix): + samples.append(fn) + +if not samples: + print( + "No sample files found. Copy *.wav files from tests/circuitpython-manual/audiocore/ to the board." + ) + +dac = audioio.AudioOut(board.A0) +for filename in sorted(samples): + print("playing", filename) + with open(filename, "rb") as sample_file: + try: + sample = audiocore.WaveFile(sample_file) + except OSError as e: + print(e) + continue + if trigger: + trigger.value = False + dac.play(sample) + while dac.playing: + time.sleep(0.1) + if trigger: + trigger.value = True + time.sleep(0.1) + print() + +dac.deinit() +print("done") diff --git a/tests/circuitpython-manual/rp2pio/README.md b/tests/circuitpython-manual/rp2pio/README.md new file mode 100644 index 00000000000..de67cf203d2 --- /dev/null +++ b/tests/circuitpython-manual/rp2pio/README.md @@ -0,0 +1,44 @@ +# rp2pio + audio DMA shared-IRQ manual tests + +These programs exercise the `DMA_IRQ_0` interrupt handlers on the RP2040 / +RP2350, which are shared between `audiocore`/`audiopwmio` (audio DMA) and +`rp2pio` (PIO background read/write DMA). + +They were written to validate the change in issue #9992 (moving `audio_dma.c` +off the fixed `isr_dma_0()` linker symbol and onto `irq_add_shared_handler()`, +with `rp2pio` registering its own shared handler). **They use only public APIs +that predate that change, so each program should behave identically before and +after it** — that is the point: they are regression tests, not feature tests. + +## What each program covers + +| Program | Audio DMA | PIO write DMA | PIO read DMA | +|---|---|---|---| +| `pio_background_write.py` | | ✓ | | +| `audio_dma_shared_irq_write.py` | ✓ | ✓ | | +| `audio_dma_shared_irq_loopback.py` | ✓ | ✓ | ✓ | + +Each goes through the background-DMA path (`background_write` / +`background_read`), which is interrupt-driven. The blocking `write`/`readinto`/ +`write_readinto` calls poll instead and do **not** use the DMA IRQ, so they are +deliberately not used here. The audio sample is created with +`single_buffer=False` so audio also uses the interrupt-driven (double-buffered) +DMA path rather than the no-interrupt single-buffer chaining path. + +## Wiring (Raspberry Pi Pico / Pico 2) + +- `GP13` — PWM audio output. Connect to an amplifier/speaker, or just leave it; + the test does not require you to hear anything, only that playback keeps + running. +- `GP2` — PIO output pin. +- `GP3` — PIO input pin (loopback test only). For a meaningful loopback, + connect `GP2` to `GP3` with a jumper. Without the jumper the read still + completes (it just reads whatever the floating/pulled pin sees), so the DMA + path is still exercised. + +## Running + +Copy one file at a time to `CIRCUITPY/code.py` and watch the serial console. +A successful run ends with a `PASS:` line. A hang (no further output) or a +`RuntimeError`/crash/safe-mode indicates a regression in the shared DMA IRQ +handling. diff --git a/tests/circuitpython-manual/rp2pio/audio_dma_shared_irq_loopback.py b/tests/circuitpython-manual/rp2pio/audio_dma_shared_irq_loopback.py new file mode 100644 index 00000000000..ba8ebbb589d --- /dev/null +++ b/tests/circuitpython-manual/rp2pio/audio_dma_shared_irq_loopback.py @@ -0,0 +1,85 @@ +"""Audio + rp2pio background write AND read sharing DMA_IRQ_0. + +Exercises all three DMA_IRQ_0 dispatch arms at once: + * audio playback (double-buffered, interrupt-driven), + * a continuous PIO background_write (write-completion interrupts), and + * repeated PIO background_read one-shots (read-completion interrupts). + +The continuous background_write keeps the state machine clocking so the read +side always has data to capture. Each background_read is a one-shot whose +completion is detected by polling `StateMachine.reading`; if that never clears, +the read-completion interrupt is not being serviced (a regression). Audio must +also keep playing throughout. + +Wiring: PWM audio on GP13 (speaker optional), PIO output on GP2, PIO input on +GP3. Jumper GP2 -> GP3 for a true loopback (then the captured data reflects what +was written); without the jumper the read still completes, so the DMA path is +still exercised. +""" + +import array +import math +import time + +import audiocore +import audiopwmio +import board +import rp2pio + +# --- Audio: signed-16 sine wave, double-buffered so it uses the DMA IRQ path. +SAMPLE_RATE = 16000 +SAMPLE_COUNT = 4000 # even count (required for single_buffer=False) +PERIODS = 32 +sine = array.array("h", [0] * SAMPLE_COUNT) +for i in range(SAMPLE_COUNT): + sine[i] = int(math.sin(2 * math.pi * PERIODS * i / SAMPLE_COUNT) * (2**14)) +sample = audiocore.RawSample(sine, sample_rate=SAMPLE_RATE, single_buffer=False) + +audio = audiopwmio.PWMAudioOut(board.GP13) +audio.play(sample, loop=True) +print("audio playing:", audio.playing) + +# --- PIO loopback program (hand assembled): +# .wrap_target +# out pins, 1 ; 0x6001 shift one bit OSR -> output pin (GP2) +# in pins, 1 ; 0x4001 shift one bit input pin (GP3) -> ISR +# .wrap +# auto_pull/auto_push at 32 bits keep both FIFOs (and their DMA) moving. +PROGRAM = array.array("H", [0x6001, 0x4001]) +sm = rp2pio.StateMachine( + PROGRAM, + frequency=2_000_000, + first_out_pin=board.GP2, + first_in_pin=board.GP3, + auto_pull=True, + pull_threshold=32, + out_shift_right=True, + auto_push=True, + push_threshold=32, + in_shift_right=True, +) + +out_buf = array.array("I", [0x0F0F0F0F] * 1024) +in_buf = array.array("I", [0] * 1024) + +# Continuous background write to keep the state machine clocking. +sm.background_write(loop=out_buf) + +ITERATIONS = 100 +for n in range(ITERATIONS): + sm.background_read(once=in_buf) + deadline = time.monotonic() + 2.0 + while sm.reading and time.monotonic() < deadline: + pass + if sm.reading: + raise RuntimeError(f"background_read stuck on iteration {n} (shared DMA IRQ wedged?)") + if not audio.playing: + raise RuntimeError(f"audio stopped unexpectedly on iteration {n}") + if n % 20 == 0: + print("iteration", n, "audio.playing", audio.playing, "first read word", hex(in_buf[0])) + +sm.stop_background_write() +audio.stop() +sm.deinit() +audio.deinit() +print("PASS: audio + rp2pio background write/read shared DMA_IRQ_0 for", ITERATIONS, "iterations") diff --git a/tests/circuitpython-manual/rp2pio/audio_dma_shared_irq_write.py b/tests/circuitpython-manual/rp2pio/audio_dma_shared_irq_write.py new file mode 100644 index 00000000000..fe00df06815 --- /dev/null +++ b/tests/circuitpython-manual/rp2pio/audio_dma_shared_irq_write.py @@ -0,0 +1,67 @@ +"""Audio playback + rp2pio background_write sharing DMA_IRQ_0. + +This is the scenario from issue #9868: audio output and a PIO peripheral (e.g. a +status NeoPixel) both want DMA completion interrupts at the same time. Audio +uses the interrupt-driven double-buffered path (`single_buffer=False`) and +rp2pio uses background_write, so both subsystems are serviced by DMA_IRQ_0 +concurrently. + +The test passes if the PIO writes keep completing AND audio keeps playing for +the whole run. A hang, crash, or audio stopping early indicates a regression. + +Wiring: PWM audio on GP13 (speaker optional), PIO output on GP2 (no connection +required). +""" + +import array +import math +import time + +import audiocore +import audiopwmio +import board +import rp2pio + +# --- Audio: signed-16 sine wave, double-buffered so it uses the DMA IRQ path. +SAMPLE_RATE = 16000 +SAMPLE_COUNT = 4000 # even count (required for single_buffer=False), several periods +PERIODS = 32 +sine = array.array("h", [0] * SAMPLE_COUNT) +for i in range(SAMPLE_COUNT): + sine[i] = int(math.sin(2 * math.pi * PERIODS * i / SAMPLE_COUNT) * (2**14)) +sample = audiocore.RawSample(sine, sample_rate=SAMPLE_RATE, single_buffer=False) + +audio = audiopwmio.PWMAudioOut(board.GP13) +audio.play(sample, loop=True) +print("audio playing:", audio.playing) + +# --- PIO: drain program that clocks the TX FIFO out on GP2 (see +# pio_background_write.py for the encoding). +PROGRAM = array.array("H", [0x6001]) +sm = rp2pio.StateMachine( + PROGRAM, + frequency=2_000_000, + first_out_pin=board.GP2, + auto_pull=True, + pull_threshold=32, + out_shift_right=True, +) +data = array.array("I", [0x5555AAAA] * 4096) + +ITERATIONS = 100 +for n in range(ITERATIONS): + sm.background_write(once=data) + deadline = time.monotonic() + 2.0 + while sm.writing and time.monotonic() < deadline: + pass + if sm.writing: + raise RuntimeError(f"background_write stuck on iteration {n} (shared DMA IRQ wedged?)") + if not audio.playing: + raise RuntimeError(f"audio stopped unexpectedly on iteration {n}") + if n % 20 == 0: + print("iteration", n, "audio.playing", audio.playing) + +audio.stop() +sm.deinit() +audio.deinit() +print("PASS: audio + rp2pio background_write shared DMA_IRQ_0 for", ITERATIONS, "iterations") diff --git a/tests/circuitpython-manual/rp2pio/pio_background_write.py b/tests/circuitpython-manual/rp2pio/pio_background_write.py new file mode 100644 index 00000000000..796175da7b1 --- /dev/null +++ b/tests/circuitpython-manual/rp2pio/pio_background_write.py @@ -0,0 +1,53 @@ +"""Baseline: rp2pio background_write DMA only (no audio). + +Exercises the PIO *write* arm of the shared DMA_IRQ_0 handler, plus the +add/remove of the shared handler as the only channel comes and goes. + +Repeatedly starts a one-shot background write and waits for it to finish by +polling `StateMachine.writing`. If `writing` never clears, the DMA completion +interrupt is not being serviced (a regression). Ends with a PASS line. + +Wiring: PIO output on GP2 (no connection required). +""" + +import array +import time + +import board +import rp2pio + +# PIO program (hand assembled, no adafruit_pioasm dependency): +# .wrap_target +# out pins, 1 ; shift one bit from OSR to the output pin +# .wrap +# With auto_pull and pull_threshold=32, the OSR is refilled from the TX FIFO +# every 32 bits, so the FIFO (and therefore the DMA) drains continuously. +# Encoding of `out pins, 1`: opcode OUT=0b011, dest PINS=0b000, count 1 -> 0x6001 +PROGRAM = array.array("H", [0x6001]) + +sm = rp2pio.StateMachine( + PROGRAM, + frequency=2_000_000, + first_out_pin=board.GP2, + auto_pull=True, + pull_threshold=32, + out_shift_right=True, +) + +# 16 KB of data per transfer, enough that the DMA genuinely runs and completes +# via interrupt rather than fitting in the FIFO. +data = array.array("I", [0x5555AAAA] * 4096) + +ITERATIONS = 50 +for n in range(ITERATIONS): + sm.background_write(once=data) + deadline = time.monotonic() + 2.0 + while sm.writing and time.monotonic() < deadline: + pass + if sm.writing: + raise RuntimeError(f"background_write stuck on iteration {n} (DMA IRQ not serviced?)") + if n % 10 == 0: + print("iteration", n, "ok") + +sm.deinit() +print("PASS: rp2pio background_write completed", ITERATIONS, "times") diff --git a/tests/circuitpython-manual/settings/code.py b/tests/circuitpython-manual/settings/code.py new file mode 100644 index 00000000000..bebed3d11ae --- /dev/null +++ b/tests/circuitpython-manual/settings/code.py @@ -0,0 +1,66 @@ +# Test supervisor.get_setting() parsing of settings.toml values. +# Copy settings.toml to the root of the board, then run this script. +# All lines should print PASS. + +import math +import supervisor + + +def check(key, expected): + got = supervisor.get_setting(key) + if type(got) is not type(expected): + print( + f"FAIL {key}: expected type {type(expected).__name__}, got {type(got).__name__} ({got!r})" + ) + return + if isinstance(expected, float) and math.isnan(expected): + ok = math.isnan(got) + else: + ok = got == expected + if ok: + print(f"PASS {key}") + else: + print(f"FAIL {key}: expected {expected!r}, got {got!r}") + + +check("str_val", "hello") +check("int_val", 42) +check("neg_int_val", -7) +check("hex_int_val", 31) +check("bool_true", True) +check("bool_false", False) +check("float_val", 3.14) +check("neg_float_val", -1.5) +check("sci_float_val", 6.626e-34) +# math.nan and math.inf are not always available +check("pos_inf", float("inf")) +check("neg_inf", -float("inf")) +check("pos_nan", float("nan")) + + +def check_bad(key): + try: + got = supervisor.get_setting(key) + print(f"FAIL {key}: expected ValueError, got {got!r}") + except ValueError: + print(f"PASS {key} raises ValueError") + + +check_bad("bad_word") # unquoted non-boolean word +check_bad("bad_float_junk") # float with trailing garbage +check_bad("bad_inf_junk") # inf with trailing characters +check_bad("bad_lone_sign") # bare + with nothing after it + +# Missing key returns default +got = supervisor.get_setting("no_such_key", "default") +if got == "default": + print("PASS missing key default") +else: + print(f"FAIL missing key default: got {got!r}") + +# Invalid value raises ValueError +try: + supervisor.get_setting("str_val") # quoted string is valid + print("PASS str via get_setting") +except ValueError: + print("FAIL str via get_setting raised ValueError unexpectedly") diff --git a/tests/circuitpython-manual/settings/settings.toml b/tests/circuitpython-manual/settings/settings.toml new file mode 100644 index 00000000000..5df2d104afe --- /dev/null +++ b/tests/circuitpython-manual/settings/settings.toml @@ -0,0 +1,16 @@ +str_val = "hello" +bad_word = hello +bad_float_junk = 1.2abc +bad_inf_junk = infoo +bad_lone_sign = + +int_val = 42 +neg_int_val = -7 +hex_int_val = 0x1F +bool_true = true +bool_false = false +float_val = 3.14 +neg_float_val = -1.5 +sci_float_val = 6.626e-34 +pos_inf = inf +neg_inf = -inf +pos_nan = nan diff --git a/tests/circuitpython/audiofilter_filter_stereo.py b/tests/circuitpython/audiofilter_filter_stereo.py new file mode 100644 index 00000000000..f260286f931 --- /dev/null +++ b/tests/circuitpython/audiofilter_filter_stereo.py @@ -0,0 +1,24 @@ +from audiofilters import Filter +from audiofilterhelper import synth_test, sine8k +from audiomixer import Mixer +from synthio import LFO + + +@synth_test +def stereo_filter(): + args = { + "bits_per_sample": 16, + "samples_signed": True, + "channel_count": 2, + } + effect = Filter(**args) + mixer = Mixer(**args) + mixer.voice[0].panning = LFO() + effect.play(mixer) + yield effect, [] + + mixer.play(sine8k, loop=True) + yield 40 + + mixer.stop_voice() + yield 20 diff --git a/tests/circuitpython/audiofilter_filter_stereo.py.exp b/tests/circuitpython/audiofilter_filter_stereo.py.exp new file mode 100644 index 00000000000..960c143a1ef --- /dev/null +++ b/tests/circuitpython/audiofilter_filter_stereo.py.exp @@ -0,0 +1,15360 @@ +0 0.0 +1 0.0 +2 0.0 +3 0.0 +4 0.0 +5 0.0 +6 0.0 +7 0.0 +8 0.0 +9 0.0 +10 0.0 +11 0.0 +12 0.0 +13 0.0 +14 0.0 +15 0.0 +16 0.0 +17 0.0 +18 0.0 +19 0.0 +20 0.0 +21 0.0 +22 0.0 +23 0.0 +24 0.0 +25 0.0 +26 0.0 +27 0.0 +28 0.0 +29 0.0 +30 0.0 +31 0.0 +32 0.0 +33 0.0 +34 0.0 +35 0.0 +36 0.0 +37 0.0 +38 0.0 +39 0.0 +40 0.0 +41 0.0 +42 0.0 +43 0.0 +44 0.0 +45 0.0 +46 0.0 +47 0.0 +48 0.0 +49 0.0 +50 0.0 +51 0.0 +52 0.0 +53 0.0 +54 0.0 +55 0.0 +56 0.0 +57 0.0 +58 0.0 +59 0.0 +60 0.0 +61 0.0 +62 0.0 +63 0.0 +64 0.0 +65 0.0 +66 0.0 +67 0.0 +68 0.0 +69 0.0 +70 0.0 +71 0.0 +72 0.0 +73 0.0 +74 0.0 +75 0.0 +76 0.0 +77 0.0 +78 0.0 +79 0.0 +80 0.0 +81 0.0 +82 0.0 +83 0.0 +84 0.0 +85 0.0 +86 0.0 +87 0.0 +88 0.0 +89 0.0 +90 0.0 +91 0.0 +92 0.0 +93 0.0 +94 0.0 +95 0.0 +96 0.0 +97 0.0 +98 0.0 +99 0.0 +100 0.0 +101 0.0 +102 0.0 +103 0.0 +104 0.0 +105 0.0 +106 0.0 +107 0.0 +108 0.0 +109 0.0 +110 0.0 +111 0.0 +112 0.0 +113 0.0 +114 0.0 +115 0.0 +116 0.0 +117 0.0 +118 0.0 +119 0.0 +120 0.0 +121 0.0 +122 0.0 +123 0.0 +124 0.0 +125 0.0 +126 0.0 +127 0.0 +128 0.0 +129 0.0 +130 0.0 +131 0.0 +132 0.0 +133 0.0 +134 0.0 +135 0.0 +136 0.0 +137 0.0 +138 0.0 +139 0.0 +140 0.0 +141 0.0 +142 0.0 +143 0.0 +144 0.0 +145 0.0 +146 0.0 +147 0.0 +148 0.0 +149 0.0 +150 0.0 +151 0.0 +152 0.0 +153 0.0 +154 0.0 +155 0.0 +156 0.0 +157 0.0 +158 0.0 +159 0.0 +160 0.0 +161 0.0 +162 0.0 +163 0.0 +164 0.0 +165 0.0 +166 0.0 +167 0.0 +168 0.0 +169 0.0 +170 0.0 +171 0.0 +172 0.0 +173 0.0 +174 0.0 +175 0.0 +176 0.0 +177 0.0 +178 0.0 +179 0.0 +180 0.0 +181 0.0 +182 0.0 +183 0.0 +184 0.0 +185 0.0 +186 0.0 +187 0.0 +188 0.0 +189 0.0 +190 0.0 +191 0.0 +192 0.0 +193 0.0 +194 0.0 +195 0.0 +196 0.0 +197 0.0 +198 0.0 +199 0.0 +200 0.0 +201 0.0 +202 0.0 +203 0.0 +204 0.0 +205 0.0 +206 0.0 +207 0.0 +208 0.0 +209 0.0 +210 0.0 +211 0.0 +212 0.0 +213 0.0 +214 0.0 +215 0.0 +216 0.0 +217 0.0 +218 0.0 +219 0.0 +220 0.0 +221 0.0 +222 0.0 +223 0.0 +224 0.0 +225 0.0 +226 0.0 +227 0.0 +228 0.0 +229 0.0 +230 0.0 +231 0.0 +232 0.0 +233 0.0 +234 0.0 +235 0.0 +236 0.0 +237 0.0 +238 0.0 +239 0.0 +240 0.0 +241 0.0 +242 0.0 +243 0.0 +244 0.0 +245 0.0 +246 0.0 +247 0.0 +248 0.0 +249 0.0 +250 0.0 +251 0.0 +252 0.0 +253 0.0 +254 0.0 +255 0.0 +256 0.0 +257 0.0 +258 0.0101318359375 +259 0.010467529296875 +260 0.020263671875 +261 0.02093505859375 +262 0.0303955078125 +263 0.031402587890625 +264 0.04052734375 +265 0.0418701171875 +266 0.050628662109375 +267 0.05230712890625 +268 0.060760498046875 +269 0.062774658203125 +270 0.07086181640625 +271 0.073211669921875 +272 0.080963134765625 +273 0.083648681640625 +274 0.091064453125 +275 0.094085693359375 +276 0.101165771484375 +277 0.104522705078125 +278 0.111236572265625 +279 0.11492919921875 +280 0.12127685546875 +281 0.12530517578125 +282 0.131317138671875 +283 0.13568115234375 +284 0.141357421875 +285 0.14605712890625 +286 0.1513671875 +287 0.156402587890625 +288 0.161407470703125 +289 0.166748046875 +290 0.17138671875 +291 0.17706298828125 +292 0.18133544921875 +293 0.187347412109375 +294 0.1912841796875 +295 0.1976318359375 +296 0.201202392578125 +297 0.2078857421875 +298 0.21112060546875 +299 0.218109130859375 +300 0.22100830078125 +301 0.22833251953125 +302 0.230865478515625 +303 0.238525390625 +304 0.240692138671875 +305 0.2486572265625 +306 0.25048828125 +307 0.2587890625 +308 0.26025390625 +309 0.268890380859375 +310 0.27001953125 +311 0.278961181640625 +312 0.27972412109375 +313 0.28900146484375 +314 0.2894287109375 +315 0.29901123046875 +316 0.299072265625 +317 0.308990478515625 +318 0.3087158203125 +319 0.318939208984375 +320 0.31829833984375 +321 0.328826904296875 +322 0.327850341796875 +323 0.338714599609375 +324 0.337371826171875 +325 0.348541259765625 +326 0.34686279296875 +327 0.35833740234375 +328 0.356292724609375 +329 0.36810302734375 +330 0.365692138671875 +331 0.3778076171875 +332 0.37506103515625 +333 0.387481689453125 +334 0.3843994140625 +335 0.397125244140625 +336 0.3936767578125 +337 0.406707763671875 +338 0.402923583984375 +339 0.416259765625 +340 0.412109375 +341 0.425750732421875 +342 0.4212646484375 +343 0.435211181640625 +344 0.43035888671875 +345 0.444610595703125 +346 0.43939208984375 +347 0.453948974609375 +348 0.44842529296875 +349 0.4632568359375 +350 0.4573974609375 +351 0.4725341796875 +352 0.466278076171875 +353 0.481719970703125 +354 0.47515869140625 +355 0.490875244140625 +356 0.48394775390625 +357 0.499969482421875 +358 0.492706298828125 +359 0.509002685546875 +360 0.50140380859375 +361 0.51800537109375 +362 0.510040283203125 +363 0.52691650390625 +364 0.51861572265625 +365 0.535797119140625 +366 0.52716064453125 +367 0.54461669921875 +368 0.535614013671875 +369 0.5533447265625 +370 0.544036865234375 +371 0.562042236328125 +372 0.552398681640625 +373 0.5706787109375 +374 0.560699462890625 +375 0.579254150390625 +376 0.56890869140625 +377 0.587738037109375 +378 0.57708740234375 +379 0.59619140625 +380 0.585174560546875 +381 0.60455322265625 +382 0.59326171875 +383 0.612884521484375 +384 0.601226806640625 +385 0.621124267578125 +386 0.609100341796875 +387 0.6292724609375 +388 0.616973876953125 +389 0.63739013671875 +390 0.624725341796875 +391 0.645416259765625 +392 0.6324462890625 +393 0.65338134765625 +394 0.640106201171875 +395 0.661285400390625 +396 0.647674560546875 +397 0.669097900390625 +398 0.6551513671875 +399 0.676849365234375 +400 0.662567138671875 +401 0.68450927734375 +402 0.669921875 +403 0.692108154296875 +404 0.677215576171875 +405 0.699615478515625 +406 0.684417724609375 +407 0.707061767578125 +408 0.691558837890625 +409 0.714447021484375 +410 0.698577880859375 +411 0.721710205078125 +412 0.705596923828125 +413 0.72894287109375 +414 0.71246337890625 +415 0.736053466796875 +416 0.71929931640625 +417 0.74310302734375 +418 0.726043701171875 +419 0.75006103515625 +420 0.732696533203125 +421 0.7569580078125 +422 0.739288330078125 +423 0.763763427734375 +424 0.74578857421875 +425 0.770477294921875 +426 0.752197265625 +427 0.777099609375 +428 0.758544921875 +429 0.783660888671875 +430 0.76483154296875 +431 0.790130615234375 +432 0.770965576171875 +433 0.796478271484375 +434 0.77703857421875 +435 0.802764892578125 +436 0.7830810546875 +437 0.808990478515625 +438 0.788970947265625 +439 0.815093994140625 +440 0.7947998046875 +441 0.82110595703125 +442 0.800537109375 +443 0.8270263671875 +444 0.80621337890625 +445 0.8328857421875 +446 0.811767578125 +447 0.838623046875 +448 0.8172607421875 +449 0.84429931640625 +450 0.8226318359375 +451 0.849853515625 +452 0.827911376953125 +453 0.855316162109375 +454 0.8331298828125 +455 0.860687255859375 +456 0.8382568359375 +457 0.865997314453125 +458 0.843292236328125 +459 0.871185302734375 +460 0.848175048828125 +461 0.876251220703125 +462 0.85302734375 +463 0.881256103515625 +464 0.8577880859375 +465 0.88616943359375 +466 0.8624267578125 +467 0.890960693359375 +468 0.866973876953125 +469 0.895660400390625 +470 0.871429443359375 +471 0.9002685546875 +472 0.87579345703125 +473 0.90478515625 +474 0.88006591796875 +475 0.9091796875 +476 0.884246826171875 +477 0.91351318359375 +478 0.888336181640625 +479 0.917724609375 +480 0.89227294921875 +481 0.92181396484375 +482 0.89617919921875 +483 0.92584228515625 +484 0.899932861328125 +485 0.929718017578125 +486 0.90362548828125 +487 0.93353271484375 +488 0.907196044921875 +489 0.937225341796875 +490 0.91070556640625 +491 0.940826416015625 +492 0.914093017578125 +493 0.9443359375 +494 0.9173583984375 +495 0.947723388671875 +496 0.920562744140625 +497 0.951019287109375 +498 0.92364501953125 +499 0.954193115234375 +500 0.926605224609375 +501 0.957275390625 +502 0.929473876953125 +503 0.960235595703125 +504 0.9322509765625 +505 0.963104248046875 +506 0.9349365234375 +507 0.96588134765625 +508 0.9375 +509 0.968536376953125 +510 0.94000244140625 +511 0.971099853515625 +512 0.911224365234375 +513 0.973541259765625 +514 0.91339111328125 +515 0.975860595703125 +516 0.91546630859375 +517 0.97808837890625 +518 0.91748046875 +519 0.980224609375 +520 0.91937255859375 +521 0.98223876953125 +522 0.921173095703125 +523 0.984161376953125 +524 0.9228515625 +525 0.9859619140625 +526 0.924407958984375 +527 0.987640380859375 +528 0.9259033203125 +529 0.989227294921875 +530 0.927276611328125 +531 0.990692138671875 +532 0.928558349609375 +533 0.9920654296875 +534 0.929718017578125 +535 0.993316650390625 +536 0.930816650390625 +537 0.994476318359375 +538 0.931793212890625 +539 0.995513916015625 +540 0.93267822265625 +541 0.9964599609375 +542 0.933441162109375 +543 0.997283935546875 +544 0.934112548828125 +545 0.99798583984375 +546 0.934661865234375 +547 0.99859619140625 +548 0.93511962890625 +549 0.999114990234375 +550 0.93548583984375 +551 0.999481201171875 +552 0.93572998046875 +553 0.999755859375 +554 0.9359130859375 +555 0.99993896484375 +556 0.93597412109375 +557 0.999969482421875 +558 0.9359130859375 +559 0.99993896484375 +560 0.93572998046875 +561 0.999755859375 +562 0.93548583984375 +563 0.999481201171875 +564 0.93511962890625 +565 0.999114990234375 +566 0.934661865234375 +567 0.99859619140625 +568 0.934112548828125 +569 0.99798583984375 +570 0.933441162109375 +571 0.997283935546875 +572 0.93267822265625 +573 0.9964599609375 +574 0.931793212890625 +575 0.995513916015625 +576 0.930816650390625 +577 0.994476318359375 +578 0.929718017578125 +579 0.993316650390625 +580 0.928558349609375 +581 0.9920654296875 +582 0.927276611328125 +583 0.990692138671875 +584 0.9259033203125 +585 0.989227294921875 +586 0.924407958984375 +587 0.987640380859375 +588 0.9228515625 +589 0.9859619140625 +590 0.921173095703125 +591 0.984161376953125 +592 0.91937255859375 +593 0.98223876953125 +594 0.91748046875 +595 0.980224609375 +596 0.91546630859375 +597 0.97808837890625 +598 0.91339111328125 +599 0.975860595703125 +600 0.911224365234375 +601 0.973541259765625 +602 0.908935546875 +603 0.971099853515625 +604 0.906524658203125 +605 0.968536376953125 +606 0.904052734375 +607 0.96588134765625 +608 0.901458740234375 +609 0.963104248046875 +610 0.898773193359375 +611 0.960235595703125 +612 0.89599609375 +613 0.957275390625 +614 0.893096923828125 +615 0.954193115234375 +616 0.89013671875 +617 0.951019287109375 +618 0.887054443359375 +619 0.947723388671875 +620 0.883880615234375 +621 0.9443359375 +622 0.880615234375 +623 0.940826416015625 +624 0.877227783203125 +625 0.937225341796875 +626 0.873779296875 +627 0.93353271484375 +628 0.870208740234375 +629 0.929718017578125 +630 0.8665771484375 +631 0.92584228515625 +632 0.86279296875 +633 0.92181396484375 +634 0.858978271484375 +635 0.917724609375 +636 0.85504150390625 +637 0.91351318359375 +638 0.850982666015625 +639 0.9091796875 +640 0.84686279296875 +641 0.90478515625 +642 0.8426513671875 +643 0.9002685546875 +644 0.83831787109375 +645 0.895660400390625 +646 0.83392333984375 +647 0.890960693359375 +648 0.829437255859375 +649 0.88616943359375 +650 0.8248291015625 +651 0.881256103515625 +652 0.820159912109375 +653 0.876251220703125 +654 0.8154296875 +655 0.871185302734375 +656 0.810546875 +657 0.865997314453125 +658 0.80560302734375 +659 0.860687255859375 +660 0.800567626953125 +661 0.855316162109375 +662 0.795440673828125 +663 0.849853515625 +664 0.790252685546875 +665 0.84429931640625 +666 0.784942626953125 +667 0.838623046875 +668 0.779571533203125 +669 0.8328857421875 +670 0.774078369140625 +671 0.8270263671875 +672 0.7685546875 +673 0.82110595703125 +674 0.762908935546875 +675 0.815093994140625 +676 0.7572021484375 +677 0.808990478515625 +678 0.751373291015625 +679 0.802764892578125 +680 0.7454833984375 +681 0.796478271484375 +682 0.73956298828125 +683 0.790130615234375 +684 0.733489990234375 +685 0.783660888671875 +686 0.72735595703125 +687 0.777099609375 +688 0.721160888671875 +689 0.770477294921875 +690 0.714874267578125 +691 0.763763427734375 +692 0.70849609375 +693 0.7569580078125 +694 0.702056884765625 +695 0.75006103515625 +696 0.695526123046875 +697 0.74310302734375 +698 0.688934326171875 +699 0.736053466796875 +700 0.682281494140625 +701 0.72894287109375 +702 0.675506591796875 +703 0.721710205078125 +704 0.668701171875 +705 0.714447021484375 +706 0.66180419921875 +707 0.707061767578125 +708 0.654815673828125 +709 0.699615478515625 +710 0.647796630859375 +711 0.692108154296875 +712 0.64068603515625 +713 0.68450927734375 +714 0.633514404296875 +715 0.676849365234375 +716 0.626251220703125 +717 0.669097900390625 +718 0.61895751953125 +719 0.661285400390625 +720 0.611541748046875 +721 0.65338134765625 +722 0.604095458984375 +723 0.645416259765625 +724 0.596588134765625 +725 0.63739013671875 +726 0.5889892578125 +727 0.6292724609375 +728 0.58135986328125 +729 0.621124267578125 +730 0.573638916015625 +731 0.612884521484375 +732 0.56585693359375 +733 0.60455322265625 +734 0.558013916015625 +735 0.59619140625 +736 0.55010986328125 +737 0.587738037109375 +738 0.54217529296875 +739 0.579254150390625 +740 0.534149169921875 +741 0.5706787109375 +742 0.52606201171875 +743 0.562042236328125 +744 0.517913818359375 +745 0.5533447265625 +746 0.509735107421875 +747 0.54461669921875 +748 0.501495361328125 +749 0.535797119140625 +750 0.493194580078125 +751 0.52691650390625 +752 0.484832763671875 +753 0.51800537109375 +754 0.476409912109375 +755 0.509002685546875 +756 0.46795654296875 +757 0.499969482421875 +758 0.459442138671875 +759 0.490875244140625 +760 0.45086669921875 +761 0.481719970703125 +762 0.442291259765625 +763 0.4725341796875 +764 0.43359375 +765 0.4632568359375 +766 0.424896240234375 +767 0.453948974609375 +768 0.40191650390625 +769 0.444610595703125 +770 0.393402099609375 +771 0.435211181640625 +772 0.384857177734375 +773 0.425750732421875 +774 0.37628173828125 +775 0.416259765625 +776 0.367645263671875 +777 0.406707763671875 +778 0.358978271484375 +779 0.397125244140625 +780 0.350250244140625 +781 0.387481689453125 +782 0.341522216796875 +783 0.3778076171875 +784 0.332733154296875 +785 0.36810302734375 +786 0.32391357421875 +787 0.35833740234375 +788 0.3150634765625 +789 0.348541259765625 +790 0.306182861328125 +791 0.338714599609375 +792 0.2972412109375 +793 0.328826904296875 +794 0.288299560546875 +795 0.318939208984375 +796 0.279296875 +797 0.308990478515625 +798 0.270294189453125 +799 0.29901123046875 +800 0.26123046875 +801 0.28900146484375 +802 0.252166748046875 +803 0.278961181640625 +804 0.243072509765625 +805 0.268890380859375 +806 0.233917236328125 +807 0.2587890625 +808 0.224761962890625 +809 0.2486572265625 +810 0.215606689453125 +811 0.238525390625 +812 0.206390380859375 +813 0.22833251953125 +814 0.1971435546875 +815 0.218109130859375 +816 0.187896728515625 +817 0.2078857421875 +818 0.17864990234375 +819 0.1976318359375 +820 0.169342041015625 +821 0.187347412109375 +822 0.1600341796875 +823 0.17706298828125 +824 0.150726318359375 +825 0.166748046875 +826 0.141357421875 +827 0.156402587890625 +828 0.13201904296875 +829 0.14605712890625 +830 0.122650146484375 +831 0.13568115234375 +832 0.113250732421875 +833 0.12530517578125 +834 0.1038818359375 +835 0.11492919921875 +836 0.094482421875 +837 0.104522705078125 +838 0.08502197265625 +839 0.094085693359375 +840 0.075592041015625 +841 0.083648681640625 +842 0.066162109375 +843 0.073211669921875 +844 0.056732177734375 +845 0.062774658203125 +846 0.047271728515625 +847 0.05230712890625 +848 0.037841796875 +849 0.0418701171875 +850 0.02838134765625 +851 0.031402587890625 +852 0.0189208984375 +853 0.02093505859375 +854 0.00946044921875 +855 0.010467529296875 +856 0.0 +857 0.0 +858 -0.00946044921875 +859 -0.010467529296875 +860 -0.0189208984375 +861 -0.02093505859375 +862 -0.02838134765625 +863 -0.031402587890625 +864 -0.037841796875 +865 -0.0418701171875 +866 -0.047271728515625 +867 -0.05230712890625 +868 -0.056732177734375 +869 -0.062774658203125 +870 -0.066162109375 +871 -0.073211669921875 +872 -0.075592041015625 +873 -0.083648681640625 +874 -0.08502197265625 +875 -0.094085693359375 +876 -0.094482421875 +877 -0.104522705078125 +878 -0.1038818359375 +879 -0.11492919921875 +880 -0.113250732421875 +881 -0.12530517578125 +882 -0.122650146484375 +883 -0.13568115234375 +884 -0.13201904296875 +885 -0.14605712890625 +886 -0.141357421875 +887 -0.156402587890625 +888 -0.150726318359375 +889 -0.166748046875 +890 -0.1600341796875 +891 -0.17706298828125 +892 -0.169342041015625 +893 -0.187347412109375 +894 -0.17864990234375 +895 -0.1976318359375 +896 -0.187896728515625 +897 -0.2078857421875 +898 -0.1971435546875 +899 -0.218109130859375 +900 -0.206390380859375 +901 -0.22833251953125 +902 -0.215606689453125 +903 -0.238525390625 +904 -0.224761962890625 +905 -0.2486572265625 +906 -0.233917236328125 +907 -0.2587890625 +908 -0.243072509765625 +909 -0.268890380859375 +910 -0.252166748046875 +911 -0.278961181640625 +912 -0.26123046875 +913 -0.28900146484375 +914 -0.270294189453125 +915 -0.29901123046875 +916 -0.279296875 +917 -0.308990478515625 +918 -0.288299560546875 +919 -0.318939208984375 +920 -0.2972412109375 +921 -0.328826904296875 +922 -0.306182861328125 +923 -0.338714599609375 +924 -0.3150634765625 +925 -0.348541259765625 +926 -0.32391357421875 +927 -0.35833740234375 +928 -0.332733154296875 +929 -0.36810302734375 +930 -0.341522216796875 +931 -0.3778076171875 +932 -0.350250244140625 +933 -0.387481689453125 +934 -0.358978271484375 +935 -0.397125244140625 +936 -0.367645263671875 +937 -0.406707763671875 +938 -0.37628173828125 +939 -0.416259765625 +940 -0.384857177734375 +941 -0.425750732421875 +942 -0.393402099609375 +943 -0.435211181640625 +944 -0.40191650390625 +945 -0.444610595703125 +946 -0.41033935546875 +947 -0.453948974609375 +948 -0.41876220703125 +949 -0.4632568359375 +950 -0.427154541015625 +951 -0.4725341796875 +952 -0.435455322265625 +953 -0.481719970703125 +954 -0.4437255859375 +955 -0.490875244140625 +956 -0.45196533203125 +957 -0.499969482421875 +958 -0.460113525390625 +959 -0.509002685546875 +960 -0.46826171875 +961 -0.51800537109375 +962 -0.476318359375 +963 -0.52691650390625 +964 -0.484344482421875 +965 -0.535797119140625 +966 -0.4923095703125 +967 -0.54461669921875 +968 -0.500213623046875 +969 -0.5533447265625 +970 -0.508056640625 +971 -0.562042236328125 +972 -0.515869140625 +973 -0.5706787109375 +974 -0.52362060546875 +975 -0.579254150390625 +976 -0.531280517578125 +977 -0.587738037109375 +978 -0.5389404296875 +979 -0.59619140625 +980 -0.5465087890625 +981 -0.60455322265625 +982 -0.55401611328125 +983 -0.612884521484375 +984 -0.56146240234375 +985 -0.621124267578125 +986 -0.56884765625 +987 -0.6292724609375 +988 -0.576171875 +989 -0.63739013671875 +990 -0.58343505859375 +991 -0.645416259765625 +992 -0.59063720703125 +993 -0.65338134765625 +994 -0.5977783203125 +995 -0.661285400390625 +996 -0.604827880859375 +997 -0.669097900390625 +998 -0.611846923828125 +999 -0.676849365234375 +1000 -0.6187744140625 +1001 -0.68450927734375 +1002 -0.625640869140625 +1003 -0.692108154296875 +1004 -0.632415771484375 +1005 -0.699615478515625 +1006 -0.63916015625 +1007 -0.707061767578125 +1008 -0.645843505859375 +1009 -0.714447021484375 +1010 -0.65240478515625 +1011 -0.721710205078125 +1012 -0.658935546875 +1013 -0.72894287109375 +1014 -0.665374755859375 +1015 -0.736053466796875 +1016 -0.6717529296875 +1017 -0.74310302734375 +1018 -0.67803955078125 +1019 -0.75006103515625 +1020 -0.68426513671875 +1021 -0.7569580078125 +1022 -0.6904296875 +1023 -0.763763427734375 +1024 -0.671844482421875 +1025 -0.770477294921875 +1026 -0.6776123046875 +1027 -0.777099609375 +1028 -0.683349609375 +1029 -0.783660888671875 +1030 -0.688995361328125 +1031 -0.790130615234375 +1032 -0.69451904296875 +1033 -0.796478271484375 +1034 -0.70001220703125 +1035 -0.802764892578125 +1036 -0.705413818359375 +1037 -0.808990478515625 +1038 -0.71075439453125 +1039 -0.815093994140625 +1040 -0.71600341796875 +1041 -0.82110595703125 +1042 -0.721160888671875 +1043 -0.8270263671875 +1044 -0.72625732421875 +1045 -0.8328857421875 +1046 -0.73126220703125 +1047 -0.838623046875 +1048 -0.7362060546875 +1049 -0.84429931640625 +1050 -0.741058349609375 +1051 -0.849853515625 +1052 -0.745819091796875 +1053 -0.855316162109375 +1054 -0.750518798828125 +1055 -0.860687255859375 +1056 -0.755126953125 +1057 -0.865997314453125 +1058 -0.759674072265625 +1059 -0.871185302734375 +1060 -0.764068603515625 +1061 -0.876251220703125 +1062 -0.7684326171875 +1063 -0.881256103515625 +1064 -0.772735595703125 +1065 -0.88616943359375 +1066 -0.77691650390625 +1067 -0.890960693359375 +1068 -0.781005859375 +1069 -0.895660400390625 +1070 -0.7850341796875 +1071 -0.9002685546875 +1072 -0.788970947265625 +1073 -0.90478515625 +1074 -0.79278564453125 +1075 -0.9091796875 +1076 -0.79656982421875 +1077 -0.91351318359375 +1078 -0.80023193359375 +1079 -0.917724609375 +1080 -0.803802490234375 +1081 -0.92181396484375 +1082 -0.80731201171875 +1083 -0.92584228515625 +1084 -0.810699462890625 +1085 -0.929718017578125 +1086 -0.81402587890625 +1087 -0.93353271484375 +1088 -0.8172607421875 +1089 -0.937225341796875 +1090 -0.820404052734375 +1091 -0.940826416015625 +1092 -0.823455810546875 +1093 -0.9443359375 +1094 -0.826416015625 +1095 -0.947723388671875 +1096 -0.82928466796875 +1097 -0.951019287109375 +1098 -0.83203125 +1099 -0.954193115234375 +1100 -0.834747314453125 +1101 -0.957275390625 +1102 -0.837310791015625 +1103 -0.960235595703125 +1104 -0.839813232421875 +1105 -0.963104248046875 +1106 -0.84222412109375 +1107 -0.96588134765625 +1108 -0.84454345703125 +1109 -0.968536376953125 +1110 -0.8468017578125 +1111 -0.971099853515625 +1112 -0.848907470703125 +1113 -0.973541259765625 +1114 -0.8509521484375 +1115 -0.975860595703125 +1116 -0.852874755859375 +1117 -0.97808837890625 +1118 -0.854736328125 +1119 -0.980224609375 +1120 -0.85650634765625 +1121 -0.98223876953125 +1122 -0.858184814453125 +1123 -0.984161376953125 +1124 -0.8597412109375 +1125 -0.9859619140625 +1126 -0.8612060546875 +1127 -0.987640380859375 +1128 -0.86260986328125 +1129 -0.989227294921875 +1130 -0.863861083984375 +1131 -0.990692138671875 +1132 -0.865081787109375 +1133 -0.9920654296875 +1134 -0.86614990234375 +1135 -0.993316650390625 +1136 -0.8671875 +1137 -0.994476318359375 +1138 -0.868072509765625 +1139 -0.995513916015625 +1140 -0.868896484375 +1141 -0.9964599609375 +1142 -0.86962890625 +1143 -0.997283935546875 +1144 -0.8702392578125 +1145 -0.99798583984375 +1146 -0.870758056640625 +1147 -0.99859619140625 +1148 -0.871185302734375 +1149 -0.999114990234375 +1150 -0.87152099609375 +1151 -0.999481201171875 +1152 -0.87176513671875 +1153 -0.999755859375 +1154 -0.871917724609375 +1155 -0.99993896484375 +1156 -0.871978759765625 +1157 -1.0 +1158 -0.871917724609375 +1159 -0.99993896484375 +1160 -0.87176513671875 +1161 -0.999755859375 +1162 -0.87152099609375 +1163 -0.999481201171875 +1164 -0.871185302734375 +1165 -0.999114990234375 +1166 -0.870758056640625 +1167 -0.99859619140625 +1168 -0.8702392578125 +1169 -0.99798583984375 +1170 -0.86962890625 +1171 -0.997283935546875 +1172 -0.868896484375 +1173 -0.9964599609375 +1174 -0.868072509765625 +1175 -0.995513916015625 +1176 -0.8671875 +1177 -0.994476318359375 +1178 -0.86614990234375 +1179 -0.993316650390625 +1180 -0.865081787109375 +1181 -0.9920654296875 +1182 -0.863861083984375 +1183 -0.990692138671875 +1184 -0.86260986328125 +1185 -0.989227294921875 +1186 -0.8612060546875 +1187 -0.987640380859375 +1188 -0.8597412109375 +1189 -0.9859619140625 +1190 -0.858184814453125 +1191 -0.984161376953125 +1192 -0.85650634765625 +1193 -0.98223876953125 +1194 -0.854736328125 +1195 -0.980224609375 +1196 -0.852874755859375 +1197 -0.97808837890625 +1198 -0.8509521484375 +1199 -0.975860595703125 +1200 -0.848907470703125 +1201 -0.973541259765625 +1202 -0.8468017578125 +1203 -0.971099853515625 +1204 -0.84454345703125 +1205 -0.968536376953125 +1206 -0.84222412109375 +1207 -0.96588134765625 +1208 -0.839813232421875 +1209 -0.963104248046875 +1210 -0.837310791015625 +1211 -0.960235595703125 +1212 -0.834747314453125 +1213 -0.957275390625 +1214 -0.83203125 +1215 -0.954193115234375 +1216 -0.82928466796875 +1217 -0.951019287109375 +1218 -0.826416015625 +1219 -0.947723388671875 +1220 -0.823455810546875 +1221 -0.9443359375 +1222 -0.820404052734375 +1223 -0.940826416015625 +1224 -0.8172607421875 +1225 -0.937225341796875 +1226 -0.81402587890625 +1227 -0.93353271484375 +1228 -0.810699462890625 +1229 -0.929718017578125 +1230 -0.80731201171875 +1231 -0.92584228515625 +1232 -0.803802490234375 +1233 -0.92181396484375 +1234 -0.80023193359375 +1235 -0.917724609375 +1236 -0.79656982421875 +1237 -0.91351318359375 +1238 -0.79278564453125 +1239 -0.9091796875 +1240 -0.788970947265625 +1241 -0.90478515625 +1242 -0.7850341796875 +1243 -0.9002685546875 +1244 -0.781005859375 +1245 -0.895660400390625 +1246 -0.77691650390625 +1247 -0.890960693359375 +1248 -0.772735595703125 +1249 -0.88616943359375 +1250 -0.7684326171875 +1251 -0.881256103515625 +1252 -0.764068603515625 +1253 -0.876251220703125 +1254 -0.759674072265625 +1255 -0.871185302734375 +1256 -0.755126953125 +1257 -0.865997314453125 +1258 -0.750518798828125 +1259 -0.860687255859375 +1260 -0.745819091796875 +1261 -0.855316162109375 +1262 -0.741058349609375 +1263 -0.849853515625 +1264 -0.7362060546875 +1265 -0.84429931640625 +1266 -0.73126220703125 +1267 -0.838623046875 +1268 -0.72625732421875 +1269 -0.8328857421875 +1270 -0.721160888671875 +1271 -0.8270263671875 +1272 -0.71600341796875 +1273 -0.82110595703125 +1274 -0.71075439453125 +1275 -0.815093994140625 +1276 -0.705413818359375 +1277 -0.808990478515625 +1278 -0.70001220703125 +1279 -0.802764892578125 +1280 -0.677001953125 +1281 -0.796478271484375 +1282 -0.671600341796875 +1283 -0.790130615234375 +1284 -0.666107177734375 +1285 -0.783660888671875 +1286 -0.6605224609375 +1287 -0.777099609375 +1288 -0.654876708984375 +1289 -0.770477294921875 +1290 -0.649169921875 +1291 -0.763763427734375 +1292 -0.643402099609375 +1293 -0.7569580078125 +1294 -0.637542724609375 +1295 -0.75006103515625 +1296 -0.631622314453125 +1297 -0.74310302734375 +1298 -0.625640869140625 +1299 -0.736053466796875 +1300 -0.619598388671875 +1301 -0.72894287109375 +1302 -0.613433837890625 +1303 -0.721710205078125 +1304 -0.607269287109375 +1305 -0.714447021484375 +1306 -0.600982666015625 +1307 -0.707061767578125 +1308 -0.59466552734375 +1309 -0.699615478515625 +1310 -0.588287353515625 +1311 -0.692108154296875 +1312 -0.581817626953125 +1313 -0.68450927734375 +1314 -0.5753173828125 +1315 -0.676849365234375 +1316 -0.5687255859375 +1317 -0.669097900390625 +1318 -0.56207275390625 +1319 -0.661285400390625 +1320 -0.55535888671875 +1321 -0.65338134765625 +1322 -0.548583984375 +1323 -0.645416259765625 +1324 -0.541778564453125 +1325 -0.63739013671875 +1326 -0.534881591796875 +1327 -0.6292724609375 +1328 -0.5279541015625 +1329 -0.621124267578125 +1330 -0.52093505859375 +1331 -0.612884521484375 +1332 -0.51385498046875 +1333 -0.60455322265625 +1334 -0.506744384765625 +1335 -0.59619140625 +1336 -0.49957275390625 +1337 -0.587738037109375 +1338 -0.492340087890625 +1339 -0.579254150390625 +1340 -0.485076904296875 +1341 -0.5706787109375 +1342 -0.47772216796875 +1343 -0.562042236328125 +1344 -0.4703369140625 +1345 -0.5533447265625 +1346 -0.462921142578125 +1347 -0.54461669921875 +1348 -0.455413818359375 +1349 -0.535797119140625 +1350 -0.4478759765625 +1351 -0.52691650390625 +1352 -0.440277099609375 +1353 -0.51800537109375 +1354 -0.432647705078125 +1355 -0.509002685546875 +1356 -0.424957275390625 +1357 -0.499969482421875 +1358 -0.417236328125 +1359 -0.490875244140625 +1360 -0.409454345703125 +1361 -0.481719970703125 +1362 -0.401641845703125 +1363 -0.4725341796875 +1364 -0.393768310546875 +1365 -0.4632568359375 +1366 -0.385833740234375 +1367 -0.453948974609375 +1368 -0.377899169921875 +1369 -0.444610595703125 +1370 -0.369903564453125 +1371 -0.435211181640625 +1372 -0.36187744140625 +1373 -0.425750732421875 +1374 -0.35382080078125 +1375 -0.416259765625 +1376 -0.345672607421875 +1377 -0.406707763671875 +1378 -0.337554931640625 +1379 -0.397125244140625 +1380 -0.329345703125 +1381 -0.387481689453125 +1382 -0.321136474609375 +1383 -0.3778076171875 +1384 -0.3128662109375 +1385 -0.36810302734375 +1386 -0.3045654296875 +1387 -0.35833740234375 +1388 -0.296234130859375 +1389 -0.348541259765625 +1390 -0.28790283203125 +1391 -0.338714599609375 +1392 -0.27947998046875 +1393 -0.328826904296875 +1394 -0.271087646484375 +1395 -0.318939208984375 +1396 -0.26263427734375 +1397 -0.308990478515625 +1398 -0.254150390625 +1399 -0.29901123046875 +1400 -0.245635986328125 +1401 -0.28900146484375 +1402 -0.237091064453125 +1403 -0.278961181640625 +1404 -0.228546142578125 +1405 -0.268890380859375 +1406 -0.219970703125 +1407 -0.2587890625 +1408 -0.211334228515625 +1409 -0.2486572265625 +1410 -0.202728271484375 +1411 -0.238525390625 +1412 -0.194061279296875 +1413 -0.22833251953125 +1414 -0.18536376953125 +1415 -0.218109130859375 +1416 -0.17669677734375 +1417 -0.2078857421875 +1418 -0.16796875 +1419 -0.1976318359375 +1420 -0.15924072265625 +1421 -0.187347412109375 +1422 -0.150482177734375 +1423 -0.17706298828125 +1424 -0.1417236328125 +1425 -0.166748046875 +1426 -0.1329345703125 +1427 -0.156402587890625 +1428 -0.1241455078125 +1429 -0.14605712890625 +1430 -0.115325927734375 +1431 -0.13568115234375 +1432 -0.10650634765625 +1433 -0.12530517578125 +1434 -0.097686767578125 +1435 -0.11492919921875 +1436 -0.088836669921875 +1437 -0.104522705078125 +1438 -0.0799560546875 +1439 -0.094085693359375 +1440 -0.071075439453125 +1441 -0.083648681640625 +1442 -0.062225341796875 +1443 -0.073211669921875 +1444 -0.0533447265625 +1445 -0.062774658203125 +1446 -0.04443359375 +1447 -0.05230712890625 +1448 -0.03558349609375 +1449 -0.0418701171875 +1450 -0.02667236328125 +1451 -0.031402587890625 +1452 -0.017791748046875 +1453 -0.02093505859375 +1454 -0.008880615234375 +1455 -0.010467529296875 +1456 0.0 +1457 0.0 +1458 0.0087890625 +1459 0.010467529296875 +1460 0.017578125 +1461 0.02093505859375 +1462 0.0263671875 +1463 0.031402587890625 +1464 0.03515625 +1465 0.0418701171875 +1466 0.043914794921875 +1467 0.05230712890625 +1468 0.052703857421875 +1469 0.062774658203125 +1470 0.061492919921875 +1471 0.073211669921875 +1472 0.07025146484375 +1473 0.083648681640625 +1474 0.079010009765625 +1475 0.094085693359375 +1476 0.0877685546875 +1477 0.104522705078125 +1478 0.096527099609375 +1479 0.11492919921875 +1480 0.105255126953125 +1481 0.12530517578125 +1482 0.11395263671875 +1483 0.13568115234375 +1484 0.1226806640625 +1485 0.14605712890625 +1486 0.13134765625 +1487 0.156402587890625 +1488 0.140045166015625 +1489 0.166748046875 +1490 0.148712158203125 +1491 0.17706298828125 +1492 0.1573486328125 +1493 0.187347412109375 +1494 0.165985107421875 +1495 0.1976318359375 +1496 0.17462158203125 +1497 0.2078857421875 +1498 0.183197021484375 +1499 0.218109130859375 +1500 0.1917724609375 +1501 0.22833251953125 +1502 0.200347900390625 +1503 0.238525390625 +1504 0.2088623046875 +1505 0.2486572265625 +1506 0.217376708984375 +1507 0.2587890625 +1508 0.225860595703125 +1509 0.268890380859375 +1510 0.23431396484375 +1511 0.278961181640625 +1512 0.24273681640625 +1513 0.28900146484375 +1514 0.25115966796875 +1515 0.29901123046875 +1516 0.259521484375 +1517 0.308990478515625 +1518 0.26788330078125 +1519 0.318939208984375 +1520 0.27618408203125 +1521 0.328826904296875 +1522 0.284515380859375 +1523 0.338714599609375 +1524 0.292755126953125 +1525 0.348541259765625 +1526 0.300994873046875 +1527 0.35833740234375 +1528 0.309173583984375 +1529 0.36810302734375 +1530 0.317352294921875 +1531 0.3778076171875 +1532 0.325469970703125 +1533 0.387481689453125 +1534 0.33355712890625 +1535 0.397125244140625 +1536 0.32861328125 +1537 0.406707763671875 +1538 0.336334228515625 +1539 0.416259765625 +1540 0.343994140625 +1541 0.425750732421875 +1542 0.351654052734375 +1543 0.435211181640625 +1544 0.359222412109375 +1545 0.444610595703125 +1546 0.366790771484375 +1547 0.453948974609375 +1548 0.374298095703125 +1549 0.4632568359375 +1550 0.381805419921875 +1551 0.4725341796875 +1552 0.38922119140625 +1553 0.481719970703125 +1554 0.3966064453125 +1555 0.490875244140625 +1556 0.403961181640625 +1557 0.499969482421875 +1558 0.4112548828125 +1559 0.509002685546875 +1560 0.418548583984375 +1561 0.51800537109375 +1562 0.425750732421875 +1563 0.52691650390625 +1564 0.43292236328125 +1565 0.535797119140625 +1566 0.440032958984375 +1567 0.54461669921875 +1568 0.44708251953125 +1569 0.5533447265625 +1570 0.454132080078125 +1571 0.562042236328125 +1572 0.461090087890625 +1573 0.5706787109375 +1574 0.468017578125 +1575 0.579254150390625 +1576 0.474884033203125 +1577 0.587738037109375 +1578 0.481719970703125 +1579 0.59619140625 +1580 0.48846435546875 +1581 0.60455322265625 +1582 0.495208740234375 +1583 0.612884521484375 +1584 0.501861572265625 +1585 0.621124267578125 +1586 0.508453369140625 +1587 0.6292724609375 +1588 0.5150146484375 +1589 0.63739013671875 +1590 0.521484375 +1591 0.645416259765625 +1592 0.527923583984375 +1593 0.65338134765625 +1594 0.5343017578125 +1595 0.661285400390625 +1596 0.540618896484375 +1597 0.669097900390625 +1598 0.546875 +1599 0.676849365234375 +1600 0.553070068359375 +1601 0.68450927734375 +1602 0.5592041015625 +1603 0.692108154296875 +1604 0.565277099609375 +1605 0.699615478515625 +1606 0.5712890625 +1607 0.707061767578125 +1608 0.5772705078125 +1609 0.714447021484375 +1610 0.5831298828125 +1611 0.721710205078125 +1612 0.5889892578125 +1613 0.72894287109375 +1614 0.5947265625 +1615 0.736053466796875 +1616 0.60040283203125 +1617 0.74310302734375 +1618 0.606048583984375 +1619 0.75006103515625 +1620 0.611602783203125 +1621 0.7569580078125 +1622 0.61712646484375 +1623 0.763763427734375 +1624 0.622528076171875 +1625 0.770477294921875 +1626 0.627899169921875 +1627 0.777099609375 +1628 0.6331787109375 +1629 0.783660888671875 +1630 0.638427734375 +1631 0.790130615234375 +1632 0.6435546875 +1633 0.796478271484375 +1634 0.64862060546875 +1635 0.802764892578125 +1636 0.653656005859375 +1637 0.808990478515625 +1638 0.658599853515625 +1639 0.815093994140625 +1640 0.6634521484375 +1641 0.82110595703125 +1642 0.668243408203125 +1643 0.8270263671875 +1644 0.6729736328125 +1645 0.8328857421875 +1646 0.6776123046875 +1647 0.838623046875 +1648 0.68218994140625 +1649 0.84429931640625 +1650 0.686676025390625 +1651 0.849853515625 +1652 0.69110107421875 +1653 0.855316162109375 +1654 0.6954345703125 +1655 0.860687255859375 +1656 0.69970703125 +1657 0.865997314453125 +1658 0.70391845703125 +1659 0.871185302734375 +1660 0.7080078125 +1661 0.876251220703125 +1662 0.7120361328125 +1663 0.881256103515625 +1664 0.71600341796875 +1665 0.88616943359375 +1666 0.719879150390625 +1667 0.890960693359375 +1668 0.72369384765625 +1669 0.895660400390625 +1670 0.7274169921875 +1671 0.9002685546875 +1672 0.731048583984375 +1673 0.90478515625 +1674 0.734619140625 +1675 0.9091796875 +1676 0.73809814453125 +1677 0.91351318359375 +1678 0.74151611328125 +1679 0.917724609375 +1680 0.74481201171875 +1681 0.92181396484375 +1682 0.748077392578125 +1683 0.92584228515625 +1684 0.751190185546875 +1685 0.929718017578125 +1686 0.7542724609375 +1687 0.93353271484375 +1688 0.75726318359375 +1689 0.937225341796875 +1690 0.76019287109375 +1691 0.940826416015625 +1692 0.763031005859375 +1693 0.9443359375 +1694 0.7657470703125 +1695 0.947723388671875 +1696 0.768402099609375 +1697 0.951019287109375 +1698 0.770965576171875 +1699 0.954193115234375 +1700 0.773468017578125 +1701 0.957275390625 +1702 0.775848388671875 +1703 0.960235595703125 +1704 0.778167724609375 +1705 0.963104248046875 +1706 0.780426025390625 +1707 0.96588134765625 +1708 0.782562255859375 +1709 0.968536376953125 +1710 0.784637451171875 +1711 0.971099853515625 +1712 0.78662109375 +1713 0.973541259765625 +1714 0.788482666015625 +1715 0.975860595703125 +1716 0.790283203125 +1717 0.97808837890625 +1718 0.792022705078125 +1719 0.980224609375 +1720 0.79364013671875 +1721 0.98223876953125 +1722 0.795196533203125 +1723 0.984161376953125 +1724 0.796661376953125 +1725 0.9859619140625 +1726 0.798004150390625 +1727 0.987640380859375 +1728 0.799285888671875 +1729 0.989227294921875 +1730 0.80047607421875 +1731 0.990692138671875 +1732 0.80157470703125 +1733 0.9920654296875 +1734 0.802581787109375 +1735 0.993316650390625 +1736 0.80352783203125 +1737 0.994476318359375 +1738 0.80438232421875 +1739 0.995513916015625 +1740 0.805145263671875 +1741 0.9964599609375 +1742 0.8057861328125 +1743 0.997283935546875 +1744 0.806365966796875 +1745 0.99798583984375 +1746 0.806854248046875 +1747 0.99859619140625 +1748 0.8072509765625 +1749 0.999114990234375 +1750 0.80755615234375 +1751 0.999481201171875 +1752 0.807769775390625 +1753 0.999755859375 +1754 0.80792236328125 +1755 0.99993896484375 +1756 0.8079833984375 +1757 0.999969482421875 +1758 0.80792236328125 +1759 0.99993896484375 +1760 0.807769775390625 +1761 0.999755859375 +1762 0.80755615234375 +1763 0.999481201171875 +1764 0.8072509765625 +1765 0.999114990234375 +1766 0.806854248046875 +1767 0.99859619140625 +1768 0.806365966796875 +1769 0.99798583984375 +1770 0.8057861328125 +1771 0.997283935546875 +1772 0.805145263671875 +1773 0.9964599609375 +1774 0.80438232421875 +1775 0.995513916015625 +1776 0.80352783203125 +1777 0.994476318359375 +1778 0.802581787109375 +1779 0.993316650390625 +1780 0.80157470703125 +1781 0.9920654296875 +1782 0.80047607421875 +1783 0.990692138671875 +1784 0.799285888671875 +1785 0.989227294921875 +1786 0.798004150390625 +1787 0.987640380859375 +1788 0.796661376953125 +1789 0.9859619140625 +1790 0.795196533203125 +1791 0.984161376953125 +1792 0.76220703125 +1793 0.98223876953125 +1794 0.7606201171875 +1795 0.980224609375 +1796 0.75897216796875 +1797 0.97808837890625 +1798 0.757232666015625 +1799 0.975860595703125 +1800 0.75543212890625 +1801 0.973541259765625 +1802 0.7535400390625 +1803 0.971099853515625 +1804 0.751556396484375 +1805 0.968536376953125 +1806 0.74951171875 +1807 0.96588134765625 +1808 0.747344970703125 +1809 0.963104248046875 +1810 0.7451171875 +1811 0.960235595703125 +1812 0.742828369140625 +1813 0.957275390625 +1814 0.740447998046875 +1815 0.954193115234375 +1816 0.73797607421875 +1817 0.951019287109375 +1818 0.73541259765625 +1819 0.947723388671875 +1820 0.7327880859375 +1821 0.9443359375 +1822 0.730072021484375 +1823 0.940826416015625 +1824 0.727264404296875 +1825 0.937225341796875 +1826 0.724395751953125 +1827 0.93353271484375 +1828 0.721435546875 +1829 0.929718017578125 +1830 0.71844482421875 +1831 0.92584228515625 +1832 0.715301513671875 +1833 0.92181396484375 +1834 0.712127685546875 +1835 0.917724609375 +1836 0.7088623046875 +1837 0.91351318359375 +1838 0.70550537109375 +1839 0.9091796875 +1840 0.70208740234375 +1841 0.90478515625 +1842 0.698577880859375 +1843 0.9002685546875 +1844 0.69500732421875 +1845 0.895660400390625 +1846 0.691375732421875 +1847 0.890960693359375 +1848 0.687652587890625 +1849 0.88616943359375 +1850 0.683837890625 +1851 0.881256103515625 +1852 0.679962158203125 +1853 0.876251220703125 +1854 0.676025390625 +1855 0.871185302734375 +1856 0.6719970703125 +1857 0.865997314453125 +1858 0.667877197265625 +1859 0.860687255859375 +1860 0.6636962890625 +1861 0.855316162109375 +1862 0.659454345703125 +1863 0.849853515625 +1864 0.6551513671875 +1865 0.84429931640625 +1866 0.6507568359375 +1867 0.838623046875 +1868 0.64630126953125 +1869 0.8328857421875 +1870 0.641754150390625 +1871 0.8270263671875 +1872 0.63714599609375 +1873 0.82110595703125 +1874 0.63250732421875 +1875 0.815093994140625 +1876 0.62774658203125 +1877 0.808990478515625 +1878 0.6229248046875 +1879 0.802764892578125 +1880 0.6180419921875 +1881 0.796478271484375 +1882 0.613128662109375 +1883 0.790130615234375 +1884 0.60809326171875 +1885 0.783660888671875 +1886 0.602996826171875 +1887 0.777099609375 +1888 0.597869873046875 +1889 0.770477294921875 +1890 0.5926513671875 +1891 0.763763427734375 +1892 0.587371826171875 +1893 0.7569580078125 +1894 0.58203125 +1895 0.75006103515625 +1896 0.576629638671875 +1897 0.74310302734375 +1898 0.5711669921875 +1899 0.736053466796875 +1900 0.565643310546875 +1901 0.72894287109375 +1902 0.560028076171875 +1903 0.721710205078125 +1904 0.55438232421875 +1905 0.714447021484375 +1906 0.548675537109375 +1907 0.707061767578125 +1908 0.542877197265625 +1909 0.699615478515625 +1910 0.53704833984375 +1911 0.692108154296875 +1912 0.531158447265625 +1913 0.68450927734375 +1914 0.52520751953125 +1915 0.676849365234375 +1916 0.519195556640625 +1917 0.669097900390625 +1918 0.513153076171875 +1919 0.661285400390625 +1920 0.50701904296875 +1921 0.65338134765625 +1922 0.500823974609375 +1923 0.645416259765625 +1924 0.494598388671875 +1925 0.63739013671875 +1926 0.48828125 +1927 0.6292724609375 +1928 0.481964111328125 +1929 0.621124267578125 +1930 0.4755859375 +1931 0.612884521484375 +1932 0.4691162109375 +1933 0.60455322265625 +1934 0.462615966796875 +1935 0.59619140625 +1936 0.4560546875 +1937 0.587738037109375 +1938 0.449493408203125 +1939 0.579254150390625 +1940 0.442840576171875 +1941 0.5706787109375 +1942 0.436126708984375 +1943 0.562042236328125 +1944 0.42938232421875 +1945 0.5533447265625 +1946 0.422607421875 +1947 0.54461669921875 +1948 0.415771484375 +1949 0.535797119140625 +1950 0.40887451171875 +1951 0.52691650390625 +1952 0.401947021484375 +1953 0.51800537109375 +1954 0.39495849609375 +1955 0.509002685546875 +1956 0.387969970703125 +1957 0.499969482421875 +1958 0.380889892578125 +1959 0.490875244140625 +1960 0.373809814453125 +1961 0.481719970703125 +1962 0.366668701171875 +1963 0.4725341796875 +1964 0.359466552734375 +1965 0.4632568359375 +1966 0.35223388671875 +1967 0.453948974609375 +1968 0.345001220703125 +1969 0.444610595703125 +1970 0.33770751953125 +1971 0.435211181640625 +1972 0.330352783203125 +1973 0.425750732421875 +1974 0.322998046875 +1975 0.416259765625 +1976 0.315582275390625 +1977 0.406707763671875 +1978 0.30816650390625 +1979 0.397125244140625 +1980 0.3006591796875 +1981 0.387481689453125 +1982 0.29315185546875 +1983 0.3778076171875 +1984 0.28564453125 +1985 0.36810302734375 +1986 0.278045654296875 +1987 0.35833740234375 +1988 0.27044677734375 +1989 0.348541259765625 +1990 0.2628173828125 +1991 0.338714599609375 +1992 0.255157470703125 +1993 0.328826904296875 +1994 0.247467041015625 +1995 0.318939208984375 +1996 0.23974609375 +1997 0.308990478515625 +1998 0.232025146484375 +1999 0.29901123046875 +2000 0.2242431640625 +2001 0.28900146484375 +2002 0.216461181640625 +2003 0.278961181640625 +2004 0.208648681640625 +2005 0.268890380859375 +2006 0.2008056640625 +2007 0.2587890625 +2008 0.19293212890625 +2009 0.2486572265625 +2010 0.185089111328125 +2011 0.238525390625 +2012 0.177154541015625 +2013 0.22833251953125 +2014 0.16925048828125 +2015 0.218109130859375 +2016 0.16131591796875 +2017 0.2078857421875 +2018 0.153350830078125 +2019 0.1976318359375 +2020 0.145355224609375 +2021 0.187347412109375 +2022 0.13739013671875 +2023 0.17706298828125 +2024 0.12939453125 +2025 0.166748046875 +2026 0.121337890625 +2027 0.156402587890625 +2028 0.113311767578125 +2029 0.14605712890625 +2030 0.10528564453125 +2031 0.13568115234375 +2032 0.09722900390625 +2033 0.12530517578125 +2034 0.08917236328125 +2035 0.11492919921875 +2036 0.081085205078125 +2037 0.104522705078125 +2038 0.072998046875 +2039 0.094085693359375 +2040 0.064910888671875 +2041 0.083648681640625 +2042 0.056793212890625 +2043 0.073211669921875 +2044 0.0487060546875 +2045 0.062774658203125 +2046 0.04058837890625 +2047 0.05230712890625 +2048 0.0311279296875 +2049 0.0418701171875 +2050 0.023345947265625 +2051 0.031402587890625 +2052 0.01556396484375 +2053 0.02093505859375 +2054 0.007781982421875 +2055 0.010467529296875 +2056 0.0 +2057 0.0 +2058 -0.007781982421875 +2059 -0.010467529296875 +2060 -0.01556396484375 +2061 -0.02093505859375 +2062 -0.023345947265625 +2063 -0.031402587890625 +2064 -0.0311279296875 +2065 -0.0418701171875 +2066 -0.038909912109375 +2067 -0.05230712890625 +2068 -0.04669189453125 +2069 -0.062774658203125 +2070 -0.054443359375 +2071 -0.073211669921875 +2072 -0.062225341796875 +2073 -0.083648681640625 +2074 -0.069976806640625 +2075 -0.094085693359375 +2076 -0.0777587890625 +2077 -0.104522705078125 +2078 -0.085479736328125 +2079 -0.11492919921875 +2080 -0.09320068359375 +2081 -0.12530517578125 +2082 -0.100921630859375 +2083 -0.13568115234375 +2084 -0.108642578125 +2085 -0.14605712890625 +2086 -0.116363525390625 +2087 -0.156402587890625 +2088 -0.124053955078125 +2089 -0.166748046875 +2090 -0.1317138671875 +2091 -0.17706298828125 +2092 -0.139373779296875 +2093 -0.187347412109375 +2094 -0.14703369140625 +2095 -0.1976318359375 +2096 -0.1546630859375 +2097 -0.2078857421875 +2098 -0.162261962890625 +2099 -0.218109130859375 +2100 -0.16986083984375 +2101 -0.22833251953125 +2102 -0.177459716796875 +2103 -0.238525390625 +2104 -0.18499755859375 +2105 -0.2486572265625 +2106 -0.192535400390625 +2107 -0.2587890625 +2108 -0.200042724609375 +2109 -0.268890380859375 +2110 -0.207550048828125 +2111 -0.278961181640625 +2112 -0.214996337890625 +2113 -0.28900146484375 +2114 -0.222442626953125 +2115 -0.29901123046875 +2116 -0.229888916015625 +2117 -0.308990478515625 +2118 -0.237274169921875 +2119 -0.318939208984375 +2120 -0.24462890625 +2121 -0.328826904296875 +2122 -0.251983642578125 +2123 -0.338714599609375 +2124 -0.259307861328125 +2125 -0.348541259765625 +2126 -0.2666015625 +2127 -0.35833740234375 +2128 -0.27386474609375 +2129 -0.36810302734375 +2130 -0.28106689453125 +2131 -0.3778076171875 +2132 -0.28826904296875 +2133 -0.387481689453125 +2134 -0.295440673828125 +2135 -0.397125244140625 +2136 -0.302581787109375 +2137 -0.406707763671875 +2138 -0.3096923828125 +2139 -0.416259765625 +2140 -0.316741943359375 +2141 -0.425750732421875 +2142 -0.32379150390625 +2143 -0.435211181640625 +2144 -0.330780029296875 +2145 -0.444610595703125 +2146 -0.337738037109375 +2147 -0.453948974609375 +2148 -0.34466552734375 +2149 -0.4632568359375 +2150 -0.3515625 +2151 -0.4725341796875 +2152 -0.3583984375 +2153 -0.481719970703125 +2154 -0.365203857421875 +2155 -0.490875244140625 +2156 -0.371978759765625 +2157 -0.499969482421875 +2158 -0.378692626953125 +2159 -0.509002685546875 +2160 -0.3853759765625 +2161 -0.51800537109375 +2162 -0.39202880859375 +2163 -0.52691650390625 +2164 -0.39862060546875 +2165 -0.535797119140625 +2166 -0.405181884765625 +2167 -0.54461669921875 +2168 -0.41168212890625 +2169 -0.5533447265625 +2170 -0.41815185546875 +2171 -0.562042236328125 +2172 -0.424591064453125 +2173 -0.5706787109375 +2174 -0.43096923828125 +2175 -0.579254150390625 +2176 -0.437255859375 +2177 -0.587738037109375 +2178 -0.44354248046875 +2179 -0.59619140625 +2180 -0.44976806640625 +2181 -0.60455322265625 +2182 -0.455963134765625 +2183 -0.612884521484375 +2184 -0.46209716796875 +2185 -0.621124267578125 +2186 -0.468170166015625 +2187 -0.6292724609375 +2188 -0.474212646484375 +2189 -0.63739013671875 +2190 -0.480194091796875 +2191 -0.645416259765625 +2192 -0.486114501953125 +2193 -0.65338134765625 +2194 -0.491973876953125 +2195 -0.661285400390625 +2196 -0.497802734375 +2197 -0.669097900390625 +2198 -0.503570556640625 +2199 -0.676849365234375 +2200 -0.50927734375 +2201 -0.68450927734375 +2202 -0.514923095703125 +2203 -0.692108154296875 +2204 -0.5205078125 +2205 -0.699615478515625 +2206 -0.526031494140625 +2207 -0.707061767578125 +2208 -0.53155517578125 +2209 -0.714447021484375 +2210 -0.536956787109375 +2211 -0.721710205078125 +2212 -0.542327880859375 +2213 -0.72894287109375 +2214 -0.547607421875 +2215 -0.736053466796875 +2216 -0.5528564453125 +2217 -0.74310302734375 +2218 -0.55804443359375 +2219 -0.75006103515625 +2220 -0.56317138671875 +2221 -0.7569580078125 +2222 -0.5682373046875 +2223 -0.763763427734375 +2224 -0.5732421875 +2225 -0.770477294921875 +2226 -0.578155517578125 +2227 -0.777099609375 +2228 -0.583038330078125 +2229 -0.783660888671875 +2230 -0.587860107421875 +2231 -0.790130615234375 +2232 -0.592559814453125 +2233 -0.796478271484375 +2234 -0.597259521484375 +2235 -0.802764892578125 +2236 -0.60186767578125 +2237 -0.808990478515625 +2238 -0.606414794921875 +2239 -0.815093994140625 +2240 -0.61090087890625 +2241 -0.82110595703125 +2242 -0.61529541015625 +2243 -0.8270263671875 +2244 -0.619659423828125 +2245 -0.8328857421875 +2246 -0.623931884765625 +2247 -0.838623046875 +2248 -0.628143310546875 +2249 -0.84429931640625 +2250 -0.632293701171875 +2251 -0.849853515625 +2252 -0.6363525390625 +2253 -0.855316162109375 +2254 -0.640350341796875 +2255 -0.860687255859375 +2256 -0.644287109375 +2257 -0.865997314453125 +2258 -0.648162841796875 +2259 -0.871185302734375 +2260 -0.65191650390625 +2261 -0.876251220703125 +2262 -0.6556396484375 +2263 -0.881256103515625 +2264 -0.6593017578125 +2265 -0.88616943359375 +2266 -0.662872314453125 +2267 -0.890960693359375 +2268 -0.666351318359375 +2269 -0.895660400390625 +2270 -0.6697998046875 +2271 -0.9002685546875 +2272 -0.67315673828125 +2273 -0.90478515625 +2274 -0.676422119140625 +2275 -0.9091796875 +2276 -0.679656982421875 +2277 -0.91351318359375 +2278 -0.682769775390625 +2279 -0.917724609375 +2280 -0.685821533203125 +2281 -0.92181396484375 +2282 -0.688812255859375 +2283 -0.92584228515625 +2284 -0.69171142578125 +2285 -0.929718017578125 +2286 -0.694549560546875 +2287 -0.93353271484375 +2288 -0.697296142578125 +2289 -0.937225341796875 +2290 -0.699981689453125 +2291 -0.940826416015625 +2292 -0.70257568359375 +2293 -0.9443359375 +2294 -0.705108642578125 +2295 -0.947723388671875 +2296 -0.707550048828125 +2297 -0.951019287109375 +2298 -0.70989990234375 +2299 -0.954193115234375 +2300 -0.71221923828125 +2301 -0.957275390625 +2302 -0.71441650390625 +2303 -0.960235595703125 +2304 -0.685699462890625 +2305 -0.963104248046875 +2306 -0.68768310546875 +2307 -0.96588134765625 +2308 -0.6895751953125 +2309 -0.968536376953125 +2310 -0.69140625 +2311 -0.971099853515625 +2312 -0.693145751953125 +2313 -0.973541259765625 +2314 -0.694793701171875 +2315 -0.975860595703125 +2316 -0.696380615234375 +2317 -0.97808837890625 +2318 -0.697906494140625 +2319 -0.980224609375 +2320 -0.6993408203125 +2321 -0.98223876953125 +2322 -0.700714111328125 +2323 -0.984161376953125 +2324 -0.701995849609375 +2325 -0.9859619140625 +2326 -0.70318603515625 +2327 -0.987640380859375 +2328 -0.704315185546875 +2329 -0.989227294921875 +2330 -0.705352783203125 +2331 -0.990692138671875 +2332 -0.706329345703125 +2333 -0.9920654296875 +2334 -0.70721435546875 +2335 -0.993316650390625 +2336 -0.708038330078125 +2337 -0.994476318359375 +2338 -0.70880126953125 +2339 -0.995513916015625 +2340 -0.70947265625 +2341 -0.9964599609375 +2342 -0.710052490234375 +2343 -0.997283935546875 +2344 -0.710540771484375 +2345 -0.99798583984375 +2346 -0.710968017578125 +2347 -0.99859619140625 +2348 -0.711334228515625 +2349 -0.999114990234375 +2350 -0.711578369140625 +2351 -0.999481201171875 +2352 -0.7117919921875 +2353 -0.999755859375 +2354 -0.7119140625 +2355 -0.99993896484375 +2356 -0.71197509765625 +2357 -1.0 +2358 -0.7119140625 +2359 -0.99993896484375 +2360 -0.7117919921875 +2361 -0.999755859375 +2362 -0.711578369140625 +2363 -0.999481201171875 +2364 -0.711334228515625 +2365 -0.999114990234375 +2366 -0.710968017578125 +2367 -0.99859619140625 +2368 -0.710540771484375 +2369 -0.99798583984375 +2370 -0.710052490234375 +2371 -0.997283935546875 +2372 -0.70947265625 +2373 -0.9964599609375 +2374 -0.70880126953125 +2375 -0.995513916015625 +2376 -0.708038330078125 +2377 -0.994476318359375 +2378 -0.70721435546875 +2379 -0.993316650390625 +2380 -0.706329345703125 +2381 -0.9920654296875 +2382 -0.705352783203125 +2383 -0.990692138671875 +2384 -0.704315185546875 +2385 -0.989227294921875 +2386 -0.70318603515625 +2387 -0.987640380859375 +2388 -0.701995849609375 +2389 -0.9859619140625 +2390 -0.700714111328125 +2391 -0.984161376953125 +2392 -0.6993408203125 +2393 -0.98223876953125 +2394 -0.697906494140625 +2395 -0.980224609375 +2396 -0.696380615234375 +2397 -0.97808837890625 +2398 -0.694793701171875 +2399 -0.975860595703125 +2400 -0.693145751953125 +2401 -0.973541259765625 +2402 -0.69140625 +2403 -0.971099853515625 +2404 -0.6895751953125 +2405 -0.968536376953125 +2406 -0.68768310546875 +2407 -0.96588134765625 +2408 -0.685699462890625 +2409 -0.963104248046875 +2410 -0.68365478515625 +2411 -0.960235595703125 +2412 -0.681549072265625 +2413 -0.957275390625 +2414 -0.67938232421875 +2415 -0.954193115234375 +2416 -0.677093505859375 +2417 -0.951019287109375 +2418 -0.674774169921875 +2419 -0.947723388671875 +2420 -0.67236328125 +2421 -0.9443359375 +2422 -0.66986083984375 +2423 -0.940826416015625 +2424 -0.66729736328125 +2425 -0.937225341796875 +2426 -0.664642333984375 +2427 -0.93353271484375 +2428 -0.66192626953125 +2429 -0.929718017578125 +2430 -0.6591796875 +2431 -0.92584228515625 +2432 -0.65631103515625 +2433 -0.92181396484375 +2434 -0.653411865234375 +2435 -0.917724609375 +2436 -0.650390625 +2437 -0.91351318359375 +2438 -0.647308349609375 +2439 -0.9091796875 +2440 -0.644195556640625 +2441 -0.90478515625 +2442 -0.640960693359375 +2443 -0.9002685546875 +2444 -0.6376953125 +2445 -0.895660400390625 +2446 -0.63433837890625 +2447 -0.890960693359375 +2448 -0.63092041015625 +2449 -0.88616943359375 +2450 -0.62744140625 +2451 -0.881256103515625 +2452 -0.623870849609375 +2453 -0.876251220703125 +2454 -0.620269775390625 +2455 -0.871185302734375 +2456 -0.6165771484375 +2457 -0.865997314453125 +2458 -0.61279296875 +2459 -0.860687255859375 +2460 -0.608978271484375 +2461 -0.855316162109375 +2462 -0.605072021484375 +2463 -0.849853515625 +2464 -0.60113525390625 +2465 -0.84429931640625 +2466 -0.597076416015625 +2467 -0.838623046875 +2468 -0.592987060546875 +2469 -0.8328857421875 +2470 -0.588836669921875 +2471 -0.8270263671875 +2472 -0.5845947265625 +2473 -0.82110595703125 +2474 -0.580322265625 +2475 -0.815093994140625 +2476 -0.57598876953125 +2477 -0.808990478515625 +2478 -0.571563720703125 +2479 -0.802764892578125 +2480 -0.56707763671875 +2481 -0.796478271484375 +2482 -0.56256103515625 +2483 -0.790130615234375 +2484 -0.557952880859375 +2485 -0.783660888671875 +2486 -0.55328369140625 +2487 -0.777099609375 +2488 -0.548553466796875 +2489 -0.770477294921875 +2490 -0.543792724609375 +2491 -0.763763427734375 +2492 -0.5389404296875 +2493 -0.7569580078125 +2494 -0.534027099609375 +2495 -0.75006103515625 +2496 -0.529083251953125 +2497 -0.74310302734375 +2498 -0.5240478515625 +2499 -0.736053466796875 +2500 -0.51898193359375 +2501 -0.72894287109375 +2502 -0.51385498046875 +2503 -0.721710205078125 +2504 -0.5086669921875 +2505 -0.714447021484375 +2506 -0.50341796875 +2507 -0.707061767578125 +2508 -0.49810791015625 +2509 -0.699615478515625 +2510 -0.492767333984375 +2511 -0.692108154296875 +2512 -0.48736572265625 +2513 -0.68450927734375 +2514 -0.481903076171875 +2515 -0.676849365234375 +2516 -0.47637939453125 +2517 -0.669097900390625 +2518 -0.4708251953125 +2519 -0.661285400390625 +2520 -0.465179443359375 +2521 -0.65338134765625 +2522 -0.45953369140625 +2523 -0.645416259765625 +2524 -0.45379638671875 +2525 -0.63739013671875 +2526 -0.448028564453125 +2527 -0.6292724609375 +2528 -0.442230224609375 +2529 -0.621124267578125 +2530 -0.436370849609375 +2531 -0.612884521484375 +2532 -0.430419921875 +2533 -0.60455322265625 +2534 -0.424468994140625 +2535 -0.59619140625 +2536 -0.41845703125 +2537 -0.587738037109375 +2538 -0.41241455078125 +2539 -0.579254150390625 +2540 -0.40631103515625 +2541 -0.5706787109375 +2542 -0.400146484375 +2543 -0.562042236328125 +2544 -0.393951416015625 +2545 -0.5533447265625 +2546 -0.38775634765625 +2547 -0.54461669921875 +2548 -0.3814697265625 +2549 -0.535797119140625 +2550 -0.375152587890625 +2551 -0.52691650390625 +2552 -0.368804931640625 +2553 -0.51800537109375 +2554 -0.362396240234375 +2555 -0.509002685546875 +2556 -0.35595703125 +2557 -0.499969482421875 +2558 -0.3494873046875 +2559 -0.490875244140625 +2560 -0.337188720703125 +2561 -0.481719970703125 +2562 -0.33074951171875 +2563 -0.4725341796875 +2564 -0.32427978515625 +2565 -0.4632568359375 +2566 -0.3177490234375 +2567 -0.453948974609375 +2568 -0.31121826171875 +2569 -0.444610595703125 +2570 -0.30462646484375 +2571 -0.435211181640625 +2572 -0.298004150390625 +2573 -0.425750732421875 +2574 -0.2913818359375 +2575 -0.416259765625 +2576 -0.28466796875 +2577 -0.406707763671875 +2578 -0.277984619140625 +2579 -0.397125244140625 +2580 -0.271209716796875 +2581 -0.387481689453125 +2582 -0.26446533203125 +2583 -0.3778076171875 +2584 -0.257659912109375 +2585 -0.36810302734375 +2586 -0.250823974609375 +2587 -0.35833740234375 +2588 -0.24395751953125 +2589 -0.348541259765625 +2590 -0.237091064453125 +2591 -0.338714599609375 +2592 -0.23016357421875 +2593 -0.328826904296875 +2594 -0.223236083984375 +2595 -0.318939208984375 +2596 -0.216278076171875 +2597 -0.308990478515625 +2598 -0.20928955078125 +2599 -0.29901123046875 +2600 -0.202301025390625 +2601 -0.28900146484375 +2602 -0.19525146484375 +2603 -0.278961181640625 +2604 -0.188201904296875 +2605 -0.268890380859375 +2606 -0.18115234375 +2607 -0.2587890625 +2608 -0.174041748046875 +2609 -0.2486572265625 +2610 -0.166961669921875 +2611 -0.238525390625 +2612 -0.159820556640625 +2613 -0.22833251953125 +2614 -0.15264892578125 +2615 -0.218109130859375 +2616 -0.1455078125 +2617 -0.2078857421875 +2618 -0.138336181640625 +2619 -0.1976318359375 +2620 -0.131134033203125 +2621 -0.187347412109375 +2622 -0.123931884765625 +2623 -0.17706298828125 +2624 -0.11669921875 +2625 -0.166748046875 +2626 -0.109466552734375 +2627 -0.156402587890625 +2628 -0.10223388671875 +2629 -0.14605712890625 +2630 -0.094970703125 +2631 -0.13568115234375 +2632 -0.08770751953125 +2633 -0.12530517578125 +2634 -0.0804443359375 +2635 -0.11492919921875 +2636 -0.073150634765625 +2637 -0.104522705078125 +2638 -0.06585693359375 +2639 -0.094085693359375 +2640 -0.05853271484375 +2641 -0.083648681640625 +2642 -0.051239013671875 +2643 -0.073211669921875 +2644 -0.043914794921875 +2645 -0.062774658203125 +2646 -0.036590576171875 +2647 -0.05230712890625 +2648 -0.029296875 +2649 -0.0418701171875 +2650 -0.02197265625 +2651 -0.031402587890625 +2652 -0.0146484375 +2653 -0.02093505859375 +2654 -0.00732421875 +2655 -0.010467529296875 +2656 0.0 +2657 0.0 +2658 0.007110595703125 +2659 0.010467529296875 +2660 0.01422119140625 +2661 0.02093505859375 +2662 0.021331787109375 +2663 0.031402587890625 +2664 0.0284423828125 +2665 0.0418701171875 +2666 0.035552978515625 +2667 0.05230712890625 +2668 0.04266357421875 +2669 0.062774658203125 +2670 0.049774169921875 +2671 0.073211669921875 +2672 0.056854248046875 +2673 0.083648681640625 +2674 0.06396484375 +2675 0.094085693359375 +2676 0.071075439453125 +2677 0.104522705078125 +2678 0.078125 +2679 0.11492919921875 +2680 0.085205078125 +2681 0.12530517578125 +2682 0.092254638671875 +2683 0.13568115234375 +2684 0.09930419921875 +2685 0.14605712890625 +2686 0.106353759765625 +2687 0.156402587890625 +2688 0.113372802734375 +2689 0.166748046875 +2690 0.120391845703125 +2691 0.17706298828125 +2692 0.12738037109375 +2693 0.187347412109375 +2694 0.134368896484375 +2695 0.1976318359375 +2696 0.141357421875 +2697 0.2078857421875 +2698 0.1483154296875 +2699 0.218109130859375 +2700 0.155242919921875 +2701 0.22833251953125 +2702 0.16217041015625 +2703 0.238525390625 +2704 0.1690673828125 +2705 0.2486572265625 +2706 0.17596435546875 +2707 0.2587890625 +2708 0.182830810546875 +2709 0.268890380859375 +2710 0.189697265625 +2711 0.278961181640625 +2712 0.196502685546875 +2713 0.28900146484375 +2714 0.20330810546875 +2715 0.29901123046875 +2716 0.210113525390625 +2717 0.308990478515625 +2718 0.21685791015625 +2719 0.318939208984375 +2720 0.223602294921875 +2721 0.328826904296875 +2722 0.230316162109375 +2723 0.338714599609375 +2724 0.23699951171875 +2725 0.348541259765625 +2726 0.24365234375 +2727 0.35833740234375 +2728 0.25030517578125 +2729 0.36810302734375 +2730 0.25689697265625 +2731 0.3778076171875 +2732 0.26348876953125 +2733 0.387481689453125 +2734 0.270050048828125 +2735 0.397125244140625 +2736 0.27655029296875 +2737 0.406707763671875 +2738 0.283050537109375 +2739 0.416259765625 +2740 0.28948974609375 +2741 0.425750732421875 +2742 0.295928955078125 +2743 0.435211181640625 +2744 0.302337646484375 +2745 0.444610595703125 +2746 0.308685302734375 +2747 0.453948974609375 +2748 0.31500244140625 +2749 0.4632568359375 +2750 0.321319580078125 +2751 0.4725341796875 +2752 0.32757568359375 +2753 0.481719970703125 +2754 0.33380126953125 +2755 0.490875244140625 +2756 0.3399658203125 +2757 0.499969482421875 +2758 0.346099853515625 +2759 0.509002685546875 +2760 0.35223388671875 +2761 0.51800537109375 +2762 0.358306884765625 +2763 0.52691650390625 +2764 0.36431884765625 +2765 0.535797119140625 +2766 0.370330810546875 +2767 0.54461669921875 +2768 0.37628173828125 +2769 0.5533447265625 +2770 0.382171630859375 +2771 0.562042236328125 +2772 0.3880615234375 +2773 0.5706787109375 +2774 0.393890380859375 +2775 0.579254150390625 +2776 0.399658203125 +2777 0.587738037109375 +2778 0.4053955078125 +2779 0.59619140625 +2780 0.411102294921875 +2781 0.60455322265625 +2782 0.416748046875 +2783 0.612884521484375 +2784 0.42236328125 +2785 0.621124267578125 +2786 0.427886962890625 +2787 0.6292724609375 +2788 0.43341064453125 +2789 0.63739013671875 +2790 0.438873291015625 +2791 0.645416259765625 +2792 0.444305419921875 +2793 0.65338134765625 +2794 0.449676513671875 +2795 0.661285400390625 +2796 0.454986572265625 +2797 0.669097900390625 +2798 0.46026611328125 +2799 0.676849365234375 +2800 0.4654541015625 +2801 0.68450927734375 +2802 0.47064208984375 +2803 0.692108154296875 +2804 0.475738525390625 +2805 0.699615478515625 +2806 0.480804443359375 +2807 0.707061767578125 +2808 0.485809326171875 +2809 0.714447021484375 +2810 0.490753173828125 +2811 0.721710205078125 +2812 0.49566650390625 +2813 0.72894287109375 +2814 0.500518798828125 +2815 0.736053466796875 +2816 0.48150634765625 +2817 0.74310302734375 +2818 0.48602294921875 +2819 0.75006103515625 +2820 0.490478515625 +2821 0.7569580078125 +2822 0.494903564453125 +2823 0.763763427734375 +2824 0.499267578125 +2825 0.770477294921875 +2826 0.5035400390625 +2827 0.777099609375 +2828 0.507781982421875 +2829 0.783660888671875 +2830 0.511993408203125 +2831 0.790130615234375 +2832 0.51611328125 +2833 0.796478271484375 +2834 0.520172119140625 +2835 0.802764892578125 +2836 0.524200439453125 +2837 0.808990478515625 +2838 0.528167724609375 +2839 0.815093994140625 +2840 0.532073974609375 +2841 0.82110595703125 +2842 0.535888671875 +2843 0.8270263671875 +2844 0.539703369140625 +2845 0.8328857421875 +2846 0.543426513671875 +2847 0.838623046875 +2848 0.547088623046875 +2849 0.84429931640625 +2850 0.550689697265625 +2851 0.849853515625 +2852 0.554229736328125 +2853 0.855316162109375 +2854 0.557708740234375 +2855 0.860687255859375 +2856 0.5611572265625 +2857 0.865997314453125 +2858 0.56451416015625 +2859 0.871185302734375 +2860 0.56781005859375 +2861 0.876251220703125 +2862 0.571044921875 +2863 0.881256103515625 +2864 0.57421875 +2865 0.88616943359375 +2866 0.57733154296875 +2867 0.890960693359375 +2868 0.58038330078125 +2869 0.895660400390625 +2870 0.583343505859375 +2871 0.9002685546875 +2872 0.586273193359375 +2873 0.90478515625 +2874 0.589141845703125 +2875 0.9091796875 +2876 0.591949462890625 +2877 0.91351318359375 +2878 0.59466552734375 +2879 0.917724609375 +2880 0.597320556640625 +2881 0.92181396484375 +2882 0.599945068359375 +2883 0.92584228515625 +2884 0.602447509765625 +2885 0.929718017578125 +2886 0.60491943359375 +2887 0.93353271484375 +2888 0.6072998046875 +2889 0.937225341796875 +2890 0.609649658203125 +2891 0.940826416015625 +2892 0.611907958984375 +2893 0.9443359375 +2894 0.614105224609375 +2895 0.947723388671875 +2896 0.616241455078125 +2897 0.951019287109375 +2898 0.618316650390625 +2899 0.954193115234375 +2900 0.62030029296875 +2901 0.957275390625 +2902 0.622222900390625 +2903 0.960235595703125 +2904 0.62408447265625 +2905 0.963104248046875 +2906 0.625885009765625 +2907 0.96588134765625 +2908 0.627593994140625 +2909 0.968536376953125 +2910 0.629241943359375 +2911 0.971099853515625 +2912 0.630828857421875 +2913 0.973541259765625 +2914 0.632354736328125 +2915 0.975860595703125 +2916 0.6337890625 +2917 0.97808837890625 +2918 0.635162353515625 +2919 0.980224609375 +2920 0.636474609375 +2921 0.98223876953125 +2922 0.637725830078125 +2923 0.984161376953125 +2924 0.638885498046875 +2925 0.9859619140625 +2926 0.639984130859375 +2927 0.987640380859375 +2928 0.6409912109375 +2929 0.989227294921875 +2930 0.6419677734375 +2931 0.990692138671875 +2932 0.642852783203125 +2933 0.9920654296875 +2934 0.643646240234375 +2935 0.993316650390625 +2936 0.6444091796875 +2937 0.994476318359375 +2938 0.64508056640625 +2939 0.995513916015625 +2940 0.64569091796875 +2941 0.9964599609375 +2942 0.646209716796875 +2943 0.997283935546875 +2944 0.64666748046875 +2945 0.99798583984375 +2946 0.647064208984375 +2947 0.99859619140625 +2948 0.64739990234375 +2949 0.999114990234375 +2950 0.647613525390625 +2951 0.999481201171875 +2952 0.647796630859375 +2953 0.999755859375 +2954 0.647918701171875 +2955 0.99993896484375 +2956 0.647979736328125 +2957 0.999969482421875 +2958 0.647918701171875 +2959 0.99993896484375 +2960 0.647796630859375 +2961 0.999755859375 +2962 0.647613525390625 +2963 0.999481201171875 +2964 0.64739990234375 +2965 0.999114990234375 +2966 0.647064208984375 +2967 0.99859619140625 +2968 0.64666748046875 +2969 0.99798583984375 +2970 0.646209716796875 +2971 0.997283935546875 +2972 0.64569091796875 +2973 0.9964599609375 +2974 0.64508056640625 +2975 0.995513916015625 +2976 0.6444091796875 +2977 0.994476318359375 +2978 0.643646240234375 +2979 0.993316650390625 +2980 0.642852783203125 +2981 0.9920654296875 +2982 0.6419677734375 +2983 0.990692138671875 +2984 0.6409912109375 +2985 0.989227294921875 +2986 0.639984130859375 +2987 0.987640380859375 +2988 0.638885498046875 +2989 0.9859619140625 +2990 0.637725830078125 +2991 0.984161376953125 +2992 0.636474609375 +2993 0.98223876953125 +2994 0.635162353515625 +2995 0.980224609375 +2996 0.6337890625 +2997 0.97808837890625 +2998 0.632354736328125 +2999 0.975860595703125 +3000 0.630828857421875 +3001 0.973541259765625 +3002 0.629241943359375 +3003 0.971099853515625 +3004 0.627593994140625 +3005 0.968536376953125 +3006 0.625885009765625 +3007 0.96588134765625 +3008 0.62408447265625 +3009 0.963104248046875 +3010 0.622222900390625 +3011 0.960235595703125 +3012 0.62030029296875 +3013 0.957275390625 +3014 0.618316650390625 +3015 0.954193115234375 +3016 0.616241455078125 +3017 0.951019287109375 +3018 0.614105224609375 +3019 0.947723388671875 +3020 0.611907958984375 +3021 0.9443359375 +3022 0.609649658203125 +3023 0.940826416015625 +3024 0.6072998046875 +3025 0.937225341796875 +3026 0.60491943359375 +3027 0.93353271484375 +3028 0.602447509765625 +3029 0.929718017578125 +3030 0.599945068359375 +3031 0.92584228515625 +3032 0.597320556640625 +3033 0.92181396484375 +3034 0.59466552734375 +3035 0.917724609375 +3036 0.591949462890625 +3037 0.91351318359375 +3038 0.589141845703125 +3039 0.9091796875 +3040 0.586273193359375 +3041 0.90478515625 +3042 0.583343505859375 +3043 0.9002685546875 +3044 0.58038330078125 +3045 0.895660400390625 +3046 0.57733154296875 +3047 0.890960693359375 +3048 0.57421875 +3049 0.88616943359375 +3050 0.571044921875 +3051 0.881256103515625 +3052 0.56781005859375 +3053 0.876251220703125 +3054 0.56451416015625 +3055 0.871185302734375 +3056 0.5611572265625 +3057 0.865997314453125 +3058 0.557708740234375 +3059 0.860687255859375 +3060 0.554229736328125 +3061 0.855316162109375 +3062 0.550689697265625 +3063 0.849853515625 +3064 0.547088623046875 +3065 0.84429931640625 +3066 0.543426513671875 +3067 0.838623046875 +3068 0.539703369140625 +3069 0.8328857421875 +3070 0.535888671875 +3071 0.8270263671875 +3072 0.505767822265625 +3073 0.82110595703125 +3074 0.5020751953125 +3075 0.815093994140625 +3076 0.498321533203125 +3077 0.808990478515625 +3078 0.494476318359375 +3079 0.802764892578125 +3080 0.4906005859375 +3081 0.796478271484375 +3082 0.4866943359375 +3083 0.790130615234375 +3084 0.482696533203125 +3085 0.783660888671875 +3086 0.478668212890625 +3087 0.777099609375 +3088 0.474578857421875 +3089 0.770477294921875 +3090 0.470458984375 +3091 0.763763427734375 +3092 0.46624755859375 +3093 0.7569580078125 +3094 0.462005615234375 +3095 0.75006103515625 +3096 0.457733154296875 +3097 0.74310302734375 +3098 0.453369140625 +3099 0.736053466796875 +3100 0.449005126953125 +3101 0.72894287109375 +3102 0.444549560546875 +3103 0.721710205078125 +3104 0.4400634765625 +3105 0.714447021484375 +3106 0.435516357421875 +3107 0.707061767578125 +3108 0.430938720703125 +3109 0.699615478515625 +3110 0.426300048828125 +3111 0.692108154296875 +3112 0.421630859375 +3113 0.68450927734375 +3114 0.416900634765625 +3115 0.676849365234375 +3116 0.412139892578125 +3117 0.669097900390625 +3118 0.407318115234375 +3119 0.661285400390625 +3120 0.4024658203125 +3121 0.65338134765625 +3122 0.397552490234375 +3123 0.645416259765625 +3124 0.392608642578125 +3125 0.63739013671875 +3126 0.387603759765625 +3127 0.6292724609375 +3128 0.382598876953125 +3129 0.621124267578125 +3130 0.37750244140625 +3131 0.612884521484375 +3132 0.37237548828125 +3133 0.60455322265625 +3134 0.367218017578125 +3135 0.59619140625 +3136 0.362030029296875 +3137 0.587738037109375 +3138 0.3568115234375 +3139 0.579254150390625 +3140 0.35150146484375 +3141 0.5706787109375 +3142 0.34619140625 +3143 0.562042236328125 +3144 0.340850830078125 +3145 0.5533447265625 +3146 0.33544921875 +3147 0.54461669921875 +3148 0.33001708984375 +3149 0.535797119140625 +3150 0.324554443359375 +3151 0.52691650390625 +3152 0.319061279296875 +3153 0.51800537109375 +3154 0.31353759765625 +3155 0.509002685546875 +3156 0.307952880859375 +3157 0.499969482421875 +3158 0.3023681640625 +3159 0.490875244140625 +3160 0.296722412109375 +3161 0.481719970703125 +3162 0.291046142578125 +3163 0.4725341796875 +3164 0.28533935546875 +3165 0.4632568359375 +3166 0.27960205078125 +3167 0.453948974609375 +3168 0.27386474609375 +3169 0.444610595703125 +3170 0.26806640625 +3171 0.435211181640625 +3172 0.262237548828125 +3173 0.425750732421875 +3174 0.25640869140625 +3175 0.416259765625 +3176 0.250518798828125 +3177 0.406707763671875 +3178 0.244598388671875 +3179 0.397125244140625 +3180 0.238677978515625 +3181 0.387481689453125 +3182 0.232696533203125 +3183 0.3778076171875 +3184 0.22674560546875 +3185 0.36810302734375 +3186 0.220703125 +3187 0.35833740234375 +3188 0.214691162109375 +3189 0.348541259765625 +3190 0.2086181640625 +3191 0.338714599609375 +3192 0.202545166015625 +3193 0.328826904296875 +3194 0.196441650390625 +3195 0.318939208984375 +3196 0.1903076171875 +3197 0.308990478515625 +3198 0.184173583984375 +3199 0.29901123046875 +3200 0.178009033203125 +3201 0.28900146484375 +3202 0.17181396484375 +3203 0.278961181640625 +3204 0.165618896484375 +3205 0.268890380859375 +3206 0.159393310546875 +3207 0.2587890625 +3208 0.153167724609375 +3209 0.2486572265625 +3210 0.14691162109375 +3211 0.238525390625 +3212 0.140625 +3213 0.22833251953125 +3214 0.13433837890625 +3215 0.218109130859375 +3216 0.1280517578125 +3217 0.2078857421875 +3218 0.121734619140625 +3219 0.1976318359375 +3220 0.115386962890625 +3221 0.187347412109375 +3222 0.109039306640625 +3223 0.17706298828125 +3224 0.102691650390625 +3225 0.166748046875 +3226 0.0963134765625 +3227 0.156402587890625 +3228 0.0899658203125 +3229 0.14605712890625 +3230 0.08355712890625 +3231 0.13568115234375 +3232 0.077178955078125 +3233 0.12530517578125 +3234 0.070770263671875 +3235 0.11492919921875 +3236 0.064361572265625 +3237 0.104522705078125 +3238 0.057952880859375 +3239 0.094085693359375 +3240 0.051513671875 +3241 0.083648681640625 +3242 0.045074462890625 +3243 0.073211669921875 +3244 0.038665771484375 +3245 0.062774658203125 +3246 0.032196044921875 +3247 0.05230712890625 +3248 0.025787353515625 +3249 0.0418701171875 +3250 0.019317626953125 +3251 0.031402587890625 +3252 0.01287841796875 +3253 0.02093505859375 +3254 0.006439208984375 +3255 0.010467529296875 +3256 0.0 +3257 0.0 +3258 -0.006439208984375 +3259 -0.010467529296875 +3260 -0.01287841796875 +3261 -0.02093505859375 +3262 -0.019317626953125 +3263 -0.031402587890625 +3264 -0.025787353515625 +3265 -0.0418701171875 +3266 -0.032196044921875 +3267 -0.05230712890625 +3268 -0.038665771484375 +3269 -0.062774658203125 +3270 -0.045074462890625 +3271 -0.073211669921875 +3272 -0.051513671875 +3273 -0.083648681640625 +3274 -0.057952880859375 +3275 -0.094085693359375 +3276 -0.064361572265625 +3277 -0.104522705078125 +3278 -0.070770263671875 +3279 -0.11492919921875 +3280 -0.077178955078125 +3281 -0.12530517578125 +3282 -0.08355712890625 +3283 -0.13568115234375 +3284 -0.0899658203125 +3285 -0.14605712890625 +3286 -0.0963134765625 +3287 -0.156402587890625 +3288 -0.102691650390625 +3289 -0.166748046875 +3290 -0.109039306640625 +3291 -0.17706298828125 +3292 -0.115386962890625 +3293 -0.187347412109375 +3294 -0.121734619140625 +3295 -0.1976318359375 +3296 -0.1280517578125 +3297 -0.2078857421875 +3298 -0.13433837890625 +3299 -0.218109130859375 +3300 -0.140625 +3301 -0.22833251953125 +3302 -0.14691162109375 +3303 -0.238525390625 +3304 -0.153167724609375 +3305 -0.2486572265625 +3306 -0.159393310546875 +3307 -0.2587890625 +3308 -0.165618896484375 +3309 -0.268890380859375 +3310 -0.17181396484375 +3311 -0.278961181640625 +3312 -0.178009033203125 +3313 -0.28900146484375 +3314 -0.184173583984375 +3315 -0.29901123046875 +3316 -0.1903076171875 +3317 -0.308990478515625 +3318 -0.196441650390625 +3319 -0.318939208984375 +3320 -0.202545166015625 +3321 -0.328826904296875 +3322 -0.2086181640625 +3323 -0.338714599609375 +3324 -0.214691162109375 +3325 -0.348541259765625 +3326 -0.220703125 +3327 -0.35833740234375 +3328 -0.2149658203125 +3329 -0.36810302734375 +3330 -0.220611572265625 +3331 -0.3778076171875 +3332 -0.226287841796875 +3333 -0.387481689453125 +3334 -0.231903076171875 +3335 -0.397125244140625 +3336 -0.23748779296875 +3337 -0.406707763671875 +3338 -0.243072509765625 +3339 -0.416259765625 +3340 -0.248626708984375 +3341 -0.425750732421875 +3342 -0.254150390625 +3343 -0.435211181640625 +3344 -0.2596435546875 +3345 -0.444610595703125 +3346 -0.265106201171875 +3347 -0.453948974609375 +3348 -0.270538330078125 +3349 -0.4632568359375 +3350 -0.27593994140625 +3351 -0.4725341796875 +3352 -0.28131103515625 +3353 -0.481719970703125 +3354 -0.286651611328125 +3355 -0.490875244140625 +3356 -0.291961669921875 +3357 -0.499969482421875 +3358 -0.2972412109375 +3359 -0.509002685546875 +3360 -0.302490234375 +3361 -0.51800537109375 +3362 -0.307708740234375 +3363 -0.52691650390625 +3364 -0.312896728515625 +3365 -0.535797119140625 +3366 -0.31805419921875 +3367 -0.54461669921875 +3368 -0.323150634765625 +3369 -0.5533447265625 +3370 -0.328216552734375 +3371 -0.562042236328125 +3372 -0.333251953125 +3373 -0.5706787109375 +3374 -0.3382568359375 +3375 -0.579254150390625 +3376 -0.343231201171875 +3377 -0.587738037109375 +3378 -0.348175048828125 +3379 -0.59619140625 +3380 -0.353057861328125 +3381 -0.60455322265625 +3382 -0.35791015625 +3383 -0.612884521484375 +3384 -0.36273193359375 +3385 -0.621124267578125 +3386 -0.36749267578125 +3387 -0.6292724609375 +3388 -0.372222900390625 +3389 -0.63739013671875 +3390 -0.376922607421875 +3391 -0.645416259765625 +3392 -0.381561279296875 +3393 -0.65338134765625 +3394 -0.38616943359375 +3395 -0.661285400390625 +3396 -0.3907470703125 +3397 -0.669097900390625 +3398 -0.395263671875 +3399 -0.676849365234375 +3400 -0.399749755859375 +3401 -0.68450927734375 +3402 -0.4041748046875 +3403 -0.692108154296875 +3404 -0.4085693359375 +3405 -0.699615478515625 +3406 -0.41290283203125 +3407 -0.707061767578125 +3408 -0.417236328125 +3409 -0.714447021484375 +3410 -0.421478271484375 +3411 -0.721710205078125 +3412 -0.425689697265625 +3413 -0.72894287109375 +3414 -0.429840087890625 +3415 -0.736053466796875 +3416 -0.4339599609375 +3417 -0.74310302734375 +3418 -0.438018798828125 +3419 -0.75006103515625 +3420 -0.442047119140625 +3421 -0.7569580078125 +3422 -0.446014404296875 +3423 -0.763763427734375 +3424 -0.449951171875 +3425 -0.770477294921875 +3426 -0.453826904296875 +3427 -0.777099609375 +3428 -0.4576416015625 +3429 -0.783660888671875 +3430 -0.46142578125 +3431 -0.790130615234375 +3432 -0.465118408203125 +3433 -0.796478271484375 +3434 -0.46881103515625 +3435 -0.802764892578125 +3436 -0.472442626953125 +3437 -0.808990478515625 +3438 -0.47601318359375 +3439 -0.815093994140625 +3440 -0.479522705078125 +3441 -0.82110595703125 +3442 -0.48297119140625 +3443 -0.8270263671875 +3444 -0.48638916015625 +3445 -0.8328857421875 +3446 -0.48974609375 +3447 -0.838623046875 +3448 -0.493072509765625 +3449 -0.84429931640625 +3450 -0.496307373046875 +3451 -0.849853515625 +3452 -0.499481201171875 +3453 -0.855316162109375 +3454 -0.50262451171875 +3455 -0.860687255859375 +3456 -0.5057373046875 +3457 -0.865997314453125 +3458 -0.508758544921875 +3459 -0.871185302734375 +3460 -0.51171875 +3461 -0.876251220703125 +3462 -0.5146484375 +3463 -0.881256103515625 +3464 -0.51751708984375 +3465 -0.88616943359375 +3466 -0.520294189453125 +3467 -0.890960693359375 +3468 -0.523040771484375 +3469 -0.895660400390625 +3470 -0.5257568359375 +3471 -0.9002685546875 +3472 -0.52838134765625 +3473 -0.90478515625 +3474 -0.53094482421875 +3475 -0.9091796875 +3476 -0.533477783203125 +3477 -0.91351318359375 +3478 -0.53594970703125 +3479 -0.917724609375 +3480 -0.538330078125 +3481 -0.92181396484375 +3482 -0.540679931640625 +3483 -0.92584228515625 +3484 -0.542938232421875 +3485 -0.929718017578125 +3486 -0.545166015625 +3487 -0.93353271484375 +3488 -0.547332763671875 +3489 -0.937225341796875 +3490 -0.5494384765625 +3491 -0.940826416015625 +3492 -0.551483154296875 +3493 -0.9443359375 +3494 -0.553466796875 +3495 -0.947723388671875 +3496 -0.555389404296875 +3497 -0.951019287109375 +3498 -0.557220458984375 +3499 -0.954193115234375 +3500 -0.55902099609375 +3501 -0.957275390625 +3502 -0.560760498046875 +3503 -0.960235595703125 +3504 -0.56243896484375 +3505 -0.963104248046875 +3506 -0.564056396484375 +3507 -0.96588134765625 +3508 -0.56561279296875 +3509 -0.968536376953125 +3510 -0.567108154296875 +3511 -0.971099853515625 +3512 -0.56854248046875 +3513 -0.973541259765625 +3514 -0.56988525390625 +3515 -0.975860595703125 +3516 -0.571197509765625 +3517 -0.97808837890625 +3518 -0.57244873046875 +3519 -0.980224609375 +3520 -0.5736083984375 +3521 -0.98223876953125 +3522 -0.574737548828125 +3523 -0.984161376953125 +3524 -0.575775146484375 +3525 -0.9859619140625 +3526 -0.5767822265625 +3527 -0.987640380859375 +3528 -0.57769775390625 +3529 -0.989227294921875 +3530 -0.57855224609375 +3531 -0.990692138671875 +3532 -0.579345703125 +3533 -0.9920654296875 +3534 -0.580078125 +3535 -0.993316650390625 +3536 -0.58074951171875 +3537 -0.994476318359375 +3538 -0.58135986328125 +3539 -0.995513916015625 +3540 -0.5819091796875 +3541 -0.9964599609375 +3542 -0.5823974609375 +3543 -0.997283935546875 +3544 -0.58282470703125 +3545 -0.99798583984375 +3546 -0.583160400390625 +3547 -0.99859619140625 +3548 -0.583465576171875 +3549 -0.999114990234375 +3550 -0.58367919921875 +3551 -0.999481201171875 +3552 -0.583831787109375 +3553 -0.999755859375 +3554 -0.58392333984375 +3555 -0.99993896484375 +3556 -0.583984375 +3557 -1.0 +3558 -0.58392333984375 +3559 -0.99993896484375 +3560 -0.583831787109375 +3561 -0.999755859375 +3562 -0.58367919921875 +3563 -0.999481201171875 +3564 -0.583465576171875 +3565 -0.999114990234375 +3566 -0.583160400390625 +3567 -0.99859619140625 +3568 -0.58282470703125 +3569 -0.99798583984375 +3570 -0.5823974609375 +3571 -0.997283935546875 +3572 -0.5819091796875 +3573 -0.9964599609375 +3574 -0.58135986328125 +3575 -0.995513916015625 +3576 -0.58074951171875 +3577 -0.994476318359375 +3578 -0.580078125 +3579 -0.993316650390625 +3580 -0.579345703125 +3581 -0.9920654296875 +3582 -0.57855224609375 +3583 -0.990692138671875 +3584 -0.5460205078125 +3585 -0.989227294921875 +3586 -0.545135498046875 +3587 -0.987640380859375 +3588 -0.544219970703125 +3589 -0.9859619140625 +3590 -0.543243408203125 +3591 -0.984161376953125 +3592 -0.54217529296875 +3593 -0.98223876953125 +3594 -0.541046142578125 +3595 -0.980224609375 +3596 -0.539886474609375 +3597 -0.97808837890625 +3598 -0.53863525390625 +3599 -0.975860595703125 +3600 -0.537353515625 +3601 -0.973541259765625 +3602 -0.5360107421875 +3603 -0.971099853515625 +3604 -0.53460693359375 +3605 -0.968536376953125 +3606 -0.53314208984375 +3607 -0.96588134765625 +3608 -0.5316162109375 +3609 -0.963104248046875 +3610 -0.530029296875 +3611 -0.960235595703125 +3612 -0.52838134765625 +3613 -0.957275390625 +3614 -0.526702880859375 +3615 -0.954193115234375 +3616 -0.524932861328125 +3617 -0.951019287109375 +3618 -0.523101806640625 +3619 -0.947723388671875 +3620 -0.521240234375 +3621 -0.9443359375 +3622 -0.519317626953125 +3623 -0.940826416015625 +3624 -0.517333984375 +3625 -0.937225341796875 +3626 -0.515289306640625 +3627 -0.93353271484375 +3628 -0.51318359375 +3629 -0.929718017578125 +3630 -0.51104736328125 +3631 -0.92584228515625 +3632 -0.508819580078125 +3633 -0.92181396484375 +3634 -0.506561279296875 +3635 -0.917724609375 +3636 -0.504241943359375 +3637 -0.91351318359375 +3638 -0.5018310546875 +3639 -0.9091796875 +3640 -0.499420166015625 +3641 -0.90478515625 +3642 -0.496917724609375 +3643 -0.9002685546875 +3644 -0.494384765625 +3645 -0.895660400390625 +3646 -0.491790771484375 +3647 -0.890960693359375 +3648 -0.4891357421875 +3649 -0.88616943359375 +3650 -0.486419677734375 +3651 -0.881256103515625 +3652 -0.483673095703125 +3653 -0.876251220703125 +3654 -0.480865478515625 +3655 -0.871185302734375 +3656 -0.477996826171875 +3657 -0.865997314453125 +3658 -0.475067138671875 +3659 -0.860687255859375 +3660 -0.47210693359375 +3661 -0.855316162109375 +3662 -0.469085693359375 +3663 -0.849853515625 +3664 -0.466033935546875 +3665 -0.84429931640625 +3666 -0.462890625 +3667 -0.838623046875 +3668 -0.459716796875 +3669 -0.8328857421875 +3670 -0.45648193359375 +3671 -0.8270263671875 +3672 -0.453216552734375 +3673 -0.82110595703125 +3674 -0.449920654296875 +3675 -0.815093994140625 +3676 -0.446533203125 +3677 -0.808990478515625 +3678 -0.443115234375 +3679 -0.802764892578125 +3680 -0.43963623046875 +3681 -0.796478271484375 +3682 -0.436126708984375 +3683 -0.790130615234375 +3684 -0.43255615234375 +3685 -0.783660888671875 +3686 -0.428924560546875 +3687 -0.777099609375 +3688 -0.42529296875 +3689 -0.770477294921875 +3690 -0.42156982421875 +3691 -0.763763427734375 +3692 -0.417816162109375 +3693 -0.7569580078125 +3694 -0.41400146484375 +3695 -0.75006103515625 +3696 -0.41015625 +3697 -0.74310302734375 +3698 -0.406280517578125 +3699 -0.736053466796875 +3700 -0.40234375 +3701 -0.72894287109375 +3702 -0.398345947265625 +3703 -0.721710205078125 +3704 -0.39434814453125 +3705 -0.714447021484375 +3706 -0.390289306640625 +3707 -0.707061767578125 +3708 -0.38616943359375 +3709 -0.699615478515625 +3710 -0.38201904296875 +3711 -0.692108154296875 +3712 -0.377838134765625 +3713 -0.68450927734375 +3714 -0.37359619140625 +3715 -0.676849365234375 +3716 -0.36932373046875 +3717 -0.669097900390625 +3718 -0.365020751953125 +3719 -0.661285400390625 +3720 -0.36065673828125 +3721 -0.65338134765625 +3722 -0.35626220703125 +3723 -0.645416259765625 +3724 -0.351806640625 +3725 -0.63739013671875 +3726 -0.347320556640625 +3727 -0.6292724609375 +3728 -0.34283447265625 +3729 -0.621124267578125 +3730 -0.338287353515625 +3731 -0.612884521484375 +3732 -0.33367919921875 +3733 -0.60455322265625 +3734 -0.329071044921875 +3735 -0.59619140625 +3736 -0.32440185546875 +3737 -0.587738037109375 +3738 -0.319732666015625 +3739 -0.579254150390625 +3740 -0.31500244140625 +3741 -0.5706787109375 +3742 -0.310211181640625 +3743 -0.562042236328125 +3744 -0.305419921875 +3745 -0.5533447265625 +3746 -0.30059814453125 +3747 -0.54461669921875 +3748 -0.295745849609375 +3749 -0.535797119140625 +3750 -0.29083251953125 +3751 -0.52691650390625 +3752 -0.285919189453125 +3753 -0.51800537109375 +3754 -0.28094482421875 +3755 -0.509002685546875 +3756 -0.275970458984375 +3757 -0.499969482421875 +3758 -0.27093505859375 +3759 -0.490875244140625 +3760 -0.265899658203125 +3761 -0.481719970703125 +3762 -0.26080322265625 +3763 -0.4725341796875 +3764 -0.255706787109375 +3765 -0.4632568359375 +3766 -0.25054931640625 +3767 -0.453948974609375 +3768 -0.245391845703125 +3769 -0.444610595703125 +3770 -0.240203857421875 +3771 -0.435211181640625 +3772 -0.2349853515625 +3773 -0.425750732421875 +3774 -0.229766845703125 +3775 -0.416259765625 +3776 -0.2244873046875 +3777 -0.406707763671875 +3778 -0.219207763671875 +3779 -0.397125244140625 +3780 -0.2138671875 +3781 -0.387481689453125 +3782 -0.208526611328125 +3783 -0.3778076171875 +3784 -0.20318603515625 +3785 -0.36810302734375 +3786 -0.197784423828125 +3787 -0.35833740234375 +3788 -0.1923828125 +3789 -0.348541259765625 +3790 -0.18695068359375 +3791 -0.338714599609375 +3792 -0.181488037109375 +3793 -0.328826904296875 +3794 -0.176025390625 +3795 -0.318939208984375 +3796 -0.1705322265625 +3797 -0.308990478515625 +3798 -0.1650390625 +3799 -0.29901123046875 +3800 -0.159515380859375 +3801 -0.28900146484375 +3802 -0.153961181640625 +3803 -0.278961181640625 +3804 -0.148406982421875 +3805 -0.268890380859375 +3806 -0.142822265625 +3807 -0.2587890625 +3808 -0.137237548828125 +3809 -0.2486572265625 +3810 -0.13165283203125 +3811 -0.238525390625 +3812 -0.126007080078125 +3813 -0.22833251953125 +3814 -0.120391845703125 +3815 -0.218109130859375 +3816 -0.11474609375 +3817 -0.2078857421875 +3818 -0.10906982421875 +3819 -0.1976318359375 +3820 -0.1033935546875 +3821 -0.187347412109375 +3822 -0.09771728515625 +3823 -0.17706298828125 +3824 -0.092041015625 +3825 -0.166748046875 +3826 -0.0863037109375 +3827 -0.156402587890625 +3828 -0.080596923828125 +3829 -0.14605712890625 +3830 -0.07489013671875 +3831 -0.13568115234375 +3832 -0.06915283203125 +3833 -0.12530517578125 +3834 -0.06341552734375 +3835 -0.11492919921875 +3836 -0.05767822265625 +3837 -0.104522705078125 +3838 -0.051910400390625 +3839 -0.094085693359375 +3840 -0.045989990234375 +3841 -0.083648681640625 +3842 -0.040252685546875 +3843 -0.073211669921875 +3844 -0.034515380859375 +3845 -0.062774658203125 +3846 -0.02874755859375 +3847 -0.05230712890625 +3848 -0.02301025390625 +3849 -0.0418701171875 +3850 -0.017242431640625 +3851 -0.031402587890625 +3852 -0.011505126953125 +3853 -0.02093505859375 +3854 -0.0057373046875 +3855 -0.010467529296875 +3856 0.0 +3857 0.0 +3858 0.00543212890625 +3859 0.010467529296875 +3860 0.0108642578125 +3861 0.02093505859375 +3862 0.016326904296875 +3863 0.031402587890625 +3864 0.021759033203125 +3865 0.0418701171875 +3866 0.027191162109375 +3867 0.05230712890625 +3868 0.032623291015625 +3869 0.062774658203125 +3870 0.038055419921875 +3871 0.073211669921875 +3872 0.043487548828125 +3873 0.083648681640625 +3874 0.048919677734375 +3875 0.094085693359375 +3876 0.054351806640625 +3877 0.104522705078125 +3878 0.05975341796875 +3879 0.11492919921875 +3880 0.065155029296875 +3881 0.12530517578125 +3882 0.070526123046875 +3883 0.13568115234375 +3884 0.075927734375 +3885 0.14605712890625 +3886 0.081329345703125 +3887 0.156402587890625 +3888 0.086700439453125 +3889 0.166748046875 +3890 0.092071533203125 +3891 0.17706298828125 +3892 0.097412109375 +3893 0.187347412109375 +3894 0.102752685546875 +3895 0.1976318359375 +3896 0.10809326171875 +3897 0.2078857421875 +3898 0.1134033203125 +3899 0.218109130859375 +3900 0.11871337890625 +3901 0.22833251953125 +3902 0.1240234375 +3903 0.238525390625 +3904 0.1292724609375 +3905 0.2486572265625 +3906 0.134552001953125 +3907 0.2587890625 +3908 0.139801025390625 +3909 0.268890380859375 +3910 0.145050048828125 +3911 0.278961181640625 +3912 0.1502685546875 +3913 0.28900146484375 +3914 0.155487060546875 +3915 0.29901123046875 +3916 0.160675048828125 +3917 0.308990478515625 +3918 0.16583251953125 +3919 0.318939208984375 +3920 0.170989990234375 +3921 0.328826904296875 +3922 0.176116943359375 +3923 0.338714599609375 +3924 0.18121337890625 +3925 0.348541259765625 +3926 0.186309814453125 +3927 0.35833740234375 +3928 0.19140625 +3929 0.36810302734375 +3930 0.196441650390625 +3931 0.3778076171875 +3932 0.20147705078125 +3933 0.387481689453125 +3934 0.20648193359375 +3935 0.397125244140625 +3936 0.21148681640625 +3937 0.406707763671875 +3938 0.2164306640625 +3939 0.416259765625 +3940 0.22137451171875 +3941 0.425750732421875 +3942 0.226287841796875 +3943 0.435211181640625 +3944 0.231170654296875 +3945 0.444610595703125 +3946 0.236053466796875 +3947 0.453948974609375 +3948 0.240875244140625 +3949 0.4632568359375 +3950 0.245697021484375 +3951 0.4725341796875 +3952 0.25048828125 +3953 0.481719970703125 +3954 0.2552490234375 +3955 0.490875244140625 +3956 0.259979248046875 +3957 0.499969482421875 +3958 0.264678955078125 +3959 0.509002685546875 +3960 0.26934814453125 +3961 0.51800537109375 +3962 0.27398681640625 +3963 0.52691650390625 +3964 0.278594970703125 +3965 0.535797119140625 +3966 0.283203125 +3967 0.54461669921875 +3968 0.2877197265625 +3969 0.5533447265625 +3970 0.292236328125 +3971 0.562042236328125 +3972 0.2967529296875 +3973 0.5706787109375 +3974 0.30120849609375 +3975 0.579254150390625 +3976 0.30560302734375 +3977 0.587738037109375 +3978 0.30999755859375 +3979 0.59619140625 +3980 0.314361572265625 +3981 0.60455322265625 +3982 0.318695068359375 +3983 0.612884521484375 +3984 0.322967529296875 +3985 0.621124267578125 +3986 0.32720947265625 +3987 0.6292724609375 +3988 0.3314208984375 +3989 0.63739013671875 +3990 0.335601806640625 +3991 0.645416259765625 +3992 0.339752197265625 +3993 0.65338134765625 +3994 0.343841552734375 +3995 0.661285400390625 +3996 0.347930908203125 +3997 0.669097900390625 +3998 0.351959228515625 +3999 0.676849365234375 +4000 0.355926513671875 +4001 0.68450927734375 +4002 0.359893798828125 +4003 0.692108154296875 +4004 0.363800048828125 +4005 0.699615478515625 +4006 0.367645263671875 +4007 0.707061767578125 +4008 0.371490478515625 +4009 0.714447021484375 +4010 0.375274658203125 +4011 0.721710205078125 +4012 0.3790283203125 +4013 0.72894287109375 +4014 0.382720947265625 +4015 0.736053466796875 +4016 0.38641357421875 +4017 0.74310302734375 +4018 0.3900146484375 +4019 0.75006103515625 +4020 0.39361572265625 +4021 0.7569580078125 +4022 0.39715576171875 +4023 0.763763427734375 +4024 0.400634765625 +4025 0.770477294921875 +4026 0.404083251953125 +4027 0.777099609375 +4028 0.407501220703125 +4029 0.783660888671875 +4030 0.410858154296875 +4031 0.790130615234375 +4032 0.414154052734375 +4033 0.796478271484375 +4034 0.41741943359375 +4035 0.802764892578125 +4036 0.420654296875 +4037 0.808990478515625 +4038 0.423828125 +4039 0.815093994140625 +4040 0.426971435546875 +4041 0.82110595703125 +4042 0.4300537109375 +4043 0.8270263671875 +4044 0.433074951171875 +4045 0.8328857421875 +4046 0.436065673828125 +4047 0.838623046875 +4048 0.43902587890625 +4049 0.84429931640625 +4050 0.441925048828125 +4051 0.849853515625 +4052 0.44476318359375 +4053 0.855316162109375 +4054 0.447540283203125 +4055 0.860687255859375 +4056 0.4503173828125 +4057 0.865997314453125 +4058 0.4530029296875 +4059 0.871185302734375 +4060 0.45562744140625 +4061 0.876251220703125 +4062 0.458251953125 +4063 0.881256103515625 +4064 0.460784912109375 +4065 0.88616943359375 +4066 0.463287353515625 +4067 0.890960693359375 +4068 0.465728759765625 +4069 0.895660400390625 +4070 0.4681396484375 +4071 0.9002685546875 +4072 0.470489501953125 +4073 0.90478515625 +4074 0.472747802734375 +4075 0.9091796875 +4076 0.475006103515625 +4077 0.91351318359375 +4078 0.477203369140625 +4079 0.917724609375 +4080 0.479339599609375 +4081 0.92181396484375 +4082 0.481414794921875 +4083 0.92584228515625 +4084 0.483428955078125 +4085 0.929718017578125 +4086 0.48541259765625 +4087 0.93353271484375 +4088 0.487335205078125 +4089 0.937225341796875 +4090 0.489227294921875 +4091 0.940826416015625 +4092 0.491058349609375 +4093 0.9443359375 +4094 0.4927978515625 +4095 0.947723388671875 +4096 0.464080810546875 +4097 0.951019287109375 +4098 0.46563720703125 +4099 0.954193115234375 +4100 0.467132568359375 +4101 0.957275390625 +4102 0.46856689453125 +4103 0.960235595703125 +4104 0.469970703125 +4105 0.963104248046875 +4106 0.4713134765625 +4107 0.96588134765625 +4108 0.472625732421875 +4109 0.968536376953125 +4110 0.473876953125 +4111 0.971099853515625 +4112 0.475067138671875 +4113 0.973541259765625 +4114 0.4761962890625 +4115 0.975860595703125 +4116 0.477294921875 +4117 0.97808837890625 +4118 0.47833251953125 +4119 0.980224609375 +4120 0.47930908203125 +4121 0.98223876953125 +4122 0.480255126953125 +4123 0.984161376953125 +4124 0.48114013671875 +4125 0.9859619140625 +4126 0.48193359375 +4127 0.987640380859375 +4128 0.48272705078125 +4129 0.989227294921875 +4130 0.483428955078125 +4131 0.990692138671875 +4132 0.484100341796875 +4133 0.9920654296875 +4134 0.484710693359375 +4135 0.993316650390625 +4136 0.48529052734375 +4137 0.994476318359375 +4138 0.48577880859375 +4139 0.995513916015625 +4140 0.486236572265625 +4141 0.9964599609375 +4142 0.486663818359375 +4143 0.997283935546875 +4144 0.48699951171875 +4145 0.99798583984375 +4146 0.4873046875 +4147 0.99859619140625 +4148 0.487518310546875 +4149 0.999114990234375 +4150 0.487701416015625 +4151 0.999481201171875 +4152 0.48785400390625 +4153 0.999755859375 +4154 0.487945556640625 +4155 0.99993896484375 +4156 0.48797607421875 +4157 0.999969482421875 +4158 0.487945556640625 +4159 0.99993896484375 +4160 0.48785400390625 +4161 0.999755859375 +4162 0.487701416015625 +4163 0.999481201171875 +4164 0.487518310546875 +4165 0.999114990234375 +4166 0.4873046875 +4167 0.99859619140625 +4168 0.48699951171875 +4169 0.99798583984375 +4170 0.486663818359375 +4171 0.997283935546875 +4172 0.486236572265625 +4173 0.9964599609375 +4174 0.48577880859375 +4175 0.995513916015625 +4176 0.48529052734375 +4177 0.994476318359375 +4178 0.484710693359375 +4179 0.993316650390625 +4180 0.484100341796875 +4181 0.9920654296875 +4182 0.483428955078125 +4183 0.990692138671875 +4184 0.48272705078125 +4185 0.989227294921875 +4186 0.48193359375 +4187 0.987640380859375 +4188 0.48114013671875 +4189 0.9859619140625 +4190 0.480255126953125 +4191 0.984161376953125 +4192 0.47930908203125 +4193 0.98223876953125 +4194 0.47833251953125 +4195 0.980224609375 +4196 0.477294921875 +4197 0.97808837890625 +4198 0.4761962890625 +4199 0.975860595703125 +4200 0.475067138671875 +4201 0.973541259765625 +4202 0.473876953125 +4203 0.971099853515625 +4204 0.472625732421875 +4205 0.968536376953125 +4206 0.4713134765625 +4207 0.96588134765625 +4208 0.469970703125 +4209 0.963104248046875 +4210 0.46856689453125 +4211 0.960235595703125 +4212 0.467132568359375 +4213 0.957275390625 +4214 0.46563720703125 +4215 0.954193115234375 +4216 0.464080810546875 +4217 0.951019287109375 +4218 0.46246337890625 +4219 0.947723388671875 +4220 0.4608154296875 +4221 0.9443359375 +4222 0.4591064453125 +4223 0.940826416015625 +4224 0.45733642578125 +4225 0.937225341796875 +4226 0.455535888671875 +4227 0.93353271484375 +4228 0.45367431640625 +4229 0.929718017578125 +4230 0.4517822265625 +4231 0.92584228515625 +4232 0.4498291015625 +4233 0.92181396484375 +4234 0.44781494140625 +4235 0.917724609375 +4236 0.445770263671875 +4237 0.91351318359375 +4238 0.44366455078125 +4239 0.9091796875 +4240 0.441497802734375 +4241 0.90478515625 +4242 0.439300537109375 +4243 0.9002685546875 +4244 0.43707275390625 +4245 0.895660400390625 +4246 0.43475341796875 +4247 0.890960693359375 +4248 0.43243408203125 +4249 0.88616943359375 +4250 0.430023193359375 +4251 0.881256103515625 +4252 0.427581787109375 +4253 0.876251220703125 +4254 0.42510986328125 +4255 0.871185302734375 +4256 0.422576904296875 +4257 0.865997314453125 +4258 0.41998291015625 +4259 0.860687255859375 +4260 0.4173583984375 +4261 0.855316162109375 +4262 0.414703369140625 +4263 0.849853515625 +4264 0.4119873046875 +4265 0.84429931640625 +4266 0.409210205078125 +4267 0.838623046875 +4268 0.40643310546875 +4269 0.8328857421875 +4270 0.403564453125 +4271 0.8270263671875 +4272 0.400665283203125 +4273 0.82110595703125 +4274 0.397735595703125 +4275 0.815093994140625 +4276 0.394775390625 +4277 0.808990478515625 +4278 0.3917236328125 +4279 0.802764892578125 +4280 0.388671875 +4281 0.796478271484375 +4282 0.38555908203125 +4283 0.790130615234375 +4284 0.382415771484375 +4285 0.783660888671875 +4286 0.37921142578125 +4287 0.777099609375 +4288 0.3759765625 +4289 0.770477294921875 +4290 0.3726806640625 +4291 0.763763427734375 +4292 0.369384765625 +4293 0.7569580078125 +4294 0.365997314453125 +4295 0.75006103515625 +4296 0.36260986328125 +4297 0.74310302734375 +4298 0.359161376953125 +4299 0.736053466796875 +4300 0.355712890625 +4301 0.72894287109375 +4302 0.3521728515625 +4303 0.721710205078125 +4304 0.3486328125 +4305 0.714447021484375 +4306 0.34503173828125 +4307 0.707061767578125 +4308 0.341400146484375 +4309 0.699615478515625 +4310 0.337738037109375 +4311 0.692108154296875 +4312 0.334014892578125 +4313 0.68450927734375 +4314 0.330291748046875 +4315 0.676849365234375 +4316 0.326507568359375 +4317 0.669097900390625 +4318 0.32269287109375 +4319 0.661285400390625 +4320 0.318817138671875 +4321 0.65338134765625 +4322 0.31494140625 +4323 0.645416259765625 +4324 0.31103515625 +4325 0.63739013671875 +4326 0.30706787109375 +4327 0.6292724609375 +4328 0.3031005859375 +4329 0.621124267578125 +4330 0.299072265625 +4331 0.612884521484375 +4332 0.295013427734375 +4333 0.60455322265625 +4334 0.290924072265625 +4335 0.59619140625 +4336 0.28680419921875 +4337 0.587738037109375 +4338 0.28265380859375 +4339 0.579254150390625 +4340 0.278472900390625 +4341 0.5706787109375 +4342 0.274261474609375 +4343 0.562042236328125 +4344 0.27001953125 +4345 0.5533447265625 +4346 0.2657470703125 +4347 0.54461669921875 +4348 0.261444091796875 +4349 0.535797119140625 +4350 0.257110595703125 +4351 0.52691650390625 +4352 0.2362060546875 +4353 0.51800537109375 +4354 0.232086181640625 +4355 0.509002685546875 +4356 0.22796630859375 +4357 0.499969482421875 +4358 0.22381591796875 +4359 0.490875244140625 +4360 0.21966552734375 +4361 0.481719970703125 +4362 0.2154541015625 +4363 0.4725341796875 +4364 0.21124267578125 +4365 0.4632568359375 +4366 0.207000732421875 +4367 0.453948974609375 +4368 0.202728271484375 +4369 0.444610595703125 +4370 0.198455810546875 +4371 0.435211181640625 +4372 0.194122314453125 +4373 0.425750732421875 +4374 0.189788818359375 +4375 0.416259765625 +4376 0.185455322265625 +4377 0.406707763671875 +4378 0.18109130859375 +4379 0.397125244140625 +4380 0.176666259765625 +4381 0.387481689453125 +4382 0.172271728515625 +4383 0.3778076171875 +4384 0.1678466796875 +4385 0.36810302734375 +4386 0.16339111328125 +4387 0.35833740234375 +4388 0.158935546875 +4389 0.348541259765625 +4390 0.154449462890625 +4391 0.338714599609375 +4392 0.149932861328125 +4393 0.328826904296875 +4394 0.145416259765625 +4395 0.318939208984375 +4396 0.140899658203125 +4397 0.308990478515625 +4398 0.136322021484375 +4399 0.29901123046875 +4400 0.13177490234375 +4401 0.28900146484375 +4402 0.127197265625 +4403 0.278961181640625 +4404 0.122589111328125 +4405 0.268890380859375 +4406 0.11798095703125 +4407 0.2587890625 +4408 0.113372802734375 +4409 0.2486572265625 +4410 0.1087646484375 +4411 0.238525390625 +4412 0.104095458984375 +4413 0.22833251953125 +4414 0.099456787109375 +4415 0.218109130859375 +4416 0.09478759765625 +4417 0.2078857421875 +4418 0.090118408203125 +4419 0.1976318359375 +4420 0.085418701171875 +4421 0.187347412109375 +4422 0.080718994140625 +4423 0.17706298828125 +4424 0.076019287109375 +4425 0.166748046875 +4426 0.071319580078125 +4427 0.156402587890625 +4428 0.06658935546875 +4429 0.14605712890625 +4430 0.061859130859375 +4431 0.13568115234375 +4432 0.05712890625 +4433 0.12530517578125 +4434 0.052398681640625 +4435 0.11492919921875 +4436 0.047637939453125 +4437 0.104522705078125 +4438 0.042877197265625 +4439 0.094085693359375 +4440 0.038116455078125 +4441 0.083648681640625 +4442 0.033355712890625 +4443 0.073211669921875 +4444 0.02862548828125 +4445 0.062774658203125 +4446 0.023834228515625 +4447 0.05230712890625 +4448 0.019073486328125 +4449 0.0418701171875 +4450 0.014312744140625 +4451 0.031402587890625 +4452 0.009521484375 +4453 0.02093505859375 +4454 0.0047607421875 +4455 0.010467529296875 +4456 0.0 +4457 0.0 +4458 -0.0047607421875 +4459 -0.010467529296875 +4460 -0.009521484375 +4461 -0.02093505859375 +4462 -0.014312744140625 +4463 -0.031402587890625 +4464 -0.019073486328125 +4465 -0.0418701171875 +4466 -0.023834228515625 +4467 -0.05230712890625 +4468 -0.02862548828125 +4469 -0.062774658203125 +4470 -0.033355712890625 +4471 -0.073211669921875 +4472 -0.038116455078125 +4473 -0.083648681640625 +4474 -0.042877197265625 +4475 -0.094085693359375 +4476 -0.047637939453125 +4477 -0.104522705078125 +4478 -0.052398681640625 +4479 -0.11492919921875 +4480 -0.05712890625 +4481 -0.12530517578125 +4482 -0.061859130859375 +4483 -0.13568115234375 +4484 -0.06658935546875 +4485 -0.14605712890625 +4486 -0.071319580078125 +4487 -0.156402587890625 +4488 -0.076019287109375 +4489 -0.166748046875 +4490 -0.080718994140625 +4491 -0.17706298828125 +4492 -0.085418701171875 +4493 -0.187347412109375 +4494 -0.090118408203125 +4495 -0.1976318359375 +4496 -0.09478759765625 +4497 -0.2078857421875 +4498 -0.099456787109375 +4499 -0.218109130859375 +4500 -0.104095458984375 +4501 -0.22833251953125 +4502 -0.1087646484375 +4503 -0.238525390625 +4504 -0.113372802734375 +4505 -0.2486572265625 +4506 -0.11798095703125 +4507 -0.2587890625 +4508 -0.122589111328125 +4509 -0.268890380859375 +4510 -0.127197265625 +4511 -0.278961181640625 +4512 -0.13177490234375 +4513 -0.28900146484375 +4514 -0.136322021484375 +4515 -0.29901123046875 +4516 -0.140899658203125 +4517 -0.308990478515625 +4518 -0.145416259765625 +4519 -0.318939208984375 +4520 -0.149932861328125 +4521 -0.328826904296875 +4522 -0.154449462890625 +4523 -0.338714599609375 +4524 -0.158935546875 +4525 -0.348541259765625 +4526 -0.16339111328125 +4527 -0.35833740234375 +4528 -0.1678466796875 +4529 -0.36810302734375 +4530 -0.172271728515625 +4531 -0.3778076171875 +4532 -0.176666259765625 +4533 -0.387481689453125 +4534 -0.18109130859375 +4535 -0.397125244140625 +4536 -0.185455322265625 +4537 -0.406707763671875 +4538 -0.189788818359375 +4539 -0.416259765625 +4540 -0.194122314453125 +4541 -0.425750732421875 +4542 -0.198455810546875 +4543 -0.435211181640625 +4544 -0.202728271484375 +4545 -0.444610595703125 +4546 -0.207000732421875 +4547 -0.453948974609375 +4548 -0.21124267578125 +4549 -0.4632568359375 +4550 -0.2154541015625 +4551 -0.4725341796875 +4552 -0.21966552734375 +4553 -0.481719970703125 +4554 -0.22381591796875 +4555 -0.490875244140625 +4556 -0.22796630859375 +4557 -0.499969482421875 +4558 -0.232086181640625 +4559 -0.509002685546875 +4560 -0.2362060546875 +4561 -0.51800537109375 +4562 -0.240264892578125 +4563 -0.52691650390625 +4564 -0.24432373046875 +4565 -0.535797119140625 +4566 -0.248321533203125 +4567 -0.54461669921875 +4568 -0.2523193359375 +4569 -0.5533447265625 +4570 -0.25628662109375 +4571 -0.562042236328125 +4572 -0.260223388671875 +4573 -0.5706787109375 +4574 -0.264129638671875 +4575 -0.579254150390625 +4576 -0.26800537109375 +4577 -0.587738037109375 +4578 -0.2718505859375 +4579 -0.59619140625 +4580 -0.275665283203125 +4581 -0.60455322265625 +4582 -0.27947998046875 +4583 -0.612884521484375 +4584 -0.283233642578125 +4585 -0.621124267578125 +4586 -0.28692626953125 +4587 -0.6292724609375 +4588 -0.2906494140625 +4589 -0.63739013671875 +4590 -0.2943115234375 +4591 -0.645416259765625 +4592 -0.297943115234375 +4593 -0.65338134765625 +4594 -0.301544189453125 +4595 -0.661285400390625 +4596 -0.305084228515625 +4597 -0.669097900390625 +4598 -0.308624267578125 +4599 -0.676849365234375 +4600 -0.3121337890625 +4601 -0.68450927734375 +4602 -0.315582275390625 +4603 -0.692108154296875 +4604 -0.319000244140625 +4605 -0.699615478515625 +4606 -0.322418212890625 +4607 -0.707061767578125 +4608 -0.30291748046875 +4609 -0.714447021484375 +4610 -0.305999755859375 +4611 -0.721710205078125 +4612 -0.309051513671875 +4613 -0.72894287109375 +4614 -0.31207275390625 +4615 -0.736053466796875 +4616 -0.3150634765625 +4617 -0.74310302734375 +4618 -0.3179931640625 +4619 -0.75006103515625 +4620 -0.3209228515625 +4621 -0.7569580078125 +4622 -0.323822021484375 +4623 -0.763763427734375 +4624 -0.32666015625 +4625 -0.770477294921875 +4626 -0.3294677734375 +4627 -0.777099609375 +4628 -0.332244873046875 +4629 -0.783660888671875 +4630 -0.334991455078125 +4631 -0.790130615234375 +4632 -0.337677001953125 +4633 -0.796478271484375 +4634 -0.340362548828125 +4635 -0.802764892578125 +4636 -0.342987060546875 +4637 -0.808990478515625 +4638 -0.3455810546875 +4639 -0.815093994140625 +4640 -0.348114013671875 +4641 -0.82110595703125 +4642 -0.35064697265625 +4643 -0.8270263671875 +4644 -0.353118896484375 +4645 -0.8328857421875 +4646 -0.355560302734375 +4647 -0.838623046875 +4648 -0.35797119140625 +4649 -0.84429931640625 +4650 -0.360321044921875 +4651 -0.849853515625 +4652 -0.362640380859375 +4653 -0.855316162109375 +4654 -0.364898681640625 +4655 -0.860687255859375 +4656 -0.367156982421875 +4657 -0.865997314453125 +4658 -0.369354248046875 +4659 -0.871185302734375 +4660 -0.37152099609375 +4661 -0.876251220703125 +4662 -0.373626708984375 +4663 -0.881256103515625 +4664 -0.375701904296875 +4665 -0.88616943359375 +4666 -0.37774658203125 +4667 -0.890960693359375 +4668 -0.379730224609375 +4669 -0.895660400390625 +4670 -0.381683349609375 +4671 -0.9002685546875 +4672 -0.38360595703125 +4673 -0.90478515625 +4674 -0.385467529296875 +4675 -0.9091796875 +4676 -0.387298583984375 +4677 -0.91351318359375 +4678 -0.38909912109375 +4679 -0.917724609375 +4680 -0.390838623046875 +4681 -0.92181396484375 +4682 -0.392547607421875 +4683 -0.92584228515625 +4684 -0.3941650390625 +4685 -0.929718017578125 +4686 -0.395782470703125 +4687 -0.93353271484375 +4688 -0.397369384765625 +4689 -0.937225341796875 +4690 -0.398895263671875 +4691 -0.940826416015625 +4692 -0.400390625 +4693 -0.9443359375 +4694 -0.401824951171875 +4695 -0.947723388671875 +4696 -0.4031982421875 +4697 -0.951019287109375 +4698 -0.404571533203125 +4699 -0.954193115234375 +4700 -0.405853271484375 +4701 -0.957275390625 +4702 -0.4071044921875 +4703 -0.960235595703125 +4704 -0.4083251953125 +4705 -0.963104248046875 +4706 -0.409515380859375 +4707 -0.96588134765625 +4708 -0.41064453125 +4709 -0.968536376953125 +4710 -0.411712646484375 +4711 -0.971099853515625 +4712 -0.412750244140625 +4713 -0.973541259765625 +4714 -0.41375732421875 +4715 -0.975860595703125 +4716 -0.4146728515625 +4717 -0.97808837890625 +4718 -0.41558837890625 +4719 -0.980224609375 +4720 -0.41644287109375 +4721 -0.98223876953125 +4722 -0.417266845703125 +4723 -0.984161376953125 +4724 -0.41802978515625 +4725 -0.9859619140625 +4726 -0.418731689453125 +4727 -0.987640380859375 +4728 -0.419403076171875 +4729 -0.989227294921875 +4730 -0.4200439453125 +4731 -0.990692138671875 +4732 -0.420623779296875 +4733 -0.9920654296875 +4734 -0.421142578125 +4735 -0.993316650390625 +4736 -0.421630859375 +4737 -0.994476318359375 +4738 -0.422088623046875 +4739 -0.995513916015625 +4740 -0.4224853515625 +4741 -0.9964599609375 +4742 -0.422821044921875 +4743 -0.997283935546875 +4744 -0.423126220703125 +4745 -0.99798583984375 +4746 -0.423370361328125 +4747 -0.99859619140625 +4748 -0.423583984375 +4749 -0.999114990234375 +4750 -0.423736572265625 +4751 -0.999481201171875 +4752 -0.423858642578125 +4753 -0.999755859375 +4754 -0.4239501953125 +4755 -0.99993896484375 +4756 -0.423980712890625 +4757 -1.0 +4758 -0.4239501953125 +4759 -0.99993896484375 +4760 -0.423858642578125 +4761 -0.999755859375 +4762 -0.423736572265625 +4763 -0.999481201171875 +4764 -0.423583984375 +4765 -0.999114990234375 +4766 -0.423370361328125 +4767 -0.99859619140625 +4768 -0.423126220703125 +4769 -0.99798583984375 +4770 -0.422821044921875 +4771 -0.997283935546875 +4772 -0.4224853515625 +4773 -0.9964599609375 +4774 -0.422088623046875 +4775 -0.995513916015625 +4776 -0.421630859375 +4777 -0.994476318359375 +4778 -0.421142578125 +4779 -0.993316650390625 +4780 -0.420623779296875 +4781 -0.9920654296875 +4782 -0.4200439453125 +4783 -0.990692138671875 +4784 -0.419403076171875 +4785 -0.989227294921875 +4786 -0.418731689453125 +4787 -0.987640380859375 +4788 -0.41802978515625 +4789 -0.9859619140625 +4790 -0.417266845703125 +4791 -0.984161376953125 +4792 -0.41644287109375 +4793 -0.98223876953125 +4794 -0.41558837890625 +4795 -0.980224609375 +4796 -0.4146728515625 +4797 -0.97808837890625 +4798 -0.41375732421875 +4799 -0.975860595703125 +4800 -0.412750244140625 +4801 -0.973541259765625 +4802 -0.411712646484375 +4803 -0.971099853515625 +4804 -0.41064453125 +4805 -0.968536376953125 +4806 -0.409515380859375 +4807 -0.96588134765625 +4808 -0.4083251953125 +4809 -0.963104248046875 +4810 -0.4071044921875 +4811 -0.960235595703125 +4812 -0.405853271484375 +4813 -0.957275390625 +4814 -0.404571533203125 +4815 -0.954193115234375 +4816 -0.4031982421875 +4817 -0.951019287109375 +4818 -0.401824951171875 +4819 -0.947723388671875 +4820 -0.400390625 +4821 -0.9443359375 +4822 -0.398895263671875 +4823 -0.940826416015625 +4824 -0.397369384765625 +4825 -0.937225341796875 +4826 -0.395782470703125 +4827 -0.93353271484375 +4828 -0.3941650390625 +4829 -0.929718017578125 +4830 -0.392547607421875 +4831 -0.92584228515625 +4832 -0.390838623046875 +4833 -0.92181396484375 +4834 -0.38909912109375 +4835 -0.917724609375 +4836 -0.387298583984375 +4837 -0.91351318359375 +4838 -0.385467529296875 +4839 -0.9091796875 +4840 -0.38360595703125 +4841 -0.90478515625 +4842 -0.381683349609375 +4843 -0.9002685546875 +4844 -0.379730224609375 +4845 -0.895660400390625 +4846 -0.37774658203125 +4847 -0.890960693359375 +4848 -0.375701904296875 +4849 -0.88616943359375 +4850 -0.373626708984375 +4851 -0.881256103515625 +4852 -0.37152099609375 +4853 -0.876251220703125 +4854 -0.369354248046875 +4855 -0.871185302734375 +4856 -0.367156982421875 +4857 -0.865997314453125 +4858 -0.364898681640625 +4859 -0.860687255859375 +4860 -0.362640380859375 +4861 -0.855316162109375 +4862 -0.360321044921875 +4863 -0.849853515625 +4864 -0.33770751953125 +4865 -0.84429931640625 +4866 -0.33544921875 +4867 -0.838623046875 +4868 -0.3331298828125 +4869 -0.8328857421875 +4870 -0.330810546875 +4871 -0.8270263671875 +4872 -0.32843017578125 +4873 -0.82110595703125 +4874 -0.326019287109375 +4875 -0.815093994140625 +4876 -0.323577880859375 +4877 -0.808990478515625 +4878 -0.32110595703125 +4879 -0.802764892578125 +4880 -0.318572998046875 +4881 -0.796478271484375 +4882 -0.3160400390625 +4883 -0.790130615234375 +4884 -0.313446044921875 +4885 -0.783660888671875 +4886 -0.310821533203125 +4887 -0.777099609375 +4888 -0.30816650390625 +4889 -0.770477294921875 +4890 -0.30548095703125 +4891 -0.763763427734375 +4892 -0.302764892578125 +4893 -0.7569580078125 +4894 -0.300018310546875 +4895 -0.75006103515625 +4896 -0.2972412109375 +4897 -0.74310302734375 +4898 -0.294403076171875 +4899 -0.736053466796875 +4900 -0.29156494140625 +4901 -0.72894287109375 +4902 -0.288665771484375 +4903 -0.721710205078125 +4904 -0.2857666015625 +4905 -0.714447021484375 +4906 -0.282806396484375 +4907 -0.707061767578125 +4908 -0.27984619140625 +4909 -0.699615478515625 +4910 -0.276824951171875 +4911 -0.692108154296875 +4912 -0.2738037109375 +4913 -0.68450927734375 +4914 -0.270721435546875 +4915 -0.676849365234375 +4916 -0.26763916015625 +4917 -0.669097900390625 +4918 -0.264495849609375 +4919 -0.661285400390625 +4920 -0.2613525390625 +4921 -0.65338134765625 +4922 -0.258148193359375 +4923 -0.645416259765625 +4924 -0.25494384765625 +4925 -0.63739013671875 +4926 -0.251708984375 +4927 -0.6292724609375 +4928 -0.248443603515625 +4929 -0.621124267578125 +4930 -0.245147705078125 +4931 -0.612884521484375 +4932 -0.2418212890625 +4933 -0.60455322265625 +4934 -0.23846435546875 +4935 -0.59619140625 +4936 -0.235076904296875 +4937 -0.587738037109375 +4938 -0.231689453125 +4939 -0.579254150390625 +4940 -0.228271484375 +4941 -0.5706787109375 +4942 -0.22479248046875 +4943 -0.562042236328125 +4944 -0.2213134765625 +4945 -0.5533447265625 +4946 -0.21783447265625 +4947 -0.54461669921875 +4948 -0.21429443359375 +4949 -0.535797119140625 +4950 -0.21075439453125 +4951 -0.52691650390625 +4952 -0.207183837890625 +4953 -0.51800537109375 +4954 -0.203582763671875 +4955 -0.509002685546875 +4956 -0.199981689453125 +4957 -0.499969482421875 +4958 -0.19635009765625 +4959 -0.490875244140625 +4960 -0.19268798828125 +4961 -0.481719970703125 +4962 -0.188995361328125 +4963 -0.4725341796875 +4964 -0.185302734375 +4965 -0.4632568359375 +4966 -0.18157958984375 +4967 -0.453948974609375 +4968 -0.177825927734375 +4969 -0.444610595703125 +4970 -0.174072265625 +4971 -0.435211181640625 +4972 -0.1702880859375 +4973 -0.425750732421875 +4974 -0.16650390625 +4975 -0.416259765625 +4976 -0.16265869140625 +4977 -0.406707763671875 +4978 -0.158843994140625 +4979 -0.397125244140625 +4980 -0.15496826171875 +4981 -0.387481689453125 +4982 -0.151123046875 +4983 -0.3778076171875 +4984 -0.147216796875 +4985 -0.36810302734375 +4986 -0.143310546875 +4987 -0.35833740234375 +4988 -0.139404296875 +4989 -0.348541259765625 +4990 -0.135467529296875 +4991 -0.338714599609375 +4992 -0.13153076171875 +4993 -0.328826904296875 +4994 -0.1275634765625 +4995 -0.318939208984375 +4996 -0.12359619140625 +4997 -0.308990478515625 +4998 -0.119598388671875 +4999 -0.29901123046875 +5000 -0.1156005859375 +5001 -0.28900146484375 +5002 -0.111572265625 +5003 -0.278961181640625 +5004 -0.1075439453125 +5005 -0.268890380859375 +5006 -0.103515625 +5007 -0.2587890625 +5008 -0.099456787109375 +5009 -0.2486572265625 +5010 -0.09539794921875 +5011 -0.238525390625 +5012 -0.09130859375 +5013 -0.22833251953125 +5014 -0.08721923828125 +5015 -0.218109130859375 +5016 -0.0831298828125 +5017 -0.2078857421875 +5018 -0.07904052734375 +5019 -0.1976318359375 +5020 -0.074920654296875 +5021 -0.187347412109375 +5022 -0.07080078125 +5023 -0.17706298828125 +5024 -0.066680908203125 +5025 -0.166748046875 +5026 -0.06256103515625 +5027 -0.156402587890625 +5028 -0.05841064453125 +5029 -0.14605712890625 +5030 -0.05426025390625 +5031 -0.13568115234375 +5032 -0.05010986328125 +5033 -0.12530517578125 +5034 -0.04595947265625 +5035 -0.11492919921875 +5036 -0.04180908203125 +5037 -0.104522705078125 +5038 -0.037628173828125 +5039 -0.094085693359375 +5040 -0.033447265625 +5041 -0.083648681640625 +5042 -0.029266357421875 +5043 -0.073211669921875 +5044 -0.02508544921875 +5045 -0.062774658203125 +5046 -0.020904541015625 +5047 -0.05230712890625 +5048 -0.0167236328125 +5049 -0.0418701171875 +5050 -0.012542724609375 +5051 -0.031402587890625 +5052 -0.00836181640625 +5053 -0.02093505859375 +5054 -0.004180908203125 +5055 -0.010467529296875 +5056 0.0 +5057 0.0 +5058 0.00408935546875 +5059 0.010467529296875 +5060 0.0081787109375 +5061 0.02093505859375 +5062 0.012298583984375 +5063 0.031402587890625 +5064 0.016387939453125 +5065 0.0418701171875 +5066 0.020477294921875 +5067 0.05230712890625 +5068 0.02459716796875 +5069 0.062774658203125 +5070 0.0286865234375 +5071 0.073211669921875 +5072 0.03277587890625 +5073 0.083648681640625 +5074 0.036865234375 +5075 0.094085693359375 +5076 0.04095458984375 +5077 0.104522705078125 +5078 0.0450439453125 +5079 0.11492919921875 +5080 0.049102783203125 +5081 0.12530517578125 +5082 0.05316162109375 +5083 0.13568115234375 +5084 0.0572509765625 +5085 0.14605712890625 +5086 0.061309814453125 +5087 0.156402587890625 +5088 0.065338134765625 +5089 0.166748046875 +5090 0.06939697265625 +5091 0.17706298828125 +5092 0.07342529296875 +5093 0.187347412109375 +5094 0.07745361328125 +5095 0.1976318359375 +5096 0.08148193359375 +5097 0.2078857421875 +5098 0.085479736328125 +5099 0.218109130859375 +5100 0.089508056640625 +5101 0.22833251953125 +5102 0.093475341796875 +5103 0.238525390625 +5104 0.09747314453125 +5105 0.2486572265625 +5106 0.1014404296875 +5107 0.2587890625 +5108 0.10540771484375 +5109 0.268890380859375 +5110 0.109344482421875 +5111 0.278961181640625 +5112 0.11328125 +5113 0.28900146484375 +5114 0.1171875 +5115 0.29901123046875 +5116 0.121124267578125 +5117 0.308990478515625 +5118 0.125 +5119 0.318939208984375 +5120 0.11834716796875 +5121 0.328826904296875 +5122 0.121917724609375 +5123 0.338714599609375 +5124 0.125457763671875 +5125 0.348541259765625 +5126 0.128997802734375 +5127 0.35833740234375 +5128 0.13250732421875 +5129 0.36810302734375 +5130 0.135986328125 +5131 0.3778076171875 +5132 0.13946533203125 +5133 0.387481689453125 +5134 0.1429443359375 +5135 0.397125244140625 +5136 0.146392822265625 +5137 0.406707763671875 +5138 0.14984130859375 +5139 0.416259765625 +5140 0.15325927734375 +5141 0.425750732421875 +5142 0.156646728515625 +5143 0.435211181640625 +5144 0.1600341796875 +5145 0.444610595703125 +5146 0.16339111328125 +5147 0.453948974609375 +5148 0.166748046875 +5149 0.4632568359375 +5150 0.17010498046875 +5151 0.4725341796875 +5152 0.17340087890625 +5153 0.481719970703125 +5154 0.17669677734375 +5155 0.490875244140625 +5156 0.179962158203125 +5157 0.499969482421875 +5158 0.1832275390625 +5159 0.509002685546875 +5160 0.18646240234375 +5161 0.51800537109375 +5162 0.189666748046875 +5163 0.52691650390625 +5164 0.19287109375 +5165 0.535797119140625 +5166 0.196044921875 +5167 0.54461669921875 +5168 0.199188232421875 +5169 0.5533447265625 +5170 0.20233154296875 +5171 0.562042236328125 +5172 0.205413818359375 +5173 0.5706787109375 +5174 0.208526611328125 +5175 0.579254150390625 +5176 0.211578369140625 +5177 0.587738037109375 +5178 0.214599609375 +5179 0.59619140625 +5180 0.217620849609375 +5181 0.60455322265625 +5182 0.220611572265625 +5183 0.612884521484375 +5184 0.223602294921875 +5185 0.621124267578125 +5186 0.226531982421875 +5187 0.6292724609375 +5188 0.22943115234375 +5189 0.63739013671875 +5190 0.232330322265625 +5191 0.645416259765625 +5192 0.235198974609375 +5193 0.65338134765625 +5194 0.238037109375 +5195 0.661285400390625 +5196 0.2408447265625 +5197 0.669097900390625 +5198 0.24365234375 +5199 0.676849365234375 +5200 0.24639892578125 +5201 0.68450927734375 +5202 0.2491455078125 +5203 0.692108154296875 +5204 0.2518310546875 +5205 0.699615478515625 +5206 0.2545166015625 +5207 0.707061767578125 +5208 0.257171630859375 +5209 0.714447021484375 +5210 0.259796142578125 +5211 0.721710205078125 +5212 0.26239013671875 +5213 0.72894287109375 +5214 0.26495361328125 +5215 0.736053466796875 +5216 0.267486572265625 +5217 0.74310302734375 +5218 0.269989013671875 +5219 0.75006103515625 +5220 0.272491455078125 +5221 0.7569580078125 +5222 0.274932861328125 +5223 0.763763427734375 +5224 0.27734375 +5225 0.770477294921875 +5226 0.27972412109375 +5227 0.777099609375 +5228 0.2821044921875 +5229 0.783660888671875 +5230 0.284423828125 +5231 0.790130615234375 +5232 0.286712646484375 +5233 0.796478271484375 +5234 0.288970947265625 +5235 0.802764892578125 +5236 0.291229248046875 +5237 0.808990478515625 +5238 0.293426513671875 +5239 0.815093994140625 +5240 0.29559326171875 +5241 0.82110595703125 +5242 0.297698974609375 +5243 0.8270263671875 +5244 0.299835205078125 +5245 0.8328857421875 +5246 0.3018798828125 +5247 0.838623046875 +5248 0.303924560546875 +5249 0.84429931640625 +5250 0.305938720703125 +5251 0.849853515625 +5252 0.307891845703125 +5253 0.855316162109375 +5254 0.309814453125 +5255 0.860687255859375 +5256 0.311737060546875 +5257 0.865997314453125 +5258 0.3135986328125 +5259 0.871185302734375 +5260 0.3154296875 +5261 0.876251220703125 +5262 0.317230224609375 +5263 0.881256103515625 +5264 0.319000244140625 +5265 0.88616943359375 +5266 0.32073974609375 +5267 0.890960693359375 +5268 0.322418212890625 +5269 0.895660400390625 +5270 0.324066162109375 +5271 0.9002685546875 +5272 0.325714111328125 +5273 0.90478515625 +5274 0.327301025390625 +5275 0.9091796875 +5276 0.328857421875 +5277 0.91351318359375 +5278 0.330352783203125 +5279 0.917724609375 +5280 0.33184814453125 +5281 0.92181396484375 +5282 0.333282470703125 +5283 0.92584228515625 +5284 0.334686279296875 +5285 0.929718017578125 +5286 0.3360595703125 +5287 0.93353271484375 +5288 0.337371826171875 +5289 0.937225341796875 +5290 0.33868408203125 +5291 0.940826416015625 +5292 0.339935302734375 +5293 0.9443359375 +5294 0.341156005859375 +5295 0.947723388671875 +5296 0.34234619140625 +5297 0.951019287109375 +5298 0.343505859375 +5299 0.954193115234375 +5300 0.3446044921875 +5301 0.957275390625 +5302 0.345672607421875 +5303 0.960235595703125 +5304 0.346710205078125 +5305 0.963104248046875 +5306 0.347686767578125 +5307 0.96588134765625 +5308 0.348663330078125 +5309 0.968536376953125 +5310 0.349578857421875 +5311 0.971099853515625 +5312 0.3504638671875 +5313 0.973541259765625 +5314 0.351287841796875 +5315 0.975860595703125 +5316 0.352081298828125 +5317 0.97808837890625 +5318 0.352874755859375 +5319 0.980224609375 +5320 0.35357666015625 +5321 0.98223876953125 +5322 0.354278564453125 +5323 0.984161376953125 +5324 0.35491943359375 +5325 0.9859619140625 +5326 0.35552978515625 +5327 0.987640380859375 +5328 0.356109619140625 +5329 0.989227294921875 +5330 0.35662841796875 +5331 0.990692138671875 +5332 0.35711669921875 +5333 0.9920654296875 +5334 0.357574462890625 +5335 0.993316650390625 +5336 0.358001708984375 +5337 0.994476318359375 +5338 0.358367919921875 +5339 0.995513916015625 +5340 0.35870361328125 +5341 0.9964599609375 +5342 0.3590087890625 +5343 0.997283935546875 +5344 0.3592529296875 +5345 0.99798583984375 +5346 0.359466552734375 +5347 0.99859619140625 +5348 0.359649658203125 +5349 0.999114990234375 +5350 0.359771728515625 +5351 0.999481201171875 +5352 0.359893798828125 +5353 0.999755859375 +5354 0.359954833984375 +5355 0.99993896484375 +5356 0.3599853515625 +5357 0.999969482421875 +5358 0.359954833984375 +5359 0.99993896484375 +5360 0.359893798828125 +5361 0.999755859375 +5362 0.359771728515625 +5363 0.999481201171875 +5364 0.359649658203125 +5365 0.999114990234375 +5366 0.359466552734375 +5367 0.99859619140625 +5368 0.3592529296875 +5369 0.99798583984375 +5370 0.3590087890625 +5371 0.997283935546875 +5372 0.35870361328125 +5373 0.9964599609375 +5374 0.358367919921875 +5375 0.995513916015625 +5376 0.326171875 +5377 0.994476318359375 +5378 0.3258056640625 +5379 0.993316650390625 +5380 0.325408935546875 +5381 0.9920654296875 +5382 0.324951171875 +5383 0.990692138671875 +5384 0.324462890625 +5385 0.989227294921875 +5386 0.323944091796875 +5387 0.987640380859375 +5388 0.323394775390625 +5389 0.9859619140625 +5390 0.32281494140625 +5391 0.984161376953125 +5392 0.322174072265625 +5393 0.98223876953125 +5394 0.321502685546875 +5395 0.980224609375 +5396 0.32080078125 +5397 0.97808837890625 +5398 0.320068359375 +5399 0.975860595703125 +5400 0.319305419921875 +5401 0.973541259765625 +5402 0.318511962890625 +5403 0.971099853515625 +5404 0.31768798828125 +5405 0.968536376953125 +5406 0.316802978515625 +5407 0.96588134765625 +5408 0.315887451171875 +5409 0.963104248046875 +5410 0.31494140625 +5411 0.960235595703125 +5412 0.313995361328125 +5413 0.957275390625 +5414 0.312957763671875 +5415 0.954193115234375 +5416 0.311920166015625 +5417 0.951019287109375 +5418 0.31085205078125 +5419 0.947723388671875 +5420 0.30975341796875 +5421 0.9443359375 +5422 0.30859375 +5423 0.940826416015625 +5424 0.307403564453125 +5425 0.937225341796875 +5426 0.306182861328125 +5427 0.93353271484375 +5428 0.304931640625 +5429 0.929718017578125 +5430 0.303680419921875 +5431 0.92584228515625 +5432 0.302337646484375 +5433 0.92181396484375 +5434 0.301025390625 +5435 0.917724609375 +5436 0.29962158203125 +5437 0.91351318359375 +5438 0.2982177734375 +5439 0.9091796875 +5440 0.2967529296875 +5441 0.90478515625 +5442 0.2952880859375 +5443 0.9002685546875 +5444 0.29376220703125 +5445 0.895660400390625 +5446 0.292236328125 +5447 0.890960693359375 +5448 0.2906494140625 +5449 0.88616943359375 +5450 0.2890625 +5451 0.881256103515625 +5452 0.28741455078125 +5453 0.876251220703125 +5454 0.285736083984375 +5455 0.871185302734375 +5456 0.2840576171875 +5457 0.865997314453125 +5458 0.28228759765625 +5459 0.860687255859375 +5460 0.280548095703125 +5461 0.855316162109375 +5462 0.27874755859375 +5463 0.849853515625 +5464 0.27691650390625 +5465 0.84429931640625 +5466 0.275054931640625 +5467 0.838623046875 +5468 0.273193359375 +5469 0.8328857421875 +5470 0.271270751953125 +5471 0.8270263671875 +5472 0.269317626953125 +5473 0.82110595703125 +5474 0.267333984375 +5475 0.815093994140625 +5476 0.265350341796875 +5477 0.808990478515625 +5478 0.2633056640625 +5479 0.802764892578125 +5480 0.26123046875 +5481 0.796478271484375 +5482 0.2591552734375 +5483 0.790130615234375 +5484 0.257049560546875 +5485 0.783660888671875 +5486 0.2548828125 +5487 0.777099609375 +5488 0.252716064453125 +5489 0.770477294921875 +5490 0.250518798828125 +5491 0.763763427734375 +5492 0.248291015625 +5493 0.7569580078125 +5494 0.246002197265625 +5495 0.75006103515625 +5496 0.243743896484375 +5497 0.74310302734375 +5498 0.241424560546875 +5499 0.736053466796875 +5500 0.23907470703125 +5501 0.72894287109375 +5502 0.236724853515625 +5503 0.721710205078125 +5504 0.234344482421875 +5505 0.714447021484375 +5506 0.231903076171875 +5507 0.707061767578125 +5508 0.229461669921875 +5509 0.699615478515625 +5510 0.227020263671875 +5511 0.692108154296875 +5512 0.224517822265625 +5513 0.68450927734375 +5514 0.22198486328125 +5515 0.676849365234375 +5516 0.219451904296875 +5517 0.669097900390625 +5518 0.216888427734375 +5519 0.661285400390625 +5520 0.21429443359375 +5521 0.65338134765625 +5522 0.211700439453125 +5523 0.645416259765625 +5524 0.20904541015625 +5525 0.63739013671875 +5526 0.206390380859375 +5527 0.6292724609375 +5528 0.2037353515625 +5529 0.621124267578125 +5530 0.201019287109375 +5531 0.612884521484375 +5532 0.198272705078125 +5533 0.60455322265625 +5534 0.195556640625 +5535 0.59619140625 +5536 0.192779541015625 +5537 0.587738037109375 +5538 0.19000244140625 +5539 0.579254150390625 +5540 0.187164306640625 +5541 0.5706787109375 +5542 0.184356689453125 +5543 0.562042236328125 +5544 0.181488037109375 +5545 0.5533447265625 +5546 0.178619384765625 +5547 0.54461669921875 +5548 0.17572021484375 +5549 0.535797119140625 +5550 0.172821044921875 +5551 0.52691650390625 +5552 0.169891357421875 +5553 0.51800537109375 +5554 0.16693115234375 +5555 0.509002685546875 +5556 0.163970947265625 +5557 0.499969482421875 +5558 0.1610107421875 +5559 0.490875244140625 +5560 0.157989501953125 +5561 0.481719970703125 +5562 0.15496826171875 +5563 0.4725341796875 +5564 0.151947021484375 +5565 0.4632568359375 +5566 0.148895263671875 +5567 0.453948974609375 +5568 0.14581298828125 +5569 0.444610595703125 +5570 0.142730712890625 +5571 0.435211181640625 +5572 0.1396484375 +5573 0.425750732421875 +5574 0.13653564453125 +5575 0.416259765625 +5576 0.133392333984375 +5577 0.406707763671875 +5578 0.1302490234375 +5579 0.397125244140625 +5580 0.1270751953125 +5581 0.387481689453125 +5582 0.1239013671875 +5583 0.3778076171875 +5584 0.1207275390625 +5585 0.36810302734375 +5586 0.117523193359375 +5587 0.35833740234375 +5588 0.11431884765625 +5589 0.348541259765625 +5590 0.111083984375 +5591 0.338714599609375 +5592 0.10784912109375 +5593 0.328826904296875 +5594 0.1046142578125 +5595 0.318939208984375 +5596 0.101348876953125 +5597 0.308990478515625 +5598 0.098052978515625 +5599 0.29901123046875 +5600 0.09478759765625 +5601 0.28900146484375 +5602 0.09149169921875 +5603 0.278961181640625 +5604 0.08819580078125 +5605 0.268890380859375 +5606 0.084869384765625 +5607 0.2587890625 +5608 0.08154296875 +5609 0.2486572265625 +5610 0.078216552734375 +5611 0.238525390625 +5612 0.07489013671875 +5613 0.22833251953125 +5614 0.071533203125 +5615 0.218109130859375 +5616 0.06817626953125 +5617 0.2078857421875 +5618 0.0648193359375 +5619 0.1976318359375 +5620 0.061431884765625 +5621 0.187347412109375 +5622 0.058074951171875 +5623 0.17706298828125 +5624 0.0546875 +5625 0.166748046875 +5626 0.051300048828125 +5627 0.156402587890625 +5628 0.047882080078125 +5629 0.14605712890625 +5630 0.04449462890625 +5631 0.13568115234375 +5632 0.037078857421875 +5633 0.12530517578125 +5634 0.03399658203125 +5635 0.11492919921875 +5636 0.030914306640625 +5637 0.104522705078125 +5638 0.02783203125 +5639 0.094085693359375 +5640 0.024749755859375 +5641 0.083648681640625 +5642 0.02166748046875 +5643 0.073211669921875 +5644 0.0185546875 +5645 0.062774658203125 +5646 0.015472412109375 +5647 0.05230712890625 +5648 0.01239013671875 +5649 0.0418701171875 +5650 0.00927734375 +5651 0.031402587890625 +5652 0.006195068359375 +5653 0.02093505859375 +5654 0.003082275390625 +5655 0.010467529296875 +5656 0.0 +5657 0.0 +5658 -0.003082275390625 +5659 -0.010467529296875 +5660 -0.006195068359375 +5661 -0.02093505859375 +5662 -0.00927734375 +5663 -0.031402587890625 +5664 -0.01239013671875 +5665 -0.0418701171875 +5666 -0.015472412109375 +5667 -0.05230712890625 +5668 -0.0185546875 +5669 -0.062774658203125 +5670 -0.02166748046875 +5671 -0.073211669921875 +5672 -0.024749755859375 +5673 -0.083648681640625 +5674 -0.02783203125 +5675 -0.094085693359375 +5676 -0.030914306640625 +5677 -0.104522705078125 +5678 -0.03399658203125 +5679 -0.11492919921875 +5680 -0.037078857421875 +5681 -0.12530517578125 +5682 -0.0401611328125 +5683 -0.13568115234375 +5684 -0.043212890625 +5685 -0.14605712890625 +5686 -0.0462646484375 +5687 -0.156402587890625 +5688 -0.049346923828125 +5689 -0.166748046875 +5690 -0.052398681640625 +5691 -0.17706298828125 +5692 -0.055450439453125 +5693 -0.187347412109375 +5694 -0.0584716796875 +5695 -0.1976318359375 +5696 -0.0615234375 +5697 -0.2078857421875 +5698 -0.064544677734375 +5699 -0.218109130859375 +5700 -0.06756591796875 +5701 -0.22833251953125 +5702 -0.070587158203125 +5703 -0.238525390625 +5704 -0.073577880859375 +5705 -0.2486572265625 +5706 -0.07659912109375 +5707 -0.2587890625 +5708 -0.07958984375 +5709 -0.268890380859375 +5710 -0.082550048828125 +5711 -0.278961181640625 +5712 -0.085540771484375 +5713 -0.28900146484375 +5714 -0.0885009765625 +5715 -0.29901123046875 +5716 -0.0914306640625 +5717 -0.308990478515625 +5718 -0.094390869140625 +5719 -0.318939208984375 +5720 -0.097320556640625 +5721 -0.328826904296875 +5722 -0.100250244140625 +5723 -0.338714599609375 +5724 -0.1031494140625 +5725 -0.348541259765625 +5726 -0.106048583984375 +5727 -0.35833740234375 +5728 -0.10894775390625 +5729 -0.36810302734375 +5730 -0.11181640625 +5731 -0.3778076171875 +5732 -0.11468505859375 +5733 -0.387481689453125 +5734 -0.117523193359375 +5735 -0.397125244140625 +5736 -0.120361328125 +5737 -0.406707763671875 +5738 -0.123199462890625 +5739 -0.416259765625 +5740 -0.126007080078125 +5741 -0.425750732421875 +5742 -0.128814697265625 +5743 -0.435211181640625 +5744 -0.131591796875 +5745 -0.444610595703125 +5746 -0.13433837890625 +5747 -0.453948974609375 +5748 -0.137115478515625 +5749 -0.4632568359375 +5750 -0.139862060546875 +5751 -0.4725341796875 +5752 -0.142578125 +5753 -0.481719970703125 +5754 -0.145294189453125 +5755 -0.490875244140625 +5756 -0.147979736328125 +5757 -0.499969482421875 +5758 -0.150634765625 +5759 -0.509002685546875 +5760 -0.1533203125 +5761 -0.51800537109375 +5762 -0.15594482421875 +5763 -0.52691650390625 +5764 -0.1585693359375 +5765 -0.535797119140625 +5766 -0.16119384765625 +5767 -0.54461669921875 +5768 -0.163787841796875 +5769 -0.5533447265625 +5770 -0.166351318359375 +5771 -0.562042236328125 +5772 -0.168914794921875 +5773 -0.5706787109375 +5774 -0.17144775390625 +5775 -0.579254150390625 +5776 -0.1739501953125 +5777 -0.587738037109375 +5778 -0.17645263671875 +5779 -0.59619140625 +5780 -0.178924560546875 +5781 -0.60455322265625 +5782 -0.181396484375 +5783 -0.612884521484375 +5784 -0.183837890625 +5785 -0.621124267578125 +5786 -0.186248779296875 +5787 -0.6292724609375 +5788 -0.18865966796875 +5789 -0.63739013671875 +5790 -0.1910400390625 +5791 -0.645416259765625 +5792 -0.193389892578125 +5793 -0.65338134765625 +5794 -0.19573974609375 +5795 -0.661285400390625 +5796 -0.198028564453125 +5797 -0.669097900390625 +5798 -0.2003173828125 +5799 -0.676849365234375 +5800 -0.202606201171875 +5801 -0.68450927734375 +5802 -0.204833984375 +5803 -0.692108154296875 +5804 -0.207061767578125 +5805 -0.699615478515625 +5806 -0.20928955078125 +5807 -0.707061767578125 +5808 -0.211456298828125 +5809 -0.714447021484375 +5810 -0.213623046875 +5811 -0.721710205078125 +5812 -0.21575927734375 +5813 -0.72894287109375 +5814 -0.217864990234375 +5815 -0.736053466796875 +5816 -0.219940185546875 +5817 -0.74310302734375 +5818 -0.222015380859375 +5819 -0.75006103515625 +5820 -0.224029541015625 +5821 -0.7569580078125 +5822 -0.226043701171875 +5823 -0.763763427734375 +5824 -0.228057861328125 +5825 -0.770477294921875 +5826 -0.230010986328125 +5827 -0.777099609375 +5828 -0.23193359375 +5829 -0.783660888671875 +5830 -0.233856201171875 +5831 -0.790130615234375 +5832 -0.235748291015625 +5833 -0.796478271484375 +5834 -0.23760986328125 +5835 -0.802764892578125 +5836 -0.23944091796875 +5837 -0.808990478515625 +5838 -0.241241455078125 +5839 -0.815093994140625 +5840 -0.2430419921875 +5841 -0.82110595703125 +5842 -0.244781494140625 +5843 -0.8270263671875 +5844 -0.24652099609375 +5845 -0.8328857421875 +5846 -0.24822998046875 +5847 -0.838623046875 +5848 -0.249908447265625 +5849 -0.84429931640625 +5850 -0.25152587890625 +5851 -0.849853515625 +5852 -0.253143310546875 +5853 -0.855316162109375 +5854 -0.2547607421875 +5855 -0.860687255859375 +5856 -0.256317138671875 +5857 -0.865997314453125 +5858 -0.257843017578125 +5859 -0.871185302734375 +5860 -0.259368896484375 +5861 -0.876251220703125 +5862 -0.260833740234375 +5863 -0.881256103515625 +5864 -0.262298583984375 +5865 -0.88616943359375 +5866 -0.263702392578125 +5867 -0.890960693359375 +5868 -0.265106201171875 +5869 -0.895660400390625 +5870 -0.266448974609375 +5871 -0.9002685546875 +5872 -0.267791748046875 +5873 -0.90478515625 +5874 -0.26910400390625 +5875 -0.9091796875 +5876 -0.2703857421875 +5877 -0.91351318359375 +5878 -0.271636962890625 +5879 -0.917724609375 +5880 -0.2728271484375 +5881 -0.92181396484375 +5882 -0.2740478515625 +5883 -0.92584228515625 +5884 -0.275177001953125 +5885 -0.929718017578125 +5886 -0.27630615234375 +5887 -0.93353271484375 +5888 -0.247406005859375 +5889 -0.937225341796875 +5890 -0.24835205078125 +5891 -0.940826416015625 +5892 -0.249267578125 +5893 -0.9443359375 +5894 -0.25018310546875 +5895 -0.947723388671875 +5896 -0.25103759765625 +5897 -0.951019287109375 +5898 -0.25189208984375 +5899 -0.954193115234375 +5900 -0.252685546875 +5901 -0.957275390625 +5902 -0.25347900390625 +5903 -0.960235595703125 +5904 -0.254241943359375 +5905 -0.963104248046875 +5906 -0.254974365234375 +5907 -0.96588134765625 +5908 -0.25567626953125 +5909 -0.968536376953125 +5910 -0.25634765625 +5911 -0.971099853515625 +5912 -0.256988525390625 +5913 -0.973541259765625 +5914 -0.257598876953125 +5915 -0.975860595703125 +5916 -0.2581787109375 +5917 -0.97808837890625 +5918 -0.258758544921875 +5919 -0.980224609375 +5920 -0.25927734375 +5921 -0.98223876953125 +5922 -0.259796142578125 +5923 -0.984161376953125 +5924 -0.26025390625 +5925 -0.9859619140625 +5926 -0.260711669921875 +5927 -0.987640380859375 +5928 -0.261138916015625 +5929 -0.989227294921875 +5930 -0.261505126953125 +5931 -0.990692138671875 +5932 -0.261871337890625 +5933 -0.9920654296875 +5934 -0.26220703125 +5935 -0.993316650390625 +5936 -0.26251220703125 +5937 -0.994476318359375 +5938 -0.262786865234375 +5939 -0.995513916015625 +5940 -0.263031005859375 +5941 -0.9964599609375 +5942 -0.26324462890625 +5943 -0.997283935546875 +5944 -0.263427734375 +5945 -0.99798583984375 +5946 -0.26361083984375 +5947 -0.99859619140625 +5948 -0.26373291015625 +5949 -0.999114990234375 +5950 -0.263824462890625 +5951 -0.999481201171875 +5952 -0.263885498046875 +5953 -0.999755859375 +5954 -0.263946533203125 +5955 -0.99993896484375 +5956 -0.26397705078125 +5957 -1.0 +5958 -0.263946533203125 +5959 -0.99993896484375 +5960 -0.263885498046875 +5961 -0.999755859375 +5962 -0.263824462890625 +5963 -0.999481201171875 +5964 -0.26373291015625 +5965 -0.999114990234375 +5966 -0.26361083984375 +5967 -0.99859619140625 +5968 -0.263427734375 +5969 -0.99798583984375 +5970 -0.26324462890625 +5971 -0.997283935546875 +5972 -0.263031005859375 +5973 -0.9964599609375 +5974 -0.262786865234375 +5975 -0.995513916015625 +5976 -0.26251220703125 +5977 -0.994476318359375 +5978 -0.26220703125 +5979 -0.993316650390625 +5980 -0.261871337890625 +5981 -0.9920654296875 +5982 -0.261505126953125 +5983 -0.990692138671875 +5984 -0.261138916015625 +5985 -0.989227294921875 +5986 -0.260711669921875 +5987 -0.987640380859375 +5988 -0.26025390625 +5989 -0.9859619140625 +5990 -0.259796142578125 +5991 -0.984161376953125 +5992 -0.25927734375 +5993 -0.98223876953125 +5994 -0.258758544921875 +5995 -0.980224609375 +5996 -0.2581787109375 +5997 -0.97808837890625 +5998 -0.257598876953125 +5999 -0.975860595703125 +6000 -0.256988525390625 +6001 -0.973541259765625 +6002 -0.25634765625 +6003 -0.971099853515625 +6004 -0.25567626953125 +6005 -0.968536376953125 +6006 -0.254974365234375 +6007 -0.96588134765625 +6008 -0.254241943359375 +6009 -0.963104248046875 +6010 -0.25347900390625 +6011 -0.960235595703125 +6012 -0.252685546875 +6013 -0.957275390625 +6014 -0.25189208984375 +6015 -0.954193115234375 +6016 -0.25103759765625 +6017 -0.951019287109375 +6018 -0.25018310546875 +6019 -0.947723388671875 +6020 -0.249267578125 +6021 -0.9443359375 +6022 -0.24835205078125 +6023 -0.940826416015625 +6024 -0.247406005859375 +6025 -0.937225341796875 +6026 -0.246429443359375 +6027 -0.93353271484375 +6028 -0.24542236328125 +6029 -0.929718017578125 +6030 -0.244384765625 +6031 -0.92584228515625 +6032 -0.243316650390625 +6033 -0.92181396484375 +6034 -0.24224853515625 +6035 -0.917724609375 +6036 -0.24114990234375 +6037 -0.91351318359375 +6038 -0.239990234375 +6039 -0.9091796875 +6040 -0.23883056640625 +6041 -0.90478515625 +6042 -0.237640380859375 +6043 -0.9002685546875 +6044 -0.236419677734375 +6045 -0.895660400390625 +6046 -0.235198974609375 +6047 -0.890960693359375 +6048 -0.233917236328125 +6049 -0.88616943359375 +6050 -0.232635498046875 +6051 -0.881256103515625 +6052 -0.231292724609375 +6053 -0.876251220703125 +6054 -0.229949951171875 +6055 -0.871185302734375 +6056 -0.228607177734375 +6057 -0.865997314453125 +6058 -0.227203369140625 +6059 -0.860687255859375 +6060 -0.22576904296875 +6061 -0.855316162109375 +6062 -0.224334716796875 +6063 -0.849853515625 +6064 -0.222869873046875 +6065 -0.84429931640625 +6066 -0.22137451171875 +6067 -0.838623046875 +6068 -0.2198486328125 +6069 -0.8328857421875 +6070 -0.218292236328125 +6071 -0.8270263671875 +6072 -0.21673583984375 +6073 -0.82110595703125 +6074 -0.21514892578125 +6075 -0.815093994140625 +6076 -0.213531494140625 +6077 -0.808990478515625 +6078 -0.2119140625 +6079 -0.802764892578125 +6080 -0.210235595703125 +6081 -0.796478271484375 +6082 -0.20855712890625 +6083 -0.790130615234375 +6084 -0.20684814453125 +6085 -0.783660888671875 +6086 -0.20513916015625 +6087 -0.777099609375 +6088 -0.203369140625 +6089 -0.770477294921875 +6090 -0.20159912109375 +6091 -0.763763427734375 +6092 -0.199798583984375 +6093 -0.7569580078125 +6094 -0.197998046875 +6095 -0.75006103515625 +6096 -0.1961669921875 +6097 -0.74310302734375 +6098 -0.194305419921875 +6099 -0.736053466796875 +6100 -0.192413330078125 +6101 -0.72894287109375 +6102 -0.19049072265625 +6103 -0.721710205078125 +6104 -0.1885986328125 +6105 -0.714447021484375 +6106 -0.1866455078125 +6107 -0.707061767578125 +6108 -0.184661865234375 +6109 -0.699615478515625 +6110 -0.18267822265625 +6111 -0.692108154296875 +6112 -0.180694580078125 +6113 -0.68450927734375 +6114 -0.17864990234375 +6115 -0.676849365234375 +6116 -0.176605224609375 +6117 -0.669097900390625 +6118 -0.174560546875 +6119 -0.661285400390625 +6120 -0.172454833984375 +6121 -0.65338134765625 +6122 -0.170379638671875 +6123 -0.645416259765625 +6124 -0.168243408203125 +6125 -0.63739013671875 +6126 -0.166107177734375 +6127 -0.6292724609375 +6128 -0.1639404296875 +6129 -0.621124267578125 +6130 -0.161773681640625 +6131 -0.612884521484375 +6132 -0.159576416015625 +6133 -0.60455322265625 +6134 -0.157379150390625 +6135 -0.59619140625 +6136 -0.1551513671875 +6137 -0.587738037109375 +6138 -0.15289306640625 +6139 -0.579254150390625 +6140 -0.150634765625 +6141 -0.5706787109375 +6142 -0.148345947265625 +6143 -0.562042236328125 +6144 -0.138336181640625 +6145 -0.5533447265625 +6146 -0.136138916015625 +6147 -0.54461669921875 +6148 -0.133941650390625 +6149 -0.535797119140625 +6150 -0.1317138671875 +6151 -0.52691650390625 +6152 -0.129486083984375 +6153 -0.51800537109375 +6154 -0.127227783203125 +6155 -0.509002685546875 +6156 -0.124969482421875 +6157 -0.499969482421875 +6158 -0.122711181640625 +6159 -0.490875244140625 +6160 -0.12042236328125 +6161 -0.481719970703125 +6162 -0.118133544921875 +6163 -0.4725341796875 +6164 -0.115814208984375 +6165 -0.4632568359375 +6166 -0.11346435546875 +6167 -0.453948974609375 +6168 -0.11114501953125 +6169 -0.444610595703125 +6170 -0.108795166015625 +6171 -0.435211181640625 +6172 -0.106414794921875 +6173 -0.425750732421875 +6174 -0.10406494140625 +6175 -0.416259765625 +6176 -0.101654052734375 +6177 -0.406707763671875 +6178 -0.099273681640625 +6179 -0.397125244140625 +6180 -0.09686279296875 +6181 -0.387481689453125 +6182 -0.094451904296875 +6183 -0.3778076171875 +6184 -0.092010498046875 +6185 -0.36810302734375 +6186 -0.089569091796875 +6187 -0.35833740234375 +6188 -0.087127685546875 +6189 -0.348541259765625 +6190 -0.08465576171875 +6191 -0.338714599609375 +6192 -0.082183837890625 +6193 -0.328826904296875 +6194 -0.0797119140625 +6195 -0.318939208984375 +6196 -0.077239990234375 +6197 -0.308990478515625 +6198 -0.074737548828125 +6199 -0.29901123046875 +6200 -0.072235107421875 +6201 -0.28900146484375 +6202 -0.069732666015625 +6203 -0.278961181640625 +6204 -0.06719970703125 +6205 -0.268890380859375 +6206 -0.064697265625 +6207 -0.2587890625 +6208 -0.062164306640625 +6209 -0.2486572265625 +6210 -0.05963134765625 +6211 -0.238525390625 +6212 -0.05706787109375 +6213 -0.22833251953125 +6214 -0.05450439453125 +6215 -0.218109130859375 +6216 -0.051971435546875 +6217 -0.2078857421875 +6218 -0.049407958984375 +6219 -0.1976318359375 +6220 -0.04681396484375 +6221 -0.187347412109375 +6222 -0.04425048828125 +6223 -0.17706298828125 +6224 -0.04168701171875 +6225 -0.166748046875 +6226 -0.039093017578125 +6227 -0.156402587890625 +6228 -0.0364990234375 +6229 -0.14605712890625 +6230 -0.033905029296875 +6231 -0.13568115234375 +6232 -0.03131103515625 +6233 -0.12530517578125 +6234 -0.028717041015625 +6235 -0.11492919921875 +6236 -0.026123046875 +6237 -0.104522705078125 +6238 -0.02349853515625 +6239 -0.094085693359375 +6240 -0.020904541015625 +6241 -0.083648681640625 +6242 -0.018280029296875 +6243 -0.073211669921875 +6244 -0.01568603515625 +6245 -0.062774658203125 +6246 -0.0130615234375 +6247 -0.05230712890625 +6248 -0.010467529296875 +6249 -0.0418701171875 +6250 -0.007843017578125 +6251 -0.031402587890625 +6252 -0.005218505859375 +6253 -0.02093505859375 +6254 -0.002593994140625 +6255 -0.010467529296875 +6256 0.0 +6257 0.0 +6258 0.002410888671875 +6259 0.010467529296875 +6260 0.004852294921875 +6261 0.02093505859375 +6262 0.00726318359375 +6263 0.031402587890625 +6264 0.00970458984375 +6265 0.0418701171875 +6266 0.012115478515625 +6267 0.05230712890625 +6268 0.014556884765625 +6269 0.062774658203125 +6270 0.0169677734375 +6271 0.073211669921875 +6272 0.019378662109375 +6273 0.083648681640625 +6274 0.021820068359375 +6275 0.094085693359375 +6276 0.02423095703125 +6277 0.104522705078125 +6278 0.026641845703125 +6279 0.11492919921875 +6280 0.029052734375 +6281 0.12530517578125 +6282 0.031463623046875 +6283 0.13568115234375 +6284 0.03387451171875 +6285 0.14605712890625 +6286 0.036285400390625 +6287 0.156402587890625 +6288 0.038665771484375 +6289 0.166748046875 +6290 0.04107666015625 +6291 0.17706298828125 +6292 0.04345703125 +6293 0.187347412109375 +6294 0.04583740234375 +6295 0.1976318359375 +6296 0.0482177734375 +6297 0.2078857421875 +6298 0.05059814453125 +6299 0.218109130859375 +6300 0.052947998046875 +6301 0.22833251953125 +6302 0.055328369140625 +6303 0.238525390625 +6304 0.05767822265625 +6305 0.2486572265625 +6306 0.060028076171875 +6307 0.2587890625 +6308 0.0623779296875 +6309 0.268890380859375 +6310 0.064697265625 +6311 0.278961181640625 +6312 0.067047119140625 +6313 0.28900146484375 +6314 0.069366455078125 +6315 0.29901123046875 +6316 0.071685791015625 +6317 0.308990478515625 +6318 0.073974609375 +6319 0.318939208984375 +6320 0.076263427734375 +6321 0.328826904296875 +6322 0.07855224609375 +6323 0.338714599609375 +6324 0.080841064453125 +6325 0.348541259765625 +6326 0.0831298828125 +6327 0.35833740234375 +6328 0.08538818359375 +6329 0.36810302734375 +6330 0.087646484375 +6331 0.3778076171875 +6332 0.089874267578125 +6333 0.387481689453125 +6334 0.092132568359375 +6335 0.397125244140625 +6336 0.094329833984375 +6337 0.406707763671875 +6338 0.0965576171875 +6339 0.416259765625 +6340 0.0987548828125 +6341 0.425750732421875 +6342 0.1009521484375 +6343 0.435211181640625 +6344 0.1031494140625 +6345 0.444610595703125 +6346 0.105316162109375 +6347 0.453948974609375 +6348 0.107452392578125 +6349 0.4632568359375 +6350 0.109619140625 +6351 0.4725341796875 +6352 0.11175537109375 +6353 0.481719970703125 +6354 0.113861083984375 +6355 0.490875244140625 +6356 0.115966796875 +6357 0.499969482421875 +6358 0.118072509765625 +6359 0.509002685546875 +6360 0.120147705078125 +6361 0.51800537109375 +6362 0.122222900390625 +6363 0.52691650390625 +6364 0.124298095703125 +6365 0.535797119140625 +6366 0.1263427734375 +6367 0.54461669921875 +6368 0.12835693359375 +6369 0.5533447265625 +6370 0.13037109375 +6371 0.562042236328125 +6372 0.13238525390625 +6373 0.5706787109375 +6374 0.134368896484375 +6375 0.579254150390625 +6376 0.1363525390625 +6377 0.587738037109375 +6378 0.1383056640625 +6379 0.59619140625 +6380 0.140228271484375 +6381 0.60455322265625 +6382 0.142181396484375 +6383 0.612884521484375 +6384 0.144073486328125 +6385 0.621124267578125 +6386 0.145965576171875 +6387 0.6292724609375 +6388 0.147857666015625 +6389 0.63739013671875 +6390 0.14971923828125 +6391 0.645416259765625 +6392 0.151580810546875 +6393 0.65338134765625 +6394 0.153411865234375 +6395 0.661285400390625 +6396 0.15521240234375 +6397 0.669097900390625 +6398 0.157012939453125 +6399 0.676849365234375 +6400 0.136871337890625 +6401 0.68450927734375 +6402 0.138397216796875 +6403 0.692108154296875 +6404 0.139892578125 +6405 0.699615478515625 +6406 0.141387939453125 +6407 0.707061767578125 +6408 0.142852783203125 +6409 0.714447021484375 +6410 0.144317626953125 +6411 0.721710205078125 +6412 0.145751953125 +6413 0.72894287109375 +6414 0.147186279296875 +6415 0.736053466796875 +6416 0.148590087890625 +6417 0.74310302734375 +6418 0.149993896484375 +6419 0.75006103515625 +6420 0.1513671875 +6421 0.7569580078125 +6422 0.152740478515625 +6423 0.763763427734375 +6424 0.154083251953125 +6425 0.770477294921875 +6426 0.1553955078125 +6427 0.777099609375 +6428 0.156707763671875 +6429 0.783660888671875 +6430 0.157989501953125 +6431 0.790130615234375 +6432 0.159271240234375 +6433 0.796478271484375 +6434 0.1605224609375 +6435 0.802764892578125 +6436 0.161773681640625 +6437 0.808990478515625 +6438 0.162994384765625 +6439 0.815093994140625 +6440 0.1641845703125 +6441 0.82110595703125 +6442 0.165374755859375 +6443 0.8270263671875 +6444 0.16656494140625 +6445 0.8328857421875 +6446 0.167694091796875 +6447 0.838623046875 +6448 0.1688232421875 +6449 0.84429931640625 +6450 0.169952392578125 +6451 0.849853515625 +6452 0.171051025390625 +6453 0.855316162109375 +6454 0.172119140625 +6455 0.860687255859375 +6456 0.173187255859375 +6457 0.865997314453125 +6458 0.174224853515625 +6459 0.871185302734375 +6460 0.17523193359375 +6461 0.876251220703125 +6462 0.176239013671875 +6463 0.881256103515625 +6464 0.177215576171875 +6465 0.88616943359375 +6466 0.17816162109375 +6467 0.890960693359375 +6468 0.179107666015625 +6469 0.895660400390625 +6470 0.180023193359375 +6471 0.9002685546875 +6472 0.180938720703125 +6473 0.90478515625 +6474 0.18182373046875 +6475 0.9091796875 +6476 0.18267822265625 +6477 0.91351318359375 +6478 0.18353271484375 +6479 0.917724609375 +6480 0.184326171875 +6481 0.92181396484375 +6482 0.185150146484375 +6483 0.92584228515625 +6484 0.1859130859375 +6485 0.929718017578125 +6486 0.186676025390625 +6487 0.93353271484375 +6488 0.187408447265625 +6489 0.937225341796875 +6490 0.188140869140625 +6491 0.940826416015625 +6492 0.1888427734375 +6493 0.9443359375 +6494 0.18951416015625 +6495 0.947723388671875 +6496 0.190185546875 +6497 0.951019287109375 +6498 0.190826416015625 +6499 0.954193115234375 +6500 0.191436767578125 +6501 0.957275390625 +6502 0.1920166015625 +6503 0.960235595703125 +6504 0.192596435546875 +6505 0.963104248046875 +6506 0.193145751953125 +6507 0.96588134765625 +6508 0.193695068359375 +6509 0.968536376953125 +6510 0.194183349609375 +6511 0.971099853515625 +6512 0.194671630859375 +6513 0.973541259765625 +6514 0.195159912109375 +6515 0.975860595703125 +6516 0.195587158203125 +6517 0.97808837890625 +6518 0.196014404296875 +6519 0.980224609375 +6520 0.1964111328125 +6521 0.98223876953125 +6522 0.196807861328125 +6523 0.984161376953125 +6524 0.197174072265625 +6525 0.9859619140625 +6526 0.197509765625 +6527 0.987640380859375 +6528 0.19781494140625 +6529 0.989227294921875 +6530 0.1981201171875 +6531 0.990692138671875 +6532 0.198394775390625 +6533 0.9920654296875 +6534 0.198638916015625 +6535 0.993316650390625 +6536 0.198883056640625 +6537 0.994476318359375 +6538 0.199066162109375 +6539 0.995513916015625 +6540 0.19927978515625 +6541 0.9964599609375 +6542 0.199432373046875 +6543 0.997283935546875 +6544 0.1995849609375 +6545 0.99798583984375 +6546 0.19970703125 +6547 0.99859619140625 +6548 0.199798583984375 +6549 0.999114990234375 +6550 0.199859619140625 +6551 0.999481201171875 +6552 0.199920654296875 +6553 0.999755859375 +6554 0.199951171875 +6555 0.99993896484375 +6556 0.199981689453125 +6557 0.999969482421875 +6558 0.199951171875 +6559 0.99993896484375 +6560 0.199920654296875 +6561 0.999755859375 +6562 0.199859619140625 +6563 0.999481201171875 +6564 0.199798583984375 +6565 0.999114990234375 +6566 0.19970703125 +6567 0.99859619140625 +6568 0.1995849609375 +6569 0.99798583984375 +6570 0.199432373046875 +6571 0.997283935546875 +6572 0.19927978515625 +6573 0.9964599609375 +6574 0.199066162109375 +6575 0.995513916015625 +6576 0.198883056640625 +6577 0.994476318359375 +6578 0.198638916015625 +6579 0.993316650390625 +6580 0.198394775390625 +6581 0.9920654296875 +6582 0.1981201171875 +6583 0.990692138671875 +6584 0.19781494140625 +6585 0.989227294921875 +6586 0.197509765625 +6587 0.987640380859375 +6588 0.197174072265625 +6589 0.9859619140625 +6590 0.196807861328125 +6591 0.984161376953125 +6592 0.1964111328125 +6593 0.98223876953125 +6594 0.196014404296875 +6595 0.980224609375 +6596 0.195587158203125 +6597 0.97808837890625 +6598 0.195159912109375 +6599 0.975860595703125 +6600 0.194671630859375 +6601 0.973541259765625 +6602 0.194183349609375 +6603 0.971099853515625 +6604 0.193695068359375 +6605 0.968536376953125 +6606 0.193145751953125 +6607 0.96588134765625 +6608 0.192596435546875 +6609 0.963104248046875 +6610 0.1920166015625 +6611 0.960235595703125 +6612 0.191436767578125 +6613 0.957275390625 +6614 0.190826416015625 +6615 0.954193115234375 +6616 0.190185546875 +6617 0.951019287109375 +6618 0.18951416015625 +6619 0.947723388671875 +6620 0.1888427734375 +6621 0.9443359375 +6622 0.188140869140625 +6623 0.940826416015625 +6624 0.187408447265625 +6625 0.937225341796875 +6626 0.186676025390625 +6627 0.93353271484375 +6628 0.1859130859375 +6629 0.929718017578125 +6630 0.185150146484375 +6631 0.92584228515625 +6632 0.184326171875 +6633 0.92181396484375 +6634 0.18353271484375 +6635 0.917724609375 +6636 0.18267822265625 +6637 0.91351318359375 +6638 0.18182373046875 +6639 0.9091796875 +6640 0.180938720703125 +6641 0.90478515625 +6642 0.180023193359375 +6643 0.9002685546875 +6644 0.179107666015625 +6645 0.895660400390625 +6646 0.17816162109375 +6647 0.890960693359375 +6648 0.177215576171875 +6649 0.88616943359375 +6650 0.176239013671875 +6651 0.881256103515625 +6652 0.17523193359375 +6653 0.876251220703125 +6654 0.174224853515625 +6655 0.871185302734375 +6656 0.145477294921875 +6657 0.865997314453125 +6658 0.14459228515625 +6659 0.860687255859375 +6660 0.1436767578125 +6661 0.855316162109375 +6662 0.14276123046875 +6663 0.849853515625 +6664 0.141845703125 +6665 0.84429931640625 +6666 0.140869140625 +6667 0.838623046875 +6668 0.139923095703125 +6669 0.8328857421875 +6670 0.138916015625 +6671 0.8270263671875 +6672 0.137939453125 +6673 0.82110595703125 +6674 0.136932373046875 +6675 0.815093994140625 +6676 0.135894775390625 +6677 0.808990478515625 +6678 0.134857177734375 +6679 0.802764892578125 +6680 0.1337890625 +6681 0.796478271484375 +6682 0.132720947265625 +6683 0.790130615234375 +6684 0.13165283203125 +6685 0.783660888671875 +6686 0.13055419921875 +6687 0.777099609375 +6688 0.129425048828125 +6689 0.770477294921875 +6690 0.1282958984375 +6691 0.763763427734375 +6692 0.127166748046875 +6693 0.7569580078125 +6694 0.126007080078125 +6695 0.75006103515625 +6696 0.12481689453125 +6697 0.74310302734375 +6698 0.1236572265625 +6699 0.736053466796875 +6700 0.1224365234375 +6701 0.72894287109375 +6702 0.121246337890625 +6703 0.721710205078125 +6704 0.120025634765625 +6705 0.714447021484375 +6706 0.1187744140625 +6707 0.707061767578125 +6708 0.117523193359375 +6709 0.699615478515625 +6710 0.11627197265625 +6711 0.692108154296875 +6712 0.114990234375 +6713 0.68450927734375 +6714 0.11370849609375 +6715 0.676849365234375 +6716 0.112396240234375 +6717 0.669097900390625 +6718 0.111083984375 +6719 0.661285400390625 +6720 0.1097412109375 +6721 0.65338134765625 +6722 0.108428955078125 +6723 0.645416259765625 +6724 0.1070556640625 +6725 0.63739013671875 +6726 0.105712890625 +6727 0.6292724609375 +6728 0.104339599609375 +6729 0.621124267578125 +6730 0.10296630859375 +6731 0.612884521484375 +6732 0.1015625 +6733 0.60455322265625 +6734 0.10015869140625 +6735 0.59619140625 +6736 0.098724365234375 +6737 0.587738037109375 +6738 0.0972900390625 +6739 0.579254150390625 +6740 0.095855712890625 +6741 0.5706787109375 +6742 0.09442138671875 +6743 0.562042236328125 +6744 0.09295654296875 +6745 0.5533447265625 +6746 0.09149169921875 +6747 0.54461669921875 +6748 0.089996337890625 +6749 0.535797119140625 +6750 0.0885009765625 +6751 0.52691650390625 +6752 0.087005615234375 +6753 0.51800537109375 +6754 0.08551025390625 +6755 0.509002685546875 +6756 0.083984375 +6757 0.499969482421875 +6758 0.08245849609375 +6759 0.490875244140625 +6760 0.080902099609375 +6761 0.481719970703125 +6762 0.079376220703125 +6763 0.4725341796875 +6764 0.07781982421875 +6765 0.4632568359375 +6766 0.076263427734375 +6767 0.453948974609375 +6768 0.074676513671875 +6769 0.444610595703125 +6770 0.073089599609375 +6771 0.435211181640625 +6772 0.071502685546875 +6773 0.425750732421875 +6774 0.069915771484375 +6775 0.416259765625 +6776 0.06829833984375 +6777 0.406707763671875 +6778 0.06671142578125 +6779 0.397125244140625 +6780 0.065093994140625 +6781 0.387481689453125 +6782 0.063446044921875 +6783 0.3778076171875 +6784 0.06182861328125 +6785 0.36810302734375 +6786 0.0601806640625 +6787 0.35833740234375 +6788 0.05853271484375 +6789 0.348541259765625 +6790 0.056884765625 +6791 0.338714599609375 +6792 0.05523681640625 +6793 0.328826904296875 +6794 0.053558349609375 +6795 0.318939208984375 +6796 0.051910400390625 +6797 0.308990478515625 +6798 0.05023193359375 +6799 0.29901123046875 +6800 0.048553466796875 +6801 0.28900146484375 +6802 0.046844482421875 +6803 0.278961181640625 +6804 0.045166015625 +6805 0.268890380859375 +6806 0.04345703125 +6807 0.2587890625 +6808 0.041748046875 +6809 0.2486572265625 +6810 0.040069580078125 +6811 0.238525390625 +6812 0.038360595703125 +6813 0.22833251953125 +6814 0.03662109375 +6815 0.218109130859375 +6816 0.034912109375 +6817 0.2078857421875 +6818 0.033172607421875 +6819 0.1976318359375 +6820 0.031463623046875 +6821 0.187347412109375 +6822 0.02972412109375 +6823 0.17706298828125 +6824 0.027984619140625 +6825 0.166748046875 +6826 0.026275634765625 +6827 0.156402587890625 +6828 0.0245361328125 +6829 0.14605712890625 +6830 0.02276611328125 +6831 0.13568115234375 +6832 0.021026611328125 +6833 0.12530517578125 +6834 0.019287109375 +6835 0.11492919921875 +6836 0.017547607421875 +6837 0.104522705078125 +6838 0.015777587890625 +6839 0.094085693359375 +6840 0.0140380859375 +6841 0.083648681640625 +6842 0.012298583984375 +6843 0.073211669921875 +6844 0.010528564453125 +6845 0.062774658203125 +6846 0.008758544921875 +6847 0.05230712890625 +6848 0.00701904296875 +6849 0.0418701171875 +6850 0.0052490234375 +6851 0.031402587890625 +6852 0.003509521484375 +6853 0.02093505859375 +6854 0.001739501953125 +6855 0.010467529296875 +6856 0.0 +6857 0.0 +6858 -0.001739501953125 +6859 -0.010467529296875 +6860 -0.003509521484375 +6861 -0.02093505859375 +6862 -0.0052490234375 +6863 -0.031402587890625 +6864 -0.00701904296875 +6865 -0.0418701171875 +6866 -0.008758544921875 +6867 -0.05230712890625 +6868 -0.010528564453125 +6869 -0.062774658203125 +6870 -0.012298583984375 +6871 -0.073211669921875 +6872 -0.0140380859375 +6873 -0.083648681640625 +6874 -0.015777587890625 +6875 -0.094085693359375 +6876 -0.017547607421875 +6877 -0.104522705078125 +6878 -0.019287109375 +6879 -0.11492919921875 +6880 -0.021026611328125 +6881 -0.12530517578125 +6882 -0.02276611328125 +6883 -0.13568115234375 +6884 -0.0245361328125 +6885 -0.14605712890625 +6886 -0.026275634765625 +6887 -0.156402587890625 +6888 -0.027984619140625 +6889 -0.166748046875 +6890 -0.02972412109375 +6891 -0.17706298828125 +6892 -0.031463623046875 +6893 -0.187347412109375 +6894 -0.033172607421875 +6895 -0.1976318359375 +6896 -0.034912109375 +6897 -0.2078857421875 +6898 -0.03662109375 +6899 -0.218109130859375 +6900 -0.038360595703125 +6901 -0.22833251953125 +6902 -0.040069580078125 +6903 -0.238525390625 +6904 -0.041748046875 +6905 -0.2486572265625 +6906 -0.04345703125 +6907 -0.2587890625 +6908 -0.045166015625 +6909 -0.268890380859375 +6910 -0.046844482421875 +6911 -0.278961181640625 +6912 -0.039276123046875 +6913 -0.28900146484375 +6914 -0.0406494140625 +6915 -0.29901123046875 +6916 -0.0419921875 +6917 -0.308990478515625 +6918 -0.043365478515625 +6919 -0.318939208984375 +6920 -0.044708251953125 +6921 -0.328826904296875 +6922 -0.046051025390625 +6923 -0.338714599609375 +6924 -0.047393798828125 +6925 -0.348541259765625 +6926 -0.0487060546875 +6927 -0.35833740234375 +6928 -0.050048828125 +6929 -0.36810302734375 +6930 -0.051361083984375 +6931 -0.3778076171875 +6932 -0.05267333984375 +6933 -0.387481689453125 +6934 -0.053985595703125 +6935 -0.397125244140625 +6936 -0.0552978515625 +6937 -0.406707763671875 +6938 -0.05657958984375 +6939 -0.416259765625 +6940 -0.057891845703125 +6941 -0.425750732421875 +6942 -0.059173583984375 +6943 -0.435211181640625 +6944 -0.060455322265625 +6945 -0.444610595703125 +6946 -0.06170654296875 +6947 -0.453948974609375 +6948 -0.06298828125 +6949 -0.4632568359375 +6950 -0.064239501953125 +6951 -0.4725341796875 +6952 -0.06549072265625 +6953 -0.481719970703125 +6954 -0.066741943359375 +6955 -0.490875244140625 +6956 -0.067962646484375 +6957 -0.499969482421875 +6958 -0.0692138671875 +6959 -0.509002685546875 +6960 -0.0704345703125 +6961 -0.51800537109375 +6962 -0.0716552734375 +6963 -0.52691650390625 +6964 -0.072845458984375 +6965 -0.535797119140625 +6966 -0.07403564453125 +6967 -0.54461669921875 +6968 -0.075225830078125 +6969 -0.5533447265625 +6970 -0.076416015625 +6971 -0.562042236328125 +6972 -0.077606201171875 +6973 -0.5706787109375 +6974 -0.078765869140625 +6975 -0.579254150390625 +6976 -0.079925537109375 +6977 -0.587738037109375 +6978 -0.0810546875 +6979 -0.59619140625 +6980 -0.082183837890625 +6981 -0.60455322265625 +6982 -0.083343505859375 +6983 -0.612884521484375 +6984 -0.084442138671875 +6985 -0.621124267578125 +6986 -0.0855712890625 +6987 -0.6292724609375 +6988 -0.086669921875 +6989 -0.63739013671875 +6990 -0.0877685546875 +6991 -0.645416259765625 +6992 -0.088836669921875 +6993 -0.65338134765625 +6994 -0.08990478515625 +6995 -0.661285400390625 +6996 -0.090972900390625 +6997 -0.669097900390625 +6998 -0.092041015625 +6999 -0.676849365234375 +7000 -0.09307861328125 +7001 -0.68450927734375 +7002 -0.0941162109375 +7003 -0.692108154296875 +7004 -0.095123291015625 +7005 -0.699615478515625 +7006 -0.09613037109375 +7007 -0.707061767578125 +7008 -0.097137451171875 +7009 -0.714447021484375 +7010 -0.09814453125 +7011 -0.721710205078125 +7012 -0.09912109375 +7013 -0.72894287109375 +7014 -0.100067138671875 +7015 -0.736053466796875 +7016 -0.101043701171875 +7017 -0.74310302734375 +7018 -0.10198974609375 +7019 -0.75006103515625 +7020 -0.102935791015625 +7021 -0.7569580078125 +7022 -0.103851318359375 +7023 -0.763763427734375 +7024 -0.104766845703125 +7025 -0.770477294921875 +7026 -0.10565185546875 +7027 -0.777099609375 +7028 -0.1065673828125 +7029 -0.783660888671875 +7030 -0.107421875 +7031 -0.790130615234375 +7032 -0.108306884765625 +7033 -0.796478271484375 +7034 -0.109161376953125 +7035 -0.802764892578125 +7036 -0.1099853515625 +7037 -0.808990478515625 +7038 -0.11083984375 +7039 -0.815093994140625 +7040 -0.11163330078125 +7041 -0.82110595703125 +7042 -0.112457275390625 +7043 -0.8270263671875 +7044 -0.113250732421875 +7045 -0.8328857421875 +7046 -0.114044189453125 +7047 -0.838623046875 +7048 -0.11480712890625 +7049 -0.84429931640625 +7050 -0.115570068359375 +7051 -0.849853515625 +7052 -0.116302490234375 +7053 -0.855316162109375 +7054 -0.117034912109375 +7055 -0.860687255859375 +7056 -0.117767333984375 +7057 -0.865997314453125 +7058 -0.11846923828125 +7059 -0.871185302734375 +7060 -0.119140625 +7061 -0.876251220703125 +7062 -0.11981201171875 +7063 -0.881256103515625 +7064 -0.1204833984375 +7065 -0.88616943359375 +7066 -0.12115478515625 +7067 -0.890960693359375 +7068 -0.121795654296875 +7069 -0.895660400390625 +7070 -0.122406005859375 +7071 -0.9002685546875 +7072 -0.123016357421875 +7073 -0.90478515625 +7074 -0.123626708984375 +7075 -0.9091796875 +7076 -0.12420654296875 +7077 -0.91351318359375 +7078 -0.124786376953125 +7079 -0.917724609375 +7080 -0.125335693359375 +7081 -0.92181396484375 +7082 -0.125885009765625 +7083 -0.92584228515625 +7084 -0.12640380859375 +7085 -0.929718017578125 +7086 -0.126922607421875 +7087 -0.93353271484375 +7088 -0.12744140625 +7089 -0.937225341796875 +7090 -0.1279296875 +7091 -0.940826416015625 +7092 -0.12841796875 +7093 -0.9443359375 +7094 -0.128875732421875 +7095 -0.947723388671875 +7096 -0.129302978515625 +7097 -0.951019287109375 +7098 -0.1297607421875 +7099 -0.954193115234375 +7100 -0.130157470703125 +7101 -0.957275390625 +7102 -0.13055419921875 +7103 -0.960235595703125 +7104 -0.130950927734375 +7105 -0.963104248046875 +7106 -0.13134765625 +7107 -0.96588134765625 +7108 -0.131683349609375 +7109 -0.968536376953125 +7110 -0.132049560546875 +7111 -0.971099853515625 +7112 -0.13238525390625 +7113 -0.973541259765625 +7114 -0.1326904296875 +7115 -0.975860595703125 +7116 -0.13299560546875 +7117 -0.97808837890625 +7118 -0.13330078125 +7119 -0.980224609375 +7120 -0.133544921875 +7121 -0.98223876953125 +7122 -0.133819580078125 +7123 -0.984161376953125 +7124 -0.134063720703125 +7125 -0.9859619140625 +7126 -0.134307861328125 +7127 -0.987640380859375 +7128 -0.134521484375 +7129 -0.989227294921875 +7130 -0.13470458984375 +7131 -0.990692138671875 +7132 -0.1348876953125 +7133 -0.9920654296875 +7134 -0.13507080078125 +7135 -0.993316650390625 +7136 -0.135223388671875 +7137 -0.994476318359375 +7138 -0.1353759765625 +7139 -0.995513916015625 +7140 -0.135498046875 +7141 -0.9964599609375 +7142 -0.1356201171875 +7143 -0.997283935546875 +7144 -0.135711669921875 +7145 -0.99798583984375 +7146 -0.135772705078125 +7147 -0.99859619140625 +7148 -0.1358642578125 +7149 -0.999114990234375 +7150 -0.135894775390625 +7151 -0.999481201171875 +7152 -0.13592529296875 +7153 -0.999755859375 +7154 -0.135955810546875 +7155 -0.99993896484375 +7156 -0.135986328125 +7157 -1.0 +7158 -0.135955810546875 +7159 -0.99993896484375 +7160 -0.13592529296875 +7161 -0.999755859375 +7162 -0.135894775390625 +7163 -0.999481201171875 +7164 -0.1358642578125 +7165 -0.999114990234375 +7166 -0.135772705078125 +7167 -0.99859619140625 +7168 -0.103790283203125 +7169 -0.99798583984375 +7170 -0.10369873046875 +7171 -0.997283935546875 +7172 -0.1036376953125 +7173 -0.9964599609375 +7174 -0.103515625 +7175 -0.995513916015625 +7176 -0.103424072265625 +7177 -0.994476318359375 +7178 -0.103302001953125 +7179 -0.993316650390625 +7180 -0.103179931640625 +7181 -0.9920654296875 +7182 -0.10302734375 +7183 -0.990692138671875 +7184 -0.102874755859375 +7185 -0.989227294921875 +7186 -0.102691650390625 +7187 -0.987640380859375 +7188 -0.1025390625 +7189 -0.9859619140625 +7190 -0.10235595703125 +7191 -0.984161376953125 +7192 -0.102142333984375 +7193 -0.98223876953125 +7194 -0.1019287109375 +7195 -0.980224609375 +7196 -0.101715087890625 +7197 -0.97808837890625 +7198 -0.101470947265625 +7199 -0.975860595703125 +7200 -0.101226806640625 +7201 -0.973541259765625 +7202 -0.100982666015625 +7203 -0.971099853515625 +7204 -0.1007080078125 +7205 -0.968536376953125 +7206 -0.100433349609375 +7207 -0.96588134765625 +7208 -0.10015869140625 +7209 -0.963104248046875 +7210 -0.099853515625 +7211 -0.960235595703125 +7212 -0.09954833984375 +7213 -0.957275390625 +7214 -0.099212646484375 +7215 -0.954193115234375 +7216 -0.098907470703125 +7217 -0.951019287109375 +7218 -0.098541259765625 +7219 -0.947723388671875 +7220 -0.09820556640625 +7221 -0.9443359375 +7222 -0.09783935546875 +7223 -0.940826416015625 +7224 -0.09747314453125 +7225 -0.937225341796875 +7226 -0.097076416015625 +7227 -0.93353271484375 +7228 -0.0966796875 +7229 -0.929718017578125 +7230 -0.096282958984375 +7231 -0.92584228515625 +7232 -0.095855712890625 +7233 -0.92181396484375 +7234 -0.095428466796875 +7235 -0.917724609375 +7236 -0.095001220703125 +7237 -0.91351318359375 +7238 -0.09454345703125 +7239 -0.9091796875 +7240 -0.094085693359375 +7241 -0.90478515625 +7242 -0.0936279296875 +7243 -0.9002685546875 +7244 -0.0931396484375 +7245 -0.895660400390625 +7246 -0.0926513671875 +7247 -0.890960693359375 +7248 -0.0921630859375 +7249 -0.88616943359375 +7250 -0.091644287109375 +7251 -0.881256103515625 +7252 -0.09112548828125 +7253 -0.876251220703125 +7254 -0.090606689453125 +7255 -0.871185302734375 +7256 -0.090057373046875 +7257 -0.865997314453125 +7258 -0.089508056640625 +7259 -0.860687255859375 +7260 -0.088958740234375 +7261 -0.855316162109375 +7262 -0.08837890625 +7263 -0.849853515625 +7264 -0.087799072265625 +7265 -0.84429931640625 +7266 -0.08721923828125 +7267 -0.838623046875 +7268 -0.08660888671875 +7269 -0.8328857421875 +7270 -0.08599853515625 +7271 -0.8270263671875 +7272 -0.08538818359375 +7273 -0.82110595703125 +7274 -0.084747314453125 +7275 -0.815093994140625 +7276 -0.084136962890625 +7277 -0.808990478515625 +7278 -0.083465576171875 +7279 -0.802764892578125 +7280 -0.08282470703125 +7281 -0.796478271484375 +7282 -0.0821533203125 +7283 -0.790130615234375 +7284 -0.08148193359375 +7285 -0.783660888671875 +7286 -0.080810546875 +7287 -0.777099609375 +7288 -0.080108642578125 +7289 -0.770477294921875 +7290 -0.07940673828125 +7291 -0.763763427734375 +7292 -0.078704833984375 +7293 -0.7569580078125 +7294 -0.0780029296875 +7295 -0.75006103515625 +7296 -0.0772705078125 +7297 -0.74310302734375 +7298 -0.0765380859375 +7299 -0.736053466796875 +7300 -0.0758056640625 +7301 -0.72894287109375 +7302 -0.075042724609375 +7303 -0.721710205078125 +7304 -0.07427978515625 +7305 -0.714447021484375 +7306 -0.073516845703125 +7307 -0.707061767578125 +7308 -0.07275390625 +7309 -0.699615478515625 +7310 -0.07196044921875 +7311 -0.692108154296875 +7312 -0.0711669921875 +7313 -0.68450927734375 +7314 -0.07037353515625 +7315 -0.676849365234375 +7316 -0.069580078125 +7317 -0.669097900390625 +7318 -0.068756103515625 +7319 -0.661285400390625 +7320 -0.06793212890625 +7321 -0.65338134765625 +7322 -0.067108154296875 +7323 -0.645416259765625 +7324 -0.0662841796875 +7325 -0.63739013671875 +7326 -0.0654296875 +7327 -0.6292724609375 +7328 -0.0645751953125 +7329 -0.621124267578125 +7330 -0.063720703125 +7331 -0.612884521484375 +7332 -0.0628662109375 +7333 -0.60455322265625 +7334 -0.061981201171875 +7335 -0.59619140625 +7336 -0.061126708984375 +7337 -0.587738037109375 +7338 -0.06024169921875 +7339 -0.579254150390625 +7340 -0.059326171875 +7341 -0.5706787109375 +7342 -0.058441162109375 +7343 -0.562042236328125 +7344 -0.057525634765625 +7345 -0.5533447265625 +7346 -0.056640625 +7347 -0.54461669921875 +7348 -0.05572509765625 +7349 -0.535797119140625 +7350 -0.054779052734375 +7351 -0.52691650390625 +7352 -0.053863525390625 +7353 -0.51800537109375 +7354 -0.05291748046875 +7355 -0.509002685546875 +7356 -0.051971435546875 +7357 -0.499969482421875 +7358 -0.051025390625 +7359 -0.490875244140625 +7360 -0.050079345703125 +7361 -0.481719970703125 +7362 -0.04913330078125 +7363 -0.4725341796875 +7364 -0.04815673828125 +7365 -0.4632568359375 +7366 -0.047210693359375 +7367 -0.453948974609375 +7368 -0.046234130859375 +7369 -0.444610595703125 +7370 -0.045257568359375 +7371 -0.435211181640625 +7372 -0.044281005859375 +7373 -0.425750732421875 +7374 -0.04327392578125 +7375 -0.416259765625 +7376 -0.04229736328125 +7377 -0.406707763671875 +7378 -0.041290283203125 +7379 -0.397125244140625 +7380 -0.040283203125 +7381 -0.387481689453125 +7382 -0.039276123046875 +7383 -0.3778076171875 +7384 -0.03826904296875 +7385 -0.36810302734375 +7386 -0.037261962890625 +7387 -0.35833740234375 +7388 -0.036224365234375 +7389 -0.348541259765625 +7390 -0.03521728515625 +7391 -0.338714599609375 +7392 -0.0341796875 +7393 -0.328826904296875 +7394 -0.03314208984375 +7395 -0.318939208984375 +7396 -0.032135009765625 +7397 -0.308990478515625 +7398 -0.031097412109375 +7399 -0.29901123046875 +7400 -0.030029296875 +7401 -0.28900146484375 +7402 -0.02899169921875 +7403 -0.278961181640625 +7404 -0.0279541015625 +7405 -0.268890380859375 +7406 -0.026885986328125 +7407 -0.2587890625 +7408 -0.025848388671875 +7409 -0.2486572265625 +7410 -0.0247802734375 +7411 -0.238525390625 +7412 -0.02374267578125 +7413 -0.22833251953125 +7414 -0.022674560546875 +7415 -0.218109130859375 +7416 -0.0216064453125 +7417 -0.2078857421875 +7418 -0.020538330078125 +7419 -0.1976318359375 +7420 -0.01947021484375 +7421 -0.187347412109375 +7422 -0.018402099609375 +7423 -0.17706298828125 +7424 -0.01666259765625 +7425 -0.166748046875 +7426 -0.015625 +7427 -0.156402587890625 +7428 -0.01458740234375 +7429 -0.14605712890625 +7430 -0.0135498046875 +7431 -0.13568115234375 +7432 -0.01251220703125 +7433 -0.12530517578125 +7434 -0.011474609375 +7435 -0.11492919921875 +7436 -0.01043701171875 +7437 -0.104522705078125 +7438 -0.0093994140625 +7439 -0.094085693359375 +7440 -0.00836181640625 +7441 -0.083648681640625 +7442 -0.007293701171875 +7443 -0.073211669921875 +7444 -0.006256103515625 +7445 -0.062774658203125 +7446 -0.005218505859375 +7447 -0.05230712890625 +7448 -0.004180908203125 +7449 -0.0418701171875 +7450 -0.00311279296875 +7451 -0.031402587890625 +7452 -0.0020751953125 +7453 -0.02093505859375 +7454 -0.00103759765625 +7455 -0.010467529296875 +7456 0.0 +7457 0.0 +7458 0.000732421875 +7459 0.010467529296875 +7460 0.001495361328125 +7461 0.02093505859375 +7462 0.00225830078125 +7463 0.031402587890625 +7464 0.00299072265625 +7465 0.0418701171875 +7466 0.003753662109375 +7467 0.05230712890625 +7468 0.0045166015625 +7469 0.062774658203125 +7470 0.0052490234375 +7471 0.073211669921875 +7472 0.006011962890625 +7473 0.083648681640625 +7474 0.006744384765625 +7475 0.094085693359375 +7476 0.00750732421875 +7477 0.104522705078125 +7478 0.008270263671875 +7479 0.11492919921875 +7480 0.009002685546875 +7481 0.12530517578125 +7482 0.009765625 +7483 0.13568115234375 +7484 0.010498046875 +7485 0.14605712890625 +7486 0.01123046875 +7487 0.156402587890625 +7488 0.011993408203125 +7489 0.166748046875 +7490 0.012725830078125 +7491 0.17706298828125 +7492 0.013458251953125 +7493 0.187347412109375 +7494 0.01422119140625 +7495 0.1976318359375 +7496 0.01495361328125 +7497 0.2078857421875 +7498 0.01568603515625 +7499 0.218109130859375 +7500 0.01641845703125 +7501 0.22833251953125 +7502 0.01715087890625 +7503 0.238525390625 +7504 0.01788330078125 +7505 0.2486572265625 +7506 0.01861572265625 +7507 0.2587890625 +7508 0.01934814453125 +7509 0.268890380859375 +7510 0.02008056640625 +7511 0.278961181640625 +7512 0.020782470703125 +7513 0.28900146484375 +7514 0.021514892578125 +7515 0.29901123046875 +7516 0.022216796875 +7517 0.308990478515625 +7518 0.02294921875 +7519 0.318939208984375 +7520 0.023651123046875 +7521 0.328826904296875 +7522 0.024383544921875 +7523 0.338714599609375 +7524 0.02508544921875 +7525 0.348541259765625 +7526 0.025787353515625 +7527 0.35833740234375 +7528 0.0264892578125 +7529 0.36810302734375 +7530 0.027191162109375 +7531 0.3778076171875 +7532 0.02789306640625 +7533 0.387481689453125 +7534 0.028564453125 +7535 0.397125244140625 +7536 0.029266357421875 +7537 0.406707763671875 +7538 0.029937744140625 +7539 0.416259765625 +7540 0.0306396484375 +7541 0.425750732421875 +7542 0.03131103515625 +7543 0.435211181640625 +7544 0.031982421875 +7545 0.444610595703125 +7546 0.03265380859375 +7547 0.453948974609375 +7548 0.0333251953125 +7549 0.4632568359375 +7550 0.03399658203125 +7551 0.4725341796875 +7552 0.03466796875 +7553 0.481719970703125 +7554 0.03533935546875 +7555 0.490875244140625 +7556 0.035980224609375 +7557 0.499969482421875 +7558 0.03662109375 +7559 0.509002685546875 +7560 0.03729248046875 +7561 0.51800537109375 +7562 0.037933349609375 +7563 0.52691650390625 +7564 0.038543701171875 +7565 0.535797119140625 +7566 0.0391845703125 +7567 0.54461669921875 +7568 0.039825439453125 +7569 0.5533447265625 +7570 0.040435791015625 +7571 0.562042236328125 +7572 0.04107666015625 +7573 0.5706787109375 +7574 0.04168701171875 +7575 0.579254150390625 +7576 0.04229736328125 +7577 0.587738037109375 +7578 0.04290771484375 +7579 0.59619140625 +7580 0.04351806640625 +7581 0.60455322265625 +7582 0.044097900390625 +7583 0.612884521484375 +7584 0.044708251953125 +7585 0.621124267578125 +7586 0.0452880859375 +7587 0.6292724609375 +7588 0.045867919921875 +7589 0.63739013671875 +7590 0.04644775390625 +7591 0.645416259765625 +7592 0.047027587890625 +7593 0.65338134765625 +7594 0.047607421875 +7595 0.661285400390625 +7596 0.04815673828125 +7597 0.669097900390625 +7598 0.0487060546875 +7599 0.676849365234375 +7600 0.04925537109375 +7601 0.68450927734375 +7602 0.0498046875 +7603 0.692108154296875 +7604 0.05035400390625 +7605 0.699615478515625 +7606 0.0509033203125 +7607 0.707061767578125 +7608 0.051422119140625 +7609 0.714447021484375 +7610 0.05194091796875 +7611 0.721710205078125 +7612 0.052459716796875 +7613 0.72894287109375 +7614 0.052978515625 +7615 0.736053466796875 +7616 0.053497314453125 +7617 0.74310302734375 +7618 0.053985595703125 +7619 0.75006103515625 +7620 0.054473876953125 +7621 0.7569580078125 +7622 0.054962158203125 +7623 0.763763427734375 +7624 0.055450439453125 +7625 0.770477294921875 +7626 0.055938720703125 +7627 0.777099609375 +7628 0.056396484375 +7629 0.783660888671875 +7630 0.056854248046875 +7631 0.790130615234375 +7632 0.05731201171875 +7633 0.796478271484375 +7634 0.057769775390625 +7635 0.802764892578125 +7636 0.0582275390625 +7637 0.808990478515625 +7638 0.05865478515625 +7639 0.815093994140625 +7640 0.059112548828125 +7641 0.82110595703125 +7642 0.059539794921875 +7643 0.8270263671875 +7644 0.0599365234375 +7645 0.8328857421875 +7646 0.06036376953125 +7647 0.838623046875 +7648 0.060760498046875 +7649 0.84429931640625 +7650 0.0611572265625 +7651 0.849853515625 +7652 0.061553955078125 +7653 0.855316162109375 +7654 0.06195068359375 +7655 0.860687255859375 +7656 0.06231689453125 +7657 0.865997314453125 +7658 0.062713623046875 +7659 0.871185302734375 +7660 0.063079833984375 +7661 0.876251220703125 +7662 0.06341552734375 +7663 0.881256103515625 +7664 0.06378173828125 +7665 0.88616943359375 +7666 0.064117431640625 +7667 0.890960693359375 +7668 0.064453125 +7669 0.895660400390625 +7670 0.064788818359375 +7671 0.9002685546875 +7672 0.06512451171875 +7673 0.90478515625 +7674 0.0654296875 +7675 0.9091796875 +7676 0.065765380859375 +7677 0.91351318359375 +7678 0.0660400390625 +7679 0.917724609375 +7680 0.036865234375 +7681 0.92181396484375 +7682 0.037017822265625 +7683 0.92584228515625 +7684 0.03717041015625 +7685 0.929718017578125 +7686 0.037322998046875 +7687 0.93353271484375 +7688 0.0374755859375 +7689 0.937225341796875 +7690 0.037628173828125 +7691 0.940826416015625 +7692 0.03778076171875 +7693 0.9443359375 +7694 0.03790283203125 +7695 0.947723388671875 +7696 0.03802490234375 +7697 0.951019287109375 +7698 0.03814697265625 +7699 0.954193115234375 +7700 0.038299560546875 +7701 0.957275390625 +7702 0.03839111328125 +7703 0.960235595703125 +7704 0.03851318359375 +7705 0.963104248046875 +7706 0.03863525390625 +7707 0.96588134765625 +7708 0.038726806640625 +7709 0.968536376953125 +7710 0.038848876953125 +7711 0.971099853515625 +7712 0.0389404296875 +7713 0.973541259765625 +7714 0.039031982421875 +7715 0.975860595703125 +7716 0.03912353515625 +7717 0.97808837890625 +7718 0.039215087890625 +7719 0.980224609375 +7720 0.039276123046875 +7721 0.98223876953125 +7722 0.03936767578125 +7723 0.984161376953125 +7724 0.0394287109375 +7725 0.9859619140625 +7726 0.03948974609375 +7727 0.987640380859375 +7728 0.03955078125 +7729 0.989227294921875 +7730 0.03961181640625 +7731 0.990692138671875 +7732 0.0396728515625 +7733 0.9920654296875 +7734 0.03973388671875 +7735 0.993316650390625 +7736 0.039764404296875 +7737 0.994476318359375 +7738 0.039825439453125 +7739 0.995513916015625 +7740 0.03985595703125 +7741 0.9964599609375 +7742 0.039886474609375 +7743 0.997283935546875 +7744 0.0399169921875 +7745 0.99798583984375 +7746 0.039947509765625 +7747 0.99859619140625 +7748 0.039947509765625 +7749 0.999114990234375 +7750 0.03997802734375 +7751 0.999481201171875 +7752 0.03997802734375 +7753 0.999755859375 +7754 0.03997802734375 +7755 0.99993896484375 +7756 0.040008544921875 +7757 0.999969482421875 +7758 0.03997802734375 +7759 0.99993896484375 +7760 0.03997802734375 +7761 0.999755859375 +7762 0.03997802734375 +7763 0.999481201171875 +7764 0.039947509765625 +7765 0.999114990234375 +7766 0.039947509765625 +7767 0.99859619140625 +7768 0.0399169921875 +7769 0.99798583984375 +7770 0.039886474609375 +7771 0.997283935546875 +7772 0.03985595703125 +7773 0.9964599609375 +7774 0.039825439453125 +7775 0.995513916015625 +7776 0.039764404296875 +7777 0.994476318359375 +7778 0.03973388671875 +7779 0.993316650390625 +7780 0.0396728515625 +7781 0.9920654296875 +7782 0.03961181640625 +7783 0.990692138671875 +7784 0.03955078125 +7785 0.989227294921875 +7786 0.03948974609375 +7787 0.987640380859375 +7788 0.0394287109375 +7789 0.9859619140625 +7790 0.03936767578125 +7791 0.984161376953125 +7792 0.039276123046875 +7793 0.98223876953125 +7794 0.039215087890625 +7795 0.980224609375 +7796 0.03912353515625 +7797 0.97808837890625 +7798 0.039031982421875 +7799 0.975860595703125 +7800 0.0389404296875 +7801 0.973541259765625 +7802 0.038848876953125 +7803 0.971099853515625 +7804 0.038726806640625 +7805 0.968536376953125 +7806 0.03863525390625 +7807 0.96588134765625 +7808 0.03851318359375 +7809 0.963104248046875 +7810 0.03839111328125 +7811 0.960235595703125 +7812 0.038299560546875 +7813 0.957275390625 +7814 0.03814697265625 +7815 0.954193115234375 +7816 0.03802490234375 +7817 0.951019287109375 +7818 0.03790283203125 +7819 0.947723388671875 +7820 0.03778076171875 +7821 0.9443359375 +7822 0.037628173828125 +7823 0.940826416015625 +7824 0.0374755859375 +7825 0.937225341796875 +7826 0.037322998046875 +7827 0.93353271484375 +7828 0.03717041015625 +7829 0.929718017578125 +7830 0.037017822265625 +7831 0.92584228515625 +7832 0.036865234375 +7833 0.92181396484375 +7834 0.036712646484375 +7835 0.917724609375 +7836 0.036529541015625 +7837 0.91351318359375 +7838 0.036346435546875 +7839 0.9091796875 +7840 0.03619384765625 +7841 0.90478515625 +7842 0.0360107421875 +7843 0.9002685546875 +7844 0.03582763671875 +7845 0.895660400390625 +7846 0.03564453125 +7847 0.890960693359375 +7848 0.035430908203125 +7849 0.88616943359375 +7850 0.035247802734375 +7851 0.881256103515625 +7852 0.0350341796875 +7853 0.876251220703125 +7854 0.03485107421875 +7855 0.871185302734375 +7856 0.034637451171875 +7857 0.865997314453125 +7858 0.034423828125 +7859 0.860687255859375 +7860 0.034210205078125 +7861 0.855316162109375 +7862 0.03399658203125 +7863 0.849853515625 +7864 0.03375244140625 +7865 0.84429931640625 +7866 0.033538818359375 +7867 0.838623046875 +7868 0.033294677734375 +7869 0.8328857421875 +7870 0.0330810546875 +7871 0.8270263671875 +7872 0.0328369140625 +7873 0.82110595703125 +7874 0.0325927734375 +7875 0.815093994140625 +7876 0.0323486328125 +7877 0.808990478515625 +7878 0.0321044921875 +7879 0.802764892578125 +7880 0.0318603515625 +7881 0.796478271484375 +7882 0.031585693359375 +7883 0.790130615234375 +7884 0.031341552734375 +7885 0.783660888671875 +7886 0.03106689453125 +7887 0.777099609375 +7888 0.03082275390625 +7889 0.770477294921875 +7890 0.030548095703125 +7891 0.763763427734375 +7892 0.0302734375 +7893 0.7569580078125 +7894 0.029998779296875 +7895 0.75006103515625 +7896 0.02972412109375 +7897 0.74310302734375 +7898 0.0294189453125 +7899 0.736053466796875 +7900 0.029144287109375 +7901 0.72894287109375 +7902 0.02886962890625 +7903 0.721710205078125 +7904 0.028564453125 +7905 0.714447021484375 +7906 0.02825927734375 +7907 0.707061767578125 +7908 0.027984619140625 +7909 0.699615478515625 +7910 0.027679443359375 +7911 0.692108154296875 +7912 0.027374267578125 +7913 0.68450927734375 +7914 0.027069091796875 +7915 0.676849365234375 +7916 0.026763916015625 +7917 0.669097900390625 +7918 0.02642822265625 +7919 0.661285400390625 +7920 0.026123046875 +7921 0.65338134765625 +7922 0.02581787109375 +7923 0.645416259765625 +7924 0.025482177734375 +7925 0.63739013671875 +7926 0.025177001953125 +7927 0.6292724609375 +7928 0.02484130859375 +7929 0.621124267578125 +7930 0.024505615234375 +7931 0.612884521484375 +7932 0.024169921875 +7933 0.60455322265625 +7934 0.023834228515625 +7935 0.59619140625 +7936 0.004669189453125 +7937 0.587738037109375 +7938 0.004608154296875 +7939 0.579254150390625 +7940 0.004547119140625 +7941 0.5706787109375 +7942 0.004486083984375 +7943 0.562042236328125 +7944 0.00439453125 +7945 0.5533447265625 +7946 0.00433349609375 +7947 0.54461669921875 +7948 0.0042724609375 +7949 0.535797119140625 +7950 0.00421142578125 +7951 0.52691650390625 +7952 0.004119873046875 +7953 0.51800537109375 +7954 0.004058837890625 +7955 0.509002685546875 +7956 0.00396728515625 +7957 0.499969482421875 +7958 0.00390625 +7959 0.490875244140625 +7960 0.00384521484375 +7961 0.481719970703125 +7962 0.003753662109375 +7963 0.4725341796875 +7964 0.003692626953125 +7965 0.4632568359375 +7966 0.00360107421875 +7967 0.453948974609375 +7968 0.0035400390625 +7969 0.444610595703125 +7970 0.00347900390625 +7971 0.435211181640625 +7972 0.003387451171875 +7973 0.425750732421875 +7974 0.003326416015625 +7975 0.416259765625 +7976 0.00323486328125 +7977 0.406707763671875 +7978 0.003173828125 +7979 0.397125244140625 +7980 0.003082275390625 +7981 0.387481689453125 +7982 0.00299072265625 +7983 0.3778076171875 +7984 0.0029296875 +7985 0.36810302734375 +7986 0.002838134765625 +7987 0.35833740234375 +7988 0.002777099609375 +7989 0.348541259765625 +7990 0.002685546875 +7991 0.338714599609375 +7992 0.00262451171875 +7993 0.328826904296875 +7994 0.002532958984375 +7995 0.318939208984375 +7996 0.00244140625 +7997 0.308990478515625 +7998 0.00238037109375 +7999 0.29901123046875 +8000 0.002288818359375 +8001 0.28900146484375 +8002 0.002227783203125 +8003 0.278961181640625 +8004 0.00213623046875 +8005 0.268890380859375 +8006 0.002044677734375 +8007 0.2587890625 +8008 0.001983642578125 +8009 0.2486572265625 +8010 0.00189208984375 +8011 0.238525390625 +8012 0.001800537109375 +8013 0.22833251953125 +8014 0.001739501953125 +8015 0.218109130859375 +8016 0.00164794921875 +8017 0.2078857421875 +8018 0.001556396484375 +8019 0.1976318359375 +8020 0.001495361328125 +8021 0.187347412109375 +8022 0.00140380859375 +8023 0.17706298828125 +8024 0.001312255859375 +8025 0.166748046875 +8026 0.001220703125 +8027 0.156402587890625 +8028 0.00115966796875 +8029 0.14605712890625 +8030 0.001068115234375 +8031 0.13568115234375 +8032 0.0009765625 +8033 0.12530517578125 +8034 0.00091552734375 +8035 0.11492919921875 +8036 0.000823974609375 +8037 0.104522705078125 +8038 0.000732421875 +8039 0.094085693359375 +8040 0.000640869140625 +8041 0.083648681640625 +8042 0.000579833984375 +8043 0.073211669921875 +8044 0.00048828125 +8045 0.062774658203125 +8046 0.000396728515625 +8047 0.05230712890625 +8048 0.00030517578125 +8049 0.0418701171875 +8050 0.000244140625 +8051 0.031402587890625 +8052 0.000152587890625 +8053 0.02093505859375 +8054 6.103515625e-05 +8055 0.010467529296875 +8056 0.0 +8057 0.0 +8058 -6.103515625e-05 +8059 -0.010467529296875 +8060 -0.000152587890625 +8061 -0.02093505859375 +8062 -0.000244140625 +8063 -0.031402587890625 +8064 -0.00030517578125 +8065 -0.0418701171875 +8066 -0.000396728515625 +8067 -0.05230712890625 +8068 -0.00048828125 +8069 -0.062774658203125 +8070 -0.000579833984375 +8071 -0.073211669921875 +8072 -0.000640869140625 +8073 -0.083648681640625 +8074 -0.000732421875 +8075 -0.094085693359375 +8076 -0.000823974609375 +8077 -0.104522705078125 +8078 -0.00091552734375 +8079 -0.11492919921875 +8080 -0.0009765625 +8081 -0.12530517578125 +8082 -0.001068115234375 +8083 -0.13568115234375 +8084 -0.00115966796875 +8085 -0.14605712890625 +8086 -0.001220703125 +8087 -0.156402587890625 +8088 -0.001312255859375 +8089 -0.166748046875 +8090 -0.00140380859375 +8091 -0.17706298828125 +8092 -0.001495361328125 +8093 -0.187347412109375 +8094 -0.001556396484375 +8095 -0.1976318359375 +8096 -0.00164794921875 +8097 -0.2078857421875 +8098 -0.001739501953125 +8099 -0.218109130859375 +8100 -0.001800537109375 +8101 -0.22833251953125 +8102 -0.00189208984375 +8103 -0.238525390625 +8104 -0.001983642578125 +8105 -0.2486572265625 +8106 -0.002044677734375 +8107 -0.2587890625 +8108 -0.00213623046875 +8109 -0.268890380859375 +8110 -0.002227783203125 +8111 -0.278961181640625 +8112 -0.002288818359375 +8113 -0.28900146484375 +8114 -0.00238037109375 +8115 -0.29901123046875 +8116 -0.00244140625 +8117 -0.308990478515625 +8118 -0.002532958984375 +8119 -0.318939208984375 +8120 -0.00262451171875 +8121 -0.328826904296875 +8122 -0.002685546875 +8123 -0.338714599609375 +8124 -0.002777099609375 +8125 -0.348541259765625 +8126 -0.002838134765625 +8127 -0.35833740234375 +8128 -0.0029296875 +8129 -0.36810302734375 +8130 -0.00299072265625 +8131 -0.3778076171875 +8132 -0.003082275390625 +8133 -0.387481689453125 +8134 -0.003173828125 +8135 -0.397125244140625 +8136 -0.00323486328125 +8137 -0.406707763671875 +8138 -0.003326416015625 +8139 -0.416259765625 +8140 -0.003387451171875 +8141 -0.425750732421875 +8142 -0.00347900390625 +8143 -0.435211181640625 +8144 -0.0035400390625 +8145 -0.444610595703125 +8146 -0.00360107421875 +8147 -0.453948974609375 +8148 -0.003692626953125 +8149 -0.4632568359375 +8150 -0.003753662109375 +8151 -0.4725341796875 +8152 -0.00384521484375 +8153 -0.481719970703125 +8154 -0.00390625 +8155 -0.490875244140625 +8156 -0.00396728515625 +8157 -0.499969482421875 +8158 -0.004058837890625 +8159 -0.509002685546875 +8160 -0.004119873046875 +8161 -0.51800537109375 +8162 -0.00421142578125 +8163 -0.52691650390625 +8164 -0.0042724609375 +8165 -0.535797119140625 +8166 -0.00433349609375 +8167 -0.54461669921875 +8168 -0.00439453125 +8169 -0.5533447265625 +8170 -0.004486083984375 +8171 -0.562042236328125 +8172 -0.004547119140625 +8173 -0.5706787109375 +8174 -0.004608154296875 +8175 -0.579254150390625 +8176 -0.004669189453125 +8177 -0.587738037109375 +8178 -0.0047607421875 +8179 -0.59619140625 +8180 -0.00482177734375 +8181 -0.60455322265625 +8182 -0.0048828125 +8183 -0.612884521484375 +8184 -0.00494384765625 +8185 -0.621124267578125 +8186 -0.0050048828125 +8187 -0.6292724609375 +8188 -0.005096435546875 +8189 -0.63739013671875 +8190 -0.005157470703125 +8191 -0.645416259765625 +8192 -0.015655517578125 +8193 -0.65338134765625 +8194 -0.015838623046875 +8195 -0.661285400390625 +8196 -0.016021728515625 +8197 -0.669097900390625 +8198 -0.0162353515625 +8199 -0.676849365234375 +8200 -0.01641845703125 +8201 -0.68450927734375 +8202 -0.0166015625 +8203 -0.692108154296875 +8204 -0.016754150390625 +8205 -0.699615478515625 +8206 -0.016937255859375 +8207 -0.707061767578125 +8208 -0.017120361328125 +8209 -0.714447021484375 +8210 -0.017303466796875 +8211 -0.721710205078125 +8212 -0.0174560546875 +8213 -0.72894287109375 +8214 -0.01763916015625 +8215 -0.736053466796875 +8216 -0.017822265625 +8217 -0.74310302734375 +8218 -0.017974853515625 +8219 -0.75006103515625 +8220 -0.01812744140625 +8221 -0.7569580078125 +8222 -0.018310546875 +8223 -0.763763427734375 +8224 -0.018463134765625 +8225 -0.770477294921875 +8226 -0.01861572265625 +8227 -0.777099609375 +8228 -0.018768310546875 +8229 -0.783660888671875 +8230 -0.018951416015625 +8231 -0.790130615234375 +8232 -0.01910400390625 +8233 -0.796478271484375 +8234 -0.01922607421875 +8235 -0.802764892578125 +8236 -0.019378662109375 +8237 -0.808990478515625 +8238 -0.01953125 +8239 -0.815093994140625 +8240 -0.019683837890625 +8241 -0.82110595703125 +8242 -0.01983642578125 +8243 -0.8270263671875 +8244 -0.01995849609375 +8245 -0.8328857421875 +8246 -0.020111083984375 +8247 -0.838623046875 +8248 -0.020233154296875 +8249 -0.84429931640625 +8250 -0.0203857421875 +8251 -0.849853515625 +8252 -0.0205078125 +8253 -0.855316162109375 +8254 -0.0206298828125 +8255 -0.860687255859375 +8256 -0.020751953125 +8257 -0.865997314453125 +8258 -0.0208740234375 +8259 -0.871185302734375 +8260 -0.02099609375 +8261 -0.876251220703125 +8262 -0.0211181640625 +8263 -0.881256103515625 +8264 -0.021240234375 +8265 -0.88616943359375 +8266 -0.0213623046875 +8267 -0.890960693359375 +8268 -0.021484375 +8269 -0.895660400390625 +8270 -0.021575927734375 +8271 -0.9002685546875 +8272 -0.021697998046875 +8273 -0.90478515625 +8274 -0.02178955078125 +8275 -0.9091796875 +8276 -0.02191162109375 +8277 -0.91351318359375 +8278 -0.022003173828125 +8279 -0.917724609375 +8280 -0.0220947265625 +8281 -0.92181396484375 +8282 -0.022186279296875 +8283 -0.92584228515625 +8284 -0.02227783203125 +8285 -0.929718017578125 +8286 -0.022369384765625 +8287 -0.93353271484375 +8288 -0.0224609375 +8289 -0.937225341796875 +8290 -0.022552490234375 +8291 -0.940826416015625 +8292 -0.02264404296875 +8293 -0.9443359375 +8294 -0.022705078125 +8295 -0.947723388671875 +8296 -0.022796630859375 +8297 -0.951019287109375 +8298 -0.02288818359375 +8299 -0.954193115234375 +8300 -0.02294921875 +8301 -0.957275390625 +8302 -0.02301025390625 +8303 -0.960235595703125 +8304 -0.023101806640625 +8305 -0.963104248046875 +8306 -0.023162841796875 +8307 -0.96588134765625 +8308 -0.023223876953125 +8309 -0.968536376953125 +8310 -0.023284912109375 +8311 -0.971099853515625 +8312 -0.023345947265625 +8313 -0.973541259765625 +8314 -0.023406982421875 +8315 -0.975860595703125 +8316 -0.0234375 +8317 -0.97808837890625 +8318 -0.02349853515625 +8319 -0.980224609375 +8320 -0.0235595703125 +8321 -0.98223876953125 +8322 -0.023590087890625 +8323 -0.984161376953125 +8324 -0.02362060546875 +8325 -0.9859619140625 +8326 -0.023681640625 +8327 -0.987640380859375 +8328 -0.023712158203125 +8329 -0.989227294921875 +8330 -0.02374267578125 +8331 -0.990692138671875 +8332 -0.023773193359375 +8333 -0.9920654296875 +8334 -0.0238037109375 +8335 -0.993316650390625 +8336 -0.023834228515625 +8337 -0.994476318359375 +8338 -0.02386474609375 +8339 -0.995513916015625 +8340 -0.023895263671875 +8341 -0.9964599609375 +8342 -0.023895263671875 +8343 -0.997283935546875 +8344 -0.02392578125 +8345 -0.99798583984375 +8346 -0.02392578125 +8347 -0.99859619140625 +8348 -0.023956298828125 +8349 -0.999114990234375 +8350 -0.023956298828125 +8351 -0.999481201171875 +8352 -0.023956298828125 +8353 -0.999755859375 +8354 -0.023956298828125 +8355 -0.99993896484375 +8356 -0.02398681640625 +8357 -1.0 +8358 -0.023956298828125 +8359 -0.99993896484375 +8360 -0.023956298828125 +8361 -0.999755859375 +8362 -0.023956298828125 +8363 -0.999481201171875 +8364 -0.023956298828125 +8365 -0.999114990234375 +8366 -0.02392578125 +8367 -0.99859619140625 +8368 -0.02392578125 +8369 -0.99798583984375 +8370 -0.023895263671875 +8371 -0.997283935546875 +8372 -0.023895263671875 +8373 -0.9964599609375 +8374 -0.02386474609375 +8375 -0.995513916015625 +8376 -0.023834228515625 +8377 -0.994476318359375 +8378 -0.0238037109375 +8379 -0.993316650390625 +8380 -0.023773193359375 +8381 -0.9920654296875 +8382 -0.02374267578125 +8383 -0.990692138671875 +8384 -0.023712158203125 +8385 -0.989227294921875 +8386 -0.023681640625 +8387 -0.987640380859375 +8388 -0.02362060546875 +8389 -0.9859619140625 +8390 -0.023590087890625 +8391 -0.984161376953125 +8392 -0.0235595703125 +8393 -0.98223876953125 +8394 -0.02349853515625 +8395 -0.980224609375 +8396 -0.0234375 +8397 -0.97808837890625 +8398 -0.023406982421875 +8399 -0.975860595703125 +8400 -0.023345947265625 +8401 -0.973541259765625 +8402 -0.023284912109375 +8403 -0.971099853515625 +8404 -0.023223876953125 +8405 -0.968536376953125 +8406 -0.023162841796875 +8407 -0.96588134765625 +8408 -0.023101806640625 +8409 -0.963104248046875 +8410 -0.02301025390625 +8411 -0.960235595703125 +8412 -0.02294921875 +8413 -0.957275390625 +8414 -0.02288818359375 +8415 -0.954193115234375 +8416 -0.022796630859375 +8417 -0.951019287109375 +8418 -0.022705078125 +8419 -0.947723388671875 +8420 -0.02264404296875 +8421 -0.9443359375 +8422 -0.022552490234375 +8423 -0.940826416015625 +8424 -0.0224609375 +8425 -0.937225341796875 +8426 -0.022369384765625 +8427 -0.93353271484375 +8428 -0.02227783203125 +8429 -0.929718017578125 +8430 -0.022186279296875 +8431 -0.92584228515625 +8432 -0.0220947265625 +8433 -0.92181396484375 +8434 -0.022003173828125 +8435 -0.917724609375 +8436 -0.02191162109375 +8437 -0.91351318359375 +8438 -0.02178955078125 +8439 -0.9091796875 +8440 -0.021697998046875 +8441 -0.90478515625 +8442 -0.021575927734375 +8443 -0.9002685546875 +8444 -0.021484375 +8445 -0.895660400390625 +8446 -0.0213623046875 +8447 -0.890960693359375 +8448 -0.044281005859375 +8449 -0.88616943359375 +8450 -0.044036865234375 +8451 -0.881256103515625 +8452 -0.043792724609375 +8453 -0.876251220703125 +8454 -0.043548583984375 +8455 -0.871185302734375 +8456 -0.04327392578125 +8457 -0.865997314453125 +8458 -0.042999267578125 +8459 -0.860687255859375 +8460 -0.042755126953125 +8461 -0.855316162109375 +8462 -0.04248046875 +8463 -0.849853515625 +8464 -0.042205810546875 +8465 -0.84429931640625 +8466 -0.041900634765625 +8467 -0.838623046875 +8468 -0.0416259765625 +8469 -0.8328857421875 +8470 -0.04132080078125 +8471 -0.8270263671875 +8472 -0.041046142578125 +8473 -0.82110595703125 +8474 -0.040740966796875 +8475 -0.815093994140625 +8476 -0.040435791015625 +8477 -0.808990478515625 +8478 -0.04010009765625 +8479 -0.802764892578125 +8480 -0.039794921875 +8481 -0.796478271484375 +8482 -0.03948974609375 +8483 -0.790130615234375 +8484 -0.039154052734375 +8485 -0.783660888671875 +8486 -0.038818359375 +8487 -0.777099609375 +8488 -0.03851318359375 +8489 -0.770477294921875 +8490 -0.038177490234375 +8491 -0.763763427734375 +8492 -0.037811279296875 +8493 -0.7569580078125 +8494 -0.0374755859375 +8495 -0.75006103515625 +8496 -0.037139892578125 +8497 -0.74310302734375 +8498 -0.036773681640625 +8499 -0.736053466796875 +8500 -0.03643798828125 +8501 -0.72894287109375 +8502 -0.03607177734375 +8503 -0.721710205078125 +8504 -0.03570556640625 +8505 -0.714447021484375 +8506 -0.03533935546875 +8507 -0.707061767578125 +8508 -0.03497314453125 +8509 -0.699615478515625 +8510 -0.034576416015625 +8511 -0.692108154296875 +8512 -0.034210205078125 +8513 -0.68450927734375 +8514 -0.0338134765625 +8515 -0.676849365234375 +8516 -0.033447265625 +8517 -0.669097900390625 +8518 -0.033050537109375 +8519 -0.661285400390625 +8520 -0.03265380859375 +8521 -0.65338134765625 +8522 -0.032257080078125 +8523 -0.645416259765625 +8524 -0.0318603515625 +8525 -0.63739013671875 +8526 -0.03143310546875 +8527 -0.6292724609375 +8528 -0.031036376953125 +8529 -0.621124267578125 +8530 -0.030609130859375 +8531 -0.612884521484375 +8532 -0.03021240234375 +8533 -0.60455322265625 +8534 -0.02978515625 +8535 -0.59619140625 +8536 -0.02935791015625 +8537 -0.587738037109375 +8538 -0.0289306640625 +8539 -0.579254150390625 +8540 -0.02850341796875 +8541 -0.5706787109375 +8542 -0.028076171875 +8543 -0.562042236328125 +8544 -0.02764892578125 +8545 -0.5533447265625 +8546 -0.0272216796875 +8547 -0.54461669921875 +8548 -0.026763916015625 +8549 -0.535797119140625 +8550 -0.026336669921875 +8551 -0.52691650390625 +8552 -0.02587890625 +8553 -0.51800537109375 +8554 -0.025421142578125 +8555 -0.509002685546875 +8556 -0.02496337890625 +8557 -0.499969482421875 +8558 -0.0245361328125 +8559 -0.490875244140625 +8560 -0.024078369140625 +8561 -0.481719970703125 +8562 -0.02362060546875 +8563 -0.4725341796875 +8564 -0.02313232421875 +8565 -0.4632568359375 +8566 -0.022674560546875 +8567 -0.453948974609375 +8568 -0.022216796875 +8569 -0.444610595703125 +8570 -0.021728515625 +8571 -0.435211181640625 +8572 -0.021270751953125 +8573 -0.425750732421875 +8574 -0.020782470703125 +8575 -0.416259765625 +8576 -0.02032470703125 +8577 -0.406707763671875 +8578 -0.01983642578125 +8579 -0.397125244140625 +8580 -0.01934814453125 +8581 -0.387481689453125 +8582 -0.01885986328125 +8583 -0.3778076171875 +8584 -0.01837158203125 +8585 -0.36810302734375 +8586 -0.01788330078125 +8587 -0.35833740234375 +8588 -0.01739501953125 +8589 -0.348541259765625 +8590 -0.01690673828125 +8591 -0.338714599609375 +8592 -0.01641845703125 +8593 -0.328826904296875 +8594 -0.01593017578125 +8595 -0.318939208984375 +8596 -0.01544189453125 +8597 -0.308990478515625 +8598 -0.014923095703125 +8599 -0.29901123046875 +8600 -0.014434814453125 +8601 -0.28900146484375 +8602 -0.013916015625 +8603 -0.278961181640625 +8604 -0.013427734375 +8605 -0.268890380859375 +8606 -0.012908935546875 +8607 -0.2587890625 +8608 -0.012420654296875 +8609 -0.2486572265625 +8610 -0.01190185546875 +8611 -0.238525390625 +8612 -0.01141357421875 +8613 -0.22833251953125 +8614 -0.010894775390625 +8615 -0.218109130859375 +8616 -0.0103759765625 +8617 -0.2078857421875 +8618 -0.009857177734375 +8619 -0.1976318359375 +8620 -0.00933837890625 +8621 -0.187347412109375 +8622 -0.00885009765625 +8623 -0.17706298828125 +8624 -0.008331298828125 +8625 -0.166748046875 +8626 -0.0078125 +8627 -0.156402587890625 +8628 -0.007293701171875 +8629 -0.14605712890625 +8630 -0.00677490234375 +8631 -0.13568115234375 +8632 -0.006256103515625 +8633 -0.12530517578125 +8634 -0.0057373046875 +8635 -0.11492919921875 +8636 -0.005218505859375 +8637 -0.104522705078125 +8638 -0.00469970703125 +8639 -0.094085693359375 +8640 -0.004180908203125 +8641 -0.083648681640625 +8642 -0.003631591796875 +8643 -0.073211669921875 +8644 -0.00311279296875 +8645 -0.062774658203125 +8646 -0.002593994140625 +8647 -0.05230712890625 +8648 -0.0020751953125 +8649 -0.0418701171875 +8650 -0.001556396484375 +8651 -0.031402587890625 +8652 -0.00103759765625 +8653 -0.02093505859375 +8654 -0.000518798828125 +8655 -0.010467529296875 +8656 0.0 +8657 0.0 +8658 0.000579833984375 +8659 0.010467529296875 +8660 0.00115966796875 +8661 0.02093505859375 +8662 0.001739501953125 +8663 0.031402587890625 +8664 0.0023193359375 +8665 0.0418701171875 +8666 0.002899169921875 +8667 0.05230712890625 +8668 0.003509521484375 +8669 0.062774658203125 +8670 0.00408935546875 +8671 0.073211669921875 +8672 0.004669189453125 +8673 0.083648681640625 +8674 0.0052490234375 +8675 0.094085693359375 +8676 0.005828857421875 +8677 0.104522705078125 +8678 0.00640869140625 +8679 0.11492919921875 +8680 0.006988525390625 +8681 0.12530517578125 +8682 0.007568359375 +8683 0.13568115234375 +8684 0.0081787109375 +8685 0.14605712890625 +8686 0.008758544921875 +8687 0.156402587890625 +8688 0.009307861328125 +8689 0.166748046875 +8690 0.0098876953125 +8691 0.17706298828125 +8692 0.010467529296875 +8693 0.187347412109375 +8694 0.01104736328125 +8695 0.1976318359375 +8696 0.011627197265625 +8697 0.2078857421875 +8698 0.01220703125 +8699 0.218109130859375 +8700 0.012786865234375 +8701 0.22833251953125 +8702 0.013336181640625 +8703 0.238525390625 +8704 0.0218505859375 +8705 0.2486572265625 +8706 0.02276611328125 +8707 0.2587890625 +8708 0.023651123046875 +8709 0.268890380859375 +8710 0.0245361328125 +8711 0.278961181640625 +8712 0.025421142578125 +8713 0.28900146484375 +8714 0.02630615234375 +8715 0.29901123046875 +8716 0.02716064453125 +8717 0.308990478515625 +8718 0.028045654296875 +8719 0.318939208984375 +8720 0.0289306640625 +8721 0.328826904296875 +8722 0.02978515625 +8723 0.338714599609375 +8724 0.0306396484375 +8725 0.348541259765625 +8726 0.031524658203125 +8727 0.35833740234375 +8728 0.032379150390625 +8729 0.36810302734375 +8730 0.033233642578125 +8731 0.3778076171875 +8732 0.034088134765625 +8733 0.387481689453125 +8734 0.034912109375 +8735 0.397125244140625 +8736 0.0357666015625 +8737 0.406707763671875 +8738 0.03662109375 +8739 0.416259765625 +8740 0.037445068359375 +8741 0.425750732421875 +8742 0.03826904296875 +8743 0.435211181640625 +8744 0.039093017578125 +8745 0.444610595703125 +8746 0.0399169921875 +8747 0.453948974609375 +8748 0.040740966796875 +8749 0.4632568359375 +8750 0.04156494140625 +8751 0.4725341796875 +8752 0.0423583984375 +8753 0.481719970703125 +8754 0.043182373046875 +8755 0.490875244140625 +8756 0.043975830078125 +8757 0.499969482421875 +8758 0.044769287109375 +8759 0.509002685546875 +8760 0.045562744140625 +8761 0.51800537109375 +8762 0.046356201171875 +8763 0.52691650390625 +8764 0.047119140625 +8765 0.535797119140625 +8766 0.04791259765625 +8767 0.54461669921875 +8768 0.048675537109375 +8769 0.5533447265625 +8770 0.0494384765625 +8771 0.562042236328125 +8772 0.050201416015625 +8773 0.5706787109375 +8774 0.05096435546875 +8775 0.579254150390625 +8776 0.05169677734375 +8777 0.587738037109375 +8778 0.05242919921875 +8779 0.59619140625 +8780 0.05316162109375 +8781 0.60455322265625 +8782 0.053924560546875 +8783 0.612884521484375 +8784 0.05462646484375 +8785 0.621124267578125 +8786 0.05535888671875 +8787 0.6292724609375 +8788 0.056060791015625 +8789 0.63739013671875 +8790 0.0567626953125 +8791 0.645416259765625 +8792 0.057464599609375 +8793 0.65338134765625 +8794 0.05816650390625 +8795 0.661285400390625 +8796 0.058868408203125 +8797 0.669097900390625 +8798 0.059539794921875 +8799 0.676849365234375 +8800 0.060211181640625 +8801 0.68450927734375 +8802 0.060882568359375 +8803 0.692108154296875 +8804 0.061553955078125 +8805 0.699615478515625 +8806 0.06219482421875 +8807 0.707061767578125 +8808 0.062835693359375 +8809 0.714447021484375 +8810 0.0634765625 +8811 0.721710205078125 +8812 0.064117431640625 +8813 0.72894287109375 +8814 0.06475830078125 +8815 0.736053466796875 +8816 0.06536865234375 +8817 0.74310302734375 +8818 0.06597900390625 +8819 0.75006103515625 +8820 0.06658935546875 +8821 0.7569580078125 +8822 0.067169189453125 +8823 0.763763427734375 +8824 0.067779541015625 +8825 0.770477294921875 +8826 0.068359375 +8827 0.777099609375 +8828 0.068939208984375 +8829 0.783660888671875 +8830 0.06951904296875 +8831 0.790130615234375 +8832 0.070068359375 +8833 0.796478271484375 +8834 0.07061767578125 +8835 0.802764892578125 +8836 0.0711669921875 +8837 0.808990478515625 +8838 0.071685791015625 +8839 0.815093994140625 +8840 0.072235107421875 +8841 0.82110595703125 +8842 0.07275390625 +8843 0.8270263671875 +8844 0.073272705078125 +8845 0.8328857421875 +8846 0.073760986328125 +8847 0.838623046875 +8848 0.07427978515625 +8849 0.84429931640625 +8850 0.07476806640625 +8851 0.849853515625 +8852 0.075225830078125 +8853 0.855316162109375 +8854 0.075714111328125 +8855 0.860687255859375 +8856 0.076171875 +8857 0.865997314453125 +8858 0.076629638671875 +8859 0.871185302734375 +8860 0.07708740234375 +8861 0.876251220703125 +8862 0.0775146484375 +8863 0.881256103515625 +8864 0.07794189453125 +8865 0.88616943359375 +8866 0.078369140625 +8867 0.890960693359375 +8868 0.07879638671875 +8869 0.895660400390625 +8870 0.079193115234375 +8871 0.9002685546875 +8872 0.07958984375 +8873 0.90478515625 +8874 0.079986572265625 +8875 0.9091796875 +8876 0.080352783203125 +8877 0.91351318359375 +8878 0.080718994140625 +8879 0.917724609375 +8880 0.081085205078125 +8881 0.92181396484375 +8882 0.081451416015625 +8883 0.92584228515625 +8884 0.081787109375 +8885 0.929718017578125 +8886 0.082122802734375 +8887 0.93353271484375 +8888 0.08245849609375 +8889 0.937225341796875 +8890 0.082763671875 +8891 0.940826416015625 +8892 0.08306884765625 +8893 0.9443359375 +8894 0.0833740234375 +8895 0.947723388671875 +8896 0.083648681640625 +8897 0.951019287109375 +8898 0.083953857421875 +8899 0.954193115234375 +8900 0.084197998046875 +8901 0.957275390625 +8902 0.08447265625 +8903 0.960235595703125 +8904 0.084716796875 +8905 0.963104248046875 +8906 0.0849609375 +8907 0.96588134765625 +8908 0.085205078125 +8909 0.968536376953125 +8910 0.085418701171875 +8911 0.971099853515625 +8912 0.08563232421875 +8913 0.973541259765625 +8914 0.085845947265625 +8915 0.975860595703125 +8916 0.086029052734375 +8917 0.97808837890625 +8918 0.08624267578125 +8919 0.980224609375 +8920 0.086395263671875 +8921 0.98223876953125 +8922 0.086578369140625 +8923 0.984161376953125 +8924 0.08673095703125 +8925 0.9859619140625 +8926 0.086883544921875 +8927 0.987640380859375 +8928 0.0870361328125 +8929 0.989227294921875 +8930 0.087158203125 +8931 0.990692138671875 +8932 0.0872802734375 +8933 0.9920654296875 +8934 0.087371826171875 +8935 0.993316650390625 +8936 0.087493896484375 +8937 0.994476318359375 +8938 0.08758544921875 +8939 0.995513916015625 +8940 0.087646484375 +8941 0.9964599609375 +8942 0.087738037109375 +8943 0.997283935546875 +8944 0.087799072265625 +8945 0.99798583984375 +8946 0.087860107421875 +8947 0.99859619140625 +8948 0.087890625 +8949 0.999114990234375 +8950 0.087921142578125 +8951 0.999481201171875 +8952 0.08795166015625 +8953 0.999755859375 +8954 0.08795166015625 +8955 0.99993896484375 +8956 0.087982177734375 +8957 0.999969482421875 +8958 0.08795166015625 +8959 0.99993896484375 +8960 0.119964599609375 +8961 0.999755859375 +8962 0.119903564453125 +8963 0.999481201171875 +8964 0.119873046875 +8965 0.999114990234375 +8966 0.11981201171875 +8967 0.99859619140625 +8968 0.1197509765625 +8969 0.99798583984375 +8970 0.119659423828125 +8971 0.997283935546875 +8972 0.11956787109375 +8973 0.9964599609375 +8974 0.11944580078125 +8975 0.995513916015625 +8976 0.11932373046875 +8977 0.994476318359375 +8978 0.119171142578125 +8979 0.993316650390625 +8980 0.1190185546875 +8981 0.9920654296875 +8982 0.118865966796875 +8983 0.990692138671875 +8984 0.118682861328125 +8985 0.989227294921875 +8986 0.118499755859375 +8987 0.987640380859375 +8988 0.1182861328125 +8989 0.9859619140625 +8990 0.118072509765625 +8991 0.984161376953125 +8992 0.11785888671875 +8993 0.98223876953125 +8994 0.11761474609375 +8995 0.980224609375 +8996 0.117340087890625 +8997 0.97808837890625 +8998 0.117095947265625 +8999 0.975860595703125 +9000 0.1168212890625 +9001 0.973541259765625 +9002 0.11651611328125 +9003 0.971099853515625 +9004 0.1162109375 +9005 0.968536376953125 +9006 0.115875244140625 +9007 0.96588134765625 +9008 0.115570068359375 +9009 0.963104248046875 +9010 0.115203857421875 +9011 0.960235595703125 +9012 0.1148681640625 +9013 0.957275390625 +9014 0.114501953125 +9015 0.954193115234375 +9016 0.114105224609375 +9017 0.951019287109375 +9018 0.11370849609375 +9019 0.947723388671875 +9020 0.113311767578125 +9021 0.9443359375 +9022 0.112884521484375 +9023 0.940826416015625 +9024 0.112457275390625 +9025 0.937225341796875 +9026 0.11199951171875 +9027 0.93353271484375 +9028 0.111541748046875 +9029 0.929718017578125 +9030 0.111083984375 +9031 0.92584228515625 +9032 0.110595703125 +9033 0.92181396484375 +9034 0.110107421875 +9035 0.917724609375 +9036 0.109619140625 +9037 0.91351318359375 +9038 0.109100341796875 +9039 0.9091796875 +9040 0.108551025390625 +9041 0.90478515625 +9042 0.108001708984375 +9043 0.9002685546875 +9044 0.107452392578125 +9045 0.895660400390625 +9046 0.106903076171875 +9047 0.890960693359375 +9048 0.1063232421875 +9049 0.88616943359375 +9050 0.105743408203125 +9051 0.881256103515625 +9052 0.105133056640625 +9053 0.876251220703125 +9054 0.104522705078125 +9055 0.871185302734375 +9056 0.103912353515625 +9057 0.865997314453125 +9058 0.103271484375 +9059 0.860687255859375 +9060 0.102630615234375 +9061 0.855316162109375 +9062 0.101959228515625 +9063 0.849853515625 +9064 0.101287841796875 +9065 0.84429931640625 +9066 0.100616455078125 +9067 0.838623046875 +9068 0.099945068359375 +9069 0.8328857421875 +9070 0.099212646484375 +9071 0.8270263671875 +9072 0.0985107421875 +9073 0.82110595703125 +9074 0.097808837890625 +9075 0.815093994140625 +9076 0.097076416015625 +9077 0.808990478515625 +9078 0.0963134765625 +9079 0.802764892578125 +9080 0.095550537109375 +9081 0.796478271484375 +9082 0.09478759765625 +9083 0.790130615234375 +9084 0.094024658203125 +9085 0.783660888671875 +9086 0.093231201171875 +9087 0.777099609375 +9088 0.092437744140625 +9089 0.770477294921875 +9090 0.091644287109375 +9091 0.763763427734375 +9092 0.0908203125 +9093 0.7569580078125 +9094 0.089996337890625 +9095 0.75006103515625 +9096 0.089141845703125 +9097 0.74310302734375 +9098 0.08831787109375 +9099 0.736053466796875 +9100 0.08746337890625 +9101 0.72894287109375 +9102 0.086578369140625 +9103 0.721710205078125 +9104 0.085723876953125 +9105 0.714447021484375 +9106 0.0848388671875 +9107 0.707061767578125 +9108 0.08392333984375 +9109 0.699615478515625 +9110 0.083038330078125 +9111 0.692108154296875 +9112 0.082122802734375 +9113 0.68450927734375 +9114 0.081207275390625 +9115 0.676849365234375 +9116 0.08026123046875 +9117 0.669097900390625 +9118 0.079345703125 +9119 0.661285400390625 +9120 0.078399658203125 +9121 0.65338134765625 +9122 0.077423095703125 +9123 0.645416259765625 +9124 0.07647705078125 +9125 0.63739013671875 +9126 0.07550048828125 +9127 0.6292724609375 +9128 0.07452392578125 +9129 0.621124267578125 +9130 0.073516845703125 +9131 0.612884521484375 +9132 0.072540283203125 +9133 0.60455322265625 +9134 0.071533203125 +9135 0.59619140625 +9136 0.070526123046875 +9137 0.587738037109375 +9138 0.069488525390625 +9139 0.579254150390625 +9140 0.068450927734375 +9141 0.5706787109375 +9142 0.06744384765625 +9143 0.562042236328125 +9144 0.066375732421875 +9145 0.5533447265625 +9146 0.065338134765625 +9147 0.54461669921875 +9148 0.06427001953125 +9149 0.535797119140625 +9150 0.063201904296875 +9151 0.52691650390625 +9152 0.0621337890625 +9153 0.51800537109375 +9154 0.061065673828125 +9155 0.509002685546875 +9156 0.059967041015625 +9157 0.499969482421875 +9158 0.05889892578125 +9159 0.490875244140625 +9160 0.05780029296875 +9161 0.481719970703125 +9162 0.05670166015625 +9163 0.4725341796875 +9164 0.055572509765625 +9165 0.4632568359375 +9166 0.054443359375 +9167 0.453948974609375 +9168 0.0533447265625 +9169 0.444610595703125 +9170 0.052215576171875 +9171 0.435211181640625 +9172 0.05108642578125 +9173 0.425750732421875 +9174 0.0499267578125 +9175 0.416259765625 +9176 0.048797607421875 +9177 0.406707763671875 +9178 0.047637939453125 +9179 0.397125244140625 +9180 0.046478271484375 +9181 0.387481689453125 +9182 0.045318603515625 +9183 0.3778076171875 +9184 0.044158935546875 +9185 0.36810302734375 +9186 0.042999267578125 +9187 0.35833740234375 +9188 0.04180908203125 +9189 0.348541259765625 +9190 0.040618896484375 +9191 0.338714599609375 +9192 0.0394287109375 +9193 0.328826904296875 +9194 0.03826904296875 +9195 0.318939208984375 +9196 0.03704833984375 +9197 0.308990478515625 +9198 0.035858154296875 +9199 0.29901123046875 +9200 0.03466796875 +9201 0.28900146484375 +9202 0.033447265625 +9203 0.278961181640625 +9204 0.032257080078125 +9205 0.268890380859375 +9206 0.031036376953125 +9207 0.2587890625 +9208 0.029815673828125 +9209 0.2486572265625 +9210 0.028594970703125 +9211 0.238525390625 +9212 0.027374267578125 +9213 0.22833251953125 +9214 0.026153564453125 +9215 0.218109130859375 +9216 0.031585693359375 +9217 0.2078857421875 +9218 0.030029296875 +9219 0.1976318359375 +9220 0.028472900390625 +9221 0.187347412109375 +9222 0.026885986328125 +9223 0.17706298828125 +9224 0.02532958984375 +9225 0.166748046875 +9226 0.023773193359375 +9227 0.156402587890625 +9228 0.022186279296875 +9229 0.14605712890625 +9230 0.020599365234375 +9231 0.13568115234375 +9232 0.01904296875 +9233 0.12530517578125 +9234 0.0174560546875 +9235 0.11492919921875 +9236 0.015869140625 +9237 0.104522705078125 +9238 0.0142822265625 +9239 0.094085693359375 +9240 0.0126953125 +9241 0.083648681640625 +9242 0.0111083984375 +9243 0.073211669921875 +9244 0.009521484375 +9245 0.062774658203125 +9246 0.0079345703125 +9247 0.05230712890625 +9248 0.00634765625 +9249 0.0418701171875 +9250 0.0047607421875 +9251 0.031402587890625 +9252 0.003173828125 +9253 0.02093505859375 +9254 0.0015869140625 +9255 0.010467529296875 +9256 0.0 +9257 0.0 +9258 -0.0015869140625 +9259 -0.010467529296875 +9260 -0.003173828125 +9261 -0.02093505859375 +9262 -0.0047607421875 +9263 -0.031402587890625 +9264 -0.00634765625 +9265 -0.0418701171875 +9266 -0.0079345703125 +9267 -0.05230712890625 +9268 -0.009521484375 +9269 -0.062774658203125 +9270 -0.0111083984375 +9271 -0.073211669921875 +9272 -0.0126953125 +9273 -0.083648681640625 +9274 -0.0142822265625 +9275 -0.094085693359375 +9276 -0.015869140625 +9277 -0.104522705078125 +9278 -0.0174560546875 +9279 -0.11492919921875 +9280 -0.01904296875 +9281 -0.12530517578125 +9282 -0.020599365234375 +9283 -0.13568115234375 +9284 -0.022186279296875 +9285 -0.14605712890625 +9286 -0.023773193359375 +9287 -0.156402587890625 +9288 -0.02532958984375 +9289 -0.166748046875 +9290 -0.026885986328125 +9291 -0.17706298828125 +9292 -0.028472900390625 +9293 -0.187347412109375 +9294 -0.030029296875 +9295 -0.1976318359375 +9296 -0.031585693359375 +9297 -0.2078857421875 +9298 -0.03314208984375 +9299 -0.218109130859375 +9300 -0.034698486328125 +9301 -0.22833251953125 +9302 -0.0362548828125 +9303 -0.238525390625 +9304 -0.03778076171875 +9305 -0.2486572265625 +9306 -0.039337158203125 +9307 -0.2587890625 +9308 -0.040863037109375 +9309 -0.268890380859375 +9310 -0.042388916015625 +9311 -0.278961181640625 +9312 -0.043914794921875 +9313 -0.28900146484375 +9314 -0.045440673828125 +9315 -0.29901123046875 +9316 -0.046966552734375 +9317 -0.308990478515625 +9318 -0.0484619140625 +9319 -0.318939208984375 +9320 -0.049957275390625 +9321 -0.328826904296875 +9322 -0.051483154296875 +9323 -0.338714599609375 +9324 -0.052978515625 +9325 -0.348541259765625 +9326 -0.054443359375 +9327 -0.35833740234375 +9328 -0.055938720703125 +9329 -0.36810302734375 +9330 -0.057403564453125 +9331 -0.3778076171875 +9332 -0.05889892578125 +9333 -0.387481689453125 +9334 -0.06036376953125 +9335 -0.397125244140625 +9336 -0.061798095703125 +9337 -0.406707763671875 +9338 -0.063262939453125 +9339 -0.416259765625 +9340 -0.064697265625 +9341 -0.425750732421875 +9342 -0.066131591796875 +9343 -0.435211181640625 +9344 -0.06756591796875 +9345 -0.444610595703125 +9346 -0.069000244140625 +9347 -0.453948974609375 +9348 -0.070404052734375 +9349 -0.4632568359375 +9350 -0.071807861328125 +9351 -0.4725341796875 +9352 -0.073211669921875 +9353 -0.481719970703125 +9354 -0.074615478515625 +9355 -0.490875244140625 +9356 -0.07598876953125 +9357 -0.499969482421875 +9358 -0.077362060546875 +9359 -0.509002685546875 +9360 -0.0787353515625 +9361 -0.51800537109375 +9362 -0.080078125 +9363 -0.52691650390625 +9364 -0.0814208984375 +9365 -0.535797119140625 +9366 -0.082763671875 +9367 -0.54461669921875 +9368 -0.0841064453125 +9369 -0.5533447265625 +9370 -0.085418701171875 +9371 -0.562042236328125 +9372 -0.08673095703125 +9373 -0.5706787109375 +9374 -0.088043212890625 +9375 -0.579254150390625 +9376 -0.089324951171875 +9377 -0.587738037109375 +9378 -0.090606689453125 +9379 -0.59619140625 +9380 -0.091888427734375 +9381 -0.60455322265625 +9382 -0.0931396484375 +9383 -0.612884521484375 +9384 -0.094390869140625 +9385 -0.621124267578125 +9386 -0.09564208984375 +9387 -0.6292724609375 +9388 -0.09686279296875 +9389 -0.63739013671875 +9390 -0.09808349609375 +9391 -0.645416259765625 +9392 -0.09930419921875 +9393 -0.65338134765625 +9394 -0.100494384765625 +9395 -0.661285400390625 +9396 -0.1016845703125 +9397 -0.669097900390625 +9398 -0.102874755859375 +9399 -0.676849365234375 +9400 -0.104034423828125 +9401 -0.68450927734375 +9402 -0.105194091796875 +9403 -0.692108154296875 +9404 -0.1063232421875 +9405 -0.699615478515625 +9406 -0.107452392578125 +9407 -0.707061767578125 +9408 -0.10858154296875 +9409 -0.714447021484375 +9410 -0.10968017578125 +9411 -0.721710205078125 +9412 -0.11077880859375 +9413 -0.72894287109375 +9414 -0.11187744140625 +9415 -0.736053466796875 +9416 -0.112945556640625 +9417 -0.74310302734375 +9418 -0.114013671875 +9419 -0.75006103515625 +9420 -0.11505126953125 +9421 -0.7569580078125 +9422 -0.1160888671875 +9423 -0.763763427734375 +9424 -0.117095947265625 +9425 -0.770477294921875 +9426 -0.11810302734375 +9427 -0.777099609375 +9428 -0.119110107421875 +9429 -0.783660888671875 +9430 -0.120086669921875 +9431 -0.790130615234375 +9432 -0.121063232421875 +9433 -0.796478271484375 +9434 -0.12200927734375 +9435 -0.802764892578125 +9436 -0.122955322265625 +9437 -0.808990478515625 +9438 -0.1239013671875 +9439 -0.815093994140625 +9440 -0.12481689453125 +9441 -0.82110595703125 +9442 -0.125701904296875 +9443 -0.8270263671875 +9444 -0.1265869140625 +9445 -0.8328857421875 +9446 -0.127471923828125 +9447 -0.838623046875 +9448 -0.128326416015625 +9449 -0.84429931640625 +9450 -0.129180908203125 +9451 -0.849853515625 +9452 -0.1300048828125 +9453 -0.855316162109375 +9454 -0.130828857421875 +9455 -0.860687255859375 +9456 -0.131622314453125 +9457 -0.865997314453125 +9458 -0.132415771484375 +9459 -0.871185302734375 +9460 -0.1331787109375 +9461 -0.876251220703125 +9462 -0.133941650390625 +9463 -0.881256103515625 +9464 -0.13470458984375 +9465 -0.88616943359375 +9466 -0.13543701171875 +9467 -0.890960693359375 +9468 -0.136138916015625 +9469 -0.895660400390625 +9470 -0.1368408203125 +9471 -0.9002685546875 +9472 -0.166473388671875 +9473 -0.90478515625 +9474 -0.167266845703125 +9475 -0.9091796875 +9476 -0.168060302734375 +9477 -0.91351318359375 +9478 -0.168853759765625 +9479 -0.917724609375 +9480 -0.169586181640625 +9481 -0.92181396484375 +9482 -0.17034912109375 +9483 -0.92584228515625 +9484 -0.171051025390625 +9485 -0.929718017578125 +9486 -0.1717529296875 +9487 -0.93353271484375 +9488 -0.17242431640625 +9489 -0.937225341796875 +9490 -0.173095703125 +9491 -0.940826416015625 +9492 -0.173736572265625 +9493 -0.9443359375 +9494 -0.174346923828125 +9495 -0.947723388671875 +9496 -0.174957275390625 +9497 -0.951019287109375 +9498 -0.175567626953125 +9499 -0.954193115234375 +9500 -0.176116943359375 +9501 -0.957275390625 +9502 -0.176666259765625 +9503 -0.960235595703125 +9504 -0.17718505859375 +9505 -0.963104248046875 +9506 -0.177703857421875 +9507 -0.96588134765625 +9508 -0.178192138671875 +9509 -0.968536376953125 +9510 -0.17864990234375 +9511 -0.971099853515625 +9512 -0.179107666015625 +9513 -0.973541259765625 +9514 -0.179534912109375 +9515 -0.975860595703125 +9516 -0.179962158203125 +9517 -0.97808837890625 +9518 -0.180328369140625 +9519 -0.980224609375 +9520 -0.18072509765625 +9521 -0.98223876953125 +9522 -0.181060791015625 +9523 -0.984161376953125 +9524 -0.181396484375 +9525 -0.9859619140625 +9526 -0.18170166015625 +9527 -0.987640380859375 +9528 -0.1820068359375 +9529 -0.989227294921875 +9530 -0.182281494140625 +9531 -0.990692138671875 +9532 -0.182525634765625 +9533 -0.9920654296875 +9534 -0.1827392578125 +9535 -0.993316650390625 +9536 -0.182952880859375 +9537 -0.994476318359375 +9538 -0.18316650390625 +9539 -0.995513916015625 +9540 -0.183319091796875 +9541 -0.9964599609375 +9542 -0.1834716796875 +9543 -0.997283935546875 +9544 -0.183624267578125 +9545 -0.99798583984375 +9546 -0.1837158203125 +9547 -0.99859619140625 +9548 -0.183807373046875 +9549 -0.999114990234375 +9550 -0.183868408203125 +9551 -0.999481201171875 +9552 -0.183929443359375 +9553 -0.999755859375 +9554 -0.1839599609375 +9555 -0.99993896484375 +9556 -0.183990478515625 +9557 -1.0 +9558 -0.1839599609375 +9559 -0.99993896484375 +9560 -0.183929443359375 +9561 -0.999755859375 +9562 -0.183868408203125 +9563 -0.999481201171875 +9564 -0.183807373046875 +9565 -0.999114990234375 +9566 -0.1837158203125 +9567 -0.99859619140625 +9568 -0.183624267578125 +9569 -0.99798583984375 +9570 -0.1834716796875 +9571 -0.997283935546875 +9572 -0.183319091796875 +9573 -0.9964599609375 +9574 -0.18316650390625 +9575 -0.995513916015625 +9576 -0.182952880859375 +9577 -0.994476318359375 +9578 -0.1827392578125 +9579 -0.993316650390625 +9580 -0.182525634765625 +9581 -0.9920654296875 +9582 -0.182281494140625 +9583 -0.990692138671875 +9584 -0.1820068359375 +9585 -0.989227294921875 +9586 -0.18170166015625 +9587 -0.987640380859375 +9588 -0.181396484375 +9589 -0.9859619140625 +9590 -0.181060791015625 +9591 -0.984161376953125 +9592 -0.18072509765625 +9593 -0.98223876953125 +9594 -0.180328369140625 +9595 -0.980224609375 +9596 -0.179962158203125 +9597 -0.97808837890625 +9598 -0.179534912109375 +9599 -0.975860595703125 +9600 -0.179107666015625 +9601 -0.973541259765625 +9602 -0.17864990234375 +9603 -0.971099853515625 +9604 -0.178192138671875 +9605 -0.968536376953125 +9606 -0.177703857421875 +9607 -0.96588134765625 +9608 -0.17718505859375 +9609 -0.963104248046875 +9610 -0.176666259765625 +9611 -0.960235595703125 +9612 -0.176116943359375 +9613 -0.957275390625 +9614 -0.175567626953125 +9615 -0.954193115234375 +9616 -0.174957275390625 +9617 -0.951019287109375 +9618 -0.174346923828125 +9619 -0.947723388671875 +9620 -0.173736572265625 +9621 -0.9443359375 +9622 -0.173095703125 +9623 -0.940826416015625 +9624 -0.17242431640625 +9625 -0.937225341796875 +9626 -0.1717529296875 +9627 -0.93353271484375 +9628 -0.171051025390625 +9629 -0.929718017578125 +9630 -0.17034912109375 +9631 -0.92584228515625 +9632 -0.169586181640625 +9633 -0.92181396484375 +9634 -0.168853759765625 +9635 -0.917724609375 +9636 -0.168060302734375 +9637 -0.91351318359375 +9638 -0.167266845703125 +9639 -0.9091796875 +9640 -0.166473388671875 +9641 -0.90478515625 +9642 -0.165618896484375 +9643 -0.9002685546875 +9644 -0.164794921875 +9645 -0.895660400390625 +9646 -0.163909912109375 +9647 -0.890960693359375 +9648 -0.16302490234375 +9649 -0.88616943359375 +9650 -0.162139892578125 +9651 -0.881256103515625 +9652 -0.161224365234375 +9653 -0.876251220703125 +9654 -0.1602783203125 +9655 -0.871185302734375 +9656 -0.159332275390625 +9657 -0.865997314453125 +9658 -0.158355712890625 +9659 -0.860687255859375 +9660 -0.1573486328125 +9661 -0.855316162109375 +9662 -0.156341552734375 +9663 -0.849853515625 +9664 -0.15533447265625 +9665 -0.84429931640625 +9666 -0.154296875 +9667 -0.838623046875 +9668 -0.153228759765625 +9669 -0.8328857421875 +9670 -0.15216064453125 +9671 -0.8270263671875 +9672 -0.15106201171875 +9673 -0.82110595703125 +9674 -0.14996337890625 +9675 -0.815093994140625 +9676 -0.148834228515625 +9677 -0.808990478515625 +9678 -0.147705078125 +9679 -0.802764892578125 +9680 -0.14654541015625 +9681 -0.796478271484375 +9682 -0.145355224609375 +9683 -0.790130615234375 +9684 -0.1441650390625 +9685 -0.783660888671875 +9686 -0.142974853515625 +9687 -0.777099609375 +9688 -0.141754150390625 +9689 -0.770477294921875 +9690 -0.1405029296875 +9691 -0.763763427734375 +9692 -0.139251708984375 +9693 -0.7569580078125 +9694 -0.13800048828125 +9695 -0.75006103515625 +9696 -0.13671875 +9697 -0.74310302734375 +9698 -0.135406494140625 +9699 -0.736053466796875 +9700 -0.13409423828125 +9701 -0.72894287109375 +9702 -0.132781982421875 +9703 -0.721710205078125 +9704 -0.131439208984375 +9705 -0.714447021484375 +9706 -0.130096435546875 +9707 -0.707061767578125 +9708 -0.12872314453125 +9709 -0.699615478515625 +9710 -0.1273193359375 +9711 -0.692108154296875 +9712 -0.125946044921875 +9713 -0.68450927734375 +9714 -0.12451171875 +9715 -0.676849365234375 +9716 -0.12310791015625 +9717 -0.669097900390625 +9718 -0.121673583984375 +9719 -0.661285400390625 +9720 -0.120208740234375 +9721 -0.65338134765625 +9722 -0.118743896484375 +9723 -0.645416259765625 +9724 -0.11724853515625 +9725 -0.63739013671875 +9726 -0.115753173828125 +9727 -0.6292724609375 +9728 -0.12420654296875 +9729 -0.621124267578125 +9730 -0.12255859375 +9731 -0.612884521484375 +9732 -0.120880126953125 +9733 -0.60455322265625 +9734 -0.11920166015625 +9735 -0.59619140625 +9736 -0.117523193359375 +9737 -0.587738037109375 +9738 -0.115814208984375 +9739 -0.579254150390625 +9740 -0.114105224609375 +9741 -0.5706787109375 +9742 -0.112396240234375 +9743 -0.562042236328125 +9744 -0.11065673828125 +9745 -0.5533447265625 +9746 -0.10888671875 +9747 -0.54461669921875 +9748 -0.107147216796875 +9749 -0.535797119140625 +9750 -0.1053466796875 +9751 -0.52691650390625 +9752 -0.10357666015625 +9753 -0.51800537109375 +9754 -0.101776123046875 +9755 -0.509002685546875 +9756 -0.0999755859375 +9757 -0.499969482421875 +9758 -0.09814453125 +9759 -0.490875244140625 +9760 -0.0963134765625 +9761 -0.481719970703125 +9762 -0.094482421875 +9763 -0.4725341796875 +9764 -0.092620849609375 +9765 -0.4632568359375 +9766 -0.09075927734375 +9767 -0.453948974609375 +9768 -0.088897705078125 +9769 -0.444610595703125 +9770 -0.0870361328125 +9771 -0.435211181640625 +9772 -0.08514404296875 +9773 -0.425750732421875 +9774 -0.083221435546875 +9775 -0.416259765625 +9776 -0.081329345703125 +9777 -0.406707763671875 +9778 -0.07940673828125 +9779 -0.397125244140625 +9780 -0.077484130859375 +9781 -0.387481689453125 +9782 -0.075531005859375 +9783 -0.3778076171875 +9784 -0.0736083984375 +9785 -0.36810302734375 +9786 -0.0716552734375 +9787 -0.35833740234375 +9788 -0.0697021484375 +9789 -0.348541259765625 +9790 -0.067718505859375 +9791 -0.338714599609375 +9792 -0.06573486328125 +9793 -0.328826904296875 +9794 -0.06378173828125 +9795 -0.318939208984375 +9796 -0.061767578125 +9797 -0.308990478515625 +9798 -0.059783935546875 +9799 -0.29901123046875 +9800 -0.057769775390625 +9801 -0.28900146484375 +9802 -0.0557861328125 +9803 -0.278961181640625 +9804 -0.05377197265625 +9805 -0.268890380859375 +9806 -0.051727294921875 +9807 -0.2587890625 +9808 -0.049713134765625 +9809 -0.2486572265625 +9810 -0.047698974609375 +9811 -0.238525390625 +9812 -0.045654296875 +9813 -0.22833251953125 +9814 -0.043609619140625 +9815 -0.218109130859375 +9816 -0.04156494140625 +9817 -0.2078857421875 +9818 -0.039520263671875 +9819 -0.1976318359375 +9820 -0.037445068359375 +9821 -0.187347412109375 +9822 -0.035400390625 +9823 -0.17706298828125 +9824 -0.0333251953125 +9825 -0.166748046875 +9826 -0.03125 +9827 -0.156402587890625 +9828 -0.029205322265625 +9829 -0.14605712890625 +9830 -0.027130126953125 +9831 -0.13568115234375 +9832 -0.025054931640625 +9833 -0.12530517578125 +9834 -0.022979736328125 +9835 -0.11492919921875 +9836 -0.0208740234375 +9837 -0.104522705078125 +9838 -0.018798828125 +9839 -0.094085693359375 +9840 -0.0167236328125 +9841 -0.083648681640625 +9842 -0.014617919921875 +9843 -0.073211669921875 +9844 -0.012542724609375 +9845 -0.062774658203125 +9846 -0.01043701171875 +9847 -0.05230712890625 +9848 -0.00836181640625 +9849 -0.0418701171875 +9850 -0.006256103515625 +9851 -0.031402587890625 +9852 -0.004180908203125 +9853 -0.02093505859375 +9854 -0.0020751953125 +9855 -0.010467529296875 +9856 0.0 +9857 0.0 +9858 0.00225830078125 +9859 0.010467529296875 +9860 0.0045166015625 +9861 0.02093505859375 +9862 0.00677490234375 +9863 0.031402587890625 +9864 0.009033203125 +9865 0.0418701171875 +9866 0.01129150390625 +9867 0.05230712890625 +9868 0.0135498046875 +9869 0.062774658203125 +9870 0.01580810546875 +9871 0.073211669921875 +9872 0.01806640625 +9873 0.083648681640625 +9874 0.020294189453125 +9875 0.094085693359375 +9876 0.022552490234375 +9877 0.104522705078125 +9878 0.024810791015625 +9879 0.11492919921875 +9880 0.02703857421875 +9881 0.12530517578125 +9882 0.029296875 +9883 0.13568115234375 +9884 0.031524658203125 +9885 0.14605712890625 +9886 0.033782958984375 +9887 0.156402587890625 +9888 0.0360107421875 +9889 0.166748046875 +9890 0.038238525390625 +9891 0.17706298828125 +9892 0.04046630859375 +9893 0.187347412109375 +9894 0.04266357421875 +9895 0.1976318359375 +9896 0.044891357421875 +9897 0.2078857421875 +9898 0.047088623046875 +9899 0.218109130859375 +9900 0.04931640625 +9901 0.22833251953125 +9902 0.051513671875 +9903 0.238525390625 +9904 0.0537109375 +9905 0.2486572265625 +9906 0.055877685546875 +9907 0.2587890625 +9908 0.058074951171875 +9909 0.268890380859375 +9910 0.06024169921875 +9911 0.278961181640625 +9912 0.062408447265625 +9913 0.28900146484375 +9914 0.0645751953125 +9915 0.29901123046875 +9916 0.066741943359375 +9917 0.308990478515625 +9918 0.068878173828125 +9919 0.318939208984375 +9920 0.071014404296875 +9921 0.328826904296875 +9922 0.073150634765625 +9923 0.338714599609375 +9924 0.075286865234375 +9925 0.348541259765625 +9926 0.077392578125 +9927 0.35833740234375 +9928 0.079498291015625 +9929 0.36810302734375 +9930 0.08160400390625 +9931 0.3778076171875 +9932 0.08367919921875 +9933 0.387481689453125 +9934 0.08575439453125 +9935 0.397125244140625 +9936 0.08782958984375 +9937 0.406707763671875 +9938 0.08990478515625 +9939 0.416259765625 +9940 0.091949462890625 +9941 0.425750732421875 +9942 0.093994140625 +9943 0.435211181640625 +9944 0.096038818359375 +9945 0.444610595703125 +9946 0.098052978515625 +9947 0.453948974609375 +9948 0.100067138671875 +9949 0.4632568359375 +9950 0.10205078125 +9951 0.4725341796875 +9952 0.104034423828125 +9953 0.481719970703125 +9954 0.10601806640625 +9955 0.490875244140625 +9956 0.10797119140625 +9957 0.499969482421875 +9958 0.10992431640625 +9959 0.509002685546875 +9960 0.11187744140625 +9961 0.51800537109375 +9962 0.113800048828125 +9963 0.52691650390625 +9964 0.11572265625 +9965 0.535797119140625 +9966 0.11761474609375 +9967 0.54461669921875 +9968 0.1195068359375 +9969 0.5533447265625 +9970 0.12139892578125 +9971 0.562042236328125 +9972 0.123260498046875 +9973 0.5706787109375 +9974 0.1251220703125 +9975 0.579254150390625 +9976 0.126953125 +9977 0.587738037109375 +9978 0.128753662109375 +9979 0.59619140625 +9980 0.130584716796875 +9981 0.60455322265625 +9982 0.13238525390625 +9983 0.612884521484375 +9984 0.154022216796875 +9985 0.621124267578125 +9986 0.156036376953125 +9987 0.6292724609375 +9988 0.158050537109375 +9989 0.63739013671875 +9990 0.1600341796875 +9991 0.645416259765625 +9992 0.162017822265625 +9993 0.65338134765625 +9994 0.163970947265625 +9995 0.661285400390625 +9996 0.165924072265625 +9997 0.669097900390625 +9998 0.1678466796875 +9999 0.676849365234375 +10000 0.16973876953125 +10001 0.68450927734375 +10002 0.171630859375 +10003 0.692108154296875 +10004 0.173492431640625 +10005 0.699615478515625 +10006 0.175323486328125 +10007 0.707061767578125 +10008 0.177154541015625 +10009 0.714447021484375 +10010 0.178955078125 +10011 0.721710205078125 +10012 0.180755615234375 +10013 0.72894287109375 +10014 0.182525634765625 +10015 0.736053466796875 +10016 0.18426513671875 +10017 0.74310302734375 +10018 0.186004638671875 +10019 0.75006103515625 +10020 0.187713623046875 +10021 0.7569580078125 +10022 0.18939208984375 +10023 0.763763427734375 +10024 0.191070556640625 +10025 0.770477294921875 +10026 0.19268798828125 +10027 0.777099609375 +10028 0.1943359375 +10029 0.783660888671875 +10030 0.1959228515625 +10031 0.790130615234375 +10032 0.197509765625 +10033 0.796478271484375 +10034 0.199066162109375 +10035 0.802764892578125 +10036 0.20062255859375 +10037 0.808990478515625 +10038 0.202117919921875 +10039 0.815093994140625 +10040 0.20361328125 +10041 0.82110595703125 +10042 0.205078125 +10043 0.8270263671875 +10044 0.20654296875 +10045 0.8328857421875 +10046 0.20794677734375 +10047 0.838623046875 +10048 0.2093505859375 +10049 0.84429931640625 +10050 0.21075439453125 +10051 0.849853515625 +10052 0.21209716796875 +10053 0.855316162109375 +10054 0.21343994140625 +10055 0.860687255859375 +10056 0.214752197265625 +10057 0.865997314453125 +10058 0.216033935546875 +10059 0.871185302734375 +10060 0.21728515625 +10061 0.876251220703125 +10062 0.218536376953125 +10063 0.881256103515625 +10064 0.219757080078125 +10065 0.88616943359375 +10066 0.220947265625 +10067 0.890960693359375 +10068 0.22210693359375 +10069 0.895660400390625 +10070 0.223236083984375 +10071 0.9002685546875 +10072 0.224365234375 +10073 0.90478515625 +10074 0.2254638671875 +10075 0.9091796875 +10076 0.226531982421875 +10077 0.91351318359375 +10078 0.227569580078125 +10079 0.917724609375 +10080 0.22857666015625 +10081 0.92181396484375 +10082 0.229583740234375 +10083 0.92584228515625 +10084 0.230560302734375 +10085 0.929718017578125 +10086 0.23150634765625 +10087 0.93353271484375 +10088 0.232421875 +10089 0.937225341796875 +10090 0.233306884765625 +10091 0.940826416015625 +10092 0.234161376953125 +10093 0.9443359375 +10094 0.235015869140625 +10095 0.947723388671875 +10096 0.23583984375 +10097 0.951019287109375 +10098 0.23663330078125 +10099 0.954193115234375 +10100 0.237396240234375 +10101 0.957275390625 +10102 0.238128662109375 +10103 0.960235595703125 +10104 0.23883056640625 +10105 0.963104248046875 +10106 0.239501953125 +10107 0.96588134765625 +10108 0.24017333984375 +10109 0.968536376953125 +10110 0.240814208984375 +10111 0.971099853515625 +10112 0.241424560546875 +10113 0.973541259765625 +10114 0.24200439453125 +10115 0.975860595703125 +10116 0.2425537109375 +10117 0.97808837890625 +10118 0.243072509765625 +10119 0.980224609375 +10120 0.243560791015625 +10121 0.98223876953125 +10122 0.244049072265625 +10123 0.984161376953125 +10124 0.2445068359375 +10125 0.9859619140625 +10126 0.244903564453125 +10127 0.987640380859375 +10128 0.24530029296875 +10129 0.989227294921875 +10130 0.24566650390625 +10131 0.990692138671875 +10132 0.246002197265625 +10133 0.9920654296875 +10134 0.246307373046875 +10135 0.993316650390625 +10136 0.246612548828125 +10137 0.994476318359375 +10138 0.246856689453125 +10139 0.995513916015625 +10140 0.247100830078125 +10141 0.9964599609375 +10142 0.247314453125 +10143 0.997283935546875 +10144 0.247467041015625 +10145 0.99798583984375 +10146 0.24761962890625 +10147 0.99859619140625 +10148 0.24774169921875 +10149 0.999114990234375 +10150 0.247833251953125 +10151 0.999481201171875 +10152 0.2479248046875 +10153 0.999755859375 +10154 0.247955322265625 +10155 0.99993896484375 +10156 0.24798583984375 +10157 0.999969482421875 +10158 0.247955322265625 +10159 0.99993896484375 +10160 0.2479248046875 +10161 0.999755859375 +10162 0.247833251953125 +10163 0.999481201171875 +10164 0.24774169921875 +10165 0.999114990234375 +10166 0.24761962890625 +10167 0.99859619140625 +10168 0.247467041015625 +10169 0.99798583984375 +10170 0.247314453125 +10171 0.997283935546875 +10172 0.247100830078125 +10173 0.9964599609375 +10174 0.246856689453125 +10175 0.995513916015625 +10176 0.246612548828125 +10177 0.994476318359375 +10178 0.246307373046875 +10179 0.993316650390625 +10180 0.246002197265625 +10181 0.9920654296875 +10182 0.24566650390625 +10183 0.990692138671875 +10184 0.24530029296875 +10185 0.989227294921875 +10186 0.244903564453125 +10187 0.987640380859375 +10188 0.2445068359375 +10189 0.9859619140625 +10190 0.244049072265625 +10191 0.984161376953125 +10192 0.243560791015625 +10193 0.98223876953125 +10194 0.243072509765625 +10195 0.980224609375 +10196 0.2425537109375 +10197 0.97808837890625 +10198 0.24200439453125 +10199 0.975860595703125 +10200 0.241424560546875 +10201 0.973541259765625 +10202 0.240814208984375 +10203 0.971099853515625 +10204 0.24017333984375 +10205 0.968536376953125 +10206 0.239501953125 +10207 0.96588134765625 +10208 0.23883056640625 +10209 0.963104248046875 +10210 0.238128662109375 +10211 0.960235595703125 +10212 0.237396240234375 +10213 0.957275390625 +10214 0.23663330078125 +10215 0.954193115234375 +10216 0.23583984375 +10217 0.951019287109375 +10218 0.235015869140625 +10219 0.947723388671875 +10220 0.234161376953125 +10221 0.9443359375 +10222 0.233306884765625 +10223 0.940826416015625 +10224 0.232421875 +10225 0.937225341796875 +10226 0.23150634765625 +10227 0.93353271484375 +10228 0.230560302734375 +10229 0.929718017578125 +10230 0.229583740234375 +10231 0.92584228515625 +10232 0.22857666015625 +10233 0.92181396484375 +10234 0.227569580078125 +10235 0.917724609375 +10236 0.226531982421875 +10237 0.91351318359375 +10238 0.2254638671875 +10239 0.9091796875 +10240 0.0 +10241 0.0 +10242 0.0 +10243 0.0 +10244 0.0 +10245 0.0 +10246 0.0 +10247 0.0 +10248 0.0 +10249 0.0 +10250 0.0 +10251 0.0 +10252 0.0 +10253 0.0 +10254 0.0 +10255 0.0 +10256 0.0 +10257 0.0 +10258 0.0 +10259 0.0 +10260 0.0 +10261 0.0 +10262 0.0 +10263 0.0 +10264 0.0 +10265 0.0 +10266 0.0 +10267 0.0 +10268 0.0 +10269 0.0 +10270 0.0 +10271 0.0 +10272 0.0 +10273 0.0 +10274 0.0 +10275 0.0 +10276 0.0 +10277 0.0 +10278 0.0 +10279 0.0 +10280 0.0 +10281 0.0 +10282 0.0 +10283 0.0 +10284 0.0 +10285 0.0 +10286 0.0 +10287 0.0 +10288 0.0 +10289 0.0 +10290 0.0 +10291 0.0 +10292 0.0 +10293 0.0 +10294 0.0 +10295 0.0 +10296 0.0 +10297 0.0 +10298 0.0 +10299 0.0 +10300 0.0 +10301 0.0 +10302 0.0 +10303 0.0 +10304 0.0 +10305 0.0 +10306 0.0 +10307 0.0 +10308 0.0 +10309 0.0 +10310 0.0 +10311 0.0 +10312 0.0 +10313 0.0 +10314 0.0 +10315 0.0 +10316 0.0 +10317 0.0 +10318 0.0 +10319 0.0 +10320 0.0 +10321 0.0 +10322 0.0 +10323 0.0 +10324 0.0 +10325 0.0 +10326 0.0 +10327 0.0 +10328 0.0 +10329 0.0 +10330 0.0 +10331 0.0 +10332 0.0 +10333 0.0 +10334 0.0 +10335 0.0 +10336 0.0 +10337 0.0 +10338 0.0 +10339 0.0 +10340 0.0 +10341 0.0 +10342 0.0 +10343 0.0 +10344 0.0 +10345 0.0 +10346 0.0 +10347 0.0 +10348 0.0 +10349 0.0 +10350 0.0 +10351 0.0 +10352 0.0 +10353 0.0 +10354 0.0 +10355 0.0 +10356 0.0 +10357 0.0 +10358 0.0 +10359 0.0 +10360 0.0 +10361 0.0 +10362 0.0 +10363 0.0 +10364 0.0 +10365 0.0 +10366 0.0 +10367 0.0 +10368 0.0 +10369 0.0 +10370 0.0 +10371 0.0 +10372 0.0 +10373 0.0 +10374 0.0 +10375 0.0 +10376 0.0 +10377 0.0 +10378 0.0 +10379 0.0 +10380 0.0 +10381 0.0 +10382 0.0 +10383 0.0 +10384 0.0 +10385 0.0 +10386 0.0 +10387 0.0 +10388 0.0 +10389 0.0 +10390 0.0 +10391 0.0 +10392 0.0 +10393 0.0 +10394 0.0 +10395 0.0 +10396 0.0 +10397 0.0 +10398 0.0 +10399 0.0 +10400 0.0 +10401 0.0 +10402 0.0 +10403 0.0 +10404 0.0 +10405 0.0 +10406 0.0 +10407 0.0 +10408 0.0 +10409 0.0 +10410 0.0 +10411 0.0 +10412 0.0 +10413 0.0 +10414 0.0 +10415 0.0 +10416 0.0 +10417 0.0 +10418 0.0 +10419 0.0 +10420 0.0 +10421 0.0 +10422 0.0 +10423 0.0 +10424 0.0 +10425 0.0 +10426 0.0 +10427 0.0 +10428 0.0 +10429 0.0 +10430 0.0 +10431 0.0 +10432 0.0 +10433 0.0 +10434 0.0 +10435 0.0 +10436 0.0 +10437 0.0 +10438 0.0 +10439 0.0 +10440 0.0 +10441 0.0 +10442 0.0 +10443 0.0 +10444 0.0 +10445 0.0 +10446 0.0 +10447 0.0 +10448 0.0 +10449 0.0 +10450 0.0 +10451 0.0 +10452 0.0 +10453 0.0 +10454 0.0 +10455 0.0 +10456 0.0 +10457 0.0 +10458 0.0 +10459 0.0 +10460 0.0 +10461 0.0 +10462 0.0 +10463 0.0 +10464 0.0 +10465 0.0 +10466 0.0 +10467 0.0 +10468 0.0 +10469 0.0 +10470 0.0 +10471 0.0 +10472 0.0 +10473 0.0 +10474 0.0 +10475 0.0 +10476 0.0 +10477 0.0 +10478 0.0 +10479 0.0 +10480 0.0 +10481 0.0 +10482 0.0 +10483 0.0 +10484 0.0 +10485 0.0 +10486 0.0 +10487 0.0 +10488 0.0 +10489 0.0 +10490 0.0 +10491 0.0 +10492 0.0 +10493 0.0 +10494 0.0 +10495 0.0 +10496 0.0 +10497 0.0 +10498 0.0 +10499 0.0 +10500 0.0 +10501 0.0 +10502 0.0 +10503 0.0 +10504 0.0 +10505 0.0 +10506 0.0 +10507 0.0 +10508 0.0 +10509 0.0 +10510 0.0 +10511 0.0 +10512 0.0 +10513 0.0 +10514 0.0 +10515 0.0 +10516 0.0 +10517 0.0 +10518 0.0 +10519 0.0 +10520 0.0 +10521 0.0 +10522 0.0 +10523 0.0 +10524 0.0 +10525 0.0 +10526 0.0 +10527 0.0 +10528 0.0 +10529 0.0 +10530 0.0 +10531 0.0 +10532 0.0 +10533 0.0 +10534 0.0 +10535 0.0 +10536 0.0 +10537 0.0 +10538 0.0 +10539 0.0 +10540 0.0 +10541 0.0 +10542 0.0 +10543 0.0 +10544 0.0 +10545 0.0 +10546 0.0 +10547 0.0 +10548 0.0 +10549 0.0 +10550 0.0 +10551 0.0 +10552 0.0 +10553 0.0 +10554 0.0 +10555 0.0 +10556 0.0 +10557 0.0 +10558 0.0 +10559 0.0 +10560 0.0 +10561 0.0 +10562 0.0 +10563 0.0 +10564 0.0 +10565 0.0 +10566 0.0 +10567 0.0 +10568 0.0 +10569 0.0 +10570 0.0 +10571 0.0 +10572 0.0 +10573 0.0 +10574 0.0 +10575 0.0 +10576 0.0 +10577 0.0 +10578 0.0 +10579 0.0 +10580 0.0 +10581 0.0 +10582 0.0 +10583 0.0 +10584 0.0 +10585 0.0 +10586 0.0 +10587 0.0 +10588 0.0 +10589 0.0 +10590 0.0 +10591 0.0 +10592 0.0 +10593 0.0 +10594 0.0 +10595 0.0 +10596 0.0 +10597 0.0 +10598 0.0 +10599 0.0 +10600 0.0 +10601 0.0 +10602 0.0 +10603 0.0 +10604 0.0 +10605 0.0 +10606 0.0 +10607 0.0 +10608 0.0 +10609 0.0 +10610 0.0 +10611 0.0 +10612 0.0 +10613 0.0 +10614 0.0 +10615 0.0 +10616 0.0 +10617 0.0 +10618 0.0 +10619 0.0 +10620 0.0 +10621 0.0 +10622 0.0 +10623 0.0 +10624 0.0 +10625 0.0 +10626 0.0 +10627 0.0 +10628 0.0 +10629 0.0 +10630 0.0 +10631 0.0 +10632 0.0 +10633 0.0 +10634 0.0 +10635 0.0 +10636 0.0 +10637 0.0 +10638 0.0 +10639 0.0 +10640 0.0 +10641 0.0 +10642 0.0 +10643 0.0 +10644 0.0 +10645 0.0 +10646 0.0 +10647 0.0 +10648 0.0 +10649 0.0 +10650 0.0 +10651 0.0 +10652 0.0 +10653 0.0 +10654 0.0 +10655 0.0 +10656 0.0 +10657 0.0 +10658 0.0 +10659 0.0 +10660 0.0 +10661 0.0 +10662 0.0 +10663 0.0 +10664 0.0 +10665 0.0 +10666 0.0 +10667 0.0 +10668 0.0 +10669 0.0 +10670 0.0 +10671 0.0 +10672 0.0 +10673 0.0 +10674 0.0 +10675 0.0 +10676 0.0 +10677 0.0 +10678 0.0 +10679 0.0 +10680 0.0 +10681 0.0 +10682 0.0 +10683 0.0 +10684 0.0 +10685 0.0 +10686 0.0 +10687 0.0 +10688 0.0 +10689 0.0 +10690 0.0 +10691 0.0 +10692 0.0 +10693 0.0 +10694 0.0 +10695 0.0 +10696 0.0 +10697 0.0 +10698 0.0 +10699 0.0 +10700 0.0 +10701 0.0 +10702 0.0 +10703 0.0 +10704 0.0 +10705 0.0 +10706 0.0 +10707 0.0 +10708 0.0 +10709 0.0 +10710 0.0 +10711 0.0 +10712 0.0 +10713 0.0 +10714 0.0 +10715 0.0 +10716 0.0 +10717 0.0 +10718 0.0 +10719 0.0 +10720 0.0 +10721 0.0 +10722 0.0 +10723 0.0 +10724 0.0 +10725 0.0 +10726 0.0 +10727 0.0 +10728 0.0 +10729 0.0 +10730 0.0 +10731 0.0 +10732 0.0 +10733 0.0 +10734 0.0 +10735 0.0 +10736 0.0 +10737 0.0 +10738 0.0 +10739 0.0 +10740 0.0 +10741 0.0 +10742 0.0 +10743 0.0 +10744 0.0 +10745 0.0 +10746 0.0 +10747 0.0 +10748 0.0 +10749 0.0 +10750 0.0 +10751 0.0 +10752 0.0 +10753 0.0 +10754 0.0 +10755 0.0 +10756 0.0 +10757 0.0 +10758 0.0 +10759 0.0 +10760 0.0 +10761 0.0 +10762 0.0 +10763 0.0 +10764 0.0 +10765 0.0 +10766 0.0 +10767 0.0 +10768 0.0 +10769 0.0 +10770 0.0 +10771 0.0 +10772 0.0 +10773 0.0 +10774 0.0 +10775 0.0 +10776 0.0 +10777 0.0 +10778 0.0 +10779 0.0 +10780 0.0 +10781 0.0 +10782 0.0 +10783 0.0 +10784 0.0 +10785 0.0 +10786 0.0 +10787 0.0 +10788 0.0 +10789 0.0 +10790 0.0 +10791 0.0 +10792 0.0 +10793 0.0 +10794 0.0 +10795 0.0 +10796 0.0 +10797 0.0 +10798 0.0 +10799 0.0 +10800 0.0 +10801 0.0 +10802 0.0 +10803 0.0 +10804 0.0 +10805 0.0 +10806 0.0 +10807 0.0 +10808 0.0 +10809 0.0 +10810 0.0 +10811 0.0 +10812 0.0 +10813 0.0 +10814 0.0 +10815 0.0 +10816 0.0 +10817 0.0 +10818 0.0 +10819 0.0 +10820 0.0 +10821 0.0 +10822 0.0 +10823 0.0 +10824 0.0 +10825 0.0 +10826 0.0 +10827 0.0 +10828 0.0 +10829 0.0 +10830 0.0 +10831 0.0 +10832 0.0 +10833 0.0 +10834 0.0 +10835 0.0 +10836 0.0 +10837 0.0 +10838 0.0 +10839 0.0 +10840 0.0 +10841 0.0 +10842 0.0 +10843 0.0 +10844 0.0 +10845 0.0 +10846 0.0 +10847 0.0 +10848 0.0 +10849 0.0 +10850 0.0 +10851 0.0 +10852 0.0 +10853 0.0 +10854 0.0 +10855 0.0 +10856 0.0 +10857 0.0 +10858 0.0 +10859 0.0 +10860 0.0 +10861 0.0 +10862 0.0 +10863 0.0 +10864 0.0 +10865 0.0 +10866 0.0 +10867 0.0 +10868 0.0 +10869 0.0 +10870 0.0 +10871 0.0 +10872 0.0 +10873 0.0 +10874 0.0 +10875 0.0 +10876 0.0 +10877 0.0 +10878 0.0 +10879 0.0 +10880 0.0 +10881 0.0 +10882 0.0 +10883 0.0 +10884 0.0 +10885 0.0 +10886 0.0 +10887 0.0 +10888 0.0 +10889 0.0 +10890 0.0 +10891 0.0 +10892 0.0 +10893 0.0 +10894 0.0 +10895 0.0 +10896 0.0 +10897 0.0 +10898 0.0 +10899 0.0 +10900 0.0 +10901 0.0 +10902 0.0 +10903 0.0 +10904 0.0 +10905 0.0 +10906 0.0 +10907 0.0 +10908 0.0 +10909 0.0 +10910 0.0 +10911 0.0 +10912 0.0 +10913 0.0 +10914 0.0 +10915 0.0 +10916 0.0 +10917 0.0 +10918 0.0 +10919 0.0 +10920 0.0 +10921 0.0 +10922 0.0 +10923 0.0 +10924 0.0 +10925 0.0 +10926 0.0 +10927 0.0 +10928 0.0 +10929 0.0 +10930 0.0 +10931 0.0 +10932 0.0 +10933 0.0 +10934 0.0 +10935 0.0 +10936 0.0 +10937 0.0 +10938 0.0 +10939 0.0 +10940 0.0 +10941 0.0 +10942 0.0 +10943 0.0 +10944 0.0 +10945 0.0 +10946 0.0 +10947 0.0 +10948 0.0 +10949 0.0 +10950 0.0 +10951 0.0 +10952 0.0 +10953 0.0 +10954 0.0 +10955 0.0 +10956 0.0 +10957 0.0 +10958 0.0 +10959 0.0 +10960 0.0 +10961 0.0 +10962 0.0 +10963 0.0 +10964 0.0 +10965 0.0 +10966 0.0 +10967 0.0 +10968 0.0 +10969 0.0 +10970 0.0 +10971 0.0 +10972 0.0 +10973 0.0 +10974 0.0 +10975 0.0 +10976 0.0 +10977 0.0 +10978 0.0 +10979 0.0 +10980 0.0 +10981 0.0 +10982 0.0 +10983 0.0 +10984 0.0 +10985 0.0 +10986 0.0 +10987 0.0 +10988 0.0 +10989 0.0 +10990 0.0 +10991 0.0 +10992 0.0 +10993 0.0 +10994 0.0 +10995 0.0 +10996 0.0 +10997 0.0 +10998 0.0 +10999 0.0 +11000 0.0 +11001 0.0 +11002 0.0 +11003 0.0 +11004 0.0 +11005 0.0 +11006 0.0 +11007 0.0 +11008 0.0 +11009 0.0 +11010 0.0 +11011 0.0 +11012 0.0 +11013 0.0 +11014 0.0 +11015 0.0 +11016 0.0 +11017 0.0 +11018 0.0 +11019 0.0 +11020 0.0 +11021 0.0 +11022 0.0 +11023 0.0 +11024 0.0 +11025 0.0 +11026 0.0 +11027 0.0 +11028 0.0 +11029 0.0 +11030 0.0 +11031 0.0 +11032 0.0 +11033 0.0 +11034 0.0 +11035 0.0 +11036 0.0 +11037 0.0 +11038 0.0 +11039 0.0 +11040 0.0 +11041 0.0 +11042 0.0 +11043 0.0 +11044 0.0 +11045 0.0 +11046 0.0 +11047 0.0 +11048 0.0 +11049 0.0 +11050 0.0 +11051 0.0 +11052 0.0 +11053 0.0 +11054 0.0 +11055 0.0 +11056 0.0 +11057 0.0 +11058 0.0 +11059 0.0 +11060 0.0 +11061 0.0 +11062 0.0 +11063 0.0 +11064 0.0 +11065 0.0 +11066 0.0 +11067 0.0 +11068 0.0 +11069 0.0 +11070 0.0 +11071 0.0 +11072 0.0 +11073 0.0 +11074 0.0 +11075 0.0 +11076 0.0 +11077 0.0 +11078 0.0 +11079 0.0 +11080 0.0 +11081 0.0 +11082 0.0 +11083 0.0 +11084 0.0 +11085 0.0 +11086 0.0 +11087 0.0 +11088 0.0 +11089 0.0 +11090 0.0 +11091 0.0 +11092 0.0 +11093 0.0 +11094 0.0 +11095 0.0 +11096 0.0 +11097 0.0 +11098 0.0 +11099 0.0 +11100 0.0 +11101 0.0 +11102 0.0 +11103 0.0 +11104 0.0 +11105 0.0 +11106 0.0 +11107 0.0 +11108 0.0 +11109 0.0 +11110 0.0 +11111 0.0 +11112 0.0 +11113 0.0 +11114 0.0 +11115 0.0 +11116 0.0 +11117 0.0 +11118 0.0 +11119 0.0 +11120 0.0 +11121 0.0 +11122 0.0 +11123 0.0 +11124 0.0 +11125 0.0 +11126 0.0 +11127 0.0 +11128 0.0 +11129 0.0 +11130 0.0 +11131 0.0 +11132 0.0 +11133 0.0 +11134 0.0 +11135 0.0 +11136 0.0 +11137 0.0 +11138 0.0 +11139 0.0 +11140 0.0 +11141 0.0 +11142 0.0 +11143 0.0 +11144 0.0 +11145 0.0 +11146 0.0 +11147 0.0 +11148 0.0 +11149 0.0 +11150 0.0 +11151 0.0 +11152 0.0 +11153 0.0 +11154 0.0 +11155 0.0 +11156 0.0 +11157 0.0 +11158 0.0 +11159 0.0 +11160 0.0 +11161 0.0 +11162 0.0 +11163 0.0 +11164 0.0 +11165 0.0 +11166 0.0 +11167 0.0 +11168 0.0 +11169 0.0 +11170 0.0 +11171 0.0 +11172 0.0 +11173 0.0 +11174 0.0 +11175 0.0 +11176 0.0 +11177 0.0 +11178 0.0 +11179 0.0 +11180 0.0 +11181 0.0 +11182 0.0 +11183 0.0 +11184 0.0 +11185 0.0 +11186 0.0 +11187 0.0 +11188 0.0 +11189 0.0 +11190 0.0 +11191 0.0 +11192 0.0 +11193 0.0 +11194 0.0 +11195 0.0 +11196 0.0 +11197 0.0 +11198 0.0 +11199 0.0 +11200 0.0 +11201 0.0 +11202 0.0 +11203 0.0 +11204 0.0 +11205 0.0 +11206 0.0 +11207 0.0 +11208 0.0 +11209 0.0 +11210 0.0 +11211 0.0 +11212 0.0 +11213 0.0 +11214 0.0 +11215 0.0 +11216 0.0 +11217 0.0 +11218 0.0 +11219 0.0 +11220 0.0 +11221 0.0 +11222 0.0 +11223 0.0 +11224 0.0 +11225 0.0 +11226 0.0 +11227 0.0 +11228 0.0 +11229 0.0 +11230 0.0 +11231 0.0 +11232 0.0 +11233 0.0 +11234 0.0 +11235 0.0 +11236 0.0 +11237 0.0 +11238 0.0 +11239 0.0 +11240 0.0 +11241 0.0 +11242 0.0 +11243 0.0 +11244 0.0 +11245 0.0 +11246 0.0 +11247 0.0 +11248 0.0 +11249 0.0 +11250 0.0 +11251 0.0 +11252 0.0 +11253 0.0 +11254 0.0 +11255 0.0 +11256 0.0 +11257 0.0 +11258 0.0 +11259 0.0 +11260 0.0 +11261 0.0 +11262 0.0 +11263 0.0 +11264 0.0 +11265 0.0 +11266 0.0 +11267 0.0 +11268 0.0 +11269 0.0 +11270 0.0 +11271 0.0 +11272 0.0 +11273 0.0 +11274 0.0 +11275 0.0 +11276 0.0 +11277 0.0 +11278 0.0 +11279 0.0 +11280 0.0 +11281 0.0 +11282 0.0 +11283 0.0 +11284 0.0 +11285 0.0 +11286 0.0 +11287 0.0 +11288 0.0 +11289 0.0 +11290 0.0 +11291 0.0 +11292 0.0 +11293 0.0 +11294 0.0 +11295 0.0 +11296 0.0 +11297 0.0 +11298 0.0 +11299 0.0 +11300 0.0 +11301 0.0 +11302 0.0 +11303 0.0 +11304 0.0 +11305 0.0 +11306 0.0 +11307 0.0 +11308 0.0 +11309 0.0 +11310 0.0 +11311 0.0 +11312 0.0 +11313 0.0 +11314 0.0 +11315 0.0 +11316 0.0 +11317 0.0 +11318 0.0 +11319 0.0 +11320 0.0 +11321 0.0 +11322 0.0 +11323 0.0 +11324 0.0 +11325 0.0 +11326 0.0 +11327 0.0 +11328 0.0 +11329 0.0 +11330 0.0 +11331 0.0 +11332 0.0 +11333 0.0 +11334 0.0 +11335 0.0 +11336 0.0 +11337 0.0 +11338 0.0 +11339 0.0 +11340 0.0 +11341 0.0 +11342 0.0 +11343 0.0 +11344 0.0 +11345 0.0 +11346 0.0 +11347 0.0 +11348 0.0 +11349 0.0 +11350 0.0 +11351 0.0 +11352 0.0 +11353 0.0 +11354 0.0 +11355 0.0 +11356 0.0 +11357 0.0 +11358 0.0 +11359 0.0 +11360 0.0 +11361 0.0 +11362 0.0 +11363 0.0 +11364 0.0 +11365 0.0 +11366 0.0 +11367 0.0 +11368 0.0 +11369 0.0 +11370 0.0 +11371 0.0 +11372 0.0 +11373 0.0 +11374 0.0 +11375 0.0 +11376 0.0 +11377 0.0 +11378 0.0 +11379 0.0 +11380 0.0 +11381 0.0 +11382 0.0 +11383 0.0 +11384 0.0 +11385 0.0 +11386 0.0 +11387 0.0 +11388 0.0 +11389 0.0 +11390 0.0 +11391 0.0 +11392 0.0 +11393 0.0 +11394 0.0 +11395 0.0 +11396 0.0 +11397 0.0 +11398 0.0 +11399 0.0 +11400 0.0 +11401 0.0 +11402 0.0 +11403 0.0 +11404 0.0 +11405 0.0 +11406 0.0 +11407 0.0 +11408 0.0 +11409 0.0 +11410 0.0 +11411 0.0 +11412 0.0 +11413 0.0 +11414 0.0 +11415 0.0 +11416 0.0 +11417 0.0 +11418 0.0 +11419 0.0 +11420 0.0 +11421 0.0 +11422 0.0 +11423 0.0 +11424 0.0 +11425 0.0 +11426 0.0 +11427 0.0 +11428 0.0 +11429 0.0 +11430 0.0 +11431 0.0 +11432 0.0 +11433 0.0 +11434 0.0 +11435 0.0 +11436 0.0 +11437 0.0 +11438 0.0 +11439 0.0 +11440 0.0 +11441 0.0 +11442 0.0 +11443 0.0 +11444 0.0 +11445 0.0 +11446 0.0 +11447 0.0 +11448 0.0 +11449 0.0 +11450 0.0 +11451 0.0 +11452 0.0 +11453 0.0 +11454 0.0 +11455 0.0 +11456 0.0 +11457 0.0 +11458 0.0 +11459 0.0 +11460 0.0 +11461 0.0 +11462 0.0 +11463 0.0 +11464 0.0 +11465 0.0 +11466 0.0 +11467 0.0 +11468 0.0 +11469 0.0 +11470 0.0 +11471 0.0 +11472 0.0 +11473 0.0 +11474 0.0 +11475 0.0 +11476 0.0 +11477 0.0 +11478 0.0 +11479 0.0 +11480 0.0 +11481 0.0 +11482 0.0 +11483 0.0 +11484 0.0 +11485 0.0 +11486 0.0 +11487 0.0 +11488 0.0 +11489 0.0 +11490 0.0 +11491 0.0 +11492 0.0 +11493 0.0 +11494 0.0 +11495 0.0 +11496 0.0 +11497 0.0 +11498 0.0 +11499 0.0 +11500 0.0 +11501 0.0 +11502 0.0 +11503 0.0 +11504 0.0 +11505 0.0 +11506 0.0 +11507 0.0 +11508 0.0 +11509 0.0 +11510 0.0 +11511 0.0 +11512 0.0 +11513 0.0 +11514 0.0 +11515 0.0 +11516 0.0 +11517 0.0 +11518 0.0 +11519 0.0 +11520 0.0 +11521 0.0 +11522 0.0 +11523 0.0 +11524 0.0 +11525 0.0 +11526 0.0 +11527 0.0 +11528 0.0 +11529 0.0 +11530 0.0 +11531 0.0 +11532 0.0 +11533 0.0 +11534 0.0 +11535 0.0 +11536 0.0 +11537 0.0 +11538 0.0 +11539 0.0 +11540 0.0 +11541 0.0 +11542 0.0 +11543 0.0 +11544 0.0 +11545 0.0 +11546 0.0 +11547 0.0 +11548 0.0 +11549 0.0 +11550 0.0 +11551 0.0 +11552 0.0 +11553 0.0 +11554 0.0 +11555 0.0 +11556 0.0 +11557 0.0 +11558 0.0 +11559 0.0 +11560 0.0 +11561 0.0 +11562 0.0 +11563 0.0 +11564 0.0 +11565 0.0 +11566 0.0 +11567 0.0 +11568 0.0 +11569 0.0 +11570 0.0 +11571 0.0 +11572 0.0 +11573 0.0 +11574 0.0 +11575 0.0 +11576 0.0 +11577 0.0 +11578 0.0 +11579 0.0 +11580 0.0 +11581 0.0 +11582 0.0 +11583 0.0 +11584 0.0 +11585 0.0 +11586 0.0 +11587 0.0 +11588 0.0 +11589 0.0 +11590 0.0 +11591 0.0 +11592 0.0 +11593 0.0 +11594 0.0 +11595 0.0 +11596 0.0 +11597 0.0 +11598 0.0 +11599 0.0 +11600 0.0 +11601 0.0 +11602 0.0 +11603 0.0 +11604 0.0 +11605 0.0 +11606 0.0 +11607 0.0 +11608 0.0 +11609 0.0 +11610 0.0 +11611 0.0 +11612 0.0 +11613 0.0 +11614 0.0 +11615 0.0 +11616 0.0 +11617 0.0 +11618 0.0 +11619 0.0 +11620 0.0 +11621 0.0 +11622 0.0 +11623 0.0 +11624 0.0 +11625 0.0 +11626 0.0 +11627 0.0 +11628 0.0 +11629 0.0 +11630 0.0 +11631 0.0 +11632 0.0 +11633 0.0 +11634 0.0 +11635 0.0 +11636 0.0 +11637 0.0 +11638 0.0 +11639 0.0 +11640 0.0 +11641 0.0 +11642 0.0 +11643 0.0 +11644 0.0 +11645 0.0 +11646 0.0 +11647 0.0 +11648 0.0 +11649 0.0 +11650 0.0 +11651 0.0 +11652 0.0 +11653 0.0 +11654 0.0 +11655 0.0 +11656 0.0 +11657 0.0 +11658 0.0 +11659 0.0 +11660 0.0 +11661 0.0 +11662 0.0 +11663 0.0 +11664 0.0 +11665 0.0 +11666 0.0 +11667 0.0 +11668 0.0 +11669 0.0 +11670 0.0 +11671 0.0 +11672 0.0 +11673 0.0 +11674 0.0 +11675 0.0 +11676 0.0 +11677 0.0 +11678 0.0 +11679 0.0 +11680 0.0 +11681 0.0 +11682 0.0 +11683 0.0 +11684 0.0 +11685 0.0 +11686 0.0 +11687 0.0 +11688 0.0 +11689 0.0 +11690 0.0 +11691 0.0 +11692 0.0 +11693 0.0 +11694 0.0 +11695 0.0 +11696 0.0 +11697 0.0 +11698 0.0 +11699 0.0 +11700 0.0 +11701 0.0 +11702 0.0 +11703 0.0 +11704 0.0 +11705 0.0 +11706 0.0 +11707 0.0 +11708 0.0 +11709 0.0 +11710 0.0 +11711 0.0 +11712 0.0 +11713 0.0 +11714 0.0 +11715 0.0 +11716 0.0 +11717 0.0 +11718 0.0 +11719 0.0 +11720 0.0 +11721 0.0 +11722 0.0 +11723 0.0 +11724 0.0 +11725 0.0 +11726 0.0 +11727 0.0 +11728 0.0 +11729 0.0 +11730 0.0 +11731 0.0 +11732 0.0 +11733 0.0 +11734 0.0 +11735 0.0 +11736 0.0 +11737 0.0 +11738 0.0 +11739 0.0 +11740 0.0 +11741 0.0 +11742 0.0 +11743 0.0 +11744 0.0 +11745 0.0 +11746 0.0 +11747 0.0 +11748 0.0 +11749 0.0 +11750 0.0 +11751 0.0 +11752 0.0 +11753 0.0 +11754 0.0 +11755 0.0 +11756 0.0 +11757 0.0 +11758 0.0 +11759 0.0 +11760 0.0 +11761 0.0 +11762 0.0 +11763 0.0 +11764 0.0 +11765 0.0 +11766 0.0 +11767 0.0 +11768 0.0 +11769 0.0 +11770 0.0 +11771 0.0 +11772 0.0 +11773 0.0 +11774 0.0 +11775 0.0 +11776 0.0 +11777 0.0 +11778 0.0 +11779 0.0 +11780 0.0 +11781 0.0 +11782 0.0 +11783 0.0 +11784 0.0 +11785 0.0 +11786 0.0 +11787 0.0 +11788 0.0 +11789 0.0 +11790 0.0 +11791 0.0 +11792 0.0 +11793 0.0 +11794 0.0 +11795 0.0 +11796 0.0 +11797 0.0 +11798 0.0 +11799 0.0 +11800 0.0 +11801 0.0 +11802 0.0 +11803 0.0 +11804 0.0 +11805 0.0 +11806 0.0 +11807 0.0 +11808 0.0 +11809 0.0 +11810 0.0 +11811 0.0 +11812 0.0 +11813 0.0 +11814 0.0 +11815 0.0 +11816 0.0 +11817 0.0 +11818 0.0 +11819 0.0 +11820 0.0 +11821 0.0 +11822 0.0 +11823 0.0 +11824 0.0 +11825 0.0 +11826 0.0 +11827 0.0 +11828 0.0 +11829 0.0 +11830 0.0 +11831 0.0 +11832 0.0 +11833 0.0 +11834 0.0 +11835 0.0 +11836 0.0 +11837 0.0 +11838 0.0 +11839 0.0 +11840 0.0 +11841 0.0 +11842 0.0 +11843 0.0 +11844 0.0 +11845 0.0 +11846 0.0 +11847 0.0 +11848 0.0 +11849 0.0 +11850 0.0 +11851 0.0 +11852 0.0 +11853 0.0 +11854 0.0 +11855 0.0 +11856 0.0 +11857 0.0 +11858 0.0 +11859 0.0 +11860 0.0 +11861 0.0 +11862 0.0 +11863 0.0 +11864 0.0 +11865 0.0 +11866 0.0 +11867 0.0 +11868 0.0 +11869 0.0 +11870 0.0 +11871 0.0 +11872 0.0 +11873 0.0 +11874 0.0 +11875 0.0 +11876 0.0 +11877 0.0 +11878 0.0 +11879 0.0 +11880 0.0 +11881 0.0 +11882 0.0 +11883 0.0 +11884 0.0 +11885 0.0 +11886 0.0 +11887 0.0 +11888 0.0 +11889 0.0 +11890 0.0 +11891 0.0 +11892 0.0 +11893 0.0 +11894 0.0 +11895 0.0 +11896 0.0 +11897 0.0 +11898 0.0 +11899 0.0 +11900 0.0 +11901 0.0 +11902 0.0 +11903 0.0 +11904 0.0 +11905 0.0 +11906 0.0 +11907 0.0 +11908 0.0 +11909 0.0 +11910 0.0 +11911 0.0 +11912 0.0 +11913 0.0 +11914 0.0 +11915 0.0 +11916 0.0 +11917 0.0 +11918 0.0 +11919 0.0 +11920 0.0 +11921 0.0 +11922 0.0 +11923 0.0 +11924 0.0 +11925 0.0 +11926 0.0 +11927 0.0 +11928 0.0 +11929 0.0 +11930 0.0 +11931 0.0 +11932 0.0 +11933 0.0 +11934 0.0 +11935 0.0 +11936 0.0 +11937 0.0 +11938 0.0 +11939 0.0 +11940 0.0 +11941 0.0 +11942 0.0 +11943 0.0 +11944 0.0 +11945 0.0 +11946 0.0 +11947 0.0 +11948 0.0 +11949 0.0 +11950 0.0 +11951 0.0 +11952 0.0 +11953 0.0 +11954 0.0 +11955 0.0 +11956 0.0 +11957 0.0 +11958 0.0 +11959 0.0 +11960 0.0 +11961 0.0 +11962 0.0 +11963 0.0 +11964 0.0 +11965 0.0 +11966 0.0 +11967 0.0 +11968 0.0 +11969 0.0 +11970 0.0 +11971 0.0 +11972 0.0 +11973 0.0 +11974 0.0 +11975 0.0 +11976 0.0 +11977 0.0 +11978 0.0 +11979 0.0 +11980 0.0 +11981 0.0 +11982 0.0 +11983 0.0 +11984 0.0 +11985 0.0 +11986 0.0 +11987 0.0 +11988 0.0 +11989 0.0 +11990 0.0 +11991 0.0 +11992 0.0 +11993 0.0 +11994 0.0 +11995 0.0 +11996 0.0 +11997 0.0 +11998 0.0 +11999 0.0 +12000 0.0 +12001 0.0 +12002 0.0 +12003 0.0 +12004 0.0 +12005 0.0 +12006 0.0 +12007 0.0 +12008 0.0 +12009 0.0 +12010 0.0 +12011 0.0 +12012 0.0 +12013 0.0 +12014 0.0 +12015 0.0 +12016 0.0 +12017 0.0 +12018 0.0 +12019 0.0 +12020 0.0 +12021 0.0 +12022 0.0 +12023 0.0 +12024 0.0 +12025 0.0 +12026 0.0 +12027 0.0 +12028 0.0 +12029 0.0 +12030 0.0 +12031 0.0 +12032 0.0 +12033 0.0 +12034 0.0 +12035 0.0 +12036 0.0 +12037 0.0 +12038 0.0 +12039 0.0 +12040 0.0 +12041 0.0 +12042 0.0 +12043 0.0 +12044 0.0 +12045 0.0 +12046 0.0 +12047 0.0 +12048 0.0 +12049 0.0 +12050 0.0 +12051 0.0 +12052 0.0 +12053 0.0 +12054 0.0 +12055 0.0 +12056 0.0 +12057 0.0 +12058 0.0 +12059 0.0 +12060 0.0 +12061 0.0 +12062 0.0 +12063 0.0 +12064 0.0 +12065 0.0 +12066 0.0 +12067 0.0 +12068 0.0 +12069 0.0 +12070 0.0 +12071 0.0 +12072 0.0 +12073 0.0 +12074 0.0 +12075 0.0 +12076 0.0 +12077 0.0 +12078 0.0 +12079 0.0 +12080 0.0 +12081 0.0 +12082 0.0 +12083 0.0 +12084 0.0 +12085 0.0 +12086 0.0 +12087 0.0 +12088 0.0 +12089 0.0 +12090 0.0 +12091 0.0 +12092 0.0 +12093 0.0 +12094 0.0 +12095 0.0 +12096 0.0 +12097 0.0 +12098 0.0 +12099 0.0 +12100 0.0 +12101 0.0 +12102 0.0 +12103 0.0 +12104 0.0 +12105 0.0 +12106 0.0 +12107 0.0 +12108 0.0 +12109 0.0 +12110 0.0 +12111 0.0 +12112 0.0 +12113 0.0 +12114 0.0 +12115 0.0 +12116 0.0 +12117 0.0 +12118 0.0 +12119 0.0 +12120 0.0 +12121 0.0 +12122 0.0 +12123 0.0 +12124 0.0 +12125 0.0 +12126 0.0 +12127 0.0 +12128 0.0 +12129 0.0 +12130 0.0 +12131 0.0 +12132 0.0 +12133 0.0 +12134 0.0 +12135 0.0 +12136 0.0 +12137 0.0 +12138 0.0 +12139 0.0 +12140 0.0 +12141 0.0 +12142 0.0 +12143 0.0 +12144 0.0 +12145 0.0 +12146 0.0 +12147 0.0 +12148 0.0 +12149 0.0 +12150 0.0 +12151 0.0 +12152 0.0 +12153 0.0 +12154 0.0 +12155 0.0 +12156 0.0 +12157 0.0 +12158 0.0 +12159 0.0 +12160 0.0 +12161 0.0 +12162 0.0 +12163 0.0 +12164 0.0 +12165 0.0 +12166 0.0 +12167 0.0 +12168 0.0 +12169 0.0 +12170 0.0 +12171 0.0 +12172 0.0 +12173 0.0 +12174 0.0 +12175 0.0 +12176 0.0 +12177 0.0 +12178 0.0 +12179 0.0 +12180 0.0 +12181 0.0 +12182 0.0 +12183 0.0 +12184 0.0 +12185 0.0 +12186 0.0 +12187 0.0 +12188 0.0 +12189 0.0 +12190 0.0 +12191 0.0 +12192 0.0 +12193 0.0 +12194 0.0 +12195 0.0 +12196 0.0 +12197 0.0 +12198 0.0 +12199 0.0 +12200 0.0 +12201 0.0 +12202 0.0 +12203 0.0 +12204 0.0 +12205 0.0 +12206 0.0 +12207 0.0 +12208 0.0 +12209 0.0 +12210 0.0 +12211 0.0 +12212 0.0 +12213 0.0 +12214 0.0 +12215 0.0 +12216 0.0 +12217 0.0 +12218 0.0 +12219 0.0 +12220 0.0 +12221 0.0 +12222 0.0 +12223 0.0 +12224 0.0 +12225 0.0 +12226 0.0 +12227 0.0 +12228 0.0 +12229 0.0 +12230 0.0 +12231 0.0 +12232 0.0 +12233 0.0 +12234 0.0 +12235 0.0 +12236 0.0 +12237 0.0 +12238 0.0 +12239 0.0 +12240 0.0 +12241 0.0 +12242 0.0 +12243 0.0 +12244 0.0 +12245 0.0 +12246 0.0 +12247 0.0 +12248 0.0 +12249 0.0 +12250 0.0 +12251 0.0 +12252 0.0 +12253 0.0 +12254 0.0 +12255 0.0 +12256 0.0 +12257 0.0 +12258 0.0 +12259 0.0 +12260 0.0 +12261 0.0 +12262 0.0 +12263 0.0 +12264 0.0 +12265 0.0 +12266 0.0 +12267 0.0 +12268 0.0 +12269 0.0 +12270 0.0 +12271 0.0 +12272 0.0 +12273 0.0 +12274 0.0 +12275 0.0 +12276 0.0 +12277 0.0 +12278 0.0 +12279 0.0 +12280 0.0 +12281 0.0 +12282 0.0 +12283 0.0 +12284 0.0 +12285 0.0 +12286 0.0 +12287 0.0 +12288 0.0 +12289 0.0 +12290 0.0 +12291 0.0 +12292 0.0 +12293 0.0 +12294 0.0 +12295 0.0 +12296 0.0 +12297 0.0 +12298 0.0 +12299 0.0 +12300 0.0 +12301 0.0 +12302 0.0 +12303 0.0 +12304 0.0 +12305 0.0 +12306 0.0 +12307 0.0 +12308 0.0 +12309 0.0 +12310 0.0 +12311 0.0 +12312 0.0 +12313 0.0 +12314 0.0 +12315 0.0 +12316 0.0 +12317 0.0 +12318 0.0 +12319 0.0 +12320 0.0 +12321 0.0 +12322 0.0 +12323 0.0 +12324 0.0 +12325 0.0 +12326 0.0 +12327 0.0 +12328 0.0 +12329 0.0 +12330 0.0 +12331 0.0 +12332 0.0 +12333 0.0 +12334 0.0 +12335 0.0 +12336 0.0 +12337 0.0 +12338 0.0 +12339 0.0 +12340 0.0 +12341 0.0 +12342 0.0 +12343 0.0 +12344 0.0 +12345 0.0 +12346 0.0 +12347 0.0 +12348 0.0 +12349 0.0 +12350 0.0 +12351 0.0 +12352 0.0 +12353 0.0 +12354 0.0 +12355 0.0 +12356 0.0 +12357 0.0 +12358 0.0 +12359 0.0 +12360 0.0 +12361 0.0 +12362 0.0 +12363 0.0 +12364 0.0 +12365 0.0 +12366 0.0 +12367 0.0 +12368 0.0 +12369 0.0 +12370 0.0 +12371 0.0 +12372 0.0 +12373 0.0 +12374 0.0 +12375 0.0 +12376 0.0 +12377 0.0 +12378 0.0 +12379 0.0 +12380 0.0 +12381 0.0 +12382 0.0 +12383 0.0 +12384 0.0 +12385 0.0 +12386 0.0 +12387 0.0 +12388 0.0 +12389 0.0 +12390 0.0 +12391 0.0 +12392 0.0 +12393 0.0 +12394 0.0 +12395 0.0 +12396 0.0 +12397 0.0 +12398 0.0 +12399 0.0 +12400 0.0 +12401 0.0 +12402 0.0 +12403 0.0 +12404 0.0 +12405 0.0 +12406 0.0 +12407 0.0 +12408 0.0 +12409 0.0 +12410 0.0 +12411 0.0 +12412 0.0 +12413 0.0 +12414 0.0 +12415 0.0 +12416 0.0 +12417 0.0 +12418 0.0 +12419 0.0 +12420 0.0 +12421 0.0 +12422 0.0 +12423 0.0 +12424 0.0 +12425 0.0 +12426 0.0 +12427 0.0 +12428 0.0 +12429 0.0 +12430 0.0 +12431 0.0 +12432 0.0 +12433 0.0 +12434 0.0 +12435 0.0 +12436 0.0 +12437 0.0 +12438 0.0 +12439 0.0 +12440 0.0 +12441 0.0 +12442 0.0 +12443 0.0 +12444 0.0 +12445 0.0 +12446 0.0 +12447 0.0 +12448 0.0 +12449 0.0 +12450 0.0 +12451 0.0 +12452 0.0 +12453 0.0 +12454 0.0 +12455 0.0 +12456 0.0 +12457 0.0 +12458 0.0 +12459 0.0 +12460 0.0 +12461 0.0 +12462 0.0 +12463 0.0 +12464 0.0 +12465 0.0 +12466 0.0 +12467 0.0 +12468 0.0 +12469 0.0 +12470 0.0 +12471 0.0 +12472 0.0 +12473 0.0 +12474 0.0 +12475 0.0 +12476 0.0 +12477 0.0 +12478 0.0 +12479 0.0 +12480 0.0 +12481 0.0 +12482 0.0 +12483 0.0 +12484 0.0 +12485 0.0 +12486 0.0 +12487 0.0 +12488 0.0 +12489 0.0 +12490 0.0 +12491 0.0 +12492 0.0 +12493 0.0 +12494 0.0 +12495 0.0 +12496 0.0 +12497 0.0 +12498 0.0 +12499 0.0 +12500 0.0 +12501 0.0 +12502 0.0 +12503 0.0 +12504 0.0 +12505 0.0 +12506 0.0 +12507 0.0 +12508 0.0 +12509 0.0 +12510 0.0 +12511 0.0 +12512 0.0 +12513 0.0 +12514 0.0 +12515 0.0 +12516 0.0 +12517 0.0 +12518 0.0 +12519 0.0 +12520 0.0 +12521 0.0 +12522 0.0 +12523 0.0 +12524 0.0 +12525 0.0 +12526 0.0 +12527 0.0 +12528 0.0 +12529 0.0 +12530 0.0 +12531 0.0 +12532 0.0 +12533 0.0 +12534 0.0 +12535 0.0 +12536 0.0 +12537 0.0 +12538 0.0 +12539 0.0 +12540 0.0 +12541 0.0 +12542 0.0 +12543 0.0 +12544 0.0 +12545 0.0 +12546 0.0 +12547 0.0 +12548 0.0 +12549 0.0 +12550 0.0 +12551 0.0 +12552 0.0 +12553 0.0 +12554 0.0 +12555 0.0 +12556 0.0 +12557 0.0 +12558 0.0 +12559 0.0 +12560 0.0 +12561 0.0 +12562 0.0 +12563 0.0 +12564 0.0 +12565 0.0 +12566 0.0 +12567 0.0 +12568 0.0 +12569 0.0 +12570 0.0 +12571 0.0 +12572 0.0 +12573 0.0 +12574 0.0 +12575 0.0 +12576 0.0 +12577 0.0 +12578 0.0 +12579 0.0 +12580 0.0 +12581 0.0 +12582 0.0 +12583 0.0 +12584 0.0 +12585 0.0 +12586 0.0 +12587 0.0 +12588 0.0 +12589 0.0 +12590 0.0 +12591 0.0 +12592 0.0 +12593 0.0 +12594 0.0 +12595 0.0 +12596 0.0 +12597 0.0 +12598 0.0 +12599 0.0 +12600 0.0 +12601 0.0 +12602 0.0 +12603 0.0 +12604 0.0 +12605 0.0 +12606 0.0 +12607 0.0 +12608 0.0 +12609 0.0 +12610 0.0 +12611 0.0 +12612 0.0 +12613 0.0 +12614 0.0 +12615 0.0 +12616 0.0 +12617 0.0 +12618 0.0 +12619 0.0 +12620 0.0 +12621 0.0 +12622 0.0 +12623 0.0 +12624 0.0 +12625 0.0 +12626 0.0 +12627 0.0 +12628 0.0 +12629 0.0 +12630 0.0 +12631 0.0 +12632 0.0 +12633 0.0 +12634 0.0 +12635 0.0 +12636 0.0 +12637 0.0 +12638 0.0 +12639 0.0 +12640 0.0 +12641 0.0 +12642 0.0 +12643 0.0 +12644 0.0 +12645 0.0 +12646 0.0 +12647 0.0 +12648 0.0 +12649 0.0 +12650 0.0 +12651 0.0 +12652 0.0 +12653 0.0 +12654 0.0 +12655 0.0 +12656 0.0 +12657 0.0 +12658 0.0 +12659 0.0 +12660 0.0 +12661 0.0 +12662 0.0 +12663 0.0 +12664 0.0 +12665 0.0 +12666 0.0 +12667 0.0 +12668 0.0 +12669 0.0 +12670 0.0 +12671 0.0 +12672 0.0 +12673 0.0 +12674 0.0 +12675 0.0 +12676 0.0 +12677 0.0 +12678 0.0 +12679 0.0 +12680 0.0 +12681 0.0 +12682 0.0 +12683 0.0 +12684 0.0 +12685 0.0 +12686 0.0 +12687 0.0 +12688 0.0 +12689 0.0 +12690 0.0 +12691 0.0 +12692 0.0 +12693 0.0 +12694 0.0 +12695 0.0 +12696 0.0 +12697 0.0 +12698 0.0 +12699 0.0 +12700 0.0 +12701 0.0 +12702 0.0 +12703 0.0 +12704 0.0 +12705 0.0 +12706 0.0 +12707 0.0 +12708 0.0 +12709 0.0 +12710 0.0 +12711 0.0 +12712 0.0 +12713 0.0 +12714 0.0 +12715 0.0 +12716 0.0 +12717 0.0 +12718 0.0 +12719 0.0 +12720 0.0 +12721 0.0 +12722 0.0 +12723 0.0 +12724 0.0 +12725 0.0 +12726 0.0 +12727 0.0 +12728 0.0 +12729 0.0 +12730 0.0 +12731 0.0 +12732 0.0 +12733 0.0 +12734 0.0 +12735 0.0 +12736 0.0 +12737 0.0 +12738 0.0 +12739 0.0 +12740 0.0 +12741 0.0 +12742 0.0 +12743 0.0 +12744 0.0 +12745 0.0 +12746 0.0 +12747 0.0 +12748 0.0 +12749 0.0 +12750 0.0 +12751 0.0 +12752 0.0 +12753 0.0 +12754 0.0 +12755 0.0 +12756 0.0 +12757 0.0 +12758 0.0 +12759 0.0 +12760 0.0 +12761 0.0 +12762 0.0 +12763 0.0 +12764 0.0 +12765 0.0 +12766 0.0 +12767 0.0 +12768 0.0 +12769 0.0 +12770 0.0 +12771 0.0 +12772 0.0 +12773 0.0 +12774 0.0 +12775 0.0 +12776 0.0 +12777 0.0 +12778 0.0 +12779 0.0 +12780 0.0 +12781 0.0 +12782 0.0 +12783 0.0 +12784 0.0 +12785 0.0 +12786 0.0 +12787 0.0 +12788 0.0 +12789 0.0 +12790 0.0 +12791 0.0 +12792 0.0 +12793 0.0 +12794 0.0 +12795 0.0 +12796 0.0 +12797 0.0 +12798 0.0 +12799 0.0 +12800 0.0 +12801 0.0 +12802 0.0 +12803 0.0 +12804 0.0 +12805 0.0 +12806 0.0 +12807 0.0 +12808 0.0 +12809 0.0 +12810 0.0 +12811 0.0 +12812 0.0 +12813 0.0 +12814 0.0 +12815 0.0 +12816 0.0 +12817 0.0 +12818 0.0 +12819 0.0 +12820 0.0 +12821 0.0 +12822 0.0 +12823 0.0 +12824 0.0 +12825 0.0 +12826 0.0 +12827 0.0 +12828 0.0 +12829 0.0 +12830 0.0 +12831 0.0 +12832 0.0 +12833 0.0 +12834 0.0 +12835 0.0 +12836 0.0 +12837 0.0 +12838 0.0 +12839 0.0 +12840 0.0 +12841 0.0 +12842 0.0 +12843 0.0 +12844 0.0 +12845 0.0 +12846 0.0 +12847 0.0 +12848 0.0 +12849 0.0 +12850 0.0 +12851 0.0 +12852 0.0 +12853 0.0 +12854 0.0 +12855 0.0 +12856 0.0 +12857 0.0 +12858 0.0 +12859 0.0 +12860 0.0 +12861 0.0 +12862 0.0 +12863 0.0 +12864 0.0 +12865 0.0 +12866 0.0 +12867 0.0 +12868 0.0 +12869 0.0 +12870 0.0 +12871 0.0 +12872 0.0 +12873 0.0 +12874 0.0 +12875 0.0 +12876 0.0 +12877 0.0 +12878 0.0 +12879 0.0 +12880 0.0 +12881 0.0 +12882 0.0 +12883 0.0 +12884 0.0 +12885 0.0 +12886 0.0 +12887 0.0 +12888 0.0 +12889 0.0 +12890 0.0 +12891 0.0 +12892 0.0 +12893 0.0 +12894 0.0 +12895 0.0 +12896 0.0 +12897 0.0 +12898 0.0 +12899 0.0 +12900 0.0 +12901 0.0 +12902 0.0 +12903 0.0 +12904 0.0 +12905 0.0 +12906 0.0 +12907 0.0 +12908 0.0 +12909 0.0 +12910 0.0 +12911 0.0 +12912 0.0 +12913 0.0 +12914 0.0 +12915 0.0 +12916 0.0 +12917 0.0 +12918 0.0 +12919 0.0 +12920 0.0 +12921 0.0 +12922 0.0 +12923 0.0 +12924 0.0 +12925 0.0 +12926 0.0 +12927 0.0 +12928 0.0 +12929 0.0 +12930 0.0 +12931 0.0 +12932 0.0 +12933 0.0 +12934 0.0 +12935 0.0 +12936 0.0 +12937 0.0 +12938 0.0 +12939 0.0 +12940 0.0 +12941 0.0 +12942 0.0 +12943 0.0 +12944 0.0 +12945 0.0 +12946 0.0 +12947 0.0 +12948 0.0 +12949 0.0 +12950 0.0 +12951 0.0 +12952 0.0 +12953 0.0 +12954 0.0 +12955 0.0 +12956 0.0 +12957 0.0 +12958 0.0 +12959 0.0 +12960 0.0 +12961 0.0 +12962 0.0 +12963 0.0 +12964 0.0 +12965 0.0 +12966 0.0 +12967 0.0 +12968 0.0 +12969 0.0 +12970 0.0 +12971 0.0 +12972 0.0 +12973 0.0 +12974 0.0 +12975 0.0 +12976 0.0 +12977 0.0 +12978 0.0 +12979 0.0 +12980 0.0 +12981 0.0 +12982 0.0 +12983 0.0 +12984 0.0 +12985 0.0 +12986 0.0 +12987 0.0 +12988 0.0 +12989 0.0 +12990 0.0 +12991 0.0 +12992 0.0 +12993 0.0 +12994 0.0 +12995 0.0 +12996 0.0 +12997 0.0 +12998 0.0 +12999 0.0 +13000 0.0 +13001 0.0 +13002 0.0 +13003 0.0 +13004 0.0 +13005 0.0 +13006 0.0 +13007 0.0 +13008 0.0 +13009 0.0 +13010 0.0 +13011 0.0 +13012 0.0 +13013 0.0 +13014 0.0 +13015 0.0 +13016 0.0 +13017 0.0 +13018 0.0 +13019 0.0 +13020 0.0 +13021 0.0 +13022 0.0 +13023 0.0 +13024 0.0 +13025 0.0 +13026 0.0 +13027 0.0 +13028 0.0 +13029 0.0 +13030 0.0 +13031 0.0 +13032 0.0 +13033 0.0 +13034 0.0 +13035 0.0 +13036 0.0 +13037 0.0 +13038 0.0 +13039 0.0 +13040 0.0 +13041 0.0 +13042 0.0 +13043 0.0 +13044 0.0 +13045 0.0 +13046 0.0 +13047 0.0 +13048 0.0 +13049 0.0 +13050 0.0 +13051 0.0 +13052 0.0 +13053 0.0 +13054 0.0 +13055 0.0 +13056 0.0 +13057 0.0 +13058 0.0 +13059 0.0 +13060 0.0 +13061 0.0 +13062 0.0 +13063 0.0 +13064 0.0 +13065 0.0 +13066 0.0 +13067 0.0 +13068 0.0 +13069 0.0 +13070 0.0 +13071 0.0 +13072 0.0 +13073 0.0 +13074 0.0 +13075 0.0 +13076 0.0 +13077 0.0 +13078 0.0 +13079 0.0 +13080 0.0 +13081 0.0 +13082 0.0 +13083 0.0 +13084 0.0 +13085 0.0 +13086 0.0 +13087 0.0 +13088 0.0 +13089 0.0 +13090 0.0 +13091 0.0 +13092 0.0 +13093 0.0 +13094 0.0 +13095 0.0 +13096 0.0 +13097 0.0 +13098 0.0 +13099 0.0 +13100 0.0 +13101 0.0 +13102 0.0 +13103 0.0 +13104 0.0 +13105 0.0 +13106 0.0 +13107 0.0 +13108 0.0 +13109 0.0 +13110 0.0 +13111 0.0 +13112 0.0 +13113 0.0 +13114 0.0 +13115 0.0 +13116 0.0 +13117 0.0 +13118 0.0 +13119 0.0 +13120 0.0 +13121 0.0 +13122 0.0 +13123 0.0 +13124 0.0 +13125 0.0 +13126 0.0 +13127 0.0 +13128 0.0 +13129 0.0 +13130 0.0 +13131 0.0 +13132 0.0 +13133 0.0 +13134 0.0 +13135 0.0 +13136 0.0 +13137 0.0 +13138 0.0 +13139 0.0 +13140 0.0 +13141 0.0 +13142 0.0 +13143 0.0 +13144 0.0 +13145 0.0 +13146 0.0 +13147 0.0 +13148 0.0 +13149 0.0 +13150 0.0 +13151 0.0 +13152 0.0 +13153 0.0 +13154 0.0 +13155 0.0 +13156 0.0 +13157 0.0 +13158 0.0 +13159 0.0 +13160 0.0 +13161 0.0 +13162 0.0 +13163 0.0 +13164 0.0 +13165 0.0 +13166 0.0 +13167 0.0 +13168 0.0 +13169 0.0 +13170 0.0 +13171 0.0 +13172 0.0 +13173 0.0 +13174 0.0 +13175 0.0 +13176 0.0 +13177 0.0 +13178 0.0 +13179 0.0 +13180 0.0 +13181 0.0 +13182 0.0 +13183 0.0 +13184 0.0 +13185 0.0 +13186 0.0 +13187 0.0 +13188 0.0 +13189 0.0 +13190 0.0 +13191 0.0 +13192 0.0 +13193 0.0 +13194 0.0 +13195 0.0 +13196 0.0 +13197 0.0 +13198 0.0 +13199 0.0 +13200 0.0 +13201 0.0 +13202 0.0 +13203 0.0 +13204 0.0 +13205 0.0 +13206 0.0 +13207 0.0 +13208 0.0 +13209 0.0 +13210 0.0 +13211 0.0 +13212 0.0 +13213 0.0 +13214 0.0 +13215 0.0 +13216 0.0 +13217 0.0 +13218 0.0 +13219 0.0 +13220 0.0 +13221 0.0 +13222 0.0 +13223 0.0 +13224 0.0 +13225 0.0 +13226 0.0 +13227 0.0 +13228 0.0 +13229 0.0 +13230 0.0 +13231 0.0 +13232 0.0 +13233 0.0 +13234 0.0 +13235 0.0 +13236 0.0 +13237 0.0 +13238 0.0 +13239 0.0 +13240 0.0 +13241 0.0 +13242 0.0 +13243 0.0 +13244 0.0 +13245 0.0 +13246 0.0 +13247 0.0 +13248 0.0 +13249 0.0 +13250 0.0 +13251 0.0 +13252 0.0 +13253 0.0 +13254 0.0 +13255 0.0 +13256 0.0 +13257 0.0 +13258 0.0 +13259 0.0 +13260 0.0 +13261 0.0 +13262 0.0 +13263 0.0 +13264 0.0 +13265 0.0 +13266 0.0 +13267 0.0 +13268 0.0 +13269 0.0 +13270 0.0 +13271 0.0 +13272 0.0 +13273 0.0 +13274 0.0 +13275 0.0 +13276 0.0 +13277 0.0 +13278 0.0 +13279 0.0 +13280 0.0 +13281 0.0 +13282 0.0 +13283 0.0 +13284 0.0 +13285 0.0 +13286 0.0 +13287 0.0 +13288 0.0 +13289 0.0 +13290 0.0 +13291 0.0 +13292 0.0 +13293 0.0 +13294 0.0 +13295 0.0 +13296 0.0 +13297 0.0 +13298 0.0 +13299 0.0 +13300 0.0 +13301 0.0 +13302 0.0 +13303 0.0 +13304 0.0 +13305 0.0 +13306 0.0 +13307 0.0 +13308 0.0 +13309 0.0 +13310 0.0 +13311 0.0 +13312 0.0 +13313 0.0 +13314 0.0 +13315 0.0 +13316 0.0 +13317 0.0 +13318 0.0 +13319 0.0 +13320 0.0 +13321 0.0 +13322 0.0 +13323 0.0 +13324 0.0 +13325 0.0 +13326 0.0 +13327 0.0 +13328 0.0 +13329 0.0 +13330 0.0 +13331 0.0 +13332 0.0 +13333 0.0 +13334 0.0 +13335 0.0 +13336 0.0 +13337 0.0 +13338 0.0 +13339 0.0 +13340 0.0 +13341 0.0 +13342 0.0 +13343 0.0 +13344 0.0 +13345 0.0 +13346 0.0 +13347 0.0 +13348 0.0 +13349 0.0 +13350 0.0 +13351 0.0 +13352 0.0 +13353 0.0 +13354 0.0 +13355 0.0 +13356 0.0 +13357 0.0 +13358 0.0 +13359 0.0 +13360 0.0 +13361 0.0 +13362 0.0 +13363 0.0 +13364 0.0 +13365 0.0 +13366 0.0 +13367 0.0 +13368 0.0 +13369 0.0 +13370 0.0 +13371 0.0 +13372 0.0 +13373 0.0 +13374 0.0 +13375 0.0 +13376 0.0 +13377 0.0 +13378 0.0 +13379 0.0 +13380 0.0 +13381 0.0 +13382 0.0 +13383 0.0 +13384 0.0 +13385 0.0 +13386 0.0 +13387 0.0 +13388 0.0 +13389 0.0 +13390 0.0 +13391 0.0 +13392 0.0 +13393 0.0 +13394 0.0 +13395 0.0 +13396 0.0 +13397 0.0 +13398 0.0 +13399 0.0 +13400 0.0 +13401 0.0 +13402 0.0 +13403 0.0 +13404 0.0 +13405 0.0 +13406 0.0 +13407 0.0 +13408 0.0 +13409 0.0 +13410 0.0 +13411 0.0 +13412 0.0 +13413 0.0 +13414 0.0 +13415 0.0 +13416 0.0 +13417 0.0 +13418 0.0 +13419 0.0 +13420 0.0 +13421 0.0 +13422 0.0 +13423 0.0 +13424 0.0 +13425 0.0 +13426 0.0 +13427 0.0 +13428 0.0 +13429 0.0 +13430 0.0 +13431 0.0 +13432 0.0 +13433 0.0 +13434 0.0 +13435 0.0 +13436 0.0 +13437 0.0 +13438 0.0 +13439 0.0 +13440 0.0 +13441 0.0 +13442 0.0 +13443 0.0 +13444 0.0 +13445 0.0 +13446 0.0 +13447 0.0 +13448 0.0 +13449 0.0 +13450 0.0 +13451 0.0 +13452 0.0 +13453 0.0 +13454 0.0 +13455 0.0 +13456 0.0 +13457 0.0 +13458 0.0 +13459 0.0 +13460 0.0 +13461 0.0 +13462 0.0 +13463 0.0 +13464 0.0 +13465 0.0 +13466 0.0 +13467 0.0 +13468 0.0 +13469 0.0 +13470 0.0 +13471 0.0 +13472 0.0 +13473 0.0 +13474 0.0 +13475 0.0 +13476 0.0 +13477 0.0 +13478 0.0 +13479 0.0 +13480 0.0 +13481 0.0 +13482 0.0 +13483 0.0 +13484 0.0 +13485 0.0 +13486 0.0 +13487 0.0 +13488 0.0 +13489 0.0 +13490 0.0 +13491 0.0 +13492 0.0 +13493 0.0 +13494 0.0 +13495 0.0 +13496 0.0 +13497 0.0 +13498 0.0 +13499 0.0 +13500 0.0 +13501 0.0 +13502 0.0 +13503 0.0 +13504 0.0 +13505 0.0 +13506 0.0 +13507 0.0 +13508 0.0 +13509 0.0 +13510 0.0 +13511 0.0 +13512 0.0 +13513 0.0 +13514 0.0 +13515 0.0 +13516 0.0 +13517 0.0 +13518 0.0 +13519 0.0 +13520 0.0 +13521 0.0 +13522 0.0 +13523 0.0 +13524 0.0 +13525 0.0 +13526 0.0 +13527 0.0 +13528 0.0 +13529 0.0 +13530 0.0 +13531 0.0 +13532 0.0 +13533 0.0 +13534 0.0 +13535 0.0 +13536 0.0 +13537 0.0 +13538 0.0 +13539 0.0 +13540 0.0 +13541 0.0 +13542 0.0 +13543 0.0 +13544 0.0 +13545 0.0 +13546 0.0 +13547 0.0 +13548 0.0 +13549 0.0 +13550 0.0 +13551 0.0 +13552 0.0 +13553 0.0 +13554 0.0 +13555 0.0 +13556 0.0 +13557 0.0 +13558 0.0 +13559 0.0 +13560 0.0 +13561 0.0 +13562 0.0 +13563 0.0 +13564 0.0 +13565 0.0 +13566 0.0 +13567 0.0 +13568 0.0 +13569 0.0 +13570 0.0 +13571 0.0 +13572 0.0 +13573 0.0 +13574 0.0 +13575 0.0 +13576 0.0 +13577 0.0 +13578 0.0 +13579 0.0 +13580 0.0 +13581 0.0 +13582 0.0 +13583 0.0 +13584 0.0 +13585 0.0 +13586 0.0 +13587 0.0 +13588 0.0 +13589 0.0 +13590 0.0 +13591 0.0 +13592 0.0 +13593 0.0 +13594 0.0 +13595 0.0 +13596 0.0 +13597 0.0 +13598 0.0 +13599 0.0 +13600 0.0 +13601 0.0 +13602 0.0 +13603 0.0 +13604 0.0 +13605 0.0 +13606 0.0 +13607 0.0 +13608 0.0 +13609 0.0 +13610 0.0 +13611 0.0 +13612 0.0 +13613 0.0 +13614 0.0 +13615 0.0 +13616 0.0 +13617 0.0 +13618 0.0 +13619 0.0 +13620 0.0 +13621 0.0 +13622 0.0 +13623 0.0 +13624 0.0 +13625 0.0 +13626 0.0 +13627 0.0 +13628 0.0 +13629 0.0 +13630 0.0 +13631 0.0 +13632 0.0 +13633 0.0 +13634 0.0 +13635 0.0 +13636 0.0 +13637 0.0 +13638 0.0 +13639 0.0 +13640 0.0 +13641 0.0 +13642 0.0 +13643 0.0 +13644 0.0 +13645 0.0 +13646 0.0 +13647 0.0 +13648 0.0 +13649 0.0 +13650 0.0 +13651 0.0 +13652 0.0 +13653 0.0 +13654 0.0 +13655 0.0 +13656 0.0 +13657 0.0 +13658 0.0 +13659 0.0 +13660 0.0 +13661 0.0 +13662 0.0 +13663 0.0 +13664 0.0 +13665 0.0 +13666 0.0 +13667 0.0 +13668 0.0 +13669 0.0 +13670 0.0 +13671 0.0 +13672 0.0 +13673 0.0 +13674 0.0 +13675 0.0 +13676 0.0 +13677 0.0 +13678 0.0 +13679 0.0 +13680 0.0 +13681 0.0 +13682 0.0 +13683 0.0 +13684 0.0 +13685 0.0 +13686 0.0 +13687 0.0 +13688 0.0 +13689 0.0 +13690 0.0 +13691 0.0 +13692 0.0 +13693 0.0 +13694 0.0 +13695 0.0 +13696 0.0 +13697 0.0 +13698 0.0 +13699 0.0 +13700 0.0 +13701 0.0 +13702 0.0 +13703 0.0 +13704 0.0 +13705 0.0 +13706 0.0 +13707 0.0 +13708 0.0 +13709 0.0 +13710 0.0 +13711 0.0 +13712 0.0 +13713 0.0 +13714 0.0 +13715 0.0 +13716 0.0 +13717 0.0 +13718 0.0 +13719 0.0 +13720 0.0 +13721 0.0 +13722 0.0 +13723 0.0 +13724 0.0 +13725 0.0 +13726 0.0 +13727 0.0 +13728 0.0 +13729 0.0 +13730 0.0 +13731 0.0 +13732 0.0 +13733 0.0 +13734 0.0 +13735 0.0 +13736 0.0 +13737 0.0 +13738 0.0 +13739 0.0 +13740 0.0 +13741 0.0 +13742 0.0 +13743 0.0 +13744 0.0 +13745 0.0 +13746 0.0 +13747 0.0 +13748 0.0 +13749 0.0 +13750 0.0 +13751 0.0 +13752 0.0 +13753 0.0 +13754 0.0 +13755 0.0 +13756 0.0 +13757 0.0 +13758 0.0 +13759 0.0 +13760 0.0 +13761 0.0 +13762 0.0 +13763 0.0 +13764 0.0 +13765 0.0 +13766 0.0 +13767 0.0 +13768 0.0 +13769 0.0 +13770 0.0 +13771 0.0 +13772 0.0 +13773 0.0 +13774 0.0 +13775 0.0 +13776 0.0 +13777 0.0 +13778 0.0 +13779 0.0 +13780 0.0 +13781 0.0 +13782 0.0 +13783 0.0 +13784 0.0 +13785 0.0 +13786 0.0 +13787 0.0 +13788 0.0 +13789 0.0 +13790 0.0 +13791 0.0 +13792 0.0 +13793 0.0 +13794 0.0 +13795 0.0 +13796 0.0 +13797 0.0 +13798 0.0 +13799 0.0 +13800 0.0 +13801 0.0 +13802 0.0 +13803 0.0 +13804 0.0 +13805 0.0 +13806 0.0 +13807 0.0 +13808 0.0 +13809 0.0 +13810 0.0 +13811 0.0 +13812 0.0 +13813 0.0 +13814 0.0 +13815 0.0 +13816 0.0 +13817 0.0 +13818 0.0 +13819 0.0 +13820 0.0 +13821 0.0 +13822 0.0 +13823 0.0 +13824 0.0 +13825 0.0 +13826 0.0 +13827 0.0 +13828 0.0 +13829 0.0 +13830 0.0 +13831 0.0 +13832 0.0 +13833 0.0 +13834 0.0 +13835 0.0 +13836 0.0 +13837 0.0 +13838 0.0 +13839 0.0 +13840 0.0 +13841 0.0 +13842 0.0 +13843 0.0 +13844 0.0 +13845 0.0 +13846 0.0 +13847 0.0 +13848 0.0 +13849 0.0 +13850 0.0 +13851 0.0 +13852 0.0 +13853 0.0 +13854 0.0 +13855 0.0 +13856 0.0 +13857 0.0 +13858 0.0 +13859 0.0 +13860 0.0 +13861 0.0 +13862 0.0 +13863 0.0 +13864 0.0 +13865 0.0 +13866 0.0 +13867 0.0 +13868 0.0 +13869 0.0 +13870 0.0 +13871 0.0 +13872 0.0 +13873 0.0 +13874 0.0 +13875 0.0 +13876 0.0 +13877 0.0 +13878 0.0 +13879 0.0 +13880 0.0 +13881 0.0 +13882 0.0 +13883 0.0 +13884 0.0 +13885 0.0 +13886 0.0 +13887 0.0 +13888 0.0 +13889 0.0 +13890 0.0 +13891 0.0 +13892 0.0 +13893 0.0 +13894 0.0 +13895 0.0 +13896 0.0 +13897 0.0 +13898 0.0 +13899 0.0 +13900 0.0 +13901 0.0 +13902 0.0 +13903 0.0 +13904 0.0 +13905 0.0 +13906 0.0 +13907 0.0 +13908 0.0 +13909 0.0 +13910 0.0 +13911 0.0 +13912 0.0 +13913 0.0 +13914 0.0 +13915 0.0 +13916 0.0 +13917 0.0 +13918 0.0 +13919 0.0 +13920 0.0 +13921 0.0 +13922 0.0 +13923 0.0 +13924 0.0 +13925 0.0 +13926 0.0 +13927 0.0 +13928 0.0 +13929 0.0 +13930 0.0 +13931 0.0 +13932 0.0 +13933 0.0 +13934 0.0 +13935 0.0 +13936 0.0 +13937 0.0 +13938 0.0 +13939 0.0 +13940 0.0 +13941 0.0 +13942 0.0 +13943 0.0 +13944 0.0 +13945 0.0 +13946 0.0 +13947 0.0 +13948 0.0 +13949 0.0 +13950 0.0 +13951 0.0 +13952 0.0 +13953 0.0 +13954 0.0 +13955 0.0 +13956 0.0 +13957 0.0 +13958 0.0 +13959 0.0 +13960 0.0 +13961 0.0 +13962 0.0 +13963 0.0 +13964 0.0 +13965 0.0 +13966 0.0 +13967 0.0 +13968 0.0 +13969 0.0 +13970 0.0 +13971 0.0 +13972 0.0 +13973 0.0 +13974 0.0 +13975 0.0 +13976 0.0 +13977 0.0 +13978 0.0 +13979 0.0 +13980 0.0 +13981 0.0 +13982 0.0 +13983 0.0 +13984 0.0 +13985 0.0 +13986 0.0 +13987 0.0 +13988 0.0 +13989 0.0 +13990 0.0 +13991 0.0 +13992 0.0 +13993 0.0 +13994 0.0 +13995 0.0 +13996 0.0 +13997 0.0 +13998 0.0 +13999 0.0 +14000 0.0 +14001 0.0 +14002 0.0 +14003 0.0 +14004 0.0 +14005 0.0 +14006 0.0 +14007 0.0 +14008 0.0 +14009 0.0 +14010 0.0 +14011 0.0 +14012 0.0 +14013 0.0 +14014 0.0 +14015 0.0 +14016 0.0 +14017 0.0 +14018 0.0 +14019 0.0 +14020 0.0 +14021 0.0 +14022 0.0 +14023 0.0 +14024 0.0 +14025 0.0 +14026 0.0 +14027 0.0 +14028 0.0 +14029 0.0 +14030 0.0 +14031 0.0 +14032 0.0 +14033 0.0 +14034 0.0 +14035 0.0 +14036 0.0 +14037 0.0 +14038 0.0 +14039 0.0 +14040 0.0 +14041 0.0 +14042 0.0 +14043 0.0 +14044 0.0 +14045 0.0 +14046 0.0 +14047 0.0 +14048 0.0 +14049 0.0 +14050 0.0 +14051 0.0 +14052 0.0 +14053 0.0 +14054 0.0 +14055 0.0 +14056 0.0 +14057 0.0 +14058 0.0 +14059 0.0 +14060 0.0 +14061 0.0 +14062 0.0 +14063 0.0 +14064 0.0 +14065 0.0 +14066 0.0 +14067 0.0 +14068 0.0 +14069 0.0 +14070 0.0 +14071 0.0 +14072 0.0 +14073 0.0 +14074 0.0 +14075 0.0 +14076 0.0 +14077 0.0 +14078 0.0 +14079 0.0 +14080 0.0 +14081 0.0 +14082 0.0 +14083 0.0 +14084 0.0 +14085 0.0 +14086 0.0 +14087 0.0 +14088 0.0 +14089 0.0 +14090 0.0 +14091 0.0 +14092 0.0 +14093 0.0 +14094 0.0 +14095 0.0 +14096 0.0 +14097 0.0 +14098 0.0 +14099 0.0 +14100 0.0 +14101 0.0 +14102 0.0 +14103 0.0 +14104 0.0 +14105 0.0 +14106 0.0 +14107 0.0 +14108 0.0 +14109 0.0 +14110 0.0 +14111 0.0 +14112 0.0 +14113 0.0 +14114 0.0 +14115 0.0 +14116 0.0 +14117 0.0 +14118 0.0 +14119 0.0 +14120 0.0 +14121 0.0 +14122 0.0 +14123 0.0 +14124 0.0 +14125 0.0 +14126 0.0 +14127 0.0 +14128 0.0 +14129 0.0 +14130 0.0 +14131 0.0 +14132 0.0 +14133 0.0 +14134 0.0 +14135 0.0 +14136 0.0 +14137 0.0 +14138 0.0 +14139 0.0 +14140 0.0 +14141 0.0 +14142 0.0 +14143 0.0 +14144 0.0 +14145 0.0 +14146 0.0 +14147 0.0 +14148 0.0 +14149 0.0 +14150 0.0 +14151 0.0 +14152 0.0 +14153 0.0 +14154 0.0 +14155 0.0 +14156 0.0 +14157 0.0 +14158 0.0 +14159 0.0 +14160 0.0 +14161 0.0 +14162 0.0 +14163 0.0 +14164 0.0 +14165 0.0 +14166 0.0 +14167 0.0 +14168 0.0 +14169 0.0 +14170 0.0 +14171 0.0 +14172 0.0 +14173 0.0 +14174 0.0 +14175 0.0 +14176 0.0 +14177 0.0 +14178 0.0 +14179 0.0 +14180 0.0 +14181 0.0 +14182 0.0 +14183 0.0 +14184 0.0 +14185 0.0 +14186 0.0 +14187 0.0 +14188 0.0 +14189 0.0 +14190 0.0 +14191 0.0 +14192 0.0 +14193 0.0 +14194 0.0 +14195 0.0 +14196 0.0 +14197 0.0 +14198 0.0 +14199 0.0 +14200 0.0 +14201 0.0 +14202 0.0 +14203 0.0 +14204 0.0 +14205 0.0 +14206 0.0 +14207 0.0 +14208 0.0 +14209 0.0 +14210 0.0 +14211 0.0 +14212 0.0 +14213 0.0 +14214 0.0 +14215 0.0 +14216 0.0 +14217 0.0 +14218 0.0 +14219 0.0 +14220 0.0 +14221 0.0 +14222 0.0 +14223 0.0 +14224 0.0 +14225 0.0 +14226 0.0 +14227 0.0 +14228 0.0 +14229 0.0 +14230 0.0 +14231 0.0 +14232 0.0 +14233 0.0 +14234 0.0 +14235 0.0 +14236 0.0 +14237 0.0 +14238 0.0 +14239 0.0 +14240 0.0 +14241 0.0 +14242 0.0 +14243 0.0 +14244 0.0 +14245 0.0 +14246 0.0 +14247 0.0 +14248 0.0 +14249 0.0 +14250 0.0 +14251 0.0 +14252 0.0 +14253 0.0 +14254 0.0 +14255 0.0 +14256 0.0 +14257 0.0 +14258 0.0 +14259 0.0 +14260 0.0 +14261 0.0 +14262 0.0 +14263 0.0 +14264 0.0 +14265 0.0 +14266 0.0 +14267 0.0 +14268 0.0 +14269 0.0 +14270 0.0 +14271 0.0 +14272 0.0 +14273 0.0 +14274 0.0 +14275 0.0 +14276 0.0 +14277 0.0 +14278 0.0 +14279 0.0 +14280 0.0 +14281 0.0 +14282 0.0 +14283 0.0 +14284 0.0 +14285 0.0 +14286 0.0 +14287 0.0 +14288 0.0 +14289 0.0 +14290 0.0 +14291 0.0 +14292 0.0 +14293 0.0 +14294 0.0 +14295 0.0 +14296 0.0 +14297 0.0 +14298 0.0 +14299 0.0 +14300 0.0 +14301 0.0 +14302 0.0 +14303 0.0 +14304 0.0 +14305 0.0 +14306 0.0 +14307 0.0 +14308 0.0 +14309 0.0 +14310 0.0 +14311 0.0 +14312 0.0 +14313 0.0 +14314 0.0 +14315 0.0 +14316 0.0 +14317 0.0 +14318 0.0 +14319 0.0 +14320 0.0 +14321 0.0 +14322 0.0 +14323 0.0 +14324 0.0 +14325 0.0 +14326 0.0 +14327 0.0 +14328 0.0 +14329 0.0 +14330 0.0 +14331 0.0 +14332 0.0 +14333 0.0 +14334 0.0 +14335 0.0 +14336 0.0 +14337 0.0 +14338 0.0 +14339 0.0 +14340 0.0 +14341 0.0 +14342 0.0 +14343 0.0 +14344 0.0 +14345 0.0 +14346 0.0 +14347 0.0 +14348 0.0 +14349 0.0 +14350 0.0 +14351 0.0 +14352 0.0 +14353 0.0 +14354 0.0 +14355 0.0 +14356 0.0 +14357 0.0 +14358 0.0 +14359 0.0 +14360 0.0 +14361 0.0 +14362 0.0 +14363 0.0 +14364 0.0 +14365 0.0 +14366 0.0 +14367 0.0 +14368 0.0 +14369 0.0 +14370 0.0 +14371 0.0 +14372 0.0 +14373 0.0 +14374 0.0 +14375 0.0 +14376 0.0 +14377 0.0 +14378 0.0 +14379 0.0 +14380 0.0 +14381 0.0 +14382 0.0 +14383 0.0 +14384 0.0 +14385 0.0 +14386 0.0 +14387 0.0 +14388 0.0 +14389 0.0 +14390 0.0 +14391 0.0 +14392 0.0 +14393 0.0 +14394 0.0 +14395 0.0 +14396 0.0 +14397 0.0 +14398 0.0 +14399 0.0 +14400 0.0 +14401 0.0 +14402 0.0 +14403 0.0 +14404 0.0 +14405 0.0 +14406 0.0 +14407 0.0 +14408 0.0 +14409 0.0 +14410 0.0 +14411 0.0 +14412 0.0 +14413 0.0 +14414 0.0 +14415 0.0 +14416 0.0 +14417 0.0 +14418 0.0 +14419 0.0 +14420 0.0 +14421 0.0 +14422 0.0 +14423 0.0 +14424 0.0 +14425 0.0 +14426 0.0 +14427 0.0 +14428 0.0 +14429 0.0 +14430 0.0 +14431 0.0 +14432 0.0 +14433 0.0 +14434 0.0 +14435 0.0 +14436 0.0 +14437 0.0 +14438 0.0 +14439 0.0 +14440 0.0 +14441 0.0 +14442 0.0 +14443 0.0 +14444 0.0 +14445 0.0 +14446 0.0 +14447 0.0 +14448 0.0 +14449 0.0 +14450 0.0 +14451 0.0 +14452 0.0 +14453 0.0 +14454 0.0 +14455 0.0 +14456 0.0 +14457 0.0 +14458 0.0 +14459 0.0 +14460 0.0 +14461 0.0 +14462 0.0 +14463 0.0 +14464 0.0 +14465 0.0 +14466 0.0 +14467 0.0 +14468 0.0 +14469 0.0 +14470 0.0 +14471 0.0 +14472 0.0 +14473 0.0 +14474 0.0 +14475 0.0 +14476 0.0 +14477 0.0 +14478 0.0 +14479 0.0 +14480 0.0 +14481 0.0 +14482 0.0 +14483 0.0 +14484 0.0 +14485 0.0 +14486 0.0 +14487 0.0 +14488 0.0 +14489 0.0 +14490 0.0 +14491 0.0 +14492 0.0 +14493 0.0 +14494 0.0 +14495 0.0 +14496 0.0 +14497 0.0 +14498 0.0 +14499 0.0 +14500 0.0 +14501 0.0 +14502 0.0 +14503 0.0 +14504 0.0 +14505 0.0 +14506 0.0 +14507 0.0 +14508 0.0 +14509 0.0 +14510 0.0 +14511 0.0 +14512 0.0 +14513 0.0 +14514 0.0 +14515 0.0 +14516 0.0 +14517 0.0 +14518 0.0 +14519 0.0 +14520 0.0 +14521 0.0 +14522 0.0 +14523 0.0 +14524 0.0 +14525 0.0 +14526 0.0 +14527 0.0 +14528 0.0 +14529 0.0 +14530 0.0 +14531 0.0 +14532 0.0 +14533 0.0 +14534 0.0 +14535 0.0 +14536 0.0 +14537 0.0 +14538 0.0 +14539 0.0 +14540 0.0 +14541 0.0 +14542 0.0 +14543 0.0 +14544 0.0 +14545 0.0 +14546 0.0 +14547 0.0 +14548 0.0 +14549 0.0 +14550 0.0 +14551 0.0 +14552 0.0 +14553 0.0 +14554 0.0 +14555 0.0 +14556 0.0 +14557 0.0 +14558 0.0 +14559 0.0 +14560 0.0 +14561 0.0 +14562 0.0 +14563 0.0 +14564 0.0 +14565 0.0 +14566 0.0 +14567 0.0 +14568 0.0 +14569 0.0 +14570 0.0 +14571 0.0 +14572 0.0 +14573 0.0 +14574 0.0 +14575 0.0 +14576 0.0 +14577 0.0 +14578 0.0 +14579 0.0 +14580 0.0 +14581 0.0 +14582 0.0 +14583 0.0 +14584 0.0 +14585 0.0 +14586 0.0 +14587 0.0 +14588 0.0 +14589 0.0 +14590 0.0 +14591 0.0 +14592 0.0 +14593 0.0 +14594 0.0 +14595 0.0 +14596 0.0 +14597 0.0 +14598 0.0 +14599 0.0 +14600 0.0 +14601 0.0 +14602 0.0 +14603 0.0 +14604 0.0 +14605 0.0 +14606 0.0 +14607 0.0 +14608 0.0 +14609 0.0 +14610 0.0 +14611 0.0 +14612 0.0 +14613 0.0 +14614 0.0 +14615 0.0 +14616 0.0 +14617 0.0 +14618 0.0 +14619 0.0 +14620 0.0 +14621 0.0 +14622 0.0 +14623 0.0 +14624 0.0 +14625 0.0 +14626 0.0 +14627 0.0 +14628 0.0 +14629 0.0 +14630 0.0 +14631 0.0 +14632 0.0 +14633 0.0 +14634 0.0 +14635 0.0 +14636 0.0 +14637 0.0 +14638 0.0 +14639 0.0 +14640 0.0 +14641 0.0 +14642 0.0 +14643 0.0 +14644 0.0 +14645 0.0 +14646 0.0 +14647 0.0 +14648 0.0 +14649 0.0 +14650 0.0 +14651 0.0 +14652 0.0 +14653 0.0 +14654 0.0 +14655 0.0 +14656 0.0 +14657 0.0 +14658 0.0 +14659 0.0 +14660 0.0 +14661 0.0 +14662 0.0 +14663 0.0 +14664 0.0 +14665 0.0 +14666 0.0 +14667 0.0 +14668 0.0 +14669 0.0 +14670 0.0 +14671 0.0 +14672 0.0 +14673 0.0 +14674 0.0 +14675 0.0 +14676 0.0 +14677 0.0 +14678 0.0 +14679 0.0 +14680 0.0 +14681 0.0 +14682 0.0 +14683 0.0 +14684 0.0 +14685 0.0 +14686 0.0 +14687 0.0 +14688 0.0 +14689 0.0 +14690 0.0 +14691 0.0 +14692 0.0 +14693 0.0 +14694 0.0 +14695 0.0 +14696 0.0 +14697 0.0 +14698 0.0 +14699 0.0 +14700 0.0 +14701 0.0 +14702 0.0 +14703 0.0 +14704 0.0 +14705 0.0 +14706 0.0 +14707 0.0 +14708 0.0 +14709 0.0 +14710 0.0 +14711 0.0 +14712 0.0 +14713 0.0 +14714 0.0 +14715 0.0 +14716 0.0 +14717 0.0 +14718 0.0 +14719 0.0 +14720 0.0 +14721 0.0 +14722 0.0 +14723 0.0 +14724 0.0 +14725 0.0 +14726 0.0 +14727 0.0 +14728 0.0 +14729 0.0 +14730 0.0 +14731 0.0 +14732 0.0 +14733 0.0 +14734 0.0 +14735 0.0 +14736 0.0 +14737 0.0 +14738 0.0 +14739 0.0 +14740 0.0 +14741 0.0 +14742 0.0 +14743 0.0 +14744 0.0 +14745 0.0 +14746 0.0 +14747 0.0 +14748 0.0 +14749 0.0 +14750 0.0 +14751 0.0 +14752 0.0 +14753 0.0 +14754 0.0 +14755 0.0 +14756 0.0 +14757 0.0 +14758 0.0 +14759 0.0 +14760 0.0 +14761 0.0 +14762 0.0 +14763 0.0 +14764 0.0 +14765 0.0 +14766 0.0 +14767 0.0 +14768 0.0 +14769 0.0 +14770 0.0 +14771 0.0 +14772 0.0 +14773 0.0 +14774 0.0 +14775 0.0 +14776 0.0 +14777 0.0 +14778 0.0 +14779 0.0 +14780 0.0 +14781 0.0 +14782 0.0 +14783 0.0 +14784 0.0 +14785 0.0 +14786 0.0 +14787 0.0 +14788 0.0 +14789 0.0 +14790 0.0 +14791 0.0 +14792 0.0 +14793 0.0 +14794 0.0 +14795 0.0 +14796 0.0 +14797 0.0 +14798 0.0 +14799 0.0 +14800 0.0 +14801 0.0 +14802 0.0 +14803 0.0 +14804 0.0 +14805 0.0 +14806 0.0 +14807 0.0 +14808 0.0 +14809 0.0 +14810 0.0 +14811 0.0 +14812 0.0 +14813 0.0 +14814 0.0 +14815 0.0 +14816 0.0 +14817 0.0 +14818 0.0 +14819 0.0 +14820 0.0 +14821 0.0 +14822 0.0 +14823 0.0 +14824 0.0 +14825 0.0 +14826 0.0 +14827 0.0 +14828 0.0 +14829 0.0 +14830 0.0 +14831 0.0 +14832 0.0 +14833 0.0 +14834 0.0 +14835 0.0 +14836 0.0 +14837 0.0 +14838 0.0 +14839 0.0 +14840 0.0 +14841 0.0 +14842 0.0 +14843 0.0 +14844 0.0 +14845 0.0 +14846 0.0 +14847 0.0 +14848 0.0 +14849 0.0 +14850 0.0 +14851 0.0 +14852 0.0 +14853 0.0 +14854 0.0 +14855 0.0 +14856 0.0 +14857 0.0 +14858 0.0 +14859 0.0 +14860 0.0 +14861 0.0 +14862 0.0 +14863 0.0 +14864 0.0 +14865 0.0 +14866 0.0 +14867 0.0 +14868 0.0 +14869 0.0 +14870 0.0 +14871 0.0 +14872 0.0 +14873 0.0 +14874 0.0 +14875 0.0 +14876 0.0 +14877 0.0 +14878 0.0 +14879 0.0 +14880 0.0 +14881 0.0 +14882 0.0 +14883 0.0 +14884 0.0 +14885 0.0 +14886 0.0 +14887 0.0 +14888 0.0 +14889 0.0 +14890 0.0 +14891 0.0 +14892 0.0 +14893 0.0 +14894 0.0 +14895 0.0 +14896 0.0 +14897 0.0 +14898 0.0 +14899 0.0 +14900 0.0 +14901 0.0 +14902 0.0 +14903 0.0 +14904 0.0 +14905 0.0 +14906 0.0 +14907 0.0 +14908 0.0 +14909 0.0 +14910 0.0 +14911 0.0 +14912 0.0 +14913 0.0 +14914 0.0 +14915 0.0 +14916 0.0 +14917 0.0 +14918 0.0 +14919 0.0 +14920 0.0 +14921 0.0 +14922 0.0 +14923 0.0 +14924 0.0 +14925 0.0 +14926 0.0 +14927 0.0 +14928 0.0 +14929 0.0 +14930 0.0 +14931 0.0 +14932 0.0 +14933 0.0 +14934 0.0 +14935 0.0 +14936 0.0 +14937 0.0 +14938 0.0 +14939 0.0 +14940 0.0 +14941 0.0 +14942 0.0 +14943 0.0 +14944 0.0 +14945 0.0 +14946 0.0 +14947 0.0 +14948 0.0 +14949 0.0 +14950 0.0 +14951 0.0 +14952 0.0 +14953 0.0 +14954 0.0 +14955 0.0 +14956 0.0 +14957 0.0 +14958 0.0 +14959 0.0 +14960 0.0 +14961 0.0 +14962 0.0 +14963 0.0 +14964 0.0 +14965 0.0 +14966 0.0 +14967 0.0 +14968 0.0 +14969 0.0 +14970 0.0 +14971 0.0 +14972 0.0 +14973 0.0 +14974 0.0 +14975 0.0 +14976 0.0 +14977 0.0 +14978 0.0 +14979 0.0 +14980 0.0 +14981 0.0 +14982 0.0 +14983 0.0 +14984 0.0 +14985 0.0 +14986 0.0 +14987 0.0 +14988 0.0 +14989 0.0 +14990 0.0 +14991 0.0 +14992 0.0 +14993 0.0 +14994 0.0 +14995 0.0 +14996 0.0 +14997 0.0 +14998 0.0 +14999 0.0 +15000 0.0 +15001 0.0 +15002 0.0 +15003 0.0 +15004 0.0 +15005 0.0 +15006 0.0 +15007 0.0 +15008 0.0 +15009 0.0 +15010 0.0 +15011 0.0 +15012 0.0 +15013 0.0 +15014 0.0 +15015 0.0 +15016 0.0 +15017 0.0 +15018 0.0 +15019 0.0 +15020 0.0 +15021 0.0 +15022 0.0 +15023 0.0 +15024 0.0 +15025 0.0 +15026 0.0 +15027 0.0 +15028 0.0 +15029 0.0 +15030 0.0 +15031 0.0 +15032 0.0 +15033 0.0 +15034 0.0 +15035 0.0 +15036 0.0 +15037 0.0 +15038 0.0 +15039 0.0 +15040 0.0 +15041 0.0 +15042 0.0 +15043 0.0 +15044 0.0 +15045 0.0 +15046 0.0 +15047 0.0 +15048 0.0 +15049 0.0 +15050 0.0 +15051 0.0 +15052 0.0 +15053 0.0 +15054 0.0 +15055 0.0 +15056 0.0 +15057 0.0 +15058 0.0 +15059 0.0 +15060 0.0 +15061 0.0 +15062 0.0 +15063 0.0 +15064 0.0 +15065 0.0 +15066 0.0 +15067 0.0 +15068 0.0 +15069 0.0 +15070 0.0 +15071 0.0 +15072 0.0 +15073 0.0 +15074 0.0 +15075 0.0 +15076 0.0 +15077 0.0 +15078 0.0 +15079 0.0 +15080 0.0 +15081 0.0 +15082 0.0 +15083 0.0 +15084 0.0 +15085 0.0 +15086 0.0 +15087 0.0 +15088 0.0 +15089 0.0 +15090 0.0 +15091 0.0 +15092 0.0 +15093 0.0 +15094 0.0 +15095 0.0 +15096 0.0 +15097 0.0 +15098 0.0 +15099 0.0 +15100 0.0 +15101 0.0 +15102 0.0 +15103 0.0 +15104 0.0 +15105 0.0 +15106 0.0 +15107 0.0 +15108 0.0 +15109 0.0 +15110 0.0 +15111 0.0 +15112 0.0 +15113 0.0 +15114 0.0 +15115 0.0 +15116 0.0 +15117 0.0 +15118 0.0 +15119 0.0 +15120 0.0 +15121 0.0 +15122 0.0 +15123 0.0 +15124 0.0 +15125 0.0 +15126 0.0 +15127 0.0 +15128 0.0 +15129 0.0 +15130 0.0 +15131 0.0 +15132 0.0 +15133 0.0 +15134 0.0 +15135 0.0 +15136 0.0 +15137 0.0 +15138 0.0 +15139 0.0 +15140 0.0 +15141 0.0 +15142 0.0 +15143 0.0 +15144 0.0 +15145 0.0 +15146 0.0 +15147 0.0 +15148 0.0 +15149 0.0 +15150 0.0 +15151 0.0 +15152 0.0 +15153 0.0 +15154 0.0 +15155 0.0 +15156 0.0 +15157 0.0 +15158 0.0 +15159 0.0 +15160 0.0 +15161 0.0 +15162 0.0 +15163 0.0 +15164 0.0 +15165 0.0 +15166 0.0 +15167 0.0 +15168 0.0 +15169 0.0 +15170 0.0 +15171 0.0 +15172 0.0 +15173 0.0 +15174 0.0 +15175 0.0 +15176 0.0 +15177 0.0 +15178 0.0 +15179 0.0 +15180 0.0 +15181 0.0 +15182 0.0 +15183 0.0 +15184 0.0 +15185 0.0 +15186 0.0 +15187 0.0 +15188 0.0 +15189 0.0 +15190 0.0 +15191 0.0 +15192 0.0 +15193 0.0 +15194 0.0 +15195 0.0 +15196 0.0 +15197 0.0 +15198 0.0 +15199 0.0 +15200 0.0 +15201 0.0 +15202 0.0 +15203 0.0 +15204 0.0 +15205 0.0 +15206 0.0 +15207 0.0 +15208 0.0 +15209 0.0 +15210 0.0 +15211 0.0 +15212 0.0 +15213 0.0 +15214 0.0 +15215 0.0 +15216 0.0 +15217 0.0 +15218 0.0 +15219 0.0 +15220 0.0 +15221 0.0 +15222 0.0 +15223 0.0 +15224 0.0 +15225 0.0 +15226 0.0 +15227 0.0 +15228 0.0 +15229 0.0 +15230 0.0 +15231 0.0 +15232 0.0 +15233 0.0 +15234 0.0 +15235 0.0 +15236 0.0 +15237 0.0 +15238 0.0 +15239 0.0 +15240 0.0 +15241 0.0 +15242 0.0 +15243 0.0 +15244 0.0 +15245 0.0 +15246 0.0 +15247 0.0 +15248 0.0 +15249 0.0 +15250 0.0 +15251 0.0 +15252 0.0 +15253 0.0 +15254 0.0 +15255 0.0 +15256 0.0 +15257 0.0 +15258 0.0 +15259 0.0 +15260 0.0 +15261 0.0 +15262 0.0 +15263 0.0 +15264 0.0 +15265 0.0 +15266 0.0 +15267 0.0 +15268 0.0 +15269 0.0 +15270 0.0 +15271 0.0 +15272 0.0 +15273 0.0 +15274 0.0 +15275 0.0 +15276 0.0 +15277 0.0 +15278 0.0 +15279 0.0 +15280 0.0 +15281 0.0 +15282 0.0 +15283 0.0 +15284 0.0 +15285 0.0 +15286 0.0 +15287 0.0 +15288 0.0 +15289 0.0 +15290 0.0 +15291 0.0 +15292 0.0 +15293 0.0 +15294 0.0 +15295 0.0 +15296 0.0 +15297 0.0 +15298 0.0 +15299 0.0 +15300 0.0 +15301 0.0 +15302 0.0 +15303 0.0 +15304 0.0 +15305 0.0 +15306 0.0 +15307 0.0 +15308 0.0 +15309 0.0 +15310 0.0 +15311 0.0 +15312 0.0 +15313 0.0 +15314 0.0 +15315 0.0 +15316 0.0 +15317 0.0 +15318 0.0 +15319 0.0 +15320 0.0 +15321 0.0 +15322 0.0 +15323 0.0 +15324 0.0 +15325 0.0 +15326 0.0 +15327 0.0 +15328 0.0 +15329 0.0 +15330 0.0 +15331 0.0 +15332 0.0 +15333 0.0 +15334 0.0 +15335 0.0 +15336 0.0 +15337 0.0 +15338 0.0 +15339 0.0 +15340 0.0 +15341 0.0 +15342 0.0 +15343 0.0 +15344 0.0 +15345 0.0 +15346 0.0 +15347 0.0 +15348 0.0 +15349 0.0 +15350 0.0 +15351 0.0 +15352 0.0 +15353 0.0 +15354 0.0 +15355 0.0 +15356 0.0 +15357 0.0 +15358 0.0 +15359 0.0 diff --git a/tests/circuitpython/audiofilter_filter_stereo_biquads.py b/tests/circuitpython/audiofilter_filter_stereo_biquads.py new file mode 100644 index 00000000000..262f8139378 --- /dev/null +++ b/tests/circuitpython/audiofilter_filter_stereo_biquads.py @@ -0,0 +1,27 @@ +from audiofilters import Filter +from audiofilterhelper import synth_test, white8k +from audiomixer import Mixer +from synthio import Biquad, FilterMode, LFO + + +@synth_test +def stereo_filter(): + args = { + "bits_per_sample": 16, + "samples_signed": True, + "channel_count": 2, + } + effect = Filter( + filter=[ + Biquad(FilterMode.LOW_PASS, 400), + Biquad(FilterMode.HIGH_PASS, 300, Q=8), + ], + **args, + ) + mixer = Mixer(**args) + mixer.voice[0].panning = LFO() + effect.play(mixer) + yield effect, [] + + mixer.play(white8k, loop=True) + yield 400 diff --git a/tests/circuitpython/audiofilter_filter_stereo_biquads.py.exp b/tests/circuitpython/audiofilter_filter_stereo_biquads.py.exp new file mode 100644 index 00000000000..7901d158079 --- /dev/null +++ b/tests/circuitpython/audiofilter_filter_stereo_biquads.py.exp @@ -0,0 +1,102400 @@ +0 0.0 +1 0.0 +2 0.0 +3 0.0 +4 0.0 +5 0.0 +6 0.0 +7 0.0 +8 0.0 +9 0.0 +10 0.0 +11 0.0 +12 0.0 +13 0.0 +14 0.0 +15 0.0 +16 0.0 +17 0.0 +18 0.0 +19 0.0 +20 0.0 +21 0.0 +22 0.0 +23 0.0 +24 0.0 +25 0.0 +26 0.0 +27 0.0 +28 0.0 +29 0.0 +30 0.0 +31 0.0 +32 0.0 +33 0.0 +34 0.0 +35 0.0 +36 0.0 +37 0.0 +38 0.0 +39 0.0 +40 0.0 +41 0.0 +42 0.0 +43 0.0 +44 0.0 +45 0.0 +46 0.0 +47 0.0 +48 0.0 +49 0.0 +50 0.0 +51 0.0 +52 0.0 +53 0.0 +54 0.0 +55 0.0 +56 0.0 +57 0.0 +58 0.0 +59 0.0 +60 0.0 +61 0.0 +62 0.0 +63 0.0 +64 0.0 +65 0.0 +66 0.0 +67 0.0 +68 0.0 +69 0.0 +70 0.0 +71 0.0 +72 0.0 +73 0.0 +74 0.0 +75 0.0 +76 0.0 +77 0.0 +78 0.0 +79 0.0 +80 0.0 +81 0.0 +82 0.0 +83 0.0 +84 0.0 +85 0.0 +86 0.0 +87 0.0 +88 0.0 +89 0.0 +90 0.0 +91 0.0 +92 0.0 +93 0.0 +94 0.0 +95 0.0 +96 0.0 +97 0.0 +98 0.0 +99 0.0 +100 0.0 +101 0.0 +102 0.0 +103 0.0 +104 0.0 +105 0.0 +106 0.0 +107 0.0 +108 0.0 +109 0.0 +110 0.0 +111 0.0 +112 0.0 +113 0.0 +114 0.0 +115 0.0 +116 0.0 +117 0.0 +118 0.0 +119 0.0 +120 0.0 +121 0.0 +122 0.0 +123 0.0 +124 0.0 +125 0.0 +126 0.0 +127 0.0 +128 0.0 +129 0.0 +130 0.0 +131 0.0 +132 0.0 +133 0.0 +134 0.0 +135 0.0 +136 0.0 +137 0.0 +138 0.0 +139 0.0 +140 0.0 +141 0.0 +142 0.0 +143 0.0 +144 0.0 +145 0.0 +146 0.0 +147 0.0 +148 0.0 +149 0.0 +150 0.0 +151 0.0 +152 0.0 +153 0.0 +154 0.0 +155 0.0 +156 0.0 +157 0.0 +158 0.0 +159 0.0 +160 0.0 +161 0.0 +162 0.0 +163 0.0 +164 0.0 +165 0.0 +166 0.0 +167 0.0 +168 0.0 +169 0.0 +170 0.0 +171 0.0 +172 0.0 +173 0.0 +174 0.0 +175 0.0 +176 0.0 +177 0.0 +178 0.0 +179 0.0 +180 0.0 +181 0.0 +182 0.0 +183 0.0 +184 0.0 +185 0.0 +186 0.0 +187 0.0 +188 0.0 +189 0.0 +190 0.0 +191 0.0 +192 0.0 +193 0.0 +194 0.0 +195 0.0 +196 0.0 +197 0.0 +198 0.0 +199 0.0 +200 0.0 +201 0.0 +202 0.0 +203 0.0 +204 0.0 +205 0.0 +206 0.0 +207 0.0 +208 0.0 +209 0.0 +210 0.0 +211 0.0 +212 0.0 +213 0.0 +214 0.0 +215 0.0 +216 0.0 +217 0.0 +218 0.0 +219 0.0 +220 0.0 +221 0.0 +222 0.0 +223 0.0 +224 0.0 +225 0.0 +226 0.0 +227 0.0 +228 0.0 +229 0.0 +230 0.0 +231 0.0 +232 0.0 +233 0.0 +234 0.0 +235 0.0 +236 0.0 +237 0.0 +238 0.0 +239 0.0 +240 0.0 +241 0.0 +242 0.0 +243 0.0 +244 0.0 +245 0.0 +246 0.0 +247 0.0 +248 0.0 +249 0.0 +250 0.0 +251 0.0 +252 0.0 +253 0.0 +254 0.0 +255 0.0 +256 0.002960205078125 +257 0.0030517578125 +258 0.020904541015625 +259 0.021575927734375 +260 0.049591064453125 +261 0.05120849609375 +262 0.052093505859375 +263 0.053802490234375 +264 9.1552734375e-05 +265 9.1552734375e-05 +266 -0.089752197265625 +267 -0.09271240234375 +268 -0.1788330078125 +269 -0.1846923828125 +270 -0.229644775390625 +271 -0.237152099609375 +272 -0.205322265625 +273 -0.21197509765625 +274 -0.1357421875 +275 -0.140045166015625 +276 -0.068145751953125 +277 -0.070159912109375 +278 0.0040283203125 +279 0.004425048828125 +280 0.085601806640625 +281 0.08868408203125 +282 0.19061279296875 +283 0.1971435546875 +284 0.28875732421875 +285 0.2984619140625 +286 0.32904052734375 +287 0.34002685546875 +288 0.328033447265625 +289 0.338958740234375 +290 0.301422119140625 +291 0.311431884765625 +292 0.248870849609375 +293 0.257110595703125 +294 0.164520263671875 +295 0.169921875 +296 0.047454833984375 +297 0.048919677734375 +298 -0.07232666015625 +299 -0.074859619140625 +300 -0.189605712890625 +301 -0.196044921875 +302 -0.30810546875 +303 -0.3184814453125 +304 -0.40386962890625 +305 -0.41741943359375 +306 -0.44793701171875 +307 -0.462921142578125 +308 -0.402435302734375 +309 -0.4158935546875 +310 -0.26312255859375 +311 -0.27197265625 +312 -0.093475341796875 +313 -0.0966796875 +314 0.030303955078125 +315 0.031219482421875 +316 0.106536865234375 +317 0.110015869140625 +318 0.16162109375 +319 0.166961669921875 +320 0.20147705078125 +321 0.20819091796875 +322 0.226287841796875 +323 0.23388671875 +324 0.201416015625 +325 0.208282470703125 +326 0.1470947265625 +327 0.152252197265625 +328 0.119049072265625 +329 0.123321533203125 +330 0.090087890625 +331 0.093414306640625 +332 0.018585205078125 +333 0.019500732421875 +334 -0.070709228515625 +335 -0.07281494140625 +336 -0.11651611328125 +337 -0.1202392578125 +338 -0.0858154296875 +339 -0.088623046875 +340 -0.024078369140625 +341 -0.024932861328125 +342 -0.006011962890625 +343 -0.00634765625 +344 -0.036468505859375 +345 -0.037872314453125 +346 -0.0826416015625 +347 -0.085601806640625 +348 -0.118194580078125 +349 -0.12237548828125 +350 -0.111480712890625 +351 -0.115478515625 +352 -0.051116943359375 +353 -0.05316162109375 +354 0.021331787109375 +355 0.02166748046875 +356 0.04974365234375 +357 0.051025390625 +358 0.0406494140625 +359 0.041656494140625 +360 0.05322265625 +361 0.0546875 +362 0.12335205078125 +363 0.127197265625 +364 0.210296630859375 +365 0.21710205078125 +366 0.254425048828125 +367 0.262786865234375 +368 0.27325439453125 +369 0.282318115234375 +370 0.30120849609375 +371 0.311279296875 +372 0.312896728515625 +373 0.32342529296875 +374 0.2645263671875 +375 0.273468017578125 +376 0.1497802734375 +377 0.1549072265625 +378 0.016937255859375 +379 0.017669677734375 +380 -0.08575439453125 +381 -0.088409423828125 +382 -0.154876708984375 +383 -0.15985107421875 +384 -0.191314697265625 +385 -0.197540283203125 +386 -0.22088623046875 +387 -0.2281494140625 +388 -0.287445068359375 +389 -0.296966552734375 +390 -0.38238525390625 +391 -0.39508056640625 +392 -0.488983154296875 +393 -0.505218505859375 +394 -0.577056884765625 +395 -0.59619140625 +396 -0.609649658203125 +397 -0.62982177734375 +398 -0.57977294921875 +399 -0.59893798828125 +400 -0.464447021484375 +401 -0.47979736328125 +402 -0.276885986328125 +403 -0.286041259765625 +404 -0.0714111328125 +405 -0.07379150390625 +406 0.12152099609375 +407 0.12548828125 +408 0.269439697265625 +409 0.278289794921875 +410 0.360321044921875 +411 0.3721923828125 +412 0.43292236328125 +413 0.44720458984375 +414 0.494903564453125 +415 0.511260986328125 +416 0.50244140625 +417 0.519073486328125 +418 0.444000244140625 +419 0.458740234375 +420 0.36920166015625 +421 0.38153076171875 +422 0.32666015625 +423 0.337646484375 +424 0.322052001953125 +425 0.332916259765625 +426 0.34649658203125 +427 0.358184814453125 +428 0.367218017578125 +429 0.379608154296875 +430 0.334686279296875 +431 0.34600830078125 +432 0.232086181640625 +433 0.239990234375 +434 0.082855224609375 +435 0.085784912109375 +436 -0.079559326171875 +437 -0.082061767578125 +438 -0.231689453125 +439 -0.239288330078125 +440 -0.358489990234375 +441 -0.370361328125 +442 -0.446044921875 +443 -0.460906982421875 +444 -0.4727783203125 +445 -0.48858642578125 +446 -0.45269775390625 +447 -0.467864990234375 +448 -0.43072509765625 +449 -0.4451904296875 +450 -0.40185546875 +451 -0.4154052734375 +452 -0.359283447265625 +453 -0.371429443359375 +454 -0.339935302734375 +455 -0.3514404296875 +456 -0.320892333984375 +457 -0.331756591796875 +458 -0.229156494140625 +459 -0.236968994140625 +460 -0.062042236328125 +461 -0.064300537109375 +462 0.1336669921875 +463 0.137908935546875 +464 0.320068359375 +465 0.33056640625 +466 0.473236083984375 +467 0.488922119140625 +468 0.56414794921875 +469 0.58294677734375 +470 0.56158447265625 +471 0.580413818359375 +472 0.481597900390625 +473 0.497894287109375 +474 0.36175537109375 +475 0.374176025390625 +476 0.243743896484375 +477 0.252288818359375 +478 0.151763916015625 +479 0.157257080078125 +480 0.0540771484375 +481 0.0562744140625 +482 -0.0638427734375 +483 -0.065643310546875 +484 -0.157470703125 +485 -0.1624755859375 +486 -0.222991943359375 +487 -0.230316162109375 +488 -0.279541015625 +489 -0.288909912109375 +490 -0.291900634765625 +491 -0.30181884765625 +492 -0.25115966796875 +493 -0.25982666015625 +494 -0.20123291015625 +495 -0.20831298828125 +496 -0.181121826171875 +497 -0.18756103515625 +498 -0.17724609375 +499 -0.18359375 +500 -0.142303466796875 +501 -0.147491455078125 +502 -0.074188232421875 +503 -0.077056884765625 +504 -0.01043701171875 +505 -0.011138916015625 +506 0.04486083984375 +507 0.04608154296875 +508 0.0850830078125 +509 0.087738037109375 +510 0.088409423828125 +511 0.091278076171875 +512 0.091705322265625 +513 0.09515380859375 +514 0.11151123046875 +515 0.11663818359375 +516 0.122528076171875 +517 0.1290283203125 +518 0.110137939453125 +519 0.116546630859375 +520 0.0689697265625 +521 0.07330322265625 +522 0.02484130859375 +523 0.026763916015625 +524 -0.02301025390625 +525 -0.02392578125 +526 -0.104278564453125 +527 -0.110504150390625 +528 -0.18359375 +529 -0.195220947265625 +530 -0.223724365234375 +531 -0.23822021484375 +532 -0.232635498046875 +533 -0.248016357421875 +534 -0.18865966796875 +535 -0.201385498046875 +536 -0.101318359375 +537 -0.108489990234375 +538 -0.002288818359375 +539 -0.00311279296875 +540 0.110382080078125 +541 0.11688232421875 +542 0.20416259765625 +543 0.21673583984375 +544 0.24432373046875 +545 0.259368896484375 +546 0.24310302734375 +547 0.257904052734375 +548 0.209259033203125 +549 0.221710205078125 +550 0.163360595703125 +551 0.1727294921875 +552 0.133575439453125 +553 0.141082763671875 +554 0.101165771484375 +555 0.106689453125 +556 0.06396484375 +557 0.0672607421875 +558 0.050018310546875 +559 0.052734375 +560 0.07598876953125 +561 0.08087158203125 +562 0.126983642578125 +563 0.1357421875 +564 0.160369873046875 +565 0.171783447265625 +566 0.154541015625 +567 0.1658935546875 +568 0.101318359375 +569 0.10931396484375 +570 0.005401611328125 +571 0.007080078125 +572 -0.1109619140625 +573 -0.1170654296875 +574 -0.2427978515625 +575 -0.2578125 +576 -0.380523681640625 +577 -0.404937744140625 +578 -0.49627685546875 +579 -0.5286865234375 +580 -0.548828125 +581 -0.58502197265625 +582 -0.498046875 +583 -0.531005859375 +584 -0.366180419921875 +585 -0.390411376953125 +586 -0.21160888671875 +587 -0.225616455078125 +588 -0.058380126953125 +589 -0.062255859375 +590 0.09466552734375 +591 0.100921630859375 +592 0.23687744140625 +593 0.252532958984375 +594 0.3428955078125 +595 0.365509033203125 +596 0.396331787109375 +597 0.422332763671875 +598 0.393890380859375 +599 0.41949462890625 +600 0.334259033203125 +601 0.355621337890625 +602 0.2401123046875 +603 0.254974365234375 +604 0.144622802734375 +605 0.152984619140625 +606 0.0594482421875 +607 0.062103271484375 +608 0.01043701171875 +609 0.00994873046875 +610 -0.004119873046875 +611 -0.00531005859375 +612 -0.013671875 +613 -0.015167236328125 +614 -0.00042724609375 +615 -0.000640869140625 +616 0.0472412109375 +617 0.050628662109375 +618 0.088409423828125 +619 0.094940185546875 +620 0.074005126953125 +621 0.079833984375 +622 0.019134521484375 +623 0.021453857421875 +624 -0.04058837890625 +625 -0.04217529296875 +626 -0.096221923828125 +627 -0.10150146484375 +628 -0.1370849609375 +629 -0.1451416015625 +630 -0.17352294921875 +631 -0.18408203125 +632 -0.21112060546875 +633 -0.224334716796875 +634 -0.250518798828125 +635 -0.2666015625 +636 -0.298919677734375 +637 -0.318572998046875 +638 -0.347076416015625 +639 -0.37030029296875 +640 -0.36907958984375 +641 -0.39410400390625 +642 -0.329833984375 +643 -0.35247802734375 +644 -0.22613525390625 +645 -0.241973876953125 +646 -0.074554443359375 +647 -0.08026123046875 +648 0.09942626953125 +649 0.105438232421875 +650 0.238983154296875 +651 0.25439453125 +652 0.31884765625 +653 0.339630126953125 +654 0.356597900390625 +655 0.379913330078125 +656 0.345703125 +657 0.368316650390625 +658 0.285797119140625 +659 0.304412841796875 +660 0.224578857421875 +661 0.239166259765625 +662 0.196319580078125 +663 0.20916748046875 +664 0.176422119140625 +665 0.188140869140625 +666 0.1492919921875 +667 0.159393310546875 +668 0.14080810546875 +669 0.150543212890625 +670 0.141937255859375 +671 0.151947021484375 +672 0.114501953125 +673 0.122833251953125 +674 0.08221435546875 +675 0.088531494140625 +676 0.06683349609375 +677 0.072296142578125 +678 0.034942626953125 +679 0.038360595703125 +680 -0.02557373046875 +681 -0.026214599609375 +682 -0.1142578125 +683 -0.1209716796875 +684 -0.230499267578125 +685 -0.245208740234375 +686 -0.34661865234375 +687 -0.369354248046875 +688 -0.4248046875 +689 -0.45306396484375 +690 -0.45147705078125 +691 -0.481781005859375 +692 -0.439483642578125 +693 -0.46917724609375 +694 -0.39300537109375 +695 -0.41973876953125 +696 -0.310028076171875 +697 -0.331298828125 +698 -0.207061767578125 +699 -0.221527099609375 +700 -0.106353759765625 +701 -0.1141357421875 +702 -0.014312744140625 +703 -0.015960693359375 +704 0.0859375 +705 0.09100341796875 +706 0.2137451171875 +707 0.22747802734375 +708 0.378204345703125 +709 0.403167724609375 +710 0.559051513671875 +711 0.596435546875 +712 0.69921875 +713 0.74627685546875 +714 0.759063720703125 +715 0.81036376953125 +716 0.736114501953125 +717 0.7860107421875 +718 0.6273193359375 +719 0.66998291015625 +720 0.431915283203125 +721 0.46142578125 +722 0.18505859375 +723 0.197906494140625 +724 -0.051727294921875 +725 -0.05487060546875 +726 -0.22491455078125 +727 -0.23974609375 +728 -0.3179931640625 +729 -0.339080810546875 +730 -0.355377197265625 +731 -0.37896728515625 +732 -0.366180419921875 +733 -0.3905029296875 +734 -0.3646240234375 +735 -0.388916015625 +736 -0.3668212890625 +737 -0.391326904296875 +738 -0.37689208984375 +739 -0.4022216796875 +740 -0.369598388671875 +741 -0.39459228515625 +742 -0.32696533203125 +743 -0.3492431640625 +744 -0.269439697265625 +745 -0.287933349609375 +746 -0.237701416015625 +747 -0.254180908203125 +748 -0.248779296875 +749 -0.26617431640625 +750 -0.25311279296875 +751 -0.270904541015625 +752 -0.197998046875 +753 -0.21209716796875 +754 -0.11328125 +755 -0.121612548828125 +756 -0.055572509765625 +757 -0.059967041015625 +758 -0.031158447265625 +759 -0.03387451171875 +760 -0.013275146484375 +761 -0.01470947265625 +762 0.028900146484375 +763 0.030426025390625 +764 0.125396728515625 +765 0.133636474609375 +766 0.249176025390625 +767 0.2659912109375 +768 0.360626220703125 +769 0.385772705078125 +770 0.4522705078125 +771 0.48480224609375 +772 0.495574951171875 +773 0.531097412109375 +774 0.478851318359375 +775 0.511962890625 +776 0.426971435546875 +777 0.454986572265625 +778 0.3798828125 +779 0.404327392578125 +780 0.354766845703125 +781 0.37890625 +782 0.32635498046875 +783 0.350616455078125 +784 0.281341552734375 +785 0.3045654296875 +786 0.22198486328125 +787 0.243011474609375 +788 0.1407470703125 +789 0.157379150390625 +790 0.0196533203125 +791 0.027496337890625 +792 -0.143341064453125 +793 -0.149139404296875 +794 -0.3201904296875 +795 -0.3416748046875 +796 -0.50091552734375 +797 -0.53924560546875 +798 -0.670166015625 +799 -0.725006103515625 +800 -0.77288818359375 +801 -0.838104248046875 +802 -0.767303466796875 +803 -0.832366943359375 +804 -0.6715087890625 +805 -0.727691650390625 +806 -0.535308837890625 +807 -0.579132080078125 +808 -0.40289306640625 +809 -0.435394287109375 +810 -0.294403076171875 +811 -0.318634033203125 +812 -0.179595947265625 +813 -0.195159912109375 +814 -0.034271240234375 +815 -0.038055419921875 +816 0.10321044921875 +817 0.1104736328125 +818 0.194732666015625 +819 0.208465576171875 +820 0.252716064453125 +821 0.26983642578125 +822 0.321044921875 +823 0.34326171875 +824 0.416107177734375 +825 0.446990966796875 +826 0.507049560546875 +827 0.546905517578125 +828 0.57098388671875 +829 0.61773681640625 +830 0.600738525390625 +831 0.6514892578125 +832 0.608062744140625 +833 0.661102294921875 +834 0.59857177734375 +835 0.652679443359375 +836 0.550811767578125 +837 0.602386474609375 +838 0.4521484375 +839 0.496124267578125 +840 0.314910888671875 +841 0.347320556640625 +842 0.152801513671875 +843 0.170989990234375 +844 -0.04058837890625 +845 -0.0401611328125 +846 -0.2442626953125 +847 -0.263031005859375 +848 -0.41192626953125 +849 -0.446502685546875 +850 -0.532440185546875 +851 -0.578399658203125 +852 -0.60150146484375 +853 -0.65399169921875 +854 -0.591156005859375 +855 -0.642364501953125 +856 -0.517791748046875 +857 -0.561676025390625 +858 -0.421661376953125 +859 -0.456390380859375 +860 -0.322113037109375 +861 -0.347869873046875 +862 -0.23809814453125 +863 -0.256988525390625 +864 -0.173553466796875 +865 -0.18792724609375 +866 -0.1256103515625 +867 -0.137359619140625 +868 -0.087310791015625 +869 -0.09747314453125 +870 -0.0498046875 +871 -0.058319091796875 +872 -0.002166748046875 +873 -0.007720947265625 +874 0.066497802734375 +875 0.06646728515625 +876 0.1446533203125 +877 0.151611328125 +878 0.228668212890625 +879 0.243743896484375 +880 0.32513427734375 +881 0.35015869140625 +882 0.42181396484375 +883 0.457366943359375 +884 0.49853515625 +885 0.542999267578125 +886 0.52288818359375 +887 0.57110595703125 +888 0.460906982421875 +889 0.504058837890625 +890 0.318328857421875 +891 0.34808349609375 +892 0.13116455078125 +893 0.142974853515625 +894 -0.053192138671875 +895 -0.0589599609375 +896 -0.20050048828125 +897 -0.219940185546875 +898 -0.309173583984375 +899 -0.33837890625 +900 -0.3717041015625 +901 -0.406005859375 +902 -0.406890869140625 +903 -0.4437255859375 +904 -0.456268310546875 +905 -0.497528076171875 +906 -0.514129638671875 +907 -0.561126708984375 +908 -0.550018310546875 +909 -0.600860595703125 +910 -0.533935546875 +911 -0.58355712890625 +912 -0.4376220703125 +913 -0.4779052734375 +914 -0.255218505859375 +915 -0.27734375 +916 -0.009002685546875 +917 -0.00640869140625 +918 0.243743896484375 +919 0.271636962890625 +920 0.4388427734375 +921 0.48583984375 +922 0.549591064453125 +923 0.60675048828125 +924 0.593017578125 +925 0.6533203125 +926 0.606170654296875 +927 0.666595458984375 +928 0.586334228515625 +929 0.64361572265625 +930 0.524200439453125 +931 0.5740966796875 +932 0.456756591796875 +933 0.499053955078125 +934 0.403167724609375 +935 0.439697265625 +936 0.34454345703125 +937 0.375091552734375 +938 0.25213623046875 +939 0.2734375 +940 0.10101318359375 +941 0.107147216796875 +942 -0.088592529296875 +943 -0.101470947265625 +944 -0.287841796875 +945 -0.320648193359375 +946 -0.497772216796875 +947 -0.551544189453125 +948 -0.7022705078125 +949 -0.77642822265625 +950 -0.853424072265625 +951 -0.864105224609375 +952 -0.861785888671875 +953 -0.870391845703125 +954 -0.861785888671875 +955 -0.868682861328125 +956 -0.855743408203125 +957 -0.86053466796875 +958 -0.739044189453125 +959 -0.759246826171875 +960 -0.530792236328125 +961 -0.52203369140625 +962 -0.247528076171875 +963 -0.20556640625 +964 0.07177734375 +965 0.146942138671875 +966 0.380706787109375 +967 0.48431396484375 +968 0.64703369140625 +969 0.771270751953125 +970 0.846282958984375 +971 0.868316650390625 +972 0.8680419921875 +973 0.870361328125 +974 0.870361328125 +975 0.86395263671875 +976 0.86505126953125 +977 0.8172607421875 +978 0.854766845703125 +979 0.657073974609375 +980 0.723175048828125 +981 0.470733642578125 +982 0.567535400390625 +983 0.279388427734375 +984 0.39276123046875 +985 0.086395263671875 +986 0.170318603515625 +987 -0.140350341796875 +988 -0.106231689453125 +989 -0.40960693359375 +990 -0.39886474609375 +991 -0.6817626953125 +992 -0.654388427734375 +993 -0.859619140625 +994 -0.83514404296875 +995 -0.870391845703125 +996 -0.8634033203125 +997 -0.870391845703125 +998 -0.8685302734375 +999 -0.86444091796875 +1000 -0.870391845703125 +1001 -0.85723876953125 +1002 -0.86846923828125 +1003 -0.790008544921875 +1004 -0.857635498046875 +1005 -0.62847900390625 +1006 -0.701019287109375 +1007 -0.3956298828125 +1008 -0.466644287109375 +1009 -0.126708984375 +1010 -0.205657958984375 +1011 0.150115966796875 +1012 0.07098388671875 +1013 0.424041748046875 +1014 0.339111328125 +1015 0.670623779296875 +1016 0.56427001953125 +1017 0.854522705078125 +1018 0.731414794921875 +1019 0.866485595703125 +1020 0.827880859375 +1021 0.86920166015625 +1022 0.8563232421875 +1023 0.8653564453125 +1024 0.85687255859375 +1025 0.857147216796875 +1026 0.841522216796875 +1027 0.766845703125 +1028 0.772613525390625 +1029 0.628509521484375 +1030 0.66552734375 +1031 0.462127685546875 +1032 0.544281005859375 +1033 0.297210693359375 +1034 0.421051025390625 +1035 0.14862060546875 +1036 0.2769775390625 +1037 -0.00537109375 +1038 0.119354248046875 +1039 -0.15753173828125 +1040 -0.05450439453125 +1041 -0.31304931640625 +1042 -0.2568359375 +1043 -0.48876953125 +1044 -0.44708251953125 +1045 -0.6416015625 +1046 -0.604278564453125 +1047 -0.751373291015625 +1048 -0.749481201171875 +1049 -0.84619140625 +1050 -0.8563232421875 +1051 -0.861297607421875 +1052 -0.863983154296875 +1053 -0.863250732421875 +1054 -0.863189697265625 +1055 -0.856597900390625 +1056 -0.855255126953125 +1057 -0.7498779296875 +1058 -0.775177001953125 +1059 -0.624542236328125 +1060 -0.657257080078125 +1061 -0.47808837890625 +1062 -0.45770263671875 +1063 -0.253387451171875 +1064 -0.217071533203125 +1065 0.003692626953125 +1066 0.004547119140625 +1067 0.2257080078125 +1068 0.217926025390625 +1069 0.427154541015625 +1070 0.451385498046875 +1071 0.643218994140625 +1072 0.6968994140625 +1073 0.855926513671875 +1074 0.859954833984375 +1075 0.870361328125 +1076 0.870361328125 +1077 0.870361328125 +1078 0.870361328125 +1079 0.862762451171875 +1080 0.8629150390625 +1081 0.79669189453125 +1082 0.790863037109375 +1083 0.595794677734375 +1084 0.6055908203125 +1085 0.362152099609375 +1086 0.402740478515625 +1087 0.1270751953125 +1088 0.2022705078125 +1089 -0.086944580078125 +1090 0.006622314453125 +1091 -0.2784423828125 +1092 -0.214813232421875 +1093 -0.484832763671875 +1094 -0.4798583984375 +1095 -0.729583740234375 +1096 -0.7462158203125 +1097 -0.86688232421875 +1098 -0.86614990234375 +1099 -0.870391845703125 +1100 -0.870391845703125 +1101 -0.86859130859375 +1102 -0.870147705078125 +1103 -0.86279296875 +1104 -0.863006591796875 +1105 -0.817962646484375 +1106 -0.77215576171875 +1107 -0.6116943359375 +1108 -0.5177001953125 +1109 -0.3128662109375 +1110 -0.203094482421875 +1111 0.039398193359375 +1112 0.15142822265625 +1113 0.422821044921875 +1114 0.5162353515625 +1115 0.805145263671875 +1116 0.83343505859375 +1117 0.870361328125 +1118 0.870361328125 +1119 0.870361328125 +1120 0.870361328125 +1121 0.860015869140625 +1122 0.860992431640625 +1123 0.727935791015625 +1124 0.75042724609375 +1125 0.48114013671875 +1126 0.542449951171875 +1127 0.2059326171875 +1128 0.320953369140625 +1129 -0.06103515625 +1130 0.1038818359375 +1131 -0.29913330078125 +1132 -0.114471435546875 +1133 -0.516204833984375 +1134 -0.343231201171875 +1135 -0.7252197265625 +1136 -0.55914306640625 +1137 -0.85980224609375 +1138 -0.733428955078125 +1139 -0.870391845703125 +1140 -0.844024658203125 +1141 -0.870391845703125 +1142 -0.8544921875 +1143 -0.858062744140625 +1144 -0.769134521484375 +1145 -0.673004150390625 +1146 -0.64306640625 +1147 -0.42694091796875 +1148 -0.52520751953125 +1149 -0.2100830078125 +1150 -0.424163818359375 +1151 -0.0362548828125 +1152 -0.324798583984375 +1153 0.10943603515625 +1154 -0.219085693359375 +1155 0.23516845703125 +1156 -0.078948974609375 +1157 0.373687744140625 +1158 0.087554931640625 +1159 0.517791748046875 +1160 0.221160888671875 +1161 0.602783203125 +1162 0.32427978515625 +1163 0.635711669921875 +1164 0.42608642578125 +1165 0.655181884765625 +1166 0.5201416015625 +1167 0.65948486328125 +1168 0.603668212890625 +1169 0.651275634765625 +1170 0.661163330078125 +1171 0.61846923828125 +1172 0.667572021484375 +1173 0.53753662109375 +1174 0.615203857421875 +1175 0.404144287109375 +1176 0.5040283203125 +1177 0.22186279296875 +1178 0.343505859375 +1179 0.003997802734375 +1180 0.157379150390625 +1181 -0.22100830078125 +1182 -0.02935791015625 +1183 -0.42449951171875 +1184 -0.192413330078125 +1185 -0.579833984375 +1186 -0.2904052734375 +1187 -0.641876220703125 +1188 -0.326690673828125 +1189 -0.6177978515625 +1190 -0.357025146484375 +1191 -0.575531005859375 +1192 -0.387298583984375 +1193 -0.526336669921875 +1194 -0.37518310546875 +1195 -0.42645263671875 +1196 -0.30108642578125 +1197 -0.2581787109375 +1198 -0.202239990234375 +1199 -0.068695068359375 +1200 -0.11859130859375 +1201 0.09222412109375 +1202 -0.040740966796875 +1203 0.232147216796875 +1204 0.033233642578125 +1205 0.3509521484375 +1206 0.07086181640625 +1207 0.410064697265625 +1208 0.040618896484375 +1209 0.372955322265625 +1210 -0.044189453125 +1211 0.2554931640625 +1212 -0.14190673828125 +1213 0.10711669921875 +1214 -0.23785400390625 +1215 -0.052886962890625 +1216 -0.3013916015625 +1217 -0.186279296875 +1218 -0.283233642578125 +1219 -0.23291015625 +1220 -0.20123291015625 +1221 -0.209442138671875 +1222 -0.10968017578125 +1223 -0.174163818359375 +1224 -0.011566162109375 +1225 -0.126739501953125 +1226 0.106658935546875 +1227 -0.048126220703125 +1228 0.225921630859375 +1229 0.0426025390625 +1230 0.311187744140625 +1231 0.10748291015625 +1232 0.35638427734375 +1233 0.1409912109375 +1234 0.4080810546875 +1235 0.19708251953125 +1236 0.464691162109375 +1237 0.273651123046875 +1238 0.48089599609375 +1239 0.31768798828125 +1240 0.4686279296875 +1241 0.341094970703125 +1242 0.4510498046875 +1243 0.368011474609375 +1244 0.407989501953125 +1245 0.37249755859375 +1246 0.29522705078125 +1247 0.30072021484375 +1248 0.11474609375 +1249 0.1517333984375 +1250 -0.07855224609375 +1251 -0.01470947265625 +1252 -0.27313232421875 +1253 -0.1883544921875 +1254 -0.469879150390625 +1255 -0.372711181640625 +1256 -0.620147705078125 +1257 -0.51397705078125 +1258 -0.687469482421875 +1259 -0.57177734375 +1260 -0.66546630859375 +1261 -0.53948974609375 +1262 -0.569793701171875 +1263 -0.43511962890625 +1264 -0.433807373046875 +1265 -0.2962646484375 +1266 -0.2918701171875 +1267 -0.161102294921875 +1268 -0.15771484375 +1269 -0.0435791015625 +1270 -0.029754638671875 +1271 0.060394287109375 +1272 0.07745361328125 +1273 0.13665771484375 +1274 0.148468017578125 +1275 0.170135498046875 +1276 0.185089111328125 +1277 0.16552734375 +1278 0.21514892578125 +1279 0.15728759765625 +1280 0.241607666015625 +1281 0.150787353515625 +1282 0.241943359375 +1283 0.12200927734375 +1284 0.222625732421875 +1285 0.080108642578125 +1286 0.205413818359375 +1287 0.05126953125 +1288 0.213592529296875 +1289 0.062896728515625 +1290 0.2286376953125 +1291 0.09271240234375 +1292 0.2108154296875 +1293 0.092987060546875 +1294 0.1739501953125 +1295 0.07855224609375 +1296 0.132232666015625 +1297 0.06427001953125 +1298 0.0743408203125 +1299 0.0347900390625 +1300 0.000518798828125 +1301 -0.01171875 +1302 -0.070953369140625 +1303 -0.056060791015625 +1304 -0.10198974609375 +1305 -0.055511474609375 +1306 -0.09124755859375 +1307 -0.010467529296875 +1308 -0.083221435546875 +1309 0.02508544921875 +1310 -0.0985107421875 +1311 0.025665283203125 +1312 -0.11431884765625 +1313 0.017333984375 +1314 -0.128875732421875 +1315 0.00189208984375 +1316 -0.151702880859375 +1317 -0.03173828125 +1318 -0.17315673828125 +1319 -0.071502685546875 +1320 -0.209381103515625 +1321 -0.13543701171875 +1322 -0.25848388671875 +1323 -0.219970703125 +1324 -0.30096435546875 +1325 -0.300506591796875 +1326 -0.337677001953125 +1327 -0.376312255859375 +1328 -0.343597412109375 +1329 -0.416107177734375 +1330 -0.278778076171875 +1331 -0.371124267578125 +1332 -0.145416259765625 +1333 -0.242279052734375 +1334 0.021087646484375 +1335 -0.069732666015625 +1336 0.201995849609375 +1337 0.125640869140625 +1338 0.370208740234375 +1339 0.31268310546875 +1340 0.494476318359375 +1341 0.45501708984375 +1342 0.57659912109375 +1343 0.554779052734375 +1344 0.615753173828125 +1345 0.61065673828125 +1346 0.602630615234375 +1347 0.610931396484375 +1348 0.517578125 +1349 0.531463623046875 +1350 0.37530517578125 +1351 0.3883056640625 +1352 0.22222900390625 +1353 0.23468017578125 +1354 0.08062744140625 +1355 0.095245361328125 +1356 -0.026092529296875 +1357 -0.00396728515625 +1358 -0.08447265625 +1359 -0.04852294921875 +1360 -0.107635498046875 +1361 -0.055145263671875 +1362 -0.138916015625 +1363 -0.0758056640625 +1364 -0.20166015625 +1365 -0.138702392578125 +1366 -0.266021728515625 +1367 -0.209197998046875 +1368 -0.3333740234375 +1369 -0.289031982421875 +1370 -0.404449462890625 +1371 -0.37884521484375 +1372 -0.460662841796875 +1373 -0.456329345703125 +1374 -0.4984130859375 +1375 -0.51641845703125 +1376 -0.484649658203125 +1377 -0.519287109375 +1378 -0.4146728515625 +1379 -0.458251953125 +1380 -0.33331298828125 +1381 -0.384796142578125 +1382 -0.26263427734375 +1383 -0.323699951171875 +1384 -0.198822021484375 +1385 -0.269287109375 +1386 -0.12042236328125 +1387 -0.1951904296875 +1388 -0.027008056640625 +1389 -0.100006103515625 +1390 0.0579833984375 +1391 -0.01055908203125 +1392 0.159881591796875 +1393 0.1033935546875 +1394 0.28466796875 +1395 0.24908447265625 +1396 0.387115478515625 +1397 0.373199462890625 +1398 0.452484130859375 +1399 0.45806884765625 +1400 0.48785400390625 +1401 0.511474609375 +1402 0.52105712890625 +1403 0.565399169921875 +1404 0.545684814453125 +1405 0.61138916015625 +1406 0.511810302734375 +1407 0.5897216796875 +1408 0.411956787109375 +1409 0.4906005859375 +1410 0.2618408203125 +1411 0.33148193359375 +1412 0.09234619140625 +1413 0.147796630859375 +1414 -0.06036376953125 +1415 -0.01873779296875 +1416 -0.172088623046875 +1417 -0.140289306640625 +1418 -0.221282958984375 +1419 -0.191986083984375 +1420 -0.2166748046875 +1421 -0.184295654296875 +1422 -0.196197509765625 +1423 -0.161834716796875 +1424 -0.1956787109375 +1425 -0.166595458984375 +1426 -0.21148681640625 +1427 -0.19390869140625 +1428 -0.227691650390625 +1429 -0.22442626953125 +1430 -0.26324462890625 +1431 -0.279754638671875 +1432 -0.301055908203125 +1433 -0.3389892578125 +1434 -0.30126953125 +1435 -0.3543701171875 +1436 -0.28350830078125 +1437 -0.348175048828125 +1438 -0.253173828125 +1439 -0.32598876953125 +1440 -0.185699462890625 +1441 -0.2581787109375 +1442 -0.077362060546875 +1443 -0.139801025390625 +1444 0.05914306640625 +1445 0.014617919921875 +1446 0.171966552734375 +1447 0.144378662109375 +1448 0.236907958984375 +1449 0.221038818359375 +1450 0.276214599609375 +1451 0.27069091796875 +1452 0.290740966796875 +1453 0.294036865234375 +1454 0.298431396484375 +1455 0.311767578125 +1456 0.31268310546875 +1457 0.339141845703125 +1458 0.320404052734375 +1459 0.360260009765625 +1460 0.309783935546875 +1461 0.360504150390625 +1462 0.2550048828125 +1463 0.308380126953125 +1464 0.1380615234375 +1465 0.18170166015625 +1466 -0.019989013671875 +1467 0.0047607421875 +1468 -0.1793212890625 +1469 -0.17559814453125 +1470 -0.301727294921875 +1471 -0.3143310546875 +1472 -0.350311279296875 +1473 -0.36785888671875 +1474 -0.3470458984375 +1475 -0.36248779296875 +1476 -0.329986572265625 +1477 -0.343536376953125 +1478 -0.2916259765625 +1479 -0.3018798828125 +1480 -0.227081298828125 +1481 -0.231414794921875 +1482 -0.12451171875 +1483 -0.117645263671875 +1484 -0.011505126953125 +1485 0.007049560546875 +1486 0.06549072265625 +1487 0.087982177734375 +1488 0.117950439453125 +1489 0.13946533203125 +1490 0.156097412109375 +1491 0.17425537109375 +1492 0.175933837890625 +1493 0.188201904296875 +1494 0.1685791015625 +1495 0.171234130859375 +1496 0.12957763671875 +1497 0.118438720703125 +1498 0.081573486328125 +1499 0.05706787109375 +1500 0.026214599609375 +1501 -0.010711669921875 +1502 -0.041961669921875 +1503 -0.0914306640625 +1504 -0.103759765625 +1505 -0.162322998046875 +1506 -0.134796142578125 +1507 -0.194549560546875 +1508 -0.102203369140625 +1509 -0.1492919921875 +1510 -0.00152587890625 +1511 -0.02166748046875 +1512 0.1136474609375 +1513 0.124053955078125 +1514 0.17926025390625 +1515 0.211151123046875 +1516 0.196441650390625 +1517 0.240447998046875 +1518 0.191009521484375 +1519 0.242218017578125 +1520 0.171112060546875 +1521 0.2257080078125 +1522 0.139923095703125 +1523 0.194366455078125 +1524 0.070220947265625 +1525 0.115509033203125 +1526 -0.017913818359375 +1527 0.0128173828125 +1528 -0.074127197265625 +1529 -0.053802490234375 +1530 -0.12054443359375 +1531 -0.110626220703125 +1532 -0.192413330078125 +1533 -0.199493408203125 +1534 -0.26806640625 +1535 -0.29437255859375 +1536 -0.295135498046875 +1537 -0.33221435546875 +1538 -0.246734619140625 +1539 -0.27972412109375 +1540 -0.162811279296875 +1541 -0.185333251953125 +1542 -0.108062744140625 +1543 -0.128204345703125 +1544 -0.089111328125 +1545 -0.115692138671875 +1546 -0.081298828125 +1547 -0.116455078125 +1548 -0.06536865234375 +1549 -0.105926513671875 +1550 -0.017364501953125 +1551 -0.053955078125 +1552 0.06988525390625 +1553 0.048797607421875 +1554 0.159881591796875 +1555 0.157318115234375 +1556 0.204376220703125 +1557 0.212005615234375 +1558 0.207977294921875 +1559 0.218475341796875 +1560 0.219757080078125 +1561 0.23724365234375 +1562 0.2698974609375 +1563 0.30535888671875 +1564 0.32513427734375 +1565 0.38128662109375 +1566 0.3369140625 +1567 0.404449462890625 +1568 0.32147216796875 +1569 0.3944091796875 +1570 0.3094482421875 +1571 0.3885498046875 +1572 0.281707763671875 +1573 0.362640380859375 +1574 0.203765869140625 +1575 0.27362060546875 +1576 0.072418212890625 +1577 0.11712646484375 +1578 -0.070098876953125 +1579 -0.054901123046875 +1580 -0.181915283203125 +1581 -0.19085693359375 +1582 -0.258941650390625 +1583 -0.28570556640625 +1584 -0.30108642578125 +1585 -0.339263916015625 +1586 -0.329437255859375 +1587 -0.3775634765625 +1588 -0.380645751953125 +1589 -0.445709228515625 +1590 -0.447998046875 +1591 -0.535064697265625 +1592 -0.51837158203125 +1593 -0.629058837890625 +1594 -0.567779541015625 +1595 -0.697601318359375 +1596 -0.56683349609375 +1597 -0.70391845703125 +1598 -0.51141357421875 +1599 -0.6424560546875 +1600 -0.384063720703125 +1601 -0.491241455078125 +1602 -0.197479248046875 +1603 -0.265716552734375 +1604 0.0013427734375 +1605 -0.023712158203125 +1606 0.185577392578125 +1607 0.201751708984375 +1608 0.326995849609375 +1609 0.375823974609375 +1610 0.414764404296875 +1611 0.485076904296875 +1612 0.480712890625 +1613 0.56884765625 +1614 0.5311279296875 +1615 0.634765625 +1616 0.529693603515625 +1617 0.63763427734375 +1618 0.4674072265625 +1619 0.5660400390625 +1620 0.3865966796875 +1621 0.4720458984375 +1622 0.328948974609375 +1623 0.40692138671875 +1624 0.300537109375 +1625 0.3778076171875 +1626 0.29534912109375 +1627 0.376953125 +1628 0.287445068359375 +1629 0.371978759765625 +1630 0.236846923828125 +1631 0.313140869140625 +1632 0.1307373046875 +1633 0.184417724609375 +1634 -0.010223388671875 +1635 0.011199951171875 +1636 -0.157379150390625 +1637 -0.171051025390625 +1638 -0.290618896484375 +1639 -0.33740234375 +1640 -0.397216796875 +1641 -0.47198486328125 +1642 -0.465728759765625 +1643 -0.560394287109375 +1644 -0.478485107421875 +1645 -0.58056640625 +1646 -0.447845458984375 +1647 -0.54754638671875 +1648 -0.412200927734375 +1649 -0.508575439453125 +1650 -0.368438720703125 +1651 -0.459503173828125 +1652 -0.311981201171875 +1653 -0.394378662109375 +1654 -0.27484130859375 +1655 -0.35260009765625 +1656 -0.239044189453125 +1657 -0.31170654296875 +1658 -0.14471435546875 +1659 -0.197418212890625 +1660 0.00946044921875 +1661 -0.007965087890625 +1662 0.1837158203125 +1663 0.207489013671875 +1664 0.345977783203125 +1665 0.409210205078125 +1666 0.47601318359375 +1667 0.57208251953125 +1668 0.549560546875 +1669 0.66595458984375 +1670 0.540863037109375 +1671 0.65875244140625 +1672 0.463836669921875 +1673 0.56744384765625 +1674 0.3504638671875 +1675 0.431396484375 +1676 0.236358642578125 +1677 0.29443359375 +1678 0.14263916015625 +1679 0.182464599609375 +1680 0.04376220703125 +1681 0.06365966796875 +1682 -0.0714111328125 +1683 -0.075958251953125 +1684 -0.16485595703125 +1685 -0.189422607421875 +1686 -0.23260498046875 +1687 -0.271942138671875 +1688 -0.28997802734375 +1689 -0.342529296875 +1690 -0.307098388671875 +1691 -0.364166259765625 +1692 -0.276214599609375 +1693 -0.327239990234375 +1694 -0.233917236328125 +1695 -0.2769775390625 +1696 -0.212921142578125 +1697 -0.253692626953125 +1698 -0.20220947265625 +1699 -0.24365234375 +1700 -0.162811279296875 +1701 -0.1983642578125 +1702 -0.093597412109375 +1703 -0.116241455078125 +1704 -0.026641845703125 +1705 -0.036834716796875 +1706 0.033843994140625 +1707 0.034881591796875 +1708 0.08154296875 +1709 0.09124755859375 +1710 0.09747314453125 +1711 0.10888671875 +1712 0.112030029296875 +1713 0.125518798828125 +1714 0.1385498046875 +1715 0.15771484375 +1716 0.155029296875 +1717 0.17828369140625 +1718 0.148468017578125 +1719 0.17108154296875 +1720 0.113983154296875 +1721 0.129974365234375 +1722 0.073822021484375 +1723 0.082427978515625 +1724 0.02752685546875 +1725 0.027679443359375 +1726 -0.050140380859375 +1727 -0.065643310546875 +1728 -0.128173828125 +1729 -0.15936279296875 +1730 -0.173828125 +1731 -0.21307373046875 +1732 -0.193359375 +1733 -0.234649658203125 +1734 -0.1673583984375 +1735 -0.2001953125 +1736 -0.103363037109375 +1737 -0.119171142578125 +1738 -0.02813720703125 +1739 -0.024749755859375 +1740 0.060577392578125 +1741 0.085784912109375 +1742 0.135101318359375 +1743 0.178131103515625 +1744 0.165771484375 +1745 0.215576171875 +1746 0.163299560546875 +1747 0.211456298828125 +1748 0.13525390625 +1749 0.17523193359375 +1750 0.099212646484375 +1751 0.128753662109375 +1752 0.079254150390625 +1753 0.1019287109375 +1754 0.058807373046875 +1755 0.0743408203125 +1756 0.035552978515625 +1757 0.04327392578125 +1758 0.033203125 +1759 0.038177490234375 +1760 0.065582275390625 +1761 0.076263427734375 +1762 0.119293212890625 +1763 0.14105224609375 +1764 0.157012939453125 +1765 0.186431884765625 +1766 0.15960693359375 +1767 0.188812255859375 +1768 0.11962890625 +1769 0.1390380859375 +1770 0.040863037109375 +1771 0.041778564453125 +1772 -0.0576171875 +1773 -0.079437255859375 +1774 -0.17156982421875 +1775 -0.219390869140625 +1776 -0.29266357421875 +1777 -0.367828369140625 +1778 -0.396697998046875 +1779 -0.494873046875 +1780 -0.447784423828125 +1781 -0.556243896484375 +1782 -0.410919189453125 +1783 -0.508697509765625 +1784 -0.304901123046875 +1785 -0.3756103515625 +1786 -0.179656982421875 +1787 -0.218902587890625 +1788 -0.05548095703125 +1789 -0.063751220703125 +1790 0.06903076171875 +1791 0.091552734375 +1792 0.18499755859375 +1793 0.23602294921875 +1794 0.27093505859375 +1795 0.342987060546875 +1796 0.313232421875 +1797 0.39520263671875 +1798 0.309539794921875 +1799 0.389373779296875 +1800 0.259063720703125 +1801 0.324249267578125 +1802 0.180816650390625 +1803 0.224090576171875 +1804 0.1024169921875 +1805 0.124267578125 +1806 0.033538818359375 +1807 0.037078857421875 +1808 -0.004425048828125 +1809 -0.010101318359375 +1810 -0.013092041015625 +1811 -0.019439697265625 +1812 -0.017059326171875 +1813 -0.022796630859375 +1814 -0.0018310546875 +1815 -0.001556396484375 +1816 0.0419921875 +1817 0.056304931640625 +1818 0.080230712890625 +1819 0.106719970703125 +1820 0.07196044921875 +1821 0.096893310546875 +1822 0.029510498046875 +1823 0.042694091796875 +1824 -0.017791748046875 +1825 -0.018035888671875 +1826 -0.062591552734375 +1827 -0.07586669921875 +1828 -0.096099853515625 +1829 -0.11944580078125 +1830 -0.12689208984375 +1831 -0.15972900390625 +1832 -0.1595458984375 +1833 -0.202606201171875 +1834 -0.194488525390625 +1835 -0.24859619140625 +1836 -0.237548828125 +1837 -0.30517578125 +1838 -0.280853271484375 +1839 -0.36212158203125 +1840 -0.302734375 +1841 -0.39141845703125 +1842 -0.273895263671875 +1843 -0.35528564453125 +1844 -0.191497802734375 +1845 -0.249969482421875 +1846 -0.069091796875 +1847 -0.092864990234375 +1848 0.0723876953125 +1849 0.08905029296875 +1850 0.185943603515625 +1851 0.2352294921875 +1852 0.250732421875 +1853 0.318817138671875 +1854 0.2813720703125 +1855 0.358642578125 +1856 0.272491455078125 +1857 0.347747802734375 +1858 0.2237548828125 +1859 0.28564453125 +1860 0.174652099609375 +1861 0.223175048828125 +1862 0.1534423828125 +1863 0.196746826171875 +1864 0.139617919921875 +1865 0.179840087890625 +1866 0.120086669921875 +1867 0.155548095703125 +1868 0.116119384765625 +1869 0.151214599609375 +1870 0.12005615234375 +1871 0.156951904296875 +1872 0.10009765625 +1873 0.13177490234375 +1874 0.075775146484375 +1875 0.100799560546875 +1876 0.06500244140625 +1877 0.087127685546875 +1878 0.03997802734375 +1879 0.05487060546875 +1880 -0.009429931640625 +1881 -0.009002685546875 +1882 -0.08282470703125 +1883 -0.10400390625 +1884 -0.1796875 +1885 -0.229400634765625 +1886 -0.27703857421875 +1887 -0.35552978515625 +1888 -0.343505859375 +1889 -0.441925048828125 +1890 -0.367706298828125 +1891 -0.473846435546875 +1892 -0.360137939453125 +1893 -0.464813232421875 +1894 -0.324127197265625 +1895 -0.419097900390625 +1896 -0.25787353515625 +1897 -0.334320068359375 +1898 -0.1749267578125 +1899 -0.227935791015625 +1900 -0.093597412109375 +1901 -0.12347412109375 +1902 -0.019073486328125 +1903 -0.02764892578125 +1904 0.06268310546875 +1905 0.077667236328125 +1906 0.167816162109375 +1907 0.2132568359375 +1908 0.303863525390625 +1909 0.38885498046875 +1910 0.45404052734375 +1911 0.582794189453125 +1912 0.57098388671875 +1913 0.734039306640625 +1914 0.621795654296875 +1915 0.800140380859375 +1916 0.604339599609375 +1917 0.7783203125 +1918 0.5159912109375 +1919 0.6651611328125 +1920 0.35601806640625 +1921 0.45965576171875 +1922 0.1534423828125 +1923 0.199188232421875 +1924 -0.040802001953125 +1925 -0.050689697265625 +1926 -0.1824951171875 +1927 -0.23297119140625 +1928 -0.258056640625 +1929 -0.33013916015625 +1930 -0.287811279296875 +1931 -0.368408203125 +1932 -0.295928955078125 +1933 -0.378936767578125 +1934 -0.294281005859375 +1935 -0.376983642578125 +1936 -0.296173095703125 +1937 -0.37969970703125 +1938 -0.305023193359375 +1939 -0.391510009765625 +1940 -0.29986572265625 +1941 -0.385345458984375 +1942 -0.2657470703125 +1943 -0.3419189453125 +1944 -0.219512939453125 +1945 -0.28289794921875 +1946 -0.194793701171875 +1947 -0.251617431640625 +1948 -0.205657958984375 +1949 -0.266143798828125 +1950 -0.210906982421875 +1951 -0.273345947265625 +1952 -0.166748046875 +1953 -0.216796875 +1954 -0.09783935546875 +1955 -0.128265380859375 +1956 -0.051055908203125 +1957 -0.068145751953125 +1958 -0.031585693359375 +1959 -0.0430908203125 +1960 -0.017181396484375 +1961 -0.024444580078125 +1962 0.0177001953125 +1963 0.020721435546875 +1964 0.097991943359375 +1965 0.124481201171875 +1966 0.201202392578125 +1967 0.25787353515625 +1968 0.294921875 +1969 0.379119873046875 +1970 0.37274169921875 +1971 0.47991943359375 +1972 0.4097900390625 +1973 0.5281982421875 +1974 0.396148681640625 +1975 0.511138916015625 +1976 0.3531494140625 +1977 0.456207275390625 +1978 0.31500244140625 +1979 0.407470703125 +1980 0.296356201171875 +1981 0.383758544921875 +1982 0.27532958984375 +1983 0.35687255859375 +1984 0.240325927734375 +1985 0.31182861328125 +1986 0.19305419921875 +1987 0.250885009765625 +1988 0.1268310546875 +1989 0.1654052734375 +1990 0.026031494140625 +1991 0.035247802734375 +1992 -0.111297607421875 +1993 -0.142059326171875 +1994 -0.261199951171875 +1995 -0.33563232421875 +1996 -0.415191650390625 +1997 -0.5345458984375 +1998 -0.56011962890625 +1999 -0.72186279296875 +2000 -0.648773193359375 +2001 -0.836669921875 +2002 -0.645233154296875 +2003 -0.8326416015625 +2004 -0.56494140625 +2005 -0.7296142578125 +2006 -0.4505615234375 +2007 -0.582550048828125 +2008 -0.339813232421875 +2009 -0.440093994140625 +2010 -0.249847412109375 +2011 -0.324310302734375 +2012 -0.154510498046875 +2013 -0.20147705078125 +2014 -0.032867431640625 +2015 -0.044647216796875 +2016 0.08233642578125 +2017 0.103973388671875 +2018 0.15850830078125 +2019 0.202392578125 +2020 0.2064208984375 +2021 0.264495849609375 +2022 0.263824462890625 +2023 0.338897705078125 +2024 0.3448486328125 +2025 0.443817138671875 +2026 0.42303466796875 +2027 0.545074462890625 +2028 0.478668212890625 +2029 0.6173095703125 +2030 0.50555419921875 +2031 0.6524658203125 +2032 0.513702392578125 +2033 0.66339111328125 +2034 0.5078125 +2035 0.6561279296875 +2036 0.469329833984375 +2037 0.606781005859375 +2038 0.38726806640625 +2039 0.501190185546875 +2040 0.272064208984375 +2041 0.352783203125 +2042 0.135345458984375 +2043 0.176544189453125 +2044 -0.028533935546875 +2045 -0.034820556640625 +2046 -0.201629638671875 +2047 -0.258209228515625 +2048 -0.344451904296875 +2049 -0.44244384765625 +2050 -0.4473876953125 +2051 -0.5753173828125 +2052 -0.50689697265625 +2053 -0.65203857421875 +2054 -0.5 +2055 -0.641632080078125 +2056 -0.440277099609375 +2057 -0.562164306640625 +2058 -0.36090087890625 +2059 -0.458038330078125 +2060 -0.277923583984375 +2061 -0.350555419921875 +2062 -0.20709228515625 +2063 -0.260528564453125 +2064 -0.15179443359375 +2065 -0.192108154296875 +2066 -0.109771728515625 +2067 -0.141937255859375 +2068 -0.075469970703125 +2069 -0.1021728515625 +2070 -0.041748046875 +2071 -0.062896728515625 +2072 0.00018310546875 +2073 -0.011932373046875 +2074 0.059173583984375 +2075 0.062835693359375 +2076 0.125640869140625 +2077 0.148712158203125 +2078 0.19647216796875 +2079 0.241729736328125 +2080 0.277008056640625 +2081 0.34912109375 +2082 0.357177734375 +2083 0.457305908203125 +2084 0.42034912109375 +2085 0.54388427734375 +2086 0.439849853515625 +2087 0.5728759765625 +2088 0.387786865234375 +2089 0.506591796875 +2090 0.268951416015625 +2091 0.351226806640625 +2092 0.11309814453125 +2093 0.146514892578125 +2094 -0.040679931640625 +2095 -0.05523681640625 +2096 -0.1640625 +2097 -0.21624755859375 +2098 -0.255645751953125 +2099 -0.334930419921875 +2100 -0.30908203125 +2101 -0.402984619140625 +2102 -0.33978271484375 +2103 -0.4412841796875 +2104 -0.3818359375 +2105 -0.49578857421875 +2106 -0.43048095703125 +2107 -0.5601806640625 +2108 -0.460601806640625 +2109 -0.600738525390625 +2110 -0.447509765625 +2111 -0.584228515625 +2112 -0.367950439453125 +2113 -0.47930908203125 +2114 -0.21710205078125 +2115 -0.27935791015625 +2116 -0.01336669921875 +2117 -0.0089111328125 +2118 0.196044921875 +2119 0.268798828125 +2120 0.35821533203125 +2121 0.482818603515625 +2122 0.451080322265625 +2123 0.60369873046875 +2124 0.488555908203125 +2125 0.650421142578125 +2126 0.50103759765625 +2127 0.66400146484375 +2128 0.486175537109375 +2129 0.6414794921875 +2130 0.436248779296875 +2131 0.572540283203125 +2132 0.38165283203125 +2133 0.498138427734375 +2134 0.338104248046875 +2135 0.439453125 +2136 0.2900390625 +2137 0.375518798828125 +2138 0.21380615234375 +2139 0.274505615234375 +2140 0.08892822265625 +2141 0.1087646484375 +2142 -0.067901611328125 +2143 -0.099395751953125 +2144 -0.232940673828125 +2145 -0.3182373046875 +2146 -0.406982421875 +2147 -0.5489501953125 +2148 -0.57666015625 +2149 -0.7738037109375 +2150 -0.702423095703125 +2151 -0.86383056640625 +2152 -0.759429931640625 +2153 -0.870391845703125 +2154 -0.760772705078125 +2155 -0.86895751953125 +2156 -0.716156005859375 +2157 -0.861053466796875 +2158 -0.612640380859375 +2159 -0.765869140625 +2160 -0.441802978515625 +2161 -0.5301513671875 +2162 -0.208953857421875 +2163 -0.214691162109375 +2164 0.0538330078125 +2165 0.137359619140625 +2166 0.308349609375 +2167 0.474822998046875 +2168 0.528106689453125 +2169 0.76239013671875 +2170 0.692901611328125 +2171 0.867462158203125 +2172 0.802978515625 +2173 0.870361328125 +2174 0.849609375 +2175 0.86480712890625 +2176 0.836669921875 +2177 0.831817626953125 +2178 0.78216552734375 +2179 0.677581787109375 +2180 0.690338134765625 +2181 0.495880126953125 +2182 0.574920654296875 +2183 0.30767822265625 +2184 0.4375 +2185 0.116180419921875 +2186 0.254425048828125 +2187 -0.110748291015625 +2188 0.02056884765625 +2189 -0.381805419921875 +2190 -0.232208251953125 +2191 -0.6572265625 +2192 -0.459320068359375 +2193 -0.857421875 +2194 -0.62872314453125 +2195 -0.870391845703125 +2196 -0.73504638671875 +2197 -0.870391845703125 +2198 -0.7982177734375 +2199 -0.86444091796875 +2200 -0.84466552734375 +2201 -0.85723876953125 +2202 -0.855194091796875 +2203 -0.790008544921875 +2204 -0.80572509765625 +2205 -0.62847900390625 +2206 -0.677398681640625 +2207 -0.3956298828125 +2208 -0.50006103515625 +2209 -0.126708984375 +2210 -0.294036865234375 +2211 0.150115966796875 +2212 -0.068023681640625 +2213 0.424041748046875 +2214 0.15789794921875 +2215 0.670623779296875 +2216 0.354888916015625 +2217 0.854522705078125 +2218 0.509765625 +2219 0.866485595703125 +2220 0.610992431640625 +2221 0.86920166015625 +2222 0.6719970703125 +2223 0.8653564453125 +2224 0.702667236328125 +2225 0.857147216796875 +2226 0.700714111328125 +2227 0.766845703125 +2228 0.669891357421875 +2229 0.628509521484375 +2230 0.605072021484375 +2231 0.462127685546875 +2232 0.525390625 +2233 0.297210693359375 +2234 0.44000244140625 +2235 0.14862060546875 +2236 0.3319091796875 +2237 -0.00537109375 +2238 0.2066650390625 +2239 -0.15753173828125 +2240 0.06158447265625 +2241 -0.31304931640625 +2242 -0.11370849609375 +2243 -0.48876953125 +2244 -0.2843017578125 +2245 -0.6416015625 +2246 -0.431732177734375 +2247 -0.751373291015625 +2248 -0.573089599609375 +2249 -0.84619140625 +2250 -0.69732666015625 +2251 -0.861297607421875 +2252 -0.779693603515625 +2253 -0.863250732421875 +2254 -0.796600341796875 +2255 -0.856597900390625 +2256 -0.75701904296875 +2257 -0.7498779296875 +2258 -0.703948974609375 +2259 -0.624542236328125 +2260 -0.620941162109375 +2261 -0.47808837890625 +2262 -0.464508056640625 +2263 -0.253387451171875 +2264 -0.268585205078125 +2265 0.003692626953125 +2266 -0.08404541015625 +2267 0.2257080078125 +2268 0.098358154296875 +2269 0.427154541015625 +2270 0.30267333984375 +2271 0.643218994140625 +2272 0.5216064453125 +2273 0.855926513671875 +2274 0.71197509765625 +2275 0.870361328125 +2276 0.836761474609375 +2277 0.870361328125 +2278 0.859588623046875 +2279 0.862762451171875 +2280 0.859771728515625 +2281 0.79669189453125 +2282 0.835174560546875 +2283 0.595794677734375 +2284 0.719207763671875 +2285 0.362152099609375 +2286 0.57598876953125 +2287 0.1270751953125 +2288 0.4212646484375 +2289 -0.086944580078125 +2290 0.256622314453125 +2291 -0.2784423828125 +2292 0.056243896484375 +2293 -0.484832763671875 +2294 -0.19403076171875 +2295 -0.729583740234375 +2296 -0.45648193359375 +2297 -0.86688232421875 +2298 -0.68389892578125 +2299 -0.870391845703125 +2300 -0.856475830078125 +2301 -0.86859130859375 +2302 -0.870391845703125 +2303 -0.86279296875 +2304 -0.870391845703125 +2305 -0.817962646484375 +2306 -0.860198974609375 +2307 -0.6116943359375 +2308 -0.718719482421875 +2309 -0.3128662109375 +2310 -0.463897705078125 +2311 0.039398193359375 +2312 -0.159515380859375 +2313 0.422821044921875 +2314 0.1685791015625 +2315 0.805145263671875 +2316 0.470794677734375 +2317 0.870361328125 +2318 0.706451416015625 +2319 0.870361328125 +2320 0.85595703125 +2321 0.860015869140625 +2322 0.8651123046875 +2323 0.727935791015625 +2324 0.8656005859375 +2325 0.48114013671875 +2326 0.859619140625 +2327 0.2059326171875 +2328 0.8074951171875 +2329 -0.06103515625 +2330 0.684539794921875 +2331 -0.29913330078125 +2332 0.526153564453125 +2333 -0.516204833984375 +2334 0.324798583984375 +2335 -0.7252197265625 +2336 0.101287841796875 +2337 -0.85980224609375 +2338 -0.1173095703125 +2339 -0.870391845703125 +2340 -0.3079833984375 +2341 -0.870391845703125 +2342 -0.434814453125 +2343 -0.858062744140625 +2344 -0.494354248046875 +2345 -0.673004150390625 +2346 -0.52423095703125 +2347 -0.42694091796875 +2348 -0.5570068359375 +2349 -0.2100830078125 +2350 -0.592803955078125 +2351 -0.0362548828125 +2352 -0.613128662109375 +2353 0.10943603515625 +2354 -0.60638427734375 +2355 0.23516845703125 +2356 -0.54595947265625 +2357 0.373687744140625 +2358 -0.4361572265625 +2359 0.517791748046875 +2360 -0.324737548828125 +2361 0.602783203125 +2362 -0.210723876953125 +2363 0.635711669921875 +2364 -0.072723388671875 +2365 0.655181884765625 +2366 0.080322265625 +2367 0.65948486328125 +2368 0.241363525390625 +2369 0.651275634765625 +2370 0.3922119140625 +2371 0.61846923828125 +2372 0.50640869140625 +2373 0.53753662109375 +2374 0.571563720703125 +2375 0.404144287109375 +2376 0.581817626953125 +2377 0.22186279296875 +2378 0.53961181640625 +2379 0.003997802734375 +2380 0.459808349609375 +2381 -0.22100830078125 +2382 0.359344482421875 +2383 -0.42449951171875 +2384 0.255828857421875 +2385 -0.579833984375 +2386 0.18206787109375 +2387 -0.641876220703125 +2388 0.1356201171875 +2389 -0.6177978515625 +2390 0.07257080078125 +2391 -0.575531005859375 +2392 -0.0091552734375 +2393 -0.526336669921875 +2394 -0.071380615234375 +2395 -0.42645263671875 +2396 -0.093719482421875 +2397 -0.2581787109375 +2398 -0.101776123046875 +2399 -0.068695068359375 +2400 -0.123138427734375 +2401 0.09222412109375 +2402 -0.145233154296875 +2403 0.232147216796875 +2404 -0.161895751953125 +2405 0.3509521484375 +2406 -0.1956787109375 +2407 0.410064697265625 +2408 -0.2691650390625 +2409 0.372955322265625 +2410 -0.36932373046875 +2411 0.2554931640625 +2412 -0.4609375 +2413 0.10711669921875 +2414 -0.531951904296875 +2415 -0.052886962890625 +2416 -0.55828857421875 +2417 -0.186279296875 +2418 -0.501617431640625 +2419 -0.23291015625 +2420 -0.379302978515625 +2421 -0.209442138671875 +2422 -0.239044189453125 +2423 -0.174163818359375 +2424 -0.087188720703125 +2425 -0.126739501953125 +2426 0.083282470703125 +2427 -0.048126220703125 +2428 0.252685546875 +2429 0.0426025390625 +2430 0.3885498046875 +2431 0.10748291015625 +2432 0.48248291015625 +2433 0.1409912109375 +2434 0.56964111328125 +2435 0.19708251953125 +2436 0.646636962890625 +2437 0.273651123046875 +2438 0.675201416015625 +2439 0.31768798828125 +2440 0.6646728515625 +2441 0.341094970703125 +2442 0.634429931640625 +2443 0.368011474609375 +2444 0.569305419921875 +2445 0.37249755859375 +2446 0.435272216796875 +2447 0.30072021484375 +2448 0.236572265625 +2449 0.1517333984375 +2450 0.02105712890625 +2451 -0.01470947265625 +2452 -0.198486328125 +2453 -0.1883544921875 +2454 -0.41937255859375 +2455 -0.372711181640625 +2456 -0.598602294921875 +2457 -0.51397705078125 +2458 -0.703460693359375 +2459 -0.57177734375 +2460 -0.726165771484375 +2461 -0.53948974609375 +2462 -0.677581787109375 +2463 -0.43511962890625 +2464 -0.583648681640625 +2465 -0.2962646484375 +2466 -0.471893310546875 +2467 -0.161102294921875 +2468 -0.353668212890625 +2469 -0.0435791015625 +2470 -0.228515625 +2471 0.060394287109375 +2472 -0.1097412109375 +2473 0.13665771484375 +2474 -0.011962890625 +2475 0.170135498046875 +2476 0.0638427734375 +2477 0.16552734375 +2478 0.137725830078125 +2479 0.15728759765625 +2480 0.209136962890625 +2481 0.150787353515625 +2482 0.2569580078125 +2483 0.12200927734375 +2484 0.284210205078125 +2485 0.080108642578125 +2486 0.3067626953125 +2487 0.05126953125 +2488 0.3421630859375 +2489 0.062896728515625 +2490 0.37353515625 +2491 0.09271240234375 +2492 0.3668212890625 +2493 0.092987060546875 +2494 0.333465576171875 +2495 0.07855224609375 +2496 0.2857666015625 +2497 0.06427001953125 +2498 0.215240478515625 +2499 0.0347900390625 +2500 0.12359619140625 +2501 -0.01171875 +2502 0.0279541015625 +2503 -0.056060791015625 +2504 -0.037567138671875 +2505 -0.055511474609375 +2506 -0.069580078125 +2507 -0.010467529296875 +2508 -0.10308837890625 +2509 0.02508544921875 +2510 -0.153167724609375 +2511 0.025665283203125 +2512 -0.198760986328125 +2513 0.017333984375 +2514 -0.23675537109375 +2515 0.00189208984375 +2516 -0.27392578125 +2517 -0.03173828125 +2518 -0.3013916015625 +2519 -0.071502685546875 +2520 -0.332427978515625 +2521 -0.13543701171875 +2522 -0.36566162109375 +2523 -0.219970703125 +2524 -0.38543701171875 +2525 -0.300506591796875 +2526 -0.393585205078125 +2527 -0.376312255859375 +2528 -0.370513916015625 +2529 -0.416107177734375 +2530 -0.284515380859375 +2531 -0.371124267578125 +2532 -0.13922119140625 +2533 -0.242279052734375 +2534 0.033843994140625 +2535 -0.069732666015625 +2536 0.2171630859375 +2537 0.125640869140625 +2538 0.38629150390625 +2539 0.31268310546875 +2540 0.513641357421875 +2541 0.45501708984375 +2542 0.599578857421875 +2543 0.554779052734375 +2544 0.6427001953125 +2545 0.61065673828125 +2546 0.634796142578125 +2547 0.610931396484375 +2548 0.559478759765625 +2549 0.531463623046875 +2550 0.42950439453125 +2551 0.3883056640625 +2552 0.2845458984375 +2553 0.23468017578125 +2554 0.144317626953125 +2555 0.095245361328125 +2556 0.02972412109375 +2557 -0.00396728515625 +2558 -0.046478271484375 +2559 -0.04852294921875 +2560 -0.09393310546875 +2561 -0.055145263671875 +2562 -0.14727783203125 +2563 -0.0758056640625 +2564 -0.22430419921875 +2565 -0.138702392578125 +2566 -0.299041748046875 +2567 -0.209197998046875 +2568 -0.37139892578125 +2569 -0.289031982421875 +2570 -0.441131591796875 +2571 -0.37884521484375 +2572 -0.492462158203125 +2573 -0.456329345703125 +2574 -0.52227783203125 +2575 -0.51641845703125 +2576 -0.50360107421875 +2577 -0.519287109375 +2578 -0.43310546875 +2579 -0.458251953125 +2580 -0.348541259765625 +2581 -0.384796142578125 +2582 -0.269195556640625 +2583 -0.323699951171875 +2584 -0.19317626953125 +2585 -0.269287109375 +2586 -0.104156494140625 +2587 -0.1951904296875 +2588 -0.003173828125 +2589 -0.100006103515625 +2590 0.08917236328125 +2591 -0.01055908203125 +2592 0.192535400390625 +2593 0.1033935546875 +2594 0.310882568359375 +2595 0.24908447265625 +2596 0.406219482421875 +2597 0.373199462890625 +2598 0.4659423828125 +2599 0.45806884765625 +2600 0.495697021484375 +2601 0.511474609375 +2602 0.518524169921875 +2603 0.565399169921875 +2604 0.529541015625 +2605 0.61138916015625 +2606 0.48828125 +2607 0.5897216796875 +2608 0.389404296875 +2609 0.4906005859375 +2610 0.24688720703125 +2611 0.33148193359375 +2612 0.087249755859375 +2613 0.147796630859375 +2614 -0.05859375 +2615 -0.01873779296875 +2616 -0.16961669921875 +2617 -0.140289306640625 +2618 -0.227081298828125 +2619 -0.191986083984375 +2620 -0.2373046875 +2621 -0.184295654296875 +2622 -0.2308349609375 +2623 -0.161834716796875 +2624 -0.236724853515625 +2625 -0.166595458984375 +2626 -0.25177001953125 +2627 -0.19390869140625 +2628 -0.262847900390625 +2629 -0.22442626953125 +2630 -0.285797119140625 +2631 -0.279754638671875 +2632 -0.307037353515625 +2633 -0.3389892578125 +2634 -0.29437255859375 +2635 -0.3543701171875 +2636 -0.264739990234375 +2637 -0.348175048828125 +2638 -0.223480224609375 +2639 -0.32598876953125 +2640 -0.151275634765625 +2641 -0.2581787109375 +2642 -0.04595947265625 +2643 -0.139801025390625 +2644 0.081146240234375 +2645 0.014617919921875 +2646 0.186553955078125 +2647 0.144378662109375 +2648 0.249725341796875 +2649 0.221038818359375 +2650 0.288543701171875 +2651 0.27069091796875 +2652 0.303436279296875 +2653 0.294036865234375 +2654 0.30914306640625 +2655 0.311767578125 +2656 0.316802978515625 +2657 0.339141845703125 +2658 0.315765380859375 +2659 0.360260009765625 +2660 0.296875 +2661 0.360504150390625 +2662 0.239898681640625 +2663 0.308380126953125 +2664 0.131072998046875 +2665 0.18170166015625 +2666 -0.011688232421875 +2667 0.0047607421875 +2668 -0.155303955078125 +2669 -0.17559814453125 +2670 -0.268035888671875 +2671 -0.3143310546875 +2672 -0.319305419921875 +2673 -0.36785888671875 +2674 -0.326263427734375 +2675 -0.36248779296875 +2676 -0.319305419921875 +2677 -0.343536376953125 +2678 -0.29205322265625 +2679 -0.3018798828125 +2680 -0.24041748046875 +2681 -0.231414794921875 +2682 -0.154876708984375 +2683 -0.117645263671875 +2684 -0.058013916015625 +2685 0.007049560546875 +2686 0.012176513671875 +2687 0.087982177734375 +2688 0.06451416015625 +2689 0.13946533203125 +2690 0.106658935546875 +2691 0.17425537109375 +2692 0.134735107421875 +2693 0.188201904296875 +2694 0.140869140625 +2695 0.171234130859375 +2696 0.120819091796875 +2697 0.118438720703125 +2698 0.09228515625 +2699 0.05706787109375 +2700 0.056060791015625 +2701 -0.010711669921875 +2702 0.00726318359375 +2703 -0.0914306640625 +2704 -0.038787841796875 +2705 -0.162322998046875 +2706 -0.0625 +2707 -0.194549560546875 +2708 -0.03729248046875 +2709 -0.1492919921875 +2710 0.04058837890625 +2711 -0.02166748046875 +2712 0.128021240234375 +2713 0.124053955078125 +2714 0.173553466796875 +2715 0.211151123046875 +2716 0.17852783203125 +2717 0.240447998046875 +2718 0.16436767578125 +2719 0.242218017578125 +2720 0.13824462890625 +2721 0.2257080078125 +2722 0.103302001953125 +2723 0.194366455078125 +2724 0.03802490234375 +2725 0.115509033203125 +2726 -0.0408935546875 +2727 0.0128173828125 +2728 -0.09228515625 +2729 -0.053802490234375 +2730 -0.1337890625 +2731 -0.110626220703125 +2732 -0.19378662109375 +2733 -0.199493408203125 +2734 -0.254730224609375 +2735 -0.29437255859375 +2736 -0.27398681640625 +2737 -0.33221435546875 +2738 -0.229400634765625 +2739 -0.27972412109375 +2740 -0.154449462890625 +2741 -0.185333251953125 +2742 -0.10357666015625 +2743 -0.128204345703125 +2744 -0.08245849609375 +2745 -0.115692138671875 +2746 -0.07049560546875 +2747 -0.116455078125 +2748 -0.051666259765625 +2749 -0.105926513671875 +2750 -0.006072998046875 +2751 -0.053955078125 +2752 0.07208251953125 +2753 0.048797607421875 +2754 0.15179443359375 +2755 0.157318115234375 +2756 0.192291259765625 +2757 0.212005615234375 +2758 0.197265625 +2759 0.218475341796875 +2760 0.207916259765625 +2761 0.23724365234375 +2762 0.2496337890625 +2763 0.30535888671875 +2764 0.29449462890625 +2765 0.38128662109375 +2766 0.301727294921875 +2767 0.404449462890625 +2768 0.28515625 +2769 0.3944091796875 +2770 0.270782470703125 +2771 0.3885498046875 +2772 0.24273681640625 +2773 0.362640380859375 +2774 0.172271728515625 +2775 0.27362060546875 +2776 0.056976318359375 +2777 0.11712646484375 +2778 -0.0673828125 +2779 -0.054901123046875 +2780 -0.16534423828125 +2781 -0.19085693359375 +2782 -0.233245849609375 +2783 -0.28570556640625 +2784 -0.270843505859375 +2785 -0.339263916015625 +2786 -0.29583740234375 +2787 -0.3775634765625 +2788 -0.339019775390625 +2789 -0.445709228515625 +2790 -0.394775390625 +2791 -0.535064697265625 +2792 -0.452117919921875 +2793 -0.629058837890625 +2794 -0.490997314453125 +2795 -0.697601318359375 +2796 -0.48687744140625 +2797 -0.70391845703125 +2798 -0.43646240234375 +2799 -0.6424560546875 +2800 -0.32525634765625 +2801 -0.491241455078125 +2802 -0.164215087890625 +2803 -0.265716552734375 +2804 0.00689697265625 +2805 -0.023712158203125 +2806 0.165313720703125 +2807 0.201751708984375 +2808 0.287078857421875 +2809 0.375823974609375 +2810 0.362945556640625 +2811 0.485076904296875 +2812 0.419647216796875 +2813 0.56884765625 +2814 0.462432861328125 +2815 0.634765625 +2816 0.461212158203125 +2817 0.63763427734375 +2818 0.409210205078125 +2819 0.5660400390625 +2820 0.341064453125 +2821 0.4720458984375 +2822 0.290252685546875 +2823 0.40692138671875 +2824 0.26177978515625 +2825 0.3778076171875 +2826 0.251068115234375 +2827 0.376953125 +2828 0.237640380859375 +2829 0.371978759765625 +2830 0.18975830078125 +2831 0.313140869140625 +2832 0.0975341796875 +2833 0.184417724609375 +2834 -0.022125244140625 +2835 0.011199951171875 +2836 -0.1458740234375 +2837 -0.171051025390625 +2838 -0.257293701171875 +2839 -0.33740234375 +2840 -0.345977783203125 +2841 -0.47198486328125 +2842 -0.402557373046875 +2843 -0.560394287109375 +2844 -0.412841796875 +2845 -0.58056640625 +2846 -0.38677978515625 +2847 -0.54754638671875 +2848 -0.35528564453125 +2849 -0.508575439453125 +2850 -0.3160400390625 +2851 -0.459503173828125 +2852 -0.265625 +2853 -0.394378662109375 +2854 -0.230010986328125 +2855 -0.35260009765625 +2856 -0.195098876953125 +2857 -0.31170654296875 +2858 -0.113250732421875 +2859 -0.197418212890625 +2860 0.016265869140625 +2861 -0.007965087890625 +2862 0.1612548828125 +2863 0.207489013671875 +2864 0.29571533203125 +2865 0.409210205078125 +2866 0.403228759765625 +2867 0.57208251953125 +2868 0.4642333984375 +2869 0.66595458984375 +2870 0.45794677734375 +2871 0.65875244140625 +2872 0.3955078125 +2873 0.56744384765625 +2874 0.302642822265625 +2875 0.431396484375 +2876 0.208038330078125 +2877 0.29443359375 +2878 0.128875732421875 +2879 0.182464599609375 +2880 0.044891357421875 +2881 0.06365966796875 +2882 -0.05255126953125 +2883 -0.075958251953125 +2884 -0.132659912109375 +2885 -0.189422607421875 +2886 -0.19195556640625 +2887 -0.271942138671875 +2888 -0.242462158203125 +2889 -0.342529296875 +2890 -0.260009765625 +2891 -0.364166259765625 +2892 -0.238189697265625 +2893 -0.327239990234375 +2894 -0.20623779296875 +2895 -0.2769775390625 +2896 -0.1903076171875 +2897 -0.253692626953125 +2898 -0.181549072265625 +2899 -0.24365234375 +2900 -0.14874267578125 +2901 -0.1983642578125 +2902 -0.091064453125 +2903 -0.116241455078125 +2904 -0.034393310546875 +2905 -0.036834716796875 +2906 0.0177001953125 +2907 0.034881591796875 +2908 0.0599365234375 +2909 0.09124755859375 +2910 0.076904296875 +2911 0.10888671875 +2912 0.092681884765625 +2913 0.125518798828125 +2914 0.117767333984375 +2915 0.15771484375 +2916 0.13433837890625 +2917 0.17828369140625 +2918 0.13177490234375 +2919 0.17108154296875 +2920 0.106048583984375 +2921 0.129974365234375 +2922 0.074920654296875 +2923 0.082427978515625 +2924 0.037994384765625 +2925 0.027679443359375 +2926 -0.024932861328125 +2927 -0.065643310546875 +2928 -0.0889892578125 +2929 -0.15936279296875 +2930 -0.127777099609375 +2931 -0.21307373046875 +2932 -0.14617919921875 +2933 -0.234649658203125 +2934 -0.12847900390625 +2935 -0.2001953125 +2936 -0.08050537109375 +2937 -0.119171142578125 +2938 -0.0235595703125 +2939 -0.024749755859375 +2940 0.04437255859375 +2941 0.085784912109375 +2942 0.101226806640625 +2943 0.178131103515625 +2944 0.123382568359375 +2945 0.215576171875 +2946 0.119537353515625 +2947 0.211456298828125 +2948 0.09588623046875 +2949 0.17523193359375 +2950 0.066558837890625 +2951 0.128753662109375 +2952 0.05084228515625 +2953 0.1019287109375 +2954 0.035430908203125 +2955 0.0743408203125 +2956 0.01837158203125 +2957 0.04327392578125 +2958 0.01861572265625 +2959 0.038177490234375 +2960 0.047088623046875 +2961 0.076263427734375 +2962 0.0928955078125 +2963 0.14105224609375 +2964 0.12591552734375 +2965 0.186431884765625 +2966 0.13067626953125 +2967 0.188812255859375 +2968 0.101104736328125 +2969 0.1390380859375 +2970 0.040069580078125 +2971 0.041778564453125 +2972 -0.0372314453125 +2973 -0.079437255859375 +2974 -0.12750244140625 +2975 -0.219390869140625 +2976 -0.224029541015625 +2977 -0.367828369140625 +2978 -0.30743408203125 +2979 -0.494873046875 +2980 -0.348968505859375 +2981 -0.556243896484375 +2982 -0.32049560546875 +2983 -0.508697509765625 +2984 -0.23699951171875 +2985 -0.3756103515625 +2986 -0.13848876953125 +2987 -0.218902587890625 +2988 -0.04107666015625 +2989 -0.063751220703125 +2990 0.056488037109375 +2991 0.091552734375 +2992 0.14727783203125 +2993 0.23602294921875 +2994 0.214141845703125 +2995 0.342987060546875 +2996 0.246063232421875 +2997 0.39520263671875 +2998 0.240997314453125 +2999 0.389373779296875 +3000 0.19818115234375 +3001 0.324249267578125 +3002 0.133331298828125 +3003 0.224090576171875 +3004 0.0693359375 +3005 0.124267578125 +3006 0.01409912109375 +3007 0.037078857421875 +3008 -0.014678955078125 +3009 -0.010101318359375 +3010 -0.0185546875 +3011 -0.019439697265625 +3012 -0.018280029296875 +3013 -0.022796630859375 +3014 -0.001953125 +3015 -0.001556396484375 +3016 0.038055419921875 +3017 0.056304931640625 +3018 0.07305908203125 +3019 0.106719970703125 +3020 0.068756103515625 +3021 0.096893310546875 +3022 0.035308837890625 +3023 0.042694091796875 +3024 -0.002838134765625 +3025 -0.018035888671875 +3026 -0.03961181640625 +3027 -0.07586669921875 +3028 -0.06768798828125 +3029 -0.11944580078125 +3030 -0.094146728515625 +3031 -0.15972900390625 +3032 -0.122772216796875 +3033 -0.202606201171875 +3034 -0.15380859375 +3035 -0.24859619140625 +3036 -0.1920166015625 +3037 -0.30517578125 +3038 -0.230743408203125 +3039 -0.36212158203125 +3040 -0.251708984375 +3041 -0.39141845703125 +3042 -0.23028564453125 +3043 -0.35528564453125 +3044 -0.163970947265625 +3045 -0.249969482421875 +3046 -0.06396484375 +3047 -0.092864990234375 +3048 0.0523681640625 +3049 0.08905029296875 +3050 0.145904541015625 +3051 0.2352294921875 +3052 0.199249267578125 +3053 0.318817138671875 +3054 0.22467041015625 +3055 0.358642578125 +3056 0.2176513671875 +3057 0.347747802734375 +3058 0.1778564453125 +3059 0.28564453125 +3060 0.138214111328125 +3061 0.223175048828125 +3062 0.122222900390625 +3063 0.196746826171875 +3064 0.1126708984375 +3065 0.179840087890625 +3066 0.0985107421875 +3067 0.155548095703125 +3068 0.097381591796875 +3069 0.151214599609375 +3070 0.102783203125 +3071 0.156951904296875 +3072 0.08819580078125 +3073 0.13177490234375 +3074 0.069366455078125 +3075 0.100799560546875 +3076 0.06103515625 +3077 0.087127685546875 +3078 0.040924072265625 +3079 0.05487060546875 +3080 0.000885009765625 +3081 -0.009002685546875 +3082 -0.0587158203125 +3083 -0.10400390625 +3084 -0.137420654296875 +3085 -0.229400634765625 +3086 -0.216888427734375 +3087 -0.35552978515625 +3088 -0.272064208984375 +3089 -0.441925048828125 +3090 -0.293792724609375 +3091 -0.473846435546875 +3092 -0.29022216796875 +3093 -0.464813232421875 +3094 -0.26385498046875 +3095 -0.419097900390625 +3096 -0.213104248046875 +3097 -0.334320068359375 +3098 -0.14862060546875 +3099 -0.227935791015625 +3100 -0.084869384765625 +3101 -0.12347412109375 +3102 -0.02593994140625 +3103 -0.02764892578125 +3104 0.039337158203125 +3105 0.077667236328125 +3106 0.12371826171875 +3107 0.2132568359375 +3108 0.233154296875 +3109 0.38885498046875 +3110 0.354217529296875 +3111 0.582794189453125 +3112 0.44921875 +3113 0.734039306640625 +3114 0.49188232421875 +3115 0.800140380859375 +3116 0.480377197265625 +3117 0.7783203125 +3118 0.412506103515625 +3119 0.6651611328125 +3120 0.287567138671875 +3121 0.45965576171875 +3122 0.128509521484375 +3123 0.199188232421875 +3124 -0.024383544921875 +3125 -0.050689697265625 +3126 -0.13604736328125 +3127 -0.23297119140625 +3128 -0.195709228515625 +3129 -0.33013916015625 +3130 -0.219482421875 +3131 -0.368408203125 +3132 -0.226531982421875 +3133 -0.378936767578125 +3134 -0.22625732421875 +3135 -0.376983642578125 +3136 -0.229156494140625 +3137 -0.37969970703125 +3138 -0.237884521484375 +3139 -0.391510009765625 +3140 -0.235687255859375 +3141 -0.385345458984375 +3142 -0.2105712890625 +3143 -0.3419189453125 +3144 -0.175811767578125 +3145 -0.28289794921875 +3146 -0.15802001953125 +3147 -0.251617431640625 +3148 -0.168212890625 +3149 -0.266143798828125 +3150 -0.17364501953125 +3151 -0.273345947265625 +3152 -0.13946533203125 +3153 -0.216796875 +3154 -0.085205078125 +3155 -0.128265380859375 +3156 -0.048095703125 +3157 -0.068145751953125 +3158 -0.0322265625 +3159 -0.0430908203125 +3160 -0.02001953125 +3161 -0.024444580078125 +3162 0.0087890625 +3163 0.020721435546875 +3164 0.073883056640625 +3165 0.124481201171875 +3166 0.1573486328125 +3167 0.25787353515625 +3168 0.23333740234375 +3169 0.379119873046875 +3170 0.296722412109375 +3171 0.47991943359375 +3172 0.32763671875 +3173 0.5281982421875 +3174 0.318145751953125 +3175 0.511138916015625 +3176 0.285125732421875 +3177 0.456207275390625 +3178 0.255706787109375 +3179 0.407470703125 +3180 0.241424560546875 +3181 0.383758544921875 +3182 0.224884033203125 +3183 0.35687255859375 +3184 0.1968994140625 +3185 0.31182861328125 +3186 0.158843994140625 +3187 0.250885009765625 +3188 0.105438232421875 +3189 0.1654052734375 +3190 0.02435302734375 +3191 0.035247802734375 +3192 -0.085906982421875 +3193 -0.142059326171875 +3194 -0.20623779296875 +3195 -0.33563232421875 +3196 -0.329803466796875 +3197 -0.5345458984375 +3198 -0.446136474609375 +3199 -0.72186279296875 +3200 -0.5177001953125 +3201 -0.836669921875 +3202 -0.515899658203125 +3203 -0.8326416015625 +3204 -0.452911376953125 +3205 -0.7296142578125 +3206 -0.36260986328125 +3207 -0.582550048828125 +3208 -0.274932861328125 +3209 -0.440093994140625 +3210 -0.203460693359375 +3211 -0.324310302734375 +3212 -0.12744140625 +3213 -0.20147705078125 +3214 -0.0302734375 +3215 -0.044647216796875 +3216 0.061981201171875 +3217 0.103973388671875 +3218 0.1234130859375 +3219 0.202392578125 +3220 0.16253662109375 +3221 0.264495849609375 +3222 0.209228515625 +3223 0.338897705078125 +3224 0.274658203125 +3225 0.443817138671875 +3226 0.337738037109375 +3227 0.545074462890625 +3228 0.382781982421875 +3229 0.6173095703125 +3230 0.40484619140625 +3231 0.6524658203125 +3232 0.41180419921875 +3233 0.66339111328125 +3234 0.4073486328125 +3235 0.6561279296875 +3236 0.376800537109375 +3237 0.606781005859375 +3238 0.311431884765625 +3239 0.501190185546875 +3240 0.21954345703125 +3241 0.352783203125 +3242 0.110382080078125 +3243 0.176544189453125 +3244 -0.020477294921875 +3245 -0.034820556640625 +3246 -0.15875244140625 +3247 -0.258209228515625 +3248 -0.27288818359375 +3249 -0.44244384765625 +3250 -0.355316162109375 +3251 -0.5753173828125 +3252 -0.403076171875 +3253 -0.65203857421875 +3254 -0.397064208984375 +3255 -0.641632080078125 +3256 -0.348388671875 +3257 -0.562164306640625 +3258 -0.284393310546875 +3259 -0.458038330078125 +3260 -0.21820068359375 +3261 -0.350555419921875 +3262 -0.162628173828125 +3263 -0.260528564453125 +3264 -0.120269775390625 +3265 -0.192108154296875 +3266 -0.08905029296875 +3267 -0.141937255859375 +3268 -0.06414794921875 +3269 -0.1021728515625 +3270 -0.03948974609375 +3271 -0.062896728515625 +3272 -0.007568359375 +3273 -0.011932373046875 +3274 0.03900146484375 +3275 0.062835693359375 +3276 0.0924072265625 +3277 0.148712158203125 +3278 0.150146484375 +3279 0.241729736328125 +3280 0.2166748046875 +3281 0.34912109375 +3282 0.283599853515625 +3283 0.457305908203125 +3284 0.33709716796875 +3285 0.54388427734375 +3286 0.355010986328125 +3287 0.5728759765625 +3288 0.31414794921875 +3289 0.506591796875 +3290 0.218292236328125 +3291 0.351226806640625 +3292 0.0919189453125 +3293 0.146514892578125 +3294 -0.032684326171875 +3295 -0.05523681640625 +3296 -0.132232666015625 +3297 -0.21624755859375 +3298 -0.205718994140625 +3299 -0.334930419921875 +3300 -0.248016357421875 +3301 -0.402984619140625 +3302 -0.27197265625 +3303 -0.4412841796875 +3304 -0.305908203125 +3305 -0.49578857421875 +3306 -0.345855712890625 +3307 -0.5601806640625 +3308 -0.371063232421875 +3309 -0.600738525390625 +3310 -0.361053466796875 +3311 -0.584228515625 +3312 -0.2965087890625 +3313 -0.47930908203125 +3314 -0.173370361328125 +3315 -0.27935791015625 +3316 -0.006744384765625 +3317 -0.0089111328125 +3318 0.164398193359375 +3319 0.268798828125 +3320 0.29638671875 +3321 0.482818603515625 +3322 0.371063232421875 +3323 0.60369873046875 +3324 0.40008544921875 +3325 0.650421142578125 +3326 0.408721923828125 +3327 0.66400146484375 +3328 0.395355224609375 +3329 0.6414794921875 +3330 0.353546142578125 +3331 0.572540283203125 +3332 0.307373046875 +3333 0.498138427734375 +3334 0.26947021484375 +3335 0.439453125 +3336 0.227874755859375 +3337 0.375518798828125 +3338 0.164276123046875 +3339 0.274505615234375 +3340 0.06280517578125 +3341 0.1087646484375 +3342 -0.063201904296875 +3343 -0.099395751953125 +3344 -0.1949462890625 +3345 -0.3182373046875 +3346 -0.33294677734375 +3347 -0.5489501953125 +3348 -0.4666748046875 +3349 -0.7738037109375 +3350 -0.56512451171875 +3351 -0.86383056640625 +3352 -0.60882568359375 +3353 -0.870391845703125 +3354 -0.608154296875 +3355 -0.86895751953125 +3356 -0.570831298828125 +3357 -0.861053466796875 +3358 -0.486846923828125 +3359 -0.765869140625 +3360 -0.349761962890625 +3361 -0.5301513671875 +3362 -0.163909912109375 +3363 -0.214691162109375 +3364 0.045379638671875 +3365 0.137359619140625 +3366 0.2479248046875 +3367 0.474822998046875 +3368 0.422760009765625 +3369 0.76239013671875 +3370 0.553924560546875 +3371 0.867462158203125 +3372 0.641510009765625 +3373 0.870361328125 +3374 0.678619384765625 +3375 0.86480712890625 +3376 0.668304443359375 +3377 0.831817626953125 +3378 0.624725341796875 +3379 0.677581787109375 +3380 0.55126953125 +3381 0.495880126953125 +3382 0.458831787109375 +3383 0.30767822265625 +3384 0.3487548828125 +3385 0.116180419921875 +3386 0.20263671875 +3387 -0.110748291015625 +3388 0.01654052734375 +3389 -0.381805419921875 +3390 -0.184326171875 +3391 -0.6572265625 +3392 -0.364837646484375 +3393 -0.857421875 +3394 -0.499755859375 +3395 -0.870391845703125 +3396 -0.584747314453125 +3397 -0.870391845703125 +3398 -0.635406494140625 +3399 -0.86444091796875 +3400 -0.67242431640625 +3401 -0.85723876953125 +3402 -0.68499755859375 +3403 -0.790008544921875 +3404 -0.641387939453125 +3405 -0.62847900390625 +3406 -0.539703369140625 +3407 -0.3956298828125 +3408 -0.39910888671875 +3409 -0.126708984375 +3410 -0.23565673828125 +3411 0.150115966796875 +3412 -0.0562744140625 +3413 0.424041748046875 +3414 0.123138427734375 +3415 0.670623779296875 +3416 0.279815673828125 +3417 0.854522705078125 +3418 0.403289794921875 +3419 0.866485595703125 +3420 0.48443603515625 +3421 0.86920166015625 +3422 0.53369140625 +3423 0.8653564453125 +3424 0.558746337890625 +3425 0.857147216796875 +3426 0.55780029296875 +3427 0.766845703125 +3428 0.533721923828125 +3429 0.628509521484375 +3430 0.482513427734375 +3431 0.462127685546875 +3432 0.41925048828125 +3433 0.297210693359375 +3434 0.351165771484375 +3435 0.14862060546875 +3436 0.26495361328125 +3437 -0.00537109375 +3438 0.16510009765625 +3439 -0.15753173828125 +3440 0.049560546875 +3441 -0.31304931640625 +3442 -0.0897216796875 +3443 -0.48876953125 +3444 -0.2252197265625 +3445 -0.6416015625 +3446 -0.34234619140625 +3447 -0.751373291015625 +3448 -0.4544677734375 +3449 -0.84619140625 +3450 -0.5528564453125 +3451 -0.861297607421875 +3452 -0.6180419921875 +3453 -0.863250732421875 +3454 -0.631500244140625 +3455 -0.856597900390625 +3456 -0.60028076171875 +3457 -0.7498779296875 +3458 -0.558135986328125 +3459 -0.624542236328125 +3460 -0.492218017578125 +3461 -0.47808837890625 +3462 -0.368408203125 +3463 -0.253387451171875 +3464 -0.21343994140625 +3465 0.003692626953125 +3466 -0.06732177734375 +3467 0.2257080078125 +3468 0.077178955078125 +3469 0.427154541015625 +3470 0.23883056640625 +3471 0.643218994140625 +3472 0.411865234375 +3473 0.855926513671875 +3474 0.56231689453125 +3475 0.870361328125 +3476 0.66107177734375 +3477 0.870361328125 +3478 0.712188720703125 +3479 0.862762451171875 +3480 0.7138671875 +3481 0.79669189453125 +3482 0.6605224609375 +3483 0.595794677734375 +3484 0.5692138671875 +3485 0.362152099609375 +3486 0.456298828125 +3487 0.1270751953125 +3488 0.33416748046875 +3489 -0.086944580078125 +3490 0.2041015625 +3491 -0.2784423828125 +3492 0.04583740234375 +3493 -0.484832763671875 +3494 -0.15167236328125 +3495 -0.729583740234375 +3496 -0.358734130859375 +3497 -0.86688232421875 +3498 -0.538238525390625 +3499 -0.870391845703125 +3500 -0.687103271484375 +3501 -0.86859130859375 +3502 -0.803955078125 +3503 -0.86279296875 +3504 -0.85595703125 +3505 -0.817962646484375 +3506 -0.851593017578125 +3507 -0.6116943359375 +3508 -0.751495361328125 +3509 -0.3128662109375 +3510 -0.5870361328125 +3511 0.039398193359375 +3512 -0.369903564453125 +3513 0.422821044921875 +3514 -0.119598388671875 +3515 0.805145263671875 +3516 0.1240234375 +3517 0.870361328125 +3518 0.3275146484375 +3519 0.870361328125 +3520 0.48382568359375 +3521 0.860015869140625 +3522 0.588226318359375 +3523 0.727935791015625 +3524 0.637176513671875 +3525 0.48114013671875 +3526 0.644561767578125 +3527 0.2059326171875 +3528 0.62335205078125 +3529 -0.06103515625 +3530 0.579193115234375 +3531 -0.29913330078125 +3532 0.503448486328125 +3533 -0.516204833984375 +3534 0.3870849609375 +3535 -0.7252197265625 +3536 0.24462890625 +3537 -0.85980224609375 +3538 0.096221923828125 +3539 -0.870391845703125 +3540 -0.0406494140625 +3541 -0.870391845703125 +3542 -0.13726806640625 +3543 -0.858062744140625 +3544 -0.190826416015625 +3545 -0.673004150390625 +3546 -0.231597900390625 +3547 -0.42694091796875 +3548 -0.285125732421875 +3549 -0.2100830078125 +3550 -0.3497314453125 +3551 -0.0362548828125 +3552 -0.4080810546875 +3553 0.10943603515625 +3554 -0.448211669921875 +3555 0.23516845703125 +3556 -0.4456787109375 +3557 0.373687744140625 +3558 -0.40142822265625 +3559 0.517791748046875 +3560 -0.352142333984375 +3561 0.602783203125 +3562 -0.294830322265625 +3563 0.635711669921875 +3564 -0.21014404296875 +3565 0.655181884765625 +3566 -0.104095458984375 +3567 0.65948486328125 +3568 0.018341064453125 +3569 0.651275634765625 +3570 0.142486572265625 +3571 0.61846923828125 +3572 0.246307373046875 +3573 0.53753662109375 +3574 0.318817138671875 +3575 0.404144287109375 +3576 0.353912353515625 +3577 0.22186279296875 +3578 0.351959228515625 +3579 0.003997802734375 +3580 0.32318115234375 +3581 -0.22100830078125 +3582 0.279327392578125 +3583 -0.42449951171875 +3584 0.23236083984375 +3585 -0.579833984375 +3586 0.206451416015625 +3587 -0.641876220703125 +3588 0.19830322265625 +3589 -0.6177978515625 +3590 0.17205810546875 +3591 -0.575531005859375 +3592 0.124725341796875 +3593 -0.526336669921875 +3594 0.084991455078125 +3595 -0.42645263671875 +3596 0.068267822265625 +3597 -0.2581787109375 +3598 0.0548095703125 +3599 -0.068695068359375 +3600 0.023773193359375 +3601 0.09222412109375 +3602 -0.014068603515625 +3603 0.232147216796875 +3604 -0.052642822265625 +3605 0.3509521484375 +3606 -0.107879638671875 +3607 0.410064697265625 +3608 -0.19561767578125 +3609 0.372955322265625 +3610 -0.303955078125 +3611 0.2554931640625 +3612 -0.4039306640625 +3613 0.10711669921875 +3614 -0.484588623046875 +3615 -0.052886962890625 +3616 -0.52593994140625 +3617 -0.186279296875 +3618 -0.497314453125 +3619 -0.23291015625 +3620 -0.411468505859375 +3621 -0.209442138671875 +3622 -0.3050537109375 +3623 -0.174163818359375 +3624 -0.183013916015625 +3625 -0.126739501953125 +3626 -0.040313720703125 +3627 -0.048126220703125 +3628 0.106964111328125 +3629 0.0426025390625 +3630 0.232635498046875 +3631 0.10748291015625 +3632 0.32891845703125 +3633 0.1409912109375 +3634 0.4217529296875 +3635 0.19708251953125 +3636 0.507049560546875 +3637 0.273651123046875 +3638 0.553741455078125 +3639 0.31768798828125 +3640 0.567779541015625 +3641 0.341094970703125 +3642 0.56304931640625 +3643 0.368011474609375 +3644 0.526885986328125 +3645 0.37249755859375 +3646 0.432220458984375 +3647 0.30072021484375 +3648 0.282012939453125 +3649 0.1517333984375 +3650 0.113311767578125 +3651 -0.01470947265625 +3652 -0.063751220703125 +3653 -0.1883544921875 +3654 -0.24658203125 +3655 -0.372711181640625 +3656 -0.401092529296875 +3657 -0.51397705078125 +3658 -0.50091552734375 +3659 -0.57177734375 +3660 -0.5389404296875 +3661 -0.53948974609375 +3662 -0.52239990234375 +3663 -0.43511962890625 +3664 -0.470245361328125 +3665 -0.2962646484375 +3666 -0.4027099609375 +3667 -0.161102294921875 +3668 -0.32757568359375 +3669 -0.0435791015625 +3670 -0.24365234375 +3671 0.060394287109375 +3672 -0.16064453125 +3673 0.13665771484375 +3674 -0.089508056640625 +3675 0.170135498046875 +3676 -0.0308837890625 +3677 0.16552734375 +3678 0.0306396484375 +3679 0.15728759765625 +3680 0.09429931640625 +3681 0.150787353515625 +3682 0.14312744140625 +3683 0.12200927734375 +3684 0.1787109375 +3685 0.080108642578125 +3686 0.212493896484375 +3687 0.05126953125 +3688 0.25714111328125 +3689 0.062896728515625 +3690 0.298583984375 +3691 0.09271240234375 +3692 0.309539794921875 +3693 0.092987060546875 +3694 0.2979736328125 +3695 0.07855224609375 +3696 0.272735595703125 +3697 0.06427001953125 +3698 0.2266845703125 +3699 0.0347900390625 +3700 0.1607666015625 +3701 -0.01171875 +3702 0.08807373046875 +3703 -0.056060791015625 +3704 0.0350341796875 +3705 -0.055511474609375 +3706 0.0045166015625 +3707 -0.010467529296875 +3708 -0.030181884765625 +3709 0.02508544921875 +3710 -0.0802001953125 +3711 0.025665283203125 +3712 -0.128509521484375 +3713 0.017333984375 +3714 -0.17193603515625 +3715 0.00189208984375 +3716 -0.214935302734375 +3717 -0.03173828125 +3718 -0.249847412109375 +3719 -0.071502685546875 +3720 -0.2862548828125 +3721 -0.13543701171875 +3722 -0.322479248046875 +3723 -0.219970703125 +3724 -0.3458251953125 +3725 -0.300506591796875 +3726 -0.357330322265625 +3727 -0.376312255859375 +3728 -0.341644287109375 +3729 -0.416107177734375 +3730 -0.27410888671875 +3731 -0.371124267578125 +3732 -0.157745361328125 +3733 -0.242279052734375 +3734 -0.017242431640625 +3735 -0.069732666015625 +3736 0.133392333984375 +3737 0.125640869140625 +3738 0.274688720703125 +3739 0.31268310546875 +3740 0.3846435546875 +3741 0.45501708984375 +3742 0.462921142578125 +3743 0.554779052734375 +3744 0.507781982421875 +3745 0.61065673828125 +3746 0.512237548828125 +3747 0.610931396484375 +3748 0.4630126953125 +3749 0.531463623046875 +3750 0.36956787109375 +3751 0.3883056640625 +3752 0.262298583984375 +3753 0.23468017578125 +3754 0.15631103515625 +3755 0.095245361328125 +3756 0.06768798828125 +3757 -0.00396728515625 +3758 0.006378173828125 +3759 -0.04852294921875 +3760 -0.03472900390625 +3761 -0.055145263671875 +3762 -0.082275390625 +3763 -0.0758056640625 +3764 -0.149871826171875 +3765 -0.138702392578125 +3766 -0.216705322265625 +3767 -0.209197998046875 +3768 -0.2823486328125 +3769 -0.289031982421875 +3770 -0.346160888671875 +3771 -0.37884521484375 +3772 -0.395263671875 +3773 -0.456329345703125 +3774 -0.4267578125 +3775 -0.51641845703125 +3776 -0.418975830078125 +3777 -0.519287109375 +3778 -0.368988037109375 +3779 -0.458251953125 +3780 -0.3062744140625 +3781 -0.384796142578125 +3782 -0.245880126953125 +3783 -0.323699951171875 +3784 -0.186248779296875 +3785 -0.269287109375 +3786 -0.114532470703125 +3787 -0.1951904296875 +3788 -0.03167724609375 +3789 -0.100006103515625 +3790 0.04583740234375 +3791 -0.01055908203125 +3792 0.13323974609375 +3793 0.1033935546875 +3794 0.233306884765625 +3795 0.24908447265625 +3796 0.315673828125 +3797 0.373199462890625 +3798 0.370025634765625 +3799 0.45806884765625 +3800 0.400390625 +3801 0.511474609375 +3802 0.424591064453125 +3803 0.565399169921875 +3804 0.43841552734375 +3805 0.61138916015625 +3806 0.40972900390625 +3807 0.5897216796875 +3808 0.334136962890625 +3809 0.4906005859375 +3810 0.222564697265625 +3811 0.33148193359375 +3812 0.095947265625 +3813 0.147796630859375 +3814 -0.021240234375 +3815 -0.01873779296875 +3816 -0.112274169921875 +3817 -0.140289306640625 +3818 -0.162139892578125 +3819 -0.191986083984375 +3820 -0.175537109375 +3821 -0.184295654296875 +3822 -0.176239013671875 +3823 -0.161834716796875 +3824 -0.18682861328125 +3825 -0.166595458984375 +3826 -0.204437255859375 +3827 -0.19390869140625 +3828 -0.218414306640625 +3829 -0.22442626953125 +3830 -0.240997314453125 +3831 -0.279754638671875 +3832 -0.26123046875 +3833 -0.3389892578125 +3834 -0.253570556640625 +3835 -0.3543701171875 +3836 -0.231292724609375 +3837 -0.348175048828125 +3838 -0.198577880859375 +3839 -0.32598876953125 +3840 -0.1402587890625 +3841 -0.2581787109375 +3842 -0.054779052734375 +3843 -0.139801025390625 +3844 0.04876708984375 +3845 0.014617919921875 +3846 0.135955810546875 +3847 0.144378662109375 +3848 0.1904296875 +3849 0.221038818359375 +3850 0.225921630859375 +3851 0.27069091796875 +3852 0.24249267578125 +3853 0.294036865234375 +3854 0.25146484375 +3855 0.311767578125 +3856 0.261322021484375 +3857 0.339141845703125 +3858 0.263336181640625 +3859 0.360260009765625 +3860 0.250213623046875 +3861 0.360504150390625 +3862 0.20654296875 +3863 0.308380126953125 +3864 0.121856689453125 +3865 0.18170166015625 +3866 0.010009765625 +3867 0.0047607421875 +3868 -0.10345458984375 +3869 -0.17559814453125 +3870 -0.194000244140625 +3871 -0.3143310546875 +3872 -0.238006591796875 +3873 -0.36785888671875 +3874 -0.248321533203125 +3875 -0.36248779296875 +3876 -0.247894287109375 +3877 -0.343536376953125 +3878 -0.2315673828125 +3879 -0.3018798828125 +3880 -0.19598388671875 +3881 -0.231414794921875 +3882 -0.133697509765625 +3883 -0.117645263671875 +3884 -0.06182861328125 +3885 0.007049560546875 +3886 -0.009307861328125 +3887 0.087982177734375 +3888 0.030609130859375 +3889 0.13946533203125 +3890 0.06378173828125 +3891 0.17425537109375 +3892 0.087158203125 +3893 0.188201904296875 +3894 0.094573974609375 +3895 0.171234130859375 +3896 0.08258056640625 +3897 0.118438720703125 +3898 0.064544677734375 +3899 0.05706787109375 +3900 0.040863037109375 +3901 -0.010711669921875 +3902 0.007568359375 +3903 -0.0914306640625 +3904 -0.023834228515625 +3905 -0.162322998046875 +3906 -0.03857421875 +3907 -0.194549560546875 +3908 -0.0164794921875 +3909 -0.1492919921875 +3910 0.045135498046875 +3911 -0.02166748046875 +3912 0.11322021484375 +3913 0.124053955078125 +3914 0.14837646484375 +3915 0.211151123046875 +3916 0.151641845703125 +3917 0.240447998046875 +3918 0.13946533203125 +3919 0.242218017578125 +3920 0.117431640625 +3921 0.2257080078125 +3922 0.08807373046875 +3923 0.194366455078125 +3924 0.03509521484375 +3925 0.115509033203125 +3926 -0.028533935546875 +3927 0.0128173828125 +3928 -0.0711669921875 +3929 -0.053802490234375 +3930 -0.1060791015625 +3931 -0.110626220703125 +3932 -0.15484619140625 +3933 -0.199493408203125 +3934 -0.203887939453125 +3935 -0.29437255859375 +3936 -0.220458984375 +3937 -0.33221435546875 +3938 -0.187530517578125 +3939 -0.27972412109375 +3940 -0.13067626953125 +3941 -0.185333251953125 +3942 -0.091522216796875 +3943 -0.128204345703125 +3944 -0.074462890625 +3945 -0.115692138671875 +3946 -0.0638427734375 +3947 -0.116455078125 +3948 -0.047454833984375 +3949 -0.105926513671875 +3950 -0.01025390625 +3951 -0.053955078125 +3952 0.052093505859375 +3953 0.048797607421875 +3954 0.115753173828125 +3955 0.157318115234375 +3956 0.14935302734375 +3957 0.212005615234375 +3958 0.155609130859375 +3959 0.218475341796875 +3960 0.165863037109375 +3961 0.23724365234375 +3962 0.199432373046875 +3963 0.30535888671875 +3964 0.234893798828125 +3965 0.38128662109375 +3966 0.24102783203125 +3967 0.404449462890625 +3968 0.228363037109375 +3969 0.3944091796875 +3970 0.216827392578125 +3971 0.3885498046875 +3972 0.194305419921875 +3973 0.362640380859375 +3974 0.138916015625 +3975 0.27362060546875 +3976 0.04888916015625 +3977 0.11712646484375 +3978 -0.04827880859375 +3979 -0.054901123046875 +3980 -0.125335693359375 +3981 -0.19085693359375 +3982 -0.17938232421875 +3983 -0.28570556640625 +3984 -0.21014404296875 +3985 -0.339263916015625 +3986 -0.23101806640625 +3987 -0.3775634765625 +3988 -0.2655029296875 +3989 -0.445709228515625 +3990 -0.309173583984375 +3991 -0.535064697265625 +3992 -0.3536376953125 +3993 -0.629058837890625 +3994 -0.383514404296875 +3995 -0.697601318359375 +3996 -0.38006591796875 +3997 -0.70391845703125 +3998 -0.340789794921875 +3999 -0.6424560546875 +4000 -0.254669189453125 +4001 -0.491241455078125 +4002 -0.130157470703125 +4003 -0.265716552734375 +4004 0.00225830078125 +4005 -0.023712158203125 +4006 0.125091552734375 +4007 0.201751708984375 +4008 0.219940185546875 +4009 0.375823974609375 +4010 0.27960205078125 +4011 0.485076904296875 +4012 0.324432373046875 +4013 0.56884765625 +4014 0.3583984375 +4015 0.634765625 +4016 0.3580322265625 +4017 0.63763427734375 +4018 0.317535400390625 +4019 0.5660400390625 +4020 0.26422119140625 +4021 0.4720458984375 +4022 0.225006103515625 +4023 0.40692138671875 +4024 0.203948974609375 +4025 0.3778076171875 +4026 0.197357177734375 +4027 0.376953125 +4028 0.188720703125 +4029 0.371978759765625 +4030 0.15252685546875 +4031 0.313140869140625 +4032 0.0806884765625 +4033 0.184417724609375 +4034 -0.0133056640625 +4035 0.011199951171875 +4036 -0.110809326171875 +4037 -0.171051025390625 +4038 -0.198760986328125 +4039 -0.33740234375 +4040 -0.268829345703125 +4041 -0.47198486328125 +4042 -0.3135986328125 +4043 -0.560394287109375 +4044 -0.321685791015625 +4045 -0.58056640625 +4046 -0.30108642578125 +4047 -0.54754638671875 +4048 -0.276580810546875 +4049 -0.508575439453125 +4050 -0.24627685546875 +4051 -0.459503173828125 +4052 -0.207366943359375 +4053 -0.394378662109375 +4054 -0.18060302734375 +4055 -0.35260009765625 +4056 -0.154571533203125 +4057 -0.31170654296875 +4058 -0.090911865234375 +4059 -0.197418212890625 +4060 0.01104736328125 +4061 -0.007965087890625 +4062 0.125579833984375 +4063 0.207489013671875 +4064 0.23193359375 +4065 0.409210205078125 +4066 0.3170166015625 +4067 0.57208251953125 +4068 0.365142822265625 +4069 0.66595458984375 +4070 0.359710693359375 +4071 0.65875244140625 +4072 0.30963134765625 +4073 0.56744384765625 +4074 0.235565185546875 +4075 0.431396484375 +4076 0.1605224609375 +4077 0.29443359375 +4078 0.098175048828125 +4079 0.182464599609375 +4080 0.0322265625 +4081 0.06365966796875 +4082 -0.044342041015625 +4083 -0.075958251953125 +4084 -0.10693359375 +4085 -0.189422607421875 +4086 -0.152862548828125 +4087 -0.271942138671875 +4088 -0.19183349609375 +4089 -0.342529296875 +4090 -0.204559326171875 +4091 -0.364166259765625 +4092 -0.18597412109375 +4093 -0.327239990234375 +4094 -0.159576416015625 +4095 -0.2769775390625 +4096 -0.146087646484375 +4097 -0.253692626953125 +4098 -0.138702392578125 +4099 -0.24365234375 +4100 -0.1134033203125 +4101 -0.1983642578125 +4102 -0.069488525390625 +4103 -0.116241455078125 +4104 -0.026336669921875 +4105 -0.036834716796875 +4106 0.013427734375 +4107 0.034881591796875 +4108 0.04583740234375 +4109 0.09124755859375 +4110 0.059234619140625 +4111 0.10888671875 +4112 0.071746826171875 +4113 0.125518798828125 +4114 0.09124755859375 +4115 0.15771484375 +4116 0.104248046875 +4117 0.17828369140625 +4118 0.10272216796875 +4119 0.17108154296875 +4120 0.083587646484375 +4121 0.129974365234375 +4122 0.060211181640625 +4123 0.082427978515625 +4124 0.032257080078125 +4125 0.027679443359375 +4126 -0.015472412109375 +4127 -0.065643310546875 +4128 -0.064178466796875 +4129 -0.15936279296875 +4130 -0.093994140625 +4131 -0.21307373046875 +4132 -0.108551025390625 +4133 -0.234649658203125 +4134 -0.095947265625 +4135 -0.2001953125 +4136 -0.060577392578125 +4137 -0.119171142578125 +4138 -0.018402099609375 +4139 -0.024749755859375 +4140 0.032073974609375 +4141 0.085784912109375 +4142 0.074310302734375 +4143 0.178131103515625 +4144 0.09051513671875 +4145 0.215576171875 +4146 0.0872802734375 +4147 0.211456298828125 +4148 0.06927490234375 +4149 0.17523193359375 +4150 0.04718017578125 +4151 0.128753662109375 +4152 0.0355224609375 +4153 0.1019287109375 +4154 0.02423095703125 +4155 0.0743408203125 +4156 0.0118408203125 +4157 0.04327392578125 +4158 0.012542724609375 +4159 0.038177490234375 +4160 0.034576416015625 +4161 0.076263427734375 +4162 0.069671630859375 +4163 0.14105224609375 +4164 0.09515380859375 +4165 0.186431884765625 +4166 0.099334716796875 +4167 0.188812255859375 +4168 0.07757568359375 +4169 0.1390380859375 +4170 0.03204345703125 +4171 0.041778564453125 +4172 -0.025848388671875 +4173 -0.079437255859375 +4174 -0.093597412109375 +4175 -0.219390869140625 +4176 -0.16619873046875 +4177 -0.367828369140625 +4178 -0.229034423828125 +4179 -0.494873046875 +4180 -0.260467529296875 +4181 -0.556243896484375 +4182 -0.239288330078125 +4183 -0.508697509765625 +4184 -0.176788330078125 +4185 -0.3756103515625 +4186 -0.10302734375 +4187 -0.218902587890625 +4188 -0.030120849609375 +4189 -0.063751220703125 +4190 0.042877197265625 +4191 0.091552734375 +4192 0.110748291015625 +4193 0.23602294921875 +4194 0.160614013671875 +4195 0.342987060546875 +4196 0.1842041015625 +4197 0.39520263671875 +4198 0.17999267578125 +4199 0.389373779296875 +4200 0.147430419921875 +4201 0.324249267578125 +4202 0.098388671875 +4203 0.224090576171875 +4204 0.050140380859375 +4205 0.124267578125 +4206 0.00860595703125 +4207 0.037078857421875 +4208 -0.012908935546875 +4209 -0.010101318359375 +4210 -0.01556396484375 +4211 -0.019439697265625 +4212 -0.0150146484375 +4213 -0.022796630859375 +4214 -0.002288818359375 +4215 -0.001556396484375 +4216 0.0283203125 +4217 0.056304931640625 +4218 0.05517578125 +4219 0.106719970703125 +4220 0.05242919921875 +4221 0.096893310546875 +4222 0.027679443359375 +4223 0.042694091796875 +4224 -0.00067138671875 +4225 -0.018035888671875 +4226 -0.028076171875 +4227 -0.07586669921875 +4228 -0.04901123046875 +4229 -0.11944580078125 +4230 -0.06884765625 +4231 -0.15972900390625 +4232 -0.0904541015625 +4233 -0.202606201171875 +4234 -0.113983154296875 +4235 -0.24859619140625 +4236 -0.143035888671875 +4237 -0.30517578125 +4238 -0.17254638671875 +4239 -0.36212158203125 +4240 -0.188720703125 +4241 -0.39141845703125 +4242 -0.173004150390625 +4243 -0.35528564453125 +4244 -0.12347412109375 +4245 -0.249969482421875 +4246 -0.04852294921875 +4247 -0.092864990234375 +4248 0.03875732421875 +4249 0.08905029296875 +4250 0.10888671875 +4251 0.2352294921875 +4252 0.148834228515625 +4253 0.318817138671875 +4254 0.167816162109375 +4255 0.358642578125 +4256 0.162445068359375 +4257 0.347747802734375 +4258 0.132476806640625 +4259 0.28564453125 +4260 0.102691650390625 +4261 0.223175048828125 +4262 0.090789794921875 +4263 0.196746826171875 +4264 0.08380126953125 +4265 0.179840087890625 +4266 0.073394775390625 +4267 0.155548095703125 +4268 0.07281494140625 +4269 0.151214599609375 +4270 0.0771484375 +4271 0.156951904296875 +4272 0.066314697265625 +4273 0.13177490234375 +4274 0.052520751953125 +4275 0.100799560546875 +4276 0.04693603515625 +4277 0.087127685546875 +4278 0.032012939453125 +4279 0.05487060546875 +4280 0.0013427734375 +4281 -0.009002685546875 +4282 -0.044830322265625 +4283 -0.10400390625 +4284 -0.10614013671875 +4285 -0.229400634765625 +4286 -0.1680908203125 +4287 -0.35552978515625 +4288 -0.210906982421875 +4289 -0.441925048828125 +4290 -0.227386474609375 +4291 -0.473846435546875 +4292 -0.22406005859375 +4293 -0.464813232421875 +4294 -0.202911376953125 +4295 -0.419097900390625 +4296 -0.1627197265625 +4297 -0.334320068359375 +4298 -0.111968994140625 +4299 -0.227935791015625 +4300 -0.06207275390625 +4301 -0.12347412109375 +4302 -0.0162353515625 +4303 -0.02764892578125 +4304 0.034423828125 +4305 0.077667236328125 +4306 0.100067138671875 +4307 0.2132568359375 +4308 0.185455322265625 +4309 0.38885498046875 +4310 0.280029296875 +4311 0.582794189453125 +4312 0.35400390625 +4313 0.734039306640625 +4314 0.38665771484375 +4315 0.800140380859375 +4316 0.3765869140625 +4317 0.7783203125 +4318 0.322113037109375 +4319 0.6651611328125 +4320 0.222686767578125 +4321 0.45965576171875 +4322 0.09649658203125 +4323 0.199188232421875 +4324 -0.024505615234375 +4325 -0.050689697265625 +4326 -0.112548828125 +4327 -0.23297119140625 +4328 -0.159149169921875 +4329 -0.33013916015625 +4330 -0.177093505859375 +4331 -0.368408203125 +4332 -0.181640625 +4333 -0.378936767578125 +4334 -0.1802978515625 +4335 -0.376983642578125 +4336 -0.18145751953125 +4337 -0.37969970703125 +4338 -0.187255859375 +4339 -0.391510009765625 +4340 -0.1844482421875 +4341 -0.385345458984375 +4342 -0.16363525390625 +4343 -0.3419189453125 +4344 -0.1353759765625 +4345 -0.28289794921875 +4346 -0.12078857421875 +4347 -0.251617431640625 +4348 -0.12860107421875 +4349 -0.266143798828125 +4350 -0.13287353515625 +4351 -0.273345947265625 +4352 -0.106170654296875 +4353 -0.216796875 +4354 -0.06365966796875 +4355 -0.128265380859375 +4356 -0.0338134765625 +4357 -0.068145751953125 +4358 -0.019805908203125 +4359 -0.0430908203125 +4360 -0.008697509765625 +4361 -0.024444580078125 +4362 0.01434326171875 +4363 0.020721435546875 +4364 0.06378173828125 +4365 0.124481201171875 +4366 0.126312255859375 +4367 0.25787353515625 +4368 0.182769775390625 +4369 0.379119873046875 +4370 0.229339599609375 +4371 0.47991943359375 +4372 0.251373291015625 +4373 0.5281982421875 +4374 0.243011474609375 +4375 0.511138916015625 +4376 0.216827392578125 +4377 0.456207275390625 +4378 0.193023681640625 +4379 0.407470703125 +4380 0.1802978515625 +4381 0.383758544921875 +4382 0.1658935546875 +4383 0.35687255859375 +4384 0.143096923828125 +4385 0.31182861328125 +4386 0.113037109375 +4387 0.250885009765625 +4388 0.071929931640625 +4389 0.1654052734375 +4390 0.010711669921875 +4391 0.035247802734375 +4392 -0.071624755859375 +4393 -0.142059326171875 +4394 -0.160919189453125 +4395 -0.33563232421875 +4396 -0.252166748046875 +4397 -0.5345458984375 +4398 -0.337615966796875 +4399 -0.72186279296875 +4400 -0.389495849609375 +4401 -0.836669921875 +4402 -0.386749267578125 +4403 -0.8326416015625 +4404 -0.3385009765625 +4405 -0.7296142578125 +4406 -0.2698974609375 +4407 -0.582550048828125 +4408 -0.20318603515625 +4409 -0.440093994140625 +4410 -0.1485595703125 +4411 -0.324310302734375 +4412 -0.0906982421875 +4413 -0.20147705078125 +4414 -0.017425537109375 +4415 -0.044647216796875 +4416 0.051910400390625 +4417 0.103973388671875 +4418 0.098052978515625 +4419 0.202392578125 +4420 0.12725830078125 +4421 0.264495849609375 +4422 0.16168212890625 +4423 0.338897705078125 +4424 0.209625244140625 +4425 0.443817138671875 +4426 0.2554931640625 +4427 0.545074462890625 +4428 0.287750244140625 +4429 0.6173095703125 +4430 0.302764892578125 +4431 0.6524658203125 +4432 0.30645751953125 +4433 0.66339111328125 +4434 0.301666259765625 +4435 0.6561279296875 +4436 0.277587890625 +4437 0.606781005859375 +4438 0.22784423828125 +4439 0.501190185546875 +4440 0.158660888671875 +4441 0.352783203125 +4442 0.076934814453125 +4443 0.176544189453125 +4444 -0.020538330078125 +4445 -0.034820556640625 +4446 -0.1231689453125 +4447 -0.258209228515625 +4448 -0.20758056640625 +4449 -0.44244384765625 +4450 -0.268218994140625 +4451 -0.5753173828125 +4452 -0.30291748046875 +4453 -0.65203857421875 +4454 -0.297576904296875 +4455 -0.641632080078125 +4456 -0.260467529296875 +4457 -0.562164306640625 +4458 -0.2119140625 +4459 -0.458038330078125 +4460 -0.16168212890625 +4461 -0.350555419921875 +4462 -0.11932373046875 +4463 -0.260528564453125 +4464 -0.086822509765625 +4465 -0.192108154296875 +4466 -0.062713623046875 +4467 -0.141937255859375 +4468 -0.043487548828125 +4469 -0.1021728515625 +4470 -0.024658203125 +4471 -0.062896728515625 +4472 -0.000701904296875 +4473 -0.011932373046875 +4474 0.033843994140625 +4475 0.062835693359375 +4476 0.07318115234375 +4477 0.148712158203125 +4478 0.115478515625 +4479 0.241729736328125 +4480 0.164031982421875 +4481 0.34912109375 +4482 0.212677001953125 +4483 0.457305908203125 +4484 0.251251220703125 +4485 0.54388427734375 +4486 0.263427734375 +4487 0.5728759765625 +4488 0.232086181640625 +4489 0.506591796875 +4490 0.16009521484375 +4491 0.351226806640625 +4492 0.065643310546875 +4493 0.146514892578125 +4494 -0.02734375 +4495 -0.05523681640625 +4496 -0.101593017578125 +4497 -0.21624755859375 +4498 -0.156341552734375 +4499 -0.334930419921875 +4500 -0.187774658203125 +4501 -0.402984619140625 +4502 -0.20538330078125 +4503 -0.4412841796875 +4504 -0.230133056640625 +4505 -0.49578857421875 +4506 -0.2591552734375 +4507 -0.5601806640625 +4508 -0.277099609375 +4509 -0.600738525390625 +4510 -0.268829345703125 +4511 -0.584228515625 +4512 -0.220123291015625 +4513 -0.47930908203125 +4514 -0.128021240234375 +4515 -0.27935791015625 +4516 -0.003753662109375 +4517 -0.0089111328125 +4518 0.123748779296875 +4519 0.268798828125 +4520 0.222137451171875 +4521 0.482818603515625 +4522 0.277923583984375 +4523 0.60369873046875 +4524 0.299713134765625 +4525 0.650421142578125 +4526 0.30621337890625 +4527 0.66400146484375 +4528 0.296051025390625 +4529 0.6414794921875 +4530 0.2645263671875 +4531 0.572540283203125 +4532 0.230316162109375 +4533 0.498138427734375 +4534 0.203094482421875 +4535 0.439453125 +4536 0.173370361328125 +4537 0.375518798828125 +4538 0.12664794921875 +4539 0.274505615234375 +4540 0.05035400390625 +4541 0.1087646484375 +4542 -0.0452880859375 +4543 -0.099395751953125 +4544 -0.145782470703125 +4545 -0.3182373046875 +4546 -0.251617431640625 +4547 -0.5489501953125 +4548 -0.35467529296875 +4549 -0.7738037109375 +4550 -0.4307861328125 +4551 -0.86383056640625 +4552 -0.464752197265625 +4553 -0.870391845703125 +4554 -0.46466064453125 +4555 -0.86895751953125 +4556 -0.436492919921875 +4557 -0.861053466796875 +4558 -0.37237548828125 +4559 -0.765869140625 +4560 -0.26715087890625 +4561 -0.5301513671875 +4562 -0.124114990234375 +4563 -0.214691162109375 +4564 0.037078857421875 +4565 0.137359619140625 +4566 0.1929931640625 +4567 0.474822998046875 +4568 0.327362060546875 +4569 0.76239013671875 +4570 0.427825927734375 +4571 0.867462158203125 +4572 0.49456787109375 +4573 0.870361328125 +4574 0.522308349609375 +4575 0.86480712890625 +4576 0.513458251953125 +4577 0.831817626953125 +4578 0.4791259765625 +4579 0.677581787109375 +4580 0.42193603515625 +4581 0.495880126953125 +4582 0.35040283203125 +4583 0.30767822265625 +4584 0.2655029296875 +4585 0.116180419921875 +4586 0.152801513671875 +4587 -0.110748291015625 +4588 0.009185791015625 +4589 -0.381805419921875 +4590 -0.14581298828125 +4591 -0.6572265625 +4592 -0.28485107421875 +4593 -0.857421875 +4594 -0.388336181640625 +4595 -0.870391845703125 +4596 -0.4530029296875 +4597 -0.870391845703125 +4598 -0.4910888671875 +4599 -0.86444091796875 +4600 -0.518829345703125 +4601 -0.85723876953125 +4602 -0.52783203125 +4603 -0.790008544921875 +4604 -0.49334716796875 +4605 -0.62847900390625 +4606 -0.413909912109375 +4607 -0.3956298828125 +4608 -0.3045654296875 +4609 -0.126708984375 +4610 -0.17779541015625 +4611 0.150115966796875 +4612 -0.039276123046875 +4613 0.424041748046875 +4614 0.098876953125 +4615 0.670623779296875 +4616 0.21966552734375 +4617 0.854522705078125 +4618 0.315093994140625 +4619 0.866485595703125 +4620 0.37823486328125 +4621 0.86920166015625 +4622 0.41650390625 +4623 0.8653564453125 +4624 0.4354248046875 +4625 0.857147216796875 +4626 0.433685302734375 +4627 0.766845703125 +4628 0.413543701171875 +4629 0.628509521484375 +4630 0.372314453125 +4631 0.462127685546875 +4632 0.3211669921875 +4633 0.297210693359375 +4634 0.265716552734375 +4635 0.14862060546875 +4636 0.1966552734375 +4637 -0.00537109375 +4638 0.11761474609375 +4639 -0.15753173828125 +4640 0.027496337890625 +4641 -0.31304931640625 +4642 -0.079193115234375 +4643 -0.48876953125 +4644 -0.182220458984375 +4645 -0.6416015625 +4646 -0.270751953125 +4647 -0.751373291015625 +4648 -0.35430908203125 +4649 -0.84619140625 +4650 -0.426513671875 +4651 -0.861297607421875 +4652 -0.47320556640625 +4653 -0.863250732421875 +4654 -0.480987548828125 +4655 -0.856597900390625 +4656 -0.455108642578125 +4657 -0.7498779296875 +4658 -0.420318603515625 +4659 -0.624542236328125 +4660 -0.367523193359375 +4661 -0.47808837890625 +4662 -0.27227783203125 +4663 -0.253387451171875 +4664 -0.154266357421875 +4665 0.003692626953125 +4666 -0.042877197265625 +4667 0.2257080078125 +4668 0.066802978515625 +4669 0.427154541015625 +4670 0.188201904296875 +4671 0.643218994140625 +4672 0.31695556640625 +4673 0.855926513671875 +4674 0.42822265625 +4675 0.870361328125 +4676 0.500823974609375 +4677 0.870361328125 +4678 0.537689208984375 +4679 0.862762451171875 +4680 0.53753662109375 +4681 0.79669189453125 +4682 0.496429443359375 +4683 0.595794677734375 +4684 0.4268798828125 +4685 0.362152099609375 +4686 0.340972900390625 +4687 0.1270751953125 +4688 0.2479248046875 +4689 -0.086944580078125 +4690 0.148956298828125 +4691 -0.2784423828125 +4692 0.02960205078125 +4693 -0.484832763671875 +4694 -0.117889404296875 +4695 -0.729583740234375 +4696 -0.27178955078125 +4697 -0.86688232421875 +4698 -0.404937744140625 +4699 -0.870391845703125 +4700 -0.514984130859375 +4701 -0.86859130859375 +4702 -0.600830078125 +4703 -0.86279296875 +4704 -0.6470947265625 +4705 -0.817962646484375 +4706 -0.634490966796875 +4707 -0.6116943359375 +4708 -0.56005859375 +4709 -0.3128662109375 +4710 -0.43817138671875 +4711 0.039398193359375 +4712 -0.2774658203125 +4713 0.422821044921875 +4714 -0.092254638671875 +4715 0.805145263671875 +4716 0.0882568359375 +4717 0.870361328125 +4718 0.239593505859375 +4719 0.870361328125 +4720 0.356475830078125 +4721 0.860015869140625 +4722 0.435302734375 +4723 0.727935791015625 +4724 0.473358154296875 +4725 0.48114013671875 +4726 0.480560302734375 +4727 0.2059326171875 +4728 0.46624755859375 +4729 -0.06103515625 +4730 0.43450927734375 +4731 -0.29913330078125 +4732 0.37908935546875 +4733 -0.516204833984375 +4734 0.29345703125 +4735 -0.7252197265625 +4736 0.188262939453125 +4737 -0.85980224609375 +4738 0.0782470703125 +4739 -0.870391845703125 +4740 -0.023773193359375 +4741 -0.870391845703125 +4742 -0.0968017578125 +4743 -0.858062744140625 +4744 -0.138641357421875 +4745 -0.673004150390625 +4746 -0.171112060546875 +4747 -0.42694091796875 +4748 -0.212615966796875 +4749 -0.2100830078125 +4750 -0.26177978515625 +4751 -0.0362548828125 +4752 -0.305877685546875 +4753 0.10943603515625 +4754 -0.336151123046875 +4755 0.23516845703125 +4756 -0.334808349609375 +4757 0.373687744140625 +4758 -0.302520751953125 +4759 0.517791748046875 +4760 -0.2659912109375 +4761 0.602783203125 +4762 -0.22308349609375 +4763 0.635711669921875 +4764 -0.15985107421875 +4765 0.655181884765625 +4766 -0.080718994140625 +4767 0.65948486328125 +4768 0.010498046875 +4769 0.651275634765625 +4770 0.10302734375 +4771 0.61846923828125 +4772 0.180755615234375 +4773 0.53753662109375 +4774 0.235565185546875 +4775 0.404144287109375 +4776 0.262939453125 +4777 0.22186279296875 +4778 0.263031005859375 +4779 0.003997802734375 +4780 0.243194580078125 +4781 -0.22100830078125 +4782 0.2119140625 +4783 -0.42449951171875 +4784 0.1781005859375 +4785 -0.579833984375 +4786 0.159820556640625 +4787 -0.641876220703125 +4788 0.154266357421875 +4789 -0.6177978515625 +4790 0.134185791015625 +4791 -0.575531005859375 +4792 0.097503662109375 +4793 -0.526336669921875 +4794 0.06646728515625 +4795 -0.42645263671875 +4796 0.053009033203125 +4797 -0.2581787109375 +4798 0.0421142578125 +4799 -0.068695068359375 +4800 0.017852783203125 +4801 0.09222412109375 +4802 -0.011474609375 +4803 0.232147216796875 +4804 -0.041168212890625 +4805 0.3509521484375 +4806 -0.08349609375 +4807 0.410064697265625 +4808 -0.150604248046875 +4809 0.372955322265625 +4810 -0.23345947265625 +4811 0.2554931640625 +4812 -0.309814453125 +4813 0.10711669921875 +4814 -0.371337890625 +4815 -0.052886962890625 +4816 -0.4027099609375 +4817 -0.186279296875 +4818 -0.380340576171875 +4819 -0.23291015625 +4820 -0.3140869140625 +4821 -0.209442138671875 +4822 -0.232147216796875 +4823 -0.174163818359375 +4824 -0.138336181640625 +4825 -0.126739501953125 +4826 -0.02880859375 +4827 -0.048126220703125 +4828 0.084136962890625 +4829 0.0426025390625 +4830 0.180389404296875 +4831 0.10748291015625 +4832 0.2540283203125 +4833 0.1409912109375 +4834 0.32489013671875 +4835 0.19708251953125 +4836 0.389923095703125 +4837 0.273651123046875 +4838 0.42529296875 +4839 0.31768798828125 +4840 0.43560791015625 +4841 0.341094970703125 +4842 0.4315185546875 +4843 0.368011474609375 +4844 0.403350830078125 +4845 0.37249755859375 +4846 0.330322265625 +4847 0.30072021484375 +4848 0.2147216796875 +4849 0.1517333984375 +4850 0.08502197265625 +4851 -0.01470947265625 +4852 -0.05096435546875 +4853 -0.1883544921875 +4854 -0.191253662109375 +4855 -0.372711181640625 +4856 -0.309661865234375 +4857 -0.51397705078125 +4858 -0.385986328125 +4859 -0.57177734375 +4860 -0.414794921875 +4861 -0.53948974609375 +4862 -0.40167236328125 +4863 -0.43511962890625 +4864 -0.3614501953125 +4865 -0.2962646484375 +4866 -0.309814453125 +4867 -0.161102294921875 +4868 -0.252593994140625 +4869 -0.0435791015625 +4870 -0.188812255859375 +4871 0.060394287109375 +4872 -0.125457763671875 +4873 0.13665771484375 +4874 -0.070465087890625 +4875 0.170135498046875 +4876 -0.02435302734375 +4877 0.16552734375 +4878 0.023895263671875 +4879 0.15728759765625 +4880 0.0736083984375 +4881 0.150787353515625 +4882 0.1123046875 +4883 0.12200927734375 +4884 0.1409912109375 +4885 0.080108642578125 +4886 0.16778564453125 +4887 0.05126953125 +4888 0.201751708984375 +4889 0.062896728515625 +4890 0.23260498046875 +4891 0.09271240234375 +4892 0.240509033203125 +4893 0.092987060546875 +4894 0.231292724609375 +4895 0.07855224609375 +4896 0.21136474609375 +4897 0.06427001953125 +4898 0.1756591796875 +4899 0.0347900390625 +4900 0.125 +4901 -0.01171875 +4902 0.069061279296875 +4903 -0.056060791015625 +4904 0.027191162109375 +4905 -0.055511474609375 +4906 0.001617431640625 +4907 -0.010467529296875 +4908 -0.02679443359375 +4909 0.02508544921875 +4910 -0.06591796875 +4911 0.025665283203125 +4912 -0.103302001953125 +4913 0.017333984375 +4914 -0.13653564453125 +4915 0.00189208984375 +4916 -0.16876220703125 +4917 -0.03173828125 +4918 -0.19439697265625 +4919 -0.071502685546875 +4920 -0.220367431640625 +4921 -0.13543701171875 +4922 -0.245513916015625 +4923 -0.219970703125 +4924 -0.26068115234375 +4925 -0.300506591796875 +4926 -0.266754150390625 +4927 -0.376312255859375 +4928 -0.252777099609375 +4929 -0.416107177734375 +4930 -0.2010498046875 +4931 -0.371124267578125 +4932 -0.113861083984375 +4933 -0.242279052734375 +4934 -0.00927734375 +4935 -0.069732666015625 +4936 0.102386474609375 +4937 0.125640869140625 +4938 0.206878662109375 +4939 0.31268310546875 +4940 0.288177490234375 +4941 0.45501708984375 +4942 0.345947265625 +4943 0.554779052734375 +4944 0.37890625 +4945 0.61065673828125 +4946 0.381988525390625 +4947 0.610931396484375 +4948 0.3455810546875 +4949 0.531463623046875 +4950 0.276580810546875 +4951 0.3883056640625 +4952 0.1971435546875 +4953 0.23468017578125 +4954 0.1182861328125 +4955 0.095245361328125 +4956 0.05181884765625 +4957 -0.00396728515625 +4958 0.00506591796875 +4959 -0.04852294921875 +4960 -0.027008056640625 +4961 -0.055145263671875 +4962 -0.063568115234375 +4963 -0.0758056640625 +4964 -0.1143798828125 +4965 -0.138702392578125 +4966 -0.164276123046875 +4967 -0.209197998046875 +4968 -0.212860107421875 +4969 -0.289031982421875 +4970 -0.259674072265625 +4971 -0.37884521484375 +4972 -0.295318603515625 +4973 -0.456329345703125 +4974 -0.31768798828125 +4975 -0.51641845703125 +4976 -0.3111572265625 +4977 -0.519287109375 +4978 -0.27362060546875 +4979 -0.458251953125 +4980 -0.2265625 +4981 -0.384796142578125 +4982 -0.18096923828125 +4983 -0.323699951171875 +4984 -0.13580322265625 +4985 -0.269287109375 +4986 -0.081878662109375 +4987 -0.1951904296875 +4988 -0.019989013671875 +4989 -0.100006103515625 +4990 0.037841796875 +4991 -0.01055908203125 +4992 0.1025390625 +4993 0.1033935546875 +4994 0.176055908203125 +4995 0.24908447265625 +4996 0.236328125 +4997 0.373199462890625 +4998 0.275848388671875 +4999 0.45806884765625 +5000 0.297576904296875 +5001 0.511474609375 +5002 0.314422607421875 +5003 0.565399169921875 +5004 0.32342529296875 +5005 0.61138916015625 +5006 0.30133056640625 +5007 0.5897216796875 +5008 0.24505615234375 +5009 0.4906005859375 +5010 0.16259765625 +5011 0.33148193359375 +5012 0.0692138671875 +5013 0.147796630859375 +5014 -0.01727294921875 +5015 -0.01873779296875 +5016 -0.084625244140625 +5017 -0.140289306640625 +5018 -0.121917724609375 +5019 -0.191986083984375 +5020 -0.13250732421875 +5021 -0.184295654296875 +5022 -0.133575439453125 +5023 -0.161834716796875 +5024 -0.141448974609375 +5025 -0.166595458984375 +5026 -0.154083251953125 +5027 -0.19390869140625 +5028 -0.163726806640625 +5029 -0.22442626953125 +5030 -0.179290771484375 +5031 -0.279754638671875 +5032 -0.192901611328125 +5033 -0.3389892578125 +5034 -0.1861572265625 +5035 -0.3543701171875 +5036 -0.168731689453125 +5037 -0.348175048828125 +5038 -0.143707275390625 +5039 -0.32598876953125 +5040 -0.100189208984375 +5041 -0.2581787109375 +5042 -0.037078857421875 +5043 -0.139801025390625 +5044 0.038970947265625 +5045 0.014617919921875 +5046 0.1029052734375 +5047 0.144378662109375 +5048 0.142822265625 +5049 0.221038818359375 +5050 0.168701171875 +5051 0.27069091796875 +5052 0.18060302734375 +5053 0.294036865234375 +5054 0.186737060546875 +5055 0.311767578125 +5056 0.193328857421875 +5057 0.339141845703125 +5058 0.194305419921875 +5059 0.360260009765625 +5060 0.184295654296875 +5061 0.360504150390625 +5062 0.151611328125 +5063 0.308380126953125 +5064 0.088348388671875 +5065 0.18170166015625 +5066 0.004852294921875 +5067 0.0047607421875 +5068 -0.0797119140625 +5069 -0.17559814453125 +5070 -0.146942138671875 +5071 -0.3143310546875 +5072 -0.179107666015625 +5073 -0.36785888671875 +5074 -0.185943603515625 +5075 -0.36248779296875 +5076 -0.184783935546875 +5077 -0.343536376953125 +5078 -0.17181396484375 +5079 -0.3018798828125 +5080 -0.144500732421875 +5081 -0.231414794921875 +5082 -0.097259521484375 +5083 -0.117645263671875 +5084 -0.042999267578125 +5085 0.007049560546875 +5086 -0.0035400390625 +5087 0.087982177734375 +5088 0.026214599609375 +5089 0.13946533203125 +5090 0.05072021484375 +5091 0.17425537109375 +5092 0.06768798828125 +5093 0.188201904296875 +5094 0.072540283203125 +5095 0.171234130859375 +5096 0.062744140625 +5097 0.118438720703125 +5098 0.04840087890625 +5099 0.05706787109375 +5100 0.02984619140625 +5101 -0.010711669921875 +5102 0.004119873046875 +5103 -0.0914306640625 +5104 -0.02008056640625 +5105 -0.162322998046875 +5106 -0.031585693359375 +5107 -0.194549560546875 +5108 -0.015167236328125 +5109 -0.1492919921875 +5110 0.031219482421875 +5111 -0.02166748046875 +5112 0.0826416015625 +5113 0.124053955078125 +5114 0.109375 +5115 0.211151123046875 +5116 0.112213134765625 +5117 0.240447998046875 +5118 0.103515625 +5119 0.242218017578125 +5120 0.086944580078125 +5121 0.2257080078125 +5122 0.06463623046875 +5123 0.194366455078125 +5124 0.025970458984375 +5125 0.115509033203125 +5126 -0.019927978515625 +5127 0.0128173828125 +5128 -0.05108642578125 +5129 -0.053802490234375 +5130 -0.076629638671875 +5131 -0.110626220703125 +5132 -0.111480712890625 +5133 -0.199493408203125 +5134 -0.146148681640625 +5135 -0.29437255859375 +5136 -0.15802001953125 +5137 -0.33221435546875 +5138 -0.13531494140625 +5139 -0.27972412109375 +5140 -0.095703125 +5141 -0.185333251953125 +5142 -0.06805419921875 +5143 -0.128204345703125 +5144 -0.055450439453125 +5145 -0.115692138671875 +5146 -0.047088623046875 +5147 -0.116455078125 +5148 -0.03460693359375 +5149 -0.105926513671875 +5150 -0.00762939453125 +5151 -0.053955078125 +5152 0.0367431640625 +5153 0.048797607421875 +5154 0.081939697265625 +5155 0.157318115234375 +5156 0.106201171875 +5157 0.212005615234375 +5158 0.111328125 +5159 0.218475341796875 +5160 0.1190185546875 +5161 0.23724365234375 +5162 0.142608642578125 +5163 0.30535888671875 +5164 0.167236328125 +5165 0.38128662109375 +5166 0.1712646484375 +5167 0.404449462890625 +5168 0.16204833984375 +5169 0.3944091796875 +5170 0.153411865234375 +5171 0.3885498046875 +5172 0.13702392578125 +5173 0.362640380859375 +5174 0.0977783203125 +5175 0.27362060546875 +5176 0.034515380859375 +5177 0.11712646484375 +5178 -0.03369140625 +5179 -0.054901123046875 +5180 -0.087921142578125 +5181 -0.19085693359375 +5182 -0.126129150390625 +5183 -0.28570556640625 +5184 -0.148101806640625 +5185 -0.339263916015625 +5186 -0.163055419921875 +5187 -0.3775634765625 +5188 -0.187225341796875 +5189 -0.445709228515625 +5190 -0.217559814453125 +5191 -0.535064697265625 +5192 -0.248260498046875 +5193 -0.629058837890625 +5194 -0.2686767578125 +5195 -0.697601318359375 +5196 -0.26580810546875 +5197 -0.70391845703125 +5198 -0.23797607421875 +5199 -0.6424560546875 +5200 -0.1776123046875 +5201 -0.491241455078125 +5202 -0.090606689453125 +5203 -0.265716552734375 +5204 0.00189208984375 +5205 -0.023712158203125 +5206 0.08770751953125 +5207 0.201751708984375 +5208 0.154052734375 +5209 0.375823974609375 +5210 0.1959228515625 +5211 0.485076904296875 +5212 0.227386474609375 +5213 0.56884765625 +5214 0.25115966796875 +5215 0.634765625 +5216 0.2509765625 +5217 0.63763427734375 +5218 0.22283935546875 +5219 0.5660400390625 +5220 0.185638427734375 +5221 0.4720458984375 +5222 0.158050537109375 +5223 0.40692138671875 +5224 0.1429443359375 +5225 0.3778076171875 +5226 0.137786865234375 +5227 0.376953125 +5228 0.13116455078125 +5229 0.371978759765625 +5230 0.10540771484375 +5231 0.313140869140625 +5232 0.055023193359375 +5233 0.184417724609375 +5234 -0.0106201171875 +5235 0.011199951171875 +5236 -0.078582763671875 +5237 -0.171051025390625 +5238 -0.139801025390625 +5239 -0.33740234375 +5240 -0.18853759765625 +5241 -0.47198486328125 +5242 -0.2196044921875 +5243 -0.560394287109375 +5244 -0.225128173828125 +5245 -0.58056640625 +5246 -0.210662841796875 +5247 -0.54754638671875 +5248 -0.193389892578125 +5249 -0.508575439453125 +5250 -0.1719970703125 +5251 -0.459503173828125 +5252 -0.144561767578125 +5253 -0.394378662109375 +5254 -0.125457763671875 +5255 -0.35260009765625 +5256 -0.106842041015625 +5257 -0.31170654296875 +5258 -0.06219482421875 +5259 -0.197418212890625 +5260 0.0089111328125 +5261 -0.007965087890625 +5262 0.088653564453125 +5263 0.207489013671875 +5264 0.16259765625 +5265 0.409210205078125 +5266 0.2216796875 +5267 0.57208251953125 +5268 0.25506591796875 +5269 0.66595458984375 +5270 0.251251220703125 +5271 0.65875244140625 +5272 0.2164306640625 +5273 0.56744384765625 +5274 0.164886474609375 +5275 0.431396484375 +5276 0.112579345703125 +5277 0.29443359375 +5278 0.069000244140625 +5279 0.182464599609375 +5280 0.02288818359375 +5281 0.06365966796875 +5282 -0.03057861328125 +5283 -0.075958251953125 +5284 -0.0743408203125 +5285 -0.189422607421875 +5286 -0.10650634765625 +5287 -0.271942138671875 +5288 -0.1337890625 +5289 -0.342529296875 +5290 -0.142822265625 +5291 -0.364166259765625 +5292 -0.130096435546875 +5293 -0.327239990234375 +5294 -0.111846923828125 +5295 -0.2769775390625 +5296 -0.1026611328125 +5297 -0.253692626953125 +5298 -0.097625732421875 +5299 -0.24365234375 +5300 -0.079376220703125 +5301 -0.1983642578125 +5302 -0.0474853515625 +5303 -0.116241455078125 +5304 -0.01629638671875 +5305 -0.036834716796875 +5306 0.01220703125 +5307 0.034881591796875 +5308 0.035125732421875 +5309 0.09124755859375 +5310 0.043914794921875 +5311 0.10888671875 +5312 0.052001953125 +5313 0.125518798828125 +5314 0.065277099609375 +5315 0.15771484375 +5316 0.0738525390625 +5317 0.17828369140625 +5318 0.071868896484375 +5319 0.17108154296875 +5320 0.057098388671875 +5321 0.129974365234375 +5322 0.039459228515625 +5323 0.082427978515625 +5324 0.018707275390625 +5325 0.027679443359375 +5326 -0.016357421875 +5327 -0.065643310546875 +5328 -0.0518798828125 +5329 -0.15936279296875 +5330 -0.0732421875 +5331 -0.21307373046875 +5332 -0.0831298828125 +5333 -0.234649658203125 +5334 -0.072845458984375 +5335 -0.2001953125 +5336 -0.045684814453125 +5337 -0.119171142578125 +5338 -0.013458251953125 +5339 -0.024749755859375 +5340 0.024871826171875 +5341 0.085784912109375 +5342 0.0570068359375 +5343 0.178131103515625 +5344 0.06976318359375 +5345 0.215576171875 +5346 0.0679931640625 +5347 0.211456298828125 +5348 0.05511474609375 +5349 0.17523193359375 +5350 0.038970947265625 +5351 0.128753662109375 +5352 0.030303955078125 +5353 0.1019287109375 +5354 0.021697998046875 +5355 0.0743408203125 +5356 0.012054443359375 +5357 0.04327392578125 +5358 0.01190185546875 +5359 0.038177490234375 +5360 0.027374267578125 +5361 0.076263427734375 +5362 0.052398681640625 +5363 0.14105224609375 +5364 0.070281982421875 +5365 0.186431884765625 +5366 0.07244873046875 +5367 0.188812255859375 +5368 0.055572509765625 +5369 0.1390380859375 +5370 0.02130126953125 +5371 0.041778564453125 +5372 -0.021942138671875 +5373 -0.079437255859375 +5374 -0.072296142578125 +5375 -0.219390869140625 +5376 -0.125701904296875 +5377 -0.367828369140625 +5378 -0.170928955078125 +5379 -0.494873046875 +5380 -0.192962646484375 +5381 -0.556243896484375 +5382 -0.1778564453125 +5383 -0.508697509765625 +5384 -0.133514404296875 +5385 -0.3756103515625 +5386 -0.080535888671875 +5387 -0.218902587890625 +5388 -0.027435302734375 +5389 -0.063751220703125 +5390 0.02606201171875 +5391 0.091552734375 +5392 0.07611083984375 +5393 0.23602294921875 +5394 0.113800048828125 +5395 0.342987060546875 +5396 0.13330078125 +5397 0.39520263671875 +5398 0.133392333984375 +5399 0.389373779296875 +5400 0.11358642578125 +5401 0.324249267578125 +5402 0.081787109375 +5403 0.224090576171875 +5404 0.049560546875 +5405 0.124267578125 +5406 0.02093505859375 +5407 0.037078857421875 +5408 0.0048828125 +5409 -0.010101318359375 +5410 0.000732421875 +5411 -0.019439697265625 +5412 -0.0018310546875 +5413 -0.022796630859375 +5414 0.003387451171875 +5415 -0.001556396484375 +5416 0.02044677734375 +5417 0.056304931640625 +5418 0.035003662109375 +5419 0.106719970703125 +5420 0.02984619140625 +5421 0.096893310546875 +5422 0.01031494140625 +5423 0.042694091796875 +5424 -0.011077880859375 +5425 -0.018035888671875 +5426 -0.031158447265625 +5427 -0.07586669921875 +5428 -0.046173095703125 +5429 -0.11944580078125 +5430 -0.0596923828125 +5431 -0.15972900390625 +5432 -0.073638916015625 +5433 -0.202606201171875 +5434 -0.088165283203125 +5435 -0.24859619140625 +5436 -0.10577392578125 +5437 -0.30517578125 +5438 -0.123199462890625 +5439 -0.36212158203125 +5440 -0.131317138671875 +5441 -0.39141845703125 +5442 -0.117828369140625 +5443 -0.35528564453125 +5444 -0.08160400390625 +5445 -0.249969482421875 +5446 -0.028472900390625 +5447 -0.092864990234375 +5448 0.032623291015625 +5449 0.08905029296875 +5450 0.081756591796875 +5451 0.2352294921875 +5452 0.110076904296875 +5453 0.318817138671875 +5454 0.12371826171875 +5455 0.358642578125 +5456 0.120391845703125 +5457 0.347747802734375 +5458 0.09991455078125 +5459 0.28564453125 +5460 0.0789794921875 +5461 0.223175048828125 +5462 0.069549560546875 +5463 0.196746826171875 +5464 0.06298828125 +5465 0.179840087890625 +5466 0.053802490234375 +5467 0.155548095703125 +5468 0.051055908203125 +5469 0.151214599609375 +5470 0.05157470703125 +5471 0.156951904296875 +5472 0.041961669921875 +5473 0.13177490234375 +5474 0.030548095703125 +5475 0.100799560546875 +5476 0.02496337890625 +5477 0.087127685546875 +5478 0.013519287109375 +5479 0.05487060546875 +5480 -0.00799560546875 +5481 -0.009002685546875 +5482 -0.039398193359375 +5483 -0.10400390625 +5484 -0.0804443359375 +5485 -0.229400634765625 +5486 -0.121429443359375 +5487 -0.35552978515625 +5488 -0.14910888671875 +5489 -0.441925048828125 +5490 -0.15869140625 +5491 -0.473846435546875 +5492 -0.1546630859375 +5493 -0.464813232421875 +5494 -0.13848876953125 +5495 -0.419097900390625 +5496 -0.109466552734375 +5497 -0.334320068359375 +5498 -0.0733642578125 +5499 -0.227935791015625 +5500 -0.0379638671875 +5501 -0.12347412109375 +5502 -0.00555419921875 +5503 -0.02764892578125 +5504 0.029754638671875 +5505 0.077667236328125 +5506 0.074737548828125 +5507 0.2132568359375 +5508 0.132568359375 +5509 0.38885498046875 +5510 0.196136474609375 +5511 0.582794189453125 +5512 0.24542236328125 +5513 0.734039306640625 +5514 0.266510009765625 +5515 0.800140380859375 +5516 0.258544921875 +5517 0.7783203125 +5518 0.220458984375 +5519 0.6651611328125 +5520 0.1519775390625 +5521 0.45965576171875 +5522 0.0654296875 +5523 0.199188232421875 +5524 -0.017608642578125 +5525 -0.050689697265625 +5526 -0.078338623046875 +5527 -0.23297119140625 +5528 -0.11102294921875 +5529 -0.33013916015625 +5530 -0.12420654296875 +5531 -0.368408203125 +5532 -0.1280517578125 +5533 -0.378936767578125 +5534 -0.127593994140625 +5535 -0.376983642578125 +5536 -0.128448486328125 +5537 -0.37969970703125 +5538 -0.132080078125 +5539 -0.391510009765625 +5540 -0.129608154296875 +5541 -0.385345458984375 +5542 -0.11474609375 +5543 -0.3419189453125 +5544 -0.094635009765625 +5545 -0.28289794921875 +5546 -0.08349609375 +5547 -0.251617431640625 +5548 -0.087310791015625 +5549 -0.266143798828125 +5550 -0.0887451171875 +5551 -0.273345947265625 +5552 -0.069305419921875 +5553 -0.216796875 +5554 -0.039459228515625 +5555 -0.128265380859375 +5556 -0.01904296875 +5557 -0.068145751953125 +5558 -0.01031494140625 +5559 -0.0430908203125 +5560 -0.003875732421875 +5561 -0.024444580078125 +5562 0.01104736328125 +5563 0.020721435546875 +5564 0.044921875 +5565 0.124481201171875 +5566 0.088287353515625 +5567 0.25787353515625 +5568 0.127471923828125 +5569 0.379119873046875 +5570 0.1597900390625 +5571 0.47991943359375 +5572 0.174774169921875 +5573 0.5281982421875 +5574 0.16827392578125 +5575 0.511138916015625 +5576 0.14935302734375 +5577 0.456207275390625 +5578 0.13250732421875 +5579 0.407470703125 +5580 0.12396240234375 +5581 0.383758544921875 +5582 0.114471435546875 +5583 0.35687255859375 +5584 0.099151611328125 +5585 0.31182861328125 +5586 0.078765869140625 +5587 0.250885009765625 +5588 0.050506591796875 +5589 0.1654052734375 +5590 0.0078125 +5591 0.035247802734375 +5592 -0.05010986328125 +5593 -0.142059326171875 +5594 -0.1131591796875 +5595 -0.33563232421875 +5596 -0.17779541015625 +5597 -0.5345458984375 +5598 -0.23846435546875 +5599 -0.72186279296875 +5600 -0.275238037109375 +5601 -0.836669921875 +5602 -0.272979736328125 +5603 -0.8326416015625 +5604 -0.238250732421875 +5605 -0.7296142578125 +5606 -0.18914794921875 +5607 -0.582550048828125 +5608 -0.14166259765625 +5609 -0.440093994140625 +5610 -0.10308837890625 +5611 -0.324310302734375 +5612 -0.0623779296875 +5613 -0.20147705078125 +5614 -0.01068115234375 +5615 -0.044647216796875 +5616 0.038116455078125 +5617 0.103973388671875 +5618 0.070220947265625 +5619 0.202392578125 +5620 0.090179443359375 +5621 0.264495849609375 +5622 0.113983154296875 +5623 0.338897705078125 +5624 0.14764404296875 +5625 0.443817138671875 +5626 0.17999267578125 +5627 0.545074462890625 +5628 0.202789306640625 +5629 0.6173095703125 +5630 0.21343994140625 +5631 0.6524658203125 +5632 0.2158203125 +5633 0.66339111328125 +5634 0.211822509765625 +5635 0.6561279296875 +5636 0.194244384765625 +5637 0.606781005859375 +5638 0.15911865234375 +5639 0.501190185546875 +5640 0.11065673828125 +5641 0.352783203125 +5642 0.053619384765625 +5643 0.176544189453125 +5644 -0.013824462890625 +5645 -0.034820556640625 +5646 -0.08453369140625 +5647 -0.258209228515625 +5648 -0.14312744140625 +5649 -0.44244384765625 +5650 -0.18572998046875 +5651 -0.5753173828125 +5652 -0.210784912109375 +5653 -0.65203857421875 +5654 -0.209014892578125 +5655 -0.641632080078125 +5656 -0.18572998046875 +5657 -0.562164306640625 +5658 -0.154083251953125 +5659 -0.458038330078125 +5660 -0.12042236328125 +5661 -0.350555419921875 +5662 -0.091064453125 +5663 -0.260528564453125 +5664 -0.067413330078125 +5665 -0.192108154296875 +5666 -0.04864501953125 +5667 -0.141937255859375 +5668 -0.03265380859375 +5669 -0.1021728515625 +5670 -0.016754150390625 +5671 -0.062896728515625 +5672 0.00238037109375 +5673 -0.011932373046875 +5674 0.02813720703125 +5675 0.062835693359375 +5676 0.05657958984375 +5677 0.148712158203125 +5678 0.086334228515625 +5679 0.241729736328125 +5680 0.119476318359375 +5681 0.34912109375 +5682 0.151947021484375 +5683 0.457305908203125 +5684 0.177093505859375 +5685 0.54388427734375 +5686 0.184326171875 +5687 0.5728759765625 +5688 0.16259765625 +5689 0.506591796875 +5690 0.1138916015625 +5691 0.351226806640625 +5692 0.05010986328125 +5693 0.146514892578125 +5694 -0.013031005859375 +5695 -0.05523681640625 +5696 -0.064178466796875 +5697 -0.21624755859375 +5698 -0.102630615234375 +5699 -0.334930419921875 +5700 -0.12579345703125 +5701 -0.402984619140625 +5702 -0.1396484375 +5703 -0.4412841796875 +5704 -0.15771484375 +5705 -0.49578857421875 +5706 -0.17803955078125 +5707 -0.5601806640625 +5708 -0.190582275390625 +5709 -0.600738525390625 +5710 -0.18548583984375 +5711 -0.584228515625 +5712 -0.15350341796875 +5713 -0.47930908203125 +5714 -0.0927734375 +5715 -0.27935791015625 +5716 -0.010650634765625 +5717 -0.0089111328125 +5718 0.073974609375 +5719 0.268798828125 +5720 0.139984130859375 +5721 0.482818603515625 +5722 0.178497314453125 +5723 0.60369873046875 +5724 0.194976806640625 +5725 0.650421142578125 +5726 0.201416015625 +5727 0.66400146484375 +5728 0.19683837890625 +5729 0.6414794921875 +5730 0.178070068359375 +5731 0.572540283203125 +5732 0.15716552734375 +5733 0.498138427734375 +5734 0.140380859375 +5735 0.439453125 +5736 0.1214599609375 +5737 0.375518798828125 +5738 0.09100341796875 +5739 0.274505615234375 +5740 0.0408935546875 +5741 0.1087646484375 +5742 -0.022186279296875 +5743 -0.099395751953125 +5744 -0.0887451171875 +5745 -0.3182373046875 +5746 -0.1590576171875 +5747 -0.5489501953125 +5748 -0.22772216796875 +5749 -0.7738037109375 +5750 -0.2789306640625 +5751 -0.86383056640625 +5752 -0.302764892578125 +5753 -0.870391845703125 +5754 -0.304351806640625 +5755 -0.86895751953125 +5756 -0.287506103515625 +5757 -0.861053466796875 +5758 -0.247039794921875 +5759 -0.765869140625 +5760 -0.179595947265625 +5761 -0.5301513671875 +5762 -0.087249755859375 +5763 -0.214691162109375 +5764 0.017242431640625 +5765 0.137359619140625 +5766 0.118682861328125 +5767 0.474822998046875 +5768 0.206512451171875 +5769 0.76239013671875 +5770 0.27264404296875 +5771 0.867462158203125 +5772 0.317138671875 +5773 0.870361328125 +5774 0.33648681640625 +5775 0.86480712890625 +5776 0.3321533203125 +5777 0.831817626953125 +5778 0.311279296875 +5779 0.677581787109375 +5780 0.2755126953125 +5781 0.495880126953125 +5782 0.23028564453125 +5783 0.30767822265625 +5784 0.17620849609375 +5785 0.116180419921875 +5786 0.103851318359375 +5787 -0.110748291015625 +5788 0.0111083984375 +5789 -0.381805419921875 +5790 -0.08929443359375 +5791 -0.6572265625 +5792 -0.179595947265625 +5793 -0.857421875 +5794 -0.247100830078125 +5795 -0.870391845703125 +5796 -0.289642333984375 +5797 -0.870391845703125 +5798 -0.315155029296875 +5799 -0.86444091796875 +5800 -0.3341064453125 +5801 -0.85723876953125 +5802 -0.34100341796875 +5803 -0.790008544921875 +5804 -0.3197021484375 +5805 -0.62847900390625 +5806 -0.26922607421875 +5807 -0.3956298828125 +5808 -0.199249267578125 +5809 -0.126708984375 +5810 -0.1177978515625 +5811 0.150115966796875 +5812 -0.0283203125 +5813 0.424041748046875 +5814 0.061187744140625 +5815 0.670623779296875 +5816 0.1392822265625 +5817 0.854522705078125 +5818 0.200714111328125 +5819 0.866485595703125 +5820 0.240936279296875 +5821 0.86920166015625 +5822 0.2652587890625 +5823 0.8653564453125 +5824 0.277618408203125 +5825 0.857147216796875 +5826 0.277099609375 +5827 0.766845703125 +5828 0.265167236328125 +5829 0.628509521484375 +5830 0.239776611328125 +5831 0.462127685546875 +5832 0.208526611328125 +5833 0.297210693359375 +5834 0.175018310546875 +5835 0.14862060546875 +5836 0.1324462890625 +5837 -0.00537109375 +5838 0.0830078125 +5839 -0.15753173828125 +5840 0.025634765625 +5841 -0.31304931640625 +5842 -0.0438232421875 +5843 -0.48876953125 +5844 -0.111480712890625 +5845 -0.6416015625 +5846 -0.16998291015625 +5847 -0.751373291015625 +5848 -0.22613525390625 +5849 -0.84619140625 +5850 -0.275543212890625 +5851 -0.861297607421875 +5852 -0.308380126953125 +5853 -0.863250732421875 +5854 -0.31524658203125 +5855 -0.856597900390625 +5856 -0.2996826171875 +5857 -0.7498779296875 +5858 -0.278778076171875 +5859 -0.624542236328125 +5860 -0.246002197265625 +5861 -0.47808837890625 +5862 -0.184051513671875 +5863 -0.253387451171875 +5864 -0.106414794921875 +5865 0.003692626953125 +5866 -0.0333251953125 +5867 0.2257080078125 +5868 0.038909912109375 +5869 0.427154541015625 +5870 0.119873046875 +5871 0.643218994140625 +5872 0.206695556640625 +5873 0.855926513671875 +5874 0.282196044921875 +5875 0.870361328125 +5876 0.3316650390625 +5877 0.870361328125 +5878 0.357208251953125 +5879 0.862762451171875 +5880 0.35791015625 +5881 0.79669189453125 +5882 0.330963134765625 +5883 0.595794677734375 +5884 0.28497314453125 +5885 0.362152099609375 +5886 0.22821044921875 +5887 0.1270751953125 +5888 0.166351318359375 +5889 -0.086944580078125 +5890 0.0997314453125 +5891 -0.2784423828125 +5892 0.01947021484375 +5893 -0.484832763671875 +5894 -0.078582763671875 +5895 -0.729583740234375 +5896 -0.1802978515625 +5897 -0.86688232421875 +5898 -0.268310546875 +5899 -0.870391845703125 +5900 -0.3408203125 +5901 -0.86859130859375 +5902 -0.3968505859375 +5903 -0.86279296875 +5904 -0.426727294921875 +5905 -0.817962646484375 +5906 -0.418426513671875 +5907 -0.6116943359375 +5908 -0.37017822265625 +5909 -0.3128662109375 +5910 -0.291107177734375 +5911 0.039398193359375 +5912 -0.186798095703125 +5913 0.422821044921875 +5914 -0.066497802734375 +5915 0.805145263671875 +5916 0.051300048828125 +5917 0.870361328125 +5918 0.15106201171875 +5919 0.870361328125 +5920 0.2291259765625 +5921 0.860015869140625 +5922 0.282958984375 +5923 0.727935791015625 +5924 0.310638427734375 +5925 0.48114013671875 +5926 0.318145751953125 +5927 0.2059326171875 +5928 0.3111572265625 +5929 -0.06103515625 +5930 0.292083740234375 +5931 -0.29913330078125 +5932 0.257049560546875 +5933 -0.516204833984375 +5934 0.202056884765625 +5935 -0.7252197265625 +5936 0.13385009765625 +5937 -0.85980224609375 +5938 0.061798095703125 +5939 -0.870391845703125 +5940 -0.005889892578125 +5941 -0.870391845703125 +5942 -0.055877685546875 +5943 -0.858062744140625 +5944 -0.0865478515625 +5945 -0.673004150390625 +5946 -0.111236572265625 +5947 -0.42694091796875 +5948 -0.141143798828125 +5949 -0.2100830078125 +5950 -0.17523193359375 +5951 -0.0362548828125 +5952 -0.205413818359375 +5953 0.10943603515625 +5954 -0.226043701171875 +5955 0.23516845703125 +5956 -0.225982666015625 +5957 0.373687744140625 +5958 -0.2056884765625 +5959 0.517791748046875 +5960 -0.181793212890625 +5961 0.602783203125 +5962 -0.153076171875 +5963 0.635711669921875 +5964 -0.1109619140625 +5965 0.655181884765625 +5966 -0.05841064453125 +5967 0.65948486328125 +5968 0.00201416015625 +5969 0.651275634765625 +5970 0.06341552734375 +5971 0.61846923828125 +5972 0.115509033203125 +5973 0.53753662109375 +5974 0.153076171875 +5975 0.404144287109375 +5976 0.173095703125 +5977 0.22186279296875 +5978 0.175537109375 +5979 0.003997802734375 +5980 0.16485595703125 +5981 -0.22100830078125 +5982 0.14630126953125 +5983 -0.42449951171875 +5984 0.125335693359375 +5985 -0.579833984375 +5986 0.113250732421875 +5987 -0.641876220703125 +5988 0.108367919921875 +5989 -0.6177978515625 +5990 0.09381103515625 +5991 -0.575531005859375 +5992 0.06842041015625 +5993 -0.526336669921875 +5994 0.04620361328125 +5995 -0.42645263671875 +5996 0.03472900390625 +5997 -0.2581787109375 +5998 0.02484130859375 +5999 -0.068695068359375 +6000 0.006805419921875 +6001 0.09222412109375 +6002 -0.0140380859375 +6003 0.232147216796875 +6004 -0.034637451171875 +6005 0.3509521484375 +6006 -0.062530517578125 +6007 0.410064697265625 +6008 -0.105224609375 +6009 0.372955322265625 +6010 -0.157073974609375 +6011 0.2554931640625 +6012 -0.2042236328125 +6013 0.10711669921875 +6014 -0.241485595703125 +6015 -0.052886962890625 +6016 -0.2593994140625 +6017 -0.186279296875 +6018 -0.243438720703125 +6019 -0.23291015625 +6020 -0.1998291015625 +6021 -0.209442138671875 +6022 -0.146270751953125 +6023 -0.174163818359375 +6024 -0.085296630859375 +6025 -0.126739501953125 +6026 -0.014617919921875 +6027 -0.048126220703125 +6028 0.05792236328125 +6029 0.0426025390625 +6030 0.11968994140625 +6031 0.10748291015625 +6032 0.166900634765625 +6033 0.1409912109375 +6034 0.211883544921875 +6035 0.19708251953125 +6036 0.252685546875 +6037 0.273651123046875 +6038 0.27447509765625 +6039 0.31768798828125 +6040 0.2801513671875 +6041 0.341094970703125 +6042 0.27642822265625 +6043 0.368011474609375 +6044 0.25732421875 +6045 0.37249755859375 +6046 0.209991455078125 +6047 0.30072021484375 +6048 0.135955810546875 +6049 0.1517333984375 +6050 0.053070068359375 +6051 -0.01470947265625 +6052 -0.03369140625 +6053 -0.1883544921875 +6054 -0.122955322265625 +6055 -0.372711181640625 +6056 -0.198333740234375 +6057 -0.51397705078125 +6058 -0.24713134765625 +6059 -0.57177734375 +6060 -0.26593017578125 +6061 -0.53948974609375 +6062 -0.258148193359375 +6063 -0.43511962890625 +6064 -0.232879638671875 +6065 -0.2962646484375 +6066 -0.199798583984375 +6067 -0.161102294921875 +6068 -0.162689208984375 +6069 -0.0435791015625 +6070 -0.121063232421875 +6071 0.060394287109375 +6072 -0.079681396484375 +6073 0.13665771484375 +6074 -0.04388427734375 +6075 0.170135498046875 +6076 -0.0140380859375 +6077 0.16552734375 +6078 0.017120361328125 +6079 0.15728759765625 +6080 0.049102783203125 +6081 0.150787353515625 +6082 0.07373046875 +6083 0.12200927734375 +6084 0.091705322265625 +6085 0.080108642578125 +6086 0.108428955078125 +6087 0.05126953125 +6088 0.129974365234375 +6089 0.062896728515625 +6090 0.14959716796875 +6091 0.09271240234375 +6092 0.154266357421875 +6093 0.092987060546875 +6094 0.1478271484375 +6095 0.07855224609375 +6096 0.13458251953125 +6097 0.06427001953125 +6098 0.111175537109375 +6099 0.0347900390625 +6100 0.078125 +6101 -0.01171875 +6102 0.041839599609375 +6103 -0.056060791015625 +6104 0.0150146484375 +6105 -0.055511474609375 +6106 -0.000885009765625 +6107 -0.010467529296875 +6108 -0.0185546875 +6109 0.02508544921875 +6110 -0.04327392578125 +6111 0.025665283203125 +6112 -0.066864013671875 +6113 0.017333984375 +6114 -0.087799072265625 +6115 0.00189208984375 +6116 -0.10821533203125 +6117 -0.03173828125 +6118 -0.12445068359375 +6119 -0.071502685546875 +6120 -0.14111328125 +6121 -0.13543701171875 +6122 -0.157470703125 +6123 -0.219970703125 +6124 -0.16748046875 +6125 -0.300506591796875 +6126 -0.171722412109375 +6127 -0.376312255859375 +6128 -0.1629638671875 +6129 -0.416107177734375 +6130 -0.12945556640625 +6131 -0.371124267578125 +6132 -0.072662353515625 +6133 -0.242279052734375 +6134 -0.004486083984375 +6135 -0.069732666015625 +6136 0.06829833984375 +6137 0.125640869140625 +6138 0.136322021484375 +6139 0.31268310546875 +6140 0.189056396484375 +6141 0.45501708984375 +6142 0.226348876953125 +6143 0.554779052734375 +6144 0.247161865234375 +6145 0.61065673828125 +6146 0.24835205078125 +6147 0.610931396484375 +6148 0.224212646484375 +6149 0.531463623046875 +6150 0.179229736328125 +6151 0.3883056640625 +6152 0.12738037109375 +6153 0.23468017578125 +6154 0.07574462890625 +6155 0.095245361328125 +6156 0.0318603515625 +6157 -0.00396728515625 +6158 0.000396728515625 +6159 -0.04852294921875 +6160 -0.021636962890625 +6161 -0.055145263671875 +6162 -0.046112060546875 +6163 -0.0758056640625 +6164 -0.079071044921875 +6165 -0.138702392578125 +6166 -0.1109619140625 +6167 -0.209197998046875 +6168 -0.14154052734375 +6169 -0.289031982421875 +6170 -0.170501708984375 +6171 -0.37884521484375 +6172 -0.1920166015625 +6173 -0.456329345703125 +6174 -0.204864501953125 +6175 -0.51641845703125 +6176 -0.199310302734375 +6177 -0.519287109375 +6178 -0.174163818359375 +6179 -0.458251953125 +6180 -0.142913818359375 +6181 -0.384796142578125 +6182 -0.112548828125 +6183 -0.323699951171875 +6184 -0.082489013671875 +6185 -0.269287109375 +6186 -0.047149658203125 +6187 -0.1951904296875 +6188 -0.007080078125 +6189 -0.100006103515625 +6190 0.030120849609375 +6191 -0.01055908203125 +6192 0.07122802734375 +6193 0.1033935546875 +6194 0.117431640625 +6195 0.24908447265625 +6196 0.15496826171875 +6197 0.373199462890625 +6198 0.17913818359375 +6199 0.45806884765625 +6200 0.191802978515625 +6201 0.511474609375 +6202 0.20111083984375 +6203 0.565399169921875 +6204 0.205291748046875 +6205 0.61138916015625 +6206 0.189910888671875 +6207 0.5897216796875 +6208 0.153106689453125 +6209 0.4906005859375 +6210 0.100006103515625 +6211 0.33148193359375 +6212 0.04022216796875 +6213 0.147796630859375 +6214 -0.015045166015625 +6215 -0.01873779296875 +6216 -0.058074951171875 +6217 -0.140289306640625 +6218 -0.082000732421875 +6219 -0.191986083984375 +6220 -0.088897705078125 +6221 -0.184295654296875 +6222 -0.089508056640625 +6223 -0.161834716796875 +6224 -0.094024658203125 +6225 -0.166595458984375 +6226 -0.1011962890625 +6227 -0.19390869140625 +6228 -0.10626220703125 +6229 -0.22442626953125 +6230 -0.114837646484375 +6231 -0.279754638671875 +6232 -0.1220703125 +6233 -0.3389892578125 +6234 -0.11651611328125 +6235 -0.3543701171875 +6236 -0.10430908203125 +6237 -0.348175048828125 +6238 -0.087432861328125 +6239 -0.32598876953125 +6240 -0.059112548828125 +6241 -0.2581787109375 +6242 -0.01873779296875 +6243 -0.139801025390625 +6244 0.029449462890625 +6245 0.014617919921875 +6246 0.069793701171875 +6247 0.144378662109375 +6248 0.09478759765625 +6249 0.221038818359375 +6250 0.110687255859375 +6251 0.27069091796875 +6252 0.117584228515625 +6253 0.294036865234375 +6254 0.12066650390625 +6255 0.311767578125 +6256 0.123809814453125 +6257 0.339141845703125 +6258 0.123077392578125 +6259 0.360260009765625 +6260 0.115264892578125 +6261 0.360504150390625 +6262 0.093658447265625 +6263 0.308380126953125 +6264 0.0537109375 +6265 0.18170166015625 +6266 0.001739501953125 +6267 0.0047607421875 +6268 -0.05072021484375 +6269 -0.17559814453125 +6270 -0.0926513671875 +6271 -0.3143310546875 +6272 -0.113433837890625 +6273 -0.36785888671875 +6274 -0.118743896484375 +6275 -0.36248779296875 +6276 -0.1187744140625 +6277 -0.343536376953125 +6278 -0.111236572265625 +6279 -0.3018798828125 +6280 -0.09466552734375 +6281 -0.231414794921875 +6282 -0.0657958984375 +6283 -0.117645263671875 +6284 -0.032318115234375 +6285 0.007049560546875 +6286 -0.007232666015625 +6287 0.087982177734375 +6288 0.012359619140625 +6289 0.13946533203125 +6290 0.028961181640625 +6291 0.17425537109375 +6292 0.041107177734375 +6293 0.188201904296875 +6294 0.04595947265625 +6295 0.171234130859375 +6296 0.041900634765625 +6297 0.118438720703125 +6298 0.034881591796875 +6299 0.05706787109375 +6300 0.02496337890625 +6301 -0.010711669921875 +6302 0.0103759765625 +6303 -0.0914306640625 +6304 -0.00372314453125 +6305 -0.162322998046875 +6306 -0.0107421875 +6307 -0.194549560546875 +6308 -0.001678466796875 +6309 -0.1492919921875 +6310 0.02471923828125 +6311 -0.02166748046875 +6312 0.053802490234375 +6313 0.124053955078125 +6314 0.068023681640625 +6315 0.211151123046875 +6316 0.067962646484375 +6317 0.240447998046875 +6318 0.061065673828125 +6319 0.242218017578125 +6320 0.049896240234375 +6321 0.2257080078125 +6322 0.035614013671875 +6323 0.194366455078125 +6324 0.011016845703125 +6325 0.115509033203125 +6326 -0.01800537109375 +6327 0.0128173828125 +6328 -0.037322998046875 +6329 -0.053802490234375 +6330 -0.0528564453125 +6331 -0.110626220703125 +6332 -0.074249267578125 +6333 -0.199493408203125 +6334 -0.095458984375 +6335 -0.29437255859375 +6336 -0.101959228515625 +6337 -0.33221435546875 +6338 -0.086181640625 +6339 -0.27972412109375 +6340 -0.059600830078125 +6341 -0.185333251953125 +6342 -0.0408935546875 +6343 -0.128204345703125 +6344 -0.032073974609375 +6345 -0.115692138671875 +6346 -0.02618408203125 +6347 -0.116455078125 +6348 -0.01788330078125 +6349 -0.105926513671875 +6350 -0.00048828125 +6351 -0.053955078125 +6352 0.02789306640625 +6353 0.048797607421875 +6354 0.05657958984375 +6355 0.157318115234375 +6356 0.071563720703125 +6357 0.212005615234375 +6358 0.074066162109375 +6359 0.218475341796875 +6360 0.078125 +6361 0.23724365234375 +6362 0.092376708984375 +6363 0.30535888671875 +6364 0.1072998046875 +6365 0.38128662109375 +6366 0.1090087890625 +6367 0.404449462890625 +6368 0.102294921875 +6369 0.3944091796875 +6370 0.0960693359375 +6371 0.3885498046875 +6372 0.08502197265625 +6373 0.362640380859375 +6374 0.0594482421875 +6375 0.27362060546875 +6376 0.018585205078125 +6377 0.11712646484375 +6378 -0.0252685546875 +6379 -0.054901123046875 +6380 -0.0599365234375 +6381 -0.19085693359375 +6382 -0.084075927734375 +6383 -0.28570556640625 +6384 -0.097564697265625 +6385 -0.339263916015625 +6386 -0.106414794921875 +6387 -0.3775634765625 +6388 -0.121124267578125 +6389 -0.445709228515625 +6390 -0.139801025390625 +6391 -0.535064697265625 +6392 -0.15875244140625 +6393 -0.629058837890625 +6394 -0.171142578125 +6395 -0.697601318359375 +6396 -0.168670654296875 +6397 -0.70391845703125 +6398 -0.150238037109375 +6399 -0.6424560546875 +6400 -0.111480712890625 +6401 -0.491241455078125 +6402 -0.056365966796875 +6403 -0.265716552734375 +6404 0.002227783203125 +6405 -0.023712158203125 +6406 0.056976318359375 +6407 0.201751708984375 +6408 0.10028076171875 +6409 0.375823974609375 +6410 0.12896728515625 +6411 0.485076904296875 +6412 0.1505126953125 +6413 0.56884765625 +6414 0.166229248046875 +6415 0.634765625 +6416 0.1669921875 +6417 0.63763427734375 +6418 0.150604248046875 +6419 0.5660400390625 +6420 0.127655029296875 +6421 0.4720458984375 +6422 0.10870361328125 +6423 0.40692138671875 +6424 0.095550537109375 +6425 0.3778076171875 +6426 0.087127685546875 +6427 0.376953125 +6428 0.077423095703125 +6429 0.371978759765625 +6430 0.056976318359375 +6431 0.313140869140625 +6432 0.023101806640625 +6433 0.184417724609375 +6434 -0.0186767578125 +6435 0.011199951171875 +6436 -0.060882568359375 +6437 -0.171051025390625 +6438 -0.098236083984375 +6439 -0.33740234375 +6440 -0.127410888671875 +6441 -0.47198486328125 +6442 -0.14544677734375 +6443 -0.560394287109375 +6444 -0.147979736328125 +6445 -0.58056640625 +6446 -0.13812255859375 +6447 -0.54754638671875 +6448 -0.1256103515625 +6449 -0.508575439453125 +6450 -0.109893798828125 +6451 -0.459503173828125 +6452 -0.090118408203125 +6453 -0.394378662109375 +6454 -0.074554443359375 +6455 -0.35260009765625 +6456 -0.059112548828125 +6457 -0.31170654296875 +6458 -0.02935791015625 +6459 -0.197418212890625 +6460 0.014678955078125 +6461 -0.007965087890625 +6462 0.06280517578125 +6463 0.207489013671875 +6464 0.10687255859375 +6465 0.409210205078125 +6466 0.141693115234375 +6467 0.57208251953125 +6468 0.161163330078125 +6469 0.66595458984375 +6470 0.158843994140625 +6471 0.65875244140625 +6472 0.138275146484375 +6473 0.56744384765625 +6474 0.107452392578125 +6475 0.431396484375 +6476 0.075408935546875 +6477 0.29443359375 +6478 0.047607421875 +6479 0.182464599609375 +6480 0.01800537109375 +6481 0.06365966796875 +6482 -0.015838623046875 +6483 -0.075958251953125 +6484 -0.044219970703125 +6485 -0.189422607421875 +6486 -0.06585693359375 +6487 -0.271942138671875 +6488 -0.08428955078125 +6489 -0.342529296875 +6490 -0.091949462890625 +6491 -0.364166259765625 +6492 -0.086761474609375 +6493 -0.327239990234375 +6494 -0.077667236328125 +6495 -0.2769775390625 +6496 -0.072723388671875 +6497 -0.253692626953125 +6498 -0.0692138671875 +6499 -0.24365234375 +6500 -0.05755615234375 +6501 -0.1983642578125 +6502 -0.03759765625 +6503 -0.116241455078125 +6504 -0.0174560546875 +6505 -0.036834716796875 +6506 0.0015869140625 +6507 0.034881591796875 +6508 0.0177001953125 +6509 0.09124755859375 +6510 0.025970458984375 +6511 0.10888671875 +6512 0.03369140625 +6513 0.125518798828125 +6514 0.043914794921875 +6515 0.15771484375 +6516 0.051025390625 +6517 0.17828369140625 +6518 0.0516357421875 +6519 0.17108154296875 +6520 0.044464111328125 +6521 0.129974365234375 +6522 0.034942626953125 +6523 0.082427978515625 +6524 0.022979736328125 +6525 0.027679443359375 +6526 0.00238037109375 +6527 -0.065643310546875 +6528 -0.01904296875 +6529 -0.15936279296875 +6530 -0.033050537109375 +6531 -0.21307373046875 +6532 -0.041046142578125 +6533 -0.234649658203125 +6534 -0.03802490234375 +6535 -0.2001953125 +6536 -0.025665283203125 +6537 -0.119171142578125 +6538 -0.010406494140625 +6539 -0.024749755859375 +6540 0.008453369140625 +6541 0.085784912109375 +6542 0.024200439453125 +6543 0.178131103515625 +6544 0.0296630859375 +6545 0.215576171875 +6546 0.027587890625 +6547 0.211456298828125 +6548 0.01995849609375 +6549 0.17523193359375 +6550 0.011138916015625 +6551 0.128753662109375 +6552 0.007049560546875 +6553 0.1019287109375 +6554 0.003509521484375 +6555 0.0743408203125 +6556 -0.000152587890625 +6557 0.04327392578125 +6558 0.001800537109375 +6559 0.038177490234375 +6560 0.012603759765625 +6561 0.076263427734375 +6562 0.028778076171875 +6563 0.14105224609375 +6564 0.040924072265625 +6565 0.186431884765625 +6566 0.044158935546875 +6567 0.188812255859375 +6568 0.036529541015625 +6569 0.1390380859375 +6570 0.018890380859375 +6571 0.041778564453125 +6572 -0.004150390625 +6573 -0.079437255859375 +6574 -0.031585693359375 +6575 -0.219390869140625 +6576 -0.06134033203125 +6577 -0.367828369140625 +6578 -0.08746337890625 +6579 -0.494873046875 +6580 -0.101043701171875 +6581 -0.556243896484375 +6582 -0.09332275390625 +6583 -0.508697509765625 +6584 -0.068878173828125 +6585 -0.3756103515625 +6586 -0.039947509765625 +6587 -0.218902587890625 +6588 -0.011444091796875 +6589 -0.063751220703125 +6590 0.01702880859375 +6591 0.091552734375 +6592 0.04345703125 +6593 0.23602294921875 +6594 0.062652587890625 +6595 0.342987060546875 +6596 0.0712890625 +6597 0.39520263671875 +6598 0.06878662109375 +6599 0.389373779296875 +6600 0.054962158203125 +6601 0.324249267578125 +6602 0.034698486328125 +6603 0.224090576171875 +6604 0.01507568359375 +6605 0.124267578125 +6606 -0.001495361328125 +6607 0.037078857421875 +6608 -0.009552001953125 +6609 -0.010101318359375 +6610 -0.0096435546875 +6611 -0.019439697265625 +6612 -0.008270263671875 +6613 -0.022796630859375 +6614 -0.0018310546875 +6615 -0.001556396484375 +6616 0.011932373046875 +6617 0.056304931640625 +6618 0.024078369140625 +6619 0.106719970703125 +6620 0.02398681640625 +6621 0.096893310546875 +6622 0.01470947265625 +6623 0.042694091796875 +6624 0.003753662109375 +6625 -0.018035888671875 +6626 -0.00701904296875 +6627 -0.07586669921875 +6628 -0.015380859375 +6629 -0.11944580078125 +6630 -0.023529052734375 +6631 -0.15972900390625 +6632 -0.032623291015625 +6633 -0.202606201171875 +6634 -0.042694091796875 +6635 -0.24859619140625 +6636 -0.05517578125 +6637 -0.30517578125 +6638 -0.0679931640625 +6639 -0.36212158203125 +6640 -0.075469970703125 +6641 -0.39141845703125 +6642 -0.0699462890625 +6643 -0.35528564453125 +6644 -0.050567626953125 +6645 -0.249969482421875 +6646 -0.020751953125 +6647 -0.092864990234375 +6648 0.01416015625 +6649 0.08905029296875 +6650 0.04217529296875 +6651 0.2352294921875 +6652 0.0579833984375 +6653 0.318817138671875 +6654 0.06536865234375 +6655 0.358642578125 +6656 0.063568115234375 +6657 0.347747802734375 +6658 0.053131103515625 +6659 0.28564453125 +6660 0.042999267578125 +6661 0.223175048828125 +6662 0.039031982421875 +6663 0.196746826171875 +6664 0.03656005859375 +6665 0.179840087890625 +6666 0.0325927734375 +6667 0.155548095703125 +6668 0.0316162109375 +6669 0.151214599609375 +6670 0.031951904296875 +6671 0.156951904296875 +6672 0.026702880859375 +6673 0.13177490234375 +6674 0.0201416015625 +6675 0.100799560546875 +6676 0.0162353515625 +6677 0.087127685546875 +6678 0.009063720703125 +6679 0.05487060546875 +6680 -0.00341796875 +6681 -0.009002685546875 +6682 -0.021026611328125 +6683 -0.10400390625 +6684 -0.043548583984375 +6685 -0.229400634765625 +6686 -0.065887451171875 +6687 -0.35552978515625 +6688 -0.081207275390625 +6689 -0.441925048828125 +6690 -0.08697509765625 +6691 -0.473846435546875 +6692 -0.085418701171875 +6693 -0.464813232421875 +6694 -0.0772705078125 +6695 -0.419097900390625 +6696 -0.062164306640625 +6697 -0.334320068359375 +6698 -0.0430908203125 +6699 -0.227935791015625 +6700 -0.024078369140625 +6701 -0.12347412109375 +6702 -0.00634765625 +6703 -0.02764892578125 +6704 0.013031005859375 +6705 0.077667236328125 +6706 0.037445068359375 +6707 0.2132568359375 +6708 0.06842041015625 +6709 0.38885498046875 +6710 0.102294921875 +6711 0.582794189453125 +6712 0.12872314453125 +6713 0.734039306640625 +6714 0.1405029296875 +6715 0.800140380859375 +6716 0.13714599609375 +6717 0.7783203125 +6718 0.118072509765625 +6719 0.6651611328125 +6720 0.083160400390625 +6721 0.45965576171875 +6722 0.038726806640625 +6723 0.199188232421875 +6724 -0.004150390625 +6725 -0.050689697265625 +6726 -0.035858154296875 +6727 -0.23297119140625 +6728 -0.05340576171875 +6729 -0.33013916015625 +6730 -0.06109619140625 +6731 -0.368408203125 +6732 -0.064117431640625 +6733 -0.378936767578125 +6734 -0.064971923828125 +6735 -0.376983642578125 +6736 -0.06646728515625 +6737 -0.37969970703125 +6738 -0.069305419921875 +6739 -0.391510009765625 +6740 -0.068878173828125 +6741 -0.385345458984375 +6742 -0.061920166015625 +6743 -0.3419189453125 +6744 -0.05206298828125 +6745 -0.28289794921875 +6746 -0.046600341796875 +6747 -0.251617431640625 +6748 -0.048583984375 +6749 -0.266143798828125 +6750 -0.049102783203125 +6751 -0.273345947265625 +6752 -0.03875732421875 +6753 -0.216796875 +6754 -0.02288818359375 +6755 -0.128265380859375 +6756 -0.011688232421875 +6757 -0.068145751953125 +6758 -0.006378173828125 +6759 -0.0430908203125 +6760 -0.002166748046875 +6761 -0.024444580078125 +6762 0.006378173828125 +6763 0.020721435546875 +6764 0.024566650390625 +6765 0.124481201171875 +6766 0.047515869140625 +6767 0.25787353515625 +6768 0.06817626953125 +6769 0.379119873046875 +6770 0.08514404296875 +6771 0.47991943359375 +6772 0.093048095703125 +6773 0.5281982421875 +6774 0.0897216796875 +6775 0.511138916015625 +6776 0.079833984375 +6777 0.456207275390625 +6778 0.070831298828125 +6779 0.407470703125 +6780 0.065948486328125 +6781 0.383758544921875 +6782 0.060455322265625 +6783 0.35687255859375 +6784 0.0518798828125 +6785 0.31182861328125 +6786 0.0406494140625 +6787 0.250885009765625 +6788 0.025421142578125 +6789 0.1654052734375 +6790 0.002838134765625 +6791 0.035247802734375 +6792 -0.027435302734375 +6793 -0.142059326171875 +6794 -0.060211181640625 +6795 -0.33563232421875 +6796 -0.0936279296875 +6797 -0.5345458984375 +6798 -0.124847412109375 +6799 -0.72186279296875 +6800 -0.143646240234375 +6801 -0.836669921875 +6802 -0.142303466796875 +6803 -0.8326416015625 +6804 -0.124176025390625 +6805 -0.7296142578125 +6806 -0.09857177734375 +6807 -0.582550048828125 +6808 -0.07373046875 +6809 -0.440093994140625 +6810 -0.053375244140625 +6811 -0.324310302734375 +6812 -0.031890869140625 +6813 -0.20147705078125 +6814 -0.004791259765625 +6815 -0.044647216796875 +6816 0.020751953125 +6817 0.103973388671875 +6818 0.03765869140625 +6819 0.202392578125 +6820 0.048248291015625 +6821 0.264495849609375 +6822 0.0606689453125 +6823 0.338897705078125 +6824 0.0780029296875 +6825 0.443817138671875 +6826 0.09454345703125 +6827 0.545074462890625 +6828 0.106048583984375 +6829 0.6173095703125 +6830 0.111236572265625 +6831 0.6524658203125 +6832 0.1123046875 +6833 0.66339111328125 +6834 0.11029052734375 +6835 0.6561279296875 +6836 0.1011962890625 +6837 0.606781005859375 +6838 0.08270263671875 +6839 0.501190185546875 +6840 0.05712890625 +6841 0.352783203125 +6842 0.027008056640625 +6843 0.176544189453125 +6844 -0.008819580078125 +6845 -0.034820556640625 +6846 -0.046417236328125 +6847 -0.258209228515625 +6848 -0.077239990234375 +6849 -0.44244384765625 +6850 -0.0992431640625 +6851 -0.5753173828125 +6852 -0.11163330078125 +6853 -0.65203857421875 +6854 -0.109283447265625 +6855 -0.641632080078125 +6856 -0.095245361328125 +6857 -0.562164306640625 +6858 -0.077056884765625 +6859 -0.458038330078125 +6860 -0.058319091796875 +6861 -0.350555419921875 +6862 -0.04254150390625 +6863 -0.260528564453125 +6864 -0.03045654296875 +6865 -0.192108154296875 +6866 -0.02154541015625 +6867 -0.141937255859375 +6868 -0.01446533203125 +6869 -0.1021728515625 +6870 -0.007598876953125 +6871 -0.062896728515625 +6872 0.001068115234375 +6873 -0.011932373046875 +6874 0.013580322265625 +6875 0.062835693359375 +6876 0.027801513671875 +6877 0.148712158203125 +6878 0.043060302734375 +6879 0.241729736328125 +6880 0.06060791015625 +6881 0.34912109375 +6882 0.078216552734375 +6883 0.457305908203125 +6884 0.092132568359375 +6885 0.54388427734375 +6886 0.096343994140625 +6887 0.5728759765625 +6888 0.084564208984375 +6889 0.506591796875 +6890 0.057861328125 +6891 0.351226806640625 +6892 0.02294921875 +6893 0.146514892578125 +6894 -0.011322021484375 +6895 -0.05523681640625 +6896 -0.038604736328125 +6897 -0.21624755859375 +6898 -0.058624267578125 +6899 -0.334930419921875 +6900 -0.0699462890625 +6901 -0.402984619140625 +6902 -0.07611083984375 +6903 -0.4412841796875 +6904 -0.084869384765625 +6905 -0.49578857421875 +6906 -0.095184326171875 +6907 -0.5601806640625 +6908 -0.1014404296875 +6909 -0.600738525390625 +6910 -0.09808349609375 +6911 -0.584228515625 +6912 -0.0802001953125 +6913 -0.47930908203125 +6914 -0.04736328125 +6915 -0.27935791015625 +6916 -0.00390625 +6917 -0.0089111328125 +6918 0.04083251953125 +6919 0.268798828125 +6920 0.0765380859375 +6921 0.482818603515625 +6922 0.098724365234375 +6923 0.60369873046875 +6924 0.109588623046875 +6925 0.650421142578125 +6926 0.11444091796875 +6927 0.66400146484375 +6928 0.112762451171875 +6929 0.6414794921875 +6930 0.103118896484375 +6931 0.572540283203125 +6932 0.091156005859375 +6933 0.498138427734375 +6934 0.0799560546875 +6935 0.439453125 +6936 0.066925048828125 +6937 0.375518798828125 +6938 0.048004150390625 +6939 0.274505615234375 +6940 0.019775390625 +6941 0.1087646484375 +6942 -0.01434326171875 +6943 -0.099395751953125 +6944 -0.0496826171875 +6945 -0.3182373046875 +6946 -0.086090087890625 +6947 -0.5489501953125 +6948 -0.120880126953125 +6949 -0.7738037109375 +6950 -0.14666748046875 +6951 -0.86383056640625 +6952 -0.15875244140625 +6953 -0.870391845703125 +6954 -0.15948486328125 +6955 -0.86895751953125 +6956 -0.150665283203125 +6957 -0.861053466796875 +6958 -0.1300048828125 +6959 -0.765869140625 +6960 -0.096099853515625 +6961 -0.5301513671875 +6962 -0.050079345703125 +6963 -0.214691162109375 +6964 0.001983642578125 +6965 0.137359619140625 +6966 0.0528564453125 +6967 0.474822998046875 +6968 0.097442626953125 +6969 0.76239013671875 +6970 0.131805419921875 +6971 0.867462158203125 +6972 0.155731201171875 +6973 0.870361328125 +6974 0.16741943359375 +6975 0.86480712890625 +6976 0.167449951171875 +6977 0.831817626953125 +6978 0.159027099609375 +6979 0.677581787109375 +6980 0.142852783203125 +6981 0.495880126953125 +6982 0.121429443359375 +6983 0.30767822265625 +6984 0.0950927734375 +6985 0.116180419921875 +6986 0.05963134765625 +6987 -0.110748291015625 +6988 0.01422119140625 +6989 -0.381805419921875 +6990 -0.03509521484375 +6991 -0.6572265625 +6992 -0.0799560546875 +6993 -0.857421875 +6994 -0.114349365234375 +6995 -0.870391845703125 +6996 -0.137115478515625 +6997 -0.870391845703125 +6998 -0.1517333984375 +6999 -0.86444091796875 +7000 -0.162872314453125 +7001 -0.85723876953125 +7002 -0.167877197265625 +7003 -0.790008544921875 +7004 -0.15924072265625 +7005 -0.62847900390625 +7006 -0.136474609375 +7007 -0.3956298828125 +7008 -0.10400390625 +7009 -0.126708984375 +7010 -0.06561279296875 +7011 0.150115966796875 +7012 -0.02294921875 +7013 0.424041748046875 +7014 0.020233154296875 +7015 0.670623779296875 +7016 0.058563232421875 +7017 0.854522705078125 +7018 0.089447021484375 +7019 0.866485595703125 +7020 0.11065673828125 +7021 0.86920166015625 +7022 0.124481201171875 +7023 0.8653564453125 +7024 0.132598876953125 +7025 0.857147216796875 +7026 0.13446044921875 +7027 0.766845703125 +7028 0.130645751953125 +7029 0.628509521484375 +7030 0.1201171875 +7031 0.462127685546875 +7032 0.1063232421875 +7033 0.297210693359375 +7034 0.09088134765625 +7035 0.14862060546875 +7036 0.0706787109375 +7037 -0.00537109375 +7038 0.04681396484375 +7039 -0.15753173828125 +7040 0.01885986328125 +7041 -0.31304931640625 +7042 -0.01495361328125 +7043 -0.48876953125 +7044 -0.048126220703125 +7045 -0.6416015625 +7046 -0.077178955078125 +7047 -0.751373291015625 +7048 -0.105133056640625 +7049 -0.84619140625 +7050 -0.129852294921875 +7051 -0.861297607421875 +7052 -0.146697998046875 +7053 -0.863250732421875 +7054 -0.151275634765625 +7055 -0.856597900390625 +7056 -0.1451416015625 +7057 -0.7498779296875 +7058 -0.1361083984375 +7059 -0.624542236328125 +7060 -0.12115478515625 +7061 -0.47808837890625 +7062 -0.092315673828125 +7063 -0.253387451171875 +7064 -0.055816650390625 +7065 0.003692626953125 +7066 -0.021026611328125 +7067 0.2257080078125 +7068 0.013641357421875 +7069 0.427154541015625 +7070 0.052490234375 +7071 0.643218994140625 +7072 0.094085693359375 +7073 0.855926513671875 +7074 0.130462646484375 +7075 0.870361328125 +7076 0.154754638671875 +7077 0.870361328125 +7078 0.167877197265625 +7079 0.862762451171875 +7080 0.16937255859375 +7081 0.79669189453125 +7082 0.157867431640625 +7083 0.595794677734375 +7084 0.137298583984375 +7085 0.362152099609375 +7086 0.111419677734375 +7087 0.1270751953125 +7088 0.083099365234375 +7089 -0.086944580078125 +7090 0.052642822265625 +7091 -0.2784423828125 +7092 0.015350341796875 +7093 -0.484832763671875 +7094 -0.031280517578125 +7095 -0.729583740234375 +7096 -0.080291748046875 +7097 -0.86688232421875 +7098 -0.123016357421875 +7099 -0.870391845703125 +7100 -0.158660888671875 +7101 -0.86859130859375 +7102 -0.186859130859375 +7103 -0.86279296875 +7104 -0.20263671875 +7105 -0.817962646484375 +7106 -0.199737548828125 +7107 -0.6116943359375 +7108 -0.177154541015625 +7109 -0.3128662109375 +7110 -0.139434814453125 +7111 0.039398193359375 +7112 -0.089263916015625 +7113 0.422821044921875 +7114 -0.031158447265625 +7115 0.805145263671875 +7116 0.025543212890625 +7117 0.870361328125 +7118 0.07305908203125 +7119 0.870361328125 +7120 0.1097412109375 +7121 0.860015869140625 +7122 0.134490966796875 +7123 0.727935791015625 +7124 0.146453857421875 +7125 0.48114013671875 +7126 0.148834228515625 +7127 0.2059326171875 +7128 0.14459228515625 +7129 -0.06103515625 +7130 0.135009765625 +7131 -0.29913330078125 +7132 0.1180419921875 +7133 -0.516204833984375 +7134 0.091583251953125 +7135 -0.7252197265625 +7136 0.0589599609375 +7137 -0.85980224609375 +7138 0.02484130859375 +7139 -0.870391845703125 +7140 -0.0067138671875 +7141 -0.870391845703125 +7142 -0.029052734375 +7143 -0.858062744140625 +7144 -0.04150390625 +7145 -0.673004150390625 +7146 -0.051116943359375 +7147 -0.42694091796875 +7148 -0.0638427734375 +7149 -0.2100830078125 +7150 -0.07928466796875 +7151 -0.0362548828125 +7152 -0.093353271484375 +7153 0.10943603515625 +7154 -0.10321044921875 +7155 0.23516845703125 +7156 -0.1031494140625 +7157 0.373687744140625 +7158 -0.093353271484375 +7159 0.517791748046875 +7160 -0.08233642578125 +7161 0.602783203125 +7162 -0.06939697265625 +7163 0.635711669921875 +7164 -0.050018310546875 +7165 0.655181884765625 +7166 -0.02557373046875 +7167 0.65948486328125 +7168 0.002471923828125 +7169 0.651275634765625 +7170 0.030731201171875 +7171 0.61846923828125 +7172 0.05462646484375 +7173 0.53753662109375 +7174 0.071990966796875 +7175 0.404144287109375 +7176 0.08154296875 +7177 0.22186279296875 +7178 0.083282470703125 +7179 0.003997802734375 +7180 0.0789794921875 +7181 -0.22100830078125 +7182 0.070770263671875 +7183 -0.42449951171875 +7184 0.0609130859375 +7185 -0.579833984375 +7186 0.053955078125 +7187 -0.641876220703125 +7188 0.049346923828125 +7189 -0.6177978515625 +7190 0.0406494140625 +7191 -0.575531005859375 +7192 0.027587890625 +7193 -0.526336669921875 +7194 0.015838623046875 +7195 -0.42645263671875 +7196 0.008544921875 +7197 -0.2581787109375 +7198 0.002197265625 +7199 -0.068695068359375 +7200 -0.0068359375 +7201 0.09222412109375 +7202 -0.016387939453125 +7203 0.232147216796875 +7204 -0.025177001953125 +7205 0.3509521484375 +7206 -0.036163330078125 +7207 0.410064697265625 +7208 -0.05230712890625 +7209 0.372955322265625 +7210 -0.071441650390625 +7211 0.2554931640625 +7212 -0.08819580078125 +7213 0.10711669921875 +7214 -0.10064697265625 +7215 -0.052886962890625 +7216 -0.105194091796875 +7217 -0.186279296875 +7218 -0.096282958984375 +7219 -0.23291015625 +7220 -0.076507568359375 +7221 -0.209442138671875 +7222 -0.053009033203125 +7223 -0.174163818359375 +7224 -0.026885986328125 +7225 -0.126739501953125 +7226 0.002593994140625 +7227 -0.048126220703125 +7228 0.03228759765625 +7229 0.0426025390625 +7230 0.057159423828125 +7231 0.10748291015625 +7232 0.07574462890625 +7233 0.1409912109375 +7234 0.0928955078125 +7235 0.19708251953125 +7236 0.107879638671875 +7237 0.273651123046875 +7238 0.114959716796875 +7239 0.31768798828125 +7240 0.1153564453125 +7241 0.341094970703125 +7242 0.11181640625 +7243 0.368011474609375 +7244 0.10211181640625 +7245 0.37249755859375 +7246 0.081298828125 +7247 0.30072021484375 +7248 0.050140380859375 +7249 0.1517333984375 +7250 0.0157470703125 +7251 -0.01470947265625 +7252 -0.019805908203125 +7253 -0.1883544921875 +7254 -0.055938720703125 +7255 -0.372711181640625 +7256 -0.08612060546875 +7257 -0.51397705078125 +7258 -0.105377197265625 +7259 -0.57177734375 +7260 -0.112335205078125 +7261 -0.53948974609375 +7262 -0.1083984375 +7263 -0.43511962890625 +7264 -0.097198486328125 +7265 -0.2962646484375 +7266 -0.0826416015625 +7267 -0.161102294921875 +7268 -0.066314697265625 +7269 -0.0435791015625 +7270 -0.048126220703125 +7271 0.060394287109375 +7272 -0.030029296875 +7273 0.13665771484375 +7274 -0.01422119140625 +7275 0.170135498046875 +7276 -0.0009765625 +7277 0.16552734375 +7278 0.01251220703125 +7279 0.15728759765625 +7280 0.025970458984375 +7281 0.150787353515625 +7282 0.0361328125 +7283 0.12200927734375 +7284 0.043304443359375 +7285 0.080108642578125 +7286 0.049591064453125 +7287 0.05126953125 +7288 0.057403564453125 +7289 0.062896728515625 +7290 0.06414794921875 +7291 0.09271240234375 +7292 0.064727783203125 +7293 0.092987060546875 +7294 0.060760498046875 +7295 0.07855224609375 +7296 0.05401611328125 +7297 0.06427001953125 +7298 0.043243408203125 +7299 0.0347900390625 +7300 0.02874755859375 +7301 -0.01171875 +7302 0.01312255859375 +7303 -0.056060791015625 +7304 0.001434326171875 +7305 -0.055511474609375 +7306 -0.00567626953125 +7307 -0.010467529296875 +7308 -0.013153076171875 +7309 0.02508544921875 +7310 -0.023040771484375 +7311 0.025665283203125 +7312 -0.032135009765625 +7313 0.017333984375 +7314 -0.039825439453125 +7315 0.00189208984375 +7316 -0.047027587890625 +7317 -0.03173828125 +7318 -0.052337646484375 +7319 -0.071502685546875 +7320 -0.05767822265625 +7321 -0.13543701171875 +7322 -0.06280517578125 +7323 -0.219970703125 +7324 -0.065399169921875 +7325 -0.300506591796875 +7326 -0.06573486328125 +7327 -0.376312255859375 +7328 -0.061065673828125 +7329 -0.416107177734375 +7330 -0.04681396484375 +7331 -0.371124267578125 +7332 -0.023651123046875 +7333 -0.242279052734375 +7334 0.003692626953125 +7335 -0.069732666015625 +7336 0.03253173828125 +7337 0.125640869140625 +7338 0.059173583984375 +7339 0.31268310546875 +7340 0.0794677734375 +7341 0.45501708984375 +7342 0.0933837890625 +7343 0.554779052734375 +7344 0.100677490234375 +7345 0.61065673828125 +7346 0.10009765625 +7347 0.610931396484375 +7348 0.0892333984375 +7349 0.531463623046875 +7350 0.0699462890625 +7351 0.3883056640625 +7352 0.048095703125 +7353 0.23468017578125 +7354 0.026641845703125 +7355 0.095245361328125 +7356 0.008697509765625 +7357 -0.00396728515625 +7358 -0.00384521484375 +7359 -0.04852294921875 +7360 -0.01226806640625 +7361 -0.055145263671875 +7362 -0.02154541015625 +7363 -0.0758056640625 +7364 -0.03424072265625 +7365 -0.138702392578125 +7366 -0.046417236328125 +7367 -0.209197998046875 +7368 -0.05804443359375 +7369 -0.289031982421875 +7370 -0.069061279296875 +7371 -0.37884521484375 +7372 -0.07708740234375 +7373 -0.456329345703125 +7374 -0.0816650390625 +7375 -0.51641845703125 +7376 -0.07879638671875 +7377 -0.519287109375 +7378 -0.0679931640625 +7379 -0.458251953125 +7380 -0.054901123046875 +7381 -0.384796142578125 +7382 -0.04241943359375 +7383 -0.323699951171875 +7384 -0.0302734375 +7385 -0.269287109375 +7386 -0.01611328125 +7387 -0.1951904296875 +7388 -0.000152587890625 +7389 -0.100006103515625 +7390 0.014495849609375 +7391 -0.01055908203125 +7392 0.03070068359375 +7393 0.1033935546875 +7394 0.048980712890625 +7395 0.24908447265625 +7396 0.06365966796875 +7397 0.373199462890625 +7398 0.072845458984375 +7399 0.45806884765625 +7400 0.077392578125 +7401 0.511474609375 +7402 0.080718994140625 +7403 0.565399169921875 +7404 0.082061767578125 +7405 0.61138916015625 +7406 0.075439453125 +7407 0.5897216796875 +7408 0.06011962890625 +7409 0.4906005859375 +7410 0.0382080078125 +7411 0.33148193359375 +7412 0.013702392578125 +7413 0.147796630859375 +7414 -0.00872802734375 +7415 -0.01873779296875 +7416 -0.02593994140625 +7417 -0.140289306640625 +7418 -0.03509521484375 +7419 -0.191986083984375 +7420 -0.037109375 +7421 -0.184295654296875 +7422 -0.0364990234375 +7423 -0.161834716796875 +7424 -0.03753662109375 +7425 -0.166595458984375 +7426 -0.039764404296875 +7427 -0.19390869140625 +7428 -0.041229248046875 +7429 -0.22442626953125 +7430 -0.044189453125 +7431 -0.279754638671875 +7432 -0.046722412109375 +7433 -0.3389892578125 +7434 -0.04425048828125 +7435 -0.3543701171875 +7436 -0.039215087890625 +7437 -0.348175048828125 +7438 -0.032440185546875 +7439 -0.32598876953125 +7440 -0.021209716796875 +7441 -0.2581787109375 +7442 -0.005279541015625 +7443 -0.139801025390625 +7444 0.013641357421875 +7445 0.014617919921875 +7446 0.029327392578125 +7447 0.144378662109375 +7448 0.038818359375 +7449 0.221038818359375 +7450 0.044647216796875 +7451 0.27069091796875 +7452 0.046875 +7453 0.294036865234375 +7454 0.047607421875 +7455 0.311767578125 +7456 0.048370361328125 +7457 0.339141845703125 +7458 0.047332763671875 +7459 0.360260009765625 +7460 0.0433349609375 +7461 0.360504150390625 +7462 0.03448486328125 +7463 0.308380126953125 +7464 0.01959228515625 +7465 0.18170166015625 +7466 0.00079345703125 +7467 0.0047607421875 +7468 -0.018096923828125 +7469 -0.17559814453125 +7470 -0.033477783203125 +7471 -0.3143310546875 +7472 -0.041900634765625 +7473 -0.36785888671875 +7474 -0.0450439453125 +7475 -0.36248779296875 +7476 -0.0460205078125 +7477 -0.343536376953125 +7478 -0.0440673828125 +7479 -0.3018798828125 +7480 -0.038726806640625 +7481 -0.231414794921875 +7482 -0.029022216796875 +7483 -0.117645263671875 +7484 -0.017425537109375 +7485 0.007049560546875 +7486 -0.008026123046875 +7487 0.087982177734375 +7488 -3.0517578125e-05 +7489 0.13946533203125 +7490 0.0072021484375 +7491 0.17425537109375 +7492 0.013092041015625 +7493 0.188201904296875 +7494 0.016632080078125 +7495 0.171234130859375 +7496 0.017242431640625 +7497 0.118438720703125 +7498 0.01666259765625 +7499 0.05706787109375 +7500 0.01483154296875 +7501 -0.010711669921875 +7502 0.011138916015625 +7503 -0.0914306640625 +7504 0.007110595703125 +7505 -0.162322998046875 +7506 0.004791259765625 +7507 -0.194549560546875 +7508 0.00701904296875 +7509 -0.1492919921875 +7510 0.01422119140625 +7511 -0.02166748046875 +7512 0.02191162109375 +7513 0.124053955078125 +7514 0.02471923828125 +7515 0.211151123046875 +7516 0.022918701171875 +7517 0.240447998046875 +7518 0.018951416015625 +7519 0.242218017578125 +7520 0.013702392578125 +7521 0.2257080078125 +7522 0.007659912109375 +7523 0.194366455078125 +7524 -0.001312255859375 +7525 0.115509033203125 +7526 -0.011322021484375 +7527 0.0128173828125 +7528 -0.0179443359375 +7529 -0.053802490234375 +7530 -0.02301025390625 +7531 -0.110626220703125 +7532 -0.02947998046875 +7533 -0.199493408203125 +7534 -0.035552978515625 +7535 -0.29437255859375 +7536 -0.036712646484375 +7537 -0.33221435546875 +7538 -0.03070068359375 +7539 -0.27972412109375 +7540 -0.021148681640625 +7541 -0.185333251953125 +7542 -0.013916015625 +7543 -0.128204345703125 +7544 -0.00970458984375 +7545 -0.115692138671875 +7546 -0.006439208984375 +7547 -0.116455078125 +7548 -0.002532958984375 +7549 -0.105926513671875 +7550 0.00396728515625 +7551 -0.053955078125 +7552 0.01361083984375 +7553 0.048797607421875 +7554 0.0230712890625 +7555 0.157318115234375 +7556 0.027984619140625 +7557 0.212005615234375 +7558 0.0286865234375 +7559 0.218475341796875 +7560 0.029541015625 +7561 0.23724365234375 +7562 0.03326416015625 +7563 0.30535888671875 +7564 0.03692626953125 +7565 0.38128662109375 +7566 0.03631591796875 +7567 0.404449462890625 +7568 0.032989501953125 +7569 0.3944091796875 +7570 0.02978515625 +7571 0.3885498046875 +7572 0.025146484375 +7573 0.362640380859375 +7574 0.016082763671875 +7575 0.27362060546875 +7576 0.00244140625 +7577 0.11712646484375 +7578 -0.01190185546875 +7579 -0.054901123046875 +7580 -0.023101806640625 +7581 -0.19085693359375 +7582 -0.03076171875 +7583 -0.28570556640625 +7584 -0.034820556640625 +7585 -0.339263916015625 +7586 -0.037200927734375 +7587 -0.3775634765625 +7588 -0.041168212890625 +7589 -0.445709228515625 +7590 -0.046173095703125 +7591 -0.535064697265625 +7592 -0.05108642578125 +7593 -0.629058837890625 +7594 -0.0538330078125 +7595 -0.697601318359375 +7596 -0.05194091796875 +7597 -0.70391845703125 +7598 -0.045135498046875 +7599 -0.6424560546875 +7600 -0.031982421875 +7601 -0.491241455078125 +7602 -0.013702392578125 +7603 -0.265716552734375 +7604 0.005401611328125 +7605 -0.023712158203125 +7606 0.022857666015625 +7607 0.201751708984375 +7608 0.0361328125 +7609 0.375823974609375 +7610 0.044219970703125 +7611 0.485076904296875 +7612 0.049957275390625 +7613 0.56884765625 +7614 0.053924560546875 +7615 0.634765625 +7616 0.05291748046875 +7617 0.63763427734375 +7618 0.04620361328125 +7619 0.5660400390625 +7620 0.03759765625 +7621 0.4720458984375 +7622 0.030914306640625 +7623 0.40692138671875 +7624 0.02679443359375 +7625 0.3778076171875 +7626 0.0247802734375 +7627 0.376953125 +7628 0.022674560546875 +7629 0.371978759765625 +7630 0.016937255859375 +7631 0.313140869140625 +7632 0.006500244140625 +7633 0.184417724609375 +7634 -0.0067138671875 +7635 0.011199951171875 +7636 -0.02008056640625 +7637 -0.171051025390625 +7638 -0.031829833984375 +7639 -0.33740234375 +7640 -0.040863037109375 +7641 -0.47198486328125 +7642 -0.04620361328125 +7643 -0.560394287109375 +7644 -0.04632568359375 +7645 -0.58056640625 +7646 -0.042388916015625 +7647 -0.54754638671875 +7648 -0.037872314453125 +7649 -0.508575439453125 +7650 -0.0325927734375 +7651 -0.459503173828125 +7652 -0.026214599609375 +7653 -0.394378662109375 +7654 -0.0216064453125 +7655 -0.35260009765625 +7656 -0.017242431640625 +7657 -0.31170654296875 +7658 -0.00787353515625 +7659 -0.197418212890625 +7660 0.00653076171875 +7661 -0.007965087890625 +7662 0.022369384765625 +7663 0.207489013671875 +7664 0.036773681640625 +7665 0.409210205078125 +7666 0.0479736328125 +7667 0.57208251953125 +7668 0.053863525390625 +7669 0.66595458984375 +7670 0.052154541015625 +7671 0.65875244140625 +7672 0.044189453125 +7673 0.56744384765625 +7674 0.032867431640625 +7675 0.431396484375 +7676 0.02142333984375 +7677 0.29443359375 +7678 0.011810302734375 +7679 0.182464599609375 +7680 0.0023193359375 +7681 0.06365966796875 +7682 -0.00787353515625 +7683 -0.075958251953125 +7684 -0.0167236328125 +7685 -0.189422607421875 +7686 -0.02374267578125 +7687 -0.271942138671875 +7688 -0.029449462890625 +7689 -0.342529296875 +7690 -0.032196044921875 +7691 -0.364166259765625 +7692 -0.031494140625 +7693 -0.327239990234375 +7694 -0.029144287109375 +7695 -0.2769775390625 +7696 -0.026824951171875 +7697 -0.253692626953125 +7698 -0.024078369140625 +7699 -0.24365234375 +7700 -0.019134521484375 +7701 -0.1983642578125 +7702 -0.01214599609375 +7703 -0.116241455078125 +7704 -0.004913330078125 +7705 -0.036834716796875 +7706 0.0020751953125 +7707 0.034881591796875 +7708 0.00830078125 +7709 0.09124755859375 +7710 0.01263427734375 +7711 0.10888671875 +7712 0.016387939453125 +7713 0.125518798828125 +7714 0.020050048828125 +7715 0.15771484375 +7716 0.022430419921875 +7717 0.17828369140625 +7718 0.022796630859375 +7719 0.17108154296875 +7720 0.02093505859375 +7721 0.129974365234375 +7722 0.0179443359375 +7723 0.082427978515625 +7724 0.013885498046875 +7725 0.027679443359375 +7726 0.007659912109375 +7727 -0.065643310546875 +7728 0.000946044921875 +7729 -0.15936279296875 +7730 -0.004425048828125 +7731 -0.21307373046875 +7732 -0.008636474609375 +7733 -0.234649658203125 +7734 -0.010528564453125 +7735 -0.2001953125 +7736 -0.01031494140625 +7737 -0.119171142578125 +7738 -0.0091552734375 +7739 -0.024749755859375 +7740 -0.00677490234375 +7741 0.085784912109375 +7742 -0.0045166015625 +7743 0.178131103515625 +7744 -0.003753662109375 +7745 0.215576171875 +7746 -0.003936767578125 +7747 0.211456298828125 +7748 -0.004669189453125 +7749 0.17523193359375 +7750 -0.005157470703125 +7751 0.128753662109375 +7752 -0.004302978515625 +7753 0.1019287109375 +7754 -0.003021240234375 +7755 0.0743408203125 +7756 -0.0015869140625 +7757 0.04327392578125 +7758 0.0009765625 +7759 0.038177490234375 +7760 0.00518798828125 +7761 0.076263427734375 +7762 0.01025390625 +7763 0.14105224609375 +7764 0.014190673828125 +7765 0.186431884765625 +7766 0.0159912109375 +7767 0.188812255859375 +7768 0.01519775390625 +7769 0.1390380859375 +7770 0.011932373046875 +7771 0.041778564453125 +7772 0.00714111328125 +7773 -0.079437255859375 +7774 0.00103759765625 +7775 -0.219390869140625 +7776 -0.005859375 +7777 -0.367828369140625 +7778 -0.012298583984375 +7779 -0.494873046875 +7780 -0.01641845703125 +7781 -0.556243896484375 +7782 -0.01641845703125 +7783 -0.508697509765625 +7784 -0.01312255859375 +7785 -0.3756103515625 +7786 -0.0089111328125 +7787 -0.218902587890625 +7788 -0.004730224609375 +7789 -0.063751220703125 +7790 -0.0003662109375 +7791 0.091552734375 +7792 0.00384521484375 +7793 0.23602294921875 +7794 0.00689697265625 +7795 0.342987060546875 +7796 0.008148193359375 +7797 0.39520263671875 +7798 0.007537841796875 +7799 0.389373779296875 +7800 0.005035400390625 +7801 0.324249267578125 +7802 0.0015869140625 +7803 0.224090576171875 +7804 -0.00140380859375 +7805 0.124267578125 +7806 -0.0035400390625 +7807 0.037078857421875 +7808 -0.003814697265625 +7809 -0.010101318359375 +7810 -0.00238037109375 +7811 -0.019439697265625 +7812 -0.000640869140625 +7813 -0.022796630859375 +7814 0.00201416015625 +7815 -0.001556396484375 +7816 0.005950927734375 +7817 0.056304931640625 +7818 0.00933837890625 +7819 0.106719970703125 +7820 0.009979248046875 +7821 0.096893310546875 +7822 0.00848388671875 +7823 0.042694091796875 +7824 0.006317138671875 +7825 -0.018035888671875 +7826 0.003875732421875 +7827 -0.07586669921875 +7828 0.00164794921875 +7829 -0.11944580078125 +7830 -0.000762939453125 +7831 -0.15972900390625 +7832 -0.0035400390625 +7833 -0.202606201171875 +7834 -0.006591796875 +7835 -0.24859619140625 +7836 -0.010162353515625 +7837 -0.30517578125 +7838 -0.0137939453125 +7839 -0.36212158203125 +7840 -0.016265869140625 +7841 -0.39141845703125 +7842 -0.016021728515625 +7843 -0.35528564453125 +7844 -0.01287841796875 +7845 -0.249969482421875 +7846 -0.0074462890625 +7847 -0.092864990234375 +7848 -0.000762939453125 +7849 0.08905029296875 +7850 0.004730224609375 +7851 0.2352294921875 +7852 0.00799560546875 +7853 0.318817138671875 +7854 0.009796142578125 +7855 0.358642578125 +7856 0.009796142578125 +7857 0.347747802734375 +7858 0.007965087890625 +7859 0.28564453125 +7860 0.00628662109375 +7861 0.223175048828125 +7862 0.00616455078125 +7863 0.196746826171875 +7864 0.0064697265625 +7865 0.179840087890625 +7866 0.006500244140625 +7867 0.155548095703125 +7868 0.00726318359375 +7869 0.151214599609375 +7870 0.00836181640625 +7871 0.156951904296875 +7872 0.008087158203125 +7873 0.13177490234375 +7874 0.007415771484375 +7875 0.100799560546875 +7876 0.007232666015625 +7877 0.087127685546875 +7878 0.006103515625 +7879 0.05487060546875 +7880 0.00347900390625 +7881 -0.009002685546875 +7882 -0.00054931640625 +7883 -0.10400390625 +7884 -0.005950927734375 +7885 -0.229400634765625 +7886 -0.01153564453125 +7887 -0.35552978515625 +7888 -0.015655517578125 +7889 -0.441925048828125 +7890 -0.01763916015625 +7891 -0.473846435546875 +7892 -0.01800537109375 +7893 -0.464813232421875 +7894 -0.016876220703125 +7895 -0.419097900390625 +7896 -0.01416015625 +7897 -0.334320068359375 +7898 -0.010467529296875 +7899 -0.227935791015625 +7900 -0.0067138671875 +7901 -0.12347412109375 +7902 -0.003173828125 +7903 -0.02764892578125 +7904 0.000885009765625 +7905 0.077667236328125 +7906 0.006256103515625 +7907 0.2132568359375 +7908 0.01336669921875 +7909 0.38885498046875 +7910 0.021331787109375 +7911 0.582794189453125 +7912 0.0277099609375 +7913 0.734039306640625 +7914 0.030731201171875 +7915 0.800140380859375 +7916 0.0302734375 +7917 0.7783203125 +7918 0.02618408203125 +7919 0.6651611328125 +7920 0.018402099609375 +7921 0.45965576171875 +7922 0.008453369140625 +7923 0.199188232421875 +7924 -0.00103759765625 +7925 -0.050689697265625 +7926 -0.007843017578125 +7927 -0.23297119140625 +7928 -0.01129150390625 +7929 -0.33013916015625 +7930 -0.012481689453125 +7931 -0.368408203125 +7932 -0.012664794921875 +7933 -0.378936767578125 +7934 -0.01251220703125 +7935 -0.376983642578125 +7936 -0.012603759765625 +7937 -0.37969970703125 +7938 -0.013092041015625 +7939 -0.391510009765625 +7940 -0.013519287109375 +7941 -0.385345458984375 +7942 -0.013458251953125 +7943 -0.3419189453125 +7944 -0.012908935546875 +7945 -0.28289794921875 +7946 -0.0120849609375 +7947 -0.251617431640625 +7948 -0.011077880859375 +7949 -0.266143798828125 +7950 -0.00946044921875 +7951 -0.273345947265625 +7952 -0.006866455078125 +7953 -0.216796875 +7954 -0.003662109375 +7955 -0.128265380859375 +7956 -0.00048828125 +7957 -0.068145751953125 +7958 0.00244140625 +7959 -0.0430908203125 +7960 0.00518798828125 +7961 -0.024444580078125 +7962 0.00787353515625 +7963 0.020721435546875 +7964 0.010589599609375 +7965 0.124481201171875 +7966 0.01300048828125 +7967 0.25787353515625 +7968 0.014678955078125 +7969 0.379119873046875 +7970 0.015533447265625 +7971 0.47991943359375 +7972 0.015350341796875 +7973 0.5281982421875 +7974 0.014068603515625 +7975 0.511138916015625 +7976 0.011962890625 +7977 0.456207275390625 +7978 0.009490966796875 +7979 0.407470703125 +7980 0.00689697265625 +7981 0.383758544921875 +7982 0.00408935546875 +7983 0.35687255859375 +7984 0.001129150390625 +7985 0.31182861328125 +7986 -0.00177001953125 +7987 0.250885009765625 +7988 -0.00457763671875 +7989 0.1654052734375 +7990 -0.00732421875 +7991 0.035247802734375 +7992 -0.00994873046875 +7993 -0.142059326171875 +7994 -0.012176513671875 +7995 -0.33563232421875 +7996 -0.013885498046875 +7997 -0.5345458984375 +7998 -0.014923095703125 +7999 -0.72186279296875 +8000 -0.01483154296875 +8001 -0.836669921875 +8002 -0.0133056640625 +8003 -0.8326416015625 +8004 -0.0106201171875 +8005 -0.7296142578125 +8006 -0.00738525390625 +8007 -0.582550048828125 +8008 -0.00408935546875 +8009 -0.440093994140625 +8010 -0.001007080078125 +8011 -0.324310302734375 +8012 0.001983642578125 +8013 -0.20147705078125 +8014 0.0050048828125 +8015 -0.044647216796875 +8016 0.007598876953125 +8017 0.103973388671875 +8018 0.009368896484375 +8019 0.202392578125 +8020 0.010406494140625 +8021 0.264495849609375 +8022 0.011077880859375 +8023 0.338897705078125 +8024 0.01153564453125 +8025 0.443817138671875 +8026 0.01153564453125 +8027 0.545074462890625 +8028 0.01092529296875 +8029 0.6173095703125 +8030 0.00970458984375 +8031 0.6524658203125 +8032 0.008087158203125 +8033 0.66339111328125 +8034 0.006195068359375 +8035 0.6561279296875 +8036 0.00396728515625 +8037 0.606781005859375 +8038 0.001373291015625 +8039 0.501190185546875 +8040 -0.0013427734375 +8041 0.352783203125 +8042 -0.003997802734375 +8043 0.176544189453125 +8044 -0.006561279296875 +8045 -0.034820556640625 +8046 -0.0087890625 +8047 -0.258209228515625 +8048 -0.01025390625 +8049 -0.44244384765625 +8050 -0.010894775390625 +8051 -0.5753173828125 +8052 -0.010711669921875 +8053 -0.65203857421875 +8054 -0.009521484375 +8055 -0.641632080078125 +8056 -0.007537841796875 +8057 -0.562164306640625 +8058 -0.005218505859375 +8059 -0.458038330078125 +8060 -0.0028076171875 +8061 -0.350555419921875 +8062 -0.00054931640625 +8063 -0.260528564453125 +8064 0.00140380859375 +8065 -0.192108154296875 +8066 0.003021240234375 +8067 -0.141937255859375 +8068 0.0042724609375 +8069 -0.1021728515625 +8070 0.005218505859375 +8071 -0.062896728515625 +8072 0.005950927734375 +8073 -0.011932373046875 +8074 0.00653076171875 +8075 0.062835693359375 +8076 0.00689697265625 +8077 0.148712158203125 +8078 0.00701904296875 +8079 0.241729736328125 +8080 0.006988525390625 +8081 0.34912109375 +8082 0.006744384765625 +8083 0.457305908203125 +8084 0.006195068359375 +8085 0.54388427734375 +8086 0.005126953125 +8087 0.5728759765625 +8088 0.0032958984375 +8089 0.506591796875 +8090 0.000823974609375 +8091 0.351226806640625 +8092 -0.001861572265625 +8093 0.146514892578125 +8094 -0.004302978515625 +8095 -0.05523681640625 +8096 -0.006134033203125 +8097 -0.21624755859375 +8098 -0.007354736328125 +8099 -0.334930419921875 +8100 -0.00787353515625 +8101 -0.402984619140625 +8102 -0.00787353515625 +8103 -0.4412841796875 +8104 -0.00775146484375 +8105 -0.49578857421875 +8106 -0.007476806640625 +8107 -0.5601806640625 +8108 -0.0068359375 +8109 -0.600738525390625 +8110 -0.005645751953125 +8111 -0.584228515625 +8112 -0.003692626953125 +8113 -0.47930908203125 +8114 -0.001007080078125 +8115 -0.27935791015625 +8116 0.00213623046875 +8117 -0.0089111328125 +8118 0.005157470703125 +8119 0.268798828125 +8120 0.0074462890625 +8121 0.482818603515625 +8122 0.008758544921875 +8123 0.60369873046875 +8124 0.009246826171875 +8125 0.650421142578125 +8126 0.009246826171875 +8127 0.66400146484375 +8128 0.008758544921875 +8129 0.6414794921875 +8130 0.007720947265625 +8131 0.572540283203125 +8132 0.006500244140625 +8133 0.498138427734375 +8134 0.005279541015625 +8135 0.439453125 +8136 0.00396728515625 +8137 0.375518798828125 +8138 0.0023193359375 +8139 0.274505615234375 +8140 0.00018310546875 +8141 0.1087646484375 +8142 -0.002197265625 +8143 -0.099395751953125 +8144 -0.004547119140625 +8145 -0.3182373046875 +8146 -0.0068359375 +8147 -0.5489501953125 +8148 -0.008880615234375 +8149 -0.7738037109375 +8150 -0.01025390625 +8151 -0.86383056640625 +8152 -0.010711669921875 +8153 -0.870391845703125 +8154 -0.010406494140625 +8155 -0.86895751953125 +8156 -0.00946044921875 +8157 -0.861053466796875 +8158 -0.007781982421875 +8159 -0.765869140625 +8160 -0.00531005859375 +8161 -0.5301513671875 +8162 -0.00213623046875 +8163 -0.214691162109375 +8164 0.0013427734375 +8165 0.137359619140625 +8166 0.004669189453125 +8167 0.474822998046875 +8168 0.007537841796875 +8169 0.76239013671875 +8170 0.00970458984375 +8171 0.867462158203125 +8172 0.011138916015625 +8173 0.870361328125 +8174 0.01171875 +8175 0.86480712890625 +8176 0.011505126953125 +8177 0.831817626953125 +8178 0.010711669921875 +8179 0.677581787109375 +8180 0.009429931640625 +8181 0.495880126953125 +8182 0.007781982421875 +8183 0.30767822265625 +8184 0.005859375 +8185 0.116180419921875 +8186 0.00341796875 +8187 -0.110748291015625 +8188 0.00042724609375 +8189 -0.381805419921875 +8190 -0.00274658203125 +8191 -0.6572265625 +8192 -0.005462646484375 +8193 -0.857421875 +8194 -0.00732421875 +8195 -0.870391845703125 +8196 -0.00836181640625 +8197 -0.870391845703125 +8198 -0.00921630859375 +8199 -0.86444091796875 +8200 -0.010650634765625 +8201 -0.85723876953125 +8202 -0.012115478515625 +8203 -0.790008544921875 +8204 -0.012176513671875 +8205 -0.62847900390625 +8206 -0.01055908203125 +8207 -0.3956298828125 +8208 -0.007843017578125 +8209 -0.126708984375 +8210 -0.0045166015625 +8211 0.150115966796875 +8212 -0.000640869140625 +8213 0.424041748046875 +8214 0.0032958984375 +8215 0.670623779296875 +8216 0.00653076171875 +8217 0.854522705078125 +8218 0.008819580078125 +8219 0.866485595703125 +8220 0.009918212890625 +8221 0.86920166015625 +8222 0.01031494140625 +8223 0.8653564453125 +8224 0.010406494140625 +8225 0.857147216796875 +8226 0.010162353515625 +8227 0.766845703125 +8228 0.009674072265625 +8229 0.628509521484375 +8230 0.00872802734375 +8231 0.462127685546875 +8232 0.00787353515625 +8233 0.297210693359375 +8234 0.00726318359375 +8235 0.14862060546875 +8236 0.0062255859375 +8237 -0.00537109375 +8238 0.004791259765625 +8239 -0.15753173828125 +8240 0.00274658203125 +8241 -0.31304931640625 +8242 -0.0003662109375 +8243 -0.48876953125 +8244 -0.0035400390625 +8245 -0.6416015625 +8246 -0.006317138671875 +8247 -0.751373291015625 +8248 -0.009307861328125 +8249 -0.84619140625 +8250 -0.01226806640625 +8251 -0.861297607421875 +8252 -0.014404296875 +8253 -0.863250732421875 +8254 -0.014984130859375 +8255 -0.856597900390625 +8256 -0.0142822265625 +8257 -0.7498779296875 +8258 -0.01361083984375 +8259 -0.624542236328125 +8260 -0.012420654296875 +8261 -0.47808837890625 +8262 -0.009185791015625 +8263 -0.253387451171875 +8264 -0.004913330078125 +8265 0.003692626953125 +8266 -0.00115966796875 +8267 0.2257080078125 +8268 0.00250244140625 +8269 0.427154541015625 +8270 0.0069580078125 +8271 0.643218994140625 +8272 0.012054443359375 +8273 0.855926513671875 +8274 0.01654052734375 +8275 0.870361328125 +8276 0.019317626953125 +8277 0.870361328125 +8278 0.020599365234375 +8279 0.862762451171875 +8280 0.020355224609375 +8281 0.79669189453125 +8282 0.018341064453125 +8283 0.595794677734375 +8284 0.015228271484375 +8285 0.362152099609375 +8286 0.011627197265625 +8287 0.1270751953125 +8288 0.00799560546875 +8289 -0.086944580078125 +8290 0.00433349609375 +8291 -0.2784423828125 +8292 -0.000274658203125 +8293 -0.484832763671875 +8294 -0.00640869140625 +8295 -0.729583740234375 +8296 -0.012969970703125 +8297 -0.86688232421875 +8298 -0.018524169921875 +8299 -0.870391845703125 +8300 -0.02301025390625 +8301 -0.86859130859375 +8302 -0.026458740234375 +8303 -0.86279296875 +8304 -0.028106689453125 +8305 -0.817962646484375 +8306 -0.02685546875 +8307 -0.6116943359375 +8308 -0.022613525390625 +8309 -0.3128662109375 +8310 -0.01617431640625 +8311 0.039398193359375 +8312 -0.007965087890625 +8313 0.422821044921875 +8314 0.001220703125 +8315 0.805145263671875 +8316 0.009796142578125 +8317 0.870361328125 +8318 0.0164794921875 +8319 0.870361328125 +8320 0.021087646484375 +8321 0.860015869140625 +8322 0.0235595703125 +8323 0.727935791015625 +8324 0.023834228515625 +8325 0.48114013671875 +8326 0.022552490234375 +8327 0.2059326171875 +8328 0.020355224609375 +8329 -0.06103515625 +8330 0.017547607421875 +8331 -0.29913330078125 +8332 0.0137939453125 +8333 -0.516204833984375 +8334 0.0087890625 +8335 -0.7252197265625 +8336 0.00311279296875 +8337 -0.85980224609375 +8338 -0.00238037109375 +8339 -0.870391845703125 +8340 -0.00701904296875 +8341 -0.870391845703125 +8342 -0.00970458984375 +8343 -0.858062744140625 +8344 -0.010406494140625 +8345 -0.673004150390625 +8346 -0.010498046875 +8347 -0.42694091796875 +8348 -0.011077880859375 +8349 -0.2100830078125 +8350 -0.012176513671875 +8351 -0.0362548828125 +8352 -0.01318359375 +8353 0.10943603515625 +8354 -0.01361083984375 +8355 0.23516845703125 +8356 -0.012542724609375 +8357 0.373687744140625 +8358 -0.01007080078125 +8359 0.517791748046875 +8360 -0.007720947265625 +8361 0.602783203125 +8362 -0.00537109375 +8363 0.635711669921875 +8364 -0.002227783203125 +8365 0.655181884765625 +8366 0.00146484375 +8367 0.65948486328125 +8368 0.0054931640625 +8369 0.651275634765625 +8370 0.009307861328125 +8371 0.61846923828125 +8372 0.012115478515625 +8373 0.53753662109375 +8374 0.0135498046875 +8375 0.404144287109375 +8376 0.013458251953125 +8377 0.22186279296875 +8378 0.011993408203125 +8379 0.003997802734375 +8380 0.009613037109375 +8381 -0.22100830078125 +8382 0.006866455078125 +8383 -0.42449951171875 +8384 0.004302978515625 +8385 -0.579833984375 +8386 0.002960205078125 +8387 -0.641876220703125 +8388 0.002685546875 +8389 -0.6177978515625 +8390 0.001922607421875 +8391 -0.575531005859375 +8392 0.000518798828125 +8393 -0.526336669921875 +8394 -0.00030517578125 +8395 -0.42645263671875 +8396 3.0517578125e-05 +8397 -0.2581787109375 +8398 0.0006103515625 +8399 -0.068695068359375 +8400 0.00048828125 +8401 0.09222412109375 +8402 6.103515625e-05 +8403 0.232147216796875 +8404 -0.000457763671875 +8405 0.3509521484375 +8406 -0.001800537109375 +8407 0.410064697265625 +8408 -0.00469970703125 +8409 0.372955322265625 +8410 -0.008697509765625 +8411 0.2554931640625 +8412 -0.012542724609375 +8413 0.10711669921875 +8414 -0.015777587890625 +8415 -0.052886962890625 +8416 -0.017547607421875 +8417 -0.186279296875 +8418 -0.01654052734375 +8419 -0.23291015625 +8420 -0.0133056640625 +8421 -0.209442138671875 +8422 -0.009368896484375 +8423 -0.174163818359375 +8424 -0.004913330078125 +8425 -0.126739501953125 +8426 0.000274658203125 +8427 -0.048126220703125 +8428 0.00555419921875 +8429 0.0426025390625 +8430 0.0098876953125 +8431 0.10748291015625 +8432 0.012969970703125 +8433 0.1409912109375 +8434 0.0159912109375 +8435 0.19708251953125 +8436 0.018829345703125 +8437 0.273651123046875 +8438 0.020172119140625 +8439 0.31768798828125 +8440 0.02032470703125 +8441 0.341094970703125 +8442 0.019927978515625 +8443 0.368011474609375 +8444 0.0184326171875 +8445 0.37249755859375 +8446 0.0146484375 +8447 0.30072021484375 +8448 0.00885009765625 +8449 0.1517333984375 +8450 0.00274658203125 +8451 -0.01470947265625 +8452 -0.004058837890625 +8453 -0.1883544921875 +8454 -0.011932373046875 +8455 -0.372711181640625 +8456 -0.018310546875 +8457 -0.51397705078125 +8458 -0.021148681640625 +8459 -0.57177734375 +8460 -0.0201416015625 +8461 -0.53948974609375 +8462 -0.01611328125 +8463 -0.43511962890625 +8464 -0.010772705078125 +8465 -0.2962646484375 +8466 -0.00592041015625 +8467 -0.161102294921875 +8468 -0.002105712890625 +8469 -0.0435791015625 +8470 0.00103759765625 +8471 0.060394287109375 +8472 0.002899169921875 +8473 0.13665771484375 +8474 0.00286865234375 +8475 0.170135498046875 +8476 0.00128173828125 +8477 0.16552734375 +8478 -3.0517578125e-05 +8479 0.15728759765625 +8480 -0.000762939453125 +8481 0.150787353515625 +8482 -0.0020751953125 +8483 0.12200927734375 +8484 -0.003570556640625 +8485 0.080108642578125 +8486 -0.00396728515625 +8487 0.05126953125 +8488 -0.001983642578125 +8489 0.062896728515625 +8490 0.00115966796875 +8491 0.09271240234375 +8492 0.002960205078125 +8493 0.092987060546875 +8494 0.004058837890625 +8495 0.07855224609375 +8496 0.005126953125 +8497 0.06427001953125 +8498 0.005279541015625 +8499 0.0347900390625 +8500 0.00433349609375 +8501 -0.01171875 +8502 0.003173828125 +8503 -0.056060791015625 +8504 0.00390625 +8505 -0.055511474609375 +8506 0.0064697265625 +8507 -0.010467529296875 +8508 0.008148193359375 +8509 0.02508544921875 +8510 0.0076904296875 +8511 0.025665283203125 +8512 0.006439208984375 +8513 0.017333984375 +8514 0.004547119140625 +8515 0.00189208984375 +8516 0.001556396484375 +8517 -0.03173828125 +8518 -0.001861572265625 +8519 -0.071502685546875 +8520 -0.006500244140625 +8521 -0.13543701171875 +8522 -0.012115478515625 +8523 -0.219970703125 +8524 -0.01739501953125 +8525 -0.300506591796875 +8526 -0.022216796875 +8527 -0.376312255859375 +8528 -0.02496337890625 +8529 -0.416107177734375 +8530 -0.023193359375 +8531 -0.371124267578125 +8532 -0.016937255859375 +8533 -0.242279052734375 +8534 -0.008209228515625 +8535 -0.069732666015625 +8536 0.00189208984375 +8537 0.125640869140625 +8538 0.011810302734375 +8539 0.31268310546875 +8540 0.0196533203125 +8541 0.45501708984375 +8542 0.025482177734375 +8543 0.554779052734375 +8544 0.029205322265625 +8545 0.61065673828125 +8546 0.030181884765625 +8547 0.610931396484375 +8548 0.02716064453125 +8549 0.531463623046875 +8550 0.020904541015625 +8551 0.3883056640625 +8552 0.014007568359375 +8553 0.23468017578125 +8554 0.0076904296875 +8555 0.095245361328125 +8556 0.003204345703125 +8557 -0.00396728515625 +8558 0.001220703125 +8559 -0.04852294921875 +8560 0.00091552734375 +8561 -0.055145263671875 +8562 -0.000274658203125 +8563 -0.0758056640625 +8564 -0.00372314453125 +8565 -0.138702392578125 +8566 -0.0076904296875 +8567 -0.209197998046875 +8568 -0.01220703125 +8569 -0.289031982421875 +8570 -0.017303466796875 +8571 -0.37884521484375 +8572 -0.0218505859375 +8573 -0.456329345703125 +8574 -0.0255126953125 +8575 -0.51641845703125 +8576 -0.026275634765625 +8577 -0.519287109375 +8578 -0.023773193359375 +8579 -0.458251953125 +8580 -0.020538330078125 +8581 -0.384796142578125 +8582 -0.017822265625 +8583 -0.323699951171875 +8584 -0.015289306640625 +8585 -0.269287109375 +8586 -0.0115966796875 +8587 -0.1951904296875 +8588 -0.0067138671875 +8589 -0.100006103515625 +8590 -0.001983642578125 +8591 -0.01055908203125 +8592 0.0040283203125 +8593 0.1033935546875 +8594 0.01165771484375 +8595 0.24908447265625 +8596 0.018218994140625 +8597 0.373199462890625 +8598 0.0228271484375 +8599 0.45806884765625 +8600 0.025848388671875 +8601 0.511474609375 +8602 0.028900146484375 +8603 0.565399169921875 +8604 0.031494140625 +8605 0.61138916015625 +8606 0.0306396484375 +8607 0.5897216796875 +8608 0.025848388671875 +8609 0.4906005859375 +8610 0.017974853515625 +8611 0.33148193359375 +8612 0.0087890625 +8613 0.147796630859375 +8614 0.000396728515625 +8615 -0.01873779296875 +8616 -0.00579833984375 +8617 -0.140289306640625 +8618 -0.008544921875 +8619 -0.191986083984375 +8620 -0.00836181640625 +8621 -0.184295654296875 +8622 -0.0074462890625 +8623 -0.161834716796875 +8624 -0.007904052734375 +8625 -0.166595458984375 +8626 -0.00946044921875 +8627 -0.19390869140625 +8628 -0.01116943359375 +8629 -0.22442626953125 +8630 -0.01409912109375 +8631 -0.279754638671875 +8632 -0.017181396484375 +8633 -0.3389892578125 +8634 -0.018035888671875 +8635 -0.3543701171875 +8636 -0.01776123046875 +8637 -0.348175048828125 +8638 -0.0166015625 +8639 -0.32598876953125 +8640 -0.01312255859375 +8641 -0.2581787109375 +8642 -0.007080078125 +8643 -0.139801025390625 +8644 0.000762939453125 +8645 0.014617919921875 +8646 0.00732421875 +8647 0.144378662109375 +8648 0.011199951171875 +8649 0.221038818359375 +8650 0.013702392578125 +8651 0.27069091796875 +8652 0.014892578125 +8653 0.294036865234375 +8654 0.01580810546875 +8655 0.311767578125 +8656 0.017242431640625 +8657 0.339141845703125 +8658 0.0184326171875 +8659 0.360260009765625 +8660 0.018646240234375 +8661 0.360504150390625 +8662 0.01605224609375 +8663 0.308380126953125 +8664 0.0093994140625 +8665 0.18170166015625 +8666 3.0517578125e-05 +8667 0.0047607421875 +8668 -0.009490966796875 +8669 -0.17559814453125 +8670 -0.016693115234375 +8671 -0.3143310546875 +8672 -0.019195556640625 +8673 -0.36785888671875 +8674 -0.018463134765625 +8675 -0.36248779296875 +8676 -0.017059326171875 +8677 -0.343536376953125 +8678 -0.014495849609375 +8679 -0.3018798828125 +8680 -0.01043701171875 +8681 -0.231414794921875 +8682 -0.00408935546875 +8683 -0.117645263671875 +8684 0.002685546875 +8685 0.007049560546875 +8686 0.006866455078125 +8687 0.087982177734375 +8688 0.009307861328125 +8689 0.13946533203125 +8690 0.0107421875 +8691 0.17425537109375 +8692 0.010986328125 +8693 0.188201904296875 +8694 0.009490966796875 +8695 0.171234130859375 +8696 0.006011962890625 +8697 0.118438720703125 +8698 0.00213623046875 +8699 0.05706787109375 +8700 -0.001983642578125 +8701 -0.010711669921875 +8702 -0.0067138671875 +8703 -0.0914306640625 +8704 -0.011199951171875 +8705 -0.162322998046875 +8706 -0.013641357421875 +8707 -0.194549560546875 +8708 -0.01031494140625 +8709 -0.1492919921875 +8710 -0.000396728515625 +8711 -0.02166748046875 +8712 0.0107421875 +8713 0.124053955078125 +8714 0.016632080078125 +8715 0.211151123046875 +8716 0.017608642578125 +8717 0.240447998046875 +8718 0.016510009765625 +8719 0.242218017578125 +8720 0.014251708984375 +8721 0.2257080078125 +8722 0.011199951171875 +8723 0.194366455078125 +8724 0.00445556640625 +8725 0.115509033203125 +8726 -0.003875732421875 +8727 0.0128173828125 +8728 -0.00860595703125 +8729 -0.053802490234375 +8730 -0.012176513671875 +8731 -0.110626220703125 +8732 -0.01837158203125 +8733 -0.199493408203125 +8734 -0.0250244140625 +8735 -0.29437255859375 +8736 -0.02667236328125 +8737 -0.33221435546875 +8738 -0.0205078125 +8739 -0.27972412109375 +8740 -0.010894775390625 +8741 -0.185333251953125 +8742 -0.004852294921875 +8743 -0.128204345703125 +8744 -0.00311279296875 +8745 -0.115692138671875 +8746 -0.002899169921875 +8747 -0.116455078125 +8748 -0.0020751953125 +8749 -0.105926513671875 +8750 0.001983642578125 +8751 -0.053955078125 +8752 0.010162353515625 +8753 0.048797607421875 +8754 0.0185546875 +8755 0.157318115234375 +8756 0.02197265625 +8757 0.212005615234375 +8758 0.02099609375 +8759 0.218475341796875 +8760 0.021026611328125 +8761 0.23724365234375 +8762 0.025421142578125 +8763 0.30535888671875 +8764 0.03057861328125 +8765 0.38128662109375 +8766 0.031280517578125 +8767 0.404449462890625 +8768 0.029327392578125 +8769 0.3944091796875 +8770 0.028045654296875 +8771 0.3885498046875 +8772 0.025360107421875 +8773 0.362640380859375 +8774 0.017486572265625 +8775 0.27362060546875 +8776 0.004058837890625 +8777 0.11712646484375 +8778 -0.0103759765625 +8779 -0.054901123046875 +8780 -0.02130126953125 +8781 -0.19085693359375 +8782 -0.02838134765625 +8783 -0.28570556640625 +8784 -0.03167724609375 +8785 -0.339263916015625 +8786 -0.033538818359375 +8787 -0.3775634765625 +8788 -0.03802490234375 +8789 -0.445709228515625 +8790 -0.04443359375 +8791 -0.535064697265625 +8792 -0.051422119140625 +8793 -0.629058837890625 +8794 -0.056365966796875 +8795 -0.697601318359375 +8796 -0.056121826171875 +8797 -0.70391845703125 +8798 -0.050201416015625 +8799 -0.6424560546875 +8800 -0.0367431640625 +8801 -0.491241455078125 +8802 -0.017059326171875 +8803 -0.265716552734375 +8804 0.00372314453125 +8805 -0.023712158203125 +8806 0.022735595703125 +8807 0.201751708984375 +8808 0.036956787109375 +8809 0.375823974609375 +8810 0.0452880859375 +8811 0.485076904296875 +8812 0.05126953125 +8813 0.56884765625 +8814 0.0556640625 +8815 0.634765625 +8816 0.054595947265625 +8817 0.63763427734375 +8818 0.047088623046875 +8819 0.5660400390625 +8820 0.03778076171875 +8821 0.4720458984375 +8822 0.03125 +8823 0.40692138671875 +8824 0.028167724609375 +8825 0.3778076171875 +8826 0.027862548828125 +8827 0.376953125 +8828 0.027496337890625 +8829 0.371978759765625 +8830 0.02264404296875 +8831 0.313140869140625 +8832 0.01190185546875 +8833 0.184417724609375 +8834 -0.00250244140625 +8835 0.011199951171875 +8836 -0.017486572265625 +8837 -0.171051025390625 +8838 -0.03094482421875 +8839 -0.33740234375 +8840 -0.041534423828125 +8841 -0.47198486328125 +8842 -0.048065185546875 +8843 -0.560394287109375 +8844 -0.048675537109375 +8845 -0.58056640625 +8846 -0.04473876953125 +8847 -0.54754638671875 +8848 -0.040496826171875 +8849 -0.508575439453125 +8850 -0.035614013671875 +8851 -0.459503173828125 +8852 -0.029571533203125 +8853 -0.394378662109375 +8854 -0.02581787109375 +8855 -0.35260009765625 +8856 -0.022369384765625 +8857 -0.31170654296875 +8858 -0.0126953125 +8859 -0.197418212890625 +8860 0.00335693359375 +8861 -0.007965087890625 +8862 0.021453857421875 +8863 0.207489013671875 +8864 0.038177490234375 +8865 0.409210205078125 +8866 0.0513916015625 +8867 0.57208251953125 +8868 0.058502197265625 +8869 0.66595458984375 +8870 0.0567626953125 +8871 0.65875244140625 +8872 0.047698974609375 +8873 0.56744384765625 +8874 0.03485107421875 +8875 0.431396484375 +8876 0.022125244140625 +8877 0.29443359375 +8878 0.011810302734375 +8879 0.182464599609375 +8880 0.00115966796875 +8881 0.06365966796875 +8882 -0.01104736328125 +8883 -0.075958251953125 +8884 -0.02069091796875 +8885 -0.189422607421875 +8886 -0.027313232421875 +8887 -0.271942138671875 +8888 -0.032684326171875 +8889 -0.342529296875 +8890 -0.03363037109375 +8891 -0.364166259765625 +8892 -0.02935791015625 +8893 -0.327239990234375 +8894 -0.023895263671875 +8895 -0.2769775390625 +8896 -0.02081298828125 +8897 -0.253692626953125 +8898 -0.01898193359375 +8899 -0.24365234375 +8900 -0.014190673828125 +8901 -0.1983642578125 +8902 -0.006317138671875 +8903 -0.116241455078125 +8904 0.001068115234375 +8905 -0.036834716796875 +8906 0.007537841796875 +8907 0.034881591796875 +8908 0.01239013671875 +8909 0.09124755859375 +8910 0.013580322265625 +8911 0.10888671875 +8912 0.01446533203125 +8913 0.125518798828125 +8914 0.01654052734375 +8915 0.15771484375 +8916 0.017486572265625 +8917 0.17828369140625 +8918 0.015899658203125 +8919 0.17108154296875 +8920 0.011322021484375 +8921 0.129974365234375 +8922 0.006195068359375 +8923 0.082427978515625 +8924 0.000518798828125 +8925 0.027679443359375 +8926 -0.00836181640625 +8927 -0.065643310546875 +8928 -0.017059326171875 +8929 -0.15936279296875 +8930 -0.02203369140625 +8931 -0.21307373046875 +8932 -0.023956298828125 +8933 -0.234649658203125 +8934 -0.020751953125 +8935 -0.2001953125 +8936 -0.013275146484375 +8937 -0.119171142578125 +8938 -0.00445556640625 +8939 -0.024749755859375 +8940 0.005889892578125 +8941 0.085784912109375 +8942 0.014678955078125 +8943 0.178131103515625 +8944 0.018646240234375 +8945 0.215576171875 +8946 0.018951416015625 +8947 0.211456298828125 +8948 0.01641845703125 +8949 0.17523193359375 +8950 0.012939453125 +8951 0.128753662109375 +8952 0.011077880859375 +8953 0.1019287109375 +8954 0.009033203125 +8955 0.0743408203125 +8956 0.006561279296875 +8957 0.04327392578125 +8958 0.006195068359375 +8959 0.038177490234375 +8960 0.010009765625 +8961 0.076263427734375 +8962 0.01702880859375 +8963 0.14105224609375 +8964 0.022308349609375 +8965 0.186431884765625 +8966 0.022857666015625 +8967 0.188812255859375 +8968 0.017425537109375 +8969 0.1390380859375 +8970 0.006439208984375 +8971 0.041778564453125 +8972 -0.007354736328125 +8973 -0.079437255859375 +8974 -0.0234375 +8975 -0.219390869140625 +8976 -0.040618896484375 +8977 -0.367828369140625 +8978 -0.055419921875 +8979 -0.494873046875 +8980 -0.06256103515625 +8981 -0.556243896484375 +8982 -0.056884765625 +8983 -0.508697509765625 +8984 -0.041168212890625 +8985 -0.3756103515625 +8986 -0.022857666015625 +8987 -0.218902587890625 +8988 -0.004913330078125 +8989 -0.063751220703125 +8990 0.012847900390625 +8991 0.091552734375 +8992 0.029205322265625 +8993 0.23602294921875 +8994 0.041015625 +8995 0.342987060546875 +8996 0.0462646484375 +8997 0.39520263671875 +8998 0.04461669921875 +8999 0.389373779296875 +9000 0.0360107421875 +9001 0.324249267578125 +9002 0.023406982421875 +9003 0.224090576171875 +9004 0.011077880859375 +9005 0.124267578125 +9006 0.00048828125 +9007 0.037078857421875 +9008 -0.005035400390625 +9009 -0.010101318359375 +9010 -0.00579833984375 +9011 -0.019439697265625 +9012 -0.005615234375 +9013 -0.022796630859375 +9014 -0.0023193359375 +9015 -0.001556396484375 +9016 0.00543212890625 +9017 0.056304931640625 +9018 0.012298583984375 +9019 0.106719970703125 +9020 0.011962890625 +9021 0.096893310546875 +9022 0.006256103515625 +9023 0.042694091796875 +9024 -0.00030517578125 +9025 -0.018035888671875 +9026 -0.006591796875 +9027 -0.07586669921875 +9028 -0.01129150390625 +9029 -0.11944580078125 +9030 -0.0157470703125 +9031 -0.15972900390625 +9032 -0.020660400390625 +9033 -0.202606201171875 +9034 -0.026123046875 +9035 -0.24859619140625 +9036 -0.032989501953125 +9037 -0.30517578125 +9038 -0.0400390625 +9039 -0.36212158203125 +9040 -0.0439453125 +9041 -0.39141845703125 +9042 -0.040130615234375 +9043 -0.35528564453125 +9044 -0.02813720703125 +9045 -0.249969482421875 +9046 -0.010009765625 +9047 -0.092864990234375 +9048 0.01104736328125 +9049 0.08905029296875 +9050 0.027801513671875 +9051 0.2352294921875 +9052 0.037109375 +9053 0.318817138671875 +9054 0.041259765625 +9055 0.358642578125 +9056 0.0394287109375 +9057 0.347747802734375 +9058 0.031585693359375 +9059 0.28564453125 +9060 0.023834228515625 +9061 0.223175048828125 +9062 0.020599365234375 +9063 0.196746826171875 +9064 0.0186767578125 +9065 0.179840087890625 +9066 0.016021728515625 +9067 0.155548095703125 +9068 0.015899658203125 +9069 0.151214599609375 +9070 0.01708984375 +9071 0.156951904296875 +9072 0.0146484375 +9073 0.13177490234375 +9074 0.011566162109375 +9075 0.100799560546875 +9076 0.010589599609375 +9077 0.087127685546875 +9078 0.007354736328125 +9079 0.05487060546875 +9080 0.000244140625 +9081 -0.009002685546875 +9082 -0.010650634765625 +9083 -0.10400390625 +9084 -0.0252685546875 +9085 -0.229400634765625 +9086 -0.040069580078125 +9087 -0.35552978515625 +9088 -0.05023193359375 +9089 -0.441925048828125 +9090 -0.053985595703125 +9091 -0.473846435546875 +9092 -0.052978515625 +9093 -0.464813232421875 +9094 -0.047698974609375 +9095 -0.419097900390625 +9096 -0.037841796875 +9097 -0.334320068359375 +9098 -0.025482177734375 +9099 -0.227935791015625 +9100 -0.013427734375 +9101 -0.12347412109375 +9102 -0.00244140625 +9103 -0.02764892578125 +9104 0.009674072265625 +9105 0.077667236328125 +9106 0.025421142578125 +9107 0.2132568359375 +9108 0.045989990234375 +9109 0.38885498046875 +9110 0.06878662109375 +9111 0.582794189453125 +9112 0.086517333984375 +9113 0.734039306640625 +9114 0.094085693359375 +9115 0.800140380859375 +9116 0.091217041015625 +9117 0.7783203125 +9118 0.0775146484375 +9119 0.6651611328125 +9120 0.0528564453125 +9121 0.45965576171875 +9122 0.021759033203125 +9123 0.199188232421875 +9124 -0.007904052734375 +9125 -0.050689697265625 +9126 -0.029296875 +9127 -0.23297119140625 +9128 -0.040374755859375 +9129 -0.33013916015625 +9130 -0.044342041015625 +9131 -0.368408203125 +9132 -0.04498291015625 +9133 -0.378936767578125 +9134 -0.044158935546875 +9135 -0.376983642578125 +9136 -0.043975830078125 +9137 -0.37969970703125 +9138 -0.044952392578125 +9139 -0.391510009765625 +9140 -0.043853759765625 +9141 -0.385345458984375 +9142 -0.038421630859375 +9143 -0.3419189453125 +9144 -0.031219482421875 +9145 -0.28289794921875 +9146 -0.0274658203125 +9147 -0.251617431640625 +9148 -0.029327392578125 +9149 -0.266143798828125 +9150 -0.030426025390625 +9151 -0.273345947265625 +9152 -0.023956298828125 +9153 -0.216796875 +9154 -0.01373291015625 +9155 -0.128265380859375 +9156 -0.006927490234375 +9157 -0.068145751953125 +9158 -0.00433349609375 +9159 -0.0430908203125 +9160 -0.00250244140625 +9161 -0.024444580078125 +9162 0.00250244140625 +9163 0.020721435546875 +9164 0.014556884765625 +9165 0.124481201171875 +9166 0.030181884765625 +9167 0.25787353515625 +9168 0.044403076171875 +9169 0.379119873046875 +9170 0.05621337890625 +9171 0.47991943359375 +9172 0.061798095703125 +9173 0.5281982421875 +9174 0.059600830078125 +9175 0.511138916015625 +9176 0.052947998046875 +9177 0.456207275390625 +9178 0.047119140625 +9179 0.407470703125 +9180 0.044403076171875 +9181 0.383758544921875 +9182 0.041351318359375 +9183 0.35687255859375 +9184 0.03619384765625 +9185 0.31182861328125 +9186 0.0291748046875 +9187 0.250885009765625 +9188 0.019256591796875 +9189 0.1654052734375 +9190 0.003997802734375 +9191 0.035247802734375 +9192 -0.016876220703125 +9193 -0.142059326171875 +9194 -0.039703369140625 +9195 -0.33563232421875 +9196 -0.06317138671875 +9197 -0.5345458984375 +9198 -0.08526611328125 +9199 -0.72186279296875 +9200 -0.098663330078125 +9201 -0.836669921875 +9202 -0.097869873046875 +9203 -0.8326416015625 +9204 -0.08526611328125 +9205 -0.7296142578125 +9206 -0.0675048828125 +9207 -0.582550048828125 +9208 -0.0504150390625 +9209 -0.440093994140625 +9210 -0.036651611328125 +9211 -0.324310302734375 +9212 -0.022125244140625 +9213 -0.20147705078125 +9214 -0.003570556640625 +9215 -0.044647216796875 +9216 0.013336181640625 +9217 0.103973388671875 +9218 0.022918701171875 +9219 0.202392578125 +9220 0.02752685546875 +9221 0.264495849609375 +9222 0.034820556640625 +9223 0.338897705078125 +9224 0.04779052734375 +9225 0.443817138671875 +9226 0.061370849609375 +9227 0.545074462890625 +9228 0.07177734375 +9229 0.6173095703125 +9230 0.0777587890625 +9231 0.6524658203125 +9232 0.08123779296875 +9233 0.66339111328125 +9234 0.082977294921875 +9235 0.6561279296875 +9236 0.079132080078125 +9237 0.606781005859375 +9238 0.067352294921875 +9239 0.501190185546875 +9240 0.049407958984375 +9241 0.352783203125 +9242 0.02734375 +9243 0.176544189453125 +9244 -0.000213623046875 +9245 -0.034820556640625 +9246 -0.02996826171875 +9247 -0.258209228515625 +9248 -0.054351806640625 +9249 -0.44244384765625 +9250 -0.071685791015625 +9251 -0.5753173828125 +9252 -0.081390380859375 +9253 -0.65203857421875 +9254 -0.078857421875 +9255 -0.641632080078125 +9256 -0.066864013671875 +9257 -0.562164306640625 +9258 -0.0521240234375 +9259 -0.458038330078125 +9260 -0.037750244140625 +9261 -0.350555419921875 +9262 -0.02679443359375 +9263 -0.260528564453125 +9264 -0.01971435546875 +9265 -0.192108154296875 +9266 -0.01580810546875 +9267 -0.141937255859375 +9268 -0.013671875 +9269 -0.1021728515625 +9270 -0.011566162109375 +9271 -0.062896728515625 +9272 -0.0074462890625 +9273 -0.011932373046875 +9274 0.000701904296875 +9275 0.062835693359375 +9276 0.011138916015625 +9277 0.148712158203125 +9278 0.02337646484375 +9279 0.241729736328125 +9280 0.03857421875 +9281 0.34912109375 +9282 0.0546875 +9283 0.457305908203125 +9284 0.068328857421875 +9285 0.54388427734375 +9286 0.074005126953125 +9287 0.5728759765625 +9288 0.06585693359375 +9289 0.506591796875 +9290 0.044708251953125 +9291 0.351226806640625 +9292 0.016448974609375 +9293 0.146514892578125 +9294 -0.0111083984375 +9295 -0.05523681640625 +9296 -0.032379150390625 +9297 -0.21624755859375 +9298 -0.04730224609375 +9299 -0.334930419921875 +9300 -0.054779052734375 +9301 -0.402984619140625 +9302 -0.058135986328125 +9303 -0.4412841796875 +9304 -0.064483642578125 +9305 -0.49578857421875 +9306 -0.07293701171875 +9307 -0.5601806640625 +9308 -0.078460693359375 +9309 -0.600738525390625 +9310 -0.076019287109375 +9311 -0.584228515625 +9312 -0.060821533203125 +9313 -0.47930908203125 +9314 -0.03179931640625 +9315 -0.27935791015625 +9316 0.00738525390625 +9317 -0.0089111328125 +9318 0.047271728515625 +9319 0.268798828125 +9320 0.077178955078125 +9321 0.482818603515625 +9322 0.092803955078125 +9323 0.60369873046875 +9324 0.09716796875 +9325 0.650421142578125 +9326 0.096649169921875 +9327 0.66400146484375 +9328 0.0909423828125 +9329 0.6414794921875 +9330 0.07861328125 +9331 0.572540283203125 +9332 0.06597900390625 +9333 0.498138427734375 +9334 0.056304931640625 +9335 0.439453125 +9336 0.04644775390625 +9337 0.375518798828125 +9338 0.031524658203125 +9339 0.274505615234375 +9340 0.007293701171875 +9341 0.1087646484375 +9342 -0.022857666015625 +9343 -0.099395751953125 +9344 -0.054229736328125 +9345 -0.3182373046875 +9346 -0.087127685546875 +9347 -0.5489501953125 +9348 -0.11895751953125 +9349 -0.7738037109375 +9350 -0.14178466796875 +9351 -0.86383056640625 +9352 -0.15069580078125 +9353 -0.870391845703125 +9354 -0.148529052734375 +9355 -0.86895751953125 +9356 -0.137420654296875 +9357 -0.861053466796875 +9358 -0.11480712890625 +9359 -0.765869140625 +9360 -0.079010009765625 +9361 -0.5301513671875 +9362 -0.031158447265625 +9363 -0.214691162109375 +9364 0.02215576171875 +9365 0.137359619140625 +9366 0.07318115234375 +9367 0.474822998046875 +9368 0.1165771484375 +9369 0.76239013671875 +9370 0.1483154296875 +9371 0.867462158203125 +9372 0.1685791015625 +9373 0.870361328125 +9374 0.1756591796875 +9375 0.86480712890625 +9376 0.170501708984375 +9377 0.831817626953125 +9378 0.156951904296875 +9379 0.677581787109375 +9380 0.136016845703125 +9381 0.495880126953125 +9382 0.110626220703125 +9383 0.30767822265625 +9384 0.081146240234375 +9385 0.116180419921875 +9386 0.0428466796875 +9387 -0.110748291015625 +9388 -0.0052490234375 +9389 -0.381805419921875 +9390 -0.056671142578125 +9391 -0.6572265625 +9392 -0.102294921875 +9393 -0.857421875 +9394 -0.135650634765625 +9395 -0.870391845703125 +9396 -0.155731201171875 +9397 -0.870391845703125 +9398 -0.16668701171875 +9399 -0.86444091796875 +9400 -0.174041748046875 +9401 -0.85723876953125 +9402 -0.175140380859375 +9403 -0.790008544921875 +9404 -0.161834716796875 +9405 -0.62847900390625 +9406 -0.13372802734375 +9407 -0.3956298828125 +9408 -0.095916748046875 +9409 -0.126708984375 +9410 -0.0526123046875 +9411 0.150115966796875 +9412 -0.005645751953125 +9413 0.424041748046875 +9414 0.040802001953125 +9415 0.670623779296875 +9416 0.08087158203125 +9417 0.854522705078125 +9418 0.11187744140625 +9419 0.866485595703125 +9420 0.131500244140625 +9421 0.86920166015625 +9422 0.142547607421875 +9423 0.8653564453125 +9424 0.14715576171875 +9425 0.857147216796875 +9426 0.14495849609375 +9427 0.766845703125 +9428 0.136810302734375 +9429 0.628509521484375 +9430 0.12176513671875 +9431 0.462127685546875 +9432 0.103851318359375 +9433 0.297210693359375 +9434 0.084991455078125 +9435 0.14862060546875 +9436 0.061767578125 +9437 -0.00537109375 +9438 0.035400390625 +9439 -0.15753173828125 +9440 0.00537109375 +9441 -0.31304931640625 +9442 -0.0303955078125 +9443 -0.48876953125 +9444 -0.064788818359375 +9445 -0.6416015625 +9446 -0.09405517578125 +9447 -0.751373291015625 +9448 -0.121734619140625 +9449 -0.84619140625 +9450 -0.145660400390625 +9451 -0.861297607421875 +9452 -0.160858154296875 +9453 -0.863250732421875 +9454 -0.162567138671875 +9455 -0.856597900390625 +9456 -0.152740478515625 +9457 -0.7498779296875 +9458 -0.1402587890625 +9459 -0.624542236328125 +9460 -0.12188720703125 +9461 -0.47808837890625 +9462 -0.088836669921875 +9463 -0.253387451171875 +9464 -0.048065185546875 +9465 0.003692626953125 +9466 -0.010009765625 +9467 0.2257080078125 +9468 0.027191162109375 +9469 0.427154541015625 +9470 0.0684814453125 +9471 0.643218994140625 +9472 0.11285400390625 +9473 0.855926513671875 +9474 0.151580810546875 +9475 0.870361328125 +9476 0.176483154296875 +9477 0.870361328125 +9478 0.18890380859375 +9479 0.862762451171875 +9480 0.188232421875 +9481 0.79669189453125 +9482 0.17254638671875 +9483 0.595794677734375 +9484 0.14697265625 +9485 0.362152099609375 +9486 0.1163330078125 +9487 0.1270751953125 +9488 0.084136962890625 +9489 -0.086944580078125 +9490 0.050384521484375 +9491 -0.2784423828125 +9492 0.008270263671875 +9493 -0.484832763671875 +9494 -0.046142578125 +9495 -0.729583740234375 +9496 -0.103912353515625 +9497 -0.86688232421875 +9498 -0.153778076171875 +9499 -0.870391845703125 +9500 -0.195037841796875 +9501 -0.86859130859375 +9502 -0.227569580078125 +9503 -0.86279296875 +9504 -0.244903564453125 +9505 -0.817962646484375 +9506 -0.238739013671875 +9507 -0.6116943359375 +9508 -0.207763671875 +9509 -0.3128662109375 +9510 -0.158050537109375 +9511 0.039398193359375 +9512 -0.0931396484375 +9513 0.422821044921875 +9514 -0.0189208984375 +9515 0.805145263671875 +9516 0.052276611328125 +9517 0.870361328125 +9518 0.1102294921875 +9519 0.870361328125 +9520 0.153106689453125 +9521 0.860015869140625 +9522 0.179779052734375 +9523 0.727935791015625 +9524 0.189483642578125 +9525 0.48114013671875 +9526 0.186859130859375 +9527 0.2059326171875 +9528 0.17626953125 +9529 -0.06103515625 +9530 0.15966796875 +9531 -0.29913330078125 +9532 0.134429931640625 +9533 -0.516204833984375 +9534 0.0977783203125 +9535 -0.7252197265625 +9536 0.054229736328125 +9537 -0.85980224609375 +9538 0.010009765625 +9539 -0.870391845703125 +9540 -0.029510498046875 +9541 -0.870391845703125 +9542 -0.055511474609375 +9543 -0.858062744140625 +9544 -0.0673828125 +9545 -0.673004150390625 +9546 -0.07501220703125 +9547 -0.42694091796875 +9548 -0.086700439453125 +9549 -0.2100830078125 +9550 -0.102203369140625 +9551 -0.0362548828125 +9552 -0.11627197265625 +9553 0.10943603515625 +9554 -0.125335693359375 +9555 0.23516845703125 +9556 -0.12188720703125 +9557 0.373687744140625 +9558 -0.106353759765625 +9559 0.517791748046875 +9560 -0.090362548828125 +9561 0.602783203125 +9562 -0.07293701171875 +9563 0.635711669921875 +9564 -0.047943115234375 +9565 0.655181884765625 +9566 -0.01715087890625 +9567 0.65948486328125 +9568 0.018035888671875 +9569 0.651275634765625 +9570 0.053192138671875 +9571 0.61846923828125 +9572 0.08160400390625 +9573 0.53753662109375 +9574 0.10003662109375 +9575 0.404144287109375 +9576 0.1068115234375 +9577 0.22186279296875 +9578 0.102325439453125 +9579 0.003997802734375 +9580 0.0899658203125 +9581 -0.22100830078125 +9582 0.0736083984375 +9583 -0.42449951171875 +9584 0.0572509765625 +9585 -0.579833984375 +9586 0.04876708984375 +9587 -0.641876220703125 +9588 0.04693603515625 +9589 -0.6177978515625 +9590 0.039886474609375 +9591 -0.575531005859375 +9592 0.02655029296875 +9593 -0.526336669921875 +9594 0.016448974609375 +9595 -0.42645263671875 +9596 0.014556884765625 +9597 -0.2581787109375 +9598 0.01409912109375 +9599 -0.068695068359375 +9600 0.0079345703125 +9601 0.09222412109375 +9602 -0.000518798828125 +9603 0.232147216796875 +9604 -0.00946044921875 +9605 0.3509521484375 +9606 -0.0244140625 +9607 0.410064697265625 +9608 -0.050872802734375 +9609 0.372955322265625 +9610 -0.08502197265625 +9611 0.2554931640625 +9612 -0.11724853515625 +9613 0.10711669921875 +9614 -0.143951416015625 +9615 -0.052886962890625 +9616 -0.158477783203125 +9617 -0.186279296875 +9618 -0.150543212890625 +9619 -0.23291015625 +9620 -0.124267578125 +9621 -0.209442138671875 +9622 -0.091766357421875 +9623 -0.174163818359375 +9624 -0.054473876953125 +9625 -0.126739501953125 +9626 -0.010528564453125 +9627 -0.048126220703125 +9628 0.03485107421875 +9629 0.0426025390625 +9630 0.07318115234375 +9631 0.10748291015625 +9632 0.10205078125 +9633 0.1409912109375 +9634 0.1302490234375 +9635 0.19708251953125 +9636 0.15655517578125 +9637 0.273651123046875 +9638 0.17071533203125 +9639 0.31768798828125 +9640 0.1748046875 +9641 0.341094970703125 +9642 0.173431396484375 +9643 0.368011474609375 +9644 0.162353515625 +9645 0.37249755859375 +9646 0.132476806640625 +9647 0.30072021484375 +9648 0.08465576171875 +9649 0.1517333984375 +9650 0.0311279296875 +9651 -0.01470947265625 +9652 -0.024871826171875 +9653 -0.1883544921875 +9654 -0.0826416015625 +9655 -0.372711181640625 +9656 -0.131011962890625 +9657 -0.51397705078125 +9658 -0.161346435546875 +9659 -0.57177734375 +9660 -0.17144775390625 +9661 -0.53948974609375 +9662 -0.16387939453125 +9663 -0.43511962890625 +9664 -0.145050048828125 +9665 -0.2962646484375 +9666 -0.12176513671875 +9667 -0.161102294921875 +9668 -0.096649169921875 +9669 -0.0435791015625 +9670 -0.06927490234375 +9671 0.060394287109375 +9672 -0.042816162109375 +9673 0.13665771484375 +9674 -0.020843505859375 +9675 0.170135498046875 +9676 -0.003448486328125 +9677 0.16552734375 +9678 0.014617919921875 +9679 0.15728759765625 +9680 0.033233642578125 +9681 0.150787353515625 +9682 0.046875 +9683 0.12200927734375 +9684 0.056243896484375 +9685 0.080108642578125 +9686 0.06524658203125 +9687 0.05126953125 +9688 0.0782470703125 +9689 0.062896728515625 +9690 0.09063720703125 +9691 0.09271240234375 +9692 0.093414306640625 +9693 0.092987060546875 +9694 0.089263916015625 +9695 0.07855224609375 +9696 0.08111572265625 +9697 0.06427001953125 +9698 0.066558837890625 +9699 0.0347900390625 +9700 0.04583740234375 +9701 -0.01171875 +9702 0.02325439453125 +9703 -0.056060791015625 +9704 0.00750732421875 +9705 -0.055511474609375 +9706 -0.00054931640625 +9707 -0.010467529296875 +9708 -0.009918212890625 +9709 0.02508544921875 +9710 -0.024444580078125 +9711 0.025665283203125 +9712 -0.038543701171875 +9713 0.017333984375 +9714 -0.051300048828125 +9715 0.00189208984375 +9716 -0.06427001953125 +9717 -0.03173828125 +9718 -0.074951171875 +9719 -0.071502685546875 +9720 -0.086578369140625 +9721 -0.13543701171875 +9722 -0.098602294921875 +9723 -0.219970703125 +9724 -0.106781005859375 +9725 -0.300506591796875 +9726 -0.111419677734375 +9727 -0.376312255859375 +9728 -0.107269287109375 +9729 -0.416107177734375 +9730 -0.08587646484375 +9731 -0.371124267578125 +9732 -0.048187255859375 +9733 -0.242279052734375 +9734 -0.002593994140625 +9735 -0.069732666015625 +9736 0.046295166015625 +9737 0.125640869140625 +9738 0.0919189453125 +9739 0.31268310546875 +9740 0.126708984375 +9741 0.45501708984375 +9742 0.15087890625 +9743 0.554779052734375 +9744 0.1640625 +9745 0.61065673828125 +9746 0.16387939453125 +9747 0.610931396484375 +9748 0.145599365234375 +9749 0.531463623046875 +9750 0.11260986328125 +9751 0.3883056640625 +9752 0.07586669921875 +9753 0.23468017578125 +9754 0.040679931640625 +9755 0.095245361328125 +9756 0.012664794921875 +9757 -0.00396728515625 +9758 -0.004852294921875 +9759 -0.04852294921875 +9760 -0.014739990234375 +9761 -0.055145263671875 +9762 -0.026947021484375 +9763 -0.0758056640625 +9764 -0.046722412109375 +9765 -0.138702392578125 +9766 -0.066741943359375 +9767 -0.209197998046875 +9768 -0.08709716796875 +9769 -0.289031982421875 +9770 -0.107696533203125 +9771 -0.37884521484375 +9772 -0.123992919921875 +9773 -0.456329345703125 +9774 -0.134979248046875 +9775 -0.51641845703125 +9776 -0.1328125 +9777 -0.519287109375 +9778 -0.116363525390625 +9779 -0.458251953125 +9780 -0.09619140625 +9781 -0.384796142578125 +9782 -0.077545166015625 +9783 -0.323699951171875 +9784 -0.0596923828125 +9785 -0.269287109375 +9786 -0.0377197265625 +9787 -0.1951904296875 +9788 -0.01177978515625 +9789 -0.100006103515625 +9790 0.012359619140625 +9791 -0.01055908203125 +9792 0.0404052734375 +9793 0.1033935546875 +9794 0.073577880859375 +9795 0.24908447265625 +9796 0.10101318359375 +9797 0.373199462890625 +9798 0.11907958984375 +9799 0.45806884765625 +9800 0.129302978515625 +9801 0.511474609375 +9802 0.13818359375 +9803 0.565399169921875 +9804 0.144134521484375 +9805 0.61138916015625 +9806 0.13543701171875 +9807 0.5897216796875 +9808 0.11041259765625 +9809 0.4906005859375 +9810 0.0728759765625 +9811 0.33148193359375 +9812 0.030242919921875 +9813 0.147796630859375 +9814 -0.008819580078125 +9815 -0.01873779296875 +9816 -0.038421630859375 +9817 -0.140289306640625 +9818 -0.053314208984375 +9819 -0.191986083984375 +9820 -0.055389404296875 +9821 -0.184295654296875 +9822 -0.053375244140625 +9823 -0.161834716796875 +9824 -0.055572509765625 +9825 -0.166595458984375 +9826 -0.061004638671875 +9827 -0.19390869140625 +9828 -0.065826416015625 +9829 -0.22442626953125 +9830 -0.074493408203125 +9831 -0.279754638671875 +9832 -0.082977294921875 +9833 -0.3389892578125 +9834 -0.081939697265625 +9835 -0.3543701171875 +9836 -0.076080322265625 +9837 -0.348175048828125 +9838 -0.0667724609375 +9839 -0.32598876953125 +9840 -0.04840087890625 +9841 -0.2581787109375 +9842 -0.02020263671875 +9843 -0.139801025390625 +9844 0.014678955078125 +9845 0.014617919921875 +9846 0.043853759765625 +9847 0.144378662109375 +9848 0.061492919921875 +9849 0.221038818359375 +9850 0.072723388671875 +9851 0.27069091796875 +9852 0.07763671875 +9853 0.294036865234375 +9854 0.080413818359375 +9855 0.311767578125 +9856 0.084228515625 +9857 0.339141845703125 +9858 0.086181640625 +9859 0.360260009765625 +9860 0.083465576171875 +9861 0.360504150390625 +9862 0.069366455078125 +9863 0.308380126953125 +9864 0.0391845703125 +9865 0.18170166015625 +9866 -0.001678466796875 +9867 0.0047607421875 +9868 -0.042999267578125 +9869 -0.17559814453125 +9870 -0.074951171875 +9871 -0.3143310546875 +9872 -0.088043212890625 +9873 -0.36785888671875 +9874 -0.087890625 +9875 -0.36248779296875 +9876 -0.084259033203125 +9877 -0.343536376953125 +9878 -0.0751953125 +9879 -0.3018798828125 +9880 -0.05938720703125 +9881 -0.231414794921875 +9882 -0.033721923828125 +9883 -0.117645263671875 +9884 -0.005279541015625 +9885 0.007049560546875 +9886 0.0140380859375 +9887 0.087982177734375 +9888 0.027191162109375 +9889 0.13946533203125 +9890 0.036834716796875 +9891 0.17425537109375 +9892 0.041961669921875 +9893 0.188201904296875 +9894 0.040252685546875 +9895 0.171234130859375 +9896 0.03057861328125 +9897 0.118438720703125 +9898 0.018768310546875 +9899 0.05706787109375 +9900 0.00518798828125 +9901 -0.010711669921875 +9902 -0.0115966796875 +9903 -0.0914306640625 +9904 -0.026702880859375 +9905 -0.162322998046875 +9906 -0.033905029296875 +9907 -0.194549560546875 +9908 -0.0247802734375 +9909 -0.1492919921875 +9910 0.001739501953125 +9911 -0.02166748046875 +9912 0.0318603515625 +9913 0.124053955078125 +9914 0.049041748046875 +9915 0.211151123046875 +9916 0.0535888671875 +9917 0.240447998046875 +9918 0.052154541015625 +9919 0.242218017578125 +9920 0.04681396484375 +9921 0.2257080078125 +9922 0.038421630859375 +9923 0.194366455078125 +9924 0.019989013671875 +9925 0.115509033203125 +9926 -0.003204345703125 +9927 0.0128173828125 +9928 -0.0181884765625 +9929 -0.053802490234375 +9930 -0.0306396484375 +9931 -0.110626220703125 +9932 -0.049591064453125 +9933 -0.199493408203125 +9934 -0.069488525390625 +9935 -0.29437255859375 +9936 -0.076751708984375 +9937 -0.33221435546875 +9938 -0.06427001953125 +9939 -0.27972412109375 +9940 -0.04254150390625 +9941 -0.185333251953125 +9942 -0.028717041015625 +9943 -0.128204345703125 +9944 -0.024505615234375 +9945 -0.115692138671875 +9946 -0.023193359375 +9947 -0.116455078125 +9948 -0.01959228515625 +9949 -0.105926513671875 +9950 -0.007232666015625 +9951 -0.053955078125 +9952 0.01580810546875 +9953 0.048797607421875 +9954 0.039794921875 +9955 0.157318115234375 +9956 0.05181884765625 +9957 0.212005615234375 +9958 0.053070068359375 +9959 0.218475341796875 +9960 0.056671142578125 +9961 0.23724365234375 +9962 0.070648193359375 +9963 0.30535888671875 +9964 0.0860595703125 +9965 0.38128662109375 +9966 0.089874267578125 +9967 0.404449462890625 +9968 0.086395263671875 +9969 0.3944091796875 +9970 0.08380126953125 +9971 0.3885498046875 +9972 0.076934814453125 +9973 0.362640380859375 +9974 0.056549072265625 +9975 0.27362060546875 +9976 0.021759033203125 +9977 0.11712646484375 +9978 -0.01611328125 +9979 -0.054901123046875 +9980 -0.0458984375 +9981 -0.19085693359375 +9982 -0.066497802734375 +9983 -0.28570556640625 +9984 -0.0772705078125 +9985 -0.339263916015625 +9986 -0.0841064453125 +9987 -0.3775634765625 +9988 -0.0982666015625 +9989 -0.445709228515625 +9990 -0.118011474609375 +9991 -0.535064697265625 +9992 -0.13958740234375 +9993 -0.629058837890625 +9994 -0.15576171875 +9995 -0.697601318359375 +9996 -0.15753173828125 +9997 -0.70391845703125 +9998 -0.143524169921875 +9999 -0.6424560546875 +10000 -0.10821533203125 +10001 -0.491241455078125 +10002 -0.0552978515625 +10003 -0.265716552734375 +10004 0.001068115234375 +10005 -0.023712158203125 +10006 0.05291748046875 +10007 0.201751708984375 +10008 0.091888427734375 +10009 0.375823974609375 +10010 0.1148681640625 +10011 0.485076904296875 +10012 0.131866455078125 +10013 0.56884765625 +10014 0.144989013671875 +10015 0.634765625 +10016 0.143218994140625 +10017 0.63763427734375 +10018 0.12384033203125 +10019 0.5660400390625 +10020 0.099853515625 +10021 0.4720458984375 +10022 0.083953857421875 +10023 0.40692138671875 +10024 0.077911376953125 +10025 0.3778076171875 +10026 0.0797119140625 +10027 0.376953125 +10028 0.0811767578125 +10029 0.371978759765625 +10030 0.06982421875 +10031 0.313140869140625 +10032 0.041473388671875 +10033 0.184417724609375 +10034 0.002227783203125 +10035 0.011199951171875 +10036 -0.039276123046875 +10037 -0.171051025390625 +10038 -0.07708740234375 +10039 -0.33740234375 +10040 -0.107452392578125 +10041 -0.47198486328125 +10042 -0.126922607421875 +10043 -0.560394287109375 +10044 -0.13018798828125 +10045 -0.58056640625 +10046 -0.12103271484375 +10047 -0.54754638671875 +10048 -0.111236572265625 +10049 -0.508575439453125 +10050 -0.0997314453125 +10051 -0.459503173828125 +10052 -0.084991455078125 +10053 -0.394378662109375 +10054 -0.07666015625 +10055 -0.35260009765625 +10056 -0.06903076171875 +10057 -0.31170654296875 +10058 -0.04351806640625 +10059 -0.197418212890625 +10060 0.00042724609375 +10061 -0.007965087890625 +10062 0.050750732421875 +10063 0.207489013671875 +10064 0.0977783203125 +10065 0.409210205078125 +10066 0.135467529296875 +10067 0.57208251953125 +10068 0.156463623046875 +10069 0.66595458984375 +10070 0.152923583984375 +10071 0.65875244140625 +10072 0.129119873046875 +10073 0.56744384765625 +10074 0.09490966796875 +10075 0.431396484375 +10076 0.061126708984375 +10077 0.29443359375 +10078 0.034210205078125 +10079 0.182464599609375 +10080 0.00616455078125 +10081 0.06365966796875 +10082 -0.02655029296875 +10083 -0.075958251953125 +10084 -0.052398681640625 +10085 -0.189422607421875 +10086 -0.070281982421875 +10087 -0.271942138671875 +10088 -0.085052490234375 +10089 -0.342529296875 +10090 -0.0877685546875 +10091 -0.364166259765625 +10092 -0.076171875 +10093 -0.327239990234375 +10094 -0.06158447265625 +10095 -0.2769775390625 +10096 -0.054107666015625 +10097 -0.253692626953125 +10098 -0.0504150390625 +10099 -0.24365234375 +10100 -0.03857421875 +10101 -0.1983642578125 +10102 -0.0181884765625 +10103 -0.116241455078125 +10104 0.000946044921875 +10105 -0.036834716796875 +10106 0.01763916015625 +10107 0.034881591796875 +10108 0.030059814453125 +10109 0.09124755859375 +10110 0.032501220703125 +10111 0.10888671875 +10112 0.034423828125 +10113 0.125518798828125 +10114 0.04010009765625 +10115 0.15771484375 +10116 0.042877197265625 +10117 0.17828369140625 +10118 0.038909912109375 +10119 0.17108154296875 +10120 0.02679443359375 +10121 0.129974365234375 +10122 0.013458251953125 +10123 0.082427978515625 +10124 -0.001220703125 +10125 0.027679443359375 +10126 -0.024932861328125 +10127 -0.065643310546875 +10128 -0.0482177734375 +10129 -0.15936279296875 +10130 -0.06109619140625 +10131 -0.21307373046875 +10132 -0.0655517578125 +10133 -0.234649658203125 +10134 -0.05572509765625 +10135 -0.2001953125 +10136 -0.034027099609375 +10137 -0.119171142578125 +10138 -0.008819580078125 +10139 -0.024749755859375 +10140 0.020477294921875 +10141 0.085784912109375 +10142 0.04522705078125 +10143 0.178131103515625 +10144 0.056243896484375 +10145 0.215576171875 +10146 0.056732177734375 +10147 0.211456298828125 +10148 0.04901123046875 +10149 0.17523193359375 +10150 0.038421630859375 +10151 0.128753662109375 +10152 0.032318115234375 +10153 0.1019287109375 +10154 0.025634765625 +10155 0.0743408203125 +10156 0.0177001953125 +10157 0.04327392578125 +10158 0.01580810546875 +10159 0.038177490234375 +10160 0.0242919921875 +10161 0.076263427734375 +10162 0.039093017578125 +10163 0.14105224609375 +10164 0.04888916015625 +10165 0.186431884765625 +10166 0.04791259765625 +10167 0.188812255859375 +10168 0.03399658203125 +10169 0.1390380859375 +10170 0.008392333984375 +10171 0.041778564453125 +10172 -0.02294921875 +10173 -0.079437255859375 +10174 -0.058685302734375 +10175 -0.219390869140625 +10176 -0.096221923828125 +10177 -0.367828369140625 +10178 -0.12811279296875 +10179 -0.494873046875 +10180 -0.14337158203125 +10181 -0.556243896484375 +10182 -0.13128662109375 +10183 -0.508697509765625 +10184 -0.09771728515625 +10185 -0.3756103515625 +10186 -0.05804443359375 +10187 -0.218902587890625 +10188 -0.018585205078125 +10189 -0.063751220703125 +10190 0.02099609375 +10191 0.091552734375 +10192 0.057952880859375 +10193 0.23602294921875 +10194 0.0855712890625 +10195 0.342987060546875 +10196 0.099578857421875 +10197 0.39520263671875 +10198 0.099090576171875 +10199 0.389373779296875 +10200 0.083709716796875 +10201 0.324249267578125 +10202 0.0594482421875 +10203 0.224090576171875 +10204 0.0350341796875 +10205 0.124267578125 +10206 0.0135498046875 +10207 0.037078857421875 +10208 0.001739501953125 +10209 -0.010101318359375 +10210 -0.000885009765625 +10211 -0.019439697265625 +10212 -0.002197265625 +10213 -0.022796630859375 +10214 0.002410888671875 +10215 -0.001556396484375 +10216 0.015960693359375 +10217 0.056304931640625 +10218 0.02752685546875 +10219 0.106719970703125 +10220 0.02410888671875 +10221 0.096893310546875 +10222 0.00970458984375 +10223 0.042694091796875 +10224 -0.0062255859375 +10225 -0.018035888671875 +10226 -0.021270751953125 +10227 -0.07586669921875 +10228 -0.0325927734375 +10229 -0.11944580078125 +10230 -0.04290771484375 +10231 -0.15972900390625 +10232 -0.05364990234375 +10233 -0.202606201171875 +10234 -0.064910888671875 +10235 -0.24859619140625 +10236 -0.078582763671875 +10237 -0.30517578125 +10238 -0.0921630859375 +10239 -0.36212158203125 +10240 -0.0986328125 +10241 -0.39141845703125 +10242 -0.088531494140625 +10243 -0.35528564453125 +10244 -0.06103515625 +10245 -0.249969482421875 +10246 -0.0203857421875 +10247 -0.092864990234375 +10248 0.026458740234375 +10249 0.08905029296875 +10250 0.0631103515625 +10251 0.2352294921875 +10252 0.082489013671875 +10253 0.318817138671875 +10254 0.0902099609375 +10255 0.358642578125 +10256 0.084564208984375 +10257 0.347747802734375 +10258 0.065582275390625 +10259 0.28564453125 +10260 0.04754638671875 +10261 0.223175048828125 +10262 0.0406494140625 +10263 0.196746826171875 +10264 0.037384033203125 +10265 0.179840087890625 +10266 0.032867431640625 +10267 0.155548095703125 +10268 0.034576416015625 +10269 0.151214599609375 +10270 0.03955078125 +10271 0.156951904296875 +10272 0.03607177734375 +10273 0.13177490234375 +10274 0.030975341796875 +10275 0.100799560546875 +10276 0.030487060546875 +10277 0.087127685546875 +10278 0.024383544921875 +10279 0.05487060546875 +10280 0.00885009765625 +10281 -0.009002685546875 +10282 -0.01605224609375 +10283 -0.10400390625 +10284 -0.05023193359375 +10285 -0.229400634765625 +10286 -0.085418701171875 +10287 -0.35552978515625 +10288 -0.110260009765625 +10289 -0.441925048828125 +10290 -0.120574951171875 +10291 -0.473846435546875 +10292 -0.120025634765625 +10293 -0.464813232421875 +10294 -0.10968017578125 +10295 -0.419097900390625 +10296 -0.088714599609375 +10297 -0.334320068359375 +10298 -0.061859130859375 +10299 -0.227935791015625 +10300 -0.035552978515625 +10301 -0.12347412109375 +10302 -0.011505126953125 +10303 -0.02764892578125 +10304 0.015472412109375 +10305 0.077667236328125 +10306 0.05133056640625 +10307 0.2132568359375 +10308 0.098907470703125 +10309 0.38885498046875 +10310 0.1522216796875 +10311 0.582794189453125 +10312 0.194183349609375 +10313 0.734039306640625 +10314 0.212890625 +10315 0.800140380859375 +10316 0.207550048828125 +10317 0.7783203125 +10318 0.177154541015625 +10319 0.6651611328125 +10320 0.12139892578125 +10321 0.45965576171875 +10322 0.050628662109375 +10323 0.199188232421875 +10324 -0.01690673828125 +10325 -0.050689697265625 +10326 -0.065399169921875 +10327 -0.23297119140625 +10328 -0.090087890625 +10329 -0.33013916015625 +10330 -0.098480224609375 +10331 -0.368408203125 +10332 -0.099395751953125 +10333 -0.378936767578125 +10334 -0.09722900390625 +10335 -0.376983642578125 +10336 -0.096893310546875 +10337 -0.37969970703125 +10338 -0.099609375 +10339 -0.391510009765625 +10340 -0.097869873046875 +10341 -0.385345458984375 +10342 -0.086212158203125 +10343 -0.3419189453125 +10344 -0.0706787109375 +10345 -0.28289794921875 +10346 -0.063323974609375 +10347 -0.251617431640625 +10348 -0.069091796875 +10349 -0.266143798828125 +10350 -0.073028564453125 +10351 -0.273345947265625 +10352 -0.059234619140625 +10353 -0.216796875 +10354 -0.0364990234375 +10355 -0.128265380859375 +10356 -0.0216064453125 +10357 -0.068145751953125 +10358 -0.01629638671875 +10359 -0.0430908203125 +10360 -0.012481689453125 +10361 -0.024444580078125 +10362 -0.0008544921875 +10363 0.020721435546875 +10364 0.027587890625 +10365 0.124481201171875 +10366 0.064727783203125 +10367 0.25787353515625 +10368 0.098876953125 +10369 0.379119873046875 +10370 0.127685546875 +10371 0.47991943359375 +10372 0.142120361328125 +10373 0.5281982421875 +10374 0.1385498046875 +10375 0.511138916015625 +10376 0.124603271484375 +10377 0.456207275390625 +10378 0.112518310546875 +10379 0.407470703125 +10380 0.10748291015625 +10381 0.383758544921875 +10382 0.101470947265625 +10383 0.35687255859375 +10384 0.090240478515625 +10385 0.31182861328125 +10386 0.0743408203125 +10387 0.250885009765625 +10388 0.051300048828125 +10389 0.1654052734375 +10390 0.01544189453125 +10391 0.035247802734375 +10392 -0.033935546875 +10393 -0.142059326171875 +10394 -0.088165283203125 +10395 -0.33563232421875 +10396 -0.1441650390625 +10397 -0.5345458984375 +10398 -0.197174072265625 +10399 -0.72186279296875 +10400 -0.230072021484375 +10401 -0.836669921875 +10402 -0.229888916015625 +10403 -0.8326416015625 +10404 -0.202117919921875 +10405 -0.7296142578125 +10406 -0.162109375 +10407 -0.582550048828125 +10408 -0.1234130859375 +10409 -0.440093994140625 +10410 -0.092132568359375 +10411 -0.324310302734375 +10412 -0.058746337890625 +10413 -0.20147705078125 +10414 -0.015655517578125 +10415 -0.044647216796875 +10416 0.02532958984375 +10417 0.103973388671875 +10418 0.052490234375 +10419 0.202392578125 +10420 0.069732666015625 +10421 0.264495849609375 +10422 0.090667724609375 +10423 0.338897705078125 +10424 0.120361328125 +10425 0.443817138671875 +10426 0.14923095703125 +10427 0.545074462890625 +10428 0.170135498046875 +10429 0.6173095703125 +10430 0.1807861328125 +10431 0.6524658203125 +10432 0.18475341796875 +10433 0.66339111328125 +10434 0.18365478515625 +10435 0.6561279296875 +10436 0.170745849609375 +10437 0.606781005859375 +10438 0.141998291015625 +10439 0.501190185546875 +10440 0.10113525390625 +10441 0.352783203125 +10442 0.05230712890625 +10443 0.176544189453125 +10444 -0.0064697265625 +10445 -0.034820556640625 +10446 -0.068756103515625 +10447 -0.258209228515625 +10448 -0.1202392578125 +10449 -0.44244384765625 +10450 -0.15753173828125 +10451 -0.5753173828125 +10452 -0.17926025390625 +10453 -0.65203857421875 +10454 -0.176727294921875 +10455 -0.641632080078125 +10456 -0.154998779296875 +10457 -0.562164306640625 +10458 -0.126495361328125 +10459 -0.458038330078125 +10460 -0.09710693359375 +10461 -0.350555419921875 +10462 -0.072601318359375 +10463 -0.260528564453125 +10464 -0.05413818359375 +10465 -0.192108154296875 +10466 -0.040740966796875 +10467 -0.141937255859375 +10468 -0.030181884765625 +10469 -0.1021728515625 +10470 -0.0196533203125 +10471 -0.062896728515625 +10472 -0.00567626953125 +10473 -0.011932373046875 +10474 0.01507568359375 +10475 0.062835693359375 +10476 0.039093017578125 +10477 0.148712158203125 +10478 0.06524658203125 +10479 0.241729736328125 +10480 0.095550537109375 +10481 0.34912109375 +10482 0.126220703125 +10483 0.457305908203125 +10484 0.15093994140625 +10485 0.54388427734375 +10486 0.15960693359375 +10487 0.5728759765625 +10488 0.141632080078125 +10489 0.506591796875 +10490 0.098724365234375 +10491 0.351226806640625 +10492 0.041961669921875 +10493 0.146514892578125 +10494 -0.0140380859375 +10495 -0.05523681640625 +10496 -0.058990478515625 +10497 -0.21624755859375 +10498 -0.09228515625 +10499 -0.334930419921875 +10500 -0.11077880859375 +10501 -0.402984619140625 +10502 -0.121063232421875 +10503 -0.4412841796875 +10504 -0.13751220703125 +10505 -0.49578857421875 +10506 -0.1580810546875 +10507 -0.5601806640625 +10508 -0.17218017578125 +10509 -0.600738525390625 +10510 -0.1693115234375 +10511 -0.584228515625 +10512 -0.1395263671875 +10513 -0.47930908203125 +10514 -0.08056640625 +10515 -0.27935791015625 +10516 9.1552734375e-05 +10517 -0.0089111328125 +10518 0.082977294921875 +10519 0.268798828125 +10520 0.146148681640625 +10521 0.482818603515625 +10522 0.18060302734375 +10523 0.60369873046875 +10524 0.192413330078125 +10525 0.650421142578125 +10526 0.194549560546875 +10527 0.66400146484375 +10528 0.1861572265625 +10529 0.6414794921875 +10530 0.164093017578125 +10531 0.572540283203125 +10532 0.141143798828125 +10533 0.498138427734375 +10534 0.123870849609375 +10535 0.439453125 +10536 0.10565185546875 +10537 0.375518798828125 +10538 0.07647705078125 +10539 0.274505615234375 +10540 0.02752685546875 +10541 0.1087646484375 +10542 -0.03436279296875 +10543 -0.099395751953125 +10544 -0.099456787109375 +10545 -0.3182373046875 +10546 -0.1683349609375 +10547 -0.5489501953125 +10548 -0.235565185546875 +10549 -0.7738037109375 +10550 -0.284820556640625 +10551 -0.86383056640625 +10552 -0.30584716796875 +10553 -0.870391845703125 +10554 -0.304290771484375 +10555 -0.86895751953125 +10556 -0.2843017578125 +10557 -0.861053466796875 +10558 -0.240509033203125 +10559 -0.765869140625 +10560 -0.16937255859375 +10561 -0.5301513671875 +10562 -0.07305908203125 +10563 -0.214691162109375 +10564 0.035064697265625 +10565 0.137359619140625 +10566 0.13909912109375 +10567 0.474822998046875 +10568 0.22808837890625 +10569 0.76239013671875 +10570 0.29376220703125 +10571 0.867462158203125 +10572 0.336395263671875 +10573 0.870361328125 +10574 0.3525390625 +10575 0.86480712890625 +10576 0.343994140625 +10577 0.831817626953125 +10578 0.3184814453125 +10579 0.677581787109375 +10580 0.277923583984375 +10581 0.495880126953125 +10582 0.2281494140625 +10583 0.30767822265625 +10584 0.169891357421875 +10585 0.116180419921875 +10586 0.09326171875 +10587 -0.110748291015625 +10588 -0.00390625 +10589 -0.381805419921875 +10590 -0.10833740234375 +10591 -0.6572265625 +10592 -0.201385498046875 +10593 -0.857421875 +10594 -0.269805908203125 +10595 -0.870391845703125 +10596 -0.311492919921875 +10597 -0.870391845703125 +10598 -0.3349609375 +10599 -0.86444091796875 +10600 -0.351470947265625 +10601 -0.85723876953125 +10602 -0.35540771484375 +10603 -0.790008544921875 +10604 -0.3299560546875 +10605 -0.62847900390625 +10606 -0.27423095703125 +10607 -0.3956298828125 +10608 -0.198516845703125 +10609 -0.126708984375 +10610 -0.111419677734375 +10611 0.150115966796875 +10612 -0.0166015625 +10613 0.424041748046875 +10614 0.0775146484375 +10615 0.670623779296875 +10616 0.158905029296875 +10617 0.854522705078125 +10618 0.22210693359375 +10619 0.866485595703125 +10620 0.26239013671875 +10621 0.86920166015625 +10622 0.2855224609375 +10623 0.8653564453125 +10624 0.295806884765625 +10625 0.857147216796875 +10626 0.29241943359375 +10627 0.766845703125 +10628 0.277069091796875 +10629 0.628509521484375 +10630 0.24774169921875 +10631 0.462127685546875 +10632 0.21258544921875 +10633 0.297210693359375 +10634 0.17547607421875 +10635 0.14862060546875 +10636 0.129364013671875 +10637 -0.00537109375 +10638 0.07659912109375 +10639 -0.15753173828125 +10640 0.016082763671875 +10641 -0.31304931640625 +10642 -0.056549072265625 +10643 -0.48876953125 +10644 -0.126708984375 +10645 -0.6416015625 +10646 -0.186767578125 +10647 -0.751373291015625 +10648 -0.243988037109375 +10649 -0.84619140625 +10650 -0.293853759765625 +10651 -0.861297607421875 +10652 -0.32611083984375 +10653 -0.863250732421875 +10654 -0.33099365234375 +10655 -0.856597900390625 +10656 -0.312408447265625 +10657 -0.7498779296875 +10658 -0.288482666015625 +10659 -0.624542236328125 +10660 -0.252410888671875 +10661 -0.47808837890625 +10662 -0.186004638671875 +10663 -0.253387451171875 +10664 -0.103546142578125 +10665 0.003692626953125 +10666 -0.0263671875 +10667 0.2257080078125 +10668 0.0494384765625 +10669 0.427154541015625 +10670 0.13397216796875 +10671 0.643218994140625 +10672 0.224273681640625 +10673 0.855926513671875 +10674 0.302337646484375 +10675 0.870361328125 +10676 0.352752685546875 +10677 0.870361328125 +10678 0.3778076171875 +10679 0.862762451171875 +10680 0.37664794921875 +10681 0.79669189453125 +10682 0.346405029296875 +10683 0.595794677734375 +10684 0.2962646484375 +10685 0.362152099609375 +10686 0.23504638671875 +10687 0.1270751953125 +10688 0.169403076171875 +10689 -0.086944580078125 +10690 0.10003662109375 +10691 -0.2784423828125 +10692 0.01611328125 +10693 -0.484832763671875 +10694 -0.08831787109375 +10695 -0.729583740234375 +10696 -0.19744873046875 +10697 -0.86688232421875 +10698 -0.29156494140625 +10699 -0.870391845703125 +10700 -0.369140625 +10701 -0.86859130859375 +10702 -0.429534912109375 +10703 -0.86279296875 +10704 -0.461578369140625 +10705 -0.817962646484375 +10706 -0.451171875 +10707 -0.6116943359375 +10708 -0.3961181640625 +10709 -0.3128662109375 +10710 -0.3070068359375 +10711 0.039398193359375 +10712 -0.190155029296875 +10713 0.422821044921875 +10714 -0.055999755859375 +10715 0.805145263671875 +10716 0.074127197265625 +10717 0.870361328125 +10718 0.182373046875 +10719 0.870361328125 +10720 0.2650146484375 +10721 0.860015869140625 +10722 0.319580078125 +10723 0.727935791015625 +10724 0.344268798828125 +10725 0.48114013671875 +10726 0.34661865234375 +10727 0.2059326171875 +10728 0.3336181640625 +10729 -0.06103515625 +10730 0.308349609375 +10731 -0.29913330078125 +10732 0.266326904296875 +10733 -0.516204833984375 +10734 0.20281982421875 +10735 -0.7252197265625 +10736 0.125640869140625 +10737 -0.85980224609375 +10738 0.045623779296875 +10739 -0.870391845703125 +10740 -0.027862548828125 +10741 -0.870391845703125 +10742 -0.0794677734375 +10743 -0.858062744140625 +10744 -0.10772705078125 +10745 -0.673004150390625 +10746 -0.12884521484375 +10747 -0.42694091796875 +10748 -0.156524658203125 +10749 -0.2100830078125 +10750 -0.189910888671875 +10751 -0.0362548828125 +10752 -0.22015380859375 +10753 0.10943603515625 +10754 -0.24102783203125 +10755 0.23516845703125 +10756 -0.238311767578125 +10757 0.373687744140625 +10758 -0.212554931640625 +10759 0.517791748046875 +10760 -0.185272216796875 +10761 0.602783203125 +10762 -0.154510498046875 +10763 0.635711669921875 +10764 -0.108612060546875 +10765 0.655181884765625 +10766 -0.050872802734375 +10767 0.65948486328125 +10768 0.016082763671875 +10769 0.651275634765625 +10770 0.083892822265625 +10771 0.61846923828125 +10772 0.139892578125 +10773 0.53753662109375 +10774 0.17791748046875 +10775 0.404144287109375 +10776 0.194580078125 +10777 0.22186279296875 +10778 0.1903076171875 +10779 0.003997802734375 +10780 0.1712646484375 +10781 -0.22100830078125 +10782 0.14447021484375 +10783 -0.42449951171875 +10784 0.117156982421875 +10785 -0.579833984375 +10786 0.103912353515625 +10787 -0.641876220703125 +10788 0.10235595703125 +10789 -0.6177978515625 +10790 0.090179443359375 +10791 -0.575531005859375 +10792 0.065460205078125 +10793 -0.526336669921875 +10794 0.045928955078125 +10795 -0.42645263671875 +10796 0.04095458984375 +10797 -0.2581787109375 +10798 0.037994384765625 +10799 -0.068695068359375 +10800 0.023834228515625 +10801 0.09222412109375 +10802 0.004852294921875 +10803 0.232147216796875 +10804 -0.01531982421875 +10805 0.3509521484375 +10806 -0.046844482421875 +10807 0.410064697265625 +10808 -0.099700927734375 +10809 0.372955322265625 +10810 -0.16656494140625 +10811 0.2554931640625 +10812 -0.229400634765625 +10813 0.10711669921875 +10814 -0.281341552734375 +10815 -0.052886962890625 +10816 -0.309814453125 +10817 -0.186279296875 +10818 -0.295501708984375 +10819 -0.23291015625 +10820 -0.246185302734375 +10821 -0.209442138671875 +10822 -0.184478759765625 +10823 -0.174163818359375 +10824 -0.11322021484375 +10825 -0.126739501953125 +10826 -0.029022216796875 +10827 -0.048126220703125 +10828 0.058380126953125 +10829 0.0426025390625 +10830 0.13287353515625 +10831 0.10748291015625 +10832 0.1898193359375 +10833 0.1409912109375 +10834 0.2454833984375 +10835 0.19708251953125 +10836 0.297454833984375 +10837 0.273651123046875 +10838 0.326416015625 +10839 0.31768798828125 +10840 0.336029052734375 +10841 0.341094970703125 +10842 0.33489990234375 +10843 0.368011474609375 +10844 0.31500244140625 +10845 0.37249755859375 +10846 0.259307861328125 +10847 0.30072021484375 +10848 0.16943359375 +10849 0.1517333984375 +10850 0.0682373046875 +10851 -0.01470947265625 +10852 -0.03814697265625 +10853 -0.1883544921875 +10854 -0.148284912109375 +10855 -0.372711181640625 +10856 -0.24114990234375 +10857 -0.51397705078125 +10858 -0.300506591796875 +10859 -0.57177734375 +10860 -0.322052001953125 +10861 -0.53948974609375 +10862 -0.3104248046875 +10863 -0.43511962890625 +10864 -0.2774658203125 +10865 -0.2962646484375 +10866 -0.235748291015625 +10867 -0.161102294921875 +10868 -0.190093994140625 +10869 -0.0435791015625 +10870 -0.13970947265625 +10871 0.060394287109375 +10872 -0.090484619140625 +10873 0.13665771484375 +10874 -0.049102783203125 +10875 0.170135498046875 +10876 -0.015777587890625 +10877 0.16552734375 +10878 0.019256591796875 +10879 0.15728759765625 +10880 0.055694580078125 +10881 0.150787353515625 +10882 0.083160400390625 +10883 0.12200927734375 +10884 0.102813720703125 +10885 0.080108642578125 +10886 0.12188720703125 +10887 0.05126953125 +10888 0.14837646484375 +10889 0.062896728515625 +10890 0.173583984375 +10891 0.09271240234375 +10892 0.18048095703125 +10893 0.092987060546875 +10894 0.17401123046875 +10895 0.07855224609375 +10896 0.159637451171875 +10897 0.06427001953125 +10898 0.1328125 +10899 0.0347900390625 +10900 0.093994140625 +10901 -0.01171875 +10902 0.051239013671875 +10903 -0.056060791015625 +10904 0.0208740234375 +10905 -0.055511474609375 +10906 0.0045166015625 +10907 -0.010467529296875 +10908 -0.014617919921875 +10909 0.02508544921875 +10910 -0.0435791015625 +10911 0.025665283203125 +10912 -0.0718994140625 +10913 0.017333984375 +10914 -0.09765625 +10915 0.00189208984375 +10916 -0.123687744140625 +10917 -0.03173828125 +10918 -0.145263671875 +10919 -0.071502685546875 +10920 -0.1683349609375 +10921 -0.13543701171875 +10922 -0.191802978515625 +10923 -0.219970703125 +10924 -0.207672119140625 +10925 -0.300506591796875 +10926 -0.216552734375 +10927 -0.376312255859375 +10928 -0.208770751953125 +10929 -0.416107177734375 +10930 -0.1688232421875 +10931 -0.371124267578125 +10932 -0.09844970703125 +10933 -0.242279052734375 +10934 -0.012939453125 +10935 -0.069732666015625 +10936 0.07904052734375 +10937 0.125640869140625 +10938 0.16546630859375 +10939 0.31268310546875 +10940 0.232696533203125 +10941 0.45501708984375 +10942 0.280609130859375 +10943 0.554779052734375 +10944 0.308135986328125 +10945 0.61065673828125 +10946 0.310943603515625 +10947 0.610931396484375 +10948 0.28076171875 +10949 0.531463623046875 +10950 0.223419189453125 +10951 0.3883056640625 +10952 0.157806396484375 +10953 0.23468017578125 +10954 0.093292236328125 +10955 0.095245361328125 +10956 0.039794921875 +10957 -0.00396728515625 +10958 0.00341796875 +10959 -0.04852294921875 +10960 -0.0203857421875 +10961 -0.055145263671875 +10962 -0.04833984375 +10963 -0.0758056640625 +10964 -0.0889892578125 +10965 -0.138702392578125 +10966 -0.129425048828125 +10967 -0.209197998046875 +10968 -0.16943359375 +10969 -0.289031982421875 +10970 -0.20867919921875 +10971 -0.37884521484375 +10972 -0.239166259765625 +10973 -0.456329345703125 +10974 -0.259063720703125 +10975 -0.51641845703125 +10976 -0.25482177734375 +10977 -0.519287109375 +10978 -0.22454833984375 +10979 -0.458251953125 +10980 -0.186614990234375 +10981 -0.384796142578125 +10982 -0.150299072265625 +10983 -0.323699951171875 +10984 -0.114532470703125 +10985 -0.269287109375 +10986 -0.071258544921875 +10987 -0.1951904296875 +10988 -0.02099609375 +10989 -0.100006103515625 +10990 0.026031494140625 +10991 -0.01055908203125 +10992 0.07940673828125 +10993 0.1033935546875 +10994 0.140899658203125 +10995 0.24908447265625 +10996 0.191650390625 +10997 0.373199462890625 +10998 0.2252197265625 +10999 0.45806884765625 +11000 0.244140625 +11001 0.511474609375 +11002 0.259490966796875 +11003 0.565399169921875 +11004 0.268646240234375 +11005 0.61138916015625 +11006 0.25152587890625 +11007 0.5897216796875 +11008 0.205291748046875 +11009 0.4906005859375 +11010 0.13653564453125 +11011 0.33148193359375 +11012 0.058380126953125 +11013 0.147796630859375 +11014 -0.013763427734375 +11015 -0.01873779296875 +11016 -0.069366455078125 +11017 -0.140289306640625 +11018 -0.099029541015625 +11019 -0.191986083984375 +11020 -0.1058349609375 +11021 -0.184295654296875 +11022 -0.104888916015625 +11023 -0.161834716796875 +11024 -0.110595703125 +11025 -0.166595458984375 +11026 -0.1212158203125 +11027 -0.19390869140625 +11028 -0.1300048828125 +11029 -0.22442626953125 +11030 -0.144683837890625 +11031 -0.279754638671875 +11032 -0.158294677734375 +11033 -0.3389892578125 +11034 -0.154571533203125 +11035 -0.3543701171875 +11036 -0.141876220703125 +11037 -0.348175048828125 +11038 -0.122772216796875 +11039 -0.32598876953125 +11040 -0.0875244140625 +11041 -0.2581787109375 +11042 -0.035064697265625 +11043 -0.139801025390625 +11044 0.0289306640625 +11045 0.014617919921875 +11046 0.08270263671875 +11047 0.144378662109375 +11048 0.115875244140625 +11049 0.221038818359375 +11050 0.137298583984375 +11051 0.27069091796875 +11052 0.1470947265625 +11053 0.294036865234375 +11054 0.1524658203125 +11055 0.311767578125 +11056 0.15899658203125 +11057 0.339141845703125 +11058 0.161651611328125 +11059 0.360260009765625 +11060 0.155548095703125 +11061 0.360504150390625 +11062 0.129058837890625 +11063 0.308380126953125 +11064 0.07415771484375 +11065 0.18170166015625 +11066 0.0003662109375 +11067 0.0047607421875 +11068 -0.0743408203125 +11069 -0.17559814453125 +11070 -0.132720947265625 +11071 -0.3143310546875 +11072 -0.158111572265625 +11073 -0.36785888671875 +11074 -0.160125732421875 +11075 -0.36248779296875 +11076 -0.1556396484375 +11077 -0.343536376953125 +11078 -0.141143798828125 +11079 -0.3018798828125 +11080 -0.114288330078125 +11081 -0.231414794921875 +11082 -0.0697021484375 +11083 -0.117645263671875 +11084 -0.019683837890625 +11085 0.007049560546875 +11086 0.01495361328125 +11087 0.087982177734375 +11088 0.03936767578125 +11089 0.13946533203125 +11090 0.058074951171875 +11091 0.17425537109375 +11092 0.069183349609375 +11093 0.188201904296875 +11094 0.068572998046875 +11095 0.171234130859375 +11096 0.054107666015625 +11097 0.118438720703125 +11098 0.035736083984375 +11099 0.05706787109375 +11100 0.0140380859375 +11101 -0.010711669921875 +11102 -0.013580322265625 +11103 -0.0914306640625 +11104 -0.0386962890625 +11105 -0.162322998046875 +11106 -0.050537109375 +11107 -0.194549560546875 +11108 -0.03448486328125 +11109 -0.1492919921875 +11110 0.011383056640625 +11111 -0.02166748046875 +11112 0.06304931640625 +11113 0.124053955078125 +11114 0.09185791015625 +11115 0.211151123046875 +11116 0.098358154296875 +11117 0.240447998046875 +11118 0.09417724609375 +11119 0.242218017578125 +11120 0.083099365234375 +11121 0.2257080078125 +11122 0.066680908203125 +11123 0.194366455078125 +11124 0.03289794921875 +11125 0.115509033203125 +11126 -0.00909423828125 +11127 0.0128173828125 +11128 -0.03662109375 +11129 -0.053802490234375 +11130 -0.0594482421875 +11131 -0.110626220703125 +11132 -0.093292236328125 +11133 -0.199493408203125 +11134 -0.128387451171875 +11135 -0.29437255859375 +11136 -0.14105224609375 +11137 -0.33221435546875 +11138 -0.118896484375 +11139 -0.27972412109375 +11140 -0.080291748046875 +11141 -0.185333251953125 +11142 -0.055206298828125 +11143 -0.128204345703125 +11144 -0.04656982421875 +11145 -0.115692138671875 +11146 -0.0428466796875 +11147 -0.116455078125 +11148 -0.0350341796875 +11149 -0.105926513671875 +11150 -0.011993408203125 +11151 -0.053955078125 +11152 0.029571533203125 +11153 0.048797607421875 +11154 0.072601318359375 +11155 0.157318115234375 +11156 0.0946044921875 +11157 0.212005615234375 +11158 0.097625732421875 +11159 0.218475341796875 +11160 0.104400634765625 +11161 0.23724365234375 +11162 0.12890625 +11163 0.30535888671875 +11164 0.155609130859375 +11165 0.38128662109375 +11166 0.161865234375 +11167 0.404449462890625 +11168 0.1551513671875 +11169 0.3944091796875 +11170 0.14971923828125 +11171 0.3885498046875 +11172 0.136627197265625 +11173 0.362640380859375 +11174 0.099884033203125 +11175 0.27362060546875 +11176 0.038055419921875 +11177 0.11712646484375 +11178 -0.0291748046875 +11179 -0.054901123046875 +11180 -0.082275390625 +11181 -0.19085693359375 +11182 -0.1192626953125 +11183 -0.28570556640625 +11184 -0.1400146484375 +11185 -0.339263916015625 +11186 -0.154327392578125 +11187 -0.3775634765625 +11188 -0.179168701171875 +11189 -0.445709228515625 +11190 -0.21136474609375 +11191 -0.535064697265625 +11192 -0.2447509765625 +11193 -0.629058837890625 +11194 -0.26812744140625 +11195 -0.697601318359375 +11196 -0.267852783203125 +11197 -0.70391845703125 +11198 -0.241973876953125 +11199 -0.6424560546875 +11200 -0.182373046875 +11201 -0.491241455078125 +11202 -0.09503173828125 +11203 -0.265716552734375 +11204 -0.0018310546875 +11205 -0.023712158203125 +11206 0.084686279296875 +11207 0.201751708984375 +11208 0.151336669921875 +11209 0.375823974609375 +11210 0.193023681640625 +11211 0.485076904296875 +11212 0.22454833984375 +11213 0.56884765625 +11214 0.248779296875 +11215 0.634765625 +11216 0.248779296875 +11217 0.63763427734375 +11218 0.2203369140625 +11219 0.5660400390625 +11220 0.18310546875 +11221 0.4720458984375 +11222 0.156463623046875 +11223 0.40692138671875 +11224 0.143218994140625 +11225 0.3778076171875 +11226 0.140625 +11227 0.376953125 +11228 0.136627197265625 +11229 0.371978759765625 +11230 0.11260986328125 +11231 0.313140869140625 +11232 0.0626220703125 +11233 0.184417724609375 +11234 -0.003662109375 +11235 0.011199951171875 +11236 -0.07281494140625 +11237 -0.171051025390625 +11238 -0.135467529296875 +11239 -0.33740234375 +11240 -0.1856689453125 +11241 -0.47198486328125 +11242 -0.218048095703125 +11243 -0.560394287109375 +11244 -0.224365234375 +11245 -0.58056640625 +11246 -0.21038818359375 +11247 -0.54754638671875 +11248 -0.1939697265625 +11249 -0.508575439453125 +11250 -0.17364501953125 +11251 -0.459503173828125 +11252 -0.14727783203125 +11253 -0.394378662109375 +11254 -0.1297607421875 +11255 -0.35260009765625 +11256 -0.112762451171875 +11257 -0.31170654296875 +11258 -0.06842041015625 +11259 -0.197418212890625 +11260 0.003814697265625 +11261 -0.007965087890625 +11262 0.08538818359375 +11263 0.207489013671875 +11264 0.161407470703125 +11265 0.409210205078125 +11266 0.2230224609375 +11267 0.57208251953125 +11268 0.25848388671875 +11269 0.66595458984375 +11270 0.254425048828125 +11271 0.65875244140625 +11272 0.2174072265625 +11273 0.56744384765625 +11274 0.1632080078125 +11275 0.431396484375 +11276 0.109405517578125 +11277 0.29443359375 +11278 0.066314697265625 +11279 0.182464599609375 +11280 0.020721435546875 +11281 0.06365966796875 +11282 -0.03326416015625 +11283 -0.075958251953125 +11284 -0.07666015625 +11285 -0.189422607421875 +11286 -0.107696533203125 +11287 -0.271942138671875 +11288 -0.134246826171875 +11289 -0.342529296875 +11290 -0.141326904296875 +11291 -0.364166259765625 +11292 -0.12506103515625 +11293 -0.327239990234375 +11294 -0.10394287109375 +11295 -0.2769775390625 +11296 -0.094390869140625 +11297 -0.253692626953125 +11298 -0.09075927734375 +11299 -0.24365234375 +11300 -0.073211669921875 +11301 -0.1983642578125 +11302 -0.041015625 +11303 -0.116241455078125 +11304 -0.010223388671875 +11305 -0.036834716796875 +11306 0.0172119140625 +11307 0.034881591796875 +11308 0.03826904296875 +11309 0.09124755859375 +11310 0.043548583984375 +11311 0.10888671875 +11312 0.04852294921875 +11313 0.125518798828125 +11314 0.06005859375 +11315 0.15771484375 +11316 0.067138671875 +11317 0.17828369140625 +11318 0.063232421875 +11319 0.17108154296875 +11320 0.0458984375 +11321 0.129974365234375 +11322 0.026336669921875 +11323 0.082427978515625 +11324 0.004241943359375 +11325 0.027679443359375 +11326 -0.033172607421875 +11327 -0.065643310546875 +11328 -0.070404052734375 +11329 -0.15936279296875 +11330 -0.091033935546875 +11331 -0.21307373046875 +11332 -0.09832763671875 +11333 -0.234649658203125 +11334 -0.0826416015625 +11335 -0.2001953125 +11336 -0.047943115234375 +11337 -0.119171142578125 +11338 -0.00787353515625 +11339 -0.024749755859375 +11340 0.038604736328125 +11341 0.085784912109375 +11342 0.077392578125 +11343 0.178131103515625 +11344 0.093505859375 +11345 0.215576171875 +11346 0.09234619140625 +11347 0.211456298828125 +11348 0.0777587890625 +11349 0.17523193359375 +11350 0.05865478515625 +11351 0.128753662109375 +11352 0.0472412109375 +11353 0.1019287109375 +11354 0.035247802734375 +11355 0.0743408203125 +11356 0.021575927734375 +11357 0.04327392578125 +11358 0.018310546875 +11359 0.038177490234375 +11360 0.03253173828125 +11361 0.076263427734375 +11362 0.057586669921875 +11363 0.14105224609375 +11364 0.074737548828125 +11365 0.186431884765625 +11366 0.074432373046875 +11367 0.188812255859375 +11368 0.053009033203125 +11369 0.1390380859375 +11370 0.012451171875 +11371 0.041778564453125 +11372 -0.03759765625 +11373 -0.079437255859375 +11374 -0.095001220703125 +11375 -0.219390869140625 +11376 -0.155517578125 +11377 -0.367828369140625 +11378 -0.20697021484375 +11379 -0.494873046875 +11380 -0.2313232421875 +11381 -0.556243896484375 +11382 -0.21099853515625 +11383 -0.508697509765625 +11384 -0.15557861328125 +11385 -0.3756103515625 +11386 -0.090423583984375 +11387 -0.218902587890625 +11388 -0.025848388671875 +11389 -0.063751220703125 +11390 0.038726806640625 +11391 0.091552734375 +11392 0.0987548828125 +11393 0.23602294921875 +11394 0.143310546875 +11395 0.342987060546875 +11396 0.165313720703125 +11397 0.39520263671875 +11398 0.16339111328125 +11399 0.389373779296875 +11400 0.13702392578125 +11401 0.324249267578125 +11402 0.096099853515625 +11403 0.224090576171875 +11404 0.055084228515625 +11405 0.124267578125 +11406 0.01898193359375 +11407 0.037078857421875 +11408 -0.0009765625 +11409 -0.010101318359375 +11410 -0.005615234375 +11411 -0.019439697265625 +11412 -0.00787353515625 +11413 -0.022796630859375 +11414 -0.000152587890625 +11415 -0.001556396484375 +11416 0.022491455078125 +11417 0.056304931640625 +11418 0.042144775390625 +11419 0.106719970703125 +11420 0.037353515625 +11421 0.096893310546875 +11422 0.014617919921875 +11423 0.042694091796875 +11424 -0.010589599609375 +11425 -0.018035888671875 +11426 -0.034393310546875 +11427 -0.07586669921875 +11428 -0.052154541015625 +11429 -0.11944580078125 +11430 -0.068359375 +11431 -0.15972900390625 +11432 -0.08544921875 +11433 -0.202606201171875 +11434 -0.103607177734375 +11435 -0.24859619140625 +11436 -0.125946044921875 +11437 -0.30517578125 +11438 -0.14837646484375 +11439 -0.36212158203125 +11440 -0.159515380859375 +11441 -0.39141845703125 +11442 -0.143951416015625 +11443 -0.35528564453125 +11444 -0.1002197265625 +11445 -0.249969482421875 +11446 -0.03546142578125 +11447 -0.092864990234375 +11448 0.03924560546875 +11449 0.08905029296875 +11450 0.09918212890625 +11451 0.2352294921875 +11452 0.133392333984375 +11453 0.318817138671875 +11454 0.149566650390625 +11455 0.358642578125 +11456 0.144866943359375 +11457 0.347747802734375 +11458 0.119110107421875 +11459 0.28564453125 +11460 0.09307861328125 +11461 0.223175048828125 +11462 0.0816650390625 +11463 0.196746826171875 +11464 0.0740966796875 +11465 0.179840087890625 +11466 0.0634765625 +11467 0.155548095703125 +11468 0.06103515625 +11469 0.151214599609375 +11470 0.062744140625 +11471 0.156951904296875 +11472 0.051910400390625 +11473 0.13177490234375 +11474 0.038818359375 +11475 0.100799560546875 +11476 0.032928466796875 +11477 0.087127685546875 +11478 0.019622802734375 +11479 0.05487060546875 +11480 -0.00640869140625 +11481 -0.009002685546875 +11482 -0.044952392578125 +11483 -0.10400390625 +11484 -0.095733642578125 +11485 -0.229400634765625 +11486 -0.146728515625 +11487 -0.35552978515625 +11488 -0.181396484375 +11489 -0.441925048828125 +11490 -0.19378662109375 +11491 -0.473846435546875 +11492 -0.189453125 +11493 -0.464813232421875 +11494 -0.170166015625 +11495 -0.419097900390625 +11496 -0.134979248046875 +11497 -0.334320068359375 +11498 -0.091033935546875 +11499 -0.227935791015625 +11500 -0.0479736328125 +11501 -0.12347412109375 +11502 -0.008575439453125 +11503 -0.02764892578125 +11504 0.0345458984375 +11505 0.077667236328125 +11506 0.08984375 +11507 0.2132568359375 +11508 0.161285400390625 +11509 0.38885498046875 +11510 0.240081787109375 +11511 0.582794189453125 +11512 0.30133056640625 +11513 0.734039306640625 +11514 0.3277587890625 +11515 0.800140380859375 +11516 0.3182373046875 +11517 0.7783203125 +11518 0.27142333984375 +11519 0.6651611328125 +11520 0.186492919921875 +11521 0.45965576171875 +11522 0.078155517578125 +11523 0.199188232421875 +11524 -0.025848388671875 +11525 -0.050689697265625 +11526 -0.100555419921875 +11527 -0.23297119140625 +11528 -0.138427734375 +11529 -0.33013916015625 +11530 -0.151123046875 +11531 -0.368408203125 +11532 -0.1524658203125 +11533 -0.378936767578125 +11534 -0.149261474609375 +11535 -0.376983642578125 +11536 -0.149078369140625 +11537 -0.37969970703125 +11538 -0.153900146484375 +11539 -0.391510009765625 +11540 -0.151763916015625 +11541 -0.385345458984375 +11542 -0.134124755859375 +11543 -0.3419189453125 +11544 -0.110382080078125 +11545 -0.28289794921875 +11546 -0.099456787109375 +11547 -0.251617431640625 +11548 -0.109130859375 +11549 -0.266143798828125 +11550 -0.115875244140625 +11551 -0.273345947265625 +11552 -0.09466552734375 +11553 -0.216796875 +11554 -0.05926513671875 +11555 -0.128265380859375 +11556 -0.03607177734375 +11557 -0.068145751953125 +11558 -0.027862548828125 +11559 -0.0430908203125 +11560 -0.021881103515625 +11561 -0.024444580078125 +11562 -0.003509521484375 +11563 0.020721435546875 +11564 0.0413818359375 +11565 0.124481201171875 +11566 0.100067138671875 +11567 0.25787353515625 +11568 0.15411376953125 +11569 0.379119873046875 +11570 0.1998291015625 +11571 0.47991943359375 +11572 0.2230224609375 +11573 0.5281982421875 +11574 0.2178955078125 +11575 0.511138916015625 +11576 0.1964111328125 +11577 0.456207275390625 +11578 0.17779541015625 +11579 0.407470703125 +11580 0.170196533203125 +11581 0.383758544921875 +11582 0.161041259765625 +11583 0.35687255859375 +11584 0.143585205078125 +11585 0.31182861328125 +11586 0.11871337890625 +11587 0.250885009765625 +11588 0.082550048828125 +11589 0.1654052734375 +11590 0.026153564453125 +11591 0.035247802734375 +11592 -0.05157470703125 +11593 -0.142059326171875 +11594 -0.137054443359375 +11595 -0.33563232421875 +11596 -0.225433349609375 +11597 -0.5345458984375 +11598 -0.3092041015625 +11599 -0.72186279296875 +11600 -0.3614501953125 +11601 -0.836669921875 +11602 -0.3616943359375 +11603 -0.8326416015625 +11604 -0.31854248046875 +11605 -0.7296142578125 +11606 -0.256103515625 +11607 -0.582550048828125 +11608 -0.19561767578125 +11609 -0.440093994140625 +11610 -0.14666748046875 +11611 -0.324310302734375 +11612 -0.094329833984375 +11613 -0.20147705078125 +11614 -0.026641845703125 +11615 -0.044647216796875 +11616 0.037841796875 +11617 0.103973388671875 +11618 0.0806884765625 +11619 0.202392578125 +11620 0.1080322265625 +11621 0.264495849609375 +11622 0.1412353515625 +11623 0.338897705078125 +11624 0.188262939453125 +11625 0.443817138671875 +11626 0.234039306640625 +11627 0.545074462890625 +11628 0.267303466796875 +11629 0.6173095703125 +11630 0.284454345703125 +11631 0.6524658203125 +11632 0.291046142578125 +11633 0.66339111328125 +11634 0.28961181640625 +11635 0.6561279296875 +11636 0.269561767578125 +11637 0.606781005859375 +11638 0.224578857421875 +11639 0.501190185546875 +11640 0.16046142578125 +11641 0.352783203125 +11642 0.083770751953125 +11643 0.176544189453125 +11644 -0.00872802734375 +11645 -0.034820556640625 +11646 -0.106842041015625 +11647 -0.258209228515625 +11648 -0.188079833984375 +11649 -0.44244384765625 +11650 -0.247039794921875 +11651 -0.5753173828125 +11652 -0.281585693359375 +11653 -0.65203857421875 +11654 -0.278045654296875 +11655 -0.641632080078125 +11656 -0.24432373046875 +11657 -0.562164306640625 +11658 -0.19989013671875 +11659 -0.458038330078125 +11660 -0.154022216796875 +11661 -0.350555419921875 +11662 -0.11578369140625 +11663 -0.260528564453125 +11664 -0.086944580078125 +11665 -0.192108154296875 +11666 -0.065948486328125 +11667 -0.141937255859375 +11668 -0.049285888671875 +11669 -0.1021728515625 +11670 -0.0325927734375 +11671 -0.062896728515625 +11672 -0.01043701171875 +11673 -0.011932373046875 +11674 0.0224609375 +11675 0.062835693359375 +11676 0.060546875 +11677 0.148712158203125 +11678 0.10205078125 +11679 0.241729736328125 +11680 0.15008544921875 +11681 0.34912109375 +11682 0.198638916015625 +11683 0.457305908203125 +11684 0.237823486328125 +11685 0.54388427734375 +11686 0.251739501953125 +11687 0.5728759765625 +11688 0.223724365234375 +11689 0.506591796875 +11690 0.15643310546875 +11691 0.351226806640625 +11692 0.067291259765625 +11693 0.146514892578125 +11694 -0.02069091796875 +11695 -0.05523681640625 +11696 -0.0909423828125 +11697 -0.21624755859375 +11698 -0.142791748046875 +11699 -0.334930419921875 +11700 -0.172576904296875 +11701 -0.402984619140625 +11702 -0.18951416015625 +11703 -0.4412841796875 +11704 -0.21380615234375 +11705 -0.49578857421875 +11706 -0.242645263671875 +11707 -0.5601806640625 +11708 -0.26116943359375 +11709 -0.600738525390625 +11710 -0.254730224609375 +11711 -0.584228515625 +11712 -0.20947265625 +11713 -0.47930908203125 +11714 -0.1224365234375 +11715 -0.27935791015625 +11716 -0.00439453125 +11717 -0.0089111328125 +11718 0.11688232421875 +11719 0.268798828125 +11720 0.210235595703125 +11721 0.482818603515625 +11722 0.26275634765625 +11723 0.60369873046875 +11724 0.282806396484375 +11725 0.650421142578125 +11726 0.2884521484375 +11727 0.66400146484375 +11728 0.278411865234375 +11729 0.6414794921875 +11730 0.248138427734375 +11731 0.572540283203125 +11732 0.21563720703125 +11733 0.498138427734375 +11734 0.190277099609375 +11735 0.439453125 +11736 0.16278076171875 +11737 0.375518798828125 +11738 0.11907958984375 +11739 0.274505615234375 +11740 0.046966552734375 +11741 0.1087646484375 +11742 -0.04376220703125 +11743 -0.099395751953125 +11744 -0.139190673828125 +11745 -0.3182373046875 +11746 -0.239898681640625 +11747 -0.5489501953125 +11748 -0.338104248046875 +11749 -0.7738037109375 +11750 -0.410552978515625 +11751 -0.86383056640625 +11752 -0.442657470703125 +11753 -0.870391845703125 +11754 -0.442230224609375 +11755 -0.86895751953125 +11756 -0.4150390625 +11757 -0.861053466796875 +11758 -0.353485107421875 +11759 -0.765869140625 +11760 -0.252593994140625 +11761 -0.5301513671875 +11762 -0.115509033203125 +11763 -0.214691162109375 +11764 0.038848876953125 +11765 0.137359619140625 +11766 0.187957763671875 +11767 0.474822998046875 +11768 0.316253662109375 +11769 0.76239013671875 +11770 0.411865234375 +11771 0.867462158203125 +11772 0.47503662109375 +11773 0.870361328125 +11774 0.500701904296875 +11775 0.86480712890625 +11776 0.491455078125 +11777 0.831817626953125 +11778 0.4581298828125 +11779 0.677581787109375 +11780 0.403228759765625 +11781 0.495880126953125 +11782 0.335205078125 +11783 0.30767822265625 +11784 0.254730224609375 +11785 0.116180419921875 +11786 0.1463623046875 +11787 -0.110748291015625 +11788 0.006378173828125 +11789 -0.381805419921875 +11790 -0.145477294921875 +11791 -0.6572265625 +11792 -0.2813720703125 +11793 -0.857421875 +11794 -0.381439208984375 +11795 -0.870391845703125 +11796 -0.442657470703125 +11797 -0.870391845703125 +11798 -0.47796630859375 +11799 -0.86444091796875 +11800 -0.504364013671875 +11801 -0.85723876953125 +11802 -0.51324462890625 +11803 -0.790008544921875 +11804 -0.47894287109375 +11805 -0.62847900390625 +11806 -0.399810791015625 +11807 -0.3956298828125 +11808 -0.2911376953125 +11809 -0.126708984375 +11810 -0.16558837890625 +11811 0.150115966796875 +11812 -0.0283203125 +11813 0.424041748046875 +11814 0.1082763671875 +11815 0.670623779296875 +11816 0.22625732421875 +11817 0.854522705078125 +11818 0.317657470703125 +11819 0.866485595703125 +11820 0.375518798828125 +11821 0.86920166015625 +11822 0.40869140625 +11823 0.8653564453125 +11824 0.423736572265625 +11825 0.857147216796875 +11826 0.419403076171875 +11827 0.766845703125 +11828 0.398223876953125 +11829 0.628509521484375 +11830 0.35699462890625 +11831 0.462127685546875 +11832 0.307830810546875 +11833 0.297210693359375 +11834 0.25640869140625 +11835 0.14862060546875 +11836 0.19171142578125 +11837 -0.00537109375 +11838 0.1170654296875 +11839 -0.15753173828125 +11840 0.03045654296875 +11841 -0.31304931640625 +11842 -0.07501220703125 +11843 -0.48876953125 +11844 -0.177490234375 +11845 -0.6416015625 +11846 -0.26556396484375 +11847 -0.751373291015625 +11848 -0.35040283203125 +11849 -0.84619140625 +11850 -0.42523193359375 +11851 -0.861297607421875 +11852 -0.474517822265625 +11853 -0.863250732421875 +11854 -0.483428955078125 +11855 -0.856597900390625 +11856 -0.457733154296875 +11857 -0.7498779296875 +11858 -0.424713134765625 +11859 -0.624542236328125 +11860 -0.373870849609375 +11861 -0.47808837890625 +11862 -0.2774658203125 +11863 -0.253387451171875 +11864 -0.1568603515625 +11865 0.003692626953125 +11866 -0.044097900390625 +11867 0.2257080078125 +11868 0.066925048828125 +11869 0.427154541015625 +11870 0.19171142578125 +11871 0.643218994140625 +11872 0.325958251953125 +11873 0.855926513671875 +11874 0.4425048828125 +11875 0.870361328125 +11876 0.51806640625 +11877 0.870361328125 +11878 0.556121826171875 +11879 0.862762451171875 +11880 0.555389404296875 +11881 0.79669189453125 +11882 0.511444091796875 +11883 0.595794677734375 +11884 0.43804931640625 +11885 0.362152099609375 +11886 0.348358154296875 +11887 0.1270751953125 +11888 0.252288818359375 +11889 -0.086944580078125 +11890 0.15069580078125 +11891 -0.2784423828125 +11892 0.0269775390625 +11893 -0.484832763671875 +11894 -0.128021240234375 +11895 -0.729583740234375 +11896 -0.29058837890625 +11897 -0.86688232421875 +11898 -0.43096923828125 +11899 -0.870391845703125 +11900 -0.54693603515625 +11901 -0.86859130859375 +11902 -0.637603759765625 +11903 -0.86279296875 +11904 -0.686065673828125 +11905 -0.817962646484375 +11906 -0.67095947265625 +11907 -0.6116943359375 +11908 -0.588958740234375 +11909 -0.3128662109375 +11910 -0.455963134765625 +11911 0.039398193359375 +11912 -0.281402587890625 +11913 0.422821044921875 +11914 -0.0809326171875 +11915 0.805145263671875 +11916 0.113311767578125 +11917 0.870361328125 +11918 0.27447509765625 +11919 0.870361328125 +11920 0.3970947265625 +11921 0.860015869140625 +11922 0.4775390625 +11923 0.727935791015625 +11924 0.51318359375 +11925 0.48114013671875 +11926 0.51544189453125 +11927 0.2059326171875 +11928 0.4949951171875 +11929 -0.06103515625 +11930 0.456573486328125 +11931 -0.29913330078125 +11932 0.393341064453125 +11933 -0.516204833984375 +11934 0.298095703125 +11935 -0.7252197265625 +11936 0.1826171875 +11937 -0.85980224609375 +11938 0.06317138671875 +11939 -0.870391845703125 +11940 -0.046173095703125 +11941 -0.870391845703125 +11942 -0.122283935546875 +11943 -0.858062744140625 +11944 -0.16302490234375 +11945 -0.673004150390625 +11946 -0.193023681640625 +11947 -0.42694091796875 +11948 -0.23309326171875 +11949 -0.2100830078125 +11950 -0.282073974609375 +11951 -0.0362548828125 +11952 -0.32611083984375 +11953 0.10943603515625 +11954 -0.355712890625 +11955 0.23516845703125 +11956 -0.35125732421875 +11957 0.373687744140625 +11958 -0.3135986328125 +11959 0.517791748046875 +11960 -0.272491455078125 +11961 0.602783203125 +11962 -0.225616455078125 +11963 0.635711669921875 +11964 -0.157318115234375 +11965 0.655181884765625 +11966 -0.072418212890625 +11967 0.65948486328125 +11968 0.02508544921875 +11969 0.651275634765625 +11970 0.12347412109375 +11971 0.61846923828125 +11972 0.205047607421875 +11973 0.53753662109375 +11974 0.26104736328125 +11975 0.404144287109375 +11976 0.286712646484375 +11977 0.22186279296875 +11978 0.282470703125 +11979 0.003997802734375 +11980 0.2567138671875 +11981 -0.22100830078125 +11982 0.2191162109375 +11983 -0.42449951171875 +11984 0.179718017578125 +11985 -0.579833984375 +11986 0.158660888671875 +11987 -0.641876220703125 +11988 0.152862548828125 +11989 -0.6177978515625 +11990 0.13189697265625 +11991 -0.575531005859375 +11992 0.0933837890625 +11993 -0.526336669921875 +11994 0.0618896484375 +11995 -0.42645263671875 +11996 0.050567626953125 +11997 -0.2581787109375 +11998 0.042449951171875 +11999 -0.068695068359375 +12000 0.01959228515625 +12001 0.09222412109375 +12002 -0.009033203125 +12003 0.232147216796875 +12004 -0.03839111328125 +12005 0.3509521484375 +12006 -0.082305908203125 +12007 0.410064697265625 +12008 -0.154510498046875 +12009 0.372955322265625 +12010 -0.245025634765625 +12011 0.2554931640625 +12012 -0.32916259765625 +12013 0.10711669921875 +12014 -0.39764404296875 +12015 -0.052886962890625 +12016 -0.43341064453125 +12017 -0.186279296875 +12018 -0.410186767578125 +12019 -0.23291015625 +12020 -0.338775634765625 +12021 -0.209442138671875 +12022 -0.250457763671875 +12023 -0.174163818359375 +12024 -0.149261474609375 +12025 -0.126739501953125 +12026 -0.030731201171875 +12027 -0.048126220703125 +12028 0.09161376953125 +12029 0.0426025390625 +12030 0.195556640625 +12031 0.10748291015625 +12032 0.275177001953125 +12033 0.1409912109375 +12034 0.353485107421875 +12035 0.19708251953125 +12036 0.426361083984375 +12037 0.273651123046875 +12038 0.4659423828125 +12039 0.31768798828125 +12040 0.477813720703125 +12041 0.341094970703125 +12042 0.474609375 +12043 0.368011474609375 +12044 0.444793701171875 +12045 0.37249755859375 +12046 0.363677978515625 +12047 0.30072021484375 +12048 0.233612060546875 +12049 0.1517333984375 +12050 0.087799072265625 +12051 -0.01470947265625 +12052 -0.064971923828125 +12053 -0.1883544921875 +12054 -0.222747802734375 +12055 -0.372711181640625 +12056 -0.355072021484375 +12057 -0.51397705078125 +12058 -0.4384765625 +12059 -0.57177734375 +12060 -0.466888427734375 +12061 -0.53948974609375 +12062 -0.44720458984375 +12063 -0.43511962890625 +12064 -0.39678955078125 +12065 -0.2962646484375 +12066 -0.334075927734375 +12067 -0.161102294921875 +12068 -0.266204833984375 +12069 -0.0435791015625 +12070 -0.192047119140625 +12071 0.060394287109375 +12072 -0.1202392578125 +12073 0.13665771484375 +12074 -0.060455322265625 +12075 0.170135498046875 +12076 -0.012969970703125 +12077 0.16552734375 +12078 0.0364990234375 +12079 0.15728759765625 +12080 0.08758544921875 +12081 0.150787353515625 +12082 0.12530517578125 +12083 0.12200927734375 +12084 0.151458740234375 +12085 0.080108642578125 +12086 0.17669677734375 +12087 0.05126953125 +12088 0.21282958984375 +12089 0.062896728515625 +12090 0.247283935546875 +12091 0.09271240234375 +12092 0.255462646484375 +12093 0.092987060546875 +12094 0.244659423828125 +12095 0.07855224609375 +12096 0.22283935546875 +12097 0.06427001953125 +12098 0.183441162109375 +12099 0.0347900390625 +12100 0.127166748046875 +12101 -0.01171875 +12102 0.065673828125 +12103 -0.056060791015625 +12104 0.022613525390625 +12105 -0.055511474609375 +12106 0.00030517578125 +12107 -0.010467529296875 +12108 -0.025726318359375 +12109 0.02508544921875 +12110 -0.06585693359375 +12111 0.025665283203125 +12112 -0.104949951171875 +12113 0.017333984375 +12114 -0.140380859375 +12115 0.00189208984375 +12116 -0.176361083984375 +12117 -0.03173828125 +12118 -0.20611572265625 +12119 -0.071502685546875 +12120 -0.238372802734375 +12121 -0.13543701171875 +12122 -0.2716064453125 +12123 -0.219970703125 +12124 -0.29425048828125 +12125 -0.300506591796875 +12126 -0.307159423828125 +12127 -0.376312255859375 +12128 -0.296234130859375 +12129 -0.416107177734375 +12130 -0.238983154296875 +12131 -0.371124267578125 +12132 -0.13787841796875 +12133 -0.242279052734375 +12134 -0.015045166015625 +12135 -0.069732666015625 +12136 0.117034912109375 +12137 0.125640869140625 +12138 0.240997314453125 +12139 0.31268310546875 +12140 0.33709716796875 +12141 0.45501708984375 +12142 0.40521240234375 +12143 0.554779052734375 +12144 0.443878173828125 +12145 0.61065673828125 +12146 0.4468994140625 +12147 0.610931396484375 +12148 0.40228271484375 +12149 0.531463623046875 +12150 0.318511962890625 +12151 0.3883056640625 +12152 0.22308349609375 +12153 0.23468017578125 +12154 0.12957763671875 +12155 0.095245361328125 +12156 0.052398681640625 +12157 -0.00396728515625 +12158 0.0003662109375 +12159 -0.04852294921875 +12160 -0.033172607421875 +12161 -0.055145263671875 +12162 -0.07257080078125 +12163 -0.0758056640625 +12164 -0.130340576171875 +12165 -0.138702392578125 +12166 -0.187835693359375 +12167 -0.209197998046875 +12168 -0.24481201171875 +12169 -0.289031982421875 +12170 -0.300811767578125 +12171 -0.37884521484375 +12172 -0.34423828125 +12173 -0.456329345703125 +12174 -0.37249755859375 +12175 -0.51641845703125 +12176 -0.365966796875 +12177 -0.519287109375 +12178 -0.321868896484375 +12179 -0.458251953125 +12180 -0.26690673828125 +12181 -0.384796142578125 +12182 -0.21453857421875 +12183 -0.323699951171875 +12184 -0.163238525390625 +12185 -0.269287109375 +12186 -0.101226806640625 +12187 -0.1951904296875 +12188 -0.0291748046875 +12189 -0.100006103515625 +12190 0.03814697265625 +12191 -0.01055908203125 +12192 0.11468505859375 +12193 0.1033935546875 +12194 0.203094482421875 +12195 0.24908447265625 +12196 0.275970458984375 +12197 0.373199462890625 +12198 0.32403564453125 +12199 0.45806884765625 +12200 0.35101318359375 +12201 0.511474609375 +12202 0.373077392578125 +12203 0.565399169921875 +12204 0.386383056640625 +12205 0.61138916015625 +12206 0.36175537109375 +12207 0.5897216796875 +12208 0.295135498046875 +12209 0.4906005859375 +12210 0.196319580078125 +12211 0.33148193359375 +12212 0.0841064453125 +12213 0.147796630859375 +12214 -0.019500732421875 +12215 -0.01873779296875 +12216 -0.0994873046875 +12217 -0.140289306640625 +12218 -0.14239501953125 +12219 -0.191986083984375 +12220 -0.152587890625 +12221 -0.184295654296875 +12222 -0.15167236328125 +12223 -0.161834716796875 +12224 -0.160186767578125 +12225 -0.166595458984375 +12226 -0.17559814453125 +12227 -0.19390869140625 +12228 -0.188262939453125 +12229 -0.22442626953125 +12230 -0.209259033203125 +12231 -0.279754638671875 +12232 -0.228607177734375 +12233 -0.3389892578125 +12234 -0.223114013671875 +12235 -0.3543701171875 +12236 -0.204681396484375 +12237 -0.348175048828125 +12238 -0.176971435546875 +12239 -0.32598876953125 +12240 -0.12615966796875 +12241 -0.2581787109375 +12242 -0.050689697265625 +12243 -0.139801025390625 +12244 0.041290283203125 +12245 0.014617919921875 +12246 0.11865234375 +12247 0.144378662109375 +12248 0.16656494140625 +12249 0.221038818359375 +12250 0.1976318359375 +12251 0.27069091796875 +12252 0.21197509765625 +12253 0.294036865234375 +12254 0.21990966796875 +12255 0.311767578125 +12256 0.229217529296875 +12257 0.339141845703125 +12258 0.23236083984375 +12259 0.360260009765625 +12260 0.222503662109375 +12261 0.360504150390625 +12262 0.184326171875 +12263 0.308380126953125 +12264 0.10736083984375 +12265 0.18170166015625 +12266 0.004638671875 +12267 0.0047607421875 +12268 -0.099517822265625 +12269 -0.17559814453125 +12270 -0.18170166015625 +12271 -0.3143310546875 +12272 -0.21929931640625 +12273 -0.36785888671875 +12274 -0.225067138671875 +12275 -0.36248779296875 +12276 -0.221435546875 +12277 -0.343536376953125 +12278 -0.20355224609375 +12279 -0.3018798828125 +12280 -0.16827392578125 +12281 -0.231414794921875 +12282 -0.10833740234375 +12283 -0.117645263671875 +12284 -0.040283203125 +12285 0.007049560546875 +12286 0.007965087890625 +12287 0.087982177734375 +12288 0.0430908203125 +12289 0.13946533203125 +12290 0.071014404296875 +12291 0.17425537109375 +12292 0.089080810546875 +12293 0.188201904296875 +12294 0.091156005859375 +12295 0.171234130859375 +12296 0.073883056640625 +12297 0.118438720703125 +12298 0.051177978515625 +12299 0.05706787109375 +12300 0.02362060546875 +12301 -0.010711669921875 +12302 -0.01275634765625 +12303 -0.0914306640625 +12304 -0.04608154296875 +12305 -0.162322998046875 +12306 -0.06109619140625 +12307 -0.194549560546875 +12308 -0.037078857421875 +12309 -0.1492919921875 +12310 0.0286865234375 +12311 -0.02166748046875 +12312 0.10198974609375 +12313 0.124053955078125 +12314 0.14202880859375 +12315 0.211151123046875 +12316 0.149688720703125 +12317 0.240447998046875 +12318 0.141632080078125 +12319 0.242218017578125 +12320 0.123382568359375 +12321 0.2257080078125 +12322 0.0972900390625 +12323 0.194366455078125 +12324 0.046356201171875 +12325 0.115509033203125 +12326 -0.0162353515625 +12327 0.0128173828125 +12328 -0.0579833984375 +12329 -0.053802490234375 +12330 -0.092681884765625 +12331 -0.110626220703125 +12332 -0.142608642578125 +12333 -0.199493408203125 +12334 -0.1937255859375 +12335 -0.29437255859375 +12336 -0.2122802734375 +12337 -0.33221435546875 +12338 -0.180572509765625 +12339 -0.27972412109375 +12340 -0.124847412109375 +12341 -0.185333251953125 +12342 -0.08782958984375 +12343 -0.128204345703125 +12344 -0.0738525390625 +12345 -0.115692138671875 +12346 -0.0665283203125 +12347 -0.116455078125 +12348 -0.053131103515625 +12349 -0.105926513671875 +12350 -0.0179443359375 +12351 -0.053955078125 +12352 0.04364013671875 +12353 0.048797607421875 +12354 0.107177734375 +12355 0.157318115234375 +12356 0.140472412109375 +12357 0.212005615234375 +12358 0.1463623046875 +12359 0.218475341796875 +12360 0.157196044921875 +12361 0.23724365234375 +12362 0.19281005859375 +12363 0.30535888671875 +12364 0.231048583984375 +12365 0.38128662109375 +12366 0.23956298828125 +12367 0.404449462890625 +12368 0.2291259765625 +12369 0.3944091796875 +12370 0.2200927734375 +12371 0.3885498046875 +12372 0.199859619140625 +12373 0.362640380859375 +12374 0.14569091796875 +12375 0.27362060546875 +12376 0.05560302734375 +12377 0.11712646484375 +12378 -0.042236328125 +12379 -0.054901123046875 +12380 -0.119842529296875 +12381 -0.19085693359375 +12382 -0.17431640625 +12383 -0.28570556640625 +12384 -0.20538330078125 +12385 -0.339263916015625 +12386 -0.2269287109375 +12387 -0.3775634765625 +12388 -0.2630615234375 +12389 -0.445709228515625 +12390 -0.309234619140625 +12391 -0.535064697265625 +12392 -0.356719970703125 +12393 -0.629058837890625 +12394 -0.389556884765625 +12395 -0.697601318359375 +12396 -0.3883056640625 +12397 -0.70391845703125 +12398 -0.3502197265625 +12399 -0.6424560546875 +12400 -0.26385498046875 +12401 -0.491241455078125 +12402 -0.13775634765625 +12403 -0.265716552734375 +12404 -0.003204345703125 +12405 -0.023712158203125 +12406 0.121826171875 +12407 0.201751708984375 +12408 0.21844482421875 +12409 0.375823974609375 +12410 0.279327392578125 +12411 0.485076904296875 +12412 0.325439453125 +12413 0.56884765625 +12414 0.360809326171875 +12415 0.634765625 +12416 0.36126708984375 +12417 0.63763427734375 +12418 0.320770263671875 +12419 0.5660400390625 +12420 0.267364501953125 +12421 0.4720458984375 +12422 0.228729248046875 +12423 0.40692138671875 +12424 0.208953857421875 +12425 0.3778076171875 +12426 0.204071044921875 +12427 0.376953125 +12428 0.196990966796875 +12429 0.371978759765625 +12430 0.16131591796875 +12431 0.313140869140625 +12432 0.088653564453125 +12433 0.184417724609375 +12434 -0.007171630859375 +12435 0.011199951171875 +12436 -0.107025146484375 +12437 -0.171051025390625 +12438 -0.197418212890625 +12439 -0.33740234375 +12440 -0.26983642578125 +12441 -0.47198486328125 +12442 -0.316558837890625 +12443 -0.560394287109375 +12444 -0.325836181640625 +12445 -0.58056640625 +12446 -0.30584716796875 +12447 -0.54754638671875 +12448 -0.282073974609375 +12449 -0.508575439453125 +12450 -0.25244140625 +12451 -0.459503173828125 +12452 -0.213958740234375 +12453 -0.394378662109375 +12454 -0.187896728515625 +12455 -0.35260009765625 +12456 -0.162445068359375 +12457 -0.31170654296875 +12458 -0.097991943359375 +12459 -0.197418212890625 +12460 0.0062255859375 +12461 -0.007965087890625 +12462 0.12371826171875 +12463 0.207489013671875 +12464 0.23309326171875 +12465 0.409210205078125 +12466 0.32086181640625 +12467 0.57208251953125 +12468 0.370849609375 +12469 0.66595458984375 +12470 0.36590576171875 +12471 0.65875244140625 +12472 0.315216064453125 +12473 0.56744384765625 +12474 0.239990234375 +12475 0.431396484375 +12476 0.16387939453125 +12477 0.29443359375 +12478 0.100921630859375 +12479 0.182464599609375 +12480 0.034210205078125 +12481 0.06365966796875 +12482 -0.043548583984375 +12483 -0.075958251953125 +12484 -0.107025146484375 +12485 -0.189422607421875 +12486 -0.153533935546875 +12487 -0.271942138671875 +12488 -0.193115234375 +12489 -0.342529296875 +12490 -0.205902099609375 +12491 -0.364166259765625 +12492 -0.186676025390625 +12493 -0.327239990234375 +12494 -0.15966796875 +12495 -0.2769775390625 +12496 -0.146514892578125 +12497 -0.253692626953125 +12498 -0.139862060546875 +12499 -0.24365234375 +12500 -0.113861083984375 +12501 -0.1983642578125 +12502 -0.0677490234375 +12503 -0.116241455078125 +12504 -0.0228271484375 +12505 -0.036834716796875 +12506 0.01806640625 +12507 0.034881591796875 +12508 0.050689697265625 +12509 0.09124755859375 +12510 0.062408447265625 +12511 0.10888671875 +12512 0.07330322265625 +12513 0.125518798828125 +12514 0.0921630859375 +12515 0.15771484375 +12516 0.104339599609375 +12517 0.17828369140625 +12518 0.101104736328125 +12519 0.17108154296875 +12520 0.079193115234375 +12521 0.129974365234375 +12522 0.05328369140625 +12523 0.082427978515625 +12524 0.023040771484375 +12525 0.027679443359375 +12526 -0.02825927734375 +12527 -0.065643310546875 +12528 -0.080108642578125 +12529 -0.15936279296875 +12530 -0.110748291015625 +12531 -0.21307373046875 +12532 -0.124298095703125 +12533 -0.234649658203125 +12534 -0.107818603515625 +12535 -0.2001953125 +12536 -0.0662841796875 +12537 -0.119171142578125 +12538 -0.017364501953125 +12539 -0.024749755859375 +12540 0.04046630859375 +12541 0.085784912109375 +12542 0.088897705078125 +12543 0.178131103515625 +12544 0.1080322265625 +12545 0.215576171875 +12546 0.104949951171875 +12547 0.211456298828125 +12548 0.0845947265625 +12549 0.17523193359375 +12550 0.059326171875 +12551 0.128753662109375 +12552 0.045989990234375 +12553 0.1019287109375 +12554 0.0328369140625 +12555 0.0743408203125 +12556 0.018157958984375 +12557 0.04327392578125 +12558 0.018463134765625 +12559 0.038177490234375 +12560 0.043365478515625 +12561 0.076263427734375 +12562 0.08331298828125 +12563 0.14105224609375 +12564 0.1119384765625 +12565 0.186431884765625 +12566 0.115692138671875 +12567 0.188812255859375 +12568 0.089263916015625 +12569 0.1390380859375 +12570 0.035247802734375 +12571 0.041778564453125 +12572 -0.03302001953125 +12573 -0.079437255859375 +12574 -0.11260986328125 +12575 -0.219390869140625 +12576 -0.1976318359375 +12577 -0.367828369140625 +12578 -0.271087646484375 +12579 -0.494873046875 +12580 -0.307708740234375 +12581 -0.556243896484375 +12582 -0.282867431640625 +12583 -0.508697509765625 +12584 -0.209686279296875 +12585 -0.3756103515625 +12586 -0.12322998046875 +12587 -0.218902587890625 +12588 -0.037628173828125 +12589 -0.063751220703125 +12590 0.048187255859375 +12591 0.091552734375 +12592 0.12811279296875 +12593 0.23602294921875 +12594 0.1871337890625 +12595 0.342987060546875 +12596 0.215545654296875 +12597 0.39520263671875 +12598 0.211517333984375 +12599 0.389373779296875 +12600 0.174346923828125 +12601 0.324249267578125 +12602 0.117828369140625 +12603 0.224090576171875 +12604 0.06201171875 +12605 0.124267578125 +12606 0.0137939453125 +12607 0.037078857421875 +12608 -0.01129150390625 +12609 -0.010101318359375 +12610 -0.014617919921875 +12611 -0.019439697265625 +12612 -0.014373779296875 +12613 -0.022796630859375 +12614 -0.0001220703125 +12615 -0.001556396484375 +12616 0.0347900390625 +12617 0.056304931640625 +12618 0.06524658203125 +12619 0.106719970703125 +12620 0.0611572265625 +12621 0.096893310546875 +12622 0.031494140625 +12623 0.042694091796875 +12624 -0.002288818359375 +12625 -0.018035888671875 +12626 -0.03485107421875 +12627 -0.07586669921875 +12628 -0.05975341796875 +12629 -0.11944580078125 +12630 -0.08319091796875 +12631 -0.15972900390625 +12632 -0.108489990234375 +12633 -0.202606201171875 +12634 -0.1358642578125 +12635 -0.24859619140625 +12636 -0.16949462890625 +12637 -0.30517578125 +12638 -0.2034912109375 +12639 -0.36212158203125 +12640 -0.22186279296875 +12641 -0.39141845703125 +12642 -0.2030029296875 +12643 -0.35528564453125 +12644 -0.14471435546875 +12645 -0.249969482421875 +12646 -0.05682373046875 +12647 -0.092864990234375 +12648 0.04541015625 +12649 0.08905029296875 +12650 0.127655029296875 +12651 0.2352294921875 +12652 0.174713134765625 +12653 0.318817138671875 +12654 0.197265625 +12655 0.358642578125 +12656 0.191375732421875 +12657 0.347747802734375 +12658 0.15673828125 +12659 0.28564453125 +12660 0.1221923828125 +12661 0.223175048828125 +12662 0.10833740234375 +12663 0.196746826171875 +12664 0.10003662109375 +12665 0.179840087890625 +12666 0.087615966796875 +12667 0.155548095703125 +12668 0.0865478515625 +12669 0.151214599609375 +12670 0.09112548828125 +12671 0.156951904296875 +12672 0.0780029296875 +12673 0.13177490234375 +12674 0.061370849609375 +12675 0.100799560546875 +12676 0.054290771484375 +12677 0.087127685546875 +12678 0.036376953125 +12679 0.05487060546875 +12680 0.00018310546875 +12681 -0.009002685546875 +12682 -0.053955078125 +12683 -0.10400390625 +12684 -0.125640869140625 +12685 -0.229400634765625 +12686 -0.197967529296875 +12687 -0.35552978515625 +12688 -0.247894287109375 +12689 -0.441925048828125 +12690 -0.26702880859375 +12691 -0.473846435546875 +12692 -0.262939453125 +12693 -0.464813232421875 +12694 -0.238006591796875 +12695 -0.419097900390625 +12696 -0.19085693359375 +12697 -0.334320068359375 +12698 -0.131317138671875 +12699 -0.227935791015625 +12700 -0.072723388671875 +12701 -0.12347412109375 +12702 -0.018829345703125 +12703 -0.02764892578125 +12704 0.0406494140625 +12705 0.077667236328125 +12706 0.117523193359375 +12707 0.2132568359375 +12708 0.217315673828125 +12709 0.38885498046875 +12710 0.32769775390625 +12711 0.582794189453125 +12712 0.41400146484375 +12713 0.734039306640625 +12714 0.45208740234375 +12715 0.800140380859375 +12716 0.4403076171875 +12717 0.7783203125 +12718 0.376708984375 +12719 0.6651611328125 +12720 0.260711669921875 +12721 0.45965576171875 +12722 0.113525390625 +12723 0.199188232421875 +12724 -0.027679443359375 +12725 -0.050689697265625 +12726 -0.13055419921875 +12727 -0.23297119140625 +12728 -0.185211181640625 +12729 -0.33013916015625 +12730 -0.206512451171875 +12731 -0.368408203125 +12732 -0.21221923828125 +12733 -0.378936767578125 +12734 -0.21099853515625 +12735 -0.376983642578125 +12736 -0.212615966796875 +12737 -0.37969970703125 +12738 -0.21954345703125 +12739 -0.391510009765625 +12740 -0.216400146484375 +12741 -0.385345458984375 +12742 -0.19219970703125 +12743 -0.3419189453125 +12744 -0.15924072265625 +12745 -0.28289794921875 +12746 -0.14208984375 +12747 -0.251617431640625 +12748 -0.150970458984375 +12749 -0.266143798828125 +12750 -0.155670166015625 +12751 -0.273345947265625 +12752 -0.124114990234375 +12753 -0.216796875 +12754 -0.074310302734375 +12755 -0.128265380859375 +12756 -0.040557861328125 +12757 -0.068145751953125 +12758 -0.02655029296875 +12759 -0.0430908203125 +12760 -0.01605224609375 +12761 -0.024444580078125 +12762 0.0096435546875 +12763 0.020721435546875 +12764 0.0687255859375 +12765 0.124481201171875 +12766 0.144744873046875 +12767 0.25787353515625 +12768 0.213958740234375 +12769 0.379119873046875 +12770 0.271636962890625 +12771 0.47991943359375 +12772 0.29949951171875 +12773 0.5281982421875 +12774 0.290283203125 +12775 0.511138916015625 +12776 0.259552001953125 +12777 0.456207275390625 +12778 0.232330322265625 +12779 0.407470703125 +12780 0.21923828125 +12781 0.383758544921875 +12782 0.204254150390625 +12783 0.35687255859375 +12784 0.178863525390625 +12785 0.31182861328125 +12786 0.14434814453125 +12787 0.250885009765625 +12788 0.095794677734375 +12789 0.1654052734375 +12790 0.021759033203125 +12791 0.035247802734375 +12792 -0.079132080078125 +12793 -0.142059326171875 +12794 -0.1893310546875 +12795 -0.33563232421875 +12796 -0.3026123046875 +12797 -0.5345458984375 +12798 -0.409332275390625 +12799 -0.72186279296875 +12800 -0.474395751953125 +12801 -0.836669921875 +12802 -0.470855712890625 +12803 -0.8326416015625 +12804 -0.410552978515625 +12805 -0.7296142578125 +12806 -0.326019287109375 +12807 -0.582550048828125 +12808 -0.24591064453125 +12809 -0.440093994140625 +12810 -0.18292236328125 +12811 -0.324310302734375 +12812 -0.116241455078125 +12813 -0.20147705078125 +12814 -0.029205322265625 +12815 -0.044647216796875 +12816 0.053314208984375 +12817 0.103973388671875 +12818 0.106475830078125 +12819 0.202392578125 +12820 0.138916015625 +12821 0.264495849609375 +12822 0.180084228515625 +12823 0.338897705078125 +12824 0.24102783203125 +12825 0.443817138671875 +12826 0.301300048828125 +12827 0.545074462890625 +12828 0.34564208984375 +12829 0.6173095703125 +12830 0.369140625 +12831 0.6524658203125 +12832 0.379302978515625 +12833 0.66339111328125 +12834 0.3795166015625 +12835 0.6561279296875 +12836 0.355133056640625 +12837 0.606781005859375 +12838 0.29736328125 +12839 0.501190185546875 +12840 0.21392822265625 +12841 0.352783203125 +12842 0.113525390625 +12843 0.176544189453125 +12844 -0.008514404296875 +12845 -0.034820556640625 +12846 -0.1385498046875 +12847 -0.258209228515625 +12848 -0.24609375 +12849 -0.44244384765625 +12850 -0.323944091796875 +12851 -0.5753173828125 +12852 -0.36932373046875 +12853 -0.65203857421875 +12854 -0.3636474609375 +12855 -0.641632080078125 +12856 -0.31768798828125 +12857 -0.562164306640625 +12858 -0.257965087890625 +12859 -0.458038330078125 +12860 -0.197052001953125 +12861 -0.350555419921875 +12862 -0.147216796875 +12863 -0.260528564453125 +12864 -0.110687255859375 +12865 -0.192108154296875 +12866 -0.085235595703125 +12867 -0.141937255859375 +12868 -0.06585693359375 +12869 -0.1021728515625 +12870 -0.04638671875 +12871 -0.062896728515625 +12872 -0.019317626953125 +12873 -0.011932373046875 +12874 0.022796630859375 +12875 0.062835693359375 +12876 0.072479248046875 +12877 0.148712158203125 +12878 0.127410888671875 +12879 0.241729736328125 +12880 0.191925048828125 +12881 0.34912109375 +12882 0.25787353515625 +12883 0.457305908203125 +12884 0.311737060546875 +12885 0.54388427734375 +12886 0.331817626953125 +12887 0.5728759765625 +12888 0.295318603515625 +12889 0.506591796875 +12890 0.20574951171875 +12891 0.351226806640625 +12892 0.08673095703125 +12893 0.146514892578125 +12894 -0.030548095703125 +12895 -0.05523681640625 +12896 -0.123626708984375 +12897 -0.21624755859375 +12898 -0.19171142578125 +12899 -0.334930419921875 +12900 -0.22998046875 +12901 -0.402984619140625 +12902 -0.2510986328125 +12903 -0.4412841796875 +12904 -0.28271484375 +12905 -0.49578857421875 +12906 -0.321075439453125 +12907 -0.5601806640625 +12908 -0.345947265625 +12909 -0.600738525390625 +12910 -0.33734130859375 +12911 -0.584228515625 +12912 -0.2763671875 +12913 -0.47930908203125 +12914 -0.158905029296875 +12915 -0.27935791015625 +12916 0.00042724609375 +12917 -0.0089111328125 +12918 0.16387939453125 +12919 0.268798828125 +12920 0.2890625 +12921 0.482818603515625 +12922 0.358489990234375 +12923 0.60369873046875 +12924 0.383697509765625 +12925 0.650421142578125 +12926 0.38946533203125 +12927 0.66400146484375 +12928 0.3741455078125 +12929 0.6414794921875 +12930 0.33160400390625 +12931 0.572540283203125 +12932 0.286468505859375 +12933 0.498138427734375 +12934 0.25146484375 +12935 0.439453125 +12936 0.213958740234375 +12937 0.375518798828125 +12938 0.154815673828125 +12939 0.274505615234375 +12940 0.057342529296875 +12941 0.1087646484375 +12942 -0.065185546875 +12943 -0.099395751953125 +12944 -0.193878173828125 +12945 -0.3182373046875 +12946 -0.32958984375 +12947 -0.5489501953125 +12948 -0.461822509765625 +12949 -0.7738037109375 +12950 -0.5589599609375 +12951 -0.86383056640625 +12952 -0.601165771484375 +12953 -0.870391845703125 +12954 -0.599212646484375 +12955 -0.86895751953125 +12956 -0.56103515625 +12957 -0.861053466796875 +12958 -0.476318359375 +12959 -0.765869140625 +12960 -0.33831787109375 +12961 -0.5301513671875 +12962 -0.151275634765625 +12963 -0.214691162109375 +12964 0.05902099609375 +12965 0.137359619140625 +12966 0.2618408203125 +12967 0.474822998046875 +12968 0.43597412109375 +12969 0.76239013671875 +12970 0.565338134765625 +12971 0.867462158203125 +12972 0.65032958984375 +12973 0.870361328125 +12974 0.684112548828125 +12975 0.86480712890625 +12976 0.670013427734375 +12977 0.831817626953125 +12978 0.622772216796875 +12979 0.677581787109375 +12980 0.545928955078125 +12981 0.495880126953125 +12982 0.45074462890625 +12983 0.30767822265625 +12984 0.33856201171875 +12985 0.116180419921875 +12986 0.190399169921875 +12987 -0.110748291015625 +12988 0.002105712890625 +12989 -0.381805419921875 +12990 -0.200653076171875 +12991 -0.6572265625 +12992 -0.381988525390625 +12993 -0.857421875 +12994 -0.5162353515625 +12995 -0.870391845703125 +12996 -0.59918212890625 +12997 -0.870391845703125 +12998 -0.647064208984375 +12999 -0.86444091796875 +13000 -0.68133544921875 +13001 -0.85723876953125 +13002 -0.69110107421875 +13003 -0.790008544921875 +13004 -0.643890380859375 +13005 -0.62847900390625 +13006 -0.53790283203125 +13007 -0.3956298828125 +13008 -0.392913818359375 +13009 -0.126708984375 +13010 -0.225433349609375 +13011 0.150115966796875 +13012 -0.042510986328125 +13013 0.424041748046875 +13014 0.1396484375 +13015 0.670623779296875 +13016 0.297821044921875 +13017 0.854522705078125 +13018 0.421417236328125 +13019 0.866485595703125 +13020 0.501220703125 +13021 0.86920166015625 +13022 0.548187255859375 +13023 0.8653564453125 +13024 0.570404052734375 +13025 0.857147216796875 +13026 0.566192626953125 +13027 0.766845703125 +13028 0.5386962890625 +13029 0.628509521484375 +13030 0.483978271484375 +13031 0.462127685546875 +13032 0.417572021484375 +13033 0.297210693359375 +13034 0.346954345703125 +13035 0.14862060546875 +13036 0.258514404296875 +13037 -0.00537109375 +13038 0.156768798828125 +13039 -0.15753173828125 +13040 0.039581298828125 +13041 -0.31304931640625 +13042 -0.101409912109375 +13043 -0.48876953125 +13044 -0.238067626953125 +13045 -0.6416015625 +13046 -0.3555908203125 +13047 -0.751373291015625 +13048 -0.46783447265625 +13049 -0.84619140625 +13050 -0.566009521484375 +13051 -0.861297607421875 +13052 -0.630279541015625 +13053 -0.863250732421875 +13054 -0.6417236328125 +13055 -0.856597900390625 +13056 -0.608306884765625 +13057 -0.7498779296875 +13058 -0.565582275390625 +13059 -0.624542236328125 +13060 -0.49896240234375 +13061 -0.47808837890625 +13062 -0.371246337890625 +13063 -0.253387451171875 +13064 -0.211029052734375 +13065 0.003692626953125 +13066 -0.06121826171875 +13067 0.2257080078125 +13068 0.086456298828125 +13069 0.427154541015625 +13070 0.252777099609375 +13071 0.643218994140625 +13072 0.431976318359375 +13073 0.855926513671875 +13074 0.58770751953125 +13075 0.870361328125 +13076 0.6888427734375 +13077 0.870361328125 +13078 0.74005126953125 +13079 0.862762451171875 +13080 0.739532470703125 +13081 0.79669189453125 +13082 0.68133544921875 +13083 0.595794677734375 +13084 0.583831787109375 +13085 0.362152099609375 +13086 0.464630126953125 +13087 0.1270751953125 +13088 0.336944580078125 +13089 -0.086944580078125 +13090 0.20184326171875 +13091 -0.2784423828125 +13092 0.037109375 +13093 -0.484832763671875 +13094 -0.169586181640625 +13095 -0.729583740234375 +13096 -0.38653564453125 +13097 -0.86688232421875 +13098 -0.573944091796875 +13099 -0.870391845703125 +13100 -0.728851318359375 +13101 -0.86859130859375 +13102 -0.85009765625 +13103 -0.86279296875 +13104 -0.861114501953125 +13105 -0.817962646484375 +13106 -0.85894775390625 +13107 -0.6116943359375 +13108 -0.78582763671875 +13109 -0.3128662109375 +13110 -0.608367919921875 +13111 0.039398193359375 +13112 -0.375335693359375 +13113 0.422821044921875 +13114 -0.107696533203125 +13115 0.805145263671875 +13116 0.151580810546875 +13117 0.870361328125 +13118 0.366607666015625 +13119 0.870361328125 +13120 0.53009033203125 +13121 0.860015869140625 +13122 0.637237548828125 +13123 0.727935791015625 +13124 0.68450927734375 +13125 0.48114013671875 +13126 0.687225341796875 +13127 0.2059326171875 +13128 0.659698486328125 +13129 -0.06103515625 +13130 0.6082763671875 +13131 -0.29913330078125 +13132 0.5238037109375 +13133 -0.516204833984375 +13134 0.396575927734375 +13135 -0.7252197265625 +13136 0.24237060546875 +13137 -0.85980224609375 +13138 0.08294677734375 +13139 -0.870391845703125 +13140 -0.0628662109375 +13141 -0.870391845703125 +13142 -0.164154052734375 +13143 -0.858062744140625 +13144 -0.218109130859375 +13145 -0.673004150390625 +13146 -0.257720947265625 +13147 -0.42694091796875 +13148 -0.31085205078125 +13149 -0.2100830078125 +13150 -0.376007080078125 +13151 -0.0362548828125 +13152 -0.43463134765625 +13153 0.10943603515625 +13154 -0.474029541015625 +13155 0.23516845703125 +13156 -0.467987060546875 +13157 0.373687744140625 +13158 -0.41766357421875 +13159 0.517791748046875 +13160 -0.362884521484375 +13161 0.602783203125 +13162 -0.300445556640625 +13163 0.635711669921875 +13164 -0.209381103515625 +13165 0.655181884765625 +13166 -0.09613037109375 +13167 0.65948486328125 +13168 0.033966064453125 +13169 0.651275634765625 +13170 0.165191650390625 +13171 0.61846923828125 +13172 0.27392578125 +13173 0.53753662109375 +13174 0.3485107421875 +13175 0.404144287109375 +13176 0.382568359375 +13177 0.22186279296875 +13178 0.37664794921875 +13179 0.003997802734375 +13180 0.342010498046875 +13181 -0.22100830078125 +13182 0.291595458984375 +13183 -0.42449951171875 +13184 0.23883056640625 +13185 -0.579833984375 +13186 0.210723876953125 +13187 -0.641876220703125 +13188 0.203125 +13189 -0.6177978515625 +13190 0.17529296875 +13191 -0.575531005859375 +13192 0.123992919921875 +13193 -0.526336669921875 +13194 0.082183837890625 +13195 -0.42645263671875 +13196 0.067413330078125 +13197 -0.2581787109375 +13198 0.056915283203125 +13199 -0.068695068359375 +13200 0.026641845703125 +13201 0.09222412109375 +13202 -0.011322021484375 +13203 0.232147216796875 +13204 -0.05035400390625 +13205 0.3509521484375 +13206 -0.10894775390625 +13207 0.410064697265625 +13208 -0.20550537109375 +13209 0.372955322265625 +13210 -0.32666015625 +13211 0.2554931640625 +13212 -0.439361572265625 +13213 0.10711669921875 +13214 -0.531219482421875 +13215 -0.052886962890625 +13216 -0.579345703125 +13217 -0.186279296875 +13218 -0.548492431640625 +13219 -0.23291015625 +13220 -0.45318603515625 +13221 -0.209442138671875 +13222 -0.335235595703125 +13223 -0.174163818359375 +13224 -0.200042724609375 +13225 -0.126739501953125 +13226 -0.0416259765625 +13227 -0.048126220703125 +13228 0.121917724609375 +13229 0.0426025390625 +13230 0.260894775390625 +13231 0.10748291015625 +13232 0.36669921875 +13233 0.1409912109375 +13234 0.469207763671875 +13235 0.19708251953125 +13236 0.56396484375 +13237 0.273651123046875 +13238 0.615509033203125 +13239 0.31768798828125 +13240 0.630706787109375 +13241 0.341094970703125 +13242 0.62548828125 +13243 0.368011474609375 +13244 0.5853271484375 +13245 0.37249755859375 +13246 0.479156494140625 +13247 0.30072021484375 +13248 0.3101806640625 +13249 0.1517333984375 +13250 0.12060546875 +13251 -0.01470947265625 +13252 -0.078155517578125 +13253 -0.1883544921875 +13254 -0.283355712890625 +13255 -0.372711181640625 +13256 -0.456146240234375 +13257 -0.51397705078125 +13258 -0.56658935546875 +13259 -0.57177734375 +13260 -0.606781005859375 +13261 -0.53948974609375 +13262 -0.585174560546875 +13263 -0.43511962890625 +13264 -0.523590087890625 +13265 -0.2962646484375 +13266 -0.44525146484375 +13267 -0.161102294921875 +13268 -0.359100341796875 +13269 -0.0435791015625 +13270 -0.2637939453125 +13271 0.060394287109375 +13272 -0.17034912109375 +13273 0.13665771484375 +13274 -0.091217041015625 +13275 0.170135498046875 +13276 -0.026947021484375 +13277 0.16552734375 +13278 0.040252685546875 +13279 0.15728759765625 +13280 0.1097412109375 +13281 0.150787353515625 +13282 0.1622314453125 +13283 0.12200927734375 +13284 0.19976806640625 +13285 0.080108642578125 +13286 0.235595703125 +13287 0.05126953125 +13288 0.284393310546875 +13289 0.062896728515625 +13290 0.33013916015625 +13291 0.09271240234375 +13292 0.341644287109375 +13293 0.092987060546875 +13294 0.328094482421875 +13295 0.07855224609375 +13296 0.299591064453125 +13297 0.06427001953125 +13298 0.2479248046875 +13299 0.0347900390625 +13300 0.174072265625 +13301 -0.01171875 +13302 0.09295654296875 +13303 -0.056060791015625 +13304 0.03472900390625 +13305 -0.055511474609375 +13306 0.00250244140625 +13307 -0.010467529296875 +13308 -0.034454345703125 +13309 0.02508544921875 +13310 -0.089019775390625 +13311 0.025665283203125 +13312 -0.14166259765625 +13313 0.017333984375 +13314 -0.18902587890625 +13315 0.00189208984375 +13316 -0.236572265625 +13317 -0.03173828125 +13318 -0.2755126953125 +13319 -0.071502685546875 +13320 -0.3172607421875 +13321 -0.13543701171875 +13322 -0.359954833984375 +13323 -0.219970703125 +13324 -0.38861083984375 +13325 -0.300506591796875 +13326 -0.404388427734375 +13327 -0.376312255859375 +13328 -0.389068603515625 +13329 -0.416107177734375 +13330 -0.31341552734375 +13331 -0.371124267578125 +13332 -0.180694580078125 +13333 -0.242279052734375 +13334 -0.019744873046875 +13335 -0.069732666015625 +13336 0.153167724609375 +13337 0.125640869140625 +13338 0.315399169921875 +13339 0.31268310546875 +13340 0.4412841796875 +13341 0.45501708984375 +13342 0.53057861328125 +13343 0.554779052734375 +13344 0.581390380859375 +13345 0.61065673828125 +13346 0.5855712890625 +13347 0.610931396484375 +13348 0.527557373046875 +13349 0.531463623046875 +13350 0.41839599609375 +13351 0.3883056640625 +13352 0.293853759765625 +13353 0.23468017578125 +13354 0.17156982421875 +13355 0.095245361328125 +13356 0.070343017578125 +13357 -0.00396728515625 +13358 0.001708984375 +13359 -0.04852294921875 +13360 -0.04290771484375 +13361 -0.055145263671875 +13362 -0.095123291015625 +13363 -0.0758056640625 +13364 -0.171173095703125 +13365 -0.138702392578125 +13366 -0.2467041015625 +13367 -0.209197998046875 +13368 -0.321380615234375 +13369 -0.289031982421875 +13370 -0.394622802734375 +13371 -0.37884521484375 +13372 -0.451324462890625 +13373 -0.456329345703125 +13374 -0.48809814453125 +13375 -0.51641845703125 +13376 -0.47943115234375 +13377 -0.519287109375 +13378 -0.421783447265625 +13379 -0.458251953125 +13380 -0.34979248046875 +13381 -0.384796142578125 +13382 -0.281097412109375 +13383 -0.323699951171875 +13384 -0.21368408203125 +13385 -0.269287109375 +13386 -0.132293701171875 +13387 -0.1951904296875 +13388 -0.037841796875 +13389 -0.100006103515625 +13390 0.050445556640625 +13391 -0.01055908203125 +13392 0.150665283203125 +13393 0.1033935546875 +13394 0.2662353515625 +13395 0.24908447265625 +13396 0.361480712890625 +13397 0.373199462890625 +13398 0.42431640625 +13399 0.45806884765625 +13400 0.4595947265625 +13401 0.511474609375 +13402 0.48828125 +13403 0.565399169921875 +13404 0.505401611328125 +13405 0.61138916015625 +13406 0.473052978515625 +13407 0.5897216796875 +13408 0.385986328125 +13409 0.4906005859375 +13410 0.256927490234375 +13411 0.33148193359375 +13412 0.110382080078125 +13413 0.147796630859375 +13414 -0.0250244140625 +13415 -0.01873779296875 +13416 -0.129730224609375 +13417 -0.140289306640625 +13418 -0.1861572265625 +13419 -0.191986083984375 +13420 -0.199981689453125 +13421 -0.184295654296875 +13422 -0.19927978515625 +13423 -0.161834716796875 +13424 -0.210723876953125 +13425 -0.166595458984375 +13426 -0.230987548828125 +13427 -0.19390869140625 +13428 -0.24749755859375 +13429 -0.22442626953125 +13430 -0.274658203125 +13431 -0.279754638671875 +13432 -0.299530029296875 +13433 -0.3389892578125 +13434 -0.2919921875 +13435 -0.3543701171875 +13436 -0.267578125 +13437 -0.348175048828125 +13438 -0.2310791015625 +13439 -0.32598876953125 +13440 -0.164520263671875 +13441 -0.2581787109375 +13442 -0.065887451171875 +13443 -0.139801025390625 +13444 0.05419921875 +13445 0.014617919921875 +13446 0.155242919921875 +13447 0.144378662109375 +13448 0.217926025390625 +13449 0.221038818359375 +13450 0.258636474609375 +13451 0.27069091796875 +13452 0.27752685546875 +13453 0.294036865234375 +13454 0.2879638671875 +13455 0.311767578125 +13456 0.30010986328125 +13457 0.339141845703125 +13458 0.30419921875 +13459 0.360260009765625 +13460 0.2913818359375 +13461 0.360504150390625 +13462 0.241455078125 +13463 0.308380126953125 +13464 0.140533447265625 +13465 0.18170166015625 +13466 0.0057373046875 +13467 0.0047607421875 +13468 -0.13092041015625 +13469 -0.17559814453125 +13470 -0.238677978515625 +13471 -0.3143310546875 +13472 -0.28778076171875 +13473 -0.36785888671875 +13474 -0.295013427734375 +13475 -0.36248779296875 +13476 -0.289947509765625 +13477 -0.343536376953125 +13478 -0.266265869140625 +13479 -0.3018798828125 +13480 -0.219757080078125 +13481 -0.231414794921875 +13482 -0.140899658203125 +13483 -0.117645263671875 +13484 -0.05145263671875 +13485 0.007049560546875 +13486 0.011810302734375 +13487 0.087982177734375 +13488 0.057769775390625 +13489 0.13946533203125 +13490 0.094207763671875 +13491 0.17425537109375 +13492 0.117584228515625 +13493 0.188201904296875 +13494 0.120452880859375 +13495 0.171234130859375 +13496 0.0987548828125 +13497 0.118438720703125 +13498 0.06988525390625 +13499 0.05706787109375 +13500 0.03466796875 +13501 -0.010711669921875 +13502 -0.011688232421875 +13503 -0.0914306640625 +13504 -0.05438232421875 +13505 -0.162322998046875 +13506 -0.074432373046875 +13507 -0.194549560546875 +13508 -0.046051025390625 +13509 -0.1492919921875 +13510 0.034149169921875 +13511 -0.02166748046875 +13512 0.12384033203125 +13513 0.124053955078125 +13514 0.172515869140625 +13515 0.211151123046875 +13516 0.181304931640625 +13517 0.240447998046875 +13518 0.170928955078125 +13519 0.242218017578125 +13520 0.148223876953125 +13521 0.2257080078125 +13522 0.1160888671875 +13523 0.194366455078125 +13524 0.053436279296875 +13525 0.115509033203125 +13526 -0.0234375 +13527 0.0128173828125 +13528 -0.074371337890625 +13529 -0.053802490234375 +13530 -0.116455078125 +13531 -0.110626220703125 +13532 -0.177337646484375 +13533 -0.199493408203125 +13534 -0.239715576171875 +13535 -0.29437255859375 +13536 -0.261810302734375 +13537 -0.33221435546875 +13538 -0.221771240234375 +13539 -0.27972412109375 +13540 -0.152099609375 +13541 -0.185333251953125 +13542 -0.10577392578125 +13543 -0.128204345703125 +13544 -0.088134765625 +13545 -0.115692138671875 +13546 -0.078948974609375 +13547 -0.116455078125 +13548 -0.06243896484375 +13549 -0.105926513671875 +13550 -0.01910400390625 +13551 -0.053955078125 +13552 0.056793212890625 +13553 0.048797607421875 +13554 0.134979248046875 +13555 0.157318115234375 +13556 0.17559814453125 +13557 0.212005615234375 +13558 0.182159423828125 +13559 0.218475341796875 +13560 0.194793701171875 +13561 0.23724365234375 +13562 0.2381591796875 +13563 0.30535888671875 +13564 0.284820556640625 +13565 0.38128662109375 +13566 0.2947998046875 +13567 0.404449462890625 +13568 0.28204345703125 +13569 0.3944091796875 +13570 0.27239990234375 +13571 0.3885498046875 +13572 0.249267578125 +13573 0.362640380859375 +13574 0.18280029296875 +13575 0.27362060546875 +13576 0.070068359375 +13577 0.11712646484375 +13578 -0.052642822265625 +13579 -0.054901123046875 +13580 -0.14935302734375 +13581 -0.19085693359375 +13582 -0.216522216796875 +13583 -0.28570556640625 +13584 -0.253997802734375 +13585 -0.339263916015625 +13586 -0.279937744140625 +13587 -0.3775634765625 +13588 -0.3258056640625 +13589 -0.445709228515625 +13590 -0.38568115234375 +13591 -0.535064697265625 +13592 -0.44818115234375 +13593 -0.629058837890625 +13594 -0.49249267578125 +13595 -0.697601318359375 +13596 -0.49322509765625 +13597 -0.70391845703125 +13598 -0.446746826171875 +13599 -0.6424560546875 +13600 -0.33795166015625 +13601 -0.491241455078125 +13602 -0.177734375 +13603 -0.265716552734375 +13604 -0.00653076171875 +13605 -0.023712158203125 +13606 0.15252685546875 +13607 0.201751708984375 +13608 0.27508544921875 +13609 0.375823974609375 +13610 0.35174560546875 +13611 0.485076904296875 +13612 0.409881591796875 +13613 0.56884765625 +13614 0.454864501953125 +13615 0.634765625 +13616 0.455291748046875 +13617 0.63763427734375 +13618 0.4033203125 +13619 0.5660400390625 +13620 0.3353271484375 +13621 0.4720458984375 +13622 0.287109375 +13623 0.40692138671875 +13624 0.263824462890625 +13625 0.3778076171875 +13626 0.260223388671875 +13627 0.376953125 +13628 0.25396728515625 +13629 0.371978759765625 +13630 0.2105712890625 +13631 0.313140869140625 +13632 0.1190185546875 +13633 0.184417724609375 +13634 -0.002899169921875 +13635 0.011199951171875 +13636 -0.130462646484375 +13637 -0.171051025390625 +13638 -0.246337890625 +13639 -0.33740234375 +13640 -0.339447021484375 +13641 -0.47198486328125 +13642 -0.39984130859375 +13643 -0.560394287109375 +13644 -0.4122314453125 +13645 -0.58056640625 +13646 -0.38720703125 +13647 -0.54754638671875 +13648 -0.357757568359375 +13649 -0.508575439453125 +13650 -0.321136474609375 +13651 -0.459503173828125 +13652 -0.273345947265625 +13653 -0.394378662109375 +13654 -0.241943359375 +13655 -0.35260009765625 +13656 -0.211395263671875 +13657 -0.31170654296875 +13658 -0.130096435546875 +13659 -0.197418212890625 +13660 0.0030517578125 +13661 -0.007965087890625 +13662 0.153778076171875 +13663 0.207489013671875 +13664 0.294403076171875 +13665 0.409210205078125 +13666 0.407470703125 +13667 0.57208251953125 +13668 0.47198486328125 +13669 0.66595458984375 +13670 0.4656982421875 +13671 0.65875244140625 +13672 0.4005126953125 +13673 0.56744384765625 +13674 0.303955078125 +13675 0.431396484375 +13676 0.206634521484375 +13677 0.29443359375 +13678 0.126678466796875 +13679 0.182464599609375 +13680 0.04205322265625 +13681 0.06365966796875 +13682 -0.056884765625 +13683 -0.075958251953125 +13684 -0.137359619140625 +13685 -0.189422607421875 +13686 -0.1959228515625 +13687 -0.271942138671875 +13688 -0.245758056640625 +13689 -0.342529296875 +13690 -0.2611083984375 +13691 -0.364166259765625 +13692 -0.23529052734375 +13693 -0.327239990234375 +13694 -0.19976806640625 +13695 -0.2769775390625 +13696 -0.182647705078125 +13697 -0.253692626953125 +13698 -0.1744384765625 +13699 -0.24365234375 +13700 -0.1414794921875 +13701 -0.1983642578125 +13702 -0.082733154296875 +13703 -0.116241455078125 +13704 -0.025787353515625 +13705 -0.036834716796875 +13706 0.0257568359375 +13707 0.034881591796875 +13708 0.066497802734375 +13709 0.09124755859375 +13710 0.080078125 +13711 0.10888671875 +13712 0.0926513671875 +13713 0.125518798828125 +13714 0.115753173828125 +13715 0.15771484375 +13716 0.13043212890625 +13717 0.17828369140625 +13718 0.12542724609375 +13719 0.17108154296875 +13720 0.09649658203125 +13721 0.129974365234375 +13722 0.062744140625 +13723 0.082427978515625 +13724 0.023712158203125 +13725 0.027679443359375 +13726 -0.0423583984375 +13727 -0.065643310546875 +13728 -0.10882568359375 +13729 -0.15936279296875 +13730 -0.14752197265625 +13731 -0.21307373046875 +13732 -0.163848876953125 +13733 -0.234649658203125 +13734 -0.14111328125 +13735 -0.2001953125 +13736 -0.0858154296875 +13737 -0.119171142578125 +13738 -0.02099609375 +13739 -0.024749755859375 +13740 0.055267333984375 +13741 0.085784912109375 +13742 0.119110107421875 +13743 0.178131103515625 +13744 0.14501953125 +13745 0.215576171875 +13746 0.142242431640625 +13747 0.211456298828125 +13748 0.117401123046875 +13749 0.17523193359375 +13750 0.085662841796875 +13751 0.128753662109375 +13752 0.06781005859375 +13753 0.1019287109375 +13754 0.049591064453125 +13755 0.0743408203125 +13756 0.029052734375 +13757 0.04327392578125 +13758 0.026611328125 +13759 0.038177490234375 +13760 0.054168701171875 +13761 0.076263427734375 +13762 0.100189208984375 +13763 0.14105224609375 +13764 0.132568359375 +13765 0.186431884765625 +13766 0.13482666015625 +13767 0.188812255859375 +13768 0.100555419921875 +13769 0.1390380859375 +13770 0.033050537109375 +13771 0.041778564453125 +13772 -0.05133056640625 +13773 -0.079437255859375 +13774 -0.148956298828125 +13775 -0.219390869140625 +13776 -0.252655029296875 +13777 -0.367828369140625 +13778 -0.34161376953125 +13779 -0.494873046875 +13780 -0.385009765625 +13781 -0.556243896484375 +13782 -0.352691650390625 +13783 -0.508697509765625 +13784 -0.2608642578125 +13785 -0.3756103515625 +13786 -0.152618408203125 +13787 -0.218902587890625 +13788 -0.045379638671875 +13789 -0.063751220703125 +13790 0.06201171875 +13791 0.091552734375 +13792 0.161956787109375 +13793 0.23602294921875 +13794 0.235931396484375 +13795 0.342987060546875 +13796 0.27197265625 +13797 0.39520263671875 +13798 0.267791748046875 +13799 0.389373779296875 +13800 0.2225341796875 +13801 0.324249267578125 +13802 0.153076171875 +13803 0.224090576171875 +13804 0.084014892578125 +13805 0.124267578125 +13806 0.023834228515625 +13807 0.037078857421875 +13808 -0.008392333984375 +13809 -0.010101318359375 +13810 -0.01422119140625 +13811 -0.019439697265625 +13812 -0.015869140625 +13813 -0.022796630859375 +13814 -0.000396728515625 +13815 -0.001556396484375 +13816 0.040496826171875 +13817 0.056304931640625 +13818 0.07611083984375 +13819 0.106719970703125 +13820 0.069671630859375 +13821 0.096893310546875 +13822 0.0322265625 +13823 0.042694091796875 +13824 -0.010223388671875 +13825 -0.018035888671875 +13826 -0.0509033203125 +13827 -0.07586669921875 +13828 -0.081329345703125 +13829 -0.11944580078125 +13830 -0.109619140625 +13831 -0.15972900390625 +13832 -0.140167236328125 +13833 -0.202606201171875 +13834 -0.173370361328125 +13835 -0.24859619140625 +13836 -0.2147216796875 +13837 -0.30517578125 +13838 -0.256805419921875 +13839 -0.36212158203125 +13840 -0.279205322265625 +13841 -0.39141845703125 +13842 -0.254302978515625 +13843 -0.35528564453125 +13844 -0.17926025390625 +13845 -0.249969482421875 +13846 -0.066680908203125 +13847 -0.092864990234375 +13848 0.063934326171875 +13849 0.08905029296875 +13850 0.168609619140625 +13851 0.2352294921875 +13852 0.2279052734375 +13853 0.318817138671875 +13854 0.255615234375 +13855 0.358642578125 +13856 0.246734619140625 +13857 0.347747802734375 +13858 0.200927734375 +13859 0.28564453125 +13860 0.155242919921875 +13861 0.223175048828125 +13862 0.136199951171875 +13863 0.196746826171875 +13864 0.124481201171875 +13865 0.179840087890625 +13866 0.107757568359375 +13867 0.155548095703125 +13868 0.1058349609375 +13869 0.151214599609375 +13870 0.1114501953125 +13871 0.156951904296875 +13872 0.09466552734375 +13873 0.13177490234375 +13874 0.07366943359375 +13875 0.100799560546875 +13876 0.065185546875 +13877 0.087127685546875 +13878 0.04302978515625 +13879 0.05487060546875 +13880 -0.002349853515625 +13881 -0.009002685546875 +13882 -0.07061767578125 +13883 -0.10400390625 +13884 -0.16131591796875 +13885 -0.229400634765625 +13886 -0.252899169921875 +13887 -0.35552978515625 +13888 -0.31585693359375 +13889 -0.441925048828125 +13890 -0.3394775390625 +13891 -0.473846435546875 +13892 -0.33355712890625 +13893 -0.464813232421875 +13894 -0.3011474609375 +13895 -0.419097900390625 +13896 -0.240447998046875 +13897 -0.334320068359375 +13898 -0.16412353515625 +13899 -0.227935791015625 +13900 -0.089263916015625 +13901 -0.12347412109375 +13902 -0.020660400390625 +13903 -0.02764892578125 +13904 0.054931640625 +13905 0.077667236328125 +13906 0.152679443359375 +13907 0.2132568359375 +13908 0.279693603515625 +13909 0.38885498046875 +13910 0.420257568359375 +13911 0.582794189453125 +13912 0.52996826171875 +13913 0.734039306640625 +13914 0.57794189453125 +13915 0.800140380859375 +13916 0.5621337890625 +13917 0.7783203125 +13918 0.480072021484375 +13919 0.6651611328125 +13920 0.331024169921875 +13921 0.45965576171875 +13922 0.14215087890625 +13923 0.199188232421875 +13924 -0.038848876953125 +13925 -0.050689697265625 +13926 -0.170562744140625 +13927 -0.23297119140625 +13928 -0.24029541015625 +13929 -0.33013916015625 +13930 -0.26715087890625 +13931 -0.368408203125 +13932 -0.27386474609375 +13933 -0.378936767578125 +13934 -0.271636962890625 +13935 -0.376983642578125 +13936 -0.27301025390625 +13937 -0.37969970703125 +13938 -0.281219482421875 +13939 -0.391510009765625 +13940 -0.276580810546875 +13941 -0.385345458984375 +13942 -0.245025634765625 +13943 -0.3419189453125 +13944 -0.202301025390625 +13945 -0.28289794921875 +13946 -0.179962158203125 +13947 -0.251617431640625 +13948 -0.19110107421875 +13949 -0.266143798828125 +13950 -0.197052001953125 +13951 -0.273345947265625 +13952 -0.15667724609375 +13953 -0.216796875 +13954 -0.093017578125 +13955 -0.128265380859375 +13956 -0.050018310546875 +13957 -0.068145751953125 +13958 -0.032501220703125 +13959 -0.0430908203125 +13960 -0.019561767578125 +13961 -0.024444580078125 +13962 0.0128173828125 +13963 0.020721435546875 +13964 0.087982177734375 +13965 0.124481201171875 +13966 0.184844970703125 +13967 0.25787353515625 +13968 0.27301025390625 +13969 0.379119873046875 +13970 0.346466064453125 +13971 0.47991943359375 +13972 0.3818359375 +13973 0.5281982421875 +13974 0.369781494140625 +13975 0.511138916015625 +13976 0.330291748046875 +13977 0.456207275390625 +13978 0.29541015625 +13979 0.407470703125 +13980 0.27880859375 +13981 0.383758544921875 +13982 0.259918212890625 +13983 0.35687255859375 +13984 0.227752685546875 +13985 0.31182861328125 +13986 0.1839599609375 +13987 0.250885009765625 +13988 0.1221923828125 +13989 0.1654052734375 +13990 0.027801513671875 +13991 0.035247802734375 +13992 -0.101043701171875 +13993 -0.142059326171875 +13994 -0.241851806640625 +13995 -0.33563232421875 +13996 -0.38665771484375 +13997 -0.5345458984375 +13998 -0.52313232421875 +13999 -0.72186279296875 +14000 -0.606903076171875 +14001 -0.836669921875 +14002 -0.604278564453125 +14003 -0.8326416015625 +14004 -0.5296630859375 +14005 -0.7296142578125 +14006 -0.42303466796875 +14007 -0.582550048828125 +14008 -0.319793701171875 +14009 -0.440093994140625 +14010 -0.235992431640625 +14011 -0.324310302734375 +14012 -0.14703369140625 +14013 -0.20147705078125 +14014 -0.03326416015625 +14015 -0.044647216796875 +14016 0.0745849609375 +14017 0.103973388671875 +14018 0.145965576171875 +14019 0.202392578125 +14020 0.19097900390625 +14021 0.264495849609375 +14022 0.245025634765625 +14023 0.338897705078125 +14024 0.321380615234375 +14025 0.443817138671875 +14026 0.395172119140625 +14027 0.545074462890625 +14028 0.447906494140625 +14029 0.6173095703125 +14030 0.473724365234375 +14031 0.6524658203125 +14032 0.481964111328125 +14033 0.66339111328125 +14034 0.477020263671875 +14035 0.6561279296875 +14036 0.441436767578125 +14037 0.606781005859375 +14038 0.364898681640625 +14039 0.501190185546875 +14040 0.25714111328125 +14041 0.352783203125 +14042 0.12908935546875 +14043 0.176544189453125 +14044 -0.024566650390625 +14045 -0.034820556640625 +14046 -0.18701171875 +14047 -0.258209228515625 +14048 -0.321014404296875 +14049 -0.44244384765625 +14050 -0.417633056640625 +14051 -0.5753173828125 +14052 -0.473419189453125 +14053 -0.65203857421875 +14054 -0.4658203125 +14055 -0.641632080078125 +14056 -0.40802001953125 +14057 -0.562164306640625 +14058 -0.33233642578125 +14059 -0.458038330078125 +14060 -0.254241943359375 +14061 -0.350555419921875 +14062 -0.18890380859375 +14063 -0.260528564453125 +14064 -0.13934326171875 +14065 -0.192108154296875 +14066 -0.103118896484375 +14067 -0.141937255859375 +14068 -0.074493408203125 +14069 -0.1021728515625 +14070 -0.04620361328125 +14071 -0.062896728515625 +14072 -0.009368896484375 +14073 -0.011932373046875 +14074 0.044830322265625 +14075 0.062835693359375 +14076 0.107177734375 +14077 0.148712158203125 +14078 0.1748046875 +14079 0.241729736328125 +14080 0.253265380859375 +14081 0.34912109375 +14082 0.33343505859375 +14083 0.457305908203125 +14084 0.398895263671875 +14085 0.54388427734375 +14086 0.4219970703125 +14087 0.5728759765625 +14088 0.37371826171875 +14089 0.506591796875 +14090 0.258453369140625 +14091 0.351226806640625 +14092 0.106109619140625 +14093 0.146514892578125 +14094 -0.043853759765625 +14095 -0.05523681640625 +14096 -0.1629638671875 +14097 -0.21624755859375 +14098 -0.25018310546875 +14099 -0.334930419921875 +14100 -0.299407958984375 +14101 -0.402984619140625 +14102 -0.326568603515625 +14103 -0.4412841796875 +14104 -0.366668701171875 +14105 -0.49578857421875 +14106 -0.41497802734375 +14107 -0.5601806640625 +14108 -0.445831298828125 +14109 -0.600738525390625 +14110 -0.4339599609375 +14111 -0.584228515625 +14112 -0.355438232421875 +14113 -0.47930908203125 +14114 -0.20513916015625 +14115 -0.27935791015625 +14116 -0.001617431640625 +14117 -0.0089111328125 +14118 0.207183837890625 +14119 0.268798828125 +14120 0.36749267578125 +14121 0.482818603515625 +14122 0.457061767578125 +14123 0.60369873046875 +14124 0.490386962890625 +14125 0.650421142578125 +14126 0.498809814453125 +14127 0.66400146484375 +14128 0.48016357421875 +14129 0.6414794921875 +14130 0.42669677734375 +14131 0.572540283203125 +14132 0.36956787109375 +14133 0.498138427734375 +14134 0.32489013671875 +14135 0.439453125 +14136 0.2767333984375 +14137 0.375518798828125 +14138 0.200836181640625 +14139 0.274505615234375 +14140 0.076141357421875 +14141 0.1087646484375 +14142 -0.080474853515625 +14143 -0.099395751953125 +14144 -0.244964599609375 +14145 -0.3182373046875 +14146 -0.418365478515625 +14147 -0.5489501953125 +14148 -0.5872802734375 +14149 -0.7738037109375 +14150 -0.711578369140625 +14151 -0.86383056640625 +14152 -0.766082763671875 +14153 -0.870391845703125 +14154 -0.76434326171875 +14155 -0.86895751953125 +14156 -0.716400146484375 +14157 -0.861053466796875 +14158 -0.60919189453125 +14159 -0.765869140625 +14160 -0.434173583984375 +14161 -0.5301513671875 +14162 -0.19671630859375 +14163 -0.214691162109375 +14164 0.070465087890625 +14165 0.137359619140625 +14166 0.328399658203125 +14167 0.474822998046875 +14168 0.550140380859375 +14169 0.76239013671875 +14170 0.715240478515625 +14171 0.867462158203125 +14172 0.8240966796875 +14173 0.870361328125 +14174 0.85595703125 +14175 0.86480712890625 +14176 0.851287841796875 +14177 0.831817626953125 +14178 0.792327880859375 +14179 0.677581787109375 +14180 0.695709228515625 +14181 0.495880126953125 +14182 0.5755615234375 +14183 0.30767822265625 +14184 0.433624267578125 +14185 0.116180419921875 +14186 0.245849609375 +14187 -0.110748291015625 +14188 0.0069580078125 +14189 -0.381805419921875 +14190 -0.25048828125 +14191 -0.6572265625 +14192 -0.48101806640625 +14193 -0.857421875 +14194 -0.652008056640625 +14195 -0.870391845703125 +14196 -0.758056640625 +14197 -0.870391845703125 +14198 -0.8197021484375 +14199 -0.86444091796875 +14200 -0.855560302734375 +14201 -0.85723876953125 +14202 -0.85699462890625 +14203 -0.790008544921875 +14204 -0.818389892578125 +14205 -0.62847900390625 +14206 -0.684783935546875 +14207 -0.3956298828125 +14208 -0.5015869140625 +14209 -0.126708984375 +14210 -0.2896728515625 +14211 0.150115966796875 +14212 -0.0579833984375 +14213 0.424041748046875 +14214 0.1729736328125 +14215 0.670623779296875 +14216 0.373748779296875 +14217 0.854522705078125 +14218 0.530914306640625 +14219 0.866485595703125 +14220 0.63275146484375 +14221 0.86920166015625 +14222 0.693084716796875 +14223 0.8653564453125 +14224 0.722137451171875 +14225 0.857147216796875 +14226 0.71771240234375 +14227 0.766845703125 +14228 0.6837158203125 +14229 0.628509521484375 +14230 0.615081787109375 +14231 0.462127685546875 +14232 0.531494140625 +14233 0.297210693359375 +14234 0.442474365234375 +14235 0.14862060546875 +14236 0.3306884765625 +14237 -0.00537109375 +14238 0.201873779296875 +14239 -0.15753173828125 +14240 0.053314208984375 +14241 -0.31304931640625 +14242 -0.125579833984375 +14243 -0.48876953125 +14244 -0.299163818359375 +14245 -0.6416015625 +14246 -0.4486083984375 +14247 -0.751373291015625 +14248 -0.591461181640625 +14249 -0.84619140625 +14250 -0.716552734375 +14251 -0.861297607421875 +14252 -0.7987060546875 +14253 -0.863250732421875 +14254 -0.813934326171875 +14255 -0.856597900390625 +14256 -0.771514892578125 +14257 -0.7498779296875 +14258 -0.7154541015625 +14259 -0.624542236328125 +14260 -0.62908935546875 +14261 -0.47808837890625 +14262 -0.468017578125 +14263 -0.253387451171875 +14264 -0.26702880859375 +14265 0.003692626953125 +14266 -0.078125 +14267 0.2257080078125 +14268 0.108184814453125 +14269 0.427154541015625 +14270 0.316436767578125 +14271 0.643218994140625 +14272 0.539276123046875 +14273 0.855926513671875 +14274 0.73260498046875 +14275 0.870361328125 +14276 0.854949951171875 +14277 0.870361328125 +14278 0.8619384765625 +14279 0.862762451171875 +14280 0.861968994140625 +14281 0.79669189453125 +14282 0.852203369140625 +14283 0.595794677734375 +14284 0.732208251953125 +14285 0.362152099609375 +14286 0.5845947265625 +14287 0.1270751953125 +14288 0.425506591796875 +14289 -0.086944580078125 +14290 0.256561279296875 +14291 -0.2784423828125 +14292 0.051422119140625 +14293 -0.484832763671875 +14294 -0.204376220703125 +14295 -0.729583740234375 +14296 -0.472259521484375 +14297 -0.86688232421875 +14298 -0.704010009765625 +14299 -0.870391845703125 +14300 -0.8590087890625 +14301 -0.86859130859375 +14302 -0.870391845703125 +14303 -0.86279296875 +14304 -0.870391845703125 +14305 -0.817962646484375 +14306 -0.860076904296875 +14307 -0.6116943359375 +14308 -0.714996337890625 +14309 -0.3128662109375 +14310 -0.45672607421875 +14311 0.039398193359375 +14312 -0.14794921875 +14313 0.422821044921875 +14314 0.18505859375 +14315 0.805145263671875 +14316 0.490570068359375 +14317 0.870361328125 +14318 0.726226806640625 +14319 0.870361328125 +14320 0.857818603515625 +14321 0.860015869140625 +14322 0.866363525390625 +14323 0.727935791015625 +14324 0.8660888671875 +14325 0.48114013671875 +14326 0.85931396484375 +14327 0.2059326171875 +14328 0.79827880859375 +14329 -0.06103515625 +14330 0.67071533203125 +14331 -0.29913330078125 +14332 0.508636474609375 +14333 -0.516204833984375 +14334 0.303466796875 +14335 -0.7252197265625 +14336 0.076995849609375 +14337 -0.85980224609375 +14338 -0.14306640625 +14339 -0.870391845703125 +14340 -0.3330078125 +14341 -0.870391845703125 +14342 -0.453765869140625 +14343 -0.858062744140625 +14344 -0.502288818359375 +14345 -0.673004150390625 +14346 -0.52117919921875 +14347 -0.42694091796875 +14348 -0.547210693359375 +14349 -0.2100830078125 +14350 -0.58087158203125 +14351 -0.0362548828125 +14352 -0.60174560546875 +14353 0.10943603515625 +14354 -0.59686279296875 +14355 0.23516845703125 +14356 -0.53631591796875 +14357 0.373687744140625 +14358 -0.4244384765625 +14359 0.517791748046875 +14360 -0.313690185546875 +14361 0.602783203125 +14362 -0.202178955078125 +14363 0.635711669921875 +14364 -0.065216064453125 +14365 0.655181884765625 +14366 0.088134765625 +14367 0.65948486328125 +14368 0.2509765625 +14369 0.651275634765625 +14370 0.403900146484375 +14371 0.61846923828125 +14372 0.51824951171875 +14373 0.53753662109375 +14374 0.580902099609375 +14375 0.404144287109375 +14376 0.585784912109375 +14377 0.22186279296875 +14378 0.535858154296875 +14379 0.003997802734375 +14380 0.44769287109375 +14381 -0.22100830078125 +14382 0.339996337890625 +14383 -0.42449951171875 +14384 0.232025146484375 +14385 -0.579833984375 +14386 0.159820556640625 +14387 -0.641876220703125 +14388 0.12005615234375 +14389 -0.6177978515625 +14390 0.063140869140625 +14391 -0.575531005859375 +14392 -0.01397705078125 +14393 -0.526336669921875 +14394 -0.069610595703125 +14395 -0.42645263671875 +14396 -0.081817626953125 +14397 -0.2581787109375 +14398 -0.0797119140625 +14399 -0.068695068359375 +14400 -0.094573974609375 +14401 0.09222412109375 +14402 -0.112823486328125 +14403 0.232147216796875 +14404 -0.12786865234375 +14405 0.3509521484375 +14406 -0.164886474609375 +14407 0.410064697265625 +14408 -0.248992919921875 +14409 0.372955322265625 +14410 -0.365447998046875 +14411 0.2554931640625 +14412 -0.4747314453125 +14413 0.10711669921875 +14414 -0.562957763671875 +14415 -0.052886962890625 +14416 -0.602813720703125 +14417 -0.186279296875 +14418 -0.551025390625 +14419 -0.23291015625 +14420 -0.42626953125 +14421 -0.209442138671875 +14422 -0.281005859375 +14423 -0.174163818359375 +14424 -0.1217041015625 +14425 -0.126739501953125 +14426 0.059906005859375 +14427 -0.048126220703125 +14428 0.2423095703125 +14429 0.0426025390625 +14430 0.389678955078125 +14431 0.10748291015625 +14432 0.49285888671875 +14433 0.1409912109375 +14434 0.590911865234375 +14435 0.19708251953125 +14436 0.679962158203125 +14437 0.273651123046875 +14438 0.717193603515625 +14439 0.31768798828125 +14440 0.712646484375 +14441 0.341094970703125 +14442 0.687408447265625 +14443 0.368011474609375 +14444 0.6241455078125 +14445 0.37249755859375 +14446 0.484466552734375 +14447 0.30072021484375 +14448 0.2725830078125 +14449 0.1517333984375 +14450 0.041229248046875 +14451 -0.01470947265625 +14452 -0.195831298828125 +14453 -0.1883544921875 +14454 -0.43597412109375 +14455 -0.372711181640625 +14456 -0.631622314453125 +14457 -0.51397705078125 +14458 -0.746490478515625 +14459 -0.57177734375 +14460 -0.772003173828125 +14461 -0.53948974609375 +14462 -0.72015380859375 +14463 -0.43511962890625 +14464 -0.61962890625 +14465 -0.2962646484375 +14466 -0.500762939453125 +14467 -0.161102294921875 +14468 -0.3758544921875 +14469 -0.0435791015625 +14470 -0.24395751953125 +14471 0.060394287109375 +14472 -0.1195068359375 +14473 0.13665771484375 +14474 -0.018310546875 +14475 0.170135498046875 +14476 0.058929443359375 +14477 0.16552734375 +14478 0.1348876953125 +14479 0.15728759765625 +14480 0.209320068359375 +14481 0.150787353515625 +14482 0.2589111328125 +14483 0.12200927734375 +14484 0.28717041015625 +14485 0.080108642578125 +14486 0.311798095703125 +14487 0.05126953125 +14488 0.35235595703125 +14489 0.062896728515625 +14490 0.389923095703125 +14491 0.09271240234375 +14492 0.386444091796875 +14493 0.092987060546875 +14494 0.3543701171875 +14495 0.07855224609375 +14496 0.30706787109375 +14497 0.06427001953125 +14498 0.23480224609375 +14499 0.0347900390625 +14500 0.139129638671875 +14501 -0.01171875 +14502 0.038726806640625 +14503 -0.056060791015625 +14504 -0.028778076171875 +14505 -0.055511474609375 +14506 -0.05987548828125 +14507 -0.010467529296875 +14508 -0.09368896484375 +14509 0.02508544921875 +14510 -0.147186279296875 +14511 0.025665283203125 +14512 -0.197021484375 +14513 0.017333984375 +14514 -0.23974609375 +14515 0.00189208984375 +14516 -0.2828369140625 +14517 -0.03173828125 +14518 -0.3162841796875 +14519 -0.071502685546875 +14520 -0.35467529296875 +14521 -0.13543701171875 +14522 -0.396240234375 +14523 -0.219970703125 +14524 -0.423248291015625 +14525 -0.300506591796875 +14526 -0.437469482421875 +14527 -0.376312255859375 +14528 -0.4168701171875 +14529 -0.416107177734375 +14530 -0.325836181640625 +14531 -0.371124267578125 +14532 -0.168212890625 +14533 -0.242279052734375 +14534 0.021148681640625 +14535 -0.069732666015625 +14536 0.222869873046875 +14537 0.125640869140625 +14538 0.409912109375 +14539 0.31268310546875 +14540 0.55157470703125 +14541 0.45501708984375 +14542 0.648284912109375 +14543 0.554779052734375 +14544 0.698333740234375 +14545 0.61065673828125 +14546 0.692474365234375 +14547 0.610931396484375 +14548 0.612274169921875 +14549 0.531463623046875 +14550 0.471710205078125 +14551 0.3883056640625 +14552 0.314697265625 +14553 0.23468017578125 +14554 0.162933349609375 +14555 0.095245361328125 +14556 0.0394287109375 +14557 -0.00396728515625 +14558 -0.041839599609375 +14559 -0.04852294921875 +14560 -0.091522216796875 +14561 -0.055145263671875 +14562 -0.1484375 +14563 -0.0758056640625 +14564 -0.232818603515625 +14565 -0.138702392578125 +14566 -0.315521240234375 +14567 -0.209197998046875 +14568 -0.39666748046875 +14569 -0.289031982421875 +14570 -0.476043701171875 +14571 -0.37884521484375 +14572 -0.535797119140625 +14573 -0.456329345703125 +14574 -0.57232666015625 +14575 -0.51641845703125 +14576 -0.554962158203125 +14577 -0.519287109375 +14578 -0.479736328125 +14579 -0.458251953125 +14580 -0.389068603515625 +14581 -0.384796142578125 +14582 -0.30450439453125 +14583 -0.323699951171875 +14584 -0.2236328125 +14585 -0.269287109375 +14586 -0.127716064453125 +14587 -0.1951904296875 +14588 -0.01763916015625 +14589 -0.100006103515625 +14590 0.083526611328125 +14591 -0.01055908203125 +14592 0.1983642578125 +14593 0.1033935546875 +14594 0.331390380859375 +14595 0.24908447265625 +14596 0.439300537109375 +14597 0.373199462890625 +14598 0.507781982421875 +14599 0.45806884765625 +14600 0.543304443359375 +14601 0.511474609375 +14602 0.5721435546875 +14603 0.565399169921875 +14604 0.588531494140625 +14605 0.61138916015625 +14606 0.545989990234375 +14607 0.5897216796875 +14608 0.438201904296875 +14609 0.4906005859375 +14610 0.280792236328125 +14611 0.33148193359375 +14612 0.103759765625 +14613 0.147796630859375 +14614 -0.057861328125 +14615 -0.01873779296875 +14616 -0.180328369140625 +14617 -0.140289306640625 +14618 -0.242462158203125 +14619 -0.191986083984375 +14620 -0.251617431640625 +14621 -0.184295654296875 +14622 -0.24285888671875 +14623 -0.161834716796875 +14624 -0.249420166015625 +14625 -0.166595458984375 +14626 -0.267578125 +14627 -0.19390869140625 +14628 -0.282257080078125 +14629 -0.22442626953125 +14630 -0.311431884765625 +14631 -0.279754638671875 +14632 -0.33941650390625 +14633 -0.3389892578125 +14634 -0.32916259765625 +14635 -0.3543701171875 +14636 -0.2998046875 +14637 -0.348175048828125 +14638 -0.257171630859375 +14639 -0.32598876953125 +14640 -0.178955078125 +14641 -0.2581787109375 +14642 -0.062469482421875 +14643 -0.139801025390625 +14644 0.079559326171875 +14645 0.014617919921875 +14646 0.1976318359375 +14647 0.144378662109375 +14648 0.268341064453125 +14649 0.221038818359375 +14650 0.31219482421875 +14651 0.27069091796875 +14652 0.329681396484375 +14653 0.294036865234375 +14654 0.337554931640625 +14655 0.311767578125 +14656 0.348602294921875 +14657 0.339141845703125 +14658 0.351104736328125 +14659 0.360260009765625 +14660 0.334228515625 +14661 0.360504150390625 +14662 0.27288818359375 +14663 0.308380126953125 +14664 0.149749755859375 +14665 0.18170166015625 +14666 -0.014129638671875 +14667 0.0047607421875 +14668 -0.179290771484375 +14669 -0.17559814453125 +14670 -0.30780029296875 +14671 -0.3143310546875 +14672 -0.363067626953125 +14673 -0.36785888671875 +14674 -0.3662109375 +14675 -0.36248779296875 +14676 -0.354278564453125 +14677 -0.343536376953125 +14678 -0.3197021484375 +14679 -0.3018798828125 +14680 -0.257568359375 +14681 -0.231414794921875 +14682 -0.15625 +14683 -0.117645263671875 +14684 -0.04290771484375 +14685 0.007049560546875 +14686 0.036712646484375 +14687 0.087982177734375 +14688 0.093658447265625 +14689 0.13946533203125 +14690 0.137603759765625 +14691 0.17425537109375 +14692 0.16424560546875 +14693 0.188201904296875 +14694 0.164459228515625 +14695 0.171234130859375 +14696 0.13348388671875 +14697 0.118438720703125 +14698 0.0931396484375 +14699 0.05706787109375 +14700 0.044677734375 +14701 -0.010711669921875 +14702 -0.017578125 +14703 -0.0914306640625 +14704 -0.074981689453125 +14705 -0.162322998046875 +14706 -0.103759765625 +14707 -0.194549560546875 +14708 -0.071746826171875 +14709 -0.1492919921875 +14710 0.02545166015625 +14711 -0.02166748046875 +14712 0.13543701171875 +14713 0.124053955078125 +14714 0.19561767578125 +14715 0.211151123046875 +14716 0.20733642578125 +14717 0.240447998046875 +14718 0.196197509765625 +14719 0.242218017578125 +14720 0.170562744140625 +14721 0.2257080078125 +14722 0.1339111328125 +14723 0.194366455078125 +14724 0.059844970703125 +14725 0.115509033203125 +14726 -0.031646728515625 +14727 0.0128173828125 +14728 -0.090911865234375 +14729 -0.053802490234375 +14730 -0.139434814453125 +14731 -0.110626220703125 +14732 -0.211700439453125 +14733 -0.199493408203125 +14734 -0.286376953125 +14735 -0.29437255859375 +14736 -0.311767578125 +14737 -0.33221435546875 +14738 -0.26080322265625 +14739 -0.27972412109375 +14740 -0.17388916015625 +14741 -0.185333251953125 +14742 -0.11676025390625 +14743 -0.128204345703125 +14744 -0.096038818359375 +14745 -0.115692138671875 +14746 -0.086517333984375 +14747 -0.116455078125 +14748 -0.0684814453125 +14749 -0.105926513671875 +14750 -0.017578125 +14751 -0.053955078125 +14752 0.073455810546875 +14753 0.048797607421875 +14754 0.167236328125 +14755 0.157318115234375 +14756 0.214508056640625 +14757 0.212005615234375 +14758 0.219818115234375 +14759 0.218475341796875 +14760 0.23309326171875 +14761 0.23724365234375 +14762 0.2850341796875 +14763 0.30535888671875 +14764 0.341705322265625 +14765 0.38128662109375 +14766 0.35357666015625 +14767 0.404449462890625 +14768 0.337158203125 +14769 0.3944091796875 +14770 0.32373046875 +14771 0.3885498046875 +14772 0.29388427734375 +14773 0.362640380859375 +14774 0.2125244140625 +14775 0.27362060546875 +14776 0.076507568359375 +14777 0.11712646484375 +14778 -0.07098388671875 +14779 -0.054901123046875 +14780 -0.1871337890625 +14781 -0.19085693359375 +14782 -0.26763916015625 +14783 -0.28570556640625 +14784 -0.31231689453125 +14785 -0.339263916015625 +14786 -0.342620849609375 +14787 -0.3775634765625 +14788 -0.395843505859375 +14789 -0.445709228515625 +14790 -0.465057373046875 +14791 -0.535064697265625 +14792 -0.536895751953125 +14793 -0.629058837890625 +14794 -0.586944580078125 +14795 -0.697601318359375 +14796 -0.585235595703125 +14797 -0.70391845703125 +14798 -0.527587890625 +14799 -0.6424560546875 +14800 -0.39630126953125 +14801 -0.491241455078125 +14802 -0.20440673828125 +14803 -0.265716552734375 +14804 9.1552734375e-05 +14805 -0.023712158203125 +14806 0.189727783203125 +14807 0.201751708984375 +14808 0.33563232421875 +14809 0.375823974609375 +14810 0.4266357421875 +14811 0.485076904296875 +14812 0.495147705078125 +14813 0.56884765625 +14814 0.54754638671875 +14815 0.634765625 +14816 0.546722412109375 +14817 0.63763427734375 +14818 0.483428955078125 +14819 0.5660400390625 +14820 0.400848388671875 +14821 0.4720458984375 +14822 0.341552734375 +14823 0.40692138671875 +14824 0.311737060546875 +14825 0.3778076171875 +14826 0.30535888671875 +14827 0.376953125 +14828 0.2960205078125 +14829 0.371978759765625 +14830 0.243011474609375 +14831 0.313140869140625 +14832 0.13336181640625 +14833 0.184417724609375 +14834 -0.01177978515625 +14835 0.011199951171875 +14836 -0.16314697265625 +14837 -0.171051025390625 +14838 -0.3001708984375 +14839 -0.33740234375 +14840 -0.4097900390625 +14841 -0.47198486328125 +14842 -0.480255126953125 +14843 -0.560394287109375 +14844 -0.493560791015625 +14845 -0.58056640625 +14846 -0.462310791015625 +14847 -0.54754638671875 +14848 -0.42578125 +14849 -0.508575439453125 +14850 -0.380584716796875 +14851 -0.459503173828125 +14852 -0.32232666015625 +14853 -0.394378662109375 +14854 -0.284881591796875 +14855 -0.35260009765625 +14856 -0.24908447265625 +14857 -0.31170654296875 +14858 -0.151397705078125 +14859 -0.197418212890625 +14860 0.00970458984375 +14861 -0.007965087890625 +14862 0.19219970703125 +14863 0.207489013671875 +14864 0.3621826171875 +14865 0.409210205078125 +14866 0.498321533203125 +14867 0.57208251953125 +14868 0.574981689453125 +14869 0.66595458984375 +14870 0.56494140625 +14871 0.65875244140625 +14872 0.48291015625 +14873 0.56744384765625 +14874 0.362823486328125 +14875 0.431396484375 +14876 0.242401123046875 +14877 0.29443359375 +14878 0.14398193359375 +14879 0.182464599609375 +14880 0.04046630859375 +14881 0.06365966796875 +14882 -0.080047607421875 +14883 -0.075958251953125 +14884 -0.17730712890625 +14885 -0.189422607421875 +14886 -0.24725341796875 +14887 -0.271942138671875 +14888 -0.306182861328125 +14889 -0.342529296875 +14890 -0.322540283203125 +14891 -0.364166259765625 +14892 -0.288238525390625 +14893 -0.327239990234375 +14894 -0.242156982421875 +14895 -0.2769775390625 +14896 -0.218994140625 +14897 -0.253692626953125 +14898 -0.2071533203125 +14899 -0.24365234375 +14900 -0.165313720703125 +14901 -0.1983642578125 +14902 -0.09228515625 +14903 -0.116241455078125 +14904 -0.02203369140625 +14905 -0.036834716796875 +14906 0.041046142578125 +14907 0.034881591796875 +14908 0.090301513671875 +14909 0.09124755859375 +14910 0.105743408203125 +14911 0.10888671875 +14912 0.11962890625 +14913 0.125518798828125 +14914 0.146209716796875 +14915 0.15771484375 +14916 0.1622314453125 +14917 0.17828369140625 +14918 0.153961181640625 +14919 0.17108154296875 +14920 0.1163330078125 +14921 0.129974365234375 +14922 0.072967529296875 +14923 0.082427978515625 +14924 0.023406982421875 +14925 0.027679443359375 +14926 -0.059051513671875 +14927 -0.065643310546875 +14928 -0.141571044921875 +14929 -0.15936279296875 +14930 -0.189483642578125 +14931 -0.21307373046875 +14932 -0.209442138671875 +14933 -0.234649658203125 +14934 -0.180908203125 +14935 -0.2001953125 +14936 -0.111968994140625 +14937 -0.119171142578125 +14938 -0.031005859375 +14939 -0.024749755859375 +14940 0.06427001953125 +14941 0.085784912109375 +14942 0.14447021484375 +14943 0.178131103515625 +14944 0.1781005859375 +14945 0.215576171875 +14946 0.176422119140625 +14947 0.211456298828125 +14948 0.147430419921875 +14949 0.17523193359375 +14950 0.1097412109375 +14951 0.128753662109375 +14952 0.088836669921875 +14953 0.1019287109375 +14954 0.067169189453125 +14955 0.0743408203125 +14956 0.04229736328125 +14957 0.04327392578125 +14958 0.039337158203125 +14959 0.038177490234375 +14960 0.07293701171875 +14961 0.076263427734375 +14962 0.128936767578125 +14963 0.14105224609375 +14964 0.167877197265625 +14965 0.186431884765625 +14966 0.1695556640625 +14967 0.188812255859375 +14968 0.126129150390625 +14969 0.1390380859375 +14970 0.04168701171875 +14971 0.041778564453125 +14972 -0.06353759765625 +14973 -0.079437255859375 +14974 -0.18499755859375 +14975 -0.219390869140625 +14976 -0.31378173828125 +14977 -0.367828369140625 +14978 -0.42425537109375 +14979 -0.494873046875 +14980 -0.478424072265625 +14981 -0.556243896484375 +14982 -0.439178466796875 +14983 -0.508697509765625 +14984 -0.326446533203125 +14985 -0.3756103515625 +14986 -0.193206787109375 +14987 -0.218902587890625 +14988 -0.060943603515625 +14989 -0.063751220703125 +14990 0.07177734375 +14991 0.091552734375 +14992 0.195587158203125 +14993 0.23602294921875 +14994 0.287628173828125 +14995 0.342987060546875 +14996 0.3331298828125 +14997 0.39520263671875 +14998 0.329193115234375 +14999 0.389373779296875 +15000 0.27471923828125 +15001 0.324249267578125 +15002 0.19036865234375 +15003 0.224090576171875 +15004 0.106353759765625 +15005 0.124267578125 +15006 0.0330810546875 +15007 0.037078857421875 +15008 -0.00604248046875 +15009 -0.010101318359375 +15010 -0.012969970703125 +15011 -0.019439697265625 +15012 -0.014984130859375 +15013 -0.022796630859375 +15014 0.003753662109375 +15015 -0.001556396484375 +15016 0.053558349609375 +15017 0.056304931640625 +15018 0.096710205078125 +15019 0.106719970703125 +15020 0.087982177734375 +15021 0.096893310546875 +15022 0.041015625 +15023 0.042694091796875 +15024 -0.011749267578125 +15025 -0.018035888671875 +15026 -0.06219482421875 +15027 -0.07586669921875 +15028 -0.100555419921875 +15029 -0.11944580078125 +15030 -0.13616943359375 +15031 -0.15972900390625 +15032 -0.17401123046875 +15033 -0.202606201171875 +15034 -0.21441650390625 +15035 -0.24859619140625 +15036 -0.26373291015625 +15037 -0.30517578125 +15038 -0.31317138671875 +15039 -0.36212158203125 +15040 -0.338775634765625 +15041 -0.39141845703125 +15042 -0.308135986328125 +15043 -0.35528564453125 +15044 -0.218048095703125 +15045 -0.249969482421875 +15046 -0.083404541015625 +15047 -0.092864990234375 +15048 0.07269287109375 +15049 0.08905029296875 +15050 0.1983642578125 +15051 0.2352294921875 +15052 0.270599365234375 +15053 0.318817138671875 +15054 0.30548095703125 +15055 0.358642578125 +15056 0.2969970703125 +15057 0.347747802734375 +15058 0.24468994140625 +15059 0.28564453125 +15060 0.192047119140625 +15061 0.223175048828125 +15062 0.170166015625 +15063 0.196746826171875 +15064 0.156341552734375 +15065 0.179840087890625 +15066 0.136077880859375 +15067 0.155548095703125 +15068 0.13275146484375 +15069 0.151214599609375 +15070 0.13787841796875 +15071 0.156951904296875 +15072 0.116302490234375 +15073 0.13177490234375 +15074 0.089569091796875 +15075 0.100799560546875 +15076 0.07745361328125 +15077 0.087127685546875 +15078 0.049285888671875 +15079 0.05487060546875 +15080 -0.00604248046875 +15081 -0.009002685546875 +15082 -0.08807373046875 +15083 -0.10400390625 +15084 -0.196136474609375 +15085 -0.229400634765625 +15086 -0.3048095703125 +15087 -0.35552978515625 +15088 -0.37939453125 +15089 -0.441925048828125 +15090 -0.40728759765625 +15091 -0.473846435546875 +15092 -0.39996337890625 +15093 -0.464813232421875 +15094 -0.361114501953125 +15095 -0.419097900390625 +15096 -0.288665771484375 +15097 -0.334320068359375 +15098 -0.19757080078125 +15099 -0.227935791015625 +15100 -0.10797119140625 +15101 -0.12347412109375 +15102 -0.025634765625 +15103 -0.02764892578125 +15104 0.06488037109375 +15105 0.077667236328125 +15106 0.181610107421875 +15107 0.2132568359375 +15108 0.333648681640625 +15109 0.38885498046875 +15110 0.502349853515625 +15111 0.582794189453125 +15112 0.634002685546875 +15113 0.734039306640625 +15114 0.691253662109375 +15115 0.800140380859375 +15116 0.6717529296875 +15117 0.7783203125 +15118 0.572509765625 +15119 0.6651611328125 +15120 0.392486572265625 +15121 0.45965576171875 +15122 0.16473388671875 +15123 0.199188232421875 +15124 -0.05279541015625 +15125 -0.050689697265625 +15126 -0.20977783203125 +15127 -0.23297119140625 +15128 -0.291015625 +15129 -0.33013916015625 +15130 -0.320098876953125 +15131 -0.368408203125 +15132 -0.324951171875 +15133 -0.378936767578125 +15134 -0.319427490234375 +15135 -0.376983642578125 +15136 -0.319000244140625 +15137 -0.37969970703125 +15138 -0.32769775390625 +15139 -0.391510009765625 +15140 -0.32159423828125 +15141 -0.385345458984375 +15142 -0.283538818359375 +15143 -0.3419189453125 +15144 -0.23272705078125 +15145 -0.28289794921875 +15146 -0.207550048828125 +15147 -0.251617431640625 +15148 -0.223846435546875 +15149 -0.266143798828125 +15150 -0.2342529296875 +15151 -0.273345947265625 +15152 -0.18841552734375 +15153 -0.216796875 +15154 -0.1142578125 +15155 -0.128265380859375 +15156 -0.065185546875 +15157 -0.068145751953125 +15158 -0.046875 +15159 -0.0430908203125 +15160 -0.03369140625 +15161 -0.024444580078125 +15162 0.0037841796875 +15163 0.020721435546875 +15164 0.09417724609375 +15165 0.124481201171875 +15166 0.211822509765625 +15167 0.25787353515625 +15168 0.319610595703125 +15169 0.379119873046875 +15170 0.410186767578125 +15171 0.47991943359375 +15172 0.4549560546875 +15173 0.5281982421875 +15174 0.44244384765625 +15175 0.511138916015625 +15176 0.3968505859375 +15177 0.456207275390625 +15178 0.357147216796875 +15179 0.407470703125 +15180 0.339813232421875 +15181 0.383758544921875 +15182 0.319610595703125 +15183 0.35687255859375 +15184 0.283050537109375 +15185 0.31182861328125 +15186 0.231903076171875 +15187 0.250885009765625 +15188 0.158355712890625 +15189 0.1654052734375 +15190 0.04443359375 +15191 0.035247802734375 +15192 -0.112091064453125 +15193 -0.142059326171875 +15194 -0.283843994140625 +15195 -0.33563232421875 +15196 -0.461090087890625 +15197 -0.5345458984375 +15198 -0.628753662109375 +15199 -0.72186279296875 +15200 -0.732635498046875 +15201 -0.836669921875 +15202 -0.73150634765625 +15203 -0.8326416015625 +15204 -0.642852783203125 +15205 -0.7296142578125 +15206 -0.5152587890625 +15207 -0.582550048828125 +15208 -0.39178466796875 +15209 -0.440093994140625 +15210 -0.2918701171875 +15211 -0.324310302734375 +15212 -0.1854248046875 +15213 -0.20147705078125 +15214 -0.048309326171875 +15215 -0.044647216796875 +15216 0.08203125 +15217 0.103973388671875 +15218 0.168426513671875 +15219 0.202392578125 +15220 0.22320556640625 +15221 0.264495849609375 +15222 0.28955078125 +15223 0.338897705078125 +15224 0.38360595703125 +15225 0.443817138671875 +15226 0.4749755859375 +15227 0.545074462890625 +15228 0.541015625 +15229 0.6173095703125 +15230 0.574493408203125 +15231 0.6524658203125 +15232 0.586639404296875 +15233 0.66339111328125 +15234 0.58270263671875 +15235 0.6561279296875 +15236 0.54132080078125 +15237 0.606781005859375 +15238 0.449798583984375 +15239 0.501190185546875 +15240 0.31988525390625 +15241 0.352783203125 +15242 0.164825439453125 +15243 0.176544189453125 +15244 -0.021881103515625 +15245 -0.034820556640625 +15246 -0.219757080078125 +15247 -0.258209228515625 +15248 -0.3834228515625 +15249 -0.44244384765625 +15250 -0.501953125 +15251 -0.5753173828125 +15252 -0.571075439453125 +15253 -0.65203857421875 +15254 -0.563232421875 +15255 -0.641632080078125 +15256 -0.494384765625 +15257 -0.562164306640625 +15258 -0.40386962890625 +15259 -0.458038330078125 +15260 -0.3104248046875 +15261 -0.350555419921875 +15262 -0.23248291015625 +15263 -0.260528564453125 +15264 -0.173614501953125 +15265 -0.192108154296875 +15266 -0.1307373046875 +15267 -0.141937255859375 +15268 -0.0968017578125 +15269 -0.1021728515625 +15270 -0.06292724609375 +15271 -0.062896728515625 +15272 -0.01824951171875 +15273 -0.011932373046875 +15274 0.048004150390625 +15275 0.062835693359375 +15276 0.12457275390625 +15277 0.148712158203125 +15278 0.207855224609375 +15279 0.241729736328125 +15280 0.30426025390625 +15281 0.34912109375 +15282 0.401641845703125 +15283 0.457305908203125 +15284 0.480010986328125 +15285 0.54388427734375 +15286 0.50738525390625 +15287 0.5728759765625 +15288 0.4501953125 +15289 0.506591796875 +15290 0.3138427734375 +15291 0.351226806640625 +15292 0.133514404296875 +15293 0.146514892578125 +15294 -0.044403076171875 +15295 -0.05523681640625 +15296 -0.1864013671875 +15297 -0.21624755859375 +15298 -0.2911376953125 +15299 -0.334930419921875 +15300 -0.351287841796875 +15301 -0.402984619140625 +15302 -0.3853759765625 +15303 -0.4412841796875 +15304 -0.434173583984375 +15305 -0.49578857421875 +15306 -0.492034912109375 +15307 -0.5601806640625 +15308 -0.52899169921875 +15309 -0.600738525390625 +15310 -0.5155029296875 +15311 -0.584228515625 +15312 -0.42364501953125 +15313 -0.47930908203125 +15314 -0.24749755859375 +15315 -0.27935791015625 +15316 -0.008758544921875 +15317 -0.0089111328125 +15318 0.23651123046875 +15319 0.268798828125 +15320 0.425384521484375 +15321 0.482818603515625 +15322 0.53179931640625 +15323 0.60369873046875 +15324 0.5726318359375 +15325 0.650421142578125 +15326 0.584320068359375 +15327 0.66400146484375 +15328 0.564239501953125 +15329 0.6414794921875 +15330 0.50323486328125 +15331 0.572540283203125 +15332 0.437652587890625 +15333 0.498138427734375 +15334 0.386260986328125 +15335 0.439453125 +15336 0.33038330078125 +15337 0.375518798828125 +15338 0.241729736328125 +15339 0.274505615234375 +15340 0.095672607421875 +15341 0.1087646484375 +15342 -0.088043212890625 +15343 -0.099395751953125 +15344 -0.28125 +15345 -0.3182373046875 +15346 -0.485107421875 +15347 -0.5489501953125 +15348 -0.683929443359375 +15349 -0.7738037109375 +15350 -0.830718994140625 +15351 -0.86383056640625 +15352 -0.859039306640625 +15353 -0.870391845703125 +15354 -0.858978271484375 +15355 -0.86895751953125 +15356 -0.84075927734375 +15357 -0.861053466796875 +15358 -0.716583251953125 +15359 -0.765869140625 +15360 -0.512786865234375 +15361 -0.5301513671875 +15362 -0.23516845703125 +15363 -0.214691162109375 +15364 0.077911376953125 +15365 0.137359619140625 +15366 0.380279541015625 +15367 0.474822998046875 +15368 0.640106201171875 +15369 0.76239013671875 +15370 0.833221435546875 +15371 0.867462158203125 +15372 0.866058349609375 +15373 0.870361328125 +15374 0.870361328125 +15375 0.86480712890625 +15376 0.86700439453125 +15377 0.831817626953125 +15378 0.8585205078125 +15379 0.677581787109375 +15380 0.772491455078125 +15381 0.495880126953125 +15382 0.628936767578125 +15383 0.30767822265625 +15384 0.46282958984375 +15385 0.116180419921875 +15386 0.24456787109375 +15387 -0.110748291015625 +15388 -0.032806396484375 +15389 -0.381805419921875 +15390 -0.330718994140625 +15391 -0.6572265625 +15392 -0.59490966796875 +15393 -0.857421875 +15394 -0.786773681640625 +15395 -0.870391845703125 +15396 -0.859527587890625 +15397 -0.870391845703125 +15398 -0.866241455078125 +15399 -0.86444091796875 +15400 -0.870391845703125 +15401 -0.85723876953125 +15402 -0.870391845703125 +15403 -0.790008544921875 +15404 -0.86126708984375 +15405 -0.62847900390625 +15406 -0.746856689453125 +15407 -0.3956298828125 +15408 -0.522003173828125 +15409 -0.126708984375 +15410 -0.267120361328125 +15411 0.150115966796875 +15412 0.007171630859375 +15413 0.424041748046875 +15414 0.27655029296875 +15415 0.670623779296875 +15416 0.50604248046875 +15417 0.854522705078125 +15418 0.68017578125 +15419 0.866485595703125 +15420 0.785736083984375 +15421 0.86920166015625 +15422 0.840484619140625 +15423 0.8653564453125 +15424 0.854827880859375 +15425 0.857147216796875 +15426 0.835968017578125 +15427 0.766845703125 +15428 0.780670166015625 +15429 0.628509521484375 +15430 0.686431884765625 +15431 0.462127685546875 +15432 0.577606201171875 +15433 0.297210693359375 +15434 0.46600341796875 +15435 0.14862060546875 +15436 0.33074951171875 +15437 -0.00537109375 +15438 0.17864990234375 +15439 -0.15753173828125 +15440 0.006134033203125 +15441 -0.31304931640625 +15442 -0.20013427734375 +15443 -0.48876953125 +15444 -0.397674560546875 +15445 -0.6416015625 +15446 -0.564453125 +15447 -0.751373291015625 +15448 -0.722503662109375 +15449 -0.84619140625 +15450 -0.855010986328125 +15451 -0.861297607421875 +15452 -0.864349365234375 +15453 -0.863250732421875 +15454 -0.865020751953125 +15455 -0.856597900390625 +15456 -0.85833740234375 +15457 -0.7498779296875 +15458 -0.8143310546875 +15459 -0.624542236328125 +15460 -0.70550537109375 +15461 -0.47808837890625 +15462 -0.509429931640625 +15463 -0.253387451171875 +15464 -0.268157958984375 +15465 0.003692626953125 +15466 -0.04443359375 +15467 0.2257080078125 +15468 0.17352294921875 +15469 0.427154541015625 +15470 0.41595458984375 +15471 0.643218994140625 +15472 0.674530029296875 +15473 0.855926513671875 +15474 0.85906982421875 +15475 0.870361328125 +15476 0.870361328125 +15477 0.870361328125 +15478 0.870361328125 +15479 0.862762451171875 +15480 0.862823486328125 +15481 0.79669189453125 +15482 0.7880859375 +15483 0.595794677734375 +15484 0.6007080078125 +15485 0.362152099609375 +15486 0.396636962890625 +15487 0.1270751953125 +15488 0.196319580078125 +15489 -0.086944580078125 +15490 0.001708984375 +15491 -0.2784423828125 +15492 -0.220123291015625 +15493 -0.484832763671875 +15494 -0.4886474609375 +15495 -0.729583740234375 +15496 -0.7598876953125 +15497 -0.86688232421875 +15498 -0.8680419921875 +15499 -0.870391845703125 +15500 -0.870391845703125 +15501 -0.86859130859375 +15502 -0.868377685546875 +15503 -0.86279296875 +15504 -0.85955810546875 +15505 -0.817962646484375 +15506 -0.724853515625 +15507 -0.6116943359375 +15508 -0.45458984375 +15509 -0.3128662109375 +15510 -0.125885009765625 +15511 0.039398193359375 +15512 0.240203857421875 +15513 0.422821044921875 +15514 0.613006591796875 +15515 0.805145263671875 +15516 0.862945556640625 +15517 0.870361328125 +15518 0.870361328125 +15519 0.870361328125 +15520 0.8675537109375 +15521 0.860015869140625 +15522 0.85540771484375 +15523 0.727935791015625 +15524 0.6759033203125 +15525 0.48114013671875 +15526 0.44873046875 +15527 0.2059326171875 +15528 0.2142333984375 +15529 -0.06103515625 +15530 -0.008758544921875 +15531 -0.29913330078125 +15532 -0.226837158203125 +15533 -0.516204833984375 +15534 -0.45050048828125 +15535 -0.7252197265625 +15536 -0.656280517578125 +15537 -0.85980224609375 +15538 -0.815155029296875 +15539 -0.870391845703125 +15540 -0.86004638671875 +15541 -0.870391845703125 +15542 -0.858367919921875 +15543 -0.858062744140625 +15544 -0.77459716796875 +15545 -0.673004150390625 +15546 -0.619171142578125 +15547 -0.42694091796875 +15548 -0.47625732421875 +15549 -0.2100830078125 +15550 -0.355865478515625 +15551 -0.0362548828125 +15552 -0.242645263671875 +15553 0.10943603515625 +15554 -0.128448486328125 +15555 0.23516845703125 +15556 0.016326904296875 +15557 0.373687744140625 +15558 0.18359375 +15559 0.517791748046875 +15560 0.311431884765625 +15561 0.602783203125 +15562 0.403228759765625 +15563 0.635711669921875 +15564 0.490753173828125 +15565 0.655181884765625 +15566 0.56842041015625 +15567 0.65948486328125 +15568 0.634521484375 +15569 0.651275634765625 +15570 0.673919677734375 +15571 0.61846923828125 +15572 0.661346435546875 +15573 0.53753662109375 +15574 0.58966064453125 +15575 0.404144287109375 +15576 0.45965576171875 +15577 0.22186279296875 +15578 0.281890869140625 +15579 0.003997802734375 +15580 0.08172607421875 +15581 -0.22100830078125 +15582 -0.114410400390625 +15583 -0.42449951171875 +15584 -0.281005859375 +15585 -0.579833984375 +15586 -0.374847412109375 +15587 -0.641876220703125 +15588 -0.400177001953125 +15589 -0.6177978515625 +15590 -0.41656494140625 +15591 -0.575531005859375 +15592 -0.431121826171875 +15593 -0.526336669921875 +15594 -0.4002685546875 +15595 -0.42645263671875 +15596 -0.304290771484375 +15597 -0.2581787109375 +15598 -0.183441162109375 +15599 -0.068695068359375 +15600 -0.080718994140625 +15601 0.09222412109375 +15602 0.01300048828125 +15603 0.232147216796875 +15604 0.0992431640625 +15605 0.3509521484375 +15606 0.143402099609375 +15607 0.410064697265625 +15608 0.112091064453125 +15609 0.372955322265625 +15610 0.019378662109375 +15611 0.2554931640625 +15612 -0.0904541015625 +15613 0.10711669921875 +15614 -0.201446533203125 +15615 -0.052886962890625 +15616 -0.28021240234375 +15617 -0.186279296875 +15618 -0.273590087890625 +15619 -0.23291015625 +15620 -0.20050048828125 +15621 -0.209442138671875 +15622 -0.11865234375 +15623 -0.174163818359375 +15624 -0.0299072265625 +15625 -0.126739501953125 +15626 0.081817626953125 +15627 -0.048126220703125 +15628 0.19683837890625 +15629 0.0426025390625 +15630 0.2779541015625 +15631 0.10748291015625 +15632 0.319183349609375 +15633 0.1409912109375 +15634 0.37164306640625 +15635 0.19708251953125 +15636 0.4337158203125 +15637 0.273651123046875 +15638 0.45587158203125 +15639 0.31768798828125 +15640 0.45074462890625 +15641 0.341094970703125 +15642 0.4429931640625 +15643 0.368011474609375 +15644 0.409912109375 +15645 0.37249755859375 +15646 0.302490234375 +15647 0.30072021484375 +15648 0.121978759765625 +15649 0.1517333984375 +15650 -0.07275390625 +15651 -0.01470947265625 +15652 -0.27001953125 +15653 -0.1883544921875 +15654 -0.471588134765625 +15655 -0.372711181640625 +15656 -0.625091552734375 +15657 -0.51397705078125 +15658 -0.691253662109375 +15659 -0.57177734375 +15660 -0.663421630859375 +15661 -0.53948974609375 +15662 -0.558807373046875 +15663 -0.43511962890625 +15664 -0.413665771484375 +15665 -0.2962646484375 +15666 -0.265228271484375 +15667 -0.161102294921875 +15668 -0.12799072265625 +15669 -0.0435791015625 +15670 0.000335693359375 +15671 0.060394287109375 +15672 0.104583740234375 +15673 0.13665771484375 +15674 0.16864013671875 +15675 0.170135498046875 +15676 0.195220947265625 +15677 0.16552734375 +15678 0.21539306640625 +15679 0.15728759765625 +15680 0.232818603515625 +15681 0.150787353515625 +15682 0.2235107421875 +15683 0.12200927734375 +15684 0.195343017578125 +15685 0.080108642578125 +15686 0.172760009765625 +15687 0.05126953125 +15688 0.181732177734375 +15689 0.062896728515625 +15690 0.201385498046875 +15691 0.09271240234375 +15692 0.18707275390625 +15693 0.092987060546875 +15694 0.15380859375 +15695 0.07855224609375 +15696 0.116943359375 +15697 0.06427001953125 +15698 0.063262939453125 +15699 0.0347900390625 +15700 -0.007537841796875 +15701 -0.01171875 +15702 -0.07568359375 +15703 -0.056060791015625 +15704 -0.099212646484375 +15705 -0.055511474609375 +15706 -0.077239990234375 +15707 -0.010467529296875 +15708 -0.059967041015625 +15709 0.02508544921875 +15710 -0.070831298828125 +15711 0.025665283203125 +15712 -0.0845947265625 +15713 0.017333984375 +15714 -0.099395751953125 +15715 0.00189208984375 +15716 -0.125946044921875 +15717 -0.03173828125 +15718 -0.15325927734375 +15719 -0.071502685546875 +15720 -0.199188232421875 +15721 -0.13543701171875 +15722 -0.261260986328125 +15723 -0.219970703125 +15724 -0.317230224609375 +15725 -0.300506591796875 +15726 -0.3675537109375 +15727 -0.376312255859375 +15728 -0.38372802734375 +15729 -0.416107177734375 +15730 -0.320587158203125 +15731 -0.371124267578125 +15732 -0.180084228515625 +15733 -0.242279052734375 +15734 -0.001312255859375 +15735 -0.069732666015625 +15736 0.195159912109375 +15737 0.125640869140625 +15738 0.3792724609375 +15739 0.31268310546875 +15740 0.516265869140625 +15741 0.45501708984375 +15742 0.608184814453125 +15743 0.554779052734375 +15744 0.654083251953125 +15745 0.61065673828125 +15746 0.643341064453125 +15747 0.610931396484375 +15748 0.553741455078125 +15749 0.531463623046875 +15750 0.401397705078125 +15751 0.3883056640625 +15752 0.23779296875 +15753 0.23468017578125 +15754 0.087371826171875 +15755 0.095245361328125 +15756 -0.024139404296875 +15757 -0.00396728515625 +15758 -0.082122802734375 +15759 -0.04852294921875 +15760 -0.10162353515625 +15761 -0.055145263671875 +15762 -0.13140869140625 +15763 -0.0758056640625 +15764 -0.197784423828125 +15765 -0.138702392578125 +15766 -0.267578125 +15767 -0.209197998046875 +15768 -0.3424072265625 +15769 -0.289031982421875 +15770 -0.423065185546875 +15771 -0.37884521484375 +15772 -0.488677978515625 +15773 -0.456329345703125 +15774 -0.535003662109375 +15775 -0.51641845703125 +15776 -0.52484130859375 +15777 -0.519287109375 +15778 -0.452606201171875 +15779 -0.458251953125 +15780 -0.3680419921875 +15781 -0.384796142578125 +15782 -0.29547119140625 +15783 -0.323699951171875 +15784 -0.23028564453125 +15785 -0.269287109375 +15786 -0.148193359375 +15787 -0.1951904296875 +15788 -0.048431396484375 +15789 -0.100006103515625 +15790 0.04302978515625 +15791 -0.01055908203125 +15792 0.1546630859375 +15793 0.1033935546875 +15794 0.293243408203125 +15795 0.24908447265625 +15796 0.408233642578125 +15797 0.373199462890625 +15798 0.48309326171875 +15799 0.45806884765625 +15800 0.525604248046875 +15801 0.511474609375 +15802 0.56671142578125 +15803 0.565399169921875 +15804 0.598968505859375 +15805 0.61138916015625 +15806 0.5662841796875 +15807 0.5897216796875 +15808 0.46002197265625 +15809 0.4906005859375 +15810 0.297454833984375 +15811 0.33148193359375 +15812 0.112823486328125 +15813 0.147796630859375 +15814 -0.053741455078125 +15815 -0.01873779296875 +15816 -0.17535400390625 +15817 -0.140289306640625 +15818 -0.2281494140625 +15819 -0.191986083984375 +15820 -0.221923828125 +15821 -0.184295654296875 +15822 -0.1990966796875 +15823 -0.161834716796875 +15824 -0.199676513671875 +15825 -0.166595458984375 +15826 -0.219512939453125 +15827 -0.19390869140625 +15828 -0.240631103515625 +15829 -0.22442626953125 +15830 -0.284027099609375 +15831 -0.279754638671875 +15832 -0.330413818359375 +15833 -0.3389892578125 +15834 -0.3349609375 +15835 -0.3543701171875 +15836 -0.31939697265625 +15837 -0.348175048828125 +15838 -0.28955078125 +15839 -0.32598876953125 +15840 -0.21771240234375 +15841 -0.2581787109375 +15842 -0.09954833984375 +15843 -0.139801025390625 +15844 0.0509033203125 +15845 0.014617919921875 +15846 0.17578125 +15847 0.144378662109375 +15848 0.248077392578125 +15849 0.221038818359375 +15850 0.292633056640625 +15851 0.27069091796875 +15852 0.31036376953125 +15853 0.294036865234375 +15854 0.321197509765625 +15855 0.311767578125 +15856 0.34002685546875 +15857 0.339141845703125 +15858 0.3521728515625 +15859 0.360260009765625 +15860 0.34423828125 +15861 0.360504150390625 +15862 0.28662109375 +15863 0.308380126953125 +15864 0.15863037109375 +15865 0.18170166015625 +15866 -0.016143798828125 +15867 0.0047607421875 +15868 -0.192840576171875 +15869 -0.17559814453125 +15870 -0.328369140625 +15871 -0.3143310546875 +15872 -0.3807373046875 +15873 -0.36785888671875 +15874 -0.37530517578125 +15875 -0.36248779296875 +15876 -0.35589599609375 +15877 -0.343536376953125 +15878 -0.31341552734375 +15879 -0.3018798828125 +15880 -0.241790771484375 +15881 -0.231414794921875 +15882 -0.126800537109375 +15883 -0.117645263671875 +15884 -0.000396728515625 +15885 0.007049560546875 +15886 0.0833740234375 +15887 0.087982177734375 +15888 0.138397216796875 +15889 0.13946533203125 +15890 0.176971435546875 +15891 0.17425537109375 +15892 0.1947021484375 +15893 0.188201904296875 +15894 0.18145751953125 +15895 0.171234130859375 +15896 0.132232666015625 +15897 0.118438720703125 +15898 0.073699951171875 +15899 0.05706787109375 +15900 0.007843017578125 +15901 -0.010711669921875 +15902 -0.071746826171875 +15903 -0.0914306640625 +15904 -0.142608642578125 +15905 -0.162322998046875 +15906 -0.17633056640625 +15907 -0.194549560546875 +15908 -0.13458251953125 +15909 -0.1492919921875 +15910 -0.01239013671875 +15911 -0.02166748046875 +15912 0.127227783203125 +15913 0.124053955078125 +15914 0.208984375 +15915 0.211151123046875 +15916 0.233917236328125 +15917 0.240447998046875 +15918 0.23199462890625 +15919 0.242218017578125 +15920 0.212554931640625 +15921 0.2257080078125 +15922 0.179107666015625 +15923 0.194366455078125 +15924 0.099639892578125 +15925 0.115509033203125 +15926 -0.002471923828125 +15927 0.0128173828125 +15928 -0.0682373046875 +15929 -0.053802490234375 +15930 -0.123504638671875 +15931 -0.110626220703125 +15932 -0.20953369140625 +15933 -0.199493408203125 +15934 -0.300811767578125 +15935 -0.29437255859375 +15936 -0.335418701171875 +15937 -0.33221435546875 +15938 -0.28076171875 +15939 -0.27972412109375 +15940 -0.184661865234375 +15941 -0.185333251953125 +15942 -0.12518310546875 +15943 -0.128204345703125 +15944 -0.109710693359375 +15945 -0.115692138671875 +15946 -0.10760498046875 +15947 -0.116455078125 +15948 -0.0948486328125 +15949 -0.105926513671875 +15950 -0.04193115234375 +15951 -0.053955078125 +15952 0.060272216796875 +15953 0.048797607421875 +15954 0.16748046875 +15955 0.157318115234375 +15956 0.22100830078125 +15957 0.212005615234375 +15958 0.2264404296875 +15959 0.218475341796875 +15960 0.243377685546875 +15961 0.23724365234375 +15962 0.308380126953125 +15963 0.30535888671875 +15964 0.380706787109375 +15965 0.38128662109375 +15966 0.40087890625 +15967 0.404449462890625 +15968 0.388275146484375 +15969 0.3944091796875 +15970 0.379852294921875 +15971 0.3885498046875 +15972 0.3519287109375 +15973 0.362640380859375 +15974 0.26220703125 +15975 0.27362060546875 +15976 0.106536865234375 +15977 0.11712646484375 +15978 -0.063873291015625 +15979 -0.054901123046875 +15980 -0.198211669921875 +15981 -0.19085693359375 +15982 -0.291534423828125 +15983 -0.28570556640625 +15984 -0.343658447265625 +15985 -0.339263916015625 +15986 -0.3802490234375 +15987 -0.3775634765625 +15988 -0.445770263671875 +15989 -0.445709228515625 +15990 -0.531829833984375 +15991 -0.535064697265625 +15992 -0.6221923828125 +15993 -0.629058837890625 +15994 -0.687408447265625 +15995 -0.697601318359375 +15996 -0.69140625 +15997 -0.70391845703125 +15998 -0.628814697265625 +15999 -0.6424560546875 +16000 -0.4781494140625 +16001 -0.491241455078125 +16002 -0.25469970703125 +16003 -0.265716552734375 +16004 -0.015411376953125 +16005 -0.023712158203125 +16006 0.207122802734375 +16007 0.201751708984375 +16008 0.37860107421875 +16009 0.375823974609375 +16010 0.485809326171875 +16011 0.485076904296875 +16012 0.5675048828125 +16013 0.56884765625 +16014 0.6312255859375 +16015 0.634765625 +16016 0.632568359375 +16017 0.63763427734375 +16018 0.560394287109375 +16019 0.5660400390625 +16020 0.466033935546875 +16021 0.4720458984375 +16022 0.400054931640625 +16023 0.40692138671875 +16024 0.369598388671875 +16025 0.3778076171875 +16026 0.367095947265625 +16027 0.376953125 +16028 0.360809326171875 +16029 0.371978759765625 +16030 0.3018798828125 +16031 0.313140869140625 +16032 0.174530029296875 +16033 0.184417724609375 +16034 0.003814697265625 +16035 0.011199951171875 +16036 -0.1754150390625 +16037 -0.171051025390625 +16038 -0.338623046875 +16039 -0.33740234375 +16040 -0.470184326171875 +16041 -0.47198486328125 +16042 -0.5560302734375 +16043 -0.560394287109375 +16044 -0.574554443359375 +16045 -0.58056640625 +16046 -0.540618896484375 +16047 -0.54754638671875 +16048 -0.500762939453125 +16049 -0.508575439453125 +16050 -0.45098876953125 +16051 -0.459503173828125 +16052 -0.385528564453125 +16053 -0.394378662109375 +16054 -0.343231201171875 +16055 -0.35260009765625 +16056 -0.302032470703125 +16057 -0.31170654296875 +16058 -0.188873291015625 +16059 -0.197418212890625 +16060 -0.002044677734375 +16061 -0.007965087890625 +16062 0.21002197265625 +16063 0.207489013671875 +16064 0.40826416015625 +16065 0.409210205078125 +16066 0.567962646484375 +16067 0.57208251953125 +16068 0.659515380859375 +16069 0.66595458984375 +16070 0.6513671875 +16071 0.65875244140625 +16072 0.560302734375 +16073 0.56744384765625 +16074 0.425140380859375 +16075 0.431396484375 +16076 0.2890625 +16077 0.29443359375 +16078 0.177642822265625 +16079 0.182464599609375 +16080 0.059661865234375 +16081 0.06365966796875 +16082 -0.078582763671875 +16083 -0.075958251953125 +16084 -0.19085693359375 +16085 -0.189422607421875 +16086 -0.27239990234375 +16087 -0.271942138671875 +16088 -0.3419189453125 +16089 -0.342529296875 +16090 -0.363037109375 +16091 -0.364166259765625 +16092 -0.3262939453125 +16093 -0.327239990234375 +16094 -0.276214599609375 +16095 -0.2769775390625 +16096 -0.25250244140625 +16097 -0.253692626953125 +16098 -0.24169921875 +16099 -0.24365234375 +16100 -0.196136474609375 +16101 -0.1983642578125 +16102 -0.11431884765625 +16103 -0.116241455078125 +16104 -0.035186767578125 +16105 -0.036834716796875 +16106 0.036285400390625 +16107 0.034881591796875 +16108 0.092498779296875 +16109 0.09124755859375 +16110 0.110443115234375 +16111 0.10888671875 +16112 0.127197265625 +16113 0.125518798828125 +16114 0.159088134765625 +16115 0.15771484375 +16116 0.1793212890625 +16117 0.17828369140625 +16118 0.1719970703125 +16119 0.17108154296875 +16120 0.131134033203125 +16121 0.129974365234375 +16122 0.083770751953125 +16123 0.082427978515625 +16124 0.02923583984375 +16125 0.027679443359375 +16126 -0.0633544921875 +16127 -0.065643310546875 +16128 -0.15618896484375 +16129 -0.159515380859375 +16130 -0.209686279296875 +16131 -0.21337890625 +16132 -0.23187255859375 +16133 -0.2347412109375 +16134 -0.1986083984375 +16135 -0.200286865234375 +16136 -0.119110107421875 +16137 -0.11956787109375 +16138 -0.0263671875 +16139 -0.025421142578125 +16140 0.082550048828125 +16141 0.084686279296875 +16142 0.173492431640625 +16143 0.1768798828125 +16144 0.20989990234375 +16145 0.21490478515625 +16146 0.205108642578125 +16147 0.211761474609375 +16148 0.16864013671875 +16149 0.176727294921875 +16150 0.12237548828125 +16151 0.13128662109375 +16152 0.096160888671875 +16153 0.1048583984375 +16154 0.069580078125 +16155 0.077423095703125 +16156 0.039794921875 +16157 0.046295166015625 +16158 0.036163330078125 +16159 0.040496826171875 +16160 0.0758056640625 +16161 0.0770263671875 +16162 0.14215087890625 +16163 0.13970947265625 +16164 0.18902587890625 +16165 0.18328857421875 +16166 0.192718505859375 +16167 0.184600830078125 +16168 0.144012451171875 +16169 0.134674072265625 +16170 0.047515869140625 +16171 0.038177490234375 +16172 -0.073272705078125 +16173 -0.08172607421875 +16174 -0.213165283203125 +16175 -0.219879150390625 +16176 -0.361846923828125 +16177 -0.366119384765625 +16178 -0.489471435546875 +16179 -0.4910888671875 +16180 -0.551727294921875 +16181 -0.551239013671875 +16182 -0.505279541015625 +16183 -0.5040283203125 +16184 -0.373443603515625 +16185 -0.3724365234375 +16186 -0.218109130859375 +16187 -0.21746826171875 +16188 -0.0643310546875 +16189 -0.063934326171875 +16190 0.08966064453125 +16191 0.08978271484375 +16192 0.232940673828125 +16193 0.232818603515625 +16194 0.338897705078125 +16195 0.3388671875 +16196 0.390380859375 +16197 0.390960693359375 +16198 0.38409423828125 +16199 0.38580322265625 +16200 0.318817138671875 +16201 0.3221435546875 +16202 0.21881103515625 +16203 0.22381591796875 +16204 0.119415283203125 +16205 0.125640869140625 +16206 0.032867431640625 +16207 0.0396728515625 +16208 -0.013427734375 +16209 -0.007080078125 +16210 -0.021728515625 +16211 -0.016754150390625 +16212 -0.023956298828125 +16213 -0.0206298828125 +16214 -0.001556396484375 +16215 -0.0003662109375 +16216 0.05743408203125 +16217 0.055877685546875 +16218 0.108856201171875 +16219 0.104766845703125 +16220 0.099884033203125 +16221 0.09442138671875 +16222 0.046356201171875 +16223 0.040496826171875 +16224 -0.013916015625 +16225 -0.019744873046875 +16226 -0.071533203125 +16227 -0.076995849609375 +16228 -0.115142822265625 +16229 -0.12005615234375 +16230 -0.15570068359375 +16231 -0.159759521484375 +16232 -0.199066162109375 +16233 -0.201904296875 +16234 -0.2457275390625 +16235 -0.2469482421875 +16236 -0.3031005859375 +16237 -0.302276611328125 +16238 -0.360931396484375 +16239 -0.357879638671875 +16240 -0.39117431640625 +16241 -0.38623046875 +16242 -0.35595703125 +16243 -0.350128173828125 +16244 -0.251495361328125 +16245 -0.245941162109375 +16246 -0.09515380859375 +16247 -0.090850830078125 +16248 0.086151123046875 +16249 0.088623046875 +16250 0.231903076171875 +16251 0.232879638671875 +16252 0.315277099609375 +16253 0.31549072265625 +16254 0.355072021484375 +16255 0.35491943359375 +16256 0.3443603515625 +16257 0.344329833984375 +16258 0.282623291015625 +16259 0.283233642578125 +16260 0.220672607421875 +16261 0.221649169921875 +16262 0.19488525390625 +16263 0.195404052734375 +16264 0.1787109375 +16265 0.178436279296875 +16266 0.15521240234375 +16267 0.154144287109375 +16268 0.15167236328125 +16269 0.149444580078125 +16270 0.158172607421875 +16271 0.154632568359375 +16272 0.1336669921875 +16273 0.12939453125 +16274 0.103240966796875 +16275 0.098480224609375 +16276 0.0899658203125 +16277 0.084625244140625 +16278 0.05792236328125 +16279 0.05255126953125 +16280 -0.005889892578125 +16281 -0.01055908203125 +16282 -0.10101318359375 +16283 -0.104156494140625 +16284 -0.2266845703125 +16285 -0.227569580078125 +16286 -0.353240966796875 +16287 -0.351593017578125 +16288 -0.440155029296875 +16289 -0.4364013671875 +16290 -0.472686767578125 +16291 -0.467559814453125 +16292 -0.46429443359375 +16293 -0.45831298828125 +16294 -0.419219970703125 +16295 -0.41290283203125 +16296 -0.335052490234375 +16297 -0.32904052734375 +16298 -0.229217529296875 +16299 -0.223907470703125 +16300 -0.125213623046875 +16301 -0.120697021484375 +16302 -0.02972412109375 +16303 -0.026031494140625 +16304 0.07537841796875 +16305 0.07794189453125 +16306 0.21087646484375 +16307 0.21160888671875 +16308 0.38653564453125 +16309 0.384521484375 +16310 0.580657958984375 +16311 0.575347900390625 +16312 0.732177734375 +16313 0.72406005859375 +16314 0.79864501953125 +16315 0.788909912109375 +16316 0.777252197265625 +16317 0.76715087890625 +16318 0.664581298828125 +16319 0.65545654296875 +16320 0.459564208984375 +16321 0.452850341796875 +16322 0.1995849609375 +16323 0.196136474609375 +16324 -0.04986572265625 +16325 -0.050140380859375 +16326 -0.231781005859375 +16327 -0.229888916015625 +16328 -0.32867431640625 +16329 -0.325836181640625 +16330 -0.36676025390625 +16331 -0.36376953125 +16332 -0.377197265625 +16333 -0.37432861328125 +16334 -0.375244140625 +16335 -0.372528076171875 +16336 -0.3780517578125 +16337 -0.375244140625 +16338 -0.390045166015625 +16339 -0.386810302734375 +16340 -0.3841552734375 +16341 -0.380615234375 +16342 -0.341064453125 +16343 -0.337677001953125 +16344 -0.28240966796875 +16345 -0.27935791015625 +16346 -0.25152587890625 +16347 -0.248291015625 +16348 -0.266448974609375 +16349 -0.26226806640625 +16350 -0.274017333984375 +16351 -0.26904296875 +16352 -0.2177734375 +16353 -0.21307373046875 +16354 -0.129486083984375 +16355 -0.1256103515625 +16356 -0.069549560546875 +16357 -0.066162109375 +16358 -0.044586181640625 +16359 -0.041259765625 +16360 -0.02593994140625 +16361 -0.022735595703125 +16362 0.019317626953125 +16363 0.021820068359375 +16364 0.12322998046875 +16365 0.12396240234375 +16366 0.2568359375 +16367 0.255157470703125 +16368 0.378326416015625 +16369 0.37432861328125 +16370 0.47943115234375 +16371 0.473358154296875 +16372 0.528045654296875 +16373 0.5206298828125 +16374 0.511322021484375 +16375 0.503570556640625 +16376 0.45672607421875 +16377 0.449249267578125 +16378 0.408294677734375 +16379 0.401031494140625 +16380 0.38482666015625 +16381 0.37744140625 +16382 0.358123779296875 +16383 0.350738525390625 +16384 0.313201904296875 +16385 0.305694580078125 +16386 0.252288818359375 +16387 0.24420166015625 +16388 0.166748046875 +16389 0.158447265625 +16390 0.036468505859375 +16391 0.029754638671875 +16392 -0.141021728515625 +16393 -0.143768310546875 +16394 -0.3348388671875 +16395 -0.33233642578125 +16396 -0.534027099609375 +16397 -0.52520751953125 +16398 -0.721649169921875 +16399 -0.706024169921875 +16400 -0.836761474609375 +16401 -0.816650390625 +16402 -0.833038330078125 +16403 -0.81292724609375 +16404 -0.73028564453125 +16405 -0.713775634765625 +16406 -0.58343505859375 +16407 -0.57159423828125 +16408 -0.441131591796875 +16409 -0.432830810546875 +16410 -0.325439453125 +16411 -0.3187255859375 +16412 -0.20263671875 +16413 -0.19744873046875 +16414 -0.0457763671875 +16415 -0.043548583984375 +16416 0.102935791015625 +16417 0.102508544921875 +16418 0.201507568359375 +16419 0.200469970703125 +16420 0.263824462890625 +16421 0.263336181640625 +16422 0.338470458984375 +16423 0.337188720703125 +16424 0.443634033203125 +16425 0.439178466796875 +16426 0.545135498046875 +16427 0.536712646484375 +16428 0.61761474609375 +16429 0.605621337890625 +16430 0.652984619140625 +16431 0.63824462890625 +16432 0.664093017578125 +16433 0.646881103515625 +16434 0.656951904296875 +16435 0.637420654296875 +16436 0.607696533203125 +16437 0.587249755859375 +16438 0.50213623046875 +16439 0.48309326171875 +16440 0.35369873046875 +16441 0.33795166015625 +16442 0.1773681640625 +16443 0.16632080078125 +16444 -0.034149169921875 +16445 -0.038543701171875 +16446 -0.257720947265625 +16447 -0.25445556640625 +16448 -0.442169189453125 +16449 -0.432525634765625 +16450 -0.57525634765625 +16451 -0.56097412109375 +16452 -0.652191162109375 +16453 -0.63519287109375 +16454 -0.6419677734375 +16455 -0.625640869140625 +16456 -0.562652587890625 +16457 -0.54949951171875 +16458 -0.458648681640625 +16459 -0.449127197265625 +16460 -0.351226806640625 +16461 -0.344879150390625 +16462 -0.26123046875 +16463 -0.256683349609375 +16464 -0.19281005859375 +16465 -0.18865966796875 +16466 -0.142608642578125 +16467 -0.137786865234375 +16468 -0.102783203125 +16469 -0.096771240234375 +16470 -0.06341552734375 +16471 -0.056365966796875 +16472 -0.0123291015625 +16473 -0.005096435546875 +16474 0.062591552734375 +16475 0.06842041015625 +16476 0.148651123046875 +16477 0.1519775390625 +16478 0.241851806640625 +16479 0.24169921875 +16480 0.34942626953125 +16481 0.344451904296875 +16482 0.457794189453125 +16483 0.447296142578125 +16484 0.544525146484375 +16485 0.5289306640625 +16486 0.5736083984375 +16487 0.55517578125 +16488 0.507354736328125 +16489 0.490234375 +16490 0.35198974609375 +16491 0.340118408203125 +16492 0.147247314453125 +16493 0.14276123046875 +16494 -0.0545654296875 +16495 -0.0518798828125 +16496 -0.215667724609375 +16497 -0.20770263671875 +16498 -0.33447265625 +16499 -0.32305908203125 +16500 -0.402679443359375 +16501 -0.389923095703125 +16502 -0.441131591796875 +16503 -0.42803955078125 +16504 -0.49578857421875 +16505 -0.4810791015625 +16506 -0.560333251953125 +16507 -0.542999267578125 +16508 -0.60101318359375 +16509 -0.581695556640625 +16510 -0.584625244140625 +16511 -0.565521240234375 +16512 -0.47979736328125 +16513 -0.46466064453125 +16514 -0.2799072265625 +16515 -0.27288818359375 +16516 -0.009490966796875 +16517 -0.013671875 +16518 0.268218994140625 +16519 0.252655029296875 +16520 0.482269287109375 +16521 0.45849609375 +16522 0.60321044921875 +16523 0.575714111328125 +16524 0.649993896484375 +16525 0.6221923828125 +16526 0.663665771484375 +16527 0.63690185546875 +16528 0.6412353515625 +16529 0.616912841796875 +16530 0.5723876953125 +16531 0.5523681640625 +16532 0.498077392578125 +16533 0.482177734375 +16534 0.439483642578125 +16535 0.426483154296875 +16536 0.375640869140625 +16537 0.365325927734375 +16538 0.274688720703125 +16539 0.268463134765625 +16540 0.1090087890625 +16541 0.109619140625 +16542 -0.09912109375 +16543 -0.08990478515625 +16544 -0.31793212890625 +16545 -0.2998046875 +16546 -0.54864501953125 +16547 -0.521148681640625 +16548 -0.773529052734375 +16549 -0.7369384765625 +16550 -0.863800048828125 +16551 -0.859100341796875 +16552 -0.870391845703125 +16553 -0.866973876953125 +16554 -0.868988037109375 +16555 -0.8670654296875 +16556 -0.861114501953125 +16557 -0.86077880859375 +16558 -0.766510009765625 +16559 -0.779083251953125 +16560 -0.53094482421875 +16561 -0.560455322265625 +16562 -0.215576171875 +16563 -0.262725830078125 +16564 0.13641357421875 +16565 0.0731201171875 +16566 0.473846435546875 +16567 0.398193359375 +16568 0.761444091796875 +16569 0.6785888671875 +16570 0.86737060546875 +16571 0.858184814453125 +16572 0.870361328125 +16573 0.870361328125 +16574 0.864898681640625 +16575 0.870361328125 +16576 0.833465576171875 +16577 0.86273193359375 +16578 0.679901123046875 +16579 0.816436767578125 +16580 0.498748779296875 +16581 0.666229248046875 +16582 0.3109130859375 +16583 0.49859619140625 +16584 0.119598388671875 +16585 0.3162841796875 +16586 -0.107330322265625 +16587 0.08905029296875 +16588 -0.378570556640625 +16589 -0.190460205078125 +16590 -0.654327392578125 +16591 -0.482940673828125 +16592 -0.857147216796875 +16593 -0.733367919921875 +16594 -0.870391845703125 +16595 -0.859832763671875 +16596 -0.870391845703125 +16597 -0.869110107421875 +16598 -0.86444091796875 +16599 -0.870391845703125 +16600 -0.85723876953125 +16601 -0.869659423828125 +16602 -0.790008544921875 +16603 -0.86541748046875 +16604 -0.62847900390625 +16605 -0.834625244140625 +16606 -0.3956298828125 +16607 -0.632965087890625 +16608 -0.126708984375 +16609 -0.38238525390625 +16610 0.150115966796875 +16611 -0.109832763671875 +16612 0.424041748046875 +16613 0.173492431640625 +16614 0.670623779296875 +16615 0.44268798828125 +16616 0.854522705078125 +16617 0.662322998046875 +16618 0.866485595703125 +16619 0.817657470703125 +16620 0.86920166015625 +16621 0.85906982421875 +16622 0.8653564453125 +16623 0.861541748046875 +16624 0.857147216796875 +16625 0.859588623046875 +16626 0.766845703125 +16627 0.84326171875 +16628 0.628509521484375 +16629 0.752777099609375 +16630 0.462127685546875 +16631 0.625946044921875 +16632 0.297210693359375 +16633 0.489471435546875 +16634 0.14862060546875 +16635 0.356658935546875 +16636 -0.00537109375 +16637 0.20672607421875 +16638 -0.15753173828125 +16639 0.047088623046875 +16640 -0.31304931640625 +16641 -0.125640869140625 +16642 -0.48876953125 +16643 -0.32574462890625 +16644 -0.6416015625 +16645 -0.511383056640625 +16646 -0.751373291015625 +16647 -0.661041259765625 +16648 -0.84619140625 +16649 -0.79754638671875 +16650 -0.861297607421875 +16651 -0.860504150390625 +16652 -0.863250732421875 +16653 -0.86688232421875 +16654 -0.856597900390625 +16655 -0.86456298828125 +16656 -0.7498779296875 +16657 -0.85498046875 +16658 -0.624542236328125 +16659 -0.75927734375 +16660 -0.47808837890625 +16661 -0.629669189453125 +16662 -0.253387451171875 +16663 -0.41741943359375 +16664 0.003692626953125 +16665 -0.165313720703125 +16666 0.2257080078125 +16667 0.06341552734375 +16668 0.427154541015625 +16669 0.28045654296875 +16670 0.643218994140625 +16671 0.5162353515625 +16672 0.855926513671875 +16673 0.762908935546875 +16674 0.870361328125 +16675 0.866912841796875 +16676 0.870361328125 +16677 0.870361328125 +16678 0.862762451171875 +16679 0.866241455078125 +16680 0.79669189453125 +16681 0.85491943359375 +16682 0.595794677734375 +16683 0.68603515625 +16684 0.362152099609375 +16685 0.47540283203125 +16686 0.1270751953125 +16687 0.255584716796875 +16688 -0.086944580078125 +16689 0.047637939453125 +16690 -0.2784423828125 +16691 -0.146270751953125 +16692 -0.484832763671875 +16693 -0.359344482421875 +16694 -0.729583740234375 +16695 -0.611785888671875 +16696 -0.86688232421875 +16697 -0.855194091796875 +16698 -0.870391845703125 +16699 -0.870391845703125 +16700 -0.86859130859375 +16701 -0.870391845703125 +16702 -0.86279296875 +16703 -0.866119384765625 +16704 -0.817962646484375 +16705 -0.855224609375 +16706 -0.6116943359375 +16707 -0.6688232421875 +16708 -0.3128662109375 +16709 -0.38580322265625 +16710 0.039398193359375 +16711 -0.0484619140625 +16712 0.422821044921875 +16713 0.32177734375 +16714 0.805145263671875 +16715 0.69415283203125 +16716 0.870361328125 +16717 0.870361328125 +16718 0.870361328125 +16719 0.870361328125 +16720 0.860015869140625 +16721 0.860382080078125 +16722 0.727935791015625 +16723 0.736968994140625 +16724 0.48114013671875 +16725 0.49810791015625 +16726 0.2059326171875 +16727 0.23040771484375 +16728 -0.06103515625 +16729 -0.031494140625 +16730 -0.29913330078125 +16731 -0.267730712890625 +16732 -0.516204833984375 +16733 -0.48455810546875 +16734 -0.7252197265625 +16735 -0.69293212890625 +16736 -0.85980224609375 +16737 -0.85626220703125 +16738 -0.870391845703125 +16739 -0.869354248046875 +16740 -0.870391845703125 +16741 -0.870391845703125 +16742 -0.858062744140625 +16743 -0.85955810546875 +16744 -0.673004150390625 +16745 -0.70391845703125 +16746 -0.42694091796875 +16747 -0.472930908203125 +16748 -0.2100830078125 +16749 -0.26458740234375 +16750 -0.0362548828125 +16751 -0.092193603515625 +16752 0.10943603515625 +16753 0.05712890625 +16754 0.23516845703125 +16755 0.190032958984375 +16756 0.373687744140625 +16757 0.33563232421875 +16758 0.517791748046875 +16759 0.48626708984375 +16760 0.602783203125 +16761 0.581451416015625 +16762 0.635711669921875 +16763 0.626800537109375 +16764 0.655181884765625 +16765 0.65704345703125 +16766 0.65948486328125 +16767 0.670013427734375 +16768 0.651275634765625 +16769 0.667755126953125 +16770 0.61846923828125 +16771 0.638946533203125 +16772 0.53753662109375 +16773 0.56201171875 +16774 0.404144287109375 +16775 0.4332275390625 +16776 0.22186279296875 +16777 0.25628662109375 +16778 0.003997802734375 +16779 0.044036865234375 +16780 -0.22100830078125 +16781 -0.1766357421875 +16782 -0.42449951171875 +16783 -0.37860107421875 +16784 -0.579833984375 +16785 -0.536468505859375 +16786 -0.641876220703125 +16787 -0.60791015625 +16788 -0.6177978515625 +16789 -0.598785400390625 +16790 -0.575531005859375 +16791 -0.570892333984375 +16792 -0.526336669921875 +16793 -0.534027099609375 +16794 -0.42645263671875 +16795 -0.447601318359375 +16796 -0.2581787109375 +16797 -0.295074462890625 +16798 -0.068695068359375 +16799 -0.11981201171875 +16800 0.09222412109375 +16801 0.032257080078125 +16802 0.232147216796875 +16803 0.167755126953125 +16804 0.3509521484375 +16805 0.2861328125 +16806 0.410064697265625 +16807 0.351318359375 +16808 0.372955322265625 +16809 0.329071044921875 +16810 0.2554931640625 +16811 0.23333740234375 +16812 0.10711669921875 +16813 0.10888671875 +16814 -0.052886962890625 +16815 -0.027191162109375 +16816 -0.186279296875 +16817 -0.1402587890625 +16818 -0.23291015625 +16819 -0.17547607421875 +16820 -0.209442138671875 +16821 -0.148529052734375 +16822 -0.174163818359375 +16823 -0.11328125 +16824 -0.126739501953125 +16825 -0.069488525390625 +16826 -0.048126220703125 +16827 0.000396728515625 +16828 0.0426025390625 +16829 0.07904052734375 +16830 0.10748291015625 +16831 0.131866455078125 +16832 0.1409912109375 +16833 0.15423583984375 +16834 0.19708251953125 +16835 0.196258544921875 +16836 0.273651123046875 +16837 0.256591796875 +16838 0.31768798828125 +16839 0.287017822265625 +16840 0.341094970703125 +16841 0.299041748046875 +16842 0.368011474609375 +16843 0.315399169921875 +16844 0.37249755859375 +16845 0.312591552734375 +16846 0.30072021484375 +16847 0.241455078125 +16848 0.1517333984375 +16849 0.101318359375 +16850 -0.01470947265625 +16851 -0.052734375 +16852 -0.1883544921875 +16853 -0.21124267578125 +16854 -0.372711181640625 +16855 -0.3775634765625 +16856 -0.51397705078125 +16857 -0.50244140625 +16858 -0.57177734375 +16859 -0.549072265625 +16860 -0.53948974609375 +16861 -0.511749267578125 +16862 -0.43511962890625 +16863 -0.407501220703125 +16864 -0.2962646484375 +16865 -0.2713623046875 +16866 -0.161102294921875 +16867 -0.138916015625 +16868 -0.0435791015625 +16869 -0.02337646484375 +16870 0.060394287109375 +16871 0.07855224609375 +16872 0.13665771484375 +16873 0.153564453125 +16874 0.170135498046875 +16875 0.18756103515625 +16876 0.16552734375 +16877 0.18475341796875 +16878 0.15728759765625 +16879 0.176788330078125 +16880 0.150787353515625 +16881 0.168701171875 +16882 0.12200927734375 +16883 0.138519287109375 +16884 0.080108642578125 +16885 0.094940185546875 +16886 0.05126953125 +16887 0.062347412109375 +16888 0.062896728515625 +16889 0.06634521484375 +16890 0.09271240234375 +16891 0.086822509765625 +16892 0.092987060546875 +16893 0.08026123046875 +16894 0.07855224609375 +16895 0.060638427734375 +16896 0.06427001953125 +16897 0.0421142578125 +16898 0.0347900390625 +16899 0.010772705078125 +16900 -0.01171875 +16901 -0.03497314453125 +16902 -0.056060791015625 +16903 -0.077484130859375 +16904 -0.055511474609375 +16905 -0.078125 +16906 -0.010467529296875 +16907 -0.037139892578125 +16908 0.02508544921875 +16909 -0.00311279296875 +16910 0.025665283203125 +16911 0.0008544921875 +16912 0.017333984375 +16913 -0.001953125 +16914 0.00189208984375 +16915 -0.01025390625 +16916 -0.03173828125 +16917 -0.034332275390625 +16918 -0.071502685546875 +16919 -0.063751220703125 +16920 -0.13543701171875 +16921 -0.115081787109375 +16922 -0.219970703125 +16923 -0.18548583984375 +16924 -0.300506591796875 +16925 -0.25311279296875 +16926 -0.376312255859375 +16927 -0.317535400390625 +16928 -0.416107177734375 +16929 -0.35076904296875 +16930 -0.371124267578125 +16931 -0.309051513671875 +16932 -0.242279052734375 +16933 -0.1932373046875 +16934 -0.069732666015625 +16935 -0.0394287109375 +16936 0.125640869140625 +16937 0.1336669921875 +16938 0.31268310546875 +16939 0.2982177734375 +16940 0.45501708984375 +16941 0.421722412109375 +16942 0.554779052734375 +16943 0.506378173828125 +16944 0.61065673828125 +16945 0.551300048828125 +16946 0.610931396484375 +16947 0.546234130859375 +16948 0.531463623046875 +16949 0.46978759765625 +16950 0.3883056640625 +16951 0.33660888671875 +16952 0.23468017578125 +16953 0.19482421875 +16954 0.095245361328125 +16955 0.06683349609375 +16956 -0.00396728515625 +16957 -0.02386474609375 +16958 -0.04852294921875 +16959 -0.064239501953125 +16960 -0.055145263671875 +16961 -0.069305419921875 +16962 -0.0758056640625 +16963 -0.085968017578125 +16964 -0.138702392578125 +16965 -0.139739990234375 +16966 -0.209197998046875 +16967 -0.199615478515625 +16968 -0.289031982421875 +16969 -0.26739501953125 +16970 -0.37884521484375 +16971 -0.343902587890625 +16972 -0.456329345703125 +16973 -0.409271240234375 +16974 -0.51641845703125 +16975 -0.45916748046875 +16976 -0.519287109375 +16977 -0.457977294921875 +16978 -0.458251953125 +16979 -0.399871826171875 +16980 -0.384796142578125 +16981 -0.33135986328125 +16982 -0.323699951171875 +16983 -0.27484130859375 +16984 -0.269287109375 +16985 -0.225250244140625 +16986 -0.1951904296875 +16987 -0.158905029296875 +16988 -0.100006103515625 +16989 -0.074462890625 +16990 -0.01055908203125 +16991 0.003997802734375 +16992 0.1033935546875 +16993 0.10382080078125 +16994 0.24908447265625 +16995 0.231689453125 +16996 0.373199462890625 +16997 0.339813232421875 +16998 0.45806884765625 +16999 0.412506103515625 +17000 0.511474609375 +17001 0.456939697265625 +17002 0.565399169921875 +17003 0.50213623046875 +17004 0.61138916015625 +17005 0.540679931640625 +17006 0.5897216796875 +17007 0.5189208984375 +17008 0.4906005859375 +17009 0.42816162109375 +17010 0.33148193359375 +17011 0.284210205078125 +17012 0.147796630859375 +17013 0.118927001953125 +17014 -0.01873779296875 +17015 -0.0301513671875 +17016 -0.140289306640625 +17017 -0.1380615234375 +17018 -0.191986083984375 +17019 -0.182464599609375 +17020 -0.184295654296875 +17021 -0.172943115234375 +17022 -0.161834716796875 +17023 -0.149810791015625 +17024 -0.166595458984375 +17025 -0.151031494140625 +17026 -0.19390869140625 +17027 -0.172576904296875 +17028 -0.22442626953125 +17029 -0.197174072265625 +17030 -0.279754638671875 +17031 -0.244415283203125 +17032 -0.3389892578125 +17033 -0.295623779296875 +17034 -0.3543701171875 +17035 -0.307952880859375 +17036 -0.348175048828125 +17037 -0.301513671875 +17038 -0.32598876953125 +17039 -0.281341552734375 +17040 -0.2581787109375 +17041 -0.220794677734375 +17042 -0.139801025390625 +17043 -0.1153564453125 +17044 0.014617919921875 +17045 0.022003173828125 +17046 0.144378662109375 +17047 0.13671875 +17048 0.221038818359375 +17049 0.203338623046875 +17050 0.27069091796875 +17051 0.2454833984375 +17052 0.294036865234375 +17053 0.263916015625 +17054 0.311767578125 +17055 0.277435302734375 +17056 0.339141845703125 +17057 0.29986572265625 +17058 0.360260009765625 +17059 0.316802978515625 +17060 0.360504150390625 +17061 0.315277099609375 +17062 0.308380126953125 +17063 0.2674560546875 +17064 0.18170166015625 +17065 0.15374755859375 +17066 0.0047607421875 +17067 -0.004150390625 +17068 -0.17559814453125 +17069 -0.16461181640625 +17070 -0.3143310546875 +17071 -0.287628173828125 +17072 -0.36785888671875 +17073 -0.33453369140625 +17074 -0.36248779296875 +17075 -0.32867431640625 +17076 -0.343536376953125 +17077 -0.310394287109375 +17078 -0.3018798828125 +17079 -0.27166748046875 +17080 -0.231414794921875 +17081 -0.207183837890625 +17082 -0.117645263671875 +17083 -0.10418701171875 +17084 0.007049560546875 +17085 0.008453369140625 +17086 0.087982177734375 +17087 0.082061767578125 +17088 0.13946533203125 +17089 0.1292724609375 +17090 0.17425537109375 +17091 0.161346435546875 +17092 0.188201904296875 +17093 0.17449951171875 +17094 0.171234130859375 +17095 0.1597900390625 +17096 0.118438720703125 +17097 0.112823486328125 +17098 0.05706787109375 +17099 0.057830810546875 +17100 -0.010711669921875 +17101 -0.00323486328125 +17102 -0.0914306640625 +17103 -0.07611083984375 +17104 -0.162322998046875 +17105 -0.140472412109375 +17106 -0.194549560546875 +17107 -0.170684814453125 +17108 -0.1492919921875 +17109 -0.132171630859375 +17110 -0.02166748046875 +17111 -0.020477294921875 +17112 0.124053955078125 +17113 0.107391357421875 +17114 0.211151123046875 +17115 0.18341064453125 +17116 0.240447998046875 +17117 0.2083740234375 +17118 0.242218017578125 +17119 0.209197998046875 +17120 0.2257080078125 +17121 0.19415283203125 +17122 0.194366455078125 +17123 0.166290283203125 +17124 0.115509033203125 +17125 0.096588134765625 +17126 0.0128173828125 +17127 0.00604248046875 +17128 -0.053802490234375 +17129 -0.052215576171875 +17130 -0.110626220703125 +17131 -0.101531982421875 +17132 -0.199493408203125 +17133 -0.179168701171875 +17134 -0.29437255859375 +17135 -0.262054443359375 +17136 -0.33221435546875 +17137 -0.294281005859375 +17138 -0.27972412109375 +17139 -0.246368408203125 +17140 -0.185333251953125 +17141 -0.16143798828125 +17142 -0.128204345703125 +17143 -0.109771728515625 +17144 -0.115692138671875 +17145 -0.09796142578125 +17146 -0.116455078125 +17147 -0.09820556640625 +17148 -0.105926513671875 +17149 -0.088714599609375 +17150 -0.053955078125 +17151 -0.042724609375 +17152 0.048797607421875 +17153 0.0478515625 +17154 0.157318115234375 +17155 0.1434326171875 +17156 0.212005615234375 +17157 0.192230224609375 +17158 0.218475341796875 +17159 0.198883056640625 +17160 0.23724365234375 +17161 0.21514892578125 +17162 0.30535888671875 +17163 0.272796630859375 +17164 0.38128662109375 +17165 0.3363037109375 +17166 0.404449462890625 +17167 0.353973388671875 +17168 0.3944091796875 +17169 0.34271240234375 +17170 0.3885498046875 +17171 0.334716796875 +17172 0.362640380859375 +17173 0.309478759765625 +17174 0.27362060546875 +17175 0.230316162109375 +17176 0.11712646484375 +17177 0.09368896484375 +17178 -0.054901123046875 +17179 -0.055816650390625 +17180 -0.19085693359375 +17181 -0.173858642578125 +17182 -0.28570556640625 +17183 -0.256072998046875 +17184 -0.339263916015625 +17185 -0.302276611328125 +17186 -0.3775634765625 +17187 -0.334747314453125 +17188 -0.445709228515625 +17189 -0.392120361328125 +17190 -0.535064697265625 +17191 -0.46710205078125 +17192 -0.629058837890625 +17193 -0.54559326171875 +17194 -0.697601318359375 +17195 -0.601959228515625 +17196 -0.70391845703125 +17197 -0.6048583984375 +17198 -0.6424560546875 +17199 -0.5496826171875 +17200 -0.491241455078125 +17201 -0.417755126953125 +17202 -0.265716552734375 +17203 -0.222412109375 +17204 -0.023712158203125 +17205 -0.0133056640625 +17206 0.201751708984375 +17207 0.181182861328125 +17208 0.375823974609375 +17209 0.3311767578125 +17210 0.485076904296875 +17211 0.425140380859375 +17212 0.56884765625 +17213 0.496734619140625 +17214 0.634765625 +17215 0.552520751953125 +17216 0.63763427734375 +17217 0.553863525390625 +17218 0.5660400390625 +17219 0.491058349609375 +17220 0.4720458984375 +17221 0.40875244140625 +17222 0.40692138671875 +17223 0.3509521484375 +17224 0.3778076171875 +17225 0.323883056640625 +17226 0.376953125 +17227 0.321044921875 +17228 0.371978759765625 +17229 0.3148193359375 +17230 0.313140869140625 +17231 0.26275634765625 +17232 0.184417724609375 +17233 0.151214599609375 +17234 0.011199951171875 +17235 0.001983642578125 +17236 -0.171051025390625 +17237 -0.154510498046875 +17238 -0.33740234375 +17239 -0.29693603515625 +17240 -0.47198486328125 +17241 -0.411712646484375 +17242 -0.560394287109375 +17243 -0.486572265625 +17244 -0.58056640625 +17245 -0.502685546875 +17246 -0.54754638671875 +17247 -0.472991943359375 +17248 -0.508575439453125 +17249 -0.438018798828125 +17250 -0.459503173828125 +17251 -0.394287109375 +17252 -0.394378662109375 +17253 -0.336822509765625 +17254 -0.35260009765625 +17255 -0.2994384765625 +17256 -0.31170654296875 +17257 -0.262969970703125 +17258 -0.197418212890625 +17259 -0.1639404296875 +17260 -0.007965087890625 +17261 -0.0008544921875 +17262 0.207489013671875 +17263 0.18414306640625 +17264 0.409210205078125 +17265 0.35699462890625 +17266 0.57208251953125 +17267 0.4962158203125 +17268 0.66595458984375 +17269 0.57598876953125 +17270 0.65875244140625 +17271 0.56890869140625 +17272 0.56744384765625 +17273 0.48956298828125 +17274 0.431396484375 +17275 0.371734619140625 +17276 0.29443359375 +17277 0.2530517578125 +17278 0.182464599609375 +17279 0.15576171875 +17280 0.06365966796875 +17281 0.05267333984375 +17282 -0.075958251953125 +17283 -0.068084716796875 +17284 -0.189422607421875 +17285 -0.166229248046875 +17286 -0.271942138671875 +17287 -0.23760986328125 +17288 -0.342529296875 +17289 -0.2984619140625 +17290 -0.364166259765625 +17291 -0.317108154296875 +17292 -0.327239990234375 +17293 -0.285369873046875 +17294 -0.2769775390625 +17295 -0.241943359375 +17296 -0.253692626953125 +17297 -0.22137451171875 +17298 -0.24365234375 +17299 -0.2119140625 +17300 -0.1983642578125 +17301 -0.172119140625 +17302 -0.116241455078125 +17303 -0.1007080078125 +17304 -0.036834716796875 +17305 -0.03155517578125 +17306 0.034881591796875 +17307 0.030975341796875 +17308 0.09124755859375 +17309 0.080291748046875 +17310 0.10888671875 +17311 0.0963134765625 +17312 0.125518798828125 +17313 0.11126708984375 +17314 0.15771484375 +17315 0.13934326171875 +17316 0.17828369140625 +17317 0.157196044921875 +17318 0.17108154296875 +17319 0.150970458984375 +17320 0.129974365234375 +17321 0.115478515625 +17322 0.082427978515625 +17323 0.074249267578125 +17324 0.027679443359375 +17325 0.02667236328125 +17326 -0.065643310546875 +17327 -0.054046630859375 +17328 -0.15936279296875 +17329 -0.135162353515625 +17330 -0.21307373046875 +17331 -0.18206787109375 +17332 -0.234649658203125 +17333 -0.201446533203125 +17334 -0.2001953125 +17335 -0.17279052734375 +17336 -0.119171142578125 +17337 -0.10418701171875 +17338 -0.024749755859375 +17339 -0.02398681640625 +17340 0.085784912109375 +17341 0.070159912109375 +17342 0.178131103515625 +17343 0.14892578125 +17344 0.215576171875 +17345 0.180908203125 +17346 0.211456298828125 +17347 0.177490234375 +17348 0.17523193359375 +17349 0.146759033203125 +17350 0.128753662109375 +17351 0.107421875 +17352 0.1019287109375 +17353 0.085052490234375 +17354 0.0743408203125 +17355 0.062164306640625 +17356 0.04327392578125 +17357 0.036376953125 +17358 0.038177490234375 +17359 0.0328369140625 +17360 0.076263427734375 +17361 0.06622314453125 +17362 0.14105224609375 +17363 0.12237548828125 +17364 0.186431884765625 +17365 0.16180419921875 +17366 0.188812255859375 +17367 0.164276123046875 +17368 0.1390380859375 +17369 0.121917724609375 +17370 0.041778564453125 +17371 0.038726806640625 +17372 -0.079437255859375 +17373 -0.06512451171875 +17374 -0.219390869140625 +17375 -0.1851806640625 +17376 -0.367828369140625 +17377 -0.312591552734375 +17378 -0.494873046875 +17379 -0.421783447265625 +17380 -0.556243896484375 +17381 -0.474853515625 +17382 -0.508697509765625 +17383 -0.43475341796875 +17384 -0.3756103515625 +17385 -0.321441650390625 +17386 -0.218902587890625 +17387 -0.187896728515625 +17388 -0.063751220703125 +17389 -0.055633544921875 +17390 0.091552734375 +17391 0.076812744140625 +17392 0.23602294921875 +17393 0.2000732421875 +17394 0.342987060546875 +17395 0.29132080078125 +17396 0.39520263671875 +17397 0.335845947265625 +17398 0.389373779296875 +17399 0.330810546875 +17400 0.324249267578125 +17401 0.275177001953125 +17402 0.224090576171875 +17403 0.189666748046875 +17404 0.124267578125 +17405 0.10455322265625 +17406 0.037078857421875 +17407 0.030303955078125 +17408 -0.010101318359375 +17409 -0.01007080078125 +17410 -0.019439697265625 +17411 -0.01824951171875 +17412 -0.022796630859375 +17413 -0.020843505859375 +17414 -0.001556396484375 +17415 -0.00274658203125 +17416 0.056304931640625 +17417 0.045745849609375 +17418 0.106719970703125 +17419 0.088134765625 +17420 0.096893310546875 +17421 0.080780029296875 +17422 0.042694091796875 +17423 0.03668212890625 +17424 -0.018035888671875 +17425 -0.01300048828125 +17426 -0.07586669921875 +17427 -0.060516357421875 +17428 -0.11944580078125 +17429 -0.09649658203125 +17430 -0.15972900390625 +17431 -0.129974365234375 +17432 -0.202606201171875 +17433 -0.165771484375 +17434 -0.24859619140625 +17435 -0.2042236328125 +17436 -0.30517578125 +17437 -0.251434326171875 +17438 -0.36212158203125 +17439 -0.298980712890625 +17440 -0.39141845703125 +17441 -0.32373046875 +17442 -0.35528564453125 +17443 -0.294464111328125 +17444 -0.249969482421875 +17445 -0.208099365234375 +17446 -0.092864990234375 +17447 -0.07891845703125 +17448 0.08905029296875 +17449 0.07086181640625 +17450 0.2352294921875 +17451 0.191314697265625 +17452 0.318817138671875 +17453 0.260345458984375 +17454 0.358642578125 +17455 0.293426513671875 +17456 0.347747802734375 +17457 0.284820556640625 +17458 0.28564453125 +17459 0.234130859375 +17460 0.223175048828125 +17461 0.183197021484375 +17462 0.196746826171875 +17463 0.161956787109375 +17464 0.179840087890625 +17465 0.1485595703125 +17466 0.155548095703125 +17467 0.129058837890625 +17468 0.151214599609375 +17469 0.1259765625 +17470 0.156951904296875 +17471 0.131103515625 +17472 0.13177490234375 +17473 0.11065673828125 +17474 0.100799560546875 +17475 0.085296630859375 +17476 0.087127685546875 +17477 0.074066162109375 +17478 0.05487060546875 +17479 0.047393798828125 +17480 -0.009002685546875 +17481 -0.00543212890625 +17482 -0.10400390625 +17483 -0.083984375 +17484 -0.229400634765625 +17485 -0.18768310546875 +17486 -0.35552978515625 +17487 -0.29205322265625 +17488 -0.441925048828125 +17489 -0.36370849609375 +17490 -0.473846435546875 +17491 -0.3905029296875 +17492 -0.464813232421875 +17493 -0.383514404296875 +17494 -0.419097900390625 +17495 -0.346221923828125 +17496 -0.334320068359375 +17497 -0.27667236328125 +17498 -0.227935791015625 +17499 -0.189239501953125 +17500 -0.12347412109375 +17501 -0.103302001953125 +17502 -0.02764892578125 +17503 -0.02435302734375 +17504 0.077667236328125 +17505 0.062530517578125 +17506 0.2132568359375 +17507 0.1744384765625 +17508 0.38885498046875 +17509 0.319366455078125 +17510 0.582794189453125 +17511 0.479461669921875 +17512 0.734039306640625 +17513 0.604400634765625 +17514 0.800140380859375 +17515 0.659210205078125 +17516 0.7783203125 +17517 0.64154052734375 +17518 0.6651611328125 +17519 0.548583984375 +17520 0.45965576171875 +17521 0.3795166015625 +17522 0.199188232421875 +17523 0.16510009765625 +17524 -0.050689697265625 +17525 -0.0406494140625 +17526 -0.23297119140625 +17527 -0.190765380859375 +17528 -0.33013916015625 +17529 -0.27081298828125 +17530 -0.368408203125 +17531 -0.3023681640625 +17532 -0.378936767578125 +17533 -0.31109619140625 +17534 -0.376983642578125 +17535 -0.30963134765625 +17536 -0.37969970703125 +17537 -0.31207275390625 +17538 -0.391510009765625 +17539 -0.322052001953125 +17540 -0.385345458984375 +17541 -0.3172607421875 +17542 -0.3419189453125 +17543 -0.281768798828125 +17544 -0.28289794921875 +17545 -0.233428955078125 +17546 -0.251617431640625 +17547 -0.207916259765625 +17548 -0.266143798828125 +17549 -0.2200927734375 +17550 -0.273345947265625 +17551 -0.2261962890625 +17552 -0.216796875 +17553 -0.179718017578125 +17554 -0.128265380859375 +17555 -0.1068115234375 +17556 -0.068145751953125 +17557 -0.0572509765625 +17558 -0.0430908203125 +17559 -0.0364990234375 +17560 -0.024444580078125 +17561 -0.020965576171875 +17562 0.020721435546875 +17563 0.0164794921875 +17564 0.124481201171875 +17565 0.10223388671875 +17566 0.25787353515625 +17567 0.21240234375 +17568 0.379119873046875 +17569 0.31256103515625 +17570 0.47991943359375 +17571 0.3958740234375 +17572 0.5281982421875 +17573 0.435882568359375 +17574 0.511138916015625 +17575 0.4219970703125 +17576 0.456207275390625 +17577 0.376861572265625 +17578 0.407470703125 +17579 0.3367919921875 +17580 0.383758544921875 +17581 0.317291259765625 +17582 0.35687255859375 +17583 0.29510498046875 +17584 0.31182861328125 +17585 0.257904052734375 +17586 0.250885009765625 +17587 0.20751953125 +17588 0.1654052734375 +17589 0.136871337890625 +17590 0.035247802734375 +17591 0.029388427734375 +17592 -0.142059326171875 +17593 -0.116943359375 +17594 -0.33563232421875 +17595 -0.27667236328125 +17596 -0.5345458984375 +17597 -0.440765380859375 +17598 -0.72186279296875 +17599 -0.595245361328125 +17600 -0.836669921875 +17601 -0.68994140625 +17602 -0.8326416015625 +17603 -0.68670654296875 +17604 -0.7296142578125 +17605 -0.60186767578125 +17606 -0.582550048828125 +17607 -0.480712890625 +17608 -0.440093994140625 +17609 -0.363311767578125 +17610 -0.324310302734375 +17611 -0.267852783203125 +17612 -0.20147705078125 +17613 -0.16656494140625 +17614 -0.044647216796875 +17615 -0.0372314453125 +17616 0.103973388671875 +17617 0.085357666015625 +17618 0.202392578125 +17619 0.166595458984375 +17620 0.264495849609375 +17621 0.2178955078125 +17622 0.338897705078125 +17623 0.279327392578125 +17624 0.443817138671875 +17625 0.365875244140625 +17626 0.545074462890625 +17627 0.44940185546875 +17628 0.6173095703125 +17629 0.50897216796875 +17630 0.6524658203125 +17631 0.537994384765625 +17632 0.66339111328125 +17633 0.547027587890625 +17634 0.6561279296875 +17635 0.541046142578125 +17636 0.606781005859375 +17637 0.500335693359375 +17638 0.501190185546875 +17639 0.413238525390625 +17640 0.352783203125 +17641 0.29083251953125 +17642 0.176544189453125 +17643 0.145477294921875 +17644 -0.034820556640625 +17645 -0.02880859375 +17646 -0.258209228515625 +17647 -0.212982177734375 +17648 -0.44244384765625 +17649 -0.364898681640625 +17650 -0.5753173828125 +17651 -0.47442626953125 +17652 -0.65203857421875 +17653 -0.53765869140625 +17654 -0.641632080078125 +17655 -0.529083251953125 +17656 -0.562164306640625 +17657 -0.463592529296875 +17658 -0.458038330078125 +17659 -0.377777099609375 +17660 -0.350555419921875 +17661 -0.289154052734375 +17662 -0.260528564453125 +17663 -0.214874267578125 +17664 -0.192108154296875 +17665 -0.158233642578125 +17666 -0.141937255859375 +17667 -0.11639404296875 +17668 -0.1021728515625 +17669 -0.08319091796875 +17670 -0.062896728515625 +17671 -0.050567626953125 +17672 -0.011932373046875 +17673 -0.00872802734375 +17674 0.062835693359375 +17675 0.05194091796875 +17676 0.148712158203125 +17677 0.121368408203125 +17678 0.241729736328125 +17679 0.19635009765625 +17680 0.34912109375 +17681 0.2825927734375 +17682 0.457305908203125 +17683 0.369293212890625 +17684 0.54388427734375 +17685 0.438629150390625 +17686 0.5728759765625 +17687 0.462066650390625 +17688 0.506591796875 +17689 0.409698486328125 +17690 0.351226806640625 +17691 0.286407470703125 +17692 0.146514892578125 +17693 0.123626708984375 +17694 -0.05523681640625 +17695 -0.037139892578125 +17696 -0.21624755859375 +17697 -0.165924072265625 +17698 -0.334930419921875 +17699 -0.26141357421875 +17700 -0.402984619140625 +17701 -0.31695556640625 +17702 -0.4412841796875 +17703 -0.3489990234375 +17704 -0.49578857421875 +17705 -0.39385986328125 +17706 -0.5601806640625 +17707 -0.4464111328125 +17708 -0.600738525390625 +17709 -0.479888916015625 +17710 -0.584228515625 +17711 -0.4678955078125 +17712 -0.47930908203125 +17713 -0.38555908203125 +17714 -0.27935791015625 +17715 -0.227630615234375 +17716 -0.0089111328125 +17717 -0.013519287109375 +17718 0.268798828125 +17719 0.206695556640625 +17720 0.482818603515625 +17721 0.376800537109375 +17722 0.60369873046875 +17723 0.473419189453125 +17724 0.650421142578125 +17725 0.51153564453125 +17726 0.66400146484375 +17727 0.5235595703125 +17728 0.6414794921875 +17729 0.507080078125 +17730 0.572540283203125 +17731 0.453857421875 +17732 0.498138427734375 +17733 0.396240234375 +17734 0.439453125 +17735 0.3509521484375 +17736 0.375518798828125 +17737 0.301300048828125 +17738 0.274505615234375 +17739 0.222015380859375 +17740 0.1087646484375 +17741 0.0911865234375 +17742 -0.099395751953125 +17743 -0.073516845703125 +17744 -0.3182373046875 +17745 -0.2469482421875 +17746 -0.5489501953125 +17747 -0.4300537109375 +17748 -0.7738037109375 +17749 -0.608734130859375 +17750 -0.86383056640625 +17751 -0.74102783203125 +17752 -0.870391845703125 +17753 -0.800567626953125 +17754 -0.86895751953125 +17755 -0.801300048828125 +17756 -0.861053466796875 +17757 -0.7535400390625 +17758 -0.765869140625 +17759 -0.6435546875 +17760 -0.5301513671875 +17761 -0.462371826171875 +17762 -0.214691162109375 +17763 -0.215576171875 +17764 0.137359619140625 +17765 0.062774658203125 +17766 0.474822998046875 +17767 0.33209228515625 +17768 0.76239013671875 +17769 0.564208984375 +17770 0.867462158203125 +17771 0.737762451171875 +17772 0.870361328125 +17773 0.85308837890625 +17774 0.86480712890625 +17775 0.85955810546875 +17776 0.831817626953125 +17777 0.857879638671875 +17778 0.677581787109375 +17779 0.82666015625 +17780 0.495880126953125 +17781 0.7281494140625 +17782 0.30767822265625 +17783 0.60491943359375 +17784 0.116180419921875 +17785 0.45867919921875 +17786 -0.110748291015625 +17787 0.26422119140625 +17788 -0.381805419921875 +17789 0.016021728515625 +17790 -0.6572265625 +17791 -0.25201416015625 +17792 -0.857421875 +17793 -0.49249267578125 +17794 -0.870391845703125 +17795 -0.67138671875 +17796 -0.870391845703125 +17797 -0.783050537109375 +17798 -0.86444091796875 +17799 -0.8487548828125 +17800 -0.85723876953125 +17801 -0.859130859375 +17802 -0.790008544921875 +17803 -0.86083984375 +17804 -0.62847900390625 +17805 -0.852935791015625 +17806 -0.3956298828125 +17807 -0.715576171875 +17808 -0.126708984375 +17809 -0.5263671875 +17810 0.150115966796875 +17811 -0.30694580078125 +17812 0.424041748046875 +17813 -0.066558837890625 +17814 0.670623779296875 +17815 0.173431396484375 +17816 0.854522705078125 +17817 0.382354736328125 +17818 0.866485595703125 +17819 0.54620361328125 +17820 0.86920166015625 +17821 0.652801513671875 +17822 0.8653564453125 +17823 0.71649169921875 +17824 0.857147216796875 +17825 0.747833251953125 +17826 0.766845703125 +17827 0.7445068359375 +17828 0.628509521484375 +17829 0.710540771484375 +17830 0.462127685546875 +17831 0.64056396484375 +17832 0.297210693359375 +17833 0.555023193359375 +17834 0.14862060546875 +17835 0.46368408203125 +17836 -0.00537109375 +17837 0.348419189453125 +17838 -0.15753173828125 +17839 0.21514892578125 +17840 -0.31304931640625 +17841 0.061004638671875 +17842 -0.48876953125 +17843 -0.125091552734375 +17844 -0.6416015625 +17845 -0.30596923828125 +17846 -0.751373291015625 +17847 -0.4620361328125 +17848 -0.84619140625 +17849 -0.61151123046875 +17850 -0.861297607421875 +17851 -0.74273681640625 +17852 -0.863250732421875 +17853 -0.829376220703125 +17854 -0.856597900390625 +17855 -0.846435546875 +17856 -0.7498779296875 +17857 -0.803497314453125 +17858 -0.624542236328125 +17859 -0.746337890625 +17860 -0.47808837890625 +17861 -0.657501220703125 +17862 -0.253387451171875 +17863 -0.490692138671875 +17864 0.003692626953125 +17865 -0.282073974609375 +17866 0.2257080078125 +17867 -0.085784912109375 +17868 0.427154541015625 +17869 0.1080322265625 +17870 0.643218994140625 +17871 0.32501220703125 +17872 0.855926513671875 +17873 0.55743408203125 +17874 0.870361328125 +17875 0.759368896484375 +17876 0.870361328125 +17877 0.8585205078125 +17878 0.862762451171875 +17879 0.86590576171875 +17880 0.79669189453125 +17881 0.86602783203125 +17882 0.595794677734375 +17883 0.858062744140625 +17884 0.362152099609375 +17885 0.763336181640625 +17886 0.1270751953125 +17887 0.610443115234375 +17888 -0.086944580078125 +17889 0.44549560546875 +17890 -0.2784423828125 +17891 0.270172119140625 +17892 -0.484832763671875 +17893 0.056976318359375 +17894 -0.729583740234375 +17895 -0.209197998046875 +17896 -0.86688232421875 +17897 -0.48822021484375 +17898 -0.870391845703125 +17899 -0.729827880859375 +17900 -0.86859130859375 +17901 -0.86273193359375 +17902 -0.86279296875 +17903 -0.870391845703125 +17904 -0.817962646484375 +17905 -0.870391845703125 +17906 -0.6116943359375 +17907 -0.859893798828125 +17908 -0.3128662109375 +17909 -0.709716796875 +17910 0.039398193359375 +17911 -0.44677734375 +17912 0.422821044921875 +17913 -0.132598876953125 +17914 0.805145263671875 +17915 0.205841064453125 +17916 0.870361328125 +17917 0.515167236328125 +17918 0.870361328125 +17919 0.751739501953125 +17920 0.860015869140625 +17921 0.860382080078125 +17922 0.727935791015625 +17923 0.868499755859375 +17924 0.48114013671875 +17925 0.86761474609375 +17926 0.2059326171875 +17927 0.860137939453125 +17928 -0.06103515625 +17929 0.799102783203125 +17930 -0.29913330078125 +17931 0.664947509765625 +17932 -0.516204833984375 +17933 0.496826171875 +17934 -0.7252197265625 +17935 0.28656005859375 +17936 -0.85980224609375 +17937 0.055999755859375 +17938 -0.870391845703125 +17939 -0.166534423828125 +17940 -0.870391845703125 +17941 -0.357177734375 +17942 -0.858062744140625 +17943 -0.4783935546875 +17944 -0.673004150390625 +17945 -0.527313232421875 +17946 -0.42694091796875 +17947 -0.544921875 +17948 -0.2100830078125 +17949 -0.566802978515625 +17950 -0.0362548828125 +17951 -0.593780517578125 +17952 0.10943603515625 +17953 -0.606658935546875 +17954 0.23516845703125 +17955 -0.593505859375 +17956 0.373687744140625 +17957 -0.526123046875 +17958 0.517791748046875 +17959 -0.40924072265625 +17960 0.602783203125 +17961 -0.293701171875 +17962 0.635711669921875 +17963 -0.17816162109375 +17964 0.655181884765625 +17965 -0.03936767578125 +17966 0.65948486328125 +17967 0.113616943359375 +17968 0.651275634765625 +17969 0.273895263671875 +17970 0.61846923828125 +17971 0.422698974609375 +17972 0.53753662109375 +17973 0.532501220703125 +17974 0.404144287109375 +17975 0.59075927734375 +17976 0.22186279296875 +17977 0.591796875 +17978 0.003997802734375 +17979 0.538726806640625 +17980 -0.22100830078125 +17981 0.447784423828125 +17982 -0.42449951171875 +17983 0.337310791015625 +17984 -0.579833984375 +17985 0.226165771484375 +17986 -0.641876220703125 +17987 0.14935302734375 +17988 -0.6177978515625 +17989 0.104095458984375 +17990 -0.575531005859375 +17991 0.043182373046875 +17992 -0.526336669921875 +17993 -0.035980224609375 +17994 -0.42645263671875 +17995 -0.0931396484375 +17996 -0.2581787109375 +17997 -0.1070556640625 +17998 -0.068695068359375 +17999 -0.105621337890625 +18000 0.09222412109375 +18001 -0.118865966796875 +18002 0.232147216796875 +18003 -0.133819580078125 +18004 0.3509521484375 +18005 -0.144378662109375 +18006 0.410064697265625 +18007 -0.17498779296875 +18008 0.372955322265625 +18009 -0.25 +18010 0.2554931640625 +18011 -0.3555908203125 +18012 0.10711669921875 +18013 -0.454193115234375 +18014 -0.052886962890625 +18015 -0.5328369140625 +18016 -0.186279296875 +18017 -0.56561279296875 +18018 -0.23291015625 +18019 -0.511322021484375 +18020 -0.209442138671875 +18021 -0.38812255859375 +18022 -0.174163818359375 +18023 -0.2464599609375 +18024 -0.126739501953125 +18025 -0.0926513671875 +18026 -0.048126220703125 +18027 0.08123779296875 +18028 0.0426025390625 +18029 0.254638671875 +18030 0.10748291015625 +18031 0.393280029296875 +18032 0.1409912109375 +18033 0.488525390625 +18034 0.19708251953125 +18035 0.578094482421875 +18036 0.273651123046875 +18037 0.658538818359375 +18038 0.31768798828125 +18039 0.689056396484375 +18040 0.341094970703125 +18041 0.679595947265625 +18042 0.368011474609375 +18043 0.65069580078125 +18044 0.37249755859375 +18045 0.5859375 +18046 0.30072021484375 +18047 0.44866943359375 +18048 0.1517333984375 +18049 0.243072509765625 +18050 -0.01470947265625 +18051 0.019866943359375 +18052 -0.1883544921875 +18053 -0.20770263671875 +18054 -0.372711181640625 +18055 -0.4371337890625 +18056 -0.51397705078125 +18057 -0.62286376953125 +18058 -0.57177734375 +18059 -0.730224609375 +18060 -0.53948974609375 +18061 -0.751190185546875 +18062 -0.43511962890625 +18063 -0.697479248046875 +18064 -0.2962646484375 +18065 -0.596832275390625 +18066 -0.161102294921875 +18067 -0.478607177734375 +18068 -0.0435791015625 +18069 -0.35479736328125 +18070 0.060394287109375 +18071 -0.2247314453125 +18072 0.13665771484375 +18073 -0.102386474609375 +18074 0.170135498046875 +18075 -0.003143310546875 +18076 0.16552734375 +18077 0.072265625 +18078 0.15728759765625 +18079 0.14556884765625 +18080 0.150787353515625 +18081 0.21649169921875 +18082 0.12200927734375 +18083 0.26275634765625 +18084 0.080108642578125 +18085 0.287811279296875 +18086 0.05126953125 +18087 0.308807373046875 +18088 0.062896728515625 +18089 0.344635009765625 +18090 0.09271240234375 +18091 0.3773193359375 +18092 0.092987060546875 +18093 0.37054443359375 +18094 0.07855224609375 +18095 0.33642578125 +18096 0.06427001953125 +18097 0.287994384765625 +18098 0.0347900390625 +18099 0.216064453125 +18100 -0.01171875 +18101 0.122222900390625 +18102 -0.056060791015625 +18103 0.024566650390625 +18104 -0.055511474609375 +18105 -0.040802001953125 +18106 -0.010467529296875 +18107 -0.07049560546875 +18108 0.02508544921875 +18109 -0.10211181640625 +18110 0.025665283203125 +18111 -0.1519775390625 +18112 0.017333984375 +18113 -0.197784423828125 +18114 0.00189208984375 +18115 -0.236328125 +18116 -0.03173828125 +18117 -0.274932861328125 +18118 -0.071502685546875 +18119 -0.304168701171875 +18120 -0.13543701171875 +18121 -0.338165283203125 +18122 -0.219970703125 +18123 -0.37542724609375 +18124 -0.300506591796875 +18125 -0.399078369140625 +18126 -0.376312255859375 +18127 -0.410888671875 +18128 -0.416107177734375 +18129 -0.389801025390625 +18130 -0.371124267578125 +18131 -0.301727294921875 +18132 -0.242279052734375 +18133 -0.150360107421875 +18134 -0.069732666015625 +18135 0.030853271484375 +18136 0.125640869140625 +18137 0.223388671875 +18138 0.31268310546875 +18139 0.401336669921875 +18140 0.45501708984375 +18141 0.535369873046875 +18142 0.554779052734375 +18143 0.625946044921875 +18144 0.61065673828125 +18145 0.671600341796875 +18146 0.610931396484375 +18147 0.66357421875 +18148 0.531463623046875 +18149 0.5843505859375 +18150 0.3883056640625 +18151 0.447418212890625 +18152 0.23468017578125 +18153 0.2950439453125 +18154 0.095245361328125 +18155 0.14813232421875 +18156 -0.00396728515625 +18157 0.02880859375 +18158 -0.04852294921875 +18159 -0.0494384765625 +18160 -0.055145263671875 +18161 -0.09686279296875 +18162 -0.0758056640625 +18163 -0.1507568359375 +18164 -0.138702392578125 +18165 -0.230560302734375 +18166 -0.209197998046875 +18167 -0.308380126953125 +18168 -0.289031982421875 +18169 -0.38446044921875 +18170 -0.37884521484375 +18171 -0.458709716796875 +18172 -0.456329345703125 +18173 -0.51409912109375 +18174 -0.51641845703125 +18175 -0.5472412109375 +18176 -0.519287109375 +18177 -0.52899169921875 +18178 -0.458251953125 +18179 -0.45562744140625 +18180 -0.384796142578125 +18181 -0.3675537109375 +18182 -0.323699951171875 +18183 -0.285308837890625 +18184 -0.269287109375 +18185 -0.20672607421875 +18186 -0.1951904296875 +18187 -0.1141357421875 +18188 -0.100006103515625 +18189 -0.008514404296875 +18190 -0.01055908203125 +18191 0.08819580078125 +18192 0.1033935546875 +18193 0.19720458984375 +18194 0.24908447265625 +18195 0.32281494140625 +18196 0.373199462890625 +18197 0.42437744140625 +18198 0.45806884765625 +18199 0.488372802734375 +18200 0.511474609375 +18201 0.520843505859375 +18202 0.565399169921875 +18203 0.546417236328125 +18204 0.61138916015625 +18205 0.559814453125 +18206 0.5897216796875 +18207 0.517547607421875 +18208 0.4906005859375 +18209 0.413818359375 +18210 0.33148193359375 +18211 0.263427734375 +18212 0.147796630859375 +18213 0.09466552734375 +18214 -0.01873779296875 +18215 -0.059478759765625 +18216 -0.140289306640625 +18217 -0.176544189453125 +18218 -0.191986083984375 +18219 -0.236572265625 +18220 -0.184295654296875 +18221 -0.24639892578125 +18222 -0.161834716796875 +18223 -0.238800048828125 +18224 -0.166595458984375 +18225 -0.24493408203125 +18226 -0.19390869140625 +18227 -0.2613525390625 +18228 -0.22442626953125 +18229 -0.27392578125 +18230 -0.279754638671875 +18231 -0.29962158203125 +18232 -0.3389892578125 +18233 -0.32379150390625 +18234 -0.3543701171875 +18235 -0.3118896484375 +18236 -0.348175048828125 +18237 -0.281951904296875 +18238 -0.32598876953125 +18239 -0.239593505859375 +18240 -0.2581787109375 +18241 -0.164031982421875 +18242 -0.139801025390625 +18243 -0.0528564453125 +18244 0.014617919921875 +18245 0.081878662109375 +18246 0.144378662109375 +18247 0.193695068359375 +18248 0.221038818359375 +18249 0.2606201171875 +18250 0.27069091796875 +18251 0.301849365234375 +18252 0.294036865234375 +18253 0.317840576171875 +18254 0.311767578125 +18255 0.324371337890625 +18256 0.339141845703125 +18257 0.33331298828125 +18258 0.360260009765625 +18259 0.333251953125 +18260 0.360504150390625 +18261 0.314300537109375 +18262 0.308380126953125 +18263 0.254730224609375 +18264 0.18170166015625 +18265 0.139739990234375 +18266 0.0047607421875 +18267 -0.011627197265625 +18268 -0.17559814453125 +18269 -0.164031982421875 +18270 -0.3143310546875 +18271 -0.283538818359375 +18272 -0.36785888671875 +18273 -0.337493896484375 +18274 -0.36248779296875 +18275 -0.34429931640625 +18276 -0.343536376953125 +18277 -0.336456298828125 +18278 -0.3018798828125 +18279 -0.307159423828125 +18280 -0.231414794921875 +18281 -0.252044677734375 +18282 -0.117645263671875 +18283 -0.160919189453125 +18284 0.007049560546875 +18285 -0.057952880859375 +18286 0.087982177734375 +18287 0.016265869140625 +18288 0.13946533203125 +18289 0.07122802734375 +18290 0.17425537109375 +18291 0.115203857421875 +18292 0.188201904296875 +18293 0.14410400390625 +18294 0.171234130859375 +18295 0.1495361328125 +18296 0.118438720703125 +18297 0.12701416015625 +18298 0.05706787109375 +18299 0.0955810546875 +18300 -0.010711669921875 +18301 0.056121826171875 +18302 -0.0914306640625 +18303 0.003448486328125 +18304 -0.162322998046875 +18305 -0.0460205078125 +18306 -0.194549560546875 +18307 -0.07135009765625 +18308 -0.1492919921875 +18309 -0.0440673828125 +18310 -0.02166748046875 +18311 0.039794921875 +18312 0.124053955078125 +18313 0.134063720703125 +18314 0.211151123046875 +18315 0.183624267578125 +18316 0.240447998046875 +18317 0.18988037109375 +18318 0.242218017578125 +18319 0.175689697265625 +18320 0.2257080078125 +18321 0.148681640625 +18322 0.194366455078125 +18323 0.1121826171875 +18324 0.115509033203125 +18325 0.043060302734375 +18326 0.0128173828125 +18327 -0.040802001953125 +18328 -0.053802490234375 +18329 -0.095367431640625 +18330 -0.110626220703125 +18331 -0.139556884765625 +18332 -0.199493408203125 +18333 -0.20379638671875 +18334 -0.29437255859375 +18335 -0.26922607421875 +18336 -0.33221435546875 +18337 -0.290252685546875 +18338 -0.27972412109375 +18339 -0.243072509765625 +18340 -0.185333251953125 +18341 -0.16351318359375 +18342 -0.128204345703125 +18343 -0.10980224609375 +18344 -0.115692138671875 +18345 -0.087982177734375 +18346 -0.116455078125 +18347 -0.07598876953125 +18348 -0.105926513671875 +18349 -0.056610107421875 +18350 -0.053955078125 +18351 -0.008544921875 +18352 0.048797607421875 +18353 0.07452392578125 +18354 0.157318115234375 +18355 0.159423828125 +18356 0.212005615234375 +18357 0.2025146484375 +18358 0.218475341796875 +18359 0.207794189453125 +18360 0.23724365234375 +18361 0.219329833984375 +18362 0.30535888671875 +18363 0.264312744140625 +18364 0.38128662109375 +18365 0.31280517578125 +18366 0.404449462890625 +18367 0.321136474609375 +18368 0.3944091796875 +18369 0.3040771484375 +18370 0.3885498046875 +18371 0.289398193359375 +18372 0.362640380859375 +18373 0.26007080078125 +18374 0.27362060546875 +18375 0.185302734375 +18376 0.11712646484375 +18377 0.06243896484375 +18378 -0.054901123046875 +18379 -0.070220947265625 +18380 -0.19085693359375 +18381 -0.174713134765625 +18382 -0.28570556640625 +18383 -0.247161865234375 +18384 -0.339263916015625 +18385 -0.287322998046875 +18386 -0.3775634765625 +18387 -0.314117431640625 +18388 -0.445709228515625 +18389 -0.36053466796875 +18390 -0.535064697265625 +18391 -0.4205322265625 +18392 -0.629058837890625 +18393 -0.48236083984375 +18394 -0.697601318359375 +18395 -0.524505615234375 +18396 -0.70391845703125 +18397 -0.520660400390625 +18398 -0.6424560546875 +18399 -0.467254638671875 +18400 -0.491241455078125 +18401 -0.348785400390625 +18402 -0.265716552734375 +18403 -0.176910400390625 +18404 -0.023712158203125 +18405 0.00579833984375 +18406 0.201751708984375 +18407 0.17498779296875 +18408 0.375823974609375 +18409 0.305084228515625 +18410 0.485076904296875 +18411 0.386199951171875 +18412 0.56884765625 +18413 0.4468994140625 +18414 0.634765625 +18415 0.492828369140625 +18416 0.63763427734375 +18417 0.49127197265625 +18418 0.5660400390625 +18419 0.434112548828125 +18420 0.4720458984375 +18421 0.35955810546875 +18422 0.40692138671875 +18423 0.305328369140625 +18424 0.3778076171875 +18425 0.277008056640625 +18426 0.376953125 +18427 0.26934814453125 +18428 0.371978759765625 +18429 0.2591552734375 +18430 0.313140869140625 +18431 0.2105712890625 +18432 0.184417724609375 +18433 0.112457275390625 +18434 0.011199951171875 +18435 -0.016204833984375 +18436 -0.171051025390625 +18437 -0.14971923828125 +18438 -0.33740234375 +18439 -0.2703857421875 +18440 -0.47198486328125 +18441 -0.36688232421875 +18442 -0.560394287109375 +18443 -0.429046630859375 +18444 -0.58056640625 +18445 -0.441558837890625 +18446 -0.54754638671875 +18447 -0.415008544921875 +18448 -0.508575439453125 +18449 -0.382537841796875 +18450 -0.459503173828125 +18451 -0.34161376953125 +18452 -0.394378662109375 +18453 -0.288482666015625 +18454 -0.35260009765625 +18455 -0.25103759765625 +18456 -0.31170654296875 +18457 -0.214080810546875 +18458 -0.197418212890625 +18459 -0.12640380859375 +18460 -0.007965087890625 +18461 0.012786865234375 +18462 0.207489013671875 +18463 0.16888427734375 +18464 0.409210205078125 +18465 0.31390380859375 +18466 0.57208251953125 +18467 0.430145263671875 +18468 0.66595458984375 +18469 0.496551513671875 +18470 0.65875244140625 +18471 0.490753173828125 +18472 0.56744384765625 +18473 0.4246826171875 +18474 0.431396484375 +18475 0.325897216796875 +18476 0.29443359375 +18477 0.2252197265625 +18478 0.182464599609375 +18479 0.140960693359375 +18480 0.06365966796875 +18481 0.0513916015625 +18482 -0.075958251953125 +18483 -0.0528564453125 +18484 -0.189422607421875 +18485 -0.138671875 +18486 -0.271942138671875 +18487 -0.202362060546875 +18488 -0.342529296875 +18489 -0.2568359375 +18490 -0.364166259765625 +18491 -0.276092529296875 +18492 -0.327239990234375 +18493 -0.25323486328125 +18494 -0.2769775390625 +18495 -0.219635009765625 +18496 -0.253692626953125 +18497 -0.20330810546875 +18498 -0.24365234375 +18499 -0.194732666015625 +18500 -0.1983642578125 +18501 -0.160308837890625 +18502 -0.116241455078125 +18503 -0.09912109375 +18504 -0.036834716796875 +18505 -0.038909912109375 +18506 0.034881591796875 +18507 0.01654052734375 +18508 0.09124755859375 +18509 0.06158447265625 +18510 0.10888671875 +18511 0.079620361328125 +18512 0.125518798828125 +18513 0.0965576171875 +18514 0.15771484375 +18515 0.1236572265625 +18516 0.17828369140625 +18517 0.14178466796875 +18518 0.17108154296875 +18519 0.139495849609375 +18520 0.129974365234375 +18521 0.1124267578125 +18522 0.082427978515625 +18523 0.079620361328125 +18524 0.027679443359375 +18525 0.04058837890625 +18526 -0.065643310546875 +18527 -0.026397705078125 +18528 -0.15936279296875 +18529 -0.0946044921875 +18530 -0.21307373046875 +18531 -0.135772705078125 +18532 -0.234649658203125 +18533 -0.1551513671875 +18534 -0.2001953125 +18535 -0.135833740234375 +18536 -0.119171142578125 +18537 -0.08416748046875 +18538 -0.024749755859375 +18539 -0.02294921875 +18540 0.085784912109375 +18541 0.0499267578125 +18542 0.178131103515625 +18543 0.11077880859375 +18544 0.215576171875 +18545 0.134246826171875 +18546 0.211456298828125 +18547 0.12969970703125 +18548 0.17523193359375 +18549 0.10382080078125 +18550 0.128753662109375 +18551 0.071807861328125 +18552 0.1019287109375 +18553 0.054443359375 +18554 0.0743408203125 +18555 0.037445068359375 +18556 0.04327392578125 +18557 0.01873779296875 +18558 0.038177490234375 +18559 0.018646240234375 +18560 0.076263427734375 +18561 0.048919677734375 +18562 0.14105224609375 +18563 0.097869873046875 +18564 0.186431884765625 +18565 0.13323974609375 +18566 0.188812255859375 +18567 0.13836669921875 +18568 0.1390380859375 +18569 0.106689453125 +18570 0.041778564453125 +18571 0.041351318359375 +18572 -0.079437255859375 +18573 -0.0413818359375 +18574 -0.219390869140625 +18575 -0.137969970703125 +18576 -0.367828369140625 +18577 -0.24127197265625 +18578 -0.494873046875 +18579 -0.330474853515625 +18580 -0.556243896484375 +18581 -0.374725341796875 +18582 -0.508697509765625 +18583 -0.343780517578125 +18584 -0.3756103515625 +18585 -0.2537841796875 +18586 -0.218902587890625 +18587 -0.147705078125 +18588 -0.063751220703125 +18589 -0.0428466796875 +18590 0.091552734375 +18591 0.062103271484375 +18592 0.23602294921875 +18593 0.15966796875 +18594 0.342987060546875 +18595 0.2314453125 +18596 0.39520263671875 +18597 0.265625 +18598 0.389373779296875 +18599 0.259979248046875 +18600 0.324249267578125 +18601 0.213714599609375 +18602 0.224090576171875 +18603 0.14373779296875 +18604 0.124267578125 +18605 0.074676513671875 +18606 0.037078857421875 +18607 0.0150146484375 +18608 -0.010101318359375 +18609 -0.016204833984375 +18610 -0.019439697265625 +18611 -0.0206298828125 +18612 -0.022796630859375 +18613 -0.02056884765625 +18614 -0.001556396484375 +18615 -0.003204345703125 +18616 0.056304931640625 +18617 0.0396728515625 +18618 0.106719970703125 +18619 0.0772705078125 +18620 0.096893310546875 +18621 0.07269287109375 +18622 0.042694091796875 +18623 0.036895751953125 +18624 -0.018035888671875 +18625 -0.003875732421875 +18626 -0.07586669921875 +18627 -0.04315185546875 +18628 -0.11944580078125 +18629 -0.07305908203125 +18630 -0.15972900390625 +18631 -0.101226806640625 +18632 -0.202606201171875 +18633 -0.1317138671875 +18634 -0.24859619140625 +18635 -0.164825439453125 +18636 -0.30517578125 +18637 -0.2056884765625 +18638 -0.36212158203125 +18639 -0.24713134765625 +18640 -0.39141845703125 +18641 -0.269561767578125 +18642 -0.35528564453125 +18643 -0.246551513671875 +18644 -0.249969482421875 +18645 -0.175384521484375 +18646 -0.092864990234375 +18647 -0.06805419921875 +18648 0.08905029296875 +18649 0.056793212890625 +18650 0.2352294921875 +18651 0.1571044921875 +18652 0.318817138671875 +18653 0.214263916015625 +18654 0.358642578125 +18655 0.24139404296875 +18656 0.347747802734375 +18657 0.233673095703125 +18658 0.28564453125 +18659 0.190765380859375 +18660 0.223175048828125 +18661 0.148040771484375 +18662 0.196746826171875 +18663 0.13079833984375 +18664 0.179840087890625 +18665 0.1204833984375 +18666 0.155548095703125 +18667 0.105255126953125 +18668 0.151214599609375 +18669 0.104034423828125 +18670 0.156951904296875 +18671 0.10986328125 +18672 0.13177490234375 +18673 0.094085693359375 +18674 0.100799560546875 +18675 0.0740966796875 +18676 0.087127685546875 +18677 0.06585693359375 +18678 0.05487060546875 +18679 0.04437255859375 +18680 -0.009002685546875 +18681 0.000518798828125 +18682 -0.10400390625 +18683 -0.06536865234375 +18684 -0.229400634765625 +18685 -0.15283203125 +18686 -0.35552978515625 +18687 -0.24114990234375 +18688 -0.441925048828125 +18689 -0.301910400390625 +18690 -0.473846435546875 +18691 -0.32452392578125 +18692 -0.464813232421875 +18693 -0.318206787109375 +18694 -0.419097900390625 +18695 -0.286285400390625 +18696 -0.334320068359375 +18697 -0.227691650390625 +18698 -0.227935791015625 +18699 -0.154388427734375 +18700 -0.12347412109375 +18701 -0.082366943359375 +18702 -0.02764892578125 +18703 -0.01629638671875 +18704 0.077667236328125 +18705 0.055694580078125 +18706 0.2132568359375 +18707 0.14727783203125 +18708 0.38885498046875 +18709 0.264801025390625 +18710 0.582794189453125 +18711 0.3939208984375 +18712 0.734039306640625 +18713 0.494110107421875 +18714 0.800140380859375 +18715 0.537261962890625 +18716 0.7783203125 +18717 0.5216064453125 +18718 0.6651611328125 +18719 0.444976806640625 +18720 0.45965576171875 +18721 0.30682373046875 +18722 0.199188232421875 +18723 0.13214111328125 +18724 -0.050689697265625 +18725 -0.035430908203125 +18726 -0.23297119140625 +18727 -0.157958984375 +18728 -0.33013916015625 +18729 -0.2237548828125 +18730 -0.368408203125 +18731 -0.2501220703125 +18732 -0.378936767578125 +18733 -0.2576904296875 +18734 -0.376983642578125 +18735 -0.256591796875 +18736 -0.37969970703125 +18737 -0.25823974609375 +18738 -0.391510009765625 +18739 -0.265594482421875 +18740 -0.385345458984375 +18741 -0.260711669921875 +18742 -0.3419189453125 +18743 -0.2308349609375 +18744 -0.28289794921875 +18745 -0.1904296875 +18746 -0.251617431640625 +18747 -0.168304443359375 +18748 -0.266143798828125 +18749 -0.176544189453125 +18750 -0.273345947265625 +18751 -0.179962158203125 +18752 -0.216796875 +18753 -0.14117431640625 +18754 -0.128265380859375 +18755 -0.081298828125 +18756 -0.068145751953125 +18757 -0.04052734375 +18758 -0.0430908203125 +18759 -0.0233154296875 +18760 -0.024444580078125 +18761 -0.010650634765625 +18762 0.020721435546875 +18763 0.019317626953125 +18764 0.124481201171875 +18765 0.087890625 +18766 0.25787353515625 +18767 0.175872802734375 +18768 0.379119873046875 +18769 0.25555419921875 +18770 0.47991943359375 +18771 0.32147216796875 +18772 0.5281982421875 +18773 0.352386474609375 +18774 0.511138916015625 +18775 0.339874267578125 +18776 0.456207275390625 +18777 0.302215576171875 +18778 0.407470703125 +18779 0.26873779296875 +18780 0.383758544921875 +18781 0.25201416015625 +18782 0.35687255859375 +18783 0.233367919921875 +18784 0.31182861328125 +18785 0.202880859375 +18786 0.250885009765625 +18787 0.16204833984375 +18788 0.1654052734375 +18789 0.10516357421875 +18790 0.035247802734375 +18791 0.01885986328125 +18792 -0.142059326171875 +18793 -0.0985107421875 +18794 -0.33563232421875 +18795 -0.2264404296875 +18796 -0.5345458984375 +18797 -0.357696533203125 +18798 -0.72186279296875 +18799 -0.481109619140625 +18800 -0.836669921875 +18801 -0.5562744140625 +18802 -0.8326416015625 +18803 -0.552520751953125 +18804 -0.7296142578125 +18805 -0.483062744140625 +18806 -0.582550048828125 +18807 -0.38446044921875 +18808 -0.440093994140625 +18809 -0.2890625 +18810 -0.324310302734375 +18811 -0.2115478515625 +18812 -0.20147705078125 +18813 -0.12957763671875 +18814 -0.044647216796875 +18815 -0.025238037109375 +18816 0.103973388671875 +18817 0.07342529296875 +18818 0.202392578125 +18819 0.13848876953125 +18820 0.264495849609375 +18821 0.179229736328125 +18822 0.338897705078125 +18823 0.22796630859375 +18824 0.443817138671875 +18825 0.29681396484375 +18826 0.545074462890625 +18827 0.363128662109375 +18828 0.6173095703125 +18829 0.410125732421875 +18830 0.6524658203125 +18831 0.432525634765625 +18832 0.66339111328125 +18833 0.43890380859375 +18834 0.6561279296875 +18835 0.433319091796875 +18836 0.606781005859375 +18837 0.399932861328125 +18838 0.501190185546875 +18839 0.329376220703125 +18840 0.352783203125 +18841 0.2305908203125 +18842 0.176544189453125 +18843 0.113525390625 +18844 -0.034820556640625 +18845 -0.026641845703125 +18846 -0.258209228515625 +18847 -0.174591064453125 +18848 -0.44244384765625 +18849 -0.296356201171875 +18850 -0.5753173828125 +18851 -0.383880615234375 +18852 -0.65203857421875 +18853 -0.43402099609375 +18854 -0.641632080078125 +18855 -0.42626953125 +18856 -0.562164306640625 +18857 -0.3726806640625 +18858 -0.458038330078125 +18859 -0.30279541015625 +18860 -0.350555419921875 +18861 -0.230743408203125 +18862 -0.260528564453125 +18863 -0.17041015625 +18864 -0.192108154296875 +18865 -0.12457275390625 +18866 -0.141937255859375 +18867 -0.091033935546875 +18868 -0.1021728515625 +18869 -0.0645751953125 +18870 -0.062896728515625 +18871 -0.038604736328125 +18872 -0.011932373046875 +18873 -0.005035400390625 +18874 0.062835693359375 +18875 0.044189453125 +18876 0.148712158203125 +18877 0.100677490234375 +18878 0.241729736328125 +18879 0.16180419921875 +18880 0.34912109375 +18881 0.232421875 +18882 0.457305908203125 +18883 0.303558349609375 +18884 0.54388427734375 +18885 0.360382080078125 +18886 0.5728759765625 +18887 0.379058837890625 +18888 0.506591796875 +18889 0.334564208984375 +18890 0.351226806640625 +18891 0.231048583984375 +18892 0.146514892578125 +18893 0.094879150390625 +18894 -0.05523681640625 +18895 -0.039154052734375 +18896 -0.21624755859375 +18897 -0.14599609375 +18898 -0.334930419921875 +18899 -0.224578857421875 +18900 -0.402984619140625 +18901 -0.269439697265625 +18902 -0.4412841796875 +18903 -0.29443359375 +18904 -0.49578857421875 +18905 -0.330108642578125 +18906 -0.5601806640625 +18907 -0.372314453125 +18908 -0.600738525390625 +18909 -0.398681640625 +18910 -0.584228515625 +18911 -0.38714599609375 +18912 -0.47930908203125 +18913 -0.31695556640625 +18914 -0.27935791015625 +18915 -0.183746337890625 +18916 -0.0089111328125 +18917 -0.003814697265625 +18918 0.268798828125 +18919 0.1807861328125 +18920 0.482818603515625 +18921 0.322967529296875 +18922 0.60369873046875 +18923 0.403167724609375 +18924 0.650421142578125 +18925 0.433990478515625 +18926 0.66400146484375 +18927 0.442718505859375 +18928 0.6414794921875 +18929 0.427398681640625 +18930 0.572540283203125 +18931 0.381195068359375 +18932 0.498138427734375 +18933 0.331329345703125 +18934 0.439453125 +18935 0.291900634765625 +18936 0.375518798828125 +18937 0.248992919921875 +18938 0.274505615234375 +18939 0.181488037109375 +18940 0.1087646484375 +18941 0.071044921875 +18942 -0.099395751953125 +18943 -0.0675048828125 +18944 -0.3182373046875 +18945 -0.2125244140625 +18946 -0.5489501953125 +18947 -0.364013671875 +18948 -0.7738037109375 +18949 -0.5103759765625 +18950 -0.86383056640625 +18951 -0.61798095703125 +18952 -0.870391845703125 +18953 -0.665740966796875 +18954 -0.86895751953125 +18955 -0.664886474609375 +18956 -0.861053466796875 +18957 -0.62384033203125 +18958 -0.765869140625 +18959 -0.5318603515625 +18960 -0.5301513671875 +18961 -0.382110595703125 +18962 -0.214691162109375 +18963 -0.17938232421875 +18964 0.137359619140625 +18965 0.04876708984375 +18966 0.474822998046875 +18967 0.26959228515625 +18968 0.76239013671875 +18969 0.4603271484375 +18970 0.867462158203125 +18971 0.603607177734375 +18972 0.870361328125 +18973 0.699462890625 +18974 0.86480712890625 +18975 0.74041748046875 +18976 0.831817626953125 +18977 0.729705810546875 +18978 0.677581787109375 +18979 0.682647705078125 +18980 0.495880126953125 +18981 0.602874755859375 +18982 0.30767822265625 +18983 0.502197265625 +18984 0.116180419921875 +18985 0.38214111328125 +18986 -0.110748291015625 +18987 0.22283935546875 +18988 -0.381805419921875 +18989 0.020111083984375 +18990 -0.6572265625 +18991 -0.198699951171875 +18992 -0.857421875 +18993 -0.3955078125 +18994 -0.870391845703125 +18995 -0.542877197265625 +18996 -0.870391845703125 +18997 -0.636077880859375 +18998 -0.86444091796875 +18999 -0.69189453125 +19000 -0.85723876953125 +19001 -0.732696533203125 +19002 -0.790008544921875 +19003 -0.746734619140625 +19004 -0.62847900390625 +19005 -0.69964599609375 +19006 -0.3956298828125 +19007 -0.58941650390625 +19008 -0.126708984375 +19009 -0.43682861328125 +19010 0.150115966796875 +19011 -0.25927734375 +19012 0.424041748046875 +19013 -0.064300537109375 +19014 0.670623779296875 +19015 0.130859375 +19016 0.854522705078125 +19017 0.301544189453125 +19018 0.866485595703125 +19019 0.43634033203125 +19020 0.86920166015625 +19021 0.525299072265625 +19022 0.8653564453125 +19023 0.57965087890625 +19024 0.857147216796875 +19025 0.607666015625 +19026 0.766845703125 +19027 0.607330322265625 +19028 0.628509521484375 +19029 0.581756591796875 +19030 0.462127685546875 +19031 0.526611328125 +19032 0.297210693359375 +19033 0.458160400390625 +19034 0.14862060546875 +19035 0.384246826171875 +19036 -0.00537109375 +19037 0.290496826171875 +19038 -0.15753173828125 +19039 0.1817626953125 +19040 -0.31304931640625 +19041 0.055908203125 +19042 -0.48876953125 +19043 -0.095733642578125 +19044 -0.6416015625 +19045 -0.24334716796875 +19046 -0.751373291015625 +19047 -0.371124267578125 +19048 -0.84619140625 +19049 -0.493438720703125 +19050 -0.861297607421875 +19051 -0.60076904296875 +19052 -0.863250732421875 +19053 -0.672027587890625 +19054 -0.856597900390625 +19055 -0.687103271484375 +19056 -0.7498779296875 +19057 -0.653594970703125 +19058 -0.624542236328125 +19059 -0.6080322265625 +19060 -0.47808837890625 +19061 -0.5364990234375 +19062 -0.253387451171875 +19063 -0.402130126953125 +19064 0.003692626953125 +19065 -0.233856201171875 +19066 0.2257080078125 +19067 -0.07501220703125 +19068 0.427154541015625 +19069 0.082183837890625 +19070 0.643218994140625 +19071 0.25799560546875 +19072 0.855926513671875 +19073 0.446136474609375 +19074 0.870361328125 +19075 0.609771728515625 +19076 0.870361328125 +19077 0.717376708984375 +19078 0.862762451171875 +19079 0.7733154296875 +19080 0.79669189453125 +19081 0.775604248046875 +19082 0.595794677734375 +19083 0.718170166015625 +19084 0.362152099609375 +19085 0.61944580078125 +19086 0.1270751953125 +19087 0.49713134765625 +19088 -0.086944580078125 +19089 0.364654541015625 +19090 -0.2784423828125 +19091 0.223419189453125 +19092 -0.484832763671875 +19093 0.05157470703125 +19094 -0.729583740234375 +19095 -0.162841796875 +19096 -0.86688232421875 +19097 -0.38763427734375 +19098 -0.870391845703125 +19099 -0.582611083984375 +19100 -0.86859130859375 +19101 -0.744415283203125 +19102 -0.86279296875 +19103 -0.856353759765625 +19104 -0.817962646484375 +19105 -0.86395263671875 +19106 -0.6116943359375 +19107 -0.862091064453125 +19108 -0.3128662109375 +19109 -0.816009521484375 +19110 0.039398193359375 +19111 -0.638153076171875 +19112 0.422821044921875 +19113 -0.40313720703125 +19114 0.805145263671875 +19115 -0.132049560546875 +19116 0.870361328125 +19117 0.131927490234375 +19118 0.870361328125 +19119 0.35260009765625 +19120 0.860015869140625 +19121 0.522308349609375 +19122 0.727935791015625 +19123 0.63592529296875 +19124 0.48114013671875 +19125 0.689544677734375 +19126 0.2059326171875 +19127 0.698150634765625 +19128 -0.06103515625 +19129 0.675750732421875 +19130 -0.29913330078125 +19131 0.628448486328125 +19132 -0.516204833984375 +19133 0.546875 +19134 -0.7252197265625 +19135 0.42120361328125 +19136 -0.85980224609375 +19137 0.267181396484375 +19138 -0.870391845703125 +19139 0.106597900390625 +19140 -0.870391845703125 +19141 -0.0416259765625 +19142 -0.858062744140625 +19143 -0.14642333984375 +19144 -0.673004150390625 +19145 -0.204742431640625 +19146 -0.42694091796875 +19147 -0.24932861328125 +19148 -0.2100830078125 +19149 -0.307769775390625 +19150 -0.0362548828125 +19151 -0.37823486328125 +19152 0.10943603515625 +19153 -0.441925048828125 +19154 0.23516845703125 +19155 -0.48583984375 +19156 0.373687744140625 +19157 -0.4835205078125 +19158 0.517791748046875 +19159 -0.435943603515625 +19160 0.602783203125 +19161 -0.382843017578125 +19162 0.635711669921875 +19163 -0.320953369140625 +19164 0.655181884765625 +19165 -0.22930908203125 +19166 0.65948486328125 +19167 -0.114410400390625 +19168 0.651275634765625 +19169 0.018280029296875 +19170 0.61846923828125 +19171 0.15289306640625 +19172 0.53753662109375 +19173 0.26556396484375 +19174 0.404144287109375 +19175 0.34442138671875 +19176 0.22186279296875 +19177 0.382843017578125 +19178 0.003997802734375 +19179 0.381134033203125 +19180 -0.22100830078125 +19181 0.350341796875 +19182 -0.42449951171875 +19183 0.30322265625 +19184 -0.579833984375 +19185 0.2530517578125 +19186 -0.641876220703125 +19187 0.2266845703125 +19188 -0.6177978515625 +19189 0.21990966796875 +19190 -0.575531005859375 +19191 0.191986083984375 +19192 -0.526336669921875 +19193 0.139678955078125 +19194 -0.42645263671875 +19195 0.096038818359375 +19196 -0.2581787109375 +19197 0.0787353515625 +19198 -0.068695068359375 +19199 0.065185546875 +19200 0.09222412109375 +19201 0.031005859375 +19202 0.232147216796875 +19203 -0.01214599609375 +19204 0.3509521484375 +19205 -0.056854248046875 +19206 0.410064697265625 +19207 -0.11993408203125 +19208 0.372955322265625 +19209 -0.21820068359375 +19210 0.2554931640625 +19211 -0.33843994140625 +19212 0.10711669921875 +19213 -0.44891357421875 +19214 -0.052886962890625 +19215 -0.53765869140625 +19216 -0.186279296875 +19217 -0.5828857421875 +19218 -0.23291015625 +19219 -0.55120849609375 +19220 -0.209442138671875 +19221 -0.45660400390625 +19222 -0.174163818359375 +19223 -0.339019775390625 +19224 -0.126739501953125 +19225 -0.2039794921875 +19226 -0.048126220703125 +19227 -0.04620361328125 +19228 0.0426025390625 +19229 0.116668701171875 +19230 0.10748291015625 +19231 0.2559814453125 +19232 0.1409912109375 +19233 0.3631591796875 +19234 0.19708251953125 +19235 0.466217041015625 +19236 0.273651123046875 +19237 0.560638427734375 +19238 0.31768798828125 +19239 0.612518310546875 +19240 0.341094970703125 +19241 0.6282958984375 +19242 0.368011474609375 +19243 0.623046875 +19244 0.37249755859375 +19245 0.5830078125 +19246 0.30072021484375 +19247 0.478851318359375 +19248 0.1517333984375 +19249 0.3138427734375 +19250 -0.01470947265625 +19251 0.128326416015625 +19252 -0.1883544921875 +19253 -0.066497802734375 +19254 -0.372711181640625 +19255 -0.267669677734375 +19256 -0.51397705078125 +19257 -0.437957763671875 +19258 -0.57177734375 +19259 -0.54864501953125 +19260 -0.53948974609375 +19261 -0.591888427734375 +19262 -0.43511962890625 +19263 -0.575469970703125 +19264 -0.2962646484375 +19265 -0.5198974609375 +19266 -0.161102294921875 +19267 -0.44708251953125 +19268 -0.0435791015625 +19269 -0.365478515625 +19270 0.060394287109375 +19271 -0.2738037109375 +19272 0.13665771484375 +19273 -0.182647705078125 +19274 0.170135498046875 +19275 -0.10400390625 +19276 0.16552734375 +19277 -0.03863525390625 +19278 0.15728759765625 +19279 0.03009033203125 +19280 0.150787353515625 +19281 0.101287841796875 +19282 0.12200927734375 +19283 0.1563720703125 +19284 0.080108642578125 +19285 0.19696044921875 +19286 0.05126953125 +19287 0.235382080078125 +19288 0.062896728515625 +19289 0.28533935546875 +19290 0.09271240234375 +19291 0.33148193359375 +19292 0.092987060546875 +19293 0.34405517578125 +19294 0.07855224609375 +19295 0.33172607421875 +19296 0.06427001953125 +19297 0.304107666015625 +19298 0.0347900390625 +19299 0.253448486328125 +19300 -0.01171875 +19301 0.180816650390625 +19302 -0.056060791015625 +19303 0.100494384765625 +19304 -0.055511474609375 +19305 0.04132080078125 +19306 -0.010467529296875 +19307 0.0064697265625 +19308 0.02508544921875 +19309 -0.032958984375 +19310 0.025665283203125 +19311 -0.088958740234375 +19312 0.017333984375 +19313 -0.1429443359375 +19314 0.00189208984375 +19315 -0.19140625 +19316 -0.03173828125 +19317 -0.2391357421875 +19318 -0.071502685546875 +19319 -0.27777099609375 +19320 -0.13543701171875 +19321 -0.31768798828125 +19322 -0.219970703125 +19323 -0.357025146484375 +19324 -0.300506591796875 +19325 -0.381988525390625 +19326 -0.376312255859375 +19327 -0.393768310546875 +19328 -0.416107177734375 +19329 -0.375701904296875 +19330 -0.371124267578125 +19331 -0.30108642578125 +19332 -0.242279052734375 +19333 -0.1732177734375 +19334 -0.069732666015625 +19335 -0.01904296875 +19336 0.125640869140625 +19337 0.1461181640625 +19338 0.31268310546875 +19339 0.301025390625 +19340 0.45501708984375 +19341 0.42169189453125 +19342 0.554779052734375 +19343 0.5076904296875 +19344 0.61065673828125 +19345 0.55706787109375 +19346 0.610931396484375 +19347 0.562225341796875 +19348 0.531463623046875 +19349 0.50872802734375 +19350 0.3883056640625 +19351 0.4068603515625 +19352 0.23468017578125 +19353 0.289703369140625 +19354 0.095245361328125 +19355 0.1737060546875 +19356 -0.00396728515625 +19357 0.076416015625 +19358 -0.04852294921875 +19359 0.0086669921875 +19360 -0.055145263671875 +19361 -0.03717041015625 +19362 -0.0758056640625 +19363 -0.09002685546875 +19364 -0.138702392578125 +19365 -0.164642333984375 +19366 -0.209197998046875 +19367 -0.23828125 +19368 -0.289031982421875 +19369 -0.310455322265625 +19370 -0.37884521484375 +19371 -0.380462646484375 +19372 -0.456329345703125 +19373 -0.434234619140625 +19374 -0.51641845703125 +19375 -0.468597412109375 +19376 -0.519287109375 +19377 -0.46002197265625 +19378 -0.458251953125 +19379 -0.405303955078125 +19380 -0.384796142578125 +19381 -0.3365478515625 +19382 -0.323699951171875 +19383 -0.2701416015625 +19384 -0.269287109375 +19385 -0.20440673828125 +19386 -0.1951904296875 +19387 -0.12548828125 +19388 -0.100006103515625 +19389 -0.034423828125 +19390 -0.01055908203125 +19391 0.05084228515625 +19392 0.1033935546875 +19393 0.146759033203125 +19394 0.24908447265625 +19395 0.256317138671875 +19396 0.373199462890625 +19397 0.346466064453125 +19398 0.45806884765625 +19399 0.405914306640625 +19400 0.511474609375 +19401 0.4390869140625 +19402 0.565399169921875 +19403 0.46533203125 +19404 0.61138916015625 +19405 0.4801025390625 +19406 0.5897216796875 +19407 0.448455810546875 +19408 0.4906005859375 +19409 0.36572265625 +19410 0.33148193359375 +19411 0.2437744140625 +19412 0.147796630859375 +19413 0.105377197265625 +19414 -0.01873779296875 +19415 -0.0228271484375 +19416 -0.140289306640625 +19417 -0.12255859375 +19418 -0.191986083984375 +19419 -0.177490234375 +19420 -0.184295654296875 +19421 -0.19268798828125 +19422 -0.161834716796875 +19423 -0.1939697265625 +19424 -0.166595458984375 +19425 -0.20587158203125 +19426 -0.19390869140625 +19427 -0.225250244140625 +19428 -0.22442626953125 +19429 -0.240509033203125 +19430 -0.279754638671875 +19431 -0.26495361328125 +19432 -0.3389892578125 +19433 -0.28668212890625 +19434 -0.3543701171875 +19435 -0.2779541015625 +19436 -0.348175048828125 +19437 -0.25323486328125 +19438 -0.32598876953125 +19439 -0.217071533203125 +19440 -0.2581787109375 +19441 -0.15301513671875 +19442 -0.139801025390625 +19443 -0.05938720703125 +19444 0.014617919921875 +19445 0.05389404296875 +19446 0.144378662109375 +19447 0.1492919921875 +19448 0.221038818359375 +19449 0.208892822265625 +19450 0.27069091796875 +19451 0.24774169921875 +19452 0.294036865234375 +19453 0.26593017578125 +19454 0.311767578125 +19455 0.2757568359375 +19456 0.339141845703125 +19457 0.286468505859375 +19458 0.360260009765625 +19459 0.288543701171875 +19460 0.360504150390625 +19461 0.2740478515625 +19462 0.308380126953125 +19463 0.226165771484375 +19464 0.18170166015625 +19465 0.13348388671875 +19466 0.0047607421875 +19467 0.011138916015625 +19468 -0.17559814453125 +19469 -0.11297607421875 +19470 -0.3143310546875 +19471 -0.21209716796875 +19472 -0.36785888671875 +19473 -0.2603759765625 +19474 -0.36248779296875 +19475 -0.271820068359375 +19476 -0.343536376953125 +19477 -0.271453857421875 +19478 -0.3018798828125 +19479 -0.253692626953125 +19480 -0.231414794921875 +19481 -0.214874267578125 +19482 -0.117645263671875 +19483 -0.14678955078125 +19484 0.007049560546875 +19485 -0.068206787109375 +19486 0.087982177734375 +19487 -0.010711669921875 +19488 0.13946533203125 +19489 0.033050537109375 +19490 0.17425537109375 +19491 0.0694580078125 +19492 0.188201904296875 +19493 0.09515380859375 +19494 0.171234130859375 +19495 0.103424072265625 +19496 0.118438720703125 +19497 0.09051513671875 +19498 0.05706787109375 +19499 0.07098388671875 +19500 -0.010711669921875 +19501 0.04522705078125 +19502 -0.0914306640625 +19503 0.008941650390625 +19504 -0.162322998046875 +19505 -0.02532958984375 +19506 -0.194549560546875 +19507 -0.04144287109375 +19508 -0.1492919921875 +19509 -0.017364501953125 +19510 -0.02166748046875 +19511 0.049835205078125 +19512 0.124053955078125 +19513 0.12408447265625 +19514 0.211151123046875 +19515 0.162353515625 +19516 0.240447998046875 +19517 0.165802001953125 +19518 0.242218017578125 +19519 0.152374267578125 +19520 0.2257080078125 +19521 0.128173828125 +19522 0.194366455078125 +19523 0.095977783203125 +19524 0.115509033203125 +19525 0.0379638671875 +19526 0.0128173828125 +19527 -0.03167724609375 +19528 -0.053802490234375 +19529 -0.078369140625 +19530 -0.110626220703125 +19531 -0.116607666015625 +19532 -0.199493408203125 +19533 -0.169921875 +19534 -0.29437255859375 +19535 -0.223480224609375 +19536 -0.33221435546875 +19537 -0.2415771484375 +19538 -0.27972412109375 +19539 -0.205596923828125 +19540 -0.185333251953125 +19541 -0.143463134765625 +19542 -0.128204345703125 +19543 -0.100616455078125 +19544 -0.115692138671875 +19545 -0.081878662109375 +19546 -0.116455078125 +19547 -0.070098876953125 +19548 -0.105926513671875 +19549 -0.052001953125 +19550 -0.053955078125 +19551 -0.011138916015625 +19552 0.048797607421875 +19553 0.057159423828125 +19554 0.157318115234375 +19555 0.126861572265625 +19556 0.212005615234375 +19557 0.1636962890625 +19558 0.218475341796875 +19559 0.170623779296875 +19560 0.23724365234375 +19561 0.181915283203125 +19562 0.30535888671875 +19563 0.218658447265625 +19564 0.38128662109375 +19565 0.257415771484375 +19566 0.404449462890625 +19567 0.264068603515625 +19568 0.3944091796875 +19569 0.25018310546875 +19570 0.3885498046875 +19571 0.23748779296875 +19572 0.362640380859375 +19573 0.2127685546875 +19574 0.27362060546875 +19575 0.152130126953125 +19576 0.11712646484375 +19577 0.05364990234375 +19578 -0.054901123046875 +19579 -0.05267333984375 +19580 -0.19085693359375 +19581 -0.137054443359375 +19582 -0.28570556640625 +19583 -0.1962890625 +19584 -0.339263916015625 +19585 -0.230072021484375 +19586 -0.3775634765625 +19587 -0.2530517578125 +19588 -0.445709228515625 +19589 -0.29083251953125 +19590 -0.535064697265625 +19591 -0.338623046875 +19592 -0.629058837890625 +19593 -0.387237548828125 +19594 -0.697601318359375 +19595 -0.41986083984375 +19596 -0.70391845703125 +19597 -0.415985107421875 +19598 -0.6424560546875 +19599 -0.3729248046875 +19600 -0.491241455078125 +19601 -0.2786865234375 +19602 -0.265716552734375 +19603 -0.142486572265625 +19604 -0.023712158203125 +19605 0.00238037109375 +19606 0.201751708984375 +19607 0.136749267578125 +19608 0.375823974609375 +19609 0.240509033203125 +19610 0.485076904296875 +19611 0.30584716796875 +19612 0.56884765625 +19613 0.35498046875 +19614 0.634765625 +19615 0.392181396484375 +19616 0.63763427734375 +19617 0.391876220703125 +19618 0.5660400390625 +19619 0.34771728515625 +19620 0.4720458984375 +19621 0.28948974609375 +19622 0.40692138671875 +19623 0.246612548828125 +19624 0.3778076171875 +19625 0.2235107421875 +19626 0.376953125 +19627 0.216156005859375 +19628 0.371978759765625 +19629 0.20654296875 +19630 0.313140869140625 +19631 0.166778564453125 +19632 0.184417724609375 +19633 0.088104248046875 +19634 0.011199951171875 +19635 -0.0147705078125 +19636 -0.171051025390625 +19637 -0.121490478515625 +19638 -0.33740234375 +19639 -0.217742919921875 +19640 -0.47198486328125 +19641 -0.294464111328125 +19642 -0.560394287109375 +19643 -0.343505859375 +19644 -0.58056640625 +19645 -0.352447509765625 +19646 -0.54754638671875 +19647 -0.329986572265625 +19648 -0.508575439453125 +19649 -0.303192138671875 +19650 -0.459503173828125 +19651 -0.269989013671875 +19652 -0.394378662109375 +19653 -0.227325439453125 +19654 -0.35260009765625 +19655 -0.1978759765625 +19656 -0.31170654296875 +19657 -0.169189453125 +19658 -0.197418212890625 +19659 -0.099395751953125 +19660 -0.007965087890625 +19661 0.01226806640625 +19662 0.207489013671875 +19663 0.13763427734375 +19664 0.409210205078125 +19665 0.2540283203125 +19666 0.57208251953125 +19667 0.34710693359375 +19668 0.66595458984375 +19669 0.399749755859375 +19670 0.65875244140625 +19671 0.393829345703125 +19672 0.56744384765625 +19673 0.339111328125 +19674 0.431396484375 +19675 0.258148193359375 +19676 0.29443359375 +19677 0.176055908203125 +19678 0.182464599609375 +19679 0.107818603515625 +19680 0.06365966796875 +19681 0.035614013671875 +19682 -0.075958251953125 +19683 -0.0482177734375 +19684 -0.189422607421875 +19685 -0.116790771484375 +19686 -0.271942138671875 +19687 -0.1671142578125 +19688 -0.342529296875 +19689 -0.2098388671875 +19690 -0.364166259765625 +19691 -0.223846435546875 +19692 -0.327239990234375 +19693 -0.20361328125 +19694 -0.2769775390625 +19695 -0.174835205078125 +19696 -0.253692626953125 +19697 -0.160430908203125 +19698 -0.24365234375 +19699 -0.152679443359375 +19700 -0.1983642578125 +19701 -0.124176025390625 +19702 -0.116241455078125 +19703 -0.074188232421875 +19704 -0.036834716796875 +19705 -0.025360107421875 +19706 0.034881591796875 +19707 0.01922607421875 +19708 0.09124755859375 +19709 0.055023193359375 +19710 0.10888671875 +19711 0.06854248046875 +19712 0.125518798828125 +19713 0.08062744140625 +19714 0.15771484375 +19715 0.100433349609375 +19716 0.17828369140625 +19717 0.112884521484375 +19718 0.17108154296875 +19719 0.109405517578125 +19720 0.129974365234375 +19721 0.086822509765625 +19722 0.082427978515625 +19723 0.059967041015625 +19724 0.027679443359375 +19725 0.028564453125 +19726 -0.065643310546875 +19727 -0.0240478515625 +19728 -0.15936279296875 +19729 -0.077239990234375 +19730 -0.21307373046875 +19731 -0.109222412109375 +19732 -0.234649658203125 +19733 -0.124053955078125 +19734 -0.2001953125 +19735 -0.1087646484375 +19736 -0.119171142578125 +19737 -0.068267822265625 +19738 -0.024749755859375 +19739 -0.020233154296875 +19740 0.085784912109375 +19741 0.036895751953125 +19742 0.178131103515625 +19743 0.0848388671875 +19744 0.215576171875 +19745 0.10400390625 +19746 0.211456298828125 +19747 0.101531982421875 +19748 0.17523193359375 +19749 0.082489013671875 +19750 0.128753662109375 +19751 0.058563232421875 +19752 0.1019287109375 +19753 0.04571533203125 +19754 0.0743408203125 +19755 0.03289794921875 +19756 0.04327392578125 +19757 0.018524169921875 +19758 0.038177490234375 +19759 0.01824951171875 +19760 0.076263427734375 +19761 0.041168212890625 +19762 0.14105224609375 +19763 0.07830810546875 +19764 0.186431884765625 +19765 0.104827880859375 +19766 0.188812255859375 +19767 0.10797119140625 +19768 0.1390380859375 +19769 0.082733154296875 +19770 0.041778564453125 +19771 0.03155517578125 +19772 -0.079437255859375 +19773 -0.032958984375 +19774 -0.219390869140625 +19775 -0.108062744140625 +19776 -0.367828369140625 +19777 -0.188201904296875 +19778 -0.494873046875 +19779 -0.25732421875 +19780 -0.556243896484375 +19781 -0.2916259765625 +19782 -0.508697509765625 +19783 -0.26788330078125 +19784 -0.3756103515625 +19785 -0.198486328125 +19786 -0.218902587890625 +19787 -0.11651611328125 +19788 -0.063751220703125 +19789 -0.035369873046875 +19790 0.091552734375 +19791 0.04595947265625 +19792 0.23602294921875 +19793 0.1217041015625 +19794 0.342987060546875 +19795 0.177642822265625 +19796 0.39520263671875 +19797 0.204620361328125 +19798 0.389373779296875 +19799 0.200927734375 +19800 0.324249267578125 +19801 0.1658935546875 +19802 0.224090576171875 +19803 0.112518310546875 +19804 0.124267578125 +19805 0.059722900390625 +19806 0.037078857421875 +19807 0.014068603515625 +19808 -0.010101318359375 +19809 -0.00982666015625 +19810 -0.019439697265625 +19811 -0.01324462890625 +19812 -0.022796630859375 +19813 -0.013336181640625 +19814 -0.001556396484375 +19815 -0.000213623046875 +19816 0.056304931640625 +19817 0.032440185546875 +19818 0.106719970703125 +19819 0.0609130859375 +19820 0.096893310546875 +19821 0.056854248046875 +19822 0.042694091796875 +19823 0.028717041015625 +19824 -0.018035888671875 +19825 -0.003265380859375 +19826 -0.07586669921875 +19827 -0.034027099609375 +19828 -0.11944580078125 +19829 -0.057525634765625 +19830 -0.15972900390625 +19831 -0.079620361328125 +19832 -0.202606201171875 +19833 -0.103424072265625 +19834 -0.24859619140625 +19835 -0.129119873046875 +19836 -0.30517578125 +19837 -0.160614013671875 +19838 -0.36212158203125 +19839 -0.192413330078125 +19840 -0.39141845703125 +19841 -0.209442138671875 +19842 -0.35528564453125 +19843 -0.191375732421875 +19844 -0.249969482421875 +19845 -0.136138916015625 +19846 -0.092864990234375 +19847 -0.053009033203125 +19848 0.08905029296875 +19849 0.04364013671875 +19850 0.2352294921875 +19851 0.121368408203125 +19852 0.318817138671875 +19853 0.16583251953125 +19854 0.358642578125 +19855 0.187103271484375 +19856 0.347747802734375 +19857 0.181488037109375 +19858 0.28564453125 +19859 0.148681640625 +19860 0.223175048828125 +19861 0.11590576171875 +19862 0.196746826171875 +19863 0.102630615234375 +19864 0.179840087890625 +19865 0.0946044921875 +19866 0.155548095703125 +19867 0.08270263671875 +19868 0.151214599609375 +19869 0.081512451171875 +19870 0.156951904296875 +19871 0.085662841796875 +19872 0.13177490234375 +19873 0.073089599609375 +19874 0.100799560546875 +19875 0.0572509765625 +19876 0.087127685546875 +19877 0.05047607421875 +19878 0.05487060546875 +19879 0.033538818359375 +19880 -0.009002685546875 +19881 -0.000579833984375 +19882 -0.10400390625 +19883 -0.051605224609375 +19884 -0.229400634765625 +19885 -0.119110107421875 +19886 -0.35552978515625 +19887 -0.18719482421875 +19888 -0.441925048828125 +19889 -0.234130859375 +19890 -0.473846435546875 +19891 -0.25201416015625 +19892 -0.464813232421875 +19893 -0.248016357421875 +19894 -0.419097900390625 +19895 -0.224365234375 +19896 -0.334320068359375 +19897 -0.17974853515625 +19898 -0.227935791015625 +19899 -0.12347412109375 +19900 -0.12347412109375 +19901 -0.068145751953125 +19902 -0.02764892578125 +19903 -0.017303466796875 +19904 0.077667236328125 +19905 0.038787841796875 +19906 0.2132568359375 +19907 0.11126708984375 +19908 0.38885498046875 +19909 0.205352783203125 +19910 0.582794189453125 +19911 0.3094482421875 +19912 0.734039306640625 +19913 0.39080810546875 +19914 0.800140380859375 +19915 0.426666259765625 +19916 0.7783203125 +19917 0.415496826171875 +19918 0.6651611328125 +19919 0.355438232421875 +19920 0.45965576171875 +19921 0.245941162109375 +19922 0.199188232421875 +19923 0.10699462890625 +19924 -0.050689697265625 +19925 -0.026275634765625 +19926 -0.23297119140625 +19927 -0.123382568359375 +19928 -0.33013916015625 +19929 -0.174957275390625 +19930 -0.368408203125 +19931 -0.195068359375 +19932 -0.378936767578125 +19933 -0.200439453125 +19934 -0.376983642578125 +19935 -0.19927978515625 +19936 -0.37969970703125 +19937 -0.200775146484375 +19938 -0.391510009765625 +19939 -0.207275390625 +19940 -0.385345458984375 +19941 -0.20428466796875 +19942 -0.3419189453125 +19943 -0.181427001953125 +19944 -0.28289794921875 +19945 -0.150299072265625 +19946 -0.251617431640625 +19947 -0.134063720703125 +19948 -0.266143798828125 +19949 -0.142364501953125 +19950 -0.273345947265625 +19951 -0.146728515625 +19952 -0.216796875 +19953 -0.11688232421875 +19954 -0.128265380859375 +19955 -0.069793701171875 +19956 -0.068145751953125 +19957 -0.037841796875 +19958 -0.0430908203125 +19959 -0.02459716796875 +19960 -0.024444580078125 +19961 -0.014678955078125 +19962 0.020721435546875 +19963 0.009552001953125 +19964 0.124481201171875 +19965 0.065277099609375 +19966 0.25787353515625 +19967 0.136962890625 +19968 0.379119873046875 +19969 0.201629638671875 +19970 0.47991943359375 +19971 0.255035400390625 +19972 0.5281982421875 +19973 0.28131103515625 +19974 0.511138916015625 +19975 0.2738037109375 +19976 0.456207275390625 +19977 0.246246337890625 +19978 0.407470703125 +19979 0.2208251953125 +19980 0.383758544921875 +19981 0.20709228515625 +19982 0.35687255859375 +19983 0.190948486328125 +19984 0.31182861328125 +19985 0.165008544921875 +19986 0.250885009765625 +19987 0.130615234375 +19988 0.1654052734375 +19989 0.0836181640625 +19990 0.035247802734375 +19991 0.014129638671875 +19992 -0.142059326171875 +19993 -0.078857421875 +19994 -0.33563232421875 +19995 -0.1795654296875 +19996 -0.5345458984375 +19997 -0.282318115234375 +19998 -0.72186279296875 +19999 -0.378448486328125 +20000 -0.836669921875 +20001 -0.437164306640625 +20002 -0.8326416015625 +20003 -0.435089111328125 +20004 -0.7296142578125 +20005 -0.382232666015625 +20006 -0.582550048828125 +20007 -0.306427001953125 +20008 -0.440093994140625 +20009 -0.232269287109375 +20010 -0.324310302734375 +20011 -0.171051025390625 +20012 -0.20147705078125 +20013 -0.105926513671875 +20014 -0.044647216796875 +20015 -0.02349853515625 +20016 0.103973388671875 +20017 0.05474853515625 +20018 0.202392578125 +20019 0.10748291015625 +20020 0.264495849609375 +20021 0.141510009765625 +20022 0.338897705078125 +20023 0.18121337890625 +20024 0.443817138671875 +20025 0.23565673828125 +20026 0.545074462890625 +20027 0.287567138671875 +20028 0.6173095703125 +20029 0.324127197265625 +20030 0.6524658203125 +20031 0.341278076171875 +20032 0.66339111328125 +20033 0.3455810546875 +20034 0.6561279296875 +20035 0.340118408203125 +20036 0.606781005859375 +20037 0.31298828125 +20038 0.501190185546875 +20039 0.257171630859375 +20040 0.352783203125 +20041 0.1795654296875 +20042 0.176544189453125 +20043 0.087921142578125 +20044 -0.034820556640625 +20045 -0.021270751953125 +20046 -0.258209228515625 +20047 -0.136199951171875 +20048 -0.44244384765625 +20049 -0.23095703125 +20050 -0.5753173828125 +20051 -0.29931640625 +20052 -0.65203857421875 +20053 -0.33880615234375 +20054 -0.641632080078125 +20055 -0.33380126953125 +20056 -0.562164306640625 +20057 -0.293426513671875 +20058 -0.458038330078125 +20059 -0.240081787109375 +20060 -0.350555419921875 +20061 -0.184539794921875 +20062 -0.260528564453125 +20063 -0.13739013671875 +20064 -0.192108154296875 +20065 -0.100830078125 +20066 -0.141937255859375 +20067 -0.07330322265625 +20068 -0.1021728515625 +20069 -0.05096435546875 +20070 -0.062896728515625 +20071 -0.028961181640625 +20072 -0.011932373046875 +20073 -0.00128173828125 +20074 0.062835693359375 +20075 0.0380859375 +20076 0.148712158203125 +20077 0.082672119140625 +20078 0.241729736328125 +20079 0.130401611328125 +20080 0.34912109375 +20081 0.18487548828125 +20082 0.457305908203125 +20083 0.2392578125 +20084 0.54388427734375 +20085 0.282257080078125 +20086 0.5728759765625 +20087 0.295806884765625 +20088 0.506591796875 +20089 0.260986328125 +20090 0.351226806640625 +20091 0.1810302734375 +20092 0.146514892578125 +20093 0.076019287109375 +20094 -0.05523681640625 +20095 -0.02752685546875 +20096 -0.21624755859375 +20097 -0.110504150390625 +20098 -0.334930419921875 +20099 -0.1719970703125 +20100 -0.402984619140625 +20101 -0.207733154296875 +20102 -0.4412841796875 +20103 -0.2281494140625 +20104 -0.49578857421875 +20105 -0.256378173828125 +20106 -0.5601806640625 +20107 -0.2891845703125 +20108 -0.600738525390625 +20109 -0.3095703125 +20110 -0.584228515625 +20111 -0.300811767578125 +20112 -0.47930908203125 +20113 -0.24713134765625 +20114 -0.27935791015625 +20115 -0.145263671875 +20116 -0.0089111328125 +20117 -0.00762939453125 +20118 0.268798828125 +20119 0.1337890625 +20120 0.482818603515625 +20121 0.243133544921875 +20122 0.60369873046875 +20123 0.305511474609375 +20124 0.650421142578125 +20125 0.330413818359375 +20126 0.66400146484375 +20127 0.33843994140625 +20128 0.6414794921875 +20129 0.328033447265625 +20130 0.572540283203125 +20131 0.2939453125 +20132 0.498138427734375 +20133 0.256805419921875 +20134 0.439453125 +20135 0.227264404296875 +20136 0.375518798828125 +20137 0.19476318359375 +20138 0.274505615234375 +20139 0.14324951171875 +20140 0.1087646484375 +20141 0.058868408203125 +20142 -0.099395751953125 +20143 -0.04705810546875 +20144 -0.3182373046875 +20145 -0.158477783203125 +20146 -0.5489501953125 +20147 -0.27593994140625 +20148 -0.7738037109375 +20149 -0.390411376953125 +20150 -0.86383056640625 +20151 -0.475189208984375 +20152 -0.870391845703125 +20153 -0.513427734375 +20154 -0.86895751953125 +20155 -0.514007568359375 +20156 -0.861053466796875 +20157 -0.4835205078125 +20158 -0.765869140625 +20159 -0.4132080078125 +20160 -0.5301513671875 +20161 -0.297393798828125 +20162 -0.214691162109375 +20163 -0.1396484375 +20164 0.137359619140625 +20165 0.038299560546875 +20166 0.474822998046875 +20167 0.2105712890625 +20168 0.76239013671875 +20169 0.35919189453125 +20170 0.867462158203125 +20171 0.470489501953125 +20172 0.870361328125 +20173 0.544677734375 +20174 0.86480712890625 +20175 0.57586669921875 +20176 0.831817626953125 +20177 0.566680908203125 +20178 0.677581787109375 +20179 0.52935791015625 +20180 0.495880126953125 +20181 0.466766357421875 +20182 0.30767822265625 +20183 0.38824462890625 +20184 0.116180419921875 +20185 0.294921875 +20186 -0.110748291015625 +20187 0.1707763671875 +20188 -0.381805419921875 +20189 0.0123291015625 +20190 -0.6572265625 +20191 -0.158843994140625 +20192 -0.857421875 +20193 -0.312530517578125 +20194 -0.870391845703125 +20195 -0.42706298828125 +20196 -0.870391845703125 +20197 -0.498809814453125 +20198 -0.86444091796875 +20199 -0.541259765625 +20200 -0.85723876953125 +20201 -0.572357177734375 +20202 -0.790008544921875 +20203 -0.58282470703125 +20204 -0.62847900390625 +20205 -0.545257568359375 +20206 -0.3956298828125 +20207 -0.4580078125 +20208 -0.126708984375 +20209 -0.33758544921875 +20210 0.150115966796875 +20211 -0.19781494140625 +20212 0.424041748046875 +20213 -0.044586181640625 +20214 0.670623779296875 +20215 0.1085205078125 +20216 0.854522705078125 +20217 0.241943359375 +20218 0.866485595703125 +20219 0.34674072265625 +20220 0.86920166015625 +20221 0.415130615234375 +20222 0.8653564453125 +20223 0.456207275390625 +20224 0.857147216796875 +20225 0.4769287109375 +20226 0.766845703125 +20227 0.47552490234375 +20228 0.628509521484375 +20229 0.454193115234375 +20230 0.462127685546875 +20231 0.4097900390625 +20232 0.297210693359375 +20233 0.354644775390625 +20234 0.14862060546875 +20235 0.2947998046875 +20236 -0.00537109375 +20237 0.219818115234375 +20238 -0.15753173828125 +20239 0.133575439453125 +20240 -0.31304931640625 +20241 0.0347900390625 +20242 -0.48876953125 +20243 -0.082794189453125 +20244 -0.6416015625 +20245 -0.1966552734375 +20246 -0.751373291015625 +20247 -0.294769287109375 +20248 -0.84619140625 +20249 -0.387786865234375 +20250 -0.861297607421875 +20251 -0.468536376953125 +20252 -0.863250732421875 +20253 -0.521240234375 +20254 -0.856597900390625 +20255 -0.53094482421875 +20256 -0.7498779296875 +20257 -0.503448486328125 +20258 -0.624542236328125 +20259 -0.4661865234375 +20260 -0.47808837890625 +20261 -0.408966064453125 +20262 -0.253387451171875 +20263 -0.304473876953125 +20264 0.003692626953125 +20265 -0.174530029296875 +20266 0.2257080078125 +20267 -0.051727294921875 +20268 0.427154541015625 +20269 0.069488525390625 +20270 0.643218994140625 +20271 0.20404052734375 +20272 0.855926513671875 +20273 0.34710693359375 +20274 0.870361328125 +20275 0.4710693359375 +20276 0.870361328125 +20277 0.552276611328125 +20278 0.862762451171875 +20279 0.593963623046875 +20280 0.79669189453125 +20281 0.594696044921875 +20282 0.595794677734375 +20283 0.550018310546875 +20284 0.362152099609375 +20285 0.473785400390625 +20286 0.1270751953125 +20287 0.37939453125 +20288 -0.086944580078125 +20289 0.277069091796875 +20290 -0.2784423828125 +20291 0.16802978515625 +20292 -0.484832763671875 +20293 0.0361328125 +20294 -0.729583740234375 +20295 -0.1273193359375 +20296 -0.86688232421875 +20297 -0.298126220703125 +20298 -0.870391845703125 +20299 -0.446075439453125 +20300 -0.86859130859375 +20301 -0.568572998046875 +20302 -0.86279296875 +20303 -0.664398193359375 +20304 -0.817962646484375 +20305 -0.7164306640625 +20306 -0.6116943359375 +20307 -0.703155517578125 +20308 -0.3128662109375 +20309 -0.621185302734375 +20310 0.039398193359375 +20311 -0.486480712890625 +20312 0.422821044921875 +20313 -0.30859375 +20314 0.805145263671875 +20315 -0.103424072265625 +20316 0.870361328125 +20317 0.09661865234375 +20318 0.870361328125 +20319 0.264312744140625 +20320 0.860015869140625 +20321 0.393829345703125 +20322 0.727935791015625 +20323 0.481170654296875 +20324 0.48114013671875 +20325 0.5233154296875 +20326 0.2059326171875 +20327 0.531341552734375 +20328 -0.06103515625 +20329 0.515625 +20330 -0.29913330078125 +20331 0.480682373046875 +20332 -0.516204833984375 +20333 0.41949462890625 +20334 -0.7252197265625 +20335 0.324798583984375 +20336 -0.85980224609375 +20337 0.2083740234375 +20338 -0.870391845703125 +20339 0.08660888671875 +20340 -0.870391845703125 +20341 -0.0262451171875 +20342 -0.858062744140625 +20343 -0.10687255859375 +20344 -0.673004150390625 +20345 -0.15283203125 +20346 -0.42694091796875 +20347 -0.188446044921875 +20348 -0.2100830078125 +20349 -0.234222412109375 +20350 -0.0362548828125 +20351 -0.2886962890625 +20352 0.10943603515625 +20353 -0.33770751953125 +20354 0.23516845703125 +20355 -0.371490478515625 +20356 0.373687744140625 +20357 -0.3702392578125 +20358 0.517791748046875 +20359 -0.33465576171875 +20360 0.602783203125 +20361 -0.29443359375 +20362 0.635711669921875 +20363 -0.247222900390625 +20364 0.655181884765625 +20365 -0.17742919921875 +20366 0.65948486328125 +20367 -0.0899658203125 +20368 0.651275634765625 +20369 0.010986328125 +20370 0.61846923828125 +20371 0.113494873046875 +20372 0.53753662109375 +20373 0.199615478515625 +20374 0.404144287109375 +20375 0.260345458984375 +20376 0.22186279296875 +20377 0.290618896484375 +20378 0.003997802734375 +20379 0.290618896484375 +20380 -0.22100830078125 +20381 0.2685546875 +20382 -0.42449951171875 +20383 0.233917236328125 +20384 -0.579833984375 +20385 0.196563720703125 +20386 -0.641876220703125 +20387 0.17657470703125 +20388 -0.6177978515625 +20389 0.17083740234375 +20390 -0.575531005859375 +20391 0.148956298828125 +20392 -0.526336669921875 +20393 0.108612060546875 +20394 -0.42645263671875 +20395 0.07452392578125 +20396 -0.2581787109375 +20397 0.05999755859375 +20398 -0.068695068359375 +20399 0.048248291015625 +20400 0.09222412109375 +20401 0.02154541015625 +20402 0.232147216796875 +20403 -0.010894775390625 +20404 0.3509521484375 +20405 -0.043853759765625 +20406 0.410064697265625 +20407 -0.090972900390625 +20408 0.372955322265625 +20409 -0.165802001953125 +20410 0.2554931640625 +20411 -0.25823974609375 +20412 0.10711669921875 +20413 -0.343536376953125 +20414 -0.052886962890625 +20415 -0.412384033203125 +20416 -0.186279296875 +20417 -0.44769287109375 +20418 -0.23291015625 +20419 -0.423248291015625 +20420 -0.209442138671875 +20421 -0.349945068359375 +20422 -0.174163818359375 +20423 -0.2591552734375 +20424 -0.126739501953125 +20425 -0.15509033203125 +20426 -0.048126220703125 +20427 -0.033447265625 +20428 0.0426025390625 +20429 0.092071533203125 +20430 0.10748291015625 +20431 0.1990966796875 +20432 0.1409912109375 +20433 0.281036376953125 +20434 0.19708251953125 +20435 0.360015869140625 +20436 0.273651123046875 +20437 0.4326171875 +20438 0.31768798828125 +20439 0.4722900390625 +20440 0.341094970703125 +20441 0.484100341796875 +20442 0.368011474609375 +20443 0.47991943359375 +20444 0.37249755859375 +20445 0.448944091796875 +20446 0.30072021484375 +20447 0.3680419921875 +20448 0.1517333984375 +20449 0.239715576171875 +20450 -0.01470947265625 +20451 0.09564208984375 +20452 -0.1883544921875 +20453 -0.0555419921875 +20454 -0.372711181640625 +20455 -0.211578369140625 +20456 -0.51397705078125 +20457 -0.343353271484375 +20458 -0.57177734375 +20459 -0.4283447265625 +20460 -0.53948974609375 +20461 -0.460479736328125 +20462 -0.43511962890625 +20463 -0.446014404296875 +20464 -0.2962646484375 +20465 -0.401123046875 +20466 -0.161102294921875 +20467 -0.3431396484375 +20468 -0.0435791015625 +20469 -0.27874755859375 +20470 0.060394287109375 +20471 -0.2069091796875 +20472 0.13665771484375 +20473 -0.135955810546875 +20474 0.170135498046875 +20475 -0.075225830078125 +20476 0.16552734375 +20477 -0.025238037109375 +20478 0.15728759765625 +20479 0.02716064453125 +20480 0.150787353515625 +20481 0.081512451171875 +20482 0.12200927734375 +20483 0.12335205078125 +20484 0.080108642578125 +20485 0.15374755859375 +20486 0.05126953125 +20487 0.182098388671875 +20488 0.062896728515625 +20489 0.218841552734375 +20490 0.09271240234375 +20491 0.2525634765625 +20492 0.092987060546875 +20493 0.26104736328125 +20494 0.07855224609375 +20495 0.2508544921875 +20496 0.06427001953125 +20497 0.229217529296875 +20498 0.0347900390625 +20499 0.19036865234375 +20500 -0.01171875 +20501 0.1351318359375 +20502 -0.056060791015625 +20503 0.074249267578125 +20504 -0.055511474609375 +20505 0.02935791015625 +20506 -0.010467529296875 +20507 0.00286865234375 +20508 0.02508544921875 +20509 -0.02691650390625 +20510 0.025665283203125 +20511 -0.0689697265625 +20512 0.017333984375 +20513 -0.109375 +20514 0.00189208984375 +20515 -0.1455078125 +20516 -0.03173828125 +20517 -0.18096923828125 +20518 -0.071502685546875 +20519 -0.20953369140625 +20520 -0.13543701171875 +20521 -0.239013671875 +20522 -0.219970703125 +20523 -0.268035888671875 +20524 -0.300506591796875 +20525 -0.28631591796875 +20526 -0.376312255859375 +20527 -0.294708251953125 +20528 -0.416107177734375 +20529 -0.28076171875 +20530 -0.371124267578125 +20531 -0.224456787109375 +20532 -0.242279052734375 +20533 -0.128326416015625 +20534 -0.069732666015625 +20535 -0.0125732421875 +20536 0.125640869140625 +20537 0.111297607421875 +20538 0.31268310546875 +20539 0.2274169921875 +20540 0.45501708984375 +20541 0.317779541015625 +20542 0.554779052734375 +20543 0.382049560546875 +20544 0.61065673828125 +20545 0.418792724609375 +20546 0.610931396484375 +20547 0.422332763671875 +20548 0.531463623046875 +20549 0.381866455078125 +20550 0.3883056640625 +20551 0.30511474609375 +20552 0.23468017578125 +20553 0.2169189453125 +20554 0.095245361328125 +20555 0.129608154296875 +20556 -0.00396728515625 +20557 0.056365966796875 +20558 -0.04852294921875 +20559 0.005340576171875 +20560 -0.055145263671875 +20561 -0.029205322265625 +20562 -0.0758056640625 +20563 -0.06890869140625 +20564 -0.138702392578125 +20565 -0.124847412109375 +20566 -0.209197998046875 +20567 -0.17999267578125 +20568 -0.289031982421875 +20569 -0.23394775390625 +20570 -0.37884521484375 +20571 -0.286224365234375 +20572 -0.456329345703125 +20573 -0.326263427734375 +20574 -0.51641845703125 +20575 -0.35174560546875 +20576 -0.519287109375 +20577 -0.345001220703125 +20578 -0.458251953125 +20579 -0.303619384765625 +20580 -0.384796142578125 +20581 -0.251708984375 +20582 -0.323699951171875 +20583 -0.20159912109375 +20584 -0.269287109375 +20585 -0.152069091796875 +20586 -0.1951904296875 +20587 -0.09271240234375 +20588 -0.100006103515625 +20589 -0.024322509765625 +20590 -0.01055908203125 +20591 0.03961181640625 +20592 0.1033935546875 +20593 0.1114501953125 +20594 0.24908447265625 +20595 0.19342041015625 +20596 0.373199462890625 +20597 0.260772705078125 +20598 0.45806884765625 +20599 0.305084228515625 +20600 0.511474609375 +20601 0.32965087890625 +20602 0.565399169921875 +20603 0.3489990234375 +20604 0.61138916015625 +20605 0.359771728515625 +20606 0.5897216796875 +20607 0.33575439453125 +20608 0.4906005859375 +20609 0.273468017578125 +20610 0.33148193359375 +20611 0.18182373046875 +20612 0.147796630859375 +20613 0.077911376953125 +20614 -0.01873779296875 +20615 -0.018310546875 +20616 -0.140289306640625 +20617 -0.093109130859375 +20618 -0.191986083984375 +20619 -0.134246826171875 +20620 -0.184295654296875 +20621 -0.1455078125 +20622 -0.161834716796875 +20623 -0.146270751953125 +20624 -0.166595458984375 +20625 -0.154937744140625 +20626 -0.19390869140625 +20627 -0.169219970703125 +20628 -0.22442626953125 +20629 -0.180389404296875 +20630 -0.279754638671875 +20631 -0.19842529296875 +20632 -0.3389892578125 +20633 -0.214447021484375 +20634 -0.3543701171875 +20635 -0.207672119140625 +20636 -0.348175048828125 +20637 -0.188934326171875 +20638 -0.32598876953125 +20639 -0.16168212890625 +20640 -0.2581787109375 +20641 -0.11358642578125 +20642 -0.139801025390625 +20643 -0.043365478515625 +20644 0.014617919921875 +20645 0.041534423828125 +20646 0.144378662109375 +20647 0.11297607421875 +20648 0.221038818359375 +20649 0.15753173828125 +20650 0.27069091796875 +20651 0.18646240234375 +20652 0.294036865234375 +20653 0.199859619140625 +20654 0.311767578125 +20655 0.207000732421875 +20656 0.339141845703125 +20657 0.21484375 +20658 0.360260009765625 +20659 0.2164306640625 +20660 0.360504150390625 +20661 0.205780029296875 +20662 0.308380126953125 +20663 0.169708251953125 +20664 0.18170166015625 +20665 0.099273681640625 +20666 0.0047607421875 +20667 0.006072998046875 +20668 -0.17559814453125 +20669 -0.08837890625 +20670 -0.3143310546875 +20671 -0.1634521484375 +20672 -0.36785888671875 +20673 -0.199249267578125 +20674 -0.36248779296875 +20675 -0.206695556640625 +20676 -0.343536376953125 +20677 -0.20526123046875 +20678 -0.3018798828125 +20679 -0.190704345703125 +20680 -0.231414794921875 +20681 -0.160186767578125 +20682 -0.117645263671875 +20683 -0.107391357421875 +20684 0.007049560546875 +20685 -0.04681396484375 +20686 0.087982177734375 +20687 -0.002899169921875 +20688 0.13946533203125 +20689 0.03009033203125 +20690 0.17425537109375 +20691 0.057159423828125 +20692 0.188201904296875 +20693 0.075775146484375 +20694 0.171234130859375 +20695 0.080810546875 +20696 0.118438720703125 +20697 0.069427490234375 +20698 0.05706787109375 +20699 0.053009033203125 +20700 -0.010711669921875 +20701 0.031951904296875 +20702 -0.0914306640625 +20703 0.0029296875 +20704 -0.162322998046875 +20705 -0.0242919921875 +20706 -0.194549560546875 +20707 -0.03717041015625 +20708 -0.1492919921875 +20709 -0.018646240234375 +20710 -0.02166748046875 +20711 0.033599853515625 +20712 0.124053955078125 +20713 0.091552734375 +20714 0.211151123046875 +20715 0.121856689453125 +20716 0.240447998046875 +20717 0.125396728515625 +20718 0.242218017578125 +20719 0.115997314453125 +20720 0.2257080078125 +20721 0.098358154296875 +20722 0.194366455078125 +20723 0.074554443359375 +20724 0.115509033203125 +20725 0.030731201171875 +20726 0.0128173828125 +20727 -0.022186279296875 +20728 -0.053802490234375 +20729 -0.057464599609375 +20730 -0.110626220703125 +20731 -0.086395263671875 +20732 -0.199493408203125 +20733 -0.12725830078125 +20734 -0.29437255859375 +20735 -0.168548583984375 +20736 -0.33221435546875 +20737 -0.1829833984375 +20738 -0.27972412109375 +20739 -0.156829833984375 +20740 -0.185333251953125 +20741 -0.11065673828125 +20742 -0.128204345703125 +20743 -0.077545166015625 +20744 -0.115692138671875 +20745 -0.061309814453125 +20746 -0.116455078125 +20747 -0.049957275390625 +20748 -0.105926513671875 +20749 -0.03424072265625 +20750 -0.053955078125 +20751 -0.002532958984375 +20752 0.048797607421875 +20753 0.048370361328125 +20754 0.157318115234375 +20755 0.09967041015625 +20756 0.212005615234375 +20757 0.126708984375 +20758 0.218475341796875 +20759 0.131622314453125 +20760 0.23724365234375 +20761 0.139068603515625 +20762 0.30535888671875 +20763 0.164276123046875 +20764 0.38128662109375 +20765 0.190521240234375 +20766 0.404449462890625 +20767 0.19342041015625 +20768 0.3944091796875 +20769 0.181365966796875 +20770 0.3885498046875 +20771 0.17010498046875 +20772 0.362640380859375 +20773 0.1502685546875 +20774 0.27362060546875 +20775 0.104827880859375 +20776 0.11712646484375 +20777 0.032501220703125 +20778 -0.054901123046875 +20779 -0.0450439453125 +20780 -0.19085693359375 +20781 -0.10638427734375 +20782 -0.28570556640625 +20783 -0.149200439453125 +20784 -0.339263916015625 +20785 -0.173248291015625 +20786 -0.3775634765625 +20787 -0.1890869140625 +20788 -0.445709228515625 +20789 -0.215179443359375 +20790 -0.535064697265625 +20791 -0.248138427734375 +20792 -0.629058837890625 +20793 -0.28143310546875 +20794 -0.697601318359375 +20795 -0.3031005859375 +20796 -0.70391845703125 +20797 -0.29852294921875 +20798 -0.6424560546875 +20799 -0.265869140625 +20800 -0.491241455078125 +20801 -0.19659423828125 +20802 -0.265716552734375 +20803 -0.097412109375 +20804 -0.023712158203125 +20805 0.007659912109375 +20806 0.201751708984375 +20807 0.1048583984375 +20808 0.375823974609375 +20809 0.1796875 +20810 0.485076904296875 +20811 0.226531982421875 +20812 0.56884765625 +20813 0.2613525390625 +20814 0.634765625 +20815 0.287261962890625 +20816 0.63763427734375 +20817 0.28594970703125 +20818 0.5660400390625 +20819 0.2529296875 +20820 0.4720458984375 +20821 0.209686279296875 +20822 0.40692138671875 +20823 0.177398681640625 +20824 0.3778076171875 +20825 0.159332275390625 +20826 0.376953125 +20827 0.152679443359375 +20828 0.371978759765625 +20829 0.14459228515625 +20830 0.313140869140625 +20831 0.115081787109375 +20832 0.184417724609375 +20833 0.057891845703125 +20834 0.011199951171875 +20835 -0.016357421875 +20836 -0.171051025390625 +20837 -0.093017578125 +20838 -0.33740234375 +20839 -0.161834716796875 +20840 -0.47198486328125 +20841 -0.21630859375 +20842 -0.560394287109375 +20843 -0.250640869140625 +20844 -0.58056640625 +20845 -0.2559814453125 +20846 -0.54754638671875 +20847 -0.2386474609375 +20848 -0.508575439453125 +20849 -0.218170166015625 +20850 -0.459503173828125 +20851 -0.193115234375 +20852 -0.394378662109375 +20853 -0.161346435546875 +20854 -0.35260009765625 +20855 -0.139190673828125 +20856 -0.31170654296875 +20857 -0.117767333984375 +20858 -0.197418212890625 +20859 -0.0670166015625 +20860 -0.007965087890625 +20861 0.0135498046875 +20862 0.207489013671875 +20863 0.10369873046875 +20864 0.409210205078125 +20865 0.187103271484375 +20866 0.57208251953125 +20867 0.253509521484375 +20868 0.66595458984375 +20869 0.2906494140625 +20870 0.65875244140625 +20871 0.285552978515625 +20872 0.56744384765625 +20873 0.24530029296875 +20874 0.431396484375 +20875 0.186126708984375 +20876 0.29443359375 +20877 0.126129150390625 +20878 0.182464599609375 +20879 0.07611083984375 +20880 0.06365966796875 +20881 0.023345947265625 +20882 -0.075958251953125 +20883 -0.037628173828125 +20884 -0.189422607421875 +20885 -0.087432861328125 +20886 -0.271942138671875 +20887 -0.123931884765625 +20888 -0.342529296875 +20889 -0.15472412109375 +20890 -0.364166259765625 +20891 -0.1646728515625 +20892 -0.327239990234375 +20893 -0.149810791015625 +20894 -0.2769775390625 +20895 -0.12860107421875 +20896 -0.253692626953125 +20897 -0.1175537109375 +20898 -0.24365234375 +20899 -0.111175537109375 +20900 -0.1983642578125 +20901 -0.089813232421875 +20902 -0.116241455078125 +20903 -0.053009033203125 +20904 -0.036834716796875 +20905 -0.017059326171875 +20906 0.034881591796875 +20907 0.0157470703125 +20908 0.09124755859375 +20909 0.042083740234375 +20910 0.10888671875 +20911 0.05224609375 +20912 0.125518798828125 +20913 0.061492919921875 +20914 0.15771484375 +20915 0.07647705078125 +20916 0.17828369140625 +20917 0.08599853515625 +20918 0.17108154296875 +20919 0.08343505859375 +20920 0.129974365234375 +20921 0.0662841796875 +20922 0.082427978515625 +20923 0.0457763671875 +20924 0.027679443359375 +20925 0.021697998046875 +20926 -0.065643310546875 +20927 -0.018585205078125 +20928 -0.15936279296875 +20929 -0.059356689453125 +20930 -0.21307373046875 +20931 -0.084014892578125 +20932 -0.234649658203125 +20933 -0.09564208984375 +20934 -0.2001953125 +20935 -0.084320068359375 +20936 -0.119171142578125 +20937 -0.05377197265625 +20938 -0.024749755859375 +20939 -0.01739501953125 +20940 0.085784912109375 +20941 0.0260009765625 +20942 0.178131103515625 +20943 0.0625 +20944 0.215576171875 +20945 0.077178955078125 +20946 0.211456298828125 +20947 0.07550048828125 +20948 0.17523193359375 +20949 0.06134033203125 +20950 0.128753662109375 +20951 0.04351806640625 +20952 0.1019287109375 +20953 0.0341796875 +20954 0.0743408203125 +20955 0.02490234375 +20956 0.04327392578125 +20957 0.014434814453125 +20958 0.038177490234375 +20959 0.014678955078125 +20960 0.076263427734375 +20961 0.032501220703125 +20962 0.14105224609375 +20963 0.061065673828125 +20964 0.186431884765625 +20965 0.081451416015625 +20966 0.188812255859375 +20967 0.08392333984375 +20968 0.1390380859375 +20969 0.064697265625 +20970 0.041778564453125 +20971 0.025634765625 +20972 -0.079437255859375 +20973 -0.023681640625 +20974 -0.219390869140625 +20975 -0.08111572265625 +20976 -0.367828369140625 +20977 -0.142425537109375 +20978 -0.494873046875 +20979 -0.19537353515625 +20980 -0.556243896484375 +20981 -0.221832275390625 +20982 -0.508697509765625 +20983 -0.204071044921875 +20984 -0.3756103515625 +20985 -0.151519775390625 +20986 -0.218902587890625 +20987 -0.08935546875 +20988 -0.063751220703125 +20989 -0.027740478515625 +20990 0.091552734375 +20991 0.0340576171875 +20992 0.23602294921875 +20993 0.091583251953125 +20994 0.342987060546875 +20995 0.134033203125 +20996 0.39520263671875 +20997 0.15472412109375 +20998 0.389373779296875 +20999 0.152679443359375 +21000 0.324249267578125 +21001 0.127655029296875 +21002 0.224090576171875 +21003 0.0889892578125 +21004 0.124267578125 +21005 0.0501708984375 +21006 0.037078857421875 +21007 0.0159912109375 +21008 -0.010101318359375 +21009 -0.00311279296875 +21010 -0.019439697265625 +21011 -0.007843017578125 +21012 -0.022796630859375 +21013 -0.0101318359375 +21014 -0.001556396484375 +21015 -0.0029296875 +21016 0.056304931640625 +21017 0.018280029296875 +21018 0.106719970703125 +21019 0.03692626953125 +21020 0.096893310546875 +21021 0.03314208984375 +21022 0.042694091796875 +21023 0.012908935546875 +21024 -0.018035888671875 +21025 -0.009552001953125 +21026 -0.07586669921875 +21027 -0.030731201171875 +21028 -0.11944580078125 +21029 -0.046417236328125 +21030 -0.15972900390625 +21031 -0.060791015625 +21032 -0.202606201171875 +21033 -0.076080322265625 +21034 -0.24859619140625 +21035 -0.092529296875 +21036 -0.30517578125 +21037 -0.113006591796875 +21038 -0.36212158203125 +21039 -0.133697509765625 +21040 -0.39141845703125 +21041 -0.144134521484375 +21042 -0.35528564453125 +21043 -0.130157470703125 +21044 -0.249969482421875 +21045 -0.090362548828125 +21046 -0.092864990234375 +21047 -0.03131103515625 +21048 0.08905029296875 +21049 0.036865234375 +21050 0.2352294921875 +21051 0.0914306640625 +21052 0.318817138671875 +21053 0.122314453125 +21054 0.358642578125 +21055 0.136627197265625 +21056 0.347747802734375 +21057 0.13177490234375 +21058 0.28564453125 +21059 0.107635498046875 +21060 0.223175048828125 +21061 0.0833740234375 +21062 0.196746826171875 +21063 0.072723388671875 +21064 0.179840087890625 +21065 0.06573486328125 +21066 0.155548095703125 +21067 0.056121826171875 +21068 0.151214599609375 +21069 0.054168701171875 +21070 0.156951904296875 +21071 0.056182861328125 +21072 0.13177490234375 +21073 0.046722412109375 +21074 0.100799560546875 +21075 0.03521728515625 +21076 0.087127685546875 +21077 0.03033447265625 +21078 0.05487060546875 +21079 0.01861572265625 +21080 -0.009002685546875 +21081 -0.0048828125 +21082 -0.10400390625 +21083 -0.03997802734375 +21084 -0.229400634765625 +21085 -0.086456298828125 +21086 -0.35552978515625 +21087 -0.133209228515625 +21088 -0.441925048828125 +21089 -0.1650390625 +21090 -0.473846435546875 +21091 -0.176483154296875 +21092 -0.464813232421875 +21093 -0.172607421875 +21094 -0.419097900390625 +21095 -0.155029296875 +21096 -0.334320068359375 +21097 -0.1229248046875 +21098 -0.227935791015625 +21099 -0.082855224609375 +21100 -0.12347412109375 +21101 -0.043670654296875 +21102 -0.02764892578125 +21103 -0.007843017578125 +21104 0.077667236328125 +21105 0.031463623046875 +21106 0.2132568359375 +21107 0.082061767578125 +21108 0.38885498046875 +21109 0.1475830078125 +21110 0.582794189453125 +21111 0.219940185546875 +21112 0.734039306640625 +21113 0.276214599609375 +21114 0.800140380859375 +21115 0.30047607421875 +21116 0.7783203125 +21117 0.291717529296875 +21118 0.6651611328125 +21119 0.248687744140625 +21120 0.45965576171875 +21121 0.1710205078125 +21122 0.199188232421875 +21123 0.072784423828125 +21124 -0.050689697265625 +21125 -0.02130126953125 +21126 -0.23297119140625 +21127 -0.08984375 +21128 -0.33013916015625 +21129 -0.126251220703125 +21130 -0.368408203125 +21131 -0.140380859375 +21132 -0.378936767578125 +21133 -0.143951416015625 +21134 -0.376983642578125 +21135 -0.14276123046875 +21136 -0.37969970703125 +21137 -0.143280029296875 +21138 -0.391510009765625 +21139 -0.147186279296875 +21140 -0.385345458984375 +21141 -0.14434814453125 +21142 -0.3419189453125 +21143 -0.127532958984375 +21144 -0.28289794921875 +21145 -0.104888916015625 +21146 -0.251617431640625 +21147 -0.092742919921875 +21148 -0.266143798828125 +21149 -0.097900390625 +21150 -0.273345947265625 +21151 -0.100433349609375 +21152 -0.216796875 +21153 -0.0791015625 +21154 -0.128265380859375 +21155 -0.045867919921875 +21156 -0.068145751953125 +21157 -0.023406982421875 +21158 -0.0430908203125 +21159 -0.014190673828125 +21160 -0.024444580078125 +21161 -0.0074462890625 +21162 0.020721435546875 +21163 0.009185791015625 +21164 0.124481201171875 +21165 0.047760009765625 +21166 0.25787353515625 +21167 0.097412109375 +21168 0.379119873046875 +21169 0.1424560546875 +21170 0.47991943359375 +21171 0.179840087890625 +21172 0.5281982421875 +21173 0.197509765625 +21174 0.511138916015625 +21175 0.190673828125 +21176 0.456207275390625 +21177 0.169708251953125 +21178 0.407470703125 +21179 0.15118408203125 +21180 0.383758544921875 +21181 0.142181396484375 +21182 0.35687255859375 +21183 0.132110595703125 +21184 0.31182861328125 +21185 0.11529541015625 +21186 0.250885009765625 +21187 0.09259033203125 +21188 0.1654052734375 +21189 0.06072998046875 +21190 0.035247802734375 +21191 0.01214599609375 +21192 -0.142059326171875 +21193 -0.054107666015625 +21194 -0.33563232421875 +21195 -0.126434326171875 +21196 -0.5345458984375 +21197 -0.20074462890625 +21198 -0.72186279296875 +21199 -0.27069091796875 +21200 -0.836669921875 +21201 -0.313385009765625 +21202 -0.8326416015625 +21203 -0.31146240234375 +21204 -0.7296142578125 +21205 -0.27239990234375 +21206 -0.582550048828125 +21207 -0.216888427734375 +21208 -0.440093994140625 +21209 -0.163238525390625 +21210 -0.324310302734375 +21211 -0.119720458984375 +21212 -0.20147705078125 +21213 -0.07366943359375 +21214 -0.044647216796875 +21215 -0.014892578125 +21216 0.103973388671875 +21217 0.040679931640625 +21218 0.202392578125 +21219 0.077301025390625 +21220 0.264495849609375 +21221 0.100189208984375 +21222 0.338897705078125 +21223 0.127655029296875 +21224 0.443817138671875 +21225 0.166595458984375 +21226 0.545074462890625 +21227 0.204193115234375 +21228 0.6173095703125 +21229 0.230926513671875 +21230 0.6524658203125 +21231 0.243804931640625 +21232 0.66339111328125 +21233 0.247650146484375 +21234 0.6561279296875 +21235 0.244781494140625 +21236 0.606781005859375 +21237 0.2261962890625 +21238 0.501190185546875 +21239 0.186553955078125 +21240 0.352783203125 +21241 0.130889892578125 +21242 0.176544189453125 +21243 0.064849853515625 +21244 -0.034820556640625 +21245 -0.014312744140625 +21246 -0.258209228515625 +21247 -0.097900390625 +21248 -0.44244384765625 +21249 -0.1668701171875 +21250 -0.5753173828125 +21251 -0.216522216796875 +21252 -0.65203857421875 +21253 -0.2452392578125 +21254 -0.641632080078125 +21255 -0.242431640625 +21256 -0.562164306640625 +21257 -0.2144775390625 +21258 -0.458038330078125 +21259 -0.176788330078125 +21260 -0.350555419921875 +21261 -0.13690185546875 +21262 -0.260528564453125 +21263 -0.102203369140625 +21264 -0.192108154296875 +21265 -0.07440185546875 +21266 -0.141937255859375 +21267 -0.0526123046875 +21268 -0.1021728515625 +21269 -0.03436279296875 +21270 -0.062896728515625 +21271 -0.0164794921875 +21272 -0.011932373046875 +21273 0.004974365234375 +21274 0.062835693359375 +21275 0.033966064453125 +21276 0.148712158203125 +21277 0.06597900390625 +21278 0.241729736328125 +21279 0.099517822265625 +21280 0.34912109375 +21281 0.137054443359375 +21282 0.457305908203125 +21283 0.17388916015625 +21284 0.54388427734375 +21285 0.202392578125 +21286 0.5728759765625 +21287 0.210296630859375 +21288 0.506591796875 +21289 0.18475341796875 +21290 0.351226806640625 +21291 0.12811279296875 +21292 0.146514892578125 +21293 0.05419921875 +21294 -0.05523681640625 +21295 -0.018768310546875 +21296 -0.21624755859375 +21297 -0.077606201171875 +21298 -0.334930419921875 +21299 -0.121551513671875 +21300 -0.402984619140625 +21301 -0.147613525390625 +21302 -0.4412841796875 +21303 -0.162841796875 +21304 -0.49578857421875 +21305 -0.182952880859375 +21306 -0.5601806640625 +21307 -0.205718994140625 +21308 -0.600738525390625 +21309 -0.21954345703125 +21310 -0.584228515625 +21311 -0.2130126953125 +21312 -0.47930908203125 +21313 -0.1754150390625 +21314 -0.27935791015625 +21315 -0.104583740234375 +21316 -0.0089111328125 +21317 -0.00909423828125 +21318 0.268798828125 +21319 0.089141845703125 +21320 0.482818603515625 +21321 0.16558837890625 +21322 0.60369873046875 +21323 0.209930419921875 +21324 0.650421142578125 +21325 0.22857666015625 +21326 0.66400146484375 +21327 0.2354736328125 +21328 0.6414794921875 +21329 0.229522705078125 +21330 0.572540283203125 +21331 0.20709228515625 +21332 0.498138427734375 +21333 0.18218994140625 +21334 0.439453125 +21335 0.162078857421875 +21336 0.375518798828125 +21337 0.13958740234375 +21338 0.274505615234375 +21339 0.103790283203125 +21340 0.1087646484375 +21341 0.04522705078125 +21342 -0.099395751953125 +21343 -0.028289794921875 +21344 -0.3182373046875 +21345 -0.105712890625 +21346 -0.5489501953125 +21347 -0.187347412109375 +21348 -0.7738037109375 +21349 -0.266937255859375 +21350 -0.86383056640625 +21351 -0.326171875 +21352 -0.870391845703125 +21353 -0.353485107421875 +21354 -0.86895751953125 +21355 -0.354888916015625 +21356 -0.861053466796875 +21357 -0.3348388671875 +21358 -0.765869140625 +21359 -0.287322998046875 +21360 -0.5301513671875 +21361 -0.20843505859375 +21362 -0.214691162109375 +21363 -0.10064697265625 +21364 0.137359619140625 +21365 0.021209716796875 +21366 0.474822998046875 +21367 0.139404296875 +21368 0.76239013671875 +21369 0.241668701171875 +21370 0.867462158203125 +21371 0.318634033203125 +21372 0.870361328125 +21373 0.370361328125 +21374 0.86480712890625 +21375 0.39276123046875 +21376 0.831817626953125 +21377 0.387603759765625 +21378 0.677581787109375 +21379 0.3631591796875 +21380 0.495880126953125 +21381 0.32135009765625 +21382 0.30767822265625 +21383 0.26849365234375 +21384 0.116180419921875 +21385 0.205322265625 +21386 -0.110748291015625 +21387 0.120880126953125 +21388 -0.381805419921875 +21389 0.01275634765625 +21390 -0.6572265625 +21391 -0.104248046875 +21392 -0.857421875 +21393 -0.209503173828125 +21394 -0.870391845703125 +21395 -0.2882080078125 +21396 -0.870391845703125 +21397 -0.337860107421875 +21398 -0.86444091796875 +21399 -0.367645263671875 +21400 -0.85723876953125 +21401 -0.389739990234375 +21402 -0.790008544921875 +21403 -0.39776611328125 +21404 -0.62847900390625 +21405 -0.37298583984375 +21406 -0.3956298828125 +21407 -0.314239501953125 +21408 -0.126708984375 +21409 -0.232757568359375 +21410 0.150115966796875 +21411 -0.137908935546875 +21412 0.424041748046875 +21413 -0.033660888671875 +21414 0.670623779296875 +21415 0.0706787109375 +21416 0.854522705078125 +21417 0.16180419921875 +21418 0.866485595703125 +21419 0.23358154296875 +21420 0.86920166015625 +21421 0.280670166015625 +21422 0.8653564453125 +21423 0.30926513671875 +21424 0.857147216796875 +21425 0.323883056640625 +21426 0.766845703125 +21427 0.323455810546875 +21428 0.628509521484375 +21429 0.3096923828125 +21430 0.462127685546875 +21431 0.28021240234375 +21432 0.297210693359375 +21433 0.24383544921875 +21434 0.14862060546875 +21435 0.204742431640625 +21436 -0.00537109375 +21437 0.155059814453125 +21438 -0.15753173828125 +21439 0.09735107421875 +21440 -0.31304931640625 +21441 0.0303955078125 +21442 -0.48876953125 +21443 -0.050628662109375 +21444 -0.6416015625 +21445 -0.129547119140625 +21446 -0.751373291015625 +21447 -0.197845458984375 +21448 -0.84619140625 +21449 -0.263427734375 +21450 -0.861297607421875 +21451 -0.3211669921875 +21452 -0.863250732421875 +21453 -0.359588623046875 +21454 -0.856597900390625 +21455 -0.367767333984375 +21456 -0.7498779296875 +21457 -0.349822998046875 +21458 -0.624542236328125 +21459 -0.325592041015625 +21460 -0.47808837890625 +21461 -0.287506103515625 +21462 -0.253387451171875 +21463 -0.215423583984375 +21464 0.003692626953125 +21465 -0.125030517578125 +21466 0.2257080078125 +21467 -0.03985595703125 +21468 0.427154541015625 +21469 0.044403076171875 +21470 0.643218994140625 +21471 0.13885498046875 +21472 0.855926513671875 +21473 0.240142822265625 +21474 0.870361328125 +21475 0.3282470703125 +21476 0.870361328125 +21477 0.386077880859375 +21478 0.862762451171875 +21479 0.416046142578125 +21480 0.79669189453125 +21481 0.4171142578125 +21482 0.595794677734375 +21483 0.385955810546875 +21484 0.362152099609375 +21485 0.33258056640625 +21486 0.1270751953125 +21487 0.2666015625 +21488 -0.086944580078125 +21489 0.195281982421875 +21490 -0.2784423828125 +21491 0.119354248046875 +21492 -0.484832763671875 +21493 0.026885986328125 +21494 -0.729583740234375 +21495 -0.08868408203125 +21496 -0.86688232421875 +21497 -0.209930419921875 +21498 -0.870391845703125 +21499 -0.315032958984375 +21500 -0.86859130859375 +21501 -0.402191162109375 +21502 -0.86279296875 +21503 -0.47064208984375 +21504 -0.817962646484375 +21505 -0.50787353515625 +21506 -0.6116943359375 +21507 -0.49853515625 +21508 -0.3128662109375 +21509 -0.4404296875 +21510 0.039398193359375 +21511 -0.344879150390625 +21512 0.422821044921875 +21513 -0.21905517578125 +21514 0.805145263671875 +21515 -0.07427978515625 +21516 0.870361328125 +21517 0.06719970703125 +21518 0.870361328125 +21519 0.186767578125 +21520 0.860015869140625 +21521 0.280029296875 +21522 0.727935791015625 +21523 0.343902587890625 +21524 0.48114013671875 +21525 0.3760986328125 +21526 0.2059326171875 +21527 0.3837890625 +21528 -0.06103515625 +21529 0.373748779296875 +21530 -0.29913330078125 +21531 0.349029541015625 +21532 -0.516204833984375 +21533 0.305206298828125 +21534 -0.7252197265625 +21535 0.23773193359375 +21536 -0.85980224609375 +21537 0.15472412109375 +21538 -0.870391845703125 +21539 0.0673828125 +21540 -0.870391845703125 +21541 -0.014434814453125 +21542 -0.858062744140625 +21543 -0.07489013671875 +21544 -0.673004150390625 +21545 -0.11199951171875 +21546 -0.42694091796875 +21547 -0.1414794921875 +21548 -0.2100830078125 +21549 -0.176544189453125 +21550 -0.0362548828125 +21551 -0.21600341796875 +21552 0.10943603515625 +21553 -0.2503662109375 +21554 0.23516845703125 +21555 -0.273101806640625 +21556 0.373687744140625 +21557 -0.2711181640625 +21558 0.517791748046875 +21559 -0.245025634765625 +21560 0.602783203125 +21561 -0.214630126953125 +21562 0.635711669921875 +21563 -0.1785888671875 +21564 0.655181884765625 +21565 -0.12689208984375 +21566 0.65948486328125 +21567 -0.063140869140625 +21568 0.651275634765625 +21569 0.009552001953125 +21570 0.61846923828125 +21571 0.08294677734375 +21572 0.53753662109375 +21573 0.1448974609375 +21574 0.404144287109375 +21575 0.189178466796875 +21576 0.22186279296875 +21577 0.2122802734375 +21578 0.003997802734375 +21579 0.214202880859375 +21580 -0.22100830078125 +21581 0.2003173828125 +21582 -0.42449951171875 +21583 0.17681884765625 +21584 -0.579833984375 +21585 0.15032958984375 +21586 -0.641876220703125 +21587 0.13427734375 +21588 -0.6177978515625 +21589 0.12677001953125 +21590 -0.575531005859375 +21591 0.107940673828125 +21592 -0.526336669921875 +21593 0.076507568359375 +21594 -0.42645263671875 +21595 0.049102783203125 +21596 -0.2581787109375 +21597 0.034759521484375 +21598 -0.068695068359375 +21599 0.02264404296875 +21600 0.09222412109375 +21601 0.00128173828125 +21602 0.232147216796875 +21603 -0.023040771484375 +21604 0.3509521484375 +21605 -0.046783447265625 +21606 0.410064697265625 +21607 -0.078857421875 +21608 0.372955322265625 +21609 -0.128204345703125 +21610 0.2554931640625 +21611 -0.18817138671875 +21612 0.10711669921875 +21613 -0.24249267578125 +21614 -0.052886962890625 +21615 -0.285125732421875 +21616 -0.186279296875 +21617 -0.304962158203125 +21618 -0.23291015625 +21619 -0.284881591796875 +21620 -0.209442138671875 +21621 -0.232330322265625 +21622 -0.174163818359375 +21623 -0.16827392578125 +21624 -0.126739501953125 +21625 -0.095733642578125 +21626 -0.048126220703125 +21627 -0.012054443359375 +21628 0.0426025390625 +21629 0.073516845703125 +21630 0.10748291015625 +21631 0.146087646484375 +21632 0.1409912109375 +21633 0.20123291015625 +21634 0.19708251953125 +21635 0.253509521484375 +21636 0.273651123046875 +21637 0.300689697265625 +21638 0.31768798828125 +21639 0.3253173828125 +21640 0.341094970703125 +21641 0.330841064453125 +21642 0.368011474609375 +21643 0.325286865234375 +21644 0.37249755859375 +21645 0.301666259765625 +21646 0.30072021484375 +21647 0.244873046875 +21648 0.1517333984375 +21649 0.156768798828125 +21650 -0.01470947265625 +21651 0.058441162109375 +21652 -0.1883544921875 +21653 -0.044189453125 +21654 -0.372711181640625 +21655 -0.1495361328125 +21656 -0.51397705078125 +21657 -0.238250732421875 +21658 -0.57177734375 +21659 -0.295379638671875 +21660 -0.53948974609375 +21661 -0.31689453125 +21662 -0.43511962890625 +21663 -0.306915283203125 +21664 -0.2962646484375 +21665 -0.276153564453125 +21666 -0.161102294921875 +21667 -0.23614501953125 +21668 -0.0435791015625 +21669 -0.19140625 +21670 0.060394287109375 +21671 -0.14141845703125 +21672 0.13665771484375 +21673 -0.091796875 +21674 0.170135498046875 +21675 -0.04888916015625 +21676 0.16552734375 +21677 -0.013214111328125 +21678 0.15728759765625 +21679 0.023773193359375 +21680 0.150787353515625 +21681 0.061553955078125 +21682 0.12200927734375 +21683 0.0904541015625 +21684 0.080108642578125 +21685 0.111297607421875 +21686 0.05126953125 +21687 0.13055419921875 +21688 0.062896728515625 +21689 0.1553955078125 +21690 0.09271240234375 +21691 0.17791748046875 +21692 0.092987060546875 +21693 0.1827392578125 +21694 0.07855224609375 +21695 0.174468994140625 +21696 0.06427001953125 +21697 0.158172607421875 +21698 0.0347900390625 +21699 0.129913330078125 +21700 -0.01171875 +21701 0.09039306640625 +21702 -0.056060791015625 +21703 0.047149658203125 +21704 -0.055511474609375 +21705 0.015228271484375 +21706 -0.010467529296875 +21707 -0.003631591796875 +21708 0.02508544921875 +21709 -0.024444580078125 +21710 0.025665283203125 +21711 -0.053466796875 +21712 0.017333984375 +21713 -0.0810546875 +21714 0.00189208984375 +21715 -0.105377197265625 +21716 -0.03173828125 +21717 -0.128997802734375 +21718 -0.071502685546875 +21719 -0.14764404296875 +21720 -0.13543701171875 +21721 -0.166778564453125 +21722 -0.219970703125 +21723 -0.185546875 +21724 -0.300506591796875 +21725 -0.196868896484375 +21726 -0.376312255859375 +21727 -0.20147705078125 +21728 -0.416107177734375 +21729 -0.1907958984375 +21730 -0.371124267578125 +21731 -0.150970458984375 +21732 -0.242279052734375 +21733 -0.08380126953125 +21734 -0.069732666015625 +21735 -0.003326416015625 +21736 0.125640869140625 +21737 0.082489013671875 +21738 0.31268310546875 +21739 0.162628173828125 +21740 0.45501708984375 +21741 0.224639892578125 +21742 0.554779052734375 +21743 0.268310546875 +21744 0.61065673828125 +21745 0.292755126953125 +21746 0.610931396484375 +21747 0.2940673828125 +21748 0.531463623046875 +21749 0.26483154296875 +21750 0.3883056640625 +21751 0.21044921875 +21752 0.23468017578125 +21753 0.148193359375 +21754 0.095245361328125 +21755 0.086700439453125 +21756 -0.00396728515625 +21757 0.035186767578125 +21758 -0.04852294921875 +21759 -0.000640869140625 +21760 -0.055145263671875 +21761 -0.024993896484375 +21762 -0.0758056640625 +21763 -0.052734375 +21764 -0.138702392578125 +21765 -0.09124755859375 +21766 -0.209197998046875 +21767 -0.1290283203125 +21768 -0.289031982421875 +21769 -0.1656494140625 +21770 -0.37884521484375 +21771 -0.20068359375 +21772 -0.456329345703125 +21773 -0.22705078125 +21774 -0.51641845703125 +21775 -0.2431640625 +21776 -0.519287109375 +21777 -0.2373046875 +21778 -0.458251953125 +21779 -0.207977294921875 +21780 -0.384796142578125 +21781 -0.17132568359375 +21782 -0.323699951171875 +21783 -0.13568115234375 +21784 -0.269287109375 +21785 -0.100341796875 +21786 -0.1951904296875 +21787 -0.05853271484375 +21788 -0.100006103515625 +21789 -0.010894775390625 +21790 -0.01055908203125 +21791 0.033447265625 +21792 0.1033935546875 +21793 0.0826416015625 +21794 0.24908447265625 +21795 0.13812255859375 +21796 0.373199462890625 +21797 0.183349609375 +21798 0.45806884765625 +21799 0.212677001953125 +21800 0.511474609375 +21801 0.228363037109375 +21802 0.565399169921875 +21803 0.240142822265625 +21804 0.61138916015625 +21805 0.245819091796875 +21806 0.5897216796875 +21807 0.22802734375 +21808 0.4906005859375 +21809 0.184539794921875 +21810 0.33148193359375 +21811 0.12139892578125 +21812 0.147796630859375 +21813 0.050140380859375 +21814 -0.01873779296875 +21815 -0.01580810546875 +21816 -0.140289306640625 +21817 -0.0672607421875 +21818 -0.191986083984375 +21819 -0.095947265625 +21820 -0.184295654296875 +21821 -0.104339599609375 +21822 -0.161834716796875 +21823 -0.10528564453125 +21824 -0.166595458984375 +21825 -0.111053466796875 +21826 -0.19390869140625 +21827 -0.120086669921875 +21828 -0.22442626953125 +21829 -0.12664794921875 +21830 -0.279754638671875 +21831 -0.137481689453125 +21832 -0.3389892578125 +21833 -0.146697998046875 +21834 -0.3543701171875 +21835 -0.140533447265625 +21836 -0.348175048828125 +21837 -0.126312255859375 +21838 -0.32598876953125 +21839 -0.1064453125 +21840 -0.2581787109375 +21841 -0.072784423828125 +21842 -0.139801025390625 +21843 -0.02459716796875 +21844 0.014617919921875 +21845 0.033111572265625 +21846 0.144378662109375 +21847 0.081512451171875 +21848 0.221038818359375 +21849 0.11163330078125 +21850 0.27069091796875 +21851 0.1309814453125 +21852 0.294036865234375 +21853 0.139617919921875 +21854 0.311767578125 +21855 0.143707275390625 +21856 0.339141845703125 +21857 0.14794921875 +21858 0.360260009765625 +21859 0.1475830078125 +21860 0.360504150390625 +21861 0.13873291015625 +21862 0.308380126953125 +21863 0.11322021484375 +21864 0.18170166015625 +21865 0.065582275390625 +21866 0.0047607421875 +21867 0.00335693359375 +21868 -0.17559814453125 +21869 -0.059539794921875 +21870 -0.3143310546875 +21871 -0.109832763671875 +21872 -0.36785888671875 +21873 -0.13470458984375 +21874 -0.36248779296875 +21875 -0.141021728515625 +21876 -0.343536376953125 +21877 -0.14111328125 +21878 -0.3018798828125 +21879 -0.1322021484375 +21880 -0.231414794921875 +21881 -0.11248779296875 +21882 -0.117645263671875 +21883 -0.0780029296875 +21884 0.007049560546875 +21885 -0.038055419921875 +21886 0.087982177734375 +21887 -0.008270263671875 +21888 0.13946533203125 +21889 0.014892578125 +21890 0.17425537109375 +21891 0.034454345703125 +21892 0.188201904296875 +21893 0.0487060546875 +21894 0.171234130859375 +21895 0.054229736328125 +21896 0.118438720703125 +21897 0.049072265625 +21898 0.05706787109375 +21899 0.040374755859375 +21900 -0.010711669921875 +21901 0.028289794921875 +21902 -0.0914306640625 +21903 0.01068115234375 +21904 -0.162322998046875 +21905 -0.006256103515625 +21906 -0.194549560546875 +21907 -0.014556884765625 +21908 -0.1492919921875 +21909 -0.00335693359375 +21910 -0.02166748046875 +21911 0.028839111328125 +21912 0.124053955078125 +21913 0.064300537109375 +21914 0.211151123046875 +21915 0.08184814453125 +21916 0.240447998046875 +21917 0.082183837890625 +21918 0.242218017578125 +21919 0.07421875 +21920 0.2257080078125 +21921 0.06103515625 +21922 0.194366455078125 +21923 0.0440673828125 +21924 0.115509033203125 +21925 0.01458740234375 +21926 0.0128173828125 +21927 -0.020355224609375 +21928 -0.053802490234375 +21929 -0.043701171875 +21930 -0.110626220703125 +21931 -0.06256103515625 +21932 -0.199493408203125 +21933 -0.08856201171875 +21934 -0.29437255859375 +21935 -0.114410400390625 +21936 -0.33221435546875 +21937 -0.122528076171875 +21938 -0.27972412109375 +21939 -0.103790283203125 +21940 -0.185333251953125 +21941 -0.072021484375 +21942 -0.128204345703125 +21943 -0.049713134765625 +21944 -0.115692138671875 +21945 -0.039306640625 +21946 -0.116455078125 +21947 -0.032379150390625 +21948 -0.105926513671875 +21949 -0.022491455078125 +21950 -0.053955078125 +21951 -0.0015869140625 +21952 0.048797607421875 +21953 0.0325927734375 +21954 0.157318115234375 +21955 0.06719970703125 +21956 0.212005615234375 +21957 0.085357666015625 +21958 0.218475341796875 +21959 0.088531494140625 +21960 0.23724365234375 +21961 0.093597412109375 +21962 0.30535888671875 +21963 0.110992431640625 +21964 0.38128662109375 +21965 0.12921142578125 +21966 0.404449462890625 +21967 0.131500244140625 +21968 0.3944091796875 +21969 0.123626708984375 +21970 0.3885498046875 +21971 0.116363525390625 +21972 0.362640380859375 +21973 0.103240966796875 +21974 0.27362060546875 +21975 0.072540283203125 +21976 0.11712646484375 +21977 0.023345947265625 +21978 -0.054901123046875 +21979 -0.029510498046875 +21980 -0.19085693359375 +21981 -0.071319580078125 +21982 -0.28570556640625 +21983 -0.100494384765625 +21984 -0.339263916015625 +21985 -0.11688232421875 +21986 -0.3775634765625 +21987 -0.12774658203125 +21988 -0.445709228515625 +21989 -0.145751953125 +21990 -0.535064697265625 +21991 -0.1685791015625 +21992 -0.629058837890625 +21993 -0.19171142578125 +21994 -0.697601318359375 +21995 -0.206939697265625 +21996 -0.70391845703125 +21997 -0.204193115234375 +21998 -0.6424560546875 +21999 -0.18218994140625 +22000 -0.491241455078125 +22001 -0.135040283203125 +22002 -0.265716552734375 +22003 -0.067352294921875 +22004 -0.023712158203125 +22005 0.004425048828125 +22006 0.201751708984375 +22007 0.070831298828125 +22008 0.375823974609375 +22009 0.121978759765625 +22010 0.485076904296875 +22011 0.15399169921875 +22012 0.56884765625 +22013 0.177825927734375 +22014 0.634765625 +22015 0.195648193359375 +22016 0.63763427734375 +22017 0.195343017578125 +22018 0.5660400390625 +22019 0.174591064453125 +22020 0.4720458984375 +22021 0.14703369140625 +22022 0.40692138671875 +22023 0.125457763671875 +22024 0.3778076171875 +22025 0.11181640625 +22026 0.376953125 +22027 0.104461669921875 +22028 0.371978759765625 +22029 0.095733642578125 +22030 0.313140869140625 +22031 0.0736083984375 +22032 0.184417724609375 +22033 0.034515380859375 +22034 0.011199951171875 +22035 -0.01483154296875 +22036 -0.171051025390625 +22037 -0.0653076171875 +22038 -0.33740234375 +22039 -0.1104736328125 +22040 -0.47198486328125 +22041 -0.146209716796875 +22042 -0.560394287109375 +22043 -0.168853759765625 +22044 -0.58056640625 +22045 -0.172943115234375 +22046 -0.54754638671875 +22047 -0.16229248046875 +22048 -0.508575439453125 +22049 -0.148834228515625 +22050 -0.459503173828125 +22051 -0.131744384765625 +22052 -0.394378662109375 +22053 -0.10986328125 +22054 -0.35260009765625 +22055 -0.093231201171875 +22056 -0.31170654296875 +22057 -0.07666015625 +22058 -0.197418212890625 +22059 -0.04205322265625 +22060 -0.007965087890625 +22061 0.010650634765625 +22062 0.207489013671875 +22063 0.06890869140625 +22064 0.409210205078125 +22065 0.122650146484375 +22066 0.57208251953125 +22067 0.165496826171875 +22068 0.66595458984375 +22069 0.18988037109375 +22070 0.65875244140625 +22071 0.18780517578125 +22072 0.56744384765625 +22073 0.16357421875 +22074 0.431396484375 +22075 0.127044677734375 +22076 0.29443359375 +22077 0.08929443359375 +22078 0.182464599609375 +22079 0.05694580078125 +22080 0.06365966796875 +22081 0.02239990234375 +22082 -0.075958251953125 +22083 -0.01751708984375 +22084 -0.189422607421875 +22085 -0.05084228515625 +22086 -0.271942138671875 +22087 -0.076080322265625 +22088 -0.342529296875 +22089 -0.097686767578125 +22090 -0.364166259765625 +22091 -0.106353759765625 +22092 -0.327239990234375 +22093 -0.099517822265625 +22094 -0.2769775390625 +22095 -0.088287353515625 +22096 -0.253692626953125 +22097 -0.082611083984375 +22098 -0.24365234375 +22099 -0.079132080078125 +22100 -0.1983642578125 +22101 -0.06591796875 +22102 -0.116241455078125 +22103 -0.042694091796875 +22104 -0.036834716796875 +22105 -0.019439697265625 +22106 0.034881591796875 +22107 0.00238037109375 +22108 0.09124755859375 +22109 0.0206298828125 +22110 0.10888671875 +22111 0.02923583984375 +22112 0.125518798828125 +22113 0.037322998046875 +22114 0.15771484375 +22115 0.048828125 +22116 0.17828369140625 +22117 0.056793212890625 +22118 0.17108154296875 +22119 0.057098388671875 +22120 0.129974365234375 +22121 0.048126220703125 +22122 0.082427978515625 +22123 0.03668212890625 +22124 0.027679443359375 +22125 0.022552490234375 +22126 -0.065643310546875 +22127 -0.001922607421875 +22128 -0.15936279296875 +22129 -0.027191162109375 +22130 -0.21307373046875 +22131 -0.043121337890625 +22132 -0.234649658203125 +22133 -0.051513671875 +22134 -0.2001953125 +22135 -0.0462646484375 +22136 -0.119171142578125 +22137 -0.029541015625 +22138 -0.024749755859375 +22139 -0.0093994140625 +22140 0.085784912109375 +22141 0.0150146484375 +22142 0.178131103515625 +22143 0.03533935546875 +22144 0.215576171875 +22145 0.0426025390625 +22146 0.211456298828125 +22147 0.040191650390625 +22148 0.17523193359375 +22149 0.030548095703125 +22150 0.128753662109375 +22151 0.01910400390625 +22152 0.1019287109375 +22153 0.01324462890625 +22154 0.0743408203125 +22155 0.007843017578125 +22156 0.04327392578125 +22157 0.002105712890625 +22158 0.038177490234375 +22159 0.003204345703125 +22160 0.076263427734375 +22161 0.015289306640625 +22162 0.14105224609375 +22163 0.034088134765625 +22164 0.186431884765625 +22165 0.04803466796875 +22166 0.188812255859375 +22167 0.051116943359375 +22168 0.1390380859375 +22169 0.040985107421875 +22170 0.041778564453125 +22171 0.0186767578125 +22172 -0.079437255859375 +22173 -0.010040283203125 +22174 -0.219390869140625 +22175 -0.0439453125 +22176 -0.367828369140625 +22177 -0.08050537109375 +22178 -0.494873046875 +22179 -0.1123046875 +22180 -0.556243896484375 +22181 -0.12835693359375 +22182 -0.508697509765625 +22183 -0.117889404296875 +22184 -0.3756103515625 +22185 -0.08660888671875 +22186 -0.218902587890625 +22187 -0.04974365234375 +22188 -0.063751220703125 +22189 -0.013458251953125 +22190 0.091552734375 +22191 0.02276611328125 +22192 0.23602294921875 +22193 0.056365966796875 +22194 0.342987060546875 +22195 0.080810546875 +22196 0.39520263671875 +22197 0.09197998046875 +22198 0.389373779296875 +22199 0.089141845703125 +22200 0.324249267578125 +22201 0.072021484375 +22202 0.224090576171875 +22203 0.046722412109375 +22204 0.124267578125 +22205 0.022003173828125 +22206 0.037078857421875 +22207 0.00091552734375 +22208 -0.010101318359375 +22209 -0.009796142578125 +22210 -0.019439697265625 +22211 -0.0107421875 +22212 -0.022796630859375 +22213 -0.0098876953125 +22214 -0.001556396484375 +22215 -0.00274658203125 +22216 0.056304931640625 +22217 0.0135498046875 +22218 0.106719970703125 +22219 0.027923583984375 +22220 0.096893310546875 +22221 0.0272216796875 +22222 0.042694091796875 +22223 0.015289306640625 +22224 -0.018035888671875 +22225 0.00140380859375 +22226 -0.07586669921875 +22227 -0.0120849609375 +22228 -0.11944580078125 +22229 -0.02239990234375 +22230 -0.15972900390625 +22231 -0.03228759765625 +22232 -0.202606201171875 +22233 -0.043182373046875 +22234 -0.24859619140625 +22235 -0.05517578125 +22236 -0.30517578125 +22237 -0.070098876953125 +22238 -0.36212158203125 +22239 -0.085357666015625 +22240 -0.39141845703125 +22241 -0.093963623046875 +22242 -0.35528564453125 +22243 -0.086456298828125 +22244 -0.249969482421875 +22245 -0.061798095703125 +22246 -0.092864990234375 +22247 -0.02423095703125 +22248 0.08905029296875 +22249 0.01959228515625 +22250 0.2352294921875 +22251 0.054718017578125 +22252 0.318817138671875 +22253 0.074554443359375 +22254 0.358642578125 +22255 0.08380126953125 +22256 0.347747802734375 +22257 0.080780029296875 +22258 0.28564453125 +22259 0.06536865234375 +22260 0.223175048828125 +22261 0.0501708984375 +22262 0.196746826171875 +22263 0.044189453125 +22264 0.179840087890625 +22265 0.040802001953125 +22266 0.155548095703125 +22267 0.0357666015625 +22268 0.151214599609375 +22269 0.035797119140625 +22270 0.156951904296875 +22271 0.03839111328125 +22272 0.13177490234375 +22273 0.033447265625 +22274 0.100799560546875 +22275 0.026702880859375 +22276 0.087127685546875 +22277 0.023681640625 +22278 0.05487060546875 +22279 0.016448974609375 +22280 -0.009002685546875 +22281 0.00213623046875 +22282 -0.10400390625 +22283 -0.0191650390625 +22284 -0.229400634765625 +22285 -0.047332763671875 +22286 -0.35552978515625 +22287 -0.07586669921875 +22288 -0.441925048828125 +22289 -0.095947265625 +22290 -0.473846435546875 +22291 -0.10430908203125 +22292 -0.464813232421875 +22293 -0.103790283203125 +22294 -0.419097900390625 +22295 -0.095184326171875 +22296 -0.334320068359375 +22297 -0.077911376953125 +22298 -0.227935791015625 +22299 -0.055633544921875 +22300 -0.12347412109375 +22301 -0.033416748046875 +22302 -0.02764892578125 +22303 -0.0126953125 +22304 0.077667236328125 +22305 0.01043701171875 +22306 0.2132568359375 +22307 0.040435791015625 +22308 0.38885498046875 +22309 0.079345703125 +22310 0.582794189453125 +22311 0.122467041015625 +22312 0.734039306640625 +22313 0.156524658203125 +22314 0.800140380859375 +22315 0.172271728515625 +22316 0.7783203125 +22317 0.16900634765625 +22318 0.6651611328125 +22319 0.145904541015625 +22320 0.45965576171875 +22321 0.10272216796875 +22322 0.199188232421875 +22323 0.0474853515625 +22324 -0.050689697265625 +22325 -0.005706787109375 +22326 -0.23297119140625 +22327 -0.0445556640625 +22328 -0.33013916015625 +22329 -0.0653076171875 +22330 -0.368408203125 +22331 -0.07366943359375 +22332 -0.378936767578125 +22333 -0.076324462890625 +22334 -0.376983642578125 +22335 -0.076568603515625 +22336 -0.37969970703125 +22337 -0.07806396484375 +22338 -0.391510009765625 +22339 -0.081695556640625 +22340 -0.385345458984375 +22341 -0.081573486328125 +22342 -0.3419189453125 +22343 -0.073455810546875 +22344 -0.28289794921875 +22345 -0.061920166015625 +22346 -0.251617431640625 +22347 -0.0562744140625 +22348 -0.266143798828125 +22349 -0.06036376953125 +22350 -0.273345947265625 +22351 -0.062652587890625 +22352 -0.216796875 +22353 -0.050933837890625 +22354 -0.128265380859375 +22355 -0.03204345703125 +22356 -0.068145751953125 +22357 -0.01898193359375 +22358 -0.0430908203125 +22359 -0.013214111328125 +22360 -0.024444580078125 +22361 -0.00860595703125 +22362 0.020721435546875 +22363 0.00189208984375 +22364 0.124481201171875 +22365 0.025146484375 +22366 0.25787353515625 +22367 0.05487060546875 +22368 0.379119873046875 +22369 0.08197021484375 +22370 0.47991943359375 +22371 0.1046142578125 +22372 0.5281982421875 +22373 0.1158447265625 +22374 0.511138916015625 +22375 0.11285400390625 +22376 0.456207275390625 +22377 0.10150146484375 +22378 0.407470703125 +22379 0.09130859375 +22380 0.383758544921875 +22381 0.086334228515625 +22382 0.35687255859375 +22383 0.0804443359375 +22384 0.31182861328125 +22385 0.0704345703125 +22386 0.250885009765625 +22387 0.05682373046875 +22388 0.1654052734375 +22389 0.03778076171875 +22390 0.035247802734375 +22391 0.009002685546875 +22392 -0.142059326171875 +22393 -0.02996826171875 +22394 -0.33563232421875 +22395 -0.07244873046875 +22396 -0.5345458984375 +22397 -0.11602783203125 +22398 -0.72186279296875 +22399 -0.157012939453125 +22400 -0.836669921875 +22401 -0.182220458984375 +22402 -0.8326416015625 +22403 -0.181640625 +22404 -0.7296142578125 +22405 -0.1595458984375 +22406 -0.582550048828125 +22407 -0.1278076171875 +22408 -0.440093994140625 +22409 -0.096954345703125 +22410 -0.324310302734375 +22411 -0.071746826171875 +22412 -0.20147705078125 +22413 -0.044891357421875 +22414 -0.044647216796875 +22415 -0.010589599609375 +22416 0.103973388671875 +22417 0.02197265625 +22418 0.202392578125 +22419 0.043701171875 +22420 0.264495849609375 +22421 0.05755615234375 +22422 0.338897705078125 +22423 0.07403564453125 +22424 0.443817138671875 +22425 0.0970458984375 +22426 0.545074462890625 +22427 0.119171142578125 +22428 0.6173095703125 +22429 0.13494873046875 +22430 0.6524658203125 +22431 0.142608642578125 +22432 0.66339111328125 +22433 0.14495849609375 +22434 0.6561279296875 +22435 0.143280029296875 +22436 0.606781005859375 +22437 0.132415771484375 +22438 0.501190185546875 +22439 0.10931396484375 +22440 0.352783203125 +22441 0.076904296875 +22442 0.176544189453125 +22443 0.0384521484375 +22444 -0.034820556640625 +22445 -0.007568359375 +22446 -0.258209228515625 +22447 -0.056121826171875 +22448 -0.44244384765625 +22449 -0.09613037109375 +22450 -0.5753173828125 +22451 -0.124969482421875 +22452 -0.65203857421875 +22453 -0.1416015625 +22454 -0.641632080078125 +22455 -0.13934326171875 +22456 -0.562164306640625 +22457 -0.12213134765625 +22458 -0.458038330078125 +22459 -0.099517822265625 +22460 -0.350555419921875 +22461 -0.076141357421875 +22462 -0.260528564453125 +22463 -0.056488037109375 +22464 -0.192108154296875 +22465 -0.041473388671875 +22466 -0.141937255859375 +22467 -0.0303955078125 +22468 -0.1021728515625 +22469 -0.021575927734375 +22470 -0.062896728515625 +22471 -0.01287841796875 +22472 -0.011932373046875 +22473 -0.001678466796875 +22474 0.062835693359375 +22475 0.014617919921875 +22476 0.148712158203125 +22477 0.03326416015625 +22478 0.241729736328125 +22479 0.053375244140625 +22480 0.34912109375 +22481 0.0765380859375 +22482 0.457305908203125 +22483 0.099822998046875 +22484 0.54388427734375 +22485 0.118377685546875 +22486 0.5728759765625 +22487 0.12445068359375 +22488 0.506591796875 +22489 0.109893798828125 +22490 0.351226806640625 +22491 0.076080322265625 +22492 0.146514892578125 +22493 0.031585693359375 +22494 -0.05523681640625 +22495 -0.012237548828125 +22496 -0.21624755859375 +22497 -0.047210693359375 +22498 -0.334930419921875 +22499 -0.072967529296875 +22500 -0.402984619140625 +22501 -0.08770751953125 +22502 -0.4412841796875 +22503 -0.095947265625 +22504 -0.49578857421875 +22505 -0.10760498046875 +22506 -0.5601806640625 +22507 -0.121337890625 +22508 -0.600738525390625 +22509 -0.129913330078125 +22510 -0.584228515625 +22511 -0.12615966796875 +22512 -0.47930908203125 +22513 -0.103302001953125 +22514 -0.27935791015625 +22515 -0.0599365234375 +22516 -0.0089111328125 +22517 -0.0013427734375 +22518 0.268798828125 +22519 0.05877685546875 +22520 0.482818603515625 +22521 0.105072021484375 +22522 0.60369873046875 +22523 0.131195068359375 +22524 0.650421142578125 +22525 0.141265869140625 +22526 0.66400146484375 +22527 0.144134521484375 +22528 0.6414794921875 +22529 0.139404296875 +22530 0.572540283203125 +22531 0.124786376953125 +22532 0.498138427734375 +22533 0.10797119140625 +22534 0.439453125 +22535 0.093170166015625 +22536 0.375518798828125 +22537 0.07684326171875 +22538 0.274505615234375 +22539 0.05340576171875 +22540 0.1087646484375 +22541 0.018096923828125 +22542 -0.099395751953125 +22543 -0.02471923828125 +22544 -0.3182373046875 +22545 -0.068939208984375 +22546 -0.5489501953125 +22547 -0.114593505859375 +22548 -0.7738037109375 +22549 -0.158233642578125 +22550 -0.86383056640625 +22551 -0.190032958984375 +22552 -0.870391845703125 +22553 -0.203857421875 +22554 -0.86895751953125 +22555 -0.2030029296875 +22556 -0.861053466796875 +22557 -0.18994140625 +22558 -0.765869140625 +22559 -0.161651611328125 +22560 -0.5301513671875 +22561 -0.1162109375 +22562 -0.214691162109375 +22563 -0.05511474609375 +22564 0.137359619140625 +22565 0.013458251953125 +22566 0.474822998046875 +22567 0.079864501953125 +22568 0.76239013671875 +22569 0.137359619140625 +22570 0.867462158203125 +22571 0.180816650390625 +22572 0.870361328125 +22573 0.21014404296875 +22574 0.86480712890625 +22575 0.223052978515625 +22576 0.831817626953125 +22577 0.220458984375 +22578 0.677581787109375 +22579 0.20684814453125 +22580 0.495880126953125 +22581 0.18328857421875 +22582 0.30767822265625 +22583 0.153228759765625 +22584 0.116180419921875 +22585 0.117156982421875 +22586 -0.110748291015625 +22587 0.06939697265625 +22588 -0.381805419921875 +22589 0.0087890625 +22590 -0.6572265625 +22591 -0.05657958984375 +22592 -0.857421875 +22593 -0.115509033203125 +22594 -0.870391845703125 +22595 -0.159942626953125 +22596 -0.870391845703125 +22597 -0.188446044921875 +22598 -0.86444091796875 +22599 -0.205841064453125 +22600 -0.85723876953125 +22601 -0.21856689453125 +22602 -0.790008544921875 +22603 -0.223175048828125 +22604 -0.62847900390625 +22605 -0.20965576171875 +22606 -0.3956298828125 +22607 -0.177398681640625 +22608 -0.126708984375 +22609 -0.132476806640625 +22610 0.150115966796875 +22611 -0.079986572265625 +22612 0.424041748046875 +22613 -0.022186279296875 +22614 0.670623779296875 +22615 0.035858154296875 +22616 0.854522705078125 +22617 0.086883544921875 +22618 0.866485595703125 +22619 0.127471923828125 +22620 0.86920166015625 +22621 0.1546630859375 +22622 0.8653564453125 +22623 0.171630859375 +22624 0.857147216796875 +22625 0.180755615234375 +22626 0.766845703125 +22627 0.181396484375 +22628 0.628509521484375 +22629 0.174407958984375 +22630 0.462127685546875 +22631 0.15850830078125 +22632 0.297210693359375 +22633 0.138458251953125 +22634 0.14862060546875 +22635 0.11651611328125 +22636 -0.00537109375 +22637 0.08856201171875 +22638 -0.15753173828125 +22639 0.056060791015625 +22640 -0.31304931640625 +22641 0.0184326171875 +22642 -0.48876953125 +22643 -0.026763916015625 +22644 -0.6416015625 +22645 -0.07080078125 +22646 -0.751373291015625 +22647 -0.1090087890625 +22648 -0.84619140625 +22649 -0.1455078125 +22650 -0.861297607421875 +22651 -0.177520751953125 +22652 -0.863250732421875 +22653 -0.198822021484375 +22654 -0.856597900390625 +22655 -0.20355224609375 +22656 -0.7498779296875 +22657 -0.19390869140625 +22658 -0.624542236328125 +22659 -0.1805419921875 +22660 -0.47808837890625 +22661 -0.159423828125 +22662 -0.253387451171875 +22663 -0.11981201171875 +22664 0.003692626953125 +22665 -0.0701904296875 +22666 0.2257080078125 +22667 -0.023193359375 +22668 0.427154541015625 +22669 0.02337646484375 +22670 0.643218994140625 +22671 0.07537841796875 +22672 0.855926513671875 +22673 0.13092041015625 +22674 0.870361328125 +22675 0.17919921875 +22676 0.870361328125 +22677 0.211029052734375 +22678 0.862762451171875 +22679 0.227691650390625 +22680 0.79669189453125 +22681 0.22857666015625 +22682 0.595794677734375 +22683 0.2119140625 +22684 0.362152099609375 +22685 0.183074951171875 +22686 0.1270751953125 +22687 0.147216796875 +22688 -0.086944580078125 +22689 0.1082763671875 +22690 -0.2784423828125 +22691 0.066680908203125 +22692 -0.484832763671875 +22693 0.01611328125 +22694 -0.729583740234375 +22695 -0.046875 +22696 -0.86688232421875 +22697 -0.112884521484375 +22698 -0.870391845703125 +22699 -0.170166015625 +22700 -0.86859130859375 +22701 -0.21771240234375 +22702 -0.86279296875 +22703 -0.255035400390625 +22704 -0.817962646484375 +22705 -0.275482177734375 +22706 -0.6116943359375 +22707 -0.2706298828125 +22708 -0.3128662109375 +22709 -0.2391357421875 +22710 0.039398193359375 +22711 -0.18719482421875 +22712 0.422821044921875 +22713 -0.1185302734375 +22714 0.805145263671875 +22715 -0.039306640625 +22716 0.870361328125 +22717 0.037841796875 +22718 0.870361328125 +22719 0.102386474609375 +22720 0.860015869140625 +22721 0.152069091796875 +22722 0.727935791015625 +22723 0.1854248046875 +22724 0.48114013671875 +22725 0.2012939453125 +22726 0.2059326171875 +22727 0.204010009765625 +22728 -0.06103515625 +22729 0.197662353515625 +22730 -0.29913330078125 +22731 0.18402099609375 +22732 -0.516204833984375 +22733 0.16033935546875 +22734 -0.7252197265625 +22735 0.123779296875 +22736 -0.85980224609375 +22737 0.07891845703125 +22738 -0.870391845703125 +22739 0.032073974609375 +22740 -0.870391845703125 +22741 -0.011199951171875 +22742 -0.858062744140625 +22743 -0.041839599609375 +22744 -0.673004150390625 +22745 -0.0589599609375 +22746 -0.42694091796875 +22747 -0.0721435546875 +22748 -0.2100830078125 +22749 -0.089385986328125 +22750 -0.0362548828125 +22751 -0.110137939453125 +22752 0.10943603515625 +22753 -0.128875732421875 +22754 0.23516845703125 +22755 -0.14178466796875 +22756 0.373687744140625 +22757 -0.14117431640625 +22758 0.517791748046875 +22759 -0.127349853515625 +22760 0.602783203125 +22761 -0.11187744140625 +22762 0.635711669921875 +22763 -0.093780517578125 +22764 0.655181884765625 +22765 -0.066986083984375 +22766 0.65948486328125 +22767 -0.03338623046875 +22768 0.651275634765625 +22769 0.005401611328125 +22770 0.61846923828125 +22771 0.04473876953125 +22772 0.53753662109375 +22773 0.077667236328125 +22774 0.404144287109375 +22775 0.1007080078125 +22776 0.22186279296875 +22777 0.1119384765625 +22778 0.003997802734375 +22779 0.111480712890625 +22780 -0.22100830078125 +22781 0.1025390625 +22782 -0.42449951171875 +22783 0.088836669921875 +22784 -0.579833984375 +22785 0.073883056640625 +22786 -0.641876220703125 +22787 0.0648193359375 +22788 -0.6177978515625 +22789 0.06103515625 +22790 -0.575531005859375 +22791 0.05242919921875 +22792 -0.526336669921875 +22793 0.03802490234375 +22794 -0.42645263671875 +22795 0.025634765625 +22796 -0.2581787109375 +22797 0.01947021484375 +22798 -0.068695068359375 +22799 0.01409912109375 +22800 0.09222412109375 +22801 0.003875732421875 +22802 0.232147216796875 +22803 -0.008148193359375 +22804 0.3509521484375 +22805 -0.020172119140625 +22806 0.410064697265625 +22807 -0.036529541015625 +22808 0.372955322265625 +22809 -0.061492919921875 +22810 0.2554931640625 +22811 -0.091766357421875 +22812 0.10711669921875 +22813 -0.11932373046875 +22814 -0.052886962890625 +22815 -0.14111328125 +22816 -0.186279296875 +22817 -0.15167236328125 +22818 -0.23291015625 +22819 -0.142608642578125 +22820 -0.209442138671875 +22821 -0.11749267578125 +22822 -0.174163818359375 +22823 -0.086517333984375 +22824 -0.126739501953125 +22825 -0.051116943359375 +22826 -0.048126220703125 +22827 -0.010040283203125 +22828 0.0426025390625 +22829 0.032196044921875 +22830 0.10748291015625 +22831 0.06829833984375 +22832 0.1409912109375 +22833 0.096038818359375 +22834 0.19708251953125 +22835 0.122467041015625 +22836 0.273651123046875 +22837 0.146453857421875 +22838 0.31768798828125 +22839 0.159423828125 +22840 0.341094970703125 +22841 0.162994384765625 +22842 0.368011474609375 +22843 0.161041259765625 +22844 0.37249755859375 +22845 0.150115966796875 +22846 0.30072021484375 +22847 0.122833251953125 +22848 0.1517333984375 +22849 0.080078125 +22850 -0.01470947265625 +22851 0.032135009765625 +22852 -0.1883544921875 +22853 -0.01806640625 +22854 -0.372711181640625 +22855 -0.06976318359375 +22856 -0.51397705078125 +22857 -0.11346435546875 +22858 -0.57177734375 +22859 -0.14190673828125 +22860 -0.53948974609375 +22861 -0.153076171875 +22862 -0.43511962890625 +22863 -0.14892578125 +22864 -0.2962646484375 +22865 -0.1346435546875 +22866 -0.161102294921875 +22867 -0.115814208984375 +22868 -0.0435791015625 +22869 -0.094635009765625 +22870 0.060394287109375 +22871 -0.070770263671875 +22872 0.13665771484375 +22873 -0.046966552734375 +22874 0.170135498046875 +22875 -0.02630615234375 +22876 0.16552734375 +22877 -0.009033203125 +22878 0.15728759765625 +22879 0.009033203125 +22880 0.150787353515625 +22881 0.027618408203125 +22882 0.12200927734375 +22883 0.0419921875 +22884 0.080108642578125 +22885 0.05255126953125 +22886 0.05126953125 +22887 0.062408447265625 +22888 0.062896728515625 +22889 0.075042724609375 +22890 0.09271240234375 +22891 0.0865478515625 +22892 0.092987060546875 +22893 0.08941650390625 +22894 0.07855224609375 +22895 0.08587646484375 +22896 0.06427001953125 +22897 0.078338623046875 +22898 0.0347900390625 +22899 0.064910888671875 +22900 -0.01171875 +22901 0.0458984375 +22902 -0.056060791015625 +22903 0.02496337890625 +22904 -0.055511474609375 +22905 0.009429931640625 +22906 -0.010467529296875 +22907 0.0001220703125 +22908 0.02508544921875 +22909 -0.010223388671875 +22910 0.025665283203125 +22911 -0.024627685546875 +22912 0.017333984375 +22913 -0.038360595703125 +22914 0.00189208984375 +22915 -0.050567626953125 +22916 -0.03173828125 +22917 -0.062469482421875 +22918 -0.071502685546875 +22919 -0.071929931640625 +22920 -0.13543701171875 +22921 -0.08160400390625 +22922 -0.219970703125 +22923 -0.091064453125 +22924 -0.300506591796875 +22925 -0.096832275390625 +22926 -0.376312255859375 +22927 -0.0992431640625 +22928 -0.416107177734375 +22929 -0.094085693359375 +22930 -0.371124267578125 +22931 -0.074676513671875 +22932 -0.242279052734375 +22933 -0.0418701171875 +22934 -0.069732666015625 +22935 -0.00250244140625 +22936 0.125640869140625 +22937 0.039520263671875 +22938 0.31268310546875 +22939 0.07879638671875 +22940 0.45501708984375 +22941 0.109222412109375 +22942 0.554779052734375 +22943 0.130706787109375 +22944 0.61065673828125 +22945 0.142791748046875 +22946 0.610931396484375 +22947 0.14361572265625 +22948 0.531463623046875 +22949 0.1295166015625 +22950 0.3883056640625 +22951 0.103118896484375 +22952 0.23468017578125 +22953 0.0728759765625 +22954 0.095245361328125 +22955 0.042999267578125 +22956 -0.00396728515625 +22957 0.0179443359375 +22958 -0.04852294921875 +22959 0.000457763671875 +22960 -0.055145263671875 +22961 -0.0113525390625 +22962 -0.0758056640625 +22963 -0.024810791015625 +22964 -0.138702392578125 +22965 -0.04364013671875 +22966 -0.209197998046875 +22967 -0.062103271484375 +22968 -0.289031982421875 +22969 -0.080078125 +22970 -0.37884521484375 +22971 -0.097412109375 +22972 -0.456329345703125 +22973 -0.110565185546875 +22974 -0.51641845703125 +22975 -0.1187744140625 +22976 -0.519287109375 +22977 -0.1160888671875 +22978 -0.458251953125 +22979 -0.101715087890625 +22980 -0.384796142578125 +22981 -0.08380126953125 +22982 -0.323699951171875 +22983 -0.066558837890625 +22984 -0.269287109375 +22985 -0.049560546875 +22986 -0.1951904296875 +22987 -0.029296875 +22988 -0.100006103515625 +22989 -0.006072998046875 +22990 -0.01055908203125 +22991 0.0155029296875 +22992 0.1033935546875 +22993 0.039642333984375 +22994 0.24908447265625 +22995 0.067108154296875 +22996 0.373199462890625 +22997 0.08953857421875 +22998 0.45806884765625 +22999 0.104095458984375 +23000 0.511474609375 +23001 0.1119384765625 +23002 0.565399169921875 +23003 0.11798095703125 +23004 0.61138916015625 +23005 0.121124267578125 +23006 0.5897216796875 +23007 0.112548828125 +23008 0.4906005859375 +23009 0.091094970703125 +23010 0.33148193359375 +23011 0.059814453125 +23012 0.147796630859375 +23013 0.02447509765625 +23014 -0.01873779296875 +23015 -0.00811767578125 +23016 -0.140289306640625 +23017 -0.0333251953125 +23018 -0.191986083984375 +23019 -0.047027587890625 +23020 -0.184295654296875 +23021 -0.050537109375 +23022 -0.161834716796875 +23023 -0.0504150390625 +23024 -0.166595458984375 +23025 -0.05291748046875 +23026 -0.19390869140625 +23027 -0.057281494140625 +23028 -0.22442626953125 +23029 -0.060577392578125 +23030 -0.279754638671875 +23031 -0.066192626953125 +23032 -0.3389892578125 +23033 -0.0711669921875 +23034 -0.3543701171875 +23035 -0.068511962890625 +23036 -0.348175048828125 +23037 -0.0618896484375 +23038 -0.32598876953125 +23039 -0.052459716796875 +23040 -0.2581787109375 +23041 -0.036102294921875 +23042 -0.139801025390625 +23043 -0.01239013671875 +23044 0.014617919921875 +23045 0.016082763671875 +23046 0.144378662109375 +23047 0.0399169921875 +23048 0.221038818359375 +23049 0.05462646484375 +23050 0.27069091796875 +23051 0.063995361328125 +23052 0.294036865234375 +23053 0.068084716796875 +23054 0.311767578125 +23055 0.07000732421875 +23056 0.339141845703125 +23057 0.072021484375 +23058 0.360260009765625 +23059 0.071533203125 +23060 0.360504150390625 +23061 0.066680908203125 +23062 0.308380126953125 +23063 0.054107666015625 +23064 0.18170166015625 +23065 0.03167724609375 +23066 0.0047607421875 +23067 0.0028076171875 +23068 -0.17559814453125 +23069 -0.0263671875 +23070 -0.3143310546875 +23071 -0.04998779296875 +23072 -0.36785888671875 +23073 -0.062469482421875 +23074 -0.36248779296875 +23075 -0.066650390625 +23076 -0.343536376953125 +23077 -0.067718505859375 +23078 -0.3018798828125 +23079 -0.064453125 +23080 -0.231414794921875 +23081 -0.05609130859375 +23082 -0.117645263671875 +23083 -0.040924072265625 +23084 0.007049560546875 +23085 -0.02301025390625 +23086 0.087982177734375 +23087 -0.009063720703125 +23088 0.13946533203125 +23089 0.0023193359375 +23090 0.17425537109375 +23091 0.012359619140625 +23092 0.188201904296875 +23093 0.02020263671875 +23094 0.171234130859375 +23095 0.0242919921875 +23096 0.118438720703125 +23097 0.023712158203125 +23098 0.05706787109375 +23099 0.021453857421875 +23100 -0.010711669921875 +23101 0.017486572265625 +23102 -0.0914306640625 +23103 0.010833740234375 +23104 -0.162322998046875 +23105 0.00408935546875 +23106 -0.194549560546875 +23107 0.000640869140625 +23108 -0.1492919921875 +23109 0.00518798828125 +23110 -0.02166748046875 +23111 0.01837158203125 +23112 0.124053955078125 +23113 0.032623291015625 +23114 0.211151123046875 +23115 0.0389404296875 +23116 0.240447998046875 +23117 0.03765869140625 +23118 0.242218017578125 +23119 0.03271484375 +23120 0.2257080078125 +23121 0.025543212890625 +23122 0.194366455078125 +23123 0.016815185546875 +23124 0.115509033203125 +23125 0.00286865234375 +23126 0.0128173828125 +23127 -0.013153076171875 +23128 -0.053802490234375 +23129 -0.023895263671875 +23130 -0.110626220703125 +23131 -0.03240966796875 +23132 -0.199493408203125 +23133 -0.043670654296875 +23134 -0.29437255859375 +23135 -0.054534912109375 +23136 -0.33221435546875 +23137 -0.0574951171875 +23138 -0.27972412109375 +23139 -0.048675537109375 +23140 -0.185333251953125 +23141 -0.034088134765625 +23142 -0.128204345703125 +23143 -0.023406982421875 +23144 -0.115692138671875 +23145 -0.017730712890625 +23146 -0.116455078125 +23147 -0.013519287109375 +23148 -0.105926513671875 +23149 -0.008056640625 +23150 -0.053955078125 +23151 0.001983642578125 +23152 0.048797607421875 +23153 0.017547607421875 +23154 0.157318115234375 +23155 0.0330810546875 +23156 0.212005615234375 +23157 0.041290283203125 +23158 0.218475341796875 +23159 0.042816162109375 +23160 0.23724365234375 +23161 0.044891357421875 +23162 0.30535888671875 +23163 0.052001953125 +23164 0.38128662109375 +23165 0.059234619140625 +23166 0.404449462890625 +23167 0.059417724609375 +23168 0.3944091796875 +23169 0.055084228515625 +23170 0.3885498046875 +23171 0.050933837890625 +23172 0.362640380859375 +23173 0.04425048828125 +23174 0.27362060546875 +23175 0.030059814453125 +23176 0.11712646484375 +23177 0.008026123046875 +23178 -0.054901123046875 +23179 -0.015411376953125 +23180 -0.19085693359375 +23181 -0.033935546875 +23182 -0.28570556640625 +23183 -0.046844482421875 +23184 -0.339263916015625 +23185 -0.054046630859375 +23186 -0.3775634765625 +23187 -0.058624267578125 +23188 -0.445709228515625 +23189 -0.066009521484375 +23190 -0.535064697265625 +23191 -0.07525634765625 +23192 -0.629058837890625 +23193 -0.08447265625 +23194 -0.697601318359375 +23195 -0.09014892578125 +23196 -0.70391845703125 +23197 -0.088043212890625 +23198 -0.6424560546875 +23199 -0.077667236328125 +23200 -0.491241455078125 +23201 -0.056549072265625 +23202 -0.265716552734375 +23203 -0.026702880859375 +23204 -0.023712158203125 +23205 0.0047607421875 +23206 0.201751708984375 +23207 0.03375244140625 +23208 0.375823974609375 +23209 0.05596923828125 +23210 0.485076904296875 +23211 0.069793701171875 +23212 0.56884765625 +23213 0.07989501953125 +23214 0.634765625 +23215 0.08721923828125 +23216 0.63763427734375 +23217 0.086395263671875 +23218 0.5660400390625 +23219 0.07611083984375 +23220 0.4720458984375 +23221 0.062744140625 +23222 0.40692138671875 +23223 0.052581787109375 +23224 0.3778076171875 +23225 0.046600341796875 +23226 0.376953125 +23227 0.04400634765625 +23228 0.371978759765625 +23229 0.041046142578125 +23230 0.313140869140625 +23231 0.0318603515625 +23232 0.184417724609375 +23233 0.0146484375 +23234 0.011199951171875 +23235 -0.0074462890625 +23236 -0.171051025390625 +23237 -0.030029296875 +23238 -0.33740234375 +23239 -0.05010986328125 +23240 -0.47198486328125 +23241 -0.065826416015625 +23242 -0.560394287109375 +23243 -0.075469970703125 +23244 -0.58056640625 +23245 -0.07647705078125 +23246 -0.54754638671875 +23247 -0.07073974609375 +23248 -0.508575439453125 +23249 -0.064056396484375 +23250 -0.459503173828125 +23251 -0.0560302734375 +23252 -0.394378662109375 +23253 -0.04608154296875 +23254 -0.35260009765625 +23255 -0.03900146484375 +23256 -0.31170654296875 +23257 -0.0322265625 +23258 -0.197418212890625 +23259 -0.016937255859375 +23260 -0.007965087890625 +23261 0.006927490234375 +23262 0.207489013671875 +23263 0.033416748046875 +23264 0.409210205078125 +23265 0.057769775390625 +23266 0.57208251953125 +23267 0.07696533203125 +23268 0.66595458984375 +23269 0.087432861328125 +23270 0.65875244140625 +23271 0.08538818359375 +23272 0.56744384765625 +23273 0.072967529296875 +23274 0.431396484375 +23275 0.054962158203125 +23276 0.29443359375 +23277 0.0367431640625 +23278 0.182464599609375 +23279 0.021484375 +23280 0.06365966796875 +23281 0.005462646484375 +23282 -0.075958251953125 +23283 -0.012847900390625 +23284 -0.189422607421875 +23285 -0.027740478515625 +23286 -0.271942138671875 +23287 -0.038543701171875 +23288 -0.342529296875 +23289 -0.047515869140625 +23290 -0.364166259765625 +23291 -0.05023193359375 +23292 -0.327239990234375 +23293 -0.045562744140625 +23294 -0.2769775390625 +23295 -0.0389404296875 +23296 -0.253692626953125 +23297 -0.03497314453125 +23298 -0.24365234375 +23299 -0.03228759765625 +23300 -0.1983642578125 +23301 -0.0262451171875 +23302 -0.116241455078125 +23303 -0.016693115234375 +23304 -0.036834716796875 +23305 -0.00714111328125 +23306 0.034881591796875 +23307 0.00189208984375 +23308 0.09124755859375 +23309 0.009613037109375 +23310 0.10888671875 +23311 0.01385498046875 +23312 0.125518798828125 +23313 0.017791748046875 +23314 0.15771484375 +23315 0.02276611328125 +23316 0.17828369140625 +23317 0.026275634765625 +23318 0.17108154296875 +23319 0.02679443359375 +23320 0.129974365234375 +23321 0.023712158203125 +23322 0.082427978515625 +23323 0.019439697265625 +23324 0.027679443359375 +23325 0.013916015625 +23326 -0.065643310546875 +23327 0.00445556640625 +23328 -0.15936279296875 +23329 -0.005523681640625 +23330 -0.21307373046875 +23331 -0.012359619140625 +23332 -0.234649658203125 +23333 -0.016632080078125 +23334 -0.2001953125 +23335 -0.016082763671875 +23336 -0.119171142578125 +23337 -0.011444091796875 +23338 -0.024749755859375 +23339 -0.0054931640625 +23340 0.085784912109375 +23341 0.00213623046875 +23342 0.178131103515625 +23343 0.00848388671875 +23344 0.215576171875 +23345 0.010406494140625 +23346 0.211456298828125 +23347 0.0091552734375 +23348 0.17523193359375 +23349 0.005645751953125 +23350 0.128753662109375 +23351 0.00177001953125 +23352 0.1019287109375 +23353 0.000152587890625 +23354 0.0743408203125 +23355 -0.00103759765625 +23356 0.04327392578125 +23357 -0.00213623046875 +23358 0.038177490234375 +23359 -0.000640869140625 +23360 0.076263427734375 +23361 0.00482177734375 +23362 0.14105224609375 +23363 0.012664794921875 +23364 0.186431884765625 +23365 0.018707275390625 +23366 0.188812255859375 +23367 0.020782470703125 +23368 0.1390380859375 +23369 0.017974853515625 +23370 0.041778564453125 +23371 0.010650634765625 +23372 -0.079437255859375 +23373 0.00079345703125 +23374 -0.219390869140625 +23375 -0.011138916015625 +23376 -0.367828369140625 +23377 -0.024200439453125 +23378 -0.494873046875 +23379 -0.0357666015625 +23380 -0.556243896484375 +23381 -0.04193115234375 +23382 -0.508697509765625 +23383 -0.038848876953125 +23384 -0.3756103515625 +23385 -0.02850341796875 +23386 -0.218902587890625 +23387 -0.016265869140625 +23388 -0.063751220703125 +23389 -0.0042724609375 +23390 0.091552734375 +23391 0.007659912109375 +23392 0.23602294921875 +23393 0.018707275390625 +23394 0.342987060546875 +23395 0.026611328125 +23396 0.39520263671875 +23397 0.029937744140625 +23398 0.389373779296875 +23399 0.0284423828125 +23400 0.324249267578125 +23401 0.0220947265625 +23402 0.224090576171875 +23403 0.0130615234375 +23404 0.124267578125 +23405 0.004425048828125 +23406 0.037078857421875 +23407 -0.002716064453125 +23408 -0.010101318359375 +23409 -0.0059814453125 +23410 -0.019439697265625 +23411 -0.005645751953125 +23412 -0.022796630859375 +23413 -0.00457763671875 +23414 -0.001556396484375 +23415 -0.001220703125 +23416 0.056304931640625 +23417 0.005340576171875 +23418 0.106719970703125 +23419 0.01116943359375 +23420 0.096893310546875 +23421 0.011566162109375 +23422 0.042694091796875 +23423 0.007843017578125 +23424 -0.018035888671875 +23425 0.0032958984375 +23426 -0.07586669921875 +23427 -0.00128173828125 +23428 -0.11944580078125 +23429 -0.0048828125 +23430 -0.15972900390625 +23431 -0.00848388671875 +23432 -0.202606201171875 +23433 -0.0125732421875 +23434 -0.24859619140625 +23435 -0.01715087890625 +23436 -0.30517578125 +23437 -0.022857666015625 +23438 -0.36212158203125 +23439 -0.02874755859375 +23440 -0.39141845703125 +23441 -0.032318115234375 +23442 -0.35528564453125 +23443 -0.030181884765625 +23444 -0.249969482421875 +23445 -0.021942138671875 +23446 -0.092864990234375 +23447 -0.00909423828125 +23448 0.08905029296875 +23449 0.006011962890625 +23450 0.2352294921875 +23451 0.01806640625 +23452 0.318817138671875 +23453 0.0247802734375 +23454 0.358642578125 +23455 0.02783203125 +23456 0.347747802734375 +23457 0.026641845703125 +23458 0.28564453125 +23459 0.021148681640625 +23460 0.223175048828125 +23461 0.01580810546875 +23462 0.196746826171875 +23463 0.013824462890625 +23464 0.179840087890625 +23465 0.01287841796875 +23466 0.155548095703125 +23467 0.011444091796875 +23468 0.151214599609375 +23469 0.011871337890625 +23470 0.156951904296875 +23471 0.01324462890625 +23472 0.13177490234375 +23473 0.01190185546875 +23474 0.100799560546875 +23475 0.010009765625 +23476 0.087127685546875 +23477 0.009552001953125 +23478 0.05487060546875 +23479 0.007354736328125 +23480 -0.009002685546875 +23481 0.002227783203125 +23482 -0.10400390625 +23483 -0.005767822265625 +23484 -0.229400634765625 +23485 -0.0166015625 +23486 -0.35552978515625 +23487 -0.027679443359375 +23488 -0.441925048828125 +23489 -0.035430908203125 +23490 -0.473846435546875 +23491 -0.03857421875 +23492 -0.464813232421875 +23493 -0.038238525390625 +23494 -0.419097900390625 +23495 -0.0347900390625 +23496 -0.334320068359375 +23497 -0.027984619140625 +23498 -0.227935791015625 +23499 -0.019317626953125 +23500 -0.12347412109375 +23501 -0.01080322265625 +23502 -0.02764892578125 +23503 -0.003021240234375 +23504 0.077667236328125 +23505 0.005645751953125 +23506 0.2132568359375 +23507 0.017059326171875 +23508 0.38885498046875 +23509 0.0321044921875 +23510 0.582794189453125 +23511 0.04888916015625 +23512 0.734039306640625 +23513 0.062042236328125 +23514 0.800140380859375 +23515 0.06781005859375 +23516 0.7783203125 +23517 0.06597900390625 +23518 0.6651611328125 +23519 0.056243896484375 +23520 0.45965576171875 +23521 0.03851318359375 +23522 0.199188232421875 +23523 0.016082763671875 +23524 -0.050689697265625 +23525 -0.00531005859375 +23526 -0.23297119140625 +23527 -0.02069091796875 +23528 -0.33013916015625 +23529 -0.028564453125 +23530 -0.368408203125 +23531 -0.031280517578125 +23532 -0.378936767578125 +23533 -0.031585693359375 +23534 -0.376983642578125 +23535 -0.030914306640625 +23536 -0.37969970703125 +23537 -0.03076171875 +23538 -0.391510009765625 +23539 -0.03155517578125 +23540 -0.385345458984375 +23541 -0.030914306640625 +23542 -0.3419189453125 +23543 -0.02716064453125 +23544 -0.28289794921875 +23545 -0.02215576171875 +23546 -0.251617431640625 +23547 -0.01971435546875 +23548 -0.266143798828125 +23549 -0.021392822265625 +23550 -0.273345947265625 +23551 -0.02252197265625 +23552 -0.216796875 +23553 -0.018218994140625 +23554 -0.128265380859375 +23555 -0.010986328125 +23556 -0.068145751953125 +23557 -0.005096435546875 +23558 -0.0430908203125 +23559 -0.0010986328125 +23560 -0.024444580078125 +23561 0.002471923828125 +23562 0.020721435546875 +23563 0.007293701171875 +23564 0.124481201171875 +23565 0.0150146484375 +23566 0.25787353515625 +23567 0.023895263671875 +23568 0.379119873046875 +23569 0.03155517578125 +23570 0.47991943359375 +23571 0.0374755859375 +23572 0.5281982421875 +23573 0.039886474609375 +23574 0.511138916015625 +23575 0.0380859375 +23576 0.456207275390625 +23577 0.033660888671875 +23578 0.407470703125 +23579 0.0291748046875 +23580 0.383758544921875 +23581 0.025787353515625 +23582 0.35687255859375 +23583 0.022003173828125 +23584 0.31182861328125 +23585 0.01715087890625 +23586 0.250885009765625 +23587 0.011474609375 +23588 0.1654052734375 +23589 0.004638671875 +23590 0.035247802734375 +23591 -0.004364013671875 +23592 -0.142059326171875 +23593 -0.01556396484375 +23594 -0.33563232421875 +23595 -0.027191162109375 +23596 -0.5345458984375 +23597 -0.038604736328125 +23598 -0.72186279296875 +23599 -0.048828125 +23600 -0.836669921875 +23601 -0.054473876953125 +23602 -0.8326416015625 +23603 -0.05303955078125 +23604 -0.7296142578125 +23605 -0.045684814453125 +23606 -0.582550048828125 +23607 -0.03564453125 +23608 -0.440093994140625 +23609 -0.025726318359375 +23610 -0.324310302734375 +23611 -0.017303466796875 +23612 -0.20147705078125 +23613 -0.008544921875 +23614 -0.044647216796875 +23615 0.001922607421875 +23616 0.103973388671875 +23617 0.01165771484375 +23618 0.202392578125 +23619 0.018218994140625 +23620 0.264495849609375 +23621 0.022308349609375 +23622 0.338897705078125 +23623 0.02667236328125 +23624 0.443817138671875 +23625 0.032318115234375 +23626 0.545074462890625 +23627 0.037353515625 +23628 0.6173095703125 +23629 0.0404052734375 +23630 0.6524658203125 +23631 0.04107666015625 +23632 0.66339111328125 +23633 0.0401611328125 +23634 0.6561279296875 +23635 0.038116455078125 +23636 0.606781005859375 +23637 0.033660888671875 +23638 0.501190185546875 +23639 0.026092529296875 +23640 0.352783203125 +23641 0.01629638671875 +23642 0.176544189453125 +23643 0.005157470703125 +23644 -0.034820556640625 +23645 -0.00762939453125 +23646 -0.258209228515625 +23647 -0.020660400390625 +23648 -0.44244384765625 +23649 -0.031097412109375 +23650 -0.5753173828125 +23651 -0.03826904296875 +23652 -0.65203857421875 +23653 -0.04193115234375 +23654 -0.641632080078125 +23655 -0.0404052734375 +23656 -0.562164306640625 +23657 -0.0347900390625 +23658 -0.458038330078125 +23659 -0.02764892578125 +23660 -0.350555419921875 +23661 -0.020233154296875 +23662 -0.260528564453125 +23663 -0.013763427734375 +23664 -0.192108154296875 +23665 -0.008575439453125 +23666 -0.141937255859375 +23667 -0.0045166015625 +23668 -0.1021728515625 +23669 -0.001251220703125 +23670 -0.062896728515625 +23671 0.001708984375 +23672 -0.011932373046875 +23673 0.005035400390625 +23674 0.062835693359375 +23675 0.0093994140625 +23676 0.148712158203125 +23677 0.0140380859375 +23678 0.241729736328125 +23679 0.018768310546875 +23680 0.34912109375 +23681 0.024017333984375 +23682 0.457305908203125 +23683 0.02911376953125 +23684 0.54388427734375 +23685 0.0328369140625 +23686 0.5728759765625 +23687 0.033233642578125 +23688 0.506591796875 +23689 0.028289794921875 +23690 0.351226806640625 +23691 0.018402099609375 +23692 0.146514892578125 +23693 0.005859375 +23694 -0.05523681640625 +23695 -0.00634765625 +23696 -0.21624755859375 +23697 -0.01605224609375 +23698 -0.334930419921875 +23699 -0.02313232421875 +23700 -0.402984619140625 +23701 -0.027099609375 +23702 -0.4412841796875 +23703 -0.029083251953125 +23704 -0.49578857421875 +23705 -0.031707763671875 +23706 -0.5601806640625 +23707 -0.03466796875 +23708 -0.600738525390625 +23709 -0.036102294921875 +23710 -0.584228515625 +23711 -0.034210205078125 +23712 -0.47930908203125 +23713 -0.027313232421875 +23714 -0.27935791015625 +23715 -0.01507568359375 +23716 -0.0089111328125 +23717 0.00103759765625 +23718 0.268798828125 +23719 0.017425537109375 +23720 0.482818603515625 +23721 0.03009033203125 +23722 0.60369873046875 +23723 0.037353515625 +23724 0.650421142578125 +23725 0.04022216796875 +23726 0.66400146484375 +23727 0.041015625 +23728 0.6414794921875 +23729 0.039581298828125 +23730 0.572540283203125 +23731 0.03533935546875 +23732 0.498138427734375 +23733 0.0306396484375 +23734 0.439453125 +23735 0.026702880859375 +23736 0.375518798828125 +23737 0.022369384765625 +23738 0.274505615234375 +23739 0.01593017578125 +23740 0.1087646484375 +23741 0.005859375 +23742 -0.099395751953125 +23743 -0.00653076171875 +23744 -0.3182373046875 +23745 -0.0194091796875 +23746 -0.5489501953125 +23747 -0.032806396484375 +23748 -0.7738037109375 +23749 -0.045684814453125 +23750 -0.86383056640625 +23751 -0.055084228515625 +23752 -0.870391845703125 +23753 -0.059173583984375 +23754 -0.86895751953125 +23755 -0.058929443359375 +23756 -0.861053466796875 +23757 -0.05511474609375 +23758 -0.765869140625 +23759 -0.046783447265625 +23760 -0.5301513671875 +23761 -0.033355712890625 +23762 -0.214691162109375 +23763 -0.0152587890625 +23764 0.137359619140625 +23765 0.005035400390625 +23766 0.474822998046875 +23767 0.024658203125 +23768 0.76239013671875 +23769 0.04156494140625 +23770 0.867462158203125 +23771 0.05419921875 +23772 0.870361328125 +23773 0.062591552734375 +23774 0.86480712890625 +23775 0.066070556640625 +23776 0.831817626953125 +23777 0.06494140625 +23778 0.677581787109375 +23779 0.060577392578125 +23780 0.495880126953125 +23781 0.053314208984375 +23782 0.30767822265625 +23783 0.044219970703125 +23784 0.116180419921875 +23785 0.033447265625 +23786 -0.110748291015625 +23787 0.01922607421875 +23788 -0.381805419921875 +23789 0.001190185546875 +23790 -0.6572265625 +23791 -0.0181884765625 +23792 -0.857421875 +23793 -0.0355224609375 +23794 -0.870391845703125 +23795 -0.04840087890625 +23796 -0.870391845703125 +23797 -0.056427001953125 +23798 -0.86444091796875 +23799 -0.061126708984375 +23800 -0.85723876953125 +23801 -0.064483642578125 +23802 -0.790008544921875 +23803 -0.065460205078125 +23804 -0.62847900390625 +23805 -0.061065673828125 +23806 -0.3956298828125 +23807 -0.05108642578125 +23808 -0.126708984375 +23809 -0.037445068359375 +23810 0.150115966796875 +23811 -0.02166748046875 +23812 0.424041748046875 +23813 -0.0047607421875 +23814 0.670623779296875 +23815 0.011962890625 +23816 0.854522705078125 +23817 0.0269775390625 +23818 0.866485595703125 +23819 0.03936767578125 +23820 0.86920166015625 +23821 0.04840087890625 +23822 0.8653564453125 +23823 0.054229736328125 +23824 0.857147216796875 +23825 0.05706787109375 +23826 0.766845703125 +23827 0.056793212890625 +23828 0.628509521484375 +23829 0.05364990234375 +23830 0.462127685546875 +23831 0.047637939453125 +23832 0.297210693359375 +23833 0.039642333984375 +23834 0.14862060546875 +23835 0.03033447265625 +23836 -0.00537109375 +23837 0.01959228515625 +23838 -0.15753173828125 +23839 0.00799560546875 +23840 -0.31304931640625 +23841 -0.004058837890625 +23842 -0.48876953125 +23843 -0.016510009765625 +23844 -0.6416015625 +23845 -0.02789306640625 +23846 -0.751373291015625 +23847 -0.03729248046875 +23848 -0.84619140625 +23849 -0.0450439453125 +23850 -0.861297607421875 +23851 -0.0506591796875 +23852 -0.863250732421875 +23853 -0.053314208984375 +23854 -0.856597900390625 +23855 -0.052276611328125 +23856 -0.7498779296875 +23857 -0.047943115234375 +23858 -0.624542236328125 +23859 -0.04193115234375 +23860 -0.47808837890625 +23861 -0.034027099609375 +23862 -0.253387451171875 +23863 -0.023101806640625 +23864 0.003692626953125 +23865 -0.0106201171875 +23866 0.2257080078125 +23867 0.00140380859375 +23868 0.427154541015625 +23869 0.012939453125 +23870 0.643218994140625 +23871 0.02447509765625 +23872 0.855926513671875 +23873 0.035491943359375 +23874 0.870361328125 +23875 0.04443359375 +23876 0.870361328125 +23877 0.050018310546875 +23878 0.862762451171875 +23879 0.0523681640625 +23880 0.79669189453125 +23881 0.05145263671875 +23882 0.595794677734375 +23883 0.047119140625 +23884 0.362152099609375 +23885 0.040191650390625 +23886 0.1270751953125 +23887 0.031524658203125 +23888 -0.086944580078125 +23889 0.021881103515625 +23890 -0.2784423828125 +23891 0.011627197265625 +23892 -0.484832763671875 +23893 0.000213623046875 +23894 -0.729583740234375 +23895 -0.012542724609375 +23896 -0.86688232421875 +23897 -0.02520751953125 +23898 -0.870391845703125 +23899 -0.0360107421875 +23900 -0.86859130859375 +23901 -0.04461669921875 +23902 -0.86279296875 +23903 -0.0509033203125 +23904 -0.817962646484375 +23905 -0.053955078125 +23906 -0.6116943359375 +23907 -0.05267333984375 +23908 -0.3128662109375 +23909 -0.0469970703125 +23910 0.039398193359375 +23911 -0.037811279296875 +23912 0.422821044921875 +23913 -0.0257568359375 +23914 0.805145263671875 +23915 -0.0118408203125 +23916 0.870361328125 +23917 0.002044677734375 +23918 0.870361328125 +23919 0.014312744140625 +23920 0.860015869140625 +23921 0.02447509765625 +23922 0.727935791015625 +23923 0.03216552734375 +23924 0.48114013671875 +23925 0.03704833984375 +23926 0.2059326171875 +23927 0.039520263671875 +23928 -0.06103515625 +23929 0.0400390625 +23930 -0.29913330078125 +23931 0.038818359375 +23932 -0.516204833984375 +23933 0.03546142578125 +23934 -0.7252197265625 +23935 0.0296630859375 +23936 -0.85980224609375 +23937 0.0220947265625 +23938 -0.870391845703125 +23939 0.013702392578125 +23940 -0.870391845703125 +23941 0.005340576171875 +23942 -0.858062744140625 +23943 -0.00164794921875 +23944 -0.673004150390625 +23945 -0.006988525390625 +23946 -0.42694091796875 +23947 -0.011749267578125 +23948 -0.2100830078125 +23949 -0.01678466796875 +23950 -0.0362548828125 +23951 -0.021881103515625 +23952 0.10943603515625 +23953 -0.0262451171875 +23954 0.23516845703125 +23955 -0.02923583984375 +23956 0.373687744140625 +23957 -0.029815673828125 +23958 0.517791748046875 +23959 -0.02801513671875 +23960 0.602783203125 +23961 -0.02532958984375 +23962 0.635711669921875 +23963 -0.021697998046875 +23964 0.655181884765625 +23965 -0.01641845703125 +23966 0.65948486328125 +23967 -0.009857177734375 +23968 0.651275634765625 +23969 -0.00238037109375 +23970 0.61846923828125 +23971 0.005218505859375 +23972 0.53753662109375 +23973 0.011932373046875 +23974 0.404144287109375 +23975 0.017181396484375 +23976 0.22186279296875 +23977 0.020599365234375 +23978 0.003997802734375 +23979 0.02215576171875 +23980 -0.22100830078125 +23981 0.02215576171875 +23982 -0.42449951171875 +23983 0.021026611328125 +23984 -0.579833984375 +23985 0.019256591796875 +23986 -0.641876220703125 +23987 0.01788330078125 +23988 -0.6177978515625 +23989 0.016754150390625 +23990 -0.575531005859375 +23991 0.014373779296875 +23992 -0.526336669921875 +23993 0.010711669921875 +23994 -0.42645263671875 +23995 0.007110595703125 +23996 -0.2581787109375 +23997 0.004364013671875 +23998 -0.068695068359375 +23999 0.001739501953125 +24000 0.09222412109375 +24001 -0.00152587890625 +24002 0.232147216796875 +24003 -0.004852294921875 +24004 0.3509521484375 +24005 -0.007904052734375 +24006 0.410064697265625 +24007 -0.01129150390625 +24008 0.372955322265625 +24009 -0.015655517578125 +24010 0.2554931640625 +24011 -0.020477294921875 +24012 0.10711669921875 +24013 -0.02447509765625 +24014 -0.052886962890625 +24015 -0.027191162109375 +24016 -0.186279296875 +24017 -0.02783203125 +24018 -0.23291015625 +24019 -0.025146484375 +24020 -0.209442138671875 +24021 -0.019805908203125 +24022 -0.174163818359375 +24023 -0.01348876953125 +24024 -0.126739501953125 +24025 -0.006500244140625 +24026 -0.048126220703125 +24027 0.001220703125 +24028 0.0426025390625 +24029 0.0089111328125 +24030 0.10748291015625 +24031 0.015380859375 +24032 0.1409912109375 +24033 0.020233154296875 +24034 0.19708251953125 +24035 0.02459716796875 +24036 0.273651123046875 +24037 0.02825927734375 +24038 0.31768798828125 +24039 0.029876708984375 +24040 0.341094970703125 +24041 0.029754638671875 +24042 0.368011474609375 +24043 0.028564453125 +24044 0.37249755859375 +24045 0.02581787109375 +24046 0.30072021484375 +24047 0.020416259765625 +24048 0.1517333984375 +24049 0.0125732421875 +24050 -0.01470947265625 +24051 0.003936767578125 +24052 -0.1883544921875 +24053 -0.00494384765625 +24054 -0.372711181640625 +24055 -0.013885498046875 +24056 -0.51397705078125 +24057 -0.0213623046875 +24058 -0.57177734375 +24059 -0.02618408203125 +24060 -0.53948974609375 +24061 -0.028045654296875 +24062 -0.43511962890625 +24063 -0.027252197265625 +24064 -0.2962646484375 +24065 -0.024932861328125 +24066 -0.161102294921875 +24067 -0.0220947265625 +24068 -0.0435791015625 +24069 -0.0189208984375 +24070 0.060394287109375 +24071 -0.01531982421875 +24072 0.13665771484375 +24073 -0.01129150390625 +24074 0.170135498046875 +24075 -0.006866455078125 +24076 0.16552734375 +24077 -0.002197265625 +24078 0.15728759765625 +24079 0.002471923828125 +24080 0.150787353515625 +24081 0.0069580078125 +24082 0.12200927734375 +24083 0.01104736328125 +24084 0.080108642578125 +24085 0.014556884765625 +24086 0.05126953125 +24087 0.017303466796875 +24088 0.062896728515625 +24089 0.019134521484375 +24090 0.09271240234375 +24091 0.019989013671875 +24092 0.092987060546875 +24093 0.019805908203125 +24094 0.07855224609375 +24095 0.01861572265625 +24096 0.06427001953125 +24097 0.0164794921875 +24098 0.0347900390625 +24099 0.01348876953125 +24100 -0.01171875 +24101 0.009857177734375 +24102 -0.056060791015625 +24103 0.00579833984375 +24104 -0.055511474609375 +24105 0.001495361328125 +24106 -0.010467529296875 +24107 -0.00274658203125 +24108 0.02508544921875 +24109 -0.006683349609375 +24110 0.025665283203125 +24111 -0.010101318359375 +24112 0.017333984375 +24113 -0.012847900390625 +24114 0.00189208984375 +24115 -0.0147705078125 +24116 -0.03173828125 +24117 -0.01580810546875 +24118 -0.071502685546875 +24119 -0.01593017578125 +24120 -0.13543701171875 +24121 -0.01513671875 +24122 -0.219970703125 +24123 -0.013519287109375 +24124 -0.300506591796875 +24125 -0.01116943359375 +24126 -0.376312255859375 +24127 -0.00823974609375 +24128 -0.416107177734375 +24129 -0.004913330078125 +24130 -0.371124267578125 +24131 -0.001373291015625 +24132 -0.242279052734375 +24133 0.00213623046875 +24134 -0.069732666015625 +24135 0.00543212890625 +24136 0.125640869140625 +24137 0.008331298828125 +24138 0.31268310546875 +24139 0.01068115234375 +24140 0.45501708984375 +24141 0.01239013671875 +24142 0.554779052734375 +24143 0.01336669921875 +24144 0.61065673828125 +24145 0.013580322265625 +24146 0.610931396484375 +24147 0.0130615234375 +24148 0.531463623046875 +24149 0.0118408203125 +24150 0.3883056640625 +24151 0.010009765625 +24152 0.23468017578125 +24153 0.0076904296875 +24154 0.095245361328125 +24155 0.0050048828125 +24156 -0.00396728515625 +24157 0.00213623046875 +24158 -0.04852294921875 +24159 -0.000732421875 +24160 -0.055145263671875 +24161 -0.003448486328125 +24162 -0.0758056640625 +24163 -0.005859375 +24164 -0.138702392578125 +24165 -0.007843017578125 +24166 -0.209197998046875 +24167 -0.009307861328125 +24168 -0.289031982421875 +24169 -0.01019287109375 +24170 -0.37884521484375 +24171 -0.010467529296875 +24172 -0.456329345703125 +24173 -0.0101318359375 +24174 -0.51641845703125 +24175 -0.00921630859375 +24176 -0.519287109375 +24177 -0.007781982421875 +24178 -0.458251953125 +24179 -0.00592041015625 +24180 -0.384796142578125 +24181 -0.003753662109375 +24182 -0.323699951171875 +24183 -0.00140380859375 +24184 -0.269287109375 +24185 0.000946044921875 +24186 -0.1951904296875 +24187 0.003173828125 +24188 -0.100006103515625 +24189 0.005157470703125 +24190 -0.01055908203125 +24191 0.006805419921875 +24192 0.1033935546875 +24193 0.008026123046875 +24194 0.24908447265625 +24195 0.0087890625 +24196 0.373199462890625 +24197 0.009063720703125 +24198 0.45806884765625 +24199 0.00885009765625 +24200 0.511474609375 +24201 0.008148193359375 +24202 0.565399169921875 +24203 0.00701904296875 +24204 0.61138916015625 +24205 0.00555419921875 +24206 0.5897216796875 +24207 0.003814697265625 +24208 0.4906005859375 +24209 0.001922607421875 +24210 0.33148193359375 +24211 0.0 +24212 0.147796630859375 +24213 -0.0018310546875 +24214 -0.01873779296875 +24215 -0.00347900390625 +24216 -0.140289306640625 +24217 -0.004852294921875 +24218 -0.191986083984375 +24219 -0.005889892578125 +24220 -0.184295654296875 +24221 -0.006561279296875 +24222 -0.161834716796875 +24223 -0.0068359375 +24224 -0.166595458984375 +24225 -0.0067138671875 +24226 -0.19390869140625 +24227 -0.006195068359375 +24228 -0.22442626953125 +24229 -0.00531005859375 +24230 -0.279754638671875 +24231 -0.004119873046875 +24232 -0.3389892578125 +24233 -0.002716064453125 +24234 -0.3543701171875 +24235 -0.00115966796875 +24236 -0.348175048828125 +24237 0.00042724609375 +24238 -0.32598876953125 +24239 0.001953125 +24240 -0.2581787109375 +24241 0.003326416015625 +24242 -0.139801025390625 +24243 0.004486083984375 +24244 0.014617919921875 +24245 0.00537109375 +24246 0.144378662109375 +24247 0.005950927734375 +24248 0.221038818359375 +24249 0.006195068359375 +24250 0.27069091796875 +24251 0.006103515625 +24252 0.294036865234375 +24253 0.00567626953125 +24254 0.311767578125 +24255 0.00494384765625 +24256 0.339141845703125 +24257 0.003997802734375 +24258 0.360260009765625 +24259 0.00299072265625 +24260 0.360504150390625 +24261 0.001953125 +24262 0.308380126953125 +24263 0.00067138671875 +24264 0.18170166015625 +24265 -0.001007080078125 +24266 0.0047607421875 +24267 -0.002838134765625 +24268 -0.17559814453125 +24269 -0.00445556640625 +24270 -0.3143310546875 +24271 -0.00555419921875 +24272 -0.36785888671875 +24273 -0.00579833984375 +24274 -0.36248779296875 +24275 -0.00543212890625 +24276 -0.343536376953125 +24277 -0.00482177734375 +24278 -0.3018798828125 +24279 -0.00390625 +24280 -0.231414794921875 +24281 -0.002685546875 +24282 -0.117645263671875 +24283 -0.001129150390625 +24284 0.007049560546875 +24285 0.00048828125 +24286 0.087982177734375 +24287 0.001708984375 +24288 0.13946533203125 +24289 0.002593994140625 +24290 0.17425537109375 +24291 0.003265380859375 +24292 0.188201904296875 +24293 0.003662109375 +24294 0.171234130859375 +24295 0.003692626953125 +24296 0.118438720703125 +24297 0.003326416015625 +24298 0.05706787109375 +24299 0.002777099609375 +24300 -0.010711669921875 +24301 0.002105712890625 +24302 -0.0914306640625 +24303 0.001220703125 +24304 -0.162322998046875 +24305 0.000335693359375 +24306 -0.194549560546875 +24307 -0.000274658203125 +24308 -0.1492919921875 +24309 -0.00030517578125 +24310 -0.02166748046875 +24311 0.000274658203125 +24312 0.124053955078125 +24313 0.0009765625 +24314 0.211151123046875 +24315 0.001190185546875 +24316 0.240447998046875 +24317 0.0009765625 +24318 0.242218017578125 +24319 0.0006103515625 +24320 0.2257080078125 +24321 0.000732421875 +24322 0.194366455078125 +24323 0.001068115234375 +24324 0.115509033203125 +24325 -0.00030517578125 +24326 0.0128173828125 +24327 -0.00250244140625 +24328 -0.053802490234375 +24329 -0.00323486328125 +24330 -0.110626220703125 +24331 -0.003631591796875 +24332 -0.199493408203125 +24333 -0.005462646484375 +24334 -0.29437255859375 +24335 -0.00775146484375 +24336 -0.33221435546875 +24337 -0.008026123046875 +24338 -0.27972412109375 +24339 -0.0050048828125 +24340 -0.185333251953125 +24341 -0.00067138671875 +24342 -0.128204345703125 +24343 0.00177001953125 +24344 -0.115692138671875 +24345 0.002044677734375 +24346 -0.116455078125 +24347 0.001434326171875 +24348 -0.105926513671875 +24349 0.0009765625 +24350 -0.053955078125 +24351 0.001922607421875 +24352 0.048797607421875 +24353 0.00469970703125 +24354 0.157318115234375 +24355 0.00762939453125 +24356 0.212005615234375 +24357 0.00836181640625 +24358 0.218475341796875 +24359 0.007232666015625 +24360 0.23724365234375 +24361 0.0067138671875 +24362 0.30535888671875 +24363 0.00836181640625 +24364 0.38128662109375 +24365 0.010528564453125 +24366 0.404449462890625 +24367 0.010833740234375 +24368 0.3944091796875 +24369 0.0101318359375 +24370 0.3885498046875 +24371 0.009918212890625 +24372 0.362640380859375 +24373 0.00921630859375 +24374 0.27362060546875 +24375 0.00628662109375 +24376 0.11712646484375 +24377 0.00091552734375 +24378 -0.054901123046875 +24379 -0.004852294921875 +24380 -0.19085693359375 +24381 -0.009033203125 +24382 -0.28570556640625 +24383 -0.011505126953125 +24384 -0.339263916015625 +24385 -0.0123291015625 +24386 -0.3775634765625 +24387 -0.01263427734375 +24388 -0.445709228515625 +24389 -0.014251708984375 +24390 -0.535064697265625 +24391 -0.01690673828125 +24392 -0.629058837890625 +24393 -0.019989013671875 +24394 -0.697601318359375 +24395 -0.022308349609375 +24396 -0.70391845703125 +24397 -0.02239990234375 +24398 -0.6424560546875 +24399 -0.020050048828125 +24400 -0.491241455078125 +24401 -0.014404296875 +24402 -0.265716552734375 +24403 -0.00604248046875 +24404 -0.023712158203125 +24405 0.00274658203125 +24406 0.201751708984375 +24407 0.01068115234375 +24408 0.375823974609375 +24409 0.01641845703125 +24410 0.485076904296875 +24411 0.01953125 +24412 0.56884765625 +24413 0.021636962890625 +24414 0.634765625 +24415 0.02313232421875 +24416 0.63763427734375 +24417 0.022247314453125 +24418 0.5660400390625 +24419 0.01861572265625 +24420 0.4720458984375 +24421 0.01434326171875 +24422 0.40692138671875 +24423 0.011474609375 +24424 0.3778076171875 +24425 0.01031494140625 +24426 0.376953125 +24427 0.01055908203125 +24428 0.371978759765625 +24429 0.0108642578125 +24430 0.313140869140625 +24431 0.009185791015625 +24432 0.184417724609375 +24433 0.004852294921875 +24434 0.011199951171875 +24435 -0.001129150390625 +24436 -0.171051025390625 +24437 -0.007354736328125 +24438 -0.33740234375 +24439 -0.012908935546875 +24440 -0.47198486328125 +24441 -0.0172119140625 +24442 -0.560394287109375 +24443 -0.019744873046875 +24444 -0.58056640625 +24445 -0.01971435546875 +24446 -0.54754638671875 +24447 -0.01776123046875 +24448 -0.508575439453125 +24449 -0.01580810546875 +24450 -0.459503173828125 +24451 -0.013671875 +24452 -0.394378662109375 +24453 -0.0111083984375 +24454 -0.35260009765625 +24455 -0.009674072265625 +24456 -0.31170654296875 +24457 -0.008453369140625 +24458 -0.197418212890625 +24459 -0.00445556640625 +24460 -0.007965087890625 +24461 0.00238037109375 +24462 0.207489013671875 +24463 0.010101318359375 +24464 0.409210205078125 +24465 0.017181396484375 +24466 0.57208251953125 +24467 0.022674560546875 +24468 0.66595458984375 +24469 0.02545166015625 +24470 0.65875244140625 +24471 0.024261474609375 +24472 0.56744384765625 +24473 0.019866943359375 +24474 0.431396484375 +24475 0.01385498046875 +24476 0.29443359375 +24477 0.008026123046875 +24478 0.182464599609375 +24479 0.00341796875 +24480 0.06365966796875 +24481 -0.001220703125 +24482 -0.075958251953125 +24483 -0.0064697265625 +24484 -0.189422607421875 +24485 -0.01043701171875 +24486 -0.271942138671875 +24487 -0.012969970703125 +24488 -0.342529296875 +24489 -0.014862060546875 +24490 -0.364166259765625 +24491 -0.0147705078125 +24492 -0.327239990234375 +24493 -0.0123291015625 +24494 -0.2769775390625 +24495 -0.0093994140625 +24496 -0.253692626953125 +24497 -0.00762939453125 +24498 -0.24365234375 +24499 -0.00653076171875 +24500 -0.1983642578125 +24501 -0.004180908203125 +24502 -0.116241455078125 +24503 -0.00054931640625 +24504 -0.036834716796875 +24505 0.00274658203125 +24506 0.034881591796875 +24507 0.0054931640625 +24508 0.09124755859375 +24509 0.00738525390625 +24510 0.10888671875 +24511 0.007537841796875 +24512 0.125518798828125 +24513 0.007476806640625 +24514 0.15771484375 +24515 0.0079345703125 +24516 0.17828369140625 +24517 0.007843017578125 +24518 0.17108154296875 +24519 0.006622314453125 +24520 0.129974365234375 +24521 0.00408935546875 +24522 0.082427978515625 +24523 0.001373291015625 +24524 0.027679443359375 +24525 -0.00146484375 +24526 -0.065643310546875 +24527 -0.005615234375 +24528 -0.15936279296875 +24529 -0.009552001953125 +24530 -0.21307373046875 +24531 -0.01165771484375 +24532 -0.234649658203125 +24533 -0.012298583984375 +24534 -0.2001953125 +24535 -0.010528564453125 +24536 -0.119171142578125 +24537 -0.006744384765625 +24538 -0.024749755859375 +24539 -0.0023193359375 +24540 0.085784912109375 +24541 0.0028076171875 +24542 0.178131103515625 +24543 0.0072021484375 +24544 0.215576171875 +24545 0.009368896484375 +24546 0.211456298828125 +24547 0.009796142578125 +24548 0.17523193359375 +24549 0.008880615234375 +24550 0.128753662109375 +24551 0.0074462890625 +24552 0.1019287109375 +24553 0.00665283203125 +24554 0.0743408203125 +24555 0.005706787109375 +24556 0.04327392578125 +24557 0.004486083984375 +24558 0.038177490234375 +24559 0.004150390625 +24560 0.076263427734375 +24561 0.00537109375 +24562 0.14105224609375 +24563 0.00750732421875 +24564 0.186431884765625 +24565 0.008758544921875 +24566 0.188812255859375 +24567 0.00823974609375 +24568 0.1390380859375 +24569 0.005615234375 +24570 0.041778564453125 +24571 0.0010986328125 +24572 -0.079437255859375 +24573 -0.004302978515625 +24574 -0.219390869140625 +24575 -0.010345458984375 +24576 -0.367828369140625 +24577 -0.01690673828125 +24578 -0.494873046875 +24579 -0.023223876953125 +24580 -0.556243896484375 +24581 -0.026580810546875 +24582 -0.508697509765625 +24583 -0.023590087890625 +24584 -0.3756103515625 +24585 -0.015655517578125 +24586 -0.218902587890625 +24587 -0.006927490234375 +24588 -0.063751220703125 +24589 0.001068115234375 +24590 0.091552734375 +24591 0.0087890625 +24592 0.23602294921875 +24593 0.01568603515625 +24594 0.342987060546875 +24595 0.020111083984375 +24596 0.39520263671875 +24597 0.021026611328125 +24598 0.389373779296875 +24599 0.018341064453125 +24600 0.324249267578125 +24601 0.0120849609375 +24602 0.224090576171875 +24603 0.00408935546875 +24604 0.124267578125 +24605 -0.003082275390625 +24606 0.037078857421875 +24607 -0.00860595703125 +24608 -0.010101318359375 +24609 -0.010589599609375 +24610 -0.019439697265625 +24611 -0.009307861328125 +24612 -0.022796630859375 +24613 -0.007171630859375 +24614 -0.001556396484375 +24615 -0.00299072265625 +24616 0.056304931640625 +24617 0.003875732421875 +24618 0.106719970703125 +24619 0.0101318359375 +24620 0.096893310546875 +24621 0.0118408203125 +24622 0.042694091796875 +24623 0.010040283203125 +24624 -0.018035888671875 +24625 0.00732421875 +24626 -0.07586669921875 +24627 0.0042724609375 +24628 -0.11944580078125 +24629 0.001708984375 +24630 -0.15972900390625 +24631 -0.00115966796875 +24632 -0.202606201171875 +24633 -0.004730224609375 +24634 -0.24859619140625 +24635 -0.009002685546875 +24636 -0.30517578125 +24637 -0.014434814453125 +24638 -0.36212158203125 +24639 -0.020233154296875 +24640 -0.39141845703125 +24641 -0.0242919921875 +24642 -0.35528564453125 +24643 -0.023773193359375 +24644 -0.249969482421875 +24645 -0.018280029296875 +24646 -0.092864990234375 +24647 -0.00897216796875 +24648 0.08905029296875 +24649 0.002288818359375 +24650 0.2352294921875 +24651 0.011260986328125 +24652 0.318817138671875 +24653 0.016082763671875 +24654 0.358642578125 +24655 0.018157958984375 +24656 0.347747802734375 +24657 0.01702880859375 +24658 0.28564453125 +24659 0.012664794921875 +24660 0.223175048828125 +24661 0.00872802734375 +24662 0.196746826171875 +24663 0.00775146484375 +24664 0.179840087890625 +24665 0.007781982421875 +24666 0.155548095703125 +24667 0.007537841796875 +24668 0.151214599609375 +24669 0.008880615234375 +24670 0.156951904296875 +24671 0.011016845703125 +24672 0.13177490234375 +24673 0.010894775390625 +24674 0.100799560546875 +24675 0.01025390625 +24676 0.087127685546875 +24677 0.010650634765625 +24678 0.05487060546875 +24679 0.00946044921875 +24680 -0.009002685546875 +24681 0.005645751953125 +24682 -0.10400390625 +24683 -0.000732421875 +24684 -0.229400634765625 +24685 -0.0096435546875 +24686 -0.35552978515625 +24687 -0.018951416015625 +24688 -0.441925048828125 +24689 -0.025726318359375 +24690 -0.473846435546875 +24691 -0.028900146484375 +24692 -0.464813232421875 +24693 -0.02935791015625 +24694 -0.419097900390625 +24695 -0.02734375 +24696 -0.334320068359375 +24697 -0.0225830078125 +24698 -0.227935791015625 +24699 -0.01629638671875 +24700 -0.12347412109375 +24701 -0.010101318359375 +24702 -0.02764892578125 +24703 -0.00439453125 +24704 0.077667236328125 +24705 0.002166748046875 +24706 0.2132568359375 +24707 0.0111083984375 +24708 0.38885498046875 +24709 0.023193359375 +24710 0.582794189453125 +24711 0.036865234375 +24712 0.734039306640625 +24713 0.047760009765625 +24714 0.800140380859375 +24715 0.052764892578125 +24716 0.7783203125 +24717 0.05169677734375 +24718 0.6651611328125 +24719 0.044281005859375 +24720 0.45965576171875 +24721 0.0303955078125 +24722 0.199188232421875 +24723 0.0126953125 +24724 -0.050689697265625 +24725 -0.004150390625 +24726 -0.23297119140625 +24727 -0.01611328125 +24728 -0.33013916015625 +24729 -0.022003173828125 +24730 -0.368408203125 +24731 -0.02374267578125 +24732 -0.378936767578125 +24733 -0.02362060546875 +24734 -0.376983642578125 +24735 -0.0228271484375 +24736 -0.37969970703125 +24737 -0.022613525390625 +24738 -0.391510009765625 +24739 -0.0233154296875 +24740 -0.385345458984375 +24741 -0.02294921875 +24742 -0.3419189453125 +24743 -0.020111083984375 +24744 -0.28289794921875 +24745 -0.016357421875 +24746 -0.251617431640625 +24747 -0.014801025390625 +24748 -0.266143798828125 +24749 -0.01666259765625 +24750 -0.273345947265625 +24751 -0.01806640625 +24752 -0.216796875 +24753 -0.014923095703125 +24754 -0.128265380859375 +24755 -0.00946044921875 +24756 -0.068145751953125 +24757 -0.005950927734375 +24758 -0.0430908203125 +24759 -0.00482177734375 +24760 -0.024444580078125 +24761 -0.003997802734375 +24762 0.020721435546875 +24763 -0.0010986328125 +24764 0.124481201171875 +24765 0.00616455078125 +24766 0.25787353515625 +24767 0.015716552734375 +24768 0.379119873046875 +24769 0.024566650390625 +24770 0.47991943359375 +24771 0.0321044921875 +24772 0.5281982421875 +24773 0.035980224609375 +24774 0.511138916015625 +24775 0.035247802734375 +24776 0.456207275390625 +24777 0.031829833984375 +24778 0.407470703125 +24779 0.02886962890625 +24780 0.383758544921875 +24781 0.0277099609375 +24782 0.35687255859375 +24783 0.026275634765625 +24784 0.31182861328125 +24785 0.023468017578125 +24786 0.250885009765625 +24787 0.019439697265625 +24788 0.1654052734375 +24789 0.0135498046875 +24790 0.035247802734375 +24791 0.004364013671875 +24792 -0.142059326171875 +24793 -0.008270263671875 +24794 -0.33563232421875 +24795 -0.022125244140625 +24796 -0.5345458984375 +24797 -0.03643798828125 +24798 -0.72186279296875 +24799 -0.04998779296875 +24800 -0.836669921875 +24801 -0.058380126953125 +24802 -0.8326416015625 +24803 -0.05828857421875 +24804 -0.7296142578125 +24805 -0.051116943359375 +24806 -0.582550048828125 +24807 -0.040863037109375 +24808 -0.440093994140625 +24809 -0.030975341796875 +24810 -0.324310302734375 +24811 -0.02301025390625 +24812 -0.20147705078125 +24813 -0.014495849609375 +24814 -0.044647216796875 +24815 -0.00347900390625 +24816 0.103973388671875 +24817 0.0069580078125 +24818 0.202392578125 +24819 0.0137939453125 +24820 0.264495849609375 +24821 0.01806640625 +24822 0.338897705078125 +24823 0.023284912109375 +24824 0.443817138671875 +24825 0.03076171875 +24826 0.545074462890625 +24827 0.03802490234375 +24828 0.6173095703125 +24829 0.04327392578125 +24830 0.6524658203125 +24831 0.0458984375 +24832 0.66339111328125 +24833 0.04718017578125 +24834 0.6561279296875 +24835 0.047698974609375 +24836 0.606781005859375 +24837 0.045074462890625 +24838 0.501190185546875 +24839 0.03765869140625 +24840 0.352783203125 +24841 0.026611328125 +24842 0.176544189453125 +24843 0.01324462890625 +24844 -0.034820556640625 +24845 -0.00347900390625 +24846 -0.258209228515625 +24847 -0.021453857421875 +24848 -0.44244384765625 +24849 -0.035675048828125 +24850 -0.5753173828125 +24851 -0.045166015625 +24852 -0.65203857421875 +24853 -0.049652099609375 +24854 -0.641632080078125 +24855 -0.046112060546875 +24856 -0.562164306640625 +24857 -0.03656005859375 +24858 -0.458038330078125 +24859 -0.025665283203125 +24860 -0.350555419921875 +24861 -0.015625 +24862 -0.260528564453125 +24863 -0.00848388671875 +24864 -0.192108154296875 +24865 -0.0045166015625 +24866 -0.141937255859375 +24867 -0.003173828125 +24868 -0.1021728515625 +24869 -0.00341796875 +24870 -0.062896728515625 +24871 -0.003936767578125 +24872 -0.011932373046875 +24873 -0.003204345703125 +24874 0.062835693359375 +24875 0.000244140625 +24876 0.148712158203125 +24877 0.005340576171875 +24878 0.241729736328125 +24879 0.0118408203125 +24880 0.34912109375 +24881 0.020660400390625 +24882 0.457305908203125 +24883 0.030487060546875 +24884 0.54388427734375 +24885 0.0390625 +24886 0.5728759765625 +24887 0.042633056640625 +24888 0.506591796875 +24889 0.037200927734375 +24890 0.351226806640625 +24891 0.0233154296875 +24892 0.146514892578125 +24893 0.00494384765625 +24894 -0.05523681640625 +24895 -0.012603759765625 +24896 -0.21624755859375 +24897 -0.025604248046875 +24898 -0.334930419921875 +24899 -0.03411865234375 +24900 -0.402984619140625 +24901 -0.0374755859375 +24902 -0.4412841796875 +24903 -0.03802490234375 +24904 -0.49578857421875 +24905 -0.040771484375 +24906 -0.5601806640625 +24907 -0.045196533203125 +24908 -0.600738525390625 +24909 -0.047882080078125 +24910 -0.584228515625 +24911 -0.045440673828125 +24912 -0.47930908203125 +24913 -0.03466796875 +24914 -0.27935791015625 +24915 -0.014801025390625 +24916 -0.0089111328125 +24917 0.011627197265625 +24918 0.268798828125 +24919 0.038177490234375 +24920 0.482818603515625 +24921 0.057586669921875 +24922 0.60369873046875 +24923 0.066986083984375 +24924 0.650421142578125 +24925 0.068511962890625 +24926 0.66400146484375 +24927 0.066650390625 +24928 0.6414794921875 +24929 0.061279296875 +24930 0.572540283203125 +24931 0.051483154296875 +24932 0.498138427734375 +24933 0.0416259765625 +24934 0.439453125 +24935 0.034027099609375 +24936 0.375518798828125 +24937 0.026580810546875 +24938 0.274505615234375 +24939 0.0159912109375 +24940 0.1087646484375 +24941 -0.0006103515625 +24942 -0.099395751953125 +24943 -0.020965576171875 +24944 -0.3182373046875 +24945 -0.041839599609375 +24946 -0.5489501953125 +24947 -0.0634765625 +24948 -0.7738037109375 +24949 -0.08416748046875 +24950 -0.86383056640625 +24951 -0.09857177734375 +24952 -0.870391845703125 +24953 -0.1033935546875 +24954 -0.86895751953125 +24955 -0.10064697265625 +24956 -0.861053466796875 +24957 -0.091827392578125 +24958 -0.765869140625 +24959 -0.075286865234375 +24960 -0.5301513671875 +24961 -0.049957275390625 +24962 -0.214691162109375 +24963 -0.0166015625 +24964 0.137359619140625 +24965 0.020233154296875 +24966 0.474822998046875 +24967 0.055206298828125 +24968 0.76239013671875 +24969 0.084686279296875 +24970 0.867462158203125 +24971 0.105926513671875 +24972 0.870361328125 +24973 0.119049072265625 +24974 0.86480712890625 +24975 0.122955322265625 +24976 0.831817626953125 +24977 0.11834716796875 +24978 0.677581787109375 +24979 0.10791015625 +24980 0.495880126953125 +24981 0.092437744140625 +24982 0.30767822265625 +24983 0.073974609375 +24984 0.116180419921875 +24985 0.0528564453125 +24986 -0.110748291015625 +24987 0.02587890625 +24988 -0.381805419921875 +24989 -0.007598876953125 +24990 -0.6572265625 +24991 -0.0430908203125 +24992 -0.857421875 +24993 -0.0743408203125 +24994 -0.870391845703125 +24995 -0.096954345703125 +24996 -0.870391845703125 +24997 -0.110260009765625 +24998 -0.86444091796875 +24999 -0.117156982421875 +25000 -0.85723876953125 +25001 -0.121429443359375 +25002 -0.790008544921875 +25003 -0.121307373046875 +25004 -0.62847900390625 +25005 -0.11126708984375 +25006 -0.3956298828125 +25007 -0.091094970703125 +25008 -0.126708984375 +25009 -0.064300537109375 +25010 0.150115966796875 +25011 -0.0338134765625 +25012 0.424041748046875 +25013 -0.0009765625 +25014 0.670623779296875 +25015 0.031341552734375 +25016 0.854522705078125 +25017 0.059051513671875 +25018 0.866485595703125 +25019 0.080352783203125 +25020 0.86920166015625 +25021 0.093658447265625 +25022 0.8653564453125 +25023 0.100921630859375 +25024 0.857147216796875 +25025 0.103607177734375 +25026 0.766845703125 +25027 0.10150146484375 +25028 0.628509521484375 +25029 0.09521484375 +25030 0.462127685546875 +25031 0.08416748046875 +25032 0.297210693359375 +25033 0.071136474609375 +25034 0.14862060546875 +25035 0.057464599609375 +25036 -0.00537109375 +25037 0.040863037109375 +25038 -0.15753173828125 +25039 0.022186279296875 +25040 -0.31304931640625 +25041 0.00115966796875 +25042 -0.48876953125 +25043 -0.02362060546875 +25044 -0.6416015625 +25045 -0.04730224609375 +25046 -0.751373291015625 +25047 -0.06732177734375 +25048 -0.84619140625 +25049 -0.086090087890625 +25050 -0.861297607421875 +25051 -0.102142333984375 +25052 -0.863250732421875 +25053 -0.112091064453125 +25054 -0.856597900390625 +25055 -0.112701416015625 +25056 -0.7498779296875 +25057 -0.1053466796875 +25058 -0.624542236328125 +25059 -0.09613037109375 +25060 -0.47808837890625 +25061 -0.0828857421875 +25062 -0.253387451171875 +25063 -0.059600830078125 +25064 0.003692626953125 +25065 -0.031097412109375 +25066 0.2257080078125 +25067 -0.00457763671875 +25068 0.427154541015625 +25069 0.021209716796875 +25070 0.643218994140625 +25071 0.049652099609375 +25072 0.855926513671875 +25073 0.0797119140625 +25074 0.870361328125 +25075 0.105438232421875 +25076 0.870361328125 +25077 0.121673583984375 +25078 0.862762451171875 +25079 0.1292724609375 +25080 0.79669189453125 +25081 0.127960205078125 +25082 0.595794677734375 +25083 0.116851806640625 +25084 0.362152099609375 +25085 0.09906005859375 +25086 0.1270751953125 +25087 0.077606201171875 +25088 -0.086944580078125 +25089 0.0552978515625 +25090 -0.2784423828125 +25091 0.03271484375 +25092 -0.484832763671875 +25093 0.0048828125 +25094 -0.729583740234375 +25095 -0.0316162109375 +25096 -0.86688232421875 +25097 -0.07061767578125 +25098 -0.870391845703125 +25099 -0.104156494140625 +25100 -0.86859130859375 +25101 -0.131988525390625 +25102 -0.86279296875 +25103 -0.154205322265625 +25104 -0.817962646484375 +25105 -0.1661376953125 +25106 -0.6116943359375 +25107 -0.161712646484375 +25108 -0.3128662109375 +25109 -0.139892578125 +25110 0.039398193359375 +25111 -0.105072021484375 +25112 0.422821044921875 +25113 -0.059722900390625 +25114 0.805145263671875 +25115 -0.008026123046875 +25116 0.870361328125 +25117 0.041107177734375 +25118 0.870361328125 +25119 0.08038330078125 +25120 0.860015869140625 +25121 0.108673095703125 +25122 0.727935791015625 +25123 0.12530517578125 +25124 0.48114013671875 +25125 0.1298828125 +25126 0.2059326171875 +25127 0.126007080078125 +25128 -0.06103515625 +25129 0.116943359375 +25130 -0.29913330078125 +25131 0.10418701171875 +25132 -0.516204833984375 +25133 0.0858154296875 +25134 -0.7252197265625 +25135 0.05975341796875 +25136 -0.85980224609375 +25137 0.029266357421875 +25138 -0.870391845703125 +25139 -0.0010986328125 +25140 -0.870391845703125 +25141 -0.027587890625 +25142 -0.858062744140625 +25143 -0.0438232421875 +25144 -0.673004150390625 +25145 -0.049560546875 +25146 -0.42694091796875 +25147 -0.05224609375 +25148 -0.2100830078125 +25149 -0.05816650390625 +25150 -0.0362548828125 +25151 -0.067291259765625 +25152 0.10943603515625 +25153 -0.07586669921875 +25154 0.23516845703125 +25155 -0.081329345703125 +25156 0.373687744140625 +25157 -0.07818603515625 +25158 0.517791748046875 +25159 -0.066741943359375 +25160 0.602783203125 +25161 -0.055572509765625 +25162 0.635711669921875 +25163 -0.0439453125 +25164 0.655181884765625 +25165 -0.0272216796875 +25166 0.65948486328125 +25167 -0.006591796875 +25168 0.651275634765625 +25169 0.016998291015625 +25170 0.61846923828125 +25171 0.0404052734375 +25172 0.53753662109375 +25173 0.058837890625 +25174 0.404144287109375 +25175 0.070037841796875 +25176 0.22186279296875 +25177 0.072906494140625 +25178 0.003997802734375 +25179 0.067840576171875 +25180 -0.22100830078125 +25181 0.05743408203125 +25182 -0.42449951171875 +25183 0.04461669921875 +25184 -0.579833984375 +25185 0.0323486328125 +25186 -0.641876220703125 +25187 0.026458740234375 +25188 -0.6177978515625 +25189 0.0260009765625 +25190 -0.575531005859375 +25191 0.022125244140625 +25192 -0.526336669921875 +25193 0.01397705078125 +25194 -0.42645263671875 +25195 0.00848388671875 +25196 -0.2581787109375 +25197 0.009185791015625 +25198 -0.068695068359375 +25199 0.010955810546875 +25200 0.09222412109375 +25201 0.0084228515625 +25202 0.232147216796875 +25203 0.00396728515625 +25204 0.3509521484375 +25205 -0.001129150390625 +25206 0.410064697265625 +25207 -0.011016845703125 +25208 0.372955322265625 +25209 -0.029815673828125 +25210 0.2554931640625 +25211 -0.054718017578125 +25212 0.10711669921875 +25213 -0.078643798828125 +25214 -0.052886962890625 +25215 -0.098907470703125 +25216 -0.186279296875 +25217 -0.110565185546875 +25218 -0.23291015625 +25219 -0.105926513671875 +25220 -0.209442138671875 +25221 -0.087982177734375 +25222 -0.174163818359375 +25223 -0.065582275390625 +25224 -0.126739501953125 +25225 -0.03973388671875 +25226 -0.048126220703125 +25227 -0.00897216796875 +25228 0.0426025390625 +25229 0.02301025390625 +25230 0.10748291015625 +25231 0.049957275390625 +25232 0.1409912109375 +25233 0.070159912109375 +25234 0.19708251953125 +25235 0.090179443359375 +25236 0.273651123046875 +25237 0.109161376953125 +25238 0.31768798828125 +25239 0.119537353515625 +25240 0.341094970703125 +25241 0.122833251953125 +25242 0.368011474609375 +25243 0.1224365234375 +25244 0.37249755859375 +25245 0.11517333984375 +25246 0.30072021484375 +25247 0.09423828125 +25248 0.1517333984375 +25249 0.060211181640625 +25250 -0.01470947265625 +25251 0.02203369140625 +25252 -0.1883544921875 +25253 -0.0179443359375 +25254 -0.372711181640625 +25255 -0.059295654296875 +25256 -0.51397705078125 +25257 -0.09381103515625 +25258 -0.57177734375 +25259 -0.115203857421875 +25260 -0.53948974609375 +25261 -0.12188720703125 +25262 -0.43511962890625 +25263 -0.11578369140625 +25264 -0.2962646484375 +25265 -0.101654052734375 +25266 -0.161102294921875 +25267 -0.08453369140625 +25268 -0.0435791015625 +25269 -0.066314697265625 +25270 0.060394287109375 +25271 -0.046661376953125 +25272 0.13665771484375 +25273 -0.02789306640625 +25274 0.170135498046875 +25275 -0.01263427734375 +25276 0.16552734375 +25277 -0.000885009765625 +25278 0.15728759765625 +25279 0.01129150390625 +25280 0.150787353515625 +25281 0.02386474609375 +25282 0.12200927734375 +25283 0.0328369140625 +25284 0.080108642578125 +25285 0.03875732421875 +25286 0.05126953125 +25287 0.04461669921875 +25288 0.062896728515625 +25289 0.05364990234375 +25290 0.09271240234375 +25291 0.062469482421875 +25292 0.092987060546875 +25293 0.064422607421875 +25294 0.07855224609375 +25295 0.061492919921875 +25296 0.06427001953125 +25297 0.055816650390625 +25298 0.0347900390625 +25299 0.04559326171875 +25300 -0.01171875 +25301 0.031005859375 +25302 -0.056060791015625 +25303 0.015167236328125 +25304 -0.055511474609375 +25305 0.004486083984375 +25306 -0.010467529296875 +25307 -0.000457763671875 +25308 0.02508544921875 +25309 -0.006378173828125 +25310 0.025665283203125 +25311 -0.01617431640625 +25312 0.017333984375 +25313 -0.02581787109375 +25314 0.00189208984375 +25315 -0.03460693359375 +25316 -0.03173828125 +25317 -0.04376220703125 +25318 -0.071502685546875 +25319 -0.05145263671875 +25320 -0.13543701171875 +25321 -0.06005859375 +25322 -0.219970703125 +25323 -0.069183349609375 +25324 -0.300506591796875 +25325 -0.075653076171875 +25326 -0.376312255859375 +25327 -0.079681396484375 +25328 -0.416107177734375 +25329 -0.077423095703125 +25330 -0.371124267578125 +25331 -0.06268310546875 +25332 -0.242279052734375 +25333 -0.036102294921875 +25334 -0.069732666015625 +25335 -0.003631591796875 +25336 0.125640869140625 +25337 0.0313720703125 +25338 0.31268310546875 +25339 0.064208984375 +25340 0.45501708984375 +25341 0.08953857421875 +25342 0.554779052734375 +25343 0.107391357421875 +25344 0.61065673828125 +25345 0.11761474609375 +25346 0.610931396484375 +25347 0.118408203125 +25348 0.531463623046875 +25349 0.105865478515625 +25350 0.3883056640625 +25351 0.08245849609375 +25352 0.23468017578125 +25353 0.0562744140625 +25354 0.095245361328125 +25355 0.03118896484375 +25356 -0.00396728515625 +25357 0.011322021484375 +25358 -0.04852294921875 +25359 -0.000885009765625 +25360 -0.055145263671875 +25361 -0.007598876953125 +25362 -0.0758056640625 +25363 -0.016326904296875 +25364 -0.138702392578125 +25365 -0.030975341796875 +25366 -0.209197998046875 +25367 -0.046051025390625 +25368 -0.289031982421875 +25369 -0.06158447265625 +25370 -0.37884521484375 +25371 -0.077484130859375 +25372 -0.456329345703125 +25373 -0.090301513671875 +25374 -0.51641845703125 +25375 -0.0992431640625 +25376 -0.519287109375 +25377 -0.098388671875 +25378 -0.458251953125 +25379 -0.08685302734375 +25380 -0.384796142578125 +25381 -0.072509765625 +25382 -0.323699951171875 +25383 -0.059295654296875 +25384 -0.269287109375 +25385 -0.046539306640625 +25386 -0.1951904296875 +25387 -0.03057861328125 +25388 -0.100006103515625 +25389 -0.011474609375 +25390 -0.01055908203125 +25391 0.006439208984375 +25392 0.1033935546875 +25393 0.027435302734375 +25394 0.24908447265625 +25395 0.05242919921875 +25396 0.373199462890625 +25397 0.073272705078125 +25398 0.45806884765625 +25399 0.08721923828125 +25400 0.511474609375 +25401 0.09539794921875 +25402 0.565399169921875 +25403 0.102630615234375 +25404 0.61138916015625 +25405 0.10772705078125 +25406 0.5897216796875 +25407 0.101837158203125 +25408 0.4906005859375 +25409 0.08367919921875 +25410 0.33148193359375 +25411 0.056060791015625 +25412 0.147796630859375 +25413 0.024505615234375 +25414 -0.01873779296875 +25415 -0.004486083984375 +25416 -0.140289306640625 +25417 -0.0264892578125 +25418 -0.191986083984375 +25419 -0.037567138671875 +25420 -0.184295654296875 +25421 -0.03912353515625 +25422 -0.161834716796875 +25423 -0.0377197265625 +25424 -0.166595458984375 +25425 -0.039581298828125 +25426 -0.19390869140625 +25427 -0.043975830078125 +25428 -0.22442626953125 +25429 -0.048004150390625 +25430 -0.279754638671875 +25431 -0.054962158203125 +25432 -0.3389892578125 +25433 -0.061798095703125 +25434 -0.3543701171875 +25435 -0.0615234375 +25436 -0.348175048828125 +25437 -0.0576171875 +25438 -0.32598876953125 +25439 -0.051055908203125 +25440 -0.2581787109375 +25441 -0.03759765625 +25442 -0.139801025390625 +25443 -0.016693115234375 +25444 0.014617919921875 +25445 0.009307861328125 +25446 0.144378662109375 +25447 0.0311279296875 +25448 0.221038818359375 +25449 0.044403076171875 +25450 0.27069091796875 +25451 0.052947998046875 +25452 0.294036865234375 +25453 0.056854248046875 +25454 0.311767578125 +25455 0.0592041015625 +25456 0.339141845703125 +25457 0.0623779296875 +25458 0.360260009765625 +25459 0.064300537109375 +25460 0.360504150390625 +25461 0.06280517578125 +25462 0.308380126953125 +25463 0.052581787109375 +25464 0.18170166015625 +25465 0.029937744140625 +25466 0.0047607421875 +25467 -0.000946044921875 +25468 -0.17559814453125 +25469 -0.032196044921875 +25470 -0.3143310546875 +25471 -0.056243896484375 +25472 -0.36785888671875 +25473 -0.065765380859375 +25474 -0.36248779296875 +25475 -0.06512451171875 +25476 -0.343536376953125 +25477 -0.06195068359375 +25478 -0.3018798828125 +25479 -0.05474853515625 +25480 -0.231414794921875 +25481 -0.042510986328125 +25482 -0.117645263671875 +25483 -0.0228271484375 +25484 0.007049560546875 +25485 -0.001190185546875 +25486 0.087982177734375 +25487 0.01318359375 +25488 0.13946533203125 +25489 0.02264404296875 +25490 0.17425537109375 +25491 0.029327392578125 +25492 0.188201904296875 +25493 0.032470703125 +25494 0.171234130859375 +25495 0.03033447265625 +25496 0.118438720703125 +25497 0.0220947265625 +25498 0.05706787109375 +25499 0.012298583984375 +25500 -0.010711669921875 +25501 0.00128173828125 +25502 -0.0914306640625 +25503 -0.01202392578125 +25504 -0.162322998046875 +25505 -0.023834228515625 +25506 -0.194549560546875 +25507 -0.029327392578125 +25508 -0.1492919921875 +25509 -0.02197265625 +25510 -0.02166748046875 +25511 -0.000946044921875 +25512 0.124053955078125 +25513 0.02301025390625 +25514 0.211151123046875 +25515 0.0369873046875 +25516 0.240447998046875 +25517 0.041168212890625 +25518 0.242218017578125 +25519 0.04071044921875 +25520 0.2257080078125 +25521 0.037200927734375 +25522 0.194366455078125 +25523 0.03125 +25524 0.115509033203125 +25525 0.017425537109375 +25526 0.0128173828125 +25527 -0.000244140625 +25528 -0.053802490234375 +25529 -0.01165771484375 +25530 -0.110626220703125 +25531 -0.021240234375 +25532 -0.199493408203125 +25533 -0.036041259765625 +25534 -0.29437255859375 +25535 -0.05169677734375 +25536 -0.33221435546875 +25537 -0.0576171875 +25538 -0.27972412109375 +25539 -0.04827880859375 +25540 -0.185333251953125 +25541 -0.031829833984375 +25542 -0.128204345703125 +25543 -0.0216064453125 +25544 -0.115692138671875 +25545 -0.01885986328125 +25546 -0.116455078125 +25547 -0.01837158203125 +25548 -0.105926513671875 +25549 -0.016021728515625 +25550 -0.053955078125 +25551 -0.006805419921875 +25552 0.048797607421875 +25553 0.01080322265625 +25554 0.157318115234375 +25555 0.02923583984375 +25556 0.212005615234375 +25557 0.0384521484375 +25558 0.218475341796875 +25559 0.039398193359375 +25560 0.23724365234375 +25561 0.042266845703125 +25562 0.30535888671875 +25563 0.053314208984375 +25564 0.38128662109375 +25565 0.065582275390625 +25566 0.404449462890625 +25567 0.068878173828125 +25568 0.3944091796875 +25569 0.066558837890625 +25570 0.3885498046875 +25571 0.06494140625 +25572 0.362640380859375 +25573 0.059967041015625 +25574 0.27362060546875 +25575 0.044464111328125 +25576 0.11712646484375 +25577 0.017730712890625 +25578 -0.054901123046875 +25579 -0.011444091796875 +25580 -0.19085693359375 +25581 -0.034393310546875 +25582 -0.28570556640625 +25583 -0.050262451171875 +25584 -0.339263916015625 +25585 -0.059051513671875 +25586 -0.3775634765625 +25587 -0.065155029296875 +25588 -0.445709228515625 +25589 -0.076171875 +25590 -0.535064697265625 +25591 -0.090667724609375 +25592 -0.629058837890625 +25593 -0.10589599609375 +25594 -0.697601318359375 +25595 -0.1168212890625 +25596 -0.70391845703125 +25597 -0.117279052734375 +25598 -0.6424560546875 +25599 -0.10638427734375 +25600 -0.491241455078125 +25601 -0.080047607421875 +25602 -0.265716552734375 +25603 -0.04071044921875 +25604 -0.023712158203125 +25605 0.0010986328125 +25606 0.201751708984375 +25607 0.039276123046875 +25608 0.375823974609375 +25609 0.0673828125 +25610 0.485076904296875 +25611 0.083221435546875 +25612 0.56884765625 +25613 0.095001220703125 +25614 0.634765625 +25615 0.1044921875 +25616 0.63763427734375 +25617 0.102813720703125 +25618 0.5660400390625 +25619 0.0877685546875 +25620 0.4720458984375 +25621 0.069732666015625 +25622 0.40692138671875 +25623 0.058868408203125 +25624 0.3778076171875 +25625 0.056427001953125 +25626 0.376953125 +25627 0.06060791015625 +25628 0.371978759765625 +25629 0.064697265625 +25630 0.313140869140625 +25631 0.05841064453125 +25632 0.184417724609375 +25633 0.0382080078125 +25634 0.011199951171875 +25635 0.008880615234375 +25636 -0.171051025390625 +25637 -0.022735595703125 +25638 -0.33740234375 +25639 -0.051910400390625 +25640 -0.47198486328125 +25641 -0.075653076171875 +25642 -0.560394287109375 +25643 -0.09124755859375 +25644 -0.58056640625 +25645 -0.0943603515625 +25646 -0.54754638671875 +25647 -0.0880126953125 +25648 -0.508575439453125 +25649 -0.081634521484375 +25650 -0.459503173828125 +25651 -0.07427978515625 +25652 -0.394378662109375 +25653 -0.064605712890625 +25654 -0.35260009765625 +25655 -0.06024169921875 +25656 -0.31170654296875 +25657 -0.05645751953125 +25658 -0.197418212890625 +25659 -0.038177490234375 +25660 -0.007965087890625 +25661 -0.004791259765625 +25662 0.207489013671875 +25663 0.0340576171875 +25664 0.409210205078125 +25665 0.0706787109375 +25666 0.57208251953125 +25667 0.1002197265625 +25668 0.66595458984375 +25669 0.1168212890625 +25670 0.65875244140625 +25671 0.1141357421875 +25672 0.56744384765625 +25673 0.09564208984375 +25674 0.431396484375 +25675 0.069183349609375 +25676 0.29443359375 +25677 0.04345703125 +25678 0.182464599609375 +25679 0.023529052734375 +25680 0.06365966796875 +25681 0.002899169921875 +25682 -0.075958251953125 +25683 -0.02142333984375 +25684 -0.189422607421875 +25685 -0.040252685546875 +25686 -0.271942138671875 +25687 -0.052825927734375 +25688 -0.342529296875 +25689 -0.06317138671875 +25690 -0.364166259765625 +25691 -0.064117431640625 +25692 -0.327239990234375 +25693 -0.053924560546875 +25694 -0.2769775390625 +25695 -0.041778564453125 +25696 -0.253692626953125 +25697 -0.035797119140625 +25698 -0.24365234375 +25699 -0.033294677734375 +25700 -0.1983642578125 +25701 -0.024566650390625 +25702 -0.116241455078125 +25703 -0.00927734375 +25704 -0.036834716796875 +25705 0.004730224609375 +25706 0.034881591796875 +25707 0.0166015625 +25708 0.09124755859375 +25709 0.024932861328125 +25710 0.10888671875 +25711 0.025238037109375 +25712 0.125518798828125 +25713 0.025238037109375 +25714 0.15771484375 +25715 0.0284423828125 +25716 0.17828369140625 +25717 0.02960205078125 +25718 0.17108154296875 +25719 0.025604248046875 +25720 0.129974365234375 +25721 0.015380859375 +25722 0.082427978515625 +25723 0.0045166015625 +25724 0.027679443359375 +25725 -0.007049560546875 +25726 -0.065643310546875 +25727 -0.02557373046875 +25728 -0.15936279296875 +25729 -0.04345703125 +25730 -0.21307373046875 +25731 -0.052703857421875 +25732 -0.234649658203125 +25733 -0.05499267578125 +25734 -0.2001953125 +25735 -0.045684814453125 +25736 -0.119171142578125 +25737 -0.026824951171875 +25738 -0.024749755859375 +25739 -0.00518798828125 +25740 0.085784912109375 +25741 0.01959228515625 +25742 0.178131103515625 +25743 0.040496826171875 +25744 0.215576171875 +25745 0.050079345703125 +25746 0.211456298828125 +25747 0.0509033203125 +25748 0.17523193359375 +25749 0.0447998046875 +25750 0.128753662109375 +25751 0.036102294921875 +25752 0.1019287109375 +25753 0.03076171875 +25754 0.0743408203125 +25755 0.02471923828125 +25756 0.04327392578125 +25757 0.0174560546875 +25758 0.038177490234375 +25759 0.01495361328125 +25760 0.076263427734375 +25761 0.020721435546875 +25762 0.14105224609375 +25763 0.031585693359375 +25764 0.186431884765625 +25765 0.038421630859375 +25766 0.188812255859375 +25767 0.036651611328125 +25768 0.1390380859375 +25769 0.024566650390625 +25770 0.041778564453125 +25771 0.00323486328125 +25772 -0.079437255859375 +25773 -0.02252197265625 +25774 -0.219390869140625 +25775 -0.051605224609375 +25776 -0.367828369140625 +25777 -0.081878662109375 +25778 -0.494873046875 +25779 -0.107391357421875 +25780 -0.556243896484375 +25781 -0.119293212890625 +25782 -0.508697509765625 +25783 -0.10894775390625 +25784 -0.3756103515625 +25785 -0.081085205078125 +25786 -0.218902587890625 +25787 -0.048187255859375 +25788 -0.063751220703125 +25789 -0.015380859375 +25790 0.091552734375 +25791 0.017486572265625 +25792 0.23602294921875 +25793 0.04815673828125 +25794 0.342987060546875 +25795 0.07122802734375 +25796 0.39520263671875 +25797 0.083160400390625 +25798 0.389373779296875 +25799 0.083221435546875 +25800 0.324249267578125 +25801 0.07110595703125 +25802 0.224090576171875 +25803 0.0516357421875 +25804 0.124267578125 +25805 0.0318603515625 +25806 0.037078857421875 +25807 0.01422119140625 +25808 -0.010101318359375 +25809 0.004241943359375 +25810 -0.019439697265625 +25811 0.001495361328125 +25812 -0.022796630859375 +25813 -0.00030517578125 +25814 -0.001556396484375 +25815 0.002593994140625 +25816 0.056304931640625 +25817 0.0126953125 +25818 0.106719970703125 +25819 0.021240234375 +25820 0.096893310546875 +25821 0.017791748046875 +25822 0.042694091796875 +25823 0.005584716796875 +25824 -0.018035888671875 +25825 -0.0076904296875 +25826 -0.07586669921875 +25827 -0.020111083984375 +25828 -0.11944580078125 +25829 -0.02935791015625 +25830 -0.15972900390625 +25831 -0.03759765625 +25832 -0.202606201171875 +25833 -0.0460205078125 +25834 -0.24859619140625 +25835 -0.054718017578125 +25836 -0.30517578125 +25837 -0.065216064453125 +25838 -0.36212158203125 +25839 -0.0755615234375 +25840 -0.39141845703125 +25841 -0.0802001953125 +25842 -0.35528564453125 +25843 -0.0716552734375 +25844 -0.249969482421875 +25845 -0.04925537109375 +25846 -0.092864990234375 +25847 -0.016571044921875 +25848 0.08905029296875 +25849 0.020904541015625 +25850 0.2352294921875 +25851 0.051025390625 +25852 0.318817138671875 +25853 0.068389892578125 +25854 0.358642578125 +25855 0.07672119140625 +25856 0.347747802734375 +25857 0.07403564453125 +25858 0.28564453125 +25859 0.0595703125 +25860 0.223175048828125 +25861 0.04473876953125 +25862 0.196746826171875 +25863 0.0382080078125 +25864 0.179840087890625 +25865 0.034088134765625 +25866 0.155548095703125 +25867 0.028594970703125 +25868 0.151214599609375 +25869 0.02813720703125 +25870 0.156951904296875 +25871 0.030426025390625 +25872 0.13177490234375 +25873 0.025909423828125 +25874 0.100799560546875 +25875 0.0203857421875 +25876 0.087127685546875 +25877 0.01910400390625 +25878 0.05487060546875 +25879 0.01361083984375 +25880 -0.009002685546875 +25881 0.000762939453125 +25882 -0.10400390625 +25883 -0.0194091796875 +25884 -0.229400634765625 +25885 -0.046875 +25886 -0.35552978515625 +25887 -0.074859619140625 +25888 -0.441925048828125 +25889 -0.094024658203125 +25890 -0.473846435546875 +25891 -0.10101318359375 +25892 -0.464813232421875 +25893 -0.098968505859375 +25894 -0.419097900390625 +25895 -0.0888671875 +25896 -0.334320068359375 +25897 -0.07012939453125 +25898 -0.227935791015625 +25899 -0.0467529296875 +25900 -0.12347412109375 +25901 -0.02410888671875 +25902 -0.02764892578125 +25903 -0.003631591796875 +25904 0.077667236328125 +25905 0.018951416015625 +25906 0.2132568359375 +25907 0.048553466796875 +25908 0.38885498046875 +25909 0.0875244140625 +25910 0.582794189453125 +25911 0.130950927734375 +25912 0.734039306640625 +25913 0.16473388671875 +25914 0.800140380859375 +25915 0.1790771484375 +25916 0.7783203125 +25917 0.17340087890625 +25918 0.6651611328125 +25919 0.146942138671875 +25920 0.45965576171875 +25921 0.0994873046875 +25922 0.199188232421875 +25923 0.039703369140625 +25924 -0.050689697265625 +25925 -0.01727294921875 +25926 -0.23297119140625 +25927 -0.058258056640625 +25928 -0.33013916015625 +25929 -0.07928466796875 +25930 -0.368408203125 +25931 -0.086517333984375 +25932 -0.378936767578125 +25933 -0.0872802734375 +25934 -0.376983642578125 +25935 -0.085235595703125 +25936 -0.37969970703125 +25937 -0.084442138671875 +25938 -0.391510009765625 +25939 -0.085968017578125 +25940 -0.385345458984375 +25941 -0.083587646484375 +25942 -0.3419189453125 +25943 -0.072906494140625 +25944 -0.28289794921875 +25945 -0.0589599609375 +25946 -0.251617431640625 +25947 -0.051788330078125 +25948 -0.266143798828125 +25949 -0.0555419921875 +25950 -0.273345947265625 +25951 -0.05792236328125 +25952 -0.216796875 +25953 -0.0457763671875 +25954 -0.128265380859375 +25955 -0.0263671875 +25956 -0.068145751953125 +25957 -0.013671875 +25958 -0.0430908203125 +25959 -0.009124755859375 +25960 -0.024444580078125 +25961 -0.00604248046875 +25962 0.020721435546875 +25963 0.00323486328125 +25964 0.124481201171875 +25965 0.026214599609375 +25966 0.25787353515625 +25967 0.056243896484375 +25968 0.379119873046875 +25969 0.08367919921875 +25970 0.47991943359375 +25971 0.10662841796875 +25972 0.5281982421875 +25973 0.117645263671875 +25974 0.511138916015625 +25975 0.11376953125 +25976 0.456207275390625 +25977 0.101348876953125 +25978 0.407470703125 +25979 0.090606689453125 +25980 0.383758544921875 +25981 0.085845947265625 +25982 0.35687255859375 +25983 0.080474853515625 +25984 0.31182861328125 +25985 0.07098388671875 +25986 0.250885009765625 +25987 0.057830810546875 +25988 0.1654052734375 +25989 0.038970947265625 +25990 0.035247802734375 +25991 0.009674072265625 +25992 -0.142059326171875 +25993 -0.0306396484375 +25994 -0.33563232421875 +25995 -0.074859619140625 +25996 -0.5345458984375 +25997 -0.120452880859375 +25998 -0.72186279296875 +25999 -0.163543701171875 +26000 -0.836669921875 +26001 -0.189971923828125 +26002 -0.8326416015625 +26003 -0.18902587890625 +26004 -0.7296142578125 +26005 -0.165313720703125 +26006 -0.582550048828125 +26007 -0.131591796875 +26008 -0.440093994140625 +26009 -0.09912109375 +26010 -0.324310302734375 +26011 -0.07293701171875 +26012 -0.20147705078125 +26013 -0.045196533203125 +26014 -0.044647216796875 +26015 -0.00958251953125 +26016 0.103973388671875 +26017 0.02410888671875 +26018 0.202392578125 +26019 0.046173095703125 +26020 0.264495849609375 +26021 0.05987548828125 +26022 0.338897705078125 +26023 0.0765380859375 +26024 0.443817138671875 +26025 0.10040283203125 +26026 0.545074462890625 +26027 0.123565673828125 +26028 0.6173095703125 +26029 0.140167236328125 +26030 0.6524658203125 +26031 0.1483154296875 +26032 0.66339111328125 +26033 0.1510009765625 +26034 0.6561279296875 +26035 0.149627685546875 +26036 0.606781005859375 +26037 0.13861083984375 +26038 0.501190185546875 +26039 0.1146240234375 +26040 0.352783203125 +26041 0.080780029296875 +26042 0.176544189453125 +26043 0.040496826171875 +26044 -0.034820556640625 +26045 -0.007904052734375 +26046 -0.258209228515625 +26047 -0.059051513671875 +26048 -0.44244384765625 +26049 -0.10113525390625 +26050 -0.5753173828125 +26051 -0.131378173828125 +26052 -0.65203857421875 +26053 -0.148681640625 +26054 -0.641632080078125 +26055 -0.145904541015625 +26056 -0.562164306640625 +26057 -0.127288818359375 +26058 -0.458038330078125 +26059 -0.103118896484375 +26060 -0.350555419921875 +26061 -0.078338623046875 +26062 -0.260528564453125 +26063 -0.0577392578125 +26064 -0.192108154296875 +26065 -0.042266845703125 +26066 -0.141937255859375 +26067 -0.031097412109375 +26068 -0.1021728515625 +26069 -0.02239990234375 +26070 -0.062896728515625 +26071 -0.01385498046875 +26072 -0.011932373046875 +26073 -0.0025634765625 +26074 0.062835693359375 +26075 0.0142822265625 +26076 0.148712158203125 +26077 0.033721923828125 +26078 0.241729736328125 +26079 0.05487060546875 +26080 0.34912109375 +26081 0.079437255859375 +26082 0.457305908203125 +26083 0.104278564453125 +26084 0.54388427734375 +26085 0.12420654296875 +26086 0.5728759765625 +26087 0.130889892578125 +26088 0.506591796875 +26089 0.1156005859375 +26090 0.351226806640625 +26091 0.07977294921875 +26092 0.146514892578125 +26093 0.0325927734375 +26094 -0.05523681640625 +26095 -0.0137939453125 +26096 -0.21624755859375 +26097 -0.050689697265625 +26098 -0.334930419921875 +26099 -0.07769775390625 +26100 -0.402984619140625 +26101 -0.092926025390625 +26102 -0.4412841796875 +26103 -0.10125732421875 +26104 -0.49578857421875 +26105 -0.1134033203125 +26106 -0.5601806640625 +26107 -0.1279296875 +26108 -0.600738525390625 +26109 -0.13702392578125 +26110 -0.584228515625 +26111 -0.133026123046875 +26112 -0.47930908203125 +26113 -0.10833740234375 +26114 -0.27935791015625 +26115 -0.06072998046875 +26116 -0.0089111328125 +26117 0.004241943359375 +26118 0.268798828125 +26119 0.070587158203125 +26120 0.482818603515625 +26121 0.1202392578125 +26122 0.60369873046875 +26123 0.145965576171875 +26124 0.650421142578125 +26125 0.153167724609375 +26126 0.66400146484375 +26127 0.15301513671875 +26128 0.6414794921875 +26129 0.144866943359375 +26130 0.572540283203125 +26131 0.1260986328125 +26132 0.498138427734375 +26133 0.107452392578125 +26134 0.439453125 +26135 0.09442138671875 +26136 0.375518798828125 +26137 0.08123779296875 +26138 0.274505615234375 +26139 0.059234619140625 +26140 0.1087646484375 +26141 0.02081298828125 +26142 -0.099395751953125 +26143 -0.028472900390625 +26144 -0.3182373046875 +26145 -0.080535888671875 +26146 -0.5489501953125 +26147 -0.13604736328125 +26148 -0.7738037109375 +26149 -0.190582275390625 +26150 -0.86383056640625 +26151 -0.23046875 +26152 -0.870391845703125 +26153 -0.247100830078125 +26154 -0.86895751953125 +26155 -0.24530029296875 +26156 -0.861053466796875 +26157 -0.22857666015625 +26158 -0.765869140625 +26159 -0.192352294921875 +26160 -0.5301513671875 +26161 -0.13360595703125 +26162 -0.214691162109375 +26163 -0.054046630859375 +26164 0.137359619140625 +26165 0.03509521484375 +26166 0.474822998046875 +26167 0.12054443359375 +26168 0.76239013671875 +26169 0.19317626953125 +26170 0.867462158203125 +26171 0.24615478515625 +26172 0.870361328125 +26173 0.279876708984375 +26174 0.86480712890625 +26175 0.29150390625 +26176 0.831817626953125 +26177 0.28265380859375 +26178 0.677581787109375 +26179 0.259918212890625 +26180 0.495880126953125 +26181 0.225006103515625 +26182 0.30767822265625 +26183 0.182861328125 +26184 0.116180419921875 +26185 0.13409423828125 +26186 -0.110748291015625 +26187 0.070281982421875 +26188 -0.381805419921875 +26189 -0.01043701171875 +26190 -0.6572265625 +26191 -0.096923828125 +26192 -0.857421875 +26193 -0.173553466796875 +26194 -0.870391845703125 +26195 -0.229217529296875 +26196 -0.870391845703125 +26197 -0.26226806640625 +26198 -0.86444091796875 +26199 -0.280029296875 +26200 -0.85723876953125 +26201 -0.29217529296875 +26202 -0.790008544921875 +26203 -0.29400634765625 +26204 -0.62847900390625 +26205 -0.271392822265625 +26206 -0.3956298828125 +26207 -0.223602294921875 +26208 -0.126708984375 +26209 -0.159393310546875 +26210 0.150115966796875 +26211 -0.08599853515625 +26212 0.424041748046875 +26213 -0.006500244140625 +26214 0.670623779296875 +26215 0.072021484375 +26216 0.854522705078125 +26217 0.139434814453125 +26218 0.866485595703125 +26219 0.19122314453125 +26220 0.86920166015625 +26221 0.2235107421875 +26222 0.8653564453125 +26223 0.24127197265625 +26224 0.857147216796875 +26225 0.24822998046875 +26226 0.766845703125 +26227 0.243804931640625 +26228 0.628509521484375 +26229 0.229522705078125 +26230 0.462127685546875 +26231 0.203704833984375 +26232 0.297210693359375 +26233 0.173309326171875 +26234 0.14862060546875 +26235 0.141632080078125 +26236 -0.00537109375 +26237 0.102691650390625 +26238 -0.15753173828125 +26239 0.058502197265625 +26240 -0.31304931640625 +26241 0.008087158203125 +26242 -0.48876953125 +26243 -0.05230712890625 +26244 -0.6416015625 +26245 -0.11041259765625 +26246 -0.751373291015625 +26247 -0.159820556640625 +26248 -0.84619140625 +26249 -0.206787109375 +26250 -0.861297607421875 +26251 -0.24755859375 +26252 -0.863250732421875 +26253 -0.2735595703125 +26254 -0.856597900390625 +26255 -0.276580810546875 +26256 -0.7498779296875 +26257 -0.259918212890625 +26258 -0.624542236328125 +26259 -0.239013671875 +26260 -0.47808837890625 +26261 -0.208099365234375 +26262 -0.253387451171875 +26263 -0.15179443359375 +26264 0.003692626953125 +26265 -0.082183837890625 +26266 0.2257080078125 +26267 -0.017333984375 +26268 0.427154541015625 +26269 0.04608154296875 +26270 0.643218994140625 +26271 0.11669921875 +26272 0.855926513671875 +26273 0.192047119140625 +26274 0.870361328125 +26275 0.256927490234375 +26276 0.870361328125 +26277 0.298370361328125 +26278 0.862762451171875 +26279 0.31842041015625 +26280 0.79669189453125 +26281 0.31640625 +26282 0.595794677734375 +26283 0.289947509765625 +26284 0.362152099609375 +26285 0.246856689453125 +26286 0.1270751953125 +26287 0.194610595703125 +26288 -0.086944580078125 +26289 0.13885498046875 +26290 -0.2784423828125 +26291 0.0802001953125 +26292 -0.484832763671875 +26293 0.009490966796875 +26294 -0.729583740234375 +26295 -0.078338623046875 +26296 -0.86688232421875 +26297 -0.169952392578125 +26298 -0.870391845703125 +26299 -0.24871826171875 +26300 -0.86859130859375 +26301 -0.313385009765625 +26302 -0.86279296875 +26303 -0.36346435546875 +26304 -0.817962646484375 +26305 -0.38958740234375 +26306 -0.6116943359375 +26307 -0.379852294921875 +26308 -0.3128662109375 +26309 -0.332489013671875 +26310 0.039398193359375 +26311 -0.2564697265625 +26312 0.422821044921875 +26313 -0.15716552734375 +26314 0.805145263671875 +26315 -0.043426513671875 +26316 0.870361328125 +26317 0.066680908203125 +26318 0.870361328125 +26319 0.158050537109375 +26320 0.860015869140625 +26321 0.227569580078125 +26322 0.727935791015625 +26323 0.273162841796875 +26324 0.48114013671875 +26325 0.293365478515625 +26326 0.2059326171875 +26327 0.294525146484375 +26328 -0.06103515625 +26329 0.28265380859375 +26330 -0.29913330078125 +26331 0.26043701171875 +26332 -0.516204833984375 +26333 0.224090576171875 +26334 -0.7252197265625 +26335 0.169647216796875 +26336 -0.85980224609375 +26337 0.103759765625 +26338 -0.870391845703125 +26339 0.035614013671875 +26340 -0.870391845703125 +26341 -0.02685546875 +26342 -0.858062744140625 +26343 -0.070648193359375 +26344 -0.673004150390625 +26345 -0.094512939453125 +26346 -0.42694091796875 +26347 -0.112152099609375 +26348 -0.2100830078125 +26349 -0.135162353515625 +26350 -0.0362548828125 +26351 -0.162872314453125 +26352 0.10943603515625 +26353 -0.187530517578125 +26354 0.23516845703125 +26355 -0.203765869140625 +26356 0.373687744140625 +26357 -0.20068359375 +26358 0.517791748046875 +26359 -0.178802490234375 +26360 0.602783203125 +26361 -0.15484619140625 +26362 0.635711669921875 +26363 -0.127532958984375 +26364 0.655181884765625 +26365 -0.088165283203125 +26366 0.65948486328125 +26367 -0.039520263671875 +26368 0.651275634765625 +26369 0.016387939453125 +26370 0.61846923828125 +26371 0.0728759765625 +26372 0.53753662109375 +26373 0.11944580078125 +26374 0.404144287109375 +26375 0.15081787109375 +26376 0.22186279296875 +26377 0.164154052734375 +26378 0.003997802734375 +26379 0.1597900390625 +26380 -0.22100830078125 +26381 0.143035888671875 +26382 -0.42449951171875 +26383 0.119903564453125 +26384 -0.579833984375 +26385 0.09661865234375 +26386 -0.641876220703125 +26387 0.085662841796875 +26388 -0.6177978515625 +26389 0.084991455078125 +26390 -0.575531005859375 +26391 0.0753173828125 +26392 -0.526336669921875 +26393 0.054901123046875 +26394 -0.42645263671875 +26395 0.03900146484375 +26396 -0.2581787109375 +26397 0.035614013671875 +26398 -0.068695068359375 +26399 0.03387451171875 +26400 0.09222412109375 +26401 0.02239990234375 +26402 0.232147216796875 +26403 0.00665283203125 +26404 0.3509521484375 +26405 -0.010284423828125 +26406 0.410064697265625 +26407 -0.037139892578125 +26408 0.372955322265625 +26409 -0.08251953125 +26410 0.2554931640625 +26411 -0.14013671875 +26412 0.10711669921875 +26413 -0.1944580078125 +26414 -0.052886962890625 +26415 -0.23956298828125 +26416 -0.186279296875 +26417 -0.264617919921875 +26418 -0.23291015625 +26419 -0.252960205078125 +26420 -0.209442138671875 +26421 -0.21124267578125 +26422 -0.174163818359375 +26423 -0.158843994140625 +26424 -0.126739501953125 +26425 -0.09820556640625 +26426 -0.048126220703125 +26427 -0.0263671875 +26428 0.0426025390625 +26429 0.048309326171875 +26430 0.10748291015625 +26431 0.11199951171875 +26432 0.1409912109375 +26433 0.1607666015625 +26434 0.19708251953125 +26435 0.208587646484375 +26436 0.273651123046875 +26437 0.253387451171875 +26438 0.31768798828125 +26439 0.278533935546875 +26440 0.341094970703125 +26441 0.287139892578125 +26442 0.368011474609375 +26443 0.28662109375 +26444 0.37249755859375 +26445 0.27001953125 +26446 0.30072021484375 +26447 0.22265625 +26448 0.1517333984375 +26449 0.1458740234375 +26450 -0.01470947265625 +26451 0.059326171875 +26452 -0.1883544921875 +26453 -0.031707763671875 +26454 -0.372711181640625 +26455 -0.12603759765625 +26456 -0.51397705078125 +26457 -0.205596923828125 +26458 -0.57177734375 +26459 -0.25640869140625 +26460 -0.53948974609375 +26461 -0.274810791015625 +26462 -0.43511962890625 +26463 -0.2647705078125 +26464 -0.2962646484375 +26465 -0.236480712890625 +26466 -0.161102294921875 +26467 -0.2008056640625 +26468 -0.0435791015625 +26469 -0.161865234375 +26470 0.060394287109375 +26471 -0.118896484375 +26472 0.13665771484375 +26473 -0.076995849609375 +26474 0.170135498046875 +26475 -0.041900634765625 +26476 0.16552734375 +26477 -0.01373291015625 +26478 0.15728759765625 +26479 0.015899658203125 +26480 0.150787353515625 +26481 0.04681396484375 +26482 0.12200927734375 +26483 0.070068359375 +26484 0.080108642578125 +26485 0.086669921875 +26486 0.05126953125 +26487 0.102874755859375 +26488 0.062896728515625 +26489 0.125579833984375 +26490 0.09271240234375 +26491 0.14727783203125 +26492 0.092987060546875 +26493 0.1533203125 +26494 0.07855224609375 +26495 0.147979736328125 +26496 0.06427001953125 +26497 0.13592529296875 +26498 0.0347900390625 +26499 0.11322021484375 +26500 -0.01171875 +26501 0.08026123046875 +26502 -0.056060791015625 +26503 0.0439453125 +26504 -0.055511474609375 +26505 0.018280029296875 +26506 -0.010467529296875 +26507 0.004638671875 +26508 0.02508544921875 +26509 -0.01141357421875 +26510 0.025665283203125 +26511 -0.035980224609375 +26512 0.017333984375 +26513 -0.060089111328125 +26514 0.00189208984375 +26515 -0.08209228515625 +26516 -0.03173828125 +26517 -0.104461669921875 +26518 -0.071502685546875 +26519 -0.12310791015625 +26520 -0.13543701171875 +26521 -0.14312744140625 +26522 -0.219970703125 +26523 -0.16357421875 +26524 -0.300506591796875 +26525 -0.17755126953125 +26526 -0.376312255859375 +26527 -0.185546875 +26528 -0.416107177734375 +26529 -0.179229736328125 +26530 -0.371124267578125 +26531 -0.145263671875 +26532 -0.242279052734375 +26533 -0.085113525390625 +26534 -0.069732666015625 +26535 -0.01190185546875 +26536 0.125640869140625 +26537 0.06695556640625 +26538 0.31268310546875 +26539 0.141082763671875 +26540 0.45501708984375 +26541 0.198760986328125 +26542 0.554779052734375 +26543 0.239898681640625 +26544 0.61065673828125 +26545 0.263580322265625 +26546 0.610931396484375 +26547 0.266082763671875 +26548 0.531463623046875 +26549 0.240264892578125 +26550 0.3883056640625 +26551 0.191162109375 +26552 0.23468017578125 +26553 0.135009765625 +26554 0.095245361328125 +26555 0.079803466796875 +26556 -0.00396728515625 +26557 0.034088134765625 +26558 -0.04852294921875 +26559 0.003082275390625 +26560 -0.055145263671875 +26561 -0.017120361328125 +26562 -0.0758056640625 +26563 -0.0408935546875 +26564 -0.138702392578125 +26565 -0.07562255859375 +26566 -0.209197998046875 +26567 -0.110260009765625 +26568 -0.289031982421875 +26569 -0.14459228515625 +26570 -0.37884521484375 +26571 -0.1783447265625 +26572 -0.456329345703125 +26573 -0.204620361328125 +26574 -0.51641845703125 +26575 -0.221832275390625 +26576 -0.519287109375 +26577 -0.21832275390625 +26578 -0.458251953125 +26579 -0.192474365234375 +26580 -0.384796142578125 +26581 -0.160064697265625 +26582 -0.323699951171875 +26583 -0.12908935546875 +26584 -0.269287109375 +26585 -0.098602294921875 +26586 -0.1951904296875 +26587 -0.061614990234375 +26588 -0.100006103515625 +26589 -0.018585205078125 +26590 -0.01055908203125 +26591 0.021728515625 +26592 0.1033935546875 +26593 0.067535400390625 +26594 0.24908447265625 +26595 0.120361328125 +26596 0.373199462890625 +26597 0.163970947265625 +26598 0.45806884765625 +26599 0.192840576171875 +26600 0.511474609375 +26601 0.20916748046875 +26602 0.565399169921875 +26603 0.222503662109375 +26604 0.61138916015625 +26605 0.230560302734375 +26606 0.5897216796875 +26607 0.216033935546875 +26608 0.4906005859375 +26609 0.176544189453125 +26610 0.33148193359375 +26611 0.117889404296875 +26612 0.147796630859375 +26613 0.05120849609375 +26614 -0.01873779296875 +26615 -0.01043701171875 +26616 -0.140289306640625 +26617 -0.05810546875 +26618 -0.191986083984375 +26619 -0.0838623046875 +26620 -0.184295654296875 +26621 -0.090240478515625 +26622 -0.161834716796875 +26623 -0.09002685546875 +26624 -0.166595458984375 +26625 -0.095367431640625 +26626 -0.19390869140625 +26627 -0.104766845703125 +26628 -0.22442626953125 +26629 -0.11248779296875 +26630 -0.279754638671875 +26631 -0.125152587890625 +26632 -0.3389892578125 +26633 -0.136810302734375 +26634 -0.3543701171875 +26635 -0.133514404296875 +26636 -0.348175048828125 +26637 -0.122467041015625 +26638 -0.32598876953125 +26639 -0.105865478515625 +26640 -0.2581787109375 +26641 -0.075408935546875 +26642 -0.139801025390625 +26643 -0.030181884765625 +26644 0.014617919921875 +26645 0.024932861328125 +26646 0.144378662109375 +26647 0.071258544921875 +26648 0.221038818359375 +26649 0.09991455078125 +26650 0.27069091796875 +26651 0.118438720703125 +26652 0.294036865234375 +26653 0.126953125 +26654 0.311767578125 +26655 0.131622314453125 +26656 0.339141845703125 +26657 0.137237548828125 +26658 0.360260009765625 +26659 0.1395263671875 +26660 0.360504150390625 +26661 0.134307861328125 +26662 0.308380126953125 +26663 0.1114501953125 +26664 0.18170166015625 +26665 0.063934326171875 +26666 0.0047607421875 +26667 0.0 +26668 -0.17559814453125 +26669 -0.064727783203125 +26670 -0.3143310546875 +26671 -0.115234375 +26672 -0.36785888671875 +26673 -0.136993408203125 +26674 -0.36248779296875 +26675 -0.138427734375 +26676 -0.343536376953125 +26677 -0.13427734375 +26678 -0.3018798828125 +26679 -0.1214599609375 +26680 -0.231414794921875 +26681 -0.09796142578125 +26682 -0.117645263671875 +26683 -0.05908203125 +26684 0.007049560546875 +26685 -0.01556396484375 +26686 0.087982177734375 +26687 0.01446533203125 +26688 0.13946533203125 +26689 0.0355224609375 +26690 0.17425537109375 +26691 0.051544189453125 +26692 0.188201904296875 +26693 0.060882568359375 +26694 0.171234130859375 +26695 0.05999755859375 +26696 0.118438720703125 +26697 0.0469970703125 +26698 0.05706787109375 +26699 0.0306396484375 +26700 -0.010711669921875 +26701 0.01141357421875 +26702 -0.0914306640625 +26703 -0.012908935546875 +26704 -0.162322998046875 +26705 -0.03497314453125 +26706 -0.194549560546875 +26707 -0.045379638671875 +26708 -0.1492919921875 +26709 -0.0313720703125 +26710 -0.02166748046875 +26711 0.00872802734375 +26712 0.124053955078125 +26713 0.053955078125 +26714 0.211151123046875 +26715 0.07928466796875 +26716 0.240447998046875 +26717 0.085205078125 +26718 0.242218017578125 +26719 0.081817626953125 +26720 0.2257080078125 +26721 0.07244873046875 +26722 0.194366455078125 +26723 0.05841064453125 +26724 0.115509033203125 +26725 0.0291748046875 +26726 0.0128173828125 +26727 -0.007232666015625 +26728 -0.053802490234375 +26729 -0.03106689453125 +26730 -0.110626220703125 +26731 -0.050872802734375 +26732 -0.199493408203125 +26733 -0.080352783203125 +26734 -0.29437255859375 +26735 -0.1109619140625 +26736 -0.33221435546875 +26737 -0.1220703125 +26738 -0.27972412109375 +26739 -0.10284423828125 +26740 -0.185333251953125 +26741 -0.069305419921875 +26742 -0.128204345703125 +26743 -0.047576904296875 +26744 -0.115692138671875 +26745 -0.040252685546875 +26746 -0.116455078125 +26747 -0.0372314453125 +26748 -0.105926513671875 +26749 -0.0306396484375 +26750 -0.053955078125 +26751 -0.010772705078125 +26752 0.048797607421875 +26753 0.0252685546875 +26754 0.157318115234375 +26755 0.0626220703125 +26756 0.212005615234375 +26757 0.0816650390625 +26758 0.218475341796875 +26759 0.084197998046875 +26760 0.23724365234375 +26761 0.090087890625 +26762 0.30535888671875 +26763 0.11151123046875 +26764 0.38128662109375 +26765 0.134918212890625 +26766 0.404449462890625 +26767 0.140472412109375 +26768 0.3944091796875 +26769 0.134765625 +26770 0.3885498046875 +26771 0.13018798828125 +26772 0.362640380859375 +26773 0.11895751953125 +26774 0.27362060546875 +26775 0.087127685546875 +26776 0.11712646484375 +26777 0.03338623046875 +26778 -0.054901123046875 +26779 -0.02508544921875 +26780 -0.19085693359375 +26781 -0.071258544921875 +26782 -0.28570556640625 +26783 -0.103424072265625 +26784 -0.339263916015625 +26785 -0.1214599609375 +26786 -0.3775634765625 +26787 -0.1339111328125 +26788 -0.445709228515625 +26789 -0.15557861328125 +26790 -0.535064697265625 +26791 -0.183685302734375 +26792 -0.629058837890625 +26793 -0.212860107421875 +26794 -0.697601318359375 +26795 -0.233367919921875 +26796 -0.70391845703125 +26797 -0.233245849609375 +26798 -0.6424560546875 +26799 -0.2108154296875 +26800 -0.491241455078125 +26801 -0.15899658203125 +26802 -0.265716552734375 +26803 -0.08294677734375 +26804 -0.023712158203125 +26805 -0.00177001953125 +26806 0.201751708984375 +26807 0.073577880859375 +26808 0.375823974609375 +26809 0.131622314453125 +26810 0.485076904296875 +26811 0.16790771484375 +26812 0.56884765625 +26813 0.195343017578125 +26814 0.634765625 +26815 0.2164306640625 +26816 0.63763427734375 +26817 0.2164306640625 +26818 0.5660400390625 +26819 0.191650390625 +26820 0.4720458984375 +26821 0.159210205078125 +26822 0.40692138671875 +26823 0.13604736328125 +26824 0.3778076171875 +26825 0.124603271484375 +26826 0.376953125 +26827 0.1224365234375 +26828 0.371978759765625 +26829 0.1190185546875 +26830 0.313140869140625 +26831 0.098114013671875 +26832 0.184417724609375 +26833 0.0545654296875 +26834 0.011199951171875 +26835 -0.003204345703125 +26836 -0.171051025390625 +26837 -0.063507080078125 +26838 -0.33740234375 +26839 -0.118133544921875 +26840 -0.47198486328125 +26841 -0.161895751953125 +26842 -0.560394287109375 +26843 -0.19012451171875 +26844 -0.58056640625 +26845 -0.195648193359375 +26846 -0.54754638671875 +26847 -0.1834716796875 +26848 -0.508575439453125 +26849 -0.169189453125 +26850 -0.459503173828125 +26851 -0.1514892578125 +26852 -0.394378662109375 +26853 -0.128509521484375 +26854 -0.35260009765625 +26855 -0.113250732421875 +26856 -0.31170654296875 +26857 -0.098419189453125 +26858 -0.197418212890625 +26859 -0.059722900390625 +26860 -0.007965087890625 +26861 0.0032958984375 +26862 0.207489013671875 +26863 0.074462890625 +26864 0.409210205078125 +26865 0.1407470703125 +26866 0.57208251953125 +26867 0.19390869140625 +26868 0.66595458984375 +26869 0.22412109375 +26870 0.65875244140625 +26871 0.22088623046875 +26872 0.56744384765625 +26873 0.1898193359375 +26874 0.431396484375 +26875 0.143890380859375 +26876 0.29443359375 +26877 0.097564697265625 +26878 0.182464599609375 +26879 0.059417724609375 +26880 0.06365966796875 +26881 0.018585205078125 +26882 -0.075958251953125 +26883 -0.029449462890625 +26884 -0.189422607421875 +26885 -0.067840576171875 +26886 -0.271942138671875 +26887 -0.0950927734375 +26888 -0.342529296875 +26889 -0.118255615234375 +26890 -0.364166259765625 +26891 -0.124176025390625 +26892 -0.327239990234375 +26893 -0.1094970703125 +26894 -0.2769775390625 +26895 -0.090545654296875 +26896 -0.253692626953125 +26897 -0.081878662109375 +26898 -0.24365234375 +26899 -0.078521728515625 +26900 -0.1983642578125 +26901 -0.06298828125 +26902 -0.116241455078125 +26903 -0.034637451171875 +26904 -0.036834716796875 +26905 -0.00762939453125 +26906 0.034881591796875 +26907 0.016326904296875 +26908 0.09124755859375 +26909 0.034576416015625 +26910 0.10888671875 +26911 0.038848876953125 +26912 0.125518798828125 +26913 0.0428466796875 +26914 0.15771484375 +26915 0.052642822265625 +26916 0.17828369140625 +26917 0.058502197265625 +26918 0.17108154296875 +26919 0.054718017578125 +26920 0.129974365234375 +26921 0.039154052734375 +26922 0.082427978515625 +26923 0.021728515625 +26924 0.027679443359375 +26925 0.002166748046875 +26926 -0.065643310546875 +26927 -0.03082275390625 +26928 -0.15936279296875 +26929 -0.063568115234375 +26930 -0.21307373046875 +26931 -0.081573486328125 +26932 -0.234649658203125 +26933 -0.0877685546875 +26934 -0.2001953125 +26935 -0.073638916015625 +26936 -0.119171142578125 +26937 -0.042694091796875 +26938 -0.024749755859375 +26939 -0.0069580078125 +26940 0.085784912109375 +26941 0.034423828125 +26942 0.178131103515625 +26943 0.069000244140625 +26944 0.215576171875 +26945 0.08349609375 +26946 0.211456298828125 +26947 0.082672119140625 +26948 0.17523193359375 +26949 0.069915771484375 +26950 0.128753662109375 +26951 0.0531005859375 +26952 0.1019287109375 +26953 0.042999267578125 +26954 0.0743408203125 +26955 0.03228759765625 +26956 0.04327392578125 +26957 0.02008056640625 +26958 0.038177490234375 +26959 0.016998291015625 +26960 0.076263427734375 +26961 0.029296875 +26962 0.14105224609375 +26963 0.051116943359375 +26964 0.186431884765625 +26965 0.065948486328125 +26966 0.188812255859375 +26967 0.065399169921875 +26968 0.1390380859375 +26969 0.0462646484375 +26970 0.041778564453125 +26971 0.010284423828125 +26972 -0.079437255859375 +26973 -0.03399658203125 +26974 -0.219390869140625 +26975 -0.084716796875 +26976 -0.367828369140625 +26977 -0.138153076171875 +26978 -0.494873046875 +26979 -0.18353271484375 +26980 -0.556243896484375 +26981 -0.2049560546875 +26982 -0.508697509765625 +26983 -0.186920166015625 +26984 -0.3756103515625 +26985 -0.13787841796875 +26986 -0.218902587890625 +26987 -0.0802001953125 +26988 -0.063751220703125 +26989 -0.023040771484375 +26990 0.091552734375 +26991 0.03411865234375 +26992 0.23602294921875 +26993 0.0872802734375 +26994 0.342987060546875 +26995 0.12677001953125 +26996 0.39520263671875 +26997 0.1463623046875 +26998 0.389373779296875 +26999 0.144805908203125 +27000 0.324249267578125 +27001 0.12164306640625 +27002 0.224090576171875 +27003 0.085601806640625 +27004 0.124267578125 +27005 0.0494384765625 +27006 0.037078857421875 +27007 0.017578125 +27008 -0.010101318359375 +27009 -9.1552734375e-05 +27010 -0.019439697265625 +27011 -0.0042724609375 +27012 -0.022796630859375 +27013 -0.00640869140625 +27014 -0.001556396484375 +27015 0.000244140625 +27016 0.056304931640625 +27017 0.020050048828125 +27018 0.106719970703125 +27019 0.03717041015625 +27020 0.096893310546875 +27021 0.032684326171875 +27022 0.042694091796875 +27023 0.012359619140625 +27024 -0.018035888671875 +27025 -0.010101318359375 +27026 -0.07586669921875 +27027 -0.031280517578125 +27028 -0.11944580078125 +27029 -0.047088623046875 +27030 -0.15972900390625 +27031 -0.06146240234375 +27032 -0.202606201171875 +27033 -0.076507568359375 +27034 -0.24859619140625 +27035 -0.092437744140625 +27036 -0.30517578125 +27037 -0.111968994140625 +27038 -0.36212158203125 +27039 -0.131500244140625 +27040 -0.39141845703125 +27041 -0.14105224609375 +27042 -0.35528564453125 +27043 -0.1270751953125 +27044 -0.249969482421875 +27045 -0.088226318359375 +27046 -0.092864990234375 +27047 -0.030853271484375 +27048 0.08905029296875 +27049 0.0352783203125 +27050 0.2352294921875 +27051 0.08831787109375 +27052 0.318817138671875 +27053 0.118621826171875 +27054 0.358642578125 +27055 0.132965087890625 +27056 0.347747802734375 +27057 0.128814697265625 +27058 0.28564453125 +27059 0.106048583984375 +27060 0.223175048828125 +27061 0.0830078125 +27062 0.196746826171875 +27063 0.07281494140625 +27064 0.179840087890625 +27065 0.06597900390625 +27066 0.155548095703125 +27067 0.056427001953125 +27068 0.151214599609375 +27069 0.0540771484375 +27070 0.156951904296875 +27071 0.055419921875 +27072 0.13177490234375 +27073 0.045684814453125 +27074 0.100799560546875 +27075 0.033966064453125 +27076 0.087127685546875 +27077 0.028594970703125 +27078 0.05487060546875 +27079 0.016693115234375 +27080 -0.009002685546875 +27081 -0.00640869140625 +27082 -0.10400390625 +27083 -0.040496826171875 +27084 -0.229400634765625 +27085 -0.0853271484375 +27086 -0.35552978515625 +27087 -0.130279541015625 +27088 -0.441925048828125 +27089 -0.160797119140625 +27090 -0.473846435546875 +27091 -0.171600341796875 +27092 -0.464813232421875 +27093 -0.1676025390625 +27094 -0.419097900390625 +27095 -0.150390625 +27096 -0.334320068359375 +27097 -0.119140625 +27098 -0.227935791015625 +27099 -0.080169677734375 +27100 -0.12347412109375 +27101 -0.0419921875 +27102 -0.02764892578125 +27103 -0.007049560546875 +27104 0.077667236328125 +27105 0.0311279296875 +27106 0.2132568359375 +27107 0.08001708984375 +27108 0.38885498046875 +27109 0.14312744140625 +27110 0.582794189453125 +27111 0.212677001953125 +27112 0.734039306640625 +27113 0.2667236328125 +27114 0.800140380859375 +27115 0.28997802734375 +27116 0.7783203125 +27117 0.281494140625 +27118 0.6651611328125 +27119 0.240081787109375 +27120 0.45965576171875 +27121 0.165435791015625 +27122 0.199188232421875 +27123 0.071044921875 +27124 -0.050689697265625 +27125 -0.01947021484375 +27126 -0.23297119140625 +27127 -0.085540771484375 +27128 -0.33013916015625 +27129 -0.120880126953125 +27130 -0.368408203125 +27131 -0.1348876953125 +27132 -0.378936767578125 +27133 -0.13873291015625 +27134 -0.376983642578125 +27135 -0.137969970703125 +27136 -0.37969970703125 +27137 -0.13885498046875 +27138 -0.391510009765625 +27139 -0.1429443359375 +27140 -0.385345458984375 +27141 -0.139923095703125 +27142 -0.3419189453125 +27143 -0.122467041015625 +27144 -0.28289794921875 +27145 -0.099273681640625 +27146 -0.251617431640625 +27147 -0.087432861328125 +27148 -0.266143798828125 +27149 -0.094085693359375 +27150 -0.273345947265625 +27151 -0.098419189453125 +27152 -0.216796875 +27153 -0.0782470703125 +27154 -0.128265380859375 +27155 -0.0458984375 +27156 -0.068145751953125 +27157 -0.02490234375 +27158 -0.0430908203125 +27159 -0.017730712890625 +27160 -0.024444580078125 +27161 -0.01300048828125 +27162 0.020721435546875 +27163 0.0023193359375 +27164 0.124481201171875 +27165 0.040924072265625 +27166 0.25787353515625 +27167 0.091583251953125 +27168 0.379119873046875 +27169 0.138031005859375 +27170 0.47991943359375 +27171 0.177032470703125 +27172 0.5281982421875 +27173 0.196044921875 +27174 0.511138916015625 +27175 0.190032958984375 +27176 0.456207275390625 +27177 0.169708251953125 +27178 0.407470703125 +27179 0.15228271484375 +27180 0.383758544921875 +27181 0.14501953125 +27182 0.35687255859375 +27183 0.136749267578125 +27184 0.31182861328125 +27185 0.1214599609375 +27186 0.250885009765625 +27187 0.09991455078125 +27188 0.1654052734375 +27189 0.068572998046875 +27190 0.035247802734375 +27191 0.01947021484375 +27192 -0.142059326171875 +27193 -0.0484619140625 +27194 -0.33563232421875 +27195 -0.123199462890625 +27196 -0.5345458984375 +27197 -0.20050048828125 +27198 -0.72186279296875 +27199 -0.27374267578125 +27200 -0.836669921875 +27201 -0.31903076171875 +27202 -0.8326416015625 +27203 -0.31817626953125 +27204 -0.7296142578125 +27205 -0.278900146484375 +27206 -0.582550048828125 +27207 -0.22271728515625 +27208 -0.440093994140625 +27209 -0.1685791015625 +27210 -0.324310302734375 +27211 -0.12506103515625 +27212 -0.20147705078125 +27213 -0.078826904296875 +27214 -0.044647216796875 +27215 -0.019195556640625 +27216 0.103973388671875 +27217 0.037353515625 +27218 0.202392578125 +27219 0.074462890625 +27220 0.264495849609375 +27221 0.097625732421875 +27222 0.338897705078125 +27223 0.125946044921875 +27224 0.443817138671875 +27225 0.1666259765625 +27226 0.545074462890625 +27227 0.206268310546875 +27228 0.6173095703125 +27229 0.23492431640625 +27230 0.6524658203125 +27231 0.249420166015625 +27232 0.66339111328125 +27233 0.254730224609375 +27234 0.6561279296875 +27235 0.253173828125 +27236 0.606781005859375 +27237 0.23529052734375 +27238 0.501190185546875 +27239 0.195465087890625 +27240 0.352783203125 +27241 0.13885498046875 +27242 0.176544189453125 +27243 0.071258544921875 +27244 -0.034820556640625 +27245 -0.01025390625 +27246 -0.258209228515625 +27247 -0.0966796875 +27248 -0.44244384765625 +27249 -0.16802978515625 +27250 -0.5753173828125 +27251 -0.21954345703125 +27252 -0.65203857421875 +27253 -0.249359130859375 +27254 -0.641632080078125 +27255 -0.245330810546875 +27256 -0.562164306640625 +27257 -0.21453857421875 +27258 -0.458038330078125 +27259 -0.17437744140625 +27260 -0.350555419921875 +27261 -0.133148193359375 +27262 -0.260528564453125 +27263 -0.098968505859375 +27264 -0.192108154296875 +27265 -0.073394775390625 +27266 -0.141937255859375 +27267 -0.055023193359375 +27268 -0.1021728515625 +27269 -0.04071044921875 +27270 -0.062896728515625 +27271 -0.0264892578125 +27272 -0.011932373046875 +27273 -0.007537841796875 +27274 0.062835693359375 +27275 0.02093505859375 +27276 0.148712158203125 +27277 0.05401611328125 +27278 0.241729736328125 +27279 0.09014892578125 +27280 0.34912109375 +27281 0.132171630859375 +27282 0.457305908203125 +27283 0.174774169921875 +27284 0.54388427734375 +27285 0.209136962890625 +27286 0.5728759765625 +27287 0.22113037109375 +27288 0.506591796875 +27289 0.195953369140625 +27290 0.351226806640625 +27291 0.135955810546875 +27292 0.146514892578125 +27293 0.056671142578125 +27294 -0.05523681640625 +27295 -0.021392822265625 +27296 -0.21624755859375 +27297 -0.083526611328125 +27298 -0.334930419921875 +27299 -0.129150390625 +27300 -0.402984619140625 +27301 -0.155029296875 +27302 -0.4412841796875 +27303 -0.16937255859375 +27304 -0.49578857421875 +27305 -0.190277099609375 +27306 -0.5601806640625 +27307 -0.21527099609375 +27308 -0.600738525390625 +27309 -0.23114013671875 +27310 -0.584228515625 +27311 -0.224884033203125 +27312 -0.47930908203125 +27313 -0.18414306640625 +27314 -0.27935791015625 +27315 -0.1063232421875 +27316 -0.0089111328125 +27317 -0.00103759765625 +27318 0.268798828125 +27319 0.106964111328125 +27320 0.482818603515625 +27321 0.189910888671875 +27322 0.60369873046875 +27323 0.236328125 +27324 0.650421142578125 +27325 0.253692626953125 +27326 0.66400146484375 +27327 0.258148193359375 +27328 0.6414794921875 +27329 0.24859619140625 +27330 0.572540283203125 +27331 0.221038818359375 +27332 0.498138427734375 +27333 0.1915283203125 +27334 0.439453125 +27335 0.16839599609375 +27336 0.375518798828125 +27337 0.1434326171875 +27338 0.274505615234375 +27339 0.104156494140625 +27340 0.1087646484375 +27341 0.0396728515625 +27342 -0.099395751953125 +27343 -0.041290283203125 +27344 -0.3182373046875 +27345 -0.126312255859375 +27346 -0.5489501953125 +27347 -0.21588134765625 +27348 -0.7738037109375 +27349 -0.3031005859375 +27350 -0.86383056640625 +27351 -0.367279052734375 +27352 -0.870391845703125 +27353 -0.39544677734375 +27354 -0.86895751953125 +27355 -0.394561767578125 +27356 -0.861053466796875 +27357 -0.36981201171875 +27358 -0.765869140625 +27359 -0.314453125 +27360 -0.5301513671875 +27361 -0.22412109375 +27362 -0.214691162109375 +27363 -0.101593017578125 +27364 0.137359619140625 +27365 0.036285400390625 +27366 0.474822998046875 +27367 0.16937255859375 +27368 0.76239013671875 +27369 0.2838134765625 +27370 0.867462158203125 +27371 0.3690185546875 +27372 0.870361328125 +27373 0.42523193359375 +27374 0.86480712890625 +27375 0.44793701171875 +27376 0.831817626953125 +27377 0.439300537109375 +27378 0.677581787109375 +27379 0.408905029296875 +27380 0.495880126953125 +27381 0.359039306640625 +27382 0.30767822265625 +27383 0.297027587890625 +27384 0.116180419921875 +27385 0.223785400390625 +27386 -0.110748291015625 +27387 0.12689208984375 +27388 -0.381805419921875 +27389 0.003662109375 +27390 -0.6572265625 +27391 -0.129119873046875 +27392 -0.857421875 +27393 -0.247833251953125 +27394 -0.870391845703125 +27395 -0.335540771484375 +27396 -0.870391845703125 +27397 -0.389617919921875 +27398 -0.86444091796875 +27399 -0.4215087890625 +27400 -0.85723876953125 +27401 -0.446197509765625 +27402 -0.790008544921875 +27403 -0.4556884765625 +27404 -0.62847900390625 +27405 -0.4267578125 +27406 -0.3956298828125 +27407 -0.35772705078125 +27408 -0.126708984375 +27409 -0.262176513671875 +27410 0.150115966796875 +27411 -0.151275634765625 +27412 0.424041748046875 +27413 -0.02960205078125 +27414 0.670623779296875 +27415 0.091827392578125 +27416 0.854522705078125 +27417 0.19696044921875 +27418 0.866485595703125 +27419 0.278656005859375 +27420 0.86920166015625 +27421 0.3306884765625 +27422 0.8653564453125 +27423 0.3609619140625 +27424 0.857147216796875 +27425 0.37530517578125 +27426 0.766845703125 +27427 0.37255859375 +27428 0.628509521484375 +27429 0.3548583984375 +27430 0.462127685546875 +27431 0.31927490234375 +27432 0.297210693359375 +27433 0.276580810546875 +27434 0.14862060546875 +27435 0.231781005859375 +27436 -0.00537109375 +27437 0.174957275390625 +27438 -0.15753173828125 +27439 0.108978271484375 +27440 -0.31304931640625 +27441 0.032012939453125 +27442 -0.48876953125 +27443 -0.062164306640625 +27444 -0.6416015625 +27445 -0.153961181640625 +27446 -0.751373291015625 +27447 -0.233123779296875 +27448 -0.84619140625 +27449 -0.30963134765625 +27450 -0.861297607421875 +27451 -0.377410888671875 +27452 -0.863250732421875 +27453 -0.4224853515625 +27454 -0.856597900390625 +27455 -0.43145751953125 +27456 -0.7498779296875 +27457 -0.40948486328125 +27458 -0.624542236328125 +27459 -0.3809814453125 +27460 -0.47808837890625 +27461 -0.336456298828125 +27462 -0.253387451171875 +27463 -0.250946044921875 +27464 0.003692626953125 +27465 -0.1435546875 +27466 0.2257080078125 +27467 -0.043060302734375 +27468 0.427154541015625 +27469 0.05609130859375 +27470 0.643218994140625 +27471 0.1678466796875 +27472 0.855926513671875 +27473 0.288330078125 +27474 0.870361328125 +27475 0.39312744140625 +27476 0.870361328125 +27477 0.461334228515625 +27478 0.862762451171875 +27479 0.49609375 +27480 0.79669189453125 +27481 0.49615478515625 +27482 0.595794677734375 +27483 0.45751953125 +27484 0.362152099609375 +27485 0.39251708984375 +27486 0.1270751953125 +27487 0.312896728515625 +27488 -0.086944580078125 +27489 0.227508544921875 +27490 -0.2784423828125 +27491 0.1370849609375 +27492 -0.484832763671875 +27493 0.02667236328125 +27494 -0.729583740234375 +27495 -0.111968994140625 +27496 -0.86688232421875 +27497 -0.257568359375 +27498 -0.870391845703125 +27499 -0.3834228515625 +27500 -0.86859130859375 +27501 -0.487548828125 +27502 -0.86279296875 +27503 -0.569122314453125 +27504 -0.817962646484375 +27505 -0.613006591796875 +27506 -0.6116943359375 +27507 -0.599945068359375 +27508 -0.3128662109375 +27509 -0.526947021484375 +27510 0.039398193359375 +27511 -0.408233642578125 +27512 0.422821044921875 +27513 -0.252227783203125 +27514 0.805145263671875 +27515 -0.072967529296875 +27516 0.870361328125 +27517 0.100738525390625 +27518 0.870361328125 +27519 0.24481201171875 +27520 0.860015869140625 +27521 0.354339599609375 +27522 0.727935791015625 +27523 0.426116943359375 +27524 0.48114013671875 +27525 0.45782470703125 +27526 0.2059326171875 +27527 0.459716796875 +27528 -0.06103515625 +27529 0.441375732421875 +27530 -0.29913330078125 +27531 0.407073974609375 +27532 -0.516204833984375 +27533 0.35064697265625 +27534 -0.7252197265625 +27535 0.26556396484375 +27536 -0.85980224609375 +27537 0.162445068359375 +27538 -0.870391845703125 +27539 0.05584716796875 +27540 -0.870391845703125 +27541 -0.0416259765625 +27542 -0.858062744140625 +27543 -0.1092529296875 +27544 -0.673004150390625 +27545 -0.145172119140625 +27546 -0.42694091796875 +27547 -0.171539306640625 +27548 -0.2100830078125 +27549 -0.20709228515625 +27550 -0.0362548828125 +27551 -0.250762939453125 +27552 0.10943603515625 +27553 -0.290130615234375 +27554 0.23516845703125 +27555 -0.316680908203125 +27556 0.373687744140625 +27557 -0.312774658203125 +27558 0.517791748046875 +27559 -0.279205322265625 +27560 0.602783203125 +27561 -0.242706298828125 +27562 0.635711669921875 +27563 -0.201080322265625 +27564 0.655181884765625 +27565 -0.140289306640625 +27566 0.65948486328125 +27567 -0.064605712890625 +27568 0.651275634765625 +27569 0.02239990234375 +27570 0.61846923828125 +27571 0.110198974609375 +27572 0.53753662109375 +27573 0.182952880859375 +27574 0.404144287109375 +27575 0.232818603515625 +27576 0.22186279296875 +27577 0.255523681640625 +27578 0.003997802734375 +27579 0.251495361328125 +27580 -0.22100830078125 +27581 0.228302001953125 +27582 -0.42449951171875 +27583 0.194580078125 +27584 -0.579833984375 +27585 0.15936279296875 +27586 -0.641876220703125 +27587 0.1407470703125 +27588 -0.6177978515625 +27589 0.13592529296875 +27590 -0.575531005859375 +27591 0.1175537109375 +27592 -0.526336669921875 +27593 0.08343505859375 +27594 -0.42645263671875 +27595 0.0556640625 +27596 -0.2581787109375 +27597 0.045989990234375 +27598 -0.068695068359375 +27599 0.039154052734375 +27600 0.09222412109375 +27601 0.01898193359375 +27602 0.232147216796875 +27603 -0.00640869140625 +27604 0.3509521484375 +27605 -0.032562255859375 +27606 0.410064697265625 +27607 -0.0718994140625 +27608 0.372955322265625 +27609 -0.136749267578125 +27610 0.2554931640625 +27611 -0.2181396484375 +27612 0.10711669921875 +27613 -0.293914794921875 +27614 -0.052886962890625 +27615 -0.355743408203125 +27616 -0.186279296875 +27617 -0.38824462890625 +27618 -0.23291015625 +27619 -0.367767333984375 +27620 -0.209442138671875 +27621 -0.304046630859375 +27622 -0.174163818359375 +27623 -0.22509765625 +27624 -0.126739501953125 +27625 -0.13458251953125 +27626 -0.048126220703125 +27627 -0.028472900390625 +27628 0.0426025390625 +27629 0.08111572265625 +27630 0.10748291015625 +27631 0.17425537109375 +27632 0.1409912109375 +27633 0.245208740234375 +27634 0.19708251953125 +27635 0.31396484375 +27636 0.273651123046875 +27637 0.377532958984375 +27638 0.31768798828125 +27639 0.41217041015625 +27640 0.341094970703125 +27641 0.4224853515625 +27642 0.368011474609375 +27643 0.41912841796875 +27644 0.37249755859375 +27645 0.392333984375 +27646 0.30072021484375 +27647 0.321258544921875 +27648 0.1517333984375 +27649 0.208221435546875 +27650 -0.01470947265625 +27651 0.081695556640625 +27652 -0.1883544921875 +27653 -0.051513671875 +27654 -0.372711181640625 +27655 -0.189971923828125 +27656 -0.51397705078125 +27657 -0.306488037109375 +27658 -0.57177734375 +27659 -0.38006591796875 +27660 -0.53948974609375 +27661 -0.4052734375 +27662 -0.43511962890625 +27663 -0.388275146484375 +27664 -0.2962646484375 +27665 -0.344573974609375 +27666 -0.161102294921875 +27667 -0.290618896484375 +27668 -0.0435791015625 +27669 -0.232574462890625 +27670 0.060394287109375 +27671 -0.169219970703125 +27672 0.13665771484375 +27673 -0.10809326171875 +27674 0.170135498046875 +27675 -0.0577392578125 +27676 0.16552734375 +27677 -0.018218994140625 +27678 0.15728759765625 +27679 0.023529052734375 +27680 0.150787353515625 +27681 0.06732177734375 +27682 0.12200927734375 +27683 0.099761962890625 +27684 0.080108642578125 +27685 0.12255859375 +27686 0.05126953125 +27687 0.14532470703125 +27688 0.062896728515625 +27689 0.17864990234375 +27690 0.09271240234375 +27691 0.211151123046875 +27692 0.092987060546875 +27693 0.2205810546875 +27694 0.07855224609375 +27695 0.21337890625 +27696 0.06427001953125 +27697 0.196563720703125 +27698 0.0347900390625 +27699 0.164093017578125 +27700 -0.01171875 +27701 0.11639404296875 +27702 -0.056060791015625 +27703 0.063812255859375 +27704 -0.055511474609375 +27705 0.027496337890625 +27706 -0.010467529296875 +27707 0.009368896484375 +27708 0.02508544921875 +27709 -0.012664794921875 +27710 0.025665283203125 +27711 -0.048004150390625 +27712 0.017333984375 +27713 -0.08306884765625 +27714 0.00189208984375 +27715 -0.115447998046875 +27716 -0.03173828125 +27717 -0.14892578125 +27718 -0.071502685546875 +27719 -0.17730712890625 +27720 -0.13543701171875 +27721 -0.208343505859375 +27722 -0.219970703125 +27723 -0.24053955078125 +27724 -0.300506591796875 +27725 -0.26336669921875 +27726 -0.376312255859375 +27727 -0.277435302734375 +27728 -0.416107177734375 +27729 -0.269927978515625 +27730 -0.371124267578125 +27731 -0.220489501953125 +27732 -0.242279052734375 +27733 -0.131195068359375 +27734 -0.069732666015625 +27735 -0.02191162109375 +27736 0.125640869140625 +27737 0.09619140625 +27738 0.31268310546875 +27739 0.207489013671875 +27740 0.45501708984375 +27741 0.29425048828125 +27742 0.554779052734375 +27743 0.3563232421875 +27744 0.61065673828125 +27745 0.392364501953125 +27746 0.610931396484375 +27747 0.39666748046875 +27748 0.531463623046875 +27749 0.35833740234375 +27750 0.3883056640625 +27751 0.284912109375 +27752 0.23468017578125 +27753 0.201019287109375 +27754 0.095245361328125 +27755 0.118743896484375 +27756 -0.00396728515625 +27757 0.050994873046875 +27758 -0.04852294921875 +27759 0.005615234375 +27760 -0.055145263671875 +27761 -0.023468017578125 +27762 -0.0758056640625 +27763 -0.05816650390625 +27764 -0.138702392578125 +27765 -0.109832763671875 +27766 -0.209197998046875 +27767 -0.161651611328125 +27768 -0.289031982421875 +27769 -0.213409423828125 +27770 -0.37884521484375 +27771 -0.264617919921875 +27772 -0.456329345703125 +27773 -0.3048095703125 +27774 -0.51641845703125 +27775 -0.33160400390625 +27776 -0.519287109375 +27777 -0.327239990234375 +27778 -0.458251953125 +27779 -0.289154052734375 +27780 -0.384796142578125 +27781 -0.241241455078125 +27782 -0.323699951171875 +27783 -0.195587158203125 +27784 -0.269287109375 +27785 -0.15069580078125 +27786 -0.1951904296875 +27787 -0.095916748046875 +27788 -0.100006103515625 +27789 -0.03179931640625 +27790 -0.01055908203125 +27791 0.02838134765625 +27792 0.1033935546875 +27793 0.09716796875 +27794 0.24908447265625 +27795 0.17694091796875 +27796 0.373199462890625 +27797 0.243072509765625 +27798 0.45806884765625 +27799 0.28717041015625 +27800 0.511474609375 +27801 0.3125 +27802 0.565399169921875 +27803 0.333526611328125 +27804 0.61138916015625 +27805 0.346771240234375 +27806 0.5897216796875 +27807 0.32586669921875 +27808 0.4906005859375 +27809 0.267120361328125 +27810 0.33148193359375 +27811 0.17926025390625 +27812 0.147796630859375 +27813 0.07916259765625 +27814 -0.01873779296875 +27815 -0.013397216796875 +27816 -0.140289306640625 +27817 -0.08489990234375 +27818 -0.191986083984375 +27819 -0.123291015625 +27820 -0.184295654296875 +27821 -0.13250732421875 +27822 -0.161834716796875 +27823 -0.13201904296875 +27824 -0.166595458984375 +27825 -0.1402587890625 +27826 -0.19390869140625 +27827 -0.1549072265625 +27828 -0.22442626953125 +27829 -0.167205810546875 +27830 -0.279754638671875 +27831 -0.18707275390625 +27832 -0.3389892578125 +27833 -0.205474853515625 +27834 -0.3543701171875 +27835 -0.201507568359375 +27836 -0.348175048828125 +27837 -0.18585205078125 +27838 -0.32598876953125 +27839 -0.161773681640625 +27840 -0.2581787109375 +27841 -0.11676025390625 +27842 -0.139801025390625 +27843 -0.049346923828125 +27844 0.014617919921875 +27845 0.03314208984375 +27846 0.144378662109375 +27847 0.102691650390625 +27848 0.221038818359375 +27849 0.145965576171875 +27850 0.27069091796875 +27851 0.174285888671875 +27852 0.294036865234375 +27853 0.187744140625 +27854 0.311767578125 +27855 0.195587158203125 +27856 0.339141845703125 +27857 0.204803466796875 +27858 0.360260009765625 +27859 0.20855712890625 +27860 0.360504150390625 +27861 0.20062255859375 +27862 0.308380126953125 +27863 0.1671142578125 +27864 0.18170166015625 +27865 0.098480224609375 +27866 0.0047607421875 +27867 0.006439208984375 +27868 -0.17559814453125 +27869 -0.087005615234375 +27870 -0.3143310546875 +27871 -0.1607666015625 +27872 -0.36785888671875 +27873 -0.194427490234375 +27874 -0.36248779296875 +27875 -0.199493408203125 +27876 -0.343536376953125 +27877 -0.196258544921875 +27878 -0.3018798828125 +27879 -0.18035888671875 +27880 -0.231414794921875 +27881 -0.148895263671875 +27882 -0.117645263671875 +27883 -0.095306396484375 +27884 0.007049560546875 +27885 -0.034515380859375 +27886 0.087982177734375 +27887 0.008270263671875 +27888 0.13946533203125 +27889 0.0391845703125 +27890 0.17425537109375 +27891 0.0635986328125 +27892 0.188201904296875 +27893 0.079132080078125 +27894 0.171234130859375 +27895 0.080657958984375 +27896 0.118438720703125 +27897 0.065460205078125 +27898 0.05706787109375 +27899 0.045501708984375 +27900 -0.010711669921875 +27901 0.021331787109375 +27902 -0.0914306640625 +27903 -0.0103759765625 +27904 -0.162322998046875 +27905 -0.03985595703125 +27906 -0.194549560546875 +27907 -0.053924560546875 +27908 -0.1492919921875 +27909 -0.033355712890625 +27910 -0.02166748046875 +27911 0.02471923828125 +27912 0.124053955078125 +27913 0.08953857421875 +27914 0.211151123046875 +27915 0.124237060546875 +27916 0.240447998046875 +27917 0.12982177734375 +27918 0.242218017578125 +27919 0.121612548828125 +27920 0.2257080078125 +27921 0.104736328125 +27922 0.194366455078125 +27923 0.081329345703125 +27924 0.115509033203125 +27925 0.035858154296875 +27926 0.0128173828125 +27927 -0.01971435546875 +27928 -0.053802490234375 +27929 -0.05596923828125 +27930 -0.110626220703125 +27931 -0.0855712890625 +27932 -0.199493408203125 +27933 -0.128936767578125 +27934 -0.29437255859375 +27935 -0.1734619140625 +27936 -0.33221435546875 +27937 -0.18853759765625 +27938 -0.27972412109375 +27939 -0.158172607421875 +27940 -0.185333251953125 +27941 -0.106292724609375 +27942 -0.128204345703125 +27943 -0.071868896484375 +27944 -0.115692138671875 +27945 -0.058868408203125 +27946 -0.116455078125 +27947 -0.0523681640625 +27948 -0.105926513671875 +27949 -0.040802001953125 +27950 -0.053955078125 +27951 -0.009765625 +27952 0.048797607421875 +27953 0.04498291015625 +27954 0.157318115234375 +27955 0.10125732421875 +27956 0.212005615234375 +27957 0.129852294921875 +27958 0.218475341796875 +27959 0.133392333984375 +27960 0.23724365234375 +27961 0.141448974609375 +27962 0.30535888671875 +27963 0.172210693359375 +27964 0.38128662109375 +27965 0.20556640625 +27966 0.404449462890625 +27967 0.212188720703125 +27968 0.3944091796875 +27969 0.201934814453125 +27970 0.3885498046875 +27971 0.193359375 +27972 0.362640380859375 +27973 0.174957275390625 +27974 0.27362060546875 +27975 0.12603759765625 +27976 0.11712646484375 +27977 0.04473876953125 +27978 -0.054901123046875 +27979 -0.04327392578125 +27980 -0.19085693359375 +27981 -0.112640380859375 +27982 -0.28570556640625 +27983 -0.1607666015625 +27984 -0.339263916015625 +27985 -0.187530517578125 +27986 -0.3775634765625 +27987 -0.20562744140625 +27988 -0.445709228515625 +27989 -0.23712158203125 +27990 -0.535064697265625 +27991 -0.277923583984375 +27992 -0.629058837890625 +27993 -0.320159912109375 +27994 -0.697601318359375 +27995 -0.349334716796875 +27996 -0.70391845703125 +27997 -0.347747802734375 +27998 -0.6424560546875 +27999 -0.31298828125 +28000 -0.491241455078125 +28001 -0.234588623046875 +28002 -0.265716552734375 +28003 -0.120330810546875 +28004 -0.023712158203125 +28005 0.001312255859375 +28006 0.201751708984375 +28007 0.11407470703125 +28008 0.375823974609375 +28009 0.200836181640625 +28010 0.485076904296875 +28011 0.254974365234375 +28012 0.56884765625 +28013 0.295654296875 +28014 0.634765625 +28015 0.326629638671875 +28016 0.63763427734375 +28017 0.325958251953125 +28018 0.5660400390625 +28019 0.2882080078125 +28020 0.4720458984375 +28021 0.23895263671875 +28022 0.40692138671875 +28023 0.203399658203125 +28024 0.3778076171875 +28025 0.18524169921875 +28026 0.376953125 +28027 0.180938720703125 +28028 0.371978759765625 +28029 0.174896240234375 +28030 0.313140869140625 +28031 0.143035888671875 +28032 0.184417724609375 +28033 0.07769775390625 +28034 0.011199951171875 +28035 -0.00860595703125 +28036 -0.171051025390625 +28037 -0.09844970703125 +28038 -0.33740234375 +28039 -0.179656982421875 +28040 -0.47198486328125 +28041 -0.244537353515625 +28042 -0.560394287109375 +28043 -0.2861328125 +28044 -0.58056640625 +28045 -0.293792724609375 +28046 -0.54754638671875 +28047 -0.27496337890625 +28048 -0.508575439453125 +28049 -0.252899169921875 +28050 -0.459503173828125 +28051 -0.2257080078125 +28052 -0.394378662109375 +28053 -0.190704345703125 +28054 -0.35260009765625 +28055 -0.167266845703125 +28056 -0.31170654296875 +28057 -0.14459228515625 +28058 -0.197418212890625 +28059 -0.086578369140625 +28060 -0.007965087890625 +28061 0.007537841796875 +28062 0.207489013671875 +28063 0.113677978515625 +28064 0.409210205078125 +28065 0.212371826171875 +28066 0.57208251953125 +28067 0.291412353515625 +28068 0.66595458984375 +28069 0.33612060546875 +28070 0.65875244140625 +28071 0.3309326171875 +28072 0.56744384765625 +28073 0.284210205078125 +28074 0.431396484375 +28075 0.21533203125 +28076 0.29443359375 +28077 0.145843505859375 +28078 0.182464599609375 +28079 0.0885009765625 +28080 0.06365966796875 +28081 0.027923583984375 +28082 -0.075958251953125 +28083 -0.04254150390625 +28084 -0.189422607421875 +28085 -0.099853515625 +28086 -0.271942138671875 +28087 -0.141571044921875 +28088 -0.342529296875 +28089 -0.176910400390625 +28090 -0.364166259765625 +28091 -0.18780517578125 +28092 -0.327239990234375 +28093 -0.169586181640625 +28094 -0.2769775390625 +28095 -0.144317626953125 +28096 -0.253692626953125 +28097 -0.1317138671875 +28098 -0.24365234375 +28099 -0.12518310546875 +28100 -0.1983642578125 +28101 -0.101165771484375 +28102 -0.116241455078125 +28103 -0.058990478515625 +28104 -0.036834716796875 +28105 -0.018035888671875 +28106 0.034881591796875 +28107 0.01910400390625 +28108 0.09124755859375 +28109 0.048583984375 +28110 0.10888671875 +28111 0.05889892578125 +28112 0.125518798828125 +28113 0.068328857421875 +28114 0.15771484375 +28115 0.084930419921875 +28116 0.17828369140625 +28117 0.09539794921875 +28118 0.17108154296875 +28119 0.09185791015625 +28120 0.129974365234375 +28121 0.071319580078125 +28122 0.082427978515625 +28123 0.047210693359375 +28124 0.027679443359375 +28125 0.01922607421875 +28126 -0.065643310546875 +28127 -0.027801513671875 +28128 -0.15936279296875 +28129 -0.075164794921875 +28130 -0.21307373046875 +28131 -0.10308837890625 +28132 -0.234649658203125 +28133 -0.11529541015625 +28134 -0.2001953125 +28135 -0.10003662109375 +28136 -0.119171142578125 +28137 -0.061859130859375 +28138 -0.024749755859375 +28139 -0.01690673828125 +28140 0.085784912109375 +28141 0.03619384765625 +28142 0.178131103515625 +28143 0.080718994140625 +28144 0.215576171875 +28145 0.098785400390625 +28146 0.211456298828125 +28147 0.096923828125 +28148 0.17523193359375 +28149 0.079742431640625 +28150 0.128753662109375 +28151 0.057861328125 +28152 0.1019287109375 +28153 0.04583740234375 +28154 0.0743408203125 +28155 0.033660888671875 +28156 0.04327392578125 +28157 0.0198974609375 +28158 0.038177490234375 +28159 0.018829345703125 +28160 0.076263427734375 +28161 0.039337158203125 +28162 0.14105224609375 +28163 0.073760986328125 +28164 0.186431884765625 +28165 0.0986328125 +28166 0.188812255859375 +28167 0.1014404296875 +28168 0.1390380859375 +28169 0.07720947265625 +28170 0.041778564453125 +28171 0.0281982421875 +28172 -0.079437255859375 +28173 -0.03350830078125 +28174 -0.219390869140625 +28175 -0.1053466796875 +28176 -0.367828369140625 +28177 -0.182037353515625 +28178 -0.494873046875 +28179 -0.24810791015625 +28180 -0.556243896484375 +28181 -0.280548095703125 +28182 -0.508697509765625 +28183 -0.256866455078125 +28184 -0.3756103515625 +28185 -0.189117431640625 +28186 -0.218902587890625 +28187 -0.109405517578125 +28188 -0.063751220703125 +28189 -0.03070068359375 +28190 0.091552734375 +28191 0.047943115234375 +28192 0.23602294921875 +28193 0.1209716796875 +28194 0.342987060546875 +28195 0.17462158203125 +28196 0.39520263671875 +28197 0.200042724609375 +28198 0.389373779296875 +28199 0.19561767578125 +28200 0.324249267578125 +28201 0.1607666015625 +28202 0.224090576171875 +28203 0.108154296875 +28204 0.124267578125 +28205 0.05621337890625 +28206 0.037078857421875 +28207 0.01129150390625 +28208 -0.010101318359375 +28209 -0.01239013671875 +28210 -0.019439697265625 +28211 -0.016021728515625 +28212 -0.022796630859375 +28213 -0.0162353515625 +28214 -0.001556396484375 +28215 -0.00341796875 +28216 0.056304931640625 +28217 0.028533935546875 +28218 0.106719970703125 +28219 0.05657958984375 +28220 0.096893310546875 +28221 0.053192138671875 +28222 0.042694091796875 +28223 0.026519775390625 +28224 -0.018035888671875 +28225 -0.003814697265625 +28226 -0.07586669921875 +28227 -0.032958984375 +28228 -0.11944580078125 +28229 -0.0550537109375 +28230 -0.15972900390625 +28231 -0.075836181640625 +28232 -0.202606201171875 +28233 -0.098358154296875 +28234 -0.24859619140625 +28235 -0.12286376953125 +28236 -0.30517578125 +28237 -0.153167724609375 +28238 -0.36212158203125 +28239 -0.183929443359375 +28240 -0.39141845703125 +28241 -0.20050048828125 +28242 -0.35528564453125 +28243 -0.183135986328125 +28244 -0.249969482421875 +28245 -0.129852294921875 +28246 -0.092864990234375 +28247 -0.049591064453125 +28248 0.08905029296875 +28249 0.043670654296875 +28250 0.2352294921875 +28251 0.1185302734375 +28252 0.318817138671875 +28253 0.16107177734375 +28254 0.358642578125 +28255 0.181121826171875 +28256 0.347747802734375 +28257 0.17510986328125 +28258 0.28564453125 +28259 0.142791748046875 +28260 0.223175048828125 +28261 0.110595703125 +28262 0.196746826171875 +28263 0.097442626953125 +28264 0.179840087890625 +28265 0.089508056640625 +28266 0.155548095703125 +28267 0.07794189453125 +28268 0.151214599609375 +28269 0.076873779296875 +28270 0.156951904296875 +28271 0.08111572265625 +28272 0.13177490234375 +28273 0.069244384765625 +28274 0.100799560546875 +28275 0.05426025390625 +28276 0.087127685546875 +28277 0.04815673828125 +28278 0.05487060546875 +28279 0.0322265625 +28280 -0.009002685546875 +28281 -0.0003662109375 +28282 -0.10400390625 +28283 -0.04937744140625 +28284 -0.229400634765625 +28285 -0.11444091796875 +28286 -0.35552978515625 +28287 -0.180145263671875 +28288 -0.441925048828125 +28289 -0.22540283203125 +28290 -0.473846435546875 +28291 -0.2425537109375 +28292 -0.464813232421875 +28293 -0.238555908203125 +28294 -0.419097900390625 +28295 -0.215606689453125 +28296 -0.334320068359375 +28297 -0.17242431640625 +28298 -0.227935791015625 +28299 -0.118011474609375 +28300 -0.12347412109375 +28301 -0.064605712890625 +28302 -0.02764892578125 +28303 -0.015655517578125 +28304 0.077667236328125 +28305 0.038330078125 +28306 0.2132568359375 +28307 0.108184814453125 +28308 0.38885498046875 +28309 0.199005126953125 +28310 0.582794189453125 +28311 0.299560546875 +28312 0.734039306640625 +28313 0.37811279296875 +28314 0.800140380859375 +28315 0.41259765625 +28316 0.7783203125 +28317 0.401519775390625 +28318 0.6651611328125 +28319 0.343109130859375 +28320 0.45965576171875 +28321 0.23681640625 +28322 0.199188232421875 +28323 0.10205078125 +28324 -0.050689697265625 +28325 -0.027099609375 +28326 -0.23297119140625 +28327 -0.121063232421875 +28328 -0.33013916015625 +28329 -0.1707763671875 +28330 -0.368408203125 +28331 -0.18994140625 +28332 -0.378936767578125 +28333 -0.19476318359375 +28334 -0.376983642578125 +28335 -0.1932373046875 +28336 -0.37969970703125 +28337 -0.194305419921875 +28338 -0.391510009765625 +28339 -0.20025634765625 +28340 -0.385345458984375 +28341 -0.197052001953125 +28342 -0.3419189453125 +28343 -0.17462158203125 +28344 -0.28289794921875 +28345 -0.14422607421875 +28346 -0.251617431640625 +28347 -0.128387451171875 +28348 -0.266143798828125 +28349 -0.136474609375 +28350 -0.273345947265625 +28351 -0.140838623046875 +28352 -0.216796875 +28353 -0.112091064453125 +28354 -0.128265380859375 +28355 -0.06671142578125 +28356 -0.068145751953125 +28357 -0.036041259765625 +28358 -0.0430908203125 +28359 -0.02349853515625 +28360 -0.024444580078125 +28361 -0.014190673828125 +28362 0.020721435546875 +28363 0.009002685546875 +28364 0.124481201171875 +28365 0.062744140625 +28366 0.25787353515625 +28367 0.131988525390625 +28368 0.379119873046875 +28369 0.19500732421875 +28370 0.47991943359375 +28371 0.247528076171875 +28372 0.5281982421875 +28373 0.272857666015625 +28374 0.511138916015625 +28375 0.2642822265625 +28376 0.456207275390625 +28377 0.236083984375 +28378 0.407470703125 +28379 0.211151123046875 +28380 0.383758544921875 +28381 0.19927978515625 +28382 0.35687255859375 +28383 0.185760498046875 +28384 0.31182861328125 +28385 0.16278076171875 +28386 0.250885009765625 +28387 0.1314697265625 +28388 0.1654052734375 +28389 0.087310791015625 +28390 0.035247802734375 +28391 0.01983642578125 +28392 -0.142059326171875 +28393 -0.072235107421875 +28394 -0.33563232421875 +28395 -0.1728515625 +28396 -0.5345458984375 +28397 -0.27630615234375 +28398 -0.72186279296875 +28399 -0.373779296875 +28400 -0.836669921875 +28401 -0.43359375 +28402 -0.8326416015625 +28403 -0.431671142578125 +28404 -0.7296142578125 +28405 -0.378326416015625 +28406 -0.582550048828125 +28407 -0.3021240234375 +28408 -0.440093994140625 +28409 -0.22833251953125 +28410 -0.324310302734375 +28411 -0.168426513671875 +28412 -0.20147705078125 +28413 -0.1048583984375 +28414 -0.044647216796875 +28415 -0.023590087890625 +28416 0.103973388671875 +28417 0.052886962890625 +28418 0.202392578125 +28419 0.102081298828125 +28420 0.264495849609375 +28421 0.131866455078125 +28422 0.338897705078125 +28423 0.169342041015625 +28424 0.443817138671875 +28425 0.2247314453125 +28426 0.545074462890625 +28427 0.279296875 +28428 0.6173095703125 +28429 0.319061279296875 +28430 0.6524658203125 +28431 0.33953857421875 +28432 0.66339111328125 +28433 0.347747802734375 +28434 0.6561279296875 +28435 0.346893310546875 +28436 0.606781005859375 +28437 0.32354736328125 +28438 0.501190185546875 +28439 0.2696533203125 +28440 0.352783203125 +28441 0.1923828125 +28442 0.176544189453125 +28443 0.099761962890625 +28444 -0.034820556640625 +28445 -0.012481689453125 +28446 -0.258209228515625 +28447 -0.1318359375 +28448 -0.44244384765625 +28449 -0.230255126953125 +28450 -0.5753173828125 +28451 -0.301116943359375 +28452 -0.65203857421875 +28453 -0.3419189453125 +28454 -0.641632080078125 +28455 -0.335662841796875 +28456 -0.562164306640625 +28457 -0.29229736328125 +28458 -0.458038330078125 +28459 -0.236297607421875 +28460 -0.350555419921875 +28461 -0.179290771484375 +28462 -0.260528564453125 +28463 -0.132598876953125 +28464 -0.192108154296875 +28465 -0.098358154296875 +28466 -0.141937255859375 +28467 -0.07452392578125 +28468 -0.1021728515625 +28469 -0.0565185546875 +28470 -0.062896728515625 +28471 -0.038665771484375 +28472 -0.011932373046875 +28473 -0.0140380859375 +28474 0.062835693359375 +28475 0.02423095703125 +28476 0.148712158203125 +28477 0.069305419921875 +28478 0.241729736328125 +28479 0.11907958984375 +28480 0.34912109375 +28481 0.177642822265625 +28482 0.457305908203125 +28483 0.23748779296875 +28484 0.54388427734375 +28485 0.28619384765625 +28486 0.5728759765625 +28487 0.303863525390625 +28488 0.506591796875 +28489 0.269561767578125 +28490 0.351226806640625 +28491 0.18658447265625 +28492 0.146514892578125 +28493 0.076690673828125 +28494 -0.05523681640625 +28495 -0.031402587890625 +28496 -0.21624755859375 +28497 -0.1170654296875 +28498 -0.334930419921875 +28499 -0.1795654296875 +28500 -0.402984619140625 +28501 -0.2144775390625 +28502 -0.4412841796875 +28503 -0.23345947265625 +28504 -0.49578857421875 +28505 -0.261993408203125 +28506 -0.5601806640625 +28507 -0.296630859375 +28508 -0.600738525390625 +28509 -0.318817138671875 +28510 -0.584228515625 +28511 -0.310211181640625 +28512 -0.47930908203125 +28513 -0.253448486328125 +28514 -0.27935791015625 +28515 -0.144775390625 +28516 -0.0089111328125 +28517 0.002349853515625 +28518 0.268798828125 +28519 0.15313720703125 +28520 0.482818603515625 +28521 0.268585205078125 +28522 0.60369873046875 +28523 0.33258056640625 +28524 0.650421142578125 +28525 0.355712890625 +28526 0.66400146484375 +28527 0.360809326171875 +28528 0.6414794921875 +28529 0.346343994140625 +28530 0.572540283203125 +28531 0.306732177734375 +28532 0.498138427734375 +28533 0.2646484375 +28534 0.439453125 +28535 0.231842041015625 +28536 0.375518798828125 +28537 0.19671630859375 +28538 0.274505615234375 +28539 0.141693115234375 +28540 0.1087646484375 +28541 0.05145263671875 +28542 -0.099395751953125 +28543 -0.061767578125 +28544 -0.3182373046875 +28545 -0.1805419921875 +28546 -0.5489501953125 +28547 -0.3056640625 +28548 -0.7738037109375 +28549 -0.42742919921875 +28550 -0.86383056640625 +28551 -0.516754150390625 +28552 -0.870391845703125 +28553 -0.555419921875 +28554 -0.86895751953125 +28555 -0.553314208984375 +28556 -0.861053466796875 +28557 -0.517791748046875 +28558 -0.765869140625 +28559 -0.439361572265625 +28560 -0.5301513671875 +28561 -0.311859130859375 +28562 -0.214691162109375 +28563 -0.13922119140625 +28564 0.137359619140625 +28565 0.054779052734375 +28566 0.474822998046875 +28567 0.24188232421875 +28568 0.76239013671875 +28569 0.402496337890625 +28570 0.867462158203125 +28571 0.521820068359375 +28572 0.870361328125 +28573 0.600189208984375 +28574 0.86480712890625 +28575 0.63134765625 +28576 0.831817626953125 +28577 0.618316650390625 +28578 0.677581787109375 +28579 0.574676513671875 +28580 0.495880126953125 +28581 0.503753662109375 +28582 0.30767822265625 +28583 0.415863037109375 +28584 0.116180419921875 +28585 0.312286376953125 +28586 -0.110748291015625 +28587 0.175567626953125 +28588 -0.381805419921875 +28589 0.001922607421875 +28590 -0.6572265625 +28591 -0.185028076171875 +28592 -0.857421875 +28593 -0.352203369140625 +28594 -0.870391845703125 +28595 -0.475982666015625 +28596 -0.870391845703125 +28597 -0.552490234375 +28598 -0.86444091796875 +28599 -0.596649169921875 +28600 -0.85723876953125 +28601 -0.62823486328125 +28602 -0.790008544921875 +28603 -0.63720703125 +28604 -0.62847900390625 +28605 -0.59368896484375 +28606 -0.3956298828125 +28607 -0.496002197265625 +28608 -0.126708984375 +28609 -0.36236572265625 +28610 0.150115966796875 +28611 -0.207977294921875 +28612 0.424041748046875 +28613 -0.03936767578125 +28614 0.670623779296875 +28615 0.128570556640625 +28616 0.854522705078125 +28617 0.2744140625 +28618 0.866485595703125 +28619 0.388427734375 +28620 0.86920166015625 +28621 0.46209716796875 +28622 0.8653564453125 +28623 0.505462646484375 +28624 0.857147216796875 +28625 0.5260009765625 +28626 0.766845703125 +28627 0.522186279296875 +28628 0.628509521484375 +28629 0.49688720703125 +28630 0.462127685546875 +28631 0.446441650390625 +28632 0.297210693359375 +28633 0.38519287109375 +28634 0.14862060546875 +28635 0.32000732421875 +28636 -0.00537109375 +28637 0.238372802734375 +28638 -0.15753173828125 +28639 0.144500732421875 +28640 -0.31304931640625 +28641 0.03643798828125 +28642 -0.48876953125 +28643 -0.093536376953125 +28644 -0.6416015625 +28645 -0.219512939453125 +28646 -0.751373291015625 +28647 -0.32781982421875 +28648 -0.84619140625 +28649 -0.43121337890625 +28650 -0.861297607421875 +28651 -0.521636962890625 +28652 -0.863250732421875 +28653 -0.580780029296875 +28654 -0.856597900390625 +28655 -0.591278076171875 +28656 -0.7498779296875 +28657 -0.559906005859375 +28658 -0.624542236328125 +28659 -0.5186767578125 +28660 -0.47808837890625 +28661 -0.45550537109375 +28662 -0.253387451171875 +28663 -0.338165283203125 +28664 0.003692626953125 +28665 -0.191925048828125 +28666 0.2257080078125 +28667 -0.0545654296875 +28668 0.427154541015625 +28669 0.080780029296875 +28670 0.643218994140625 +28671 0.231964111328125 +28672 0.855926513671875 +28673 0.39410400390625 +28674 0.870361328125 +28675 0.53521728515625 +28676 0.870361328125 +28677 0.627197265625 +28678 0.862762451171875 +28679 0.674224853515625 +28680 0.79669189453125 +28681 0.674468994140625 +28682 0.595794677734375 +28683 0.622161865234375 +28684 0.362152099609375 +28685 0.534088134765625 +28686 0.1270751953125 +28687 0.42626953125 +28688 -0.086944580078125 +28689 0.310699462890625 +28690 -0.2784423828125 +28691 0.188232421875 +28692 -0.484832763671875 +28693 0.0382080078125 +28694 -0.729583740234375 +28695 -0.15093994140625 +28696 -0.86688232421875 +28697 -0.3499755859375 +28698 -0.870391845703125 +28699 -0.522186279296875 +28700 -0.86859130859375 +28701 -0.664886474609375 +28702 -0.86279296875 +28703 -0.777008056640625 +28704 -0.817962646484375 +28705 -0.837615966796875 +28706 -0.6116943359375 +28707 -0.820220947265625 +28708 -0.3128662109375 +28709 -0.7205810546875 +28710 0.039398193359375 +28711 -0.558258056640625 +28712 0.422821044921875 +28713 -0.34478759765625 +28714 0.805145263671875 +28715 -0.099395751953125 +28716 0.870361328125 +28717 0.138336181640625 +28718 0.870361328125 +28719 0.3353271484375 +28720 0.860015869140625 +28721 0.48492431640625 +28722 0.727935791015625 +28723 0.582763671875 +28724 0.48114013671875 +28725 0.625640869140625 +28726 0.2059326171875 +28727 0.62774658203125 +28728 -0.06103515625 +28729 0.602294921875 +28730 -0.29913330078125 +28731 0.555145263671875 +28732 -0.516204833984375 +28733 0.477813720703125 +28734 -0.7252197265625 +28735 0.361297607421875 +28736 -0.85980224609375 +28737 0.2200927734375 +28738 -0.870391845703125 +28739 0.07427978515625 +28740 -0.870391845703125 +28741 -0.058837890625 +28742 -0.858062744140625 +28743 -0.15081787109375 +28744 -0.673004150390625 +28745 -0.19915771484375 +28746 -0.42694091796875 +28747 -0.234405517578125 +28748 -0.2100830078125 +28749 -0.28240966796875 +28750 -0.0362548828125 +28751 -0.341796875 +28752 0.10943603515625 +28753 -0.3955078125 +28754 0.23516845703125 +28755 -0.43182373046875 +28756 0.373687744140625 +28757 -0.426483154296875 +28758 0.517791748046875 +28759 -0.38055419921875 +28760 0.602783203125 +28761 -0.330780029296875 +28762 0.635711669921875 +28763 -0.274169921875 +28764 0.655181884765625 +28765 -0.1912841796875 +28766 0.65948486328125 +28767 -0.0880126953125 +28768 0.651275634765625 +28769 0.030853271484375 +28770 0.61846923828125 +28771 0.15081787109375 +28772 0.53753662109375 +28773 0.2501220703125 +28774 0.404144287109375 +28775 0.31805419921875 +28776 0.22186279296875 +28777 0.348785400390625 +28778 0.003997802734375 +28779 0.342864990234375 +28780 -0.22100830078125 +28781 0.31072998046875 +28782 -0.42449951171875 +28783 0.264312744140625 +28784 -0.579833984375 +28785 0.21600341796875 +28786 -0.641876220703125 +28787 0.190704345703125 +28788 -0.6177978515625 +28789 0.184539794921875 +28790 -0.575531005859375 +28791 0.159820556640625 +28792 -0.526336669921875 +28793 0.113525390625 +28794 -0.42645263671875 +28795 0.076019287109375 +28796 -0.2581787109375 +28797 0.063446044921875 +28798 -0.068695068359375 +28799 0.05474853515625 +28800 0.09222412109375 +28801 0.02764892578125 +28802 0.232147216796875 +28803 -0.00677490234375 +28804 0.3509521484375 +28805 -0.042388916015625 +28806 0.410064697265625 +28807 -0.0963134765625 +28808 0.372955322265625 +28809 -0.185577392578125 +28810 0.2554931640625 +28811 -0.29779052734375 +28812 0.10711669921875 +28813 -0.40240478515625 +28814 -0.052886962890625 +28815 -0.4879150390625 +28816 -0.186279296875 +28817 -0.533172607421875 +28818 -0.23291015625 +28819 -0.50555419921875 +28820 -0.209442138671875 +28821 -0.418426513671875 +28822 -0.174163818359375 +28823 -0.31036376953125 +28824 -0.126739501953125 +28825 -0.18634033203125 +28826 -0.048126220703125 +28827 -0.040740966796875 +28828 0.0426025390625 +28829 0.1097412109375 +28830 0.10748291015625 +28831 0.237701416015625 +28832 0.1409912109375 +28833 0.335205078125 +28834 0.19708251953125 +28835 0.42987060546875 +28836 0.273651123046875 +28837 0.517547607421875 +28838 0.31768798828125 +28839 0.56549072265625 +28840 0.341094970703125 +28841 0.580047607421875 +28842 0.368011474609375 +28843 0.575897216796875 +28844 0.37249755859375 +28845 0.539520263671875 +28846 0.30072021484375 +28847 0.442169189453125 +28848 0.1517333984375 +28849 0.286773681640625 +28850 -0.01470947265625 +28851 0.1123046875 +28852 -0.1883544921875 +28853 -0.070709228515625 +28854 -0.372711181640625 +28855 -0.259765625 +28856 -0.51397705078125 +28857 -0.419036865234375 +28858 -0.57177734375 +28859 -0.520843505859375 +28860 -0.53948974609375 +28861 -0.557861328125 +28862 -0.43511962890625 +28863 -0.537933349609375 +28864 -0.2962646484375 +28865 -0.481231689453125 +28866 -0.161102294921875 +28867 -0.4091796875 +28868 -0.0435791015625 +28869 -0.33001708984375 +28870 0.060394287109375 +28871 -0.242431640625 +28872 0.13665771484375 +28873 -0.156646728515625 +28874 0.170135498046875 +28875 -0.0841064453125 +28876 0.16552734375 +28877 -0.025299072265625 +28878 0.15728759765625 +28879 0.036285400390625 +28880 0.150787353515625 +28881 0.100006103515625 +28882 0.12200927734375 +28883 0.148101806640625 +28884 0.080108642578125 +28885 0.182464599609375 +28886 0.05126953125 +28887 0.21539306640625 +28888 0.062896728515625 +28889 0.26043701171875 +28890 0.09271240234375 +28891 0.30279541015625 +28892 0.092987060546875 +28893 0.313629150390625 +28894 0.07855224609375 +28895 0.301422119140625 +28896 0.06427001953125 +28897 0.2755126953125 +28898 0.0347900390625 +28899 0.228240966796875 +28900 -0.01171875 +28901 0.160552978515625 +28902 -0.056060791015625 +28903 0.086151123046875 +28904 -0.055511474609375 +28905 0.032867431640625 +28906 -0.010467529296875 +28907 0.003570556640625 +28908 0.02508544921875 +28909 -0.0301513671875 +28910 0.025665283203125 +28911 -0.08026123046875 +28912 0.017333984375 +28913 -0.12890625 +28914 0.00189208984375 +28915 -0.1728515625 +28916 -0.03173828125 +28917 -0.2169189453125 +28918 -0.071502685546875 +28919 -0.2530517578125 +28920 -0.13543701171875 +28921 -0.291412353515625 +28922 -0.219970703125 +28923 -0.3302001953125 +28924 -0.300506591796875 +28925 -0.355926513671875 +28926 -0.376312255859375 +28927 -0.36962890625 +28928 -0.416107177734375 +28929 -0.354888916015625 +28930 -0.371124267578125 +28931 -0.28533935546875 +28932 -0.242279052734375 +28933 -0.164031982421875 +28934 -0.069732666015625 +28935 -0.017242431640625 +28936 0.125640869140625 +28937 0.14031982421875 +28938 0.31268310546875 +28939 0.28802490234375 +28940 0.45501708984375 +28941 0.402374267578125 +28942 0.554779052734375 +28943 0.48333740234375 +28944 0.61065673828125 +28945 0.52923583984375 +28946 0.610931396484375 +28947 0.53265380859375 +28948 0.531463623046875 +28949 0.479217529296875 +28950 0.3883056640625 +28951 0.37908935546875 +28952 0.23468017578125 +28953 0.26519775390625 +28954 0.095245361328125 +28955 0.153778076171875 +28956 -0.00396728515625 +28957 0.06207275390625 +28958 -0.04852294921875 +28959 0.000579833984375 +28960 -0.055145263671875 +28961 -0.0386962890625 +28962 -0.0758056640625 +28963 -0.085052490234375 +28964 -0.138702392578125 +28965 -0.153594970703125 +28966 -0.209197998046875 +28967 -0.221954345703125 +28968 -0.289031982421875 +28969 -0.289886474609375 +28970 -0.37884521484375 +28971 -0.356903076171875 +28972 -0.456329345703125 +28973 -0.409027099609375 +28974 -0.51641845703125 +28975 -0.44317626953125 +28976 -0.519287109375 +28977 -0.435791015625 +28978 -0.458251953125 +28979 -0.383544921875 +28980 -0.384796142578125 +28981 -0.318359375 +28982 -0.323699951171875 +28983 -0.25640869140625 +28984 -0.269287109375 +28985 -0.19580078125 +28986 -0.1951904296875 +28987 -0.122314453125 +28988 -0.100006103515625 +28989 -0.036712646484375 +28990 -0.01055908203125 +28991 0.0433349609375 +28992 0.1033935546875 +28993 0.134613037109375 +28994 0.24908447265625 +28995 0.240325927734375 +28996 0.373199462890625 +28997 0.327606201171875 +28998 0.45806884765625 +28999 0.385284423828125 +29000 0.511474609375 +29001 0.4178466796875 +29002 0.565399169921875 +29003 0.444671630859375 +29004 0.61138916015625 +29005 0.461151123046875 +29006 0.5897216796875 +29007 0.432220458984375 +29008 0.4906005859375 +29009 0.352996826171875 +29010 0.33148193359375 +29011 0.23516845703125 +29012 0.147796630859375 +29013 0.101226806640625 +29014 -0.01873779296875 +29015 -0.022430419921875 +29016 -0.140289306640625 +29017 -0.117767333984375 +29018 -0.191986083984375 +29019 -0.168701171875 +29020 -0.184295654296875 +29021 -0.18048095703125 +29022 -0.161834716796875 +29023 -0.179107666015625 +29024 -0.166595458984375 +29025 -0.189239501953125 +29026 -0.19390869140625 +29027 -0.207794189453125 +29028 -0.22442626953125 +29029 -0.22320556640625 +29030 -0.279754638671875 +29031 -0.24871826171875 +29032 -0.3389892578125 +29033 -0.272369384765625 +29034 -0.3543701171875 +29035 -0.26629638671875 +29036 -0.348175048828125 +29037 -0.244781494140625 +29038 -0.32598876953125 +29039 -0.212188720703125 +29040 -0.2581787109375 +29041 -0.151885986328125 +29042 -0.139801025390625 +29043 -0.06195068359375 +29044 0.014617919921875 +29045 0.047882080078125 +29046 0.144378662109375 +29047 0.1402587890625 +29048 0.221038818359375 +29049 0.197418212890625 +29050 0.27069091796875 +29051 0.234527587890625 +29052 0.294036865234375 +29053 0.251739501953125 +29054 0.311767578125 +29055 0.261383056640625 +29056 0.339141845703125 +29057 0.272857666015625 +29058 0.360260009765625 +29059 0.277191162109375 +29060 0.360504150390625 +29061 0.266143798828125 +29062 0.308380126953125 +29063 0.22088623046875 +29064 0.18170166015625 +29065 0.12847900390625 +29066 0.0047607421875 +29067 0.00469970703125 +29068 -0.17559814453125 +29069 -0.120819091796875 +29070 -0.3143310546875 +29071 -0.2196044921875 +29072 -0.36785888671875 +29073 -0.26409912109375 +29074 -0.36248779296875 +29075 -0.269927978515625 +29076 -0.343536376953125 +29077 -0.264617919921875 +29078 -0.3018798828125 +29079 -0.242279052734375 +29080 -0.231414794921875 +29081 -0.19903564453125 +29082 -0.117645263671875 +29083 -0.12603759765625 +29084 0.007049560546875 +29085 -0.043487548828125 +29086 0.087982177734375 +29087 0.0145263671875 +29088 0.13946533203125 +29089 0.056304931640625 +29090 0.17425537109375 +29091 0.089141845703125 +29092 0.188201904296875 +29093 0.10980224609375 +29094 0.171234130859375 +29095 0.11138916015625 +29096 0.118438720703125 +29097 0.090240478515625 +29098 0.05706787109375 +29099 0.06256103515625 +29100 -0.010711669921875 +29101 0.02911376953125 +29102 -0.0914306640625 +29103 -0.01446533203125 +29104 -0.162322998046875 +29105 -0.054412841796875 +29106 -0.194549560546875 +29107 -0.073150634765625 +29108 -0.1492919921875 +29109 -0.0467529296875 +29110 -0.02166748046875 +29111 0.0279541015625 +29112 0.124053955078125 +29113 0.1116943359375 +29114 0.211151123046875 +29115 0.157562255859375 +29116 0.240447998046875 +29117 0.16656494140625 +29118 0.242218017578125 +29119 0.1578369140625 +29120 0.2257080078125 +29121 0.137664794921875 +29122 0.194366455078125 +29123 0.108734130859375 +29124 0.115509033203125 +29125 0.0513916015625 +29126 0.0128173828125 +29127 -0.019256591796875 +29128 -0.053802490234375 +29129 -0.06597900390625 +29130 -0.110626220703125 +29131 -0.104705810546875 +29132 -0.199493408203125 +29133 -0.161041259765625 +29134 -0.29437255859375 +29135 -0.218963623046875 +29136 -0.33221435546875 +29137 -0.239715576171875 +29138 -0.27972412109375 +29139 -0.2030029296875 +29140 -0.185333251953125 +29141 -0.138916015625 +29142 -0.128204345703125 +29143 -0.0965576171875 +29144 -0.115692138671875 +29145 -0.08087158203125 +29146 -0.116455078125 +29147 -0.07305908203125 +29148 -0.105926513671875 +29149 -0.0584716796875 +29150 -0.053955078125 +29151 -0.018951416015625 +29152 0.048797607421875 +29153 0.05084228515625 +29154 0.157318115234375 +29155 0.122894287109375 +29156 0.212005615234375 +29157 0.16021728515625 +29158 0.218475341796875 +29159 0.166107177734375 +29160 0.23724365234375 +29161 0.17779541015625 +29162 0.30535888671875 +29163 0.218170166015625 +29164 0.38128662109375 +29165 0.261749267578125 +29166 0.404449462890625 +29167 0.27142333984375 +29168 0.3944091796875 +29169 0.259552001953125 +29170 0.3885498046875 +29171 0.24951171875 +29172 0.362640380859375 +29173 0.22674560546875 +29174 0.27362060546875 +29175 0.165130615234375 +29176 0.11712646484375 +29177 0.06231689453125 +29178 -0.054901123046875 +29179 -0.04931640625 +29180 -0.19085693359375 +29181 -0.1376953125 +29182 -0.28570556640625 +29183 -0.19952392578125 +29184 -0.339263916015625 +29185 -0.233917236328125 +29186 -0.3775634765625 +29187 -0.257110595703125 +29188 -0.445709228515625 +29189 -0.29833984375 +29190 -0.535064697265625 +29191 -0.352508544921875 +29192 -0.629058837890625 +29193 -0.409271240234375 +29194 -0.697601318359375 +29195 -0.449554443359375 +29196 -0.70391845703125 +29197 -0.4498291015625 +29198 -0.6424560546875 +29199 -0.406768798828125 +29200 -0.491241455078125 +29201 -0.306304931640625 +29202 -0.265716552734375 +29203 -0.1585693359375 +29204 -0.023712158203125 +29205 -0.001068115234375 +29206 0.201751708984375 +29207 0.144775390625 +29208 0.375823974609375 +29209 0.256439208984375 +29210 0.485076904296875 +29211 0.325347900390625 +29212 0.56884765625 +29213 0.37713623046875 +29214 0.634765625 +29215 0.416900634765625 +29216 0.63763427734375 +29217 0.415557861328125 +29218 0.5660400390625 +29219 0.36590576171875 +29220 0.4720458984375 +29221 0.301849365234375 +29222 0.40692138671875 +29223 0.256805419921875 +29224 0.3778076171875 +29225 0.23553466796875 +29226 0.376953125 +29227 0.233154296875 +29228 0.371978759765625 +29229 0.228790283203125 +29230 0.313140869140625 +29231 0.190216064453125 +29232 0.184417724609375 +29233 0.1070556640625 +29234 0.011199951171875 +29235 -0.004241943359375 +29236 -0.171051025390625 +29237 -0.120758056640625 +29238 -0.33740234375 +29239 -0.2264404296875 +29240 -0.47198486328125 +29241 -0.311126708984375 +29242 -0.560394287109375 +29243 -0.365692138671875 +29244 -0.58056640625 +29245 -0.3759765625 +29246 -0.54754638671875 +29247 -0.351898193359375 +29248 -0.508575439453125 +29249 -0.324188232421875 +29250 -0.459503173828125 +29251 -0.290283203125 +29252 -0.394378662109375 +29253 -0.2464599609375 +29254 -0.35260009765625 +29255 -0.218292236328125 +29256 -0.31170654296875 +29257 -0.191253662109375 +29258 -0.197418212890625 +29259 -0.11724853515625 +29260 -0.007965087890625 +29261 0.004852294921875 +29262 0.207489013671875 +29263 0.14324951171875 +29264 0.409210205078125 +29265 0.27227783203125 +29266 0.57208251953125 +29267 0.37579345703125 +29268 0.66595458984375 +29269 0.434356689453125 +29270 0.65875244140625 +29271 0.427337646484375 +29272 0.56744384765625 +29273 0.3658447265625 +29274 0.431396484375 +29275 0.2755126953125 +29276 0.29443359375 +29277 0.18487548828125 +29278 0.182464599609375 +29279 0.11077880859375 +29280 0.06365966796875 +29281 0.03271484375 +29282 -0.075958251953125 +29283 -0.058319091796875 +29284 -0.189422607421875 +29285 -0.131866455078125 +29286 -0.271942138671875 +29287 -0.184844970703125 +29288 -0.342529296875 +29289 -0.2296142578125 +29290 -0.364166259765625 +29291 -0.242279052734375 +29292 -0.327239990234375 +29293 -0.216705322265625 +29294 -0.2769775390625 +29295 -0.182281494140625 +29296 -0.253692626953125 +29297 -0.165252685546875 +29298 -0.24365234375 +29299 -0.15679931640625 +29300 -0.1983642578125 +29301 -0.125640869140625 +29302 -0.116241455078125 +29303 -0.070831298828125 +29304 -0.036834716796875 +29305 -0.018035888671875 +29306 0.034881591796875 +29307 0.0294189453125 +29308 0.09124755859375 +29309 0.0665283203125 +29310 0.10888671875 +29311 0.078155517578125 +29312 0.125518798828125 +29313 0.08868408203125 +29314 0.15771484375 +29315 0.108917236328125 +29316 0.17828369140625 +29317 0.12127685546875 +29318 0.17108154296875 +29319 0.115325927734375 +29320 0.129974365234375 +29321 0.08721923828125 +29322 0.082427978515625 +29323 0.0548095703125 +29324 0.027679443359375 +29325 0.017730712890625 +29326 -0.065643310546875 +29327 -0.04425048828125 +29328 -0.15936279296875 +29329 -0.1063232421875 +29330 -0.21307373046875 +29331 -0.142242431640625 +29332 -0.234649658203125 +29333 -0.1571044921875 +29334 -0.2001953125 +29335 -0.135345458984375 +29336 -0.119171142578125 +29337 -0.08306884765625 +29338 -0.024749755859375 +29339 -0.02178955078125 +29340 0.085784912109375 +29341 0.050262451171875 +29342 0.178131103515625 +29343 0.110809326171875 +29344 0.215576171875 +29345 0.136016845703125 +29346 0.211456298828125 +29347 0.13446044921875 +29348 0.17523193359375 +29349 0.112213134765625 +29350 0.128753662109375 +29351 0.0833740234375 +29352 0.1019287109375 +29353 0.067230224609375 +29354 0.0743408203125 +29355 0.050506591796875 +29356 0.04327392578125 +29357 0.0313720703125 +29358 0.038177490234375 +29359 0.028839111328125 +29360 0.076263427734375 +29361 0.054046630859375 +29362 0.14105224609375 +29363 0.096282958984375 +29364 0.186431884765625 +29365 0.12567138671875 +29366 0.188812255859375 +29367 0.126922607421875 +29368 0.1390380859375 +29369 0.094146728515625 +29370 0.041778564453125 +29371 0.0303955078125 +29372 -0.079437255859375 +29373 -0.04901123046875 +29374 -0.219390869140625 +29375 -0.140655517578125 +29376 -0.367828369140625 +29377 -0.237823486328125 +29378 -0.494873046875 +29379 -0.32110595703125 +29380 -0.556243896484375 +29381 -0.36175537109375 +29382 -0.508697509765625 +29383 -0.33172607421875 +29384 -0.3756103515625 +29385 -0.246124267578125 +29386 -0.218902587890625 +29387 -0.145050048828125 +29388 -0.063751220703125 +29389 -0.0447998046875 +29390 0.091552734375 +29391 0.05572509765625 +29392 0.23602294921875 +29393 0.149444580078125 +29394 0.342987060546875 +29395 0.219024658203125 +29396 0.39520263671875 +29397 0.2532958984375 +29398 0.389373779296875 +29399 0.2501220703125 +29400 0.324249267578125 +29401 0.208648681640625 +29402 0.224090576171875 +29403 0.14453125 +29404 0.124267578125 +29405 0.08062744140625 +29406 0.037078857421875 +29407 0.024871826171875 +29408 -0.010101318359375 +29409 -0.0050048828125 +29410 -0.019439697265625 +29411 -0.010467529296875 +29412 -0.022796630859375 +29413 -0.012176513671875 +29414 -0.001556396484375 +29415 0.001861572265625 +29416 0.056304931640625 +29417 0.039459228515625 +29418 0.106719970703125 +29419 0.072052001953125 +29420 0.096893310546875 +29421 0.065460205078125 +29422 0.042694091796875 +29423 0.02996826171875 +29424 -0.018035888671875 +29425 -0.0098876953125 +29426 -0.07586669921875 +29427 -0.047943115234375 +29428 -0.11944580078125 +29429 -0.0767822265625 +29430 -0.15972900390625 +29431 -0.103515625 +29432 -0.202606201171875 +29433 -0.13189697265625 +29434 -0.24859619140625 +29435 -0.162200927734375 +29436 -0.30517578125 +29437 -0.199249267578125 +29438 -0.36212158203125 +29439 -0.236419677734375 +29440 -0.39141845703125 +29441 -0.255462646484375 +29442 -0.35528564453125 +29443 -0.231719970703125 +29444 -0.249969482421875 +29445 -0.162872314453125 +29446 -0.092864990234375 +29447 -0.060028076171875 +29448 0.08905029296875 +29449 0.05908203125 +29450 0.2352294921875 +29451 0.15386962890625 +29452 0.318817138671875 +29453 0.206512451171875 +29454 0.358642578125 +29455 0.23016357421875 +29456 0.347747802734375 +29457 0.220367431640625 +29458 0.28564453125 +29459 0.176910400390625 +29460 0.223175048828125 +29461 0.1343994140625 +29462 0.196746826171875 +29463 0.1175537109375 +29464 0.179840087890625 +29465 0.10821533203125 +29466 0.155548095703125 +29467 0.094696044921875 +29468 0.151214599609375 +29469 0.09539794921875 +29470 0.156951904296875 +29471 0.10333251953125 +29472 0.13177490234375 +29473 0.090362548828125 +29474 0.100799560546875 +29475 0.073333740234375 +29476 0.087127685546875 +29477 0.06768798828125 +29478 0.05487060546875 +29479 0.048858642578125 +29480 -0.009002685546875 +29481 0.0078125 +29482 -0.10400390625 +29483 -0.05523681640625 +29484 -0.229400634765625 +29485 -0.139862060546875 +29486 -0.35552978515625 +29487 -0.22589111328125 +29488 -0.441925048828125 +29489 -0.285736083984375 +29490 -0.473846435546875 +29491 -0.309326171875 +29492 -0.464813232421875 +29493 -0.305694580078125 +29494 -0.419097900390625 +29495 -0.277618408203125 +29496 -0.334320068359375 +29497 -0.223297119140625 +29498 -0.227935791015625 +29499 -0.154388427734375 +29500 -0.12347412109375 +29501 -0.08673095703125 +29502 -0.02764892578125 +29503 -0.024688720703125 +29504 0.077667236328125 +29505 0.044219970703125 +29506 0.2132568359375 +29507 0.134246826171875 +29508 0.38885498046875 +29509 0.252105712890625 +29510 0.582794189453125 +29511 0.383148193359375 +29512 0.734039306640625 +29513 0.48590087890625 +29514 0.800140380859375 +29515 0.531494140625 +29516 0.7783203125 +29517 0.5179443359375 +29518 0.6651611328125 +29519 0.442840576171875 +29520 0.45965576171875 +29521 0.305419921875 +29522 0.199188232421875 +29523 0.1309814453125 +29524 -0.050689697265625 +29525 -0.03607177734375 +29526 -0.23297119140625 +29527 -0.157135009765625 +29528 -0.33013916015625 +29529 -0.220458984375 +29530 -0.368408203125 +29531 -0.2440185546875 +29532 -0.378936767578125 +29533 -0.249114990234375 +29534 -0.376983642578125 +29535 -0.246246337890625 +29536 -0.37969970703125 +29537 -0.247161865234375 +29538 -0.391510009765625 +29539 -0.254913330078125 +29540 -0.385345458984375 +29541 -0.251068115234375 +29542 -0.3419189453125 +29543 -0.22247314453125 +29544 -0.28289794921875 +29545 -0.183807373046875 +29546 -0.251617431640625 +29547 -0.1644287109375 +29548 -0.266143798828125 +29549 -0.176483154296875 +29550 -0.273345947265625 +29551 -0.183746337890625 +29552 -0.216796875 +29553 -0.147674560546875 +29554 -0.128265380859375 +29555 -0.0897216796875 +29556 -0.068145751953125 +29557 -0.050872802734375 +29558 -0.0430908203125 +29559 -0.035552978515625 +29560 -0.024444580078125 +29561 -0.024200439453125 +29562 0.020721435546875 +29563 0.005645751953125 +29564 0.124481201171875 +29565 0.075836181640625 +29566 0.25787353515625 +29567 0.1666259765625 +29568 0.379119873046875 +29569 0.249603271484375 +29570 0.47991943359375 +29571 0.319122314453125 +29572 0.5281982421875 +29573 0.353302001953125 +29574 0.511138916015625 +29575 0.34332275390625 +29576 0.456207275390625 +29577 0.307769775390625 +29578 0.407470703125 +29579 0.276519775390625 +29580 0.383758544921875 +29581 0.26226806640625 +29582 0.35687255859375 +29583 0.2457275390625 +29584 0.31182861328125 +29585 0.21661376953125 +29586 0.250885009765625 +29587 0.1763916015625 +29588 0.1654052734375 +29589 0.119140625 +29590 0.035247802734375 +29591 0.031097412109375 +29592 -0.142059326171875 +29593 -0.089385986328125 +29594 -0.33563232421875 +29595 -0.2213134765625 +29596 -0.5345458984375 +29597 -0.357208251953125 +29598 -0.72186279296875 +29599 -0.48553466796875 +29600 -0.836669921875 +29601 -0.564788818359375 +29602 -0.8326416015625 +29603 -0.56341552734375 +29604 -0.7296142578125 +29605 -0.49481201171875 +29606 -0.582550048828125 +29607 -0.396270751953125 +29608 -0.440093994140625 +29609 -0.30078125 +29610 -0.324310302734375 +29611 -0.22332763671875 +29612 -0.20147705078125 +29613 -0.140869140625 +29614 -0.044647216796875 +29615 -0.0350341796875 +29616 0.103973388671875 +29617 0.065521240234375 +29618 0.202392578125 +29619 0.132232666015625 +29620 0.264495849609375 +29621 0.174530029296875 +29622 0.338897705078125 +29623 0.2254638671875 +29624 0.443817138671875 +29625 0.29742431640625 +29626 0.545074462890625 +29627 0.36712646484375 +29628 0.6173095703125 +29629 0.417236328125 +29630 0.6524658203125 +29631 0.4422607421875 +29632 0.66339111328125 +29633 0.45086669921875 +29634 0.6561279296875 +29635 0.44708251953125 +29636 0.606781005859375 +29637 0.41455078125 +29638 0.501190185546875 +29639 0.3436279296875 +29640 0.352783203125 +29641 0.243377685546875 +29642 0.176544189453125 +29643 0.123992919921875 +29644 -0.034820556640625 +29645 -0.01947021484375 +29646 -0.258209228515625 +29647 -0.17132568359375 +29648 -0.44244384765625 +29649 -0.296783447265625 +29650 -0.5753173828125 +29651 -0.38751220703125 +29652 -0.65203857421875 +29653 -0.440216064453125 +29654 -0.641632080078125 +29655 -0.433807373046875 +29656 -0.562164306640625 +29657 -0.38055419921875 +29658 -0.458038330078125 +29659 -0.31060791015625 +29660 -0.350555419921875 +29661 -0.238372802734375 +29662 -0.260528564453125 +29663 -0.177978515625 +29664 -0.192108154296875 +29665 -0.1322021484375 +29666 -0.141937255859375 +29667 -0.098724365234375 +29668 -0.1021728515625 +29669 -0.07220458984375 +29670 -0.062896728515625 +29671 -0.04583740234375 +29672 -0.011932373046875 +29673 -0.011322021484375 +29674 0.062835693359375 +29675 0.03955078125 +29676 0.148712158203125 +29677 0.098175048828125 +29678 0.241729736328125 +29679 0.16180419921875 +29680 0.34912109375 +29681 0.2353515625 +29682 0.457305908203125 +29683 0.309539794921875 +29684 0.54388427734375 +29685 0.369110107421875 +29686 0.5728759765625 +29687 0.389556884765625 +29688 0.506591796875 +29689 0.345184326171875 +29690 0.351226806640625 +29691 0.240203857421875 +29692 0.146514892578125 +29693 0.1015625 +29694 -0.05523681640625 +29695 -0.03515625 +29696 -0.21624755859375 +29697 -0.144622802734375 +29698 -0.334930419921875 +29699 -0.225555419921875 +29700 -0.402984619140625 +29701 -0.271484375 +29702 -0.4412841796875 +29703 -0.297332763671875 +29704 -0.49578857421875 +29705 -0.335845947265625 +29706 -0.5601806640625 +29707 -0.382476806640625 +29708 -0.600738525390625 +29709 -0.4130859375 +29710 -0.584228515625 +29711 -0.40386962890625 +29712 -0.47930908203125 +29713 -0.332305908203125 +29714 -0.27935791015625 +29715 -0.193511962890625 +29716 -0.0089111328125 +29717 -0.00469970703125 +29718 0.268798828125 +29719 0.189300537109375 +29720 0.482818603515625 +29721 0.33819580078125 +29722 0.60369873046875 +29723 0.421173095703125 +29724 0.650421142578125 +29725 0.451904296875 +29726 0.66400146484375 +29727 0.459716796875 +29728 0.6414794921875 +29729 0.442596435546875 +29730 0.572540283203125 +29731 0.39324951171875 +29732 0.498138427734375 +29733 0.340789794921875 +29734 0.439453125 +29735 0.300262451171875 +29736 0.375518798828125 +29737 0.25665283203125 +29738 0.274505615234375 +29739 0.187164306640625 +29740 0.1087646484375 +29741 0.07196044921875 +29742 -0.099395751953125 +29743 -0.073211669921875 +29744 -0.3182373046875 +29745 -0.225921630859375 +29746 -0.5489501953125 +29747 -0.38720703125 +29748 -0.7738037109375 +29749 -0.544586181640625 +29750 -0.86383056640625 +29751 -0.6605224609375 +29752 -0.870391845703125 +29753 -0.71142578125 +29754 -0.86895751953125 +29755 -0.71002197265625 +29756 -0.861053466796875 +29757 -0.665679931640625 +29758 -0.765869140625 +29759 -0.56610107421875 +29760 -0.5301513671875 +29761 -0.403228759765625 +29762 -0.214691162109375 +29763 -0.182037353515625 +29764 0.137359619140625 +29765 0.06689453125 +29766 0.474822998046875 +29767 0.30712890625 +29768 0.76239013671875 +29769 0.513519287109375 +29770 0.867462158203125 +29771 0.666961669921875 +29772 0.870361328125 +29773 0.767913818359375 +29774 0.86480712890625 +29775 0.808319091796875 +29776 0.831817626953125 +29777 0.792083740234375 +29778 0.677581787109375 +29779 0.736663818359375 +29780 0.495880126953125 +29781 0.646270751953125 +29782 0.30767822265625 +29783 0.534149169921875 +29784 0.116180419921875 +29785 0.401885986328125 +29786 -0.110748291015625 +29787 0.226898193359375 +29788 -0.381805419921875 +29789 0.00421142578125 +29790 -0.6572265625 +29791 -0.23577880859375 +29792 -0.857421875 +29793 -0.450531005859375 +29794 -0.870391845703125 +29795 -0.60955810546875 +29796 -0.870391845703125 +29797 -0.707855224609375 +29798 -0.86444091796875 +29799 -0.76470947265625 +29800 -0.85723876953125 +29801 -0.805633544921875 +29802 -0.790008544921875 +29803 -0.817626953125 +29804 -0.62847900390625 +29805 -0.762176513671875 +29806 -0.3956298828125 +29807 -0.6370849609375 +29808 -0.126708984375 +29809 -0.46575927734375 +29810 0.150115966796875 +29811 -0.2677001953125 +29812 0.424041748046875 +29813 -0.05126953125 +29814 0.670623779296875 +29815 0.164306640625 +29816 0.854522705078125 +29817 0.35150146484375 +29818 0.866485595703125 +29819 0.497772216796875 +29820 0.86920166015625 +29821 0.59222412109375 +29822 0.8653564453125 +29823 0.6478271484375 +29824 0.857147216796875 +29825 0.6741943359375 +29826 0.766845703125 +29827 0.669342041015625 +29828 0.628509521484375 +29829 0.63702392578125 +29830 0.462127685546875 +29831 0.572479248046875 +29832 0.297210693359375 +29833 0.494171142578125 +29834 0.14862060546875 +29835 0.41094970703125 +29836 -0.00537109375 +29837 0.30657958984375 +29838 -0.15753173828125 +29839 0.186431884765625 +29840 -0.31304931640625 +29841 0.04791259765625 +29842 -0.48876953125 +29843 -0.118927001953125 +29844 -0.6416015625 +29845 -0.28076171875 +29846 -0.751373291015625 +29847 -0.41998291015625 +29848 -0.84619140625 +29849 -0.553070068359375 +29850 -0.861297607421875 +29851 -0.669586181640625 +29852 -0.863250732421875 +29853 -0.746002197265625 +29854 -0.856597900390625 +29855 -0.759857177734375 +29856 -0.7498779296875 +29857 -0.7198486328125 +29858 -0.624542236328125 +29859 -0.667205810546875 +29860 -0.47808837890625 +29861 -0.586334228515625 +29862 -0.253387451171875 +29863 -0.4356689453125 +29864 0.003692626953125 +29865 -0.24774169921875 +29866 0.2257080078125 +29867 -0.071258544921875 +29868 0.427154541015625 +29869 0.102691650390625 +29870 0.643218994140625 +29871 0.297119140625 +29872 0.855926513671875 +29873 0.50518798828125 +29874 0.870361328125 +29875 0.685638427734375 +29876 0.870361328125 +29877 0.80316162109375 +29878 0.862762451171875 +29879 0.85540771484375 +29880 0.79669189453125 +29881 0.855377197265625 +29882 0.595794677734375 +29883 0.795928955078125 +29884 0.362152099609375 +29885 0.683380126953125 +29886 0.1270751953125 +29887 0.54510498046875 +29888 -0.086944580078125 +29889 0.396209716796875 +29890 -0.2784423828125 +29891 0.238250732421875 +29892 -0.484832763671875 +29893 0.0465087890625 +29894 -0.729583740234375 +29895 -0.192626953125 +29896 -0.86688232421875 +29897 -0.44305419921875 +29898 -0.870391845703125 +29899 -0.65960693359375 +29900 -0.86859130859375 +29901 -0.8387451171875 +29902 -0.86279296875 +29903 -0.868072509765625 +29904 -0.817962646484375 +29905 -0.870391845703125 +29906 -0.6116943359375 +29907 -0.86260986328125 +29908 -0.3128662109375 +29909 -0.76226806640625 +29910 0.039398193359375 +29911 -0.527099609375 +29912 0.422821044921875 +29913 -0.238983154296875 +29914 0.805145263671875 +29915 0.07733154296875 +29916 0.870361328125 +29917 0.373016357421875 +29918 0.870361328125 +29919 0.60772705078125 +29920 0.860015869140625 +29921 0.77392578125 +29922 0.727935791015625 +29923 0.85589599609375 +29924 0.48114013671875 +29925 0.857940673828125 +29926 0.2059326171875 +29927 0.849639892578125 +29928 -0.06103515625 +29929 0.775909423828125 +29930 -0.29913330078125 +29931 0.6746826171875 +29932 -0.516204833984375 +29933 0.538055419921875 +29934 -0.7252197265625 +29935 0.357269287109375 +29936 -0.85980224609375 +29937 0.15203857421875 +29938 -0.870391845703125 +29939 -0.051513671875 +29940 -0.870391845703125 +29941 -0.231170654296875 +29942 -0.858062744140625 +29943 -0.351470947265625 +29944 -0.673004150390625 +29945 -0.409210205078125 +29946 -0.42694091796875 +29947 -0.441986083984375 +29948 -0.2100830078125 +29949 -0.4820556640625 +29950 -0.0362548828125 +29951 -0.529052734375 +29952 0.10943603515625 +29953 -0.564056396484375 +29954 0.23516845703125 +29955 -0.57476806640625 +29956 0.373687744140625 +29957 -0.5323486328125 +29958 0.517791748046875 +29959 -0.440032958984375 +29960 0.602783203125 +29961 -0.346405029296875 +29962 0.635711669921875 +29963 -0.249114990234375 +29964 0.655181884765625 +29965 -0.124603271484375 +29966 0.65948486328125 +29967 0.018798828125 +29968 0.651275634765625 +29969 0.174560546875 +29970 0.61846923828125 +29971 0.324249267578125 +29972 0.53753662109375 +29973 0.4405517578125 +29974 0.404144287109375 +29975 0.510528564453125 +29976 0.22186279296875 +29977 0.527862548828125 +29978 0.003997802734375 +29979 0.49456787109375 +29980 -0.22100830078125 +29981 0.425445556640625 +29982 -0.42449951171875 +29983 0.33734130859375 +29984 -0.579833984375 +29985 0.24761962890625 +29986 -0.641876220703125 +29987 0.189544677734375 +29988 -0.6177978515625 +29989 0.159515380859375 +29990 -0.575531005859375 +29991 0.110626220703125 +29992 -0.526336669921875 +29993 0.039825439453125 +29994 -0.42645263671875 +29995 -0.013702392578125 +29996 -0.2581787109375 +29997 -0.029205322265625 +29998 -0.068695068359375 +29999 -0.03375244140625 +30000 0.09222412109375 +30001 -0.056304931640625 +30002 0.232147216796875 +30003 -0.083526611328125 +30004 0.3509521484375 +30005 -0.108673095703125 +30006 0.410064697265625 +30007 -0.15478515625 +30008 0.372955322265625 +30009 -0.24481201171875 +30010 0.2554931640625 +30011 -0.36431884765625 +30012 0.10711669921875 +30013 -0.47564697265625 +30014 -0.052886962890625 +30015 -0.565338134765625 +30016 -0.186279296875 +30017 -0.60736083984375 +30018 -0.23291015625 +30019 -0.560943603515625 +30020 -0.209442138671875 +30021 -0.443572998046875 +30022 -0.174163818359375 +30023 -0.304595947265625 +30024 -0.126739501953125 +30025 -0.1502685546875 +30026 -0.048126220703125 +30027 0.02685546875 +30028 0.0426025390625 +30029 0.2061767578125 +30030 0.10748291015625 +30031 0.353546142578125 +30032 0.1409912109375 +30033 0.459808349609375 +30034 0.19708251953125 +30035 0.561187744140625 +30036 0.273651123046875 +30037 0.65350341796875 +30038 0.31768798828125 +30039 0.69610595703125 +30040 0.341094970703125 +30041 0.697998046875 +30042 0.368011474609375 +30043 0.678741455078125 +30044 0.37249755859375 +30045 0.621856689453125 +30046 0.30072021484375 +30047 0.49114990234375 +30048 0.1517333984375 +30049 0.290618896484375 +30050 -0.01470947265625 +30051 0.0699462890625 +30052 -0.1883544921875 +30053 -0.157684326171875 +30054 -0.372711181640625 +30055 -0.389495849609375 +30056 -0.51397705078125 +30057 -0.58038330078125 +30058 -0.57177734375 +30059 -0.695892333984375 +30060 -0.53948974609375 +30061 -0.727569580078125 +30062 -0.43511962890625 +30063 -0.68621826171875 +30064 -0.2962646484375 +30065 -0.598388671875 +30066 -0.161102294921875 +30067 -0.49224853515625 +30068 -0.0435791015625 +30069 -0.379058837890625 +30070 0.060394287109375 +30071 -0.257781982421875 +30072 0.13665771484375 +30073 -0.141876220703125 +30074 0.170135498046875 +30075 -0.04620361328125 +30076 0.16552734375 +30077 0.028533935546875 +30078 0.15728759765625 +30079 0.103485107421875 +30080 0.150787353515625 +30081 0.17816162109375 +30082 0.12200927734375 +30083 0.230377197265625 +30084 0.080108642578125 +30085 0.263092041015625 +30086 0.05126953125 +30087 0.2926025390625 +30088 0.062896728515625 +30089 0.3369140625 +30090 0.09271240234375 +30091 0.377899169921875 +30092 0.092987060546875 +30093 0.379547119140625 +30094 0.07855224609375 +30095 0.353271484375 +30096 0.06427001953125 +30097 0.311492919921875 +30098 0.0347900390625 +30099 0.244903564453125 +30100 -0.01171875 +30101 0.154937744140625 +30102 -0.056060791015625 +30103 0.059234619140625 +30104 -0.055511474609375 +30105 -0.006744384765625 +30106 -0.010467529296875 +30107 -0.039581298828125 +30108 0.02508544921875 +30109 -0.075775146484375 +30110 0.025665283203125 +30111 -0.1309814453125 +30112 0.017333984375 +30113 -0.183013916015625 +30114 0.00189208984375 +30115 -0.22833251953125 +30116 -0.03173828125 +30117 -0.273681640625 +30118 -0.071502685546875 +30119 -0.30938720703125 +30120 -0.13543701171875 +30121 -0.348907470703125 +30122 -0.219970703125 +30123 -0.390472412109375 +30124 -0.300506591796875 +30125 -0.41729736328125 +30126 -0.376312255859375 +30127 -0.430999755859375 +30128 -0.416107177734375 +30129 -0.410888671875 +30130 -0.371124267578125 +30131 -0.3236083984375 +30132 -0.242279052734375 +30133 -0.172882080078125 +30134 -0.069732666015625 +30135 0.008392333984375 +30136 0.125640869140625 +30137 0.20184326171875 +30138 0.31268310546875 +30139 0.38177490234375 +30140 0.45501708984375 +30141 0.519134521484375 +30142 0.554779052734375 +30143 0.61407470703125 +30144 0.61065673828125 +30145 0.664794921875 +30146 0.610931396484375 +30147 0.662384033203125 +30148 0.531463623046875 +30149 0.58941650390625 +30150 0.3883056640625 +30151 0.458892822265625 +30152 0.23468017578125 +30153 0.31201171875 +30154 0.095245361328125 +30155 0.16912841796875 +30156 -0.00396728515625 +30157 0.051910400390625 +30158 -0.04852294921875 +30159 -0.026397705078125 +30160 -0.055145263671875 +30161 -0.075714111328125 +30162 -0.0758056640625 +30163 -0.132293701171875 +30164 -0.138702392578125 +30165 -0.214996337890625 +30166 -0.209197998046875 +30167 -0.29620361328125 +30168 -0.289031982421875 +30169 -0.375885009765625 +30170 -0.37884521484375 +30171 -0.453643798828125 +30172 -0.456329345703125 +30173 -0.51251220703125 +30174 -0.51641845703125 +30175 -0.5489501953125 +30176 -0.519287109375 +30177 -0.534088134765625 +30178 -0.458251953125 +30179 -0.464111328125 +30180 -0.384796142578125 +30181 -0.37884521484375 +30182 -0.323699951171875 +30183 -0.298614501953125 +30184 -0.269287109375 +30185 -0.221160888671875 +30186 -0.1951904296875 +30187 -0.128997802734375 +30188 -0.100006103515625 +30189 -0.0230712890625 +30190 -0.01055908203125 +30191 0.074737548828125 +30192 0.1033935546875 +30193 0.18536376953125 +30194 0.24908447265625 +30195 0.31292724609375 +30196 0.373199462890625 +30197 0.416961669921875 +30198 0.45806884765625 +30199 0.483856201171875 +30200 0.511474609375 +30201 0.519439697265625 +30202 0.565399169921875 +30203 0.5479736328125 +30204 0.61138916015625 +30205 0.563995361328125 +30206 0.5897216796875 +30207 0.524261474609375 +30208 0.4906005859375 +30209 0.42279052734375 +30210 0.33148193359375 +30211 0.274078369140625 +30212 0.147796630859375 +30213 0.1063232421875 +30214 -0.01873779296875 +30215 -0.047515869140625 +30216 -0.140289306640625 +30217 -0.16497802734375 +30218 -0.191986083984375 +30219 -0.22601318359375 +30220 -0.184295654296875 +30221 -0.237396240234375 +30222 -0.161834716796875 +30223 -0.2318115234375 +30224 -0.166595458984375 +30225 -0.240264892578125 +30226 -0.19390869140625 +30227 -0.2591552734375 +30228 -0.22442626953125 +30229 -0.274261474609375 +30230 -0.279754638671875 +30231 -0.302398681640625 +30232 -0.3389892578125 +30233 -0.32879638671875 +30234 -0.3543701171875 +30235 -0.318756103515625 +30236 -0.348175048828125 +30237 -0.290252685546875 +30238 -0.32598876953125 +30239 -0.248809814453125 +30240 -0.2581787109375 +30241 -0.17364501953125 +30242 -0.139801025390625 +30243 -0.062347412109375 +30244 0.014617919921875 +30245 0.073028564453125 +30246 0.144378662109375 +30247 0.185943603515625 +30248 0.221038818359375 +30249 0.254364013671875 +30250 0.27069091796875 +30251 0.29736328125 +30252 0.294036865234375 +30253 0.31536865234375 +30254 0.311767578125 +30255 0.323974609375 +30256 0.339141845703125 +30257 0.335113525390625 +30258 0.360260009765625 +30259 0.33782958984375 +30260 0.360504150390625 +30261 0.321929931640625 +30262 0.308380126953125 +30263 0.2637939453125 +30264 0.18170166015625 +30265 0.147125244140625 +30266 0.0047607421875 +30267 -0.008209228515625 +30268 -0.17559814453125 +30269 -0.16497802734375 +30270 -0.3143310546875 +30271 -0.287384033203125 +30272 -0.36785888671875 +30273 -0.34088134765625 +30274 -0.36248779296875 +30275 -0.3453369140625 +30276 -0.343536376953125 +30277 -0.335540771484375 +30278 -0.3018798828125 +30279 -0.30426025390625 +30280 -0.231414794921875 +30281 -0.246826171875 +30282 -0.117645263671875 +30283 -0.1522216796875 +30284 0.007049560546875 +30285 -0.0460205078125 +30286 0.087982177734375 +30287 0.02874755859375 +30288 0.13946533203125 +30289 0.082489013671875 +30290 0.17425537109375 +30291 0.124298095703125 +30292 0.188201904296875 +30293 0.15008544921875 +30294 0.171234130859375 +30295 0.15118408203125 +30296 0.118438720703125 +30297 0.123077392578125 +30298 0.05706787109375 +30299 0.08624267578125 +30300 -0.010711669921875 +30301 0.04180908203125 +30302 -0.0914306640625 +30303 -0.015625 +30304 -0.162322998046875 +30305 -0.068603515625 +30306 -0.194549560546875 +30307 -0.09478759765625 +30308 -0.1492919921875 +30309 -0.063873291015625 +30310 -0.02166748046875 +30311 0.028228759765625 +30312 0.124053955078125 +30313 0.13214111328125 +30314 0.211151123046875 +30315 0.188873291015625 +30316 0.240447998046875 +30317 0.19970703125 +30318 0.242218017578125 +30319 0.18878173828125 +30320 0.2257080078125 +30321 0.16400146484375 +30322 0.194366455078125 +30323 0.128692626953125 +30324 0.115509033203125 +30325 0.058013916015625 +30326 0.0128173828125 +30327 -0.029144287109375 +30328 -0.053802490234375 +30329 -0.085968017578125 +30330 -0.110626220703125 +30331 -0.13262939453125 +30332 -0.199493408203125 +30333 -0.2015380859375 +30334 -0.29437255859375 +30335 -0.2725830078125 +30336 -0.33221435546875 +30337 -0.2969970703125 +30338 -0.27972412109375 +30339 -0.24932861328125 +30340 -0.185333251953125 +30341 -0.167572021484375 +30342 -0.128204345703125 +30343 -0.113677978515625 +30344 -0.115692138671875 +30345 -0.0938720703125 +30346 -0.116455078125 +30347 -0.08441162109375 +30348 -0.105926513671875 +30349 -0.066802978515625 +30350 -0.053955078125 +30351 -0.01812744140625 +30352 0.048797607421875 +30353 0.06842041015625 +30354 0.157318115234375 +30355 0.1575927734375 +30356 0.212005615234375 +30357 0.202911376953125 +30358 0.218475341796875 +30359 0.208648681640625 +30360 0.23724365234375 +30361 0.221771240234375 +30362 0.30535888671875 +30363 0.27117919921875 +30364 0.38128662109375 +30365 0.324859619140625 +30366 0.404449462890625 +30367 0.336151123046875 +30368 0.3944091796875 +30369 0.320648193359375 +30370 0.3885498046875 +30371 0.30780029296875 +30372 0.362640380859375 +30373 0.279327392578125 +30374 0.27362060546875 +30375 0.202239990234375 +30376 0.11712646484375 +30377 0.073577880859375 +30378 -0.054901123046875 +30379 -0.065948486328125 +30380 -0.19085693359375 +30381 -0.176025390625 +30382 -0.28570556640625 +30383 -0.252532958984375 +30384 -0.339263916015625 +30385 -0.295257568359375 +30386 -0.3775634765625 +30387 -0.3243408203125 +30388 -0.445709228515625 +30389 -0.3748779296875 +30390 -0.535064697265625 +30391 -0.44036865234375 +30392 -0.629058837890625 +30393 -0.5081787109375 +30394 -0.697601318359375 +30395 -0.5552978515625 +30396 -0.70391845703125 +30397 -0.55352783203125 +30398 -0.6424560546875 +30399 -0.498931884765625 +30400 -0.491241455078125 +30401 -0.3748779296875 +30402 -0.265716552734375 +30403 -0.19366455078125 +30404 -0.023712158203125 +30405 -0.000518798828125 +30406 0.201751708984375 +30407 0.17864990234375 +30408 0.375823974609375 +30409 0.316619873046875 +30410 0.485076904296875 +30411 0.40283203125 +30412 0.56884765625 +30413 0.4677734375 +30414 0.634765625 +30415 0.517425537109375 +30416 0.63763427734375 +30417 0.516845703125 +30418 0.5660400390625 +30419 0.457366943359375 +30420 0.4720458984375 +30421 0.379638671875 +30422 0.40692138671875 +30423 0.323699951171875 +30424 0.3778076171875 +30425 0.295440673828125 +30426 0.376953125 +30427 0.289154052734375 +30428 0.371978759765625 +30429 0.280029296875 +30430 0.313140869140625 +30431 0.229736328125 +30432 0.184417724609375 +30433 0.126068115234375 +30434 0.011199951171875 +30435 -0.011077880859375 +30436 -0.171051025390625 +30437 -0.154083251953125 +30438 -0.33740234375 +30439 -0.283538818359375 +30440 -0.47198486328125 +30441 -0.387115478515625 +30442 -0.560394287109375 +30443 -0.4537353515625 +30444 -0.58056640625 +30445 -0.466461181640625 +30446 -0.54754638671875 +30447 -0.437103271484375 +30448 -0.508575439453125 +30449 -0.402587890625 +30450 -0.459503173828125 +30451 -0.359893798828125 +30452 -0.394378662109375 +30453 -0.304718017578125 +30454 -0.35260009765625 +30455 -0.267852783203125 +30456 -0.31170654296875 +30457 -0.232086181640625 +30458 -0.197418212890625 +30459 -0.139984130859375 +30460 -0.007965087890625 +30461 0.009613037109375 +30462 0.207489013671875 +30463 0.178436279296875 +30464 0.409210205078125 +30465 0.33563232421875 +30466 0.57208251953125 +30467 0.462310791015625 +30468 0.66595458984375 +30469 0.534698486328125 +30470 0.65875244140625 +30471 0.526580810546875 +30472 0.56744384765625 +30473 0.451416015625 +30474 0.431396484375 +30475 0.340850830078125 +30476 0.29443359375 +30477 0.2301025390625 +30478 0.182464599609375 +30479 0.13995361328125 +30480 0.06365966796875 +30481 0.044586181640625 +30482 -0.075958251953125 +30483 -0.0673828125 +30484 -0.189422607421875 +30485 -0.158050537109375 +30486 -0.271942138671875 +30487 -0.223602294921875 +30488 -0.342529296875 +30489 -0.27947998046875 +30490 -0.364166259765625 +30491 -0.29583740234375 +30492 -0.327239990234375 +30493 -0.264923095703125 +30494 -0.2769775390625 +30495 -0.22332763671875 +30496 -0.253692626953125 +30497 -0.203643798828125 +30498 -0.24365234375 +30499 -0.194793701171875 +30500 -0.1983642578125 +30501 -0.157623291015625 +30502 -0.116241455078125 +30503 -0.090850830078125 +30504 -0.036834716796875 +30505 -0.02642822265625 +30506 0.034881591796875 +30507 0.031585693359375 +30508 0.09124755859375 +30509 0.076995849609375 +30510 0.10888671875 +30511 0.090972900390625 +30512 0.125518798828125 +30513 0.103973388671875 +30514 0.15771484375 +30515 0.129425048828125 +30516 0.17828369140625 +30517 0.145355224609375 +30518 0.17108154296875 +30519 0.1387939453125 +30520 0.129974365234375 +30521 0.104827880859375 +30522 0.082427978515625 +30523 0.065673828125 +30524 0.027679443359375 +30525 0.02081298828125 +30526 -0.065643310546875 +30527 -0.055084228515625 +30528 -0.15936279296875 +30529 -0.131134033203125 +30530 -0.21307373046875 +30531 -0.174713134765625 +30532 -0.234649658203125 +30533 -0.192169189453125 +30534 -0.2001953125 +30535 -0.164215087890625 +30536 -0.119171142578125 +30537 -0.0985107421875 +30538 -0.024749755859375 +30539 -0.021881103515625 +30540 0.085784912109375 +30541 0.06787109375 +30542 0.178131103515625 +30543 0.14300537109375 +30544 0.215576171875 +30545 0.173828125 +30546 0.211456298828125 +30547 0.171051025390625 +30548 0.17523193359375 +30549 0.142303466796875 +30550 0.128753662109375 +30551 0.105194091796875 +30552 0.1019287109375 +30553 0.083892822265625 +30554 0.0743408203125 +30555 0.0618896484375 +30556 0.04327392578125 +30557 0.036956787109375 +30558 0.038177490234375 +30559 0.03289794921875 +30560 0.076263427734375 +30561 0.063629150390625 +30562 0.14105224609375 +30563 0.1158447265625 +30564 0.186431884765625 +30565 0.15228271484375 +30566 0.188812255859375 +30567 0.153900146484375 +30568 0.1390380859375 +30569 0.11328125 +30570 0.041778564453125 +30571 0.03424072265625 +30572 -0.079437255859375 +30573 -0.06414794921875 +30574 -0.219390869140625 +30575 -0.17767333984375 +30576 -0.367828369140625 +30577 -0.298004150390625 +30578 -0.494873046875 +30579 -0.4010009765625 +30580 -0.556243896484375 +30581 -0.450836181640625 +30582 -0.508697509765625 +30583 -0.412567138671875 +30584 -0.3756103515625 +30585 -0.305084228515625 +30586 -0.218902587890625 +30587 -0.178436279296875 +30588 -0.063751220703125 +30589 -0.052978515625 +30590 0.091552734375 +30591 0.072662353515625 +30592 0.23602294921875 +30593 0.189605712890625 +30594 0.342987060546875 +30595 0.27630615234375 +30596 0.39520263671875 +30597 0.318817138671875 +30598 0.389373779296875 +30599 0.314453125 +30600 0.324249267578125 +30601 0.26220703125 +30602 0.224090576171875 +30603 0.181640625 +30604 0.124267578125 +30605 0.101287841796875 +30606 0.037078857421875 +30607 0.03106689453125 +30608 -0.010101318359375 +30609 -0.006866455078125 +30610 -0.019439697265625 +30611 -0.014312744140625 +30612 -0.022796630859375 +30613 -0.016998291015625 +30614 -0.001556396484375 +30615 9.1552734375e-05 +30616 0.056304931640625 +30617 0.04669189453125 +30618 0.106719970703125 +30619 0.08721923828125 +30620 0.096893310546875 +30621 0.079010009765625 +30622 0.042694091796875 +30623 0.034942626953125 +30624 -0.018035888671875 +30625 -0.014434814453125 +30626 -0.07586669921875 +30627 -0.06146240234375 +30628 -0.11944580078125 +30629 -0.096954345703125 +30630 -0.15972900390625 +30631 -0.1297607421875 +30632 -0.202606201171875 +30633 -0.16461181640625 +30634 -0.24859619140625 +30635 -0.201904296875 +30636 -0.30517578125 +30637 -0.2476806640625 +30638 -0.36212158203125 +30639 -0.293670654296875 +30640 -0.39141845703125 +30641 -0.317291259765625 +30642 -0.35528564453125 +30643 -0.2879638671875 +30644 -0.249969482421875 +30645 -0.20269775390625 +30646 -0.092864990234375 +30647 -0.0755615234375 +30648 0.08905029296875 +30649 0.0716552734375 +30650 0.2352294921875 +30651 0.19000244140625 +30652 0.318817138671875 +30653 0.257781982421875 +30654 0.358642578125 +30655 0.290191650390625 +30656 0.347747802734375 +30657 0.281585693359375 +30658 0.28564453125 +30659 0.2315673828125 +30660 0.223175048828125 +30661 0.18121337890625 +30662 0.196746826171875 +30663 0.159942626953125 +30664 0.179840087890625 +30665 0.146331787109375 +30666 0.155548095703125 +30667 0.126678466796875 +30668 0.151214599609375 +30669 0.12310791015625 +30670 0.156951904296875 +30671 0.12762451171875 +30672 0.13177490234375 +30673 0.10711669921875 +30674 0.100799560546875 +30675 0.0819091796875 +30676 0.087127685546875 +30677 0.070648193359375 +30678 0.05487060546875 +30679 0.044342041015625 +30680 -0.009002685546875 +30681 -0.00750732421875 +30682 -0.10400390625 +30683 -0.08447265625 +30684 -0.229400634765625 +30685 -0.18597412109375 +30686 -0.35552978515625 +30687 -0.28802490234375 +30688 -0.441925048828125 +30689 -0.357879638671875 +30690 -0.473846435546875 +30691 -0.383697509765625 +30692 -0.464813232421875 +30693 -0.3763427734375 +30694 -0.419097900390625 +30695 -0.33929443359375 +30696 -0.334320068359375 +30697 -0.2706298828125 +30698 -0.227935791015625 +30699 -0.1844482421875 +30700 -0.12347412109375 +30701 -0.099822998046875 +30702 -0.02764892578125 +30703 -0.022186279296875 +30704 0.077667236328125 +30705 0.063140869140625 +30706 0.2132568359375 +30707 0.17291259765625 +30708 0.38885498046875 +30709 0.314971923828125 +30710 0.582794189453125 +30711 0.4718017578125 +30712 0.734039306640625 +30713 0.594085693359375 +30714 0.800140380859375 +30715 0.64752197265625 +30716 0.7783203125 +30717 0.629852294921875 +30718 0.6651611328125 +30719 0.538299560546875 +30720 0.45965576171875 +30721 0.371612548828125 +30722 0.199188232421875 +30723 0.159454345703125 +30724 -0.050689697265625 +30725 -0.044219970703125 +30726 -0.23297119140625 +30727 -0.19171142578125 +30728 -0.33013916015625 +30729 -0.2684326171875 +30730 -0.368408203125 +30731 -0.2965087890625 +30732 -0.378936767578125 +30733 -0.302215576171875 +30734 -0.376983642578125 +30735 -0.2984619140625 +30736 -0.37969970703125 +30737 -0.29974365234375 +30738 -0.391510009765625 +30739 -0.309722900390625 +30740 -0.385345458984375 +30741 -0.30560302734375 +30742 -0.3419189453125 +30743 -0.271087646484375 +30744 -0.28289794921875 +30745 -0.2242431640625 +30746 -0.251617431640625 +30747 -0.2012939453125 +30748 -0.266143798828125 +30749 -0.21722412109375 +30750 -0.273345947265625 +30751 -0.227203369140625 +30752 -0.216796875 +30753 -0.18359375 +30754 -0.128265380859375 +30755 -0.112884521484375 +30756 -0.068145751953125 +30757 -0.065643310546875 +30758 -0.0430908203125 +30759 -0.04730224609375 +30760 -0.024444580078125 +30761 -0.03363037109375 +30762 0.020721435546875 +30763 0.00311279296875 +30764 0.124481201171875 +30765 0.08990478515625 +30766 0.25787353515625 +30767 0.202392578125 +30768 0.379119873046875 +30769 0.305389404296875 +30770 0.47991943359375 +30771 0.39190673828125 +30772 0.5281982421875 +30773 0.434844970703125 +30774 0.511138916015625 +30775 0.423309326171875 +30776 0.456207275390625 +30777 0.380218505859375 +30778 0.407470703125 +30779 0.3424072265625 +30780 0.383758544921875 +30781 0.325531005859375 +30782 0.35687255859375 +30783 0.30572509765625 +30784 0.31182861328125 +30785 0.270263671875 +30786 0.250885009765625 +30787 0.220916748046875 +30788 0.1654052734375 +30789 0.150360107421875 +30790 0.035247802734375 +30791 0.0416259765625 +30792 -0.142059326171875 +30793 -0.10736083984375 +30794 -0.33563232421875 +30795 -0.270660400390625 +30796 -0.5345458984375 +30797 -0.43902587890625 +30798 -0.72186279296875 +30799 -0.59814453125 +30800 -0.836669921875 +30801 -0.696746826171875 +30802 -0.8326416015625 +30803 -0.69580078125 +30804 -0.7296142578125 +30805 -0.611846923828125 +30806 -0.582550048828125 +30807 -0.490875244140625 +30808 -0.440093994140625 +30809 -0.37359619140625 +30810 -0.324310302734375 +30811 -0.2784423828125 +30812 -0.20147705078125 +30813 -0.177001953125 +30814 -0.044647216796875 +30815 -0.0465087890625 +30816 0.103973388671875 +30817 0.07763671875 +30818 0.202392578125 +30819 0.16015625 +30820 0.264495849609375 +30821 0.21270751953125 +30822 0.338897705078125 +30823 0.276092529296875 +30824 0.443817138671875 +30825 0.36553955078125 +30826 0.545074462890625 +30827 0.452239990234375 +30828 0.6173095703125 +30829 0.514801025390625 +30830 0.6524658203125 +30831 0.54638671875 +30832 0.66339111328125 +30833 0.557647705078125 +30834 0.6561279296875 +30835 0.553558349609375 +30836 0.606781005859375 +30837 0.513916015625 +30838 0.501190185546875 +30839 0.426727294921875 +30840 0.352783203125 +30841 0.30322265625 +30842 0.176544189453125 +30843 0.155914306640625 +30844 -0.034820556640625 +30845 -0.02130126953125 +30846 -0.258209228515625 +30847 -0.20904541015625 +30848 -0.44244384765625 +30849 -0.36431884765625 +30850 -0.5753173828125 +30851 -0.476806640625 +30852 -0.65203857421875 +30853 -0.542449951171875 +30854 -0.641632080078125 +30855 -0.535125732421875 +30856 -0.562164306640625 +30857 -0.469940185546875 +30858 -0.458038330078125 +30859 -0.384124755859375 +30860 -0.350555419921875 +30861 -0.29547119140625 +30862 -0.260528564453125 +30863 -0.221343994140625 +30864 -0.192108154296875 +30865 -0.165191650390625 +30866 -0.141937255859375 +30867 -0.1241455078125 +30868 -0.1021728515625 +30869 -0.091552734375 +30870 -0.062896728515625 +30871 -0.05902099609375 +30872 -0.011932373046875 +30873 -0.01629638671875 +30874 0.062835693359375 +30875 0.046783447265625 +30876 0.148712158203125 +30877 0.119537353515625 +30878 0.241729736328125 +30879 0.19854736328125 +30880 0.34912109375 +30881 0.28985595703125 +30882 0.457305908203125 +30883 0.381988525390625 +30884 0.54388427734375 +30885 0.4560546875 +30886 0.5728759765625 +30887 0.481781005859375 +30888 0.506591796875 +30889 0.427398681640625 +30890 0.351226806640625 +30891 0.298065185546875 +30892 0.146514892578125 +30893 0.127105712890625 +30894 -0.05523681640625 +30895 -0.041595458984375 +30896 -0.21624755859375 +30897 -0.176361083984375 +30898 -0.334930419921875 +30899 -0.27587890625 +30900 -0.402984619140625 +30901 -0.333160400390625 +30902 -0.4412841796875 +30903 -0.36572265625 +30904 -0.49578857421875 +30905 -0.412139892578125 +30906 -0.5601806640625 +30907 -0.467071533203125 +30908 -0.600738525390625 +30909 -0.50213623046875 +30910 -0.584228515625 +30911 -0.489349365234375 +30912 -0.47930908203125 +30913 -0.402313232421875 +30914 -0.27935791015625 +30915 -0.235443115234375 +30916 -0.0089111328125 +30917 -0.00927734375 +30918 0.268798828125 +30919 0.22308349609375 +30920 0.482818603515625 +30921 0.402130126953125 +30922 0.60369873046875 +30923 0.503143310546875 +30924 0.650421142578125 +30925 0.542083740234375 +30926 0.66400146484375 +30927 0.553436279296875 +30928 0.6414794921875 +30929 0.53466796875 +30930 0.572540283203125 +30931 0.47711181640625 +30932 0.498138427734375 +30933 0.4151611328125 +30934 0.439453125 +30935 0.3665771484375 +30936 0.375518798828125 +30937 0.313690185546875 +30938 0.274505615234375 +30939 0.229705810546875 +30940 0.1087646484375 +30941 0.09136962890625 +30942 -0.099395751953125 +30943 -0.0826416015625 +30944 -0.3182373046875 +30945 -0.265655517578125 +30946 -0.5489501953125 +30947 -0.458770751953125 +30948 -0.7738037109375 +30949 -0.647064208984375 +30950 -0.86383056640625 +30951 -0.7861328125 +30952 -0.870391845703125 +30953 -0.848052978515625 +30954 -0.86895751953125 +30955 -0.847686767578125 +30956 -0.861053466796875 +30957 -0.79608154296875 +30958 -0.765869140625 +30959 -0.678680419921875 +30960 -0.5301513671875 +30961 -0.485992431640625 +30962 -0.214691162109375 +30963 -0.223968505859375 +30964 0.137359619140625 +30965 0.071258544921875 +30966 0.474822998046875 +30967 0.35662841796875 +30968 0.76239013671875 +30969 0.602325439453125 +30970 0.867462158203125 +30971 0.78570556640625 +30972 0.870361328125 +30973 0.8602294921875 +30974 0.86480712890625 +30975 0.86566162109375 +30976 0.831817626953125 +30977 0.863800048828125 +30978 0.677581787109375 +30979 0.856903076171875 +30980 0.495880126953125 +30981 0.77191162109375 +30982 0.30767822265625 +30983 0.64141845703125 +30984 0.116180419921875 +30985 0.48681640625 +30986 -0.110748291015625 +30987 0.27996826171875 +30988 -0.381805419921875 +30989 0.014312744140625 +30990 -0.6572265625 +30991 -0.273223876953125 +30992 -0.857421875 +30993 -0.5308837890625 +30994 -0.870391845703125 +30995 -0.72161865234375 +30996 -0.870391845703125 +30997 -0.8394775390625 +30998 -0.86444091796875 +30999 -0.8603515625 +31000 -0.85723876953125 +31001 -0.86590576171875 +31002 -0.790008544921875 +31003 -0.86773681640625 +31004 -0.62847900390625 +31005 -0.8607177734375 +31006 -0.3956298828125 +31007 -0.762725830078125 +31008 -0.126708984375 +31009 -0.558319091796875 +31010 0.150115966796875 +31011 -0.321685791015625 +31012 0.424041748046875 +31013 -0.062744140625 +31014 0.670623779296875 +31015 0.195343017578125 +31016 0.854522705078125 +31017 0.419158935546875 +31018 0.866485595703125 +31019 0.5936279296875 +31020 0.86920166015625 +31021 0.70562744140625 +31022 0.8653564453125 +31023 0.771270751953125 +31024 0.857147216796875 +31025 0.80242919921875 +31026 0.766845703125 +31027 0.796661376953125 +31028 0.628509521484375 +31029 0.758453369140625 +31030 0.462127685546875 +31031 0.68194580078125 +31032 0.297210693359375 +31033 0.58953857421875 +31034 0.14862060546875 +31035 0.491851806640625 +31036 -0.00537109375 +31037 0.3687744140625 +31038 -0.15753173828125 +31039 0.226593017578125 +31040 -0.31304931640625 +31041 0.0618896484375 +31042 -0.48876953125 +31043 -0.137847900390625 +31044 -0.6416015625 +31045 -0.332000732421875 +31046 -0.751373291015625 +31047 -0.499237060546875 +31048 -0.84619140625 +31049 -0.659881591796875 +31050 -0.861297607421875 +31051 -0.80126953125 +31052 -0.863250732421875 +31053 -0.85888671875 +31054 -0.856597900390625 +31055 -0.860809326171875 +31056 -0.7498779296875 +31057 -0.855682373046875 +31058 -0.624542236328125 +31059 -0.8033447265625 +31060 -0.47808837890625 +31061 -0.7076416015625 +31062 -0.253387451171875 +31063 -0.526947021484375 +31064 0.003692626953125 +31065 -0.300872802734375 +31066 0.2257080078125 +31067 -0.08880615234375 +31068 0.427154541015625 +31069 0.120361328125 +31070 0.643218994140625 +31071 0.35504150390625 +31072 0.855926513671875 +31073 0.607025146484375 +31074 0.870361328125 +31075 0.825927734375 +31076 0.870361328125 +31077 0.866912841796875 +31078 0.862762451171875 +31079 0.870361328125 +31080 0.79669189453125 +31081 0.866241455078125 +31082 0.595794677734375 +31083 0.849365234375 +31084 0.362152099609375 +31085 0.688079833984375 +31086 0.1270751953125 +31087 0.5040283203125 +31088 -0.086944580078125 +31089 0.316253662109375 +31090 -0.2784423828125 +31091 0.126708984375 +31092 -0.484832763671875 +31093 -0.095306396484375 +31094 -0.729583740234375 +31095 -0.367431640625 +31096 -0.86688232421875 +31097 -0.646820068359375 +31098 -0.870391845703125 +31099 -0.857269287109375 +31100 -0.86859130859375 +31101 -0.870391845703125 +31102 -0.86279296875 +31103 -0.870391845703125 +31104 -0.817962646484375 +31105 -0.86346435546875 +31106 -0.6116943359375 +31107 -0.778167724609375 +31108 -0.3128662109375 +31109 -0.52508544921875 +31110 0.039398193359375 +31111 -0.211395263671875 +31112 0.422821044921875 +31113 0.142669677734375 +31114 0.805145263671875 +31115 0.50750732421875 +31116 0.870361328125 +31117 0.8251953125 +31118 0.870361328125 +31119 0.870361328125 +31120 0.860015869140625 +31121 0.870361328125 +31122 0.727935791015625 +31123 0.860992431640625 +31124 0.48114013671875 +31125 0.75042724609375 +31126 0.2059326171875 +31127 0.542449951171875 +31128 -0.06103515625 +31129 0.320953369140625 +31130 -0.29913330078125 +31131 0.1038818359375 +31132 -0.516204833984375 +31133 -0.114471435546875 +31134 -0.7252197265625 +31135 -0.343231201171875 +31136 -0.85980224609375 +31137 -0.55914306640625 +31138 -0.870391845703125 +31139 -0.733428955078125 +31140 -0.870391845703125 +31141 -0.844024658203125 +31142 -0.858062744140625 +31143 -0.8544921875 +31144 -0.673004150390625 +31145 -0.769134521484375 +31146 -0.42694091796875 +31147 -0.64306640625 +31148 -0.2100830078125 +31149 -0.525177001953125 +31150 -0.0362548828125 +31151 -0.424102783203125 +31152 0.10943603515625 +31153 -0.32470703125 +31154 0.23516845703125 +31155 -0.219024658203125 +31156 0.373687744140625 +31157 -0.07891845703125 +31158 0.517791748046875 +31159 0.0875244140625 +31160 0.602783203125 +31161 0.221099853515625 +31162 0.635711669921875 +31163 0.324188232421875 +31164 0.655181884765625 +31165 0.425933837890625 +31166 0.65948486328125 +31167 0.519927978515625 +31168 0.651275634765625 +31169 0.603424072265625 +31170 0.61846923828125 +31171 0.660919189453125 +31172 0.53753662109375 +31173 0.667327880859375 +31174 0.404144287109375 +31175 0.614959716796875 +31176 0.22186279296875 +31177 0.503814697265625 +31178 0.003997802734375 +31179 0.3433837890625 +31180 -0.22100830078125 +31181 0.1573486328125 +31182 -0.42449951171875 +31183 -0.029296875 +31184 -0.579833984375 +31185 -0.1922607421875 +31186 -0.641876220703125 +31187 -0.2901611328125 +31188 -0.6177978515625 +31189 -0.326385498046875 +31190 -0.575531005859375 +31191 -0.356689453125 +31192 -0.526336669921875 +31193 -0.386932373046875 +31194 -0.42645263671875 +31195 -0.374847412109375 +31196 -0.2581787109375 +31197 -0.30078125 +31198 -0.068695068359375 +31199 -0.20196533203125 +31200 0.09222412109375 +31201 -0.11834716796875 +31202 0.232147216796875 +31203 -0.04052734375 +31204 0.3509521484375 +31205 0.03338623046875 +31206 0.410064697265625 +31207 0.070953369140625 +31208 0.372955322265625 +31209 0.0406494140625 +31210 0.2554931640625 +31211 -0.044219970703125 +31212 0.10711669921875 +31213 -0.141998291015625 +31214 -0.052886962890625 +31215 -0.238006591796875 +31216 -0.186279296875 +31217 -0.30157470703125 +31218 -0.23291015625 +31219 -0.283416748046875 +31220 -0.209442138671875 +31221 -0.201446533203125 +31222 -0.174163818359375 +31223 -0.109893798828125 +31224 -0.126739501953125 +31225 -0.01177978515625 +31226 -0.048126220703125 +31227 0.106475830078125 +31228 0.0426025390625 +31229 0.22576904296875 +31230 0.10748291015625 +31231 0.31109619140625 +31232 0.1409912109375 +31233 0.35687255859375 +31234 0.19708251953125 +31235 0.410369873046875 +31236 0.273651123046875 +31237 0.469207763671875 +31238 0.31768798828125 +31239 0.4866943359375 +31240 0.341094970703125 +31241 0.47515869140625 +31242 0.368011474609375 +31243 0.458465576171875 +31244 0.37249755859375 +31245 0.415771484375 +31246 0.30072021484375 +31247 0.3013916015625 +31248 0.1517333984375 +31249 0.117279052734375 +31250 -0.01470947265625 +31251 -0.080047607421875 +31252 -0.1883544921875 +31253 -0.278839111328125 +31254 -0.372711181640625 +31255 -0.480072021484375 +31256 -0.51397705078125 +31257 -0.63360595703125 +31258 -0.57177734375 +31259 -0.701873779296875 +31260 -0.53948974609375 +31261 -0.678375244140625 +31262 -0.43511962890625 +31263 -0.579315185546875 +31264 -0.2962646484375 +31265 -0.439117431640625 +31266 -0.161102294921875 +31267 -0.29327392578125 +31268 -0.0435791015625 +31269 -0.1558837890625 +31270 0.060394287109375 +31271 -0.025238037109375 +31272 0.13665771484375 +31273 0.083740234375 +31274 0.170135498046875 +31275 0.15521240234375 +31276 0.16552734375 +31277 0.191131591796875 +31278 0.15728759765625 +31279 0.2203369140625 +31280 0.150787353515625 +31281 0.24578857421875 +31282 0.12200927734375 +31283 0.244293212890625 +31284 0.080108642578125 +31285 0.222930908203125 +31286 0.05126953125 +31287 0.204620361328125 +31288 0.062896728515625 +31289 0.213897705078125 +31290 0.09271240234375 +31291 0.230987548828125 +31292 0.092987060546875 +31293 0.2137451171875 +31294 0.07855224609375 +31295 0.176666259765625 +31296 0.06427001953125 +31297 0.1346435546875 +31298 0.0347900390625 +31299 0.075592041015625 +31300 -0.01171875 +31301 -0.000274658203125 +31302 -0.056060791015625 +31303 -0.073760986328125 +31304 -0.055511474609375 +31305 -0.1046142578125 +31306 -0.010467529296875 +31307 -0.091522216796875 +31308 0.02508544921875 +31309 -0.081695556640625 +31310 0.025665283203125 +31311 -0.09698486328125 +31312 0.017333984375 +31313 -0.113250732421875 +31314 0.00189208984375 +31315 -0.12860107421875 +31316 -0.03173828125 +31317 -0.15313720703125 +31318 -0.071502685546875 +31319 -0.176605224609375 +31320 -0.13543701171875 +31321 -0.216064453125 +31322 -0.219970703125 +31323 -0.26947021484375 +31324 -0.300506591796875 +31325 -0.3160400390625 +31326 -0.376312255859375 +31327 -0.356597900390625 +31328 -0.416107177734375 +31329 -0.364532470703125 +31330 -0.371124267578125 +31331 -0.2974853515625 +31332 -0.242279052734375 +31333 -0.15771484375 +31334 -0.069732666015625 +31335 0.01739501953125 +31336 0.125640869140625 +31337 0.208099365234375 +31338 0.31268310546875 +31339 0.385650634765625 +31340 0.45501708984375 +31341 0.51702880859375 +31342 0.554779052734375 +31343 0.6041259765625 +31344 0.61065673828125 +31345 0.646087646484375 +31346 0.610931396484375 +31347 0.63299560546875 +31348 0.531463623046875 +31349 0.54400634765625 +31350 0.3883056640625 +31351 0.394622802734375 +31352 0.23468017578125 +31353 0.23394775390625 +31354 0.095245361328125 +31355 0.08544921875 +31356 -0.00396728515625 +31357 -0.02618408203125 +31358 -0.04852294921875 +31359 -0.086761474609375 +31360 -0.055145263671875 +31361 -0.1102294921875 +31362 -0.0758056640625 +31363 -0.14251708984375 +31364 -0.138702392578125 +31365 -0.2083740234375 +31366 -0.209197998046875 +31367 -0.2762451171875 +31368 -0.289031982421875 +31369 -0.347625732421875 +31370 -0.37884521484375 +31371 -0.423248291015625 +31372 -0.456329345703125 +31373 -0.483428955078125 +31374 -0.51641845703125 +31375 -0.524261474609375 +31376 -0.519287109375 +31377 -0.5107421875 +31378 -0.458251953125 +31379 -0.43780517578125 +31380 -0.384796142578125 +31381 -0.35284423828125 +31382 -0.323699951171875 +31383 -0.2791748046875 +31384 -0.269287109375 +31385 -0.21270751953125 +31386 -0.1951904296875 +31387 -0.130645751953125 +31388 -0.100006103515625 +31389 -0.032501220703125 +31390 -0.01055908203125 +31391 0.056976318359375 +31392 0.1033935546875 +31393 0.16461181640625 +31394 0.24908447265625 +31395 0.2967529296875 +31396 0.373199462890625 +31397 0.405487060546875 +31398 0.45806884765625 +31399 0.4752197265625 +31400 0.511474609375 +31401 0.51336669921875 +31402 0.565399169921875 +31403 0.54937744140625 +31404 0.61138916015625 +31405 0.576416015625 +31406 0.5897216796875 +31407 0.541534423828125 +31408 0.4906005859375 +31409 0.436798095703125 +31410 0.33148193359375 +31411 0.278778076171875 +31412 0.147796630859375 +31413 0.100128173828125 +31414 -0.01873779296875 +31415 -0.0609130859375 +31416 -0.140289306640625 +31417 -0.178741455078125 +31418 -0.191986083984375 +31419 -0.230560302734375 +31420 -0.184295654296875 +31421 -0.225616455078125 +31422 -0.161834716796875 +31423 -0.204071044921875 +31424 -0.166595458984375 +31425 -0.203887939453125 +31426 -0.19390869140625 +31427 -0.22119140625 +31428 -0.22442626953125 +31429 -0.239013671875 +31430 -0.279754638671875 +31431 -0.27740478515625 +31432 -0.3389892578125 +31433 -0.3182373046875 +31434 -0.3543701171875 +31435 -0.319244384765625 +31436 -0.348175048828125 +31437 -0.301177978515625 +31438 -0.32598876953125 +31439 -0.269744873046875 +31440 -0.2581787109375 +31441 -0.198883056640625 +31442 -0.139801025390625 +31443 -0.084625244140625 +31444 0.014617919921875 +31445 0.05963134765625 +31446 0.144378662109375 +31447 0.178985595703125 +31448 0.221038818359375 +31449 0.247802734375 +31450 0.27069091796875 +31451 0.289642333984375 +31452 0.294036865234375 +31453 0.305389404296875 +31454 0.311767578125 +31455 0.31402587890625 +31456 0.339141845703125 +31457 0.329742431640625 +31458 0.360260009765625 +31459 0.33880615234375 +31460 0.360504150390625 +31461 0.328643798828125 +31462 0.308380126953125 +31463 0.27130126953125 +31464 0.18170166015625 +31465 0.14727783203125 +31466 0.0047607421875 +31467 -0.02093505859375 +31468 -0.17559814453125 +31469 -0.190582275390625 +31470 -0.3143310546875 +31471 -0.3206787109375 +31472 -0.36785888671875 +31473 -0.37164306640625 +31474 -0.36248779296875 +31475 -0.367156982421875 +31476 -0.343536376953125 +31477 -0.348236083984375 +31478 -0.3018798828125 +31479 -0.30682373046875 +31480 -0.231414794921875 +31481 -0.23760986328125 +31482 -0.117645263671875 +31483 -0.127838134765625 +31484 0.007049560546875 +31485 -0.0072021484375 +31486 0.087982177734375 +31487 0.074371337890625 +31488 0.13946533203125 +31489 0.12933349609375 +31490 0.17425537109375 +31491 0.168792724609375 +31492 0.188201904296875 +31493 0.1885986328125 +31494 0.171234130859375 +31495 0.178802490234375 +31496 0.118438720703125 +31497 0.134429931640625 +31498 0.05706787109375 +31499 0.08062744140625 +31500 -0.010711669921875 +31501 0.0191650390625 +31502 -0.0914306640625 +31503 -0.05609130859375 +31504 -0.162322998046875 +31505 -0.123809814453125 +31506 -0.194549560546875 +31507 -0.15692138671875 +31508 -0.1492919921875 +31509 -0.118865966796875 +31510 -0.02166748046875 +31511 -0.004791259765625 +31512 0.124053955078125 +31513 0.12548828125 +31514 0.211151123046875 +31515 0.20050048828125 +31516 0.240447998046875 +31517 0.221435546875 +31518 0.242218017578125 +31519 0.216949462890625 +31520 0.2257080078125 +31521 0.196075439453125 +31522 0.194366455078125 +31523 0.16229248046875 +31524 0.115509033203125 +31525 0.085205078125 +31526 0.0128173828125 +31527 -0.0128173828125 +31528 -0.053802490234375 +31529 -0.07568359375 +31530 -0.110626220703125 +31531 -0.127960205078125 +31532 -0.199493408203125 +31533 -0.20892333984375 +31534 -0.29437255859375 +31535 -0.29437255859375 +31536 -0.33221435546875 +31537 -0.325469970703125 +31538 -0.27972412109375 +31539 -0.2713623046875 +31540 -0.185333251953125 +31541 -0.17767333984375 +31542 -0.128204345703125 +31543 -0.1187744140625 +31544 -0.115692138671875 +31545 -0.101806640625 +31546 -0.116455078125 +31547 -0.097747802734375 +31548 -0.105926513671875 +31549 -0.0838623046875 +31550 -0.053955078125 +31551 -0.032135009765625 +31552 0.048797607421875 +31553 0.066009521484375 +31554 0.157318115234375 +31555 0.16839599609375 +31556 0.212005615234375 +31557 0.219207763671875 +31558 0.218475341796875 +31559 0.223785400390625 +31560 0.23724365234375 +31561 0.2388916015625 +31562 0.30535888671875 +31563 0.299346923828125 +31564 0.38128662109375 +31565 0.366455078125 +31566 0.404449462890625 +31567 0.383758544921875 +31568 0.3944091796875 +31569 0.36981201171875 +31570 0.3885498046875 +31571 0.35986328125 +31572 0.362640380859375 +31573 0.331512451171875 +31574 0.27362060546875 +31575 0.24462890625 +31576 0.11712646484375 +31577 0.095306396484375 +31578 -0.054901123046875 +31579 -0.06768798828125 +31580 -0.19085693359375 +31581 -0.195953369140625 +31582 -0.28570556640625 +31583 -0.284759521484375 +31584 -0.339263916015625 +31585 -0.333984375 +31586 -0.3775634765625 +31587 -0.3680419921875 +31588 -0.445709228515625 +31589 -0.429290771484375 +31590 -0.535064697265625 +31591 -0.50982666015625 +31592 -0.629058837890625 +31593 -0.59429931640625 +31594 -0.697601318359375 +31595 -0.654754638671875 +31596 -0.70391845703125 +31597 -0.656951904296875 +31598 -0.6424560546875 +31599 -0.595916748046875 +31600 -0.491241455078125 +31601 -0.451263427734375 +31602 -0.265716552734375 +31603 -0.23760986328125 +31604 -0.023712158203125 +31605 -0.009185791015625 +31606 0.201751708984375 +31607 0.202972412109375 +31608 0.375823974609375 +31609 0.366241455078125 +31610 0.485076904296875 +31611 0.468048095703125 +31612 0.56884765625 +31613 0.545257568359375 +31614 0.634765625 +31615 0.6051025390625 +31616 0.63763427734375 +31617 0.60540771484375 +31618 0.5660400390625 +31619 0.535614013671875 +31620 0.4720458984375 +31621 0.444610595703125 +31622 0.40692138671875 +31623 0.38055419921875 +31624 0.3778076171875 +31625 0.350311279296875 +31626 0.376953125 +31627 0.3468017578125 +31628 0.371978759765625 +31629 0.33984375 +31630 0.313140869140625 +31631 0.282989501953125 +31632 0.184417724609375 +31633 0.16131591796875 +31634 0.011199951171875 +31635 -0.0013427734375 +31636 -0.171051025390625 +31637 -0.17181396484375 +31638 -0.33740234375 +31639 -0.3267822265625 +31640 -0.47198486328125 +31641 -0.451416015625 +31642 -0.560394287109375 +31643 -0.5323486328125 +31644 -0.58056640625 +31645 -0.549072265625 +31646 -0.54754638671875 +31647 -0.5157470703125 +31648 -0.508575439453125 +31649 -0.47674560546875 +31650 -0.459503173828125 +31651 -0.4283447265625 +31652 -0.394378662109375 +31653 -0.3651123046875 +31654 -0.35260009765625 +31655 -0.324005126953125 +31656 -0.31170654296875 +31657 -0.284088134765625 +31658 -0.197418212890625 +31659 -0.175933837890625 +31660 -0.007965087890625 +31661 0.0020751953125 +31662 0.207489013671875 +31663 0.203857421875 +31664 0.409210205078125 +31665 0.392242431640625 +31666 0.57208251953125 +31667 0.54376220703125 +31668 0.66595458984375 +31669 0.6302490234375 +31670 0.65875244140625 +31671 0.621795654296875 +31672 0.56744384765625 +31673 0.53436279296875 +31674 0.431396484375 +31675 0.404937744140625 +31676 0.29443359375 +31677 0.274658203125 +31678 0.182464599609375 +31679 0.167877197265625 +31680 0.06365966796875 +31681 0.054931640625 +31682 -0.075958251953125 +31683 -0.077178955078125 +31684 -0.189422607421875 +31685 -0.1844482421875 +31686 -0.271942138671875 +31687 -0.2623291015625 +31688 -0.342529296875 +31689 -0.328582763671875 +31690 -0.364166259765625 +31691 -0.348602294921875 +31692 -0.327239990234375 +31693 -0.31341552734375 +31694 -0.2769775390625 +31695 -0.265380859375 +31696 -0.253692626953125 +31697 -0.242279052734375 +31698 -0.24365234375 +31699 -0.231353759765625 +31700 -0.1983642578125 +31701 -0.18731689453125 +31702 -0.116241455078125 +31703 -0.1087646484375 +31704 -0.036834716796875 +31705 -0.03277587890625 +31706 0.034881591796875 +31707 0.035858154296875 +31708 0.09124755859375 +31709 0.08990478515625 +31710 0.10888671875 +31711 0.107452392578125 +31712 0.125518798828125 +31713 0.12371826171875 +31714 0.15771484375 +31715 0.1541748046875 +31716 0.17828369140625 +31717 0.173370361328125 +31718 0.17108154296875 +31719 0.166229248046875 +31720 0.129974365234375 +31721 0.127044677734375 +31722 0.082427978515625 +31723 0.08154296875 +31724 0.027679443359375 +31725 0.02911376953125 +31726 -0.065643310546875 +31727 -0.059539794921875 +31728 -0.15936279296875 +31729 -0.148590087890625 +31730 -0.21307373046875 +31731 -0.200164794921875 +31732 -0.234649658203125 +31733 -0.221588134765625 +31734 -0.2001953125 +31735 -0.1904296875 +31736 -0.119171142578125 +31737 -0.115478515625 +31738 -0.024749755859375 +31739 -0.027740478515625 +31740 0.085784912109375 +31741 0.07537841796875 +31742 0.178131103515625 +31743 0.1617431640625 +31744 0.215576171875 +31745 0.196807861328125 +31746 0.211456298828125 +31747 0.192840576171875 +31748 0.17523193359375 +31749 0.1585693359375 +31750 0.128753662109375 +31751 0.115020751953125 +31752 0.1019287109375 +31753 0.09100341796875 +31754 0.0743408203125 +31755 0.066650390625 +31756 0.04327392578125 +31757 0.039154052734375 +31758 0.038177490234375 +31759 0.036834716796875 +31760 0.076263427734375 +31761 0.07623291015625 +31762 0.14105224609375 +31763 0.141265869140625 +31764 0.186431884765625 +31765 0.1871337890625 +31766 0.188812255859375 +31767 0.19091796875 +31768 0.1390380859375 +31769 0.1436767578125 +31770 0.041778564453125 +31771 0.0499267578125 +31772 -0.079437255859375 +31773 -0.067535400390625 +31774 -0.219390869140625 +31775 -0.20367431640625 +31776 -0.367828369140625 +31777 -0.348480224609375 +31778 -0.494873046875 +31779 -0.47296142578125 +31780 -0.556243896484375 +31781 -0.5341796875 +31782 -0.508697509765625 +31783 -0.490142822265625 +31784 -0.3756103515625 +31785 -0.363372802734375 +31786 -0.218902587890625 +31787 -0.213714599609375 +31788 -0.063751220703125 +31789 -0.065399169921875 +31790 0.091552734375 +31791 0.08331298828125 +31792 0.23602294921875 +31793 0.22186279296875 +31794 0.342987060546875 +31795 0.32452392578125 +31796 0.39520263671875 +31797 0.3746337890625 +31798 0.389373779296875 +31799 0.3690185546875 +31800 0.324249267578125 +31801 0.306427001953125 +31802 0.224090576171875 +31803 0.210296630859375 +31804 0.124267578125 +31805 0.114837646484375 +31806 0.037078857421875 +31807 0.0318603515625 +31808 -0.010101318359375 +31809 -0.01220703125 +31810 -0.019439697265625 +31811 -0.019561767578125 +31812 -0.022796630859375 +31813 -0.0211181640625 +31814 -0.001556396484375 +31815 0.001007080078125 +31816 0.056304931640625 +31817 0.058380126953125 +31818 0.106719970703125 +31819 0.1082763671875 +31820 0.096893310546875 +31821 0.09954833984375 +31822 0.042694091796875 +31823 0.04754638671875 +31824 -0.018035888671875 +31825 -0.01116943359375 +31826 -0.07586669921875 +31827 -0.067413330078125 +31828 -0.11944580078125 +31829 -0.11016845703125 +31830 -0.15972900390625 +31831 -0.150054931640625 +31832 -0.202606201171875 +31833 -0.19268798828125 +31834 -0.24859619140625 +31835 -0.23846435546875 +31836 -0.30517578125 +31837 -0.2945556640625 +31838 -0.36212158203125 +31839 -0.35101318359375 +31840 -0.39141845703125 +31841 -0.380645751953125 +31842 -0.35528564453125 +31843 -0.3468017578125 +31844 -0.249969482421875 +31845 -0.245819091796875 +31846 -0.092864990234375 +31847 -0.094482421875 +31848 0.08905029296875 +31849 0.081146240234375 +31850 0.2352294921875 +31851 0.22247314453125 +31852 0.318817138671875 +31853 0.303497314453125 +31854 0.358642578125 +31855 0.342437744140625 +31856 0.347747802734375 +31857 0.33251953125 +31858 0.28564453125 +31859 0.273223876953125 +31860 0.223175048828125 +31861 0.2137451171875 +31862 0.196746826171875 +31863 0.189239501953125 +31864 0.179840087890625 +31865 0.17401123046875 +31866 0.155548095703125 +31867 0.151611328125 +31868 0.151214599609375 +31869 0.1484375 +31870 0.156951904296875 +31871 0.154876708984375 +31872 0.13177490234375 +31873 0.131195068359375 +31874 0.100799560546875 +31875 0.1016845703125 +31876 0.087127685546875 +31877 0.088653564453125 +31878 0.05487060546875 +31879 0.057403564453125 +31880 -0.009002685546875 +31881 -0.004669189453125 +31882 -0.10400390625 +31883 -0.0970458984375 +31884 -0.229400634765625 +31885 -0.21905517578125 +31886 -0.35552978515625 +31887 -0.3419189453125 +31888 -0.441925048828125 +31889 -0.4263916015625 +31890 -0.473846435546875 +31891 -0.458221435546875 +31892 -0.464813232421875 +31893 -0.45037841796875 +31894 -0.419097900390625 +31895 -0.406951904296875 +31896 -0.334320068359375 +31897 -0.32562255859375 +31898 -0.227935791015625 +31899 -0.223236083984375 +31900 -0.12347412109375 +31901 -0.12255859375 +31902 -0.02764892578125 +31903 -0.030059814453125 +31904 0.077667236328125 +31905 0.07183837890625 +31906 0.2132568359375 +31907 0.203216552734375 +31908 0.38885498046875 +31909 0.37347412109375 +31910 0.582794189453125 +31911 0.5616455078125 +31912 0.734039306640625 +31913 0.7086181640625 +31914 0.800140380859375 +31915 0.77325439453125 +31916 0.7783203125 +31917 0.752838134765625 +31918 0.6651611328125 +31919 0.644012451171875 +31920 0.45965576171875 +31921 0.445770263671875 +31922 0.199188232421875 +31923 0.194244384765625 +31924 -0.050689697265625 +31925 -0.047149658203125 +31926 -0.23297119140625 +31927 -0.223236083984375 +31928 -0.33013916015625 +31929 -0.31707763671875 +31930 -0.368408203125 +31931 -0.354034423828125 +31932 -0.378936767578125 +31933 -0.3642578125 +31934 -0.376983642578125 +31935 -0.362548828125 +31936 -0.37969970703125 +31937 -0.365509033203125 +31938 -0.391510009765625 +31939 -0.377349853515625 +31940 -0.385345458984375 +31941 -0.37188720703125 +31942 -0.3419189453125 +31943 -0.330413818359375 +31944 -0.28289794921875 +31945 -0.27386474609375 +31946 -0.251617431640625 +31947 -0.244140625 +31948 -0.266143798828125 +31949 -0.258697509765625 +31950 -0.273345947265625 +31951 -0.266082763671875 +31952 -0.216796875 +31953 -0.211669921875 +31954 -0.128265380859375 +31955 -0.12615966796875 +31956 -0.068145751953125 +31957 -0.06805419921875 +31958 -0.0430908203125 +31959 -0.04376220703125 +31960 -0.024444580078125 +31961 -0.025543212890625 +31962 0.020721435546875 +31963 0.018463134765625 +31964 0.124481201171875 +31965 0.1192626953125 +31966 0.25787353515625 +31967 0.248779296875 +31968 0.379119873046875 +31969 0.3665771484375 +31970 0.47991943359375 +31971 0.464599609375 +31972 0.5281982421875 +31973 0.511749267578125 +31974 0.511138916015625 +31975 0.495635986328125 +31976 0.456207275390625 +31977 0.44281005859375 +31978 0.407470703125 +31979 0.39593505859375 +31980 0.383758544921875 +31981 0.373199462890625 +31982 0.35687255859375 +31983 0.3472900390625 +31984 0.31182861328125 +31985 0.3037109375 +31986 0.250885009765625 +31987 0.24462890625 +31988 0.1654052734375 +31989 0.16168212890625 +31990 0.035247802734375 +31991 0.035400390625 +31992 -0.142059326171875 +31993 -0.1365966796875 +31994 -0.33563232421875 +31995 -0.32440185546875 +31996 -0.5345458984375 +31997 -0.517364501953125 +31998 -0.72186279296875 +31999 -0.699066162109375 +32000 -0.836669921875 +32001 -0.81005859375 +32002 -0.8326416015625 +32003 -0.804901123046875 +32004 -0.7296142578125 +32005 -0.703369140625 +32006 -0.582550048828125 +32007 -0.5599365234375 +32008 -0.440093994140625 +32009 -0.422698974609375 +32010 -0.324310302734375 +32011 -0.313232421875 +32012 -0.20147705078125 +32013 -0.197296142578125 +32014 -0.044647216796875 +32015 -0.047393798828125 +32016 0.103973388671875 +32017 0.094696044921875 +32018 0.202392578125 +32019 0.1873779296875 +32020 0.264495849609375 +32021 0.24481201171875 +32022 0.338897705078125 +32023 0.315887451171875 +32024 0.443817138671875 +32025 0.4189453125 +32026 0.545074462890625 +32027 0.519866943359375 +32028 0.6173095703125 +32029 0.59320068359375 +32030 0.6524658203125 +32031 0.63079833984375 +32032 0.66339111328125 +32033 0.64532470703125 +32034 0.6561279296875 +32035 0.642578125 +32036 0.606781005859375 +32037 0.598358154296875 +32038 0.501190185546875 +32039 0.498199462890625 +32040 0.352783203125 +32041 0.355224609375 +32042 0.176544189453125 +32043 0.184112548828125 +32044 -0.034820556640625 +32045 -0.022674560546875 +32046 -0.258209228515625 +32047 -0.242279052734375 +32048 -0.44244384765625 +32049 -0.4237060546875 +32050 -0.5753173828125 +32051 -0.55487060546875 +32052 -0.65203857421875 +32053 -0.63104248046875 +32054 -0.641632080078125 +32055 -0.621246337890625 +32056 -0.562164306640625 +32057 -0.543487548828125 +32058 -0.458038330078125 +32059 -0.442047119140625 +32060 -0.350555419921875 +32061 -0.338043212890625 +32062 -0.260528564453125 +32063 -0.2520751953125 +32064 -0.192108154296875 +32065 -0.188079833984375 +32066 -0.141937255859375 +32067 -0.1424560546875 +32068 -0.1021728515625 +32069 -0.107086181640625 +32070 -0.062896728515625 +32071 -0.07183837890625 +32072 -0.011932373046875 +32073 -0.0242919921875 +32074 0.062835693359375 +32075 0.047821044921875 +32076 0.148712158203125 +32077 0.131988525390625 +32078 0.241729736328125 +32079 0.2242431640625 +32080 0.34912109375 +32081 0.33184814453125 +32082 0.457305908203125 +32083 0.441192626953125 +32084 0.54388427734375 +32085 0.52978515625 +32086 0.5728759765625 +32087 0.561492919921875 +32088 0.506591796875 +32089 0.49847412109375 +32090 0.351226806640625 +32091 0.34674072265625 +32092 0.146514892578125 +32093 0.145782470703125 +32094 -0.05523681640625 +32095 -0.052276611328125 +32096 -0.21624755859375 +32097 -0.2098388671875 +32098 -0.334930419921875 +32099 -0.325469970703125 +32100 -0.402984619140625 +32101 -0.391082763671875 +32102 -0.4412841796875 +32103 -0.427642822265625 +32104 -0.49578857421875 +32105 -0.481201171875 +32106 -0.5601806640625 +32107 -0.54547119140625 +32108 -0.600738525390625 +32109 -0.586700439453125 +32110 -0.584228515625 +32111 -0.571624755859375 +32112 -0.47930908203125 +32113 -0.468780517578125 +32114 -0.27935791015625 +32115 -0.27142333984375 +32116 -0.0089111328125 +32117 -0.00390625 +32118 0.268798828125 +32119 0.270660400390625 +32120 0.482818603515625 +32121 0.4815673828125 +32122 0.60369873046875 +32123 0.5994873046875 +32124 0.650421142578125 +32125 0.6435546875 +32126 0.66400146484375 +32127 0.654937744140625 +32128 0.6414794921875 +32129 0.630767822265625 +32130 0.572540283203125 +32131 0.560821533203125 +32132 0.498138427734375 +32133 0.486053466796875 +32134 0.439453125 +32135 0.42767333984375 +32136 0.375518798828125 +32137 0.36468505859375 +32138 0.274505615234375 +32139 0.265167236328125 +32140 0.1087646484375 +32141 0.10137939453125 +32142 -0.099395751953125 +32143 -0.1044921875 +32144 -0.3182373046875 +32145 -0.320831298828125 +32146 -0.5489501953125 +32147 -0.548980712890625 +32148 -0.7738037109375 +32149 -0.771331787109375 +32150 -0.86383056640625 +32151 -0.863311767578125 +32152 -0.870391845703125 +32153 -0.870391845703125 +32154 -0.86895751953125 +32155 -0.869476318359375 +32156 -0.861053466796875 +32157 -0.862030029296875 +32158 -0.765869140625 +32159 -0.77838134765625 +32160 -0.5301513671875 +32161 -0.5455322265625 +32162 -0.214691162109375 +32163 -0.232025146484375 +32164 0.137359619140625 +32165 0.119049072265625 +32166 0.474822998046875 +32167 0.45654296875 +32168 0.76239013671875 +32169 0.7451171875 +32170 0.867462158203125 +32171 0.86578369140625 +32172 0.870361328125 +32173 0.870361328125 +32174 0.86480712890625 +32175 0.866424560546875 +32176 0.831817626953125 +32177 0.855133056640625 +32178 0.677581787109375 +32179 0.7178955078125 +32180 0.495880126953125 +32181 0.545379638671875 +32182 0.30767822265625 +32183 0.3634033203125 +32184 0.116180419921875 +32185 0.1749267578125 +32186 -0.110748291015625 +32187 -0.05224609375 +32188 -0.381805419921875 +32189 -0.32672119140625 +32190 -0.6572265625 +32191 -0.60845947265625 +32192 -0.857421875 +32193 -0.841217041015625 +32194 -0.870391845703125 +32195 -0.868896484375 +32196 -0.870391845703125 +32197 -0.870391845703125 +32198 -0.86444091796875 +32199 -0.865875244140625 +32200 -0.85723876953125 +32201 -0.860015869140625 +32202 -0.790008544921875 +32203 -0.825897216796875 +32204 -0.62847900390625 +32205 -0.67254638671875 +32206 -0.3956298828125 +32207 -0.445220947265625 +32208 -0.126708984375 +32209 -0.178955078125 +32210 0.150115966796875 +32211 0.09814453125 +32212 0.424041748046875 +32213 0.375152587890625 +32214 0.670623779296875 +32215 0.627410888671875 +32216 0.854522705078125 +32217 0.819610595703125 +32218 0.866485595703125 +32219 0.8636474609375 +32220 0.86920166015625 +32221 0.8675537109375 +32222 0.8653564453125 +32223 0.86492919921875 +32224 0.857147216796875 +32225 0.857940673828125 +32226 0.766845703125 +32227 0.784393310546875 +32228 0.628509521484375 +32229 0.655181884765625 +32230 0.462127685546875 +32231 0.4962158203125 +32232 0.297210693359375 +32233 0.336639404296875 +32234 0.14862060546875 +32235 0.19110107421875 +32236 -0.00537109375 +32237 0.0377197265625 +32238 -0.15753173828125 +32239 -0.116180419921875 +32240 -0.31304931640625 +32241 -0.275634765625 +32242 -0.48876953125 +32243 -0.45721435546875 +32244 -0.6416015625 +32245 -0.617462158203125 +32246 -0.751373291015625 +32247 -0.735748291015625 +32248 -0.84619140625 +32249 -0.839691162109375 +32250 -0.861297607421875 +32251 -0.861572265625 +32252 -0.863250732421875 +32253 -0.864501953125 +32254 -0.856597900390625 +32255 -0.85870361328125 +32256 -0.749298095703125 +32257 -0.775909423828125 +32258 -0.62200927734375 +32259 -0.655609130859375 +32260 -0.473663330078125 +32261 -0.512359619140625 +32262 -0.249298095703125 +32263 -0.288909912109375 +32264 0.00634765625 +32265 -0.03106689453125 +32266 0.227630615234375 +32267 0.193603515625 +32268 0.42828369140625 +32269 0.39935302734375 +32270 0.642120361328125 +32271 0.621124267578125 +32272 0.85540771484375 +32273 0.8524169921875 +32274 0.870361328125 +32275 0.870361328125 +32276 0.870361328125 +32277 0.870361328125 +32278 0.862823486328125 +32279 0.862762451171875 +32280 0.798126220703125 +32281 0.79669189453125 +32282 0.598968505859375 +32283 0.595794677734375 +32284 0.3670654296875 +32285 0.362152099609375 +32286 0.133056640625 +32287 0.1270751953125 +32288 -0.080902099609375 +32289 -0.086944580078125 +32290 -0.2730712890625 +32291 -0.2784423828125 +32292 -0.479248046875 +32293 -0.484832763671875 +32294 -0.72186279296875 +32295 -0.729583740234375 +32296 -0.86572265625 +32297 -0.86688232421875 +32298 -0.870391845703125 +32299 -0.870391845703125 +32300 -0.86968994140625 +32301 -0.86859130859375 +32302 -0.8648681640625 +32303 -0.86279296875 +32304 -0.8447265625 +32305 -0.817962646484375 +32306 -0.64630126953125 +32307 -0.6116943359375 +32308 -0.35528564453125 +32309 -0.3128662109375 +32310 -0.00970458984375 +32311 0.039398193359375 +32312 0.3685302734375 +32313 0.422821044921875 +32314 0.747711181640625 +32315 0.805145263671875 +32316 0.870361328125 +32317 0.870361328125 +32318 0.870361328125 +32319 0.870361328125 +32320 0.86016845703125 +32321 0.860015869140625 +32322 0.7315673828125 +32323 0.727935791015625 +32324 0.48797607421875 +32325 0.48114013671875 +32326 0.215789794921875 +32327 0.2059326171875 +32328 -0.049163818359375 +32329 -0.06103515625 +32330 -0.28656005859375 +32331 -0.29913330078125 +32332 -0.50360107421875 +32333 -0.516204833984375 +32334 -0.71240234375 +32335 -0.7252197265625 +32336 -0.8583984375 +32337 -0.85980224609375 +32338 -0.870391845703125 +32339 -0.870391845703125 +32340 -0.870391845703125 +32341 -0.870391845703125 +32342 -0.8582763671875 +32343 -0.858062744140625 +32344 -0.6783447265625 +32345 -0.673004150390625 +32346 -0.435394287109375 +32347 -0.42694091796875 +32348 -0.219696044921875 +32349 -0.2100830078125 +32350 -0.044921875 +32351 -0.0362548828125 +32352 0.10296630859375 +32353 0.10943603515625 +32354 0.23150634765625 +32355 0.23516845703125 +32356 0.37200927734375 +32357 0.373687744140625 +32358 0.51715087890625 +32359 0.517791748046875 +32360 0.604034423828125 +32361 0.602783203125 +32362 0.639312744140625 +32363 0.635711669921875 +32364 0.66015625 +32365 0.655181884765625 +32366 0.66485595703125 +32367 0.65948486328125 +32368 0.655975341796875 +32369 0.651275634765625 +32370 0.62188720703125 +32371 0.61846923828125 +32372 0.540008544921875 +32373 0.53753662109375 +32374 0.4063720703125 +32375 0.404144287109375 +32376 0.224700927734375 +32377 0.22186279296875 +32378 0.008209228515625 +32379 0.003997802734375 +32380 -0.21527099609375 +32381 -0.22100830078125 +32382 -0.417724609375 +32383 -0.42449951171875 +32384 -0.573028564453125 +32385 -0.579833984375 +32386 -0.637237548828125 +32387 -0.641876220703125 +32388 -0.617095947265625 +32389 -0.6177978515625 +32390 -0.578216552734375 +32391 -0.575531005859375 +32392 -0.53143310546875 +32393 -0.526336669921875 +32394 -0.43438720703125 +32395 -0.42645263671875 +32396 -0.269927978515625 +32397 -0.2581787109375 +32398 -0.083892822265625 +32399 -0.068695068359375 +32400 0.07537841796875 +32401 0.09222412109375 +32402 0.2149658203125 +32403 0.232147216796875 +32404 0.33453369140625 +32405 0.3509521484375 +32406 0.396453857421875 +32407 0.410064697265625 +32408 0.3651123046875 +32409 0.372955322265625 +32410 0.255645751953125 +32411 0.2554931640625 +32412 0.115692138671875 +32413 0.10711669921875 +32414 -0.036285400390625 +32415 -0.052886962890625 +32416 -0.163360595703125 +32417 -0.186279296875 +32418 -0.20745849609375 +32419 -0.23291015625 +32420 -0.1846923828125 +32421 -0.209442138671875 +32422 -0.151458740234375 +32423 -0.174163818359375 +32424 -0.107391357421875 +32425 -0.126739501953125 +32426 -0.033935546875 +32427 -0.048126220703125 +32428 0.050628662109375 +32429 0.0426025390625 +32430 0.109771728515625 +32431 0.10748291015625 +32432 0.138336181640625 +32433 0.1409912109375 +32434 0.188751220703125 +32435 0.19708251953125 +32436 0.25921630859375 +32437 0.273651123046875 +32438 0.298614501953125 +32439 0.31768798828125 +32440 0.318603515625 +32441 0.341094970703125 +32442 0.34271240234375 +32443 0.368011474609375 +32444 0.34588623046875 +32445 0.37249755859375 +32446 0.27606201171875 +32447 0.30072021484375 +32448 0.132293701171875 +32449 0.1517333984375 +32450 -0.027618408203125 +32451 -0.01470947265625 +32452 -0.193817138671875 +32453 -0.1883544921875 +32454 -0.36981201171875 +32455 -0.372711181640625 +32456 -0.503692626953125 +32457 -0.51397705078125 +32458 -0.556488037109375 +32459 -0.57177734375 +32460 -0.522003173828125 +32461 -0.53948974609375 +32462 -0.4178466796875 +32463 -0.43511962890625 +32464 -0.280609130859375 +32465 -0.2962646484375 +32466 -0.147369384765625 +32467 -0.161102294921875 +32468 -0.031707763671875 +32469 -0.0435791015625 +32470 0.0701904296875 +32471 0.060394287109375 +32472 0.144561767578125 +32473 0.13665771484375 +32474 0.176849365234375 +32475 0.170135498046875 +32476 0.171630859375 +32477 0.16552734375 +32478 0.16229248046875 +32479 0.15728759765625 +32480 0.154144287109375 +32481 0.150787353515625 +32482 0.1240234375 +32483 0.12200927734375 +32484 0.0809326171875 +32485 0.080108642578125 +32486 0.05035400390625 +32487 0.05126953125 +32488 0.05902099609375 +32489 0.062896728515625 +32490 0.08544921875 +32491 0.09271240234375 +32492 0.0836181640625 +32493 0.092987060546875 +32494 0.067962646484375 +32495 0.07855224609375 +32496 0.052947998046875 +32497 0.06427001953125 +32498 0.02374267578125 +32499 0.0347900390625 +32500 -0.021392822265625 +32501 -0.01171875 +32502 -0.06390380859375 +32503 -0.056060791015625 +32504 -0.06243896484375 +32505 -0.055511474609375 +32506 -0.0174560546875 +32507 -0.010467529296875 +32508 0.01873779296875 +32509 0.02508544921875 +32510 0.0213623046875 +32511 0.025665283203125 +32512 0.015289306640625 +32513 0.017333984375 +32514 0.00225830078125 +32515 0.00189208984375 +32516 -0.028289794921875 +32517 -0.03173828125 +32518 -0.06494140625 +32519 -0.071502685546875 +32520 -0.124755859375 +32521 -0.13543701171875 +32522 -0.204345703125 +32523 -0.219970703125 +32524 -0.28033447265625 +32525 -0.300506591796875 +32526 -0.352020263671875 +32527 -0.376312255859375 +32528 -0.38970947265625 +32529 -0.416107177734375 +32530 -0.347076416015625 +32531 -0.371124267578125 +32532 -0.2249755859375 +32533 -0.242279052734375 +32534 -0.061553955078125 +32535 -0.069732666015625 +32536 0.12335205078125 +32537 0.125640869140625 +32538 0.3001708984375 +32539 0.31268310546875 +32540 0.43438720703125 +32541 0.45501708984375 +32542 0.528076171875 +32543 0.554779052734375 +32544 0.580047607421875 +32545 0.61065673828125 +32546 0.579254150390625 +32547 0.610931396484375 +32548 0.502838134765625 +32549 0.531463623046875 +32550 0.366058349609375 +32551 0.3883056640625 +32552 0.219482421875 +32553 0.23468017578125 +32554 0.08660888671875 +32555 0.095245361328125 +32556 -0.007843017578125 +32557 -0.00396728515625 +32558 -0.050140380859375 +32559 -0.04852294921875 +32560 -0.05615234375 +32561 -0.055145263671875 +32562 -0.075347900390625 +32563 -0.0758056640625 +32564 -0.134490966796875 +32565 -0.138702392578125 +32566 -0.200714111328125 +32567 -0.209197998046875 +32568 -0.275726318359375 +32569 -0.289031982421875 +32570 -0.360198974609375 +32571 -0.37884521484375 +32572 -0.432952880859375 +32573 -0.456329345703125 +32574 -0.4892578125 +32575 -0.51641845703125 +32576 -0.491302490234375 +32577 -0.519287109375 +32578 -0.432769775390625 +32579 -0.458251953125 +32580 -0.36260986328125 +32581 -0.384796142578125 +32582 -0.304351806640625 +32583 -0.323699951171875 +32584 -0.252593994140625 +32585 -0.269287109375 +32586 -0.18231201171875 +32587 -0.1951904296875 +32588 -0.0921630859375 +32589 -0.100006103515625 +32590 -0.00762939453125 +32591 -0.01055908203125 +32592 0.10003662109375 +32593 0.1033935546875 +32594 0.237762451171875 +32595 0.24908447265625 +32596 0.354949951171875 +32597 0.373199462890625 +32598 0.43487548828125 +32599 0.45806884765625 +32600 0.48492431640625 +32601 0.511474609375 +32602 0.535552978515625 +32603 0.565399169921875 +32604 0.5787353515625 +32605 0.61138916015625 +32606 0.557769775390625 +32607 0.5897216796875 +32608 0.463348388671875 +32609 0.4906005859375 +32610 0.312103271484375 +32611 0.33148193359375 +32612 0.137664794921875 +32613 0.147796630859375 +32614 -0.020355224609375 +32615 -0.01873779296875 +32616 -0.135498046875 +32617 -0.140289306640625 +32618 -0.184173583984375 +32619 -0.191986083984375 +32620 -0.17633056640625 +32621 -0.184295654296875 +32622 -0.1544189453125 +32623 -0.161834716796875 +32624 -0.1583251953125 +32625 -0.166595458984375 +32626 -0.18365478515625 +32627 -0.19390869140625 +32628 -0.212066650390625 +32629 -0.22442626953125 +32630 -0.26409912109375 +32631 -0.279754638671875 +32632 -0.319976806640625 +32633 -0.3389892578125 +32634 -0.334320068359375 +32635 -0.3543701171875 +32636 -0.32830810546875 +32637 -0.348175048828125 +32638 -0.3072509765625 +32639 -0.32598876953125 +32640 -0.24298095703125 +32641 -0.2581787109375 +32642 -0.13079833984375 +32643 -0.139801025390625 +32644 0.015533447265625 +32645 0.014617919921875 +32646 0.138336181640625 +32647 0.144378662109375 +32648 0.21063232421875 +32649 0.221038818359375 +32650 0.257232666015625 +32651 0.27069091796875 +32652 0.278900146484375 +32653 0.294036865234375 +32654 0.2952880859375 +32655 0.311767578125 +32656 0.320892333984375 +32657 0.339141845703125 +32658 0.34039306640625 +32659 0.360260009765625 +32660 0.339996337890625 +32661 0.360504150390625 +32662 0.290313720703125 +32663 0.308380126953125 +32664 0.17071533203125 +32665 0.18170166015625 +32666 0.004058837890625 +32667 0.0047607421875 +32668 -0.165740966796875 +32669 -0.17559814453125 +32670 -0.2965087890625 +32671 -0.3143310546875 +32672 -0.347381591796875 +32673 -0.36785888671875 +32674 -0.3428955078125 +32675 -0.36248779296875 +32676 -0.325439453125 +32677 -0.343536376953125 +32678 -0.2864990234375 +32679 -0.3018798828125 +32680 -0.220367431640625 +32681 -0.231414794921875 +32682 -0.11346435546875 +32683 -0.117645263671875 +32684 0.00384521484375 +32685 0.007049560546875 +32686 0.080352783203125 +32687 0.087982177734375 +32688 0.12939453125 +32689 0.13946533203125 +32690 0.162872314453125 +32691 0.17425537109375 +32692 0.17681884765625 +32693 0.188201904296875 +32694 0.1617431640625 +32695 0.171234130859375 +32696 0.113006591796875 +32697 0.118438720703125 +32698 0.05609130859375 +32699 0.05706787109375 +32700 -0.006988525390625 +32701 -0.010711669921875 +32702 -0.082366943359375 +32703 -0.0914306640625 +32704 -0.148712158203125 +32705 -0.162322998046875 +32706 -0.179046630859375 +32707 -0.194549560546875 +32708 -0.137054443359375 +32709 -0.1492919921875 +32710 -0.01806640625 +32711 -0.02166748046875 +32712 0.117767333984375 +32713 0.124053955078125 +32714 0.19866943359375 +32715 0.211151123046875 +32716 0.2254638671875 +32717 0.240447998046875 +32718 0.226470947265625 +32719 0.242218017578125 +32720 0.210418701171875 +32721 0.2257080078125 +32722 0.1805419921875 +32723 0.194366455078125 +32724 0.10626220703125 +32725 0.115509033203125 +32726 0.009765625 +32727 0.0128173828125 +32728 -0.052825927734375 +32729 -0.053802490234375 +32730 -0.1060791015625 +32731 -0.110626220703125 +32732 -0.189208984375 +32733 -0.199493408203125 +32734 -0.277801513671875 +32735 -0.29437255859375 +32736 -0.3128662109375 +32737 -0.33221435546875 +32738 -0.2633056640625 +32739 -0.27972412109375 +32740 -0.174468994140625 +32741 -0.185333251953125 +32742 -0.120452880859375 +32743 -0.128204345703125 +32744 -0.108154296875 +32745 -0.115692138671875 +32746 -0.1082763671875 +32747 -0.116455078125 +32748 -0.097900390625 +32749 -0.105926513671875 +32750 -0.048797607421875 +32751 -0.053955078125 +32752 0.0477294921875 +32753 0.048797607421875 +32754 0.1495361328125 +32755 0.157318115234375 +32756 0.2008056640625 +32757 0.212005615234375 +32758 0.206817626953125 +32759 0.218475341796875 +32760 0.2242431640625 +32761 0.23724365234375 +32762 0.287750244140625 +32763 0.30535888671875 +32764 0.35845947265625 +32765 0.38128662109375 +32766 0.37969970703125 +32767 0.404449462890625 +32768 0.36920166015625 +32769 0.3944091796875 +32770 0.361358642578125 +32771 0.3885498046875 +32772 0.334503173828125 +32773 0.362640380859375 +32774 0.25006103515625 +32775 0.27362060546875 +32776 0.10443115234375 +32777 0.11712646484375 +32778 -0.055084228515625 +32779 -0.054901123046875 +32780 -0.181549072265625 +32781 -0.19085693359375 +32782 -0.270233154296875 +32783 -0.28570556640625 +32784 -0.320831298828125 +32785 -0.339263916015625 +32786 -0.35675048828125 +32787 -0.3775634765625 +32788 -0.418701171875 +32789 -0.445709228515625 +32790 -0.4989013671875 +32791 -0.535064697265625 +32792 -0.582427978515625 +32793 -0.629058837890625 +32794 -0.642181396484375 +32795 -0.697601318359375 +32796 -0.64508056640625 +32797 -0.70391845703125 +32798 -0.5863037109375 +32799 -0.6424560546875 +32800 -0.4461669921875 +32801 -0.491241455078125 +32802 -0.238800048828125 +32803 -0.265716552734375 +32804 -0.016693115234375 +32805 -0.023712158203125 +32806 0.190093994140625 +32807 0.201751708984375 +32808 0.34991455078125 +32809 0.375823974609375 +32810 0.45050048828125 +32811 0.485076904296875 +32812 0.52734375 +32813 0.56884765625 +32814 0.58734130859375 +32815 0.634765625 +32816 0.589599609375 +32817 0.63763427734375 +32818 0.523834228515625 +32819 0.5660400390625 +32820 0.437164306640625 +32821 0.4720458984375 +32822 0.376068115234375 +32823 0.40692138671875 +32824 0.347137451171875 +32825 0.3778076171875 +32826 0.343505859375 +32827 0.376953125 +32828 0.3360595703125 +32829 0.371978759765625 +32830 0.280029296875 +32831 0.313140869140625 +32832 0.16107177734375 +32833 0.184417724609375 +32834 0.002288818359375 +32835 0.011199951171875 +32836 -0.1641845703125 +32837 -0.171051025390625 +32838 -0.315704345703125 +32839 -0.33740234375 +32840 -0.437896728515625 +32841 -0.47198486328125 +32842 -0.517730712890625 +32843 -0.560394287109375 +32844 -0.5352783203125 +32845 -0.58056640625 +32846 -0.504180908203125 +32847 -0.54754638671875 +32848 -0.46722412109375 +32849 -0.508575439453125 +32850 -0.4207763671875 +32851 -0.459503173828125 +32852 -0.359588623046875 +32853 -0.394378662109375 +32854 -0.319427490234375 +32855 -0.35260009765625 +32856 -0.28009033203125 +32857 -0.31170654296875 +32858 -0.174560546875 +32859 -0.197418212890625 +32860 -0.001312255859375 +32861 -0.007965087890625 +32862 0.195068359375 +32863 0.207489013671875 +32864 0.3785400390625 +32865 0.409210205078125 +32866 0.5263671875 +32867 0.57208251953125 +32868 0.611297607421875 +32869 0.66595458984375 +32870 0.604339599609375 +32871 0.65875244140625 +32872 0.5208740234375 +32873 0.56744384765625 +32874 0.39654541015625 +32875 0.431396484375 +32876 0.271087646484375 +32877 0.29443359375 +32878 0.167999267578125 +32879 0.182464599609375 +32880 0.058624267578125 +32881 0.06365966796875 +32882 -0.069549560546875 +32883 -0.075958251953125 +32884 -0.1739501953125 +32885 -0.189422607421875 +32886 -0.25018310546875 +32887 -0.271942138671875 +32888 -0.315338134765625 +32889 -0.342529296875 +32890 -0.335906982421875 +32891 -0.364166259765625 +32892 -0.30316162109375 +32893 -0.327239990234375 +32894 -0.2579345703125 +32895 -0.2769775390625 +32896 -0.236663818359375 +32897 -0.253692626953125 +32898 -0.226959228515625 +32899 -0.24365234375 +32900 -0.18505859375 +32901 -0.1983642578125 +32902 -0.10955810546875 +32903 -0.116241455078125 +32904 -0.036285400390625 +32905 -0.036834716796875 +32906 0.0301513671875 +32907 0.034881591796875 +32908 0.082733154296875 +32909 0.09124755859375 +32910 0.100250244140625 +32911 0.10888671875 +32912 0.11669921875 +32913 0.125518798828125 +32914 0.147003173828125 +32915 0.15771484375 +32916 0.16650390625 +32917 0.17828369140625 +32918 0.160552978515625 +32919 0.17108154296875 +32920 0.123626708984375 +32921 0.129974365234375 +32922 0.080535888671875 +32923 0.082427978515625 +32924 0.0306396484375 +32925 0.027679443359375 +32926 -0.054412841796875 +32927 -0.065643310546875 +32928 -0.140045166015625 +32929 -0.15936279296875 +32930 -0.189727783203125 +32931 -0.21307373046875 +32932 -0.210479736328125 +32933 -0.234649658203125 +32934 -0.180633544921875 +32935 -0.2001953125 +32936 -0.108673095703125 +32937 -0.119171142578125 +32938 -0.024505615234375 +32939 -0.024749755859375 +32940 0.074371337890625 +32941 0.085784912109375 +32942 0.157012939453125 +32943 0.178131103515625 +32944 0.190277099609375 +32945 0.215576171875 +32946 0.18621826171875 +32947 0.211456298828125 +32948 0.153411865234375 +32949 0.17523193359375 +32950 0.111602783203125 +32951 0.128753662109375 +32952 0.087799072265625 +32953 0.1019287109375 +32954 0.06353759765625 +32955 0.0743408203125 +32956 0.03631591796875 +32957 0.04327392578125 +32958 0.032684326171875 +32959 0.038177490234375 +32960 0.06817626953125 +32961 0.076263427734375 +32962 0.127838134765625 +32963 0.14105224609375 +32964 0.169921875 +32965 0.186431884765625 +32966 0.17303466796875 +32967 0.188812255859375 +32968 0.12884521484375 +32969 0.1390380859375 +32970 0.04156494140625 +32971 0.041778564453125 +32972 -0.06756591796875 +32973 -0.079437255859375 +32974 -0.19390869140625 +32975 -0.219390869140625 +32976 -0.328155517578125 +32977 -0.367828369140625 +32978 -0.44329833984375 +32979 -0.494873046875 +32980 -0.499298095703125 +32981 -0.556243896484375 +32982 -0.45703125 +32983 -0.508697509765625 +32984 -0.337554931640625 +32985 -0.3756103515625 +32986 -0.196807861328125 +32987 -0.218902587890625 +32988 -0.0574951171875 +32989 -0.063751220703125 +32990 0.08197021484375 +32991 0.091552734375 +32992 0.211700439453125 +32993 0.23602294921875 +32994 0.3076171875 +32995 0.342987060546875 +32996 0.354217529296875 +32997 0.39520263671875 +32998 0.348541259765625 +32999 0.389373779296875 +33000 0.289459228515625 +33001 0.324249267578125 +33002 0.198883056640625 +33003 0.224090576171875 +33004 0.10882568359375 +33005 0.124267578125 +33006 0.03033447265625 +33007 0.037078857421875 +33008 -0.0118408203125 +33009 -0.010101318359375 +33010 -0.019683837890625 +33011 -0.019439697265625 +33012 -0.022003173828125 +33013 -0.022796630859375 +33014 -0.00201416015625 +33015 -0.001556396484375 +33016 0.05108642578125 +33017 0.056304931640625 +33018 0.097412109375 +33019 0.106719970703125 +33020 0.089202880859375 +33021 0.096893310546875 +33022 0.040802001953125 +33023 0.042694091796875 +33024 -0.01336669921875 +33025 -0.018035888671875 +33026 -0.06494140625 +33027 -0.07586669921875 +33028 -0.104248046875 +33029 -0.11944580078125 +33030 -0.140716552734375 +33031 -0.15972900390625 +33032 -0.179351806640625 +33033 -0.202606201171875 +33034 -0.220489501953125 +33035 -0.24859619140625 +33036 -0.270538330078125 +33037 -0.30517578125 +33038 -0.320587158203125 +33039 -0.36212158203125 +33040 -0.34619140625 +33041 -0.39141845703125 +33042 -0.31439208984375 +33043 -0.35528564453125 +33044 -0.22198486328125 +33045 -0.249969482421875 +33046 -0.084197998046875 +33047 -0.092864990234375 +33048 0.075408935546875 +33049 0.08905029296875 +33050 0.2039794921875 +33051 0.2352294921875 +33052 0.27801513671875 +33053 0.318817138671875 +33054 0.313873291015625 +33055 0.358642578125 +33056 0.305419921875 +33057 0.347747802734375 +33058 0.252166748046875 +33059 0.28564453125 +33060 0.198394775390625 +33061 0.223175048828125 +33062 0.175811767578125 +33063 0.196746826171875 +33064 0.16131591796875 +33065 0.179840087890625 +33066 0.14013671875 +33067 0.155548095703125 +33068 0.1361083984375 +33069 0.151214599609375 +33070 0.140625 +33071 0.156951904296875 +33072 0.11798095703125 +33073 0.13177490234375 +33074 0.090118408203125 +33075 0.100799560546875 +33076 0.07720947265625 +33077 0.087127685546875 +33078 0.048065185546875 +33079 0.05487060546875 +33080 -0.008636474609375 +33081 -0.009002685546875 +33082 -0.092376708984375 +33083 -0.10400390625 +33084 -0.2025146484375 +33085 -0.229400634765625 +33086 -0.3131103515625 +33087 -0.35552978515625 +33088 -0.38885498046875 +33089 -0.441925048828125 +33090 -0.41693115234375 +33091 -0.473846435546875 +33092 -0.4090576171875 +33093 -0.464813232421875 +33094 -0.36895751953125 +33095 -0.419097900390625 +33096 -0.29461669921875 +33097 -0.334320068359375 +33098 -0.20123291015625 +33099 -0.227935791015625 +33100 -0.109405517578125 +33101 -0.12347412109375 +33102 -0.0250244140625 +33103 -0.02764892578125 +33104 0.06768798828125 +33105 0.077667236328125 +33106 0.186767578125 +33107 0.2132568359375 +33108 0.340667724609375 +33109 0.38885498046875 +33110 0.51043701171875 +33111 0.582794189453125 +33112 0.642822265625 +33113 0.734039306640625 +33114 0.7008056640625 +33115 0.800140380859375 +33116 0.68194580078125 +33117 0.7783203125 +33118 0.583282470703125 +33119 0.6651611328125 +33120 0.4039306640625 +33121 0.45965576171875 +33122 0.176483154296875 +33123 0.199188232421875 +33124 -0.0418701171875 +33125 -0.050689697265625 +33126 -0.201385498046875 +33127 -0.23297119140625 +33128 -0.286773681640625 +33129 -0.33013916015625 +33130 -0.32086181640625 +33131 -0.368408203125 +33132 -0.33074951171875 +33133 -0.378936767578125 +33134 -0.3297119140625 +33135 -0.376983642578125 +33136 -0.332672119140625 +33137 -0.37969970703125 +33138 -0.34344482421875 +33139 -0.391510009765625 +33140 -0.338409423828125 +33141 -0.385345458984375 +33142 -0.300750732421875 +33143 -0.3419189453125 +33144 -0.249359130859375 +33145 -0.28289794921875 +33146 -0.22198486328125 +33147 -0.251617431640625 +33148 -0.234405517578125 +33149 -0.266143798828125 +33150 -0.24029541015625 +33151 -0.273345947265625 +33152 -0.19049072265625 +33153 -0.216796875 +33154 -0.112701416015625 +33155 -0.128265380859375 +33156 -0.0596923828125 +33157 -0.068145751953125 +33158 -0.037261962890625 +33159 -0.0430908203125 +33160 -0.02044677734375 +33161 -0.024444580078125 +33162 0.01947021484375 +33163 0.020721435546875 +33164 0.11041259765625 +33165 0.124481201171875 +33166 0.22705078125 +33167 0.25787353515625 +33168 0.33294677734375 +33169 0.379119873046875 +33170 0.4208984375 +33171 0.47991943359375 +33172 0.462921142578125 +33173 0.5281982421875 +33174 0.447845458984375 +33175 0.511138916015625 +33176 0.399627685546875 +33177 0.456207275390625 +33178 0.356719970703125 +33179 0.407470703125 +33180 0.335601806640625 +33181 0.383758544921875 +33182 0.311676025390625 +33183 0.35687255859375 +33184 0.271881103515625 +33185 0.31182861328125 +33186 0.218231201171875 +33187 0.250885009765625 +33188 0.143218994140625 +33189 0.1654052734375 +33190 0.029327392578125 +33191 0.035247802734375 +33192 -0.125579833984375 +33193 -0.142059326171875 +33194 -0.294586181640625 +33195 -0.33563232421875 +33196 -0.4681396484375 +33197 -0.5345458984375 +33198 -0.631439208984375 +33199 -0.72186279296875 +33200 -0.73138427734375 +33201 -0.836669921875 +33202 -0.72760009765625 +33203 -0.8326416015625 +33204 -0.637420654296875 +33205 -0.7296142578125 +33206 -0.508758544921875 +33207 -0.582550048828125 +33208 -0.384063720703125 +33209 -0.440093994140625 +33210 -0.282623291015625 +33211 -0.324310302734375 +33212 -0.175079345703125 +33213 -0.20147705078125 +33214 -0.03790283203125 +33215 -0.044647216796875 +33216 0.092071533203125 +33217 0.103973388671875 +33218 0.17816162109375 +33219 0.202392578125 +33220 0.23248291015625 +33221 0.264495849609375 +33222 0.29742431640625 +33223 0.338897705078125 +33224 0.38885498046875 +33225 0.443817138671875 +33226 0.47698974609375 +33227 0.545074462890625 +33228 0.539703369140625 +33229 0.6173095703125 +33230 0.57000732421875 +33231 0.6524658203125 +33232 0.579132080078125 +33233 0.66339111328125 +33234 0.572357177734375 +33235 0.6561279296875 +33236 0.528900146484375 +33237 0.606781005859375 +33238 0.436431884765625 +33239 0.501190185546875 +33240 0.306671142578125 +33241 0.352783203125 +33242 0.152679443359375 +33243 0.176544189453125 +33244 -0.031829833984375 +33245 -0.034820556640625 +33246 -0.22674560546875 +33247 -0.258209228515625 +33248 -0.387451171875 +33249 -0.44244384765625 +33250 -0.503265380859375 +33251 -0.5753173828125 +33252 -0.57000732421875 +33253 -0.65203857421875 +33254 -0.560699462890625 +33255 -0.641632080078125 +33256 -0.491119384765625 +33257 -0.562164306640625 +33258 -0.399993896484375 +33259 -0.458038330078125 +33260 -0.305877685546875 +33261 -0.350555419921875 +33262 -0.22698974609375 +33263 -0.260528564453125 +33264 -0.166961669921875 +33265 -0.192108154296875 +33266 -0.1229248046875 +33267 -0.141937255859375 +33268 -0.0880126953125 +33269 -0.1021728515625 +33270 -0.0535888671875 +33271 -0.062896728515625 +33272 -0.009033203125 +33273 -0.011932373046875 +33274 0.05621337890625 +33275 0.062835693359375 +33276 0.131072998046875 +33277 0.148712158203125 +33278 0.212066650390625 +33279 0.241729736328125 +33280 0.305206298828125 +33281 0.34912109375 +33282 0.397918701171875 +33283 0.457305908203125 +33284 0.47076416015625 +33285 0.54388427734375 +33286 0.493896484375 +33287 0.5728759765625 +33288 0.436004638671875 +33289 0.506591796875 +33290 0.302642822265625 +33291 0.351226806640625 +33292 0.127471923828125 +33293 0.146514892578125 +33294 -0.0452880859375 +33295 -0.05523681640625 +33296 -0.183685302734375 +33297 -0.21624755859375 +33298 -0.286163330078125 +33299 -0.334930419921875 +33300 -0.345611572265625 +33301 -0.402984619140625 +33302 -0.37945556640625 +33303 -0.4412841796875 +33304 -0.42626953125 +33305 -0.49578857421875 +33306 -0.480712890625 +33307 -0.5601806640625 +33308 -0.51446533203125 +33309 -0.600738525390625 +33310 -0.49969482421875 +33311 -0.584228515625 +33312 -0.410125732421875 +33313 -0.47930908203125 +33314 -0.2403564453125 +33315 -0.27935791015625 +33316 -0.0111083984375 +33317 -0.0089111328125 +33318 0.224365234375 +33319 0.268798828125 +33320 0.4063720703125 +33321 0.482818603515625 +33322 0.510040283203125 +33323 0.60369873046875 +33324 0.551177978515625 +33325 0.650421142578125 +33326 0.56414794921875 +33327 0.66400146484375 +33328 0.54638671875 +33329 0.6414794921875 +33330 0.489166259765625 +33331 0.572540283203125 +33332 0.4268798828125 +33333 0.498138427734375 +33334 0.3773193359375 +33335 0.439453125 +33336 0.322906494140625 +33337 0.375518798828125 +33338 0.2369384765625 +33339 0.274505615234375 +33340 0.096282958984375 +33341 0.1087646484375 +33342 -0.080230712890625 +33343 -0.099395751953125 +33344 -0.265838623046875 +33345 -0.3182373046875 +33346 -0.461456298828125 +33347 -0.5489501953125 +33348 -0.65203857421875 +33349 -0.7738037109375 +33350 -0.793060302734375 +33351 -0.86383056640625 +33352 -0.854736328125 +33353 -0.870391845703125 +33354 -0.85479736328125 +33355 -0.86895751953125 +33356 -0.806060791015625 +33357 -0.861053466796875 +33358 -0.6885986328125 +33359 -0.765869140625 +33360 -0.495330810546875 +33361 -0.5301513671875 +33362 -0.23223876953125 +33363 -0.214691162109375 +33364 0.064453125 +33365 0.137359619140625 +33366 0.351593017578125 +33367 0.474822998046875 +33368 0.599273681640625 +33369 0.76239013671875 +33370 0.784759521484375 +33371 0.867462158203125 +33372 0.8603515625 +33373 0.870361328125 +33374 0.865997314453125 +33375 0.86480712890625 +33376 0.86431884765625 +33377 0.831817626953125 +33378 0.8575439453125 +33379 0.677581787109375 +33380 0.778106689453125 +33381 0.495880126953125 +33382 0.647186279296875 +33383 0.30767822265625 +33384 0.491546630859375 +33385 0.116180419921875 +33386 0.284515380859375 +33387 -0.110748291015625 +33388 0.020294189453125 +33389 -0.381805419921875 +33390 -0.26513671875 +33391 -0.6572265625 +33392 -0.52142333984375 +33393 -0.857421875 +33394 -0.712432861328125 +33395 -0.870391845703125 +33396 -0.83209228515625 +33397 -0.870391845703125 +33398 -0.85980224609375 +33399 -0.86444091796875 +33400 -0.865447998046875 +33401 -0.85723876953125 +33402 -0.867340087890625 +33403 -0.790008544921875 +33404 -0.860504150390625 +33405 -0.62847900390625 +33406 -0.76409912109375 +33407 -0.3956298828125 +33408 -0.563323974609375 +33409 -0.126708984375 +33410 -0.33026123046875 +33411 0.150115966796875 +33412 -0.074737548828125 +33413 0.424041748046875 +33414 0.180572509765625 +33415 0.670623779296875 +33416 0.403106689453125 +33417 0.854522705078125 +33418 0.577972412109375 +33419 0.866485595703125 +33420 0.692138671875 +33421 0.86920166015625 +33422 0.760772705078125 +33423 0.8653564453125 +33424 0.7950439453125 +33425 0.857147216796875 +33426 0.79241943359375 +33427 0.766845703125 +33428 0.757110595703125 +33429 0.628509521484375 +33430 0.683380126953125 +33431 0.462127685546875 +33432 0.5928955078125 +33433 0.297210693359375 +33434 0.49603271484375 +33435 0.14862060546875 +33436 0.37359619140625 +33437 -0.00537109375 +33438 0.231842041015625 +33439 -0.15753173828125 +33440 0.067779541015625 +33441 -0.31304931640625 +33442 -0.13031005859375 +33443 -0.48876953125 +33444 -0.322998046875 +33445 -0.6416015625 +33446 -0.48944091796875 +33447 -0.751373291015625 +33448 -0.64892578125 +33449 -0.84619140625 +33450 -0.788970947265625 +33451 -0.861297607421875 +33452 -0.85748291015625 +33453 -0.863250732421875 +33454 -0.859527587890625 +33455 -0.856597900390625 +33456 -0.854583740234375 +33457 -0.7498779296875 +33458 -0.794952392578125 +33459 -0.624542236328125 +33460 -0.700836181640625 +33461 -0.47808837890625 +33462 -0.52386474609375 +33463 -0.253387451171875 +33464 -0.3023681640625 +33465 0.003692626953125 +33466 -0.09381103515625 +33467 0.2257080078125 +33468 0.112274169921875 +33469 0.427154541015625 +33470 0.343017578125 +33471 0.643218994140625 +33472 0.590240478515625 +33473 0.855926513671875 +33474 0.805145263671875 +33475 0.870361328125 +33476 0.86444091796875 +33477 0.870361328125 +33478 0.870361328125 +33479 0.862762451171875 +33480 0.868682861328125 +33481 0.79669189453125 +33482 0.85870361328125 +33483 0.595794677734375 +33484 0.75067138671875 +33485 0.362152099609375 +33486 0.580963134765625 +33487 0.1270751953125 +33488 0.40228271484375 +33489 -0.086944580078125 +33490 0.216522216796875 +33491 -0.2784423828125 +33492 -0.005584716796875 +33493 -0.484832763671875 +33494 -0.280426025390625 +33495 -0.729583740234375 +33496 -0.56591796875 +33497 -0.86688232421875 +33498 -0.80938720703125 +33499 -0.870391845703125 +33500 -0.870391845703125 +33501 -0.86859130859375 +33502 -0.870391845703125 +33503 -0.86279296875 +33504 -0.863494873046875 +33505 -0.817962646484375 +33506 -0.780487060546875 +33507 -0.6116943359375 +33508 -0.531280517578125 +33509 -0.3128662109375 +33510 -0.22247314453125 +33511 0.039398193359375 +33512 0.126068115234375 +33513 0.422821044921875 +33514 0.48541259765625 +33515 0.805145263671875 +33516 0.79931640625 +33517 0.870361328125 +33518 0.870361328125 +33519 0.870361328125 +33520 0.870361328125 +33521 0.860015869140625 +33522 0.861114501953125 +33523 0.727935791015625 +33524 0.75372314453125 +33525 0.48114013671875 +33526 0.5479736328125 +33527 0.2059326171875 +33528 0.327972412109375 +33529 -0.06103515625 +33530 0.111358642578125 +33531 -0.29913330078125 +33532 -0.10687255859375 +33533 -0.516204833984375 +33534 -0.335113525390625 +33535 -0.7252197265625 +33536 -0.550689697265625 +33537 -0.85980224609375 +33538 -0.72503662109375 +33539 -0.870391845703125 +33540 -0.836578369140625 +33541 -0.870391845703125 +33542 -0.8514404296875 +33543 -0.858062744140625 +33544 -0.773651123046875 +33545 -0.673004150390625 +33546 -0.654541015625 +33547 -0.42694091796875 +33548 -0.539764404296875 +33549 -0.2100830078125 +33550 -0.43780517578125 +33551 -0.0362548828125 +33552 -0.33526611328125 +33553 0.10943603515625 +33554 -0.225372314453125 +33555 0.23516845703125 +33556 -0.08282470703125 +33557 0.373687744140625 +33558 0.084197998046875 +33559 0.517791748046875 +33560 0.220123291015625 +33561 0.602783203125 +33562 0.3265380859375 +33563 0.635711669921875 +33564 0.429931640625 +33565 0.655181884765625 +33566 0.52392578125 +33567 0.65948486328125 +33568 0.60565185546875 +33569 0.651275634765625 +33570 0.66058349609375 +33571 0.61846923828125 +33572 0.66546630859375 +33573 0.53753662109375 +33574 0.613311767578125 +33575 0.404144287109375 +33576 0.504425048828125 +33577 0.22186279296875 +33578 0.347991943359375 +33579 0.003997802734375 +33580 0.166412353515625 +33581 -0.22100830078125 +33582 -0.0166015625 +33583 -0.42449951171875 +33584 -0.17791748046875 +33585 -0.579833984375 +33586 -0.278656005859375 +33587 -0.641876220703125 +33588 -0.321441650390625 +33589 -0.6177978515625 +33590 -0.357421875 +33591 -0.575531005859375 +33592 -0.391632080078125 +33593 -0.526336669921875 +33594 -0.384613037109375 +33595 -0.42645263671875 +33596 -0.3179931640625 +33597 -0.2581787109375 +33598 -0.22625732421875 +33599 -0.068695068359375 +33600 -0.146484375 +33601 0.09222412109375 +33602 -0.070159912109375 +33603 0.232147216796875 +33604 0.00421142578125 +33605 0.3509521484375 +33606 0.046173095703125 +33607 0.410064697265625 +33608 0.026123046875 +33609 0.372955322265625 +33610 -0.0440673828125 +33611 0.2554931640625 +33612 -0.12628173828125 +33613 0.10711669921875 +33614 -0.207366943359375 +33615 -0.052886962890625 +33616 -0.25933837890625 +33617 -0.186279296875 +33618 -0.23687744140625 +33619 -0.23291015625 +33620 -0.1568603515625 +33621 -0.209442138671875 +33622 -0.069732666015625 +33623 -0.174163818359375 +33624 0.021636962890625 +33625 -0.126739501953125 +33626 0.129913330078125 +33627 -0.048126220703125 +33628 0.23748779296875 +33629 0.0426025390625 +33630 0.3121337890625 +33631 0.10748291015625 +33632 0.3485107421875 +33633 0.1409912109375 +33634 0.390045166015625 +33635 0.19708251953125 +33636 0.4356689453125 +33637 0.273651123046875 +33638 0.44378662109375 +33639 0.31768798828125 +33640 0.425811767578125 +33641 0.341094970703125 +33642 0.403564453125 +33643 0.368011474609375 +33644 0.358673095703125 +33645 0.37249755859375 +33646 0.250396728515625 +33647 0.30072021484375 +33648 0.08074951171875 +33649 0.1517333984375 +33650 -0.09930419921875 +33651 -0.01470947265625 +33652 -0.279083251953125 +33653 -0.1883544921875 +33654 -0.45947265625 +33655 -0.372711181640625 +33656 -0.59552001953125 +33657 -0.51397705078125 +33658 -0.653656005859375 +33659 -0.57177734375 +33660 -0.62823486328125 +33661 -0.53948974609375 +33662 -0.5340576171875 +33663 -0.43511962890625 +33664 -0.40234375 +33665 -0.2962646484375 +33666 -0.265289306640625 +33667 -0.161102294921875 +33668 -0.135894775390625 +33669 -0.0435791015625 +33670 -0.012939453125 +33671 0.060394287109375 +33672 0.08984375 +33673 0.13665771484375 +33674 0.15802001953125 +33675 0.170135498046875 +33676 0.193115234375 +33677 0.16552734375 +33678 0.220916748046875 +33679 0.15728759765625 +33680 0.244049072265625 +33681 0.150787353515625 +33682 0.24169921875 +33683 0.12200927734375 +33684 0.2203369140625 +33685 0.080108642578125 +33686 0.20068359375 +33687 0.05126953125 +33688 0.204986572265625 +33689 0.062896728515625 +33690 0.215728759765625 +33691 0.09271240234375 +33692 0.1953125 +33693 0.092987060546875 +33694 0.15704345703125 +33695 0.07855224609375 +33696 0.11456298828125 +33697 0.06427001953125 +33698 0.057281494140625 +33699 0.0347900390625 +33700 -0.014404296875 +33701 -0.01171875 +33702 -0.083099365234375 +33703 -0.056060791015625 +33704 -0.112518310546875 +33705 -0.055511474609375 +33706 -0.101409912109375 +33707 -0.010467529296875 +33708 -0.092132568359375 +33709 0.02508544921875 +33710 -0.104400634765625 +33711 0.025665283203125 +33712 -0.116607666015625 +33713 0.017333984375 +33714 -0.127288818359375 +33715 0.00189208984375 +33716 -0.14569091796875 +33717 -0.03173828125 +33718 -0.16278076171875 +33719 -0.071502685546875 +33720 -0.194091796875 +33721 -0.13543701171875 +33722 -0.238006591796875 +33723 -0.219970703125 +33724 -0.276123046875 +33725 -0.300506591796875 +33726 -0.309356689453125 +33727 -0.376312255859375 +33728 -0.31396484375 +33729 -0.416107177734375 +33730 -0.252044677734375 +33731 -0.371124267578125 +33732 -0.12567138671875 +33733 -0.242279052734375 +33734 0.03155517578125 +33735 -0.069732666015625 +33736 0.201873779296875 +33737 0.125640869140625 +33738 0.359619140625 +33739 0.31268310546875 +33740 0.4752197265625 +33741 0.45501708984375 +33742 0.550537109375 +33743 0.554779052734375 +33744 0.5849609375 +33745 0.61065673828125 +33746 0.569793701171875 +33747 0.610931396484375 +33748 0.48651123046875 +33749 0.531463623046875 +33750 0.349212646484375 +33751 0.3883056640625 +33752 0.2021484375 +33753 0.23468017578125 +33754 0.0665283203125 +33755 0.095245361328125 +33756 -0.035369873046875 +33757 -0.00396728515625 +33758 -0.090728759765625 +33759 -0.04852294921875 +33760 -0.112060546875 +33761 -0.055145263671875 +33762 -0.140594482421875 +33763 -0.0758056640625 +33764 -0.198577880859375 +33765 -0.138702392578125 +33766 -0.25775146484375 +33767 -0.209197998046875 +33768 -0.319580078125 +33769 -0.289031982421875 +33770 -0.3848876953125 +33771 -0.37884521484375 +33772 -0.436126708984375 +33773 -0.456329345703125 +33774 -0.469970703125 +33775 -0.51641845703125 +33776 -0.45513916015625 +33777 -0.519287109375 +33778 -0.38720703125 +33779 -0.458251953125 +33780 -0.308837890625 +33781 -0.384796142578125 +33782 -0.2410888671875 +33783 -0.323699951171875 +33784 -0.18035888671875 +33785 -0.269287109375 +33786 -0.106231689453125 +33787 -0.1951904296875 +33788 -0.018280029296875 +33789 -0.100006103515625 +33790 0.061279296875 +33791 -0.01055908203125 +33792 0.156463623046875 +33793 0.1033935546875 +33794 0.27313232421875 +33795 0.24908447265625 +33796 0.368682861328125 +33797 0.373199462890625 +33798 0.429229736328125 +33799 0.45806884765625 +33800 0.461456298828125 +33801 0.511474609375 +33802 0.4915771484375 +33803 0.565399169921875 +33804 0.5135498046875 +33805 0.61138916015625 +33806 0.48046875 +33807 0.5897216796875 +33808 0.385345458984375 +33809 0.4906005859375 +33810 0.2430419921875 +33811 0.33148193359375 +33812 0.08270263671875 +33813 0.147796630859375 +33814 -0.061614990234375 +33815 -0.01873779296875 +33816 -0.1671142578125 +33817 -0.140289306640625 +33818 -0.2135009765625 +33819 -0.191986083984375 +33820 -0.208984375 +33821 -0.184295654296875 +33822 -0.18927001953125 +33823 -0.161834716796875 +33824 -0.188140869140625 +33825 -0.166595458984375 +33826 -0.20220947265625 +33827 -0.19390869140625 +33828 -0.21649169921875 +33829 -0.22442626953125 +33830 -0.248870849609375 +33831 -0.279754638671875 +33832 -0.2833251953125 +33833 -0.3389892578125 +33834 -0.28240966796875 +33835 -0.3543701171875 +33836 -0.264678955078125 +33837 -0.348175048828125 +33838 -0.235260009765625 +33839 -0.32598876953125 +33840 -0.17108154296875 +33841 -0.2581787109375 +33842 -0.06866455078125 +33843 -0.139801025390625 +33844 0.060028076171875 +33845 0.014617919921875 +33846 0.166168212890625 +33847 0.144378662109375 +33848 0.227020263671875 +33849 0.221038818359375 +33850 0.2635498046875 +33851 0.27069091796875 +33852 0.276580810546875 +33853 0.294036865234375 +33854 0.28302001953125 +33855 0.311767578125 +33856 0.295501708984375 +33857 0.339141845703125 +33858 0.30157470703125 +33859 0.360260009765625 +33860 0.29022216796875 +33861 0.360504150390625 +33862 0.237762451171875 +33863 0.308380126953125 +33864 0.127716064453125 +33865 0.18170166015625 +33866 -0.020294189453125 +33867 0.0047607421875 +33868 -0.169342041015625 +33869 -0.17559814453125 +33870 -0.284027099609375 +33871 -0.3143310546875 +33872 -0.330169677734375 +33873 -0.36785888671875 +33874 -0.3280029296875 +33875 -0.36248779296875 +33876 -0.312652587890625 +33877 -0.343536376953125 +33878 -0.27716064453125 +33879 -0.3018798828125 +33880 -0.217010498046875 +33881 -0.231414794921875 +33882 -0.121337890625 +33883 -0.117645263671875 +33884 -0.015716552734375 +33885 0.007049560546875 +33886 0.056884765625 +33887 0.087982177734375 +33888 0.10699462890625 +33889 0.13946533203125 +33890 0.143951416015625 +33891 0.17425537109375 +33892 0.163970947265625 +33893 0.188201904296875 +33894 0.15875244140625 +33895 0.171234130859375 +33896 0.12408447265625 +33897 0.118438720703125 +33898 0.080841064453125 +33899 0.05706787109375 +33900 0.03045654296875 +33901 -0.010711669921875 +33902 -0.032135009765625 +33903 -0.0914306640625 +33904 -0.08917236328125 +33905 -0.162322998046875 +33906 -0.1181640625 +33907 -0.194549560546875 +33908 -0.088714599609375 +33909 -0.1492919921875 +33910 0.003326416015625 +33911 -0.02166748046875 +33912 0.108489990234375 +33913 0.124053955078125 +33914 0.167724609375 +33915 0.211151123046875 +33916 0.182159423828125 +33917 0.240447998046875 +33918 0.175689697265625 +33919 0.242218017578125 +33920 0.15594482421875 +33921 0.2257080078125 +33922 0.125946044921875 +33923 0.194366455078125 +33924 0.060577392578125 +33925 0.115509033203125 +33926 -0.02154541015625 +33927 0.0128173828125 +33928 -0.073883056640625 +33929 -0.053802490234375 +33930 -0.1168212890625 +33931 -0.110626220703125 +33932 -0.1829833984375 +33933 -0.199493408203125 +33934 -0.25238037109375 +33935 -0.29437255859375 +33936 -0.27630615234375 +33937 -0.33221435546875 +33938 -0.22930908203125 +33939 -0.27972412109375 +33940 -0.149322509765625 +33941 -0.185333251953125 +33942 -0.098114013671875 +33943 -0.128204345703125 +33944 -0.081756591796875 +33945 -0.115692138671875 +33946 -0.0762939453125 +33947 -0.116455078125 +33948 -0.06298828125 +33949 -0.105926513671875 +33950 -0.018707275390625 +33951 -0.053955078125 +33952 0.0635986328125 +33953 0.048797607421875 +33954 0.14892578125 +33955 0.157318115234375 +33956 0.19097900390625 +33957 0.212005615234375 +33958 0.194183349609375 +33959 0.218475341796875 +33960 0.20562744140625 +33961 0.23724365234375 +33962 0.2542724609375 +33963 0.30535888671875 +33964 0.308135986328125 +33965 0.38128662109375 +33966 0.320526123046875 +33967 0.404449462890625 +33968 0.30694580078125 +33969 0.3944091796875 +33970 0.296722412109375 +33971 0.3885498046875 +33972 0.271392822265625 +33973 0.362640380859375 +33974 0.197784423828125 +33975 0.27362060546875 +33976 0.072723388671875 +33977 0.11712646484375 +33978 -0.063262939453125 +33979 -0.054901123046875 +33980 -0.1700439453125 +33981 -0.19085693359375 +33982 -0.243682861328125 +33983 -0.28570556640625 +33984 -0.284088134765625 +33985 -0.339263916015625 +33986 -0.3115234375 +33987 -0.3775634765625 +33988 -0.36114501953125 +33989 -0.445709228515625 +33990 -0.426513671875 +33991 -0.535064697265625 +33992 -0.494964599609375 +33993 -0.629058837890625 +33994 -0.543426513671875 +33995 -0.697601318359375 +33996 -0.543609619140625 +33997 -0.70391845703125 +33998 -0.491455078125 +33999 -0.6424560546875 +34000 -0.37017822265625 +34001 -0.491241455078125 +34002 -0.191925048828125 +34003 -0.265716552734375 +34004 -0.001739501953125 +34005 -0.023712158203125 +34006 0.17462158203125 +34007 0.201751708984375 +34008 0.310089111328125 +34009 0.375823974609375 +34010 0.39422607421875 +34011 0.485076904296875 +34012 0.4576416015625 +34013 0.56884765625 +34014 0.506378173828125 +34015 0.634765625 +34016 0.5054931640625 +34017 0.63763427734375 +34018 0.446319580078125 +34019 0.5660400390625 +34020 0.369476318359375 +34021 0.4720458984375 +34022 0.314971923828125 +34023 0.40692138671875 +34024 0.28857421875 +34025 0.3778076171875 +34026 0.284454345703125 +34027 0.376953125 +34028 0.277679443359375 +34029 0.371978759765625 +34030 0.22979736328125 +34031 0.313140869140625 +34032 0.12847900390625 +34033 0.184417724609375 +34034 -0.006500244140625 +34035 0.011199951171875 +34036 -0.14764404296875 +34037 -0.171051025390625 +34038 -0.275634765625 +34039 -0.33740234375 +34040 -0.378204345703125 +34041 -0.47198486328125 +34042 -0.4443359375 +34043 -0.560394287109375 +34044 -0.45709228515625 +34045 -0.58056640625 +34046 -0.42828369140625 +34047 -0.54754638671875 +34048 -0.3946533203125 +34049 -0.508575439453125 +34050 -0.353363037109375 +34051 -0.459503173828125 +34052 -0.299774169921875 +34053 -0.394378662109375 +34054 -0.263458251953125 +34055 -0.35260009765625 +34056 -0.227935791015625 +34057 -0.31170654296875 +34058 -0.13818359375 +34059 -0.197418212890625 +34060 0.006866455078125 +34061 -0.007965087890625 +34062 0.17041015625 +34063 0.207489013671875 +34064 0.32275390625 +34065 0.409210205078125 +34066 0.44512939453125 +34067 0.57208251953125 +34068 0.515106201171875 +34069 0.66595458984375 +34070 0.5087890625 +34071 0.65875244140625 +34072 0.43890380859375 +34073 0.56744384765625 +34074 0.334869384765625 +34075 0.431396484375 +34076 0.229522705078125 +34077 0.29443359375 +34078 0.142303466796875 +34079 0.182464599609375 +34080 0.049774169921875 +34081 0.06365966796875 +34082 -0.0582275390625 +34083 -0.075958251953125 +34084 -0.14654541015625 +34085 -0.189422607421875 +34086 -0.211395263671875 +34087 -0.271942138671875 +34088 -0.26678466796875 +34089 -0.342529296875 +34090 -0.2850341796875 +34091 -0.364166259765625 +34092 -0.258880615234375 +34093 -0.327239990234375 +34094 -0.221923828125 +34095 -0.2769775390625 +34096 -0.20416259765625 +34097 -0.253692626953125 +34098 -0.1954345703125 +34099 -0.24365234375 +34100 -0.159759521484375 +34101 -0.1983642578125 +34102 -0.096099853515625 +34103 -0.116241455078125 +34104 -0.03399658203125 +34105 -0.036834716796875 +34106 0.02264404296875 +34107 0.034881591796875 +34108 0.067962646484375 +34109 0.09124755859375 +34110 0.084381103515625 +34111 0.10888671875 +34112 0.099761962890625 +34113 0.125518798828125 +34114 0.12628173828125 +34115 0.15771484375 +34116 0.143585205078125 +34117 0.17828369140625 +34118 0.139556884765625 +34119 0.17108154296875 +34120 0.109619140625 +34121 0.129974365234375 +34122 0.07415771484375 +34123 0.082427978515625 +34124 0.03265380859375 +34125 0.027679443359375 +34126 -0.03814697265625 +34127 -0.065643310546875 +34128 -0.1097412109375 +34129 -0.15936279296875 +34130 -0.152008056640625 +34131 -0.21307373046875 +34132 -0.170654296875 +34133 -0.234649658203125 +34134 -0.147735595703125 +34135 -0.2001953125 +34136 -0.09014892578125 +34137 -0.119171142578125 +34138 -0.0224609375 +34139 -0.024749755859375 +34140 0.057525634765625 +34141 0.085784912109375 +34142 0.1243896484375 +34143 0.178131103515625 +34144 0.150909423828125 +34145 0.215576171875 +34146 0.14703369140625 +34147 0.211456298828125 +34148 0.119873046875 +34149 0.17523193359375 +34150 0.085662841796875 +34151 0.128753662109375 +34152 0.066619873046875 +34153 0.1019287109375 +34154 0.047515869140625 +34155 0.0743408203125 +34156 0.026214599609375 +34157 0.04327392578125 +34158 0.024505615234375 +34159 0.038177490234375 +34160 0.0550537109375 +34161 0.076263427734375 +34162 0.10546875 +34163 0.14105224609375 +34164 0.141357421875 +34165 0.186431884765625 +34166 0.145050048828125 +34167 0.188812255859375 +34168 0.109619140625 +34169 0.1390380859375 +34170 0.038482666015625 +34171 0.041778564453125 +34172 -0.0509033203125 +34173 -0.079437255859375 +34174 -0.154693603515625 +34175 -0.219390869140625 +34176 -0.2652587890625 +34177 -0.367828369140625 +34178 -0.3603515625 +34179 -0.494873046875 +34180 -0.406982421875 +34181 -0.556243896484375 +34182 -0.3729248046875 +34183 -0.508697509765625 +34184 -0.27545166015625 +34185 -0.3756103515625 +34186 -0.16058349609375 +34187 -0.218902587890625 +34188 -0.04693603515625 +34189 -0.063751220703125 +34190 0.066802978515625 +34191 0.091552734375 +34192 0.172576904296875 +34193 0.23602294921875 +34194 0.250640869140625 +34195 0.342987060546875 +34196 0.28826904296875 +34197 0.39520263671875 +34198 0.2830810546875 +34199 0.389373779296875 +34200 0.234161376953125 +34201 0.324249267578125 +34202 0.159576416015625 +34203 0.224090576171875 +34204 0.085601806640625 +34205 0.124267578125 +34206 0.0213623046875 +34207 0.037078857421875 +34208 -0.01275634765625 +34209 -0.010101318359375 +34210 -0.018463134765625 +34211 -0.019439697265625 +34212 -0.01953125 +34213 -0.022796630859375 +34214 -0.002166748046875 +34215 -0.001556396484375 +34216 0.04241943359375 +34217 0.056304931640625 +34218 0.081390380859375 +34219 0.106719970703125 +34220 0.07537841796875 +34221 0.096893310546875 +34222 0.036163330078125 +34223 0.042694091796875 +34224 -0.008209228515625 +34225 -0.018035888671875 +34226 -0.05072021484375 +34227 -0.07586669921875 +34228 -0.08294677734375 +34229 -0.11944580078125 +34230 -0.113037109375 +34231 -0.15972900390625 +34232 -0.145355224609375 +34233 -0.202606201171875 +34234 -0.18023681640625 +34235 -0.24859619140625 +34236 -0.22320556640625 +34237 -0.30517578125 +34238 -0.266632080078125 +34239 -0.36212158203125 +34240 -0.28961181640625 +34241 -0.39141845703125 +34242 -0.263946533203125 +34243 -0.35528564453125 +34244 -0.186767578125 +34245 -0.249969482421875 +34246 -0.071014404296875 +34247 -0.092864990234375 +34248 0.063323974609375 +34249 0.08905029296875 +34250 0.1712646484375 +34251 0.2352294921875 +34252 0.232879638671875 +34253 0.318817138671875 +34254 0.262176513671875 +34255 0.358642578125 +34256 0.253997802734375 +34257 0.347747802734375 +34258 0.207977294921875 +34259 0.28564453125 +34260 0.161956787109375 +34261 0.223175048828125 +34262 0.1429443359375 +34263 0.196746826171875 +34264 0.131195068359375 +34265 0.179840087890625 +34266 0.114105224609375 +34267 0.155548095703125 +34268 0.1119384765625 +34269 0.151214599609375 +34270 0.117279052734375 +34271 0.156951904296875 +34272 0.099517822265625 +34273 0.13177490234375 +34274 0.07733154296875 +34275 0.100799560546875 +34276 0.06787109375 +34277 0.087127685546875 +34278 0.044403076171875 +34279 0.05487060546875 +34280 -0.002777099609375 +34281 -0.009002685546875 +34282 -0.07330322265625 +34283 -0.10400390625 +34284 -0.166656494140625 +34285 -0.229400634765625 +34286 -0.260772705078125 +34287 -0.35552978515625 +34288 -0.32550048828125 +34289 -0.441925048828125 +34290 -0.349884033203125 +34291 -0.473846435546875 +34292 -0.343902587890625 +34293 -0.464813232421875 +34294 -0.3106689453125 +34295 -0.419097900390625 +34296 -0.248382568359375 +34297 -0.334320068359375 +34298 -0.170013427734375 +34299 -0.227935791015625 +34300 -0.093017578125 +34301 -0.12347412109375 +34302 -0.0223388671875 +34303 -0.02764892578125 +34304 0.055572509765625 +34305 0.077667236328125 +34306 0.15594482421875 +34307 0.2132568359375 +34308 0.28521728515625 +34309 0.38885498046875 +34310 0.42730712890625 +34311 0.582794189453125 +34312 0.53826904296875 +34313 0.734039306640625 +34314 0.587554931640625 +34315 0.800140380859375 +34316 0.572967529296875 +34317 0.7783203125 +34318 0.49200439453125 +34319 0.6651611328125 +34320 0.344024658203125 +34321 0.45965576171875 +34322 0.15576171875 +34323 0.199188232421875 +34324 -0.02587890625 +34325 -0.050689697265625 +34326 -0.1600341796875 +34327 -0.23297119140625 +34328 -0.233978271484375 +34329 -0.33013916015625 +34330 -0.266021728515625 +34331 -0.368408203125 +34332 -0.278045654296875 +34333 -0.378936767578125 +34334 -0.2806396484375 +34335 -0.376983642578125 +34336 -0.285797119140625 +34337 -0.37969970703125 +34338 -0.2965087890625 +34339 -0.391510009765625 +34340 -0.29339599609375 +34341 -0.385345458984375 +34342 -0.262664794921875 +34343 -0.3419189453125 +34344 -0.21978759765625 +34345 -0.28289794921875 +34346 -0.1956787109375 +34347 -0.251617431640625 +34348 -0.20330810546875 +34349 -0.266143798828125 +34350 -0.205047607421875 +34351 -0.273345947265625 +34352 -0.160888671875 +34353 -0.216796875 +34354 -0.093658447265625 +34355 -0.128265380859375 +34356 -0.046630859375 +34357 -0.068145751953125 +34358 -0.0247802734375 +34359 -0.0430908203125 +34360 -0.007904052734375 +34361 -0.024444580078125 +34362 0.027252197265625 +34363 0.020721435546875 +34364 0.10333251953125 +34365 0.124481201171875 +34366 0.199615478515625 +34367 0.25787353515625 +34368 0.28631591796875 +34369 0.379119873046875 +34370 0.357574462890625 +34371 0.47991943359375 +34372 0.390594482421875 +34373 0.5281982421875 +34374 0.3763427734375 +34375 0.511138916015625 +34376 0.334503173828125 +34377 0.456207275390625 +34378 0.296630859375 +34379 0.407470703125 +34380 0.27630615234375 +34381 0.383758544921875 +34382 0.253631591796875 +34383 0.35687255859375 +34384 0.2181396484375 +34385 0.31182861328125 +34386 0.171630859375 +34387 0.250885009765625 +34388 0.108123779296875 +34389 0.1654052734375 +34390 0.013397216796875 +34391 0.035247802734375 +34392 -0.11419677734375 +34393 -0.142059326171875 +34394 -0.252593994140625 +34395 -0.33563232421875 +34396 -0.394012451171875 +34397 -0.5345458984375 +34398 -0.52642822265625 +34399 -0.72186279296875 +34400 -0.606536865234375 +34401 -0.836669921875 +34402 -0.601470947265625 +34403 -0.8326416015625 +34404 -0.5255126953125 +34405 -0.7296142578125 +34406 -0.41796875 +34407 -0.582550048828125 +34408 -0.3135986328125 +34409 -0.440093994140625 +34410 -0.228302001953125 +34411 -0.324310302734375 +34412 -0.138214111328125 +34413 -0.20147705078125 +34414 -0.024261474609375 +34415 -0.044647216796875 +34416 0.0833740234375 +34417 0.103973388671875 +34418 0.15472412109375 +34419 0.202392578125 +34420 0.199615478515625 +34421 0.264495849609375 +34422 0.25262451171875 +34423 0.338897705078125 +34424 0.32672119140625 +34425 0.443817138671875 +34426 0.39764404296875 +34427 0.545074462890625 +34428 0.447418212890625 +34429 0.6173095703125 +34430 0.47039794921875 +34431 0.6524658203125 +34432 0.475860595703125 +34433 0.66339111328125 +34434 0.46826171875 +34435 0.6561279296875 +34436 0.430694580078125 +34437 0.606781005859375 +34438 0.353240966796875 +34439 0.501190185546875 +34440 0.245574951171875 +34441 0.352783203125 +34442 0.118438720703125 +34443 0.176544189453125 +34444 -0.03326416015625 +34445 -0.034820556640625 +34446 -0.1929931640625 +34447 -0.258209228515625 +34448 -0.324310302734375 +34449 -0.44244384765625 +34450 -0.41851806640625 +34451 -0.5753173828125 +34452 -0.4722900390625 +34453 -0.65203857421875 +34454 -0.463592529296875 +34455 -0.641632080078125 +34456 -0.4053955078125 +34457 -0.562164306640625 +34458 -0.32940673828125 +34459 -0.458038330078125 +34460 -0.250885009765625 +34461 -0.350555419921875 +34462 -0.184783935546875 +34463 -0.260528564453125 +34464 -0.1341552734375 +34465 -0.192108154296875 +34466 -0.096710205078125 +34467 -0.141937255859375 +34468 -0.06695556640625 +34469 -0.1021728515625 +34470 -0.037872314453125 +34471 -0.062896728515625 +34472 -0.0008544921875 +34473 -0.011932373046875 +34474 0.05267333984375 +34475 0.062835693359375 +34476 0.113677978515625 +34477 0.148712158203125 +34478 0.179351806640625 +34479 0.241729736328125 +34480 0.254852294921875 +34481 0.34912109375 +34482 0.330596923828125 +34483 0.457305908203125 +34484 0.3907470703125 +34485 0.54388427734375 +34486 0.409759521484375 +34487 0.5728759765625 +34488 0.360870361328125 +34489 0.506591796875 +34490 0.24859619140625 +34491 0.351226806640625 +34492 0.101318359375 +34493 0.146514892578125 +34494 -0.04364013671875 +34495 -0.05523681640625 +34496 -0.1593017578125 +34497 -0.21624755859375 +34498 -0.244476318359375 +34499 -0.334930419921875 +34500 -0.29327392578125 +34501 -0.402984619140625 +34502 -0.32049560546875 +34503 -0.4412841796875 +34504 -0.35888671875 +34505 -0.49578857421875 +34506 -0.40399169921875 +34507 -0.5601806640625 +34508 -0.431854248046875 +34509 -0.600738525390625 +34510 -0.41888427734375 +34511 -0.584228515625 +34512 -0.34283447265625 +34513 -0.47930908203125 +34514 -0.199066162109375 +34515 -0.27935791015625 +34516 -0.005126953125 +34517 -0.0089111328125 +34518 0.19384765625 +34519 0.268798828125 +34520 0.347320556640625 +34521 0.482818603515625 +34522 0.43426513671875 +34523 0.60369873046875 +34524 0.4681396484375 +34525 0.650421142578125 +34526 0.478118896484375 +34527 0.66400146484375 +34528 0.462066650390625 +34529 0.6414794921875 +34530 0.41265869140625 +34531 0.572540283203125 +34532 0.359100341796875 +34533 0.498138427734375 +34534 0.3165283203125 +34535 0.439453125 +34536 0.270050048828125 +34537 0.375518798828125 +34538 0.197052001953125 +34539 0.274505615234375 +34540 0.077911376953125 +34541 0.1087646484375 +34542 -0.0714111328125 +34543 -0.099395751953125 +34544 -0.228240966796875 +34545 -0.3182373046875 +34546 -0.3934326171875 +34547 -0.5489501953125 +34548 -0.55426025390625 +34549 -0.7738037109375 +34550 -0.673004150390625 +34551 -0.86383056640625 +34552 -0.7259521484375 +34553 -0.870391845703125 +34554 -0.7257080078125 +34555 -0.86895751953125 +34556 -0.681640625 +34557 -0.861053466796875 +34558 -0.581451416015625 +34559 -0.765869140625 +34560 -0.417205810546875 +34561 -0.5301513671875 +34562 -0.19451904296875 +34563 -0.214691162109375 +34564 0.05609130859375 +34565 0.137359619140625 +34566 0.2987060546875 +34567 0.474822998046875 +34568 0.508270263671875 +34569 0.76239013671875 +34570 0.665740966796875 +34571 0.867462158203125 +34572 0.770904541015625 +34573 0.870361328125 +34574 0.81561279296875 +34575 0.86480712890625 +34576 0.8033447265625 +34577 0.831817626953125 +34578 0.750701904296875 +34579 0.677581787109375 +34580 0.66180419921875 +34581 0.495880126953125 +34582 0.549591064453125 +34583 0.30767822265625 +34584 0.415985107421875 +34585 0.116180419921875 +34586 0.2398681640625 +34587 -0.110748291015625 +34588 0.01708984375 +34589 -0.381805419921875 +34590 -0.222686767578125 +34591 -0.6572265625 +34592 -0.43817138671875 +34593 -0.857421875 +34594 -0.599700927734375 +34595 -0.870391845703125 +34596 -0.701995849609375 +34597 -0.870391845703125 +34598 -0.763031005859375 +34599 -0.86444091796875 +34600 -0.806854248046875 +34601 -0.85723876953125 +34602 -0.82086181640625 +34603 -0.790008544921875 +34604 -0.7681884765625 +34605 -0.62847900390625 +34606 -0.646759033203125 +34607 -0.3956298828125 +34608 -0.4791259765625 +34609 -0.126708984375 +34610 -0.28424072265625 +34611 0.150115966796875 +34612 -0.0704345703125 +34613 0.424041748046875 +34614 0.1435546875 +34615 0.670623779296875 +34616 0.3309326171875 +34617 0.854522705078125 +34618 0.479217529296875 +34619 0.866485595703125 +34620 0.577545166015625 +34621 0.86920166015625 +34622 0.637908935546875 +34623 0.8653564453125 +34624 0.66912841796875 +34625 0.857147216796875 +34626 0.668975830078125 +34627 0.766845703125 +34628 0.64080810546875 +34629 0.628509521484375 +34630 0.580047607421875 +34631 0.462127685546875 +34632 0.5042724609375 +34633 0.297210693359375 +34634 0.42205810546875 +34635 0.14862060546875 +34636 0.318145751953125 +34637 -0.00537109375 +34638 0.1978759765625 +34639 -0.15753173828125 +34640 0.05914306640625 +34641 -0.31304931640625 +34642 -0.107177734375 +34643 -0.48876953125 +34644 -0.268829345703125 +34645 -0.6416015625 +34646 -0.408660888671875 +34647 -0.751373291015625 +34648 -0.542022705078125 +34649 -0.84619140625 +34650 -0.65863037109375 +34651 -0.861297607421875 +34652 -0.7357177734375 +34653 -0.863250732421875 +34654 -0.751678466796875 +34655 -0.856597900390625 +34656 -0.714691162109375 +34657 -0.7498779296875 +34658 -0.66412353515625 +34659 -0.624542236328125 +34660 -0.58514404296875 +34661 -0.47808837890625 +34662 -0.43817138671875 +34663 -0.253387451171875 +34664 -0.254486083984375 +34665 0.003692626953125 +34666 -0.08087158203125 +34667 0.2257080078125 +34668 0.09088134765625 +34669 0.427154541015625 +34670 0.282470703125 +34671 0.643218994140625 +34672 0.486968994140625 +34673 0.855926513671875 +34674 0.6646728515625 +34675 0.870361328125 +34676 0.781585693359375 +34677 0.870361328125 +34678 0.84234619140625 +34679 0.862762451171875 +34680 0.84478759765625 +34681 0.79669189453125 +34682 0.78240966796875 +34683 0.595794677734375 +34684 0.675079345703125 +34685 0.362152099609375 +34686 0.54193115234375 +34687 0.1270751953125 +34688 0.397491455078125 +34689 -0.086944580078125 +34690 0.243408203125 +34691 -0.2784423828125 +34692 0.0562744140625 +34693 -0.484832763671875 +34694 -0.1766357421875 +34695 -0.729583740234375 +34696 -0.420562744140625 +34697 -0.86688232421875 +34698 -0.63214111328125 +34699 -0.870391845703125 +34700 -0.80767822265625 +34701 -0.86859130859375 +34702 -0.86444091796875 +34703 -0.86279296875 +34704 -0.870391845703125 +34705 -0.817962646484375 +34706 -0.8663330078125 +34707 -0.6116943359375 +34708 -0.829803466796875 +34709 -0.3128662109375 +34710 -0.62481689453125 +34711 0.039398193359375 +34712 -0.362091064453125 +34713 0.422821044921875 +34714 -0.06475830078125 +34715 0.805145263671875 +34716 0.220550537109375 +34717 0.870361328125 +34718 0.454925537109375 +34719 0.870361328125 +34720 0.630401611328125 +34721 0.860015869140625 +34722 0.741973876953125 +34723 0.727935791015625 +34724 0.786163330078125 +34725 0.48114013671875 +34726 0.7799072265625 +34727 0.2059326171875 +34728 0.739166259765625 +34729 -0.06103515625 +34730 0.67144775390625 +34731 -0.29913330078125 +34732 0.567596435546875 +34733 -0.516204833984375 +34734 0.41790771484375 +34735 -0.7252197265625 +34736 0.24005126953125 +34737 -0.85980224609375 +34738 0.05804443359375 +34739 -0.870391845703125 +34740 -0.107330322265625 +34741 -0.870391845703125 +34742 -0.222381591796875 +34743 -0.858062744140625 +34744 -0.2838134765625 +34745 -0.673004150390625 +34746 -0.3270263671875 +34747 -0.42694091796875 +34748 -0.382080078125 +34749 -0.2100830078125 +34750 -0.447540283203125 +34751 -0.0362548828125 +34752 -0.5037841796875 +34753 0.10943603515625 +34754 -0.537567138671875 +34755 0.23516845703125 +34756 -0.52117919921875 +34757 0.373687744140625 +34758 -0.45648193359375 +34759 0.517791748046875 +34760 -0.38690185546875 +34761 0.602783203125 +34762 -0.309600830078125 +34763 0.635711669921875 +34764 -0.20257568359375 +34765 0.655181884765625 +34766 -0.073211669921875 +34767 0.65948486328125 +34768 0.072418212890625 +34769 0.651275634765625 +34770 0.2171630859375 +34771 0.61846923828125 +34772 0.335479736328125 +34773 0.53753662109375 +34774 0.414794921875 +34775 0.404144287109375 +34776 0.448333740234375 +34777 0.22186279296875 +34778 0.43695068359375 +34779 0.003997802734375 +34780 0.393096923828125 +34781 -0.22100830078125 +34782 0.331085205078125 +34783 -0.42449951171875 +34784 0.265838623046875 +34785 -0.579833984375 +34786 0.22686767578125 +34787 -0.641876220703125 +34788 0.210205078125 +34789 -0.6177978515625 +34790 0.1724853515625 +34791 -0.575531005859375 +34792 0.110626220703125 +34793 -0.526336669921875 +34794 0.060394287109375 +34795 -0.42645263671875 +34796 0.04095458984375 +34797 -0.2581787109375 +34798 0.0279541015625 +34799 -0.068695068359375 +34800 -0.004425048828125 +34801 0.09222412109375 +34802 -0.043304443359375 +34803 0.232147216796875 +34804 -0.0816650390625 +34805 0.3509521484375 +34806 -0.139678955078125 +34807 0.410064697265625 +34808 -0.237457275390625 +34809 0.372955322265625 +34810 -0.360992431640625 +34811 0.2554931640625 +34812 -0.475128173828125 +34813 0.10711669921875 +34814 -0.566925048828125 +34815 -0.052886962890625 +34816 -0.612579345703125 +34817 -0.186279296875 +34818 -0.574951171875 +34819 -0.23291015625 +34820 -0.46905517578125 +34821 -0.209442138671875 +34822 -0.3388671875 +34823 -0.174163818359375 +34824 -0.19085693359375 +34825 -0.126739501953125 +34826 -0.0196533203125 +34827 -0.048126220703125 +34828 0.155517578125 +34829 0.0426025390625 +34830 0.3035888671875 +34831 0.10748291015625 +34832 0.4154052734375 +34833 0.1409912109375 +34834 0.521514892578125 +34835 0.19708251953125 +34836 0.617340087890625 +34837 0.273651123046875 +34838 0.66656494140625 +34839 0.31768798828125 +34840 0.676544189453125 +34841 0.341094970703125 +34842 0.66400146484375 +34843 0.368011474609375 +34844 0.614471435546875 +34845 0.37249755859375 +34846 0.496490478515625 +34847 0.30072021484375 +34848 0.313873291015625 +34849 0.1517333984375 +34850 0.110595703125 +34851 -0.01470947265625 +34852 -0.1011962890625 +34853 -0.1883544921875 +34854 -0.318267822265625 +34855 -0.372711181640625 +34856 -0.500396728515625 +34857 -0.51397705078125 +34858 -0.6165771484375 +34859 -0.57177734375 +34860 -0.6585693359375 +34861 -0.53948974609375 +34862 -0.635101318359375 +34863 -0.43511962890625 +34864 -0.5687255859375 +34865 -0.2962646484375 +34866 -0.4835205078125 +34867 -0.161102294921875 +34868 -0.389007568359375 +34869 -0.0435791015625 +34870 -0.284149169921875 +34871 0.060394287109375 +34872 -0.180694580078125 +34873 0.13665771484375 +34874 -0.091888427734375 +34875 0.170135498046875 +34876 -0.018707275390625 +34877 0.16552734375 +34878 0.056793212890625 +34879 0.15728759765625 +34880 0.133575439453125 +34881 0.150787353515625 +34882 0.191619873046875 +34883 0.12200927734375 +34884 0.2327880859375 +34885 0.080108642578125 +34886 0.2706298828125 +34887 0.05126953125 +34888 0.32025146484375 +34889 0.062896728515625 +34890 0.365264892578125 +34891 0.09271240234375 +34892 0.373748779296875 +34893 0.092987060546875 +34894 0.3553466796875 +34895 0.07855224609375 +34896 0.320709228515625 +34897 0.06427001953125 +34898 0.261688232421875 +34899 0.0347900390625 +34900 0.1796875 +34901 -0.01171875 +34902 0.09033203125 +34903 -0.056060791015625 +34904 0.02496337890625 +34905 -0.055511474609375 +34906 -0.012908935546875 +34907 -0.010467529296875 +34908 -0.054656982421875 +34909 0.02508544921875 +34910 -0.11334228515625 +34911 0.025665283203125 +34912 -0.16900634765625 +34913 0.017333984375 +34914 -0.217987060546875 +34915 0.00189208984375 +34916 -0.26568603515625 +34917 -0.03173828125 +34918 -0.30328369140625 +34919 -0.071502685546875 +34920 -0.342254638671875 +34921 -0.13543701171875 +34922 -0.380828857421875 +34923 -0.219970703125 +34924 -0.404266357421875 +34925 -0.300506591796875 +34926 -0.4140625 +34927 -0.376312255859375 +34928 -0.392303466796875 +34929 -0.416107177734375 +34930 -0.310150146484375 +34931 -0.371124267578125 +34932 -0.171234130859375 +34933 -0.242279052734375 +34934 -0.004730224609375 +34935 -0.069732666015625 +34936 0.172821044921875 +34937 0.125640869140625 +34938 0.338531494140625 +34939 0.31268310546875 +34940 0.466552734375 +34941 0.45501708984375 +34942 0.55657958984375 +34943 0.554779052734375 +34944 0.606689453125 +34945 0.61065673828125 +34946 0.60882568359375 +34947 0.610931396484375 +34948 0.54754638671875 +34949 0.531463623046875 +34950 0.434112548828125 +34951 0.3883056640625 +34952 0.304534912109375 +34953 0.23468017578125 +34954 0.1767578125 +34955 0.095245361328125 +34956 0.069915771484375 +34957 -0.00396728515625 +34958 -0.004150390625 +34959 -0.04852294921875 +34960 -0.053741455078125 +34961 -0.055145263671875 +34962 -0.110198974609375 +34963 -0.0758056640625 +34964 -0.189544677734375 +34965 -0.138702392578125 +34966 -0.26727294921875 +34967 -0.209197998046875 +34968 -0.342987060546875 +34969 -0.289031982421875 +34970 -0.416046142578125 +34971 -0.37884521484375 +34972 -0.471405029296875 +34973 -0.456329345703125 +34974 -0.505767822265625 +34975 -0.51641845703125 +34976 -0.493804931640625 +34977 -0.519287109375 +34978 -0.432159423828125 +34979 -0.458251953125 +34980 -0.355743408203125 +34981 -0.384796142578125 +34982 -0.28240966796875 +34983 -0.323699951171875 +34984 -0.210418701171875 +34985 -0.269287109375 +34986 -0.124755859375 +34987 -0.1951904296875 +34988 -0.026580810546875 +34989 -0.100006103515625 +34990 0.064697265625 +34991 -0.01055908203125 +34992 0.167022705078125 +34993 0.1033935546875 +34994 0.283721923828125 +34995 0.24908447265625 +34996 0.379119873046875 +34997 0.373199462890625 +34998 0.441162109375 +34999 0.45806884765625 +35000 0.4747314453125 +35001 0.511474609375 +35002 0.50091552734375 +35003 0.565399169921875 +35004 0.514923095703125 +35005 0.61138916015625 +35006 0.47900390625 +35007 0.5897216796875 +35008 0.388153076171875 +35009 0.4906005859375 +35010 0.25531005859375 +35011 0.33148193359375 +35012 0.10516357421875 +35013 0.147796630859375 +35014 -0.033447265625 +35015 -0.01873779296875 +35016 -0.140777587890625 +35017 -0.140289306640625 +35018 -0.19915771484375 +35019 -0.191986083984375 +35020 -0.21417236328125 +35021 -0.184295654296875 +35022 -0.213836669921875 +35023 -0.161834716796875 +35024 -0.224853515625 +35025 -0.166595458984375 +35026 -0.243927001953125 +35027 -0.19390869140625 +35028 -0.258575439453125 +35029 -0.22442626953125 +35030 -0.2833251953125 +35031 -0.279754638671875 +35032 -0.305389404296875 +35033 -0.3389892578125 +35034 -0.2947998046875 +35035 -0.3543701171875 +35036 -0.267242431640625 +35037 -0.348175048828125 +35038 -0.22772216796875 +35039 -0.32598876953125 +35040 -0.158416748046875 +35041 -0.2581787109375 +35042 -0.057464599609375 +35043 -0.139801025390625 +35044 0.064422607421875 +35045 0.014617919921875 +35046 0.166656494140625 +35047 0.144378662109375 +35048 0.229888916015625 +35049 0.221038818359375 +35050 0.270477294921875 +35051 0.27069091796875 +35052 0.288604736328125 +35053 0.294036865234375 +35054 0.297698974609375 +35055 0.311767578125 +35056 0.307952880859375 +35057 0.339141845703125 +35058 0.309539794921875 +35059 0.360260009765625 +35060 0.293792724609375 +35061 0.360504150390625 +35062 0.241241455078125 +35063 0.308380126953125 +35064 0.138641357421875 +35065 0.18170166015625 +35066 0.002960205078125 +35067 0.0047607421875 +35068 -0.13427734375 +35069 -0.17559814453125 +35070 -0.242828369140625 +35071 -0.3143310546875 +35072 -0.29388427734375 +35073 -0.36785888671875 +35074 -0.30328369140625 +35075 -0.36248779296875 +35076 -0.2991943359375 +35077 -0.343536376953125 +35078 -0.27593994140625 +35079 -0.3018798828125 +35080 -0.229888916015625 +35081 -0.231414794921875 +35082 -0.15252685546875 +35083 -0.117645263671875 +35084 -0.06439208984375 +35085 0.007049560546875 +35086 6.103515625e-05 +35087 0.087982177734375 +35088 0.04876708984375 +35089 0.13946533203125 +35090 0.088592529296875 +35091 0.17425537109375 +35092 0.115936279296875 +35093 0.188201904296875 +35094 0.12359619140625 +35095 0.171234130859375 +35096 0.10760498046875 +35097 0.118438720703125 +35098 0.08392333984375 +35099 0.05706787109375 +35100 0.05316162109375 +35101 -0.010711669921875 +35102 0.01080322265625 +35103 -0.0914306640625 +35104 -0.029388427734375 +35105 -0.162322998046875 +35106 -0.04974365234375 +35107 -0.194549560546875 +35108 -0.02618408203125 +35109 -0.1492919921875 +35110 0.044647216796875 +35111 -0.02166748046875 +35112 0.123687744140625 +35113 0.124053955078125 +35114 0.164337158203125 +35115 0.211151123046875 +35116 0.16790771484375 +35117 0.240447998046875 +35118 0.15386962890625 +35119 0.242218017578125 +35120 0.128753662109375 +35121 0.2257080078125 +35122 0.095489501953125 +35123 0.194366455078125 +35124 0.034698486328125 +35125 0.115509033203125 +35126 -0.03839111328125 +35127 0.0128173828125 +35128 -0.08642578125 +35129 -0.053802490234375 +35130 -0.125274658203125 +35131 -0.110626220703125 +35132 -0.180633544921875 +35133 -0.199493408203125 +35134 -0.23651123046875 +35135 -0.29437255859375 +35136 -0.254302978515625 +35137 -0.33221435546875 +35138 -0.213897705078125 +35139 -0.27972412109375 +35140 -0.1456298828125 +35141 -0.185333251953125 +35142 -0.098876953125 +35143 -0.128204345703125 +35144 -0.078826904296875 +35145 -0.115692138671875 +35146 -0.066864013671875 +35147 -0.116455078125 +35148 -0.048583984375 +35149 -0.105926513671875 +35150 -0.006011962890625 +35151 -0.053955078125 +35152 0.0660400390625 +35153 0.048797607421875 +35154 0.13946533203125 +35155 0.157318115234375 +35156 0.177215576171875 +35157 0.212005615234375 +35158 0.182586669921875 +35159 0.218475341796875 +35160 0.19287109375 +35161 0.23724365234375 +35162 0.231048583984375 +35163 0.30535888671875 +35164 0.27178955078125 +35165 0.38128662109375 +35166 0.278167724609375 +35167 0.404449462890625 +35168 0.262725830078125 +35169 0.3944091796875 +35170 0.2490234375 +35171 0.3885498046875 +35172 0.22271728515625 +35173 0.362640380859375 +35174 0.157867431640625 +35175 0.27362060546875 +35176 0.052337646484375 +35177 0.11712646484375 +35178 -0.061370849609375 +35179 -0.054901123046875 +35180 -0.151123046875 +35181 -0.19085693359375 +35182 -0.213531494140625 +35183 -0.28570556640625 +35184 -0.248321533203125 +35185 -0.339263916015625 +35186 -0.271484375 +35187 -0.3775634765625 +35188 -0.3109130859375 +35189 -0.445709228515625 +35190 -0.361480712890625 +35191 -0.535064697265625 +35192 -0.413299560546875 +35193 -0.629058837890625 +35194 -0.44818115234375 +35195 -0.697601318359375 +35196 -0.443939208984375 +35197 -0.70391845703125 +35198 -0.3975830078125 +35199 -0.6424560546875 +35200 -0.296051025390625 +35201 -0.491241455078125 +35202 -0.149322509765625 +35203 -0.265716552734375 +35204 0.00653076171875 +35205 -0.023712158203125 +35206 0.150848388671875 +35207 0.201751708984375 +35208 0.261871337890625 +35209 0.375823974609375 +35210 0.331207275390625 +35211 0.485076904296875 +35212 0.383026123046875 +35213 0.56884765625 +35214 0.42205810546875 +35215 0.634765625 +35216 0.420623779296875 +35217 0.63763427734375 +35218 0.37188720703125 +35219 0.5660400390625 +35220 0.308197021484375 +35221 0.4720458984375 +35222 0.261505126953125 +35223 0.40692138671875 +35224 0.236602783203125 +35225 0.3778076171875 +35226 0.229095458984375 +35227 0.376953125 +35228 0.219390869140625 +35229 0.371978759765625 +35230 0.17724609375 +35231 0.313140869140625 +35232 0.09307861328125 +35233 0.184417724609375 +35234 -0.0172119140625 +35235 0.011199951171875 +35236 -0.13165283203125 +35237 -0.171051025390625 +35238 -0.23480224609375 +35239 -0.33740234375 +35240 -0.316864013671875 +35241 -0.47198486328125 +35242 -0.369049072265625 +35243 -0.560394287109375 +35244 -0.377960205078125 +35245 -0.58056640625 +35246 -0.353118896484375 +35247 -0.54754638671875 +35248 -0.3238525390625 +35249 -0.508575439453125 +35250 -0.2879638671875 +35251 -0.459503173828125 +35252 -0.2420654296875 +35253 -0.394378662109375 +35254 -0.21075439453125 +35255 -0.35260009765625 +35256 -0.18048095703125 +35257 -0.31170654296875 +35258 -0.10577392578125 +35259 -0.197418212890625 +35260 0.014251708984375 +35261 -0.007965087890625 +35262 0.149139404296875 +35263 0.207489013671875 +35264 0.274322509765625 +35265 0.409210205078125 +35266 0.374298095703125 +35267 0.57208251953125 +35268 0.430572509765625 +35269 0.66595458984375 +35270 0.42352294921875 +35271 0.65875244140625 +35272 0.36376953125 +35273 0.56744384765625 +35274 0.2757568359375 +35275 0.431396484375 +35276 0.186737060546875 +35277 0.29443359375 +35278 0.11297607421875 +35279 0.182464599609375 +35280 0.035125732421875 +35281 0.06365966796875 +35282 -0.05517578125 +35283 -0.075958251953125 +35284 -0.1287841796875 +35285 -0.189422607421875 +35286 -0.182525634765625 +35287 -0.271942138671875 +35288 -0.22796630859375 +35289 -0.342529296875 +35290 -0.242279052734375 +35291 -0.364166259765625 +35292 -0.219512939453125 +35293 -0.327239990234375 +35294 -0.187530517578125 +35295 -0.2769775390625 +35296 -0.171295166015625 +35297 -0.253692626953125 +35298 -0.162445068359375 +35299 -0.24365234375 +35300 -0.13128662109375 +35301 -0.1983642578125 +35302 -0.0770263671875 +35303 -0.116241455078125 +35304 -0.02423095703125 +35305 -0.036834716796875 +35306 0.0238037109375 +35307 0.034881591796875 +35308 0.0621337890625 +35309 0.09124755859375 +35310 0.076171875 +35311 0.10888671875 +35312 0.0889892578125 +35313 0.125518798828125 +35314 0.1107177734375 +35315 0.15771484375 +35316 0.124481201171875 +35317 0.17828369140625 +35318 0.12030029296875 +35319 0.17108154296875 +35320 0.09442138671875 +35321 0.129974365234375 +35322 0.063812255859375 +35323 0.082427978515625 +35324 0.028106689453125 +35325 0.027679443359375 +35326 -0.031890869140625 +35327 -0.065643310546875 +35328 -0.092864990234375 +35329 -0.15936279296875 +35330 -0.129364013671875 +35331 -0.21307373046875 +35332 -0.145416259765625 +35333 -0.234649658203125 +35334 -0.12725830078125 +35335 -0.2001953125 +35336 -0.0806884765625 +35337 -0.119171142578125 +35338 -0.02532958984375 +35339 -0.024749755859375 +35340 0.0401611328125 +35341 0.085784912109375 +35342 0.095550537109375 +35343 0.178131103515625 +35344 0.119232177734375 +35345 0.215576171875 +35346 0.11883544921875 +35347 0.211456298828125 +35348 0.099761962890625 +35349 0.17523193359375 +35350 0.07464599609375 +35351 0.128753662109375 +35352 0.06085205078125 +35353 0.1019287109375 +35354 0.04638671875 +35355 0.0743408203125 +35356 0.02960205078125 +35357 0.04327392578125 +35358 0.027618408203125 +35359 0.038177490234375 +35360 0.05047607421875 +35361 0.076263427734375 +35362 0.08856201171875 +35363 0.14105224609375 +35364 0.11492919921875 +35365 0.186431884765625 +35366 0.115814208984375 +35367 0.188812255859375 +35368 0.0859375 +35369 0.1390380859375 +35370 0.028106689453125 +35371 0.041778564453125 +35372 -0.043853759765625 +35373 -0.079437255859375 +35374 -0.1268310546875 +35375 -0.219390869140625 +35376 -0.21478271484375 +35377 -0.367828369140625 +35378 -0.290191650390625 +35379 -0.494873046875 +35380 -0.327117919921875 +35381 -0.556243896484375 +35382 -0.300262451171875 +35383 -0.508697509765625 +35384 -0.223236083984375 +35385 -0.3756103515625 +35386 -0.1322021484375 +35387 -0.218902587890625 +35388 -0.04180908203125 +35389 -0.063751220703125 +35390 0.04888916015625 +35391 0.091552734375 +35392 0.133514404296875 +35393 0.23602294921875 +35394 0.196441650390625 +35395 0.342987060546875 +35396 0.22760009765625 +35397 0.39520263671875 +35398 0.225006103515625 +35399 0.389373779296875 +35400 0.187896728515625 +35401 0.324249267578125 +35402 0.130401611328125 +35403 0.224090576171875 +35404 0.0731201171875 +35405 0.124267578125 +35406 0.02313232421875 +35407 0.037078857421875 +35408 -0.003570556640625 +35409 -0.010101318359375 +35410 -0.008331298828125 +35411 -0.019439697265625 +35412 -0.009765625 +35413 -0.022796630859375 +35414 0.0029296875 +35415 -0.001556396484375 +35416 0.036773681640625 +35417 0.056304931640625 +35418 0.0660400390625 +35419 0.106719970703125 +35420 0.0599365234375 +35421 0.096893310546875 +35422 0.027740478515625 +35423 0.042694091796875 +35424 -0.008392333984375 +35425 -0.018035888671875 +35426 -0.04290771484375 +35427 -0.07586669921875 +35428 -0.06915283203125 +35429 -0.11944580078125 +35430 -0.093475341796875 +35431 -0.15972900390625 +35432 -0.1192626953125 +35433 -0.202606201171875 +35434 -0.146728515625 +35435 -0.24859619140625 +35436 -0.18023681640625 +35437 -0.30517578125 +35438 -0.21380615234375 +35439 -0.36212158203125 +35440 -0.231109619140625 +35441 -0.39141845703125 +35442 -0.210052490234375 +35443 -0.35528564453125 +35444 -0.148468017578125 +35445 -0.249969482421875 +35446 -0.056488037109375 +35447 -0.092864990234375 +35448 0.050079345703125 +35449 0.08905029296875 +35450 0.1358642578125 +35451 0.2352294921875 +35452 0.1851806640625 +35453 0.318817138671875 +35454 0.208953857421875 +35455 0.358642578125 +35456 0.203125 +35457 0.347747802734375 +35458 0.167388916015625 +35459 0.28564453125 +35460 0.131378173828125 +35461 0.223175048828125 +35462 0.1163330078125 +35463 0.196746826171875 +35464 0.106781005859375 +35465 0.179840087890625 +35466 0.092803955078125 +35467 0.155548095703125 +35468 0.090362548828125 +35469 0.151214599609375 +35470 0.09368896484375 +35471 0.156951904296875 +35472 0.078857421875 +35473 0.13177490234375 +35474 0.060546875 +35475 0.100799560546875 +35476 0.05224609375 +35477 0.087127685546875 +35478 0.03302001953125 +35479 0.05487060546875 +35480 -0.00469970703125 +35481 -0.009002685546875 +35482 -0.06060791015625 +35483 -0.10400390625 +35484 -0.13427734375 +35485 -0.229400634765625 +35486 -0.20831298828125 +35487 -0.35552978515625 +35488 -0.259063720703125 +35489 -0.441925048828125 +35490 -0.2779541015625 +35491 -0.473846435546875 +35492 -0.2728271484375 +35493 -0.464813232421875 +35494 -0.246185302734375 +35495 -0.419097900390625 +35496 -0.1966552734375 +35497 -0.334320068359375 +35498 -0.1343994140625 +35499 -0.227935791015625 +35500 -0.07318115234375 +35501 -0.12347412109375 +35502 -0.016937255859375 +35503 -0.02764892578125 +35504 0.044921875 +35505 0.077667236328125 +35506 0.124481201171875 +35507 0.2132568359375 +35508 0.227386474609375 +35509 0.38885498046875 +35510 0.340972900390625 +35511 0.582794189453125 +35512 0.4295654296875 +35513 0.734039306640625 +35514 0.4683837890625 +35515 0.800140380859375 +35516 0.455780029296875 +35517 0.7783203125 +35518 0.389739990234375 +35519 0.6651611328125 +35520 0.26971435546875 +35521 0.45965576171875 +35522 0.117523193359375 +35523 0.199188232421875 +35524 -0.02850341796875 +35525 -0.050689697265625 +35526 -0.135101318359375 +35527 -0.23297119140625 +35528 -0.1920166015625 +35529 -0.33013916015625 +35530 -0.21453857421875 +35531 -0.368408203125 +35532 -0.220855712890625 +35533 -0.378936767578125 +35534 -0.21990966796875 +35535 -0.376983642578125 +35536 -0.221710205078125 +35537 -0.37969970703125 +35538 -0.22882080078125 +35539 -0.391510009765625 +35540 -0.225433349609375 +35541 -0.385345458984375 +35542 -0.20025634765625 +35543 -0.3419189453125 +35544 -0.165924072265625 +35545 -0.28289794921875 +35546 -0.147735595703125 +35547 -0.251617431640625 +35548 -0.156219482421875 +35549 -0.266143798828125 +35550 -0.160369873046875 +35551 -0.273345947265625 +35552 -0.12725830078125 +35553 -0.216796875 +35554 -0.075408935546875 +35555 -0.128265380859375 +35556 -0.04010009765625 +35557 -0.068145751953125 +35558 -0.02520751953125 +35559 -0.0430908203125 +35560 -0.0140380859375 +35561 -0.024444580078125 +35562 0.012603759765625 +35563 0.020721435546875 +35564 0.07342529296875 +35565 0.124481201171875 +35566 0.1514892578125 +35567 0.25787353515625 +35568 0.222381591796875 +35569 0.379119873046875 +35570 0.281280517578125 +35571 0.47991943359375 +35572 0.3094482421875 +35573 0.5281982421875 +35574 0.299407958984375 +35575 0.511138916015625 +35576 0.2672119140625 +35577 0.456207275390625 +35578 0.238616943359375 +35579 0.407470703125 +35580 0.224609375 +35581 0.383758544921875 +35582 0.208740234375 +35583 0.35687255859375 +35584 0.181732177734375 +35585 0.31182861328125 +35586 0.14459228515625 +35587 0.250885009765625 +35588 0.09295654296875 +35589 0.1654052734375 +35590 0.0162353515625 +35591 0.035247802734375 +35592 -0.08648681640625 +35593 -0.142059326171875 +35594 -0.19775390625 +35595 -0.33563232421875 +35596 -0.311187744140625 +35597 -0.5345458984375 +35598 -0.41717529296875 +35599 -0.72186279296875 +35600 -0.481964111328125 +35601 -0.836669921875 +35602 -0.47991943359375 +35603 -0.8326416015625 +35604 -0.4219970703125 +35605 -0.7296142578125 +35606 -0.338653564453125 +35607 -0.582550048828125 +35608 -0.25689697265625 +35609 -0.440093994140625 +35610 -0.189117431640625 +35611 -0.324310302734375 +35612 -0.116912841796875 +35613 -0.20147705078125 +35614 -0.02569580078125 +35615 -0.044647216796875 +35616 0.060943603515625 +35617 0.103973388671875 +35618 0.11956787109375 +35619 0.202392578125 +35620 0.1575927734375 +35621 0.264495849609375 +35622 0.201690673828125 +35623 0.338897705078125 +35624 0.261749267578125 +35625 0.443817138671875 +35626 0.318817138671875 +35627 0.545074462890625 +35628 0.358856201171875 +35629 0.6173095703125 +35630 0.37744140625 +35631 0.6524658203125 +35632 0.3817138671875 +35633 0.66339111328125 +35634 0.375152587890625 +35635 0.6561279296875 +35636 0.3447265625 +35637 0.606781005859375 +35638 0.282806396484375 +35639 0.501190185546875 +35640 0.196990966796875 +35641 0.352783203125 +35642 0.095794677734375 +35643 0.176544189453125 +35644 -0.024566650390625 +35645 -0.034820556640625 +35646 -0.151123046875 +35647 -0.258209228515625 +35648 -0.2554931640625 +35649 -0.44244384765625 +35650 -0.330810546875 +35651 -0.5753173828125 +35652 -0.37432861328125 +35653 -0.65203857421875 +35654 -0.368927001953125 +35655 -0.641632080078125 +35656 -0.3245849609375 +35657 -0.562164306640625 +35658 -0.265869140625 +35659 -0.458038330078125 +35660 -0.204620361328125 +35661 -0.350555419921875 +35662 -0.152435302734375 +35663 -0.260528564453125 +35664 -0.111785888671875 +35665 -0.192108154296875 +35666 -0.080963134765625 +35667 -0.141937255859375 +35668 -0.055816650390625 +35669 -0.1021728515625 +35670 -0.03106689453125 +35671 -0.062896728515625 +35672 -0.0001220703125 +35673 -0.011932373046875 +35674 0.04351806640625 +35675 0.062835693359375 +35676 0.092742919921875 +35677 0.148712158203125 +35678 0.145263671875 +35679 0.241729736328125 +35680 0.205047607421875 +35681 0.34912109375 +35682 0.26458740234375 +35683 0.457305908203125 +35684 0.3115234375 +35685 0.54388427734375 +35686 0.326080322265625 +35687 0.5728759765625 +35688 0.287567138671875 +35689 0.506591796875 +35690 0.199493408203125 +35691 0.351226806640625 +35692 0.083953857421875 +35693 0.146514892578125 +35694 -0.030029296875 +35695 -0.05523681640625 +35696 -0.121490478515625 +35697 -0.21624755859375 +35698 -0.189361572265625 +35699 -0.334930419921875 +35700 -0.22894287109375 +35701 -0.402984619140625 +35702 -0.251678466796875 +35703 -0.4412841796875 +35704 -0.282867431640625 +35705 -0.49578857421875 +35706 -0.318939208984375 +35707 -0.5601806640625 +35708 -0.34130859375 +35709 -0.600738525390625 +35710 -0.331634521484375 +35711 -0.584228515625 +35712 -0.27264404296875 +35713 -0.47930908203125 +35714 -0.1607666015625 +35715 -0.27935791015625 +35716 -0.0096435546875 +35717 -0.0089111328125 +35718 0.145660400390625 +35719 0.268798828125 +35720 0.265899658203125 +35721 0.482818603515625 +35722 0.334686279296875 +35723 0.60369873046875 +35724 0.36236572265625 +35725 0.650421142578125 +35726 0.37152099609375 +35727 0.66400146484375 +35728 0.360443115234375 +35729 0.6414794921875 +35730 0.3233642578125 +35731 0.572540283203125 +35732 0.2828369140625 +35733 0.498138427734375 +35734 0.25054931640625 +35735 0.439453125 +35736 0.21490478515625 +35737 0.375518798828125 +35738 0.15838623046875 +35739 0.274505615234375 +35740 0.0657958984375 +35741 0.1087646484375 +35742 -0.05047607421875 +35743 -0.099395751953125 +35744 -0.172821044921875 +35745 -0.3182373046875 +35746 -0.301849365234375 +35747 -0.5489501953125 +35748 -0.4276123046875 +35749 -0.7738037109375 +35750 -0.52081298828125 +35751 -0.86383056640625 +35752 -0.563018798828125 +35753 -0.870391845703125 +35754 -0.563934326171875 +35755 -0.86895751953125 +35756 -0.53076171875 +35757 -0.861053466796875 +35758 -0.45391845703125 +35759 -0.765869140625 +35760 -0.3271484375 +35761 -0.5301513671875 +35762 -0.154388427734375 +35763 -0.214691162109375 +35764 0.040557861328125 +35765 0.137359619140625 +35766 0.2293701171875 +35767 0.474822998046875 +35768 0.392333984375 +35769 0.76239013671875 +35770 0.514495849609375 +35771 0.867462158203125 +35772 0.596038818359375 +35773 0.870361328125 +35774 0.6304931640625 +35775 0.86480712890625 +35776 0.6207275390625 +35777 0.831817626953125 +35778 0.58013916015625 +35779 0.677581787109375 +35780 0.511871337890625 +35781 0.495880126953125 +35782 0.426116943359375 +35783 0.30767822265625 +35784 0.32403564453125 +35785 0.116180419921875 +35786 0.1881103515625 +35787 -0.110748291015625 +35788 0.014556884765625 +35789 -0.381805419921875 +35790 -0.1729736328125 +35791 -0.6572265625 +35792 -0.34136962890625 +35793 -0.857421875 +35794 -0.4669189453125 +35795 -0.870391845703125 +35796 -0.545654296875 +35797 -0.870391845703125 +35798 -0.59234619140625 +35799 -0.86444091796875 +35800 -0.626617431640625 +35801 -0.85723876953125 +35802 -0.6383056640625 +35803 -0.790008544921875 +35804 -0.59735107421875 +35805 -0.62847900390625 +35806 -0.501953125 +35807 -0.3956298828125 +35808 -0.370208740234375 +35809 -0.126708984375 +35810 -0.21722412109375 +35811 0.150115966796875 +35812 -0.049468994140625 +35813 0.424041748046875 +35814 0.1181640625 +35815 0.670623779296875 +35816 0.2642822265625 +35817 0.854522705078125 +35818 0.37908935546875 +35819 0.866485595703125 +35820 0.45404052734375 +35821 0.86920166015625 +35822 0.49908447265625 +35823 0.8653564453125 +35824 0.5216064453125 +35825 0.857147216796875 +35826 0.51995849609375 +35827 0.766845703125 +35828 0.496856689453125 +35829 0.628509521484375 +35830 0.44854736328125 +35831 0.462127685546875 +35832 0.389251708984375 +35833 0.297210693359375 +35834 0.32574462890625 +35835 0.14862060546875 +35836 0.24542236328125 +35837 -0.00537109375 +35838 0.152435302734375 +35839 -0.15753173828125 +35840 0.04522705078125 +35841 -0.31304931640625 +35842 -0.083831787109375 +35843 -0.48876953125 +35844 -0.210174560546875 +35845 -0.6416015625 +35846 -0.320098876953125 +35847 -0.751373291015625 +35848 -0.4249267578125 +35849 -0.84619140625 +35850 -0.51641845703125 +35851 -0.861297607421875 +35852 -0.576934814453125 +35853 -0.863250732421875 +35854 -0.58978271484375 +35855 -0.856597900390625 +35856 -0.5611572265625 +35857 -0.7498779296875 +35858 -0.52117919921875 +35859 -0.624542236328125 +35860 -0.458587646484375 +35861 -0.47808837890625 +35862 -0.34332275390625 +35863 -0.253387451171875 +35864 -0.199493408203125 +35865 0.003692626953125 +35866 -0.063079833984375 +35867 0.2257080078125 +35868 0.07196044921875 +35869 0.427154541015625 +35870 0.22198486328125 +35871 0.643218994140625 +35872 0.381500244140625 +35873 0.855926513671875 +35874 0.51995849609375 +35875 0.870361328125 +35876 0.611236572265625 +35877 0.870361328125 +35878 0.6588134765625 +35879 0.862762451171875 +35880 0.66094970703125 +35881 0.79669189453125 +35882 0.612701416015625 +35883 0.595794677734375 +35884 0.529296875 +35885 0.362152099609375 +35886 0.425445556640625 +35887 0.1270751953125 +35888 0.312408447265625 +35889 -0.086944580078125 +35890 0.191619873046875 +35891 -0.2784423828125 +35892 0.04534912109375 +35893 -0.484832763671875 +35894 -0.135955810546875 +35895 -0.729583740234375 +35896 -0.325592041015625 +35897 -0.86688232421875 +35898 -0.490203857421875 +35899 -0.870391845703125 +35900 -0.626800537109375 +35901 -0.86859130859375 +35902 -0.733978271484375 +35903 -0.86279296875 +35904 -0.792724609375 +35905 -0.817962646484375 +35906 -0.779266357421875 +35907 -0.6116943359375 +35908 -0.689849853515625 +35909 -0.3128662109375 +35910 -0.5419921875 +35911 0.039398193359375 +35912 -0.346221923828125 +35913 0.422821044921875 +35914 -0.120025634765625 +35915 0.805145263671875 +35916 0.100830078125 +35917 0.870361328125 +35918 0.286346435546875 +35919 0.870361328125 +35920 0.42999267578125 +35921 0.860015869140625 +35922 0.52734375 +35923 0.727935791015625 +35924 0.57501220703125 +35925 0.48114013671875 +35926 0.58514404296875 +35927 0.2059326171875 +35928 0.569091796875 +35929 -0.06103515625 +35930 0.531768798828125 +35931 -0.29913330078125 +35932 0.46539306640625 +35933 -0.516204833984375 +35934 0.36187744140625 +35935 -0.7252197265625 +35936 0.23419189453125 +35937 -0.85980224609375 +35938 0.100341796875 +35939 -0.870391845703125 +35940 -0.02398681640625 +35941 -0.870391845703125 +35942 -0.11309814453125 +35943 -0.858062744140625 +35944 -0.164306640625 +35945 -0.673004150390625 +35946 -0.204345703125 +35947 -0.42694091796875 +35948 -0.255706787109375 +35949 -0.2100830078125 +35950 -0.31671142578125 +35951 -0.0362548828125 +35952 -0.37176513671875 +35953 0.10943603515625 +35954 -0.4100341796875 +35955 0.23516845703125 +35956 -0.409637451171875 +35957 0.373687744140625 +35958 -0.371307373046875 +35959 0.517791748046875 +35960 -0.327728271484375 +35961 0.602783203125 +35962 -0.27618408203125 +35963 0.635711669921875 +35964 -0.19952392578125 +35965 0.655181884765625 +35966 -0.103179931640625 +35967 0.65948486328125 +35968 0.008270263671875 +35969 0.651275634765625 +35970 0.12158203125 +35971 0.61846923828125 +35972 0.217010498046875 +35973 0.53753662109375 +35974 0.28460693359375 +35975 0.404144287109375 +35976 0.31878662109375 +35977 0.22186279296875 +35978 0.3197021484375 +35979 0.003997802734375 +35980 0.29632568359375 +35981 -0.22100830078125 +35982 0.259002685546875 +35983 -0.42449951171875 +35984 0.21856689453125 +35985 -0.579833984375 +35986 0.1971435546875 +35987 -0.641876220703125 +35988 0.19122314453125 +35989 -0.6177978515625 +35990 0.167327880859375 +35991 -0.575531005859375 +35992 0.122894287109375 +35993 -0.526336669921875 +35994 0.085174560546875 +35995 -0.42645263671875 +35996 0.06884765625 +35997 -0.2581787109375 +35998 0.05548095703125 +35999 -0.068695068359375 +36000 0.0255126953125 +36001 0.09222412109375 +36002 -0.0108642578125 +36003 0.232147216796875 +36004 -0.0478515625 +36005 0.3509521484375 +36006 -0.1004638671875 +36007 0.410064697265625 +36008 -0.18359375 +36009 0.372955322265625 +36010 -0.286041259765625 +36011 0.2554931640625 +36012 -0.380523681640625 +36013 0.10711669921875 +36014 -0.456756591796875 +36015 -0.052886962890625 +36016 -0.49591064453125 +36017 -0.186279296875 +36018 -0.46905517578125 +36019 -0.23291015625 +36020 -0.38824462890625 +36021 -0.209442138671875 +36022 -0.28802490234375 +36023 -0.174163818359375 +36024 -0.173065185546875 +36025 -0.126739501953125 +36026 -0.038665771484375 +36027 -0.048126220703125 +36028 0.10009765625 +36029 0.0426025390625 +36030 0.218536376953125 +36031 0.10748291015625 +36032 0.309356689453125 +36033 0.1409912109375 +36034 0.396942138671875 +36035 0.19708251953125 +36036 0.4774169921875 +36037 0.273651123046875 +36038 0.52154541015625 +36039 0.31768798828125 +36040 0.534912109375 +36041 0.341094970703125 +36042 0.530609130859375 +36043 0.368011474609375 +36044 0.496673583984375 +36045 0.37249755859375 +36046 0.4075927734375 +36047 0.30072021484375 +36048 0.26617431640625 +36049 0.1517333984375 +36050 0.107269287109375 +36051 -0.01470947265625 +36052 -0.059539794921875 +36053 -0.1883544921875 +36054 -0.2318115234375 +36055 -0.372711181640625 +36056 -0.37738037109375 +36057 -0.51397705078125 +36058 -0.471435546875 +36059 -0.57177734375 +36060 -0.50732421875 +36061 -0.53948974609375 +36062 -0.491851806640625 +36063 -0.43511962890625 +36064 -0.442840576171875 +36065 -0.2962646484375 +36066 -0.379364013671875 +36067 -0.161102294921875 +36068 -0.3087158203125 +36069 -0.0435791015625 +36070 -0.229766845703125 +36071 0.060394287109375 +36072 -0.151702880859375 +36073 0.13665771484375 +36074 -0.084808349609375 +36075 0.170135498046875 +36076 -0.0296630859375 +36077 0.16552734375 +36078 0.028228759765625 +36079 0.15728759765625 +36080 0.088165283203125 +36081 0.150787353515625 +36082 0.134185791015625 +36083 0.12200927734375 +36084 0.167755126953125 +36085 0.080108642578125 +36086 0.19964599609375 +36087 0.05126953125 +36088 0.2418212890625 +36089 0.062896728515625 +36090 0.281036376953125 +36091 0.09271240234375 +36092 0.291534423828125 +36093 0.092987060546875 +36094 0.28082275390625 +36095 0.07855224609375 +36096 0.25732421875 +36097 0.06427001953125 +36098 0.21429443359375 +36099 0.0347900390625 +36100 0.15252685546875 +36101 -0.01171875 +36102 0.084136962890625 +36103 -0.056060791015625 +36104 0.0333251953125 +36105 -0.055511474609375 +36106 0.002899169921875 +36107 -0.010467529296875 +36108 -0.0311279296875 +36109 0.02508544921875 +36110 -0.07867431640625 +36111 0.025665283203125 +36112 -0.124176025390625 +36113 0.017333984375 +36114 -0.16473388671875 +36115 0.00189208984375 +36116 -0.204315185546875 +36117 -0.03173828125 +36118 -0.235992431640625 +36119 -0.071502685546875 +36120 -0.2684326171875 +36121 -0.13543701171875 +36122 -0.3001708984375 +36123 -0.219970703125 +36124 -0.31976318359375 +36125 -0.300506591796875 +36126 -0.32830810546875 +36127 -0.376312255859375 +36128 -0.31201171875 +36129 -0.416107177734375 +36130 -0.248687744140625 +36131 -0.371124267578125 +36132 -0.141143798828125 +36133 -0.242279052734375 +36134 -0.011871337890625 +36135 -0.069732666015625 +36136 0.126312255859375 +36137 0.125640869140625 +36138 0.25567626953125 +36139 0.31268310546875 +36140 0.356231689453125 +36141 0.45501708984375 +36142 0.427642822265625 +36143 0.554779052734375 +36144 0.468292236328125 +36145 0.61065673828125 +36146 0.471893310546875 +36147 0.610931396484375 +36148 0.426483154296875 +36149 0.531463623046875 +36150 0.340606689453125 +36151 0.3883056640625 +36152 0.241912841796875 +36153 0.23468017578125 +36154 0.1441650390625 +36155 0.095245361328125 +36156 0.06207275390625 +36157 -0.00396728515625 +36158 0.00469970703125 +36159 -0.04852294921875 +36160 -0.03424072265625 +36161 -0.055145263671875 +36162 -0.07879638671875 +36163 -0.0758056640625 +36164 -0.1412353515625 +36165 -0.138702392578125 +36166 -0.202667236328125 +36167 -0.209197998046875 +36168 -0.262664794921875 +36169 -0.289031982421875 +36170 -0.32061767578125 +36171 -0.37884521484375 +36172 -0.3648681640625 +36173 -0.456329345703125 +36174 -0.392791748046875 +36175 -0.51641845703125 +36176 -0.38482666015625 +36177 -0.519287109375 +36178 -0.33831787109375 +36179 -0.458251953125 +36180 -0.28009033203125 +36181 -0.384796142578125 +36182 -0.223846435546875 +36183 -0.323699951171875 +36184 -0.16827392578125 +36185 -0.269287109375 +36186 -0.101837158203125 +36187 -0.1951904296875 +36188 -0.02545166015625 +36189 -0.100006103515625 +36190 0.0458984375 +36191 -0.01055908203125 +36192 0.12591552734375 +36193 0.1033935546875 +36194 0.21710205078125 +36195 0.24908447265625 +36196 0.291900634765625 +36197 0.373199462890625 +36198 0.340972900390625 +36199 0.45806884765625 +36200 0.368011474609375 +36201 0.511474609375 +36202 0.389190673828125 +36203 0.565399169921875 +36204 0.4007568359375 +36205 0.61138916015625 +36206 0.3736572265625 +36207 0.5897216796875 +36208 0.303985595703125 +36209 0.4906005859375 +36210 0.20172119140625 +36211 0.33148193359375 +36212 0.085845947265625 +36213 0.147796630859375 +36214 -0.021392822265625 +36215 -0.01873779296875 +36216 -0.10479736328125 +36217 -0.140289306640625 +36218 -0.150726318359375 +36219 -0.191986083984375 +36220 -0.16339111328125 +36221 -0.184295654296875 +36222 -0.164276123046875 +36223 -0.161834716796875 +36224 -0.173858642578125 +36225 -0.166595458984375 +36226 -0.189544677734375 +36227 -0.19390869140625 +36228 -0.20172119140625 +36229 -0.22442626953125 +36230 -0.22149658203125 +36231 -0.279754638671875 +36232 -0.238983154296875 +36233 -0.3389892578125 +36234 -0.231109619140625 +36235 -0.3543701171875 +36236 -0.209930419921875 +36237 -0.348175048828125 +36238 -0.179290771484375 +36239 -0.32598876953125 +36240 -0.125518798828125 +36241 -0.2581787109375 +36242 -0.047210693359375 +36243 -0.139801025390625 +36244 0.04736328125 +36245 0.014617919921875 +36246 0.126922607421875 +36247 0.144378662109375 +36248 0.176513671875 +36249 0.221038818359375 +36250 0.20867919921875 +36251 0.27069091796875 +36252 0.223480224609375 +36253 0.294036865234375 +36254 0.231231689453125 +36255 0.311767578125 +36256 0.239715576171875 +36257 0.339141845703125 +36258 0.2412109375 +36259 0.360260009765625 +36260 0.22906494140625 +36261 0.360504150390625 +36262 0.188690185546875 +36263 0.308380126953125 +36264 0.110198974609375 +36265 0.18170166015625 +36266 0.006439208984375 +36267 0.0047607421875 +36268 -0.09869384765625 +36269 -0.17559814453125 +36270 -0.18231201171875 +36271 -0.3143310546875 +36272 -0.2222900390625 +36273 -0.36785888671875 +36274 -0.230743408203125 +36275 -0.36248779296875 +36276 -0.229278564453125 +36277 -0.343536376953125 +36278 -0.213134765625 +36279 -0.3018798828125 +36280 -0.17919921875 +36281 -0.231414794921875 +36282 -0.120452880859375 +36283 -0.117645263671875 +36284 -0.053009033203125 +36285 0.007049560546875 +36286 -0.0040283203125 +36287 0.087982177734375 +36288 0.032867431640625 +36289 0.13946533203125 +36290 0.063201904296875 +36291 0.17425537109375 +36292 0.08416748046875 +36293 0.188201904296875 +36294 0.09002685546875 +36295 0.171234130859375 +36296 0.07763671875 +36297 0.118438720703125 +36298 0.05963134765625 +36299 0.05706787109375 +36300 0.03643798828125 +36301 -0.010711669921875 +36302 0.004364013671875 +36303 -0.0914306640625 +36304 -0.025787353515625 +36305 -0.162322998046875 +36306 -0.04010009765625 +36307 -0.194549560546875 +36308 -0.019622802734375 +36309 -0.1492919921875 +36310 0.038177490234375 +36311 -0.02166748046875 +36312 0.102264404296875 +36313 0.124053955078125 +36314 0.135650634765625 +36315 0.211151123046875 +36316 0.139312744140625 +36317 0.240447998046875 +36318 0.128631591796875 +36319 0.242218017578125 +36320 0.10882568359375 +36321 0.2257080078125 +36322 0.08221435546875 +36323 0.194366455078125 +36324 0.033447265625 +36325 0.115509033203125 +36326 -0.025390625 +36327 0.0128173828125 +36328 -0.06463623046875 +36329 -0.053802490234375 +36330 -0.0968017578125 +36331 -0.110626220703125 +36332 -0.142120361328125 +36333 -0.199493408203125 +36334 -0.187835693359375 +36335 -0.29437255859375 +36336 -0.20330810546875 +36337 -0.33221435546875 +36338 -0.17254638671875 +36339 -0.27972412109375 +36340 -0.1195068359375 +36341 -0.185333251953125 +36342 -0.083251953125 +36343 -0.128204345703125 +36344 -0.067840576171875 +36345 -0.115692138671875 +36346 -0.058502197265625 +36347 -0.116455078125 +36348 -0.0438232421875 +36349 -0.105926513671875 +36350 -0.009613037109375 +36351 -0.053955078125 +36352 0.048004150390625 +36353 0.048797607421875 +36354 0.10699462890625 +36355 0.157318115234375 +36356 0.139068603515625 +36357 0.212005615234375 +36358 0.14642333984375 +36359 0.218475341796875 +36360 0.156463623046875 +36361 0.23724365234375 +36362 0.186126708984375 +36363 0.30535888671875 +36364 0.216644287109375 +36365 0.38128662109375 +36366 0.220703125 +36367 0.404449462890625 +36368 0.20770263671875 +36369 0.3944091796875 +36370 0.195220947265625 +36371 0.3885498046875 +36372 0.172821044921875 +36373 0.362640380859375 +36374 0.121490478515625 +36375 0.27362060546875 +36376 0.03985595703125 +36377 0.11712646484375 +36378 -0.047821044921875 +36379 -0.054901123046875 +36380 -0.117523193359375 +36381 -0.19085693359375 +36382 -0.16656494140625 +36383 -0.28570556640625 +36384 -0.194610595703125 +36385 -0.339263916015625 +36386 -0.21337890625 +36387 -0.3775634765625 +36388 -0.243438720703125 +36389 -0.445709228515625 +36390 -0.281005859375 +36391 -0.535064697265625 +36392 -0.3187255859375 +36393 -0.629058837890625 +36394 -0.34320068359375 +36395 -0.697601318359375 +36396 -0.338104248046875 +36397 -0.70391845703125 +36398 -0.301361083984375 +36399 -0.6424560546875 +36400 -0.223480224609375 +36401 -0.491241455078125 +36402 -0.111968994140625 +36403 -0.265716552734375 +36404 0.00628662109375 +36405 -0.023712158203125 +36406 0.115814208984375 +36407 0.201751708984375 +36408 0.200408935546875 +36409 0.375823974609375 +36410 0.253692626953125 +36411 0.485076904296875 +36412 0.293487548828125 +36413 0.56884765625 +36414 0.323272705078125 +36415 0.634765625 +36416 0.322479248046875 +36417 0.63763427734375 +36418 0.28607177734375 +36419 0.5660400390625 +36420 0.238037109375 +36421 0.4720458984375 +36422 0.202056884765625 +36423 0.40692138671875 +36424 0.181793212890625 +36425 0.3778076171875 +36426 0.174102783203125 +36427 0.376953125 +36428 0.16461181640625 +36429 0.371978759765625 +36430 0.13104248046875 +36431 0.313140869140625 +36432 0.06640625 +36433 0.184417724609375 +36434 -0.017364501953125 +36435 0.011199951171875 +36436 -0.103851318359375 +36437 -0.171051025390625 +36438 -0.181549072265625 +36439 -0.33740234375 +36440 -0.2431640625 +36441 -0.47198486328125 +36442 -0.28216552734375 +36443 -0.560394287109375 +36444 -0.28863525390625 +36445 -0.58056640625 +36446 -0.26959228515625 +36447 -0.54754638671875 +36448 -0.24688720703125 +36449 -0.508575439453125 +36450 -0.2188720703125 +36451 -0.459503173828125 +36452 -0.18316650390625 +36453 -0.394378662109375 +36454 -0.1580810546875 +36455 -0.35260009765625 +36456 -0.133697509765625 +36457 -0.31170654296875 +36458 -0.076446533203125 +36459 -0.197418212890625 +36460 0.014190673828125 +36461 -0.007965087890625 +36462 0.115570068359375 +36463 0.207489013671875 +36464 0.20941162109375 +36465 0.409210205078125 +36466 0.28424072265625 +36467 0.57208251953125 +36468 0.326324462890625 +36469 0.66595458984375 +36470 0.321075439453125 +36471 0.65875244140625 +36472 0.276397705078125 +36473 0.56744384765625 +36474 0.210418701171875 +36475 0.431396484375 +36476 0.143402099609375 +36477 0.29443359375 +36478 0.08740234375 +36479 0.182464599609375 +36480 0.028228759765625 +36481 0.06365966796875 +36482 -0.040252685546875 +36483 -0.075958251953125 +36484 -0.096343994140625 +36485 -0.189422607421875 +36486 -0.13763427734375 +36487 -0.271942138671875 +36488 -0.172607421875 +36489 -0.342529296875 +36490 -0.18426513671875 +36491 -0.364166259765625 +36492 -0.16815185546875 +36493 -0.327239990234375 +36494 -0.1448974609375 +36495 -0.2769775390625 +36496 -0.1329345703125 +36497 -0.253692626953125 +36498 -0.1260986328125 +36499 -0.24365234375 +36500 -0.102447509765625 +36501 -0.1983642578125 +36502 -0.061431884765625 +36503 -0.116241455078125 +36504 -0.021270751953125 +36505 -0.036834716796875 +36506 0.0155029296875 +36507 0.034881591796875 +36508 0.045166015625 +36509 0.09124755859375 +36510 0.056884765625 +36511 0.10888671875 +36512 0.067657470703125 +36513 0.125518798828125 +36514 0.084869384765625 +36515 0.15771484375 +36516 0.095977783203125 +36517 0.17828369140625 +36518 0.09356689453125 +36519 0.17108154296875 +36520 0.0748291015625 +36521 0.129974365234375 +36522 0.05230712890625 +36523 0.082427978515625 +36524 0.025726318359375 +36525 0.027679443359375 +36526 -0.019073486328125 +36527 -0.065643310546875 +36528 -0.064544677734375 +36529 -0.15936279296875 +36530 -0.09210205078125 +36531 -0.21307373046875 +36532 -0.105194091796875 +36533 -0.234649658203125 +36534 -0.092742919921875 +36535 -0.2001953125 +36536 -0.058868408203125 +36537 -0.119171142578125 +36538 -0.0185546875 +36539 -0.024749755859375 +36540 0.029571533203125 +36541 0.085784912109375 +36542 0.069976806640625 +36543 0.178131103515625 +36544 0.08599853515625 +36545 0.215576171875 +36546 0.083770751953125 +36547 0.211456298828125 +36548 0.067596435546875 +36549 0.17523193359375 +36550 0.047393798828125 +36551 0.128753662109375 +36552 0.0367431640625 +36553 0.1019287109375 +36554 0.0262451171875 +36555 0.0743408203125 +36556 0.0145263671875 +36557 0.04327392578125 +36558 0.014862060546875 +36559 0.038177490234375 +36560 0.034942626953125 +36561 0.076263427734375 +36562 0.067108154296875 +36563 0.14105224609375 +36564 0.090179443359375 +36565 0.186431884765625 +36566 0.093292236328125 +36567 0.188812255859375 +36568 0.0721435546875 +36569 0.1390380859375 +36570 0.028839111328125 +36571 0.041778564453125 +36572 -0.025909423828125 +36573 -0.079437255859375 +36574 -0.08978271484375 +36575 -0.219390869140625 +36576 -0.158050537109375 +36577 -0.367828369140625 +36578 -0.217041015625 +36579 -0.494873046875 +36580 -0.246490478515625 +36581 -0.556243896484375 +36582 -0.226593017578125 +36583 -0.508697509765625 +36584 -0.16790771484375 +36585 -0.3756103515625 +36586 -0.09857177734375 +36587 -0.218902587890625 +36588 -0.029937744140625 +36589 -0.063751220703125 +36590 0.038848876953125 +36591 0.091552734375 +36592 0.102874755859375 +36593 0.23602294921875 +36594 0.150115966796875 +36595 0.342987060546875 +36596 0.17279052734375 +36597 0.39520263671875 +36598 0.16943359375 +36599 0.389373779296875 +36600 0.1395263671875 +36601 0.324249267578125 +36602 0.0941162109375 +36603 0.224090576171875 +36604 0.04931640625 +36605 0.124267578125 +36606 0.010650634765625 +36607 0.037078857421875 +36608 -0.0098876953125 +36609 -0.010101318359375 +36610 -0.013153076171875 +36611 -0.019439697265625 +36612 -0.01312255859375 +36613 -0.022796630859375 +36614 -0.002197265625 +36615 -0.001556396484375 +36616 0.024444580078125 +36617 0.056304931640625 +36618 0.047821044921875 +36619 0.106719970703125 +36620 0.04541015625 +36621 0.096893310546875 +36622 0.0238037109375 +36623 0.042694091796875 +36624 -0.00103759765625 +36625 -0.018035888671875 +36626 -0.025146484375 +36627 -0.07586669921875 +36628 -0.043701171875 +36629 -0.11944580078125 +36630 -0.06134033203125 +36631 -0.15972900390625 +36632 -0.080474853515625 +36633 -0.202606201171875 +36634 -0.1011962890625 +36635 -0.24859619140625 +36636 -0.126617431640625 +36637 -0.30517578125 +36638 -0.152313232421875 +36639 -0.36212158203125 +36640 -0.16632080078125 +36641 -0.39141845703125 +36642 -0.15252685546875 +36643 -0.35528564453125 +36644 -0.1092529296875 +36645 -0.249969482421875 +36646 -0.043792724609375 +36647 -0.092864990234375 +36648 0.032470703125 +36649 0.08905029296875 +36650 0.093902587890625 +36651 0.2352294921875 +36652 0.129150390625 +36653 0.318817138671875 +36654 0.14617919921875 +36655 0.358642578125 +36656 0.14202880859375 +36657 0.347747802734375 +36658 0.116424560546875 +36659 0.28564453125 +36660 0.090911865234375 +36661 0.223175048828125 +36662 0.080841064453125 +36663 0.196746826171875 +36664 0.074920654296875 +36665 0.179840087890625 +36666 0.06591796875 +36667 0.155548095703125 +36668 0.065338134765625 +36669 0.151214599609375 +36670 0.068939208984375 +36671 0.156951904296875 +36672 0.05926513671875 +36673 0.13177490234375 +36674 0.046905517578125 +36675 0.100799560546875 +36676 0.0416259765625 +36677 0.087127685546875 +36678 0.0281982421875 +36679 0.05487060546875 +36680 0.001068115234375 +36681 -0.009002685546875 +36682 -0.03948974609375 +36683 -0.10400390625 +36684 -0.093170166015625 +36685 -0.229400634765625 +36686 -0.1473388671875 +36687 -0.35552978515625 +36688 -0.184783935546875 +36689 -0.441925048828125 +36690 -0.199249267578125 +36691 -0.473846435546875 +36692 -0.1964111328125 +36693 -0.464813232421875 +36694 -0.178009033203125 +36695 -0.419097900390625 +36696 -0.142974853515625 +36697 -0.334320068359375 +36698 -0.098663330078125 +36699 -0.227935791015625 +36700 -0.055023193359375 +36701 -0.12347412109375 +36702 -0.014862060546875 +36703 -0.02764892578125 +36704 0.029541015625 +36705 0.077667236328125 +36706 0.08697509765625 +36707 0.2132568359375 +36708 0.16156005859375 +36709 0.38885498046875 +36710 0.24407958984375 +36711 0.582794189453125 +36712 0.30865478515625 +36713 0.734039306640625 +36714 0.337249755859375 +36715 0.800140380859375 +36716 0.328643798828125 +36717 0.7783203125 +36718 0.2813720703125 +36719 0.6651611328125 +36720 0.194976806640625 +36721 0.45965576171875 +36722 0.08526611328125 +36723 0.199188232421875 +36724 -0.019989013671875 +36725 -0.050689697265625 +36726 -0.096649169921875 +36727 -0.23297119140625 +36728 -0.1373291015625 +36729 -0.33013916015625 +36730 -0.1531982421875 +36731 -0.368408203125 +36732 -0.157440185546875 +36733 -0.378936767578125 +36734 -0.15655517578125 +36735 -0.376983642578125 +36736 -0.1578369140625 +36737 -0.37969970703125 +36738 -0.16314697265625 +36739 -0.391510009765625 +36740 -0.160980224609375 +36741 -0.385345458984375 +36742 -0.143096923828125 +36743 -0.3419189453125 +36744 -0.118682861328125 +36745 -0.28289794921875 +36746 -0.1060791015625 +36747 -0.251617431640625 +36748 -0.112884521484375 +36749 -0.266143798828125 +36750 -0.116546630859375 +36751 -0.273345947265625 +36752 -0.093109130859375 +36753 -0.216796875 +36754 -0.055999755859375 +36755 -0.128265380859375 +36756 -0.03082275390625 +36757 -0.068145751953125 +36758 -0.0203857421875 +36759 -0.0430908203125 +36760 -0.01251220703125 +36761 -0.024444580078125 +36762 0.006744384765625 +36763 0.020721435546875 +36764 0.050933837890625 +36765 0.124481201171875 +36766 0.1077880859375 +36767 0.25787353515625 +36768 0.159576416015625 +36769 0.379119873046875 +36770 0.2027587890625 +36771 0.47991943359375 +36772 0.22369384765625 +36773 0.5281982421875 +36774 0.2169189453125 +36775 0.511138916015625 +36776 0.194061279296875 +36777 0.456207275390625 +36778 0.17376708984375 +36779 0.407470703125 +36780 0.16400146484375 +36781 0.383758544921875 +36782 0.152801513671875 +36783 0.35687255859375 +36784 0.1337890625 +36785 0.31182861328125 +36786 0.107940673828125 +36787 0.250885009765625 +36788 0.071624755859375 +36789 0.1654052734375 +36790 0.016265869140625 +36791 0.035247802734375 +36792 -0.059112548828125 +36793 -0.142059326171875 +36794 -0.141448974609375 +36795 -0.33563232421875 +36796 -0.226043701171875 +36797 -0.5345458984375 +36798 -0.30572509765625 +36799 -0.72186279296875 +36800 -0.3546142578125 +36801 -0.836669921875 +36802 -0.353118896484375 +36803 -0.8326416015625 +36804 -0.309600830078125 +36805 -0.7296142578125 +36806 -0.247406005859375 +36807 -0.582550048828125 +36808 -0.1871337890625 +36809 -0.440093994140625 +36810 -0.13812255859375 +36811 -0.324310302734375 +36812 -0.0860595703125 +36813 -0.20147705078125 +36814 -0.01953125 +36815 -0.044647216796875 +36816 0.0435791015625 +36817 0.103973388671875 +36818 0.085418701171875 +36819 0.202392578125 +36820 0.11187744140625 +36821 0.264495849609375 +36822 0.1435546875 +36823 0.338897705078125 +36824 0.18817138671875 +36825 0.443817138671875 +36826 0.231231689453125 +36827 0.545074462890625 +36828 0.261962890625 +36829 0.6173095703125 +36830 0.2769775390625 +36831 0.6524658203125 +36832 0.28167724609375 +36833 0.66339111328125 +36834 0.27862548828125 +36835 0.6561279296875 +36836 0.2576904296875 +36837 0.606781005859375 +36838 0.212860107421875 +36839 0.501190185546875 +36840 0.14984130859375 +36841 0.352783203125 +36842 0.07501220703125 +36843 0.176544189453125 +36844 -0.014678955078125 +36845 -0.034820556640625 +36846 -0.10943603515625 +36847 -0.258209228515625 +36848 -0.18756103515625 +36849 -0.44244384765625 +36850 -0.243865966796875 +36851 -0.5753173828125 +36852 -0.2763671875 +36853 -0.65203857421875 +36854 -0.271942138671875 +36855 -0.641632080078125 +36856 -0.23822021484375 +36857 -0.562164306640625 +36858 -0.194061279296875 +36859 -0.458038330078125 +36860 -0.148468017578125 +36861 -0.350555419921875 +36862 -0.110260009765625 +36863 -0.260528564453125 +36864 -0.081024169921875 +36865 -0.192108154296875 +36866 -0.059295654296875 +36867 -0.141937255859375 +36868 -0.042022705078125 +36869 -0.1021728515625 +36870 -0.025115966796875 +36871 -0.062896728515625 +36872 -0.00372314453125 +36873 -0.011932373046875 +36874 0.026947021484375 +36875 0.062835693359375 +36876 0.06195068359375 +36877 0.148712158203125 +36878 0.099700927734375 +36879 0.241729736328125 +36880 0.1429443359375 +36881 0.34912109375 +36882 0.186309814453125 +36883 0.457305908203125 +36884 0.220947265625 +36885 0.54388427734375 +36886 0.23272705078125 +36887 0.5728759765625 +36888 0.206787109375 +36889 0.506591796875 +36890 0.14556884765625 +36891 0.351226806640625 +36892 0.06463623046875 +36893 0.146514892578125 +36894 -0.01544189453125 +36895 -0.05523681640625 +36896 -0.079833984375 +36897 -0.21624755859375 +36898 -0.1278076171875 +36899 -0.334930419921875 +36900 -0.156036376953125 +36901 -0.402984619140625 +36902 -0.172637939453125 +36903 -0.4412841796875 +36904 -0.195556640625 +36905 -0.49578857421875 +36906 -0.22222900390625 +36907 -0.5601806640625 +36908 -0.2393798828125 +36909 -0.600738525390625 +36910 -0.233917236328125 +36911 -0.584228515625 +36912 -0.1934814453125 +36913 -0.47930908203125 +36914 -0.115478515625 +36915 -0.27935791015625 +36916 -0.009490966796875 +36917 -0.0089111328125 +36918 0.09967041015625 +36919 0.268798828125 +36920 0.18414306640625 +36921 0.482818603515625 +36922 0.23236083984375 +36923 0.60369873046875 +36924 0.251708984375 +36925 0.650421142578125 +36926 0.258209228515625 +36927 0.66400146484375 +36928 0.250640869140625 +36929 0.6414794921875 +36930 0.224884033203125 +36931 0.572540283203125 +36932 0.196929931640625 +36933 0.498138427734375 +36934 0.175018310546875 +36935 0.439453125 +36936 0.15087890625 +36937 0.375518798828125 +36938 0.11199951171875 +36939 0.274505615234375 +36940 0.0474853515625 +36941 0.1087646484375 +36942 -0.033935546875 +36943 -0.099395751953125 +36944 -0.11981201171875 +36945 -0.3182373046875 +36946 -0.210601806640625 +36947 -0.5489501953125 +36948 -0.299285888671875 +36949 -0.7738037109375 +36950 -0.365081787109375 +36951 -0.86383056640625 +36952 -0.394927978515625 +36953 -0.870391845703125 +36954 -0.395721435546875 +36955 -0.86895751953125 +36956 -0.37255859375 +36957 -0.861053466796875 +36958 -0.318603515625 +36959 -0.765869140625 +36960 -0.229400634765625 +36961 -0.5301513671875 +36962 -0.107666015625 +36963 -0.214691162109375 +36964 0.029754638671875 +36965 0.137359619140625 +36966 0.162750244140625 +36967 0.474822998046875 +36968 0.277435302734375 +36969 0.76239013671875 +36970 0.36322021484375 +36971 0.867462158203125 +36972 0.420318603515625 +36973 0.870361328125 +36974 0.44415283203125 +36975 0.86480712890625 +36976 0.436798095703125 +36977 0.831817626953125 +36978 0.40777587890625 +36979 0.677581787109375 +36980 0.35931396484375 +36981 0.495880126953125 +36982 0.29864501953125 +36983 0.30767822265625 +36984 0.22662353515625 +36985 0.116180419921875 +36986 0.130767822265625 +36987 -0.110748291015625 +36988 0.008331298828125 +36989 -0.381805419921875 +36990 -0.123931884765625 +36991 -0.6572265625 +36992 -0.242584228515625 +36993 -0.857421875 +36994 -0.330810546875 +36995 -0.870391845703125 +36996 -0.385833740234375 +36997 -0.870391845703125 +36998 -0.418182373046875 +36999 -0.86444091796875 +37000 -0.441864013671875 +37001 -0.85723876953125 +37002 -0.449676513671875 +37003 -0.790008544921875 +37004 -0.420318603515625 +37005 -0.62847900390625 +37006 -0.352508544921875 +37007 -0.3956298828125 +37008 -0.25909423828125 +37009 -0.126708984375 +37010 -0.150787353515625 +37011 0.150115966796875 +37012 -0.03216552734375 +37013 0.424041748046875 +37014 0.086212158203125 +37015 0.670623779296875 +37016 0.189178466796875 +37017 0.854522705078125 +37018 0.26983642578125 +37019 0.866485595703125 +37020 0.32220458984375 +37021 0.86920166015625 +37022 0.3533935546875 +37023 0.8653564453125 +37024 0.36865234375 +37025 0.857147216796875 +37026 0.366851806640625 +37027 0.766845703125 +37028 0.3499755859375 +37029 0.628509521484375 +37030 0.31536865234375 +37031 0.462127685546875 +37032 0.27313232421875 +37033 0.297210693359375 +37034 0.228118896484375 +37035 0.14862060546875 +37036 0.171356201171875 +37037 -0.00537109375 +37038 0.105712890625 +37039 -0.15753173828125 +37040 0.02978515625 +37041 -0.31304931640625 +37042 -0.061920166015625 +37043 -0.48876953125 +37044 -0.151031494140625 +37045 -0.6416015625 +37046 -0.227874755859375 +37047 -0.751373291015625 +37048 -0.301513671875 +37049 -0.84619140625 +37050 -0.366180419921875 +37051 -0.861297607421875 +37052 -0.408843994140625 +37053 -0.863250732421875 +37054 -0.4171142578125 +37055 -0.856597900390625 +37056 -0.395751953125 +37057 -0.7498779296875 +37058 -0.367431640625 +37059 -0.624542236328125 +37060 -0.32354736328125 +37061 -0.47808837890625 +37062 -0.24114990234375 +37063 -0.253387451171875 +37064 -0.13812255859375 +37065 0.003692626953125 +37066 -0.041259765625 +37067 0.2257080078125 +37068 0.0543212890625 +37069 0.427154541015625 +37070 0.16131591796875 +37071 0.643218994140625 +37072 0.27593994140625 +37073 0.855926513671875 +37074 0.375457763671875 +37075 0.870361328125 +37076 0.440399169921875 +37077 0.870361328125 +37078 0.473602294921875 +37079 0.862762451171875 +37080 0.473907470703125 +37081 0.79669189453125 +37082 0.437591552734375 +37083 0.595794677734375 +37084 0.376129150390625 +37085 0.362152099609375 +37086 0.300506591796875 +37087 0.1270751953125 +37088 0.218994140625 +37089 -0.086944580078125 +37090 0.132415771484375 +37091 -0.2784423828125 +37092 0.02716064453125 +37093 -0.484832763671875 +37094 -0.104248046875 +37095 -0.729583740234375 +37096 -0.241943359375 +37097 -0.86688232421875 +37098 -0.361114501953125 +37099 -0.870391845703125 +37100 -0.459747314453125 +37101 -0.86859130859375 +37102 -0.537017822265625 +37103 -0.86279296875 +37104 -0.578765869140625 +37105 -0.817962646484375 +37106 -0.567169189453125 +37107 -0.6116943359375 +37108 -0.49945068359375 +37109 -0.3128662109375 +37110 -0.3887939453125 +37111 0.039398193359375 +37112 -0.243072509765625 +37113 0.422821044921875 +37114 -0.075347900390625 +37115 0.805145263671875 +37116 0.087615966796875 +37117 0.870361328125 +37118 0.223419189453125 +37119 0.870361328125 +37120 0.327178955078125 +37121 0.860015869140625 +37122 0.396270751953125 +37123 0.727935791015625 +37124 0.428741455078125 +37125 0.48114013671875 +37126 0.43328857421875 +37127 0.2059326171875 +37128 0.41815185546875 +37129 -0.06103515625 +37130 0.387054443359375 +37131 -0.29913330078125 +37132 0.335052490234375 +37133 -0.516204833984375 +37134 0.256927490234375 +37135 -0.7252197265625 +37136 0.16204833984375 +37137 -0.85980224609375 +37138 0.063232421875 +37139 -0.870391845703125 +37140 -0.0283203125 +37141 -0.870391845703125 +37142 -0.094573974609375 +37143 -0.858062744140625 +37144 -0.13348388671875 +37145 -0.673004150390625 +37146 -0.163421630859375 +37147 -0.42694091796875 +37148 -0.19989013671875 +37149 -0.2100830078125 +37150 -0.241729736328125 +37151 -0.0362548828125 +37152 -0.278167724609375 +37153 0.10943603515625 +37154 -0.3018798828125 +37155 0.23516845703125 +37156 -0.297882080078125 +37157 0.373687744140625 +37158 -0.2669677734375 +37159 0.517791748046875 +37160 -0.23199462890625 +37161 0.602783203125 +37162 -0.191375732421875 +37163 0.635711669921875 +37164 -0.133514404296875 +37165 0.655181884765625 +37166 -0.062408447265625 +37167 0.65948486328125 +37168 0.018524169921875 +37169 0.651275634765625 +37170 0.099945068359375 +37171 0.61846923828125 +37172 0.16802978515625 +37173 0.53753662109375 +37174 0.2158203125 +37175 0.404144287109375 +37176 0.239410400390625 +37177 0.22186279296875 +37178 0.23895263671875 +37179 0.003997802734375 +37180 0.220733642578125 +37181 -0.22100830078125 +37182 0.19207763671875 +37183 -0.42449951171875 +37184 0.160675048828125 +37185 -0.579833984375 +37186 0.141998291015625 +37187 -0.641876220703125 +37188 0.133880615234375 +37189 -0.6177978515625 +37190 0.113372802734375 +37191 -0.575531005859375 +37192 0.078887939453125 +37193 -0.526336669921875 +37194 0.049530029296875 +37195 -0.42645263671875 +37196 0.03558349609375 +37197 -0.2581787109375 +37198 0.0244140625 +37199 -0.068695068359375 +37200 0.0025634765625 +37201 0.09222412109375 +37202 -0.022857666015625 +37203 0.232147216796875 +37204 -0.047882080078125 +37205 0.3509521484375 +37206 -0.082916259765625 +37207 0.410064697265625 +37208 -0.138397216796875 +37209 0.372955322265625 +37210 -0.206695556640625 +37211 0.2554931640625 +37212 -0.269073486328125 +37213 0.10711669921875 +37214 -0.31854248046875 +37215 -0.052886962890625 +37216 -0.34228515625 +37217 -0.186279296875 +37218 -0.320465087890625 +37219 -0.23291015625 +37220 -0.2615966796875 +37221 -0.209442138671875 +37222 -0.18975830078125 +37223 -0.174163818359375 +37224 -0.108306884765625 +37225 -0.126739501953125 +37226 -0.014068603515625 +37227 -0.048126220703125 +37228 0.082427978515625 +37229 0.0426025390625 +37230 0.16412353515625 +37231 0.10748291015625 +37232 0.22601318359375 +37233 0.1409912109375 +37234 0.285003662109375 +37235 0.19708251953125 +37236 0.33856201171875 +37237 0.273651123046875 +37238 0.3665771484375 +37239 0.31768798828125 +37240 0.373077392578125 +37241 0.341094970703125 +37242 0.367279052734375 +37243 0.368011474609375 +37244 0.341064453125 +37245 0.37249755859375 +37246 0.276885986328125 +37247 0.30072021484375 +37248 0.17681884765625 +37249 0.1517333984375 +37250 0.06512451171875 +37251 -0.01470947265625 +37252 -0.051483154296875 +37253 -0.1883544921875 +37254 -0.171234130859375 +37255 -0.372711181640625 +37256 -0.27191162109375 +37257 -0.51397705078125 +37258 -0.336334228515625 +37259 -0.57177734375 +37260 -0.35992431640625 +37261 -0.53948974609375 +37262 -0.347503662109375 +37263 -0.43511962890625 +37264 -0.311553955078125 +37265 -0.2962646484375 +37266 -0.265350341796875 +37267 -0.161102294921875 +37268 -0.214080810546875 +37269 -0.0435791015625 +37270 -0.1571044921875 +37271 0.060394287109375 +37272 -0.10089111328125 +37273 0.13665771484375 +37274 -0.052703857421875 +37275 0.170135498046875 +37276 -0.013031005859375 +37277 0.16552734375 +37278 0.028106689453125 +37279 0.15728759765625 +37280 0.070159912109375 +37281 0.150787353515625 +37282 0.10205078125 +37283 0.12200927734375 +37284 0.124847412109375 +37285 0.080108642578125 +37286 0.146026611328125 +37287 0.05126953125 +37288 0.173919677734375 +37289 0.062896728515625 +37290 0.199432373046875 +37291 0.09271240234375 +37292 0.204864501953125 +37293 0.092987060546875 +37294 0.19549560546875 +37295 0.07855224609375 +37296 0.17718505859375 +37297 0.06427001953125 +37298 0.1453857421875 +37299 0.0347900390625 +37300 0.100799560546875 +37301 -0.01171875 +37302 0.05206298828125 +37303 -0.056060791015625 +37304 0.0164794921875 +37305 -0.055511474609375 +37306 -0.003997802734375 +37307 -0.010467529296875 +37308 -0.02679443359375 +37309 0.02508544921875 +37310 -0.059173583984375 +37311 0.025665283203125 +37312 -0.090057373046875 +37313 0.017333984375 +37314 -0.117431640625 +37315 0.00189208984375 +37316 -0.144256591796875 +37317 -0.03173828125 +37318 -0.165618896484375 +37319 -0.071502685546875 +37320 -0.187835693359375 +37321 -0.13543701171875 +37322 -0.20989990234375 +37323 -0.219970703125 +37324 -0.223602294921875 +37325 -0.300506591796875 +37326 -0.229736328125 +37327 -0.376312255859375 +37328 -0.21832275390625 +37329 -0.416107177734375 +37330 -0.173370361328125 +37331 -0.371124267578125 +37332 -0.09686279296875 +37333 -0.242279052734375 +37334 -0.00494384765625 +37335 -0.069732666015625 +37336 0.09320068359375 +37337 0.125640869140625 +37338 0.1849365234375 +37339 0.31268310546875 +37340 0.25592041015625 +37341 0.45501708984375 +37342 0.30596923828125 +37343 0.554779052734375 +37344 0.334014892578125 +37345 0.61065673828125 +37346 0.335601806640625 +37347 0.610931396484375 +37348 0.302154541015625 +37349 0.531463623046875 +37350 0.2398681640625 +37351 0.3883056640625 +37352 0.168670654296875 +37353 0.23468017578125 +37354 0.098480224609375 +37355 0.095245361328125 +37356 0.039825439453125 +37357 -0.00396728515625 +37358 -0.000732421875 +37359 -0.04852294921875 +37360 -0.027801513671875 +37361 -0.055145263671875 +37362 -0.05877685546875 +37363 -0.0758056640625 +37364 -0.1025390625 +37365 -0.138702392578125 +37366 -0.145538330078125 +37367 -0.209197998046875 +37368 -0.18756103515625 +37369 -0.289031982421875 +37370 -0.228240966796875 +37371 -0.37884521484375 +37372 -0.259185791015625 +37373 -0.456329345703125 +37374 -0.278594970703125 +37375 -0.51641845703125 +37376 -0.272552490234375 +37377 -0.519287109375 +37378 -0.23919677734375 +37379 -0.458251953125 +37380 -0.19744873046875 +37381 -0.384796142578125 +37382 -0.156951904296875 +37383 -0.323699951171875 +37384 -0.116851806640625 +37385 -0.269287109375 +37386 -0.06915283203125 +37387 -0.1951904296875 +37388 -0.014617919921875 +37389 -0.100006103515625 +37390 0.03619384765625 +37391 -0.01055908203125 +37392 0.092864990234375 +37393 0.1033935546875 +37394 0.15704345703125 +37395 0.24908447265625 +37396 0.20947265625 +37397 0.373199462890625 +37398 0.243621826171875 +37399 0.45806884765625 +37400 0.2620849609375 +37401 0.511474609375 +37402 0.276214599609375 +37403 0.565399169921875 +37404 0.283416748046875 +37405 0.61138916015625 +37406 0.263397216796875 +37407 0.5897216796875 +37408 0.213531494140625 +37409 0.4906005859375 +37410 0.140838623046875 +37411 0.33148193359375 +37412 0.058685302734375 +37413 0.147796630859375 +37414 -0.017333984375 +37415 -0.01873779296875 +37416 -0.07647705078125 +37417 -0.140289306640625 +37418 -0.10919189453125 +37419 -0.191986083984375 +37420 -0.118408203125 +37421 -0.184295654296875 +37422 -0.119140625 +37423 -0.161834716796875 +37424 -0.125732421875 +37425 -0.166595458984375 +37426 -0.136383056640625 +37427 -0.19390869140625 +37428 -0.144378662109375 +37429 -0.22442626953125 +37430 -0.15753173828125 +37431 -0.279754638671875 +37432 -0.1689453125 +37433 -0.3389892578125 +37434 -0.162506103515625 +37435 -0.3543701171875 +37436 -0.146728515625 +37437 -0.348175048828125 +37438 -0.124359130859375 +37439 -0.32598876953125 +37440 -0.085845947265625 +37441 -0.2581787109375 +37442 -0.030303955078125 +37443 -0.139801025390625 +37444 0.03643798828125 +37445 0.014617919921875 +37446 0.09246826171875 +37447 0.144378662109375 +37448 0.1273193359375 +37449 0.221038818359375 +37450 0.149749755859375 +37451 0.27069091796875 +37452 0.159820556640625 +37453 0.294036865234375 +37454 0.164764404296875 +37455 0.311767578125 +37456 0.170013427734375 +37457 0.339141845703125 +37458 0.1700439453125 +37459 0.360260009765625 +37460 0.16033935546875 +37461 0.360504150390625 +37462 0.131256103515625 +37463 0.308380126953125 +37464 0.076263427734375 +37465 0.18170166015625 +37466 0.00421142578125 +37467 0.0047607421875 +37468 -0.068695068359375 +37469 -0.17559814453125 +37470 -0.126922607421875 +37471 -0.3143310546875 +37472 -0.155487060546875 +37473 -0.36785888671875 +37474 -0.1624755859375 +37475 -0.36248779296875 +37476 -0.162322998046875 +37477 -0.343536376953125 +37478 -0.15179443359375 +37479 -0.3018798828125 +37480 -0.1287841796875 +37481 -0.231414794921875 +37482 -0.088653564453125 +37483 -0.117645263671875 +37484 -0.042266845703125 +37485 0.007049560546875 +37486 -0.0079345703125 +37487 0.087982177734375 +37488 0.018524169921875 +37489 0.13946533203125 +37490 0.04071044921875 +37491 0.17425537109375 +37492 0.056671142578125 +37493 0.188201904296875 +37494 0.06243896484375 +37495 0.171234130859375 +37496 0.0557861328125 +37497 0.118438720703125 +37498 0.045135498046875 +37499 0.05706787109375 +37500 0.030670166015625 +37501 -0.010711669921875 +37502 0.0098876953125 +37503 -0.0914306640625 +37504 -0.010009765625 +37505 -0.162322998046875 +37506 -0.019683837890625 +37507 -0.194549560546875 +37508 -0.00634765625 +37509 -0.1492919921875 +37510 0.031707763671875 +37511 -0.02166748046875 +37512 0.07366943359375 +37513 0.124053955078125 +37514 0.094757080078125 +37515 0.211151123046875 +37516 0.095703125 +37517 0.240447998046875 +37518 0.0869140625 +37519 0.242218017578125 +37520 0.072021484375 +37521 0.2257080078125 +37522 0.052642822265625 +37523 0.194366455078125 +37524 0.0185546875 +37525 0.115509033203125 +37526 -0.02203369140625 +37527 0.0128173828125 +37528 -0.04913330078125 +37529 -0.053802490234375 +37530 -0.07110595703125 +37531 -0.110626220703125 +37532 -0.101593017578125 +37533 -0.199493408203125 +37534 -0.13201904296875 +37535 -0.29437255859375 +37536 -0.14178466796875 +37537 -0.33221435546875 +37538 -0.120208740234375 +37539 -0.27972412109375 +37540 -0.08343505859375 +37541 -0.185333251953125 +37542 -0.05780029296875 +37543 -0.128204345703125 +37544 -0.046112060546875 +37545 -0.115692138671875 +37546 -0.038543701171875 +37547 -0.116455078125 +37548 -0.0274658203125 +37549 -0.105926513671875 +37550 -0.003387451171875 +37551 -0.053955078125 +37552 0.036346435546875 +37553 0.048797607421875 +37554 0.076690673828125 +37555 0.157318115234375 +37556 0.097869873046875 +37557 0.212005615234375 +37558 0.101593017578125 +37559 0.218475341796875 +37560 0.107696533203125 +37561 0.23724365234375 +37562 0.12835693359375 +37563 0.30535888671875 +37564 0.15008544921875 +37565 0.38128662109375 +37566 0.1531982421875 +37567 0.404449462890625 +37568 0.144439697265625 +37569 0.3944091796875 +37570 0.1363525390625 +37571 0.3885498046875 +37572 0.12139892578125 +37573 0.362640380859375 +37574 0.0858154296875 +37575 0.27362060546875 +37576 0.02850341796875 +37577 0.11712646484375 +37578 -0.033172607421875 +37579 -0.054901123046875 +37580 -0.082000732421875 +37581 -0.19085693359375 +37582 -0.11614990234375 +37583 -0.28570556640625 +37584 -0.13543701171875 +37585 -0.339263916015625 +37586 -0.148345947265625 +37587 -0.3775634765625 +37588 -0.169677734375 +37589 -0.445709228515625 +37590 -0.196685791015625 +37591 -0.535064697265625 +37592 -0.224090576171875 +37593 -0.629058837890625 +37594 -0.24224853515625 +37595 -0.697601318359375 +37596 -0.239349365234375 +37597 -0.70391845703125 +37598 -0.2138671875 +37599 -0.6424560546875 +37600 -0.158905029296875 +37601 -0.491241455078125 +37602 -0.079803466796875 +37603 -0.265716552734375 +37604 0.004119873046875 +37605 -0.023712158203125 +37606 0.081817626953125 +37607 0.201751708984375 +37608 0.141693115234375 +37609 0.375823974609375 +37610 0.179229736328125 +37611 0.485076904296875 +37612 0.207244873046875 +37613 0.56884765625 +37614 0.228271484375 +37615 0.634765625 +37616 0.227569580078125 +37617 0.63763427734375 +37618 0.201507568359375 +37619 0.5660400390625 +37620 0.16729736328125 +37621 0.4720458984375 +37622 0.1419677734375 +37623 0.40692138671875 +37624 0.12811279296875 +37625 0.3778076171875 +37626 0.1234130859375 +37627 0.376953125 +37628 0.11749267578125 +37629 0.371978759765625 +37630 0.09423828125 +37631 0.313140869140625 +37632 0.048828125 +37633 0.184417724609375 +37634 -0.009918212890625 +37635 0.011199951171875 +37636 -0.07049560546875 +37637 -0.171051025390625 +37638 -0.1251220703125 +37639 -0.33740234375 +37640 -0.168792724609375 +37641 -0.47198486328125 +37642 -0.19708251953125 +37643 -0.560394287109375 +37644 -0.203369140625 +37645 -0.58056640625 +37646 -0.192138671875 +37647 -0.54754638671875 +37648 -0.177490234375 +37649 -0.508575439453125 +37650 -0.158416748046875 +37651 -0.459503173828125 +37652 -0.133453369140625 +37653 -0.394378662109375 +37654 -0.114593505859375 +37655 -0.35260009765625 +37656 -0.0955810546875 +37657 -0.31170654296875 +37658 -0.0548095703125 +37659 -0.197418212890625 +37660 0.007843017578125 +37661 -0.007965087890625 +37662 0.077423095703125 +37663 0.207489013671875 +37664 0.141876220703125 +37665 0.409210205078125 +37666 0.193572998046875 +37667 0.57208251953125 +37668 0.223419189453125 +37669 0.66595458984375 +37670 0.22186279296875 +37671 0.65875244140625 +37672 0.193939208984375 +37673 0.56744384765625 +37674 0.1513671875 +37675 0.431396484375 +37676 0.1072998046875 +37677 0.29443359375 +37678 0.069610595703125 +37679 0.182464599609375 +37680 0.0291748046875 +37681 0.06365966796875 +37682 -0.017791748046875 +37683 -0.075958251953125 +37684 -0.057098388671875 +37685 -0.189422607421875 +37686 -0.087005615234375 +37687 -0.271942138671875 +37688 -0.112823486328125 +37689 -0.342529296875 +37690 -0.123382568359375 +37691 -0.364166259765625 +37692 -0.115631103515625 +37693 -0.327239990234375 +37694 -0.102813720703125 +37695 -0.2769775390625 +37696 -0.096771240234375 +37697 -0.253692626953125 +37698 -0.09344482421875 +37699 -0.24365234375 +37700 -0.0784912109375 +37701 -0.1983642578125 +37702 -0.051605224609375 +37703 -0.116241455078125 +37704 -0.02459716796875 +37705 -0.036834716796875 +37706 0.00079345703125 +37707 0.034881591796875 +37708 0.02203369140625 +37709 0.09124755859375 +37710 0.031982421875 +37711 0.10888671875 +37712 0.04150390625 +37713 0.125518798828125 +37714 0.055267333984375 +37715 0.15771484375 +37716 0.06500244140625 +37717 0.17828369140625 +37718 0.06573486328125 +37719 0.17108154296875 +37720 0.0555419921875 +37721 0.129974365234375 +37722 0.042449951171875 +37723 0.082427978515625 +37724 0.026214599609375 +37725 0.027679443359375 +37726 -0.00238037109375 +37727 -0.065643310546875 +37728 -0.031951904296875 +37729 -0.15936279296875 +37730 -0.0504150390625 +37731 -0.21307373046875 +37732 -0.059967041015625 +37733 -0.234649658203125 +37734 -0.0533447265625 +37735 -0.2001953125 +37736 -0.03314208984375 +37737 -0.119171142578125 +37738 -0.00897216796875 +37739 -0.024749755859375 +37740 0.0201416015625 +37741 0.085784912109375 +37742 0.04425048828125 +37743 0.178131103515625 +37744 0.052642822265625 +37745 0.215576171875 +37746 0.049407958984375 +37747 0.211456298828125 +37748 0.0374755859375 +37749 0.17523193359375 +37750 0.023345947265625 +37751 0.128753662109375 +37752 0.015869140625 +37753 0.1019287109375 +37754 0.00897216796875 +37755 0.0743408203125 +37756 0.001739501953125 +37757 0.04327392578125 +37758 0.002716064453125 +37759 0.038177490234375 +37760 0.016876220703125 +37761 0.076263427734375 +37762 0.039154052734375 +37763 0.14105224609375 +37764 0.05572509765625 +37765 0.186431884765625 +37766 0.0594482421875 +37767 0.188812255859375 +37768 0.047454833984375 +37769 0.1390380859375 +37770 0.02099609375 +37771 0.041778564453125 +37772 -0.0130615234375 +37773 -0.079437255859375 +37774 -0.053253173828125 +37775 -0.219390869140625 +37776 -0.0965576171875 +37777 -0.367828369140625 +37778 -0.134185791015625 +37779 -0.494873046875 +37780 -0.15301513671875 +37781 -0.556243896484375 +37782 -0.14019775390625 +37783 -0.508697509765625 +37784 -0.102569580078125 +37785 -0.3756103515625 +37786 -0.058349609375 +37787 -0.218902587890625 +37788 -0.014862060546875 +37789 -0.063751220703125 +37790 0.028472900390625 +37791 0.091552734375 +37792 0.068603515625 +37793 0.23602294921875 +37794 0.097747802734375 +37795 0.342987060546875 +37796 0.1109619140625 +37797 0.39520263671875 +37798 0.107391357421875 +37799 0.389373779296875 +37800 0.08673095703125 +37801 0.324249267578125 +37802 0.0562744140625 +37803 0.224090576171875 +37804 0.0264892578125 +37805 0.124267578125 +37806 0.001007080078125 +37807 0.037078857421875 +37808 -0.0120849609375 +37809 -0.010101318359375 +37810 -0.01348876953125 +37811 -0.019439697265625 +37812 -0.012725830078125 +37813 -0.022796630859375 +37814 -0.004364013671875 +37815 -0.001556396484375 +37816 0.014984130859375 +37817 0.056304931640625 +37818 0.032135009765625 +37819 0.106719970703125 +37820 0.031341552734375 +37821 0.096893310546875 +37822 0.017242431640625 +37823 0.042694091796875 +37824 0.000885009765625 +37825 -0.018035888671875 +37826 -0.01495361328125 +37827 -0.07586669921875 +37828 -0.027008056640625 +37829 -0.11944580078125 +37830 -0.038543701171875 +37831 -0.15972900390625 +37832 -0.05133056640625 +37833 -0.202606201171875 +37834 -0.065460205078125 +37835 -0.24859619140625 +37836 -0.083099365234375 +37837 -0.30517578125 +37838 -0.1011962890625 +37839 -0.36212158203125 +37840 -0.11138916015625 +37841 -0.39141845703125 +37842 -0.102386474609375 +37843 -0.35528564453125 +37844 -0.072998046875 +37845 -0.249969482421875 +37846 -0.028289794921875 +37847 -0.092864990234375 +37848 0.02386474609375 +37849 0.08905029296875 +37850 0.06561279296875 +37851 0.2352294921875 +37852 0.089080810546875 +37853 0.318817138671875 +37854 0.099945068359375 +37855 0.358642578125 +37856 0.096160888671875 +37857 0.347747802734375 +37858 0.077606201171875 +37859 0.28564453125 +37860 0.059326171875 +37861 0.223175048828125 +37862 0.05206298828125 +37863 0.196746826171875 +37864 0.047943115234375 +37865 0.179840087890625 +37866 0.041900634765625 +37867 0.155548095703125 +37868 0.041961669921875 +37869 0.151214599609375 +37870 0.045135498046875 +37871 0.156951904296875 +37872 0.0391845703125 +37873 0.13177490234375 +37874 0.031463623046875 +37875 0.100799560546875 +37876 0.028717041015625 +37877 0.087127685546875 +37878 0.020263671875 +37879 0.05487060546875 +37880 0.002197265625 +37881 -0.009002685546875 +37882 -0.025360107421875 +37883 -0.10400390625 +37884 -0.06219482421875 +37885 -0.229400634765625 +37886 -0.099517822265625 +37887 -0.35552978515625 +37888 -0.12518310546875 +37889 -0.441925048828125 +37890 -0.13446044921875 +37891 -0.473846435546875 +37892 -0.1312255859375 +37893 -0.464813232421875 +37894 -0.117156982421875 +37895 -0.419097900390625 +37896 -0.092132568359375 +37897 -0.334320068359375 +37898 -0.061126708984375 +37899 -0.227935791015625 +37900 -0.030731201171875 +37901 -0.12347412109375 +37902 -0.0029296875 +37903 -0.02764892578125 +37904 0.02685546875 +37905 0.077667236328125 +37906 0.06396484375 +37907 0.2132568359375 +37908 0.110931396484375 +37909 0.38885498046875 +37910 0.16204833984375 +37911 0.582794189453125 +37912 0.201263427734375 +37913 0.734039306640625 +37914 0.21746826171875 +37915 0.800140380859375 +37916 0.210052490234375 +37917 0.7783203125 +37918 0.17822265625 +37919 0.6651611328125 +37920 0.12188720703125 +37921 0.45965576171875 +37922 0.051055908203125 +37923 0.199188232421875 +37924 -0.016815185546875 +37925 -0.050689697265625 +37926 -0.066558837890625 +37927 -0.23297119140625 +37928 -0.093475341796875 +37929 -0.33013916015625 +37930 -0.10443115234375 +37931 -0.368408203125 +37932 -0.10760498046875 +37933 -0.378936767578125 +37934 -0.1070556640625 +37935 -0.376983642578125 +37936 -0.1072998046875 +37937 -0.37969970703125 +37938 -0.10955810546875 +37939 -0.391510009765625 +37940 -0.106719970703125 +37941 -0.385345458984375 +37942 -0.093780517578125 +37943 -0.3419189453125 +37944 -0.0765380859375 +37945 -0.28289794921875 +37946 -0.0665283203125 +37947 -0.251617431640625 +37948 -0.068634033203125 +37949 -0.266143798828125 +37950 -0.068939208984375 +37951 -0.273345947265625 +37952 -0.0526123046875 +37953 -0.216796875 +37954 -0.028106689453125 +37955 -0.128265380859375 +37956 -0.01141357421875 +37957 -0.068145751953125 +37958 -0.00433349609375 +37959 -0.0430908203125 +37960 0.000640869140625 +37961 -0.024444580078125 +37962 0.012237548828125 +37963 0.020721435546875 +37964 0.0389404296875 +37965 0.124481201171875 +37966 0.073150634765625 +37967 0.25787353515625 +37968 0.103912353515625 +37969 0.379119873046875 +37970 0.129119873046875 +37971 0.47991943359375 +37972 0.140380859375 +37973 0.5281982421875 +37974 0.134368896484375 +37975 0.511138916015625 +37976 0.118438720703125 +37977 0.456207275390625 +37978 0.10430908203125 +37979 0.407470703125 +37980 0.097015380859375 +37981 0.383758544921875 +37982 0.089111328125 +37983 0.35687255859375 +37984 0.076690673828125 +37985 0.31182861328125 +37986 0.060394287109375 +37987 0.250885009765625 +37988 0.037933349609375 +37989 0.1654052734375 +37990 0.003997802734375 +37991 0.035247802734375 +37992 -0.042083740234375 +37993 -0.142059326171875 +37994 -0.092193603515625 +37995 -0.33563232421875 +37996 -0.143524169921875 +37997 -0.5345458984375 +37998 -0.191680908203125 +37999 -0.72186279296875 +38000 -0.220611572265625 +38001 -0.836669921875 +38002 -0.218170166015625 +38003 -0.8326416015625 +38004 -0.189697265625 +38005 -0.7296142578125 +38006 -0.149810791015625 +38007 -0.582550048828125 +38008 -0.11138916015625 +38009 -0.440093994140625 +38010 -0.080291748046875 +38011 -0.324310302734375 +38012 -0.047607421875 +38013 -0.20147705078125 +38014 -0.006195068359375 +38015 -0.044647216796875 +38016 0.03277587890625 +38017 0.103973388671875 +38018 0.0582275390625 +38019 0.202392578125 +38020 0.0738525390625 +38021 0.264495849609375 +38022 0.092498779296875 +38023 0.338897705078125 +38024 0.11907958984375 +38025 0.443817138671875 +38026 0.14459228515625 +38027 0.545074462890625 +38028 0.162445068359375 +38029 0.6173095703125 +38030 0.170562744140625 +38031 0.6524658203125 +38032 0.17242431640625 +38033 0.66339111328125 +38034 0.169677734375 +38035 0.6561279296875 +38036 0.156005859375 +38037 0.606781005859375 +38038 0.127685546875 +38039 0.501190185546875 +38040 0.08831787109375 +38041 0.352783203125 +38042 0.0418701171875 +38043 0.176544189453125 +38044 -0.0135498046875 +38045 -0.034820556640625 +38046 -0.071868896484375 +38047 -0.258209228515625 +38048 -0.11962890625 +38049 -0.44244384765625 +38050 -0.1536865234375 +38051 -0.5753173828125 +38052 -0.1728515625 +38053 -0.65203857421875 +38054 -0.16900634765625 +38055 -0.641632080078125 +38056 -0.14697265625 +38057 -0.562164306640625 +38058 -0.118499755859375 +38059 -0.458038330078125 +38060 -0.08929443359375 +38061 -0.350555419921875 +38062 -0.06488037109375 +38063 -0.260528564453125 +38064 -0.04638671875 +38065 -0.192108154296875 +38066 -0.032928466796875 +38067 -0.141937255859375 +38068 -0.0224609375 +38069 -0.1021728515625 +38070 -0.012359619140625 +38071 -0.062896728515625 +38072 0.0006103515625 +38073 -0.011932373046875 +38074 0.019683837890625 +38075 0.062835693359375 +38076 0.04156494140625 +38077 0.148712158203125 +38078 0.06524658203125 +38079 0.241729736328125 +38080 0.092681884765625 +38081 0.34912109375 +38082 0.120330810546875 +38083 0.457305908203125 +38084 0.142303466796875 +38085 0.54388427734375 +38086 0.149169921875 +38087 0.5728759765625 +38088 0.131011962890625 +38089 0.506591796875 +38090 0.089508056640625 +38091 0.351226806640625 +38092 0.035186767578125 +38093 0.146514892578125 +38094 -0.01812744140625 +38095 -0.05523681640625 +38096 -0.060455322265625 +38097 -0.21624755859375 +38098 -0.0914306640625 +38099 -0.334930419921875 +38100 -0.108856201171875 +38101 -0.402984619140625 +38102 -0.1182861328125 +38103 -0.4412841796875 +38104 -0.13189697265625 +38105 -0.49578857421875 +38106 -0.148040771484375 +38107 -0.5601806640625 +38108 -0.157867431640625 +38109 -0.600738525390625 +38110 -0.152679443359375 +38111 -0.584228515625 +38112 -0.124237060546875 +38113 -0.47930908203125 +38114 -0.070831298828125 +38115 -0.27935791015625 +38116 0.0009765625 +38117 -0.0089111328125 +38118 0.074493408203125 +38119 0.268798828125 +38120 0.1309814453125 +38121 0.482818603515625 +38122 0.162689208984375 +38123 0.60369873046875 +38124 0.17462158203125 +38125 0.650421142578125 +38126 0.17767333984375 +38127 0.66400146484375 +38128 0.17108154296875 +38129 0.6414794921875 +38130 0.15216064453125 +38131 0.572540283203125 +38132 0.13177490234375 +38133 0.498138427734375 +38134 0.115570068359375 +38135 0.439453125 +38136 0.098052978515625 +38137 0.375518798828125 +38138 0.070831298828125 +38139 0.274505615234375 +38140 0.026611328125 +38141 0.1087646484375 +38142 -0.0286865234375 +38143 -0.099395751953125 +38144 -0.08612060546875 +38145 -0.3182373046875 +38146 -0.14520263671875 +38147 -0.5489501953125 +38148 -0.201446533203125 +38149 -0.7738037109375 +38150 -0.242431640625 +38151 -0.86383056640625 +38152 -0.2603759765625 +38153 -0.870391845703125 +38154 -0.25946044921875 +38155 -0.86895751953125 +38156 -0.24285888671875 +38157 -0.861053466796875 +38158 -0.206756591796875 +38159 -0.765869140625 +38160 -0.1488037109375 +38161 -0.5301513671875 +38162 -0.070953369140625 +38163 -0.214691162109375 +38164 0.01641845703125 +38165 0.137359619140625 +38166 0.101104736328125 +38167 0.474822998046875 +38168 0.174530029296875 +38169 0.76239013671875 +38170 0.230133056640625 +38171 0.867462158203125 +38172 0.26776123046875 +38173 0.870361328125 +38174 0.284515380859375 +38175 0.86480712890625 +38176 0.28155517578125 +38177 0.831817626953125 +38178 0.26446533203125 +38179 0.677581787109375 +38180 0.234619140625 +38181 0.495880126953125 +38182 0.196380615234375 +38183 0.30767822265625 +38184 0.150390625 +38185 0.116180419921875 +38186 0.0894775390625 +38187 -0.110748291015625 +38188 0.01226806640625 +38189 -0.381805419921875 +38190 -0.071014404296875 +38191 -0.6572265625 +38192 -0.14617919921875 +38193 -0.857421875 +38194 -0.203033447265625 +38195 -0.870391845703125 +38196 -0.23968505859375 +38197 -0.870391845703125 +38198 -0.26214599609375 +38199 -0.86444091796875 +38200 -0.278564453125 +38201 -0.85723876953125 +38202 -0.284576416015625 +38203 -0.790008544921875 +38204 -0.267547607421875 +38205 -0.62847900390625 +38206 -0.226715087890625 +38207 -0.3956298828125 +38208 -0.169769287109375 +38209 -0.126708984375 +38210 -0.1031494140625 +38211 0.150115966796875 +38212 -0.02972412109375 +38213 0.424041748046875 +38214 0.0440673828125 +38215 0.670623779296875 +38216 0.1090087890625 +38217 0.854522705078125 +38218 0.160797119140625 +38219 0.866485595703125 +38220 0.195648193359375 +38221 0.86920166015625 +38222 0.21759033203125 +38223 0.8653564453125 +38224 0.22955322265625 +38225 0.857147216796875 +38226 0.230712890625 +38227 0.766845703125 +38228 0.222137451171875 +38229 0.628509521484375 +38230 0.20220947265625 +38231 0.462127685546875 +38232 0.176910400390625 +38233 0.297210693359375 +38234 0.14910888671875 +38235 0.14862060546875 +38236 0.11358642578125 +38237 -0.00537109375 +38238 0.07220458984375 +38239 -0.15753173828125 +38240 0.024322509765625 +38241 -0.31304931640625 +38242 -0.03314208984375 +38243 -0.48876953125 +38244 -0.08917236328125 +38245 -0.6416015625 +38246 -0.137847900390625 +38247 -0.751373291015625 +38248 -0.184356689453125 +38249 -0.84619140625 +38250 -0.22515869140625 +38251 -0.861297607421875 +38252 -0.252410888671875 +38253 -0.863250732421875 +38254 -0.2586669921875 +38255 -0.856597900390625 +38256 -0.2467041015625 +38257 -0.7498779296875 +38258 -0.22991943359375 +38259 -0.624542236328125 +38260 -0.203216552734375 +38261 -0.47808837890625 +38262 -0.153106689453125 +38263 -0.253387451171875 +38264 -0.090240478515625 +38265 0.003692626953125 +38266 -0.030609130859375 +38267 0.2257080078125 +38268 0.028533935546875 +38269 0.427154541015625 +38270 0.09454345703125 +38271 0.643218994140625 +38272 0.1650390625 +38273 0.855926513671875 +38274 0.226409912109375 +38275 0.870361328125 +38276 0.26702880859375 +38277 0.870361328125 +38278 0.288421630859375 +38279 0.862762451171875 +38280 0.28985595703125 +38281 0.79669189453125 +38282 0.269073486328125 +38283 0.595794677734375 +38284 0.232818603515625 +38285 0.362152099609375 +38286 0.1876220703125 +38287 0.1270751953125 +38288 0.138427734375 +38289 -0.086944580078125 +38290 0.085784912109375 +38291 -0.2784423828125 +38292 0.021728515625 +38293 -0.484832763671875 +38294 -0.05804443359375 +38295 -0.729583740234375 +38296 -0.14166259765625 +38297 -0.86688232421875 +38298 -0.214324951171875 +38299 -0.870391845703125 +38300 -0.27471923828125 +38301 -0.86859130859375 +38302 -0.322235107421875 +38303 -0.86279296875 +38304 -0.34844970703125 +38305 -0.817962646484375 +38306 -0.34271240234375 +38307 -0.6116943359375 +38308 -0.3033447265625 +38309 -0.3128662109375 +38310 -0.23809814453125 +38311 0.039398193359375 +38312 -0.151641845703125 +38313 0.422821044921875 +38314 -0.0517578125 +38315 0.805145263671875 +38316 0.045684814453125 +38317 0.870361328125 +38318 0.127349853515625 +38319 0.870361328125 +38320 0.190399169921875 +38321 0.860015869140625 +38322 0.232879638671875 +38323 0.727935791015625 +38324 0.25335693359375 +38325 0.48114013671875 +38326 0.257293701171875 +38327 0.2059326171875 +38328 0.249755859375 +38329 -0.06103515625 +38330 0.23297119140625 +38331 -0.29913330078125 +38332 0.203460693359375 +38333 -0.516204833984375 +38334 0.157623291015625 +38335 -0.7252197265625 +38336 0.101226806640625 +38337 -0.85980224609375 +38338 0.042236328125 +38339 -0.870391845703125 +38340 -0.01239013671875 +38341 -0.870391845703125 +38342 -0.051177978515625 +38343 -0.858062744140625 +38344 -0.072998046875 +38345 -0.673004150390625 +38346 -0.089874267578125 +38347 -0.42694091796875 +38348 -0.111907958984375 +38349 -0.2100830078125 +38350 -0.138397216796875 +38351 -0.0362548828125 +38352 -0.162384033203125 +38353 0.10943603515625 +38354 -0.179046630859375 +38355 0.23516845703125 +38356 -0.17864990234375 +38357 0.373687744140625 +38358 -0.16156005859375 +38359 0.517791748046875 +38360 -0.142333984375 +38361 0.602783203125 +38362 -0.1197509765625 +38363 0.635711669921875 +38364 -0.08612060546875 +38365 0.655181884765625 +38366 -0.0438232421875 +38367 0.65948486328125 +38368 0.00506591796875 +38369 0.651275634765625 +38370 0.05474853515625 +38371 0.61846923828125 +38372 0.096435546875 +38373 0.53753662109375 +38374 0.125732421875 +38375 0.404144287109375 +38376 0.140228271484375 +38377 0.22186279296875 +38378 0.1400146484375 +38379 0.003997802734375 +38380 0.129119873046875 +38381 -0.22100830078125 +38382 0.112213134765625 +38383 -0.42449951171875 +38384 0.0941162109375 +38385 -0.579833984375 +38386 0.084686279296875 +38387 -0.641876220703125 +38388 0.082366943359375 +38389 -0.6177978515625 +38390 0.072174072265625 +38391 -0.575531005859375 +38392 0.052947998046875 +38393 -0.526336669921875 +38394 0.036773681640625 +38395 -0.42645263671875 +38396 0.0301513671875 +38397 -0.2581787109375 +38398 0.02484130859375 +38399 -0.068695068359375 +38400 0.0115966796875 +38401 0.09222412109375 +38402 -0.005615234375 +38403 0.232147216796875 +38404 -0.023712158203125 +38405 0.3509521484375 +38406 -0.047882080078125 +38407 0.410064697265625 +38408 -0.083404541015625 +38409 0.372955322265625 +38410 -0.125640869140625 +38411 0.2554931640625 +38412 -0.163818359375 +38413 0.10711669921875 +38414 -0.193817138671875 +38415 -0.052886962890625 +38416 -0.208343505859375 +38417 -0.186279296875 +38418 -0.19635009765625 +38419 -0.23291015625 +38420 -0.16259765625 +38421 -0.209442138671875 +38422 -0.120574951171875 +38423 -0.174163818359375 +38424 -0.07232666015625 +38425 -0.126739501953125 +38426 -0.016265869140625 +38427 -0.048126220703125 +38428 0.041473388671875 +38429 0.0426025390625 +38430 0.091156005859375 +38431 0.10748291015625 +38432 0.129730224609375 +38433 0.1409912109375 +38434 0.166351318359375 +38435 0.19708251953125 +38436 0.19940185546875 +38437 0.273651123046875 +38438 0.217559814453125 +38439 0.31768798828125 +38440 0.222930908203125 +38441 0.341094970703125 +38442 0.220550537109375 +38443 0.368011474609375 +38444 0.205902099609375 +38445 0.37249755859375 +38446 0.1693115234375 +38447 0.30072021484375 +38448 0.111968994140625 +38449 0.1517333984375 +38450 0.0474853515625 +38451 -0.01470947265625 +38452 -0.020263671875 +38453 -0.1883544921875 +38454 -0.090118408203125 +38455 -0.372711181640625 +38456 -0.149566650390625 +38457 -0.51397705078125 +38458 -0.188873291015625 +38459 -0.57177734375 +38460 -0.20526123046875 +38461 -0.53948974609375 +38462 -0.20123291015625 +38463 -0.43511962890625 +38464 -0.183563232421875 +38465 -0.2962646484375 +38466 -0.1595458984375 +38467 -0.161102294921875 +38468 -0.131988525390625 +38469 -0.0435791015625 +38470 -0.10052490234375 +38471 0.060394287109375 +38472 -0.0687255859375 +38473 0.13665771484375 +38474 -0.040679931640625 +38475 0.170135498046875 +38476 -0.01678466796875 +38477 0.16552734375 +38478 0.00836181640625 +38479 0.15728759765625 +38480 0.034332275390625 +38481 0.150787353515625 +38482 0.054840087890625 +38483 0.12200927734375 +38484 0.0703125 +38485 0.080108642578125 +38486 0.084747314453125 +38487 0.05126953125 +38488 0.102630615234375 +38489 0.062896728515625 +38490 0.118804931640625 +38491 0.09271240234375 +38492 0.123321533203125 +38493 0.092987060546875 +38494 0.119049072265625 +38495 0.07855224609375 +38496 0.109222412109375 +38497 0.06427001953125 +38498 0.09130859375 +38499 0.0347900390625 +38500 0.06573486328125 +38501 -0.01171875 +38502 0.037353515625 +38503 -0.056060791015625 +38504 0.015869140625 +38505 -0.055511474609375 +38506 0.00244140625 +38507 -0.010467529296875 +38508 -0.012451171875 +38509 0.02508544921875 +38510 -0.032745361328125 +38511 0.025665283203125 +38512 -0.052154541015625 +38513 0.017333984375 +38514 -0.06939697265625 +38515 0.00189208984375 +38516 -0.086029052734375 +38517 -0.03173828125 +38518 -0.0992431640625 +38519 -0.071502685546875 +38520 -0.11248779296875 +38521 -0.13543701171875 +38522 -0.125152587890625 +38523 -0.219970703125 +38524 -0.1326904296875 +38525 -0.300506591796875 +38526 -0.135528564453125 +38527 -0.376312255859375 +38528 -0.128204345703125 +38529 -0.416107177734375 +38530 -0.10186767578125 +38531 -0.371124267578125 +38532 -0.0577392578125 +38533 -0.242279052734375 +38534 -0.0048828125 +38535 -0.069732666015625 +38536 0.051483154296875 +38537 0.125640869140625 +38538 0.104248046875 +38539 0.31268310546875 +38540 0.14532470703125 +38541 0.45501708984375 +38542 0.174530029296875 +38543 0.554779052734375 +38544 0.19122314453125 +38545 0.61065673828125 +38546 0.19287109375 +38547 0.610931396484375 +38548 0.1746826171875 +38549 0.531463623046875 +38550 0.140106201171875 +38551 0.3883056640625 +38552 0.1002197265625 +38553 0.23468017578125 +38554 0.060546875 +38555 0.095245361328125 +38556 0.027008056640625 +38557 -0.00396728515625 +38558 0.003265380859375 +38559 -0.04852294921875 +38560 -0.013153076171875 +38561 -0.055145263671875 +38562 -0.031829833984375 +38563 -0.0758056640625 +38564 -0.0576171875 +38565 -0.138702392578125 +38566 -0.0828857421875 +38567 -0.209197998046875 +38568 -0.107452392578125 +38569 -0.289031982421875 +38570 -0.13104248046875 +38571 -0.37884521484375 +38572 -0.148956298828125 +38573 -0.456329345703125 +38574 -0.16015625 +38575 -0.51641845703125 +38576 -0.156829833984375 +38577 -0.519287109375 +38578 -0.137939453125 +38579 -0.458251953125 +38580 -0.11419677734375 +38581 -0.384796142578125 +38582 -0.09112548828125 +38583 -0.323699951171875 +38584 -0.0682373046875 +38585 -0.269287109375 +38586 -0.040924072265625 +38587 -0.1951904296875 +38588 -0.009613037109375 +38589 -0.100006103515625 +38590 0.019622802734375 +38591 -0.01055908203125 +38592 0.052215576171875 +38593 0.1033935546875 +38594 0.089141845703125 +38595 0.24908447265625 +38596 0.119384765625 +38597 0.373199462890625 +38598 0.13916015625 +38599 0.45806884765625 +38600 0.14996337890625 +38601 0.511474609375 +38602 0.15826416015625 +38603 0.565399169921875 +38604 0.162567138671875 +38605 0.61138916015625 +38606 0.151275634765625 +38607 0.5897216796875 +38608 0.12286376953125 +38609 0.4906005859375 +38610 0.08135986328125 +38611 0.33148193359375 +38612 0.034423828125 +38613 0.147796630859375 +38614 -0.009033203125 +38615 -0.01873779296875 +38616 -0.042877197265625 +38617 -0.140289306640625 +38618 -0.0616455078125 +38619 -0.191986083984375 +38620 -0.0670166015625 +38621 -0.184295654296875 +38622 -0.06756591796875 +38623 -0.161834716796875 +38624 -0.07147216796875 +38625 -0.166595458984375 +38626 -0.07769775390625 +38627 -0.19390869140625 +38628 -0.0823974609375 +38629 -0.22442626953125 +38630 -0.09002685546875 +38631 -0.279754638671875 +38632 -0.096649169921875 +38633 -0.3389892578125 +38634 -0.09307861328125 +38635 -0.3543701171875 +38636 -0.084136962890625 +38637 -0.348175048828125 +38638 -0.0714111328125 +38639 -0.32598876953125 +38640 -0.049468994140625 +38641 -0.2581787109375 +38642 -0.01776123046875 +38643 -0.139801025390625 +38644 0.0203857421875 +38645 0.014617919921875 +38646 0.052398681640625 +38647 0.144378662109375 +38648 0.07232666015625 +38649 0.221038818359375 +38650 0.085174560546875 +38651 0.27069091796875 +38652 0.09100341796875 +38653 0.294036865234375 +38654 0.09393310546875 +38655 0.311767578125 +38656 0.09698486328125 +38657 0.339141845703125 +38658 0.096771240234375 +38659 0.360260009765625 +38660 0.09075927734375 +38661 0.360504150390625 +38662 0.074188232421875 +38663 0.308380126953125 +38664 0.043914794921875 +38665 0.18170166015625 +38666 0.004608154296875 +38667 0.0047607421875 +38668 -0.035186767578125 +38669 -0.17559814453125 +38670 -0.0673828125 +38671 -0.3143310546875 +38672 -0.084136962890625 +38673 -0.36785888671875 +38674 -0.0894775390625 +38675 -0.36248779296875 +38676 -0.090728759765625 +38677 -0.343536376953125 +38678 -0.086181640625 +38679 -0.3018798828125 +38680 -0.074737548828125 +38681 -0.231414794921875 +38682 -0.053985595703125 +38683 -0.117645263671875 +38684 -0.029541015625 +38685 0.007049560546875 +38686 -0.010833740234375 +38687 0.087982177734375 +38688 0.004180908203125 +38689 0.13946533203125 +38690 0.01727294921875 +38691 0.17425537109375 +38692 0.027313232421875 +38693 0.188201904296875 +38694 0.03216552734375 +38695 0.171234130859375 +38696 0.03057861328125 +38697 0.118438720703125 +38698 0.02679443359375 +38699 0.05706787109375 +38700 0.02081298828125 +38701 -0.010711669921875 +38702 0.011260986328125 +38703 -0.0914306640625 +38704 0.001800537109375 +38705 -0.162322998046875 +38706 -0.0028076171875 +38707 -0.194549560546875 +38708 0.003936767578125 +38709 -0.1492919921875 +38710 0.02294921875 +38711 -0.02166748046875 +38712 0.04364013671875 +38713 0.124053955078125 +38714 0.053314208984375 +38715 0.211151123046875 +38716 0.05242919921875 +38717 0.240447998046875 +38718 0.046417236328125 +38719 0.242218017578125 +38720 0.0372314453125 +38721 0.2257080078125 +38722 0.025787353515625 +38723 0.194366455078125 +38724 0.006927490234375 +38725 0.115509033203125 +38726 -0.015045166015625 +38727 0.0128173828125 +38728 -0.02984619140625 +38729 -0.053802490234375 +38730 -0.041748046875 +38731 -0.110626220703125 +38732 -0.05767822265625 +38733 -0.199493408203125 +38734 -0.0732421875 +38735 -0.29437255859375 +38736 -0.077911376953125 +38737 -0.33221435546875 +38738 -0.066253662109375 +38739 -0.27972412109375 +38740 -0.04656982421875 +38741 -0.185333251953125 +38742 -0.032379150390625 +38743 -0.128204345703125 +38744 -0.02520751953125 +38745 -0.115692138671875 +38746 -0.02008056640625 +38747 -0.116455078125 +38748 -0.013153076171875 +38749 -0.105926513671875 +38750 0.00030517578125 +38751 -0.053955078125 +38752 0.021636962890625 +38753 0.048797607421875 +38754 0.0430908203125 +38755 0.157318115234375 +38756 0.05450439453125 +38757 0.212005615234375 +38758 0.05670166015625 +38759 0.218475341796875 +38760 0.059844970703125 +38761 0.23724365234375 +38762 0.0701904296875 +38763 0.30535888671875 +38764 0.08087158203125 +38765 0.38128662109375 +38766 0.081787109375 +38767 0.404449462890625 +38768 0.076446533203125 +38769 0.3944091796875 +38770 0.07135009765625 +38771 0.3885498046875 +38772 0.062652587890625 +38773 0.362640380859375 +38774 0.043365478515625 +38775 0.27362060546875 +38776 0.01300048828125 +38777 0.11712646484375 +38778 -0.01947021484375 +38779 -0.054901123046875 +38780 -0.045166015625 +38781 -0.19085693359375 +38782 -0.0631103515625 +38783 -0.28570556640625 +38784 -0.073211669921875 +38785 -0.339263916015625 +38786 -0.079803466796875 +38787 -0.3775634765625 +38788 -0.090484619140625 +38789 -0.445709228515625 +38790 -0.1038818359375 +38791 -0.535064697265625 +38792 -0.1173095703125 +38793 -0.629058837890625 +38794 -0.1258544921875 +38795 -0.697601318359375 +38796 -0.123504638671875 +38797 -0.70391845703125 +38798 -0.109527587890625 +38799 -0.6424560546875 +38800 -0.0804443359375 +38801 -0.491241455078125 +38802 -0.039093017578125 +38803 -0.265716552734375 +38804 0.004608154296875 +38805 -0.023712158203125 +38806 0.044952392578125 +38807 0.201751708984375 +38808 0.07598876953125 +38809 0.375823974609375 +38810 0.095367431640625 +38811 0.485076904296875 +38812 0.10968017578125 +38813 0.56884765625 +38814 0.120208740234375 +38815 0.634765625 +38816 0.11944580078125 +38817 0.63763427734375 +38818 0.10552978515625 +38819 0.5660400390625 +38820 0.08734130859375 +38821 0.4720458984375 +38822 0.073638916015625 +38823 0.40692138671875 +38824 0.065765380859375 +38825 0.3778076171875 +38826 0.062591552734375 +38827 0.376953125 +38828 0.058868408203125 +38829 0.371978759765625 +38830 0.046356201171875 +38831 0.313140869140625 +38832 0.02252197265625 +38833 0.184417724609375 +38834 -0.00823974609375 +38835 0.011199951171875 +38836 -0.039886474609375 +38837 -0.171051025390625 +38838 -0.06817626953125 +38839 -0.33740234375 +38840 -0.0904541015625 +38841 -0.47198486328125 +38842 -0.104339599609375 +38843 -0.560394287109375 +38844 -0.106201171875 +38845 -0.58056640625 +38846 -0.09869384765625 +38847 -0.54754638671875 +38848 -0.089874267578125 +38849 -0.508575439453125 +38850 -0.07916259765625 +38851 -0.459503173828125 +38852 -0.065704345703125 +38853 -0.394378662109375 +38854 -0.056243896484375 +38855 -0.35260009765625 +38856 -0.047088623046875 +38857 -0.31170654296875 +38858 -0.02593994140625 +38859 -0.197418212890625 +38860 0.007415771484375 +38861 -0.007965087890625 +38862 0.044586181640625 +38863 0.207489013671875 +38864 0.078887939453125 +38865 0.409210205078125 +38866 0.1060791015625 +38867 0.57208251953125 +38868 0.121124267578125 +38869 0.66595458984375 +38870 0.118682861328125 +38871 0.65875244140625 +38872 0.101715087890625 +38873 0.56744384765625 +38874 0.076934814453125 +38875 0.431396484375 +38876 0.05181884765625 +38877 0.29443359375 +38878 0.03082275390625 +38879 0.182464599609375 +38880 0.008758544921875 +38881 0.06365966796875 +38882 -0.016632080078125 +38883 -0.075958251953125 +38884 -0.037322998046875 +38885 -0.189422607421875 +38886 -0.05242919921875 +38887 -0.271942138671875 +38888 -0.0650634765625 +38889 -0.342529296875 +38890 -0.06903076171875 +38891 -0.364166259765625 +38892 -0.062713623046875 +38893 -0.327239990234375 +38894 -0.0537109375 +38895 -0.2769775390625 +38896 -0.048828125 +38897 -0.253692626953125 +38898 -0.04583740234375 +38899 -0.24365234375 +38900 -0.03668212890625 +38901 -0.1983642578125 +38902 -0.02117919921875 +38903 -0.116241455078125 +38904 -0.006072998046875 +38905 -0.036834716796875 +38906 0.0076904296875 +38907 0.034881591796875 +38908 0.01873779296875 +38909 0.09124755859375 +38910 0.023040771484375 +38911 0.10888671875 +38912 0.0264892578125 +38913 0.125518798828125 +38914 0.031707763671875 +38915 0.15771484375 +38916 0.03460693359375 +38917 0.17828369140625 +38918 0.03314208984375 +38919 0.17108154296875 +38920 0.026580810546875 +38921 0.129974365234375 +38922 0.018798828125 +38923 0.082427978515625 +38924 0.009765625 +38925 0.027679443359375 +38926 -0.004608154296875 +38927 -0.065643310546875 +38928 -0.019073486328125 +38929 -0.15936279296875 +38930 -0.028045654296875 +38931 -0.21307373046875 +38932 -0.03253173828125 +38933 -0.234649658203125 +38934 -0.02923583984375 +38935 -0.2001953125 +38936 -0.0194091796875 +38937 -0.119171142578125 +38938 -0.00750732421875 +38939 -0.024749755859375 +38940 0.006866455078125 +38941 0.085784912109375 +38942 0.01904296875 +38943 0.178131103515625 +38944 0.0240478515625 +38945 0.215576171875 +38946 0.023681640625 +38947 0.211456298828125 +38948 0.019256591796875 +38949 0.17523193359375 +38950 0.013671875 +38951 0.128753662109375 +38952 0.010955810546875 +38953 0.1019287109375 +38954 0.008270263671875 +38955 0.0743408203125 +38956 0.00518798828125 +38957 0.04327392578125 +38958 0.005615234375 +38959 0.038177490234375 +38960 0.011871337890625 +38961 0.076263427734375 +38962 0.0216064453125 +38963 0.14105224609375 +38964 0.028533935546875 +38965 0.186431884765625 +38966 0.0294189453125 +38967 0.188812255859375 +38968 0.02301025390625 +38969 0.1390380859375 +38970 0.009918212890625 +38971 0.041778564453125 +38972 -0.006622314453125 +38973 -0.079437255859375 +38974 -0.025909423828125 +38975 -0.219390869140625 +38976 -0.046478271484375 +38977 -0.367828369140625 +38978 -0.06427001953125 +38979 -0.494873046875 +38980 -0.0732421875 +38981 -0.556243896484375 +38982 -0.0675048828125 +38983 -0.508697509765625 +38984 -0.0501708984375 +38985 -0.3756103515625 +38986 -0.0296630859375 +38987 -0.218902587890625 +38988 -0.009307861328125 +38989 -0.063751220703125 +38990 0.011077880859375 +38991 0.091552734375 +38992 0.030059814453125 +38993 0.23602294921875 +38994 0.0440673828125 +38995 0.342987060546875 +38996 0.05078125 +38997 0.39520263671875 +38998 0.04974365234375 +38999 0.389373779296875 +39000 0.04083251953125 +39001 0.324249267578125 +39002 0.027374267578125 +39003 0.224090576171875 +39004 0.01416015625 +39005 0.124267578125 +39006 0.0028076171875 +39007 0.037078857421875 +39008 -0.002960205078125 +39009 -0.010101318359375 +39010 -0.003509521484375 +39011 -0.019439697265625 +39012 -0.003204345703125 +39013 -0.022796630859375 +39014 0.00042724609375 +39015 -0.001556396484375 +39016 0.008941650390625 +39017 0.056304931640625 +39018 0.016326904296875 +39019 0.106719970703125 +39020 0.015411376953125 +39021 0.096893310546875 +39022 0.00830078125 +39023 0.042694091796875 +39024 0.00018310546875 +39025 -0.018035888671875 +39026 -0.007659912109375 +39027 -0.07586669921875 +39028 -0.013671875 +39029 -0.11944580078125 +39030 -0.01934814453125 +39031 -0.15972900390625 +39032 -0.025482177734375 +39033 -0.202606201171875 +39034 -0.0321044921875 +39035 -0.24859619140625 +39036 -0.040191650390625 +39037 -0.30517578125 +39038 -0.04833984375 +39039 -0.36212158203125 +39040 -0.052764892578125 +39041 -0.39141845703125 +39042 -0.04827880859375 +39043 -0.35528564453125 +39044 -0.034332275390625 +39045 -0.249969482421875 +39046 -0.0133056640625 +39047 -0.092864990234375 +39048 0.011138916015625 +39049 0.08905029296875 +39050 0.030792236328125 +39051 0.2352294921875 +39052 0.0419921875 +39053 0.318817138671875 +39054 0.047332763671875 +39055 0.358642578125 +39056 0.04583740234375 +39057 0.347747802734375 +39058 0.0374755859375 +39059 0.28564453125 +39060 0.02911376953125 +39061 0.223175048828125 +39062 0.025726318359375 +39063 0.196746826171875 +39064 0.023681640625 +39065 0.179840087890625 +39066 0.020660400390625 +39067 0.155548095703125 +39068 0.020355224609375 +39069 0.151214599609375 +39070 0.02142333984375 +39071 0.156951904296875 +39072 0.018280029296875 +39073 0.13177490234375 +39074 0.014312744140625 +39075 0.100799560546875 +39076 0.01263427734375 +39077 0.087127685546875 +39078 0.008392333984375 +39079 0.05487060546875 +39080 -0.000152587890625 +39081 -0.009002685546875 +39082 -0.012939453125 +39083 -0.10400390625 +39084 -0.0299072265625 +39085 -0.229400634765625 +39086 -0.047027587890625 +39087 -0.35552978515625 +39088 -0.05877685546875 +39089 -0.441925048828125 +39090 -0.063140869140625 +39091 -0.473846435546875 +39092 -0.061981201171875 +39093 -0.464813232421875 +39094 -0.055877685546875 +39095 -0.419097900390625 +39096 -0.04449462890625 +39097 -0.334320068359375 +39098 -0.03021240234375 +39099 -0.227935791015625 +39100 -0.016204833984375 +39101 -0.12347412109375 +39102 -0.003387451171875 +39103 -0.02764892578125 +39104 0.010711669921875 +39105 0.077667236328125 +39106 0.0289306640625 +39107 0.2132568359375 +39108 0.0526123046875 +39109 0.38885498046875 +39110 0.07879638671875 +39111 0.582794189453125 +39112 0.099212646484375 +39113 0.734039306640625 +39114 0.108062744140625 +39115 0.800140380859375 +39116 0.10498046875 +39117 0.7783203125 +39118 0.08953857421875 +39119 0.6651611328125 +39120 0.06158447265625 +39121 0.45965576171875 +39122 0.0262451171875 +39123 0.199188232421875 +39124 -0.007568359375 +39125 -0.050689697265625 +39126 -0.032135009765625 +39127 -0.23297119140625 +39128 -0.045074462890625 +39129 -0.33013916015625 +39130 -0.049957275390625 +39131 -0.368408203125 +39132 -0.051055908203125 +39133 -0.378936767578125 +39134 -0.050506591796875 +39135 -0.376983642578125 +39136 -0.050628662109375 +39137 -0.37969970703125 +39138 -0.052032470703125 +39139 -0.391510009765625 +39140 -0.051025390625 +39141 -0.385345458984375 +39142 -0.045013427734375 +39143 -0.3419189453125 +39144 -0.036956787109375 +39145 -0.28289794921875 +39146 -0.03271484375 +39147 -0.251617431640625 +39148 -0.034759521484375 +39149 -0.266143798828125 +39150 -0.035858154296875 +39151 -0.273345947265625 +39152 -0.0283203125 +39153 -0.216796875 +39154 -0.016448974609375 +39155 -0.128265380859375 +39156 -0.0084228515625 +39157 -0.068145751953125 +39158 -0.005157470703125 +39159 -0.0430908203125 +39160 -0.002777099609375 +39161 -0.024444580078125 +39162 0.003173828125 +39163 0.020721435546875 +39164 0.01708984375 +39165 0.124481201171875 +39166 0.035003662109375 +39167 0.25787353515625 +39168 0.050689697265625 +39169 0.379119873046875 +39170 0.063262939453125 +39171 0.47991943359375 +39172 0.0697021484375 +39173 0.5281982421875 +39174 0.06854248046875 +39175 0.511138916015625 +39176 0.062530517578125 +39177 0.456207275390625 +39178 0.056243896484375 +39179 0.407470703125 +39180 0.051727294921875 +39181 0.383758544921875 +39182 0.046142578125 +39183 0.35687255859375 +39184 0.038116455078125 +39185 0.31182861328125 +39186 0.02813720703125 +39187 0.250885009765625 +39188 0.0155029296875 +39189 0.1654052734375 +39190 -0.001617431640625 +39191 0.035247802734375 +39192 -0.02325439453125 +39193 -0.142059326171875 +39194 -0.0460205078125 +39195 -0.33563232421875 +39196 -0.068634033203125 +39197 -0.5345458984375 +39198 -0.089263916015625 +39199 -0.72186279296875 +39200 -0.10150146484375 +39201 -0.836669921875 +39202 -0.10052490234375 +39203 -0.8326416015625 +39204 -0.0885009765625 +39205 -0.7296142578125 +39206 -0.07122802734375 +39207 -0.582550048828125 +39208 -0.05389404296875 +39209 -0.440093994140625 +39210 -0.0389404296875 +39211 -0.324310302734375 +39212 -0.02301025390625 +39213 -0.20147705078125 +39214 -0.00347900390625 +39215 -0.044647216796875 +39216 0.015045166015625 +39217 0.103973388671875 +39218 0.028045654296875 +39219 0.202392578125 +39220 0.03680419921875 +39221 0.264495849609375 +39222 0.0462646484375 +39223 0.338897705078125 +39224 0.0582275390625 +39225 0.443817138671875 +39226 0.069091796875 +39227 0.545074462890625 +39228 0.076263427734375 +39229 0.6173095703125 +39230 0.07891845703125 +39231 0.6524658203125 +39232 0.078460693359375 +39233 0.66339111328125 +39234 0.075653076171875 +39235 0.6561279296875 +39236 0.068084716796875 +39237 0.606781005859375 +39238 0.054443359375 +39239 0.501190185546875 +39240 0.036285400390625 +39241 0.352783203125 +39242 0.015350341796875 +39243 0.176544189453125 +39244 -0.00897216796875 +39245 -0.034820556640625 +39246 -0.03411865234375 +39247 -0.258209228515625 +39248 -0.0546875 +39249 -0.44244384765625 +39250 -0.069366455078125 +39251 -0.5753173828125 +39252 -0.077606201171875 +39253 -0.65203857421875 +39254 -0.076202392578125 +39255 -0.641632080078125 +39256 -0.067108154296875 +39257 -0.562164306640625 +39258 -0.05499267578125 +39259 -0.458038330078125 +39260 -0.042144775390625 +39261 -0.350555419921875 +39262 -0.03082275390625 +39263 -0.260528564453125 +39264 -0.021575927734375 +39265 -0.192108154296875 +39266 -0.014190673828125 +39267 -0.141937255859375 +39268 -0.007965087890625 +39269 -0.1021728515625 +39270 -0.001953125 +39271 -0.062896728515625 +39272 0.004974365234375 +39273 -0.011932373046875 +39274 0.014007568359375 +39275 0.062835693359375 +39276 0.023773193359375 +39277 0.148712158203125 +39278 0.0338134765625 +39279 0.241729736328125 +39280 0.04486083984375 +39281 0.34912109375 +39282 0.055511474609375 +39283 0.457305908203125 +39284 0.063507080078125 +39285 0.54388427734375 +39286 0.065185546875 +39287 0.5728759765625 +39288 0.056671142578125 +39289 0.506591796875 +39290 0.038726806640625 +39291 0.351226806640625 +39292 0.01556396484375 +39293 0.146514892578125 +39294 -0.007232666015625 +39295 -0.05523681640625 +39296 -0.025634765625 +39297 -0.21624755859375 +39298 -0.03936767578125 +39299 -0.334930419921875 +39300 -0.047515869140625 +39301 -0.402984619140625 +39302 -0.05218505859375 +39303 -0.4412841796875 +39304 -0.058135986328125 +39305 -0.49578857421875 +39306 -0.064727783203125 +39307 -0.5601806640625 +39308 -0.068450927734375 +39309 -0.600738525390625 +39310 -0.065887451171875 +39311 -0.584228515625 +39312 -0.0538330078125 +39313 -0.47930908203125 +39314 -0.031707763671875 +39315 -0.27935791015625 +39316 -0.002105712890625 +39317 -0.0089111328125 +39318 0.02825927734375 +39319 0.268798828125 +39320 0.051910400390625 +39321 0.482818603515625 +39322 0.065704345703125 +39323 0.60369873046875 +39324 0.071563720703125 +39325 0.650421142578125 +39326 0.07373046875 +39327 0.66400146484375 +39328 0.071868896484375 +39329 0.6414794921875 +39330 0.064910888671875 +39331 0.572540283203125 +39332 0.05706787109375 +39333 0.498138427734375 +39334 0.050567626953125 +39335 0.439453125 +39336 0.04327392578125 +39337 0.375518798828125 +39338 0.031890869140625 +39339 0.274505615234375 +39340 0.013641357421875 +39341 0.1087646484375 +39342 -0.00909423828125 +39343 -0.099395751953125 +39344 -0.032928466796875 +39345 -0.3182373046875 +39346 -0.05792236328125 +39347 -0.5489501953125 +39348 -0.082183837890625 +39349 -0.7738037109375 +39350 -0.10015869140625 +39351 -0.86383056640625 +39352 -0.1083984375 +39353 -0.870391845703125 +39354 -0.108673095703125 +39355 -0.86895751953125 +39356 -0.10235595703125 +39357 -0.861053466796875 +39358 -0.087677001953125 +39359 -0.765869140625 +39360 -0.0634765625 +39361 -0.5301513671875 +39362 -0.030487060546875 +39363 -0.214691162109375 +39364 0.006744384765625 +39365 0.137359619140625 +39366 0.0428466796875 +39367 0.474822998046875 +39368 0.0740966796875 +39369 0.76239013671875 +39370 0.097625732421875 +39371 0.867462158203125 +39372 0.113433837890625 +39373 0.870361328125 +39374 0.120269775390625 +39375 0.86480712890625 +39376 0.11865234375 +39377 0.831817626953125 +39378 0.111114501953125 +39379 0.677581787109375 +39380 0.0982666015625 +39381 0.495880126953125 +39382 0.08203125 +39383 0.30767822265625 +39384 0.062652587890625 +39385 0.116180419921875 +39386 0.036834716796875 +39387 -0.110748291015625 +39388 0.00384521484375 +39389 -0.381805419921875 +39390 -0.03179931640625 +39391 -0.6572265625 +39392 -0.063812255859375 +39393 -0.857421875 +39394 -0.087738037109375 +39395 -0.870391845703125 +39396 -0.102813720703125 +39397 -0.870391845703125 +39398 -0.11181640625 +39399 -0.86444091796875 +39400 -0.118438720703125 +39401 -0.85723876953125 +39402 -0.120758056640625 +39403 -0.790008544921875 +39404 -0.11309814453125 +39405 -0.62847900390625 +39406 -0.095123291015625 +39407 -0.3956298828125 +39408 -0.07025146484375 +39409 -0.126708984375 +39410 -0.04132080078125 +39411 0.150115966796875 +39412 -0.00958251953125 +39413 0.424041748046875 +39414 0.02215576171875 +39415 0.670623779296875 +39416 0.0498046875 +39417 0.854522705078125 +39418 0.071533203125 +39419 0.866485595703125 +39420 0.08575439453125 +39421 0.86920166015625 +39422 0.094329833984375 +39423 0.8653564453125 +39424 0.098907470703125 +39425 0.857147216796875 +39426 0.098907470703125 +39427 0.766845703125 +39428 0.094482421875 +39429 0.628509521484375 +39430 0.085205078125 +39431 0.462127685546875 +39432 0.0731201171875 +39433 0.297210693359375 +39434 0.059326171875 +39435 0.14862060546875 +39436 0.042510986328125 +39437 -0.00537109375 +39438 0.023590087890625 +39439 -0.15753173828125 +39440 0.002716064453125 +39441 -0.31304931640625 +39442 -0.02069091796875 +39443 -0.48876953125 +39444 -0.04290771484375 +39445 -0.6416015625 +39446 -0.0618896484375 +39447 -0.751373291015625 +39448 -0.07904052734375 +39449 -0.84619140625 +39450 -0.0931396484375 +39451 -0.861297607421875 +39452 -0.1016845703125 +39453 -0.863250732421875 +39454 -0.102386474609375 +39455 -0.856597900390625 +39456 -0.09625244140625 +39457 -0.7498779296875 +39458 -0.08758544921875 +39459 -0.624542236328125 +39460 -0.07501220703125 +39461 -0.47808837890625 +39462 -0.05462646484375 +39463 -0.253387451171875 +39464 -0.030029296875 +39465 0.003692626953125 +39466 -0.0064697265625 +39467 0.2257080078125 +39468 0.016632080078125 +39469 0.427154541015625 +39470 0.04132080078125 +39471 0.643218994140625 +39472 0.066619873046875 +39473 0.855926513671875 +39474 0.088165283203125 +39475 0.870361328125 +39476 0.102203369140625 +39477 0.870361328125 +39478 0.109161376953125 +39479 0.862762451171875 +39480 0.108856201171875 +39481 0.79669189453125 +39482 0.100677490234375 +39483 0.595794677734375 +39484 0.0867919921875 +39485 0.362152099609375 +39486 0.069427490234375 +39487 0.1270751953125 +39488 0.050323486328125 +39489 -0.086944580078125 +39490 0.02984619140625 +39491 -0.2784423828125 +39492 0.005767822265625 +39493 -0.484832763671875 +39494 -0.02301025390625 +39495 -0.729583740234375 +39496 -0.052581787109375 +39497 -0.86688232421875 +39498 -0.078125 +39499 -0.870391845703125 +39500 -0.099090576171875 +39501 -0.86859130859375 +39502 -0.115203857421875 +39503 -0.86279296875 +39504 -0.123809814453125 +39505 -0.817962646484375 +39506 -0.121612548828125 +39507 -0.6116943359375 +39508 -0.108123779296875 +39509 -0.3128662109375 +39510 -0.08587646484375 +39511 0.039398193359375 +39512 -0.05645751953125 +39513 0.422821044921875 +39514 -0.022430419921875 +39515 0.805145263671875 +39516 0.011077880859375 +39517 0.870361328125 +39518 0.039764404296875 +39519 0.870361328125 +39520 0.06256103515625 +39521 0.860015869140625 +39522 0.07867431640625 +39523 0.727935791015625 +39524 0.0875244140625 +39525 0.48114013671875 +39526 0.0906982421875 +39527 0.2059326171875 +39528 0.08966064453125 +39529 -0.06103515625 +39530 0.0850830078125 +39531 -0.29913330078125 +39532 0.075836181640625 +39533 -0.516204833984375 +39534 0.06085205078125 +39535 -0.7252197265625 +39536 0.041961669921875 +39537 -0.85980224609375 +39538 0.021728515625 +39539 -0.870391845703125 +39540 0.00244140625 +39541 -0.870391845703125 +39542 -0.012176513671875 +39543 -0.858062744140625 +39544 -0.021636962890625 +39545 -0.673004150390625 +39546 -0.029541015625 +39547 -0.42694091796875 +39548 -0.03887939453125 +39549 -0.2100830078125 +39550 -0.04925537109375 +39551 -0.0362548828125 +39552 -0.058441162109375 +39553 0.10943603515625 +39554 -0.0648193359375 +39555 0.23516845703125 +39556 -0.065338134765625 +39557 0.373687744140625 +39558 -0.060089111328125 +39559 0.517791748046875 +39560 -0.053619384765625 +39561 0.602783203125 +39562 -0.045562744140625 +39563 0.635711669921875 +39564 -0.03363037109375 +39565 0.655181884765625 +39566 -0.0186767578125 +39567 0.65948486328125 +39568 -0.00140380859375 +39569 0.651275634765625 +39570 0.016204833984375 +39571 0.61846923828125 +39572 0.03131103515625 +39573 0.53753662109375 +39574 0.04241943359375 +39575 0.404144287109375 +39576 0.048675537109375 +39577 0.22186279296875 +39578 0.050048828125 +39579 0.003997802734375 +39580 0.0477294921875 +39581 -0.22100830078125 +39582 0.043121337890625 +39583 -0.42449951171875 +39584 0.03765869140625 +39585 -0.579833984375 +39586 0.034423828125 +39587 -0.641876220703125 +39588 0.032958984375 +39589 -0.6177978515625 +39590 0.0286865234375 +39591 -0.575531005859375 +39592 0.021270751953125 +39593 -0.526336669921875 +39594 0.01458740234375 +39595 -0.42645263671875 +39596 0.010711669921875 +39597 -0.2581787109375 +39598 0.007232666015625 +39599 -0.068695068359375 +39600 0.001495361328125 +39601 0.09222412109375 +39602 -0.00494384765625 +39603 0.232147216796875 +39604 -0.01123046875 +39605 0.3509521484375 +39606 -0.019378662109375 +39607 0.410064697265625 +39608 -0.031402587890625 +39609 0.372955322265625 +39610 -0.04571533203125 +39611 0.2554931640625 +39612 -0.058563232421875 +39613 0.10711669921875 +39614 -0.068511962890625 +39615 -0.052886962890625 +39616 -0.073028564453125 +39617 -0.186279296875 +39618 -0.068145751953125 +39619 -0.23291015625 +39620 -0.055633544921875 +39621 -0.209442138671875 +39622 -0.04034423828125 +39623 -0.174163818359375 +39624 -0.02301025390625 +39625 -0.126739501953125 +39626 -0.0030517578125 +39627 -0.048126220703125 +39628 0.017333984375 +39629 0.0426025390625 +39630 0.03466796875 +39631 0.10748291015625 +39632 0.047882080078125 +39633 0.1409912109375 +39634 0.060333251953125 +39635 0.19708251953125 +39636 0.07147216796875 +39637 0.273651123046875 +39638 0.0772705078125 +39639 0.31768798828125 +39640 0.07855224609375 +39641 0.341094970703125 +39642 0.077178955078125 +39643 0.368011474609375 +39644 0.071533203125 +39645 0.37249755859375 +39646 0.058135986328125 +39647 0.30072021484375 +39648 0.037445068359375 +39649 0.1517333984375 +39650 0.01434326171875 +39651 -0.01470947265625 +39652 -0.009765625 +39653 -0.1883544921875 +39654 -0.03448486328125 +39655 -0.372711181640625 +39656 -0.0552978515625 +39657 -0.51397705078125 +39658 -0.068756103515625 +39659 -0.57177734375 +39660 -0.07391357421875 +39661 -0.53948974609375 +39662 -0.071746826171875 +39663 -0.43511962890625 +39664 -0.064727783203125 +39665 -0.2962646484375 +39666 -0.05548095703125 +39667 -0.161102294921875 +39668 -0.045074462890625 +39669 -0.0435791015625 +39670 -0.033355712890625 +39671 0.060394287109375 +39672 -0.02166748046875 +39673 0.13665771484375 +39674 -0.011505126953125 +39675 0.170135498046875 +39676 -0.002960205078125 +39677 0.16552734375 +39678 0.005889892578125 +39679 0.15728759765625 +39680 0.015045166015625 +39681 0.150787353515625 +39682 0.022308349609375 +39683 0.12200927734375 +39684 0.027557373046875 +39685 0.080108642578125 +39686 0.0318603515625 +39687 0.05126953125 +39688 0.03643798828125 +39689 0.062896728515625 +39690 0.040069580078125 +39691 0.09271240234375 +39692 0.04034423828125 +39693 0.092987060546875 +39694 0.038055419921875 +39695 0.07855224609375 +39696 0.034088134765625 +39697 0.06427001953125 +39698 0.02789306640625 +39699 0.0347900390625 +39700 0.0196533203125 +39701 -0.01171875 +39702 0.01068115234375 +39703 -0.056060791015625 +39704 0.003448486328125 +39705 -0.055511474609375 +39706 -0.0015869140625 +39707 -0.010467529296875 +39708 -0.00677490234375 +39709 0.02508544921875 +39710 -0.013031005859375 +39711 0.025665283203125 +39712 -0.01873779296875 +39713 0.017333984375 +39714 -0.0235595703125 +39715 0.00189208984375 +39716 -0.027862548828125 +39717 -0.03173828125 +39718 -0.03094482421875 +39719 -0.071502685546875 +39720 -0.03369140625 +39721 -0.13543701171875 +39722 -0.035980224609375 +39723 -0.219970703125 +39724 -0.036712646484375 +39725 -0.300506591796875 +39726 -0.03607177734375 +39727 -0.376312255859375 +39728 -0.032806396484375 +39729 -0.416107177734375 +39730 -0.0247802734375 +39731 -0.371124267578125 +39732 -0.012359619140625 +39733 -0.242279052734375 +39734 0.0020751953125 +39735 -0.069732666015625 +39736 0.017181396484375 +39737 0.125640869140625 +39738 0.0311279296875 +39739 0.31268310546875 +39740 0.041839599609375 +39741 0.45501708984375 +39742 0.04925537109375 +39743 0.554779052734375 +39744 0.053253173828125 +39745 0.61065673828125 +39746 0.053192138671875 +39747 0.610931396484375 +39748 0.04791259765625 +39749 0.531463623046875 +39750 0.038330078125 +39751 0.3883056640625 +39752 0.027252197265625 +39753 0.23468017578125 +39754 0.01617431640625 +39755 0.095245361328125 +39756 0.006622314453125 +39757 -0.00396728515625 +39758 -0.00042724609375 +39759 -0.04852294921875 +39760 -0.005523681640625 +39761 -0.055145263671875 +39762 -0.011016845703125 +39763 -0.0758056640625 +39764 -0.01806640625 +39765 -0.138702392578125 +39766 -0.024749755859375 +39767 -0.209197998046875 +39768 -0.030975341796875 +39769 -0.289031982421875 +39770 -0.036712646484375 +39771 -0.37884521484375 +39772 -0.040802001953125 +39773 -0.456329345703125 +39774 -0.04302978515625 +39775 -0.51641845703125 +39776 -0.04144287109375 +39777 -0.519287109375 +39778 -0.03582763671875 +39779 -0.458251953125 +39780 -0.0289306640625 +39781 -0.384796142578125 +39782 -0.022186279296875 +39783 -0.323699951171875 +39784 -0.0155029296875 +39785 -0.269287109375 +39786 -0.007781982421875 +39787 -0.1951904296875 +39788 0.000762939453125 +39789 -0.100006103515625 +39790 0.00860595703125 +39791 -0.01055908203125 +39792 0.017059326171875 +39793 0.1033935546875 +39794 0.0263671875 +39795 0.24908447265625 +39796 0.033782958984375 +39797 0.373199462890625 +39798 0.038360595703125 +39799 0.45806884765625 +39800 0.040496826171875 +39801 0.511474609375 +39802 0.041839599609375 +39803 0.565399169921875 +39804 0.042083740234375 +39805 0.61138916015625 +39806 0.038360595703125 +39807 0.5897216796875 +39808 0.03033447265625 +39809 0.4906005859375 +39810 0.019073486328125 +39811 0.33148193359375 +39812 0.006561279296875 +39813 0.147796630859375 +39814 -0.004913330078125 +39815 -0.01873779296875 +39816 -0.0137939453125 +39817 -0.140289306640625 +39818 -0.018707275390625 +39819 -0.191986083984375 +39820 -0.02008056640625 +39821 -0.184295654296875 +39822 -0.020050048828125 +39823 -0.161834716796875 +39824 -0.02069091796875 +39825 -0.166595458984375 +39826 -0.021728515625 +39827 -0.19390869140625 +39828 -0.02227783203125 +39829 -0.22442626953125 +39830 -0.023468017578125 +39831 -0.279754638671875 +39832 -0.02435302734375 +39833 -0.3389892578125 +39834 -0.022674560546875 +39835 -0.3543701171875 +39836 -0.019683837890625 +39837 -0.348175048828125 +39838 -0.01580810546875 +39839 -0.32598876953125 +39840 -0.009735107421875 +39841 -0.2581787109375 +39842 -0.0013427734375 +39843 -0.139801025390625 +39844 0.00848388671875 +39845 0.014617919921875 +39846 0.016571044921875 +39847 0.144378662109375 +39848 0.02142333984375 +39849 0.221038818359375 +39850 0.024322509765625 +39851 0.27069091796875 +39852 0.025299072265625 +39853 0.294036865234375 +39854 0.025421142578125 +39855 0.311767578125 +39856 0.025482177734375 +39857 0.339141845703125 +39858 0.024658203125 +39859 0.360260009765625 +39860 0.022369384765625 +39861 0.360504150390625 +39862 0.017547607421875 +39863 0.308380126953125 +39864 0.00946044921875 +39865 0.18170166015625 +39866 -0.00067138671875 +39867 0.0047607421875 +39868 -0.010772705078125 +39869 -0.17559814453125 +39870 -0.01885986328125 +39871 -0.3143310546875 +39872 -0.0230712890625 +39873 -0.36785888671875 +39874 -0.02435302734375 +39875 -0.36248779296875 +39876 -0.02447509765625 +39877 -0.343536376953125 +39878 -0.023040771484375 +39879 -0.3018798828125 +39880 -0.01983642578125 +39881 -0.231414794921875 +39882 -0.014312744140625 +39883 -0.117645263671875 +39884 -0.007843017578125 +39885 0.007049560546875 +39886 -0.002716064453125 +39887 0.087982177734375 +39888 0.00152587890625 +39889 0.13946533203125 +39890 0.005279541015625 +39891 0.17425537109375 +39892 0.008209228515625 +39893 0.188201904296875 +39894 0.009796142578125 +39895 0.171234130859375 +39896 0.009735107421875 +39897 0.118438720703125 +39898 0.009033203125 +39899 0.05706787109375 +39900 0.0076904296875 +39901 -0.010711669921875 +39902 0.00537109375 +39903 -0.0914306640625 +39904 0.0029296875 +39905 -0.162322998046875 +39906 0.00152587890625 +39907 -0.194549560546875 +39908 0.002716064453125 +39909 -0.1492919921875 +39910 0.0067138671875 +39911 -0.02166748046875 +39912 0.011016845703125 +39913 0.124053955078125 +39914 0.012664794921875 +39915 0.211151123046875 +39916 0.011810302734375 +39917 0.240447998046875 +39918 0.009765625 +39919 0.242218017578125 +39920 0.007049560546875 +39921 0.2257080078125 +39922 0.00390625 +39923 0.194366455078125 +39924 -0.0008544921875 +39925 0.115509033203125 +39926 -0.006134033203125 +39927 0.0128173828125 +39928 -0.009521484375 +39929 -0.053802490234375 +39930 -0.012054443359375 +39931 -0.110626220703125 +39932 -0.015411376953125 +39933 -0.199493408203125 +39934 -0.018585205078125 +39935 -0.29437255859375 +39936 -0.01947021484375 +39937 -0.33221435546875 +39938 -0.01751708984375 +39939 -0.27972412109375 +39940 -0.013671875 +39941 -0.185333251953125 +39942 -0.00909423828125 +39943 -0.128204345703125 +39944 -0.004302978515625 +39945 -0.115692138671875 +39946 0.000457763671875 +39947 -0.116455078125 +39948 0.005035400390625 +39949 -0.105926513671875 +39950 0.0093994140625 +39951 -0.053955078125 +39952 0.01336669921875 +39953 0.048797607421875 +39954 0.01641845703125 +39955 0.157318115234375 +39956 0.01800537109375 +39957 0.212005615234375 +39958 0.018157958984375 +39959 0.218475341796875 +39960 0.01739501953125 +39961 0.23724365234375 +39962 0.01611328125 +39963 0.30535888671875 +39964 0.01409912109375 +39965 0.38128662109375 +39966 0.011077880859375 +39967 0.404449462890625 +39968 0.007415771484375 +39969 0.3944091796875 +39970 0.003631591796875 +39971 0.3885498046875 +39972 -0.000213623046875 +39973 0.362640380859375 +39974 -0.0042724609375 +39975 0.27362060546875 +39976 -0.008392333984375 +39977 0.11712646484375 +39978 -0.011993408203125 +39979 -0.054901123046875 +39980 -0.014556884765625 +39981 -0.19085693359375 +39982 -0.0159912109375 +39983 -0.28570556640625 +39984 -0.01629638671875 +39985 -0.339263916015625 +39986 -0.015716552734375 +39987 -0.3775634765625 +39988 -0.014678955078125 +39989 -0.445709228515625 +39990 -0.01318359375 +39991 -0.535064697265625 +39992 -0.01129150390625 +39993 -0.629058837890625 +39994 -0.008880615234375 +39995 -0.697601318359375 +39996 -0.005828857421875 +39997 -0.70391845703125 +39998 -0.002288818359375 +39999 -0.6424560546875 +40000 0.001708984375 +40001 -0.491241455078125 +40002 0.00592041015625 +40003 -0.265716552734375 +40004 0.009735107421875 +40005 -0.023712158203125 +40006 0.012786865234375 +40007 0.201751708984375 +40008 0.0147705078125 +40009 0.375823974609375 +40010 0.015594482421875 +40011 0.485076904296875 +40012 0.015594482421875 +40013 0.56884765625 +40014 0.014862060546875 +40015 0.634765625 +40016 0.01312255859375 +40017 0.63763427734375 +40018 0.010406494140625 +40019 0.5660400390625 +40020 0.00726318359375 +40021 0.4720458984375 +40022 0.004241943359375 +40023 0.40692138671875 +40024 0.00152587890625 +40025 0.3778076171875 +40026 -0.000823974609375 +40027 0.376953125 +40028 -0.0029296875 +40029 0.371978759765625 +40030 -0.005096435546875 +40031 0.313140869140625 +40032 -0.00732421875 +40033 0.184417724609375 +40034 -0.009368896484375 +40035 0.011199951171875 +40036 -0.010894775390625 +40037 -0.171051025390625 +40038 -0.01171875 +40039 -0.33740234375 +40040 -0.011749267578125 +40041 -0.47198486328125 +40042 -0.010955810546875 +40043 -0.560394287109375 +40044 -0.009246826171875 +40045 -0.58056640625 +40046 -0.00689697265625 +40047 -0.54754638671875 +40048 -0.004425048828125 +40049 -0.508575439453125 +40050 -0.00189208984375 +40051 -0.459503173828125 +40052 0.0006103515625 +40053 -0.394378662109375 +40054 0.002685546875 +40055 -0.35260009765625 +40056 0.00439453125 +40057 -0.31170654296875 +40058 0.00628662109375 +40059 -0.197418212890625 +40060 0.00830078125 +40061 -0.007965087890625 +40062 0.010040283203125 +40063 0.207489013671875 +40064 0.01116943359375 +40065 0.409210205078125 +40066 0.011566162109375 +40067 0.57208251953125 +40068 0.01104736328125 +40069 0.66595458984375 +40070 0.00946044921875 +40071 0.65875244140625 +40072 0.00701904296875 +40073 0.56744384765625 +40074 0.004150390625 +40075 0.431396484375 +40076 0.00128173828125 +40077 0.29443359375 +40078 -0.001251220703125 +40079 0.182464599609375 +40080 -0.00360107421875 +40081 0.06365966796875 +40082 -0.005828857421875 +40083 -0.075958251953125 +40084 -0.00750732421875 +40085 -0.189422607421875 +40086 -0.008544921875 +40087 -0.271942138671875 +40088 -0.009063720703125 +40089 -0.342529296875 +40090 -0.00885009765625 +40091 -0.364166259765625 +40092 -0.007843017578125 +40093 -0.327239990234375 +40094 -0.006439208984375 +40095 -0.2769775390625 +40096 -0.005035400390625 +40097 -0.253692626953125 +40098 -0.00360107421875 +40099 -0.24365234375 +40100 -0.001800537109375 +40101 -0.1983642578125 +40102 0.000244140625 +40103 -0.116241455078125 +40104 0.002166748046875 +40105 -0.036834716796875 +40106 0.00384521484375 +40107 0.034881591796875 +40108 0.00518798828125 +40109 0.09124755859375 +40110 0.0059814453125 +40111 0.10888671875 +40112 0.006500244140625 +40113 0.125518798828125 +40114 0.0068359375 +40115 0.15771484375 +40116 0.00677490234375 +40117 0.17828369140625 +40118 0.006195068359375 +40119 0.17108154296875 +40120 0.005126953125 +40121 0.129974365234375 +40122 0.003814697265625 +40123 0.082427978515625 +40124 0.002288818359375 +40125 0.027679443359375 +40126 0.000396728515625 +40127 -0.065643310546875 +40128 -0.00146484375 +40129 -0.15936279296875 +40130 -0.0029296875 +40131 -0.21307373046875 +40132 -0.0040283203125 +40133 -0.234649658203125 +40134 -0.0045166015625 +40135 -0.2001953125 +40136 -0.004425048828125 +40137 -0.119171142578125 +40138 -0.003997802734375 +40139 -0.024749755859375 +40140 -0.003173828125 +40141 0.085784912109375 +40142 -0.002288818359375 +40143 0.178131103515625 +40144 -0.001617431640625 +40145 0.215576171875 +40146 -0.0010986328125 +40147 0.211456298828125 +40148 -0.00067138671875 +40149 0.17523193359375 +40150 -0.00018310546875 +40151 0.128753662109375 +40152 0.00054931640625 +40153 0.1019287109375 +40154 0.001251220703125 +40155 0.0743408203125 +40156 0.001861572265625 +40157 0.04327392578125 +40158 0.002593994140625 +40159 0.038177490234375 +40160 0.00347900390625 +40161 0.076263427734375 +40162 0.00439453125 +40163 0.14105224609375 +40164 0.00494384765625 +40165 0.186431884765625 +40166 0.00494384765625 +40167 0.188812255859375 +40168 0.00433349609375 +40169 0.1390380859375 +40170 0.003173828125 +40171 0.041778564453125 +40172 0.001708984375 +40173 -0.079437255859375 +40174 0.0 +40175 -0.219390869140625 +40176 -0.001800537109375 +40177 -0.367828369140625 +40178 -0.00341796875 +40179 -0.494873046875 +40180 -0.004486083984375 +40181 -0.556243896484375 +40182 -0.004638671875 +40183 -0.508697509765625 +40184 -0.0040283203125 +40185 -0.3756103515625 +40186 -0.00311279296875 +40187 -0.218902587890625 +40188 -0.00213623046875 +40189 -0.063751220703125 +40190 -0.001068115234375 +40191 0.091552734375 +40192 3.0517578125e-05 +40193 0.23602294921875 +40194 0.000946044921875 +40195 0.342987060546875 +40196 0.00140380859375 +40197 0.39520263671875 +40198 0.001251220703125 +40199 0.389373779296875 +40200 0.000335693359375 +40201 0.324249267578125 +40202 -0.000885009765625 +40203 0.224090576171875 +40204 -0.001739501953125 +40205 0.124267578125 +40206 -0.002044677734375 +40207 0.037078857421875 +40208 -0.00128173828125 +40209 -0.010101318359375 +40210 0.000335693359375 +40211 -0.019439697265625 +40212 0.001953125 +40213 -0.022796630859375 +40214 0.003936767578125 +40215 -0.001556396484375 +40216 0.006439208984375 +40217 0.056304931640625 +40218 0.008392333984375 +40219 0.106719970703125 +40220 0.008514404296875 +40221 0.096893310546875 +40222 0.0072021484375 +40223 0.042694091796875 +40224 0.005401611328125 +40225 -0.018035888671875 +40226 0.00335693359375 +40227 -0.07586669921875 +40228 0.00140380859375 +40229 -0.11944580078125 +40230 -0.00067138671875 +40231 -0.15972900390625 +40232 -0.0029296875 +40233 -0.202606201171875 +40234 -0.0052490234375 +40235 -0.24859619140625 +40236 -0.007781982421875 +40237 -0.30517578125 +40238 -0.010223388671875 +40239 -0.36212158203125 +40240 -0.011871337890625 +40241 -0.39141845703125 +40242 -0.011749267578125 +40243 -0.35528564453125 +40244 -0.009735107421875 +40245 -0.249969482421875 +40246 -0.0062255859375 +40247 -0.092864990234375 +40248 -0.00189208984375 +40249 0.08905029296875 +40250 0.001800537109375 +40251 0.2352294921875 +40252 0.004180908203125 +40253 0.318817138671875 +40254 0.005706787109375 +40255 0.358642578125 +40256 0.00616455078125 +40257 0.347747802734375 +40258 0.005462646484375 +40259 0.28564453125 +40260 0.00482177734375 +40261 0.223175048828125 +40262 0.005035400390625 +40263 0.196746826171875 +40264 0.00543212890625 +40265 0.179840087890625 +40266 0.005584716796875 +40267 0.155548095703125 +40268 0.006072998046875 +40269 0.151214599609375 +40270 0.00665283203125 +40271 0.156951904296875 +40272 0.006317138671875 +40273 0.13177490234375 +40274 0.005645751953125 +40275 0.100799560546875 +40276 0.005218505859375 +40277 0.087127685546875 +40278 0.004180908203125 +40279 0.05487060546875 +40280 0.002227783203125 +40281 -0.009002685546875 +40282 -0.00054931640625 +40283 -0.10400390625 +40284 -0.004150390625 +40285 -0.229400634765625 +40286 -0.0078125 +40287 -0.35552978515625 +40288 -0.010498046875 +40289 -0.441925048828125 +40290 -0.011810302734375 +40291 -0.473846435546875 +40292 -0.0120849609375 +40293 -0.464813232421875 +40294 -0.011383056640625 +40295 -0.419097900390625 +40296 -0.0096435546875 +40297 -0.334320068359375 +40298 -0.00726318359375 +40299 -0.227935791015625 +40300 -0.004791259765625 +40301 -0.12347412109375 +40302 -0.00238037109375 +40303 -0.02764892578125 +40304 0.0003662109375 +40305 0.077667236328125 +40306 0.00390625 +40307 0.2132568359375 +40308 0.008453369140625 +40309 0.38885498046875 +40310 0.01348876953125 +40311 0.582794189453125 +40312 0.01751708984375 +40313 0.734039306640625 +40314 0.01947021484375 +40315 0.800140380859375 +40316 0.019256591796875 +40317 0.7783203125 +40318 0.016815185546875 +40319 0.6651611328125 +40320 0.012115478515625 +40321 0.45965576171875 +40322 0.006072998046875 +40323 0.199188232421875 +40324 0.000244140625 +40325 -0.050689697265625 +40326 -0.003997802734375 +40327 -0.23297119140625 +40328 -0.006256103515625 +40329 -0.33013916015625 +40330 -0.007171630859375 +40331 -0.368408203125 +40332 -0.007476806640625 +40333 -0.378936767578125 +40334 -0.007568359375 +40335 -0.376983642578125 +40336 -0.007843017578125 +40337 -0.37969970703125 +40338 -0.00836181640625 +40339 -0.391510009765625 +40340 -0.008453369140625 +40341 -0.385345458984375 +40342 -0.007659912109375 +40343 -0.3419189453125 +40344 -0.0064697265625 +40345 -0.28289794921875 +40346 -0.00592041015625 +40347 -0.251617431640625 +40348 -0.006439208984375 +40349 -0.266143798828125 +40350 -0.006744384765625 +40351 -0.273345947265625 +40352 -0.0054931640625 +40353 -0.216796875 +40354 -0.003448486328125 +40355 -0.128265380859375 +40356 -0.00201416015625 +40357 -0.068145751953125 +40358 -0.0013427734375 +40359 -0.0430908203125 +40360 -0.000762939453125 +40361 -0.024444580078125 +40362 0.000457763671875 +40363 0.020721435546875 +40364 0.003082275390625 +40365 0.124481201171875 +40366 0.00640869140625 +40367 0.25787353515625 +40368 0.0093994140625 +40369 0.379119873046875 +40370 0.011871337890625 +40371 0.47991943359375 +40372 0.0130615234375 +40373 0.5281982421875 +40374 0.01263427734375 +40375 0.511138916015625 +40376 0.01129150390625 +40377 0.456207275390625 +40378 0.01007080078125 +40379 0.407470703125 +40380 0.009429931640625 +40381 0.383758544921875 +40382 0.008636474609375 +40383 0.35687255859375 +40384 0.00738525390625 +40385 0.31182861328125 +40386 0.0057373046875 +40387 0.250885009765625 +40388 0.0035400390625 +40389 0.1654052734375 +40390 0.00030517578125 +40391 0.035247802734375 +40392 -0.00396728515625 +40393 -0.142059326171875 +40394 -0.008544921875 +40395 -0.33563232421875 +40396 -0.01318359375 +40397 -0.5345458984375 +40398 -0.01751708984375 +40399 -0.72186279296875 +40400 -0.02001953125 +40401 -0.836669921875 +40402 -0.019622802734375 +40403 -0.8326416015625 +40404 -0.016845703125 +40405 -0.7296142578125 +40406 -0.0130615234375 +40407 -0.582550048828125 +40408 -0.009429931640625 +40409 -0.440093994140625 +40410 -0.006500244140625 +40411 -0.324310302734375 +40412 -0.00341796875 +40413 -0.20147705078125 +40414 0.00042724609375 +40415 -0.044647216796875 +40416 0.003997802734375 +40417 0.103973388671875 +40418 0.006256103515625 +40419 0.202392578125 +40420 0.007568359375 +40421 0.264495849609375 +40422 0.009124755859375 +40423 0.338897705078125 +40424 0.0113525390625 +40425 0.443817138671875 +40426 0.013458251953125 +40427 0.545074462890625 +40428 0.014862060546875 +40429 0.6173095703125 +40430 0.015380859375 +40431 0.6524658203125 +40432 0.01531982421875 +40433 0.66339111328125 +40434 0.014862060546875 +40435 0.6561279296875 +40436 0.013427734375 +40437 0.606781005859375 +40438 0.01068115234375 +40439 0.501190185546875 +40440 0.006988525390625 +40441 0.352783203125 +40442 0.002685546875 +40443 0.176544189453125 +40444 -0.0023193359375 +40445 -0.034820556640625 +40446 -0.007476806640625 +40447 -0.258209228515625 +40448 -0.011383056640625 +40449 -0.44244384765625 +40450 -0.013946533203125 +40451 -0.5753173828125 +40452 -0.01495361328125 +40453 -0.65203857421875 +40454 -0.0126953125 +40455 -0.641632080078125 +40456 -0.008056640625 +40457 -0.562164306640625 +40458 -0.00341796875 +40459 -0.458038330078125 +40460 0.000213623046875 +40461 -0.350555419921875 +40462 0.00189208984375 +40463 -0.260528564453125 +40464 0.001617431640625 +40465 -0.192108154296875 +40466 -0.0001220703125 +40467 -0.141937255859375 +40468 -0.00262451171875 +40469 -0.1021728515625 +40470 -0.005096435546875 +40471 -0.062896728515625 +40472 -0.006591796875 +40473 -0.011932373046875 +40474 -0.0062255859375 +40475 0.062835693359375 +40476 -0.0045166015625 +40477 0.148712158203125 +40478 -0.0015869140625 +40479 0.241729736328125 +40480 0.0030517578125 +40481 0.34912109375 +40482 0.0086669921875 +40483 0.457305908203125 +40484 0.014007568359375 +40485 0.54388427734375 +40486 0.016998291015625 +40487 0.5728759765625 +40488 0.01544189453125 +40489 0.506591796875 +40490 0.009552001953125 +40491 0.351226806640625 +40492 0.001373291015625 +40493 0.146514892578125 +40494 -0.00634765625 +40495 -0.05523681640625 +40496 -0.011688232421875 +40497 -0.21624755859375 +40498 -0.014739990234375 +40499 -0.334930419921875 +40500 -0.01519775390625 +40501 -0.402984619140625 +40502 -0.01446533203125 +40503 -0.4412841796875 +40504 -0.0152587890625 +40505 -0.49578857421875 +40506 -0.017333984375 +40507 -0.5601806640625 +40508 -0.01885986328125 +40509 -0.600738525390625 +40510 -0.01800537109375 +40511 -0.584228515625 +40512 -0.012969970703125 +40513 -0.47930908203125 +40514 -0.003326416015625 +40515 -0.27935791015625 +40516 0.0096435546875 +40517 -0.0089111328125 +40518 0.02252197265625 +40519 0.268798828125 +40520 0.031494140625 +40521 0.482818603515625 +40522 0.03509521484375 +40523 0.60369873046875 +40524 0.0345458984375 +40525 0.650421142578125 +40526 0.0323486328125 +40527 0.66400146484375 +40528 0.028472900390625 +40529 0.6414794921875 +40530 0.0224609375 +40531 0.572540283203125 +40532 0.0167236328125 +40533 0.498138427734375 +40534 0.01251220703125 +40535 0.439453125 +40536 0.008697509765625 +40537 0.375518798828125 +40538 0.003509521484375 +40539 0.274505615234375 +40540 -0.004638671875 +40541 0.1087646484375 +40542 -0.01458740234375 +40543 -0.099395751953125 +40544 -0.024658203125 +40545 -0.3182373046875 +40546 -0.035064697265625 +40547 -0.5489501953125 +40548 -0.044921875 +40549 -0.7738037109375 +40550 -0.051422119140625 +40551 -0.86383056640625 +40552 -0.052886962890625 +40553 -0.870391845703125 +40554 -0.050445556640625 +40555 -0.86895751953125 +40556 -0.044952392578125 +40557 -0.861053466796875 +40558 -0.0355224609375 +40559 -0.765869140625 +40560 -0.021636962890625 +40561 -0.5301513671875 +40562 -0.00372314453125 +40563 -0.214691162109375 +40564 0.015777587890625 +40565 0.137359619140625 +40566 0.034027099609375 +40567 0.474822998046875 +40568 0.049102783203125 +40569 0.76239013671875 +40570 0.0595703125 +40571 0.867462158203125 +40572 0.065582275390625 +40573 0.870361328125 +40574 0.066558837890625 +40575 0.86480712890625 +40576 0.062957763671875 +40577 0.831817626953125 +40578 0.056304931640625 +40579 0.677581787109375 +40580 0.047027587890625 +40581 0.495880126953125 +40582 0.03631591796875 +40583 0.30767822265625 +40584 0.0244140625 +40585 0.116180419921875 +40586 0.00958251953125 +40587 -0.110748291015625 +40588 -0.00848388671875 +40589 -0.381805419921875 +40590 -0.027374267578125 +40591 -0.6572265625 +40592 -0.043731689453125 +40593 -0.857421875 +40594 -0.055206298828125 +40595 -0.870391845703125 +40596 -0.061492919921875 +40597 -0.870391845703125 +40598 -0.064208984375 +40599 -0.86444091796875 +40600 -0.06549072265625 +40601 -0.85723876953125 +40602 -0.064422607421875 +40603 -0.790008544921875 +40604 -0.05810546875 +40605 -0.62847900390625 +40606 -0.046417236328125 +40607 -0.3956298828125 +40608 -0.03131103515625 +40609 -0.126708984375 +40610 -0.014434814453125 +40611 0.150115966796875 +40612 0.00347900390625 +40613 0.424041748046875 +40614 0.020904541015625 +40615 0.670623779296875 +40616 0.03564453125 +40617 0.854522705078125 +40618 0.046722412109375 +40619 0.866485595703125 +40620 0.053314208984375 +40621 0.86920166015625 +40622 0.0565185546875 +40623 0.8653564453125 +40624 0.05712890625 +40625 0.857147216796875 +40626 0.05511474609375 +40627 0.766845703125 +40628 0.050872802734375 +40629 0.628509521484375 +40630 0.044097900390625 +40631 0.462127685546875 +40632 0.03631591796875 +40633 0.297210693359375 +40634 0.028289794921875 +40635 0.14862060546875 +40636 0.01885986328125 +40637 -0.00537109375 +40638 0.00848388671875 +40639 -0.15753173828125 +40640 -0.002960205078125 +40641 -0.31304931640625 +40642 -0.016204833984375 +40643 -0.48876953125 +40644 -0.02862548828125 +40645 -0.6416015625 +40646 -0.03887939453125 +40647 -0.751373291015625 +40648 -0.048309326171875 +40649 -0.84619140625 +40650 -0.056182861328125 +40651 -0.861297607421875 +40652 -0.060699462890625 +40653 -0.863250732421875 +40654 -0.0601806640625 +40655 -0.856597900390625 +40656 -0.055419921875 +40657 -0.7498779296875 +40658 -0.04974365234375 +40659 -0.624542236328125 +40660 -0.042022705078125 +40661 -0.47808837890625 +40662 -0.029052734375 +40663 -0.253387451171875 +40664 -0.013458251953125 +40665 0.003692626953125 +40666 0.000885009765625 +40667 0.2257080078125 +40668 0.014678955078125 +40669 0.427154541015625 +40670 0.029693603515625 +40671 0.643218994140625 +40672 0.04541015625 +40673 0.855926513671875 +40674 0.05865478515625 +40675 0.870361328125 +40676 0.06671142578125 +40677 0.870361328125 +40678 0.070068359375 +40679 0.862762451171875 +40680 0.068634033203125 +40681 0.79669189453125 +40682 0.06195068359375 +40683 0.595794677734375 +40684 0.0517578125 +40685 0.362152099609375 +40686 0.039703369140625 +40687 0.1270751953125 +40688 0.027008056640625 +40689 -0.086944580078125 +40690 0.01385498046875 +40691 -0.2784423828125 +40692 -0.001617431640625 +40693 -0.484832763671875 +40694 -0.020477294921875 +40695 -0.729583740234375 +40696 -0.0399169921875 +40697 -0.86688232421875 +40698 -0.056396484375 +40699 -0.870391845703125 +40700 -0.06964111328125 +40701 -0.86859130859375 +40702 -0.07958984375 +40703 -0.86279296875 +40704 -0.084381103515625 +40705 -0.817962646484375 +40706 -0.081207275390625 +40707 -0.6116943359375 +40708 -0.069488525390625 +40709 -0.3128662109375 +40710 -0.051361083984375 +40711 0.039398193359375 +40712 -0.0277099609375 +40713 0.422821044921875 +40714 -0.000640869140625 +40715 0.805145263671875 +40716 0.024688720703125 +40717 0.870361328125 +40718 0.044036865234375 +40719 0.870361328125 +40720 0.057037353515625 +40721 0.860015869140625 +40722 0.0635986328125 +40723 0.727935791015625 +40724 0.06365966796875 +40725 0.48114013671875 +40726 0.05963134765625 +40727 0.2059326171875 +40728 0.053680419921875 +40729 -0.06103515625 +40730 0.04669189453125 +40731 -0.29913330078125 +40732 0.03729248046875 +40733 -0.516204833984375 +40734 0.02392578125 +40735 -0.7252197265625 +40736 0.00848388671875 +40737 -0.85980224609375 +40738 -0.00640869140625 +40739 -0.870391845703125 +40740 -0.0185546875 +40741 -0.870391845703125 +40742 -0.024169921875 +40743 -0.858062744140625 +40744 -0.023345947265625 +40745 -0.673004150390625 +40746 -0.021148681640625 +40747 -0.42694091796875 +40748 -0.0218505859375 +40749 -0.2100830078125 +40750 -0.02557373046875 +40751 -0.0362548828125 +40752 -0.029998779296875 +40753 0.10943603515625 +40754 -0.033447265625 +40755 0.23516845703125 +40756 -0.0323486328125 +40757 0.373687744140625 +40758 -0.02685546875 +40759 0.517791748046875 +40760 -0.022369384765625 +40761 0.602783203125 +40762 -0.01824951171875 +40763 0.635711669921875 +40764 -0.01129150390625 +40765 0.655181884765625 +40766 -0.00201416015625 +40767 0.65948486328125 +40768 0.009185791015625 +40769 0.651275634765625 +40770 0.020477294921875 +40771 0.61846923828125 +40772 0.0289306640625 +40773 0.53753662109375 +40774 0.033294677734375 +40775 0.404144287109375 +40776 0.03302001953125 +40777 0.22186279296875 +40778 0.0284423828125 +40779 0.003997802734375 +40780 0.021331787109375 +40781 -0.22100830078125 +40782 0.013519287109375 +40783 -0.42449951171875 +40784 0.00689697265625 +40785 -0.579833984375 +40786 0.005126953125 +40787 -0.641876220703125 +40788 0.0074462890625 +40789 -0.6177978515625 +40790 0.00799560546875 +40791 -0.575531005859375 +40792 0.00604248046875 +40793 -0.526336669921875 +40794 0.005859375 +40795 -0.42645263671875 +40796 0.009552001953125 +40797 -0.2581787109375 +40798 0.013641357421875 +40799 -0.068695068359375 +40800 0.014495849609375 +40801 0.09222412109375 +40802 0.013519287109375 +40803 0.232147216796875 +40804 0.011444091796875 +40805 0.3509521484375 +40806 0.00555419921875 +40807 0.410064697265625 +40808 -0.00677490234375 +40809 0.372955322265625 +40810 -0.023712158203125 +40811 0.2554931640625 +40812 -0.040618896484375 +40813 0.10711669921875 +40814 -0.055633544921875 +40815 -0.052886962890625 +40816 -0.065460205078125 +40817 -0.186279296875 +40818 -0.06500244140625 +40819 -0.23291015625 +40820 -0.0560302734375 +40821 -0.209442138671875 +40822 -0.04412841796875 +40823 -0.174163818359375 +40824 -0.029815673828125 +40825 -0.126739501953125 +40826 -0.01202392578125 +40827 -0.048126220703125 +40828 0.0069580078125 +40829 0.0426025390625 +40830 0.023162841796875 +40831 0.10748291015625 +40832 0.0355224609375 +40833 0.1409912109375 +40834 0.04827880859375 +40835 0.19708251953125 +40836 0.0609130859375 +40837 0.273651123046875 +40838 0.068511962890625 +40839 0.31768798828125 +40840 0.071990966796875 +40841 0.341094970703125 +40842 0.073455810546875 +40843 0.368011474609375 +40844 0.07073974609375 +40845 0.37249755859375 +40846 0.059356689453125 +40847 0.30072021484375 +40848 0.039520263671875 +40849 0.1517333984375 +40850 0.01690673828125 +40851 -0.01470947265625 +40852 -0.007080078125 +40853 -0.1883544921875 +40854 -0.032257080078125 +40855 -0.372711181640625 +40856 -0.053375244140625 +40857 -0.51397705078125 +40858 -0.06640625 +40859 -0.57177734375 +40860 -0.07037353515625 +40861 -0.53948974609375 +40862 -0.0665283203125 +40863 -0.43511962890625 +40864 -0.05792236328125 +40865 -0.2962646484375 +40866 -0.047760009765625 +40867 -0.161102294921875 +40868 -0.0372314453125 +40869 -0.0435791015625 +40870 -0.026031494140625 +40871 0.060394287109375 +40872 -0.01556396484375 +40873 0.13665771484375 +40874 -0.007415771484375 +40875 0.170135498046875 +40876 -0.00152587890625 +40877 0.16552734375 +40878 0.0047607421875 +40879 0.15728759765625 +40880 0.011505126953125 +40881 0.150787353515625 +40882 0.016143798828125 +40883 0.12200927734375 +40884 0.01910400390625 +40885 0.080108642578125 +40886 0.022369384765625 +40887 0.05126953125 +40888 0.028045654296875 +40889 0.062896728515625 +40890 0.033966064453125 +40891 0.09271240234375 +40892 0.035797119140625 +40893 0.092987060546875 +40894 0.0347900390625 +40895 0.07855224609375 +40896 0.032257080078125 +40897 0.06427001953125 +40898 0.0269775390625 +40899 0.0347900390625 +40900 0.018951416015625 +40901 -0.01171875 +40902 0.010162353515625 +40903 -0.056060791015625 +40904 0.004638671875 +40905 -0.055511474609375 +40906 0.002655029296875 +40907 -0.010467529296875 +40908 -0.000152587890625 +40909 0.02508544921875 +40910 -0.005706787109375 +40911 0.025665283203125 +40912 -0.01141357421875 +40913 0.017333984375 +40914 -0.016876220703125 +40915 0.00189208984375 +40916 -0.022857666015625 +40917 -0.03173828125 +40918 -0.028167724609375 +40919 -0.071502685546875 +40920 -0.034332275390625 +40921 -0.13543701171875 +40922 -0.041015625 +40923 -0.219970703125 +40924 -0.046142578125 +40925 -0.300506591796875 +40926 -0.0498046875 +40927 -0.376312255859375 +40928 -0.0494384765625 +40929 -0.416107177734375 +40930 -0.041015625 +40931 -0.371124267578125 +40932 -0.024871826171875 +40933 -0.242279052734375 +40934 -0.00482177734375 +40935 -0.069732666015625 +40936 0.01702880859375 +40937 0.125640869140625 +40938 0.037689208984375 +40939 0.31268310546875 +40940 0.0537109375 +40941 0.45501708984375 +40942 0.06512451171875 +40943 0.554779052734375 +40944 0.07171630859375 +40945 0.61065673828125 +40946 0.072357177734375 +40947 0.610931396484375 +40948 0.06494140625 +40949 0.531463623046875 +40950 0.05096435546875 +40951 0.3883056640625 +40952 0.03521728515625 +40953 0.23468017578125 +40954 0.02001953125 +40955 0.095245361328125 +40956 0.0078125 +40957 -0.00396728515625 +40958 3.0517578125e-05 +40959 -0.04852294921875 +40960 -0.004302978515625 +40961 -0.055145263671875 +40962 -0.009674072265625 +40963 -0.0758056640625 +40964 -0.018646240234375 +40965 -0.138702392578125 +40966 -0.027740478515625 +40967 -0.209197998046875 +40968 -0.037139892578125 +40969 -0.289031982421875 +40970 -0.04693603515625 +40971 -0.37884521484375 +40972 -0.054931640625 +40973 -0.456329345703125 +40974 -0.060638427734375 +40975 -0.51641845703125 +40976 -0.060150146484375 +40977 -0.519287109375 +40978 -0.0528564453125 +40979 -0.458251953125 +40980 -0.043975830078125 +40981 -0.384796142578125 +40982 -0.036102294921875 +40983 -0.323699951171875 +40984 -0.028717041015625 +40985 -0.269287109375 +40986 -0.019317626953125 +40987 -0.1951904296875 +40988 -0.00787353515625 +40989 -0.100006103515625 +40990 0.0028076171875 +40991 -0.01055908203125 +40992 0.015625 +40993 0.1033935546875 +40994 0.03125 +40995 0.24908447265625 +40996 0.044342041015625 +40997 0.373199462890625 +40998 0.0531005859375 +40999 0.45806884765625 +41000 0.05828857421875 +41001 0.511474609375 +41002 0.063140869140625 +41003 0.565399169921875 +41004 0.06683349609375 +41005 0.61138916015625 +41006 0.0634765625 +41007 0.5897216796875 +41008 0.052154541015625 +41009 0.4906005859375 +41010 0.034698486328125 +41011 0.33148193359375 +41012 0.0147705078125 +41013 0.147796630859375 +41014 -0.00335693359375 +41015 -0.01873779296875 +41016 -0.016845703125 +41017 -0.140289306640625 +41018 -0.02313232421875 +41019 -0.191986083984375 +41020 -0.023223876953125 +41021 -0.184295654296875 +41022 -0.021514892578125 +41023 -0.161834716796875 +41024 -0.022216796875 +41025 -0.166595458984375 +41026 -0.02484130859375 +41027 -0.19390869140625 +41028 -0.0274658203125 +41029 -0.22442626953125 +41030 -0.03228759765625 +41031 -0.279754638671875 +41032 -0.037261962890625 +41033 -0.3389892578125 +41034 -0.03765869140625 +41035 -0.3543701171875 +41036 -0.035797119140625 +41037 -0.348175048828125 +41038 -0.032318115234375 +41039 -0.32598876953125 +41040 -0.0242919921875 +41041 -0.2581787109375 +41042 -0.01129150390625 +41043 -0.139801025390625 +41044 0.005126953125 +41045 0.014617919921875 +41046 0.018829345703125 +41047 0.144378662109375 +41048 0.026947021484375 +41049 0.221038818359375 +41050 0.032073974609375 +41051 0.27069091796875 +41052 0.034271240234375 +41053 0.294036865234375 +41054 0.03564453125 +41055 0.311767578125 +41056 0.037811279296875 +41057 0.339141845703125 +41058 0.03948974609375 +41059 0.360260009765625 +41060 0.0391845703125 +41061 0.360504150390625 +41062 0.03302001953125 +41063 0.308380126953125 +41064 0.018218994140625 +41065 0.18170166015625 +41066 -0.002288818359375 +41067 0.0047607421875 +41068 -0.02301025390625 +41069 -0.17559814453125 +41070 -0.038604736328125 +41071 -0.3143310546875 +41072 -0.043975830078125 +41073 -0.36785888671875 +41074 -0.042327880859375 +41075 -0.36248779296875 +41076 -0.039154052734375 +41077 -0.343536376953125 +41078 -0.033416748046875 +41079 -0.3018798828125 +41080 -0.0244140625 +41081 -0.231414794921875 +41082 -0.01043701171875 +41083 -0.117645263671875 +41084 0.004608154296875 +41085 0.007049560546875 +41086 0.01416015625 +41087 0.087982177734375 +41088 0.01995849609375 +41089 0.13946533203125 +41090 0.023590087890625 +41091 0.17425537109375 +41092 0.02459716796875 +41093 0.188201904296875 +41094 0.02178955078125 +41095 0.171234130859375 +41096 0.0146484375 +41097 0.118438720703125 +41098 0.00653076171875 +41099 0.05706787109375 +41100 -0.00225830078125 +41101 -0.010711669921875 +41102 -0.012481689453125 +41103 -0.0914306640625 +41104 -0.021392822265625 +41105 -0.162322998046875 +41106 -0.025543212890625 +41107 -0.194549560546875 +41108 -0.020233154296875 +41109 -0.1492919921875 +41110 -0.0048828125 +41111 -0.02166748046875 +41112 0.01275634765625 +41113 0.124053955078125 +41114 0.0234375 +41115 0.211151123046875 +41116 0.027252197265625 +41117 0.240447998046875 +41118 0.02783203125 +41119 0.242218017578125 +41120 0.026275634765625 +41121 0.2257080078125 +41122 0.022979736328125 +41123 0.194366455078125 +41124 0.01397705078125 +41125 0.115509033203125 +41126 0.00213623046875 +41127 0.0128173828125 +41128 -0.00537109375 +41129 -0.053802490234375 +41130 -0.011749267578125 +41131 -0.110626220703125 +41132 -0.02203369140625 +41133 -0.199493408203125 +41134 -0.03314208984375 +41135 -0.29437255859375 +41136 -0.037506103515625 +41137 -0.33221435546875 +41138 -0.031158447265625 +41139 -0.27972412109375 +41140 -0.0198974609375 +41141 -0.185333251953125 +41142 -0.013214111328125 +41143 -0.128204345703125 +41144 -0.011962890625 +41145 -0.115692138671875 +41146 -0.01239013671875 +41147 -0.116455078125 +41148 -0.011505126953125 +41149 -0.105926513671875 +41150 -0.00567626953125 +41151 -0.053955078125 +41152 0.0062255859375 +41153 0.048797607421875 +41154 0.018798828125 +41155 0.157318115234375 +41156 0.02490234375 +41157 0.212005615234375 +41158 0.0252685546875 +41159 0.218475341796875 +41160 0.027191162109375 +41161 0.23724365234375 +41162 0.035125732421875 +41163 0.30535888671875 +41164 0.044097900390625 +41165 0.38128662109375 +41166 0.046783447265625 +41167 0.404449462890625 +41168 0.045562744140625 +41169 0.3944091796875 +41170 0.044952392578125 +41171 0.3885498046875 +41172 0.042022705078125 +41173 0.362640380859375 +41174 0.0316162109375 +41175 0.27362060546875 +41176 0.01318359375 +41177 0.11712646484375 +41178 -0.007049560546875 +41179 -0.054901123046875 +41180 -0.022918701171875 +41181 -0.19085693359375 +41182 -0.033843994140625 +41183 -0.28570556640625 +41184 -0.039825439453125 +41185 -0.339263916015625 +41186 -0.04400634765625 +41187 -0.3775634765625 +41188 -0.05181884765625 +41189 -0.445709228515625 +41190 -0.062255859375 +41191 -0.535064697265625 +41192 -0.073333740234375 +41193 -0.629058837890625 +41194 -0.0814208984375 +41195 -0.697601318359375 +41196 -0.082122802734375 +41197 -0.70391845703125 +41198 -0.074798583984375 +41199 -0.6424560546875 +41200 -0.05682373046875 +41201 -0.491241455078125 +41202 -0.029998779296875 +41203 -0.265716552734375 +41204 -0.00128173828125 +41205 -0.023712158203125 +41206 0.025360107421875 +41207 0.201751708984375 +41208 0.045745849609375 +41209 0.375823974609375 +41210 0.058349609375 +41211 0.485076904296875 +41212 0.06787109375 +41213 0.56884765625 +41214 0.075286865234375 +41215 0.634765625 +41216 0.07470703125 +41217 0.63763427734375 +41218 0.064056396484375 +41219 0.5660400390625 +41220 0.0506591796875 +41221 0.4720458984375 +41222 0.04241943359375 +41223 0.40692138671875 +41224 0.04046630859375 +41225 0.3778076171875 +41226 0.043548583984375 +41227 0.376953125 +41228 0.046630859375 +41229 0.371978759765625 +41230 0.0419921875 +41231 0.313140869140625 +41232 0.026947021484375 +41233 0.184417724609375 +41234 0.005126953125 +41235 0.011199951171875 +41236 -0.01824951171875 +41237 -0.171051025390625 +41238 -0.039642333984375 +41239 -0.33740234375 +41240 -0.056854248046875 +41241 -0.47198486328125 +41242 -0.06787109375 +41243 -0.560394287109375 +41244 -0.0694580078125 +41245 -0.58056640625 +41246 -0.06396484375 +41247 -0.54754638671875 +41248 -0.058624267578125 +41249 -0.508575439453125 +41250 -0.052703857421875 +41251 -0.459503173828125 +41252 -0.045196533203125 +41253 -0.394378662109375 +41254 -0.041900634765625 +41255 -0.35260009765625 +41256 -0.039276123046875 +41257 -0.31170654296875 +41258 -0.02581787109375 +41259 -0.197418212890625 +41260 -0.001007080078125 +41261 -0.007965087890625 +41262 0.02783203125 +41263 0.207489013671875 +41264 0.054901123046875 +41265 0.409210205078125 +41266 0.0765380859375 +41267 0.57208251953125 +41268 0.088348388671875 +41269 0.66595458984375 +41270 0.0855712890625 +41271 0.65875244140625 +41272 0.07086181640625 +41273 0.56744384765625 +41274 0.05023193359375 +41275 0.431396484375 +41276 0.030303955078125 +41277 0.29443359375 +41278 0.014923095703125 +41279 0.182464599609375 +41280 -0.00079345703125 +41281 0.06365966796875 +41282 -0.019134521484375 +41283 -0.075958251953125 +41284 -0.03314208984375 +41285 -0.189422607421875 +41286 -0.042266845703125 +41287 -0.271942138671875 +41288 -0.049591064453125 +41289 -0.342529296875 +41290 -0.049713134765625 +41291 -0.364166259765625 +41292 -0.04132080078125 +41293 -0.327239990234375 +41294 -0.03143310546875 +41295 -0.2769775390625 +41296 -0.026275634765625 +41297 -0.253692626953125 +41298 -0.0238037109375 +41299 -0.24365234375 +41300 -0.016693115234375 +41301 -0.1983642578125 +41302 -0.00469970703125 +41303 -0.116241455078125 +41304 0.00616455078125 +41305 -0.036834716796875 +41306 0.0152587890625 +41307 0.034881591796875 +41308 0.02154541015625 +41309 0.09124755859375 +41310 0.021575927734375 +41311 0.10888671875 +41312 0.021270751953125 +41313 0.125518798828125 +41314 0.0233154296875 +41315 0.15771484375 +41316 0.023712158203125 +41317 0.17828369140625 +41318 0.0201416015625 +41319 0.17108154296875 +41320 0.011810302734375 +41321 0.129974365234375 +41322 0.00299072265625 +41323 0.082427978515625 +41324 -0.00628662109375 +41325 0.027679443359375 +41326 -0.020782470703125 +41327 -0.065643310546875 +41328 -0.034698486328125 +41329 -0.15936279296875 +41330 -0.04193115234375 +41331 -0.21307373046875 +41332 -0.04376220703125 +41333 -0.234649658203125 +41334 -0.036651611328125 +41335 -0.2001953125 +41336 -0.02215576171875 +41337 -0.119171142578125 +41338 -0.00543212890625 +41339 -0.024749755859375 +41340 0.01373291015625 +41341 0.085784912109375 +41342 0.029998779296875 +41343 0.178131103515625 +41344 0.037689208984375 +41345 0.215576171875 +41346 0.038726806640625 +41347 0.211456298828125 +41348 0.034515380859375 +41349 0.17523193359375 +41350 0.0283203125 +41351 0.128753662109375 +41352 0.024627685546875 +41353 0.1019287109375 +41354 0.02032470703125 +41355 0.0743408203125 +41356 0.0150146484375 +41357 0.04327392578125 +41358 0.01318359375 +41359 0.038177490234375 +41360 0.017547607421875 +41361 0.076263427734375 +41362 0.025665283203125 +41363 0.14105224609375 +41364 0.0306396484375 +41365 0.186431884765625 +41366 0.02899169921875 +41367 0.188812255859375 +41368 0.01947021484375 +41369 0.1390380859375 +41370 0.00286865234375 +41371 0.041778564453125 +41372 -0.01708984375 +41373 -0.079437255859375 +41374 -0.03955078125 +41375 -0.219390869140625 +41376 -0.062896728515625 +41377 -0.367828369140625 +41378 -0.08251953125 +41379 -0.494873046875 +41380 -0.091705322265625 +41381 -0.556243896484375 +41382 -0.083953857421875 +41383 -0.508697509765625 +41384 -0.062835693359375 +41385 -0.3756103515625 +41386 -0.037841796875 +41387 -0.218902587890625 +41388 -0.012847900390625 +41389 -0.063751220703125 +41390 0.01226806640625 +41391 0.091552734375 +41392 0.0357666015625 +41393 0.23602294921875 +41394 0.05352783203125 +41395 0.342987060546875 +41396 0.062835693359375 +41397 0.39520263671875 +41398 0.063140869140625 +41399 0.389373779296875 +41400 0.054168701171875 +41401 0.324249267578125 +41402 0.039581298828125 +41403 0.224090576171875 +41404 0.024749755859375 +41405 0.124267578125 +41406 0.011505126953125 +41407 0.037078857421875 +41408 0.0040283203125 +41409 -0.010101318359375 +41410 0.00201416015625 +41411 -0.019439697265625 +41412 0.000640869140625 +41413 -0.022796630859375 +41414 0.0028076171875 +41415 -0.001556396484375 +41416 0.0103759765625 +41417 0.056304931640625 +41418 0.016754150390625 +41419 0.106719970703125 +41420 0.01397705078125 +41421 0.096893310546875 +41422 0.0045166015625 +41423 0.042694091796875 +41424 -0.005767822265625 +41425 -0.018035888671875 +41426 -0.015380859375 +41427 -0.07586669921875 +41428 -0.022552490234375 +41429 -0.11944580078125 +41430 -0.0289306640625 +41431 -0.15972900390625 +41432 -0.035430908203125 +41433 -0.202606201171875 +41434 -0.042083740234375 +41435 -0.24859619140625 +41436 -0.050079345703125 +41437 -0.30517578125 +41438 -0.057891845703125 +41439 -0.36212158203125 +41440 -0.06134033203125 +41441 -0.39141845703125 +41442 -0.05474853515625 +41443 -0.35528564453125 +41444 -0.037628173828125 +41445 -0.249969482421875 +41446 -0.012664794921875 +41447 -0.092864990234375 +41448 0.015960693359375 +41449 0.08905029296875 +41450 0.03900146484375 +41451 0.2352294921875 +41452 0.05230712890625 +41453 0.318817138671875 +41454 0.058746337890625 +41455 0.358642578125 +41456 0.057220458984375 +41457 0.347747802734375 +41458 0.04766845703125 +41459 0.28564453125 +41460 0.037841796875 +41461 0.223175048828125 +41462 0.033294677734375 +41463 0.196746826171875 +41464 0.030029296875 +41465 0.179840087890625 +41466 0.025482177734375 +41467 0.155548095703125 +41468 0.023895263671875 +41469 0.151214599609375 +41470 0.0238037109375 +41471 0.156951904296875 +41472 0.018890380859375 +41473 0.13177490234375 +41474 0.013458251953125 +41475 0.100799560546875 +41476 0.011260986328125 +41477 0.087127685546875 +41478 0.005828857421875 +41479 0.05487060546875 +41480 -0.005126953125 +41481 -0.009002685546875 +41482 -0.021514892578125 +41483 -0.10400390625 +41484 -0.043243408203125 +41485 -0.229400634765625 +41486 -0.064910888671875 +41487 -0.35552978515625 +41488 -0.07916259765625 +41489 -0.441925048828125 +41490 -0.083404541015625 +41491 -0.473846435546875 +41492 -0.080230712890625 +41493 -0.464813232421875 +41494 -0.070526123046875 +41495 -0.419097900390625 +41496 -0.053924560546875 +41497 -0.334320068359375 +41498 -0.033721923828125 +41499 -0.227935791015625 +41500 -0.0142822265625 +41501 -0.12347412109375 +41502 0.00311279296875 +41503 -0.02764892578125 +41504 0.021820068359375 +41505 0.077667236328125 +41506 0.045684814453125 +41507 0.2132568359375 +41508 0.076568603515625 +41509 0.38885498046875 +41510 0.110565185546875 +41511 0.582794189453125 +41512 0.136566162109375 +41513 0.734039306640625 +41514 0.1468505859375 +41515 0.800140380859375 +41516 0.1409912109375 +41517 0.7783203125 +41518 0.118499755859375 +41519 0.6651611328125 +41520 0.07928466796875 +41521 0.45965576171875 +41522 0.03033447265625 +41523 0.199188232421875 +41524 -0.0162353515625 +41525 -0.050689697265625 +41526 -0.049957275390625 +41527 -0.23297119140625 +41528 -0.067626953125 +41529 -0.33013916015625 +41530 -0.074066162109375 +41531 -0.368408203125 +41532 -0.075042724609375 +41533 -0.378936767578125 +41534 -0.073486328125 +41535 -0.376983642578125 +41536 -0.072601318359375 +41537 -0.37969970703125 +41538 -0.0732421875 +41539 -0.391510009765625 +41540 -0.070526123046875 +41541 -0.385345458984375 +41542 -0.06097412109375 +41543 -0.3419189453125 +41544 -0.048675537109375 +41545 -0.28289794921875 +41546 -0.04168701171875 +41547 -0.251617431640625 +41548 -0.04339599609375 +41549 -0.266143798828125 +41550 -0.0440673828125 +41551 -0.273345947265625 +41552 -0.0333251953125 +41553 -0.216796875 +41554 -0.01702880859375 +41555 -0.128265380859375 +41556 -0.006256103515625 +41557 -0.068145751953125 +41558 -0.002227783203125 +41559 -0.0430908203125 +41560 0.000335693359375 +41561 -0.024444580078125 +41562 0.007568359375 +41563 0.020721435546875 +41564 0.025390625 +41565 0.124481201171875 +41566 0.048553466796875 +41567 0.25787353515625 +41568 0.0694580078125 +41569 0.379119873046875 +41570 0.086669921875 +41571 0.47991943359375 +41572 0.094329833984375 +41573 0.5281982421875 +41574 0.09014892578125 +41575 0.511138916015625 +41576 0.079254150390625 +41577 0.456207275390625 +41578 0.069793701171875 +41579 0.407470703125 +41580 0.065216064453125 +41581 0.383758544921875 +41582 0.060333251953125 +41583 0.35687255859375 +41584 0.052398681640625 +41585 0.31182861328125 +41586 0.041778564453125 +41587 0.250885009765625 +41588 0.026885986328125 +41589 0.1654052734375 +41590 0.00396728515625 +41591 0.035247802734375 +41592 -0.027496337890625 +41593 -0.142059326171875 +41594 -0.0618896484375 +41595 -0.33563232421875 +41596 -0.097259521484375 +41597 -0.5345458984375 +41598 -0.13055419921875 +41599 -0.72186279296875 +41600 -0.150604248046875 +41601 -0.836669921875 +41602 -0.148956298828125 +41603 -0.8326416015625 +41604 -0.12933349609375 +41605 -0.7296142578125 +41606 -0.101898193359375 +41607 -0.582550048828125 +41608 -0.075592041015625 +41609 -0.440093994140625 +41610 -0.054473876953125 +41611 -0.324310302734375 +41612 -0.03228759765625 +41613 -0.20147705078125 +41614 -0.004058837890625 +41615 -0.044647216796875 +41616 0.022491455078125 +41617 0.103973388671875 +41618 0.039642333984375 +41619 0.202392578125 +41620 0.050018310546875 +41621 0.264495849609375 +41622 0.0626220703125 +41623 0.338897705078125 +41624 0.080841064453125 +41625 0.443817138671875 +41626 0.09844970703125 +41627 0.545074462890625 +41628 0.11083984375 +41629 0.6173095703125 +41630 0.1165771484375 +41631 0.6524658203125 +41632 0.1180419921875 +41633 0.66339111328125 +41634 0.11639404296875 +41635 0.6561279296875 +41636 0.107208251953125 +41637 0.606781005859375 +41638 0.087890625 +41639 0.501190185546875 +41640 0.0609130859375 +41641 0.352783203125 +41642 0.029022216796875 +41643 0.176544189453125 +41644 -0.009124755859375 +41645 -0.034820556640625 +41646 -0.049285888671875 +41647 -0.258209228515625 +41648 -0.082122802734375 +41649 -0.44244384765625 +41650 -0.105438232421875 +41651 -0.5753173828125 +41652 -0.118438720703125 +41653 -0.65203857421875 +41654 -0.115478515625 +41655 -0.641632080078125 +41656 -0.0999755859375 +41657 -0.562164306640625 +41658 -0.08013916015625 +41659 -0.458038330078125 +41660 -0.059906005859375 +41661 -0.350555419921875 +41662 -0.043121337890625 +41663 -0.260528564453125 +41664 -0.030548095703125 +41665 -0.192108154296875 +41666 -0.021575927734375 +41667 -0.141937255859375 +41668 -0.01470947265625 +41669 -0.1021728515625 +41670 -0.00811767578125 +41671 -0.062896728515625 +41672 0.000457763671875 +41673 -0.011932373046875 +41674 0.0133056640625 +41675 0.062835693359375 +41676 0.02813720703125 +41677 0.148712158203125 +41678 0.044281005859375 +41679 0.241729736328125 +41680 0.063079833984375 +41681 0.34912109375 +41682 0.082122802734375 +41683 0.457305908203125 +41684 0.097320556640625 +41685 0.54388427734375 +41686 0.10211181640625 +41687 0.5728759765625 +41688 0.089569091796875 +41689 0.506591796875 +41690 0.06085205078125 +41691 0.351226806640625 +41692 0.02325439453125 +41693 0.146514892578125 +41694 -0.013580322265625 +41695 -0.05523681640625 +41696 -0.042724609375 +41697 -0.21624755859375 +41698 -0.06390380859375 +41699 -0.334930419921875 +41700 -0.07562255859375 +41701 -0.402984619140625 +41702 -0.081787109375 +41703 -0.4412841796875 +41704 -0.09088134765625 +41705 -0.49578857421875 +41706 -0.101806640625 +41707 -0.5601806640625 +41708 -0.1083984375 +41709 -0.600738525390625 +41710 -0.1046142578125 +41711 -0.584228515625 +41712 -0.084747314453125 +41713 -0.47930908203125 +41714 -0.047576904296875 +41715 -0.27935791015625 +41716 0.0023193359375 +41717 -0.0089111328125 +41718 0.053314208984375 +41719 0.268798828125 +41720 0.09234619140625 +41721 0.482818603515625 +41722 0.114044189453125 +41723 0.60369873046875 +41724 0.121917724609375 +41725 0.650421142578125 +41726 0.12359619140625 +41727 0.66400146484375 +41728 0.11834716796875 +41729 0.6414794921875 +41730 0.104400634765625 +41731 0.572540283203125 +41732 0.09051513671875 +41733 0.498138427734375 +41734 0.08099365234375 +41735 0.439453125 +41736 0.071044921875 +41737 0.375518798828125 +41738 0.05352783203125 +41739 0.274505615234375 +41740 0.022186279296875 +41741 0.1087646484375 +41742 -0.018402099609375 +41743 -0.099395751953125 +41744 -0.061614990234375 +41745 -0.3182373046875 +41746 -0.107940673828125 +41747 -0.5489501953125 +41748 -0.1536865234375 +41749 -0.7738037109375 +41750 -0.187530517578125 +41751 -0.86383056640625 +41752 -0.202362060546875 +41753 -0.870391845703125 +41754 -0.20208740234375 +41755 -0.86895751953125 +41756 -0.189483642578125 +41757 -0.861053466796875 +41758 -0.1607666015625 +41759 -0.765869140625 +41760 -0.1134033203125 +41761 -0.5301513671875 +41762 -0.04876708984375 +41763 -0.214691162109375 +41764 0.02398681640625 +41765 0.137359619140625 +41766 0.093994140625 +41767 0.474822998046875 +41768 0.15374755859375 +41769 0.76239013671875 +41770 0.197662353515625 +41771 0.867462158203125 +41772 0.225982666015625 +41773 0.870361328125 +41774 0.236358642578125 +41775 0.86480712890625 +41776 0.230072021484375 +41777 0.831817626953125 +41778 0.212493896484375 +41779 0.677581787109375 +41780 0.184906005859375 +41781 0.495880126953125 +41782 0.1513671875 +41783 0.30767822265625 +41784 0.1123046875 +41785 0.116180419921875 +41786 0.060760498046875 +41787 -0.110748291015625 +41788 -0.00482177734375 +41789 -0.381805419921875 +41790 -0.075347900390625 +41791 -0.6572265625 +41792 -0.138031005859375 +41793 -0.857421875 +41794 -0.18377685546875 +41795 -0.870391845703125 +41796 -0.211212158203125 +41797 -0.870391845703125 +41798 -0.226318359375 +41799 -0.86444091796875 +41800 -0.2369384765625 +41801 -0.85723876953125 +41802 -0.239227294921875 +41803 -0.790008544921875 +41804 -0.2215576171875 +41805 -0.62847900390625 +41806 -0.183258056640625 +41807 -0.3956298828125 +41808 -0.1314697265625 +41809 -0.126708984375 +41810 -0.072113037109375 +41811 0.150115966796875 +41812 -0.00762939453125 +41813 0.424041748046875 +41814 0.056182861328125 +41815 0.670623779296875 +41816 0.111083984375 +41817 0.854522705078125 +41818 0.15338134765625 +41819 0.866485595703125 +41820 0.17987060546875 +41821 0.86920166015625 +41822 0.19464111328125 +41823 0.8653564453125 +41824 0.200714111328125 +41825 0.857147216796875 +41826 0.19757080078125 +41827 0.766845703125 +41828 0.18646240234375 +41829 0.628509521484375 +41830 0.165985107421875 +41831 0.462127685546875 +41832 0.141754150390625 +41833 0.297210693359375 +41834 0.116455078125 +41835 0.14862060546875 +41836 0.085174560546875 +41837 -0.00537109375 +41838 0.049530029296875 +41839 -0.15753173828125 +41840 0.0086669921875 +41841 -0.31304931640625 +41842 -0.040496826171875 +41843 -0.48876953125 +41844 -0.087921142578125 +41845 -0.6416015625 +41846 -0.12835693359375 +41847 -0.751373291015625 +41848 -0.16693115234375 +41849 -0.84619140625 +41850 -0.2005615234375 +41851 -0.861297607421875 +41852 -0.22216796875 +41853 -0.863250732421875 +41854 -0.22503662109375 +41855 -0.856597900390625 +41856 -0.211883544921875 +41857 -0.7498779296875 +41858 -0.195281982421875 +41859 -0.624542236328125 +41860 -0.170501708984375 +41861 -0.47808837890625 +41862 -0.124908447265625 +41863 -0.253387451171875 +41864 -0.068389892578125 +41865 0.003692626953125 +41866 -0.015655517578125 +41867 0.2257080078125 +41868 0.0360107421875 +41869 0.427154541015625 +41870 0.093658447265625 +41871 0.643218994140625 +41872 0.1552734375 +41873 0.855926513671875 +41874 0.20843505859375 +41875 0.870361328125 +41876 0.24249267578125 +41877 0.870361328125 +41878 0.25909423828125 +41879 0.862762451171875 +41880 0.257720947265625 +41881 0.79669189453125 +41882 0.236419677734375 +41883 0.595794677734375 +41884 0.2015380859375 +41885 0.362152099609375 +41886 0.1591796875 +41887 0.1270751953125 +41888 0.11395263671875 +41889 -0.086944580078125 +41890 0.066314697265625 +41891 -0.2784423828125 +41892 0.008758544921875 +41893 -0.484832763671875 +41894 -0.0628662109375 +41895 -0.729583740234375 +41896 -0.137664794921875 +41897 -0.86688232421875 +41898 -0.201995849609375 +41899 -0.870391845703125 +41900 -0.254852294921875 +41901 -0.86859130859375 +41902 -0.295867919921875 +41903 -0.86279296875 +41904 -0.317352294921875 +41905 -0.817962646484375 +41906 -0.3095703125 +41907 -0.6116943359375 +41908 -0.27105712890625 +41909 -0.3128662109375 +41910 -0.209136962890625 +41911 0.039398193359375 +41912 -0.128204345703125 +41913 0.422821044921875 +41914 -0.035491943359375 +41915 0.805145263671875 +41916 0.054229736328125 +41917 0.870361328125 +41918 0.128662109375 +41919 0.870361328125 +41920 0.18524169921875 +41921 0.860015869140625 +41922 0.222320556640625 +41923 0.727935791015625 +41924 0.238677978515625 +41925 0.48114013671875 +41926 0.239532470703125 +41927 0.2059326171875 +41928 0.22979736328125 +41929 -0.06103515625 +41930 0.211669921875 +41931 -0.29913330078125 +41932 0.18206787109375 +41933 -0.516204833984375 +41934 0.137725830078125 +41935 -0.7252197265625 +41936 0.0841064453125 +41937 -0.85980224609375 +41938 0.028656005859375 +41939 -0.870391845703125 +41940 -0.0220947265625 +41941 -0.870391845703125 +41942 -0.05755615234375 +41943 -0.858062744140625 +41944 -0.07672119140625 +41945 -0.673004150390625 +41946 -0.090850830078125 +41947 -0.42694091796875 +41948 -0.109405517578125 +41949 -0.2100830078125 +41950 -0.131866455078125 +41951 -0.0362548828125 +41952 -0.151885986328125 +41953 0.10943603515625 +41954 -0.165130615234375 +41955 0.23516845703125 +41956 -0.16265869140625 +41957 0.373687744140625 +41958 -0.1448974609375 +41959 0.517791748046875 +41960 -0.125457763671875 +41961 0.602783203125 +41962 -0.10333251953125 +41963 0.635711669921875 +41964 -0.0714111328125 +41965 0.655181884765625 +41966 -0.031951904296875 +41967 0.65948486328125 +41968 0.01318359375 +41969 0.651275634765625 +41970 0.058624267578125 +41971 0.61846923828125 +41972 0.096221923828125 +41973 0.53753662109375 +41974 0.121978759765625 +41975 0.404144287109375 +41976 0.133697509765625 +41977 0.22186279296875 +41978 0.131622314453125 +41979 0.003997802734375 +41980 0.119598388671875 +41981 -0.22100830078125 +41982 0.10205078125 +41983 -0.42449951171875 +41984 0.08392333984375 +41985 -0.579833984375 +41986 0.07513427734375 +41987 -0.641876220703125 +41988 0.073699951171875 +41989 -0.6177978515625 +41990 0.06396484375 +41991 -0.575531005859375 +41992 0.044891357421875 +41993 -0.526336669921875 +41994 0.029541015625 +41995 -0.42645263671875 +41996 0.02490234375 +41997 -0.2581787109375 +41998 0.0220947265625 +41999 -0.068695068359375 +42000 0.01165771484375 +42001 0.09222412109375 +42002 -0.001739501953125 +42003 0.232147216796875 +42004 -0.015533447265625 +42005 0.3509521484375 +42006 -0.037109375 +42007 0.410064697265625 +42008 -0.073760986328125 +42009 0.372955322265625 +42010 -0.120361328125 +42011 0.2554931640625 +42012 -0.16400146484375 +42013 0.10711669921875 +42014 -0.1998291015625 +42015 -0.052886962890625 +42016 -0.218902587890625 +42017 -0.186279296875 +42018 -0.2073974609375 +42019 -0.23291015625 +42020 -0.170989990234375 +42021 -0.209442138671875 +42022 -0.126007080078125 +42023 -0.174163818359375 +42024 -0.07452392578125 +42025 -0.126739501953125 +42026 -0.014068603515625 +42027 -0.048126220703125 +42028 0.048309326171875 +42029 0.0426025390625 +42030 0.101043701171875 +42031 0.10748291015625 +42032 0.140869140625 +42033 0.1409912109375 +42034 0.179595947265625 +42035 0.19708251953125 +42036 0.215545654296875 +42037 0.273651123046875 +42038 0.23486328125 +42039 0.31768798828125 +42040 0.240325927734375 +42041 0.341094970703125 +42042 0.2381591796875 +42043 0.368011474609375 +42044 0.222686767578125 +42045 0.37249755859375 +42046 0.181671142578125 +42047 0.30072021484375 +42048 0.116363525390625 +42049 0.1517333984375 +42050 0.043243408203125 +42051 -0.01470947265625 +42052 -0.03326416015625 +42053 -0.1883544921875 +42054 -0.112152099609375 +42055 -0.372711181640625 +42056 -0.178314208984375 +42057 -0.51397705078125 +42058 -0.220062255859375 +42059 -0.57177734375 +42060 -0.234375 +42061 -0.53948974609375 +42062 -0.22467041015625 +42063 -0.43511962890625 +42064 -0.199554443359375 +42065 -0.2962646484375 +42066 -0.168212890625 +42067 -0.161102294921875 +42068 -0.1341552734375 +42069 -0.0435791015625 +42070 -0.09686279296875 +42071 0.060394287109375 +42072 -0.060638427734375 +42073 0.13665771484375 +42074 -0.03033447265625 +42075 0.170135498046875 +42076 -0.006134033203125 +42077 0.16552734375 +42078 0.019012451171875 +42079 0.15728759765625 +42080 0.044891357421875 +42081 0.150787353515625 +42082 0.064056396484375 +42083 0.12200927734375 +42084 0.077362060546875 +42085 0.080108642578125 +42086 0.090087890625 +42087 0.05126953125 +42088 0.108062744140625 +42089 0.062896728515625 +42090 0.12506103515625 +42091 0.09271240234375 +42092 0.12890625 +42093 0.092987060546875 +42094 0.123199462890625 +42095 0.07855224609375 +42096 0.1119384765625 +42097 0.06427001953125 +42098 0.091888427734375 +42099 0.0347900390625 +42100 0.06341552734375 +42101 -0.01171875 +42102 0.0323486328125 +42103 -0.056060791015625 +42104 0.010467529296875 +42105 -0.055511474609375 +42106 -0.00103759765625 +42107 -0.010467529296875 +42108 -0.0142822265625 +42109 0.02508544921875 +42110 -0.034423828125 +42111 0.025665283203125 +42112 -0.053955078125 +42113 0.017333984375 +42114 -0.071533203125 +42115 0.00189208984375 +42116 -0.089263916015625 +42117 -0.03173828125 +42118 -0.103790283203125 +42119 -0.071502685546875 +42120 -0.11944580078125 +42121 -0.13543701171875 +42122 -0.135528564453125 +42123 -0.219970703125 +42124 -0.14630126953125 +42125 -0.300506591796875 +42126 -0.152191162109375 +42127 -0.376312255859375 +42128 -0.14630126953125 +42129 -0.416107177734375 +42130 -0.117462158203125 +42131 -0.371124267578125 +42132 -0.066925048828125 +42133 -0.242279052734375 +42134 -0.00567626953125 +42135 -0.069732666015625 +42136 0.06005859375 +42137 0.125640869140625 +42138 0.12164306640625 +42139 0.31268310546875 +42140 0.169281005859375 +42141 0.45501708984375 +42142 0.202911376953125 +42143 0.554779052734375 +42144 0.221832275390625 +42145 0.61065673828125 +42146 0.222991943359375 +42147 0.610931396484375 +42148 0.200439453125 +42149 0.531463623046875 +42150 0.158447265625 +42151 0.3883056640625 +42152 0.11065673828125 +42153 0.23468017578125 +42154 0.063812255859375 +42155 0.095245361328125 +42156 0.02508544921875 +42157 -0.00396728515625 +42158 -0.001068115234375 +42159 -0.04852294921875 +42160 -0.0179443359375 +42161 -0.055145263671875 +42162 -0.037628173828125 +42163 -0.0758056640625 +42164 -0.066314697265625 +42165 -0.138702392578125 +42166 -0.094757080078125 +42167 -0.209197998046875 +42168 -0.122833251953125 +42169 -0.289031982421875 +42170 -0.150360107421875 +42171 -0.37884521484375 +42172 -0.17156982421875 +42173 -0.456329345703125 +42174 -0.1851806640625 +42175 -0.51641845703125 +42176 -0.1815185546875 +42177 -0.519287109375 +42178 -0.15924072265625 +42179 -0.458251953125 +42180 -0.131561279296875 +42181 -0.384796142578125 +42182 -0.105224609375 +42183 -0.323699951171875 +42184 -0.0794677734375 +42185 -0.269287109375 +42186 -0.0484619140625 +42187 -0.1951904296875 +42188 -0.0125732421875 +42189 -0.100006103515625 +42190 0.0208740234375 +42191 -0.01055908203125 +42192 0.05877685546875 +42193 0.1033935546875 +42194 0.102447509765625 +42195 0.24908447265625 +42196 0.138336181640625 +42197 0.373199462890625 +42198 0.161865234375 +42199 0.45806884765625 +42200 0.17486572265625 +42201 0.511474609375 +42202 0.18536376953125 +42203 0.565399169921875 +42204 0.191497802734375 +42205 0.61138916015625 +42206 0.1788330078125 +42207 0.5897216796875 +42208 0.1453857421875 +42209 0.4906005859375 +42210 0.096038818359375 +42211 0.33148193359375 +42212 0.040130615234375 +42213 0.147796630859375 +42214 -0.01141357421875 +42215 -0.01873779296875 +42216 -0.051116943359375 +42217 -0.140289306640625 +42218 -0.072296142578125 +42219 -0.191986083984375 +42220 -0.0771484375 +42221 -0.184295654296875 +42222 -0.076416015625 +42223 -0.161834716796875 +42224 -0.080291748046875 +42225 -0.166595458984375 +42226 -0.0875244140625 +42227 -0.19390869140625 +42228 -0.093353271484375 +42229 -0.22442626953125 +42230 -0.103302001953125 +42231 -0.279754638671875 +42232 -0.112457275390625 +42233 -0.3389892578125 +42234 -0.10931396484375 +42235 -0.3543701171875 +42236 -0.099822998046875 +42237 -0.348175048828125 +42238 -0.085845947265625 +42239 -0.32598876953125 +42240 -0.06048583984375 +42241 -0.2581787109375 +42242 -0.02294921875 +42243 -0.139801025390625 +42244 0.022705078125 +42245 0.014617919921875 +42246 0.0609130859375 +42247 0.144378662109375 +42248 0.084320068359375 +42249 0.221038818359375 +42250 0.099273681640625 +42251 0.27069091796875 +42252 0.105865478515625 +42253 0.294036865234375 +42254 0.109283447265625 +42255 0.311767578125 +42256 0.113525390625 +42257 0.339141845703125 +42258 0.115203857421875 +42259 0.360260009765625 +42260 0.11077880859375 +42261 0.360504150390625 +42262 0.091583251953125 +42263 0.308380126953125 +42264 0.051544189453125 +42265 0.18170166015625 +42266 -0.0023193359375 +42267 0.0047607421875 +42268 -0.056732177734375 +42269 -0.17559814453125 +42270 -0.09893798828125 +42271 -0.3143310546875 +42272 -0.1165771484375 +42273 -0.36785888671875 +42274 -0.116943359375 +42275 -0.36248779296875 +42276 -0.112640380859375 +42277 -0.343536376953125 +42278 -0.101104736328125 +42279 -0.3018798828125 +42280 -0.08062744140625 +42281 -0.231414794921875 +42282 -0.047210693359375 +42283 -0.117645263671875 +42284 -0.010009765625 +42285 0.007049560546875 +42286 0.015472412109375 +42287 0.087982177734375 +42288 0.033111572265625 +42289 0.13946533203125 +42290 0.046295166015625 +42291 0.17425537109375 +42292 0.053680419921875 +42293 0.188201904296875 +42294 0.05224609375 +42295 0.171234130859375 +42296 0.040435791015625 +42297 0.118438720703125 +42298 0.025787353515625 +42299 0.05706787109375 +42300 0.00872802734375 +42301 -0.010711669921875 +42302 -0.012603759765625 +42303 -0.0914306640625 +42304 -0.031890869140625 +42305 -0.162322998046875 +42306 -0.04107666015625 +42307 -0.194549560546875 +42308 -0.029266357421875 +42309 -0.1492919921875 +42310 0.004913330078125 +42311 -0.02166748046875 +42312 0.043609619140625 +42313 0.124053955078125 +42314 0.0654296875 +42315 0.211151123046875 +42316 0.070770263671875 +42317 0.240447998046875 +42318 0.068267822265625 +42319 0.242218017578125 +42320 0.06072998046875 +42321 0.2257080078125 +42322 0.04925537109375 +42323 0.194366455078125 +42324 0.02484130859375 +42325 0.115509033203125 +42326 -0.005706787109375 +42327 0.0128173828125 +42328 -0.025543212890625 +42329 -0.053802490234375 +42330 -0.0419921875 +42331 -0.110626220703125 +42332 -0.0667724609375 +42333 -0.199493408203125 +42334 -0.092620849609375 +42335 -0.29437255859375 +42336 -0.1019287109375 +42337 -0.33221435546875 +42338 -0.085479736328125 +42339 -0.27972412109375 +42340 -0.05694580078125 +42341 -0.185333251953125 +42342 -0.038604736328125 +42343 -0.128204345703125 +42344 -0.03265380859375 +42345 -0.115692138671875 +42346 -0.03045654296875 +42347 -0.116455078125 +42348 -0.0252685546875 +42349 -0.105926513671875 +42350 -0.008758544921875 +42351 -0.053955078125 +42352 0.021575927734375 +42353 0.048797607421875 +42354 0.05303955078125 +42355 0.157318115234375 +42356 0.06890869140625 +42357 0.212005615234375 +42358 0.07073974609375 +42359 0.218475341796875 +42360 0.07550048828125 +42361 0.23724365234375 +42362 0.093597412109375 +42363 0.30535888671875 +42364 0.11346435546875 +42365 0.38128662109375 +42366 0.11822509765625 +42367 0.404449462890625 +42368 0.11346435546875 +42369 0.3944091796875 +42370 0.109771728515625 +42371 0.3885498046875 +42372 0.1004638671875 +42373 0.362640380859375 +42374 0.0736083984375 +42375 0.27362060546875 +42376 0.028076171875 +42377 0.11712646484375 +42378 -0.021484375 +42379 -0.054901123046875 +42380 -0.060516357421875 +42381 -0.19085693359375 +42382 -0.08758544921875 +42383 -0.28570556640625 +42384 -0.1026611328125 +42385 -0.339263916015625 +42386 -0.113006591796875 +42387 -0.3775634765625 +42388 -0.131317138671875 +42389 -0.445709228515625 +42390 -0.15521240234375 +42391 -0.535064697265625 +42392 -0.18011474609375 +42393 -0.629058837890625 +42394 -0.197662353515625 +42395 -0.697601318359375 +42396 -0.197662353515625 +42397 -0.70391845703125 +42398 -0.1787109375 +42399 -0.6424560546875 +42400 -0.134735107421875 +42401 -0.491241455078125 +42402 -0.07012939453125 +42403 -0.265716552734375 +42404 -0.00115966796875 +42405 -0.023712158203125 +42406 0.062835693359375 +42407 0.201751708984375 +42408 0.112060546875 +42409 0.375823974609375 +42410 0.14276123046875 +42411 0.485076904296875 +42412 0.165924072265625 +42413 0.56884765625 +42414 0.183746337890625 +42415 0.634765625 +42416 0.18359375 +42417 0.63763427734375 +42418 0.162353515625 +42419 0.5660400390625 +42420 0.1346435546875 +42421 0.4720458984375 +42422 0.114898681640625 +42423 0.40692138671875 +42424 0.105255126953125 +42425 0.3778076171875 +42426 0.10357666015625 +42427 0.376953125 +42428 0.10089111328125 +42429 0.371978759765625 +42430 0.08331298828125 +42431 0.313140869140625 +42432 0.046417236328125 +42433 0.184417724609375 +42434 -0.002593994140625 +42435 0.011199951171875 +42436 -0.05377197265625 +42437 -0.171051025390625 +42438 -0.100128173828125 +42439 -0.33740234375 +42440 -0.13726806640625 +42441 -0.47198486328125 +42442 -0.16119384765625 +42443 -0.560394287109375 +42444 -0.165802001953125 +42445 -0.58056640625 +42446 -0.15533447265625 +42447 -0.54754638671875 +42448 -0.14312744140625 +42449 -0.508575439453125 +42450 -0.128082275390625 +42451 -0.459503173828125 +42452 -0.10858154296875 +42453 -0.394378662109375 +42454 -0.095703125 +42455 -0.35260009765625 +42456 -0.083221435546875 +42457 -0.31170654296875 +42458 -0.0504150390625 +42459 -0.197418212890625 +42460 0.003143310546875 +42461 -0.007965087890625 +42462 0.06365966796875 +42463 0.207489013671875 +42464 0.1199951171875 +42465 0.409210205078125 +42466 0.165130615234375 +42467 0.57208251953125 +42468 0.190673828125 +42469 0.66595458984375 +42470 0.187713623046875 +42471 0.65875244140625 +42472 0.161041259765625 +42473 0.56744384765625 +42474 0.12176513671875 +42475 0.431396484375 +42476 0.082244873046875 +42477 0.29443359375 +42478 0.049774169921875 +42479 0.182464599609375 +42480 0.0155029296875 +42481 0.06365966796875 +42482 -0.0244140625 +42483 -0.075958251953125 +42484 -0.056793212890625 +42485 -0.189422607421875 +42486 -0.08026123046875 +42487 -0.271942138671875 +42488 -0.10009765625 +42489 -0.342529296875 +42490 -0.105987548828125 +42491 -0.364166259765625 +42492 -0.095245361328125 +42493 -0.327239990234375 +42494 -0.08056640625 +42495 -0.2769775390625 +42496 -0.07354736328125 +42497 -0.253692626953125 +42498 -0.070159912109375 +42499 -0.24365234375 +42500 -0.0557861328125 +42501 -0.1983642578125 +42502 -0.030059814453125 +42503 -0.116241455078125 +42504 -0.00543212890625 +42505 -0.036834716796875 +42506 0.016448974609375 +42507 0.034881591796875 +42508 0.033172607421875 +42509 0.09124755859375 +42510 0.037506103515625 +42511 0.10888671875 +42512 0.041259765625 +42513 0.125518798828125 +42514 0.049713134765625 +42515 0.15771484375 +42516 0.054473876953125 +42517 0.17828369140625 +42518 0.050567626953125 +42519 0.17108154296875 +42520 0.0362548828125 +42521 0.129974365234375 +42522 0.020172119140625 +42523 0.082427978515625 +42524 0.00213623046875 +42525 0.027679443359375 +42526 -0.02752685546875 +42527 -0.065643310546875 +42528 -0.056884765625 +42529 -0.15936279296875 +42530 -0.073333740234375 +42531 -0.21307373046875 +42532 -0.079376220703125 +42533 -0.234649658203125 +42534 -0.067596435546875 +42535 -0.2001953125 +42536 -0.041015625 +42537 -0.119171142578125 +42538 -0.01007080078125 +42539 -0.024749755859375 +42540 0.0260009765625 +42541 0.085784912109375 +42542 0.056396484375 +42543 0.178131103515625 +42544 0.069549560546875 +42545 0.215576171875 +42546 0.069549560546875 +42547 0.211456298828125 +42548 0.059326171875 +42549 0.17523193359375 +42550 0.045623779296875 +42551 0.128753662109375 +42552 0.037750244140625 +42553 0.1019287109375 +42554 0.029327392578125 +42555 0.0743408203125 +42556 0.019500732421875 +42557 0.04327392578125 +42558 0.017425537109375 +42559 0.038177490234375 +42560 0.028564453125 +42561 0.076263427734375 +42562 0.047760009765625 +42563 0.14105224609375 +42564 0.06072998046875 +42565 0.186431884765625 +42566 0.0601806640625 +42567 0.188812255859375 +42568 0.043304443359375 +42569 0.1390380859375 +42570 0.011688232421875 +42571 0.041778564453125 +42572 -0.027252197265625 +42573 -0.079437255859375 +42574 -0.071868896484375 +42575 -0.219390869140625 +42576 -0.118865966796875 +42577 -0.367828369140625 +42578 -0.158905029296875 +42579 -0.494873046875 +42580 -0.178192138671875 +42581 -0.556243896484375 +42582 -0.1632080078125 +42583 -0.508697509765625 +42584 -0.12127685546875 +42585 -0.3756103515625 +42586 -0.071746826171875 +42587 -0.218902587890625 +42588 -0.02252197265625 +42589 -0.063751220703125 +42590 0.02685546875 +42591 0.091552734375 +42592 0.072906494140625 +42593 0.23602294921875 +42594 0.10723876953125 +42595 0.342987060546875 +42596 0.12445068359375 +42597 0.39520263671875 +42598 0.12347412109375 +42599 0.389373779296875 +42600 0.1038818359375 +42601 0.324249267578125 +42602 0.073211669921875 +42603 0.224090576171875 +42604 0.042449951171875 +42605 0.124267578125 +42606 0.015411376953125 +42607 0.037078857421875 +42608 0.000640869140625 +42609 -0.010101318359375 +42610 -0.00250244140625 +42611 -0.019439697265625 +42612 -0.003936767578125 +42613 -0.022796630859375 +42614 0.00213623046875 +42615 -0.001556396484375 +42616 0.019500732421875 +42617 0.056304931640625 +42618 0.034454345703125 +42619 0.106719970703125 +42620 0.030548095703125 +42621 0.096893310546875 +42622 0.0128173828125 +42623 0.042694091796875 +42624 -0.00689697265625 +42625 -0.018035888671875 +42626 -0.025604248046875 +42627 -0.07586669921875 +42628 -0.039703369140625 +42629 -0.11944580078125 +42630 -0.0526123046875 +42631 -0.15972900390625 +42632 -0.066131591796875 +42633 -0.202606201171875 +42634 -0.080413818359375 +42635 -0.24859619140625 +42636 -0.0977783203125 +42637 -0.30517578125 +42638 -0.115081787109375 +42639 -0.36212158203125 +42640 -0.1236572265625 +42641 -0.39141845703125 +42642 -0.111724853515625 +42643 -0.35528564453125 +42644 -0.07818603515625 +42645 -0.249969482421875 +42646 -0.02850341796875 +42647 -0.092864990234375 +42648 0.02886962890625 +42649 0.08905029296875 +42650 0.07501220703125 +42651 0.2352294921875 +42652 0.101531982421875 +42653 0.318817138671875 +42654 0.114288330078125 +42655 0.358642578125 +42656 0.111083984375 +42657 0.347747802734375 +42658 0.09173583984375 +42659 0.28564453125 +42660 0.0721435546875 +42661 0.223175048828125 +42662 0.06365966796875 +42663 0.196746826171875 +42664 0.05804443359375 +42665 0.179840087890625 +42666 0.050048828125 +42667 0.155548095703125 +42668 0.0482177734375 +42669 0.151214599609375 +42670 0.049468994140625 +42671 0.156951904296875 +42672 0.041046142578125 +42673 0.13177490234375 +42674 0.030853271484375 +42675 0.100799560546875 +42676 0.026092529296875 +42677 0.087127685546875 +42678 0.015594482421875 +42679 0.05487060546875 +42680 -0.004638671875 +42681 -0.009002685546875 +42682 -0.034454345703125 +42683 -0.10400390625 +42684 -0.073638916015625 +42685 -0.229400634765625 +42686 -0.1129150390625 +42687 -0.35552978515625 +42688 -0.1396484375 +42689 -0.441925048828125 +42690 -0.149261474609375 +42691 -0.473846435546875 +42692 -0.14599609375 +42693 -0.464813232421875 +42694 -0.1312255859375 +42695 -0.419097900390625 +42696 -0.104248046875 +42697 -0.334320068359375 +42698 -0.070526123046875 +42699 -0.227935791015625 +42700 -0.037445068359375 +42701 -0.12347412109375 +42702 -0.007110595703125 +42703 -0.02764892578125 +42704 0.026092529296875 +42705 0.077667236328125 +42706 0.068634033203125 +42707 0.2132568359375 +42708 0.12353515625 +42709 0.38885498046875 +42710 0.184051513671875 +42711 0.582794189453125 +42712 0.231109619140625 +42713 0.734039306640625 +42714 0.25146484375 +42715 0.800140380859375 +42716 0.244293212890625 +42717 0.7783203125 +42718 0.20855712890625 +42719 0.6651611328125 +42720 0.144012451171875 +42721 0.45965576171875 +42722 0.06231689453125 +42723 0.199188232421875 +42724 -0.016021728515625 +42725 -0.050689697265625 +42726 -0.0732421875 +42727 -0.23297119140625 +42728 -0.103851318359375 +42729 -0.33013916015625 +42730 -0.11602783203125 +42731 -0.368408203125 +42732 -0.11944580078125 +42733 -0.378936767578125 +42734 -0.118927001953125 +42735 -0.376983642578125 +42736 -0.11981201171875 +42737 -0.37969970703125 +42738 -0.1234130859375 +42739 -0.391510009765625 +42740 -0.121307373046875 +42741 -0.385345458984375 +42742 -0.107513427734375 +42743 -0.3419189453125 +42744 -0.08880615234375 +42745 -0.28289794921875 +42746 -0.078704833984375 +42747 -0.251617431640625 +42748 -0.082855224609375 +42749 -0.266143798828125 +42750 -0.084716796875 +42751 -0.273345947265625 +42752 -0.066558837890625 +42753 -0.216796875 +42754 -0.038604736328125 +42755 -0.128265380859375 +42756 -0.02069091796875 +42757 -0.068145751953125 +42758 -0.014923095703125 +42759 -0.0430908203125 +42760 -0.01129150390625 +42761 -0.024444580078125 +42762 0.001678466796875 +42763 0.020721435546875 +42764 0.03515625 +42765 0.124481201171875 +42766 0.07928466796875 +42767 0.25787353515625 +42768 0.1197509765625 +42769 0.379119873046875 +42770 0.15380859375 +42771 0.47991943359375 +42772 0.17041015625 +42773 0.5281982421875 +42774 0.165130615234375 +42775 0.511138916015625 +42776 0.147369384765625 +42777 0.456207275390625 +42778 0.132232666015625 +42779 0.407470703125 +42780 0.1260986328125 +42781 0.383758544921875 +42782 0.119110107421875 +42783 0.35687255859375 +42784 0.10601806640625 +42785 0.31182861328125 +42786 0.087432861328125 +42787 0.250885009765625 +42788 0.060272216796875 +42789 0.1654052734375 +42790 0.017486572265625 +42791 0.035247802734375 +42792 -0.041839599609375 +42793 -0.142059326171875 +42794 -0.107147216796875 +42795 -0.33563232421875 +42796 -0.174774169921875 +42797 -0.5345458984375 +42798 -0.2388916015625 +42799 -0.72186279296875 +42800 -0.278564453125 +42801 -0.836669921875 +42802 -0.27783203125 +42803 -0.8326416015625 +42804 -0.24346923828125 +42805 -0.7296142578125 +42806 -0.1943359375 +42807 -0.582550048828125 +42808 -0.147064208984375 +42809 -0.440093994140625 +42810 -0.109161376953125 +42811 -0.324310302734375 +42812 -0.068878173828125 +42813 -0.20147705078125 +42814 -0.016845703125 +42815 -0.044647216796875 +42816 0.032501220703125 +42817 0.103973388671875 +42818 0.0648193359375 +42819 0.202392578125 +42820 0.0849609375 +42821 0.264495849609375 +42822 0.10968017578125 +42823 0.338897705078125 +42824 0.145294189453125 +42825 0.443817138671875 +42826 0.1800537109375 +42827 0.545074462890625 +42828 0.205230712890625 +42829 0.6173095703125 +42830 0.218017578125 +42831 0.6524658203125 +42832 0.222808837890625 +42833 0.66339111328125 +42834 0.22161865234375 +42835 0.6561279296875 +42836 0.20611572265625 +42837 0.606781005859375 +42838 0.17132568359375 +42839 0.501190185546875 +42840 0.121826171875 +42841 0.352783203125 +42842 0.06268310546875 +42843 0.176544189453125 +42844 -0.0086669921875 +42845 -0.034820556640625 +42846 -0.084320068359375 +42847 -0.258209228515625 +42848 -0.146759033203125 +42849 -0.44244384765625 +42850 -0.191802978515625 +42851 -0.5753173828125 +42852 -0.217864990234375 +42853 -0.65203857421875 +42854 -0.21429443359375 +42855 -0.641632080078125 +42856 -0.18731689453125 +42857 -0.562164306640625 +42858 -0.152191162109375 +42859 -0.458038330078125 +42860 -0.11614990234375 +42861 -0.350555419921875 +42862 -0.086334228515625 +42863 -0.260528564453125 +42864 -0.0640869140625 +42865 -0.192108154296875 +42866 -0.048187255859375 +42867 -0.141937255859375 +42868 -0.035858154296875 +42869 -0.1021728515625 +42870 -0.023590087890625 +42871 -0.062896728515625 +42872 -0.00714111328125 +42873 -0.011932373046875 +42874 0.0177001953125 +42875 0.062835693359375 +42876 0.046630859375 +42877 0.148712158203125 +42878 0.078277587890625 +42879 0.241729736328125 +42880 0.11517333984375 +42881 0.34912109375 +42882 0.152618408203125 +42883 0.457305908203125 +42884 0.182891845703125 +42885 0.54388427734375 +42886 0.193572998046875 +42887 0.5728759765625 +42888 0.171661376953125 +42889 0.506591796875 +42890 0.119232177734375 +42891 0.351226806640625 +42892 0.049896240234375 +42893 0.146514892578125 +42894 -0.018402099609375 +42895 -0.05523681640625 +42896 -0.072723388671875 +42897 -0.21624755859375 +42898 -0.112579345703125 +42899 -0.334930419921875 +42900 -0.135162353515625 +42901 -0.402984619140625 +42902 -0.147674560546875 +42903 -0.4412841796875 +42904 -0.165985107421875 +42905 -0.49578857421875 +42906 -0.187957763671875 +42907 -0.5601806640625 +42908 -0.20196533203125 +42909 -0.600738525390625 +42910 -0.19659423828125 +42911 -0.584228515625 +42912 -0.1610107421875 +42913 -0.47930908203125 +42914 -0.092926025390625 +42915 -0.27935791015625 +42916 -0.000732421875 +42917 -0.0089111328125 +42918 0.093841552734375 +42919 0.268798828125 +42920 0.166473388671875 +42921 0.482818603515625 +42922 0.207061767578125 +42923 0.60369873046875 +42924 0.222198486328125 +42925 0.650421142578125 +42926 0.226043701171875 +42927 0.66400146484375 +42928 0.21759033203125 +42929 0.6414794921875 +42930 0.193359375 +42931 0.572540283203125 +42932 0.16748046875 +42933 0.498138427734375 +42934 0.147216796875 +42935 0.439453125 +42936 0.125396728515625 +42937 0.375518798828125 +42938 0.091033935546875 +42939 0.274505615234375 +42940 0.034576416015625 +42941 0.1087646484375 +42942 -0.03631591796875 +42943 -0.099395751953125 +42944 -0.110748291015625 +42945 -0.3182373046875 +42946 -0.189208984375 +42947 -0.5489501953125 +42948 -0.265594482421875 +42949 -0.7738037109375 +42950 -0.32177734375 +42951 -0.86383056640625 +42952 -0.34637451171875 +42953 -0.870391845703125 +42954 -0.345550537109375 +42955 -0.86895751953125 +42956 -0.323822021484375 +42957 -0.861053466796875 +42958 -0.2752685546875 +42959 -0.765869140625 +42960 -0.196014404296875 +42961 -0.5301513671875 +42962 -0.088531494140625 +42963 -0.214691162109375 +42964 0.032379150390625 +42965 0.137359619140625 +42966 0.1490478515625 +42967 0.474822998046875 +42968 0.24932861328125 +42969 0.76239013671875 +42970 0.323944091796875 +42971 0.867462158203125 +42972 0.37310791015625 +42973 0.870361328125 +42974 0.39288330078125 +42975 0.86480712890625 +42976 0.385162353515625 +42977 0.831817626953125 +42978 0.358367919921875 +42979 0.677581787109375 +42980 0.314544677734375 +42981 0.495880126953125 +42982 0.260101318359375 +42983 0.30767822265625 +42984 0.195831298828125 +42985 0.116180419921875 +42986 0.11083984375 +42987 -0.110748291015625 +42988 0.002716064453125 +42989 -0.381805419921875 +42990 -0.113739013671875 +42991 -0.6572265625 +42992 -0.21795654296875 +42993 -0.857421875 +42994 -0.295196533203125 +42995 -0.870391845703125 +42996 -0.343017578125 +42997 -0.870391845703125 +42998 -0.3707275390625 +42999 -0.86444091796875 +43000 -0.390625 +43001 -0.85723876953125 +43002 -0.396453857421875 +43003 -0.790008544921875 +43004 -0.36962890625 +43005 -0.62847900390625 +43006 -0.30908203125 +43007 -0.3956298828125 +43008 -0.22607421875 +43009 -0.126708984375 +43010 -0.130035400390625 +43011 0.150115966796875 +43012 -0.024749755859375 +43013 0.424041748046875 +43014 0.080291748046875 +43015 0.670623779296875 +43016 0.171051025390625 +43017 0.854522705078125 +43018 0.24139404296875 +43019 0.866485595703125 +43020 0.285919189453125 +43021 0.86920166015625 +43022 0.31170654296875 +43023 0.8653564453125 +43024 0.323974609375 +43025 0.857147216796875 +43026 0.321685791015625 +43027 0.766845703125 +43028 0.30670166015625 +43029 0.628509521484375 +43030 0.276336669921875 +43031 0.462127685546875 +43032 0.24005126953125 +43033 0.297210693359375 +43034 0.202178955078125 +43035 0.14862060546875 +43036 0.153778076171875 +43037 -0.00537109375 +43038 0.0972900390625 +43039 -0.15753173828125 +43040 0.030975341796875 +43041 -0.31304931640625 +43042 -0.05078125 +43043 -0.48876953125 +43044 -0.130706787109375 +43045 -0.6416015625 +43046 -0.199798583984375 +43047 -0.751373291015625 +43048 -0.2669677734375 +43049 -0.84619140625 +43050 -0.32684326171875 +43051 -0.861297607421875 +43052 -0.367034912109375 +43053 -0.863250732421875 +43054 -0.3756103515625 +43055 -0.856597900390625 +43056 -0.357086181640625 +43057 -0.7498779296875 +43058 -0.33306884765625 +43059 -0.624542236328125 +43060 -0.2950439453125 +43061 -0.47808837890625 +43062 -0.220794677734375 +43063 -0.253387451171875 +43064 -0.127197265625 +43065 0.003692626953125 +43066 -0.0396728515625 +43067 0.2257080078125 +43068 0.046783447265625 +43069 0.427154541015625 +43070 0.1446533203125 +43071 0.643218994140625 +43072 0.250518798828125 +43073 0.855926513671875 +43074 0.342803955078125 +43075 0.870361328125 +43076 0.402984619140625 +43077 0.870361328125 +43078 0.433837890625 +43079 0.862762451171875 +43080 0.43426513671875 +43081 0.79669189453125 +43082 0.400665283203125 +43083 0.595794677734375 +43084 0.34393310546875 +43085 0.362152099609375 +43086 0.274444580078125 +43087 0.1270751953125 +43088 0.199981689453125 +43089 -0.086944580078125 +43090 0.121124267578125 +43091 -0.2784423828125 +43092 0.0245361328125 +43093 -0.484832763671875 +43094 -0.097198486328125 +43095 -0.729583740234375 +43096 -0.225250244140625 +43097 -0.86688232421875 +43098 -0.335968017578125 +43099 -0.870391845703125 +43100 -0.427642822265625 +43101 -0.86859130859375 +43102 -0.4996337890625 +43103 -0.86279296875 +43104 -0.5384521484375 +43105 -0.817962646484375 +43106 -0.52703857421875 +43107 -0.6116943359375 +43108 -0.46270751953125 +43109 -0.3128662109375 +43110 -0.358062744140625 +43111 0.039398193359375 +43112 -0.220550537109375 +43113 0.422821044921875 +43114 -0.06256103515625 +43115 0.805145263671875 +43116 0.090423583984375 +43117 0.870361328125 +43118 0.217071533203125 +43119 0.870361328125 +43120 0.313140869140625 +43121 0.860015869140625 +43122 0.3758544921875 +43123 0.727935791015625 +43124 0.403167724609375 +43125 0.48114013671875 +43126 0.404205322265625 +43127 0.2059326171875 +43128 0.38751220703125 +43129 -0.06103515625 +43130 0.35687255859375 +43131 -0.29913330078125 +43132 0.306854248046875 +43133 -0.516204833984375 +43134 0.231658935546875 +43135 -0.7252197265625 +43136 0.140625 +43137 -0.85980224609375 +43138 0.04669189453125 +43139 -0.870391845703125 +43140 -0.03900146484375 +43141 -0.870391845703125 +43142 -0.09814453125 +43143 -0.858062744140625 +43144 -0.129119873046875 +43145 -0.673004150390625 +43146 -0.151641845703125 +43147 -0.42694091796875 +43148 -0.182342529296875 +43149 -0.2100830078125 +43150 -0.2203369140625 +43151 -0.0362548828125 +43152 -0.254638671875 +43153 0.10943603515625 +43154 -0.2777099609375 +43155 0.23516845703125 +43156 -0.273956298828125 +43157 0.373687744140625 +43158 -0.244110107421875 +43159 0.517791748046875 +43160 -0.21185302734375 +43161 0.602783203125 +43162 -0.17523193359375 +43163 0.635711669921875 +43164 -0.121734619140625 +43165 0.655181884765625 +43166 -0.05517578125 +43167 0.65948486328125 +43168 0.021331787109375 +43169 0.651275634765625 +43170 0.098480224609375 +43171 0.61846923828125 +43172 0.162261962890625 +43173 0.53753662109375 +43174 0.20574951171875 +43175 0.404144287109375 +43176 0.2252197265625 +43177 0.22186279296875 +43178 0.2210693359375 +43179 0.003997802734375 +43180 0.200042724609375 +43181 -0.22100830078125 +43182 0.16986083984375 +43183 -0.42449951171875 +43184 0.13848876953125 +43185 -0.579833984375 +43186 0.121978759765625 +43187 -0.641876220703125 +43188 0.117828369140625 +43189 -0.6177978515625 +43190 0.101806640625 +43191 -0.575531005859375 +43192 0.07196044921875 +43193 -0.526336669921875 +43194 0.047821044921875 +43195 -0.42645263671875 +43196 0.039794921875 +43197 -0.2581787109375 +43198 0.0343017578125 +43199 -0.068695068359375 +43200 0.0169677734375 +43201 0.09222412109375 +43202 -0.005035400390625 +43203 0.232147216796875 +43204 -0.02777099609375 +43205 0.3509521484375 +43206 -0.062286376953125 +43207 0.410064697265625 +43208 -0.1195068359375 +43209 0.372955322265625 +43210 -0.191497802734375 +43211 0.2554931640625 +43212 -0.25860595703125 +43213 0.10711669921875 +43214 -0.31341552734375 +43215 -0.052886962890625 +43216 -0.342315673828125 +43217 -0.186279296875 +43218 -0.3243408203125 +43219 -0.23291015625 +43220 -0.268096923828125 +43221 -0.209442138671875 +43222 -0.19842529296875 +43223 -0.174163818359375 +43224 -0.1185302734375 +43225 -0.126739501953125 +43226 -0.02484130859375 +43227 -0.048126220703125 +43228 0.071929931640625 +43229 0.0426025390625 +43230 0.154144287109375 +43231 0.10748291015625 +43232 0.216705322265625 +43233 0.1409912109375 +43234 0.277374267578125 +43235 0.19708251953125 +43236 0.333526611328125 +43237 0.273651123046875 +43238 0.36407470703125 +43239 0.31768798828125 +43240 0.373138427734375 +43241 0.341094970703125 +43242 0.37017822265625 +43243 0.368011474609375 +43244 0.346527099609375 +43245 0.37249755859375 +43246 0.283660888671875 +43247 0.30072021484375 +43248 0.183502197265625 +43249 0.1517333984375 +43250 0.071136474609375 +43251 -0.01470947265625 +43252 -0.046661376953125 +43253 -0.1883544921875 +43254 -0.168304443359375 +43255 -0.372711181640625 +43256 -0.27069091796875 +43257 -0.51397705078125 +43258 -0.336029052734375 +43259 -0.57177734375 +43260 -0.359619140625 +43261 -0.53948974609375 +43262 -0.346527099609375 +43263 -0.43511962890625 +43264 -0.3094482421875 +43265 -0.2962646484375 +43266 -0.2620849609375 +43267 -0.161102294921875 +43268 -0.209930419921875 +43269 -0.0435791015625 +43270 -0.15228271484375 +43271 0.060394287109375 +43272 -0.096221923828125 +43273 0.13665771484375 +43274 -0.049591064453125 +43275 0.170135498046875 +43276 -0.012664794921875 +43277 0.16552734375 +43278 0.02593994140625 +43279 0.15728759765625 +43280 0.065948486328125 +43281 0.150787353515625 +43282 0.09539794921875 +43283 0.12200927734375 +43284 0.115753173828125 +43285 0.080108642578125 +43286 0.135589599609375 +43287 0.05126953125 +43288 0.164337158203125 +43289 0.062896728515625 +43290 0.191986083984375 +43291 0.09271240234375 +43292 0.1988525390625 +43293 0.092987060546875 +43294 0.190765380859375 +43295 0.07855224609375 +43296 0.174072265625 +43297 0.06427001953125 +43298 0.14349365234375 +43299 0.0347900390625 +43300 0.099578857421875 +43301 -0.01171875 +43302 0.051544189453125 +43303 -0.056060791015625 +43304 0.018310546875 +43305 -0.055511474609375 +43306 0.001617431640625 +43307 -0.010467529296875 +43308 -0.018157958984375 +43309 0.02508544921875 +43310 -0.04937744140625 +43311 0.025665283203125 +43312 -0.0799560546875 +43313 0.017333984375 +43314 -0.107818603515625 +43315 0.00189208984375 +43316 -0.136383056640625 +43317 -0.03173828125 +43318 -0.16021728515625 +43319 -0.071502685546875 +43320 -0.186279296875 +43321 -0.13543701171875 +43322 -0.21337890625 +43323 -0.219970703125 +43324 -0.232177734375 +43325 -0.300506591796875 +43326 -0.243316650390625 +43327 -0.376312255859375 +43328 -0.23553466796875 +43329 -0.416107177734375 +43330 -0.190765380859375 +43331 -0.371124267578125 +43332 -0.11090087890625 +43333 -0.242279052734375 +43334 -0.013580322265625 +43335 -0.069732666015625 +43336 0.091278076171875 +43337 0.125640869140625 +43338 0.189788818359375 +43339 0.31268310546875 +43340 0.266204833984375 +43341 0.45501708984375 +43342 0.3204345703125 +43343 0.554779052734375 +43344 0.351348876953125 +43345 0.61065673828125 +43346 0.35394287109375 +43347 0.610931396484375 +43348 0.318603515625 +43349 0.531463623046875 +43350 0.252105712890625 +43351 0.3883056640625 +43352 0.176422119140625 +43353 0.23468017578125 +43354 0.10235595703125 +43355 0.095245361328125 +43356 0.041412353515625 +43357 -0.00396728515625 +43358 0.000579833984375 +43359 -0.04852294921875 +43360 -0.025482177734375 +43361 -0.055145263671875 +43362 -0.0562744140625 +43363 -0.0758056640625 +43364 -0.101898193359375 +43365 -0.138702392578125 +43366 -0.147430419921875 +43367 -0.209197998046875 +43368 -0.19268798828125 +43369 -0.289031982421875 +43370 -0.23736572265625 +43371 -0.37884521484375 +43372 -0.27215576171875 +43373 -0.456329345703125 +43374 -0.29498291015625 +43375 -0.51641845703125 +43376 -0.290130615234375 +43377 -0.519287109375 +43378 -0.25537109375 +43379 -0.458251953125 +43380 -0.212005615234375 +43381 -0.384796142578125 +43382 -0.1707763671875 +43383 -0.323699951171875 +43384 -0.130401611328125 +43385 -0.269287109375 +43386 -0.081451416015625 +43387 -0.1951904296875 +43388 -0.0244140625 +43389 -0.100006103515625 +43390 0.0289306640625 +43391 -0.01055908203125 +43392 0.089752197265625 +43393 0.1033935546875 +43394 0.160186767578125 +43395 0.24908447265625 +43396 0.21832275390625 +43397 0.373199462890625 +43398 0.256744384765625 +43399 0.45806884765625 +43400 0.2784423828125 +43401 0.511474609375 +43402 0.296295166015625 +43403 0.565399169921875 +43404 0.307281494140625 +43405 0.61138916015625 +43406 0.287994384765625 +43407 0.5897216796875 +43408 0.23516845703125 +43409 0.4906005859375 +43410 0.156585693359375 +43411 0.33148193359375 +43412 0.067291259765625 +43413 0.147796630859375 +43414 -0.015106201171875 +43415 -0.01873779296875 +43416 -0.07861328125 +43417 -0.140289306640625 +43418 -0.112518310546875 +43419 -0.191986083984375 +43420 -0.120330810546875 +43421 -0.184295654296875 +43422 -0.119354248046875 +43423 -0.161834716796875 +43424 -0.126007080078125 +43425 -0.166595458984375 +43426 -0.1383056640625 +43427 -0.19390869140625 +43428 -0.14849853515625 +43429 -0.22442626953125 +43430 -0.165435791015625 +43431 -0.279754638671875 +43432 -0.18115234375 +43433 -0.3389892578125 +43434 -0.177093505859375 +43435 -0.3543701171875 +43436 -0.162750244140625 +43437 -0.348175048828125 +43438 -0.14105224609375 +43439 -0.32598876953125 +43440 -0.10089111328125 +43441 -0.2581787109375 +43442 -0.040985107421875 +43443 -0.139801025390625 +43444 0.03216552734375 +43445 0.014617919921875 +43446 0.093658447265625 +43447 0.144378662109375 +43448 0.131683349609375 +43449 0.221038818359375 +43450 0.156341552734375 +43451 0.27069091796875 +43452 0.167724609375 +43453 0.294036865234375 +43454 0.174072265625 +43455 0.311767578125 +43456 0.181640625 +43457 0.339141845703125 +43458 0.184417724609375 +43459 0.360260009765625 +43460 0.176910400390625 +43461 0.360504150390625 +43462 0.146728515625 +43463 0.308380126953125 +43464 0.085296630859375 +43465 0.18170166015625 +43466 0.003082275390625 +43467 0.0047607421875 +43468 -0.08026123046875 +43469 -0.17559814453125 +43470 -0.145843505859375 +43471 -0.3143310546875 +43472 -0.175445556640625 +43473 -0.36785888671875 +43474 -0.179412841796875 +43475 -0.36248779296875 +43476 -0.175933837890625 +43477 -0.343536376953125 +43478 -0.1611328125 +43479 -0.3018798828125 +43480 -0.132415771484375 +43481 -0.231414794921875 +43482 -0.083953857421875 +43483 -0.117645263671875 +43484 -0.029144287109375 +43485 0.007049560546875 +43486 0.009429931640625 +43487 0.087982177734375 +43488 0.037261962890625 +43489 0.13946533203125 +43490 0.059173583984375 +43491 0.17425537109375 +43492 0.073028564453125 +43493 0.188201904296875 +43494 0.07421875 +43495 0.171234130859375 +43496 0.060333251953125 +43497 0.118438720703125 +43498 0.0421142578125 +43499 0.05706787109375 +43500 0.020050048828125 +43501 -0.010711669921875 +43502 -0.0087890625 +43503 -0.0914306640625 +43504 -0.035247802734375 +43505 -0.162322998046875 +43506 -0.047698974609375 +43507 -0.194549560546875 +43508 -0.0302734375 +43509 -0.1492919921875 +43510 0.01910400390625 +43511 -0.02166748046875 +43512 0.074432373046875 +43513 0.124053955078125 +43514 0.104644775390625 +43515 0.211151123046875 +43516 0.11041259765625 +43517 0.240447998046875 +43518 0.104461669921875 +43519 0.242218017578125 +43520 0.091461181640625 +43521 0.2257080078125 +43522 0.07293701171875 +43523 0.194366455078125 +43524 0.034149169921875 +43525 0.115509033203125 +43526 -0.014190673828125 +43527 0.0128173828125 +43528 -0.04559326171875 +43529 -0.053802490234375 +43530 -0.071502685546875 +43531 -0.110626220703125 +43532 -0.11029052734375 +43533 -0.199493408203125 +43534 -0.150543212890625 +43535 -0.29437255859375 +43536 -0.16461181640625 +43537 -0.33221435546875 +43538 -0.13800048828125 +43539 -0.27972412109375 +43540 -0.092254638671875 +43541 -0.185333251953125 +43542 -0.06243896484375 +43543 -0.128204345703125 +43544 -0.052032470703125 +43545 -0.115692138671875 +43546 -0.047515869140625 +43547 -0.116455078125 +43548 -0.038330078125 +43549 -0.105926513671875 +43550 -0.011474609375 +43551 -0.053955078125 +43552 0.036956787109375 +43553 0.048797607421875 +43554 0.087005615234375 +43555 0.157318115234375 +43556 0.112335205078125 +43557 0.212005615234375 +43558 0.115386962890625 +43559 0.218475341796875 +43560 0.122802734375 +43561 0.23724365234375 +43562 0.150970458984375 +43563 0.30535888671875 +43564 0.18170166015625 +43565 0.38128662109375 +43566 0.188507080078125 +43567 0.404449462890625 +43568 0.180206298828125 +43569 0.3944091796875 +43570 0.1734619140625 +43571 0.3885498046875 +43572 0.157867431640625 +43573 0.362640380859375 +43574 0.114715576171875 +43575 0.27362060546875 +43576 0.042327880859375 +43577 0.11712646484375 +43578 -0.0362548828125 +43579 -0.054901123046875 +43580 -0.09820556640625 +43581 -0.19085693359375 +43582 -0.141204833984375 +43583 -0.28570556640625 +43584 -0.165130615234375 +43585 -0.339263916015625 +43586 -0.18145751953125 +43587 -0.3775634765625 +43588 -0.210052490234375 +43589 -0.445709228515625 +43590 -0.24725341796875 +43591 -0.535064697265625 +43592 -0.285888671875 +43593 -0.629058837890625 +43594 -0.3128662109375 +43595 -0.697601318359375 +43596 -0.31219482421875 +43597 -0.70391845703125 +43598 -0.281646728515625 +43599 -0.6424560546875 +43600 -0.21173095703125 +43601 -0.491241455078125 +43602 -0.10943603515625 +43603 -0.265716552734375 +43604 -0.0003662109375 +43605 -0.023712158203125 +43606 0.10076904296875 +43607 0.201751708984375 +43608 0.1785888671875 +43609 0.375823974609375 +43610 0.227142333984375 +43611 0.485076904296875 +43612 0.26373291015625 +43613 0.56884765625 +43614 0.291748046875 +43615 0.634765625 +43616 0.2913818359375 +43617 0.63763427734375 +43618 0.2576904296875 +43619 0.5660400390625 +43620 0.213714599609375 +43621 0.4720458984375 +43622 0.182159423828125 +43623 0.40692138671875 +43624 0.166351318359375 +43625 0.3778076171875 +43626 0.163055419921875 +43627 0.376953125 +43628 0.158172607421875 +43629 0.371978759765625 +43630 0.129974365234375 +43631 0.313140869140625 +43632 0.071502685546875 +43633 0.184417724609375 +43634 -0.005950927734375 +43635 0.011199951171875 +43636 -0.08673095703125 +43637 -0.171051025390625 +43638 -0.15985107421875 +43639 -0.33740234375 +43640 -0.21832275390625 +43641 -0.47198486328125 +43642 -0.25592041015625 +43643 -0.560394287109375 +43644 -0.26300048828125 +43645 -0.58056640625 +43646 -0.24627685546875 +43647 -0.54754638671875 +43648 -0.226715087890625 +43649 -0.508575439453125 +43650 -0.20263671875 +43651 -0.459503173828125 +43652 -0.171539306640625 +43653 -0.394378662109375 +43654 -0.150848388671875 +43655 -0.35260009765625 +43656 -0.13079833984375 +43657 -0.31170654296875 +43658 -0.078826904296875 +43659 -0.197418212890625 +43660 0.0057373046875 +43661 -0.007965087890625 +43662 0.101165771484375 +43663 0.207489013671875 +43664 0.189971923828125 +43665 0.409210205078125 +43666 0.2611083984375 +43667 0.57208251953125 +43668 0.301361083984375 +43669 0.66595458984375 +43670 0.296722412109375 +43671 0.65875244140625 +43672 0.254730224609375 +43673 0.56744384765625 +43674 0.192840576171875 +43675 0.431396484375 +43676 0.130462646484375 +43677 0.29443359375 +43678 0.079071044921875 +43679 0.182464599609375 +43680 0.024810791015625 +43681 0.06365966796875 +43682 -0.038360595703125 +43683 -0.075958251953125 +43684 -0.089691162109375 +43685 -0.189422607421875 +43686 -0.126983642578125 +43687 -0.271942138671875 +43688 -0.1585693359375 +43689 -0.342529296875 +43690 -0.168182373046875 +43691 -0.364166259765625 +43692 -0.151580810546875 +43693 -0.327239990234375 +43694 -0.128692626953125 +43695 -0.2769775390625 +43696 -0.117340087890625 +43697 -0.253692626953125 +43698 -0.11151123046875 +43699 -0.24365234375 +43700 -0.089996337890625 +43701 -0.1983642578125 +43702 -0.052154541015625 +43703 -0.116241455078125 +43704 -0.015472412109375 +43705 -0.036834716796875 +43706 0.017730712890625 +43707 0.034881591796875 +43708 0.04400634765625 +43709 0.09124755859375 +43710 0.053009033203125 +43711 0.10888671875 +43712 0.061248779296875 +43713 0.125518798828125 +43714 0.07598876953125 +43715 0.15771484375 +43716 0.085235595703125 +43717 0.17828369140625 +43718 0.08184814453125 +43719 0.17108154296875 +43720 0.063201904296875 +43721 0.129974365234375 +43722 0.041412353515625 +43723 0.082427978515625 +43724 0.016204833984375 +43725 0.027679443359375 +43726 -0.026123046875 +43727 -0.065643310546875 +43728 -0.0687255859375 +43729 -0.15936279296875 +43730 -0.09375 +43731 -0.21307373046875 +43732 -0.104583740234375 +43733 -0.234649658203125 +43734 -0.09063720703125 +43735 -0.2001953125 +43736 -0.055999755859375 +43737 -0.119171142578125 +43738 -0.015228271484375 +43739 -0.024749755859375 +43740 0.03289794921875 +43741 0.085784912109375 +43742 0.073272705078125 +43743 0.178131103515625 +43744 0.08978271484375 +43745 0.215576171875 +43746 0.0882568359375 +43747 0.211456298828125 +43748 0.072845458984375 +43749 0.17523193359375 +43750 0.053131103515625 +43751 0.128753662109375 +43752 0.042236328125 +43753 0.1019287109375 +43754 0.0311279296875 +43755 0.0743408203125 +43756 0.0185546875 +43757 0.04327392578125 +43758 0.01739501953125 +43759 0.038177490234375 +43760 0.03515625 +43761 0.076263427734375 +43762 0.064544677734375 +43763 0.14105224609375 +43764 0.085235595703125 +43765 0.186431884765625 +43766 0.0867919921875 +43767 0.188812255859375 +43768 0.065185546875 +43769 0.1390380859375 +43770 0.0224609375 +43771 0.041778564453125 +43772 -0.031005859375 +43773 -0.079437255859375 +43774 -0.0928955078125 +43775 -0.219390869140625 +43776 -0.15899658203125 +43777 -0.367828369140625 +43778 -0.21661376953125 +43779 -0.494873046875 +43780 -0.2452392578125 +43781 -0.556243896484375 +43782 -0.224151611328125 +43783 -0.508697509765625 +43784 -0.164031982421875 +43785 -0.3756103515625 +43786 -0.093719482421875 +43787 -0.218902587890625 +43788 -0.0247802734375 +43789 -0.063751220703125 +43790 0.043975830078125 +43791 0.091552734375 +43792 0.107696533203125 +43793 0.23602294921875 +43794 0.15411376953125 +43795 0.342987060546875 +43796 0.17535400390625 +43797 0.39520263671875 +43798 0.16998291015625 +43799 0.389373779296875 +43800 0.137542724609375 +43801 0.324249267578125 +43802 0.08953857421875 +43803 0.224090576171875 +43804 0.042694091796875 +43805 0.124267578125 +43806 0.002716064453125 +43807 0.037078857421875 +43808 -0.017547607421875 +43809 -0.010101318359375 +43810 -0.019287109375 +43811 -0.019439697265625 +43812 -0.0177001953125 +43813 -0.022796630859375 +43814 -0.004180908203125 +43815 -0.001556396484375 +43816 0.026702880859375 +43817 0.056304931640625 +43818 0.053924560546875 +43819 0.106719970703125 +43820 0.05242919921875 +43821 0.096893310546875 +43822 0.029541015625 +43823 0.042694091796875 +43824 0.002960205078125 +43825 -0.018035888671875 +43826 -0.022918701171875 +43827 -0.07586669921875 +43828 -0.04278564453125 +43829 -0.11944580078125 +43830 -0.061859130859375 +43831 -0.15972900390625 +43832 -0.0828857421875 +43833 -0.202606201171875 +43834 -0.10601806640625 +43835 -0.24859619140625 +43836 -0.134674072265625 +43837 -0.30517578125 +43838 -0.1639404296875 +43839 -0.36212158203125 +43840 -0.180450439453125 +43841 -0.39141845703125 +43842 -0.16619873046875 +43843 -0.35528564453125 +43844 -0.1192626953125 +43845 -0.249969482421875 +43846 -0.0477294921875 +43847 -0.092864990234375 +43848 0.035797119140625 +43849 0.08905029296875 +43850 0.102874755859375 +43851 0.2352294921875 +43852 0.140899658203125 +43853 0.318817138671875 +43854 0.1588134765625 +43855 0.358642578125 +43856 0.15338134765625 +43857 0.347747802734375 +43858 0.1243896484375 +43859 0.28564453125 +43860 0.09576416015625 +43861 0.223175048828125 +43862 0.084625244140625 +43863 0.196746826171875 +43864 0.078399658203125 +43865 0.179840087890625 +43866 0.069000244140625 +43867 0.155548095703125 +43868 0.069183349609375 +43869 0.151214599609375 +43870 0.074188232421875 +43871 0.156951904296875 +43872 0.06451416015625 +43873 0.13177490234375 +43874 0.051910400390625 +43875 0.100799560546875 +43876 0.04718017578125 +43877 0.087127685546875 +43878 0.0333251953125 +43879 0.05487060546875 +43880 0.004119873046875 +43881 -0.009002685546875 +43882 -0.040252685546875 +43883 -0.10400390625 +43884 -0.099456787109375 +43885 -0.229400634765625 +43886 -0.159454345703125 +43887 -0.35552978515625 +43888 -0.20111083984375 +43889 -0.441925048828125 +43890 -0.217437744140625 +43891 -0.473846435546875 +43892 -0.2147216796875 +43893 -0.464813232421875 +43894 -0.19488525390625 +43895 -0.419097900390625 +43896 -0.156707763671875 +43897 -0.334320068359375 +43898 -0.1082763671875 +43899 -0.227935791015625 +43900 -0.060638427734375 +43901 -0.12347412109375 +43902 -0.01690673828125 +43903 -0.02764892578125 +43904 0.03155517578125 +43905 0.077667236328125 +43906 0.0946044921875 +43907 0.2132568359375 +43908 0.1768798828125 +43909 0.38885498046875 +43910 0.2681884765625 +43911 0.582794189453125 +43912 0.3397216796875 +43913 0.734039306640625 +43914 0.371429443359375 +43915 0.800140380859375 +43916 0.361968994140625 +43917 0.7783203125 +43918 0.309661865234375 +43919 0.6651611328125 +43920 0.2139892578125 +43921 0.45965576171875 +43922 0.092529296875 +43923 0.199188232421875 +43924 -0.02386474609375 +43925 -0.050689697265625 +43926 -0.108367919921875 +43927 -0.23297119140625 +43928 -0.15283203125 +43929 -0.33013916015625 +43930 -0.169677734375 +43931 -0.368408203125 +43932 -0.173675537109375 +43933 -0.378936767578125 +43934 -0.172088623046875 +43935 -0.376983642578125 +43936 -0.173065185546875 +43937 -0.37969970703125 +43938 -0.178680419921875 +43939 -0.391510009765625 +43940 -0.176116943359375 +43941 -0.385345458984375 +43942 -0.15625 +43943 -0.3419189453125 +43944 -0.1292724609375 +43945 -0.28289794921875 +43946 -0.115570068359375 +43947 -0.251617431640625 +43948 -0.12359619140625 +43949 -0.266143798828125 +43950 -0.12823486328125 +43951 -0.273345947265625 +43952 -0.102752685546875 +43953 -0.216796875 +43954 -0.06207275390625 +43955 -0.128265380859375 +43956 -0.03466796875 +43957 -0.068145751953125 +43958 -0.02362060546875 +43959 -0.0430908203125 +43960 -0.015380859375 +43961 -0.024444580078125 +43962 0.005615234375 +43963 0.020721435546875 +43964 0.05450439453125 +43965 0.124481201171875 +43966 0.117584228515625 +43967 0.25787353515625 +43968 0.175140380859375 +43969 0.379119873046875 +43970 0.223236083984375 +43971 0.47991943359375 +43972 0.2467041015625 +43973 0.5281982421875 +43974 0.239471435546875 +43975 0.511138916015625 +43976 0.214447021484375 +43977 0.456207275390625 +43978 0.192352294921875 +43979 0.407470703125 +43980 0.182037353515625 +43981 0.383758544921875 +43982 0.170135498046875 +43983 0.35687255859375 +43984 0.1495361328125 +43985 0.31182861328125 +43986 0.121246337890625 +43987 0.250885009765625 +43988 0.081207275390625 +43989 0.1654052734375 +43990 0.019927978515625 +43991 0.035247802734375 +43992 -0.063751220703125 +43993 -0.142059326171875 +43994 -0.155242919921875 +43995 -0.33563232421875 +43996 -0.249420166015625 +43997 -0.5345458984375 +43998 -0.3382568359375 +43999 -0.72186279296875 +44000 -0.392974853515625 +44001 -0.836669921875 +44002 -0.391693115234375 +44003 -0.8326416015625 +44004 -0.343719482421875 +44005 -0.7296142578125 +44006 -0.27496337890625 +44007 -0.582550048828125 +44008 -0.208343505859375 +44009 -0.440093994140625 +44010 -0.154266357421875 +44011 -0.324310302734375 +44012 -0.09674072265625 +44013 -0.20147705078125 +44014 -0.02301025390625 +44015 -0.044647216796875 +44016 0.04693603515625 +44017 0.103973388671875 +44018 0.093292236328125 +44019 0.202392578125 +44020 0.122650146484375 +44021 0.264495849609375 +44022 0.157928466796875 +44023 0.338897705078125 +44024 0.20770263671875 +44025 0.443817138671875 +44026 0.255859375 +44027 0.545074462890625 +44028 0.290374755859375 +44029 0.6173095703125 +44030 0.30743408203125 +44031 0.6524658203125 +44032 0.31341552734375 +44033 0.66339111328125 +44034 0.311309814453125 +44035 0.6561279296875 +44036 0.289154052734375 +44037 0.606781005859375 +44038 0.239654541015625 +44039 0.501190185546875 +44040 0.169342041015625 +44041 0.352783203125 +44042 0.085479736328125 +44043 0.176544189453125 +44044 -0.015899658203125 +44045 -0.034820556640625 +44046 -0.123443603515625 +44047 -0.258209228515625 +44048 -0.211669921875 +44049 -0.44244384765625 +44050 -0.274658203125 +44051 -0.5753173828125 +44052 -0.31024169921875 +44053 -0.65203857421875 +44054 -0.302978515625 +44055 -0.641632080078125 +44056 -0.262054443359375 +44057 -0.562164306640625 +44058 -0.20989990234375 +44059 -0.458038330078125 +44060 -0.15716552734375 +44061 -0.350555419921875 +44062 -0.114227294921875 +44063 -0.260528564453125 +44064 -0.083038330078125 +44065 -0.192108154296875 +44066 -0.06170654296875 +44067 -0.141937255859375 +44068 -0.046051025390625 +44069 -0.1021728515625 +44070 -0.030792236328125 +44071 -0.062896728515625 +44072 -0.009552001953125 +44073 -0.011932373046875 +44074 0.02398681640625 +44075 0.062835693359375 +44076 0.063690185546875 +44077 0.148712158203125 +44078 0.107696533203125 +44079 0.241729736328125 +44080 0.159820556640625 +44081 0.34912109375 +44082 0.2132568359375 +44083 0.457305908203125 +44084 0.25677490234375 +44085 0.54388427734375 +44086 0.272216796875 +44087 0.5728759765625 +44088 0.240509033203125 +44089 0.506591796875 +44090 0.1646728515625 +44091 0.351226806640625 +44092 0.0645751953125 +44093 0.146514892578125 +44094 -0.033599853515625 +44095 -0.05523681640625 +44096 -0.11102294921875 +44097 -0.21624755859375 +44098 -0.167083740234375 +44099 -0.334930419921875 +44100 -0.19781494140625 +44101 -0.402984619140625 +44102 -0.21392822265625 +44103 -0.4412841796875 +44104 -0.238739013671875 +44105 -0.49578857421875 +44106 -0.269195556640625 +44107 -0.5601806640625 +44108 -0.288360595703125 +44109 -0.600738525390625 +44110 -0.279571533203125 +44111 -0.584228515625 +44112 -0.227020263671875 +44113 -0.47930908203125 +44114 -0.127349853515625 +44115 -0.27935791015625 +44116 0.007110595703125 +44117 -0.0089111328125 +44118 0.1446533203125 +44119 0.268798828125 +44120 0.249664306640625 +44121 0.482818603515625 +44122 0.307464599609375 +44123 0.60369873046875 +44124 0.3277587890625 +44125 0.650421142578125 +44126 0.331451416015625 +44127 0.66400146484375 +44128 0.31719970703125 +44129 0.6414794921875 +44130 0.279998779296875 +44131 0.572540283203125 +44132 0.2406005859375 +44133 0.498138427734375 +44134 0.209747314453125 +44135 0.439453125 +44136 0.176910400390625 +44137 0.375518798828125 +44138 0.126068115234375 +44139 0.274505615234375 +44140 0.04327392578125 +44141 0.1087646484375 +44142 -0.060272216796875 +44143 -0.099395751953125 +44144 -0.16864013671875 +44145 -0.3182373046875 +44146 -0.2825927734375 +44147 -0.5489501953125 +44148 -0.393280029296875 +44149 -0.7738037109375 +44150 -0.474212646484375 +44151 -0.86383056640625 +44152 -0.5087890625 +44153 -0.870391845703125 +44154 -0.506072998046875 +44155 -0.86895751953125 +44156 -0.472808837890625 +44157 -0.861053466796875 +44158 -0.400390625 +44159 -0.765869140625 +44160 -0.283203125 +44161 -0.5301513671875 +44162 -0.124908447265625 +44163 -0.214691162109375 +44164 0.052764892578125 +44165 0.137359619140625 +44166 0.223968505859375 +44167 0.474822998046875 +44168 0.370819091796875 +44169 0.76239013671875 +44170 0.479766845703125 +44171 0.867462158203125 +44172 0.5511474609375 +44173 0.870361328125 +44174 0.579254150390625 +44175 0.86480712890625 +44176 0.56689453125 +44177 0.831817626953125 +44178 0.5264892578125 +44179 0.677581787109375 +44180 0.4610595703125 +44181 0.495880126953125 +44182 0.380096435546875 +44183 0.30767822265625 +44184 0.28485107421875 +44185 0.116180419921875 +44186 0.15936279296875 +44187 -0.110748291015625 +44188 0.000213623046875 +44189 -0.381805419921875 +44190 -0.170989990234375 +44191 -0.6572265625 +44192 -0.32403564453125 +44193 -0.857421875 +44194 -0.43731689453125 +44195 -0.870391845703125 +44196 -0.50726318359375 +44197 -0.870391845703125 +44198 -0.5474853515625 +44199 -0.86444091796875 +44200 -0.576080322265625 +44201 -0.85723876953125 +44202 -0.583892822265625 +44203 -0.790008544921875 +44204 -0.543701171875 +44205 -0.62847900390625 +44206 -0.454010009765625 +44207 -0.3956298828125 +44208 -0.331451416015625 +44209 -0.126708984375 +44210 -0.18994140625 +44211 0.150115966796875 +44212 -0.035430908203125 +44213 0.424041748046875 +44214 0.118408203125 +44215 0.670623779296875 +44216 0.251983642578125 +44217 0.854522705078125 +44218 0.35638427734375 +44219 0.866485595703125 +44220 0.423858642578125 +44221 0.86920166015625 +44222 0.46356201171875 +44223 0.8653564453125 +44224 0.482330322265625 +44225 0.857147216796875 +44226 0.478729248046875 +44227 0.766845703125 +44228 0.455413818359375 +44229 0.628509521484375 +44230 0.409088134765625 +44231 0.462127685546875 +44232 0.352813720703125 +44233 0.297210693359375 +44234 0.292938232421875 +44235 0.14862060546875 +44236 0.218017578125 +44237 -0.00537109375 +44238 0.13189697265625 +44239 -0.15753173828125 +44240 0.032806396484375 +44241 -0.31304931640625 +44242 -0.08624267578125 +44243 -0.48876953125 +44244 -0.20159912109375 +44245 -0.6416015625 +44246 -0.300750732421875 +44247 -0.751373291015625 +44248 -0.395355224609375 +44249 -0.84619140625 +44250 -0.477996826171875 +44251 -0.861297607421875 +44252 -0.532012939453125 +44253 -0.863250732421875 +44254 -0.54150390625 +44255 -0.856597900390625 +44256 -0.512664794921875 +44257 -0.7498779296875 +44258 -0.4747314453125 +44259 -0.624542236328125 +44260 -0.41668701171875 +44261 -0.47808837890625 +44262 -0.30914306640625 +44263 -0.253387451171875 +44264 -0.175201416015625 +44265 0.003692626953125 +44266 -0.04937744140625 +44267 0.2257080078125 +44268 0.074554443359375 +44269 0.427154541015625 +44270 0.212860107421875 +44271 0.643218994140625 +44272 0.36065673828125 +44273 0.855926513671875 +44274 0.488739013671875 +44275 0.870361328125 +44276 0.57208251953125 +44277 0.870361328125 +44278 0.614288330078125 +44279 0.862762451171875 +44280 0.6138916015625 +44281 0.79669189453125 +44282 0.566192626953125 +44283 0.595794677734375 +44284 0.4859619140625 +44285 0.362152099609375 +44286 0.38739013671875 +44287 0.1270751953125 +44288 0.281768798828125 +44289 -0.086944580078125 +44290 0.17059326171875 +44291 -0.2784423828125 +44292 0.034942626953125 +44293 -0.484832763671875 +44294 -0.136199951171875 +44295 -0.729583740234375 +44296 -0.316375732421875 +44297 -0.86688232421875 +44298 -0.47222900390625 +44299 -0.870391845703125 +44300 -0.60150146484375 +44301 -0.86859130859375 +44302 -0.703338623046875 +44303 -0.86279296875 +44304 -0.75860595703125 +44305 -0.817962646484375 +44306 -0.74298095703125 +44307 -0.6116943359375 +44308 -0.65252685546875 +44309 -0.3128662109375 +44310 -0.505126953125 +44311 0.039398193359375 +44312 -0.31121826171875 +44313 0.422821044921875 +44314 -0.08831787109375 +44315 0.805145263671875 +44316 0.12738037109375 +44317 0.870361328125 +44318 0.3056640625 +44319 0.870361328125 +44320 0.440582275390625 +44321 0.860015869140625 +44322 0.528289794921875 +44323 0.727935791015625 +44324 0.565948486328125 +44325 0.48114013671875 +44326 0.566680908203125 +44327 0.2059326171875 +44328 0.542694091796875 +44329 -0.06103515625 +44330 0.499359130859375 +44331 -0.29913330078125 +44332 0.42889404296875 +44333 -0.516204833984375 +44334 0.322998046875 +44335 -0.7252197265625 +44336 0.19488525390625 +44337 -0.85980224609375 +44338 0.0628662109375 +44339 -0.870391845703125 +44340 -0.057281494140625 +44341 -0.870391845703125 +44342 -0.1395263671875 +44343 -0.858062744140625 +44344 -0.18170166015625 +44345 -0.673004150390625 +44346 -0.21197509765625 +44347 -0.42694091796875 +44348 -0.254180908203125 +44349 -0.2100830078125 +44350 -0.30718994140625 +44351 -0.0362548828125 +44352 -0.355377197265625 +44353 0.10943603515625 +44354 -0.388031005859375 +44355 0.23516845703125 +44356 -0.382904052734375 +44357 0.373687744140625 +44358 -0.340972900390625 +44359 0.517791748046875 +44360 -0.29595947265625 +44361 0.602783203125 +44362 -0.24505615234375 +44363 0.635711669921875 +44364 -0.17034912109375 +44365 0.655181884765625 +44366 -0.077178955078125 +44367 0.65948486328125 +44368 0.030120849609375 +44369 0.651275634765625 +44370 0.138427734375 +44371 0.61846923828125 +44372 0.22784423828125 +44373 0.53753662109375 +44374 0.288604736328125 +44375 0.404144287109375 +44376 0.3154296875 +44377 0.22186279296875 +44378 0.30889892578125 +44379 0.003997802734375 +44380 0.278656005859375 +44381 -0.22100830078125 +44382 0.235687255859375 +44383 -0.42449951171875 +44384 0.191375732421875 +44385 -0.579833984375 +44386 0.168548583984375 +44387 -0.641876220703125 +44388 0.16363525390625 +44389 -0.6177978515625 +44390 0.141998291015625 +44391 -0.575531005859375 +44392 0.100799560546875 +44393 -0.526336669921875 +44394 0.06781005859375 +44395 -0.42645263671875 +44396 0.05780029296875 +44397 -0.2581787109375 +44398 0.05133056640625 +44399 -0.068695068359375 +44400 0.027862548828125 +44401 0.09222412109375 +44402 -0.00250244140625 +44403 0.232147216796875 +44404 -0.034210205078125 +44405 0.3509521484375 +44406 -0.083038330078125 +44407 0.410064697265625 +44408 -0.164581298828125 +44409 0.372955322265625 +44410 -0.26751708984375 +44411 0.2554931640625 +44412 -0.363800048828125 +44413 0.10711669921875 +44414 -0.44287109375 +44415 -0.052886962890625 +44416 -0.4852294921875 +44417 -0.186279296875 +44418 -0.46087646484375 +44419 -0.23291015625 +44420 -0.382049560546875 +44421 -0.209442138671875 +44422 -0.2840576171875 +44423 -0.174163818359375 +44424 -0.171417236328125 +44425 -0.126739501953125 +44426 -0.0389404296875 +44427 -0.048126220703125 +44428 0.09814453125 +44429 0.0426025390625 +44430 0.2147216796875 +44431 0.10748291015625 +44432 0.303558349609375 +44433 0.1409912109375 +44434 0.3900146484375 +44435 0.19708251953125 +44436 0.470306396484375 +44437 0.273651123046875 +44438 0.514404296875 +44439 0.31768798828125 +44440 0.528106689453125 +44441 0.341094970703125 +44442 0.52484130859375 +44443 0.368011474609375 +44444 0.4921875 +44445 0.37249755859375 +44446 0.403717041015625 +44447 0.30072021484375 +44448 0.2620849609375 +44449 0.1517333984375 +44450 0.102996826171875 +44451 -0.01470947265625 +44452 -0.06396484375 +44453 -0.1883544921875 +44454 -0.236541748046875 +44455 -0.372711181640625 +44456 -0.38189697265625 +44457 -0.51397705078125 +44458 -0.474700927734375 +44459 -0.57177734375 +44460 -0.508270263671875 +44461 -0.53948974609375 +44462 -0.489776611328125 +44463 -0.43511962890625 +44464 -0.437744140625 +44465 -0.2962646484375 +44466 -0.371826171875 +44467 -0.161102294921875 +44468 -0.299591064453125 +44469 -0.0435791015625 +44470 -0.219818115234375 +44471 0.060394287109375 +44472 -0.141815185546875 +44473 0.13665771484375 +44474 -0.0760498046875 +44475 0.170135498046875 +44476 -0.022918701171875 +44477 0.16552734375 +44478 0.032745361328125 +44479 0.15728759765625 +44480 0.0904541015625 +44481 0.150787353515625 +44482 0.133941650390625 +44483 0.12200927734375 +44484 0.164947509765625 +44485 0.080108642578125 +44486 0.19476318359375 +44487 0.05126953125 +44488 0.235870361328125 +44489 0.062896728515625 +44490 0.274688720703125 +44491 0.09271240234375 +44492 0.284759521484375 +44493 0.092987060546875 +44494 0.27386474609375 +44495 0.07855224609375 +44496 0.250518798828125 +44497 0.06427001953125 +44498 0.20770263671875 +44499 0.0347900390625 +44500 0.146209716796875 +44501 -0.01171875 +44502 0.07861328125 +44503 -0.056060791015625 +44504 0.030426025390625 +44505 -0.055511474609375 +44506 0.004180908203125 +44507 -0.010467529296875 +44508 -0.02618408203125 +44509 0.02508544921875 +44510 -0.0716552734375 +44511 0.025665283203125 +44512 -0.11590576171875 +44513 0.017333984375 +44514 -0.155975341796875 +44515 0.00189208984375 +44516 -0.1962890625 +44517 -0.03173828125 +44518 -0.2294921875 +44519 -0.071502685546875 +44520 -0.264862060546875 +44521 -0.13543701171875 +44522 -0.30078125 +44523 -0.219970703125 +44524 -0.3248291015625 +44525 -0.300506591796875 +44526 -0.33795166015625 +44527 -0.376312255859375 +44528 -0.325103759765625 +44529 -0.416107177734375 +44530 -0.26220703125 +44531 -0.371124267578125 +44532 -0.15203857421875 +44533 -0.242279052734375 +44534 -0.01837158203125 +44535 -0.069732666015625 +44536 0.12530517578125 +44537 0.125640869140625 +44538 0.260223388671875 +44539 0.31268310546875 +44540 0.3651123046875 +44541 0.45501708984375 +44542 0.439727783203125 +44543 0.554779052734375 +44544 0.482666015625 +44545 0.61065673828125 +44546 0.487060546875 +44547 0.610931396484375 +44548 0.43939208984375 +44549 0.531463623046875 +44550 0.348846435546875 +44551 0.3883056640625 +44552 0.24554443359375 +44553 0.23468017578125 +44554 0.144287109375 +44555 0.095245361328125 +44556 0.060821533203125 +44557 -0.00396728515625 +44558 0.0047607421875 +44559 -0.04852294921875 +44560 -0.03125 +44561 -0.055145263671875 +44562 -0.07403564453125 +44563 -0.0758056640625 +44564 -0.13739013671875 +44565 -0.138702392578125 +44566 -0.200775146484375 +44567 -0.209197998046875 +44568 -0.263916015625 +44569 -0.289031982421875 +44570 -0.3262939453125 +44571 -0.37884521484375 +44572 -0.375091552734375 +44573 -0.456329345703125 +44574 -0.407379150390625 +44575 -0.51641845703125 +44576 -0.4014892578125 +44577 -0.519287109375 +44578 -0.354339599609375 +44579 -0.458251953125 +44580 -0.295166015625 +44581 -0.384796142578125 +44582 -0.238739013671875 +44583 -0.323699951171875 +44584 -0.18328857421875 +44585 -0.269287109375 +44586 -0.11578369140625 +44587 -0.1951904296875 +44588 -0.036956787109375 +44589 -0.100006103515625 +44590 0.036956787109375 +44591 -0.01055908203125 +44592 0.121307373046875 +44593 0.1033935546875 +44594 0.218963623046875 +44595 0.24908447265625 +44596 0.299774169921875 +44597 0.373199462890625 +44598 0.353515625 +44599 0.45806884765625 +44600 0.384185791015625 +44601 0.511474609375 +44602 0.40948486328125 +44603 0.565399169921875 +44604 0.4251708984375 +44605 0.61138916015625 +44606 0.399078369140625 +44607 0.5897216796875 +44608 0.32672119140625 +44609 0.4906005859375 +44610 0.21875 +44611 0.33148193359375 +44612 0.095855712890625 +44613 0.147796630859375 +44614 -0.01776123046875 +44615 -0.01873779296875 +44616 -0.1055908203125 +44617 -0.140289306640625 +44618 -0.15283203125 +44619 -0.191986083984375 +44620 -0.164276123046875 +44621 -0.184295654296875 +44622 -0.1636962890625 +44623 -0.161834716796875 +44624 -0.173675537109375 +44625 -0.166595458984375 +44626 -0.19134521484375 +44627 -0.19390869140625 +44628 -0.2060546875 +44629 -0.22442626953125 +44630 -0.22991943359375 +44631 -0.279754638671875 +44632 -0.251983642578125 +44633 -0.3389892578125 +44634 -0.24664306640625 +44635 -0.3543701171875 +44636 -0.22698974609375 +44637 -0.348175048828125 +44638 -0.197052001953125 +44639 -0.32598876953125 +44640 -0.141571044921875 +44641 -0.2581787109375 +44642 -0.058807373046875 +44643 -0.139801025390625 +44644 0.04229736328125 +44645 0.014617919921875 +44646 0.127471923828125 +44647 0.144378662109375 +44648 0.180450439453125 +44649 0.221038818359375 +44650 0.21502685546875 +44651 0.27069091796875 +44652 0.231353759765625 +44653 0.294036865234375 +44654 0.24072265625 +44655 0.311767578125 +44656 0.251708984375 +44657 0.339141845703125 +44658 0.256103515625 +44659 0.360260009765625 +44660 0.246307373046875 +44661 0.360504150390625 +44662 0.2049560546875 +44663 0.308380126953125 +44664 0.120086669921875 +44665 0.18170166015625 +44666 0.006195068359375 +44667 0.0047607421875 +44668 -0.109375 +44669 -0.17559814453125 +44670 -0.20037841796875 +44671 -0.3143310546875 +44672 -0.241455078125 +44673 -0.36785888671875 +44674 -0.24700927734375 +44675 -0.36248779296875 +44676 -0.24237060546875 +44677 -0.343536376953125 +44678 -0.222137451171875 +44679 -0.3018798828125 +44680 -0.18267822265625 +44681 -0.231414794921875 +44682 -0.115814208984375 +44683 -0.117645263671875 +44684 -0.040130615234375 +44685 0.007049560546875 +44686 0.012969970703125 +44687 0.087982177734375 +44688 0.0511474609375 +44689 0.13946533203125 +44690 0.08111572265625 +44691 0.17425537109375 +44692 0.09991455078125 +44693 0.188201904296875 +44694 0.101226806640625 +44695 0.171234130859375 +44696 0.081634521484375 +44697 0.118438720703125 +44698 0.056121826171875 +44699 0.05706787109375 +44700 0.025421142578125 +44701 -0.010711669921875 +44702 -0.014556884765625 +44703 -0.0914306640625 +44704 -0.0511474609375 +44705 -0.162322998046875 +44706 -0.068115234375 +44707 -0.194549560546875 +44708 -0.04345703125 +44709 -0.1492919921875 +44710 0.0257568359375 +44711 -0.02166748046875 +44712 0.103271484375 +44713 0.124053955078125 +44714 0.145843505859375 +44715 0.211151123046875 +44716 0.15435791015625 +44717 0.240447998046875 +44718 0.146484375 +44719 0.242218017578125 +44720 0.12799072265625 +44721 0.2257080078125 +44722 0.101348876953125 +44723 0.194366455078125 +44724 0.0484619140625 +44725 0.115509033203125 +44726 -0.016754150390625 +44727 0.0128173828125 +44728 -0.059967041015625 +44729 -0.053802490234375 +44730 -0.0958251953125 +44731 -0.110626220703125 +44732 -0.147979736328125 +44733 -0.199493408203125 +44734 -0.20159912109375 +44735 -0.29437255859375 +44736 -0.220947265625 +44737 -0.33221435546875 +44738 -0.187286376953125 +44739 -0.27972412109375 +44740 -0.128387451171875 +44741 -0.185333251953125 +44742 -0.089508056640625 +44743 -0.128204345703125 +44744 -0.075225830078125 +44745 -0.115692138671875 +44746 -0.068145751953125 +44747 -0.116455078125 +44748 -0.054718017578125 +44749 -0.105926513671875 +44750 -0.01824951171875 +44751 -0.053955078125 +44752 0.046173095703125 +44753 0.048797607421875 +44754 0.112701416015625 +44755 0.157318115234375 +44756 0.147247314453125 +44757 0.212005615234375 +44758 0.15283203125 +44759 0.218475341796875 +44760 0.163787841796875 +44761 0.23724365234375 +44762 0.201202392578125 +44763 0.30535888671875 +44764 0.241546630859375 +44765 0.38128662109375 +44766 0.2506103515625 +44767 0.404449462890625 +44768 0.239776611328125 +44769 0.3944091796875 +44770 0.2305908203125 +44771 0.3885498046875 +44772 0.20965576171875 +44773 0.362640380859375 +44774 0.152862548828125 +44775 0.27362060546875 +44776 0.058074951171875 +44777 0.11712646484375 +44778 -0.044891357421875 +44779 -0.054901123046875 +44780 -0.126434326171875 +44781 -0.19085693359375 +44782 -0.183502197265625 +44783 -0.28570556640625 +44784 -0.21588134765625 +44785 -0.339263916015625 +44786 -0.23828125 +44787 -0.3775634765625 +44788 -0.27630615234375 +44789 -0.445709228515625 +44790 -0.325103759765625 +44791 -0.535064697265625 +44792 -0.37542724609375 +44793 -0.629058837890625 +44794 -0.410369873046875 +44795 -0.697601318359375 +44796 -0.409271240234375 +44797 -0.70391845703125 +44798 -0.369293212890625 +44799 -0.6424560546875 +44800 -0.27777099609375 +44801 -0.491241455078125 +44802 -0.143585205078125 +44803 -0.265716552734375 +44804 -0.0006103515625 +44805 -0.023712158203125 +44806 0.131622314453125 +44807 0.201751708984375 +44808 0.232513427734375 +44809 0.375823974609375 +44810 0.294281005859375 +44811 0.485076904296875 +44812 0.340789794921875 +44813 0.56884765625 +44814 0.376861572265625 +44815 0.634765625 +44816 0.37554931640625 +44817 0.63763427734375 +44818 0.33013916015625 +44819 0.5660400390625 +44820 0.27197265625 +44821 0.4720458984375 +44822 0.23187255859375 +44823 0.40692138671875 +44824 0.214141845703125 +44825 0.3778076171875 +44826 0.214080810546875 +44827 0.376953125 +44828 0.21221923828125 +44829 0.371978759765625 +44830 0.178619384765625 +44831 0.313140869140625 +44832 0.103546142578125 +44833 0.184417724609375 +44834 0.002105712890625 +44835 0.011199951171875 +44836 -0.10455322265625 +44837 -0.171051025390625 +44838 -0.20166015625 +44839 -0.33740234375 +44840 -0.279815673828125 +44841 -0.47198486328125 +44842 -0.33050537109375 +44843 -0.560394287109375 +44844 -0.34063720703125 +44845 -0.58056640625 +44846 -0.3193359375 +44847 -0.54754638671875 +44848 -0.295013427734375 +44849 -0.508575439453125 +44850 -0.265228271484375 +44851 -0.459503173828125 +44852 -0.226409912109375 +44853 -0.394378662109375 +44854 -0.202117919921875 +44855 -0.35260009765625 +44856 -0.1788330078125 +44857 -0.31170654296875 +44858 -0.111907958984375 +44859 -0.197418212890625 +44860 -0.000152587890625 +44861 -0.007965087890625 +44862 0.126983642578125 +44863 0.207489013671875 +44864 0.24578857421875 +44865 0.409210205078125 +44866 0.34130859375 +44867 0.57208251953125 +44868 0.395599365234375 +44869 0.66595458984375 +44870 0.389495849609375 +44871 0.65875244140625 +44872 0.333282470703125 +44873 0.56744384765625 +44874 0.25067138671875 +44875 0.431396484375 +44876 0.16796875 +44877 0.29443359375 +44878 0.10076904296875 +44879 0.182464599609375 +44880 0.029937744140625 +44881 0.06365966796875 +44882 -0.05291748046875 +44883 -0.075958251953125 +44884 -0.119720458984375 +44885 -0.189422607421875 +44886 -0.167633056640625 +44887 -0.271942138671875 +44888 -0.208160400390625 +44889 -0.342529296875 +44890 -0.21923828125 +44891 -0.364166259765625 +44892 -0.1951904296875 +44893 -0.327239990234375 +44894 -0.163238525390625 +44895 -0.2769775390625 +44896 -0.147705078125 +44897 -0.253692626953125 +44898 -0.140380859375 +44899 -0.24365234375 +44900 -0.112274169921875 +44901 -0.1983642578125 +44902 -0.06243896484375 +44903 -0.116241455078125 +44904 -0.0146484375 +44905 -0.036834716796875 +44906 0.028106689453125 +44907 0.034881591796875 +44908 0.061279296875 +44909 0.09124755859375 +44910 0.07086181640625 +44911 0.10888671875 +44912 0.079559326171875 +44913 0.125518798828125 +44914 0.097412109375 +44915 0.15771484375 +44916 0.108154296875 +44917 0.17828369140625 +44918 0.102203369140625 +44919 0.17108154296875 +44920 0.07598876953125 +44921 0.129974365234375 +44922 0.046051025390625 +44923 0.082427978515625 +44924 0.01202392578125 +44925 0.027679443359375 +44926 -0.04486083984375 +44927 -0.065643310546875 +44928 -0.101654052734375 +44929 -0.15936279296875 +44930 -0.134063720703125 +44931 -0.21307373046875 +44932 -0.1468505859375 +44933 -0.234649658203125 +44934 -0.12567138671875 +44935 -0.2001953125 +44936 -0.076263427734375 +44937 -0.119171142578125 +44938 -0.0185546875 +44939 -0.024749755859375 +44940 0.048980712890625 +44941 0.085784912109375 +44942 0.105712890625 +44943 0.178131103515625 +44944 0.129547119140625 +44945 0.215576171875 +44946 0.12835693359375 +44947 0.211456298828125 +44948 0.1077880859375 +44949 0.17523193359375 +44950 0.080902099609375 +44951 0.128753662109375 +44952 0.065582275390625 +44953 0.1019287109375 +44954 0.049560546875 +44955 0.0743408203125 +44956 0.03118896484375 +44957 0.04327392578125 +44958 0.028106689453125 +44959 0.038177490234375 +44960 0.0506591796875 +44961 0.076263427734375 +44962 0.088958740234375 +44963 0.14105224609375 +44964 0.115386962890625 +44965 0.186431884765625 +44966 0.1158447265625 +44967 0.188812255859375 +44968 0.084869384765625 +44969 0.1390380859375 +44970 0.025360107421875 +44971 0.041778564453125 +44972 -0.0484619140625 +44973 -0.079437255859375 +44974 -0.133453369140625 +44975 -0.219390869140625 +44976 -0.223358154296875 +44977 -0.367828369140625 +44978 -0.300262451171875 +44979 -0.494873046875 +44980 -0.337554931640625 +44981 -0.556243896484375 +44982 -0.309234619140625 +44983 -0.508697509765625 +44984 -0.229339599609375 +44985 -0.3756103515625 +44986 -0.135040283203125 +44987 -0.218902587890625 +44988 -0.041473388671875 +44989 -0.063751220703125 +44990 0.05230712890625 +44991 0.091552734375 +44992 0.13970947265625 +44993 0.23602294921875 +44994 0.204681396484375 +44995 0.342987060546875 +44996 0.236846923828125 +44997 0.39520263671875 +44998 0.234161376953125 +44999 0.389373779296875 +45000 0.19586181640625 +45001 0.324249267578125 +45002 0.136444091796875 +45003 0.224090576171875 +45004 0.077117919921875 +45005 0.124267578125 +45006 0.02520751953125 +45007 0.037078857421875 +45008 -0.002838134765625 +45009 -0.010101318359375 +45010 -0.00836181640625 +45011 -0.019439697265625 +45012 -0.01043701171875 +45013 -0.022796630859375 +45014 0.0020751953125 +45015 -0.001556396484375 +45016 0.036407470703125 +45017 0.056304931640625 +45018 0.066131591796875 +45019 0.106719970703125 +45020 0.059600830078125 +45021 0.096893310546875 +45022 0.026397705078125 +45023 0.042694091796875 +45024 -0.010772705078125 +45025 -0.018035888671875 +45026 -0.046173095703125 +45027 -0.07586669921875 +45028 -0.07293701171875 +45029 -0.11944580078125 +45030 -0.09765625 +45031 -0.15972900390625 +45032 -0.123809814453125 +45033 -0.202606201171875 +45034 -0.15167236328125 +45035 -0.24859619140625 +45036 -0.185699462890625 +45037 -0.30517578125 +45038 -0.21978759765625 +45039 -0.36212158203125 +45040 -0.237152099609375 +45041 -0.39141845703125 +45042 -0.215087890625 +45043 -0.35528564453125 +45044 -0.151397705078125 +45045 -0.249969482421875 +45046 -0.05657958984375 +45047 -0.092864990234375 +45048 0.053131103515625 +45049 0.08905029296875 +45050 0.141387939453125 +45051 0.2352294921875 +45052 0.192047119140625 +45053 0.318817138671875 +45054 0.21636962890625 +45055 0.358642578125 +45056 0.2095947265625 +45057 0.347747802734375 +45058 0.170745849609375 +45059 0.28564453125 +45060 0.13153076171875 +45061 0.223175048828125 +45062 0.11517333984375 +45063 0.196746826171875 +45064 0.1051025390625 +45065 0.179840087890625 +45066 0.090728759765625 +45067 0.155548095703125 +45068 0.08935546875 +45069 0.151214599609375 +45070 0.0947265625 +45071 0.156951904296875 +45072 0.080841064453125 +45073 0.13177490234375 +45074 0.0634765625 +45075 0.100799560546875 +45076 0.057098388671875 +45077 0.087127685546875 +45078 0.038909912109375 +45079 0.05487060546875 +45080 0.000518798828125 +45081 -0.009002685546875 +45082 -0.057861328125 +45083 -0.10400390625 +45084 -0.1358642578125 +45085 -0.229400634765625 +45086 -0.214813232421875 +45087 -0.35552978515625 +45088 -0.2691650390625 +45089 -0.441925048828125 +45090 -0.28961181640625 +45091 -0.473846435546875 +45092 -0.284698486328125 +45093 -0.464813232421875 +45094 -0.257049560546875 +45095 -0.419097900390625 +45096 -0.205078125 +45097 -0.334320068359375 +45098 -0.139739990234375 +45099 -0.227935791015625 +45100 -0.0758056640625 +45101 -0.12347412109375 +45102 -0.017364501953125 +45103 -0.02764892578125 +45104 0.047149658203125 +45105 0.077667236328125 +45106 0.130950927734375 +45107 0.2132568359375 +45108 0.24029541015625 +45109 0.38885498046875 +45110 0.361541748046875 +45111 0.582794189453125 +45112 0.456207275390625 +45113 0.734039306640625 +45114 0.49749755859375 +45115 0.800140380859375 +45116 0.483673095703125 +45117 0.7783203125 +45118 0.412567138671875 +45119 0.6651611328125 +45120 0.283538818359375 +45121 0.45965576171875 +45122 0.120147705078125 +45123 0.199188232421875 +45124 -0.0362548828125 +45125 -0.050689697265625 +45126 -0.149749755859375 +45127 -0.23297119140625 +45128 -0.209381103515625 +45129 -0.33013916015625 +45130 -0.231781005859375 +45131 -0.368408203125 +45132 -0.23675537109375 +45133 -0.378936767578125 +45134 -0.2340087890625 +45135 -0.376983642578125 +45136 -0.2344970703125 +45137 -0.37969970703125 +45138 -0.241058349609375 +45139 -0.391510009765625 +45140 -0.23663330078125 +45141 -0.385345458984375 +45142 -0.20904541015625 +45143 -0.3419189453125 +45144 -0.1719970703125 +45145 -0.28289794921875 +45146 -0.15283203125 +45147 -0.251617431640625 +45148 -0.16290283203125 +45149 -0.266143798828125 +45150 -0.1685791015625 +45151 -0.273345947265625 +45152 -0.1341552734375 +45153 -0.216796875 +45154 -0.079620361328125 +45155 -0.128265380859375 +45156 -0.0430908203125 +45157 -0.068145751953125 +45158 -0.02862548828125 +45159 -0.0430908203125 +45160 -0.018096923828125 +45161 -0.024444580078125 +45162 0.009368896484375 +45163 0.020721435546875 +45164 0.0740966796875 +45165 0.124481201171875 +45166 0.157806396484375 +45167 0.25787353515625 +45168 0.234130859375 +45169 0.379119873046875 +45170 0.2978515625 +45171 0.47991943359375 +45172 0.32867431640625 +45173 0.5281982421875 +45174 0.3184814453125 +45175 0.511138916015625 +45176 0.284576416015625 +45177 0.456207275390625 +45178 0.2547607421875 +45179 0.407470703125 +45180 0.240875244140625 +45181 0.383758544921875 +45182 0.22503662109375 +45183 0.35687255859375 +45184 0.197723388671875 +45185 0.31182861328125 +45186 0.160308837890625 +45187 0.250885009765625 +45188 0.10723876953125 +45189 0.1654052734375 +45190 0.0257568359375 +45191 0.035247802734375 +45192 -0.085723876953125 +45193 -0.142059326171875 +45194 -0.20770263671875 +45195 -0.33563232421875 +45196 -0.333282470703125 +45197 -0.5345458984375 +45198 -0.4517822265625 +45199 -0.72186279296875 +45200 -0.524658203125 +45201 -0.836669921875 +45202 -0.52264404296875 +45203 -0.8326416015625 +45204 -0.458221435546875 +45205 -0.7296142578125 +45206 -0.366119384765625 +45207 -0.582550048828125 +45208 -0.277008056640625 +45209 -0.440093994140625 +45210 -0.20477294921875 +45211 -0.324310302734375 +45212 -0.1280517578125 +45213 -0.20147705078125 +45214 -0.029754638671875 +45215 -0.044647216796875 +45216 0.0634765625 +45217 0.103973388671875 +45218 0.1251220703125 +45219 0.202392578125 +45220 0.163970947265625 +45221 0.264495849609375 +45222 0.210784912109375 +45223 0.338897705078125 +45224 0.277069091796875 +45225 0.443817138671875 +45226 0.34124755859375 +45227 0.545074462890625 +45228 0.387237548828125 +45229 0.6173095703125 +45230 0.409942626953125 +45231 0.6524658203125 +45232 0.417449951171875 +45233 0.66339111328125 +45234 0.413543701171875 +45235 0.6561279296875 +45236 0.383056640625 +45237 0.606781005859375 +45238 0.3170166015625 +45239 0.501190185546875 +45240 0.223846435546875 +45241 0.352783203125 +45242 0.113037109375 +45243 0.176544189453125 +45244 -0.020050048828125 +45245 -0.034820556640625 +45246 -0.16082763671875 +45247 -0.258209228515625 +45248 -0.2769775390625 +45249 -0.44244384765625 +45250 -0.360809326171875 +45251 -0.5753173828125 +45252 -0.4093017578125 +45253 -0.65203857421875 +45254 -0.402862548828125 +45255 -0.641632080078125 +45256 -0.3529052734375 +45257 -0.562164306640625 +45258 -0.287506103515625 +45259 -0.458038330078125 +45260 -0.220062255859375 +45261 -0.350555419921875 +45262 -0.163726806640625 +45263 -0.260528564453125 +45264 -0.121063232421875 +45265 -0.192108154296875 +45266 -0.089935302734375 +45267 -0.141937255859375 +45268 -0.065338134765625 +45269 -0.1021728515625 +45270 -0.040985107421875 +45271 -0.062896728515625 +45272 -0.009124755859375 +45273 -0.011932373046875 +45274 0.037872314453125 +45275 0.062835693359375 +45276 0.092010498046875 +45277 0.148712158203125 +45278 0.1507568359375 +45279 0.241729736328125 +45280 0.21868896484375 +45281 0.34912109375 +45282 0.2872314453125 +45283 0.457305908203125 +45284 0.342193603515625 +45285 0.54388427734375 +45286 0.36083984375 +45287 0.5728759765625 +45288 0.3193359375 +45289 0.506591796875 +45290 0.2215576171875 +45291 0.351226806640625 +45292 0.092620849609375 +45293 0.146514892578125 +45294 -0.034454345703125 +45295 -0.05523681640625 +45296 -0.13580322265625 +45297 -0.21624755859375 +45298 -0.210418701171875 +45299 -0.334930419921875 +45300 -0.253082275390625 +45301 -0.402984619140625 +45302 -0.277008056640625 +45303 -0.4412841796875 +45304 -0.311279296875 +45305 -0.49578857421875 +45306 -0.351898193359375 +45307 -0.5601806640625 +45308 -0.3775634765625 +45309 -0.600738525390625 +45310 -0.36724853515625 +45311 -0.584228515625 +45312 -0.30084228515625 +45313 -0.47930908203125 +45314 -0.173492431640625 +45315 -0.27935791015625 +45316 -0.000518798828125 +45317 -0.0089111328125 +45318 0.17681884765625 +45319 0.268798828125 +45320 0.31207275390625 +45321 0.482818603515625 +45322 0.386199951171875 +45323 0.60369873046875 +45324 0.412200927734375 +45325 0.650421142578125 +45326 0.417633056640625 +45327 0.66400146484375 +45328 0.400665283203125 +45329 0.6414794921875 +45330 0.35455322265625 +45331 0.572540283203125 +45332 0.306427001953125 +45333 0.498138427734375 +45334 0.270172119140625 +45335 0.439453125 +45336 0.231689453125 +45337 0.375518798828125 +45338 0.169525146484375 +45339 0.274505615234375 +45340 0.065032958984375 +45341 0.1087646484375 +45342 -0.067352294921875 +45343 -0.099395751953125 +45344 -0.206878662109375 +45345 -0.3182373046875 +45346 -0.35467529296875 +45347 -0.5489501953125 +45348 -0.499237060546875 +45349 -0.7738037109375 +45350 -0.60565185546875 +45351 -0.86383056640625 +45352 -0.65203857421875 +45353 -0.870391845703125 +45354 -0.6502685546875 +45355 -0.86895751953125 +45356 -0.609130859375 +45357 -0.861053466796875 +45358 -0.51708984375 +45359 -0.765869140625 +45360 -0.3665771484375 +45361 -0.5301513671875 +45362 -0.16217041015625 +45363 -0.214691162109375 +45364 0.0677490234375 +45365 0.137359619140625 +45366 0.28936767578125 +45367 0.474822998046875 +45368 0.479339599609375 +45369 0.76239013671875 +45370 0.6199951171875 +45371 0.867462158203125 +45372 0.7119140625 +45373 0.870361328125 +45374 0.747650146484375 +45375 0.86480712890625 +45376 0.73095703125 +45377 0.831817626953125 +45378 0.67816162109375 +45379 0.677581787109375 +45380 0.593231201171875 +45381 0.495880126953125 +45382 0.48858642578125 +45383 0.30767822265625 +45384 0.365692138671875 +45385 0.116180419921875 +45386 0.20343017578125 +45387 -0.110748291015625 +45388 -0.002899169921875 +45389 -0.381805419921875 +45390 -0.225006103515625 +45391 -0.6572265625 +45392 -0.42333984375 +45393 -0.857421875 +45394 -0.569580078125 +45395 -0.870391845703125 +45396 -0.6591796875 +45397 -0.870391845703125 +45398 -0.710205078125 +45399 -0.86444091796875 +45400 -0.74658203125 +45401 -0.85723876953125 +45402 -0.75628662109375 +45403 -0.790008544921875 +45404 -0.703460693359375 +45405 -0.62847900390625 +45406 -0.586090087890625 +45407 -0.3956298828125 +45408 -0.426055908203125 +45409 -0.126708984375 +45410 -0.2415771484375 +45411 0.150115966796875 +45412 -0.0404052734375 +45413 0.424041748046875 +45414 0.159576416015625 +45415 0.670623779296875 +45416 0.332763671875 +45417 0.854522705078125 +45418 0.467559814453125 +45419 0.866485595703125 +45420 0.55389404296875 +45421 0.86920166015625 +45422 0.603973388671875 +45423 0.8653564453125 +45424 0.626861572265625 +45425 0.857147216796875 +45426 0.620758056640625 +45427 0.766845703125 +45428 0.5892333984375 +45429 0.628509521484375 +45430 0.5279541015625 +45431 0.462127685546875 +45432 0.454193115234375 +45433 0.297210693359375 +45434 0.376251220703125 +45435 0.14862060546875 +45436 0.278961181640625 +45437 -0.00537109375 +45438 0.167327880859375 +45439 -0.15753173828125 +45440 0.038909912109375 +45441 -0.31304931640625 +45442 -0.115631103515625 +45443 -0.48876953125 +45444 -0.2652587890625 +45445 -0.6416015625 +45446 -0.3936767578125 +45447 -0.751373291015625 +45448 -0.51629638671875 +45449 -0.84619140625 +45450 -0.62347412109375 +45451 -0.861297607421875 +45452 -0.693328857421875 +45453 -0.863250732421875 +45454 -0.70501708984375 +45455 -0.856597900390625 +45456 -0.66668701171875 +45457 -0.7498779296875 +45458 -0.61688232421875 +45459 -0.624542236328125 +45460 -0.541046142578125 +45461 -0.47808837890625 +45462 -0.400421142578125 +45463 -0.253387451171875 +45464 -0.225372314453125 +45465 0.003692626953125 +45466 -0.061279296875 +45467 0.2257080078125 +45468 0.10015869140625 +45469 0.427154541015625 +45470 0.280517578125 +45471 0.643218994140625 +45472 0.47344970703125 +45473 0.855926513671875 +45474 0.6405029296875 +45475 0.870361328125 +45476 0.74884033203125 +45477 0.870361328125 +45478 0.803314208984375 +45479 0.862762451171875 +45480 0.80206298828125 +45481 0.79669189453125 +45482 0.7388916015625 +45483 0.595794677734375 +45484 0.63323974609375 +45485 0.362152099609375 +45486 0.503814697265625 +45487 0.1270751953125 +45488 0.36474609375 +45489 -0.086944580078125 +45490 0.21746826171875 +45491 -0.2784423828125 +45492 0.038909912109375 +45493 -0.484832763671875 +45494 -0.18359375 +45495 -0.729583740234375 +45496 -0.416412353515625 +45497 -0.86688232421875 +45498 -0.617462158203125 +45499 -0.870391845703125 +45500 -0.78350830078125 +45501 -0.86859130859375 +45502 -0.86090087890625 +45503 -0.86279296875 +45504 -0.86846923828125 +45505 -0.817962646484375 +45506 -0.866180419921875 +45507 -0.6116943359375 +45508 -0.845306396484375 +45509 -0.3128662109375 +45510 -0.65655517578125 +45511 0.039398193359375 +45512 -0.408538818359375 +45513 0.422821044921875 +45514 -0.123504638671875 +45515 0.805145263671875 +45516 0.153228759765625 +45517 0.870361328125 +45518 0.3836669921875 +45519 0.870361328125 +45520 0.55987548828125 +45521 0.860015869140625 +45522 0.676605224609375 +45523 0.727935791015625 +45524 0.72991943359375 +45525 0.48114013671875 +45526 0.73577880859375 +45527 0.2059326171875 +45528 0.70904541015625 +45529 -0.06103515625 +45530 0.656280517578125 +45531 -0.29913330078125 +45532 0.56781005859375 +45533 -0.516204833984375 +45534 0.4334716796875 +45535 -0.7252197265625 +45536 0.269866943359375 +45537 -0.85980224609375 +45538 0.100006103515625 +45539 -0.870391845703125 +45540 -0.056182861328125 +45541 -0.870391845703125 +45542 -0.166046142578125 +45543 -0.858062744140625 +45544 -0.226409912109375 +45545 -0.673004150390625 +45546 -0.271759033203125 +45547 -0.42694091796875 +45548 -0.331146240234375 +45549 -0.2100830078125 +45550 -0.402801513671875 +45551 -0.0362548828125 +45552 -0.46710205078125 +45553 0.10943603515625 +45554 -0.51055908203125 +45555 0.23516845703125 +45556 -0.505523681640625 +45557 0.373687744140625 +45558 -0.45318603515625 +45559 0.517791748046875 +45560 -0.3953857421875 +45561 0.602783203125 +45562 -0.32879638671875 +45563 0.635711669921875 +45564 -0.231475830078125 +45565 0.655181884765625 +45566 -0.11029052734375 +45567 0.65948486328125 +45568 0.02935791015625 +45569 0.651275634765625 +45570 0.170745849609375 +45571 0.61846923828125 +45572 0.288299560546875 +45573 0.53753662109375 +45574 0.369232177734375 +45575 0.404144287109375 +45576 0.406524658203125 +45577 0.22186279296875 +45578 0.4007568359375 +45579 0.003997802734375 +45580 0.36419677734375 +45581 -0.22100830078125 +45582 0.31097412109375 +45583 -0.42449951171875 +45584 0.25567626953125 +45585 -0.579833984375 +45586 0.227874755859375 +45587 -0.641876220703125 +45588 0.2227783203125 +45589 -0.6177978515625 +45590 0.19537353515625 +45591 -0.575531005859375 +45592 0.14190673828125 +45593 -0.526336669921875 +45594 0.0985107421875 +45595 -0.42645263671875 +45596 0.084381103515625 +45597 -0.2581787109375 +45598 0.074371337890625 +45599 -0.068695068359375 +45600 0.0418701171875 +45601 0.09222412109375 +45602 0.0001220703125 +45603 0.232147216796875 +45604 -0.043487548828125 +45605 0.3509521484375 +45606 -0.10931396484375 +45607 0.410064697265625 +45608 -0.217498779296875 +45609 0.372955322265625 +45610 -0.35321044921875 +45611 0.2554931640625 +45612 -0.47991943359375 +45613 0.10711669921875 +45614 -0.58380126953125 +45615 -0.052886962890625 +45616 -0.6395263671875 +45617 -0.186279296875 +45618 -0.608154296875 +45619 -0.23291015625 +45620 -0.5054931640625 +45621 -0.209442138671875 +45622 -0.377471923828125 +45623 -0.174163818359375 +45624 -0.230010986328125 +45625 -0.126739501953125 +45626 -0.056396484375 +45627 -0.048126220703125 +45628 0.123504638671875 +45629 0.0426025390625 +45630 0.276947021484375 +45631 0.10748291015625 +45632 0.3944091796875 +45633 0.1409912109375 +45634 0.508697509765625 +45635 0.19708251953125 +45636 0.614837646484375 +45637 0.273651123046875 +45638 0.673675537109375 +45639 0.31768798828125 +45640 0.69268798828125 +45641 0.341094970703125 +45642 0.68927001953125 +45643 0.368011474609375 +45644 0.647247314453125 +45645 0.37249755859375 +45646 0.53228759765625 +45647 0.30072021484375 +45648 0.34783935546875 +45649 0.1517333984375 +45650 0.14031982421875 +45651 -0.01470947265625 +45652 -0.0777587890625 +45653 -0.1883544921875 +45654 -0.30340576171875 +45655 -0.372711181640625 +45656 -0.493865966796875 +45657 -0.51397705078125 +45658 -0.616119384765625 +45659 -0.57177734375 +45660 -0.661407470703125 +45661 -0.53948974609375 +45662 -0.639007568359375 +45663 -0.43511962890625 +45664 -0.57281494140625 +45665 -0.2962646484375 +45666 -0.488311767578125 +45667 -0.161102294921875 +45668 -0.395294189453125 +45669 -0.0435791015625 +45670 -0.292144775390625 +45671 0.060394287109375 +45672 -0.190948486328125 +45673 0.13665771484375 +45674 -0.10528564453125 +45675 0.170135498046875 +45676 -0.03570556640625 +45677 0.16552734375 +45678 0.037506103515625 +45679 0.15728759765625 +45680 0.11358642578125 +45681 0.150787353515625 +45682 0.17138671875 +45683 0.12200927734375 +45684 0.213104248046875 +45685 0.080108642578125 +45686 0.253265380859375 +45687 0.05126953125 +45688 0.308013916015625 +45689 0.062896728515625 +45690 0.35968017578125 +45691 0.09271240234375 +45692 0.373809814453125 +45693 0.092987060546875 +45694 0.360443115234375 +45695 0.07855224609375 +45696 0.33062744140625 +45697 0.06427001953125 +45698 0.27520751953125 +45699 0.0347900390625 +45700 0.195220947265625 +45701 -0.01171875 +45702 0.10699462890625 +45703 -0.056060791015625 +45704 0.043670654296875 +45705 -0.055511474609375 +45706 0.008636474609375 +45707 -0.010467529296875 +45708 -0.031951904296875 +45709 0.02508544921875 +45710 -0.092254638671875 +45711 0.025665283203125 +45712 -0.150970458984375 +45713 0.017333984375 +45714 -0.2042236328125 +45715 0.00189208984375 +45716 -0.2576904296875 +45717 -0.03173828125 +45718 -0.301727294921875 +45719 -0.071502685546875 +45720 -0.348388671875 +45721 -0.13543701171875 +45722 -0.39544677734375 +45723 -0.219970703125 +45724 -0.426849365234375 +45725 -0.300506591796875 +45726 -0.44378662109375 +45727 -0.376312255859375 +45728 -0.4267578125 +45729 -0.416107177734375 +45730 -0.34454345703125 +45731 -0.371124267578125 +45732 -0.200714111328125 +45733 -0.242279052734375 +45734 -0.0262451171875 +45735 -0.069732666015625 +45736 0.16131591796875 +45737 0.125640869140625 +45738 0.337554931640625 +45739 0.31268310546875 +45740 0.474822998046875 +45741 0.45501708984375 +45742 0.57275390625 +45743 0.554779052734375 +45744 0.629180908203125 +45745 0.61065673828125 +45746 0.635284423828125 +45747 0.610931396484375 +45748 0.57427978515625 +45749 0.531463623046875 +45750 0.457977294921875 +45751 0.3883056640625 +45752 0.324615478515625 +45753 0.23468017578125 +45754 0.193115234375 +45755 0.095245361328125 +45756 0.08367919921875 +45757 -0.00396728515625 +45758 0.00872802734375 +45759 -0.04852294921875 +45760 -0.040863037109375 +45761 -0.055145263671875 +45762 -0.098785400390625 +45763 -0.0758056640625 +45764 -0.182342529296875 +45765 -0.138702392578125 +45766 -0.265350341796875 +45767 -0.209197998046875 +45768 -0.34735107421875 +45769 -0.289031982421875 +45770 -0.427581787109375 +45771 -0.37884521484375 +45772 -0.489776611328125 +45773 -0.456329345703125 +45774 -0.53021240234375 +45775 -0.51641845703125 +45776 -0.52154541015625 +45777 -0.519287109375 +45778 -0.4599609375 +45779 -0.458251953125 +45780 -0.382568359375 +45781 -0.384796142578125 +45782 -0.308258056640625 +45783 -0.323699951171875 +45784 -0.2349853515625 +45785 -0.269287109375 +45786 -0.146453857421875 +45787 -0.1951904296875 +45788 -0.043701171875 +45789 -0.100006103515625 +45790 0.052581787109375 +45791 -0.01055908203125 +45792 0.161651611328125 +45793 0.1033935546875 +45794 0.28704833984375 +45795 0.24908447265625 +45796 0.39056396484375 +45797 0.373199462890625 +45798 0.459136962890625 +45799 0.45806884765625 +45800 0.49786376953125 +45801 0.511474609375 +45802 0.5291748046875 +45803 0.565399169921875 +45804 0.547760009765625 +45805 0.61138916015625 +45806 0.512969970703125 +45807 0.5897216796875 +45808 0.41925048828125 +45809 0.4906005859375 +45810 0.280242919921875 +45811 0.33148193359375 +45812 0.12225341796875 +45813 0.147796630859375 +45814 -0.02398681640625 +45815 -0.01873779296875 +45816 -0.137451171875 +45817 -0.140289306640625 +45818 -0.19927978515625 +45819 -0.191986083984375 +45820 -0.2154541015625 +45821 -0.184295654296875 +45822 -0.215972900390625 +45823 -0.161834716796875 +45824 -0.229339599609375 +45825 -0.166595458984375 +45826 -0.251953125 +45827 -0.19390869140625 +45828 -0.270294189453125 +45829 -0.22442626953125 +45830 -0.29986572265625 +45831 -0.279754638671875 +45832 -0.32672119140625 +45833 -0.3389892578125 +45834 -0.318389892578125 +45835 -0.3543701171875 +45836 -0.2916259765625 +45837 -0.348175048828125 +45838 -0.251678466796875 +45839 -0.32598876953125 +45840 -0.179229736328125 +45841 -0.2581787109375 +45842 -0.072174072265625 +45843 -0.139801025390625 +45844 0.058013916015625 +45845 0.014617919921875 +45846 0.167694091796875 +45847 0.144378662109375 +45848 0.236053466796875 +45849 0.221038818359375 +45850 0.2806396484375 +45851 0.27069091796875 +45852 0.301544189453125 +45853 0.294036865234375 +45854 0.31317138671875 +45855 0.311767578125 +45856 0.326507568359375 +45857 0.339141845703125 +45858 0.331207275390625 +45859 0.360260009765625 +45860 0.317626953125 +45861 0.360504150390625 +45862 0.263580322265625 +45863 0.308380126953125 +45864 0.15374755859375 +45865 0.18170166015625 +45866 0.00677490234375 +45867 0.0047607421875 +45868 -0.14227294921875 +45869 -0.17559814453125 +45870 -0.259735107421875 +45871 -0.3143310546875 +45872 -0.313018798828125 +45873 -0.36785888671875 +45874 -0.320556640625 +45875 -0.36248779296875 +45876 -0.3148193359375 +45877 -0.343536376953125 +45878 -0.288848876953125 +45879 -0.3018798828125 +45880 -0.238067626953125 +45881 -0.231414794921875 +45882 -0.1519775390625 +45883 -0.117645263671875 +45884 -0.054412841796875 +45885 0.007049560546875 +45886 0.01434326171875 +45887 0.087982177734375 +45888 0.0640869140625 +45889 0.13946533203125 +45890 0.103363037109375 +45891 0.17425537109375 +45892 0.128326416015625 +45893 0.188201904296875 +45894 0.13079833984375 +45895 0.171234130859375 +45896 0.1064453125 +45897 0.118438720703125 +45898 0.0743408203125 +45899 0.05706787109375 +45900 0.035400390625 +45901 -0.010711669921875 +45902 -0.015625 +45903 -0.0914306640625 +45904 -0.0625 +45905 -0.162322998046875 +45906 -0.084381103515625 +45907 -0.194549560546875 +45908 -0.05303955078125 +45909 -0.1492919921875 +45910 0.035247802734375 +45911 -0.02166748046875 +45912 0.134063720703125 +45913 0.124053955078125 +45914 0.188018798828125 +45915 0.211151123046875 +45916 0.19830322265625 +45917 0.240447998046875 +45918 0.18756103515625 +45919 0.242218017578125 +45920 0.16326904296875 +45921 0.2257080078125 +45922 0.128570556640625 +45923 0.194366455078125 +45924 0.060333251953125 +45925 0.115509033203125 +45926 -0.02362060546875 +45927 0.0128173828125 +45928 -0.079254150390625 +45929 -0.053802490234375 +45930 -0.125335693359375 +45931 -0.110626220703125 +45932 -0.192169189453125 +45933 -0.199493408203125 +45934 -0.2607421875 +45935 -0.29437255859375 +45936 -0.285247802734375 +45937 -0.33221435546875 +45938 -0.24169921875 +45939 -0.27972412109375 +45940 -0.165740966796875 +45941 -0.185333251953125 +45942 -0.11541748046875 +45943 -0.128204345703125 +45944 -0.096588134765625 +45945 -0.115692138671875 +45946 -0.087005615234375 +45947 -0.116455078125 +45948 -0.069366455078125 +45949 -0.105926513671875 +45950 -0.02227783203125 +45951 -0.053955078125 +45952 0.060577392578125 +45953 0.048797607421875 +45954 0.146026611328125 +45955 0.157318115234375 +45956 0.190399169921875 +45957 0.212005615234375 +45958 0.19757080078125 +45959 0.218475341796875 +45960 0.211517333984375 +45961 0.23724365234375 +45962 0.25927734375 +45963 0.30535888671875 +45964 0.310760498046875 +45965 0.38128662109375 +45966 0.322113037109375 +45967 0.404449462890625 +45968 0.30792236328125 +45969 0.3944091796875 +45970 0.29583740234375 +45971 0.3885498046875 +45972 0.2686767578125 +45973 0.362640380859375 +45974 0.195556640625 +45975 0.27362060546875 +45976 0.07373046875 +45977 0.11712646484375 +45978 -0.05853271484375 +45979 -0.054901123046875 +45980 -0.16326904296875 +45981 -0.19085693359375 +45982 -0.236572265625 +45983 -0.28570556640625 +45984 -0.27813720703125 +45985 -0.339263916015625 +45986 -0.306793212890625 +45987 -0.3775634765625 +45988 -0.35540771484375 +45989 -0.445709228515625 +45990 -0.417816162109375 +45991 -0.535064697265625 +45992 -0.48211669921875 +45993 -0.629058837890625 +45994 -0.52667236328125 +45995 -0.697601318359375 +45996 -0.525054931640625 +45997 -0.70391845703125 +45998 -0.47357177734375 +45999 -0.6424560546875 +46000 -0.356597900390625 +46001 -0.491241455078125 +46002 -0.185791015625 +46003 -0.265716552734375 +46004 -0.003570556640625 +46005 -0.023712158203125 +46006 0.1656494140625 +46007 0.201751708984375 +46008 0.296295166015625 +46009 0.375823974609375 +46010 0.37841796875 +46011 0.485076904296875 +46012 0.440521240234375 +46013 0.56884765625 +46014 0.4881591796875 +46015 0.634765625 +46016 0.488494873046875 +46017 0.63763427734375 +46018 0.433349609375 +46019 0.5660400390625 +46020 0.36083984375 +46021 0.4720458984375 +46022 0.308502197265625 +46023 0.40692138671875 +46024 0.2818603515625 +46025 0.3778076171875 +46026 0.27557373046875 +46027 0.376953125 +46028 0.266387939453125 +46029 0.371978759765625 +46030 0.218414306640625 +46031 0.313140869140625 +46032 0.1202392578125 +46033 0.184417724609375 +46034 -0.0093994140625 +46035 0.011199951171875 +46036 -0.144561767578125 +46037 -0.171051025390625 +46038 -0.2669677734375 +46039 -0.33740234375 +46040 -0.365020751953125 +46041 -0.47198486328125 +46042 -0.42828369140625 +46043 -0.560394287109375 +46044 -0.440826416015625 +46045 -0.58056640625 +46046 -0.4136962890625 +46047 -0.54754638671875 +46048 -0.381500244140625 +46049 -0.508575439453125 +46050 -0.341461181640625 +46051 -0.459503173828125 +46052 -0.28948974609375 +46053 -0.394378662109375 +46054 -0.254486083984375 +46055 -0.35260009765625 +46056 -0.2203369140625 +46057 -0.31170654296875 +46058 -0.13323974609375 +46059 -0.197418212890625 +46060 0.00787353515625 +46061 -0.007965087890625 +46062 0.167083740234375 +46063 0.207489013671875 +46064 0.315338134765625 +46065 0.409210205078125 +46066 0.434295654296875 +46067 0.57208251953125 +46068 0.502044677734375 +46069 0.66595458984375 +46070 0.495269775390625 +46071 0.65875244140625 +46072 0.42645263671875 +46073 0.56744384765625 +46074 0.324371337890625 +46075 0.431396484375 +46076 0.221160888671875 +46077 0.29443359375 +46078 0.135894775390625 +46079 0.182464599609375 +46080 0.04510498046875 +46081 0.06365966796875 +46082 -0.06121826171875 +46083 -0.075958251953125 +46084 -0.1473388671875 +46085 -0.189422607421875 +46086 -0.209686279296875 +46087 -0.271942138671875 +46088 -0.262786865234375 +46089 -0.342529296875 +46090 -0.278594970703125 +46091 -0.364166259765625 +46092 -0.2498779296875 +46093 -0.327239990234375 +46094 -0.211029052734375 +46095 -0.2769775390625 +46096 -0.1927490234375 +46097 -0.253692626953125 +46098 -0.184600830078125 +46099 -0.24365234375 +46100 -0.149749755859375 +46101 -0.1983642578125 +46102 -0.087005615234375 +46103 -0.116241455078125 +46104 -0.026397705078125 +46105 -0.036834716796875 +46106 0.028228759765625 +46107 0.034881591796875 +46108 0.071075439453125 +46109 0.09124755859375 +46110 0.08441162109375 +46111 0.10888671875 +46112 0.096893310546875 +46113 0.125518798828125 +46114 0.121124267578125 +46115 0.15771484375 +46116 0.136444091796875 +46117 0.17828369140625 +46118 0.130584716796875 +46119 0.17108154296875 +46120 0.098968505859375 +46121 0.129974365234375 +46122 0.06243896484375 +46123 0.082427978515625 +46124 0.020477294921875 +46125 0.027679443359375 +46126 -0.05072021484375 +46127 -0.065643310546875 +46128 -0.122161865234375 +46129 -0.15936279296875 +46130 -0.163116455078125 +46131 -0.21307373046875 +46132 -0.179595947265625 +46133 -0.234649658203125 +46134 -0.153411865234375 +46135 -0.2001953125 +46136 -0.091766357421875 +46137 -0.119171142578125 +46138 -0.019866943359375 +46139 -0.024749755859375 +46140 0.0643310546875 +46141 0.085784912109375 +46142 0.134735107421875 +46143 0.178131103515625 +46144 0.1634521484375 +46145 0.215576171875 +46146 0.16058349609375 +46147 0.211456298828125 +46148 0.133331298828125 +46149 0.17523193359375 +46150 0.0982666015625 +46151 0.128753662109375 +46152 0.078094482421875 +46153 0.1019287109375 +46154 0.057342529296875 +46155 0.0743408203125 +46156 0.033905029296875 +46157 0.04327392578125 +46158 0.0301513671875 +46159 0.038177490234375 +46160 0.05914306640625 +46161 0.076263427734375 +46162 0.10833740234375 +46163 0.14105224609375 +46164 0.1427001953125 +46165 0.186431884765625 +46166 0.144317626953125 +46167 0.188812255859375 +46168 0.10626220703125 +46169 0.1390380859375 +46170 0.0321044921875 +46171 0.041778564453125 +46172 -0.06024169921875 +46173 -0.079437255859375 +46174 -0.16680908203125 +46175 -0.219390869140625 +46176 -0.27978515625 +46177 -0.367828369140625 +46178 -0.376495361328125 +46179 -0.494873046875 +46180 -0.42327880859375 +46181 -0.556243896484375 +46182 -0.38726806640625 +46183 -0.508697509765625 +46184 -0.28619384765625 +46185 -0.3756103515625 +46186 -0.1671142578125 +46187 -0.218902587890625 +46188 -0.049163818359375 +46189 -0.063751220703125 +46190 0.06890869140625 +46191 0.091552734375 +46192 0.178802490234375 +46193 0.23602294921875 +46194 0.260223388671875 +46195 0.342987060546875 +46196 0.300048828125 +46197 0.39520263671875 +46198 0.2957763671875 +46199 0.389373779296875 +46200 0.246429443359375 +46201 0.324249267578125 +46202 0.170440673828125 +46203 0.224090576171875 +46204 0.094696044921875 +46205 0.124267578125 +46206 0.02850341796875 +46207 0.037078857421875 +46208 -0.007293701171875 +46209 -0.010101318359375 +46210 -0.01434326171875 +46211 -0.019439697265625 +46212 -0.016845703125 +46213 -0.022796630859375 +46214 -0.00067138671875 +46215 -0.001556396484375 +46216 0.04327392578125 +46217 0.056304931640625 +46218 0.081512451171875 +46219 0.106719970703125 +46220 0.073944091796875 +46221 0.096893310546875 +46222 0.03265380859375 +46223 0.042694091796875 +46224 -0.01361083984375 +46225 -0.018035888671875 +46226 -0.057647705078125 +46227 -0.07586669921875 +46228 -0.090850830078125 +46229 -0.11944580078125 +46230 -0.121551513671875 +46231 -0.15972900390625 +46232 -0.154205322265625 +46233 -0.202606201171875 +46234 -0.189178466796875 +46235 -0.24859619140625 +46236 -0.232147216796875 +46237 -0.30517578125 +46238 -0.275360107421875 +46239 -0.36212158203125 +46240 -0.297576904296875 +46241 -0.39141845703125 +46242 -0.270050048828125 +46243 -0.35528564453125 +46244 -0.18994140625 +46245 -0.249969482421875 +46246 -0.07049560546875 +46247 -0.092864990234375 +46248 0.067779541015625 +46249 0.08905029296875 +46250 0.17889404296875 +46251 0.2352294921875 +46252 0.242462158203125 +46253 0.318817138671875 +46254 0.272735595703125 +46255 0.358642578125 +46256 0.26446533203125 +46257 0.347747802734375 +46258 0.21728515625 +46259 0.28564453125 +46260 0.169830322265625 +46261 0.223175048828125 +46262 0.14971923828125 +46263 0.196746826171875 +46264 0.1368408203125 +46265 0.179840087890625 +46266 0.118377685546875 +46267 0.155548095703125 +46268 0.115081787109375 +46269 0.151214599609375 +46270 0.11944580078125 +46271 0.156951904296875 +46272 0.10028076171875 +46273 0.13177490234375 +46274 0.07672119140625 +46275 0.100799560546875 +46276 0.0662841796875 +46277 0.087127685546875 +46278 0.041717529296875 +46279 0.05487060546875 +46280 -0.006866455078125 +46281 -0.009002685546875 +46282 -0.079071044921875 +46283 -0.10400390625 +46284 -0.17437744140625 +46285 -0.229400634765625 +46286 -0.270233154296875 +46287 -0.35552978515625 +46288 -0.33587646484375 +46289 -0.441925048828125 +46290 -0.360137939453125 +46291 -0.473846435546875 +46292 -0.353240966796875 +46293 -0.464813232421875 +46294 -0.318450927734375 +46295 -0.419097900390625 +46296 -0.25396728515625 +46297 -0.334320068359375 +46298 -0.173065185546875 +46299 -0.227935791015625 +46300 -0.093658447265625 +46301 -0.12347412109375 +46302 -0.02081298828125 +46303 -0.02764892578125 +46304 0.05926513671875 +46305 0.077667236328125 +46306 0.162322998046875 +46307 0.2132568359375 +46308 0.295745849609375 +46309 0.38885498046875 +46310 0.443084716796875 +46311 0.582794189453125 +46312 0.5579833984375 +46313 0.734039306640625 +46314 0.608184814453125 +46315 0.800140380859375 +46316 0.591552734375 +46317 0.7783203125 +46318 0.505523681640625 +46319 0.6651611328125 +46320 0.349334716796875 +46321 0.45965576171875 +46322 0.1513671875 +46323 0.199188232421875 +46324 -0.038543701171875 +46325 -0.050689697265625 +46326 -0.17706298828125 +46327 -0.23297119140625 +46328 -0.250885009765625 +46329 -0.33013916015625 +46330 -0.279937744140625 +46331 -0.368408203125 +46332 -0.28790283203125 +46333 -0.378936767578125 +46334 -0.286376953125 +46335 -0.376983642578125 +46336 -0.28851318359375 +46337 -0.37969970703125 +46338 -0.297607421875 +46339 -0.391510009765625 +46340 -0.292510986328125 +46341 -0.385345458984375 +46342 -0.2581787109375 +46343 -0.3419189453125 +46344 -0.2119140625 +46345 -0.28289794921875 +46346 -0.188140869140625 +46347 -0.251617431640625 +46348 -0.201202392578125 +46349 -0.266143798828125 +46350 -0.208984375 +46351 -0.273345947265625 +46352 -0.166717529296875 +46353 -0.216796875 +46354 -0.099365234375 +46355 -0.128265380859375 +46356 -0.054656982421875 +46357 -0.068145751953125 +46358 -0.037689208984375 +46359 -0.0430908203125 +46360 -0.02557373046875 +46361 -0.024444580078125 +46362 0.007904052734375 +46363 0.020721435546875 +46364 0.088287353515625 +46365 0.124481201171875 +46366 0.19268798828125 +46367 0.25787353515625 +46368 0.2880859375 +46369 0.379119873046875 +46370 0.36798095703125 +46371 0.47991943359375 +46372 0.40692138671875 +46373 0.5281982421875 +46374 0.39471435546875 +46375 0.511138916015625 +46376 0.352996826171875 +46377 0.456207275390625 +46378 0.31658935546875 +46379 0.407470703125 +46380 0.30029296875 +46381 0.383758544921875 +46382 0.2816162109375 +46383 0.35687255859375 +46384 0.24853515625 +46385 0.31182861328125 +46386 0.202667236328125 +46387 0.250885009765625 +46388 0.1370849609375 +46389 0.1654052734375 +46390 0.035736083984375 +46391 0.035247802734375 +46392 -0.103424072265625 +46393 -0.142059326171875 +46394 -0.256011962890625 +46395 -0.33563232421875 +46396 -0.413360595703125 +46397 -0.5345458984375 +46398 -0.562042236328125 +46399 -0.72186279296875 +46400 -0.65380859375 +46401 -0.836669921875 +46402 -0.65191650390625 +46403 -0.8326416015625 +46404 -0.571990966796875 +46405 -0.7296142578125 +46406 -0.45745849609375 +46407 -0.582550048828125 +46408 -0.346710205078125 +46409 -0.440093994140625 +46410 -0.257110595703125 +46411 -0.324310302734375 +46412 -0.161865234375 +46413 -0.20147705078125 +46414 -0.03948974609375 +46415 -0.044647216796875 +46416 0.076690673828125 +46417 0.103973388671875 +46418 0.153472900390625 +46419 0.202392578125 +46420 0.201873779296875 +46421 0.264495849609375 +46422 0.260467529296875 +46423 0.338897705078125 +46424 0.343658447265625 +46425 0.443817138671875 +46426 0.424346923828125 +46427 0.545074462890625 +46428 0.482452392578125 +46429 0.6173095703125 +46430 0.51153564453125 +46431 0.6524658203125 +46432 0.52166748046875 +46433 0.66339111328125 +46434 0.517547607421875 +46435 0.6561279296875 +46436 0.480133056640625 +46437 0.606781005859375 +46438 0.39813232421875 +46439 0.501190185546875 +46440 0.2821044921875 +46441 0.352783203125 +46442 0.143829345703125 +46443 0.176544189453125 +46444 -0.022491455078125 +46445 -0.034820556640625 +46446 -0.1986083984375 +46447 -0.258209228515625 +46448 -0.34405517578125 +46449 -0.44244384765625 +46450 -0.44915771484375 +46451 -0.5753173828125 +46452 -0.5101318359375 +46453 -0.65203857421875 +46454 -0.502410888671875 +46455 -0.641632080078125 +46456 -0.4403076171875 +46457 -0.562164306640625 +46458 -0.358917236328125 +46459 -0.458038330078125 +46460 -0.275054931640625 +46461 -0.350555419921875 +46462 -0.205108642578125 +46463 -0.260528564453125 +46464 -0.152313232421875 +46465 -0.192108154296875 +46466 -0.113922119140625 +46467 -0.141937255859375 +46468 -0.083648681640625 +46469 -0.1021728515625 +46470 -0.0535888671875 +46471 -0.062896728515625 +46472 -0.014007568359375 +46473 -0.011932373046875 +46474 0.044708251953125 +46475 0.062835693359375 +46476 0.112518310546875 +46477 0.148712158203125 +46478 0.186248779296875 +46479 0.241729736328125 +46480 0.271636962890625 +46481 0.34912109375 +46482 0.35791015625 +46483 0.457305908203125 +46484 0.427276611328125 +46485 0.54388427734375 +46486 0.451202392578125 +46487 0.5728759765625 +46488 0.3997802734375 +46489 0.506591796875 +46490 0.277862548828125 +46491 0.351226806640625 +46492 0.1168212890625 +46493 0.146514892578125 +46494 -0.04193115234375 +46495 -0.05523681640625 +46496 -0.168548583984375 +46497 -0.21624755859375 +46498 -0.261810302734375 +46499 -0.334930419921875 +46500 -0.315185546875 +46501 -0.402984619140625 +46502 -0.345184326171875 +46503 -0.4412841796875 +46504 -0.38824462890625 +46505 -0.49578857421875 +46506 -0.439361572265625 +46507 -0.5601806640625 +46508 -0.471832275390625 +46509 -0.600738525390625 +46510 -0.45928955078125 +46511 -0.584228515625 +46512 -0.37689208984375 +46513 -0.47930908203125 +46514 -0.2193603515625 +46515 -0.27935791015625 +46516 -0.006072998046875 +46517 -0.0089111328125 +46518 0.212921142578125 +46519 0.268798828125 +46520 0.381500244140625 +46521 0.482818603515625 +46522 0.47637939453125 +46523 0.60369873046875 +46524 0.51263427734375 +46525 0.650421142578125 +46526 0.522796630859375 +46527 0.66400146484375 +46528 0.5045166015625 +46529 0.6414794921875 +46530 0.449676513671875 +46531 0.572540283203125 +46532 0.390716552734375 +46533 0.498138427734375 +46534 0.34442138671875 +46535 0.439453125 +46536 0.294158935546875 +46537 0.375518798828125 +46538 0.2147216796875 +46539 0.274505615234375 +46540 0.08416748046875 +46541 0.1087646484375 +46542 -0.079925537109375 +46543 -0.099395751953125 +46544 -0.252410888671875 +46545 -0.3182373046875 +46546 -0.434295654296875 +46547 -0.5489501953125 +46548 -0.611572265625 +46549 -0.7738037109375 +46550 -0.742340087890625 +46551 -0.86383056640625 +46552 -0.800323486328125 +46553 -0.870391845703125 +46554 -0.799560546875 +46555 -0.86895751953125 +46556 -0.75048828125 +46557 -0.861053466796875 +46558 -0.639404296875 +46559 -0.765869140625 +46560 -0.457366943359375 +46561 -0.5301513671875 +46562 -0.209991455078125 +46563 -0.214691162109375 +46564 0.068603515625 +46565 0.137359619140625 +46566 0.33782958984375 +46567 0.474822998046875 +46568 0.569549560546875 +46569 0.76239013671875 +46570 0.742431640625 +46571 0.867462158203125 +46572 0.854736328125 +46573 0.870361328125 +46574 0.85986328125 +46575 0.86480712890625 +46576 0.858062744140625 +46577 0.831817626953125 +46578 0.826934814453125 +46579 0.677581787109375 +46580 0.7271728515625 +46581 0.495880126953125 +46582 0.602783203125 +46583 0.30767822265625 +46584 0.45550537109375 +46585 0.116180419921875 +46586 0.260223388671875 +46587 -0.110748291015625 +46588 0.011444091796875 +46589 -0.381805419921875 +46590 -0.25689697265625 +46591 -0.6572265625 +46592 -0.49725341796875 +46593 -0.857421875 +46594 -0.67547607421875 +46595 -0.870391845703125 +46596 -0.7861328125 +46597 -0.870391845703125 +46598 -0.851348876953125 +46599 -0.86444091796875 +46600 -0.859527587890625 +46601 -0.85723876953125 +46602 -0.861419677734375 +46603 -0.790008544921875 +46604 -0.85498046875 +46605 -0.62847900390625 +46606 -0.72039794921875 +46607 -0.3956298828125 +46608 -0.52911376953125 +46609 -0.126708984375 +46610 -0.30718994140625 +46611 0.150115966796875 +46612 -0.063873291015625 +46613 0.424041748046875 +46614 0.17901611328125 +46615 0.670623779296875 +46616 0.389923095703125 +46617 0.854522705078125 +46618 0.55462646484375 +46619 0.866485595703125 +46620 0.660736083984375 +46621 0.86920166015625 +46622 0.723388671875 +46623 0.8653564453125 +46624 0.7537841796875 +46625 0.857147216796875 +46626 0.74951171875 +46627 0.766845703125 +46628 0.71478271484375 +46629 0.628509521484375 +46630 0.643890380859375 +46631 0.462127685546875 +46632 0.5579833984375 +46633 0.297210693359375 +46634 0.467010498046875 +46635 0.14862060546875 +46636 0.351898193359375 +46637 -0.00537109375 +46638 0.218505859375 +46639 -0.15753173828125 +46640 0.063568115234375 +46641 -0.31304931640625 +46642 -0.124755859375 +46643 -0.48876953125 +46644 -0.30810546875 +46645 -0.6416015625 +46646 -0.466339111328125 +46647 -0.751373291015625 +46648 -0.618621826171875 +46649 -0.84619140625 +46650 -0.75299072265625 +46651 -0.861297607421875 +46652 -0.842132568359375 +46653 -0.863250732421875 +46654 -0.8551025390625 +46655 -0.856597900390625 +46656 -0.81658935546875 +46657 -0.7498779296875 +46658 -0.7593994140625 +46659 -0.624542236328125 +46660 -0.670135498046875 +46661 -0.47808837890625 +46662 -0.50042724609375 +46663 -0.253387451171875 +46664 -0.287628173828125 +46665 0.003692626953125 +46666 -0.087860107421875 +46667 0.2257080078125 +46668 0.109405517578125 +46669 0.427154541015625 +46670 0.3310546875 +46671 0.643218994140625 +46672 0.56927490234375 +46673 0.855926513671875 +46674 0.77642822265625 +46675 0.870361328125 +46676 0.8607177734375 +46677 0.870361328125 +46678 0.8682861328125 +46679 0.862762451171875 +46680 0.868408203125 +46681 0.79669189453125 +46682 0.860198974609375 +46683 0.595794677734375 +46684 0.779296875 +46685 0.362152099609375 +46686 0.62255859375 +46687 0.1270751953125 +46688 0.453857421875 +46689 -0.086944580078125 +46690 0.274810791015625 +46691 -0.2784423828125 +46692 0.05657958984375 +46693 -0.484832763671875 +46694 -0.21673583984375 +46695 -0.729583740234375 +46696 -0.5035400390625 +46697 -0.86688232421875 +46698 -0.751739501953125 +46699 -0.870391845703125 +46700 -0.86572265625 +46701 -0.86859130859375 +46702 -0.870391845703125 +46703 -0.86279296875 +46704 -0.8680419921875 +46705 -0.817962646484375 +46706 -0.855224609375 +46707 -0.6116943359375 +46708 -0.646514892578125 +46709 -0.3128662109375 +46710 -0.365692138671875 +46711 0.039398193359375 +46712 -0.03717041015625 +46713 0.422821044921875 +46714 0.311065673828125 +46715 0.805145263671875 +46716 0.62384033203125 +46717 0.870361328125 +46718 0.85467529296875 +46719 0.870361328125 +46720 0.870361328125 +46721 0.860015869140625 +46722 0.870361328125 +46723 0.727935791015625 +46724 0.86126708984375 +46725 0.48114013671875 +46726 0.778228759765625 +46727 0.2059326171875 +46728 0.610809326171875 +46729 -0.06103515625 +46730 0.429595947265625 +46731 -0.29913330078125 +46732 0.228363037109375 +46733 -0.516204833984375 +46734 -0.001220703125 +46735 -0.7252197265625 +46736 -0.235870361328125 +46737 -0.85980224609375 +46738 -0.44622802734375 +46739 -0.870391845703125 +46740 -0.608551025390625 +46741 -0.870391845703125 +46742 -0.684906005859375 +46743 -0.858062744140625 +46744 -0.675445556640625 +46745 -0.673004150390625 +46746 -0.628265380859375 +46747 -0.42694091796875 +46748 -0.58563232421875 +46749 -0.2100830078125 +46750 -0.55206298828125 +46751 -0.0362548828125 +46752 -0.510040283203125 +46753 0.10943603515625 +46754 -0.449493408203125 +46755 0.23516845703125 +46756 -0.34210205078125 +46757 0.373687744140625 +46758 -0.1944580078125 +46759 0.517791748046875 +46760 -0.062469482421875 +46761 0.602783203125 +46762 0.055328369140625 +46763 0.635711669921875 +46764 0.184967041015625 +46765 0.655181884765625 +46766 0.31817626953125 +46767 0.65948486328125 +46768 0.449615478515625 +46769 0.651275634765625 +46770 0.561553955078125 +46771 0.61846923828125 +46772 0.62701416015625 +46773 0.53753662109375 +46774 0.635406494140625 +46775 0.404144287109375 +46776 0.583648681640625 +46777 0.22186279296875 +46778 0.4779052734375 +46779 0.003997802734375 +46780 0.3382568359375 +46781 -0.22100830078125 +46782 0.186614990234375 +46783 -0.42449951171875 +46784 0.044952392578125 +46785 -0.579833984375 +46786 -0.047943115234375 +46787 -0.641876220703125 +46788 -0.094879150390625 +46789 -0.6177978515625 +46790 -0.147491455078125 +46791 -0.575531005859375 +46792 -0.209686279296875 +46793 -0.526336669921875 +46794 -0.2393798828125 +46795 -0.42645263671875 +46796 -0.215606689453125 +46797 -0.2581787109375 +46798 -0.1708984375 +46799 -0.068695068359375 +46800 -0.1402587890625 +46801 0.09222412109375 +46802 -0.1121826171875 +46803 0.232147216796875 +46804 -0.082427978515625 +46805 0.3509521484375 +46806 -0.079620361328125 +46807 0.410064697265625 +46808 -0.131988525390625 +46809 0.372955322265625 +46810 -0.2259521484375 +46811 0.2554931640625 +46812 -0.321624755859375 +46813 0.10711669921875 +46814 -0.405303955078125 +46815 -0.052886962890625 +46816 -0.448699951171875 +46817 -0.186279296875 +46818 -0.40643310546875 +46819 -0.23291015625 +46820 -0.297027587890625 +46821 -0.209442138671875 +46822 -0.173675537109375 +46823 -0.174163818359375 +46824 -0.0413818359375 +46825 -0.126739501953125 +46826 0.110443115234375 +46827 -0.048126220703125 +46828 0.261566162109375 +46829 0.0426025390625 +46830 0.376861572265625 +46831 0.10748291015625 +46832 0.448822021484375 +46833 0.1409912109375 +46834 0.51995849609375 +46835 0.19708251953125 +46836 0.587799072265625 +46837 0.273651123046875 +46838 0.60894775390625 +46839 0.31768798828125 +46840 0.5946044921875 +46841 0.341094970703125 +46842 0.567047119140625 +46843 0.368011474609375 +46844 0.508056640625 +46845 0.37249755859375 +46846 0.377044677734375 +46847 0.30072021484375 +46848 0.17755126953125 +46849 0.1517333984375 +46850 -0.03668212890625 +46851 -0.01470947265625 +46852 -0.2537841796875 +46853 -0.1883544921875 +46854 -0.473114013671875 +46855 -0.372711181640625 +46856 -0.645751953125 +46857 -0.51397705078125 +46858 -0.73480224609375 +46859 -0.57177734375 +46860 -0.732818603515625 +46861 -0.53948974609375 +46862 -0.65411376953125 +46863 -0.43511962890625 +46864 -0.530517578125 +46865 -0.2962646484375 +46866 -0.395172119140625 +46867 -0.161102294921875 +46868 -0.26141357421875 +46869 -0.0435791015625 +46870 -0.127960205078125 +46871 0.060394287109375 +46872 -0.00958251953125 +46873 0.13665771484375 +46874 0.077728271484375 +46875 0.170135498046875 +46876 0.134613037109375 +46877 0.16552734375 +46878 0.186981201171875 +46879 0.15728759765625 +46880 0.236236572265625 +46881 0.150787353515625 +46882 0.25909423828125 +46883 0.12200927734375 +46884 0.260955810546875 +46885 0.080108642578125 +46886 0.2623291015625 +46887 0.05126953125 +46888 0.28546142578125 +46889 0.062896728515625 +46890 0.31103515625 +46891 0.09271240234375 +46892 0.298858642578125 +46893 0.092987060546875 +46894 0.262542724609375 +46895 0.07855224609375 +46896 0.216400146484375 +46897 0.06427001953125 +46898 0.149505615234375 +46899 0.0347900390625 +46900 0.062774658203125 +46901 -0.01171875 +46902 -0.02471923828125 +46903 -0.056060791015625 +46904 -0.073883056640625 +46905 -0.055511474609375 +46906 -0.08233642578125 +46907 -0.010467529296875 +46908 -0.093475341796875 +46909 0.02508544921875 +46910 -0.126861572265625 +46911 0.025665283203125 +46912 -0.15869140625 +46913 0.017333984375 +46914 -0.186370849609375 +46915 0.00189208984375 +46916 -0.21881103515625 +46917 -0.03173828125 +46918 -0.245941162109375 +46919 -0.071502685546875 +46920 -0.283721923828125 +46921 -0.13543701171875 +46922 -0.330291748046875 +46923 -0.219970703125 +46924 -0.366363525390625 +46925 -0.300506591796875 +46926 -0.393280029296875 +46927 -0.376312255859375 +46928 -0.38665771484375 +46929 -0.416107177734375 +46930 -0.30731201171875 +46931 -0.371124267578125 +46932 -0.158294677734375 +46933 -0.242279052734375 +46934 0.02410888671875 +46935 -0.069732666015625 +46936 0.220306396484375 +46937 0.125640869140625 +46938 0.402374267578125 +46939 0.31268310546875 +46940 0.538360595703125 +46941 0.45501708984375 +46942 0.62945556640625 +46943 0.554779052734375 +46944 0.674468994140625 +46945 0.61065673828125 +46946 0.663848876953125 +46947 0.610931396484375 +46948 0.577911376953125 +46949 0.531463623046875 +46950 0.431488037109375 +46951 0.3883056640625 +46952 0.271331787109375 +46953 0.23468017578125 +46954 0.12017822265625 +46955 0.095245361328125 +46956 0.00201416015625 +46957 -0.00396728515625 +46958 -0.06903076171875 +46959 -0.04852294921875 +46960 -0.1053466796875 +46961 -0.055145263671875 +46962 -0.1495361328125 +46963 -0.0758056640625 +46964 -0.2242431640625 +46965 -0.138702392578125 +46966 -0.29901123046875 +46967 -0.209197998046875 +46968 -0.374664306640625 +46969 -0.289031982421875 +46970 -0.4515380859375 +46971 -0.37884521484375 +46972 -0.510833740234375 +46973 -0.456329345703125 +46974 -0.548828125 +46975 -0.51641845703125 +46976 -0.532562255859375 +46977 -0.519287109375 +46978 -0.457550048828125 +46979 -0.458251953125 +46980 -0.36895751953125 +46981 -0.384796142578125 +46982 -0.289306640625 +46983 -0.323699951171875 +46984 -0.21533203125 +46985 -0.269287109375 +46986 -0.12615966796875 +46987 -0.1951904296875 +46988 -0.02197265625 +46989 -0.100006103515625 +46990 0.073211669921875 +46991 -0.01055908203125 +46992 0.184173583984375 +46993 0.1033935546875 +46994 0.316436767578125 +46995 0.24908447265625 +46996 0.424407958984375 +46997 0.373199462890625 +46998 0.49310302734375 +46999 0.45806884765625 +47000 0.52947998046875 +47001 0.511474609375 +47002 0.5614013671875 +47003 0.565399169921875 +47004 0.58258056640625 +47005 0.61138916015625 +47006 0.5433349609375 +47007 0.5897216796875 +47008 0.436553955078125 +47009 0.4906005859375 +47010 0.27838134765625 +47011 0.33148193359375 +47012 0.10015869140625 +47013 0.147796630859375 +47014 -0.06146240234375 +47015 -0.01873779296875 +47016 -0.181793212890625 +47017 -0.140289306640625 +47018 -0.23883056640625 +47019 -0.191986083984375 +47020 -0.24090576171875 +47021 -0.184295654296875 +47022 -0.225616455078125 +47023 -0.161834716796875 +47024 -0.228546142578125 +47025 -0.166595458984375 +47026 -0.24591064453125 +47027 -0.19390869140625 +47028 -0.261749267578125 +47029 -0.22442626953125 +47030 -0.295074462890625 +47031 -0.279754638671875 +47032 -0.3289794921875 +47033 -0.3389892578125 +47034 -0.3238525390625 +47035 -0.3543701171875 +47036 -0.2996826171875 +47037 -0.348175048828125 +47038 -0.262237548828125 +47039 -0.32598876953125 +47040 -0.1873779296875 +47041 -0.2581787109375 +47042 -0.07177734375 +47043 -0.139801025390625 +47044 0.07147216796875 +47045 0.014617919921875 +47046 0.190185546875 +47047 0.144378662109375 +47048 0.259857177734375 +47049 0.221038818359375 +47050 0.302490234375 +47051 0.27069091796875 +47052 0.318817138671875 +47053 0.294036865234375 +47054 0.32672119140625 +47055 0.311767578125 +47056 0.339691162109375 +47057 0.339141845703125 +47058 0.344940185546875 +47059 0.360260009765625 +47060 0.330780029296875 +47061 0.360504150390625 +47062 0.27105712890625 +47063 0.308380126953125 +47064 0.1475830078125 +47065 0.18170166015625 +47066 -0.017974853515625 +47067 0.0047607421875 +47068 -0.184814453125 +47069 -0.17559814453125 +47070 -0.31378173828125 +47071 -0.3143310546875 +47072 -0.367095947265625 +47073 -0.36785888671875 +47074 -0.366912841796875 +47075 -0.36248779296875 +47076 -0.351898193359375 +47077 -0.343536376953125 +47078 -0.314300537109375 +47079 -0.3018798828125 +47080 -0.249053955078125 +47081 -0.231414794921875 +47082 -0.14410400390625 +47083 -0.117645263671875 +47084 -0.02764892578125 +47085 0.007049560546875 +47086 0.05291748046875 +47087 0.087982177734375 +47088 0.10919189453125 +47089 0.13946533203125 +47090 0.151397705078125 +47091 0.17425537109375 +47092 0.175262451171875 +47093 0.188201904296875 +47094 0.171539306640625 +47095 0.171234130859375 +47096 0.135467529296875 +47097 0.118438720703125 +47098 0.089935302734375 +47099 0.05706787109375 +47100 0.03643798828125 +47101 -0.010711669921875 +47102 -0.03076171875 +47103 -0.0914306640625 +47104 -0.09259033203125 +47105 -0.162322998046875 +47106 -0.12408447265625 +47107 -0.194549560546875 +47108 -0.090240478515625 +47109 -0.1492919921875 +47110 0.0140380859375 +47111 -0.02166748046875 +47112 0.132537841796875 +47113 0.124053955078125 +47114 0.197967529296875 +47115 0.211151123046875 +47116 0.211883544921875 +47117 0.240447998046875 +47118 0.201873779296875 +47119 0.242218017578125 +47120 0.176849365234375 +47121 0.2257080078125 +47122 0.140411376953125 +47123 0.194366455078125 +47124 0.063934326171875 +47125 0.115509033203125 +47126 -0.03125 +47127 0.0128173828125 +47128 -0.091827392578125 +47129 -0.053802490234375 +47130 -0.141143798828125 +47131 -0.110626220703125 +47132 -0.216552734375 +47133 -0.199493408203125 +47134 -0.295196533203125 +47135 -0.29437255859375 +47136 -0.32147216796875 +47137 -0.33221435546875 +47138 -0.26629638671875 +47139 -0.27972412109375 +47140 -0.173187255859375 +47141 -0.185333251953125 +47142 -0.112945556640625 +47143 -0.128204345703125 +47144 -0.092620849609375 +47145 -0.115692138671875 +47146 -0.084869384765625 +47147 -0.116455078125 +47148 -0.068359375 +47149 -0.105926513671875 +47150 -0.01666259765625 +47151 -0.053955078125 +47152 0.0782470703125 +47153 0.048797607421875 +47154 0.17626953125 +47155 0.157318115234375 +47156 0.22442626953125 +47157 0.212005615234375 +47158 0.227783203125 +47159 0.218475341796875 +47160 0.24029541015625 +47161 0.23724365234375 +47162 0.295135498046875 +47163 0.30535888671875 +47164 0.355743408203125 +47165 0.38128662109375 +47166 0.368743896484375 +47167 0.404449462890625 +47168 0.3519287109375 +47169 0.3944091796875 +47170 0.338958740234375 +47171 0.3885498046875 +47172 0.308746337890625 +47173 0.362640380859375 +47174 0.223419189453125 +47175 0.27362060546875 +47176 0.07940673828125 +47177 0.11712646484375 +47178 -0.076873779296875 +47179 -0.054901123046875 +47180 -0.199432373046875 +47181 -0.19085693359375 +47182 -0.283782958984375 +47183 -0.28570556640625 +47184 -0.329833984375 +47185 -0.339263916015625 +47186 -0.36083984375 +47187 -0.3775634765625 +47188 -0.417022705078125 +47189 -0.445709228515625 +47190 -0.49102783203125 +47191 -0.535064697265625 +47192 -0.568450927734375 +47193 -0.629058837890625 +47194 -0.622894287109375 +47195 -0.697601318359375 +47196 -0.6220703125 +47197 -0.70391845703125 +47198 -0.5614013671875 +47199 -0.6424560546875 +47200 -0.421722412109375 +47201 -0.491241455078125 +47202 -0.21697998046875 +47203 -0.265716552734375 +47204 0.001220703125 +47205 -0.023712158203125 +47206 0.203399658203125 +47207 0.201751708984375 +47208 0.358551025390625 +47209 0.375823974609375 +47210 0.45477294921875 +47211 0.485076904296875 +47212 0.527099609375 +47213 0.56884765625 +47214 0.582427978515625 +47215 0.634765625 +47216 0.580841064453125 +47217 0.63763427734375 +47218 0.512420654296875 +47219 0.5660400390625 +47220 0.4237060546875 +47221 0.4720458984375 +47222 0.360504150390625 +47223 0.40692138671875 +47224 0.329498291015625 +47225 0.3778076171875 +47226 0.324066162109375 +47227 0.376953125 +47228 0.315704345703125 +47229 0.371978759765625 +47230 0.26043701171875 +47231 0.313140869140625 +47232 0.1441650390625 +47233 0.184417724609375 +47234 -0.010467529296875 +47235 0.011199951171875 +47236 -0.171966552734375 +47237 -0.171051025390625 +47238 -0.318267822265625 +47239 -0.33740234375 +47240 -0.43536376953125 +47241 -0.47198486328125 +47242 -0.510650634765625 +47243 -0.560394287109375 +47244 -0.52471923828125 +47245 -0.58056640625 +47246 -0.491180419921875 +47247 -0.54754638671875 +47248 -0.45220947265625 +47249 -0.508575439453125 +47250 -0.40435791015625 +47251 -0.459503173828125 +47252 -0.34259033203125 +47253 -0.394378662109375 +47254 -0.30206298828125 +47255 -0.35260009765625 +47256 -0.26300048828125 +47257 -0.31170654296875 +47258 -0.159576416015625 +47259 -0.197418212890625 +47260 0.009674072265625 +47261 -0.007965087890625 +47262 0.2010498046875 +47263 0.207489013671875 +47264 0.3792724609375 +47265 0.409210205078125 +47266 0.52215576171875 +47267 0.57208251953125 +47268 0.60302734375 +47269 0.66595458984375 +47270 0.59356689453125 +47271 0.65875244140625 +47272 0.509033203125 +47273 0.56744384765625 +47274 0.38458251953125 +47275 0.431396484375 +47276 0.259368896484375 +47277 0.29443359375 +47278 0.156585693359375 +47279 0.182464599609375 +47280 0.048126220703125 +47281 0.06365966796875 +47282 -0.0782470703125 +47283 -0.075958251953125 +47284 -0.180755615234375 +47285 -0.189422607421875 +47286 -0.255035400390625 +47287 -0.271942138671875 +47288 -0.31793212890625 +47289 -0.342529296875 +47290 -0.336639404296875 +47291 -0.364166259765625 +47292 -0.302642822265625 +47293 -0.327239990234375 +47294 -0.256195068359375 +47295 -0.2769775390625 +47296 -0.233184814453125 +47297 -0.253692626953125 +47298 -0.2215576171875 +47299 -0.24365234375 +47300 -0.178436279296875 +47301 -0.1983642578125 +47302 -0.102569580078125 +47303 -0.116241455078125 +47304 -0.029205322265625 +47305 -0.036834716796875 +47306 0.03704833984375 +47307 0.034881591796875 +47308 0.089263916015625 +47309 0.09124755859375 +47310 0.1065673828125 +47311 0.10888671875 +47312 0.12237548828125 +47313 0.125518798828125 +47314 0.1513671875 +47315 0.15771484375 +47316 0.169403076171875 +47317 0.17828369140625 +47318 0.16217041015625 +47319 0.17108154296875 +47320 0.12432861328125 +47321 0.129974365234375 +47322 0.080322265625 +47323 0.082427978515625 +47324 0.02960205078125 +47325 0.027679443359375 +47326 -0.05560302734375 +47327 -0.065643310546875 +47328 -0.1412353515625 +47329 -0.15936279296875 +47330 -0.1912841796875 +47331 -0.21307373046875 +47332 -0.212615966796875 +47333 -0.234649658203125 +47334 -0.18389892578125 +47335 -0.2001953125 +47336 -0.113433837890625 +47337 -0.119171142578125 +47338 -0.030609130859375 +47339 -0.024749755859375 +47340 0.0670166015625 +47341 0.085784912109375 +47342 0.149017333984375 +47343 0.178131103515625 +47344 0.182769775390625 +47345 0.215576171875 +47346 0.1800537109375 +47347 0.211456298828125 +47348 0.149200439453125 +47349 0.17523193359375 +47350 0.10955810546875 +47351 0.128753662109375 +47352 0.08758544921875 +47353 0.1019287109375 +47354 0.0650634765625 +47355 0.0743408203125 +47356 0.039459228515625 +47357 0.04327392578125 +47358 0.03680419921875 +47359 0.038177490234375 +47360 0.072845458984375 +47361 0.076263427734375 +47362 0.13330078125 +47363 0.14105224609375 +47364 0.17626953125 +47365 0.186431884765625 +47366 0.1798095703125 +47367 0.188812255859375 +47368 0.135284423828125 +47369 0.1390380859375 +47370 0.046875 +47371 0.041778564453125 +47372 -0.06390380859375 +47373 -0.079437255859375 +47374 -0.192413330078125 +47375 -0.219390869140625 +47376 -0.3292236328125 +47377 -0.367828369140625 +47378 -0.446868896484375 +47379 -0.494873046875 +47380 -0.504547119140625 +47381 -0.556243896484375 +47382 -0.462432861328125 +47383 -0.508697509765625 +47384 -0.3419189453125 +47385 -0.3756103515625 +47386 -0.19989013671875 +47387 -0.218902587890625 +47388 -0.059356689453125 +47389 -0.063751220703125 +47390 0.08135986328125 +47391 0.091552734375 +47392 0.212310791015625 +47393 0.23602294921875 +47394 0.309051513671875 +47395 0.342987060546875 +47396 0.355804443359375 +47397 0.39520263671875 +47398 0.349609375 +47399 0.389373779296875 +47400 0.28936767578125 +47401 0.324249267578125 +47402 0.1973876953125 +47403 0.224090576171875 +47404 0.106201171875 +47405 0.124267578125 +47406 0.02703857421875 +47407 0.037078857421875 +47408 -0.01495361328125 +47409 -0.010101318359375 +47410 -0.0218505859375 +47411 -0.019439697265625 +47412 -0.023040771484375 +47413 -0.022796630859375 +47414 -0.00152587890625 +47415 -0.001556396484375 +47416 0.053619384765625 +47417 0.056304931640625 +47418 0.10174560546875 +47419 0.106719970703125 +47420 0.094207763671875 +47421 0.096893310546875 +47422 0.0455322265625 +47423 0.042694091796875 +47424 -0.009552001953125 +47425 -0.018035888671875 +47426 -0.062347412109375 +47427 -0.07586669921875 +47428 -0.102447509765625 +47429 -0.11944580078125 +47430 -0.139923095703125 +47431 -0.15972900390625 +47432 -0.18017578125 +47433 -0.202606201171875 +47434 -0.223602294921875 +47435 -0.24859619140625 +47436 -0.277008056640625 +47437 -0.30517578125 +47438 -0.3309326171875 +47439 -0.36212158203125 +47440 -0.3594970703125 +47441 -0.39141845703125 +47442 -0.32781982421875 +47443 -0.35528564453125 +47444 -0.23236083984375 +47445 -0.249969482421875 +47446 -0.089111328125 +47447 -0.092864990234375 +47448 0.077178955078125 +47449 0.08905029296875 +47450 0.210906982421875 +47451 0.2352294921875 +47452 0.287384033203125 +47453 0.318817138671875 +47454 0.323944091796875 +47455 0.358642578125 +47456 0.314178466796875 +47457 0.347747802734375 +47458 0.25762939453125 +47459 0.28564453125 +47460 0.201019287109375 +47461 0.223175048828125 +47462 0.177734375 +47463 0.196746826171875 +47464 0.163360595703125 +47465 0.179840087890625 +47466 0.14227294921875 +47467 0.155548095703125 +47468 0.139556884765625 +47469 0.151214599609375 +47470 0.14605712890625 +47471 0.156951904296875 +47472 0.123992919921875 +47473 0.13177490234375 +47474 0.096405029296875 +47475 0.100799560546875 +47476 0.084503173828125 +47477 0.087127685546875 +47478 0.055267333984375 +47479 0.05487060546875 +47480 -0.0032958984375 +47481 -0.009002685546875 +47482 -0.09075927734375 +47483 -0.10400390625 +47484 -0.20648193359375 +47485 -0.229400634765625 +47486 -0.3231201171875 +47487 -0.35552978515625 +47488 -0.40338134765625 +47489 -0.441925048828125 +47490 -0.433685302734375 +47491 -0.473846435546875 +47492 -0.4263916015625 +47493 -0.464813232421875 +47494 -0.3853759765625 +47495 -0.419097900390625 +47496 -0.308380126953125 +47497 -0.334320068359375 +47498 -0.211395263671875 +47499 -0.227935791015625 +47500 -0.1160888671875 +47501 -0.12347412109375 +47502 -0.028564453125 +47503 -0.02764892578125 +47504 0.067901611328125 +47505 0.077667236328125 +47506 0.19244384765625 +47507 0.2132568359375 +47508 0.35400390625 +47509 0.38885498046875 +47510 0.532623291015625 +47511 0.582794189453125 +47512 0.672149658203125 +47513 0.734039306640625 +47514 0.7335205078125 +47515 0.800140380859375 +47516 0.714111328125 +47517 0.7783203125 +47518 0.610748291015625 +47519 0.6651611328125 +47520 0.4224853515625 +47521 0.45965576171875 +47522 0.18365478515625 +47523 0.199188232421875 +47524 -0.04547119140625 +47525 -0.050689697265625 +47526 -0.212493896484375 +47527 -0.23297119140625 +47528 -0.30133056640625 +47529 -0.33013916015625 +47530 -0.33612060546875 +47531 -0.368408203125 +47532 -0.345550537109375 +47533 -0.378936767578125 +47534 -0.34368896484375 +47535 -0.376983642578125 +47536 -0.3463134765625 +47537 -0.37969970703125 +47538 -0.357452392578125 +47539 -0.391510009765625 +47540 -0.352203369140625 +47541 -0.385345458984375 +47542 -0.312774658203125 +47543 -0.3419189453125 +47544 -0.25909423828125 +47545 -0.28289794921875 +47546 -0.230987548828125 +47547 -0.251617431640625 +47548 -0.2449951171875 +47549 -0.266143798828125 +47550 -0.25225830078125 +47551 -0.273345947265625 +47552 -0.2008056640625 +47553 -0.216796875 +47554 -0.11981201171875 +47555 -0.128265380859375 +47556 -0.06488037109375 +47557 -0.068145751953125 +47558 -0.042083740234375 +47559 -0.0430908203125 +47560 -0.0250244140625 +47561 -0.024444580078125 +47562 0.016571044921875 +47563 0.020721435546875 +47564 0.112213134765625 +47565 0.124481201171875 +47566 0.2352294921875 +47567 0.25787353515625 +47568 0.34716796875 +47569 0.379119873046875 +47570 0.44036865234375 +47571 0.47991943359375 +47572 0.48529052734375 +47573 0.5281982421875 +47574 0.470123291015625 +47575 0.511138916015625 +47576 0.42010498046875 +47577 0.456207275390625 +47578 0.375762939453125 +47579 0.407470703125 +47580 0.354400634765625 +47581 0.383758544921875 +47582 0.33001708984375 +47583 0.35687255859375 +47584 0.288818359375 +47585 0.31182861328125 +47586 0.23284912109375 +47587 0.250885009765625 +47588 0.154205322265625 +47589 0.1654052734375 +47590 0.03436279296875 +47591 0.035247802734375 +47592 -0.128936767578125 +47593 -0.142059326171875 +47594 -0.30731201171875 +47595 -0.33563232421875 +47596 -0.49066162109375 +47597 -0.5345458984375 +47598 -0.663360595703125 +47599 -0.72186279296875 +47600 -0.769378662109375 +47601 -0.836669921875 +47602 -0.766082763671875 +47603 -0.8326416015625 +47604 -0.67169189453125 +47605 -0.7296142578125 +47606 -0.5367431640625 +47607 -0.582550048828125 +47608 -0.405975341796875 +47609 -0.440093994140625 +47610 -0.299713134765625 +47611 -0.324310302734375 +47612 -0.1868896484375 +47613 -0.20147705078125 +47614 -0.042694091796875 +47615 -0.044647216796875 +47616 0.093475341796875 +47617 0.103973388671875 +47618 0.18231201171875 +47619 0.202392578125 +47620 0.23724365234375 +47621 0.264495849609375 +47622 0.3048095703125 +47623 0.338897705078125 +47624 0.402496337890625 +47625 0.443817138671875 +47626 0.49786376953125 +47627 0.545074462890625 +47628 0.5667724609375 +47629 0.6173095703125 +47630 0.601531982421875 +47631 0.6524658203125 +47632 0.614288330078125 +47633 0.66339111328125 +47634 0.610626220703125 +47635 0.6561279296875 +47636 0.567596435546875 +47637 0.606781005859375 +47638 0.471466064453125 +47639 0.501190185546875 +47640 0.334747314453125 +47641 0.352783203125 +47642 0.17144775390625 +47643 0.176544189453125 +47644 -0.025604248046875 +47645 -0.034820556640625 +47646 -0.234649658203125 +47647 -0.258209228515625 +47648 -0.407135009765625 +47649 -0.44244384765625 +47650 -0.53155517578125 +47651 -0.5753173828125 +47652 -0.60345458984375 +47653 -0.65203857421875 +47654 -0.5933837890625 +47655 -0.641632080078125 +47656 -0.518524169921875 +47657 -0.562164306640625 +47658 -0.42108154296875 +47659 -0.458038330078125 +47660 -0.321197509765625 +47661 -0.350555419921875 +47662 -0.238555908203125 +47663 -0.260528564453125 +47664 -0.176910400390625 +47665 -0.192108154296875 +47666 -0.13287353515625 +47667 -0.141937255859375 +47668 -0.0987548828125 +47669 -0.1021728515625 +47670 -0.06494140625 +47671 -0.062896728515625 +47672 -0.01959228515625 +47673 -0.011932373046875 +47674 0.0489501953125 +47675 0.062835693359375 +47676 0.128753662109375 +47677 0.148712158203125 +47678 0.216094970703125 +47679 0.241729736328125 +47680 0.317901611328125 +47681 0.34912109375 +47682 0.421295166015625 +47683 0.457305908203125 +47684 0.5048828125 +47685 0.54388427734375 +47686 0.534332275390625 +47687 0.5728759765625 +47688 0.4736328125 +47689 0.506591796875 +47690 0.32855224609375 +47691 0.351226806640625 +47692 0.13671875 +47693 0.146514892578125 +47694 -0.052215576171875 +47695 -0.05523681640625 +47696 -0.202484130859375 +47697 -0.21624755859375 +47698 -0.312713623046875 +47699 -0.334930419921875 +47700 -0.37518310546875 +47701 -0.402984619140625 +47702 -0.409820556640625 +47703 -0.4412841796875 +47704 -0.460479736328125 +47705 -0.49578857421875 +47706 -0.521209716796875 +47707 -0.5601806640625 +47708 -0.5599365234375 +47709 -0.600738525390625 +47710 -0.54498291015625 +47711 -0.584228515625 +47712 -0.446441650390625 +47713 -0.47930908203125 +47714 -0.2579345703125 +47715 -0.27935791015625 +47716 -0.002685546875 +47717 -0.0089111328125 +47718 0.259185791015625 +47719 0.268798828125 +47720 0.4603271484375 +47721 0.482818603515625 +47722 0.5728759765625 +47723 0.60369873046875 +47724 0.614990234375 +47725 0.650421142578125 +47726 0.6258544921875 +47727 0.66400146484375 +47728 0.60272216796875 +47729 0.6414794921875 +47730 0.535888671875 +47731 0.572540283203125 +47732 0.46435546875 +47733 0.498138427734375 +47734 0.4083251953125 +47735 0.439453125 +47736 0.34783935546875 +47737 0.375518798828125 +47738 0.2525634765625 +47739 0.274505615234375 +47740 0.09613037109375 +47741 0.1087646484375 +47742 -0.100311279296875 +47743 -0.099395751953125 +47744 -0.306640625 +47745 -0.3182373046875 +47746 -0.524139404296875 +47747 -0.5489501953125 +47748 -0.73602294921875 +47749 -0.7738037109375 +47750 -0.858612060546875 +47751 -0.86383056640625 +47752 -0.8660888671875 +47753 -0.870391845703125 +47754 -0.865875244140625 +47755 -0.86895751953125 +47756 -0.859344482421875 +47757 -0.861053466796875 +47758 -0.764617919921875 +47759 -0.765869140625 +47760 -0.54541015625 +47761 -0.5301513671875 +47762 -0.247955322265625 +47763 -0.214691162109375 +47764 0.086822509765625 +47765 0.137359619140625 +47766 0.41009521484375 +47767 0.474822998046875 +47768 0.688079833984375 +47769 0.76239013671875 +47770 0.858917236328125 +47771 0.867462158203125 +47772 0.870361328125 +47773 0.870361328125 +47774 0.870361328125 +47775 0.86480712890625 +47776 0.86273193359375 +47777 0.831817626953125 +47778 0.816436767578125 +47779 0.677581787109375 +47780 0.666229248046875 +47781 0.495880126953125 +47782 0.49859619140625 +47783 0.30767822265625 +47784 0.3162841796875 +47785 0.116180419921875 +47786 0.08905029296875 +47787 -0.110748291015625 +47788 -0.190460205078125 +47789 -0.381805419921875 +47790 -0.482940673828125 +47791 -0.6572265625 +47792 -0.733367919921875 +47793 -0.857421875 +47794 -0.859832763671875 +47795 -0.870391845703125 +47796 -0.869110107421875 +47797 -0.870391845703125 +47798 -0.870391845703125 +47799 -0.86444091796875 +47800 -0.869659423828125 +47801 -0.85723876953125 +47802 -0.86541748046875 +47803 -0.790008544921875 +47804 -0.834625244140625 +47805 -0.62847900390625 +47806 -0.632965087890625 +47807 -0.3956298828125 +47808 -0.38238525390625 +47809 -0.126708984375 +47810 -0.109832763671875 +47811 0.150115966796875 +47812 0.173492431640625 +47813 0.424041748046875 +47814 0.44268798828125 +47815 0.670623779296875 +47816 0.662322998046875 +47817 0.854522705078125 +47818 0.817657470703125 +47819 0.866485595703125 +47820 0.85906982421875 +47821 0.86920166015625 +47822 0.861541748046875 +47823 0.8653564453125 +47824 0.859588623046875 +47825 0.857147216796875 +47826 0.84326171875 +47827 0.766845703125 +47828 0.752777099609375 +47829 0.628509521484375 +47830 0.625946044921875 +47831 0.462127685546875 +47832 0.489471435546875 +47833 0.297210693359375 +47834 0.356658935546875 +47835 0.14862060546875 +47836 0.20672607421875 +47837 -0.00537109375 +47838 0.047088623046875 +47839 -0.15753173828125 +47840 -0.126068115234375 +47841 -0.31304931640625 +47842 -0.32708740234375 +47843 -0.48876953125 +47844 -0.51287841796875 +47845 -0.6416015625 +47846 -0.661834716796875 +47847 -0.751373291015625 +47848 -0.7982177734375 +47849 -0.84619140625 +47850 -0.860626220703125 +47851 -0.861297607421875 +47852 -0.8670654296875 +47853 -0.863250732421875 +47854 -0.86468505859375 +47855 -0.856597900390625 +47856 -0.85498046875 +47857 -0.7498779296875 +47858 -0.759735107421875 +47859 -0.624542236328125 +47860 -0.630950927734375 +47861 -0.47808837890625 +47862 -0.41778564453125 +47863 -0.253387451171875 +47864 -0.164093017578125 +47865 0.003692626953125 +47866 0.065093994140625 +47867 0.2257080078125 +47868 0.2823486328125 +47869 0.427154541015625 +47870 0.519561767578125 +47871 0.643218994140625 +47872 0.769500732421875 +47873 0.855926513671875 +47874 0.8680419921875 +47875 0.870361328125 +47876 0.870361328125 +47877 0.870361328125 +47878 0.8651123046875 +47879 0.862762451171875 +47880 0.83843994140625 +47881 0.79669189453125 +47882 0.655731201171875 +47883 0.595794677734375 +47884 0.436767578125 +47885 0.362152099609375 +47886 0.2117919921875 +47887 0.1270751953125 +47888 0.00262451171875 +47889 -0.086944580078125 +47890 -0.189300537109375 +47891 -0.2784423828125 +47892 -0.400421142578125 +47893 -0.484832763671875 +47894 -0.6533203125 +47895 -0.729583740234375 +47896 -0.85980224609375 +47897 -0.86688232421875 +47898 -0.870391845703125 +47899 -0.870391845703125 +47900 -0.870391845703125 +47901 -0.86859130859375 +47902 -0.866241455078125 +47903 -0.86279296875 +47904 -0.855377197265625 +47905 -0.817962646484375 +47906 -0.667388916015625 +47907 -0.6116943359375 +47908 -0.37738037109375 +47909 -0.3128662109375 +47910 -0.0308837890625 +47911 0.039398193359375 +47912 0.35009765625 +47913 0.422821044921875 +47914 0.73345947265625 +47915 0.805145263671875 +47916 0.870361328125 +47917 0.870361328125 +47918 0.870361328125 +47919 0.870361328125 +47920 0.860076904296875 +47921 0.860015869140625 +47922 0.729766845703125 +47923 0.727935791015625 +47924 0.48455810546875 +47925 0.48114013671875 +47926 0.210845947265625 +47927 0.2059326171875 +47928 -0.05511474609375 +47929 -0.06103515625 +47930 -0.292877197265625 +47931 -0.29913330078125 +47932 -0.50994873046875 +47933 -0.516204833984375 +47934 -0.7188720703125 +47935 -0.7252197265625 +47936 -0.859100341796875 +47937 -0.85980224609375 +47938 -0.870391845703125 +47939 -0.870391845703125 +47940 -0.870391845703125 +47941 -0.870391845703125 +47942 -0.858184814453125 +47943 -0.858062744140625 +47944 -0.675689697265625 +47945 -0.673004150390625 +47946 -0.43121337890625 +47947 -0.42694091796875 +47948 -0.2149658203125 +47949 -0.2100830078125 +47950 -0.040679931640625 +47951 -0.0362548828125 +47952 0.1060791015625 +47953 0.10943603515625 +47954 0.233184814453125 +47955 0.23516845703125 +47956 0.3726806640625 +47957 0.373687744140625 +47958 0.517303466796875 +47959 0.517791748046875 +47960 0.603271484375 +47961 0.602783203125 +47962 0.63739013671875 +47963 0.635711669921875 +47964 0.657562255859375 +47965 0.655181884765625 +47966 0.662078857421875 +47967 0.65948486328125 +47968 0.653533935546875 +47969 0.651275634765625 +47970 0.620086669921875 +47971 0.61846923828125 +47972 0.538665771484375 +47973 0.53753662109375 +47974 0.4051513671875 +47975 0.404144287109375 +47976 0.22320556640625 +47977 0.22186279296875 +47978 0.00604248046875 +47979 0.003997802734375 +47980 -0.21820068359375 +47981 -0.22100830078125 +47982 -0.421173095703125 +47983 -0.42449951171875 +47984 -0.57647705078125 +47985 -0.579833984375 +47986 -0.63958740234375 +47987 -0.641876220703125 +47988 -0.617462158203125 +47989 -0.6177978515625 +47990 -0.576873779296875 +47991 -0.575531005859375 +47992 -0.52886962890625 +47993 -0.526336669921875 +47994 -0.430389404296875 +47995 -0.42645263671875 +47996 -0.264007568359375 +47997 -0.2581787109375 +47998 -0.076202392578125 +47999 -0.068695068359375 +48000 0.083953857421875 +48001 0.09222412109375 +48002 0.2237548828125 +48003 0.232147216796875 +48004 0.34295654296875 +48005 0.3509521484375 +48006 0.403472900390625 +48007 0.410064697265625 +48008 0.369232177734375 +48009 0.372955322265625 +48010 0.2557373046875 +48011 0.2554931640625 +48012 0.11151123046875 +48013 0.10711669921875 +48014 -0.0445556640625 +48015 -0.052886962890625 +48016 -0.17486572265625 +48017 -0.186279296875 +48018 -0.22027587890625 +48019 -0.23291015625 +48020 -0.19720458984375 +48021 -0.209442138671875 +48022 -0.162994384765625 +48023 -0.174163818359375 +48024 -0.11724853515625 +48025 -0.126739501953125 +48026 -0.04119873046875 +48027 -0.048126220703125 +48028 0.046478271484375 +48029 0.0426025390625 +48030 0.1085205078125 +48031 0.10748291015625 +48032 0.13958740234375 +48033 0.1409912109375 +48034 0.19287109375 +48035 0.19708251953125 +48036 0.266448974609375 +48037 0.273651123046875 +48038 0.3082275390625 +48039 0.31768798828125 +48040 0.329986572265625 +48041 0.341094970703125 +48042 0.355560302734375 +48043 0.368011474609375 +48044 0.35943603515625 +48045 0.37249755859375 +48046 0.288665771484375 +48047 0.30072021484375 +48048 0.14227294921875 +48049 0.1517333984375 +48050 -0.02093505859375 +48051 -0.01470947265625 +48052 -0.190887451171875 +48053 -0.1883544921875 +48054 -0.37109375 +48055 -0.372711181640625 +48056 -0.50872802734375 +48057 -0.51397705078125 +48058 -0.564117431640625 +48059 -0.57177734375 +48060 -0.53082275390625 +48061 -0.53948974609375 +48062 -0.426666259765625 +48063 -0.43511962890625 +48064 -0.2886962890625 +48065 -0.2962646484375 +48066 -0.154541015625 +48067 -0.161102294921875 +48068 -0.0379638671875 +48069 -0.0435791015625 +48070 0.06494140625 +48071 0.060394287109375 +48072 0.1402587890625 +48073 0.13665771484375 +48074 0.17315673828125 +48075 0.170135498046875 +48076 0.16827392578125 +48077 0.16552734375 +48078 0.1595458984375 +48079 0.15728759765625 +48080 0.152313232421875 +48081 0.150787353515625 +48082 0.12298583984375 +48083 0.12200927734375 +48084 0.08062744140625 +48085 0.080108642578125 +48086 0.051055908203125 +48087 0.05126953125 +48088 0.06134033203125 +48089 0.062896728515625 +48090 0.089569091796875 +48091 0.09271240234375 +48092 0.088836669921875 +48093 0.092987060546875 +48094 0.07379150390625 +48095 0.07855224609375 +48096 0.059112548828125 +48097 0.06427001953125 +48098 0.029693603515625 +48099 0.0347900390625 +48100 -0.016265869140625 +48101 -0.01171875 +48102 -0.059814453125 +48103 -0.056060791015625 +48104 -0.058929443359375 +48105 -0.055511474609375 +48106 -0.014007568359375 +48107 -0.010467529296875 +48108 0.02178955078125 +48109 0.02508544921875 +48110 0.0233154296875 +48111 0.025665283203125 +48112 0.01617431640625 +48113 0.017333984375 +48114 0.002044677734375 +48115 0.00189208984375 +48116 -0.029998779296875 +48117 -0.03173828125 +48118 -0.068206787109375 +48119 -0.071502685546875 +48120 -0.130340576171875 +48121 -0.13543701171875 +48122 -0.212921142578125 +48123 -0.219970703125 +48124 -0.291778564453125 +48125 -0.300506591796875 +48126 -0.3662109375 +48127 -0.376312255859375 +48128 -0.40533447265625 +48129 -0.416107177734375 +48130 -0.360992431640625 +48131 -0.371124267578125 +48132 -0.23406982421875 +48133 -0.242279052734375 +48134 -0.0643310546875 +48135 -0.069732666015625 +48136 0.127716064453125 +48137 0.125640869140625 +48138 0.311248779296875 +48139 0.31268310546875 +48140 0.450225830078125 +48141 0.45501708984375 +48142 0.547027587890625 +48143 0.554779052734375 +48144 0.600555419921875 +48145 0.61065673828125 +48146 0.599212646484375 +48147 0.610931396484375 +48148 0.518951416015625 +48149 0.531463623046875 +48150 0.37579345703125 +48151 0.3883056640625 +48152 0.222930908203125 +48153 0.23468017578125 +48154 0.0849609375 +48155 0.095245361328125 +48156 -0.01220703125 +48157 -0.00396728515625 +48158 -0.05426025390625 +48159 -0.04852294921875 +48160 -0.05810546875 +48161 -0.055145263671875 +48162 -0.075897216796875 +48163 -0.0758056640625 +48164 -0.136016845703125 +48165 -0.138702392578125 +48166 -0.203948974609375 +48167 -0.209197998046875 +48168 -0.281585693359375 +48169 -0.289031982421875 +48170 -0.36968994140625 +48171 -0.37884521484375 +48172 -0.446014404296875 +48173 -0.456329345703125 +48174 -0.505523681640625 +48175 -0.51641845703125 +48176 -0.5084228515625 +48177 -0.519287109375 +48178 -0.448028564453125 +48179 -0.458251953125 +48180 -0.37579345703125 +48181 -0.384796142578125 +48182 -0.31634521484375 +48183 -0.323699951171875 +48184 -0.263946533203125 +48185 -0.269287109375 +48186 -0.192108154296875 +48187 -0.1951904296875 +48188 -0.099273681640625 +48189 -0.100006103515625 +48190 -0.012115478515625 +48191 -0.01055908203125 +48192 0.09967041015625 +48193 0.1033935546875 +48194 0.24346923828125 +48195 0.24908447265625 +48196 0.366058349609375 +48197 0.373199462890625 +48198 0.4498291015625 +48199 0.45806884765625 +48200 0.502593994140625 +48201 0.511474609375 +48202 0.556396484375 +48203 0.565399169921875 +48204 0.602783203125 +48205 0.61138916015625 +48206 0.58197021484375 +48207 0.5897216796875 +48208 0.484100341796875 +48209 0.4906005859375 +48210 0.326568603515625 +48211 0.33148193359375 +48212 0.144683837890625 +48213 0.147796630859375 +48214 -0.01995849609375 +48215 -0.01873779296875 +48216 -0.139617919921875 +48217 -0.140289306640625 +48218 -0.18951416015625 +48219 -0.191986083984375 +48220 -0.180206298828125 +48221 -0.184295654296875 +48222 -0.1563720703125 +48223 -0.161834716796875 +48224 -0.16009521484375 +48225 -0.166595458984375 +48226 -0.186737060546875 +48227 -0.19390869140625 +48228 -0.217010498046875 +48229 -0.22442626953125 +48230 -0.272491455078125 +48231 -0.279754638671875 +48232 -0.332244873046875 +48233 -0.3389892578125 +48234 -0.348541259765625 +48235 -0.3543701171875 +48236 -0.34356689453125 +48237 -0.348175048828125 +48238 -0.322784423828125 +48239 -0.32598876953125 +48240 -0.25653076171875 +48241 -0.2581787109375 +48242 -0.139739990234375 +48243 -0.139801025390625 +48244 0.013153076171875 +48245 0.014617919921875 +48246 0.141510009765625 +48247 0.144378662109375 +48248 0.21697998046875 +48249 0.221038818359375 +48250 0.26568603515625 +48251 0.27069091796875 +48252 0.28839111328125 +48253 0.294036865234375 +48254 0.305816650390625 +48255 0.311767578125 +48256 0.333251953125 +48257 0.339111328125 +48258 0.354766845703125 +48259 0.35992431640625 +48260 0.355712890625 +48261 0.35968017578125 +48262 0.30450439453125 +48263 0.3074951171875 +48264 0.17889404296875 +48265 0.181640625 +48266 0.003173828125 +48267 0.00616455078125 +48268 -0.1759033203125 +48269 -0.1727294921875 +48270 -0.3133544921875 +48271 -0.310638427734375 +48272 -0.365692138671875 +48273 -0.364593505859375 +48274 -0.359283447265625 +48275 -0.3603515625 +48276 -0.3394775390625 +48277 -0.342498779296875 +48278 -0.297210693359375 +48279 -0.302032470703125 +48280 -0.226409912109375 +48281 -0.232879638671875 +48282 -0.112579345703125 +48283 -0.120819091796875 +48284 0.01190185546875 +48285 0.00225830078125 +48286 0.092376708984375 +48287 0.082550048828125 +48288 0.143157958984375 +48289 0.13409423828125 +48290 0.177093505859375 +48291 0.169403076171875 +48292 0.190032958984375 +48293 0.184295654296875 +48294 0.17193603515625 +48295 0.16876220703125 +48296 0.118011474609375 +48297 0.117919921875 +48298 0.0555419921875 +48299 0.05853271484375 +48300 -0.01324462890625 +48301 -0.00732421875 +48302 -0.094818115234375 +48303 -0.08612060546875 +48304 -0.166351318359375 +48305 -0.15545654296875 +48306 -0.198974609375 +48307 -0.18701171875 +48308 -0.15386962890625 +48309 -0.142608642578125 +48310 -0.026153564453125 +48311 -0.01739501953125 +48312 0.119903564453125 +48313 0.12542724609375 +48314 0.207550048828125 +48315 0.210418701171875 +48316 0.237579345703125 +48317 0.238433837890625 +48318 0.240203857421875 +48319 0.2392578125 +48320 0.224639892578125 +48321 0.222076416015625 +48322 0.19427490234375 +48323 0.190338134765625 +48324 0.116363525390625 +48325 0.111907958984375 +48326 0.0145263671875 +48327 0.010101318359375 +48328 -0.051361083984375 +48329 -0.056060791015625 +48330 -0.10760498046875 +48331 -0.11236572265625 +48332 -0.196075439453125 +48333 -0.20001220703125 +48334 -0.290771484375 +48335 -0.293365478515625 +48336 -0.32861328125 +48337 -0.330352783203125 +48338 -0.27630615234375 +48339 -0.278289794921875 +48340 -0.182281494140625 +48341 -0.18487548828125 +48342 -0.12567138671875 +48343 -0.12799072265625 +48344 -0.113800048828125 +48345 -0.1148681640625 +48346 -0.11529541015625 +48347 -0.11474609375 +48348 -0.10552978515625 +48349 -0.103546142578125 +48350 -0.0543212890625 +48351 -0.051666259765625 +48352 0.047698974609375 +48353 0.050079345703125 +48354 0.15557861328125 +48355 0.157379150390625 +48356 0.209716796875 +48357 0.2115478515625 +48358 0.215789794921875 +48359 0.218109130859375 +48360 0.23431396484375 +48361 0.236602783203125 +48362 0.3023681640625 +48363 0.303497314453125 +48364 0.378387451171875 +48365 0.377899169921875 +48366 0.40179443359375 +48367 0.400238037109375 +48368 0.392120361328125 +48369 0.3897705078125 +48370 0.386749267578125 +48371 0.383331298828125 +48372 0.361419677734375 +48373 0.357147216796875 +48374 0.273040771484375 +48375 0.26885986328125 +48376 0.1171875 +48377 0.114227294921875 +48378 -0.054229736328125 +48379 -0.05560302734375 +48380 -0.189605712890625 +48381 -0.189788818359375 +48382 -0.283935546875 +48383 -0.283416748046875 +48384 -0.33709716796875 +48385 -0.3369140625 +48386 -0.375152587890625 +48387 -0.375579833984375 +48388 -0.443206787109375 +48389 -0.4423828125 +48390 -0.532623291015625 +48391 -0.528717041015625 +48392 -0.626800537109375 +48393 -0.618560791015625 +48394 -0.695648193359375 +48395 -0.68310546875 +48396 -0.702392578125 +48397 -0.68731689453125 +48398 -0.641448974609375 +48399 -0.6259765625 +48400 -0.49078369140625 +48401 -0.478363037109375 +48402 -0.26580810546875 +48403 -0.25933837890625 +48404 -0.024322509765625 +48405 -0.02423095703125 +48406 0.200653076171875 +48407 0.195220947265625 +48408 0.37432861328125 +48409 0.36553955078125 +48410 0.4832763671875 +48411 0.47369384765625 +48412 0.56683349609375 +48413 0.556884765625 +48414 0.632659912109375 +48415 0.6221923828125 +48416 0.63555908203125 +48417 0.62646484375 +48418 0.564117431640625 +48419 0.558746337890625 +48420 0.470367431640625 +48421 0.468597412109375 +48422 0.405548095703125 +48423 0.404876708984375 +48424 0.376800537109375 +48425 0.374542236328125 +48426 0.3763427734375 +48427 0.370361328125 +48428 0.371795654296875 +48429 0.361724853515625 +48430 0.313385009765625 +48431 0.301513671875 +48432 0.18505859375 +48433 0.1746826171875 +48434 0.012176513671875 +48435 0.00567626953125 +48436 -0.1697998046875 +48437 -0.171539306640625 +48438 -0.335968017578125 +48439 -0.333038330078125 +48440 -0.470428466796875 +48441 -0.46356201171875 +48442 -0.558807373046875 +48443 -0.54931640625 +48444 -0.57904052734375 +48445 -0.569244384765625 +48446 -0.546142578125 +48447 -0.53759765625 +48448 -0.50738525390625 +48449 -0.4993896484375 +48450 -0.458587646484375 +48451 -0.45074462890625 +48452 -0.393798828125 +48453 -0.38616943359375 +48454 -0.352386474609375 +48455 -0.343292236328125 +48456 -0.311859130859375 +48457 -0.3009033203125 +48458 -0.197906494140625 +48459 -0.188507080078125 +48460 -0.008758544921875 +48461 -0.004608154296875 +48462 0.2064208984375 +48463 0.203765869140625 +48464 0.407928466796875 +48465 0.398590087890625 +48466 0.5706787109375 +48467 0.55584716796875 +48468 0.664520263671875 +48469 0.646728515625 +48470 0.6573486328125 +48471 0.640625 +48472 0.566131591796875 +48473 0.5537109375 +48474 0.43023681640625 +48475 0.4234619140625 +48476 0.293487548828125 +48477 0.291656494140625 +48478 0.181793212890625 +48479 0.183074951171875 +48480 0.06329345703125 +48481 0.067535400390625 +48482 -0.076019287109375 +48483 -0.068115234375 +48484 -0.189178466796875 +48485 -0.179046630859375 +48486 -0.27142333984375 +48487 -0.260498046875 +48488 -0.341766357421875 +48489 -0.33038330078125 +48490 -0.36322021484375 +48491 -0.353363037109375 +48492 -0.326171875 +48493 -0.320159912109375 +48494 -0.275848388671875 +48495 -0.27374267578125 +48496 -0.2525634765625 +48497 -0.252410888671875 +48498 -0.242584228515625 +48499 -0.243072509765625 +48500 -0.197418212890625 +48501 -0.1995849609375 +48502 -0.115478515625 +48503 -0.120452880859375 +48504 -0.036285400390625 +48505 -0.04339599609375 +48506 0.035186767578125 +48507 0.0267333984375 +48508 0.091278076171875 +48509 0.08251953125 +48510 0.108642578125 +48511 0.101654052734375 +48512 0.125 +48513 0.119842529296875 +48514 0.156982421875 +48515 0.15277099609375 +48516 0.1773681640625 +48517 0.174407958984375 +48518 0.170013427734375 +48519 0.169281005859375 +48520 0.128814697265625 +48521 0.131500244140625 +48522 0.08123779296875 +48523 0.087127685546875 +48524 0.026519775390625 +48525 0.035430908203125 +48526 -0.06671142578125 +48527 -0.053497314453125 +48528 -0.1602783203125 +48529 -0.143280029296875 +48530 -0.21380615234375 +48531 -0.195404052734375 +48532 -0.235137939453125 +48533 -0.217315673828125 +48534 -0.200408935546875 +48535 -0.1861572265625 +48536 -0.119110107421875 +48537 -0.110870361328125 +48538 -0.0244140625 +48539 -0.02294921875 +48540 0.08636474609375 +48541 0.080352783203125 +48542 0.178924560546875 +48543 0.166473388671875 +48544 0.216522216796875 +48545 0.200592041015625 +48546 0.212493896484375 +48547 0.195404052734375 +48548 0.176300048828125 +48549 0.160003662109375 +48550 0.129791259765625 +48551 0.115234375 +48552 0.102874755859375 +48553 0.089599609375 +48554 0.075164794921875 +48555 0.063690185546875 +48556 0.0439453125 +48557 0.03485107421875 +48558 0.038665771484375 +48559 0.03106689453125 +48560 0.0765380859375 +48561 0.06866455078125 +48562 0.141082763671875 +48563 0.131866455078125 +48564 0.18621826171875 +48565 0.17669677734375 +48566 0.1883544921875 +48567 0.180572509765625 +48568 0.13836669921875 +48569 0.134674072265625 +48570 0.04095458984375 +48571 0.043426513671875 +48572 -0.080352783203125 +48573 -0.07086181640625 +48574 -0.2203369140625 +48575 -0.20330810546875 +48576 -0.3687744140625 +48577 -0.344146728515625 +48578 -0.49578857421875 +48579 -0.4649658203125 +48580 -0.557098388671875 +48581 -0.52362060546875 +48582 -0.50946044921875 +48583 -0.4788818359375 +48584 -0.376251220703125 +48585 -0.352996826171875 +48586 -0.219390869140625 +48587 -0.204864501953125 +48588 -0.064056396484375 +48589 -0.058349609375 +48590 0.0914306640625 +48591 0.08819580078125 +48592 0.236083984375 +48593 0.22442626953125 +48594 0.34320068359375 +48595 0.32501220703125 +48596 0.395538330078125 +48597 0.37359619140625 +48598 0.389801025390625 +48599 0.367095947265625 +48600 0.324737548828125 +48601 0.30438232421875 +48602 0.224609375 +48603 0.20855712890625 +48604 0.124786376953125 +48605 0.113311767578125 +48606 0.037567138671875 +48607 0.030364990234375 +48608 -0.009674072265625 +48609 -0.01422119140625 +48610 -0.01910400390625 +48611 -0.022552490234375 +48612 -0.022552490234375 +48613 -0.02496337890625 +48614 -0.00140380859375 +48615 -0.003814697265625 +48616 0.056365966796875 +48617 0.05230712890625 +48618 0.106658935546875 +48619 0.10137939453125 +48620 0.096710205078125 +48621 0.09307861328125 +48622 0.04241943359375 +48623 0.04248046875 +48624 -0.01837158203125 +48625 -0.01446533203125 +48626 -0.07623291015625 +48627 -0.068817138671875 +48628 -0.11981201171875 +48629 -0.109832763671875 +48630 -0.16009521484375 +48631 -0.14794921875 +48632 -0.20294189453125 +48633 -0.18878173828125 +48634 -0.2489013671875 +48635 -0.232818603515625 +48636 -0.305419921875 +48637 -0.287109375 +48638 -0.3623046875 +48639 -0.3419189453125 +48640 -0.39154052734375 +48641 -0.370697021484375 +48642 -0.3553466796875 +48643 -0.337493896484375 +48644 -0.249969482421875 +48645 -0.2386474609375 +48646 -0.092803955078125 +48647 -0.090850830078125 +48648 0.08917236328125 +48649 0.08050537109375 +48650 0.23541259765625 +48651 0.21917724609375 +48652 0.319061279296875 +48653 0.300048828125 +48654 0.358917236328125 +48655 0.340057373046875 +48656 0.348052978515625 +48657 0.33258056640625 +48658 0.285980224609375 +48659 0.27703857421875 +48660 0.2235107421875 +48661 0.220123291015625 +48662 0.197052001953125 +48663 0.195343017578125 +48664 0.18011474609375 +48665 0.178375244140625 +48666 0.155792236328125 +48667 0.15380859375 +48668 0.15142822265625 +48669 0.14697265625 +48670 0.157135009765625 +48671 0.14898681640625 +48672 0.13189697265625 +48673 0.122344970703125 +48674 0.100860595703125 +48675 0.09033203125 +48676 0.087127685546875 +48677 0.074432373046875 +48678 0.0548095703125 +48679 0.041839599609375 +48680 -0.00909423828125 +48681 -0.019256591796875 +48682 -0.1041259765625 +48683 -0.108306884765625 +48684 -0.22955322265625 +48685 -0.224578857421875 +48686 -0.355712890625 +48687 -0.34075927734375 +48688 -0.442108154296875 +48689 -0.41961669921875 +48690 -0.474029541015625 +48691 -0.447662353515625 +48692 -0.4649658203125 +48693 -0.437408447265625 +48694 -0.419219970703125 +48695 -0.392913818359375 +48696 -0.334381103515625 +48697 -0.3121337890625 +48698 -0.227935791015625 +48699 -0.211273193359375 +48700 -0.1234130859375 +48701 -0.112152099609375 +48702 -0.02752685546875 +48703 -0.021148681640625 +48704 0.077850341796875 +48705 0.078277587890625 +48706 0.2135009765625 +48707 0.205108642578125 +48708 0.38916015625 +48709 0.368194580078125 +48710 0.583160400390625 +48711 0.547515869140625 +48712 0.73443603515625 +48713 0.686920166015625 +48714 0.800537109375 +48715 0.747344970703125 +48716 0.7786865234375 +48717 0.72625732421875 +48718 0.665496826171875 +48719 0.62060546875 +48720 0.459930419921875 +48721 0.429595947265625 +48722 0.19940185546875 +48723 0.187713623046875 +48724 -0.050567626953125 +48725 -0.044586181640625 +48726 -0.232940673828125 +48727 -0.2147216796875 +48728 -0.3302001953125 +48729 -0.30645751953125 +48730 -0.3685302734375 +48731 -0.343780517578125 +48732 -0.379119873046875 +48733 -0.355224609375 +48734 -0.377227783203125 +48735 -0.354766845703125 +48736 -0.379974365234375 +48737 -0.358154296875 +48738 -0.391815185546875 +48739 -0.369384765625 +48740 -0.38568115234375 +48741 -0.36358642578125 +48742 -0.34228515625 +48743 -0.322998046875 +48744 -0.28326416015625 +48745 -0.267608642578125 +48746 -0.251983642578125 +48747 -0.23736572265625 +48748 -0.2664794921875 +48749 -0.248992919921875 +48750 -0.27362060546875 +48751 -0.25372314453125 +48752 -0.217010498046875 +48753 -0.199737548828125 +48754 -0.128387451171875 +48755 -0.1163330078125 +48756 -0.06817626953125 +48757 -0.059234619140625 +48758 -0.04302978515625 +48759 -0.034637451171875 +48760 -0.0242919921875 +48761 -0.0162353515625 +48762 0.020965576171875 +48763 0.02618408203125 +48764 0.12481689453125 +48765 0.122100830078125 +48766 0.258270263671875 +48767 0.244842529296875 +48768 0.379547119140625 +48769 0.355987548828125 +48770 0.480377197265625 +48771 0.44793701171875 +48772 0.528656005859375 +48773 0.491241455078125 +48774 0.5115966796875 +48775 0.474151611328125 +48776 0.456634521484375 +48777 0.422027587890625 +48778 0.4078369140625 +48779 0.37554931640625 +48780 0.384033203125 +48781 0.35211181640625 +48782 0.357025146484375 +48783 0.325836181640625 +48784 0.311859130859375 +48785 0.28302001953125 +48786 0.25079345703125 +48787 0.225799560546875 +48788 0.165191650390625 +48789 0.14630126953125 +48790 0.034912109375 +48791 0.026031494140625 +48792 -0.14251708984375 +48793 -0.137237548828125 +48794 -0.336181640625 +48795 -0.31512451171875 +48796 -0.53515625 +48797 -0.49755859375 +48798 -0.722503662109375 +48799 -0.668975830078125 +48800 -0.8372802734375 +48801 -0.7734375 +48802 -0.83319091796875 +48803 -0.768402099609375 +48804 -0.730072021484375 +48805 -0.672210693359375 +48806 -0.5828857421875 +48807 -0.535491943359375 +48808 -0.440277099609375 +48809 -0.403045654296875 +48810 -0.3243408203125 +48811 -0.2952880859375 +48812 -0.20135498046875 +48813 -0.1812744140625 +48814 -0.04437255859375 +48815 -0.036224365234375 +48816 0.1043701171875 +48817 0.100982666015625 +48818 0.202911376953125 +48819 0.191680908203125 +48820 0.265106201171875 +48821 0.2486572265625 +48822 0.339569091796875 +48823 0.316680908203125 +48824 0.444488525390625 +48825 0.412506103515625 +48826 0.545684814453125 +48827 0.504791259765625 +48828 0.617828369140625 +48829 0.570220947265625 +48830 0.652862548828125 +48831 0.6014404296875 +48832 0.66363525390625 +48833 0.6103515625 +48834 0.65618896484375 +48835 0.602569580078125 +48836 0.606658935546875 +48837 0.55615234375 +48838 0.500885009765625 +48839 0.4581298828125 +48840 0.352325439453125 +48841 0.32086181640625 +48842 0.17596435546875 +48843 0.158203125 +48844 -0.035491943359375 +48845 -0.036529541015625 +48846 -0.258941650390625 +48847 -0.2420654296875 +48848 -0.443206787109375 +48849 -0.41131591796875 +48850 -0.5760498046875 +48851 -0.5330810546875 +48852 -0.6527099609375 +48853 -0.602996826171875 +48854 -0.6422119140625 +48855 -0.59259033203125 +48856 -0.5626220703125 +48857 -0.518524169921875 +48858 -0.4583740234375 +48859 -0.4217529296875 +48860 -0.350738525390625 +48861 -0.3218994140625 +48862 -0.26055908203125 +48863 -0.2381591796875 +48864 -0.191986083984375 +48865 -0.174407958984375 +48866 -0.141693115234375 +48867 -0.12762451171875 +48868 -0.101837158203125 +48869 -0.090606689453125 +48870 -0.062469482421875 +48871 -0.054229736328125 +48872 -0.011444091796875 +48873 -0.007293701171875 +48874 0.0633544921875 +48875 0.06134033203125 +48876 0.149261474609375 +48877 0.1400146484375 +48878 0.242279052734375 +48879 0.225067138671875 +48880 0.349639892578125 +48881 0.323211669921875 +48882 0.457794189453125 +48883 0.4219970703125 +48884 0.5443115234375 +48885 0.5008544921875 +48886 0.573211669921875 +48887 0.5267333984375 +48888 0.506805419921875 +48889 0.464996337890625 +48890 0.351318359375 +48891 0.321380615234375 +48892 0.146484375 +48893 0.132476806640625 +48894 -0.055389404296875 +48895 -0.053558349609375 +48896 -0.21649169921875 +48897 -0.201629638671875 +48898 -0.335235595703125 +48899 -0.310455322265625 +48900 -0.403350830078125 +48901 -0.373291015625 +48902 -0.441680908203125 +48903 -0.408538818359375 +48904 -0.496185302734375 +48905 -0.457061767578125 +48906 -0.560546875 +48907 -0.5133056640625 +48908 -0.601043701171875 +48909 -0.547454833984375 +48910 -0.58447265625 +48911 -0.5301513671875 +48912 -0.479461669921875 +48913 -0.433746337890625 +48914 -0.2794189453125 +48915 -0.252593994140625 +48916 -0.008880615234375 +48917 -0.0086669921875 +48918 0.268890380859375 +48919 0.24163818359375 +48920 0.48297119140625 +48921 0.43511962890625 +48922 0.603912353515625 +48923 0.545440673828125 +48924 0.650665283203125 +48925 0.58929443359375 +48926 0.66424560546875 +48927 0.602996826171875 +48928 0.641693115234375 +48929 0.5838623046875 +48930 0.572723388671875 +48931 0.522705078125 +48932 0.498291015625 +48933 0.455902099609375 +48934 0.4395751953125 +48935 0.402313232421875 +48936 0.3756103515625 +48937 0.34344482421875 +48938 0.274566650390625 +48939 0.251129150390625 +48940 0.108795166015625 +48941 0.100982666015625 +48942 -0.099395751953125 +48943 -0.08697509765625 +48944 -0.318267822265625 +48945 -0.28436279296875 +48946 -0.54901123046875 +48947 -0.492095947265625 +48948 -0.773895263671875 +48949 -0.694305419921875 +48950 -0.86383056640625 +48951 -0.843841552734375 +48952 -0.870391845703125 +48953 -0.860687255859375 +48954 -0.86895751953125 +48955 -0.860748291015625 +48956 -0.86102294921875 +48957 -0.85479736328125 +48958 -0.765625 +48959 -0.732086181640625 +48960 -0.529876708984375 +48961 -0.52679443359375 +48962 -0.21441650390625 +48963 -0.247528076171875 +48964 0.137603759765625 +48965 0.067352294921875 +48966 0.475006103515625 +48967 0.372161865234375 +48968 0.76251220703125 +48969 0.63519287109375 +48970 0.867462158203125 +48971 0.83233642578125 +48972 0.870361328125 +48973 0.866424560546875 +48974 0.864776611328125 +48975 0.870361328125 +48976 0.831695556640625 +48977 0.866668701171875 +48978 0.677398681640625 +48979 0.85784912109375 +48980 0.49566650390625 +48981 0.762847900390625 +48982 0.30743408203125 +48983 0.615936279296875 +48984 0.115936279296875 +48985 0.44683837890625 +48986 -0.1109619140625 +48987 0.227508544921875 +48988 -0.381988525390625 +48989 -0.048248291015625 +48990 -0.6573486328125 +48991 -0.34271240234375 +48992 -0.857421875 +48993 -0.603179931640625 +48994 -0.870391845703125 +48995 -0.7921142578125 +48996 -0.870391845703125 +48997 -0.859893798828125 +48998 -0.86444091796875 +48999 -0.866363525390625 +49000 -0.85723876953125 +49001 -0.870391845703125 +49002 -0.790008544921875 +49003 -0.870391845703125 +49004 -0.62847900390625 +49005 -0.861358642578125 +49006 -0.3956298828125 +49007 -0.75006103515625 +49008 -0.126708984375 +49009 -0.527862548828125 +49010 0.150115966796875 +49011 -0.2755126953125 +49012 0.424041748046875 +49013 -0.003631591796875 +49014 0.670623779296875 +49015 0.26385498046875 +49016 0.854522705078125 +49017 0.492767333984375 +49018 0.866485595703125 +49019 0.667816162109375 +49020 0.86920166015625 +49021 0.775909423828125 +49022 0.8653564453125 +49023 0.83380126953125 +49024 0.857147216796875 +49025 0.854156494140625 +49026 0.766845703125 +49027 0.835235595703125 +49028 0.628509521484375 +49029 0.782379150390625 +49030 0.462127685546875 +49031 0.69036865234375 +49032 0.297210693359375 +49033 0.582794189453125 +49034 0.14862060546875 +49035 0.47119140625 +49036 -0.00537109375 +49037 0.335693359375 +49038 -0.15753173828125 +49039 0.183197021484375 +49040 -0.31304931640625 +49041 0.010589599609375 +49042 -0.48876953125 +49043 -0.194671630859375 +49044 -0.6416015625 +49045 -0.3912353515625 +49046 -0.751373291015625 +49047 -0.557525634765625 +49048 -0.84619140625 +49049 -0.71453857421875 +49050 -0.861297607421875 +49051 -0.849822998046875 +49052 -0.863250732421875 +49053 -0.863250732421875 +49054 -0.856597900390625 +49055 -0.863983154296875 +49056 -0.7498779296875 +49057 -0.85748291015625 +49058 -0.624542236328125 +49059 -0.80743408203125 +49060 -0.47808837890625 +49061 -0.699554443359375 +49062 -0.253387451171875 +49063 -0.50653076171875 +49064 0.003692626953125 +49065 -0.269195556640625 +49066 0.2257080078125 +49067 -0.048370361328125 +49068 0.427154541015625 +49069 0.16705322265625 +49070 0.643218994140625 +49071 0.405975341796875 +49072 0.855926513671875 +49073 0.660064697265625 +49074 0.870361328125 +49075 0.857086181640625 +49076 0.870361328125 +49077 0.870361328125 +49078 0.862762451171875 +49079 0.870361328125 +49080 0.79669189453125 +49081 0.862884521484375 +49082 0.595794677734375 +49083 0.789947509765625 +49084 0.362152099609375 +49085 0.60394287109375 +49086 0.1270751953125 +49087 0.400665283203125 +49088 -0.086944580078125 +49089 0.200225830078125 +49090 -0.2784423828125 +49091 0.004913330078125 +49092 -0.484832763671875 +49093 -0.21661376953125 +49094 -0.729583740234375 +49095 -0.482757568359375 +49096 -0.86688232421875 +49097 -0.750701904296875 +49098 -0.870391845703125 +49099 -0.86676025390625 +49100 -0.86859130859375 +49101 -0.870391845703125 +49102 -0.86279296875 +49103 -0.86956787109375 +49104 -0.817962646484375 +49105 -0.86187744140625 +49106 -0.6116943359375 +49107 -0.756622314453125 +49108 -0.3128662109375 +49109 -0.496978759765625 +49110 0.039398193359375 +49111 -0.177703857421875 +49112 0.422821044921875 +49113 0.1806640625 +49114 0.805145263671875 +49115 0.548126220703125 +49116 0.870361328125 +49117 0.855743408203125 +49118 0.870361328125 +49119 0.870361328125 +49120 0.860015869140625 +49121 0.870361328125 +49122 0.727935791015625 +49123 0.86090087890625 +49124 0.48114013671875 +49125 0.74871826171875 +49126 0.2059326171875 +49127 0.539642333984375 +49128 -0.06103515625 +49129 0.317413330078125 +49130 -0.29913330078125 +49131 0.100067138671875 +49132 -0.516204833984375 +49133 -0.118377685546875 +49134 -0.7252197265625 +49135 -0.34747314453125 +49136 -0.85980224609375 +49137 -0.563720703125 +49138 -0.870391845703125 +49139 -0.73797607421875 +49140 -0.870391845703125 +49141 -0.84796142578125 +49142 -0.858062744140625 +49143 -0.854736328125 +49144 -0.673004150390625 +49145 -0.768707275390625 +49146 -0.42694091796875 +49147 -0.640045166015625 +49148 -0.2100830078125 +49149 -0.520538330078125 +49150 -0.0362548828125 +49151 -0.418914794921875 +49152 0.10943603515625 +49153 -0.319366455078125 +49154 0.23516845703125 +49155 -0.213470458984375 +49156 0.373687744140625 +49157 -0.073699951171875 +49158 0.517791748046875 +49159 0.091888427734375 +49160 0.602783203125 +49161 0.224945068359375 +49162 0.635711669921875 +49163 0.32769775390625 +49164 0.655181884765625 +49165 0.42864990234375 +49166 0.65948486328125 +49167 0.52142333984375 +49168 0.651275634765625 +49169 0.603271484375 +49170 0.61846923828125 +49171 0.65899658203125 +49172 0.53753662109375 +49173 0.664031982421875 +49174 0.404144287109375 +49175 0.61090087890625 +49176 0.22186279296875 +49177 0.49969482421875 +49178 0.003997802734375 +49179 0.339874267578125 +49180 -0.22100830078125 +49181 0.15478515625 +49182 -0.42449951171875 +49183 -0.030853271484375 +49184 -0.579833984375 +49185 -0.19305419921875 +49186 -0.641876220703125 +49187 -0.29107666015625 +49188 -0.6177978515625 +49189 -0.328155517578125 +49190 -0.575531005859375 +49191 -0.35894775390625 +49192 -0.526336669921875 +49193 -0.389190673828125 +49194 -0.42645263671875 +49195 -0.3773193359375 +49196 -0.2581787109375 +49197 -0.304107666015625 +49198 -0.068695068359375 +49199 -0.2061767578125 +49200 0.09222412109375 +49201 -0.12274169921875 +49202 0.232147216796875 +49203 -0.044677734375 +49204 0.3509521484375 +49205 0.02978515625 +49206 0.410064697265625 +49207 0.06866455078125 +49208 0.372955322265625 +49209 0.040924072265625 +49210 0.2554931640625 +49211 -0.040496826171875 +49212 0.10711669921875 +49213 -0.134796142578125 +49214 -0.052886962890625 +49215 -0.227630615234375 +49216 -0.186279296875 +49217 -0.288970947265625 +49218 -0.23291015625 +49219 -0.2705078125 +49220 -0.209442138671875 +49221 -0.1898193359375 +49222 -0.174163818359375 +49223 -0.100189208984375 +49224 -0.126739501953125 +49225 -0.0045166015625 +49226 -0.048126220703125 +49227 0.110565185546875 +49228 0.0426025390625 +49229 0.22637939453125 +49230 0.10748291015625 +49231 0.308624267578125 +49232 0.1409912109375 +49233 0.351409912109375 +49234 0.19708251953125 +49235 0.400543212890625 +49236 0.273651123046875 +49237 0.454559326171875 +49238 0.31768798828125 +49239 0.46905517578125 +49240 0.341094970703125 +49241 0.455810546875 +49242 0.368011474609375 +49243 0.4376220703125 +49244 0.37249755859375 +49245 0.394744873046875 +49246 0.30072021484375 +49247 0.28375244140625 +49248 0.1517333984375 +49249 0.10662841796875 +49250 -0.01470947265625 +49251 -0.082763671875 +49252 -0.1883544921875 +49253 -0.27313232421875 +49254 -0.372711181640625 +49255 -0.465362548828125 +49256 -0.51397705078125 +49257 -0.61175537109375 +49258 -0.57177734375 +49259 -0.67657470703125 +49260 -0.53948974609375 +49261 -0.653656005859375 +49262 -0.43511962890625 +49263 -0.558441162109375 +49264 -0.2962646484375 +49265 -0.423736572265625 +49266 -0.161102294921875 +49267 -0.283355712890625 +49268 -0.0435791015625 +49269 -0.15081787109375 +49270 0.060394287109375 +49271 -0.024627685546875 +49272 0.13665771484375 +49273 0.0809326171875 +49274 0.170135498046875 +49275 0.150665283203125 +49276 0.16552734375 +49277 0.18634033203125 +49278 0.15728759765625 +49279 0.21533203125 +49280 0.150787353515625 +49281 0.24041748046875 +49282 0.12200927734375 +49283 0.239471435546875 +49284 0.080108642578125 +49285 0.21923828125 +49286 0.05126953125 +49287 0.201507568359375 +49288 0.062896728515625 +49289 0.20965576171875 +49290 0.09271240234375 +49291 0.22491455078125 +49292 0.092987060546875 +49293 0.207275390625 +49294 0.07855224609375 +49295 0.17059326171875 +49296 0.06427001953125 +49297 0.12908935546875 +49298 0.0347900390625 +49299 0.071380615234375 +49300 -0.01171875 +49301 -0.00225830078125 +49302 -0.056060791015625 +49303 -0.073486328125 +49304 -0.055511474609375 +49305 -0.10394287109375 +49306 -0.010467529296875 +49307 -0.092315673828125 +49308 0.02508544921875 +49309 -0.083465576171875 +49310 0.025665283203125 +49311 -0.098175048828125 +49312 0.017333984375 +49313 -0.113494873046875 +49314 0.00189208984375 +49315 -0.127655029296875 +49316 -0.03173828125 +49317 -0.1502685546875 +49318 -0.071502685546875 +49319 -0.171600341796875 +49320 -0.13543701171875 +49321 -0.207977294921875 +49322 -0.219970703125 +49323 -0.25750732421875 +49324 -0.300506591796875 +49325 -0.30047607421875 +49326 -0.376312255859375 +49327 -0.337799072265625 +49328 -0.416107177734375 +49329 -0.344207763671875 +49330 -0.371124267578125 +49331 -0.27947998046875 +49332 -0.242279052734375 +49333 -0.145782470703125 +49334 -0.069732666015625 +49335 0.021270751953125 +49336 0.125640869140625 +49337 0.202850341796875 +49338 0.31268310546875 +49339 0.371673583984375 +49340 0.45501708984375 +49341 0.496307373046875 +49342 0.554779052734375 +49343 0.57861328125 +49344 0.61065673828125 +49345 0.6177978515625 +49346 0.610931396484375 +49347 0.60443115234375 +49348 0.531463623046875 +49349 0.518768310546875 +49350 0.3883056640625 +49351 0.3756103515625 +49352 0.23468017578125 +49353 0.22174072265625 +49354 0.095245361328125 +49355 0.079559326171875 +49356 -0.00396728515625 +49357 -0.027435302734375 +49358 -0.04852294921875 +49359 -0.085693359375 +49360 -0.055145263671875 +49361 -0.108489990234375 +49362 -0.0758056640625 +49363 -0.139495849609375 +49364 -0.138702392578125 +49365 -0.20220947265625 +49366 -0.209197998046875 +49367 -0.2666015625 +49368 -0.289031982421875 +49369 -0.3341064453125 +49370 -0.37884521484375 +49371 -0.40545654296875 +49372 -0.456329345703125 +49373 -0.46197509765625 +49374 -0.51641845703125 +49375 -0.5 +49376 -0.519287109375 +49377 -0.48626708984375 +49378 -0.458251953125 +49379 -0.416015625 +49380 -0.384796142578125 +49381 -0.3343505859375 +49382 -0.323699951171875 +49383 -0.2635498046875 +49384 -0.269287109375 +49385 -0.19970703125 +49386 -0.1951904296875 +49387 -0.1212158203125 +49388 -0.100006103515625 +49389 -0.027587890625 +49390 -0.01055908203125 +49391 0.057586669921875 +49392 0.1033935546875 +49393 0.15985107421875 +49394 0.24908447265625 +49395 0.285247802734375 +49396 0.373199462890625 +49397 0.38824462890625 +49398 0.45806884765625 +49399 0.4539794921875 +49400 0.511474609375 +49401 0.489593505859375 +49402 0.565399169921875 +49403 0.52313232421875 +49404 0.61138916015625 +49405 0.548095703125 +49406 0.5897216796875 +49407 0.514190673828125 +49408 0.4906005859375 +49409 0.41400146484375 +49410 0.33148193359375 +49411 0.26348876953125 +49412 0.147796630859375 +49413 0.09356689453125 +49414 -0.01873779296875 +49415 -0.059600830078125 +49416 -0.140289306640625 +49417 -0.171783447265625 +49418 -0.191986083984375 +49419 -0.221435546875 +49420 -0.184295654296875 +49421 -0.21728515625 +49422 -0.161834716796875 +49423 -0.19720458984375 +49424 -0.166595458984375 +49425 -0.197021484375 +49426 -0.19390869140625 +49427 -0.213134765625 +49428 -0.22442626953125 +49429 -0.229522705078125 +49430 -0.279754638671875 +49431 -0.26513671875 +49432 -0.3389892578125 +49433 -0.30291748046875 +49434 -0.3543701171875 +49435 -0.302978515625 +49436 -0.348175048828125 +49437 -0.28497314453125 +49438 -0.32598876953125 +49439 -0.254364013671875 +49440 -0.2581787109375 +49441 -0.186553955078125 +49442 -0.139801025390625 +49443 -0.077850341796875 +49444 0.014617919921875 +49445 0.05902099609375 +49446 0.144378662109375 +49447 0.172210693359375 +49448 0.221038818359375 +49449 0.23748779296875 +49450 0.27069091796875 +49451 0.277130126953125 +49452 0.294036865234375 +49453 0.29193115234375 +49454 0.311767578125 +49455 0.299835205078125 +49456 0.339141845703125 +49457 0.314178466796875 +49458 0.360260009765625 +49459 0.321624755859375 +49460 0.360504150390625 +49461 0.310455322265625 +49462 0.308380126953125 +49463 0.2554931640625 +49464 0.18170166015625 +49465 0.13922119140625 +49466 0.0047607421875 +49467 -0.017578125 +49468 -0.17559814453125 +49469 -0.17572021484375 +49470 -0.3143310546875 +49471 -0.297607421875 +49472 -0.36785888671875 +49473 -0.346923828125 +49474 -0.36248779296875 +49475 -0.345123291015625 +49476 -0.343536376953125 +49477 -0.3294677734375 +49478 -0.3018798828125 +49479 -0.29254150390625 +49480 -0.231414794921875 +49481 -0.229522705078125 +49482 -0.117645263671875 +49483 -0.128814697265625 +49484 0.007049560546875 +49485 -0.017547607421875 +49486 0.087982177734375 +49487 0.0587158203125 +49488 0.13946533203125 +49489 0.111236572265625 +49490 0.17425537109375 +49491 0.149932861328125 +49492 0.188201904296875 +49493 0.17083740234375 +49494 0.171234130859375 +49495 0.165130615234375 +49496 0.118438720703125 +49497 0.128326416015625 +49498 0.05706787109375 +49499 0.08258056640625 +49500 -0.010711669921875 +49501 0.029449462890625 +49502 -0.0914306640625 +49503 -0.0364990234375 +49504 -0.162322998046875 +49505 -0.096466064453125 +49506 -0.194549560546875 +49507 -0.1265869140625 +49508 -0.1492919921875 +49509 -0.094635009765625 +49510 -0.02166748046875 +49511 0.003753662109375 +49512 0.124053955078125 +49513 0.1160888671875 +49514 0.211151123046875 +49515 0.179595947265625 +49516 0.240447998046875 +49517 0.195404052734375 +49518 0.242218017578125 +49519 0.18890380859375 +49520 0.2257080078125 +49521 0.168182373046875 +49522 0.194366455078125 +49523 0.13641357421875 +49524 0.115509033203125 +49525 0.06695556640625 +49526 0.0128173828125 +49527 -0.02044677734375 +49528 -0.053802490234375 +49529 -0.076324462890625 +49530 -0.110626220703125 +49531 -0.122344970703125 +49532 -0.199493408203125 +49533 -0.193115234375 +49534 -0.29437255859375 +49535 -0.267333984375 +49536 -0.33221435546875 +49537 -0.293304443359375 +49538 -0.27972412109375 +49539 -0.243927001953125 +49540 -0.185333251953125 +49541 -0.15948486328125 +49542 -0.128204345703125 +49543 -0.105560302734375 +49544 -0.115692138671875 +49545 -0.08856201171875 +49546 -0.116455078125 +49547 -0.08306884765625 +49548 -0.105926513671875 +49549 -0.069122314453125 +49550 -0.053955078125 +49551 -0.02215576171875 +49552 0.048797607421875 +49553 0.0653076171875 +49554 0.157318115234375 +49555 0.15606689453125 +49556 0.212005615234375 +49557 0.201019287109375 +49558 0.218475341796875 +49559 0.204803466796875 +49560 0.23724365234375 +49561 0.2174072265625 +49562 0.30535888671875 +49563 0.269561767578125 +49564 0.38128662109375 +49565 0.3272705078125 +49566 0.404449462890625 +49567 0.340911865234375 +49568 0.3944091796875 +49569 0.326904296875 +49570 0.3885498046875 +49571 0.31640625 +49572 0.362640380859375 +49573 0.289794921875 +49574 0.27362060546875 +49575 0.211822509765625 +49576 0.11712646484375 +49577 0.079132080078125 +49578 -0.054901123046875 +49579 -0.065277099609375 +49580 -0.19085693359375 +49581 -0.178741455078125 +49582 -0.28570556640625 +49583 -0.257110595703125 +49584 -0.339263916015625 +49585 -0.30029296875 +49586 -0.3775634765625 +49587 -0.32977294921875 +49588 -0.445709228515625 +49589 -0.38287353515625 +49590 -0.535064697265625 +49591 -0.452667236328125 +49592 -0.629058837890625 +49593 -0.5257568359375 +49594 -0.697601318359375 +49595 -0.577606201171875 +49596 -0.70391845703125 +49597 -0.578155517578125 +49598 -0.6424560546875 +49599 -0.523101806640625 +49600 -0.491241455078125 +49601 -0.394561767578125 +49602 -0.265716552734375 +49603 -0.2054443359375 +49604 -0.023712158203125 +49605 -0.003570556640625 +49606 0.201751708984375 +49607 0.1837158203125 +49608 0.375823974609375 +49609 0.327667236328125 +49610 0.485076904296875 +49611 0.417205810546875 +49612 0.56884765625 +49613 0.48480224609375 +49614 0.634765625 +49615 0.536865234375 +49616 0.63763427734375 +49617 0.53631591796875 +49618 0.5660400390625 +49619 0.473876953125 +49620 0.4720458984375 +49621 0.392669677734375 +49622 0.40692138671875 +49623 0.33514404296875 +49624 0.3778076171875 +49625 0.307403564453125 +49626 0.376953125 +49627 0.30328369140625 +49628 0.371978759765625 +49629 0.2962646484375 +49630 0.313140869140625 +49631 0.245513916015625 +49632 0.184417724609375 +49633 0.137939453125 +49634 0.011199951171875 +49635 -0.00543212890625 +49636 -0.171051025390625 +49637 -0.155426025390625 +49638 -0.33740234375 +49639 -0.291534423828125 +49640 -0.47198486328125 +49641 -0.4007568359375 +49642 -0.560394287109375 +49643 -0.4713134765625 +49644 -0.58056640625 +49645 -0.485198974609375 +49646 -0.54754638671875 +49647 -0.454986572265625 +49648 -0.508575439453125 +49649 -0.41973876953125 +49650 -0.459503173828125 +49651 -0.376220703125 +49652 -0.394378662109375 +49653 -0.3197021484375 +49654 -0.35260009765625 +49655 -0.282806396484375 +49656 -0.31170654296875 +49657 -0.24713134765625 +49658 -0.197418212890625 +49659 -0.15155029296875 +49660 -0.007965087890625 +49661 0.00531005859375 +49662 0.207489013671875 +49663 0.18292236328125 +49664 0.409210205078125 +49665 0.348480224609375 +49666 0.57208251953125 +49667 0.48077392578125 +49668 0.66595458984375 +49669 0.5555419921875 +49670 0.65875244140625 +49671 0.54779052734375 +49672 0.56744384765625 +49673 0.47149658203125 +49674 0.431396484375 +49675 0.358367919921875 +49676 0.29443359375 +49677 0.24365234375 +49678 0.182464599609375 +49679 0.148345947265625 +49680 0.06365966796875 +49681 0.0477294921875 +49682 -0.075958251953125 +49683 -0.068878173828125 +49684 -0.189422607421875 +49685 -0.163970947265625 +49686 -0.271942138671875 +49687 -0.233489990234375 +49688 -0.342529296875 +49689 -0.29229736328125 +49690 -0.364166259765625 +49691 -0.311004638671875 +49692 -0.327239990234375 +49693 -0.281951904296875 +49694 -0.2769775390625 +49695 -0.240997314453125 +49696 -0.253692626953125 +49697 -0.22021484375 +49698 -0.24365234375 +49699 -0.208892822265625 +49700 -0.1983642578125 +49701 -0.168853759765625 +49702 -0.116241455078125 +49703 -0.09912109375 +49704 -0.036834716796875 +49705 -0.031280517578125 +49706 0.034881591796875 +49707 0.030426025390625 +49708 0.09124755859375 +49709 0.079681396484375 +49710 0.10888671875 +49711 0.097747802734375 +49712 0.125518798828125 +49713 0.114227294921875 +49714 0.15771484375 +49715 0.142120361328125 +49716 0.17828369140625 +49717 0.159759521484375 +49718 0.17108154296875 +49719 0.154327392578125 +49720 0.129974365234375 +49721 0.12103271484375 +49722 0.082427978515625 +49723 0.0816650390625 +49724 0.027679443359375 +49725 0.0357666015625 +49726 -0.065643310546875 +49727 -0.041351318359375 +49728 -0.15936279296875 +49729 -0.1192626953125 +49730 -0.21307373046875 +49731 -0.165771484375 +49732 -0.234649658203125 +49733 -0.1868896484375 +49734 -0.2001953125 +49735 -0.1634521484375 +49736 -0.119171142578125 +49737 -0.10272216796875 +49738 -0.024749755859375 +49739 -0.03082275390625 +49740 0.085784912109375 +49741 0.054534912109375 +49742 0.178131103515625 +49743 0.12628173828125 +49744 0.215576171875 +49745 0.1553955078125 +49746 0.211456298828125 +49747 0.152435302734375 +49748 0.17523193359375 +49749 0.124847412109375 +49750 0.128753662109375 +49751 0.089874267578125 +49752 0.1019287109375 +49753 0.07110595703125 +49754 0.0743408203125 +49755 0.052215576171875 +49756 0.04327392578125 +49757 0.030853271484375 +49758 0.038177490234375 +49759 0.0301513671875 +49760 0.076263427734375 +49761 0.063568115234375 +49762 0.14105224609375 +49763 0.11785888671875 +49764 0.186431884765625 +49765 0.1563720703125 +49766 0.188812255859375 +49767 0.1602783203125 +49768 0.1390380859375 +49769 0.122222900390625 +49770 0.041778564453125 +49771 0.045867919921875 +49772 -0.079437255859375 +49773 -0.0501708984375 +49774 -0.219390869140625 +49775 -0.1617431640625 +49776 -0.367828369140625 +49777 -0.280670166015625 +49778 -0.494873046875 +49779 -0.3831787109375 +49780 -0.556243896484375 +49781 -0.43408203125 +49782 -0.508697509765625 +49783 -0.399017333984375 +49784 -0.3756103515625 +49785 -0.29632568359375 +49786 -0.218902587890625 +49787 -0.1749267578125 +49788 -0.063751220703125 +49789 -0.0545654296875 +49790 0.091552734375 +49791 0.066192626953125 +49792 0.23602294921875 +49793 0.17877197265625 +49794 0.342987060546875 +49795 0.26214599609375 +49796 0.39520263671875 +49797 0.302703857421875 +49798 0.389373779296875 +49799 0.297882080078125 +49800 0.324249267578125 +49801 0.246673583984375 +49802 0.224090576171875 +49803 0.168243408203125 +49804 0.124267578125 +49805 0.090545654296875 +49806 0.037078857421875 +49807 0.023223876953125 +49808 -0.010101318359375 +49809 -0.012115478515625 +49810 -0.019439697265625 +49811 -0.017333984375 +49812 -0.022796630859375 +49813 -0.017730712890625 +49814 -0.001556396484375 +49815 0.001251220703125 +49816 0.056304931640625 +49817 0.049041748046875 +49818 0.106719970703125 +49819 0.090606689453125 +49820 0.096893310546875 +49821 0.0841064453125 +49822 0.042694091796875 +49823 0.042022705078125 +49824 -0.018035888671875 +49825 -0.005706787109375 +49826 -0.07586669921875 +49827 -0.051605224609375 +49828 -0.11944580078125 +49829 -0.086669921875 +49830 -0.15972900390625 +49831 -0.11956787109375 +49832 -0.202606201171875 +49833 -0.154876708984375 +49834 -0.24859619140625 +49835 -0.192901611328125 +49836 -0.30517578125 +49837 -0.239471435546875 +49838 -0.36212158203125 +49839 -0.286376953125 +49840 -0.39141845703125 +49841 -0.311370849609375 +49842 -0.35528564453125 +49843 -0.284393310546875 +49844 -0.249969482421875 +49845 -0.202392578125 +49846 -0.092864990234375 +49847 -0.0791015625 +49848 0.08905029296875 +49849 0.064178466796875 +49850 0.2352294921875 +49851 0.179534912109375 +49852 0.318817138671875 +49853 0.2457275390625 +49854 0.358642578125 +49855 0.277618408203125 +49856 0.347747802734375 +49857 0.269683837890625 +49858 0.28564453125 +49859 0.221466064453125 +49860 0.223175048828125 +49861 0.173187255859375 +49862 0.196746826171875 +49863 0.15362548828125 +49864 0.179840087890625 +49865 0.141693115234375 +49866 0.155548095703125 +49867 0.123931884765625 +49868 0.151214599609375 +49869 0.121917724609375 +49870 0.156951904296875 +49871 0.12774658203125 +49872 0.13177490234375 +49873 0.10882568359375 +49874 0.100799560546875 +49875 0.08502197265625 +49876 0.087127685546875 +49877 0.0745849609375 +49878 0.05487060546875 +49879 0.049102783203125 +49880 -0.009002685546875 +49881 -0.001708984375 +49882 -0.10400390625 +49883 -0.077423095703125 +49884 -0.229400634765625 +49885 -0.177459716796875 +49886 -0.35552978515625 +49887 -0.278289794921875 +49888 -0.441925048828125 +49889 -0.347747802734375 +49890 -0.473846435546875 +49891 -0.374176025390625 +49892 -0.464813232421875 +49893 -0.3681640625 +49894 -0.419097900390625 +49895 -0.333038330078125 +49896 -0.334320068359375 +49897 -0.266876220703125 +49898 -0.227935791015625 +49899 -0.183441162109375 +49900 -0.12347412109375 +49901 -0.101348876953125 +49902 -0.02764892578125 +49903 -0.02587890625 +49904 0.077667236328125 +49905 0.057342529296875 +49906 0.2132568359375 +49907 0.164764404296875 +49908 0.38885498046875 +49909 0.3040771484375 +49910 0.582794189453125 +49911 0.4581298828125 +49912 0.734039306640625 +49913 0.578521728515625 +49914 0.800140380859375 +49915 0.631622314453125 +49916 0.7783203125 +49917 0.61517333984375 +49918 0.6651611328125 +49919 0.52642822265625 +49920 0.45965576171875 +49921 0.36505126953125 +49922 0.199188232421875 +49923 0.161163330078125 +49924 -0.050689697265625 +49925 -0.03436279296875 +49926 -0.23297119140625 +49927 -0.178070068359375 +49928 -0.33013916015625 +49929 -0.25653076171875 +49930 -0.368408203125 +49931 -0.289520263671875 +49932 -0.378936767578125 +49933 -0.3006591796875 +49934 -0.376983642578125 +49935 -0.30145263671875 +49936 -0.37969970703125 +49937 -0.304901123046875 +49938 -0.391510009765625 +49939 -0.314361572265625 +49940 -0.385345458984375 +49941 -0.30926513671875 +49942 -0.3419189453125 +49943 -0.274993896484375 +49944 -0.28289794921875 +49945 -0.2281494140625 +49946 -0.251617431640625 +49947 -0.2017822265625 +49948 -0.266143798828125 +49949 -0.209747314453125 +49950 -0.273345947265625 +49951 -0.21185302734375 +49952 -0.216796875 +49953 -0.1654052734375 +49954 -0.128265380859375 +49955 -0.094696044921875 +49956 -0.068145751953125 +49957 -0.045867919921875 +49958 -0.0430908203125 +49959 -0.024078369140625 +49960 -0.024444580078125 +49961 -0.007720947265625 +49962 0.020721435546875 +49963 0.02813720703125 +49964 0.124481201171875 +49965 0.1077880859375 +49966 0.25787353515625 +49967 0.209197998046875 +49968 0.379119873046875 +49969 0.3006591796875 +49970 0.47991943359375 +49971 0.37591552734375 +49972 0.5281982421875 +49973 0.41070556640625 +49974 0.511138916015625 +49975 0.3953857421875 +49976 0.456207275390625 +49977 0.350982666015625 +49978 0.407470703125 +49979 0.3111572265625 +49980 0.383758544921875 +49981 0.290374755859375 +49982 0.35687255859375 +49983 0.267333984375 +49984 0.31182861328125 +49985 0.23077392578125 +49986 0.250885009765625 +49987 0.1824951171875 +49988 0.1654052734375 +49989 0.116058349609375 +49990 0.035247802734375 +49991 0.0162353515625 +49992 -0.142059326171875 +49993 -0.11883544921875 +49994 -0.33563232421875 +49995 -0.265655517578125 +49996 -0.5345458984375 +49997 -0.415924072265625 +49998 -0.72186279296875 +49999 -0.556854248046875 +50000 -0.836669921875 +50001 -0.64227294921875 +50002 -0.8326416015625 +50003 -0.6370849609375 +50004 -0.7296142578125 +50005 -0.5565185546875 +50006 -0.582550048828125 +50007 -0.44244384765625 +50008 -0.440093994140625 +50009 -0.331939697265625 +50010 -0.324310302734375 +50011 -0.241912841796875 +50012 -0.20147705078125 +50013 -0.146820068359375 +50014 -0.044647216796875 +50015 -0.0262451171875 +50016 0.103973388671875 +50017 0.087646484375 +50018 0.202392578125 +50019 0.16290283203125 +50020 0.264495849609375 +50021 0.21002197265625 +50022 0.338897705078125 +50023 0.2659912109375 +50024 0.443817138671875 +50025 0.3447265625 +50026 0.545074462890625 +50027 0.4202880859375 +50028 0.6173095703125 +50029 0.4735107421875 +50030 0.6524658203125 +50031 0.49835205078125 +50032 0.66339111328125 +50033 0.50469970703125 +50034 0.6561279296875 +50035 0.49725341796875 +50036 0.606781005859375 +50037 0.457977294921875 +50038 0.501190185546875 +50039 0.376190185546875 +50040 0.352783203125 +50041 0.262115478515625 +50042 0.176544189453125 +50043 0.12725830078125 +50044 -0.034820556640625 +50045 -0.03387451171875 +50046 -0.258209228515625 +50047 -0.203704833984375 +50048 -0.44244384765625 +50049 -0.3433837890625 +50050 -0.5753173828125 +50051 -0.443603515625 +50052 -0.65203857421875 +50053 -0.50079345703125 +50054 -0.641632080078125 +50055 -0.49151611328125 +50056 -0.562164306640625 +50057 -0.429595947265625 +50058 -0.458038330078125 +50059 -0.348846435546875 +50060 -0.350555419921875 +50061 -0.265533447265625 +50062 -0.260528564453125 +50063 -0.195556640625 +50064 -0.192108154296875 +50065 -0.142181396484375 +50066 -0.141937255859375 +50067 -0.1029052734375 +50068 -0.1021728515625 +50069 -0.07183837890625 +50070 -0.062896728515625 +50071 -0.04150390625 +50072 -0.011932373046875 +50073 -0.00262451171875 +50074 0.062835693359375 +50075 0.053985595703125 +50076 0.148712158203125 +50077 0.11871337890625 +50078 0.241729736328125 +50079 0.188568115234375 +50080 0.34912109375 +50081 0.26910400390625 +50082 0.457305908203125 +50083 0.35009765625 +50084 0.54388427734375 +50085 0.414581298828125 +50086 0.5728759765625 +50087 0.435272216796875 +50088 0.506591796875 +50089 0.38360595703125 +50090 0.351226806640625 +50091 0.264373779296875 +50092 0.146514892578125 +50093 0.107818603515625 +50094 -0.05523681640625 +50095 -0.0462646484375 +50096 -0.21624755859375 +50097 -0.16912841796875 +50098 -0.334930419921875 +50099 -0.259521484375 +50100 -0.402984619140625 +50101 -0.3111572265625 +50102 -0.4412841796875 +50103 -0.33990478515625 +50104 -0.49578857421875 +50105 -0.380706787109375 +50106 -0.5601806640625 +50107 -0.4288330078125 +50108 -0.600738525390625 +50109 -0.45867919921875 +50110 -0.584228515625 +50111 -0.445037841796875 +50112 -0.47930908203125 +50113 -0.364166259765625 +50114 -0.27935791015625 +50115 -0.21112060546875 +50116 -0.0089111328125 +50117 -0.004608154296875 +50118 0.268798828125 +50119 0.207244873046875 +50120 0.482818603515625 +50121 0.37054443359375 +50122 0.60369873046875 +50123 0.462860107421875 +50124 0.650421142578125 +50125 0.498565673828125 +50126 0.66400146484375 +50127 0.508819580078125 +50128 0.6414794921875 +50129 0.49139404296875 +50130 0.572540283203125 +50131 0.4384765625 +50132 0.498138427734375 +50133 0.381256103515625 +50134 0.439453125 +50135 0.335845947265625 +50136 0.375518798828125 +50137 0.286376953125 +50138 0.274505615234375 +50139 0.20867919921875 +50140 0.1087646484375 +50141 0.081817626953125 +50142 -0.099395751953125 +50143 -0.07720947265625 +50144 -0.3182373046875 +50145 -0.244232177734375 +50146 -0.5489501953125 +50147 -0.42010498046875 +50148 -0.7738037109375 +50149 -0.591339111328125 +50150 -0.86383056640625 +50151 -0.717681884765625 +50152 -0.870391845703125 +50153 -0.77386474609375 +50154 -0.86895751953125 +50155 -0.773345947265625 +50156 -0.861053466796875 +50157 -0.726104736328125 +50158 -0.765869140625 +50159 -0.619049072265625 +50160 -0.5301513671875 +50161 -0.443634033203125 +50162 -0.214691162109375 +50163 -0.205291748046875 +50164 0.137359619140625 +50165 0.063201904296875 +50166 0.474822998046875 +50167 0.322784423828125 +50168 0.76239013671875 +50169 0.546417236328125 +50170 0.867462158203125 +50171 0.71356201171875 +50172 0.870361328125 +50173 0.824493408203125 +50174 0.86480712890625 +50175 0.856231689453125 +50176 0.831817626953125 +50177 0.85455322265625 +50178 0.677581787109375 +50179 0.797454833984375 +50180 0.495880126953125 +50181 0.701385498046875 +50182 0.30767822265625 +50183 0.5809326171875 +50184 0.116180419921875 +50185 0.438140869140625 +50186 -0.110748291015625 +50187 0.2503662109375 +50188 -0.381805419921875 +50189 0.0130615234375 +50190 -0.6572265625 +50191 -0.24212646484375 +50192 -0.857421875 +50193 -0.47113037109375 +50194 -0.870391845703125 +50195 -0.64227294921875 +50196 -0.870391845703125 +50197 -0.75006103515625 +50198 -0.86444091796875 +50199 -0.813812255859375 +50200 -0.85723876953125 +50201 -0.85504150390625 +50202 -0.790008544921875 +50203 -0.8565673828125 +50204 -0.62847900390625 +50205 -0.816131591796875 +50206 -0.3956298828125 +50207 -0.685791015625 +50208 -0.126708984375 +50209 -0.50634765625 +50210 0.150115966796875 +50211 -0.298095703125 +50212 0.424041748046875 +50213 -0.069915771484375 +50214 0.670623779296875 +50215 0.158172607421875 +50216 0.854522705078125 +50217 0.3575439453125 +50218 0.866485595703125 +50219 0.514923095703125 +50220 0.86920166015625 +50221 0.6187744140625 +50222 0.8653564453125 +50223 0.6820068359375 +50224 0.857147216796875 +50225 0.714111328125 +50226 0.766845703125 +50227 0.7127685546875 +50228 0.628509521484375 +50229 0.681671142578125 +50230 0.462127685546875 +50231 0.61590576171875 +50232 0.297210693359375 +50233 0.534393310546875 +50234 0.14862060546875 +50235 0.4462890625 +50236 -0.00537109375 +50237 0.335235595703125 +50238 -0.15753173828125 +50239 0.20697021484375 +50240 -0.31304931640625 +50241 0.0592041015625 +50242 -0.48876953125 +50243 -0.117919921875 +50244 -0.6416015625 +50245 -0.2899169921875 +50246 -0.751373291015625 +50247 -0.438446044921875 +50248 -0.84619140625 +50249 -0.580047607421875 +50250 -0.861297607421875 +50251 -0.703765869140625 +50252 -0.863250732421875 +50253 -0.7852783203125 +50254 -0.856597900390625 +50255 -0.801513671875 +50256 -0.7498779296875 +50257 -0.76129150390625 +50258 -0.624542236328125 +50259 -0.706787109375 +50260 -0.47808837890625 +50261 -0.62213134765625 +50262 -0.253387451171875 +50263 -0.46490478515625 +50264 0.003692626953125 +50265 -0.26861572265625 +50266 0.2257080078125 +50267 -0.083282470703125 +50268 0.427154541015625 +50269 0.099884033203125 +50270 0.643218994140625 +50271 0.30413818359375 +50272 0.855926513671875 +50273 0.52215576171875 +50274 0.870361328125 +50275 0.71148681640625 +50276 0.870361328125 +50277 0.83575439453125 +50278 0.862762451171875 +50279 0.85943603515625 +50280 0.79669189453125 +50281 0.859649658203125 +50282 0.595794677734375 +50283 0.83465576171875 +50284 0.362152099609375 +50285 0.71942138671875 +50286 0.1270751953125 +50287 0.57672119140625 +50288 -0.086944580078125 +50289 0.422149658203125 +50290 -0.2784423828125 +50291 0.257415771484375 +50292 -0.484832763671875 +50293 0.0574951171875 +50294 -0.729583740234375 +50295 -0.191314697265625 +50296 -0.86688232421875 +50297 -0.45184326171875 +50298 -0.870391845703125 +50299 -0.67767333984375 +50300 -0.86859130859375 +50301 -0.85565185546875 +50302 -0.86279296875 +50303 -0.870391845703125 +50304 -0.817962646484375 +50305 -0.870391845703125 +50306 -0.6116943359375 +50307 -0.860260009765625 +50308 -0.3128662109375 +50309 -0.7203369140625 +50310 0.039398193359375 +50311 -0.46673583984375 +50312 0.422821044921875 +50313 -0.163330078125 +50314 0.805145263671875 +50315 0.16424560546875 +50316 0.870361328125 +50317 0.4659423828125 +50318 0.870361328125 +50319 0.700714111328125 +50320 0.860015869140625 +50321 0.855224609375 +50322 0.727935791015625 +50323 0.8642578125 +50324 0.48114013671875 +50325 0.8646240234375 +50326 0.2059326171875 +50327 0.858642578125 +50328 -0.06103515625 +50329 0.79901123046875 +50330 -0.29913330078125 +50331 0.677520751953125 +50332 -0.516204833984375 +50333 0.521026611328125 +50334 -0.7252197265625 +50335 0.32147216796875 +50336 -0.85980224609375 +50337 0.099761962890625 +50338 -0.870391845703125 +50339 -0.11688232421875 +50340 -0.870391845703125 +50341 -0.305328369140625 +50342 -0.858062744140625 +50343 -0.42919921875 +50344 -0.673004150390625 +50345 -0.4852294921875 +50346 -0.42694091796875 +50347 -0.512176513671875 +50348 -0.2100830078125 +50349 -0.54351806640625 +50350 -0.0362548828125 +50351 -0.5794677734375 +50352 0.10943603515625 +50353 -0.60107421875 +50354 0.23516845703125 +50355 -0.596405029296875 +50356 0.373687744140625 +50357 -0.538055419921875 +50358 0.517791748046875 +50359 -0.430267333984375 +50360 0.602783203125 +50361 -0.321563720703125 +50362 0.635711669921875 +50363 -0.21063232421875 +50364 0.655181884765625 +50365 -0.07525634765625 +50366 0.65948486328125 +50367 0.07568359375 +50368 0.651275634765625 +50369 0.235321044921875 +50370 0.61846923828125 +50371 0.385284423828125 +50372 0.53753662109375 +50373 0.498748779296875 +50374 0.404144287109375 +50375 0.563232421875 +50376 0.22186279296875 +50377 0.57281494140625 +50378 0.003997802734375 +50379 0.529998779296875 +50380 -0.22100830078125 +50381 0.449920654296875 +50382 -0.42449951171875 +50383 0.349761962890625 +50384 -0.579833984375 +50385 0.247344970703125 +50386 -0.641876220703125 +50387 0.176055908203125 +50388 -0.6177978515625 +50389 0.13311767578125 +50390 -0.575531005859375 +50391 0.0733642578125 +50392 -0.526336669921875 +50393 -0.005584716796875 +50394 -0.42645263671875 +50395 -0.06494140625 +50396 -0.2581787109375 +50397 -0.084075927734375 +50398 -0.068695068359375 +50399 -0.08935546875 +50400 0.09222412109375 +50401 -0.109100341796875 +50402 0.232147216796875 +50403 -0.13055419921875 +50404 0.3509521484375 +50405 -0.147491455078125 +50406 0.410064697265625 +50407 -0.182891845703125 +50408 0.372955322265625 +50409 -0.25982666015625 +50410 0.2554931640625 +50411 -0.364837646484375 +50412 0.10711669921875 +50413 -0.461761474609375 +50414 -0.052886962890625 +50415 -0.53802490234375 +50416 -0.186279296875 +50417 -0.56878662109375 +50418 -0.23291015625 +50419 -0.514678955078125 +50420 -0.209442138671875 +50421 -0.39324951171875 +50422 -0.174163818359375 +50423 -0.25311279296875 +50424 -0.126739501953125 +50425 -0.10052490234375 +50426 -0.048126220703125 +50427 0.07177734375 +50428 0.0426025390625 +50429 0.2437744140625 +50430 0.10748291015625 +50431 0.38232421875 +50432 0.1409912109375 +50433 0.478363037109375 +50434 0.19708251953125 +50435 0.567047119140625 +50436 0.273651123046875 +50437 0.645599365234375 +50438 0.31768798828125 +50439 0.6761474609375 +50440 0.341094970703125 +50441 0.667694091796875 +50442 0.368011474609375 +50443 0.639129638671875 +50444 0.37249755859375 +50445 0.575469970703125 +50446 0.30072021484375 +50447 0.44317626953125 +50448 0.1517333984375 +50449 0.2464599609375 +50450 -0.01470947265625 +50451 0.032470703125 +50452 -0.1883544921875 +50453 -0.18609619140625 +50454 -0.372711181640625 +50455 -0.40643310546875 +50456 -0.51397705078125 +50457 -0.586090087890625 +50458 -0.57177734375 +50459 -0.692657470703125 +50460 -0.53948974609375 +50461 -0.71832275390625 +50462 -0.43511962890625 +50463 -0.673614501953125 +50464 -0.2962646484375 +50465 -0.583831787109375 +50466 -0.161102294921875 +50467 -0.475921630859375 +50468 -0.0435791015625 +50469 -0.360931396484375 +50470 0.060394287109375 +50471 -0.238372802734375 +50472 0.13665771484375 +50473 -0.121307373046875 +50474 0.170135498046875 +50475 -0.024169921875 +50476 0.16552734375 +50477 0.052032470703125 +50478 0.15728759765625 +50479 0.12689208984375 +50480 0.150787353515625 +50481 0.19976806640625 +50482 0.12200927734375 +50483 0.24969482421875 +50484 0.080108642578125 +50485 0.27947998046875 +50486 0.05126953125 +50487 0.304534912109375 +50488 0.062896728515625 +50489 0.34197998046875 +50490 0.09271240234375 +50491 0.37506103515625 +50492 0.092987060546875 +50493 0.37017822265625 +50494 0.07855224609375 +50495 0.3385009765625 +50496 0.06427001953125 +50497 0.292083740234375 +50498 0.0347900390625 +50499 0.22259521484375 +50500 -0.01171875 +50501 0.131744384765625 +50502 -0.056060791015625 +50503 0.03643798828125 +50504 -0.055511474609375 +50505 -0.029693603515625 +50506 -0.010467529296875 +50507 -0.063232421875 +50508 0.02508544921875 +50509 -0.09844970703125 +50510 0.025665283203125 +50511 -0.150054931640625 +50512 0.017333984375 +50513 -0.197235107421875 +50514 0.00189208984375 +50515 -0.23675537109375 +50516 -0.03173828125 +50517 -0.27520751953125 +50518 -0.071502685546875 +50519 -0.30377197265625 +50520 -0.13543701171875 +50521 -0.33538818359375 +50522 -0.219970703125 +50523 -0.368682861328125 +50524 -0.300506591796875 +50525 -0.38818359375 +50526 -0.376312255859375 +50527 -0.395721435546875 +50528 -0.416107177734375 +50529 -0.37213134765625 +50530 -0.371124267578125 +50531 -0.2862548828125 +50532 -0.242279052734375 +50533 -0.14178466796875 +50534 -0.069732666015625 +50535 0.030181884765625 +50536 0.125640869140625 +50537 0.212310791015625 +50538 0.31268310546875 +50539 0.380523681640625 +50540 0.45501708984375 +50541 0.507568359375 +50542 0.554779052734375 +50543 0.593719482421875 +50544 0.61065673828125 +50545 0.63751220703125 +50546 0.610931396484375 +50547 0.630828857421875 +50548 0.531463623046875 +50549 0.557464599609375 +50550 0.3883056640625 +50551 0.429931640625 +50552 0.23468017578125 +50553 0.2872314453125 +50554 0.095245361328125 +50555 0.148773193359375 +50556 -0.00396728515625 +50557 0.03515625 +50558 -0.04852294921875 +50559 -0.041015625 +50560 -0.055145263671875 +50561 -0.08892822265625 +50562 -0.0758056640625 +50563 -0.1427001953125 +50564 -0.138702392578125 +50565 -0.22003173828125 +50566 -0.209197998046875 +50567 -0.295013427734375 +50568 -0.289031982421875 +50569 -0.367706298828125 +50570 -0.37884521484375 +50571 -0.4378662109375 +50572 -0.456329345703125 +50573 -0.48974609375 +50574 -0.51641845703125 +50575 -0.520233154296875 +50576 -0.519287109375 +50577 -0.5023193359375 +50578 -0.458251953125 +50579 -0.432647705078125 +50580 -0.384796142578125 +50581 -0.348968505859375 +50582 -0.323699951171875 +50583 -0.2705078125 +50584 -0.269287109375 +50585 -0.195343017578125 +50586 -0.1951904296875 +50587 -0.107086181640625 +50588 -0.100006103515625 +50589 -0.0067138671875 +50590 -0.01055908203125 +50591 0.085205078125 +50592 0.1033935546875 +50593 0.188385009765625 +50594 0.24908447265625 +50595 0.306793212890625 +50596 0.373199462890625 +50597 0.40240478515625 +50598 0.45806884765625 +50599 0.46258544921875 +50600 0.511474609375 +50601 0.49298095703125 +50602 0.565399169921875 +50603 0.516571044921875 +50604 0.61138916015625 +50605 0.528411865234375 +50606 0.5897216796875 +50607 0.488006591796875 +50608 0.4906005859375 +50609 0.389984130859375 +50610 0.33148193359375 +50611 0.248291015625 +50612 0.147796630859375 +50613 0.08935546875 +50614 -0.01873779296875 +50615 -0.055938720703125 +50616 -0.140289306640625 +50617 -0.16656494140625 +50618 -0.191986083984375 +50619 -0.22381591796875 +50620 -0.184295654296875 +50621 -0.2340087890625 +50622 -0.161834716796875 +50623 -0.227691650390625 +50624 -0.166595458984375 +50625 -0.233917236328125 +50626 -0.19390869140625 +50627 -0.249420166015625 +50628 -0.22442626953125 +50629 -0.26104736328125 +50630 -0.279754638671875 +50631 -0.28466796875 +50632 -0.3389892578125 +50633 -0.306610107421875 +50634 -0.3543701171875 +50635 -0.294647216796875 +50636 -0.348175048828125 +50637 -0.26568603515625 +50638 -0.32598876953125 +50639 -0.22503662109375 +50640 -0.2581787109375 +50641 -0.153350830078125 +50642 -0.139801025390625 +50643 -0.048431396484375 +50644 0.014617919921875 +50645 0.07843017578125 +50646 0.144378662109375 +50647 0.183746337890625 +50648 0.221038818359375 +50649 0.246978759765625 +50650 0.27069091796875 +50651 0.2860107421875 +50652 0.294036865234375 +50653 0.301239013671875 +50654 0.311767578125 +50655 0.307373046875 +50656 0.339141845703125 +50657 0.3155517578125 +50658 0.360260009765625 +50659 0.315338134765625 +50660 0.360504150390625 +50661 0.297454833984375 +50662 0.308380126953125 +50663 0.241058349609375 +50664 0.18170166015625 +50665 0.131866455078125 +50666 0.0047607421875 +50667 -0.011962890625 +50668 -0.17559814453125 +50669 -0.15673828125 +50670 -0.3143310546875 +50671 -0.270111083984375 +50672 -0.36785888671875 +50673 -0.320892333984375 +50674 -0.36248779296875 +50675 -0.32672119140625 +50676 -0.343536376953125 +50677 -0.318756103515625 +50678 -0.3018798828125 +50679 -0.290496826171875 +50680 -0.231414794921875 +50681 -0.237762451171875 +50682 -0.117645263671875 +50683 -0.150787353515625 +50684 0.007049560546875 +50685 -0.05267333984375 +50686 0.087982177734375 +50687 0.017822265625 +50688 0.13946533203125 +50689 0.069793701171875 +50690 0.17425537109375 +50691 0.1112060546875 +50692 0.188201904296875 +50693 0.13812255859375 +50694 0.171234130859375 +50695 0.143035888671875 +50696 0.118438720703125 +50697 0.121978759765625 +50698 0.05706787109375 +50699 0.092437744140625 +50700 -0.010711669921875 +50701 0.055328369140625 +50702 -0.0914306640625 +50703 0.006011962890625 +50704 -0.162322998046875 +50705 -0.04046630859375 +50706 -0.194549560546875 +50707 -0.06488037109375 +50708 -0.1492919921875 +50709 -0.04119873046875 +50710 -0.02166748046875 +50711 0.03424072265625 +50712 0.124053955078125 +50713 0.119384765625 +50714 0.211151123046875 +50715 0.1639404296875 +50716 0.240447998046875 +50717 0.16925048828125 +50718 0.242218017578125 +50719 0.15618896484375 +50720 0.2257080078125 +50721 0.131683349609375 +50722 0.194366455078125 +50723 0.098724365234375 +50724 0.115509033203125 +50725 0.03619384765625 +50726 0.0128173828125 +50727 -0.03961181640625 +50728 -0.053802490234375 +50729 -0.088623046875 +50730 -0.110626220703125 +50731 -0.128082275390625 +50732 -0.199493408203125 +50733 -0.185791015625 +50734 -0.29437255859375 +50735 -0.24462890625 +50736 -0.33221435546875 +50737 -0.263031005859375 +50738 -0.27972412109375 +50739 -0.219329833984375 +50740 -0.185333251953125 +50741 -0.146240234375 +50742 -0.128204345703125 +50743 -0.096923828125 +50744 -0.115692138671875 +50745 -0.076904296875 +50746 -0.116455078125 +50747 -0.066009521484375 +50748 -0.105926513671875 +50749 -0.04852294921875 +50750 -0.053955078125 +50751 -0.0050048828125 +50752 0.048797607421875 +50753 0.070281982421875 +50754 0.157318115234375 +50755 0.14715576171875 +50756 0.212005615234375 +50757 0.185791015625 +50758 0.218475341796875 +50759 0.18988037109375 +50760 0.23724365234375 +50761 0.19970703125 +50762 0.30535888671875 +50763 0.2401123046875 +50764 0.38128662109375 +50765 0.2838134765625 +50766 0.404449462890625 +50767 0.290985107421875 +50768 0.3944091796875 +50769 0.275115966796875 +50770 0.3885498046875 +50771 0.261566162109375 +50772 0.362640380859375 +50773 0.23480224609375 +50774 0.27362060546875 +50775 0.166717529296875 +50776 0.11712646484375 +50777 0.054901123046875 +50778 -0.054901123046875 +50779 -0.06573486328125 +50780 -0.19085693359375 +50781 -0.160614013671875 +50782 -0.28570556640625 +50783 -0.2261962890625 +50784 -0.339263916015625 +50785 -0.262298583984375 +50786 -0.3775634765625 +50787 -0.286224365234375 +50788 -0.445709228515625 +50789 -0.32806396484375 +50790 -0.535064697265625 +50791 -0.38232421875 +50792 -0.629058837890625 +50793 -0.438323974609375 +50794 -0.697601318359375 +50795 -0.476470947265625 +50796 -0.70391845703125 +50797 -0.4727783203125 +50798 -0.6424560546875 +50799 -0.423980712890625 +50800 -0.491241455078125 +50801 -0.315948486328125 +50802 -0.265716552734375 +50803 -0.159332275390625 +50804 -0.023712158203125 +50805 0.007080078125 +50806 0.201751708984375 +50807 0.16107177734375 +50808 0.375823974609375 +50809 0.27935791015625 +50810 0.485076904296875 +50811 0.352874755859375 +50812 0.56884765625 +50813 0.40777587890625 +50814 0.634765625 +50815 0.449188232421875 +50816 0.63763427734375 +50817 0.447296142578125 +50818 0.5660400390625 +50819 0.394775390625 +50820 0.4720458984375 +50821 0.326507568359375 +50822 0.40692138671875 +50823 0.27685546875 +50824 0.3778076171875 +50825 0.25091552734375 +50826 0.376953125 +50827 0.243896484375 +50828 0.371978759765625 +50829 0.23468017578125 +50830 0.313140869140625 +50831 0.1905517578125 +50832 0.184417724609375 +50833 0.101104736328125 +50834 0.011199951171875 +50835 -0.016571044921875 +50836 -0.171051025390625 +50837 -0.138824462890625 +50838 -0.33740234375 +50839 -0.249114990234375 +50840 -0.47198486328125 +50841 -0.336944580078125 +50842 -0.560394287109375 +50843 -0.39288330078125 +50844 -0.58056640625 +50845 -0.4024658203125 +50846 -0.54754638671875 +50847 -0.375885009765625 +50848 -0.508575439453125 +50849 -0.344818115234375 +50850 -0.459503173828125 +50851 -0.306793212890625 +50852 -0.394378662109375 +50853 -0.2581787109375 +50854 -0.35260009765625 +50855 -0.22540283203125 +50856 -0.31170654296875 +50857 -0.19378662109375 +50858 -0.197418212890625 +50859 -0.114288330078125 +50860 -0.007965087890625 +50861 0.01409912109375 +50862 0.207489013671875 +50863 0.158599853515625 +50864 0.409210205078125 +50865 0.292755126953125 +50866 0.57208251953125 +50867 0.399932861328125 +50868 0.66595458984375 +50869 0.460205078125 +50870 0.65875244140625 +50871 0.45245361328125 +50872 0.56744384765625 +50873 0.388092041015625 +50874 0.431396484375 +50875 0.29351806640625 +50876 0.29443359375 +50877 0.198089599609375 +50878 0.182464599609375 +50879 0.1192626953125 +50880 0.06365966796875 +50881 0.0361328125 +50882 -0.075958251953125 +50883 -0.060333251953125 +50884 -0.189422607421875 +50885 -0.1387939453125 +50886 -0.271942138671875 +50887 -0.195892333984375 +50888 -0.342529296875 +50889 -0.244140625 +50890 -0.364166259765625 +50891 -0.258941650390625 +50892 -0.327239990234375 +50893 -0.233917236328125 +50894 -0.2769775390625 +50895 -0.19915771484375 +50896 -0.253692626953125 +50897 -0.1815185546875 +50898 -0.24365234375 +50899 -0.1719970703125 +50900 -0.1983642578125 +50901 -0.13861083984375 +50902 -0.116241455078125 +50903 -0.080474853515625 +50904 -0.036834716796875 +50905 -0.0240478515625 +50906 0.034881591796875 +50907 0.027130126953125 +50908 0.09124755859375 +50909 0.067779541015625 +50910 0.10888671875 +50911 0.082244873046875 +50912 0.125518798828125 +50913 0.095428466796875 +50914 0.15771484375 +50915 0.118255615234375 +50916 0.17828369140625 +50917 0.132568359375 +50918 0.17108154296875 +50919 0.127655029296875 +50920 0.129974365234375 +50921 0.099456787109375 +50922 0.082427978515625 +50923 0.0662841796875 +50924 0.027679443359375 +50925 0.027740478515625 +50926 -0.065643310546875 +50927 -0.036834716796875 +50928 -0.15936279296875 +50929 -0.1019287109375 +50930 -0.21307373046875 +50931 -0.140594482421875 +50932 -0.234649658203125 +50933 -0.157867431640625 +50934 -0.2001953125 +50935 -0.1376953125 +50936 -0.119171142578125 +50937 -0.086273193359375 +50938 -0.024749755859375 +50939 -0.025482177734375 +50940 0.085784912109375 +50941 0.046539306640625 +50942 0.178131103515625 +50943 0.107086181640625 +50944 0.215576171875 +50945 0.13201904296875 +50946 0.211456298828125 +50947 0.13031005859375 +50948 0.17523193359375 +50949 0.108306884765625 +50950 0.128753662109375 +50951 0.079833984375 +50952 0.1019287109375 +50953 0.063812255859375 +50954 0.0743408203125 +50955 0.047332763671875 +50956 0.04327392578125 +50957 0.02862548828125 +50958 0.038177490234375 +50959 0.0262451171875 +50960 0.076263427734375 +50961 0.051025390625 +50962 0.14105224609375 +50963 0.092498779296875 +50964 0.186431884765625 +50965 0.121551513671875 +50966 0.188812255859375 +50967 0.12322998046875 +50968 0.1390380859375 +50969 0.09173583984375 +50970 0.041778564453125 +50971 0.030029296875 +50972 -0.079437255859375 +50973 -0.046966552734375 +50974 -0.219390869140625 +50975 -0.135986328125 +50976 -0.367828369140625 +50977 -0.23046875 +50978 -0.494873046875 +50979 -0.3115234375 +50980 -0.556243896484375 +50981 -0.351104736328125 +50982 -0.508697509765625 +50983 -0.32183837890625 +50984 -0.3756103515625 +50985 -0.238433837890625 +50986 -0.218902587890625 +50987 -0.1400146484375 +50988 -0.063751220703125 +50989 -0.042449951171875 +50990 0.091552734375 +50991 0.0552978515625 +50992 0.23602294921875 +50993 0.146331787109375 +50994 0.342987060546875 +50995 0.21380615234375 +50996 0.39520263671875 +50997 0.246856689453125 +50998 0.389373779296875 +50999 0.243377685546875 +51000 0.324249267578125 +51001 0.20257568359375 +51002 0.224090576171875 +51003 0.139739990234375 +51004 0.124267578125 +51005 0.07720947265625 +51006 0.037078857421875 +51007 0.022705078125 +51008 -0.010101318359375 +51009 -0.0064697265625 +51010 -0.019439697265625 +51011 -0.01171875 +51012 -0.022796630859375 +51013 -0.01324462890625 +51014 -0.001556396484375 +51015 0.00067138671875 +51016 0.056304931640625 +51017 0.037628173828125 +51018 0.106719970703125 +51019 0.06976318359375 +51020 0.096893310546875 +51021 0.063690185546875 +51022 0.042694091796875 +51023 0.0294189453125 +51024 -0.018035888671875 +51025 -0.009124755859375 +51026 -0.07586669921875 +51027 -0.04595947265625 +51028 -0.11944580078125 +51029 -0.0738525390625 +51030 -0.15972900390625 +51031 -0.0997314453125 +51032 -0.202606201171875 +51033 -0.127288818359375 +51034 -0.24859619140625 +51035 -0.156829833984375 +51036 -0.30517578125 +51037 -0.193023681640625 +51038 -0.36212158203125 +51039 -0.229400634765625 +51040 -0.39141845703125 +51041 -0.248291015625 +51042 -0.35528564453125 +51043 -0.225738525390625 +51044 -0.249969482421875 +51045 -0.15936279296875 +51046 -0.092864990234375 +51047 -0.0601806640625 +51048 0.08905029296875 +51049 0.054779052734375 +51050 0.2352294921875 +51051 0.147216796875 +51052 0.318817138671875 +51053 0.200164794921875 +51054 0.358642578125 +51055 0.22552490234375 +51056 0.347747802734375 +51057 0.2188720703125 +51058 0.28564453125 +51059 0.179901123046875 +51060 0.223175048828125 +51061 0.1407470703125 +51062 0.196746826171875 +51063 0.124359130859375 +51064 0.179840087890625 +51065 0.113983154296875 +51066 0.155548095703125 +51067 0.098907470703125 +51068 0.151214599609375 +51069 0.096405029296875 +51070 0.156951904296875 +51071 0.100250244140625 +51072 0.13177490234375 +51073 0.084503173828125 +51074 0.100799560546875 +51075 0.065032958984375 +51076 0.087127685546875 +51077 0.056396484375 +51078 0.05487060546875 +51079 0.03594970703125 +51080 -0.009002685546875 +51081 -0.004547119140625 +51082 -0.10400390625 +51083 -0.06475830078125 +51084 -0.229400634765625 +51085 -0.14422607421875 +51086 -0.35552978515625 +51087 -0.22418212890625 +51088 -0.441925048828125 +51089 -0.279022216796875 +51090 -0.473846435546875 +51091 -0.299407958984375 +51092 -0.464813232421875 +51093 -0.29388427734375 +51094 -0.419097900390625 +51095 -0.26513671875 +51096 -0.334320068359375 +51097 -0.211669921875 +51098 -0.227935791015625 +51099 -0.144500732421875 +51100 -0.12347412109375 +51101 -0.0784912109375 +51102 -0.02764892578125 +51103 -0.01788330078125 +51104 0.077667236328125 +51105 0.04876708984375 +51106 0.2132568359375 +51107 0.134552001953125 +51108 0.38885498046875 +51109 0.245635986328125 +51110 0.582794189453125 +51111 0.3682861328125 +51112 0.734039306640625 +51113 0.463958740234375 +51114 0.800140380859375 +51115 0.505828857421875 +51116 0.7783203125 +51117 0.492095947265625 +51118 0.6651611328125 +51119 0.420623779296875 +51120 0.45965576171875 +51121 0.290771484375 +51122 0.199188232421875 +51123 0.12615966796875 +51124 -0.050689697265625 +51125 -0.031768798828125 +51126 -0.23297119140625 +51127 -0.147003173828125 +51128 -0.33013916015625 +51129 -0.208465576171875 +51130 -0.368408203125 +51131 -0.232666015625 +51132 -0.378936767578125 +51133 -0.23931884765625 +51134 -0.376983642578125 +51135 -0.23809814453125 +51136 -0.37969970703125 +51137 -0.239837646484375 +51138 -0.391510009765625 +51139 -0.247314453125 +51140 -0.385345458984375 +51141 -0.243408203125 +51142 -0.3419189453125 +51143 -0.2159423828125 +51144 -0.28289794921875 +51145 -0.178619384765625 +51146 -0.251617431640625 +51147 -0.158843994140625 +51148 -0.266143798828125 +51149 -0.167999267578125 +51150 -0.273345947265625 +51151 -0.17254638671875 +51152 -0.216796875 +51153 -0.136810302734375 +51154 -0.128265380859375 +51155 -0.080841064453125 +51156 -0.068145751953125 +51157 -0.0428466796875 +51158 -0.0430908203125 +51159 -0.027008056640625 +51160 -0.024444580078125 +51161 -0.015228271484375 +51162 0.020721435546875 +51163 0.013336181640625 +51164 0.124481201171875 +51165 0.07891845703125 +51166 0.25787353515625 +51167 0.1632080078125 +51168 0.379119873046875 +51169 0.23980712890625 +51170 0.47991943359375 +51171 0.303466796875 +51172 0.5281982421875 +51173 0.33392333984375 +51174 0.511138916015625 +51175 0.323089599609375 +51176 0.456207275390625 +51177 0.288299560546875 +51178 0.407470703125 +51179 0.257415771484375 +51180 0.383758544921875 +51181 0.242340087890625 +51182 0.35687255859375 +51183 0.225250244140625 +51184 0.31182861328125 +51185 0.196685791015625 +51186 0.250885009765625 +51187 0.158111572265625 +51188 0.1654052734375 +51189 0.104034423828125 +51190 0.035247802734375 +51191 0.021759033203125 +51192 -0.142059326171875 +51193 -0.09027099609375 +51194 -0.33563232421875 +51195 -0.2125244140625 +51196 -0.5345458984375 +51197 -0.338104248046875 +51198 -0.72186279296875 +51199 -0.456329345703125 +51200 -0.836669921875 +51201 -0.5291748046875 +51202 -0.8326416015625 +51203 -0.528045654296875 +51204 -0.7296142578125 +51205 -0.46484375 +51206 -0.582550048828125 +51207 -0.373016357421875 +51208 -0.440093994140625 +51209 -0.28228759765625 +51210 -0.324310302734375 +51211 -0.206451416015625 +51212 -0.20147705078125 +51213 -0.12579345703125 +51214 -0.044647216796875 +51215 -0.02459716796875 +51216 0.103973388671875 +51217 0.0712890625 +51218 0.202392578125 +51219 0.136260986328125 +51220 0.264495849609375 +51221 0.1783447265625 +51222 0.338897705078125 +51223 0.22650146484375 +51224 0.443817138671875 +51225 0.291473388671875 +51226 0.545074462890625 +51227 0.35272216796875 +51228 0.6173095703125 +51229 0.39508056640625 +51230 0.6524658203125 +51231 0.413787841796875 +51232 0.66339111328125 +51233 0.416748046875 +51234 0.6561279296875 +51235 0.4078369140625 +51236 0.606781005859375 +51237 0.373016357421875 +51238 0.501190185546875 +51239 0.304107666015625 +51240 0.352783203125 +51241 0.209442138671875 +51242 0.176544189453125 +51243 0.098358154296875 +51244 -0.034820556640625 +51245 -0.033233642578125 +51246 -0.258209228515625 +51247 -0.171173095703125 +51248 -0.44244384765625 +51249 -0.28460693359375 +51250 -0.5753173828125 +51251 -0.366058349609375 +51252 -0.65203857421875 +51253 -0.41259765625 +51254 -0.641632080078125 +51255 -0.405670166015625 +51256 -0.562164306640625 +51257 -0.356170654296875 +51258 -0.458038330078125 +51259 -0.2908935546875 +51260 -0.350555419921875 +51261 -0.2227783203125 +51262 -0.260528564453125 +51263 -0.164520263671875 +51264 -0.192108154296875 +51265 -0.118865966796875 +51266 -0.141937255859375 +51267 -0.0841064453125 +51268 -0.1021728515625 +51269 -0.055755615234375 +51270 -0.062896728515625 +51271 -0.028106689453125 +51272 -0.011932373046875 +51273 0.005889892578125 +51274 0.062835693359375 +51275 0.0533447265625 +51276 0.148712158203125 +51277 0.106536865234375 +51278 0.241729736328125 +51279 0.16302490234375 +51280 0.34912109375 +51281 0.22711181640625 +51282 0.457305908203125 +51283 0.290740966796875 +51284 0.54388427734375 +51285 0.340545654296875 +51286 0.5728759765625 +51287 0.3551025390625 +51288 0.506591796875 +51289 0.311981201171875 +51290 0.351226806640625 +51291 0.215057373046875 +51292 0.146514892578125 +51293 0.088409423828125 +51294 -0.05523681640625 +51295 -0.036376953125 +51296 -0.21624755859375 +51297 -0.136444091796875 +51298 -0.334930419921875 +51299 -0.21063232421875 +51300 -0.402984619140625 +51301 -0.2537841796875 +51302 -0.4412841796875 +51303 -0.2783203125 +51304 -0.49578857421875 +51305 -0.311767578125 +51306 -0.5601806640625 +51307 -0.350341796875 +51308 -0.600738525390625 +51309 -0.37384033203125 +51310 -0.584228515625 +51311 -0.36236572265625 +51312 -0.47930908203125 +51313 -0.2972412109375 +51314 -0.27935791015625 +51315 -0.17462158203125 +51316 -0.0089111328125 +51317 -0.0093994140625 +51318 0.268798828125 +51319 0.160308837890625 +51320 0.482818603515625 +51321 0.291748046875 +51322 0.60369873046875 +51323 0.367095947265625 +51324 0.650421142578125 +51325 0.3975830078125 +51326 0.66400146484375 +51327 0.40771484375 +51328 0.6414794921875 +51329 0.3956298828125 +51330 0.572540283203125 +51331 0.355072021484375 +51332 0.498138427734375 +51333 0.31060791015625 +51334 0.439453125 +51335 0.274932861328125 +51336 0.375518798828125 +51337 0.235504150390625 +51338 0.274505615234375 +51339 0.173309326171875 +51340 0.1087646484375 +51341 0.071868896484375 +51342 -0.099395751953125 +51343 -0.055328369140625 +51344 -0.3182373046875 +51345 -0.1890869140625 +51346 -0.5489501953125 +51347 -0.329986572265625 +51348 -0.7738037109375 +51349 -0.467254638671875 +51350 -0.86383056640625 +51351 -0.569000244140625 +51352 -0.870391845703125 +51353 -0.615142822265625 +51354 -0.86895751953125 +51355 -0.616241455078125 +51356 -0.861053466796875 +51357 -0.580078125 +51358 -0.765869140625 +51359 -0.49627685546875 +51360 -0.5301513671875 +51361 -0.358062744140625 +51362 -0.214691162109375 +51363 -0.16973876953125 +51364 0.137359619140625 +51365 0.042816162109375 +51366 0.474822998046875 +51367 0.24871826171875 +51368 0.76239013671875 +51369 0.426544189453125 +51370 0.867462158203125 +51371 0.55999755859375 +51372 0.870361328125 +51373 0.64923095703125 +51374 0.86480712890625 +51375 0.68719482421875 +51376 0.831817626953125 +51377 0.677001953125 +51378 0.677581787109375 +51379 0.6331787109375 +51380 0.495880126953125 +51381 0.559112548828125 +51382 0.30767822265625 +51383 0.46588134765625 +51384 0.116180419921875 +51385 0.354766845703125 +51386 -0.110748291015625 +51387 0.206756591796875 +51388 -0.381805419921875 +51389 0.0177001953125 +51390 -0.6572265625 +51391 -0.1866455078125 +51392 -0.857421875 +51393 -0.37030029296875 +51394 -0.870391845703125 +51395 -0.507415771484375 +51396 -0.870391845703125 +51397 -0.5936279296875 +51398 -0.86444091796875 +51399 -0.644989013671875 +51400 -0.85723876953125 +51401 -0.682769775390625 +51402 -0.790008544921875 +51403 -0.69586181640625 +51404 -0.62847900390625 +51405 -0.651641845703125 +51406 -0.3956298828125 +51407 -0.548126220703125 +51408 -0.126708984375 +51409 -0.40496826171875 +51410 0.150115966796875 +51411 -0.23858642578125 +51412 0.424041748046875 +51413 -0.055999755859375 +51414 0.670623779296875 +51415 0.126556396484375 +51416 0.854522705078125 +51417 0.28582763671875 +51418 0.866485595703125 +51419 0.411163330078125 +51420 0.86920166015625 +51421 0.49322509765625 +51422 0.8653564453125 +51423 0.542816162109375 +51424 0.857147216796875 +51425 0.56787109375 +51426 0.766845703125 +51427 0.566558837890625 +51428 0.628509521484375 +51429 0.541839599609375 +51430 0.462127685546875 +51431 0.4896240234375 +51432 0.297210693359375 +51433 0.425323486328125 +51434 0.14862060546875 +51435 0.3563232421875 +51436 -0.00537109375 +51437 0.2689208984375 +51438 -0.15753173828125 +51439 0.167633056640625 +51440 -0.31304931640625 +51441 0.05029296875 +51442 -0.48876953125 +51443 -0.0914306640625 +51444 -0.6416015625 +51445 -0.229339599609375 +51446 -0.751373291015625 +51447 -0.34857177734375 +51448 -0.84619140625 +51449 -0.462860107421875 +51450 -0.861297607421875 +51451 -0.56329345703125 +51452 -0.863250732421875 +51453 -0.629913330078125 +51454 -0.856597900390625 +51455 -0.6436767578125 +51456 -0.7498779296875 +51457 -0.611236572265625 +51458 -0.624542236328125 +51459 -0.566436767578125 +51460 -0.47808837890625 +51461 -0.497528076171875 +51462 -0.253387451171875 +51463 -0.371551513671875 +51464 0.003692626953125 +51465 -0.21478271484375 +51466 0.2257080078125 +51467 -0.066436767578125 +51468 0.427154541015625 +51469 0.080169677734375 +51470 0.643218994140625 +51471 0.24298095703125 +51472 0.855926513671875 +51473 0.416107177734375 +51474 0.870361328125 +51475 0.5662841796875 +51476 0.870361328125 +51477 0.665008544921875 +51478 0.862762451171875 +51479 0.716156005859375 +51480 0.79669189453125 +51481 0.717926025390625 +51482 0.595794677734375 +51483 0.6649169921875 +51484 0.362152099609375 +51485 0.573760986328125 +51486 0.1270751953125 +51487 0.4605712890625 +51488 -0.086944580078125 +51489 0.33758544921875 +51490 -0.2784423828125 +51491 0.206329345703125 +51492 -0.484832763671875 +51493 0.047393798828125 +51494 -0.729583740234375 +51495 -0.14971923828125 +51496 -0.86688232421875 +51497 -0.3558349609375 +51498 -0.870391845703125 +51499 -0.53460693359375 +51500 -0.86859130859375 +51501 -0.682861328125 +51502 -0.86279296875 +51503 -0.799102783203125 +51504 -0.817962646484375 +51505 -0.85540771484375 +51506 -0.6116943359375 +51507 -0.847564697265625 +51508 -0.3128662109375 +51509 -0.749664306640625 +51510 0.039398193359375 +51511 -0.588134765625 +51512 0.422821044921875 +51513 -0.374481201171875 +51514 0.805145263671875 +51515 -0.1278076171875 +51516 0.870361328125 +51517 0.11285400390625 +51518 0.870361328125 +51519 0.314788818359375 +51520 0.860015869140625 +51521 0.470916748046875 +51522 0.727935791015625 +51523 0.576446533203125 +51524 0.48114013671875 +51525 0.627716064453125 +51526 0.2059326171875 +51527 0.63800048828125 +51528 -0.06103515625 +51529 0.619781494140625 +51530 -0.29913330078125 +51531 0.57843017578125 +51532 -0.516204833984375 +51533 0.505523681640625 +51534 -0.7252197265625 +51535 0.3922119140625 +51536 -0.85980224609375 +51537 0.252685546875 +51538 -0.870391845703125 +51539 0.106597900390625 +51540 -0.870391845703125 +51541 -0.028900146484375 +51542 -0.858062744140625 +51543 -0.125762939453125 +51544 -0.673004150390625 +51545 -0.18109130859375 +51546 -0.42694091796875 +51547 -0.22412109375 +51548 -0.2100830078125 +51549 -0.279510498046875 +51550 -0.0362548828125 +51551 -0.345458984375 +51552 0.10943603515625 +51553 -0.4049072265625 +51554 0.23516845703125 +51555 -0.446136474609375 +51556 0.373687744140625 +51557 -0.44525146484375 +51558 0.517791748046875 +51559 -0.403106689453125 +51560 0.602783203125 +51561 -0.3553466796875 +51562 0.635711669921875 +51563 -0.299072265625 +51564 0.655181884765625 +51565 -0.21551513671875 +51566 0.65948486328125 +51567 -0.110595703125 +51568 0.651275634765625 +51569 0.010711669921875 +51570 0.61846923828125 +51571 0.134002685546875 +51572 0.53753662109375 +51573 0.237701416015625 +51574 0.404144287109375 +51575 0.31097412109375 +51576 0.22186279296875 +51577 0.347747802734375 +51578 0.003997802734375 +51579 0.34820556640625 +51580 -0.22100830078125 +51581 0.322174072265625 +51582 -0.42449951171875 +51583 0.281036376953125 +51584 -0.579833984375 +51585 0.23663330078125 +51586 -0.641876220703125 +51587 0.213104248046875 +51588 -0.6177978515625 +51589 0.206634521484375 +51590 -0.575531005859375 +51591 0.1806640625 +51592 -0.526336669921875 +51593 0.13238525390625 +51594 -0.42645263671875 +51595 0.091552734375 +51596 -0.2581787109375 +51597 0.07415771484375 +51598 -0.068695068359375 +51599 0.05999755859375 +51600 0.09222412109375 +51601 0.0277099609375 +51602 0.232147216796875 +51603 -0.011566162109375 +51604 0.3509521484375 +51605 -0.05157470703125 +51606 0.410064697265625 +51607 -0.108673095703125 +51608 0.372955322265625 +51609 -0.19915771484375 +51610 0.2554931640625 +51611 -0.31085205078125 +51612 0.10711669921875 +51613 -0.4139404296875 +51614 -0.052886962890625 +51615 -0.4971923828125 +51616 -0.186279296875 +51617 -0.540069580078125 +51618 -0.23291015625 +51619 -0.51092529296875 +51620 -0.209442138671875 +51621 -0.42291259765625 +51622 -0.174163818359375 +51623 -0.313751220703125 +51624 -0.126739501953125 +51625 -0.18853759765625 +51626 -0.048126220703125 +51627 -0.042083740234375 +51628 0.0426025390625 +51629 0.109130859375 +51630 0.10748291015625 +51631 0.2381591796875 +51632 0.1409912109375 +51633 0.337066650390625 +51634 0.19708251953125 +51635 0.4324951171875 +51636 0.273651123046875 +51637 0.520263671875 +51638 0.31768798828125 +51639 0.568389892578125 +51640 0.341094970703125 +51641 0.5830078125 +51642 0.368011474609375 +51643 0.578369140625 +51644 0.37249755859375 +51645 0.541412353515625 +51646 0.30072021484375 +51647 0.444305419921875 +51648 0.1517333984375 +51649 0.2900390625 +51650 -0.01470947265625 +51651 0.11669921875 +51652 -0.1883544921875 +51653 -0.06524658203125 +51654 -0.372711181640625 +51655 -0.253143310546875 +51656 -0.51397705078125 +51657 -0.411895751953125 +51658 -0.57177734375 +51659 -0.514404296875 +51660 -0.53948974609375 +51661 -0.553375244140625 +51662 -0.43511962890625 +51663 -0.536285400390625 +51664 -0.2962646484375 +51665 -0.482635498046875 +51666 -0.161102294921875 +51667 -0.4132080078125 +51668 -0.0435791015625 +51669 -0.336029052734375 +51670 0.060394287109375 +51671 -0.249847412109375 +51672 0.13665771484375 +51673 -0.1646728515625 +51674 0.170135498046875 +51675 -0.091766357421875 +51676 0.16552734375 +51677 -0.03173828125 +51678 0.15728759765625 +51679 0.03125 +51680 0.150787353515625 +51681 0.096435546875 +51682 0.12200927734375 +51683 0.146392822265625 +51684 0.080108642578125 +51685 0.18280029296875 +51686 0.05126953125 +51687 0.2174072265625 +51688 0.062896728515625 +51689 0.263275146484375 +51690 0.09271240234375 +51691 0.305938720703125 +51692 0.092987060546875 +51693 0.317291259765625 +51694 0.07855224609375 +51695 0.3055419921875 +51696 0.06427001953125 +51697 0.279754638671875 +51698 0.0347900390625 +51699 0.232574462890625 +51700 -0.01171875 +51701 0.16497802734375 +51702 -0.056060791015625 +51703 0.0904541015625 +51704 -0.055511474609375 +51705 0.036163330078125 +51706 -0.010467529296875 +51707 0.005035400390625 +51708 0.02508544921875 +51709 -0.0303955078125 +51710 0.025665283203125 +51711 -0.081634521484375 +51712 0.017333984375 +51713 -0.131378173828125 +51714 0.00189208984375 +51715 -0.176239013671875 +51716 -0.03173828125 +51717 -0.220550537109375 +51718 -0.071502685546875 +51719 -0.25653076171875 +51720 -0.13543701171875 +51721 -0.293548583984375 +51722 -0.219970703125 +51723 -0.329833984375 +51724 -0.300506591796875 +51725 -0.35272216796875 +51726 -0.376312255859375 +51727 -0.36328125 +51728 -0.416107177734375 +51729 -0.346282958984375 +51730 -0.371124267578125 +51731 -0.27728271484375 +51732 -0.242279052734375 +51733 -0.15936279296875 +51734 -0.069732666015625 +51735 -0.01727294921875 +51736 0.125640869140625 +51737 0.134918212890625 +51738 0.31268310546875 +51739 0.277679443359375 +51740 0.45501708984375 +51741 0.388946533203125 +51742 0.554779052734375 +51743 0.46832275390625 +51744 0.61065673828125 +51745 0.51397705078125 +51746 0.610931396484375 +51747 0.5189208984375 +51748 0.531463623046875 +51749 0.46990966796875 +51750 0.3883056640625 +51751 0.3763427734375 +51752 0.23468017578125 +51753 0.268585205078125 +51754 0.095245361328125 +51755 0.161712646484375 +51756 -0.00396728515625 +51757 0.07183837890625 +51758 -0.04852294921875 +51759 0.009002685546875 +51760 -0.055145263671875 +51761 -0.0338134765625 +51762 -0.0758056640625 +51763 -0.083038330078125 +51764 -0.138702392578125 +51765 -0.152130126953125 +51766 -0.209197998046875 +51767 -0.22027587890625 +51768 -0.289031982421875 +51769 -0.286956787109375 +51770 -0.37884521484375 +51771 -0.351470947265625 +51772 -0.456329345703125 +51773 -0.40093994140625 +51774 -0.51641845703125 +51775 -0.432464599609375 +51776 -0.519287109375 +51777 -0.424468994140625 +51778 -0.458251953125 +51779 -0.3740234375 +51780 -0.384796142578125 +51781 -0.310577392578125 +51782 -0.323699951171875 +51783 -0.249176025390625 +51784 -0.269287109375 +51785 -0.188323974609375 +51786 -0.1951904296875 +51787 -0.115325927734375 +51788 -0.100006103515625 +51789 -0.03118896484375 +51790 -0.01055908203125 +51791 0.047576904296875 +51792 0.1033935546875 +51793 0.136016845703125 +51794 0.24908447265625 +51795 0.236846923828125 +51796 0.373199462890625 +51797 0.31976318359375 +51798 0.45806884765625 +51799 0.37445068359375 +51800 0.511474609375 +51801 0.4049072265625 +51802 0.565399169921875 +51803 0.42889404296875 +51804 0.61138916015625 +51805 0.4422607421875 +51806 0.5897216796875 +51807 0.412994384765625 +51808 0.4906005859375 +51809 0.3367919921875 +51810 0.33148193359375 +51811 0.224578857421875 +51812 0.147796630859375 +51813 0.097259521484375 +51814 -0.01873779296875 +51815 -0.020751953125 +51816 -0.140289306640625 +51817 -0.1126708984375 +51818 -0.191986083984375 +51819 -0.163482666015625 +51820 -0.184295654296875 +51821 -0.177825927734375 +51822 -0.161834716796875 +51823 -0.1793212890625 +51824 -0.166595458984375 +51825 -0.190460205078125 +51826 -0.19390869140625 +51827 -0.2083740234375 +51828 -0.22442626953125 +51829 -0.222381591796875 +51830 -0.279754638671875 +51831 -0.244720458984375 +51832 -0.3389892578125 +51833 -0.26446533203125 +51834 -0.3543701171875 +51835 -0.256195068359375 +51836 -0.348175048828125 +51837 -0.233184814453125 +51838 -0.32598876953125 +51839 -0.19964599609375 +51840 -0.2581787109375 +51841 -0.140533447265625 +51842 -0.139801025390625 +51843 -0.0543212890625 +51844 0.014617919921875 +51845 0.04986572265625 +51846 0.144378662109375 +51847 0.13763427734375 +51848 0.221038818359375 +51849 0.19256591796875 +51850 0.27069091796875 +51851 0.2283935546875 +51852 0.294036865234375 +51853 0.245208740234375 +51854 0.311767578125 +51855 0.2542724609375 +51856 0.339141845703125 +51857 0.26409912109375 +51858 0.360260009765625 +51859 0.26617431640625 +51860 0.360504150390625 +51861 0.253173828125 +51862 0.308380126953125 +51863 0.209075927734375 +51864 0.18170166015625 +51865 0.123016357421875 +51866 0.0047607421875 +51867 0.009124755859375 +51868 -0.17559814453125 +51869 -0.106414794921875 +51870 -0.3143310546875 +51871 -0.19842529296875 +51872 -0.36785888671875 +51873 -0.242584228515625 +51874 -0.36248779296875 +51875 -0.252227783203125 +51876 -0.343536376953125 +51877 -0.25103759765625 +51878 -0.3018798828125 +51879 -0.233734130859375 +51880 -0.231414794921875 +51881 -0.1968994140625 +51882 -0.117645263671875 +51883 -0.132843017578125 +51884 0.007049560546875 +51885 -0.059173583984375 +51886 0.087982177734375 +51887 -0.005706787109375 +51888 0.13946533203125 +51889 0.034576416015625 +51890 0.17425537109375 +51891 0.0677490234375 +51892 0.188201904296875 +51893 0.090728759765625 +51894 0.171234130859375 +51895 0.097259521484375 +51896 0.118438720703125 +51897 0.083831787109375 +51898 0.05706787109375 +51899 0.064300537109375 +51900 -0.010711669921875 +51901 0.039093017578125 +51902 -0.0914306640625 +51903 0.004180908203125 +51904 -0.162322998046875 +51905 -0.028594970703125 +51906 -0.194549560546875 +51907 -0.043975830078125 +51908 -0.1492919921875 +51909 -0.02117919921875 +51910 -0.02166748046875 +51911 0.042572021484375 +51912 0.124053955078125 +51913 0.11322021484375 +51914 0.211151123046875 +51915 0.15008544921875 +51916 0.240447998046875 +51917 0.15423583984375 +51918 0.242218017578125 +51919 0.142547607421875 +51920 0.2257080078125 +51921 0.120758056640625 +51922 0.194366455078125 +51923 0.091400146484375 +51924 0.115509033203125 +51925 0.037628173828125 +51926 0.0128173828125 +51927 -0.027252197265625 +51928 -0.053802490234375 +51929 -0.07061767578125 +51930 -0.110626220703125 +51931 -0.106201171875 +51932 -0.199493408203125 +51933 -0.15625 +51934 -0.29437255859375 +51935 -0.206756591796875 +51936 -0.33221435546875 +51937 -0.2239990234375 +51938 -0.27972412109375 +51939 -0.1904296875 +51940 -0.185333251953125 +51941 -0.132354736328125 +51942 -0.128204345703125 +51943 -0.0926513671875 +51944 -0.115692138671875 +51945 -0.0758056640625 +51946 -0.116455078125 +51947 -0.06561279296875 +51948 -0.105926513671875 +51949 -0.04949951171875 +51950 -0.053955078125 +51951 -0.011871337890625 +51952 0.048797607421875 +51953 0.0517578125 +51954 0.157318115234375 +51955 0.116851806640625 +51956 0.212005615234375 +51957 0.151123046875 +51958 0.218475341796875 +51959 0.157379150390625 +51960 0.23724365234375 +51961 0.167938232421875 +51962 0.30535888671875 +51963 0.20269775390625 +51964 0.38128662109375 +51965 0.23956298828125 +51966 0.404449462890625 +51967 0.246337890625 +51968 0.3944091796875 +51969 0.2332763671875 +51970 0.3885498046875 +51971 0.220184326171875 +51972 0.362640380859375 +51973 0.195556640625 +51974 0.27362060546875 +51975 0.13848876953125 +51976 0.11712646484375 +51977 0.047607421875 +51978 -0.054901123046875 +51979 -0.0501708984375 +51980 -0.19085693359375 +51981 -0.128204345703125 +51982 -0.28570556640625 +51983 -0.183441162109375 +51984 -0.339263916015625 +51985 -0.215423583984375 +51986 -0.3775634765625 +51987 -0.237091064453125 +51988 -0.445709228515625 +51989 -0.2711181640625 +51990 -0.535064697265625 +51991 -0.313232421875 +51992 -0.629058837890625 +51993 -0.355316162109375 +51994 -0.697601318359375 +51995 -0.382537841796875 +51996 -0.70391845703125 +51997 -0.376861572265625 +51998 -0.6424560546875 +51999 -0.336029052734375 +52000 -0.491241455078125 +52001 -0.249542236328125 +52002 -0.265716552734375 +52003 -0.125762939453125 +52004 -0.023712158203125 +52005 0.005584716796875 +52006 0.201751708984375 +52007 0.12738037109375 +52008 0.375823974609375 +52009 0.22161865234375 +52010 0.485076904296875 +52011 0.281219482421875 +52012 0.56884765625 +52013 0.32586669921875 +52014 0.634765625 +52015 0.35931396484375 +52016 0.63763427734375 +52017 0.35882568359375 +52018 0.5660400390625 +52019 0.318817138671875 +52020 0.4720458984375 +52021 0.265777587890625 +52022 0.40692138671875 +52023 0.225921630859375 +52024 0.3778076171875 +52025 0.203277587890625 +52026 0.376953125 +52027 0.194427490234375 +52028 0.371978759765625 +52029 0.183502197265625 +52030 0.313140869140625 +52031 0.145904541015625 +52032 0.184417724609375 +52033 0.073944091796875 +52034 0.011199951171875 +52035 -0.0191650390625 +52036 -0.171051025390625 +52037 -0.11529541015625 +52038 -0.33740234375 +52039 -0.20166015625 +52040 -0.47198486328125 +52041 -0.27020263671875 +52042 -0.560394287109375 +52043 -0.313690185546875 +52044 -0.58056640625 +52045 -0.32110595703125 +52046 -0.54754638671875 +52047 -0.300201416015625 +52048 -0.508575439453125 +52049 -0.275115966796875 +52050 -0.459503173828125 +52051 -0.244049072265625 +52052 -0.394378662109375 +52053 -0.20440673828125 +52054 -0.35260009765625 +52055 -0.176422119140625 +52056 -0.31170654296875 +52057 -0.14910888671875 +52058 -0.197418212890625 +52059 -0.085418701171875 +52060 -0.007965087890625 +52061 0.01519775390625 +52062 0.207489013671875 +52063 0.127685546875 +52064 0.409210205078125 +52065 0.23187255859375 +52066 0.57208251953125 +52067 0.31500244140625 +52068 0.66595458984375 +52069 0.36187744140625 +52070 0.65875244140625 +52071 0.35638427734375 +52072 0.56744384765625 +52073 0.3072509765625 +52074 0.431396484375 +52075 0.2344970703125 +52076 0.29443359375 +52077 0.160491943359375 +52078 0.182464599609375 +52079 0.098541259765625 +52080 0.06365966796875 +52081 0.032928466796875 +52082 -0.075958251953125 +52083 -0.04302978515625 +52084 -0.189422607421875 +52085 -0.1053466796875 +52086 -0.271942138671875 +52087 -0.151336669921875 +52088 -0.342529296875 +52089 -0.19036865234375 +52090 -0.364166259765625 +52091 -0.20367431640625 +52092 -0.327239990234375 +52093 -0.186309814453125 +52094 -0.2769775390625 +52095 -0.161041259765625 +52096 -0.253692626953125 +52097 -0.148193359375 +52098 -0.24365234375 +52099 -0.14093017578125 +52100 -0.1983642578125 +52101 -0.114990234375 +52102 -0.116241455078125 +52103 -0.069732666015625 +52104 -0.036834716796875 +52105 -0.02532958984375 +52106 0.034881591796875 +52107 0.01544189453125 +52108 0.09124755859375 +52109 0.0484619140625 +52110 0.10888671875 +52111 0.06170654296875 +52112 0.125518798828125 +52113 0.073944091796875 +52114 0.15771484375 +52115 0.09332275390625 +52116 0.17828369140625 +52117 0.105987548828125 +52118 0.17108154296875 +52119 0.10369873046875 +52120 0.129974365234375 +52121 0.0833740234375 +52122 0.082427978515625 +52123 0.058807373046875 +52124 0.027679443359375 +52125 0.029693603515625 +52126 -0.065643310546875 +52127 -0.019622802734375 +52128 -0.15936279296875 +52129 -0.06976318359375 +52130 -0.21307373046875 +52131 -0.1002197265625 +52132 -0.234649658203125 +52133 -0.114776611328125 +52134 -0.2001953125 +52135 -0.10113525390625 +52136 -0.119171142578125 +52137 -0.06390380859375 +52138 -0.024749755859375 +52139 -0.01959228515625 +52140 0.085784912109375 +52141 0.0333251953125 +52142 0.178131103515625 +52143 0.077667236328125 +52144 0.215576171875 +52145 0.095062255859375 +52146 0.211456298828125 +52147 0.09228515625 +52148 0.17523193359375 +52149 0.07415771484375 +52150 0.128753662109375 +52151 0.0516357421875 +52152 0.1019287109375 +52153 0.03973388671875 +52154 0.0743408203125 +52155 0.028045654296875 +52156 0.04327392578125 +52157 0.015045166015625 +52158 0.038177490234375 +52159 0.015411376953125 +52160 0.076263427734375 +52161 0.03765869140625 +52162 0.14105224609375 +52163 0.07330322265625 +52164 0.186431884765625 +52165 0.09893798828125 +52166 0.188812255859375 +52167 0.1025390625 +52168 0.1390380859375 +52169 0.079376220703125 +52170 0.041778564453125 +52171 0.03173828125 +52172 -0.079437255859375 +52173 -0.028533935546875 +52174 -0.219390869140625 +52175 -0.098907470703125 +52176 -0.367828369140625 +52177 -0.17413330078125 +52178 -0.494873046875 +52179 -0.239166259765625 +52180 -0.556243896484375 +52181 -0.2716064453125 +52182 -0.508697509765625 +52183 -0.24957275390625 +52184 -0.3756103515625 +52185 -0.184722900390625 +52186 -0.218902587890625 +52187 -0.108154296875 +52188 -0.063751220703125 +52189 -0.03240966796875 +52190 0.091552734375 +52191 0.04345703125 +52192 0.23602294921875 +52193 0.11407470703125 +52194 0.342987060546875 +52195 0.166107177734375 +52196 0.39520263671875 +52197 0.19097900390625 +52198 0.389373779296875 +52199 0.187103271484375 +52200 0.324249267578125 +52201 0.15386962890625 +52202 0.224090576171875 +52203 0.103546142578125 +52204 0.124267578125 +52205 0.05389404296875 +52206 0.037078857421875 +52207 0.011077880859375 +52208 -0.010101318359375 +52209 -0.01116943359375 +52210 -0.019439697265625 +52211 -0.0140380859375 +52212 -0.022796630859375 +52213 -0.013702392578125 +52214 -0.001556396484375 +52215 -0.000885009765625 +52216 0.056304931640625 +52217 0.030303955078125 +52218 0.106719970703125 +52219 0.057586669921875 +52220 0.096893310546875 +52221 0.05426025390625 +52222 0.042694091796875 +52223 0.028228759765625 +52224 -0.018035888671875 +52225 -0.00115966796875 +52226 -0.07586669921875 +52227 -0.029388427734375 +52228 -0.11944580078125 +52229 -0.051361083984375 +52230 -0.15972900390625 +52231 -0.07208251953125 +52232 -0.202606201171875 +52233 -0.094146728515625 +52234 -0.24859619140625 +52235 -0.117645263671875 +52236 -0.30517578125 +52237 -0.145965576171875 +52238 -0.36212158203125 +52239 -0.174224853515625 +52240 -0.39141845703125 +52241 -0.18914794921875 +52242 -0.35528564453125 +52243 -0.172821044921875 +52244 -0.249969482421875 +52245 -0.12347412109375 +52246 -0.092864990234375 +52247 -0.049346923828125 +52248 0.08905029296875 +52249 0.036834716796875 +52250 0.2352294921875 +52251 0.106475830078125 +52252 0.318817138671875 +52253 0.1468505859375 +52254 0.358642578125 +52255 0.166717529296875 +52256 0.347747802734375 +52257 0.162750244140625 +52258 0.28564453125 +52259 0.134674072265625 +52260 0.223175048828125 +52261 0.10638427734375 +52262 0.196746826171875 +52263 0.095001220703125 +52264 0.179840087890625 +52265 0.087982177734375 +52266 0.155548095703125 +52267 0.077301025390625 +52268 0.151214599609375 +52269 0.075836181640625 +52270 0.156951904296875 +52271 0.078857421875 +52272 0.13177490234375 +52273 0.0670166015625 +52274 0.100799560546875 +52275 0.052154541015625 +52276 0.087127685546875 +52277 0.045196533203125 +52278 0.05487060546875 +52279 0.029266357421875 +52280 -0.009002685546875 +52281 -0.001739501953125 +52282 -0.10400390625 +52283 -0.04754638671875 +52284 -0.229400634765625 +52285 -0.107757568359375 +52286 -0.35552978515625 +52287 -0.168304443359375 +52288 -0.441925048828125 +52289 -0.21002197265625 +52290 -0.473846435546875 +52291 -0.225921630859375 +52292 -0.464813232421875 +52293 -0.222320556640625 +52294 -0.419097900390625 +52295 -0.201202392578125 +52296 -0.334320068359375 +52297 -0.16143798828125 +52298 -0.227935791015625 +52299 -0.111236572265625 +52300 -0.12347412109375 +52301 -0.06170654296875 +52302 -0.02764892578125 +52303 -0.016082763671875 +52304 0.077667236328125 +52305 0.0341796875 +52306 0.2132568359375 +52307 0.098846435546875 +52308 0.38885498046875 +52309 0.182464599609375 +52310 0.582794189453125 +52311 0.2747802734375 +52312 0.734039306640625 +52313 0.346954345703125 +52314 0.800140380859375 +52315 0.37890625 +52316 0.7783203125 +52317 0.3692626953125 +52318 0.6651611328125 +52319 0.316375732421875 +52320 0.45965576171875 +52321 0.219757080078125 +52322 0.199188232421875 +52323 0.0970458984375 +52324 -0.050689697265625 +52325 -0.02081298828125 +52326 -0.23297119140625 +52327 -0.106903076171875 +52328 -0.33013916015625 +52329 -0.152984619140625 +52330 -0.368408203125 +52331 -0.17138671875 +52332 -0.378936767578125 +52333 -0.176788330078125 +52334 -0.376983642578125 +52335 -0.1763916015625 +52336 -0.37969970703125 +52337 -0.17828369140625 +52338 -0.391510009765625 +52339 -0.18450927734375 +52340 -0.385345458984375 +52341 -0.182220458984375 +52342 -0.3419189453125 +52343 -0.16229248046875 +52344 -0.28289794921875 +52345 -0.134918212890625 +52346 -0.251617431640625 +52347 -0.120513916015625 +52348 -0.266143798828125 +52349 -0.127593994140625 +52350 -0.273345947265625 +52351 -0.131103515625 +52352 -0.216796875 +52353 -0.1043701171875 +52354 -0.128265380859375 +52355 -0.062408447265625 +52356 -0.068145751953125 +52357 -0.033721923828125 +52358 -0.0430908203125 +52359 -0.021484375 +52360 -0.024444580078125 +52361 -0.01220703125 +52362 0.020721435546875 +52363 0.0096435546875 +52364 0.124481201171875 +52365 0.05914306640625 +52366 0.25787353515625 +52367 0.12255859375 +52368 0.379119873046875 +52369 0.18017578125 +52370 0.47991943359375 +52371 0.228057861328125 +52372 0.5281982421875 +52373 0.25103759765625 +52374 0.511138916015625 +52375 0.24310302734375 +52376 0.456207275390625 +52377 0.217193603515625 +52378 0.407470703125 +52379 0.194091796875 +52380 0.383758544921875 +52381 0.182708740234375 +52382 0.35687255859375 +52383 0.16973876953125 +52384 0.31182861328125 +52385 0.14813232421875 +52386 0.250885009765625 +52387 0.11895751953125 +52388 0.1654052734375 +52389 0.07818603515625 +52390 0.035247802734375 +52391 0.016357421875 +52392 -0.142059326171875 +52393 -0.067657470703125 +52394 -0.33563232421875 +52395 -0.159271240234375 +52396 -0.5345458984375 +52397 -0.253326416015625 +52398 -0.72186279296875 +52399 -0.341827392578125 +52400 -0.836669921875 +52401 -0.396026611328125 +52402 -0.8326416015625 +52403 -0.394073486328125 +52404 -0.7296142578125 +52405 -0.345306396484375 +52406 -0.582550048828125 +52407 -0.27569580078125 +52408 -0.440093994140625 +52409 -0.208221435546875 +52410 -0.324310302734375 +52411 -0.1533203125 +52412 -0.20147705078125 +52413 -0.095062255859375 +52414 -0.044647216796875 +52415 -0.020721435546875 +52416 0.103973388671875 +52417 0.049713134765625 +52418 0.202392578125 +52419 0.096405029296875 +52420 0.264495849609375 +52421 0.12591552734375 +52422 0.338897705078125 +52423 0.161163330078125 +52424 0.443817138671875 +52425 0.210723876953125 +52426 0.545074462890625 +52427 0.258514404296875 +52428 0.6173095703125 +52429 0.29254150390625 +52430 0.6524658203125 +52431 0.308990478515625 +52432 0.66339111328125 +52433 0.313934326171875 +52434 0.6561279296875 +52435 0.310272216796875 +52436 0.606781005859375 +52437 0.286712646484375 +52438 0.501190185546875 +52439 0.236572265625 +52440 0.352783203125 +52441 0.166229248046875 +52442 0.176544189453125 +52443 0.082763671875 +52444 -0.034820556640625 +52445 -0.017242431640625 +52446 -0.258209228515625 +52447 -0.122833251953125 +52448 -0.44244384765625 +52449 -0.2098388671875 +52450 -0.5753173828125 +52451 -0.27252197265625 +52452 -0.65203857421875 +52453 -0.30865478515625 +52454 -0.641632080078125 +52455 -0.3035888671875 +52456 -0.562164306640625 +52457 -0.265899658203125 +52458 -0.458038330078125 +52459 -0.216552734375 +52460 -0.350555419921875 +52461 -0.16558837890625 +52462 -0.260528564453125 +52463 -0.122833251953125 +52464 -0.192108154296875 +52465 -0.09027099609375 +52466 -0.141937255859375 +52467 -0.06634521484375 +52468 -0.1021728515625 +52469 -0.04736328125 +52470 -0.062896728515625 +52471 -0.028656005859375 +52472 -0.011932373046875 +52473 -0.004486083984375 +52474 0.062835693359375 +52475 0.030853271484375 +52476 0.148712158203125 +52477 0.071380615234375 +52478 0.241729736328125 +52479 0.11517333984375 +52480 0.34912109375 +52481 0.165374755859375 +52482 0.457305908203125 +52483 0.21484375 +52484 0.54388427734375 +52485 0.25311279296875 +52486 0.5728759765625 +52487 0.264739990234375 +52488 0.506591796875 +52489 0.23345947265625 +52490 0.351226806640625 +52491 0.162322998046875 +52492 0.146514892578125 +52493 0.069091796875 +52494 -0.05523681640625 +52495 -0.022918701171875 +52496 -0.21624755859375 +52497 -0.096832275390625 +52498 -0.334930419921875 +52499 -0.151763916015625 +52500 -0.402984619140625 +52501 -0.183929443359375 +52502 -0.4412841796875 +52503 -0.202423095703125 +52504 -0.49578857421875 +52505 -0.2274169921875 +52506 -0.5601806640625 +52507 -0.256072998046875 +52508 -0.600738525390625 +52509 -0.27362060546875 +52510 -0.584228515625 +52511 -0.265472412109375 +52512 -0.47930908203125 +52513 -0.217926025390625 +52514 -0.27935791015625 +52515 -0.128173828125 +52516 -0.0089111328125 +52517 -0.007171630859375 +52518 0.268798828125 +52519 0.11712646484375 +52520 0.482818603515625 +52521 0.213409423828125 +52522 0.60369873046875 +52523 0.268585205078125 +52524 0.650421142578125 +52525 0.2908935546875 +52526 0.66400146484375 +52527 0.298309326171875 +52528 0.6414794921875 +52529 0.289459228515625 +52530 0.572540283203125 +52531 0.259735107421875 +52532 0.498138427734375 +52533 0.227142333984375 +52534 0.439453125 +52535 0.201019287109375 +52536 0.375518798828125 +52537 0.17218017578125 +52538 0.274505615234375 +52539 0.12664794921875 +52540 0.1087646484375 +52541 0.052337646484375 +52542 -0.099395751953125 +52543 -0.040802001953125 +52544 -0.3182373046875 +52545 -0.13873291015625 +52546 -0.5489501953125 +52547 -0.24188232421875 +52548 -0.7738037109375 +52549 -0.34234619140625 +52550 -0.86383056640625 +52551 -0.416748046875 +52552 -0.870391845703125 +52553 -0.45037841796875 +52554 -0.86895751953125 +52555 -0.451019287109375 +52556 -0.861053466796875 +52557 -0.424407958984375 +52558 -0.765869140625 +52559 -0.3629150390625 +52560 -0.5301513671875 +52561 -0.261566162109375 +52562 -0.214691162109375 +52563 -0.12353515625 +52564 0.137359619140625 +52565 0.032196044921875 +52566 0.474822998046875 +52567 0.183013916015625 +52568 0.76239013671875 +52569 0.313232421875 +52570 0.867462158203125 +52571 0.410888671875 +52572 0.870361328125 +52573 0.476104736328125 +52574 0.86480712890625 +52575 0.503692626953125 +52576 0.831817626953125 +52577 0.4959716796875 +52578 0.677581787109375 +52579 0.463592529296875 +52580 0.495880126953125 +52581 0.409088134765625 +52582 0.30767822265625 +52583 0.340576171875 +52584 0.116180419921875 +52585 0.259033203125 +52586 -0.110748291015625 +52587 0.150482177734375 +52588 -0.381805419921875 +52589 0.01190185546875 +52590 -0.6572265625 +52591 -0.1378173828125 +52592 -0.857421875 +52593 -0.27227783203125 +52594 -0.870391845703125 +52595 -0.372589111328125 +52596 -0.870391845703125 +52597 -0.435516357421875 +52598 -0.86444091796875 +52599 -0.472869873046875 +52600 -0.85723876953125 +52601 -0.500274658203125 +52602 -0.790008544921875 +52603 -0.509613037109375 +52604 -0.62847900390625 +52605 -0.476959228515625 +52606 -0.3956298828125 +52607 -0.40087890625 +52608 -0.126708984375 +52609 -0.2957763671875 +52610 0.150115966796875 +52611 -0.173675537109375 +52612 0.424041748046875 +52613 -0.039764404296875 +52614 0.670623779296875 +52615 0.09405517578125 +52616 0.854522705078125 +52617 0.210723876953125 +52618 0.866485595703125 +52619 0.30242919921875 +52620 0.86920166015625 +52621 0.362335205078125 +52622 0.8653564453125 +52623 0.398406982421875 +52624 0.857147216796875 +52625 0.416473388671875 +52626 0.766845703125 +52627 0.41522216796875 +52628 0.628509521484375 +52629 0.3968505859375 +52630 0.462127685546875 +52631 0.358367919921875 +52632 0.297210693359375 +52633 0.311065673828125 +52634 0.14862060546875 +52635 0.260345458984375 +52636 -0.00537109375 +52637 0.1961669921875 +52638 -0.15753173828125 +52639 0.121856689453125 +52640 -0.31304931640625 +52641 0.035858154296875 +52642 -0.48876953125 +52643 -0.0679931640625 +52644 -0.6416015625 +52645 -0.16900634765625 +52646 -0.751373291015625 +52647 -0.256256103515625 +52648 -0.84619140625 +52649 -0.33984375 +52650 -0.861297607421875 +52651 -0.413238525390625 +52652 -0.863250732421875 +52653 -0.461822509765625 +52654 -0.856597900390625 +52655 -0.471649169921875 +52656 -0.7498779296875 +52657 -0.447998046875 +52658 -0.624542236328125 +52659 -0.41632080078125 +52660 -0.47808837890625 +52661 -0.366943359375 +52662 -0.253387451171875 +52663 -0.274169921875 +52664 0.003692626953125 +52665 -0.158050537109375 +52666 0.2257080078125 +52667 -0.048736572265625 +52668 0.427154541015625 +52669 0.05926513671875 +52670 0.643218994140625 +52671 0.180145263671875 +52672 0.855926513671875 +52673 0.30963134765625 +52674 0.870361328125 +52675 0.422149658203125 +52676 0.870361328125 +52677 0.495819091796875 +52678 0.862762451171875 +52679 0.53375244140625 +52680 0.79669189453125 +52681 0.53460693359375 +52682 0.595794677734375 +52683 0.49420166015625 +52684 0.362152099609375 +52685 0.425384521484375 +52686 0.1270751953125 +52687 0.3404541015625 +52688 -0.086944580078125 +52689 0.248748779296875 +52690 -0.2784423828125 +52691 0.151214599609375 +52692 -0.484832763671875 +52693 0.032562255859375 +52694 -0.729583740234375 +52695 -0.115570068359375 +52696 -0.86688232421875 +52697 -0.27081298828125 +52698 -0.870391845703125 +52699 -0.4052734375 +52700 -0.86859130859375 +52701 -0.516693115234375 +52702 -0.86279296875 +52703 -0.60406494140625 +52704 -0.817962646484375 +52705 -0.6514892578125 +52706 -0.6116943359375 +52707 -0.638916015625 +52708 -0.3128662109375 +52709 -0.563201904296875 +52710 0.039398193359375 +52711 -0.43914794921875 +52712 0.422821044921875 +52713 -0.27557373046875 +52714 0.805145263671875 +52715 -0.087188720703125 +52716 0.870361328125 +52717 0.09600830078125 +52718 0.870361328125 +52719 0.24884033203125 +52720 0.860015869140625 +52721 0.36602783203125 +52722 0.727935791015625 +52723 0.444061279296875 +52724 0.48114013671875 +52725 0.48028564453125 +52726 0.2059326171875 +52727 0.485198974609375 +52728 -0.06103515625 +52729 0.4686279296875 +52730 -0.29913330078125 +52731 0.434814453125 +52732 -0.516204833984375 +52733 0.3773193359375 +52734 -0.7252197265625 +52735 0.289337158203125 +52736 -0.85980224609375 +52737 0.181640625 +52738 -0.870391845703125 +52739 0.069854736328125 +52740 -0.870391845703125 +52741 -0.032806396484375 +52742 -0.858062744140625 +52743 -0.106201171875 +52744 -0.673004150390625 +52745 -0.148345947265625 +52746 -0.42694091796875 +52747 -0.18035888671875 +52748 -0.2100830078125 +52749 -0.22003173828125 +52750 -0.0362548828125 +52751 -0.2662353515625 +52752 0.10943603515625 +52753 -0.306854248046875 +52754 0.23516845703125 +52755 -0.3336181640625 +52756 0.373687744140625 +52757 -0.329559326171875 +52758 0.517791748046875 +52759 -0.2955322265625 +52760 0.602783203125 +52761 -0.257354736328125 +52762 0.635711669921875 +52763 -0.213165283203125 +52764 0.655181884765625 +52765 -0.149627685546875 +52766 0.65948486328125 +52767 -0.071197509765625 +52768 0.651275634765625 +52769 0.018402099609375 +52770 0.61846923828125 +52771 0.108734130859375 +52772 0.53753662109375 +52773 0.18426513671875 +52774 0.404144287109375 +52775 0.2371826171875 +52776 0.22186279296875 +52777 0.263092041015625 +52778 0.003997802734375 +52779 0.26220703125 +52780 -0.22100830078125 +52781 0.24169921875 +52782 -0.42449951171875 +52783 0.2098388671875 +52784 -0.579833984375 +52785 0.17529296875 +52786 -0.641876220703125 +52787 0.155548095703125 +52788 -0.6177978515625 +52789 0.14801025390625 +52790 -0.575531005859375 +52791 0.1265869140625 +52792 -0.526336669921875 +52793 0.089385986328125 +52794 -0.42645263671875 +52795 0.057891845703125 +52796 -0.2581787109375 +52797 0.043731689453125 +52798 -0.068695068359375 +52799 0.032470703125 +52800 0.09222412109375 +52801 0.008819580078125 +52802 0.232147216796875 +52803 -0.01922607421875 +52804 0.3509521484375 +52805 -0.047210693359375 +52806 0.410064697265625 +52807 -0.0869140625 +52808 0.372955322265625 +52809 -0.150146484375 +52810 0.2554931640625 +52811 -0.228271484375 +52812 0.10711669921875 +52813 -0.29998779296875 +52814 -0.052886962890625 +52815 -0.35736083984375 +52816 -0.186279296875 +52817 -0.385772705078125 +52818 -0.23291015625 +52819 -0.362640380859375 +52820 -0.209442138671875 +52821 -0.297515869140625 +52822 -0.174163818359375 +52823 -0.21759033203125 +52824 -0.126739501953125 +52825 -0.1265869140625 +52826 -0.048126220703125 +52827 -0.02081298828125 +52828 0.0426025390625 +52829 0.087860107421875 +52830 0.10748291015625 +52831 0.180084228515625 +52832 0.1409912109375 +52833 0.25018310546875 +52834 0.19708251953125 +52835 0.317352294921875 +52836 0.273651123046875 +52837 0.378662109375 +52838 0.31768798828125 +52839 0.411285400390625 +52840 0.341094970703125 +52841 0.419708251953125 +52842 0.368011474609375 +52843 0.414337158203125 +52844 0.37249755859375 +52845 0.385894775390625 +52846 0.30072021484375 +52847 0.314453125 +52848 0.1517333984375 +52849 0.2022705078125 +52850 -0.01470947265625 +52851 0.076751708984375 +52852 -0.1883544921875 +52853 -0.054534912109375 +52854 -0.372711181640625 +52855 -0.18963623046875 +52856 -0.51397705078125 +52857 -0.303375244140625 +52858 -0.57177734375 +52859 -0.376312255859375 +52860 -0.53948974609375 +52861 -0.40325927734375 +52862 -0.43511962890625 +52863 -0.3896484375 +52864 -0.2962646484375 +52865 -0.34954833984375 +52866 -0.161102294921875 +52867 -0.2979736328125 +52868 -0.0435791015625 +52869 -0.240814208984375 +52870 0.060394287109375 +52871 -0.177276611328125 +52872 0.13665771484375 +52873 -0.1146240234375 +52874 0.170135498046875 +52875 -0.061004638671875 +52876 0.16552734375 +52877 -0.016937255859375 +52878 0.15728759765625 +52879 0.0289306640625 +52880 0.150787353515625 +52881 0.076019287109375 +52882 0.12200927734375 +52883 0.111785888671875 +52884 0.080108642578125 +52885 0.137451171875 +52886 0.05126953125 +52887 0.1614990234375 +52888 0.062896728515625 +52889 0.193359375 +52890 0.09271240234375 +52891 0.22271728515625 +52892 0.092987060546875 +52893 0.229461669921875 +52894 0.07855224609375 +52895 0.219573974609375 +52896 0.06427001953125 +52897 0.199676513671875 +52898 0.0347900390625 +52899 0.164520263671875 +52900 -0.01171875 +52901 0.1148681640625 +52902 -0.056060791015625 +52903 0.060455322265625 +52904 -0.055511474609375 +52905 0.020843505859375 +52906 -0.010467529296875 +52907 -0.001800537109375 +52908 0.02508544921875 +52909 -0.0272216796875 +52910 0.025665283203125 +52911 -0.063690185546875 +52912 0.017333984375 +52913 -0.098663330078125 +52914 0.00189208984375 +52915 -0.12982177734375 +52916 -0.03173828125 +52917 -0.160552978515625 +52918 -0.071502685546875 +52919 -0.185272216796875 +52920 -0.13543701171875 +52921 -0.211090087890625 +52922 -0.219970703125 +52923 -0.23681640625 +52924 -0.300506591796875 +52925 -0.25311279296875 +52926 -0.376312255859375 +52927 -0.26080322265625 +52928 -0.416107177734375 +52929 -0.24859619140625 +52930 -0.371124267578125 +52931 -0.19830322265625 +52932 -0.242279052734375 +52933 -0.11212158203125 +52934 -0.069732666015625 +52935 -0.008331298828125 +52936 0.125640869140625 +52937 0.102691650390625 +52938 0.31268310546875 +52939 0.20660400390625 +52940 0.45501708984375 +52941 0.28717041015625 +52942 0.554779052734375 +52943 0.34417724609375 +52944 0.61065673828125 +52945 0.37640380859375 +52946 0.610931396484375 +52947 0.37872314453125 +52948 0.531463623046875 +52949 0.341400146484375 +52950 0.3883056640625 +52951 0.271453857421875 +52952 0.23468017578125 +52953 0.19140625 +52954 0.095245361328125 +52955 0.112457275390625 +52956 -0.00396728515625 +52957 0.04656982421875 +52958 -0.04852294921875 +52959 0.001068115234375 +52960 -0.055145263671875 +52961 -0.029296875 +52962 -0.0758056640625 +52963 -0.064208984375 +52964 -0.138702392578125 +52965 -0.113739013671875 +52966 -0.209197998046875 +52967 -0.162567138671875 +52968 -0.289031982421875 +52969 -0.21038818359375 +52970 -0.37884521484375 +52971 -0.25677490234375 +52972 -0.456329345703125 +52973 -0.292266845703125 +52974 -0.51641845703125 +52975 -0.31475830078125 +52976 -0.519287109375 +52977 -0.308258056640625 +52978 -0.458251953125 +52979 -0.2706298828125 +52980 -0.384796142578125 +52981 -0.223724365234375 +52982 -0.323699951171875 +52983 -0.1787109375 +52984 -0.269287109375 +52985 -0.134429931640625 +52986 -0.1951904296875 +52987 -0.081390380859375 +52988 -0.100006103515625 +52989 -0.020263671875 +52990 -0.01055908203125 +52991 0.036773681640625 +52992 0.1033935546875 +52993 0.100830078125 +52994 0.24908447265625 +52995 0.17401123046875 +52996 0.373199462890625 +52997 0.234283447265625 +52998 0.45806884765625 +52999 0.2740478515625 +53000 0.511474609375 +53001 0.296142578125 +53002 0.565399169921875 +53003 0.313446044921875 +53004 0.61138916015625 +53005 0.32293701171875 +53006 0.5897216796875 +53007 0.30133056640625 +53008 0.4906005859375 +53009 0.245513916015625 +53010 0.33148193359375 +53011 0.1634521484375 +53012 0.147796630859375 +53013 0.07037353515625 +53014 -0.01873779296875 +53015 -0.015899658203125 +53016 -0.140289306640625 +53017 -0.083160400390625 +53018 -0.191986083984375 +53019 -0.120452880859375 +53020 -0.184295654296875 +53021 -0.131134033203125 +53022 -0.161834716796875 +53023 -0.13238525390625 +53024 -0.166595458984375 +53025 -0.140533447265625 +53026 -0.19390869140625 +53027 -0.153472900390625 +53028 -0.22442626953125 +53029 -0.163482666015625 +53030 -0.279754638671875 +53031 -0.179412841796875 +53032 -0.3389892578125 +53033 -0.193389892578125 +53034 -0.3543701171875 +53035 -0.186920166015625 +53036 -0.348175048828125 +53037 -0.169708251953125 +53038 -0.32598876953125 +53039 -0.14483642578125 +53040 -0.2581787109375 +53041 -0.10137939453125 +53042 -0.139801025390625 +53043 -0.038238525390625 +53044 0.014617919921875 +53045 0.03790283203125 +53046 0.144378662109375 +53047 0.10198974609375 +53048 0.221038818359375 +53049 0.14208984375 +53050 0.27069091796875 +53051 0.168182373046875 +53052 0.294036865234375 +53053 0.180328369140625 +53054 0.311767578125 +53055 0.18670654296875 +53056 0.339141845703125 +53057 0.193511962890625 +53058 0.360260009765625 +53059 0.19439697265625 +53060 0.360504150390625 +53061 0.18408203125 +53062 0.308380126953125 +53063 0.151519775390625 +53064 0.18170166015625 +53065 0.089202880859375 +53066 0.0047607421875 +53067 0.007232666015625 +53068 -0.17559814453125 +53069 -0.07586669921875 +53070 -0.3143310546875 +53071 -0.142333984375 +53072 -0.36785888671875 +53073 -0.175018310546875 +53074 -0.36248779296875 +53075 -0.183135986328125 +53076 -0.343536376953125 +53077 -0.183258056640625 +53078 -0.3018798828125 +53079 -0.171630859375 +53080 -0.231414794921875 +53081 -0.14581298828125 +53082 -0.117645263671875 +53083 -0.100433349609375 +53084 0.007049560546875 +53085 -0.04791259765625 +53086 0.087982177734375 +53087 -0.00921630859375 +53088 0.13946533203125 +53089 0.020477294921875 +53090 0.17425537109375 +53091 0.04534912109375 +53092 0.188201904296875 +53093 0.063140869140625 +53094 0.171234130859375 +53095 0.069366455078125 +53096 0.118438720703125 +53097 0.061492919921875 +53098 0.05706787109375 +53099 0.049163818359375 +53100 -0.010711669921875 +53101 0.032623291015625 +53102 -0.0914306640625 +53103 0.008941650390625 +53104 -0.162322998046875 +53105 -0.0135498046875 +53106 -0.194549560546875 +53107 -0.024200439453125 +53108 -0.1492919921875 +53109 -0.0084228515625 +53110 -0.02166748046875 +53111 0.035736083984375 +53112 0.124053955078125 +53113 0.08441162109375 +53114 0.211151123046875 +53115 0.109130859375 +53116 0.240447998046875 +53117 0.1107177734375 +53118 0.242218017578125 +53119 0.101104736328125 +53120 0.2257080078125 +53121 0.084381103515625 +53122 0.194366455078125 +53123 0.062408447265625 +53124 0.115509033203125 +53125 0.023468017578125 +53126 0.0128173828125 +53127 -0.023040771484375 +53128 -0.053802490234375 +53129 -0.05419921875 +53130 -0.110626220703125 +53131 -0.079620361328125 +53132 -0.199493408203125 +53133 -0.114898681640625 +53134 -0.29437255859375 +53135 -0.15020751953125 +53136 -0.33221435546875 +53137 -0.161895751953125 +53138 -0.27972412109375 +53139 -0.137664794921875 +53140 -0.185333251953125 +53141 -0.096038818359375 +53142 -0.128204345703125 +53143 -0.067169189453125 +53144 -0.115692138671875 +53145 -0.05419921875 +53146 -0.116455078125 +53147 -0.045867919921875 +53148 -0.105926513671875 +53149 -0.033416748046875 +53150 -0.053955078125 +53151 -0.0059814453125 +53152 0.048797607421875 +53153 0.039520263671875 +53154 0.157318115234375 +53155 0.085845947265625 +53156 0.212005615234375 +53157 0.110321044921875 +53158 0.218475341796875 +53159 0.1148681640625 +53160 0.23724365234375 +53161 0.1221923828125 +53162 0.30535888671875 +53163 0.146270751953125 +53164 0.38128662109375 +53165 0.171630859375 +53166 0.404449462890625 +53167 0.175689697265625 +53168 0.3944091796875 +53169 0.16607666015625 +53170 0.3885498046875 +53171 0.1572265625 +53172 0.362640380859375 +53173 0.140411376953125 +53174 0.27362060546875 +53175 0.099853515625 +53176 0.11712646484375 +53177 0.0343017578125 +53178 -0.054901123046875 +53179 -0.036346435546875 +53180 -0.19085693359375 +53181 -0.092376708984375 +53182 -0.28570556640625 +53183 -0.13165283203125 +53184 -0.339263916015625 +53185 -0.153961181640625 +53186 -0.3775634765625 +53187 -0.16900634765625 +53188 -0.445709228515625 +53189 -0.193756103515625 +53190 -0.535064697265625 +53191 -0.225067138671875 +53192 -0.629058837890625 +53193 -0.256866455078125 +53194 -0.697601318359375 +53195 -0.278045654296875 +53196 -0.70391845703125 +53197 -0.27508544921875 +53198 -0.6424560546875 +53199 -0.2462158203125 +53200 -0.491241455078125 +53201 -0.1834716796875 +53202 -0.265716552734375 +53203 -0.093017578125 +53204 -0.023712158203125 +53205 0.003082275390625 +53206 0.201751708984375 +53207 0.0921630859375 +53208 0.375823974609375 +53209 0.160919189453125 +53210 0.485076904296875 +53211 0.204132080078125 +53212 0.56884765625 +53213 0.23651123046875 +53214 0.634765625 +53215 0.26092529296875 +53216 0.63763427734375 +53217 0.26043701171875 +53218 0.5660400390625 +53219 0.230865478515625 +53220 0.4720458984375 +53221 0.19195556640625 +53222 0.40692138671875 +53223 0.1632080078125 +53224 0.3778076171875 +53225 0.147552490234375 +53226 0.376953125 +53227 0.142364501953125 +53228 0.371978759765625 +53229 0.1357421875 +53230 0.313140869140625 +53231 0.109222412109375 +53232 0.184417724609375 +53233 0.056976318359375 +53234 0.011199951171875 +53235 -0.011199951171875 +53236 -0.171051025390625 +53237 -0.081787109375 +53238 -0.33740234375 +53239 -0.145355224609375 +53240 -0.47198486328125 +53241 -0.1959228515625 +53242 -0.560394287109375 +53243 -0.22808837890625 +53244 -0.58056640625 +53245 -0.233673095703125 +53246 -0.54754638671875 +53247 -0.218475341796875 +53248 -0.508575439453125 +53249 -0.2003173828125 +53250 -0.459503173828125 +53251 -0.17803955078125 +53252 -0.394378662109375 +53253 -0.1494140625 +53254 -0.35260009765625 +53255 -0.1282958984375 +53256 -0.31170654296875 +53257 -0.107330322265625 +53258 -0.197418212890625 +53259 -0.06134033203125 +53260 -0.007965087890625 +53261 0.009918212890625 +53262 0.207489013671875 +53263 0.0892333984375 +53264 0.409210205078125 +53265 0.162689208984375 +53266 0.57208251953125 +53267 0.22149658203125 +53268 0.66595458984375 +53269 0.255157470703125 +53270 0.65875244140625 +53271 0.25262451171875 +53272 0.56744384765625 +53273 0.219757080078125 +53274 0.431396484375 +53275 0.17022705078125 +53276 0.29443359375 +53277 0.1192626953125 +53278 0.182464599609375 +53279 0.0760498046875 +53280 0.06365966796875 +53281 0.0299072265625 +53282 -0.075958251953125 +53283 -0.023651123046875 +53284 -0.189422607421875 +53285 -0.068145751953125 +53286 -0.271942138671875 +53287 -0.10162353515625 +53288 -0.342529296875 +53289 -0.13037109375 +53290 -0.364166259765625 +53291 -0.141448974609375 +53292 -0.327239990234375 +53293 -0.131378173828125 +53294 -0.2769775390625 +53295 -0.115631103515625 +53296 -0.253692626953125 +53297 -0.108001708984375 +53298 -0.24365234375 +53299 -0.103790283203125 +53300 -0.1983642578125 +53301 -0.08636474609375 +53302 -0.116241455078125 +53303 -0.055328369140625 +53304 -0.036834716796875 +53305 -0.0244140625 +53306 0.034881591796875 +53307 0.00439453125 +53308 0.09124755859375 +53309 0.028228759765625 +53310 0.10888671875 +53311 0.038787841796875 +53312 0.125518798828125 +53313 0.048797607421875 +53314 0.15771484375 +53315 0.063720703125 +53316 0.17828369140625 +53317 0.074005126953125 +53318 0.17108154296875 +53319 0.073944091796875 +53320 0.129974365234375 +53321 0.06134033203125 +53322 0.082427978515625 +53323 0.045562744140625 +53324 0.027679443359375 +53325 0.0263671875 +53326 -0.065643310546875 +53327 -0.0069580078125 +53328 -0.15936279296875 +53329 -0.04119873046875 +53330 -0.21307373046875 +53331 -0.06231689453125 +53332 -0.234649658203125 +53333 -0.0728759765625 +53334 -0.2001953125 +53335 -0.064483642578125 +53336 -0.119171142578125 +53337 -0.04022216796875 +53338 -0.024749755859375 +53339 -0.01129150390625 +53340 0.085784912109375 +53341 0.0234375 +53342 0.178131103515625 +53343 0.05230712890625 +53344 0.215576171875 +53345 0.0628662109375 +53346 0.211456298828125 +53347 0.059783935546875 +53348 0.17523193359375 +53349 0.04644775390625 +53350 0.128753662109375 +53351 0.030364990234375 +53352 0.1019287109375 +53353 0.021820068359375 +53354 0.0743408203125 +53355 0.01373291015625 +53356 0.04327392578125 +53357 0.005035400390625 +53358 0.038177490234375 +53359 0.0057373046875 +53360 0.076263427734375 +53361 0.0216064453125 +53362 0.14105224609375 +53363 0.04681396484375 +53364 0.186431884765625 +53365 0.06536865234375 +53366 0.188812255859375 +53367 0.0689697265625 +53368 0.1390380859375 +53369 0.0543212890625 +53370 0.041778564453125 +53371 0.022918701171875 +53372 -0.079437255859375 +53373 -0.0172119140625 +53374 -0.219390869140625 +53375 -0.064361572265625 +53376 -0.367828369140625 +53377 -0.115020751953125 +53378 -0.494873046875 +53379 -0.158935546875 +53380 -0.556243896484375 +53381 -0.18084716796875 +53382 -0.508697509765625 +53383 -0.165802001953125 +53384 -0.3756103515625 +53385 -0.12176513671875 +53386 -0.218902587890625 +53387 -0.0699462890625 +53388 -0.063751220703125 +53389 -0.018890380859375 +53390 0.091552734375 +53391 0.032073974609375 +53392 0.23602294921875 +53393 0.079345703125 +53394 0.342987060546875 +53395 0.113861083984375 +53396 0.39520263671875 +53397 0.129852294921875 +53398 0.389373779296875 +53399 0.126251220703125 +53400 0.324249267578125 +53401 0.10272216796875 +53402 0.224090576171875 +53403 0.067657470703125 +53404 0.124267578125 +53405 0.03326416015625 +53406 0.037078857421875 +53407 0.003753662109375 +53408 -0.010101318359375 +53409 -0.011505126953125 +53410 -0.019439697265625 +53411 -0.013336181640625 +53412 -0.022796630859375 +53413 -0.012786865234375 +53414 -0.001556396484375 +53415 -0.0035400390625 +53416 0.056304931640625 +53417 0.018402099609375 +53418 0.106719970703125 +53419 0.037750244140625 +53420 0.096893310546875 +53421 0.036285400390625 +53422 0.042694091796875 +53423 0.01934814453125 +53424 -0.018035888671875 +53425 -0.0001220703125 +53426 -0.07586669921875 +53427 -0.018951416015625 +53428 -0.11944580078125 +53429 -0.03326416015625 +53430 -0.15972900390625 +53431 -0.046875 +53432 -0.202606201171875 +53433 -0.061798095703125 +53434 -0.24859619140625 +53435 -0.07818603515625 +53436 -0.30517578125 +53437 -0.09857177734375 +53438 -0.36212158203125 +53439 -0.119384765625 +53440 -0.39141845703125 +53441 -0.13092041015625 +53442 -0.35528564453125 +53443 -0.120086669921875 +53444 -0.249969482421875 +53445 -0.08551025390625 +53446 -0.092864990234375 +53447 -0.0330810546875 +53448 0.08905029296875 +53449 0.027984619140625 +53450 0.2352294921875 +53451 0.07696533203125 +53452 0.318817138671875 +53453 0.10467529296875 +53454 0.358642578125 +53455 0.11761474609375 +53456 0.347747802734375 +53457 0.11346435546875 +53458 0.28564453125 +53459 0.092041015625 +53460 0.223175048828125 +53461 0.070831298828125 +53462 0.196746826171875 +53463 0.062347412109375 +53464 0.179840087890625 +53465 0.057403564453125 +53466 0.155548095703125 +53467 0.0501708984375 +53468 0.151214599609375 +53469 0.049957275390625 +53470 0.156951904296875 +53471 0.05328369140625 +53472 0.13177490234375 +53473 0.04595947265625 +53474 0.100799560546875 +53475 0.03656005859375 +53476 0.087127685546875 +53477 0.032989501953125 +53478 0.05487060546875 +53479 0.0228271484375 +53480 -0.009002685546875 +53481 0.00152587890625 +53482 -0.10400390625 +53483 -0.030731201171875 +53484 -0.229400634765625 +53485 -0.07373046875 +53486 -0.35552978515625 +53487 -0.11724853515625 +53488 -0.441925048828125 +53489 -0.1473388671875 +53490 -0.473846435546875 +53491 -0.158905029296875 +53492 -0.464813232421875 +53493 -0.15655517578125 +53494 -0.419097900390625 +53495 -0.1417236328125 +53496 -0.334320068359375 +53497 -0.113525390625 +53498 -0.227935791015625 +53499 -0.07794189453125 +53500 -0.12347412109375 +53501 -0.04296875 +53502 -0.02764892578125 +53503 -0.010894775390625 +53504 0.077667236328125 +53505 0.02459716796875 +53506 0.2132568359375 +53507 0.0704345703125 +53508 0.38885498046875 +53509 0.129180908203125 +53510 0.582794189453125 +53511 0.1934814453125 +53512 0.734039306640625 +53513 0.243743896484375 +53514 0.800140380859375 +53515 0.26641845703125 +53516 0.7783203125 +53517 0.260467529296875 +53518 0.6651611328125 +53519 0.2247314453125 +53520 0.45965576171875 +53521 0.158966064453125 +53522 0.199188232421875 +53523 0.074981689453125 +53524 -0.050689697265625 +53525 -0.00653076171875 +53526 -0.23297119140625 +53527 -0.067535400390625 +53528 -0.33013916015625 +53529 -0.102264404296875 +53530 -0.368408203125 +53531 -0.11865234375 +53532 -0.378936767578125 +53533 -0.1260986328125 +53534 -0.376983642578125 +53535 -0.129150390625 +53536 -0.37969970703125 +53537 -0.132965087890625 +53538 -0.391510009765625 +53539 -0.13873291015625 +53540 -0.385345458984375 +53541 -0.137908935546875 +53542 -0.3419189453125 +53543 -0.124420166015625 +53544 -0.28289794921875 +53545 -0.105072021484375 +53546 -0.251617431640625 +53547 -0.09344482421875 +53548 -0.266143798828125 +53549 -0.095306396484375 +53550 -0.273345947265625 +53551 -0.094268798828125 +53552 -0.216796875 +53553 -0.072906494140625 +53554 -0.128265380859375 +53555 -0.04132080078125 +53556 -0.068145751953125 +53557 -0.018585205078125 +53558 -0.0430908203125 +53559 -0.006988525390625 +53560 -0.024444580078125 +53561 0.00213623046875 +53562 0.020721435546875 +53563 0.0189208984375 +53564 0.124481201171875 +53565 0.05322265625 +53566 0.25787353515625 +53567 0.095916748046875 +53568 0.379119873046875 +53569 0.133941650390625 +53570 0.47991943359375 +53571 0.16473388671875 +53572 0.5281982421875 +53573 0.1783447265625 +53574 0.511138916015625 +53575 0.170867919921875 +53576 0.456207275390625 +53577 0.1510009765625 +53578 0.407470703125 +53579 0.132659912109375 +53580 0.383758544921875 +53581 0.121917724609375 +53582 0.35687255859375 +53583 0.110137939453125 +53584 0.31182861328125 +53585 0.09283447265625 +53586 0.250885009765625 +53587 0.0709228515625 +53588 0.1654052734375 +53589 0.0418701171875 +53590 0.035247802734375 +53591 -0.00048828125 +53592 -0.142059326171875 +53593 -0.056854248046875 +53594 -0.33563232421875 +53595 -0.1175537109375 +53596 -0.5345458984375 +53597 -0.179168701171875 +53598 -0.72186279296875 +53599 -0.236480712890625 +53600 -0.836669921875 +53601 -0.27056884765625 +53602 -0.8326416015625 +53603 -0.267059326171875 +53604 -0.7296142578125 +53605 -0.2322998046875 +53606 -0.582550048828125 +53607 -0.183624267578125 +53608 -0.440093994140625 +53609 -0.1363525390625 +53610 -0.324310302734375 +53611 -0.097503662109375 +53612 -0.20147705078125 +53613 -0.05670166015625 +53614 -0.044647216796875 +53615 -0.00567626953125 +53616 0.103973388671875 +53617 0.04229736328125 +53618 0.202392578125 +53619 0.07403564453125 +53620 0.264495849609375 +53621 0.093841552734375 +53622 0.338897705078125 +53623 0.116851806640625 +53624 0.443817138671875 +53625 0.148773193359375 +53626 0.545074462890625 +53627 0.178985595703125 +53628 0.6173095703125 +53629 0.199676513671875 +53630 0.6524658203125 +53631 0.208465576171875 +53632 0.66339111328125 +53633 0.209503173828125 +53634 0.6561279296875 +53635 0.204803466796875 +53636 0.606781005859375 +53637 0.187042236328125 +53638 0.501190185546875 +53639 0.15191650390625 +53640 0.352783203125 +53641 0.10369873046875 +53642 0.176544189453125 +53643 0.047210693359375 +53644 -0.034820556640625 +53645 -0.019744873046875 +53646 -0.258209228515625 +53647 -0.08990478515625 +53648 -0.44244384765625 +53649 -0.14727783203125 +53650 -0.5753173828125 +53651 -0.188079833984375 +53652 -0.65203857421875 +53653 -0.210906982421875 +53654 -0.641632080078125 +53655 -0.206146240234375 +53656 -0.562164306640625 +53657 -0.179534912109375 +53658 -0.458038330078125 +53659 -0.145050048828125 +53660 -0.350555419921875 +53661 -0.10943603515625 +53662 -0.260528564453125 +53663 -0.07928466796875 +53664 -0.192108154296875 +53665 -0.0560302734375 +53666 -0.141937255859375 +53667 -0.038726806640625 +53668 -0.1021728515625 +53669 -0.024993896484375 +53670 -0.062896728515625 +53671 -0.011810302734375 +53672 -0.011932373046875 +53673 0.00457763671875 +53674 0.062835693359375 +53675 0.027923583984375 +53676 0.148712158203125 +53677 0.054290771484375 +53678 0.241729736328125 +53679 0.082489013671875 +53680 0.34912109375 +53681 0.11480712890625 +53682 0.457305908203125 +53683 0.1470947265625 +53684 0.54388427734375 +53685 0.172454833984375 +53686 0.5728759765625 +53687 0.17974853515625 +53688 0.506591796875 +53689 0.157318115234375 +53690 0.351226806640625 +53691 0.107208251953125 +53692 0.146514892578125 +53693 0.0418701171875 +53694 -0.05523681640625 +53695 -0.02227783203125 +53696 -0.21624755859375 +53697 -0.0733642578125 +53698 -0.334930419921875 +53699 -0.110870361328125 +53700 -0.402984619140625 +53701 -0.132171630859375 +53702 -0.4412841796875 +53703 -0.143798828125 +53704 -0.49578857421875 +53705 -0.160125732421875 +53706 -0.5601806640625 +53707 -0.179229736328125 +53708 -0.600738525390625 +53709 -0.190673828125 +53710 -0.584228515625 +53711 -0.18414306640625 +53712 -0.47930908203125 +53713 -0.149932861328125 +53714 -0.27935791015625 +53715 -0.086090087890625 +53716 -0.0089111328125 +53717 -0.000335693359375 +53718 0.268798828125 +53719 0.087493896484375 +53720 0.482818603515625 +53721 0.15521240234375 +53722 0.60369873046875 +53723 0.193603515625 +53724 0.650421142578125 +53725 0.208526611328125 +53726 0.66400146484375 +53727 0.2127685546875 +53728 0.6414794921875 +53729 0.2054443359375 +53730 0.572540283203125 +53731 0.183380126953125 +53732 0.498138427734375 +53733 0.15936279296875 +53734 0.439453125 +53735 0.14007568359375 +53736 0.375518798828125 +53737 0.1190185546875 +53738 0.274505615234375 +53739 0.086334228515625 +53740 0.1087646484375 +53741 0.033447265625 +53742 -0.099395751953125 +53743 -0.0325927734375 +53744 -0.3182373046875 +53745 -0.101806640625 +53746 -0.5489501953125 +53747 -0.174560546875 +53748 -0.7738037109375 +53749 -0.245269775390625 +53750 -0.86383056640625 +53751 -0.29736328125 +53752 -0.870391845703125 +53753 -0.320465087890625 +53754 -0.86895751953125 +53755 -0.32012939453125 +53756 -0.861053466796875 +53757 -0.300445556640625 +53758 -0.765869140625 +53759 -0.25604248046875 +53760 -0.5301513671875 +53761 -0.183563232421875 +53762 -0.214691162109375 +53763 -0.085784912109375 +53764 0.137359619140625 +53765 0.02398681640625 +53766 0.474822998046875 +53767 0.13037109375 +53768 0.76239013671875 +53769 0.2225341796875 +53770 0.867462158203125 +53771 0.292205810546875 +53772 0.870361328125 +53773 0.339019775390625 +53774 0.86480712890625 +53775 0.35943603515625 +53776 0.831817626953125 +53777 0.354827880859375 +53778 0.677581787109375 +53779 0.33209228515625 +53780 0.495880126953125 +53781 0.293060302734375 +53782 0.30767822265625 +53783 0.243255615234375 +53784 0.116180419921875 +53785 0.1837158203125 +53786 -0.110748291015625 +53787 0.106048583984375 +53788 -0.381805419921875 +53789 0.008880615234375 +53790 -0.6572265625 +53791 -0.095245361328125 +53792 -0.857421875 +53793 -0.188995361328125 +53794 -0.870391845703125 +53795 -0.2598876953125 +53796 -0.870391845703125 +53797 -0.3055419921875 +53798 -0.86444091796875 +53799 -0.33319091796875 +53800 -0.85723876953125 +53801 -0.352630615234375 +53802 -0.790008544921875 +53803 -0.358612060546875 +53804 -0.62847900390625 +53805 -0.335968017578125 +53806 -0.3956298828125 +53807 -0.283935546875 +53808 -0.126708984375 +53809 -0.211944580078125 +53810 0.150115966796875 +53811 -0.128021240234375 +53812 0.424041748046875 +53813 -0.035797119140625 +53814 0.670623779296875 +53815 0.056732177734375 +53816 0.854522705078125 +53817 0.1383056640625 +53818 0.866485595703125 +53819 0.20355224609375 +53820 0.86920166015625 +53821 0.247772216796875 +53822 0.8653564453125 +53823 0.27569580078125 +53824 0.857147216796875 +53825 0.290802001953125 +53826 0.766845703125 +53827 0.2921142578125 +53828 0.628509521484375 +53829 0.28094482421875 +53830 0.462127685546875 +53831 0.255401611328125 +53832 0.297210693359375 +53833 0.2227783203125 +53834 0.14862060546875 +53835 0.186737060546875 +53836 -0.00537109375 +53837 0.141082763671875 +53838 -0.15753173828125 +53839 0.088226318359375 +53840 -0.31304931640625 +53841 0.027496337890625 +53842 -0.48876953125 +53843 -0.044647216796875 +53844 -0.6416015625 +53845 -0.114715576171875 +53846 -0.751373291015625 +53847 -0.175445556640625 +53848 -0.84619140625 +53849 -0.233001708984375 +53850 -0.861297607421875 +53851 -0.28302001953125 +53852 -0.863250732421875 +53853 -0.316070556640625 +53854 -0.856597900390625 +53855 -0.32318115234375 +53856 -0.7498779296875 +53857 -0.307708740234375 +53858 -0.624542236328125 +53859 -0.285919189453125 +53860 -0.47808837890625 +53861 -0.251739501953125 +53862 -0.253387451171875 +53863 -0.188995361328125 +53864 0.003692626953125 +53865 -0.1107177734375 +53866 0.2257080078125 +53867 -0.03631591796875 +53868 0.427154541015625 +53869 0.037384033203125 +53870 0.643218994140625 +53871 0.119140625 +53872 0.855926513671875 +53873 0.205963134765625 +53874 0.870361328125 +53875 0.2813720703125 +53876 0.870361328125 +53877 0.33123779296875 +53878 0.862762451171875 +53879 0.357421875 +53880 0.79669189453125 +53881 0.358978271484375 +53882 0.595794677734375 +53883 0.333251953125 +53884 0.362152099609375 +53885 0.288421630859375 +53886 0.1270751953125 +53887 0.232421875 +53888 -0.086944580078125 +53889 0.171295166015625 +53890 -0.2784423828125 +53891 0.1058349609375 +53892 -0.484832763671875 +53893 0.026519775390625 +53894 -0.729583740234375 +53895 -0.07171630859375 +53896 -0.86688232421875 +53897 -0.174468994140625 +53898 -0.870391845703125 +53899 -0.263763427734375 +53900 -0.86859130859375 +53901 -0.33795166015625 +53902 -0.86279296875 +53903 -0.396209716796875 +53904 -0.817962646484375 +53905 -0.428314208984375 +53906 -0.6116943359375 +53907 -0.42144775390625 +53908 -0.3128662109375 +53909 -0.37353515625 +53910 0.039398193359375 +53911 -0.294036865234375 +53912 0.422821044921875 +53913 -0.1885986328125 +53914 0.805145263671875 +53915 -0.066650390625 +53916 0.870361328125 +53917 0.052520751953125 +53918 0.870361328125 +53919 0.152740478515625 +53920 0.860015869140625 +53921 0.23046875 +53922 0.727935791015625 +53923 0.2833251953125 +53924 0.48114013671875 +53925 0.3094482421875 +53926 0.2059326171875 +53927 0.315338134765625 +53928 -0.06103515625 +53929 0.307098388671875 +53930 -0.29913330078125 +53931 0.287384033203125 +53932 -0.516204833984375 +53933 0.251983642578125 +53934 -0.7252197265625 +53935 0.196502685546875 +53936 -0.85980224609375 +53937 0.1279296875 +53938 -0.870391845703125 +53939 0.055938720703125 +53940 -0.870391845703125 +53941 -0.011016845703125 +53942 -0.858062744140625 +53943 -0.05908203125 +53944 -0.673004150390625 +53945 -0.086822509765625 +53946 -0.42694091796875 +53947 -0.108642578125 +53948 -0.2100830078125 +53949 -0.136627197265625 +53950 -0.0362548828125 +53951 -0.16986083984375 +53952 0.10943603515625 +53953 -0.19989013671875 +53954 0.23516845703125 +53955 -0.220855712890625 +53956 0.373687744140625 +53957 -0.220977783203125 +53958 0.517791748046875 +53959 -0.20062255859375 +53960 0.602783203125 +53961 -0.1773681640625 +53962 0.635711669921875 +53963 -0.1497802734375 +53964 0.655181884765625 +53965 -0.10858154296875 +53966 0.65948486328125 +53967 -0.05670166015625 +53968 0.651275634765625 +53969 0.00335693359375 +53970 0.61846923828125 +53971 0.064483642578125 +53972 0.53753662109375 +53973 0.115997314453125 +53974 0.404144287109375 +53975 0.152557373046875 +53976 0.22186279296875 +53977 0.171142578125 +53978 0.003997802734375 +53979 0.171844482421875 +53980 -0.22100830078125 +53981 0.15948486328125 +53982 -0.42449951171875 +53983 0.139617919921875 +53984 -0.579833984375 +53985 0.118072509765625 +53986 -0.641876220703125 +53987 0.106719970703125 +53988 -0.6177978515625 +53989 0.103668212890625 +53990 -0.575531005859375 +53991 0.090911865234375 +53992 -0.526336669921875 +53993 0.067047119140625 +53994 -0.42645263671875 +53995 0.046783447265625 +53996 -0.2581787109375 +53997 0.0379638671875 +53998 -0.068695068359375 +53999 0.030670166015625 +54000 0.09222412109375 +54001 0.014373779296875 +54002 0.232147216796875 +54003 -0.00537109375 +54004 0.3509521484375 +54005 -0.025482177734375 +54006 0.410064697265625 +54007 -0.053985595703125 +54008 0.372955322265625 +54009 -0.098907470703125 +54010 0.2554931640625 +54011 -0.154205322265625 +54012 0.10711669921875 +54013 -0.205169677734375 +54014 -0.052886962890625 +54015 -0.24627685546875 +54016 -0.186279296875 +54017 -0.267791748046875 +54018 -0.23291015625 +54019 -0.254608154296875 +54020 -0.209442138671875 +54021 -0.21234130859375 +54022 -0.174163818359375 +54023 -0.158355712890625 +54024 -0.126739501953125 +54025 -0.09564208984375 +54026 -0.048126220703125 +54027 -0.022705078125 +54028 0.0426025390625 +54029 0.052490234375 +54030 0.10748291015625 +54031 0.117431640625 +54032 0.1409912109375 +54033 0.1680908203125 +54034 0.19708251953125 +54035 0.215789794921875 +54036 0.273651123046875 +54037 0.25836181640625 +54038 0.31768798828125 +54039 0.281585693359375 +54040 0.341094970703125 +54041 0.288116455078125 +54042 0.368011474609375 +54043 0.284332275390625 +54044 0.37249755859375 +54045 0.2646484375 +54046 0.30072021484375 +54047 0.217041015625 +54048 0.1517333984375 +54049 0.1431884765625 +54050 -0.01470947265625 +54051 0.06024169921875 +54052 -0.1883544921875 +54053 -0.02679443359375 +54054 -0.372711181640625 +54055 -0.116363525390625 +54056 -0.51397705078125 +54057 -0.192626953125 +54058 -0.57177734375 +54059 -0.243316650390625 +54060 -0.53948974609375 +54061 -0.264923095703125 +54062 -0.43511962890625 +54063 -0.26055908203125 +54064 -0.2962646484375 +54065 -0.2386474609375 +54066 -0.161102294921875 +54067 -0.208282470703125 +54068 -0.0435791015625 +54069 -0.17303466796875 +54070 0.060394287109375 +54071 -0.132476806640625 +54072 0.13665771484375 +54073 -0.0911865234375 +54074 0.170135498046875 +54075 -0.054351806640625 +54076 0.16552734375 +54077 -0.02252197265625 +54078 0.15728759765625 +54079 0.01092529296875 +54080 0.150787353515625 +54081 0.04534912109375 +54082 0.12200927734375 +54083 0.07275390625 +54084 0.080108642578125 +54085 0.093597412109375 +54086 0.05126953125 +54087 0.11279296875 +54088 0.062896728515625 +54089 0.135894775390625 +54090 0.09271240234375 +54091 0.156402587890625 +54092 0.092987060546875 +54093 0.161895751953125 +54094 0.07855224609375 +54095 0.156005859375 +54096 0.06427001953125 +54097 0.142791748046875 +54098 0.0347900390625 +54099 0.119110107421875 +54100 -0.01171875 +54101 0.085601806640625 +54102 -0.056060791015625 +54103 0.048431396484375 +54104 -0.055511474609375 +54105 0.01983642578125 +54106 -0.010467529296875 +54107 0.0013427734375 +54108 0.02508544921875 +54109 -0.01885986328125 +54110 0.025665283203125 +54111 -0.045562744140625 +54112 0.017333984375 +54113 -0.07086181640625 +54114 0.00189208984375 +54115 -0.0931396484375 +54116 -0.03173828125 +54117 -0.114288330078125 +54118 -0.071502685546875 +54119 -0.13079833984375 +54120 -0.13543701171875 +54121 -0.14697265625 +54122 -0.219970703125 +54123 -0.162109375 +54124 -0.300506591796875 +54125 -0.1705322265625 +54126 -0.376312255859375 +54127 -0.1728515625 +54128 -0.416107177734375 +54129 -0.162322998046875 +54130 -0.371124267578125 +54131 -0.12799072265625 +54132 -0.242279052734375 +54133 -0.0714111328125 +54134 -0.069732666015625 +54135 -0.003997802734375 +54136 0.125640869140625 +54137 0.06768798828125 +54138 0.31268310546875 +54139 0.1346435546875 +54140 0.45501708984375 +54141 0.186737060546875 +54142 0.554779052734375 +54143 0.223724365234375 +54144 0.61065673828125 +54145 0.2447509765625 +54146 0.610931396484375 +54147 0.246673583984375 +54148 0.531463623046875 +54149 0.2235107421875 +54150 0.3883056640625 +54151 0.1795654296875 +54152 0.23468017578125 +54153 0.128753662109375 +54154 0.095245361328125 +54155 0.07806396484375 +54156 -0.00396728515625 +54157 0.034942626953125 +54158 -0.04852294921875 +54159 0.0040283203125 +54160 -0.055145263671875 +54161 -0.0177001953125 +54162 -0.0758056640625 +54163 -0.042144775390625 +54164 -0.138702392578125 +54165 -0.0753173828125 +54166 -0.209197998046875 +54167 -0.107635498046875 +54168 -0.289031982421875 +54169 -0.138824462890625 +54170 -0.37884521484375 +54171 -0.16851806640625 +54172 -0.456329345703125 +54173 -0.190887451171875 +54174 -0.51641845703125 +54175 -0.204620361328125 +54176 -0.519287109375 +54177 -0.199951171875 +54178 -0.458251953125 +54179 -0.17559814453125 +54180 -0.384796142578125 +54181 -0.145050048828125 +54182 -0.323699951171875 +54183 -0.115234375 +54184 -0.269287109375 +54185 -0.085601806640625 +54186 -0.1951904296875 +54187 -0.050506591796875 +54188 -0.100006103515625 +54189 -0.010498046875 +54190 -0.01055908203125 +54191 0.02679443359375 +54192 0.1033935546875 +54193 0.06817626953125 +54194 0.24908447265625 +54195 0.11480712890625 +54196 0.373199462890625 +54197 0.15289306640625 +54198 0.45806884765625 +54199 0.177734375 +54200 0.511474609375 +54201 0.191131591796875 +54202 0.565399169921875 +54203 0.201202392578125 +54204 0.61138916015625 +54205 0.20611572265625 +54206 0.5897216796875 +54207 0.19140625 +54208 0.4906005859375 +54209 0.15521240234375 +54210 0.33148193359375 +54211 0.102569580078125 +54212 0.147796630859375 +54213 0.043060302734375 +54214 -0.01873779296875 +54215 -0.0120849609375 +54216 -0.140289306640625 +54217 -0.05517578125 +54218 -0.191986083984375 +54219 -0.079315185546875 +54220 -0.184295654296875 +54221 -0.086578369140625 +54222 -0.161834716796875 +54223 -0.087677001953125 +54224 -0.166595458984375 +54225 -0.0927734375 +54226 -0.19390869140625 +54227 -0.1005859375 +54228 -0.22442626953125 +54229 -0.1063232421875 +54230 -0.279754638671875 +54231 -0.115570068359375 +54232 -0.3389892578125 +54233 -0.1234130859375 +54234 -0.3543701171875 +54235 -0.118377685546875 +54236 -0.348175048828125 +54237 -0.1065673828125 +54238 -0.32598876953125 +54239 -0.0899658203125 +54240 -0.2581787109375 +54241 -0.061798095703125 +54242 -0.139801025390625 +54243 -0.02142333984375 +54244 0.014617919921875 +54245 0.02691650390625 +54246 0.144378662109375 +54247 0.067535400390625 +54248 0.221038818359375 +54249 0.092926025390625 +54250 0.27069091796875 +54251 0.10931396484375 +54252 0.294036865234375 +54253 0.11676025390625 +54254 0.311767578125 +54255 0.12042236328125 +54256 0.339141845703125 +54257 0.12420654296875 +54258 0.360260009765625 +54259 0.12432861328125 +54260 0.360504150390625 +54261 0.11749267578125 +54262 0.308380126953125 +54263 0.0963134765625 +54264 0.18170166015625 +54265 0.0557861328125 +54266 0.0047607421875 +54267 0.00250244140625 +54268 -0.17559814453125 +54269 -0.0513916015625 +54270 -0.3143310546875 +54271 -0.09423828125 +54272 -0.36785888671875 +54273 -0.11517333984375 +54274 -0.36248779296875 +54275 -0.119964599609375 +54276 -0.343536376953125 +54277 -0.11895751953125 +54278 -0.3018798828125 +54279 -0.110321044921875 +54280 -0.231414794921875 +54281 -0.092926025390625 +54282 -0.117645263671875 +54283 -0.063934326171875 +54284 0.007049560546875 +54285 -0.030731201171875 +54286 0.087982177734375 +54287 -0.005523681640625 +54288 0.13946533203125 +54289 0.0142822265625 +54290 0.17425537109375 +54291 0.03094482421875 +54292 0.188201904296875 +54293 0.0430908203125 +54294 0.171234130859375 +54295 0.048065185546875 +54296 0.118438720703125 +54297 0.04437255859375 +54298 0.05706787109375 +54299 0.037567138671875 +54300 -0.010711669921875 +54301 0.02777099609375 +54302 -0.0914306640625 +54303 0.01336669921875 +54304 -0.162322998046875 +54305 -0.00079345703125 +54306 -0.194549560546875 +54307 -0.008514404296875 +54308 -0.1492919921875 +54309 -0.00128173828125 +54310 -0.02166748046875 +54311 0.022125244140625 +54312 0.124053955078125 +54313 0.048095703125 +54314 0.211151123046875 +54315 0.06036376953125 +54316 0.240447998046875 +54317 0.059539794921875 +54318 0.242218017578125 +54319 0.05255126953125 +54320 0.2257080078125 +54321 0.04180908203125 +54322 0.194366455078125 +54323 0.0284423828125 +54324 0.115509033203125 +54325 0.0057373046875 +54326 0.0128173828125 +54327 -0.020843505859375 +54328 -0.053802490234375 +54329 -0.038177490234375 +54330 -0.110626220703125 +54331 -0.05181884765625 +54332 -0.199493408203125 +54333 -0.070770263671875 +54334 -0.29437255859375 +54335 -0.089508056640625 +54336 -0.33221435546875 +54337 -0.09454345703125 +54338 -0.27972412109375 +54339 -0.07891845703125 +54340 -0.185333251953125 +54341 -0.053314208984375 +54342 -0.128204345703125 +54343 -0.03515625 +54344 -0.115692138671875 +54345 -0.0263671875 +54346 -0.116455078125 +54347 -0.0205078125 +54348 -0.105926513671875 +54349 -0.01263427734375 +54350 -0.053955078125 +54351 0.003448486328125 +54352 0.048797607421875 +54353 0.029541015625 +54354 0.157318115234375 +54355 0.05572509765625 +54356 0.212005615234375 +54357 0.069000244140625 +54358 0.218475341796875 +54359 0.070556640625 +54360 0.23724365234375 +54361 0.073516845703125 +54362 0.30535888671875 +54363 0.085968017578125 +54364 0.38128662109375 +54365 0.09906005859375 +54366 0.404449462890625 +54367 0.09991455078125 +54368 0.3944091796875 +54369 0.093017578125 +54370 0.3885498046875 +54371 0.086700439453125 +54372 0.362640380859375 +54373 0.0760498046875 +54374 0.27362060546875 +54375 0.052032470703125 +54376 0.11712646484375 +54377 0.01397705078125 +54378 -0.054901123046875 +54379 -0.026641845703125 +54380 -0.19085693359375 +54381 -0.05853271484375 +54382 -0.28570556640625 +54383 -0.08050537109375 +54384 -0.339263916015625 +54385 -0.092437744140625 +54386 -0.3775634765625 +54387 -0.100006103515625 +54388 -0.445709228515625 +54389 -0.113006591796875 +54390 -0.535064697265625 +54391 -0.12969970703125 +54392 -0.629058837890625 +54393 -0.14666748046875 +54394 -0.697601318359375 +54395 -0.1575927734375 +54396 -0.70391845703125 +54397 -0.15478515625 +54398 -0.6424560546875 +54399 -0.13726806640625 +54400 -0.491241455078125 +54401 -0.100555419921875 +54402 -0.265716552734375 +54403 -0.0482177734375 +54404 -0.023712158203125 +54405 0.007049560546875 +54406 0.201751708984375 +54407 0.058013916015625 +54408 0.375823974609375 +54409 0.097015380859375 +54410 0.485076904296875 +54411 0.12109375 +54412 0.56884765625 +54413 0.138763427734375 +54414 0.634765625 +54415 0.151702880859375 +54416 0.63763427734375 +54417 0.1502685546875 +54418 0.5660400390625 +54419 0.132110595703125 +54420 0.4720458984375 +54421 0.108642578125 +54422 0.40692138671875 +54423 0.091156005859375 +54424 0.3778076171875 +54425 0.08135986328125 +54426 0.376953125 +54427 0.0777587890625 +54428 0.371978759765625 +54429 0.07354736328125 +54430 0.313140869140625 +54431 0.05816650390625 +54432 0.184417724609375 +54433 0.028289794921875 +54434 0.011199951171875 +54435 -0.010498046875 +54436 -0.171051025390625 +54437 -0.050445556640625 +54438 -0.33740234375 +54439 -0.086181640625 +54440 -0.47198486328125 +54441 -0.114288330078125 +54442 -0.560394287109375 +54443 -0.131744384765625 +54444 -0.58056640625 +54445 -0.133880615234375 +54446 -0.54754638671875 +54447 -0.124114990234375 +54448 -0.508575439453125 +54449 -0.112823486328125 +54450 -0.459503173828125 +54451 -0.099273681640625 +54452 -0.394378662109375 +54453 -0.08233642578125 +54454 -0.35260009765625 +54455 -0.07061767578125 +54456 -0.31170654296875 +54457 -0.0594482421875 +54458 -0.197418212890625 +54459 -0.03289794921875 +54460 -0.007965087890625 +54461 0.009307861328125 +54462 0.207489013671875 +54463 0.05645751953125 +54464 0.409210205078125 +54465 0.0999755859375 +54466 0.57208251953125 +54467 0.134490966796875 +54468 0.66595458984375 +54469 0.153533935546875 +54470 0.65875244140625 +54471 0.150238037109375 +54472 0.56744384765625 +54473 0.12841796875 +54474 0.431396484375 +54475 0.0966796875 +54476 0.29443359375 +54477 0.064605712890625 +54478 0.182464599609375 +54479 0.037933349609375 +54480 0.06365966796875 +54481 0.009918212890625 +54482 -0.075958251953125 +54483 -0.02227783203125 +54484 -0.189422607421875 +54485 -0.048431396484375 +54486 -0.271942138671875 +54487 -0.0673828125 +54488 -0.342529296875 +54489 -0.083221435546875 +54490 -0.364166259765625 +54491 -0.08795166015625 +54492 -0.327239990234375 +54493 -0.079498291015625 +54494 -0.2769775390625 +54495 -0.06768798828125 +54496 -0.253692626953125 +54497 -0.061279296875 +54498 -0.24365234375 +54499 -0.057373046875 +54500 -0.1983642578125 +54501 -0.045654296875 +54502 -0.116241455078125 +54503 -0.025848388671875 +54504 -0.036834716796875 +54505 -0.006622314453125 +54506 0.034881591796875 +54507 0.01080322265625 +54508 0.09124755859375 +54509 0.024688720703125 +54510 0.10888671875 +54511 0.029876708984375 +54512 0.125518798828125 +54513 0.03448486328125 +54514 0.15771484375 +54515 0.042022705078125 +54516 0.17828369140625 +54517 0.046600341796875 +54518 0.17108154296875 +54519 0.04473876953125 +54520 0.129974365234375 +54521 0.035125732421875 +54522 0.082427978515625 +54523 0.02374267578125 +54524 0.027679443359375 +54525 0.010498046875 +54526 -0.065643310546875 +54527 -0.01123046875 +54528 -0.15936279296875 +54529 -0.033477783203125 +54530 -0.21307373046875 +54531 -0.047027587890625 +54532 -0.234649658203125 +54533 -0.0528564453125 +54534 -0.2001953125 +54535 -0.046875 +54536 -0.119171142578125 +54537 -0.03118896484375 +54538 -0.024749755859375 +54539 -0.01220703125 +54540 0.085784912109375 +54541 0.01025390625 +54542 0.178131103515625 +54543 0.029571533203125 +54544 0.215576171875 +54545 0.038818359375 +54546 0.211456298828125 +54547 0.040252685546875 +54548 0.17523193359375 +54549 0.0355224609375 +54550 0.128753662109375 +54551 0.028533935546875 +54552 0.1019287109375 +54553 0.02471923828125 +54554 0.0743408203125 +54555 0.020294189453125 +54556 0.04327392578125 +54557 0.0147705078125 +54558 0.038177490234375 +54559 0.0135498046875 +54560 0.076263427734375 +54561 0.019866943359375 +54562 0.14105224609375 +54563 0.030731201171875 +54564 0.186431884765625 +54565 0.03778076171875 +54566 0.188812255859375 +54567 0.0367431640625 +54568 0.1390380859375 +54569 0.026031494140625 +54570 0.041778564453125 +54571 0.006622314453125 +54572 -0.079437255859375 +54573 -0.017059326171875 +54574 -0.219390869140625 +54575 -0.04400634765625 +54576 -0.367828369140625 +54577 -0.072235107421875 +54578 -0.494873046875 +54579 -0.09619140625 +54580 -0.556243896484375 +54581 -0.10772705078125 +54582 -0.508697509765625 +54583 -0.098876953125 +54584 -0.3756103515625 +54585 -0.073974609375 +54586 -0.218902587890625 +54587 -0.044464111328125 +54588 -0.063751220703125 +54589 -0.0150146484375 +54590 0.091552734375 +54591 0.01458740234375 +54592 0.23602294921875 +54593 0.042236328125 +54594 0.342987060546875 +54595 0.06298828125 +54596 0.39520263671875 +54597 0.07366943359375 +54598 0.389373779296875 +54599 0.073577880859375 +54600 0.324249267578125 +54601 0.06243896484375 +54602 0.224090576171875 +54603 0.044708251953125 +54604 0.124267578125 +54605 0.026824951171875 +54606 0.037078857421875 +54607 0.01104736328125 +54608 -0.010101318359375 +54609 0.00238037109375 +54610 -0.019439697265625 +54611 0.000457763671875 +54612 -0.022796630859375 +54613 -0.00054931640625 +54614 -0.001556396484375 +54615 0.002777099609375 +54616 0.056304931640625 +54617 0.012664794921875 +54618 0.106719970703125 +54619 0.02105712890625 +54620 0.096893310546875 +54621 0.018310546875 +54622 0.042694091796875 +54623 0.007415771484375 +54624 -0.018035888671875 +54625 -0.004608154296875 +54626 -0.07586669921875 +54627 -0.015960693359375 +54628 -0.11944580078125 +54629 -0.024505615234375 +54630 -0.15972900390625 +54631 -0.032257080078125 +54632 -0.202606201171875 +54633 -0.040283203125 +54634 -0.24859619140625 +54635 -0.048675537109375 +54636 -0.30517578125 +54637 -0.058807373046875 +54638 -0.36212158203125 +54639 -0.06884765625 +54640 -0.39141845703125 +54641 -0.07366943359375 +54642 -0.35528564453125 +54643 -0.06634521484375 +54644 -0.249969482421875 +54645 -0.046234130859375 +54646 -0.092864990234375 +54647 -0.016571044921875 +54648 0.08905029296875 +54649 0.017578125 +54650 0.2352294921875 +54651 0.045074462890625 +54652 0.318817138671875 +54653 0.060943603515625 +54654 0.358642578125 +54655 0.068603515625 +54656 0.347747802734375 +54657 0.0667724609375 +54658 0.28564453125 +54659 0.05535888671875 +54660 0.223175048828125 +54661 0.043731689453125 +54662 0.196746826171875 +54663 0.038604736328125 +54664 0.179840087890625 +54665 0.035125732421875 +54666 0.155548095703125 +54667 0.030181884765625 +54668 0.151214599609375 +54669 0.028839111328125 +54670 0.156951904296875 +54671 0.029327392578125 +54672 0.13177490234375 +54673 0.02410888671875 +54674 0.100799560546875 +54675 0.017852783203125 +54676 0.087127685546875 +54677 0.01483154296875 +54678 0.05487060546875 +54679 0.00848388671875 +54680 -0.009002685546875 +54681 -0.003570556640625 +54682 -0.10400390625 +54683 -0.02117919921875 +54684 -0.229400634765625 +54685 -0.04425048828125 +54686 -0.35552978515625 +54687 -0.06732177734375 +54688 -0.441925048828125 +54689 -0.08294677734375 +54690 -0.473846435546875 +54691 -0.08843994140625 +54692 -0.464813232421875 +54693 -0.0863037109375 +54694 -0.419097900390625 +54695 -0.077362060546875 +54696 -0.334320068359375 +54697 -0.06121826171875 +54698 -0.227935791015625 +54699 -0.041107177734375 +54700 -0.12347412109375 +54701 -0.021392822265625 +54702 -0.02764892578125 +54703 -0.003326416015625 +54704 0.077667236328125 +54705 0.016387939453125 +54706 0.2132568359375 +54707 0.04156494140625 +54708 0.38885498046875 +54709 0.073944091796875 +54710 0.582794189453125 +54711 0.10955810546875 +54712 0.734039306640625 +54713 0.13720703125 +54714 0.800140380859375 +54715 0.1490478515625 +54716 0.7783203125 +54717 0.144622802734375 +54718 0.6651611328125 +54719 0.123291015625 +54720 0.45965576171875 +54721 0.084930419921875 +54722 0.199188232421875 +54723 0.0364990234375 +54724 -0.050689697265625 +54725 -0.009918212890625 +54726 -0.23297119140625 +54727 -0.0438232421875 +54728 -0.33013916015625 +54729 -0.06195068359375 +54730 -0.368408203125 +54731 -0.06915283203125 +54732 -0.378936767578125 +54733 -0.0711669921875 +54734 -0.376983642578125 +54735 -0.07080078125 +54736 -0.37969970703125 +54737 -0.07122802734375 +54738 -0.391510009765625 +54739 -0.073211669921875 +54740 -0.385345458984375 +54741 -0.071807861328125 +54742 -0.3419189453125 +54743 -0.0634765625 +54744 -0.28289794921875 +54745 -0.052215576171875 +54746 -0.251617431640625 +54747 -0.0460205078125 +54748 -0.266143798828125 +54749 -0.048248291015625 +54750 -0.273345947265625 +54751 -0.04913330078125 +54752 -0.216796875 +54753 -0.038360595703125 +54754 -0.128265380859375 +54755 -0.021759033203125 +54756 -0.068145751953125 +54757 -0.01043701171875 +54758 -0.0430908203125 +54759 -0.005645751953125 +54760 -0.024444580078125 +54761 -0.00213623046875 +54762 0.020721435546875 +54763 0.006103515625 +54764 0.124481201171875 +54765 0.024993896484375 +54766 0.25787353515625 +54767 0.049224853515625 +54768 0.379119873046875 +54769 0.071136474609375 +54770 0.47991943359375 +54771 0.0892333984375 +54772 0.5281982421875 +54773 0.097625732421875 +54774 0.511138916015625 +54775 0.093994140625 +54776 0.456207275390625 +54777 0.083404541015625 +54778 0.407470703125 +54779 0.074005126953125 +54780 0.383758544921875 +54781 0.06927490234375 +54782 0.35687255859375 +54783 0.06402587890625 +54784 0.31182861328125 +54785 0.05499267578125 +54786 0.250885009765625 +54787 0.042327880859375 +54788 0.1654052734375 +54789 0.02508544921875 +54790 0.035247802734375 +54791 0.000701904296875 +54792 -0.142059326171875 +54793 -0.030731201171875 +54794 -0.33563232421875 +54795 -0.064117431640625 +54796 -0.5345458984375 +54797 -0.097503662109375 +54798 -0.72186279296875 +54799 -0.128082275390625 +54800 -0.836669921875 +54801 -0.146484375 +54802 -0.8326416015625 +54803 -0.145599365234375 +54804 -0.7296142578125 +54805 -0.1285400390625 +54806 -0.582550048828125 +54807 -0.103790283203125 +54808 -0.440093994140625 +54809 -0.078857421875 +54810 -0.324310302734375 +54811 -0.057342529296875 +54812 -0.20147705078125 +54813 -0.034332275390625 +54814 -0.044647216796875 +54815 -0.0059814453125 +54816 0.103973388671875 +54817 0.02099609375 +54818 0.202392578125 +54819 0.03997802734375 +54820 0.264495849609375 +54821 0.052825927734375 +54822 0.338897705078125 +54823 0.066741943359375 +54824 0.443817138671875 +54825 0.084381103515625 +54826 0.545074462890625 +54827 0.100494384765625 +54828 0.6173095703125 +54829 0.1112060546875 +54830 0.6524658203125 +54831 0.1153564453125 +54832 0.66339111328125 +54833 0.114959716796875 +54834 0.6561279296875 +54835 0.111053466796875 +54836 0.606781005859375 +54837 0.10015869140625 +54838 0.501190185546875 +54839 0.080352783203125 +54840 0.352783203125 +54841 0.053924560546875 +54842 0.176544189453125 +54843 0.023345947265625 +54844 -0.034820556640625 +54845 -0.01226806640625 +54846 -0.258209228515625 +54847 -0.0491943359375 +54848 -0.44244384765625 +54849 -0.079498291015625 +54850 -0.5753173828125 +54851 -0.101226806640625 +54852 -0.65203857421875 +54853 -0.11358642578125 +54854 -0.641632080078125 +54855 -0.11187744140625 +54856 -0.562164306640625 +54857 -0.098907470703125 +54858 -0.458038330078125 +54859 -0.08148193359375 +54860 -0.350555419921875 +54861 -0.062896728515625 +54862 -0.260528564453125 +54863 -0.046478271484375 +54864 -0.192108154296875 +54865 -0.03302001953125 +54866 -0.141937255859375 +54867 -0.022186279296875 +54868 -0.1021728515625 +54869 -0.012969970703125 +54870 -0.062896728515625 +54871 -0.0040283203125 +54872 -0.011932373046875 +54873 0.00628662109375 +54874 0.062835693359375 +54875 0.01971435546875 +54876 0.148712158203125 +54877 0.03424072265625 +54878 0.241729736328125 +54879 0.0491943359375 +54880 0.34912109375 +54881 0.065643310546875 +54882 0.457305908203125 +54883 0.081512451171875 +54884 0.54388427734375 +54885 0.093475341796875 +54886 0.5728759765625 +54887 0.09613037109375 +54888 0.506591796875 +54889 0.0838623046875 +54890 0.351226806640625 +54891 0.0577392578125 +54892 0.146514892578125 +54893 0.02392578125 +54894 -0.05523681640625 +54895 -0.009429931640625 +54896 -0.21624755859375 +54897 -0.036407470703125 +54898 -0.334930419921875 +54899 -0.056640625 +54900 -0.402984619140625 +54901 -0.068756103515625 +54902 -0.4412841796875 +54903 -0.07586669921875 +54904 -0.49578857421875 +54905 -0.08489990234375 +54906 -0.5601806640625 +54907 -0.0948486328125 +54908 -0.600738525390625 +54909 -0.100616455078125 +54910 -0.584228515625 +54911 -0.097198486328125 +54912 -0.47930908203125 +54913 -0.07989501953125 +54914 -0.27935791015625 +54915 -0.04779052734375 +54916 -0.0089111328125 +54917 -0.004730224609375 +54918 0.268798828125 +54919 0.039581298828125 +54920 0.482818603515625 +54921 0.074188232421875 +54922 0.60369873046875 +54923 0.09454345703125 +54924 0.650421142578125 +54925 0.1033935546875 +54926 0.66400146484375 +54927 0.10687255859375 +54928 0.6414794921875 +54929 0.1044921875 +54930 0.572540283203125 +54931 0.094635009765625 +54932 0.498138427734375 +54933 0.083526611328125 +54934 0.439453125 +54935 0.074371337890625 +54936 0.375518798828125 +54937 0.06402587890625 +54938 0.274505615234375 +54939 0.04766845703125 +54940 0.1087646484375 +54941 0.02117919921875 +54942 -0.099395751953125 +54943 -0.011932373046875 +54944 -0.3182373046875 +54945 -0.0467529296875 +54946 -0.5489501953125 +54947 -0.083404541015625 +54948 -0.7738037109375 +54949 -0.11907958984375 +54950 -0.86383056640625 +54951 -0.1456298828125 +54952 -0.870391845703125 +54953 -0.157958984375 +54954 -0.86895751953125 +54955 -0.158721923828125 +54956 -0.861053466796875 +54957 -0.14990234375 +54958 -0.765869140625 +54959 -0.12884521484375 +54960 -0.5301513671875 +54961 -0.09381103515625 +54962 -0.214691162109375 +54963 -0.0458984375 +54964 0.137359619140625 +54965 0.008270263671875 +54966 0.474822998046875 +54967 0.060882568359375 +54968 0.76239013671875 +54969 0.10650634765625 +54970 0.867462158203125 +54971 0.140960693359375 +54972 0.870361328125 +54973 0.16424560546875 +54974 0.86480712890625 +54975 0.17449951171875 +54976 0.831817626953125 +54977 0.1724853515625 +54978 0.677581787109375 +54979 0.161865234375 +54980 0.495880126953125 +54981 0.14349365234375 +54982 0.30767822265625 +54983 0.12017822265625 +54984 0.116180419921875 +54985 0.092193603515625 +54986 -0.110748291015625 +54987 0.05474853515625 +54988 -0.381805419921875 +54989 0.006805419921875 +54990 -0.6572265625 +54991 -0.04510498046875 +54992 -0.857421875 +54993 -0.09185791015625 +54994 -0.870391845703125 +54995 -0.12689208984375 +54996 -0.870391845703125 +54997 -0.149078369140625 +54998 -0.86444091796875 +54999 -0.162445068359375 +55000 -0.85723876953125 +55001 -0.172393798828125 +55002 -0.790008544921875 +55003 -0.17608642578125 +55004 -0.62847900390625 +55005 -0.165252685546875 +55006 -0.3956298828125 +55007 -0.139373779296875 +55008 -0.126708984375 +55009 -0.1033935546875 +55010 0.150115966796875 +55011 -0.061431884765625 +55012 0.424041748046875 +55013 -0.015289306640625 +55014 0.670623779296875 +55015 0.0308837890625 +55016 0.854522705078125 +55017 0.07122802734375 +55018 0.866485595703125 +55019 0.10302734375 +55020 0.86920166015625 +55021 0.1239013671875 +55022 0.8653564453125 +55023 0.1365966796875 +55024 0.857147216796875 +55025 0.143157958984375 +55026 0.766845703125 +55027 0.14306640625 +55028 0.628509521484375 +55029 0.1370849609375 +55030 0.462127685546875 +55031 0.1241455078125 +55032 0.297210693359375 +55033 0.108123779296875 +55034 0.14862060546875 +55035 0.09088134765625 +55036 -0.00537109375 +55037 0.06890869140625 +55038 -0.15753173828125 +55039 0.043365478515625 +55040 -0.31304931640625 +55041 0.01416015625 +55042 -0.48876953125 +55043 -0.020721435546875 +55044 -0.6416015625 +55045 -0.05548095703125 +55046 -0.751373291015625 +55047 -0.08636474609375 +55048 -0.84619140625 +55049 -0.115478515625 +55050 -0.861297607421875 +55051 -0.1405029296875 +55052 -0.863250732421875 +55053 -0.1571044921875 +55054 -0.856597900390625 +55055 -0.161224365234375 +55056 -0.7498779296875 +55057 -0.15423583984375 +55058 -0.624542236328125 +55059 -0.143096923828125 +55060 -0.47808837890625 +55061 -0.125396728515625 +55062 -0.253387451171875 +55063 -0.094390869140625 +55064 0.003692626953125 +55065 -0.05596923828125 +55066 0.2257080078125 +55067 -0.018768310546875 +55068 0.427154541015625 +55069 0.01824951171875 +55070 0.643218994140625 +55071 0.058502197265625 +55072 0.855926513671875 +55073 0.100433349609375 +55074 0.870361328125 +55075 0.13665771484375 +55076 0.870361328125 +55077 0.16094970703125 +55078 0.862762451171875 +55079 0.1739501953125 +55080 0.79669189453125 +55081 0.17523193359375 +55082 0.595794677734375 +55083 0.16363525390625 +55084 0.362152099609375 +55085 0.1427001953125 +55086 0.1270751953125 +55087 0.115997314453125 +55088 -0.086944580078125 +55089 0.0863037109375 +55090 -0.2784423828125 +55091 0.05413818359375 +55092 -0.484832763671875 +55093 0.01568603515625 +55094 -0.729583740234375 +55095 -0.030975341796875 +55096 -0.86688232421875 +55097 -0.07940673828125 +55098 -0.870391845703125 +55099 -0.121673583984375 +55100 -0.86859130859375 +55101 -0.156829833984375 +55102 -0.86279296875 +55103 -0.18438720703125 +55104 -0.817962646484375 +55105 -0.199859619140625 +55106 -0.6116943359375 +55107 -0.197662353515625 +55108 -0.3128662109375 +55109 -0.176910400390625 +55110 0.039398193359375 +55111 -0.141693115234375 +55112 0.422821044921875 +55113 -0.09454345703125 +55114 0.805145263671875 +55115 -0.03961181640625 +55116 0.870361328125 +55117 0.014617919921875 +55118 0.870361328125 +55119 0.061065673828125 +55120 0.860015869140625 +55121 0.0980224609375 +55122 0.727935791015625 +55123 0.124267578125 +55124 0.48114013671875 +55125 0.1387939453125 +55126 0.2059326171875 +55127 0.144195556640625 +55128 -0.06103515625 +55129 0.142974853515625 +55130 -0.29913330078125 +55131 0.136138916015625 +55132 -0.516204833984375 +55133 0.121856689453125 +55134 -0.7252197265625 +55135 0.098236083984375 +55136 -0.85980224609375 +55137 0.0682373046875 +55138 -0.870391845703125 +55139 0.03607177734375 +55140 -0.870391845703125 +55141 0.005401611328125 +55142 -0.858062744140625 +55143 -0.01763916015625 +55144 -0.673004150390625 +55145 -0.03228759765625 +55146 -0.42694091796875 +55147 -0.04461669921875 +55148 -0.2100830078125 +55149 -0.05963134765625 +55150 -0.0362548828125 +55151 -0.07672119140625 +55152 0.10943603515625 +55153 -0.092132568359375 +55154 0.23516845703125 +55155 -0.10321044921875 +55156 0.373687744140625 +55157 -0.10479736328125 +55158 0.517791748046875 +55159 -0.097015380859375 +55160 0.602783203125 +55161 -0.08734130859375 +55162 0.635711669921875 +55163 -0.075164794921875 +55164 0.655181884765625 +55165 -0.056549072265625 +55166 0.65948486328125 +55167 -0.0328369140625 +55168 0.651275634765625 +55169 -0.005157470703125 +55170 0.61846923828125 +55171 0.023284912109375 +55172 0.53753662109375 +55173 0.047760009765625 +55174 0.404144287109375 +55175 0.065887451171875 +55176 0.22186279296875 +55177 0.07623291015625 +55178 0.003997802734375 +55179 0.07867431640625 +55180 -0.22100830078125 +55181 0.0751953125 +55182 -0.42449951171875 +55183 0.068084716796875 +55184 -0.579833984375 +55185 0.059783935546875 +55186 -0.641876220703125 +55187 0.055328369140625 +55188 -0.6177978515625 +55189 0.053924560546875 +55190 -0.575531005859375 +55191 0.0478515625 +55192 -0.526336669921875 +55193 0.03656005859375 +55194 -0.42645263671875 +55195 0.026397705078125 +55196 -0.2581787109375 +55197 0.02081298828125 +55198 -0.068695068359375 +55199 0.01568603515625 +55200 0.09222412109375 +55201 0.006622314453125 +55202 0.232147216796875 +55203 -0.003875732421875 +55204 0.3509521484375 +55205 -0.014373779296875 +55206 0.410064697265625 +55207 -0.0281982421875 +55208 0.372955322265625 +55209 -0.0487060546875 +55210 0.2554931640625 +55211 -0.073272705078125 +55212 0.10711669921875 +55213 -0.095550537109375 +55214 -0.052886962890625 +55215 -0.11309814453125 +55216 -0.186279296875 +55217 -0.12164306640625 +55218 -0.23291015625 +55219 -0.114532470703125 +55220 -0.209442138671875 +55221 -0.0946044921875 +55222 -0.174163818359375 +55223 -0.0699462890625 +55224 -0.126739501953125 +55225 -0.041748046875 +55226 -0.048126220703125 +55227 -0.009002685546875 +55228 0.0426025390625 +55229 0.024688720703125 +55230 0.10748291015625 +55231 0.053558349609375 +55232 0.1409912109375 +55233 0.075836181640625 +55234 0.19708251953125 +55235 0.097076416015625 +55236 0.273651123046875 +55237 0.1163330078125 +55238 0.31768798828125 +55239 0.126861572265625 +55240 0.341094970703125 +55241 0.12994384765625 +55242 0.368011474609375 +55243 0.128570556640625 +55244 0.37249755859375 +55245 0.120025634765625 +55246 0.30072021484375 +55247 0.098480224609375 +55248 0.1517333984375 +55249 0.06463623046875 +55250 -0.01470947265625 +55251 0.026641845703125 +55252 -0.1883544921875 +55253 -0.013214111328125 +55254 -0.372711181640625 +55255 -0.054290771484375 +55256 -0.51397705078125 +55257 -0.089080810546875 +55258 -0.57177734375 +55259 -0.11181640625 +55260 -0.53948974609375 +55261 -0.120880126953125 +55262 -0.43511962890625 +55263 -0.11785888671875 +55264 -0.2962646484375 +55265 -0.106842041015625 +55266 -0.161102294921875 +55267 -0.092193603515625 +55268 -0.0435791015625 +55269 -0.07562255859375 +55270 0.060394287109375 +55271 -0.056884765625 +55272 0.13665771484375 +55273 -0.03814697265625 +55274 0.170135498046875 +55275 -0.021820068359375 +55276 0.16552734375 +55277 -0.008056640625 +55278 0.15728759765625 +55279 0.006378173828125 +55280 0.150787353515625 +55281 0.021270751953125 +55282 0.12200927734375 +55283 0.03289794921875 +55284 0.080108642578125 +55285 0.04150390625 +55286 0.05126953125 +55287 0.049560546875 +55288 0.062896728515625 +55289 0.059783935546875 +55290 0.09271240234375 +55291 0.069091796875 +55292 0.092987060546875 +55293 0.071533203125 +55294 0.07855224609375 +55295 0.06884765625 +55296 0.06427001953125 +55297 0.0631103515625 +55298 0.0347900390625 +55299 0.052764892578125 +55300 -0.01171875 +55301 0.037933349609375 +55302 -0.056060791015625 +55303 0.02130126953125 +55304 -0.055511474609375 +55305 0.007965087890625 +55306 -0.010467529296875 +55307 -0.001251220703125 +55308 0.02508544921875 +55309 -0.01092529296875 +55310 0.025665283203125 +55311 -0.02288818359375 +55312 0.017333984375 +55313 -0.033905029296875 +55314 0.00189208984375 +55315 -0.043304443359375 +55316 -0.03173828125 +55317 -0.05181884765625 +55318 -0.071502685546875 +55319 -0.058074951171875 +55320 -0.13543701171875 +55321 -0.0638427734375 +55322 -0.219970703125 +55323 -0.06890869140625 +55324 -0.300506591796875 +55325 -0.071014404296875 +55326 -0.376312255859375 +55327 -0.070526123046875 +55328 -0.416107177734375 +55329 -0.064849853515625 +55330 -0.371124267578125 +55331 -0.049652099609375 +55332 -0.242279052734375 +55333 -0.025665283203125 +55334 -0.069732666015625 +55335 0.00244140625 +55336 0.125640869140625 +55337 0.031982421875 +55338 0.31268310546875 +55339 0.059356689453125 +55340 0.45501708984375 +55341 0.0804443359375 +55342 0.554779052734375 +55343 0.09515380859375 +55344 0.61065673828125 +55345 0.1031494140625 +55346 0.610931396484375 +55347 0.10321044921875 +55348 0.531463623046875 +55349 0.093017578125 +55350 0.3883056640625 +55351 0.0743408203125 +55352 0.23468017578125 +55353 0.05279541015625 +55354 0.095245361328125 +55355 0.031280517578125 +55356 -0.00396728515625 +55357 0.012847900390625 +55358 -0.04852294921875 +55359 -0.000579833984375 +55360 -0.055145263671875 +55361 -0.01019287109375 +55362 -0.0758056640625 +55363 -0.020660400390625 +55364 -0.138702392578125 +55365 -0.03436279296875 +55366 -0.209197998046875 +55367 -0.047454833984375 +55368 -0.289031982421875 +55369 -0.059844970703125 +55370 -0.37884521484375 +55371 -0.0714111328125 +55372 -0.456329345703125 +55373 -0.079833984375 +55374 -0.51641845703125 +55375 -0.084625244140625 +55376 -0.519287109375 +55377 -0.0819091796875 +55378 -0.458251953125 +55379 -0.07122802734375 +55380 -0.384796142578125 +55381 -0.05804443359375 +55382 -0.323699951171875 +55383 -0.045166015625 +55384 -0.269287109375 +55385 -0.032379150390625 +55386 -0.1951904296875 +55387 -0.017486572265625 +55388 -0.100006103515625 +55389 -0.00079345703125 +55390 -0.01055908203125 +55391 0.014617919921875 +55392 0.1033935546875 +55393 0.03143310546875 +55394 0.24908447265625 +55395 0.05010986328125 +55396 0.373199462890625 +55397 0.06512451171875 +55398 0.45806884765625 +55399 0.074615478515625 +55400 0.511474609375 +55401 0.079345703125 +55402 0.565399169921875 +55403 0.08258056640625 +55404 0.61138916015625 +55405 0.083648681640625 +55406 0.5897216796875 +55407 0.07684326171875 +55408 0.4906005859375 +55409 0.06146240234375 +55410 0.33148193359375 +55411 0.03955078125 +55412 0.147796630859375 +55413 0.0150146484375 +55414 -0.01873779296875 +55415 -0.00762939453125 +55416 -0.140289306640625 +55417 -0.0252685546875 +55418 -0.191986083984375 +55419 -0.035125732421875 +55420 -0.184295654296875 +55421 -0.03802490234375 +55422 -0.161834716796875 +55423 -0.03826904296875 +55424 -0.166595458984375 +55425 -0.0399169921875 +55426 -0.19390869140625 +55427 -0.04248046875 +55428 -0.22442626953125 +55429 -0.0440673828125 +55430 -0.279754638671875 +55431 -0.046966552734375 +55432 -0.3389892578125 +55433 -0.04925537109375 +55434 -0.3543701171875 +55435 -0.04638671875 +55436 -0.348175048828125 +55437 -0.040863037109375 +55438 -0.32598876953125 +55439 -0.033538818359375 +55440 -0.2581787109375 +55441 -0.021728515625 +55442 -0.139801025390625 +55443 -0.00518798828125 +55444 0.014617919921875 +55445 0.01434326171875 +55446 0.144378662109375 +55447 0.03057861328125 +55448 0.221038818359375 +55449 0.04052734375 +55450 0.27069091796875 +55451 0.04669189453125 +55452 0.294036865234375 +55453 0.049102783203125 +55454 0.311767578125 +55455 0.04986572265625 +55456 0.339141845703125 +55457 0.05059814453125 +55458 0.360260009765625 +55459 0.0496826171875 +55460 0.360504150390625 +55461 0.045867919921875 +55462 0.308380126953125 +55463 0.036651611328125 +55464 0.18170166015625 +55465 0.020416259765625 +55466 0.0047607421875 +55467 -0.000335693359375 +55468 -0.17559814453125 +55469 -0.021148681640625 +55470 -0.3143310546875 +55471 -0.037811279296875 +55472 -0.36785888671875 +55473 -0.0462646484375 +55474 -0.36248779296875 +55475 -0.04864501953125 +55476 -0.343536376953125 +55477 -0.04876708984375 +55478 -0.3018798828125 +55479 -0.0457763671875 +55480 -0.231414794921875 +55481 -0.039154052734375 +55482 -0.117645263671875 +55483 -0.027679443359375 +55484 0.007049560546875 +55485 -0.01434326171875 +55486 0.087982177734375 +55487 -0.00408935546875 +55488 0.13946533203125 +55489 0.004119873046875 +55490 0.17425537109375 +55491 0.01123046875 +55492 0.188201904296875 +55493 0.0166015625 +55494 0.171234130859375 +55495 0.019134521484375 +55496 0.118438720703125 +55497 0.0181884765625 +55498 0.05706787109375 +55499 0.0159912109375 +55500 -0.010711669921875 +55501 0.0125732421875 +55502 -0.0914306640625 +55503 0.0072021484375 +55504 -0.162322998046875 +55505 0.0018310546875 +55506 -0.194549560546875 +55507 -0.001007080078125 +55508 -0.1492919921875 +55509 0.002105712890625 +55510 -0.02166748046875 +55511 0.01165771484375 +55512 0.124053955078125 +55513 0.0220947265625 +55514 0.211151123046875 +55515 0.02679443359375 +55516 0.240447998046875 +55517 0.0260009765625 +55518 0.242218017578125 +55519 0.0225830078125 +55520 0.2257080078125 +55521 0.017578125 +55522 0.194366455078125 +55523 0.011505126953125 +55524 0.115509033203125 +55525 0.00164794921875 +55526 0.0128173828125 +55527 -0.009674072265625 +55528 -0.053802490234375 +55529 -0.017120361328125 +55530 -0.110626220703125 +55531 -0.02294921875 +55532 -0.199493408203125 +55533 -0.03082275390625 +55534 -0.29437255859375 +55535 -0.038482666015625 +55536 -0.33221435546875 +55537 -0.0404052734375 +55538 -0.27972412109375 +55539 -0.033782958984375 +55540 -0.185333251953125 +55541 -0.02301025390625 +55542 -0.128204345703125 +55543 -0.01519775390625 +55544 -0.115692138671875 +55545 -0.011138916015625 +55546 -0.116455078125 +55547 -0.00823974609375 +55548 -0.105926513671875 +55549 -0.0045166015625 +55550 -0.053955078125 +55551 0.00250244140625 +55552 0.048797607421875 +55553 0.0133056640625 +55554 0.157318115234375 +55555 0.024169921875 +55556 0.212005615234375 +55557 0.0308837890625 +55558 0.218475341796875 +55559 0.033538818359375 +55560 0.23724365234375 +55561 0.035430908203125 +55562 0.30535888671875 +55563 0.03863525390625 +55564 0.38128662109375 +55565 0.0408935546875 +55566 0.404449462890625 +55567 0.039031982421875 +55568 0.3944091796875 +55569 0.034393310546875 +55570 0.3885498046875 +55571 0.02935791015625 +55572 0.362640380859375 +55573 0.022857666015625 +55574 0.27362060546875 +55575 0.012786865234375 +55576 0.11712646484375 +55577 -0.000762939453125 +55578 -0.054901123046875 +55579 -0.014617919921875 +55580 -0.19085693359375 +55581 -0.025665283203125 +55582 -0.28570556640625 +55583 -0.033447265625 +55584 -0.339263916015625 +55585 -0.037841796875 +55586 -0.3775634765625 +55587 -0.040283203125 +55588 -0.445709228515625 +55589 -0.043304443359375 +55590 -0.535064697265625 +55591 -0.046478271484375 +55592 -0.629058837890625 +55593 -0.04901123046875 +55594 -0.697601318359375 +55595 -0.04937744140625 +55596 -0.70391845703125 +55597 -0.045745849609375 +55598 -0.6424560546875 +55599 -0.038055419921875 +55600 -0.491241455078125 +55601 -0.025299072265625 +55602 -0.265716552734375 +55603 -0.00860595703125 +55604 -0.023712158203125 +55605 0.008544921875 +55606 0.201751708984375 +55607 0.02410888671875 +55608 0.375823974609375 +55609 0.0360107421875 +55610 0.485076904296875 +55611 0.04339599609375 +55612 0.56884765625 +55613 0.04840087890625 +55614 0.634765625 +55615 0.051483154296875 +55616 0.63763427734375 +55617 0.050201416015625 +55618 0.5660400390625 +55619 0.04400634765625 +55620 0.4720458984375 +55621 0.03594970703125 +55622 0.40692138671875 +55623 0.029083251953125 +55624 0.3778076171875 +55625 0.02398681640625 +55626 0.376953125 +55627 0.020416259765625 +55628 0.371978759765625 +55629 0.016754150390625 +55630 0.313140869140625 +55631 0.0103759765625 +55632 0.184417724609375 +55633 0.00054931640625 +55634 0.011199951171875 +55635 -0.011138916015625 +55636 -0.171051025390625 +55637 -0.0225830078125 +55638 -0.33740234375 +55639 -0.0323486328125 +55640 -0.47198486328125 +55641 -0.03955078125 +55642 -0.560394287109375 +55643 -0.043426513671875 +55644 -0.58056640625 +55645 -0.042816162109375 +55646 -0.54754638671875 +55647 -0.038665771484375 +55648 -0.508575439453125 +55649 -0.033843994140625 +55650 -0.459503173828125 +55651 -0.028228759765625 +55652 -0.394378662109375 +55653 -0.021636962890625 +55654 -0.35260009765625 +55655 -0.016387939453125 +55656 -0.31170654296875 +55657 -0.01141357421875 +55658 -0.197418212890625 +55659 -0.002685546875 +55660 -0.007965087890625 +55661 0.009735107421875 +55662 0.207489013671875 +55663 0.022979736328125 +55664 0.409210205078125 +55665 0.0347900390625 +55666 0.57208251953125 +55667 0.043731689453125 +55668 0.66595458984375 +55669 0.04815673828125 +55670 0.65875244140625 +55671 0.046356201171875 +55672 0.56744384765625 +55673 0.03936767578125 +55674 0.431396484375 +55675 0.029510498046875 +55676 0.29443359375 +55677 0.019378662109375 +55678 0.182464599609375 +55679 0.01055908203125 +55680 0.06365966796875 +55681 0.00140380859375 +55682 -0.075958251953125 +55683 -0.008697509765625 +55684 -0.189422607421875 +55685 -0.016998291015625 +55686 -0.271942138671875 +55687 -0.023101806640625 +55688 -0.342529296875 +55689 -0.02801513671875 +55690 -0.364166259765625 +55691 -0.0296630859375 +55692 -0.327239990234375 +55693 -0.027496337890625 +55694 -0.2769775390625 +55695 -0.024078369140625 +55696 -0.253692626953125 +55697 -0.021697998046875 +55698 -0.24365234375 +55699 -0.0196533203125 +55700 -0.1983642578125 +55701 -0.01531982421875 +55702 -0.116241455078125 +55703 -0.00872802734375 +55704 -0.036834716796875 +55705 -0.002197265625 +55706 0.034881591796875 +55707 0.00384521484375 +55708 0.09124755859375 +55709 0.008880615234375 +55710 0.10888671875 +55711 0.011474609375 +55712 0.125518798828125 +55713 0.013671875 +55714 0.15771484375 +55715 0.016357421875 +55716 0.17828369140625 +55717 0.0179443359375 +55718 0.17108154296875 +55719 0.01751708984375 +55720 0.129974365234375 +55721 0.014739990234375 +55722 0.082427978515625 +55723 0.011199951171875 +55724 0.027679443359375 +55725 0.0069580078125 +55726 -0.065643310546875 +55727 0.000335693359375 +55728 -0.15936279296875 +55729 -0.006439208984375 +55730 -0.21307373046875 +55731 -0.01104736328125 +55732 -0.234649658203125 +55733 -0.013824462890625 +55734 -0.2001953125 +55735 -0.01336669921875 +55736 -0.119171142578125 +55737 -0.010101318359375 +55738 -0.024749755859375 +55739 -0.005859375 +55740 0.085784912109375 +55741 -0.000396728515625 +55742 0.178131103515625 +55743 0.004302978515625 +55744 0.215576171875 +55745 0.0062255859375 +55746 0.211456298828125 +55747 0.006134033203125 +55748 0.17523193359375 +55749 0.00457763671875 +55750 0.128753662109375 +55751 0.002716064453125 +55752 0.1019287109375 +55753 0.002197265625 +55754 0.0743408203125 +55755 0.001800537109375 +55756 0.04327392578125 +55757 0.001312255859375 +55758 0.038177490234375 +55759 0.0023193359375 +55760 0.076263427734375 +55761 0.005706787109375 +55762 0.14105224609375 +55763 0.01043701171875 +55764 0.186431884765625 +55765 0.013885498046875 +55766 0.188812255859375 +55767 0.01470947265625 +55768 0.1390380859375 +55769 0.012359619140625 +55770 0.041778564453125 +55771 0.007080078125 +55772 -0.079437255859375 +55773 0.000213623046875 +55774 -0.219390869140625 +55775 -0.0079345703125 +55776 -0.367828369140625 +55777 -0.0167236328125 +55778 -0.494873046875 +55779 -0.02447509765625 +55780 -0.556243896484375 +55781 -0.028656005859375 +55782 -0.508697509765625 +55783 -0.026824951171875 +55784 -0.3756103515625 +55785 -0.020233154296875 +55786 -0.218902587890625 +55787 -0.012298583984375 +55788 -0.063751220703125 +55789 -0.004425048828125 +55790 0.091552734375 +55791 0.00347900390625 +55792 0.23602294921875 +55793 0.0108642578125 +55794 0.342987060546875 +55795 0.01629638671875 +55796 0.39520263671875 +55797 0.01885986328125 +55798 0.389373779296875 +55799 0.01837158203125 +55800 0.324249267578125 +55801 0.0147705078125 +55802 0.224090576171875 +55803 0.0093994140625 +55804 0.124267578125 +55805 0.004241943359375 +55806 0.037078857421875 +55807 -6.103515625e-05 +55808 -0.010101318359375 +55809 -0.00244140625 +55810 -0.019439697265625 +55811 -0.002838134765625 +55812 -0.022796630859375 +55813 -0.002410888671875 +55814 -0.001556396484375 +55815 -0.0009765625 +55816 0.056304931640625 +55817 0.001495361328125 +55818 0.106719970703125 +55819 0.0037841796875 +55820 0.096893310546875 +55821 0.004425048828125 +55822 0.042694091796875 +55823 0.003753662109375 +55824 -0.018035888671875 +55825 0.00262451171875 +55826 -0.07586669921875 +55827 0.001251220703125 +55828 -0.11944580078125 +55829 -3.0517578125e-05 +55830 -0.15972900390625 +55831 -0.001434326171875 +55832 -0.202606201171875 +55833 -0.003082275390625 +55834 -0.24859619140625 +55835 -0.0048828125 +55836 -0.30517578125 +55837 -0.006988525390625 +55838 -0.36212158203125 +55839 -0.00909423828125 +55840 -0.39141845703125 +55841 -0.010467529296875 +55842 -0.35528564453125 +55843 -0.01019287109375 +55844 -0.249969482421875 +55845 -0.00811767578125 +55846 -0.092864990234375 +55847 -0.004638671875 +55848 0.08905029296875 +55849 -0.000396728515625 +55850 0.2352294921875 +55851 0.00311279296875 +55852 0.318817138671875 +55853 0.0052490234375 +55854 0.358642578125 +55855 0.0064697265625 +55856 0.347747802734375 +55857 0.006561279296875 +55858 0.28564453125 +55859 0.005523681640625 +55860 0.223175048828125 +55861 0.004547119140625 +55862 0.196746826171875 +55863 0.00445556640625 +55864 0.179840087890625 +55865 0.004608154296875 +55866 0.155548095703125 +55867 0.00457763671875 +55868 0.151214599609375 +55869 0.00494384765625 +55870 0.156951904296875 +55871 0.005462646484375 +55872 0.13177490234375 +55873 0.005126953125 +55874 0.100799560546875 +55875 0.0045166015625 +55876 0.087127685546875 +55877 0.00421142578125 +55878 0.05487060546875 +55879 0.00335693359375 +55880 -0.009002685546875 +55881 0.001617431640625 +55882 -0.10400390625 +55883 -0.00091552734375 +55884 -0.229400634765625 +55885 -0.004241943359375 +55886 -0.35552978515625 +55887 -0.00762939453125 +55888 -0.441925048828125 +55889 -0.01007080078125 +55890 -0.473846435546875 +55891 -0.01116943359375 +55892 -0.464813232421875 +55893 -0.011260986328125 +55894 -0.419097900390625 +55895 -0.01043701171875 +55896 -0.334320068359375 +55897 -0.008636474609375 +55898 -0.227935791015625 +55899 -0.0062255859375 +55900 -0.12347412109375 +55901 -0.0037841796875 +55902 -0.02764892578125 +55903 -0.00146484375 +55904 0.077667236328125 +55905 0.001129150390625 +55906 0.2132568359375 +55907 0.004486083984375 +55908 0.38885498046875 +55909 0.00885009765625 +55910 0.582794189453125 +55911 0.013671875 +55912 0.734039306640625 +55913 0.017486572265625 +55914 0.800140380859375 +55915 0.01922607421875 +55916 0.7783203125 +55917 0.018829345703125 +55918 0.6651611328125 +55919 0.0162353515625 +55920 0.45965576171875 +55921 0.01141357421875 +55922 0.199188232421875 +55923 0.005279541015625 +55924 -0.050689697265625 +55925 -0.000579833984375 +55926 -0.23297119140625 +55927 -0.00482177734375 +55928 -0.33013916015625 +55929 -0.007049560546875 +55930 -0.368408203125 +55931 -0.00787353515625 +55932 -0.378936767578125 +55933 -0.008056640625 +55934 -0.376983642578125 +55935 -0.00799560546875 +55936 -0.37969970703125 +55937 -0.008087158203125 +55938 -0.391510009765625 +55939 -0.0084228515625 +55940 -0.385345458984375 +55941 -0.00836181640625 +55942 -0.3419189453125 +55943 -0.007415771484375 +55944 -0.28289794921875 +55945 -0.006103515625 +55946 -0.251617431640625 +55947 -0.00543212890625 +55948 -0.266143798828125 +55949 -0.005859375 +55950 -0.273345947265625 +55951 -0.006103515625 +55952 -0.216796875 +55953 -0.00482177734375 +55954 -0.128265380859375 +55955 -0.002777099609375 +55956 -0.068145751953125 +55957 -0.001373291015625 +55958 -0.0430908203125 +55959 -0.000762939453125 +55960 -0.024444580078125 +55961 -0.000274658203125 +55962 0.020721435546875 +55963 0.000823974609375 +55964 0.124481201171875 +55965 0.0032958984375 +55966 0.25787353515625 +55967 0.0064697265625 +55968 0.379119873046875 +55969 0.009307861328125 +55970 0.47991943359375 +55971 0.01165771484375 +55972 0.5281982421875 +55973 0.01275634765625 +55974 0.511138916015625 +55975 0.01226806640625 +55976 0.456207275390625 +55977 0.010894775390625 +55978 0.407470703125 +55979 0.009674072265625 +55980 0.383758544921875 +55981 0.009063720703125 +55982 0.35687255859375 +55983 0.008331298828125 +55984 0.31182861328125 +55985 0.007171630859375 +55986 0.250885009765625 +55987 0.005615234375 +55988 0.1654052734375 +55989 0.003509521484375 +55990 0.035247802734375 +55991 0.0003662109375 +55992 -0.142059326171875 +55993 -0.00384521484375 +55994 -0.33563232421875 +55995 -0.008392333984375 +55996 -0.5345458984375 +55997 -0.01300048828125 +55998 -0.72186279296875 +55999 -0.017303466796875 +56000 -0.836669921875 +56001 -0.019805908203125 +56002 -0.8326416015625 +56003 -0.019439697265625 +56004 -0.7296142578125 +56005 -0.016693115234375 +56006 -0.582550048828125 +56007 -0.012939453125 +56008 -0.440093994140625 +56009 -0.009368896484375 +56010 -0.324310302734375 +56011 -0.006500244140625 +56012 -0.20147705078125 +56013 -0.00347900390625 +56014 -0.044647216796875 +56015 0.00030517578125 +56016 0.103973388671875 +56017 0.003814697265625 +56018 0.202392578125 +56019 0.00604248046875 +56020 0.264495849609375 +56021 0.007354736328125 +56022 0.338897705078125 +56023 0.0089111328125 +56024 0.443817138671875 +56025 0.011138916015625 +56026 0.545074462890625 +56027 0.01324462890625 +56028 0.6173095703125 +56029 0.0146484375 +56030 0.6524658203125 +56031 0.01519775390625 +56032 0.66339111328125 +56033 0.015167236328125 +56034 0.6561279296875 +56035 0.0147705078125 +56036 0.606781005859375 +56037 0.013397216796875 +56038 0.501190185546875 +56039 0.010711669921875 +56040 0.352783203125 +56041 0.007080078125 +56042 0.176544189453125 +56043 0.002838134765625 +56044 -0.034820556640625 +56045 -0.002105712890625 +56046 -0.258209228515625 +56047 -0.0072021484375 +56048 -0.44244384765625 +56049 -0.011260986328125 +56050 -0.5753173828125 +56051 -0.0140380859375 +56052 -0.65203857421875 +56053 -0.01544189453125 +56054 -0.641632080078125 +56055 -0.014739990234375 +56056 -0.562164306640625 +56057 -0.012420654296875 +56058 -0.458038330078125 +56059 -0.00958251953125 +56060 -0.350555419921875 +56061 -0.0067138671875 +56062 -0.260528564453125 +56063 -0.00433349609375 +56064 -0.192108154296875 +56065 -0.002471923828125 +56066 -0.141937255859375 +56067 -0.00103759765625 +56068 -0.1021728515625 +56069 3.0517578125e-05 +56070 -0.062896728515625 +56071 0.000885009765625 +56072 -0.011932373046875 +56073 0.001708984375 +56074 0.062835693359375 +56075 0.002655029296875 +56076 0.148712158203125 +56077 0.003631591796875 +56078 0.241729736328125 +56079 0.00457763671875 +56080 0.34912109375 +56081 0.005584716796875 +56082 0.457305908203125 +56083 0.00653076171875 +56084 0.54388427734375 +56085 0.007232666015625 +56086 0.5728759765625 +56087 0.007415771484375 +56088 0.506591796875 +56089 0.006744384765625 +56090 0.351226806640625 +56091 0.0052490234375 +56092 0.146514892578125 +56093 0.003265380859375 +56094 -0.05523681640625 +56095 0.001220703125 +56096 -0.21624755859375 +56097 -0.00054931640625 +56098 -0.334930419921875 +56099 -0.001983642578125 +56100 -0.402984619140625 +56101 -0.00299072265625 +56102 -0.4412841796875 +56103 -0.00372314453125 +56104 -0.49578857421875 +56105 -0.0045166015625 +56106 -0.5601806640625 +56107 -0.005340576171875 +56108 -0.600738525390625 +56109 -0.00592041015625 +56110 -0.584228515625 +56111 -0.005950927734375 +56112 -0.47930908203125 +56113 -0.00518798828125 +56114 -0.27935791015625 +56115 -0.003570556640625 +56116 -0.0089111328125 +56117 -0.001312255859375 +56118 0.268798828125 +56119 0.00103759765625 +56120 0.482818603515625 +56121 0.002899169921875 +56122 0.60369873046875 +56123 0.004058837890625 +56124 0.650421142578125 +56125 0.004669189453125 +56126 0.66400146484375 +56127 0.005035400390625 +56128 0.6414794921875 +56129 0.005126953125 +56130 0.572540283203125 +56131 0.004852294921875 +56132 0.498138427734375 +56133 0.0045166015625 +56134 0.439453125 +56135 0.0042724609375 +56136 0.375518798828125 +56137 0.003936767578125 +56138 0.274505615234375 +56139 0.00323486328125 +56140 0.1087646484375 +56141 0.001953125 +56142 -0.099395751953125 +56143 0.000274658203125 +56144 -0.3182373046875 +56145 -0.00152587890625 +56146 -0.5489501953125 +56147 -0.00341796875 +56148 -0.7738037109375 +56149 -0.0052490234375 +56150 -0.86383056640625 +56151 -0.006622314453125 +56152 -0.870391845703125 +56153 -0.00726318359375 +56154 -0.86895751953125 +56155 -0.00732421875 +56156 -0.861053466796875 +56157 -0.006927490234375 +56158 -0.765869140625 +56159 -0.00592041015625 +56160 -0.5301513671875 +56161 -0.00421142578125 +56162 -0.214691162109375 +56163 -0.001861572265625 +56164 0.137359619140625 +56165 0.00079345703125 +56166 0.474822998046875 +56167 0.00335693359375 +56168 0.76239013671875 +56169 0.00555419921875 +56170 0.867462158203125 +56171 0.007171630859375 +56172 0.870361328125 +56173 0.008209228515625 +56174 0.86480712890625 +56175 0.008575439453125 +56176 0.831817626953125 +56177 0.00830078125 +56178 0.677581787109375 +56179 0.007598876953125 +56180 0.495880126953125 +56181 0.006561279296875 +56182 0.30767822265625 +56183 0.00531005859375 +56184 0.116180419921875 +56185 0.00390625 +56186 -0.110748291015625 +56187 0.0020751953125 +56188 -0.381805419921875 +56189 -0.000244140625 +56190 -0.6572265625 +56191 -0.002716064453125 +56192 -0.857421875 +56193 -0.004852294921875 +56194 -0.870391845703125 +56195 -0.00634765625 +56196 -0.870391845703125 +56197 -0.007171630859375 +56198 -0.86444091796875 +56199 -0.007537841796875 +56200 -0.85723876953125 +56201 -0.00775146484375 +56202 -0.790008544921875 +56203 -0.0076904296875 +56204 -0.62847900390625 +56205 -0.0069580078125 +56206 -0.3956298828125 +56207 -0.005523681640625 +56208 -0.126708984375 +56209 -0.003631591796875 +56210 0.150115966796875 +56211 -0.001495361328125 +56212 0.424041748046875 +56213 0.000762939453125 +56214 0.670623779296875 +56215 0.0029296875 +56216 0.854522705078125 +56217 0.00469970703125 +56218 0.866485595703125 +56219 0.005950927734375 +56220 0.86920166015625 +56221 0.006622314453125 +56222 0.8653564453125 +56223 0.00689697265625 +56224 0.857147216796875 +56225 0.006866455078125 +56226 0.766845703125 +56227 0.006561279296875 +56228 0.628509521484375 +56229 0.0059814453125 +56230 0.462127685546875 +56231 0.005126953125 +56232 0.297210693359375 +56233 0.004180908203125 +56234 0.14862060546875 +56235 0.00323486328125 +56236 -0.00537109375 +56237 0.002105712890625 +56238 -0.15753173828125 +56239 0.0008544921875 +56240 -0.31304931640625 +56241 -0.000518798828125 +56242 -0.48876953125 +56243 -0.002105712890625 +56244 -0.6416015625 +56245 -0.003570556640625 +56246 -0.751373291015625 +56247 -0.004730224609375 +56248 -0.84619140625 +56249 -0.00579833984375 +56250 -0.861297607421875 +56251 -0.00665283203125 +56252 -0.863250732421875 +56253 -0.007080078125 +56254 -0.856597900390625 +56255 -0.006805419921875 +56256 -0.7498779296875 +56257 -0.0059814453125 +56258 -0.624542236328125 +56259 -0.005096435546875 +56260 -0.47808837890625 +56261 -0.003997802734375 +56262 -0.253387451171875 +56263 -0.002227783203125 +56264 0.003692626953125 +56265 -0.000152587890625 +56266 0.2257080078125 +56267 0.00164794921875 +56268 0.427154541015625 +56269 0.003265380859375 +56270 0.643218994140625 +56271 0.004974365234375 +56272 0.855926513671875 +56273 0.0067138671875 +56274 0.870361328125 +56275 0.008087158203125 +56276 0.870361328125 +56277 0.00872802734375 +56278 0.862762451171875 +56279 0.008758544921875 +56280 0.79669189453125 +56281 0.0081787109375 +56282 0.595794677734375 +56283 0.0069580078125 +56284 0.362152099609375 +56285 0.005340576171875 +56286 0.1270751953125 +56287 0.003570556640625 +56288 -0.086944580078125 +56289 0.0018310546875 +56290 -0.2784423828125 +56291 0.0001220703125 +56292 -0.484832763671875 +56293 -0.00177001953125 +56294 -0.729583740234375 +56295 -0.004058837890625 +56296 -0.86688232421875 +56297 -0.006317138671875 +56298 -0.870391845703125 +56299 -0.00811767578125 +56300 -0.86859130859375 +56301 -0.009429931640625 +56302 -0.86279296875 +56303 -0.010284423828125 +56304 -0.817962646484375 +56305 -0.01043701171875 +56306 -0.6116943359375 +56307 -0.00958251953125 +56308 -0.3128662109375 +56309 -0.007659912109375 +56310 0.039398193359375 +56311 -0.004974365234375 +56312 0.422821044921875 +56313 -0.001739501953125 +56314 0.805145263671875 +56315 0.001708984375 +56316 0.870361328125 +56317 0.0048828125 +56318 0.870361328125 +56319 0.00732421875 +56320 0.860015869140625 +56321 0.0091552734375 +56322 0.727935791015625 +56323 0.0098876953125 +56324 0.48114013671875 +56325 0.0091552734375 +56326 0.2059326171875 +56327 0.00787353515625 +56328 -0.06103515625 +56329 0.006805419921875 +56330 -0.29913330078125 +56331 0.006103515625 +56332 -0.516204833984375 +56333 0.00494384765625 +56334 -0.7252197265625 +56335 0.00238037109375 +56336 -0.85980224609375 +56337 -0.00091552734375 +56338 -0.870391845703125 +56339 -0.003936767578125 +56340 -0.870391845703125 +56341 -0.005889892578125 +56342 -0.858062744140625 +56343 -0.005218505859375 +56344 -0.673004150390625 +56345 -0.0020751953125 +56346 -0.42694091796875 +56347 0.00103759765625 +56348 -0.2100830078125 +56349 0.00213623046875 +56350 -0.0362548828125 +56351 0.0010986328125 +56352 0.10943603515625 +56353 -0.0009765625 +56354 0.23516845703125 +56355 -0.003265380859375 +56356 0.373687744140625 +56357 -0.00408935546875 +56358 0.517791748046875 +56359 -0.00341796875 +56360 0.602783203125 +56361 -0.003631591796875 +56362 0.635711669921875 +56363 -0.004302978515625 +56364 0.655181884765625 +56365 -0.003814697265625 +56366 0.65948486328125 +56367 -0.002227783203125 +56368 0.651275634765625 +56369 0.000396728515625 +56370 0.61846923828125 +56371 0.0032958984375 +56372 0.53753662109375 +56373 0.00531005859375 +56374 0.404144287109375 +56375 0.005950927734375 +56376 0.22186279296875 +56377 0.005035400390625 +56378 0.003997802734375 +56379 0.00274658203125 +56380 -0.22100830078125 +56381 -9.1552734375e-05 +56382 -0.42449951171875 +56383 -0.002655029296875 +56384 -0.579833984375 +56385 -0.00421142578125 +56386 -0.641876220703125 +56387 -0.003173828125 +56388 -0.6177978515625 +56389 0.0 +56390 -0.575531005859375 +56391 0.00250244140625 +56392 -0.526336669921875 +56393 0.003875732421875 +56394 -0.42645263671875 +56395 0.00592041015625 +56396 -0.2581787109375 +56397 0.009490966796875 +56398 -0.068695068359375 +56399 0.01287841796875 +56400 0.09222412109375 +56401 0.014404296875 +56402 0.232147216796875 +56403 0.014617919921875 +56404 0.3509521484375 +56405 0.01385498046875 +56406 0.410064697265625 +56407 0.0108642578125 +56408 0.372955322265625 +56409 0.004486083984375 +56410 0.2554931640625 +56411 -0.004364013671875 +56412 0.10711669921875 +56413 -0.01348876953125 +56414 -0.052886962890625 +56415 -0.021942138671875 +56416 -0.186279296875 +56417 -0.028167724609375 +56418 -0.23291015625 +56419 -0.02972412109375 +56420 -0.209442138671875 +56421 -0.027374267578125 +56422 -0.174163818359375 +56423 -0.023529052734375 +56424 -0.126739501953125 +56425 -0.018341064453125 +56426 -0.048126220703125 +56427 -0.011260986328125 +56428 0.0426025390625 +56429 -0.003265380859375 +56430 0.10748291015625 +56431 0.00384521484375 +56432 0.1409912109375 +56433 0.00958251953125 +56434 0.19708251953125 +56435 0.015838623046875 +56436 0.273651123046875 +56437 0.0223388671875 +56438 0.31768798828125 +56439 0.026824951171875 +56440 0.341094970703125 +56441 0.029632568359375 +56442 0.368011474609375 +56443 0.03167724609375 +56444 0.37249755859375 +56445 0.031890869140625 +56446 0.30072021484375 +56447 0.02813720703125 +56448 0.1517333984375 +56449 0.020477294921875 +56450 -0.01470947265625 +56451 0.011383056640625 +56452 -0.1883544921875 +56453 0.001434326171875 +56454 -0.372711181640625 +56455 -0.009307861328125 +56456 -0.51397705078125 +56457 -0.018524169921875 +56458 -0.57177734375 +56459 -0.024383544921875 +56460 -0.53948974609375 +56461 -0.02642822265625 +56462 -0.43511962890625 +56463 -0.02520751953125 +56464 -0.2962646484375 +56465 -0.022064208984375 +56466 -0.161102294921875 +56467 -0.018402099609375 +56468 -0.0435791015625 +56469 -0.01470947265625 +56470 0.060394287109375 +56471 -0.01080322265625 +56472 0.13665771484375 +56473 -0.00726318359375 +56474 0.170135498046875 +56475 -0.004730224609375 +56476 0.16552734375 +56477 -0.00311279296875 +56478 0.15728759765625 +56479 -0.001129150390625 +56480 0.150787353515625 +56481 0.00128173828125 +56482 0.12200927734375 +56483 0.00299072265625 +56484 0.080108642578125 +56485 0.004180908203125 +56486 0.05126953125 +56487 0.005767822265625 +56488 0.062896728515625 +56489 0.008697509765625 +56490 0.09271240234375 +56491 0.011962890625 +56492 0.092987060546875 +56493 0.013519287109375 +56494 0.07855224609375 +56495 0.013916015625 +56496 0.06427001953125 +56497 0.013702392578125 +56498 0.0347900390625 +56499 0.01226806640625 +56500 -0.01171875 +56501 0.009552001953125 +56502 -0.056060791015625 +56503 0.006378173828125 +56504 -0.055511474609375 +56505 0.00457763671875 +56506 -0.010467529296875 +56507 0.004241943359375 +56508 0.02508544921875 +56509 0.003326416015625 +56510 0.025665283203125 +56511 0.000946044921875 +56512 0.017333984375 +56513 -0.001678466796875 +56514 0.00189208984375 +56515 -0.00433349609375 +56516 -0.03173828125 +56517 -0.00738525390625 +56518 -0.071502685546875 +56519 -0.010284423828125 +56520 -0.13543701171875 +56521 -0.013671875 +56522 -0.219970703125 +56523 -0.017364501953125 +56524 -0.300506591796875 +56525 -0.020355224609375 +56526 -0.376312255859375 +56527 -0.022674560546875 +56528 -0.416107177734375 +56529 -0.02313232421875 +56530 -0.371124267578125 +56531 -0.019866943359375 +56532 -0.242279052734375 +56533 -0.01300048828125 +56534 -0.069732666015625 +56535 -0.004241943359375 +56536 0.125640869140625 +56537 0.00543212890625 +56538 0.31268310546875 +56539 0.014678955078125 +56540 0.45501708984375 +56541 0.021942138671875 +56542 0.554779052734375 +56543 0.027252197265625 +56544 0.61065673828125 +56545 0.030487060546875 +56546 0.610931396484375 +56547 0.0311279296875 +56548 0.531463623046875 +56549 0.028228759765625 +56550 0.3883056640625 +56551 0.02239990234375 +56552 0.23468017578125 +56553 0.015777587890625 +56554 0.095245361328125 +56555 0.009429931640625 +56556 -0.00396728515625 +56557 0.004425048828125 +56558 -0.04852294921875 +56559 0.001373291015625 +56560 -0.055145263671875 +56561 -0.000274658203125 +56562 -0.0758056640625 +56563 -0.002532958984375 +56564 -0.138702392578125 +56565 -0.006439208984375 +56566 -0.209197998046875 +56567 -0.010528564453125 +56568 -0.289031982421875 +56569 -0.014801025390625 +56570 -0.37884521484375 +56571 -0.01922607421875 +56572 -0.456329345703125 +56573 -0.02288818359375 +56574 -0.51641845703125 +56575 -0.025543212890625 +56576 -0.519287109375 +56577 -0.025421142578125 +56578 -0.458251953125 +56579 -0.02227783203125 +56580 -0.384796142578125 +56581 -0.01861572265625 +56582 -0.323699951171875 +56583 -0.015655517578125 +56584 -0.269287109375 +56585 -0.0130615234375 +56586 -0.1951904296875 +56587 -0.009490966796875 +56588 -0.100006103515625 +56589 -0.0048828125 +56590 -0.01055908203125 +56591 -0.00054931640625 +56592 0.1033935546875 +56593 0.0050048828125 +56594 0.24908447265625 +56595 0.01214599609375 +56596 0.373199462890625 +56597 0.01824951171875 +56598 0.45806884765625 +56599 0.02239990234375 +56600 0.511474609375 +56601 0.024993896484375 +56602 0.565399169921875 +56603 0.02764892578125 +56604 0.61138916015625 +56605 0.029937744140625 +56606 0.5897216796875 +56607 0.028900146484375 +56608 0.4906005859375 +56609 0.0240478515625 +56610 0.33148193359375 +56611 0.016204833984375 +56612 0.147796630859375 +56613 0.00714111328125 +56614 -0.01873779296875 +56615 -0.001007080078125 +56616 -0.140289306640625 +56617 -0.006866455078125 +56618 -0.191986083984375 +56619 -0.00921630859375 +56620 -0.184295654296875 +56621 -0.008636474609375 +56622 -0.161834716796875 +56623 -0.00732421875 +56624 -0.166595458984375 +56625 -0.00738525390625 +56626 -0.19390869140625 +56627 -0.008575439453125 +56628 -0.22442626953125 +56629 -0.009979248046875 +56630 -0.279754638671875 +56631 -0.012664794921875 +56632 -0.3389892578125 +56633 -0.015594482421875 +56634 -0.3543701171875 +56635 -0.016387939453125 +56636 -0.348175048828125 +56637 -0.016143798828125 +56638 -0.32598876953125 +56639 -0.015106201171875 +56640 -0.2581787109375 +56641 -0.011810302734375 +56642 -0.139801025390625 +56643 -0.006011962890625 +56644 0.014617919921875 +56645 0.001556396484375 +56646 0.144378662109375 +56647 0.0078125 +56648 0.221038818359375 +56649 0.0113525390625 +56650 0.27069091796875 +56651 0.013519287109375 +56652 0.294036865234375 +56653 0.014373779296875 +56654 0.311767578125 +56655 0.014984130859375 +56656 0.339141845703125 +56657 0.01617431640625 +56658 0.360260009765625 +56659 0.0174560546875 +56660 0.360504150390625 +56661 0.01800537109375 +56662 0.308380126953125 +56663 0.015411376953125 +56664 0.18170166015625 +56665 0.0079345703125 +56666 0.0047607421875 +56667 -0.0028076171875 +56668 -0.17559814453125 +56669 -0.01361083984375 +56670 -0.3143310546875 +56671 -0.0213623046875 +56672 -0.36785888671875 +56673 -0.023101806640625 +56674 -0.36248779296875 +56675 -0.0208740234375 +56676 -0.343536376953125 +56677 -0.01800537109375 +56678 -0.3018798828125 +56679 -0.013946533203125 +56680 -0.231414794921875 +56681 -0.008270263671875 +56682 -0.117645263671875 +56683 0.0 +56684 0.007049560546875 +56685 0.008544921875 +56686 0.087982177734375 +56687 0.013458251953125 +56688 0.13946533203125 +56689 0.015869140625 +56690 0.17425537109375 +56691 0.01678466796875 +56692 0.188201904296875 +56693 0.016021728515625 +56694 0.171234130859375 +56695 0.012939453125 +56696 0.118438720703125 +56697 0.00732421875 +56698 0.05706787109375 +56699 0.001251220703125 +56700 -0.010711669921875 +56701 -0.005035400390625 +56702 -0.0914306640625 +56703 -0.011932373046875 +56704 -0.162322998046875 +56705 -0.01776123046875 +56706 -0.194549560546875 +56707 -0.02044677734375 +56708 -0.1492919921875 +56709 -0.01715087890625 +56710 -0.02166748046875 +56711 -0.007568359375 +56712 0.124053955078125 +56713 0.003631591796875 +56714 0.211151123046875 +56715 0.010833740234375 +56716 0.240447998046875 +56717 0.014068603515625 +56718 0.242218017578125 +56719 0.015472412109375 +56720 0.2257080078125 +56721 0.015625 +56722 0.194366455078125 +56723 0.01470947265625 +56724 0.115509033203125 +56725 0.010284423828125 +56726 0.0128173828125 +56727 0.0040283203125 +56728 -0.053802490234375 +56729 0.000152587890625 +56730 -0.110626220703125 +56731 -0.00323486328125 +56732 -0.199493408203125 +56733 -0.0091552734375 +56734 -0.29437255859375 +56735 -0.015777587890625 +56736 -0.33221435546875 +56737 -0.0185546875 +56738 -0.27972412109375 +56739 -0.015106201171875 +56740 -0.185333251953125 +56741 -0.008880615234375 +56742 -0.128204345703125 +56743 -0.005523681640625 +56744 -0.115692138671875 +56745 -0.005523681640625 +56746 -0.116455078125 +56747 -0.006591796875 +56748 -0.105926513671875 +56749 -0.00689697265625 +56750 -0.053955078125 +56751 -0.00421142578125 +56752 0.048797607421875 +56753 0.002166748046875 +56754 0.157318115234375 +56755 0.009033203125 +56756 0.212005615234375 +56757 0.012176513671875 +56758 0.218475341796875 +56759 0.012054443359375 +56760 0.23724365234375 +56761 0.013031005859375 +56762 0.30535888671875 +56763 0.017791748046875 +56764 0.38128662109375 +56765 0.0233154296875 +56766 0.404449462890625 +56767 0.025238037109375 +56768 0.3944091796875 +56769 0.024993896484375 +56770 0.3885498046875 +56771 0.025238037109375 +56772 0.362640380859375 +56773 0.024200439453125 +56774 0.27362060546875 +56775 0.018707275390625 +56776 0.11712646484375 +56777 0.00836181640625 +56778 -0.054901123046875 +56779 -0.003082275390625 +56780 -0.19085693359375 +56781 -0.011962890625 +56782 -0.28570556640625 +56783 -0.017974853515625 +56784 -0.339263916015625 +56785 -0.021148681640625 +56786 -0.3775634765625 +56787 -0.023406982421875 +56788 -0.445709228515625 +56789 -0.02801513671875 +56790 -0.535064697265625 +56791 -0.034332275390625 +56792 -0.629058837890625 +56793 -0.041168212890625 +56794 -0.697601318359375 +56795 -0.04632568359375 +56796 -0.70391845703125 +56797 -0.04718017578125 +56798 -0.6424560546875 +56799 -0.043304443359375 +56800 -0.491241455078125 +56801 -0.0330810546875 +56802 -0.265716552734375 +56803 -0.017578125 +56804 -0.023712158203125 +56805 -0.000946044921875 +56806 0.201751708984375 +56807 0.01446533203125 +56808 0.375823974609375 +56809 0.026214599609375 +56810 0.485076904296875 +56811 0.033355712890625 +56812 0.56884765625 +56813 0.03875732421875 +56814 0.634765625 +56815 0.04302978515625 +56816 0.63763427734375 +56817 0.04290771484375 +56818 0.5660400390625 +56819 0.03759765625 +56820 0.4720458984375 +56821 0.03082275390625 +56822 0.40692138671875 +56823 0.02630615234375 +56824 0.3778076171875 +56825 0.0245361328125 +56826 0.376953125 +56827 0.024932861328125 +56828 0.371978759765625 +56829 0.025146484375 +56830 0.313140869140625 +56831 0.021514892578125 +56832 0.184417724609375 +56833 0.01263427734375 +56834 0.011199951171875 +56835 6.103515625e-05 +56836 -0.171051025390625 +56837 -0.013336181640625 +56838 -0.33740234375 +56839 -0.025360107421875 +56840 -0.47198486328125 +56841 -0.03466796875 +56842 -0.560394287109375 +56843 -0.040069580078125 +56844 -0.58056640625 +56845 -0.03948974609375 +56846 -0.54754638671875 +56847 -0.03460693359375 +56848 -0.508575439453125 +56849 -0.030364990234375 +56850 -0.459503173828125 +56851 -0.026336669921875 +56852 -0.394378662109375 +56853 -0.02178955078125 +56854 -0.35260009765625 +56855 -0.0206298828125 +56856 -0.31170654296875 +56857 -0.02032470703125 +56858 -0.197418212890625 +56859 -0.012908935546875 +56860 -0.007965087890625 +56861 0.00201416015625 +56862 0.207489013671875 +56863 0.01959228515625 +56864 0.409210205078125 +56865 0.03594970703125 +56866 0.57208251953125 +56867 0.048736572265625 +56868 0.66595458984375 +56869 0.0550537109375 +56870 0.65875244140625 +56871 0.051727294921875 +56872 0.56744384765625 +56873 0.040618896484375 +56874 0.431396484375 +56875 0.025909423828125 +56876 0.29443359375 +56877 0.012176513671875 +56878 0.182464599609375 +56879 0.002044677734375 +56880 0.06365966796875 +56881 -0.00787353515625 +56882 -0.075958251953125 +56883 -0.01922607421875 +56884 -0.189422607421875 +56885 -0.027313232421875 +56886 -0.271942138671875 +56887 -0.03179931640625 +56888 -0.342529296875 +56889 -0.034912109375 +56890 -0.364166259765625 +56891 -0.0330810546875 +56892 -0.327239990234375 +56893 -0.0255126953125 +56894 -0.2769775390625 +56895 -0.01708984375 +56896 -0.253692626953125 +56897 -0.012176513671875 +56898 -0.24365234375 +56899 -0.00946044921875 +56900 -0.1983642578125 +56901 -0.00396728515625 +56902 -0.116241455078125 +56903 0.004425048828125 +56904 -0.036834716796875 +56905 0.01165771484375 +56906 0.034881591796875 +56907 0.01727294921875 +56908 0.09124755859375 +56909 0.020599365234375 +56910 0.10888671875 +56911 0.01934814453125 +56912 0.125518798828125 +56913 0.01763916015625 +56914 0.15771484375 +56915 0.01739501953125 +56916 0.17828369140625 +56917 0.0159912109375 +56918 0.17108154296875 +56919 0.011932373046875 +56920 0.129974365234375 +56921 0.0047607421875 +56922 0.082427978515625 +56923 -0.00250244140625 +56924 0.027679443359375 +56925 -0.009796142578125 +56926 -0.065643310546875 +56927 -0.02032470703125 +56928 -0.15936279296875 +56929 -0.03009033203125 +56930 -0.21307373046875 +56931 -0.034912109375 +56932 -0.234649658203125 +56933 -0.03570556640625 +56934 -0.2001953125 +56935 -0.03009033203125 +56936 -0.119171142578125 +56937 -0.0191650390625 +56938 -0.024749755859375 +56939 -0.00653076171875 +56940 0.085784912109375 +56941 0.007904052734375 +56942 0.178131103515625 +56943 0.0203857421875 +56944 0.215576171875 +56945 0.026947021484375 +56946 0.211456298828125 +56947 0.02886962890625 +56948 0.17523193359375 +56949 0.02703857421875 +56950 0.128753662109375 +56951 0.023651123046875 +56952 0.1019287109375 +56953 0.021697998046875 +56954 0.0743408203125 +56955 0.019073486328125 +56956 0.04327392578125 +56957 0.01544189453125 +56958 0.038177490234375 +56959 0.013916015625 +56960 0.076263427734375 +56961 0.016357421875 +56962 0.14105224609375 +56963 0.0211181640625 +56964 0.186431884765625 +56965 0.0235595703125 +56966 0.188812255859375 +56967 0.0213623046875 +56968 0.1390380859375 +56969 0.01373291015625 +56970 0.041778564453125 +56971 0.00128173828125 +56972 -0.079437255859375 +56973 -0.013397216796875 +56974 -0.219390869140625 +56975 -0.0296630859375 +56976 -0.367828369140625 +56977 -0.04632568359375 +56978 -0.494873046875 +56979 -0.06024169921875 +56980 -0.556243896484375 +56981 -0.066802978515625 +56982 -0.508697509765625 +56983 -0.061492919921875 +56984 -0.3756103515625 +56985 -0.046783447265625 +56986 -0.218902587890625 +56987 -0.029205322265625 +56988 -0.063751220703125 +56989 -0.011444091796875 +56990 0.091552734375 +56991 0.00653076171875 +56992 0.23602294921875 +56993 0.023468017578125 +56994 0.342987060546875 +56995 0.0364990234375 +56996 0.39520263671875 +56997 0.043731689453125 +56998 0.389373779296875 +56999 0.04473876953125 +57000 0.324249267578125 +57001 0.039306640625 +57002 0.224090576171875 +57003 0.029937744140625 +57004 0.124267578125 +57005 0.020233154296875 +57006 0.037078857421875 +57007 0.01141357421875 +57008 -0.010101318359375 +57009 0.00634765625 +57010 -0.019439697265625 +57011 0.00482177734375 +57012 -0.022796630859375 +57013 0.0035400390625 +57014 -0.001556396484375 +57015 0.0045166015625 +57016 0.056304931640625 +57017 0.009033203125 +57018 0.106719970703125 +57019 0.01263427734375 +57020 0.096893310546875 +57021 0.009918212890625 +57022 0.042694091796875 +57023 0.002655029296875 +57024 -0.018035888671875 +57025 -0.005126953125 +57026 -0.07586669921875 +57027 -0.012359619140625 +57028 -0.11944580078125 +57029 -0.017791748046875 +57030 -0.15972900390625 +57031 -0.022552490234375 +57032 -0.202606201171875 +57033 -0.0272216796875 +57034 -0.24859619140625 +57035 -0.03179931640625 +57036 -0.30517578125 +57037 -0.037109375 +57038 -0.36212158203125 +57039 -0.042144775390625 +57040 -0.39141845703125 +57041 -0.0440673828125 +57042 -0.35528564453125 +57043 -0.03900146484375 +57044 -0.249969482421875 +57045 -0.026641845703125 +57046 -0.092864990234375 +57047 -0.008880615234375 +57048 0.08905029296875 +57049 0.011383056640625 +57050 0.2352294921875 +57051 0.02777099609375 +57052 0.318817138671875 +57053 0.03741455078125 +57054 0.358642578125 +57055 0.042236328125 +57056 0.347747802734375 +57057 0.041473388671875 +57058 0.28564453125 +57059 0.03509521484375 +57060 0.223175048828125 +57061 0.02838134765625 +57062 0.196746826171875 +57063 0.025115966796875 +57064 0.179840087890625 +57065 0.0225830078125 +57066 0.155548095703125 +57067 0.01910400390625 +57068 0.151214599609375 +57069 0.017547607421875 +57070 0.156951904296875 +57071 0.0169677734375 +57072 0.13177490234375 +57073 0.013153076171875 +57074 0.100799560546875 +57075 0.008819580078125 +57076 0.087127685546875 +57077 0.00640869140625 +57078 0.05487060546875 +57079 0.002227783203125 +57080 -0.009002685546875 +57081 -0.0050048828125 +57082 -0.10400390625 +57083 -0.01519775390625 +57084 -0.229400634765625 +57085 -0.02825927734375 +57086 -0.35552978515625 +57087 -0.0411376953125 +57088 -0.441925048828125 +57089 -0.049835205078125 +57090 -0.473846435546875 +57091 -0.05316162109375 +57092 -0.464813232421875 +57093 -0.052703857421875 +57094 -0.419097900390625 +57095 -0.048492431640625 +57096 -0.334320068359375 +57097 -0.039703369140625 +57098 -0.227935791015625 +57099 -0.02825927734375 +57100 -0.12347412109375 +57101 -0.01702880859375 +57102 -0.02764892578125 +57103 -0.006683349609375 +57104 0.077667236328125 +57105 0.00543212890625 +57106 0.2132568359375 +57107 0.022247314453125 +57108 0.38885498046875 +57109 0.045166015625 +57110 0.582794189453125 +57111 0.071258544921875 +57112 0.734039306640625 +57113 0.0921630859375 +57114 0.800140380859375 +57115 0.102020263671875 +57116 0.7783203125 +57117 0.100372314453125 +57118 0.6651611328125 +57119 0.086639404296875 +57120 0.45965576171875 +57121 0.06060791015625 +57122 0.199188232421875 +57123 0.027191162109375 +57124 -0.050689697265625 +57125 -0.004791259765625 +57126 -0.23297119140625 +57127 -0.027740478515625 +57128 -0.33013916015625 +57129 -0.039337158203125 +57130 -0.368408203125 +57131 -0.04327392578125 +57132 -0.378936767578125 +57133 -0.0438232421875 +57134 -0.376983642578125 +57135 -0.04315185546875 +57136 -0.37969970703125 +57137 -0.043548583984375 +57138 -0.391510009765625 +57139 -0.045623779296875 +57140 -0.385345458984375 +57141 -0.045623779296875 +57142 -0.3419189453125 +57143 -0.0408935546875 +57144 -0.28289794921875 +57145 -0.0343017578125 +57146 -0.251617431640625 +57147 -0.031646728515625 +57148 -0.266143798828125 +57149 -0.0352783203125 +57150 -0.273345947265625 +57151 -0.03790283203125 +57152 -0.216796875 +57153 -0.03173828125 +57154 -0.128265380859375 +57155 -0.021026611328125 +57156 -0.068145751953125 +57157 -0.01385498046875 +57158 -0.0430908203125 +57159 -0.0111083984375 +57160 -0.024444580078125 +57161 -0.0089111328125 +57162 0.020721435546875 +57163 -0.00274658203125 +57164 0.124481201171875 +57165 0.011688232421875 +57166 0.25787353515625 +57167 0.030426025390625 +57168 0.379119873046875 +57169 0.0477294921875 +57170 0.47991943359375 +57171 0.06243896484375 +57172 0.5281982421875 +57173 0.07012939453125 +57174 0.511138916015625 +57175 0.069000244140625 +57176 0.456207275390625 +57177 0.06268310546875 +57178 0.407470703125 +57179 0.05712890625 +57180 0.383758544921875 +57181 0.054840087890625 +57182 0.35687255859375 +57183 0.051910400390625 +57184 0.31182861328125 +57185 0.046295166015625 +57186 0.250885009765625 +57187 0.038299560546875 +57188 0.1654052734375 +57189 0.0267333984375 +57190 0.035247802734375 +57191 0.008880615234375 +57192 -0.142059326171875 +57193 -0.01556396484375 +57194 -0.33563232421875 +57195 -0.042388916015625 +57196 -0.5345458984375 +57197 -0.070068359375 +57198 -0.72186279296875 +57199 -0.09625244140625 +57200 -0.836669921875 +57201 -0.11260986328125 +57202 -0.8326416015625 +57203 -0.11279296875 +57204 -0.7296142578125 +57205 -0.099456787109375 +57206 -0.582550048828125 +57207 -0.080108642578125 +57208 -0.440093994140625 +57209 -0.061309814453125 +57210 -0.324310302734375 +57211 -0.0460205078125 +57212 -0.20147705078125 +57213 -0.02960205078125 +57214 -0.044647216796875 +57215 -0.008392333984375 +57216 0.103973388671875 +57217 0.0118408203125 +57218 0.202392578125 +57219 0.025390625 +57220 0.264495849609375 +57221 0.03411865234375 +57222 0.338897705078125 +57223 0.044586181640625 +57224 0.443817138671875 +57225 0.05926513671875 +57226 0.545074462890625 +57227 0.073486328125 +57228 0.6173095703125 +57229 0.083770751953125 +57230 0.6524658203125 +57231 0.089019775390625 +57232 0.66339111328125 +57233 0.0909423828125 +57234 0.6561279296875 +57235 0.09033203125 +57236 0.606781005859375 +57237 0.083892822265625 +57238 0.501190185546875 +57239 0.0697021484375 +57240 0.352783203125 +57241 0.049591064453125 +57242 0.176544189453125 +57243 0.025604248046875 +57244 -0.034820556640625 +57245 -0.003204345703125 +57246 -0.258209228515625 +57247 -0.03369140625 +57248 -0.44244384765625 +57249 -0.05889892578125 +57250 -0.5753173828125 +57251 -0.0771484375 +57252 -0.65203857421875 +57253 -0.087799072265625 +57254 -0.641632080078125 +57255 -0.08660888671875 +57256 -0.562164306640625 +57257 -0.0760498046875 +57258 -0.458038330078125 +57259 -0.062164306640625 +57260 -0.350555419921875 +57261 -0.047821044921875 +57262 -0.260528564453125 +57263 -0.035797119140625 +57264 -0.192108154296875 +57265 -0.026641845703125 +57266 -0.141937255859375 +57267 -0.019927978515625 +57268 -0.1021728515625 +57269 -0.01458740234375 +57270 -0.062896728515625 +57271 -0.00921630859375 +57272 -0.011932373046875 +57273 -0.002197265625 +57274 0.062835693359375 +57275 0.008087158203125 +57276 0.148712158203125 +57277 0.0198974609375 +57278 0.241729736328125 +57279 0.032684326171875 +57280 0.34912109375 +57281 0.047454833984375 +57282 0.457305908203125 +57283 0.06231689453125 +57284 0.54388427734375 +57285 0.074249267578125 +57286 0.5728759765625 +57287 0.07830810546875 +57288 0.506591796875 +57289 0.06939697265625 +57290 0.351226806640625 +57291 0.048370361328125 +57292 0.146514892578125 +57293 0.020599365234375 +57294 -0.05523681640625 +57295 -0.00677490234375 +57296 -0.21624755859375 +57297 -0.02862548828125 +57298 -0.334930419921875 +57299 -0.04473876953125 +57300 -0.402984619140625 +57301 -0.053985595703125 +57302 -0.4412841796875 +57303 -0.0592041015625 +57304 -0.49578857421875 +57305 -0.066650390625 +57306 -0.5601806640625 +57307 -0.075439453125 +57308 -0.600738525390625 +57309 -0.081024169921875 +57310 -0.584228515625 +57311 -0.078857421875 +57312 -0.47930908203125 +57313 -0.064666748046875 +57314 -0.27935791015625 +57315 -0.037567138671875 +57316 -0.0089111328125 +57317 -0.0008544921875 +57318 0.268798828125 +57319 0.036834716796875 +57320 0.482818603515625 +57321 0.065826416015625 +57322 0.60369873046875 +57323 0.082122802734375 +57324 0.650421142578125 +57325 0.08831787109375 +57326 0.66400146484375 +57327 0.09002685546875 +57328 0.6414794921875 +57329 0.08685302734375 +57330 0.572540283203125 +57331 0.077392578125 +57332 0.498138427734375 +57333 0.067230224609375 +57334 0.439453125 +57335 0.059234619140625 +57336 0.375518798828125 +57337 0.050567626953125 +57338 0.274505615234375 +57339 0.036895751953125 +57340 0.1087646484375 +57341 0.01446533203125 +57342 -0.099395751953125 +57343 -0.013671875 +57344 -0.3182373046875 +57345 -0.04376220703125 +57346 -0.5489501953125 +57347 -0.0767822265625 +57348 -0.7738037109375 +57349 -0.110107421875 +57350 -0.86383056640625 +57351 -0.135009765625 +57352 -0.870391845703125 +57353 -0.14599609375 +57354 -0.86895751953125 +57355 -0.146026611328125 +57356 -0.861053466796875 +57357 -0.137237548828125 +57358 -0.765869140625 +57359 -0.116546630859375 +57360 -0.5301513671875 +57361 -0.08184814453125 +57362 -0.214691162109375 +57363 -0.034027099609375 +57364 0.137359619140625 +57365 0.019927978515625 +57366 0.474822998046875 +57367 0.07171630859375 +57368 0.76239013671875 +57369 0.115692138671875 +57370 0.867462158203125 +57371 0.147613525390625 +57372 0.870361328125 +57373 0.167816162109375 +57374 0.86480712890625 +57375 0.174560546875 +57376 0.831817626953125 +57377 0.16888427734375 +57378 0.677581787109375 +57379 0.154998779296875 +57380 0.495880126953125 +57381 0.1339111328125 +57382 0.30767822265625 +57383 0.108734130859375 +57384 0.116180419921875 +57385 0.0797119140625 +57386 -0.110748291015625 +57387 0.0413818359375 +57388 -0.381805419921875 +57389 -0.007598876953125 +57390 -0.6572265625 +57391 -0.060272216796875 +57392 -0.857421875 +57393 -0.106781005859375 +57394 -0.870391845703125 +57395 -0.14019775390625 +57396 -0.870391845703125 +57397 -0.159576416015625 +57398 -0.86444091796875 +57399 -0.169677734375 +57400 -0.85723876953125 +57401 -0.176666259765625 +57402 -0.790008544921875 +57403 -0.1776123046875 +57404 -0.62847900390625 +57405 -0.16351318359375 +57406 -0.3956298828125 +57407 -0.133880615234375 +57408 -0.126708984375 +57409 -0.094207763671875 +57410 0.150115966796875 +57411 -0.049041748046875 +57412 0.424041748046875 +57413 -0.000244140625 +57414 0.670623779296875 +57415 0.047760009765625 +57416 0.854522705078125 +57417 0.088653564453125 +57418 0.866485595703125 +57419 0.119659423828125 +57420 0.86920166015625 +57421 0.138427734375 +57422 0.8653564453125 +57423 0.148193359375 +57424 0.857147216796875 +57425 0.151397705078125 +57426 0.766845703125 +57427 0.147735595703125 +57428 0.628509521484375 +57429 0.13824462890625 +57430 0.462127685546875 +57431 0.12188720703125 +57432 0.297210693359375 +57433 0.10302734375 +57434 0.14862060546875 +57435 0.083709716796875 +57436 -0.00537109375 +57437 0.06011962890625 +57438 -0.15753173828125 +57439 0.033416748046875 +57440 -0.31304931640625 +57441 0.0029296875 +57442 -0.48876953125 +57443 -0.033843994140625 +57444 -0.6416015625 +57445 -0.069183349609375 +57446 -0.751373291015625 +57447 -0.099090576171875 +57448 -0.84619140625 +57449 -0.127593994140625 +57450 -0.861297607421875 +57451 -0.152374267578125 +57452 -0.863250732421875 +57453 -0.168060302734375 +57454 -0.856597900390625 +57455 -0.16943359375 +57456 -0.7498779296875 +57457 -0.158660888671875 +57458 -0.624542236328125 +57459 -0.1455078125 +57460 -0.47808837890625 +57461 -0.1263427734375 +57462 -0.253387451171875 +57463 -0.091339111328125 +57464 0.003692626953125 +57465 -0.048126220703125 +57466 0.2257080078125 +57467 -0.00811767578125 +57468 0.427154541015625 +57469 0.030853271484375 +57470 0.643218994140625 +57471 0.0743408203125 +57472 0.855926513671875 +57473 0.120849609375 +57474 0.870361328125 +57475 0.160797119140625 +57476 0.870361328125 +57477 0.18603515625 +57478 0.862762451171875 +57479 0.1978759765625 +57480 0.79669189453125 +57481 0.195953369140625 +57482 0.595794677734375 +57483 0.178802490234375 +57484 0.362152099609375 +57485 0.151397705078125 +57486 0.1270751953125 +57487 0.118499755859375 +57488 -0.086944580078125 +57489 0.083648681640625 +57490 -0.2784423828125 +57491 0.047210693359375 +57492 -0.484832763671875 +57493 0.003265380859375 +57494 -0.729583740234375 +57495 -0.051422119140625 +57496 -0.86688232421875 +57497 -0.10845947265625 +57498 -0.870391845703125 +57499 -0.157318115234375 +57500 -0.86859130859375 +57501 -0.197265625 +57502 -0.86279296875 +57503 -0.228057861328125 +57504 -0.817962646484375 +57505 -0.243804931640625 +57506 -0.6116943359375 +57507 -0.236968994140625 +57508 -0.3128662109375 +57509 -0.2064208984375 +57510 0.039398193359375 +57511 -0.157928466796875 +57512 0.422821044921875 +57513 -0.094879150390625 +57514 0.805145263671875 +57515 -0.022918701171875 +57516 0.870361328125 +57517 0.046478271484375 +57518 0.870361328125 +57519 0.103759765625 +57520 0.860015869140625 +57521 0.14697265625 +57522 0.727935791015625 +57523 0.17486572265625 +57524 0.48114013671875 +57525 0.186553955078125 +57526 0.2059326171875 +57527 0.186187744140625 +57528 -0.06103515625 +57529 0.1776123046875 +57530 -0.29913330078125 +57531 0.16259765625 +57532 -0.516204833984375 +57533 0.1387939453125 +57534 -0.7252197265625 +57535 0.103729248046875 +57536 -0.85980224609375 +57537 0.0616455078125 +57538 -0.870391845703125 +57539 0.01837158203125 +57540 -0.870391845703125 +57541 -0.021026611328125 +57542 -0.858062744140625 +57543 -0.048309326171875 +57544 -0.673004150390625 +57545 -0.062713623046875 +57546 -0.42694091796875 +57547 -0.07305908203125 +57548 -0.2100830078125 +57549 -0.086761474609375 +57550 -0.0362548828125 +57551 -0.103424072265625 +57552 0.10943603515625 +57553 -0.118194580078125 +57554 0.23516845703125 +57555 -0.127685546875 +57556 0.373687744140625 +57557 -0.125 +57558 0.517791748046875 +57559 -0.110504150390625 +57560 0.602783203125 +57561 -0.0948486328125 +57562 0.635711669921875 +57563 -0.0772705078125 +57564 0.655181884765625 +57565 -0.05224609375 +57566 0.65948486328125 +57567 -0.02154541015625 +57568 0.651275634765625 +57569 0.013397216796875 +57570 0.61846923828125 +57571 0.048370361328125 +57572 0.53753662109375 +57573 0.07708740234375 +57574 0.404144287109375 +57575 0.096466064453125 +57576 0.22186279296875 +57577 0.1048583984375 +57578 0.003997802734375 +57579 0.102508544921875 +57580 -0.22100830078125 +57581 0.092437744140625 +57582 -0.42449951171875 +57583 0.078125 +57584 -0.579833984375 +57585 0.063201904296875 +57586 -0.641876220703125 +57587 0.05487060546875 +57588 -0.6177978515625 +57589 0.05206298828125 +57590 -0.575531005859375 +57591 0.04400634765625 +57592 -0.526336669921875 +57593 0.029876708984375 +57594 -0.42645263671875 +57595 0.0184326171875 +57596 -0.2581787109375 +57597 0.01434326171875 +57598 -0.068695068359375 +57599 0.011566162109375 +57600 0.09222412109375 +57601 0.00421142578125 +57602 0.232147216796875 +57603 -0.003936767578125 +57604 0.3509521484375 +57605 -0.01165771484375 +57606 0.410064697265625 +57607 -0.025390625 +57608 0.372955322265625 +57609 -0.05145263671875 +57610 0.2554931640625 +57611 -0.086029052734375 +57612 0.10711669921875 +57613 -0.118988037109375 +57614 -0.052886962890625 +57615 -0.146575927734375 +57616 -0.186279296875 +57617 -0.161651611328125 +57618 -0.23291015625 +57619 -0.153076171875 +57620 -0.209442138671875 +57621 -0.125335693359375 +57622 -0.174163818359375 +57623 -0.091461181640625 +57624 -0.126739501953125 +57625 -0.05291748046875 +57626 -0.048126220703125 +57627 -0.007568359375 +57628 0.0426025390625 +57629 0.039154052734375 +57630 0.10748291015625 +57631 0.078155517578125 +57632 0.1409912109375 +57633 0.10699462890625 +57634 0.19708251953125 +57635 0.1353759765625 +57636 0.273651123046875 +57637 0.162109375 +57638 0.31768798828125 +57639 0.1761474609375 +57640 0.341094970703125 +57641 0.179779052734375 +57642 0.368011474609375 +57643 0.178070068359375 +57644 0.37249755859375 +57645 0.1663818359375 +57646 0.30072021484375 +57647 0.134796142578125 +57648 0.1517333984375 +57649 0.084197998046875 +57650 -0.01470947265625 +57651 0.027801513671875 +57652 -0.1883544921875 +57653 -0.031005859375 +57654 -0.372711181640625 +57655 -0.091583251953125 +57656 -0.51397705078125 +57657 -0.14190673828125 +57658 -0.57177734375 +57659 -0.172760009765625 +57660 -0.53948974609375 +57661 -0.18182373046875 +57662 -0.43511962890625 +57663 -0.171966552734375 +57664 -0.2962646484375 +57665 -0.150238037109375 +57666 -0.161102294921875 +57667 -0.12408447265625 +57668 -0.0435791015625 +57669 -0.096405029296875 +57670 0.060394287109375 +57671 -0.0667724609375 +57672 0.13665771484375 +57673 -0.038604736328125 +57674 0.170135498046875 +57675 -0.0157470703125 +57676 0.16552734375 +57677 0.001739501953125 +57678 0.15728759765625 +57679 0.019683837890625 +57680 0.150787353515625 +57681 0.038055419921875 +57682 0.12200927734375 +57683 0.05096435546875 +57684 0.080108642578125 +57685 0.05926513671875 +57686 0.05126953125 +57687 0.06732177734375 +57688 0.062896728515625 +57689 0.0799560546875 +57690 0.09271240234375 +57691 0.092254638671875 +57692 0.092987060546875 +57693 0.094451904296875 +57694 0.07855224609375 +57695 0.089508056640625 +57696 0.06427001953125 +57697 0.080657958984375 +57698 0.0347900390625 +57699 0.06524658203125 +57700 -0.01171875 +57701 0.04351806640625 +57702 -0.056060791015625 +57703 0.02008056640625 +57704 -0.055511474609375 +57705 0.004364013671875 +57706 -0.010467529296875 +57707 -0.0028076171875 +57708 0.02508544921875 +57709 -0.0113525390625 +57710 0.025665283203125 +57711 -0.025543212890625 +57712 0.017333984375 +57713 -0.0394287109375 +57714 0.00189208984375 +57715 -0.052001953125 +57716 -0.03173828125 +57717 -0.0650634765625 +57718 -0.071502685546875 +57719 -0.075958251953125 +57720 -0.13543701171875 +57721 -0.088226318359375 +57722 -0.219970703125 +57723 -0.10125732421875 +57724 -0.300506591796875 +57725 -0.110443115234375 +57726 -0.376312255859375 +57727 -0.1160888671875 +57728 -0.416107177734375 +57729 -0.112548828125 +57730 -0.371124267578125 +57731 -0.09075927734375 +57732 -0.242279052734375 +57733 -0.051666259765625 +57734 -0.069732666015625 +57735 -0.0040283203125 +57736 0.125640869140625 +57737 0.0472412109375 +57738 0.31268310546875 +57739 0.095306396484375 +57740 0.45501708984375 +57741 0.13232421875 +57742 0.554779052734375 +57743 0.158294677734375 +57744 0.61065673828125 +57745 0.1727294921875 +57746 0.610931396484375 +57747 0.173187255859375 +57748 0.531463623046875 +57749 0.1549072265625 +57750 0.3883056640625 +57751 0.121337890625 +57752 0.23468017578125 +57753 0.083465576171875 +57754 0.095245361328125 +57755 0.046661376953125 +57756 -0.00396728515625 +57757 0.01666259765625 +57758 -0.04852294921875 +57759 -0.0030517578125 +57760 -0.055145263671875 +57761 -0.01519775390625 +57762 -0.0758056640625 +57763 -0.02960205078125 +57764 -0.138702392578125 +57765 -0.051361083984375 +57766 -0.209197998046875 +57767 -0.07305908203125 +57768 -0.289031982421875 +57769 -0.094696044921875 +57770 -0.37884521484375 +57771 -0.116119384765625 +57772 -0.456329345703125 +57773 -0.132720947265625 +57774 -0.51641845703125 +57775 -0.1435546875 +57776 -0.519287109375 +57777 -0.140777587890625 +57778 -0.458251953125 +57779 -0.123291015625 +57780 -0.384796142578125 +57781 -0.101715087890625 +57782 -0.323699951171875 +57783 -0.0814208984375 +57784 -0.269287109375 +57785 -0.061737060546875 +57786 -0.1951904296875 +57787 -0.03790283203125 +57788 -0.100006103515625 +57789 -0.0101318359375 +57790 -0.01055908203125 +57791 0.015716552734375 +57792 0.1033935546875 +57793 0.045257568359375 +57794 0.24908447265625 +57795 0.079620361328125 +57796 0.373199462890625 +57797 0.107879638671875 +57798 0.45806884765625 +57799 0.126373291015625 +57800 0.511474609375 +57801 0.136627197265625 +57802 0.565399169921875 +57803 0.1451416015625 +57804 0.61138916015625 +57805 0.150360107421875 +57806 0.5897216796875 +57807 0.140625 +57808 0.4906005859375 +57809 0.11431884765625 +57810 0.33148193359375 +57811 0.0753173828125 +57812 0.147796630859375 +57813 0.0311279296875 +57814 -0.01873779296875 +57815 -0.009490966796875 +57816 -0.140289306640625 +57817 -0.040557861328125 +57818 -0.191986083984375 +57819 -0.056732177734375 +57820 -0.184295654296875 +57821 -0.059844970703125 +57822 -0.161834716796875 +57823 -0.05859375 +57824 -0.166595458984375 +57825 -0.061248779296875 +57826 -0.19390869140625 +57827 -0.066802978515625 +57828 -0.22442626953125 +57829 -0.071441650390625 +57830 -0.279754638671875 +57831 -0.079620361328125 +57832 -0.3389892578125 +57833 -0.08734130859375 +57834 -0.3543701171875 +57835 -0.0853271484375 +57836 -0.348175048828125 +57837 -0.078338623046875 +57838 -0.32598876953125 +57839 -0.06781005859375 +57840 -0.2581787109375 +57841 -0.048187255859375 +57842 -0.139801025390625 +57843 -0.018798828125 +57844 0.014617919921875 +57845 0.01715087890625 +57846 0.144378662109375 +57847 0.047210693359375 +57848 0.221038818359375 +57849 0.065521240234375 +57850 0.27069091796875 +57851 0.077178955078125 +57852 0.294036865234375 +57853 0.082275390625 +57854 0.311767578125 +57855 0.0849609375 +57856 0.339141845703125 +57857 0.088470458984375 +57858 0.360260009765625 +57859 0.090179443359375 +57860 0.360504150390625 +57861 0.08721923828125 +57862 0.308380126953125 +57863 0.072296142578125 +57864 0.18170166015625 +57865 0.040313720703125 +57866 0.0047607421875 +57867 -0.002960205078125 +57868 -0.17559814453125 +57869 -0.046661376953125 +57870 -0.3143310546875 +57871 -0.080291748046875 +57872 -0.36785888671875 +57873 -0.093719482421875 +57874 -0.36248779296875 +57875 -0.093017578125 +57876 -0.343536376953125 +57877 -0.08868408203125 +57878 -0.3018798828125 +57879 -0.078643798828125 +57880 -0.231414794921875 +57881 -0.061492919921875 +57882 -0.117645263671875 +57883 -0.033905029296875 +57884 0.007049560546875 +57885 -0.00347900390625 +57886 0.087982177734375 +57887 0.016998291015625 +57888 0.13946533203125 +57889 0.03076171875 +57890 0.17425537109375 +57891 0.040679931640625 +57892 0.188201904296875 +57893 0.045684814453125 +57894 0.171234130859375 +57895 0.0433349609375 +57896 0.118438720703125 +57897 0.032440185546875 +57898 0.05706787109375 +57899 0.019256591796875 +57900 -0.010711669921875 +57901 0.004241943359375 +57902 -0.0914306640625 +57903 -0.014129638671875 +57904 -0.162322998046875 +57905 -0.03057861328125 +57906 -0.194549560546875 +57907 -0.038421630859375 +57908 -0.1492919921875 +57909 -0.02862548828125 +57910 -0.02166748046875 +57911 -3.0517578125e-05 +57912 0.124053955078125 +57913 0.03253173828125 +57914 0.211151123046875 +57915 0.051300048828125 +57916 0.240447998046875 +57917 0.056549072265625 +57918 0.242218017578125 +57919 0.055389404296875 +57920 0.2257080078125 +57921 0.050079345703125 +57922 0.194366455078125 +57923 0.04150390625 +57924 0.115509033203125 +57925 0.022125244140625 +57926 0.0128173828125 +57927 -0.00244140625 +57928 -0.053802490234375 +57929 -0.018280029296875 +57930 -0.110626220703125 +57931 -0.031494140625 +57932 -0.199493408203125 +57933 -0.05181884765625 +57934 -0.29437255859375 +57935 -0.073211669921875 +57936 -0.33221435546875 +57937 -0.081085205078125 +57938 -0.27972412109375 +57939 -0.067779541015625 +57940 -0.185333251953125 +57941 -0.04461669921875 +57942 -0.128204345703125 +57943 -0.030029296875 +57944 -0.115692138671875 +57945 -0.025787353515625 +57946 -0.116455078125 +57947 -0.024688720703125 +57948 -0.105926513671875 +57949 -0.0211181640625 +57950 -0.053955078125 +57951 -0.00811767578125 +57952 0.048797607421875 +57953 0.016387939453125 +57954 0.157318115234375 +57955 0.04193115234375 +57956 0.212005615234375 +57957 0.054656982421875 +57958 0.218475341796875 +57959 0.055877685546875 +57960 0.23724365234375 +57961 0.0596923828125 +57962 0.30535888671875 +57963 0.07470703125 +57964 0.38128662109375 +57965 0.091339111328125 +57966 0.404449462890625 +57967 0.0955810546875 +57968 0.3944091796875 +57969 0.092071533203125 +57970 0.3885498046875 +57971 0.089508056640625 +57972 0.362640380859375 +57973 0.082366943359375 +57974 0.27362060546875 +57975 0.060699462890625 +57976 0.11712646484375 +57977 0.0235595703125 +57978 -0.054901123046875 +57979 -0.01690673828125 +57980 -0.19085693359375 +57981 -0.0487060546875 +57982 -0.28570556640625 +57983 -0.070709228515625 +57984 -0.339263916015625 +57985 -0.082855224609375 +57986 -0.3775634765625 +57987 -0.091217041015625 +57988 -0.445709228515625 +57989 -0.106292724609375 +57990 -0.535064697265625 +57991 -0.12615966796875 +57992 -0.629058837890625 +57993 -0.147003173828125 +57994 -0.697601318359375 +57995 -0.161865234375 +57996 -0.70391845703125 +57997 -0.16229248046875 +57998 -0.6424560546875 +57999 -0.14703369140625 +58000 -0.491241455078125 +58001 -0.111053466796875 +58002 -0.265716552734375 +58003 -0.058013916015625 +58004 -0.023712158203125 +58005 -0.0013427734375 +58006 0.201751708984375 +58007 0.051239013671875 +58008 0.375823974609375 +58009 0.09161376953125 +58010 0.485076904296875 +58011 0.11669921875 +58012 0.56884765625 +58013 0.135650634765625 +58014 0.634765625 +58015 0.1502685546875 +58016 0.63763427734375 +58017 0.150115966796875 +58018 0.5660400390625 +58019 0.132598876953125 +58020 0.4720458984375 +58021 0.109832763671875 +58022 0.40692138671875 +58023 0.093780517578125 +58024 0.3778076171875 +58025 0.08612060546875 +58026 0.376953125 +58027 0.085113525390625 +58028 0.371978759765625 +58029 0.083282470703125 +58030 0.313140869140625 +58031 0.069122314453125 +58032 0.184417724609375 +58033 0.0389404296875 +58034 0.011199951171875 +58035 -0.001312255859375 +58036 -0.171051025390625 +58037 -0.04339599609375 +58038 -0.33740234375 +58039 -0.08154296875 +58040 -0.47198486328125 +58041 -0.11212158203125 +58042 -0.560394287109375 +58043 -0.1318359375 +58044 -0.58056640625 +58045 -0.135650634765625 +58046 -0.54754638671875 +58047 -0.1270751953125 +58048 -0.508575439453125 +58049 -0.117156982421875 +58050 -0.459503173828125 +58051 -0.104949951171875 +58052 -0.394378662109375 +58053 -0.089111328125 +58054 -0.35260009765625 +58055 -0.078765869140625 +58056 -0.31170654296875 +58057 -0.06878662109375 +58058 -0.197418212890625 +58059 -0.04193115234375 +58060 -0.007965087890625 +58061 0.00213623046875 +58062 0.207489013671875 +58063 0.052001953125 +58064 0.409210205078125 +58065 0.09844970703125 +58066 0.57208251953125 +58067 0.135711669921875 +58068 0.66595458984375 +58069 0.156829833984375 +58070 0.65875244140625 +58071 0.154388427734375 +58072 0.56744384765625 +58073 0.132354736328125 +58074 0.431396484375 +58075 0.099945068359375 +58076 0.29443359375 +58077 0.067352294921875 +58078 0.182464599609375 +58079 0.040618896484375 +58080 0.06365966796875 +58081 0.012420654296875 +58082 -0.075958251953125 +58083 -0.020416259765625 +58084 -0.189422607421875 +58085 -0.0469970703125 +58086 -0.271942138671875 +58087 -0.066192626953125 +58088 -0.342529296875 +58089 -0.082427978515625 +58090 -0.364166259765625 +58091 -0.087158203125 +58092 -0.327239990234375 +58093 -0.078155517578125 +58094 -0.2769775390625 +58095 -0.06591796875 +58096 -0.253692626953125 +58097 -0.059844970703125 +58098 -0.24365234375 +58099 -0.056793212890625 +58100 -0.1983642578125 +58101 -0.0455322265625 +58102 -0.116241455078125 +58103 -0.025726318359375 +58104 -0.036834716796875 +58105 -0.006591796875 +58106 0.034881591796875 +58107 0.0106201171875 +58108 0.09124755859375 +58109 0.02410888671875 +58110 0.10888671875 +58111 0.028411865234375 +58112 0.125518798828125 +58113 0.032684326171875 +58114 0.15771484375 +58115 0.0408935546875 +58116 0.17828369140625 +58117 0.046234130859375 +58118 0.17108154296875 +58119 0.044342041015625 +58120 0.129974365234375 +58121 0.03350830078125 +58122 0.082427978515625 +58123 0.02093505859375 +58124 0.027679443359375 +58125 0.00640869140625 +58126 -0.065643310546875 +58127 -0.018341064453125 +58128 -0.15936279296875 +58129 -0.043212890625 +58130 -0.21307373046875 +58131 -0.057525634765625 +58132 -0.234649658203125 +58133 -0.063323974609375 +58134 -0.2001953125 +58135 -0.054290771484375 +58136 -0.119171142578125 +58137 -0.032928466796875 +58138 -0.024749755859375 +58139 -0.00799560546875 +58140 0.085784912109375 +58141 0.021240234375 +58142 0.178131103515625 +58143 0.04571533203125 +58144 0.215576171875 +58145 0.055755615234375 +58146 0.211456298828125 +58147 0.05487060546875 +58148 0.17523193359375 +58149 0.045562744140625 +58150 0.128753662109375 +58151 0.033599853515625 +58152 0.1019287109375 +58153 0.02685546875 +58154 0.0743408203125 +58155 0.0198974609375 +58156 0.04327392578125 +58157 0.011993408203125 +58158 0.038177490234375 +58159 0.010894775390625 +58160 0.076263427734375 +58161 0.021148681640625 +58162 0.14105224609375 +58163 0.03839111328125 +58164 0.186431884765625 +58165 0.050445556640625 +58166 0.188812255859375 +58167 0.051055908203125 +58168 0.1390380859375 +58169 0.037841796875 +58170 0.041778564453125 +58171 0.012054443359375 +58172 -0.079437255859375 +58173 -0.02008056640625 +58174 -0.219390869140625 +58175 -0.05718994140625 +58176 -0.367828369140625 +58177 -0.096527099609375 +58178 -0.494873046875 +58179 -0.130218505859375 +58180 -0.556243896484375 +58181 -0.14654541015625 +58182 -0.508697509765625 +58183 -0.13409423828125 +58184 -0.3756103515625 +58185 -0.09906005859375 +58186 -0.218902587890625 +58187 -0.057769775390625 +58188 -0.063751220703125 +58189 -0.016845703125 +58190 0.091552734375 +58191 0.024078369140625 +58192 0.23602294921875 +58193 0.0621337890625 +58194 0.342987060546875 +58195 0.09027099609375 +58196 0.39520263671875 +58197 0.103973388671875 +58198 0.389373779296875 +58199 0.10235595703125 +58200 0.324249267578125 +58201 0.085113525390625 +58202 0.224090576171875 +58203 0.05865478515625 +58204 0.124267578125 +58205 0.0323486328125 +58206 0.037078857421875 +58207 0.0093994140625 +58208 -0.010101318359375 +58209 -0.0029296875 +58210 -0.019439697265625 +58211 -0.0052490234375 +58212 -0.022796630859375 +58213 -0.0059814453125 +58214 -0.001556396484375 +58215 -0.00018310546875 +58216 0.056304931640625 +58217 0.0152587890625 +58218 0.106719970703125 +58219 0.0286865234375 +58220 0.096893310546875 +58221 0.026153564453125 +58222 0.042694091796875 +58223 0.011871337890625 +58224 -0.018035888671875 +58225 -0.004150390625 +58226 -0.07586669921875 +58227 -0.0194091796875 +58228 -0.11944580078125 +58229 -0.030914306640625 +58230 -0.15972900390625 +58231 -0.04156494140625 +58232 -0.202606201171875 +58233 -0.05291748046875 +58234 -0.24859619140625 +58235 -0.0650634765625 +58236 -0.30517578125 +58237 -0.079986572265625 +58238 -0.36212158203125 +58239 -0.095001220703125 +58240 -0.39141845703125 +58241 -0.102752685546875 +58242 -0.35528564453125 +58243 -0.093231201171875 +58244 -0.249969482421875 +58245 -0.065460205078125 +58246 -0.092864990234375 +58247 -0.024017333984375 +58248 0.08905029296875 +58249 0.02392578125 +58250 0.2352294921875 +58251 0.062408447265625 +58252 0.318817138671875 +58253 0.084381103515625 +58254 0.358642578125 +58255 0.09478759765625 +58256 0.347747802734375 +58257 0.091796875 +58258 0.28564453125 +58259 0.075286865234375 +58260 0.223175048828125 +58261 0.058685302734375 +58262 0.196746826171875 +58263 0.051605224609375 +58264 0.179840087890625 +58265 0.047088623046875 +58266 0.155548095703125 +58267 0.0406494140625 +58268 0.151214599609375 +58269 0.039520263671875 +58270 0.156951904296875 +58271 0.04107666015625 +58272 0.13177490234375 +58273 0.03448486328125 +58274 0.100799560546875 +58275 0.026397705078125 +58276 0.087127685546875 +58277 0.02288818359375 +58278 0.05487060546875 +58279 0.01446533203125 +58280 -0.009002685546875 +58281 -0.002288818359375 +58282 -0.10400390625 +58283 -0.027252197265625 +58284 -0.229400634765625 +58285 -0.06024169921875 +58286 -0.35552978515625 +58287 -0.093414306640625 +58288 -0.441925048828125 +58289 -0.1160888671875 +58290 -0.473846435546875 +58291 -0.124420166015625 +58292 -0.464813232421875 +58293 -0.1219482421875 +58294 -0.419097900390625 +58295 -0.10980224609375 +58296 -0.334320068359375 +58297 -0.087371826171875 +58298 -0.227935791015625 +58299 -0.059234619140625 +58300 -0.12347412109375 +58301 -0.031646728515625 +58302 -0.02764892578125 +58303 -0.00634765625 +58304 0.077667236328125 +58305 0.021392822265625 +58306 0.2132568359375 +58307 0.05706787109375 +58308 0.38885498046875 +58309 0.103271484375 +58310 0.582794189453125 +58311 0.154296875 +58312 0.734039306640625 +58313 0.19403076171875 +58314 0.800140380859375 +58315 0.21124267578125 +58316 0.7783203125 +58317 0.205230712890625 +58318 0.6651611328125 +58319 0.17510986328125 +58320 0.45965576171875 +58321 0.12066650390625 +58322 0.199188232421875 +58323 0.051788330078125 +58324 -0.050689697265625 +58325 -0.01422119140625 +58326 -0.23297119140625 +58327 -0.06231689453125 +58328 -0.33013916015625 +58329 -0.087890625 +58330 -0.368408203125 +58331 -0.09783935546875 +58332 -0.378936767578125 +58333 -0.10040283203125 +58334 -0.376983642578125 +58335 -0.099639892578125 +58336 -0.37969970703125 +58337 -0.10009765625 +58338 -0.391510009765625 +58339 -0.102935791015625 +58340 -0.385345458984375 +58341 -0.101043701171875 +58342 -0.3419189453125 +58343 -0.089324951171875 +58344 -0.28289794921875 +58345 -0.073516845703125 +58346 -0.251617431640625 +58347 -0.0650634765625 +58348 -0.266143798828125 +58349 -0.068756103515625 +58350 -0.273345947265625 +58351 -0.070587158203125 +58352 -0.216796875 +58353 -0.055633544921875 +58354 -0.128265380859375 +58355 -0.03228759765625 +58356 -0.068145751953125 +58357 -0.0164794921875 +58358 -0.0430908203125 +58359 -0.009979248046875 +58360 -0.024444580078125 +58361 -0.005218505859375 +58362 0.020721435546875 +58363 0.0064697265625 +58364 0.124481201171875 +58365 0.0335693359375 +58366 0.25787353515625 +58367 0.068450927734375 +58368 0.379119873046875 +58369 0.100677490234375 +58370 0.47991943359375 +58371 0.127899169921875 +58372 0.5281982421875 +58373 0.140289306640625 +58374 0.511138916015625 +58375 0.134246826171875 +58376 0.456207275390625 +58377 0.118011474609375 +58378 0.407470703125 +58379 0.104644775390625 +58380 0.383758544921875 +58381 0.099639892578125 +58382 0.35687255859375 +58383 0.094482421875 +58384 0.31182861328125 +58385 0.0845947265625 +58386 0.250885009765625 +58387 0.070404052734375 +58388 0.1654052734375 +58389 0.04913330078125 +58390 0.035247802734375 +58391 0.01458740234375 +58392 -0.142059326171875 +58393 -0.0341796875 +58394 -0.33563232421875 +58395 -0.0882568359375 +58396 -0.5345458984375 +58397 -0.14453125 +58398 -0.72186279296875 +58399 -0.198150634765625 +58400 -0.836669921875 +58401 -0.23114013671875 +58402 -0.8326416015625 +58403 -0.2298583984375 +58404 -0.7296142578125 +58405 -0.200164794921875 +58406 -0.582550048828125 +58407 -0.15826416015625 +58408 -0.440093994140625 +58409 -0.118438720703125 +58410 -0.324310302734375 +58411 -0.08709716796875 +58412 -0.20147705078125 +58413 -0.054046630859375 +58414 -0.044647216796875 +58415 -0.0111083984375 +58416 0.103973388671875 +58417 0.029388427734375 +58418 0.202392578125 +58419 0.055206298828125 +58420 0.264495849609375 +58421 0.07061767578125 +58422 0.338897705078125 +58423 0.09014892578125 +58424 0.443817138671875 +58425 0.11932373046875 +58426 0.545074462890625 +58427 0.14813232421875 +58428 0.6173095703125 +58429 0.169097900390625 +58430 0.6524658203125 +58431 0.179840087890625 +58432 0.66339111328125 +58433 0.184112548828125 +58434 0.6561279296875 +58435 0.183624267578125 +58436 0.606781005859375 +58437 0.171173095703125 +58438 0.501190185546875 +58439 0.1424560546875 +58440 0.352783203125 +58441 0.101318359375 +58442 0.176544189453125 +58443 0.052001953125 +58444 -0.034820556640625 +58445 -0.00775146484375 +58446 -0.258209228515625 +58447 -0.07122802734375 +58448 -0.44244384765625 +58449 -0.1234130859375 +58450 -0.5753173828125 +58451 -0.160858154296875 +58452 -0.65203857421875 +58453 -0.182220458984375 +58454 -0.641632080078125 +58455 -0.178375244140625 +58456 -0.562164306640625 +58457 -0.154754638671875 +58458 -0.458038330078125 +58459 -0.124481201171875 +58460 -0.350555419921875 +58461 -0.093780517578125 +58462 -0.260528564453125 +58463 -0.0687255859375 +58464 -0.192108154296875 +58465 -0.05047607421875 +58466 -0.141937255859375 +58467 -0.03790283203125 +58468 -0.1021728515625 +58469 -0.028564453125 +58470 -0.062896728515625 +58471 -0.01934814453125 +58472 -0.011932373046875 +58473 -0.006561279296875 +58474 0.062835693359375 +58475 0.013519287109375 +58476 0.148712158203125 +58477 0.0372314453125 +58478 0.241729736328125 +58479 0.0634765625 +58480 0.34912109375 +58481 0.09442138671875 +58482 0.457305908203125 +58483 0.126129150390625 +58484 0.54388427734375 +58485 0.151947021484375 +58486 0.5728759765625 +58487 0.16119384765625 +58488 0.506591796875 +58489 0.142669677734375 +58490 0.351226806640625 +58491 0.09814453125 +58492 0.146514892578125 +58493 0.039276123046875 +58494 -0.05523681640625 +58495 -0.01849365234375 +58496 -0.21624755859375 +58497 -0.064117431640625 +58498 -0.334930419921875 +58499 -0.09722900390625 +58500 -0.402984619140625 +58501 -0.115478515625 +58502 -0.4412841796875 +58503 -0.1251220703125 +58504 -0.49578857421875 +58505 -0.139892578125 +58506 -0.5601806640625 +58507 -0.157958984375 +58508 -0.600738525390625 +58509 -0.169403076171875 +58510 -0.584228515625 +58511 -0.164398193359375 +58512 -0.47930908203125 +58513 -0.1336669921875 +58514 -0.27935791015625 +58515 -0.075225830078125 +58516 -0.0089111328125 +58517 0.003662109375 +58518 0.268798828125 +58519 0.0843505859375 +58520 0.482818603515625 +58521 0.145965576171875 +58522 0.60369873046875 +58523 0.17987060546875 +58524 0.650421142578125 +58525 0.191802978515625 +58526 0.66400146484375 +58527 0.194000244140625 +58528 0.6414794921875 +58529 0.185699462890625 +58530 0.572540283203125 +58531 0.1639404296875 +58532 0.498138427734375 +58533 0.140899658203125 +58534 0.439453125 +58535 0.1229248046875 +58536 0.375518798828125 +58537 0.10382080078125 +58538 0.274505615234375 +58539 0.07415771484375 +58540 0.1087646484375 +58541 0.025726318359375 +58542 -0.099395751953125 +58543 -0.034912109375 +58544 -0.3182373046875 +58545 -0.098388671875 +58546 -0.5489501953125 +58547 -0.165191650390625 +58548 -0.7738037109375 +58549 -0.2301025390625 +58550 -0.86383056640625 +58551 -0.277557373046875 +58552 -0.870391845703125 +58553 -0.297821044921875 +58554 -0.86895751953125 +58555 -0.296234130859375 +58556 -0.861053466796875 +58557 -0.276763916015625 +58558 -0.765869140625 +58559 -0.234344482421875 +58560 -0.5301513671875 +58561 -0.165679931640625 +58562 -0.214691162109375 +58563 -0.072906494140625 +58564 0.137359619140625 +58565 0.031219482421875 +58566 0.474822998046875 +58567 0.13153076171875 +58568 0.76239013671875 +58569 0.217559814453125 +58570 0.867462158203125 +58571 0.281341552734375 +58572 0.870361328125 +58573 0.323089599609375 +58574 0.86480712890625 +58575 0.339447021484375 +58576 0.831817626953125 +58577 0.332061767578125 +58578 0.677581787109375 +58579 0.308258056640625 +58580 0.495880126953125 +58581 0.269805908203125 +58582 0.30767822265625 +58583 0.2222900390625 +58584 0.116180419921875 +58585 0.166412353515625 +58586 -0.110748291015625 +58587 0.09283447265625 +58588 -0.381805419921875 +58589 -0.000457763671875 +58590 -0.6572265625 +58591 -0.10076904296875 +58592 -0.857421875 +58593 -0.19036865234375 +58594 -0.870391845703125 +58595 -0.256591796875 +58596 -0.870391845703125 +58597 -0.29736328125 +58598 -0.86444091796875 +58599 -0.320709228515625 +58600 -0.85723876953125 +58601 -0.337249755859375 +58602 -0.790008544921875 +58603 -0.341644287109375 +58604 -0.62847900390625 +58605 -0.31787109375 +58606 -0.3956298828125 +58607 -0.26507568359375 +58608 -0.126708984375 +58609 -0.19305419921875 +58610 0.150115966796875 +58611 -0.109954833984375 +58612 0.424041748046875 +58613 -0.019317626953125 +58614 0.670623779296875 +58615 0.070831298828125 +58616 0.854522705078125 +58617 0.149017333984375 +58618 0.866485595703125 +58619 0.21002197265625 +58620 0.86920166015625 +58621 0.249298095703125 +58622 0.8653564453125 +58623 0.272247314453125 +58624 0.857147216796875 +58625 0.282623291015625 +58626 0.766845703125 +58627 0.2799072265625 +58628 0.628509521484375 +58629 0.266021728515625 +58630 0.462127685546875 +58631 0.23870849609375 +58632 0.297210693359375 +58633 0.20635986328125 +58634 0.14862060546875 +58635 0.17279052734375 +58636 -0.00537109375 +58637 0.130279541015625 +58638 -0.15753173828125 +58639 0.080963134765625 +58640 -0.31304931640625 +58641 0.023345947265625 +58642 -0.48876953125 +58643 -0.04754638671875 +58644 -0.6416015625 +58645 -0.11663818359375 +58646 -0.751373291015625 +58647 -0.176116943359375 +58648 -0.84619140625 +58649 -0.233795166015625 +58650 -0.861297607421875 +58651 -0.285064697265625 +58652 -0.863250732421875 +58653 -0.319183349609375 +58654 -0.856597900390625 +58655 -0.3258056640625 +58656 -0.7498779296875 +58657 -0.30889892578125 +58658 -0.624542236328125 +58659 -0.287353515625 +58660 -0.47808837890625 +58661 -0.2537841796875 +58662 -0.253387451171875 +58663 -0.1888427734375 +58664 0.003692626953125 +58665 -0.10723876953125 +58666 0.2257080078125 +58667 -0.0311279296875 +58668 0.427154541015625 +58669 0.04388427734375 +58670 0.643218994140625 +58671 0.128662109375 +58672 0.855926513671875 +58673 0.220306396484375 +58674 0.870361328125 +58675 0.300018310546875 +58676 0.870361328125 +58677 0.3516845703125 +58678 0.862762451171875 +58679 0.377777099609375 +58680 0.79669189453125 +58681 0.37738037109375 +58682 0.595794677734375 +58683 0.347412109375 +58684 0.362152099609375 +58685 0.29742431640625 +58686 0.1270751953125 +58687 0.2364501953125 +58688 -0.086944580078125 +58689 0.171295166015625 +58690 -0.2784423828125 +58691 0.10247802734375 +58692 -0.484832763671875 +58693 0.018402099609375 +58694 -0.729583740234375 +58695 -0.087432861328125 +58696 -0.86688232421875 +58697 -0.19866943359375 +58698 -0.870391845703125 +58699 -0.294708251953125 +58700 -0.86859130859375 +58701 -0.37408447265625 +58702 -0.86279296875 +58703 -0.43621826171875 +58704 -0.817962646484375 +58705 -0.46942138671875 +58706 -0.6116943359375 +58707 -0.4588623046875 +58708 -0.3128662109375 +58709 -0.402191162109375 +58710 0.039398193359375 +58711 -0.310455322265625 +58712 0.422821044921875 +58713 -0.190155029296875 +58714 0.805145263671875 +58715 -0.0521240234375 +58716 0.870361328125 +58717 0.081390380859375 +58718 0.870361328125 +58719 0.191802978515625 +58720 0.860015869140625 +58721 0.275421142578125 +58722 0.727935791015625 +58723 0.329803466796875 +58724 0.48114013671875 +58725 0.353179931640625 +58726 0.2059326171875 +58727 0.35357666015625 +58728 -0.06103515625 +58729 0.3385009765625 +58730 -0.29913330078125 +58731 0.311248779296875 +58732 -0.516204833984375 +58733 0.26708984375 +58734 -0.7252197265625 +58735 0.2010498046875 +58736 -0.85980224609375 +58737 0.12127685546875 +58738 -0.870391845703125 +58739 0.0390625 +58740 -0.870391845703125 +58741 -0.035858154296875 +58742 -0.858062744140625 +58743 -0.087493896484375 +58744 -0.673004150390625 +58745 -0.11444091796875 +58746 -0.42694091796875 +58747 -0.133941650390625 +58748 -0.2100830078125 +58749 -0.16046142578125 +58750 -0.0362548828125 +58751 -0.193267822265625 +58752 0.10943603515625 +58753 -0.222808837890625 +58754 0.23516845703125 +58755 -0.242523193359375 +58756 0.373687744140625 +58757 -0.23883056640625 +58758 0.517791748046875 +58759 -0.212371826171875 +58760 0.602783203125 +58761 -0.183807373046875 +58762 0.635711669921875 +58763 -0.1514892578125 +58764 0.655181884765625 +58765 -0.10455322265625 +58766 0.65948486328125 +58767 -0.04632568359375 +58768 0.651275634765625 +58769 0.020477294921875 +58770 0.61846923828125 +58771 0.087738037109375 +58772 0.53753662109375 +58773 0.143218994140625 +58774 0.404144287109375 +58775 0.180938720703125 +58776 0.22186279296875 +58777 0.1976318359375 +58778 0.003997802734375 +58779 0.19366455078125 +58780 -0.22100830078125 +58781 0.1749267578125 +58782 -0.42449951171875 +58783 0.148162841796875 +58784 -0.579833984375 +58785 0.120391845703125 +58786 -0.641876220703125 +58787 0.105621337890625 +58788 -0.6177978515625 +58789 0.1016845703125 +58790 -0.575531005859375 +58791 0.08746337890625 +58792 -0.526336669921875 +58793 0.061248779296875 +58794 -0.42645263671875 +58795 0.04010009765625 +58796 -0.2581787109375 +58797 0.0330810546875 +58798 -0.068695068359375 +58799 0.02838134765625 +58800 0.09222412109375 +58801 0.013458251953125 +58802 0.232147216796875 +58803 -0.0054931640625 +58804 0.3509521484375 +58805 -0.0250244140625 +58806 0.410064697265625 +58807 -0.0548095703125 +58808 0.372955322265625 +58809 -0.1043701171875 +58810 0.2554931640625 +58811 -0.16680908203125 +58812 0.10711669921875 +58813 -0.225006103515625 +58814 -0.052886962890625 +58815 -0.27252197265625 +58816 -0.186279296875 +58817 -0.2974853515625 +58818 -0.23291015625 +58819 -0.2816162109375 +58820 -0.209442138671875 +58821 -0.232452392578125 +58822 -0.174163818359375 +58823 -0.171630859375 +58824 -0.126739501953125 +58825 -0.10198974609375 +58826 -0.048126220703125 +58827 -0.020355224609375 +58828 0.0426025390625 +58829 0.063873291015625 +58830 0.10748291015625 +58831 0.135345458984375 +58832 0.1409912109375 +58833 0.189605712890625 +58834 0.19708251953125 +58835 0.2421875 +58836 0.273651123046875 +58837 0.29083251953125 +58838 0.31768798828125 +58839 0.317169189453125 +58840 0.341094970703125 +58841 0.32476806640625 +58842 0.368011474609375 +58843 0.321929931640625 +58844 0.37249755859375 +58845 0.301116943359375 +58846 0.30072021484375 +58847 0.246185302734375 +58848 0.1517333984375 +58849 0.15875244140625 +58850 -0.01470947265625 +58851 0.060760498046875 +58852 -0.1883544921875 +58853 -0.041900634765625 +58854 -0.372711181640625 +58855 -0.147796630859375 +58856 -0.51397705078125 +58857 -0.236846923828125 +58858 -0.57177734375 +58859 -0.293548583984375 +58860 -0.53948974609375 +58861 -0.313812255859375 +58862 -0.43511962890625 +58863 -0.30206298828125 +58864 -0.2962646484375 +58865 -0.2696533203125 +58866 -0.161102294921875 +58867 -0.228668212890625 +58868 -0.0435791015625 +58869 -0.183746337890625 +58870 0.060394287109375 +58871 -0.134185791015625 +58872 0.13665771484375 +58873 -0.08575439453125 +58874 0.170135498046875 +58875 -0.04486083984375 +58876 0.16552734375 +58877 -0.01177978515625 +58878 0.15728759765625 +58879 0.022705078125 +58880 0.150787353515625 +58881 0.058074951171875 +58882 0.12200927734375 +58883 0.0843505859375 +58884 0.080108642578125 +58885 0.10296630859375 +58886 0.05126953125 +58887 0.121185302734375 +58888 0.062896728515625 +58889 0.147125244140625 +58890 0.09271240234375 +58891 0.171905517578125 +58892 0.092987060546875 +58893 0.17822265625 +58894 0.07855224609375 +58895 0.171142578125 +58896 0.06427001953125 +58897 0.15625 +58898 0.0347900390625 +58899 0.12890625 +58900 -0.01171875 +58901 0.089630126953125 +58902 -0.056060791015625 +58903 0.04656982421875 +58904 -0.055511474609375 +58905 0.016326904296875 +58906 -0.010467529296875 +58907 0.00054931640625 +58908 0.02508544921875 +58909 -0.017852783203125 +58910 0.025665283203125 +58911 -0.046142578125 +58912 0.017333984375 +58913 -0.073699951171875 +58914 0.00189208984375 +58915 -0.098663330078125 +58916 -0.03173828125 +58917 -0.123992919921875 +58918 -0.071502685546875 +58919 -0.144927978515625 +58920 -0.13543701171875 +58921 -0.16754150390625 +58922 -0.219970703125 +58923 -0.1907958984375 +58924 -0.300506591796875 +58925 -0.20660400390625 +58926 -0.376312255859375 +58927 -0.21551513671875 +58928 -0.416107177734375 +58929 -0.207733154296875 +58930 -0.371124267578125 +58931 -0.16748046875 +58932 -0.242279052734375 +58933 -0.09649658203125 +58934 -0.069732666015625 +58935 -0.01031494140625 +58936 0.125640869140625 +58937 0.082305908203125 +58938 0.31268310546875 +58939 0.169219970703125 +58940 0.45501708984375 +58941 0.236572265625 +58942 0.554779052734375 +58943 0.2843017578125 +58944 0.61065673828125 +58945 0.3114013671875 +58946 0.610931396484375 +58947 0.313507080078125 +58948 0.531463623046875 +58949 0.282196044921875 +58950 0.3883056640625 +58951 0.223480224609375 +58952 0.23468017578125 +58953 0.15655517578125 +58954 0.095245361328125 +58955 0.0909423828125 +58956 -0.00396728515625 +58957 0.036773681640625 +58958 -0.04852294921875 +58959 0.00018310546875 +58960 -0.055145263671875 +58961 -0.0234375 +58962 -0.0758056640625 +58963 -0.051116943359375 +58964 -0.138702392578125 +58965 -0.091644287109375 +58966 -0.209197998046875 +58967 -0.131927490234375 +58968 -0.289031982421875 +58969 -0.17181396484375 +58970 -0.37884521484375 +58971 -0.210968017578125 +58972 -0.456329345703125 +58973 -0.241302490234375 +58974 -0.51641845703125 +58975 -0.260986328125 +58976 -0.519287109375 +58977 -0.256256103515625 +58978 -0.458251953125 +58979 -0.225250244140625 +58980 -0.384796142578125 +58981 -0.186614990234375 +58982 -0.323699951171875 +58983 -0.14984130859375 +58984 -0.269287109375 +58985 -0.11383056640625 +58986 -0.1951904296875 +58987 -0.0703125 +58988 -0.100006103515625 +58989 -0.019805908203125 +58990 -0.01055908203125 +58991 0.027374267578125 +58992 0.1033935546875 +58993 0.080963134765625 +58994 0.24908447265625 +58995 0.142852783203125 +58996 0.373199462890625 +58997 0.19384765625 +58998 0.45806884765625 +58999 0.227447509765625 +59000 0.511474609375 +59001 0.24627685546875 +59002 0.565399169921875 +59003 0.261627197265625 +59004 0.61138916015625 +59005 0.27081298828125 +59006 0.5897216796875 +59007 0.25341796875 +59008 0.4906005859375 +59009 0.20660400390625 +59010 0.33148193359375 +59011 0.137237548828125 +59012 0.147796630859375 +59013 0.058502197265625 +59014 -0.01873779296875 +59015 -0.01416015625 +59016 -0.140289306640625 +59017 -0.070220947265625 +59018 -0.191986083984375 +59019 -0.10028076171875 +59020 -0.184295654296875 +59021 -0.107391357421875 +59022 -0.161834716796875 +59023 -0.106689453125 +59024 -0.166595458984375 +59025 -0.112548828125 +59026 -0.19390869140625 +59027 -0.123199462890625 +59028 -0.22442626953125 +59029 -0.13189697265625 +59030 -0.279754638671875 +59031 -0.146392822265625 +59032 -0.3389892578125 +59033 -0.15972900390625 +59034 -0.3543701171875 +59035 -0.155670166015625 +59036 -0.348175048828125 +59037 -0.142578125 +59038 -0.32598876953125 +59039 -0.123077392578125 +59040 -0.2581787109375 +59041 -0.08746337890625 +59042 -0.139801025390625 +59043 -0.034637451171875 +59044 0.014617919921875 +59045 0.02972412109375 +59046 0.144378662109375 +59047 0.08380126953125 +59048 0.221038818359375 +59049 0.117218017578125 +59050 0.27069091796875 +59051 0.1387939453125 +59052 0.294036865234375 +59053 0.148651123046875 +59054 0.311767578125 +59055 0.154022216796875 +59056 0.339141845703125 +59057 0.160400390625 +59058 0.360260009765625 +59059 0.162567138671875 +59060 0.360504150390625 +59061 0.155731201171875 +59062 0.308380126953125 +59063 0.128936767578125 +59064 0.18170166015625 +59065 0.074615478515625 +59066 0.0047607421875 +59067 0.00201416015625 +59068 -0.17559814453125 +59069 -0.071502685546875 +59070 -0.3143310546875 +59071 -0.129302978515625 +59072 -0.36785888671875 +59073 -0.155303955078125 +59074 -0.36248779296875 +59075 -0.15869140625 +59076 -0.343536376953125 +59077 -0.155487060546875 +59078 -0.3018798828125 +59079 -0.142303466796875 +59080 -0.231414794921875 +59081 -0.11688232421875 +59082 -0.117645263671875 +59083 -0.07403564453125 +59084 0.007049560546875 +59085 -0.02557373046875 +59086 0.087982177734375 +59087 0.008575439453125 +59088 0.13946533203125 +59089 0.033233642578125 +59090 0.17425537109375 +59091 0.052642822265625 +59092 0.188201904296875 +59093 0.06488037109375 +59094 0.171234130859375 +59095 0.06591796875 +59096 0.118438720703125 +59097 0.0535888671875 +59098 0.05706787109375 +59099 0.03741455078125 +59100 -0.010711669921875 +59101 0.017822265625 +59102 -0.0914306640625 +59103 -0.007720947265625 +59104 -0.162322998046875 +59105 -0.03118896484375 +59106 -0.194549560546875 +59107 -0.042266845703125 +59108 -0.1492919921875 +59109 -0.026947021484375 +59110 -0.02166748046875 +59111 0.016571044921875 +59112 0.124053955078125 +59113 0.065338134765625 +59114 0.211151123046875 +59115 0.091949462890625 +59116 0.240447998046875 +59117 0.097015380859375 +59118 0.242218017578125 +59119 0.091766357421875 +59120 0.2257080078125 +59121 0.079864501953125 +59122 0.194366455078125 +59123 0.062896728515625 +59124 0.115509033203125 +59125 0.02935791015625 +59126 0.0128173828125 +59127 -0.01190185546875 +59128 -0.053802490234375 +59129 -0.039093017578125 +59130 -0.110626220703125 +59131 -0.061553955078125 +59132 -0.199493408203125 +59133 -0.094268798828125 +59134 -0.29437255859375 +59135 -0.12786865234375 +59136 -0.33221435546875 +59137 -0.139373779296875 +59138 -0.27972412109375 +59139 -0.116180419921875 +59140 -0.185333251953125 +59141 -0.076995849609375 +59142 -0.128204345703125 +59143 -0.052642822265625 +59144 -0.115692138671875 +59145 -0.0458984375 +59146 -0.116455078125 +59147 -0.044403076171875 +59148 -0.105926513671875 +59149 -0.038543701171875 +59150 -0.053955078125 +59151 -0.016510009765625 +59152 0.048797607421875 +59153 0.025238037109375 +59154 0.157318115234375 +59155 0.06903076171875 +59156 0.212005615234375 +59157 0.0914306640625 +59158 0.218475341796875 +59159 0.0946044921875 +59160 0.23724365234375 +59161 0.102203369140625 +59162 0.30535888671875 +59163 0.12872314453125 +59164 0.38128662109375 +59165 0.157867431640625 +59166 0.404449462890625 +59167 0.165924072265625 +59168 0.3944091796875 +59169 0.160614013671875 +59170 0.3885498046875 +59171 0.15667724609375 +59172 0.362640380859375 +59173 0.144683837890625 +59174 0.27362060546875 +59175 0.10784912109375 +59176 0.11712646484375 +59177 0.044586181640625 +59178 -0.054901123046875 +59179 -0.024627685546875 +59180 -0.19085693359375 +59181 -0.079437255859375 +59182 -0.28570556640625 +59183 -0.1177978515625 +59184 -0.339263916015625 +59185 -0.139617919921875 +59186 -0.3775634765625 +59187 -0.155029296875 +59188 -0.445709228515625 +59189 -0.1817626953125 +59190 -0.535064697265625 +59191 -0.2164306640625 +59192 -0.629058837890625 +59193 -0.252532958984375 +59194 -0.697601318359375 +59195 -0.2783203125 +59196 -0.70391845703125 +59197 -0.279449462890625 +59198 -0.6424560546875 +59199 -0.25384521484375 +59200 -0.491241455078125 +59201 -0.1929931640625 +59202 -0.265716552734375 +59203 -0.10302734375 +59204 -0.023712158203125 +59205 -0.006683349609375 +59206 0.201751708984375 +59207 0.082977294921875 +59208 0.375823974609375 +59209 0.152252197265625 +59210 0.485076904296875 +59211 0.19580078125 +59212 0.56884765625 +59213 0.229034423828125 +59214 0.634765625 +59215 0.25494384765625 +59216 0.63763427734375 +59217 0.25579833984375 +59218 0.5660400390625 +59219 0.227142333984375 +59220 0.4720458984375 +59221 0.189422607421875 +59222 0.40692138671875 +59223 0.16278076171875 +59224 0.3778076171875 +59225 0.150115966796875 +59226 0.376953125 +59227 0.1484375 +59228 0.371978759765625 +59229 0.1451416015625 +59230 0.313140869140625 +59231 0.12078857421875 +59232 0.184417724609375 +59233 0.06915283203125 +59234 0.011199951171875 +59235 0.000274658203125 +59236 -0.171051025390625 +59237 -0.071868896484375 +59238 -0.33740234375 +59239 -0.137451171875 +59240 -0.47198486328125 +59241 -0.19024658203125 +59242 -0.560394287109375 +59243 -0.224639892578125 +59244 -0.58056640625 +59245 -0.23199462890625 +59246 -0.54754638671875 +59247 -0.21826171875 +59248 -0.508575439453125 +59249 -0.2020263671875 +59250 -0.459503173828125 +59251 -0.18170166015625 +59252 -0.394378662109375 +59253 -0.155029296875 +59254 -0.35260009765625 +59255 -0.137481689453125 +59256 -0.31170654296875 +59257 -0.120330810546875 +59258 -0.197418212890625 +59259 -0.07452392578125 +59260 -0.007965087890625 +59261 0.00054931640625 +59262 0.207489013671875 +59263 0.0855712890625 +59264 0.409210205078125 +59265 0.164947509765625 +59266 0.57208251953125 +59267 0.228851318359375 +59268 0.66595458984375 +59269 0.26544189453125 +59270 0.65875244140625 +59271 0.262176513671875 +59272 0.56744384765625 +59273 0.22576904296875 +59274 0.431396484375 +59275 0.171661376953125 +59276 0.29443359375 +59277 0.1170654296875 +59278 0.182464599609375 +59279 0.07220458984375 +59280 0.06365966796875 +59281 0.024658203125 +59282 -0.075958251953125 +59283 -0.030975341796875 +59284 -0.189422607421875 +59285 -0.076263427734375 +59286 -0.271942138671875 +59287 -0.1092529296875 +59288 -0.342529296875 +59289 -0.13739013671875 +59290 -0.364166259765625 +59291 -0.14617919921875 +59292 -0.327239990234375 +59293 -0.131805419921875 +59294 -0.2769775390625 +59295 -0.11199951171875 +59296 -0.253692626953125 +59297 -0.10260009765625 +59298 -0.24365234375 +59299 -0.09820556640625 +59300 -0.1983642578125 +59301 -0.079833984375 +59302 -0.116241455078125 +59303 -0.04693603515625 +59304 -0.036834716796875 +59305 -0.0150146484375 +59306 0.034881591796875 +59307 0.013885498046875 +59308 0.09124755859375 +59309 0.036712646484375 +59310 0.10888671875 +59311 0.0443115234375 +59312 0.125518798828125 +59313 0.051422119140625 +59314 0.15771484375 +59315 0.064483642578125 +59316 0.17828369140625 +59317 0.07281494140625 +59318 0.17108154296875 +59319 0.070068359375 +59320 0.129974365234375 +59321 0.05389404296875 +59322 0.082427978515625 +59323 0.0350341796875 +59324 0.027679443359375 +59325 0.013214111328125 +59326 -0.065643310546875 +59327 -0.0238037109375 +59328 -0.15936279296875 +59329 -0.06103515625 +59330 -0.21307373046875 +59331 -0.082611083984375 +59332 -0.234649658203125 +59333 -0.09161376953125 +59334 -0.2001953125 +59335 -0.078643798828125 +59336 -0.119171142578125 +59337 -0.04736328125 +59338 -0.024749755859375 +59339 -0.010772705078125 +59340 0.085784912109375 +59341 0.032196044921875 +59342 0.178131103515625 +59343 0.068115234375 +59344 0.215576171875 +59345 0.082611083984375 +59346 0.211456298828125 +59347 0.08087158203125 +59348 0.17523193359375 +59349 0.066680908203125 +59350 0.128753662109375 +59351 0.048583984375 +59352 0.1019287109375 +59353 0.038299560546875 +59354 0.0743408203125 +59355 0.02783203125 +59356 0.04327392578125 +59357 0.01605224609375 +59358 0.038177490234375 +59359 0.01446533203125 +59360 0.076263427734375 +59361 0.029815673828125 +59362 0.14105224609375 +59363 0.05560302734375 +59364 0.186431884765625 +59365 0.073760986328125 +59366 0.188812255859375 +59367 0.07501220703125 +59368 0.1390380859375 +59369 0.055755615234375 +59370 0.041778564453125 +59371 0.017822265625 +59372 -0.079437255859375 +59373 -0.029571533203125 +59374 -0.219390869140625 +59375 -0.084381103515625 +59376 -0.367828369140625 +59377 -0.142578125 +59378 -0.494873046875 +59379 -0.19244384765625 +59380 -0.556243896484375 +59381 -0.21661376953125 +59382 -0.508697509765625 +59383 -0.198150634765625 +59384 -0.3756103515625 +59385 -0.14617919921875 +59386 -0.218902587890625 +59387 -0.084991455078125 +59388 -0.063751220703125 +59389 -0.0244140625 +59390 0.091552734375 +59391 0.036163330078125 +59392 0.23602294921875 +59393 0.092529296875 +59394 0.342987060546875 +59395 0.13421630859375 +59396 0.39520263671875 +59397 0.15423583984375 +59398 0.389373779296875 +59399 0.1510009765625 +59400 0.324249267578125 +59401 0.123748779296875 +59402 0.224090576171875 +59403 0.08258056640625 +59404 0.124267578125 +59405 0.042236328125 +59406 0.037078857421875 +59407 0.007720947265625 +59408 -0.010101318359375 +59409 -0.009521484375 +59410 -0.019439697265625 +59411 -0.010589599609375 +59412 -0.022796630859375 +59413 -0.0091552734375 +59414 -0.001556396484375 +59415 0.002471923828125 +59416 0.056304931640625 +59417 0.029266357421875 +59418 0.106719970703125 +59419 0.052459716796875 +59420 0.096893310546875 +59421 0.049591064453125 +59422 0.042694091796875 +59423 0.027374267578125 +59424 -0.018035888671875 +59425 0.001800537109375 +59426 -0.07586669921875 +59427 -0.0230712890625 +59428 -0.11944580078125 +59429 -0.042388916015625 +59430 -0.15972900390625 +59431 -0.06072998046875 +59432 -0.202606201171875 +59433 -0.080474853515625 +59434 -0.24859619140625 +59435 -0.10174560546875 +59436 -0.30517578125 +59437 -0.12762451171875 +59438 -0.36212158203125 +59439 -0.153656005859375 +59440 -0.39141845703125 +59441 -0.167877197265625 +59442 -0.35528564453125 +59443 -0.1541748046875 +59444 -0.249969482421875 +59445 -0.11090087890625 +59446 -0.092864990234375 +59447 -0.04534912109375 +59448 0.08905029296875 +59449 0.03106689453125 +59450 0.2352294921875 +59451 0.09271240234375 +59452 0.318817138671875 +59453 0.12823486328125 +59454 0.358642578125 +59455 0.14556884765625 +59456 0.347747802734375 +59457 0.141754150390625 +59458 0.28564453125 +59459 0.116546630859375 +59460 0.223175048828125 +59461 0.091400146484375 +59462 0.196746826171875 +59463 0.0816650390625 +59464 0.179840087890625 +59465 0.076019287109375 +59466 0.155548095703125 +59467 0.067230224609375 +59468 0.151214599609375 +59469 0.0667724609375 +59470 0.156951904296875 +59471 0.070404052734375 +59472 0.13177490234375 +59473 0.0606689453125 +59474 0.100799560546875 +59475 0.048187255859375 +59476 0.087127685546875 +59477 0.042724609375 +59478 0.05487060546875 +59479 0.029083251953125 +59480 -0.009002685546875 +59481 0.001708984375 +59482 -0.10400390625 +59483 -0.03912353515625 +59484 -0.229400634765625 +59485 -0.09307861328125 +59486 -0.35552978515625 +59487 -0.14752197265625 +59488 -0.441925048828125 +59489 -0.18524169921875 +59490 -0.473846435546875 +59491 -0.199951171875 +59492 -0.464813232421875 +59493 -0.19732666015625 +59494 -0.419097900390625 +59495 -0.1790771484375 +59496 -0.334320068359375 +59497 -0.144134521484375 +59498 -0.227935791015625 +59499 -0.099853515625 +59500 -0.12347412109375 +59501 -0.056182861328125 +59502 -0.02764892578125 +59503 -0.01593017578125 +59504 0.077667236328125 +59505 0.028594970703125 +59506 0.2132568359375 +59507 0.086181640625 +59508 0.38885498046875 +59509 0.16094970703125 +59510 0.582794189453125 +59511 0.243682861328125 +59512 0.734039306640625 +59513 0.3084716796875 +59514 0.800140380859375 +59515 0.3372802734375 +59516 0.7783203125 +59517 0.328857421875 +59518 0.6651611328125 +59519 0.28173828125 +59520 0.45965576171875 +59521 0.195465087890625 +59522 0.199188232421875 +59523 0.085845947265625 +59524 -0.050689697265625 +59525 -0.019378662109375 +59526 -0.23297119140625 +59527 -0.096038818359375 +59528 -0.33013916015625 +59529 -0.136749267578125 +59530 -0.368408203125 +59531 -0.152679443359375 +59532 -0.378936767578125 +59533 -0.157012939453125 +59534 -0.376983642578125 +59535 -0.15625 +59536 -0.37969970703125 +59537 -0.157684326171875 +59538 -0.391510009765625 +59539 -0.16314697265625 +59540 -0.385345458984375 +59541 -0.1611328125 +59542 -0.3419189453125 +59543 -0.143402099609375 +59544 -0.28289794921875 +59545 -0.119110107421875 +59546 -0.251617431640625 +59547 -0.106597900390625 +59548 -0.266143798828125 +59549 -0.11346435546875 +59550 -0.273345947265625 +59551 -0.117156982421875 +59552 -0.216796875 +59553 -0.093719482421875 +59554 -0.128265380859375 +59555 -0.056549072265625 +59556 -0.068145751953125 +59557 -0.031280517578125 +59558 -0.0430908203125 +59559 -0.020721435546875 +59560 -0.024444580078125 +59561 -0.012725830078125 +59562 0.020721435546875 +59563 0.00665283203125 +59564 0.124481201171875 +59565 0.050994873046875 +59566 0.25787353515625 +59567 0.10797119140625 +59568 0.379119873046875 +59569 0.15985107421875 +59570 0.47991943359375 +59571 0.203094482421875 +59572 0.5281982421875 +59573 0.22406005859375 +59574 0.511138916015625 +59575 0.21728515625 +59576 0.456207275390625 +59577 0.194427490234375 +59578 0.407470703125 +59579 0.17413330078125 +59580 0.383758544921875 +59581 0.16436767578125 +59582 0.35687255859375 +59583 0.153167724609375 +59584 0.31182861328125 +59585 0.1341552734375 +59586 0.250885009765625 +59587 0.1082763671875 +59588 0.1654052734375 +59589 0.0718994140625 +59590 0.035247802734375 +59591 0.0164794921875 +59592 -0.142059326171875 +59593 -0.058990478515625 +59594 -0.33563232421875 +59595 -0.14141845703125 +59596 -0.5345458984375 +59597 -0.226104736328125 +59598 -0.72186279296875 +59599 -0.305877685546875 +59600 -0.836669921875 +59601 -0.3548583984375 +59602 -0.8326416015625 +59603 -0.353424072265625 +59604 -0.7296142578125 +59605 -0.309967041015625 +59606 -0.582550048828125 +59607 -0.247802734375 +59608 -0.440093994140625 +59609 -0.187530517578125 +59610 -0.324310302734375 +59611 -0.13848876953125 +59612 -0.20147705078125 +59613 -0.08636474609375 +59614 -0.044647216796875 +59615 -0.019744873046875 +59616 0.103973388671875 +59617 0.04345703125 +59618 0.202392578125 +59619 0.08538818359375 +59620 0.264495849609375 +59621 0.1119384765625 +59622 0.338897705078125 +59623 0.143707275390625 +59624 0.443817138671875 +59625 0.18841552734375 +59626 0.545074462890625 +59627 0.231536865234375 +59628 0.6173095703125 +59629 0.2623291015625 +59630 0.6524658203125 +59631 0.277374267578125 +59632 0.66339111328125 +59633 0.2821044921875 +59634 0.6561279296875 +59635 0.279052734375 +59636 0.606781005859375 +59637 0.258087158203125 +59638 0.501190185546875 +59639 0.213226318359375 +59640 0.352783203125 +59641 0.150177001953125 +59642 0.176544189453125 +59643 0.075286865234375 +59644 -0.034820556640625 +59645 -0.014495849609375 +59646 -0.258209228515625 +59647 -0.109375 +59648 -0.44244384765625 +59649 -0.18743896484375 +59650 -0.5753173828125 +59651 -0.24365234375 +59652 -0.65203857421875 +59653 -0.275848388671875 +59654 -0.641632080078125 +59655 -0.269866943359375 +59656 -0.562164306640625 +59657 -0.233856201171875 +59658 -0.458038330078125 +59659 -0.18792724609375 +59660 -0.350555419921875 +59661 -0.141571044921875 +59662 -0.260528564453125 +59663 -0.10406494140625 +59664 -0.192108154296875 +59665 -0.077056884765625 +59666 -0.141937255859375 +59667 -0.058746337890625 +59668 -0.1021728515625 +59669 -0.0452880859375 +59670 -0.062896728515625 +59671 -0.03192138671875 +59672 -0.011932373046875 +59673 -0.012847900390625 +59674 0.062835693359375 +59675 0.017669677734375 +59676 0.148712158203125 +59677 0.053985595703125 +59678 0.241729736328125 +59679 0.09442138671875 +59680 0.34912109375 +59681 0.142364501953125 +59682 0.457305908203125 +59683 0.191650390625 +59684 0.54388427734375 +59685 0.23199462890625 +59686 0.5728759765625 +59687 0.246917724609375 +59688 0.506591796875 +59689 0.2191162109375 +59690 0.351226806640625 +59691 0.151275634765625 +59692 0.146514892578125 +59693 0.06134033203125 +59694 -0.05523681640625 +59695 -0.027008056640625 +59696 -0.21624755859375 +59697 -0.09674072265625 +59698 -0.334930419921875 +59699 -0.147369384765625 +59700 -0.402984619140625 +59701 -0.17529296875 +59702 -0.4412841796875 +59703 -0.190155029296875 +59704 -0.49578857421875 +59705 -0.21307373046875 +59706 -0.5601806640625 +59707 -0.241241455078125 +59708 -0.600738525390625 +59709 -0.25933837890625 +59710 -0.584228515625 +59711 -0.252227783203125 +59712 -0.47930908203125 +59713 -0.20556640625 +59714 -0.27935791015625 +59715 -0.11627197265625 +59716 -0.0089111328125 +59717 0.00457763671875 +59718 0.268798828125 +59719 0.128326416015625 +59720 0.482818603515625 +59721 0.222808837890625 +59722 0.60369873046875 +59723 0.2747802734375 +59724 0.650421142578125 +59725 0.293060302734375 +59726 0.66400146484375 +59727 0.2965087890625 +59728 0.6414794921875 +59729 0.283905029296875 +59730 0.572540283203125 +59731 0.25067138671875 +59732 0.498138427734375 +59733 0.215545654296875 +59734 0.439453125 +59735 0.188262939453125 +59736 0.375518798828125 +59737 0.159271240234375 +59738 0.274505615234375 +59739 0.114044189453125 +59740 0.1087646484375 +59741 0.039886474609375 +59742 -0.099395751953125 +59743 -0.053131103515625 +59744 -0.3182373046875 +59745 -0.150634765625 +59746 -0.5489501953125 +59747 -0.2532958984375 +59748 -0.7738037109375 +59749 -0.353179931640625 +59750 -0.86383056640625 +59751 -0.42626953125 +59752 -0.870391845703125 +59753 -0.457550048828125 +59754 -0.86895751953125 +59755 -0.455230712890625 +59756 -0.861053466796875 +59757 -0.4254150390625 +59758 -0.765869140625 +59759 -0.36029052734375 +59760 -0.5301513671875 +59761 -0.2547607421875 +59762 -0.214691162109375 +59763 -0.112091064453125 +59764 0.137359619140625 +59765 0.048065185546875 +59766 0.474822998046875 +59767 0.202362060546875 +59768 0.76239013671875 +59769 0.33465576171875 +59770 0.867462158203125 +59771 0.432708740234375 +59772 0.870361328125 +59773 0.496856689453125 +59774 0.86480712890625 +59775 0.52197265625 +59776 0.831817626953125 +59777 0.510589599609375 +59778 0.677581787109375 +59779 0.473968505859375 +59780 0.495880126953125 +59781 0.41485595703125 +59782 0.30767822265625 +59783 0.341827392578125 +59784 0.116180419921875 +59785 0.255950927734375 +59786 -0.110748291015625 +59787 0.142822265625 +59788 -0.381805419921875 +59789 -0.000640869140625 +59790 -0.6572265625 +59791 -0.15496826171875 +59792 -0.857421875 +59793 -0.2928466796875 +59794 -0.870391845703125 +59795 -0.394775390625 +59796 -0.870391845703125 +59797 -0.45758056640625 +59798 -0.86444091796875 +59799 -0.493621826171875 +59800 -0.85723876953125 +59801 -0.519256591796875 +59802 -0.790008544921875 +59803 -0.526214599609375 +59804 -0.62847900390625 +59805 -0.489837646484375 +59806 -0.3956298828125 +59807 -0.40875244140625 +59808 -0.126708984375 +59809 -0.298004150390625 +59810 0.150115966796875 +59811 -0.170196533203125 +59812 0.424041748046875 +59813 -0.030731201171875 +59814 0.670623779296875 +59815 0.108062744140625 +59816 0.854522705078125 +59817 0.228485107421875 +59818 0.866485595703125 +59819 0.322479248046875 +59820 0.86920166015625 +59821 0.383087158203125 +59822 0.8653564453125 +59823 0.418609619140625 +59824 0.857147216796875 +59825 0.435211181640625 +59826 0.766845703125 +59827 0.431640625 +59828 0.628509521484375 +59829 0.410308837890625 +59830 0.462127685546875 +59831 0.36822509765625 +59832 0.297210693359375 +59833 0.3172607421875 +59834 0.14862060546875 +59835 0.26312255859375 +59836 -0.00537109375 +59837 0.195465087890625 +59838 -0.15753173828125 +59839 0.117767333984375 +59840 -0.31304931640625 +59841 0.0284423828125 +59842 -0.48876953125 +59843 -0.078887939453125 +59844 -0.6416015625 +59845 -0.182830810546875 +59846 -0.751373291015625 +59847 -0.2720947265625 +59848 -0.84619140625 +59849 -0.35723876953125 +59850 -0.861297607421875 +59851 -0.43157958984375 +59852 -0.863250732421875 +59853 -0.480072021484375 +59854 -0.856597900390625 +59855 -0.488372802734375 +59856 -0.7498779296875 +59857 -0.462066650390625 +59858 -0.624542236328125 +59859 -0.427642822265625 +59860 -0.47808837890625 +59861 -0.375152587890625 +59862 -0.253387451171875 +59863 -0.277984619140625 +59864 0.003692626953125 +59865 -0.157012939453125 +59866 0.2257080078125 +59867 -0.04345703125 +59868 0.427154541015625 +59869 0.068359375 +59870 0.643218994140625 +59871 0.193145751953125 +59872 0.855926513671875 +59873 0.326507568359375 +59874 0.870361328125 +59875 0.4420166015625 +59876 0.870361328125 +59877 0.51702880859375 +59878 0.862762451171875 +59879 0.55487060546875 +59880 0.79669189453125 +59881 0.554229736328125 +59882 0.595794677734375 +59883 0.5108642578125 +59884 0.362152099609375 +59885 0.438140869140625 +59886 0.1270751953125 +59887 0.34893798828125 +59888 -0.086944580078125 +59889 0.252960205078125 +59890 -0.2784423828125 +59891 0.151214599609375 +59892 -0.484832763671875 +59893 0.027923583984375 +59894 -0.729583740234375 +59895 -0.125579833984375 +59896 -0.86688232421875 +59897 -0.286163330078125 +59898 -0.870391845703125 +59899 -0.424896240234375 +59900 -0.86859130859375 +59901 -0.53948974609375 +59902 -0.86279296875 +59903 -0.62896728515625 +59904 -0.817962646484375 +59905 -0.677001953125 +59906 -0.6116943359375 +59907 -0.66253662109375 +59908 -0.3128662109375 +59909 -0.58209228515625 +59910 0.039398193359375 +59911 -0.4512939453125 +59912 0.422821044921875 +59913 -0.279052734375 +59914 0.805145263671875 +59915 -0.080780029296875 +59916 0.870361328125 +59917 0.111053466796875 +59918 0.870361328125 +59919 0.26934814453125 +59920 0.860015869140625 +59921 0.388946533203125 +59922 0.727935791015625 +59923 0.466552734375 +59924 0.48114013671875 +59925 0.499664306640625 +59926 0.2059326171875 +59927 0.500244140625 +59928 -0.06103515625 +59929 0.479339599609375 +59930 -0.29913330078125 +59931 0.4417724609375 +59932 -0.516204833984375 +59933 0.380279541015625 +59934 -0.7252197265625 +59935 0.287109375 +59936 -0.85980224609375 +59937 0.174072265625 +59938 -0.870391845703125 +59939 0.0576171875 +59940 -0.870391845703125 +59941 -0.048126220703125 +59942 -0.858062744140625 +59943 -0.11968994140625 +59944 -0.673004150390625 +59945 -0.1552734375 +59946 -0.42694091796875 +59947 -0.180694580078125 +59948 -0.2100830078125 +59949 -0.21771240234375 +59950 -0.0362548828125 +59951 -0.265350341796875 +59952 0.10943603515625 +59953 -0.309417724609375 +59954 0.23516845703125 +59955 -0.340087890625 +59956 0.373687744140625 +59957 -0.3370361328125 +59958 0.517791748046875 +59959 -0.30108642578125 +59960 0.602783203125 +59961 -0.262786865234375 +59962 0.635711669921875 +59963 -0.21942138671875 +59964 0.655181884765625 +59965 -0.154510498046875 +59966 0.65948486328125 +59967 -0.072723388671875 +59968 0.651275634765625 +59969 0.02215576171875 +59970 0.61846923828125 +59971 0.1182861328125 +59972 0.53753662109375 +59973 0.19769287109375 +59974 0.404144287109375 +59975 0.251617431640625 +59976 0.22186279296875 +59977 0.275299072265625 +59978 0.003997802734375 +59979 0.269287109375 +59980 -0.22100830078125 +59981 0.242340087890625 +59982 -0.42449951171875 +59983 0.204376220703125 +59984 -0.579833984375 +59985 0.16571044921875 +59986 -0.641876220703125 +59987 0.14703369140625 +59988 -0.6177978515625 +59989 0.144927978515625 +59990 -0.575531005859375 +59991 0.12774658203125 +59992 -0.526336669921875 +59993 0.092742919921875 +59994 -0.42645263671875 +59995 0.065093994140625 +59996 -0.2581787109375 +59997 0.05810546875 +59998 -0.068695068359375 +59999 0.053985595703125 +60000 0.09222412109375 +60001 0.033935546875 +60002 0.232147216796875 +60003 0.007080078125 +60004 0.3509521484375 +60005 -0.021514892578125 +60006 0.410064697265625 +60007 -0.06622314453125 +60008 0.372955322265625 +60009 -0.1412353515625 +60010 0.2554931640625 +60011 -0.23614501953125 +60012 0.10711669921875 +60013 -0.32537841796875 +60014 -0.052886962890625 +60015 -0.399169921875 +60016 -0.186279296875 +60017 -0.439697265625 +60018 -0.23291015625 +60019 -0.4195556640625 +60020 -0.209442138671875 +60021 -0.349761962890625 +60022 -0.174163818359375 +60023 -0.262359619140625 +60024 -0.126739501953125 +60025 -0.161346435546875 +60026 -0.048126220703125 +60027 -0.04193115234375 +60028 0.0426025390625 +60029 0.082061767578125 +60030 0.10748291015625 +60031 0.18780517578125 +60032 0.1409912109375 +60033 0.268707275390625 +60034 0.19708251953125 +60035 0.347869873046875 +60036 0.273651123046875 +60037 0.42181396484375 +60038 0.31768798828125 +60039 0.463104248046875 +60040 0.341094970703125 +60041 0.47698974609375 +60042 0.368011474609375 +60043 0.4755859375 +60044 0.37249755859375 +60045 0.447540283203125 +60046 0.30072021484375 +60047 0.368682861328125 +60048 0.1517333984375 +60049 0.241302490234375 +60050 -0.01470947265625 +60051 0.09783935546875 +60052 -0.1883544921875 +60053 -0.053070068359375 +60054 -0.372711181640625 +60055 -0.20941162109375 +60056 -0.51397705078125 +60057 -0.34130859375 +60058 -0.57177734375 +60059 -0.425689697265625 +60060 -0.53948974609375 +60061 -0.456512451171875 +60062 -0.43511962890625 +60063 -0.440277099609375 +60064 -0.2962646484375 +60065 -0.393768310546875 +60066 -0.161102294921875 +60067 -0.3348388671875 +60068 -0.0435791015625 +60069 -0.270294189453125 +60070 0.060394287109375 +60071 -0.198974609375 +60072 0.13665771484375 +60073 -0.1292724609375 +60074 0.170135498046875 +60075 -0.0706787109375 +60076 0.16552734375 +60077 -0.023468017578125 +60078 0.15728759765625 +60079 0.026214599609375 +60080 0.150787353515625 +60081 0.077972412109375 +60082 0.12200927734375 +60083 0.117034912109375 +60084 0.080108642578125 +60085 0.14501953125 +60086 0.05126953125 +60087 0.172210693359375 +60088 0.062896728515625 +60089 0.2099609375 +60090 0.09271240234375 +60091 0.245880126953125 +60092 0.092987060546875 +60093 0.255828857421875 +60094 0.07855224609375 +60095 0.246856689453125 +60096 0.06427001953125 +60097 0.226654052734375 +60098 0.0347900390625 +60099 0.18878173828125 +60100 -0.01171875 +60101 0.133880615234375 +60102 -0.056060791015625 +60103 0.073333740234375 +60104 -0.055511474609375 +60105 0.030303955078125 +60106 -0.010467529296875 +60107 0.007080078125 +60108 0.02508544921875 +60109 -0.020111083984375 +60110 0.025665283203125 +60111 -0.061309814453125 +60112 0.017333984375 +60113 -0.101593017578125 +60114 0.00189208984375 +60115 -0.138275146484375 +60116 -0.03173828125 +60117 -0.175384521484375 +60118 -0.071502685546875 +60119 -0.2061767578125 +60120 -0.13543701171875 +60121 -0.23907470703125 +60122 -0.219970703125 +60123 -0.27252197265625 +60124 -0.300506591796875 +60125 -0.295196533203125 +60126 -0.376312255859375 +60127 -0.30792236328125 +60128 -0.416107177734375 +60129 -0.296966552734375 +60130 -0.371124267578125 +60131 -0.240386962890625 +60132 -0.242279052734375 +60133 -0.140655517578125 +60134 -0.069732666015625 +60135 -0.0194091796875 +60136 0.125640869140625 +60137 0.111114501953125 +60138 0.31268310546875 +60139 0.233856201171875 +60140 0.45501708984375 +60141 0.329437255859375 +60142 0.554779052734375 +60143 0.39764404296875 +60144 0.61065673828125 +60145 0.43695068359375 +60146 0.610931396484375 +60147 0.441192626953125 +60148 0.531463623046875 +60149 0.398590087890625 +60150 0.3883056640625 +60151 0.317413330078125 +60152 0.23468017578125 +60153 0.2244873046875 +60154 0.095245361328125 +60155 0.133026123046875 +60156 -0.00396728515625 +60157 0.057159423828125 +60158 -0.04852294921875 +60159 0.005523681640625 +60160 -0.055145263671875 +60161 -0.028106689453125 +60162 -0.0758056640625 +60163 -0.067535400390625 +60164 -0.138702392578125 +60165 -0.125244140625 +60166 -0.209197998046875 +60167 -0.182647705078125 +60168 -0.289031982421875 +60169 -0.2396240234375 +60170 -0.37884521484375 +60171 -0.295806884765625 +60172 -0.456329345703125 +60173 -0.339630126953125 +60174 -0.51641845703125 +60175 -0.3685302734375 +60176 -0.519287109375 +60177 -0.36285400390625 +60178 -0.458251953125 +60179 -0.31982421875 +60180 -0.384796142578125 +60181 -0.266021728515625 +60182 -0.323699951171875 +60183 -0.21490478515625 +60184 -0.269287109375 +60185 -0.16485595703125 +60186 -0.1951904296875 +60187 -0.10400390625 +60188 -0.100006103515625 +60189 -0.032928466796875 +60190 -0.01055908203125 +60191 0.03363037109375 +60192 0.1033935546875 +60193 0.109649658203125 +60194 0.24908447265625 +60195 0.197784423828125 +60196 0.373199462890625 +60197 0.27069091796875 +60198 0.45806884765625 +60199 0.319091796875 +60200 0.511474609375 +60201 0.3466796875 +60202 0.565399169921875 +60203 0.36956787109375 +60204 0.61138916015625 +60205 0.383880615234375 +60206 0.5897216796875 +60207 0.3603515625 +60208 0.4906005859375 +60209 0.29486083984375 +60210 0.33148193359375 +60211 0.1971435546875 +60212 0.147796630859375 +60213 0.0859375 +60214 -0.01873779296875 +60215 -0.01678466796875 +60216 -0.140289306640625 +60217 -0.096038818359375 +60218 -0.191986083984375 +60219 -0.138397216796875 +60220 -0.184295654296875 +60221 -0.14825439453125 +60222 -0.161834716796875 +60223 -0.147247314453125 +60224 -0.166595458984375 +60225 -0.155914306640625 +60226 -0.19390869140625 +60227 -0.17169189453125 +60228 -0.22442626953125 +60229 -0.1849365234375 +60230 -0.279754638671875 +60231 -0.206634521484375 +60232 -0.3389892578125 +60233 -0.226806640625 +60234 -0.3543701171875 +60235 -0.222198486328125 +60236 -0.348175048828125 +60237 -0.204681396484375 +60238 -0.32598876953125 +60239 -0.17791748046875 +60240 -0.2581787109375 +60241 -0.12799072265625 +60242 -0.139801025390625 +60243 -0.05328369140625 +60244 0.014617919921875 +60245 0.038116455078125 +60246 0.144378662109375 +60247 0.115081787109375 +60248 0.221038818359375 +60249 0.162811279296875 +60250 0.27069091796875 +60251 0.19390869140625 +60252 0.294036865234375 +60253 0.208465576171875 +60254 0.311767578125 +60255 0.216796875 +60256 0.339141845703125 +60257 0.226715087890625 +60258 0.360260009765625 +60259 0.230804443359375 +60260 0.360504150390625 +60261 0.222137451171875 +60262 0.308380126953125 +60263 0.184783935546875 +60264 0.18170166015625 +60265 0.107757568359375 +60266 0.0047607421875 +60267 0.004302978515625 +60268 -0.17559814453125 +60269 -0.10064697265625 +60270 -0.3143310546875 +60271 -0.18310546875 +60272 -0.36785888671875 +60273 -0.21990966796875 +60274 -0.36248779296875 +60275 -0.224273681640625 +60276 -0.343536376953125 +60277 -0.21942138671875 +60278 -0.3018798828125 +60279 -0.200439453125 +60280 -0.231414794921875 +60281 -0.164031982421875 +60282 -0.117645263671875 +60283 -0.10272216796875 +60284 0.007049560546875 +60285 -0.033538818359375 +60286 0.087982177734375 +60287 0.0147705078125 +60288 0.13946533203125 +60289 0.04925537109375 +60290 0.17425537109375 +60291 0.07611083984375 +60292 0.188201904296875 +60293 0.0926513671875 +60294 0.171234130859375 +60295 0.093109130859375 +60296 0.118438720703125 +60297 0.074432373046875 +60298 0.05706787109375 +60299 0.05035400390625 +60300 -0.010711669921875 +60301 0.021575927734375 +60302 -0.0914306640625 +60303 -0.015594482421875 +60304 -0.162322998046875 +60305 -0.04949951171875 +60306 -0.194549560546875 +60307 -0.065277099609375 +60308 -0.1492919921875 +60309 -0.042755126953125 +60310 -0.02166748046875 +60311 0.020721435546875 +60312 0.124053955078125 +60313 0.091949462890625 +60314 0.211151123046875 +60315 0.131317138671875 +60316 0.240447998046875 +60317 0.1396484375 +60318 0.242218017578125 +60319 0.133026123046875 +60320 0.2257080078125 +60321 0.116729736328125 +60322 0.194366455078125 +60323 0.092987060546875 +60324 0.115509033203125 +60325 0.045196533203125 +60326 0.0128173828125 +60327 -0.013946533203125 +60328 -0.053802490234375 +60329 -0.05303955078125 +60330 -0.110626220703125 +60331 -0.08551025390625 +60332 -0.199493408203125 +60333 -0.133026123046875 +60334 -0.29437255859375 +60335 -0.182037353515625 +60336 -0.33221435546875 +60337 -0.199798583984375 +60338 -0.27972412109375 +60339 -0.169158935546875 +60340 -0.185333251953125 +60341 -0.115509033203125 +60342 -0.128204345703125 +60343 -0.080291748046875 +60344 -0.115692138671875 +60345 -0.067657470703125 +60346 -0.116455078125 +60347 -0.061676025390625 +60348 -0.105926513671875 +60349 -0.0499267578125 +60350 -0.053955078125 +60351 -0.017059326171875 +60352 0.048797607421875 +60353 0.04144287109375 +60354 0.157318115234375 +60355 0.101898193359375 +60356 0.212005615234375 +60357 0.133148193359375 +60358 0.218475341796875 +60359 0.13800048828125 +60360 0.23724365234375 +60361 0.147857666015625 +60362 0.30535888671875 +60363 0.182037353515625 +60364 0.38128662109375 +60365 0.21905517578125 +60366 0.404449462890625 +60367 0.227569580078125 +60368 0.3944091796875 +60369 0.217987060546875 +60370 0.3885498046875 +60371 0.209991455078125 +60372 0.362640380859375 +60373 0.1912841796875 +60374 0.27362060546875 +60375 0.1397705078125 +60376 0.11712646484375 +60377 0.053466796875 +60378 -0.054901123046875 +60379 -0.04034423828125 +60380 -0.19085693359375 +60381 -0.1146240234375 +60382 -0.28570556640625 +60383 -0.166595458984375 +60384 -0.339263916015625 +60385 -0.196044921875 +60386 -0.3775634765625 +60387 -0.2164306640625 +60388 -0.445709228515625 +60389 -0.251190185546875 +60390 -0.535064697265625 +60391 -0.295928955078125 +60392 -0.629058837890625 +60393 -0.3421630859375 +60394 -0.697601318359375 +60395 -0.3743896484375 +60396 -0.70391845703125 +60397 -0.373687744140625 +60398 -0.6424560546875 +60399 -0.337432861328125 +60400 -0.491241455078125 +60401 -0.254425048828125 +60402 -0.265716552734375 +60403 -0.1329345703125 +60404 -0.023712158203125 +60405 -0.003265380859375 +60406 0.201751708984375 +60407 0.1171875 +60408 0.375823974609375 +60409 0.21014404296875 +60410 0.485076904296875 +60411 0.26849365234375 +60412 0.56884765625 +60413 0.31268310546875 +60414 0.634765625 +60415 0.346649169921875 +60416 0.63763427734375 +60417 0.346435546875 +60418 0.5660400390625 +60419 0.305450439453125 +60420 0.4720458984375 +60421 0.251983642578125 +60422 0.40692138671875 +60423 0.214599609375 +60424 0.3778076171875 +60425 0.197479248046875 +60426 0.376953125 +60427 0.196502685546875 +60428 0.371978759765625 +60429 0.19390869140625 +60430 0.313140869140625 +60431 0.1622314453125 +60432 0.184417724609375 +60433 0.092559814453125 +60434 0.011199951171875 +60435 -0.0010986328125 +60436 -0.171051025390625 +60437 -0.09930419921875 +60438 -0.33740234375 +60439 -0.188446044921875 +60440 -0.47198486328125 +60441 -0.259918212890625 +60442 -0.560394287109375 +60443 -0.305938720703125 +60444 -0.58056640625 +60445 -0.31451416015625 +60446 -0.54754638671875 +60447 -0.2940673828125 +60448 -0.508575439453125 +60449 -0.270843505859375 +60450 -0.459503173828125 +60451 -0.24261474609375 +60452 -0.394378662109375 +60453 -0.206146240234375 +60454 -0.35260009765625 +60455 -0.183197021484375 +60456 -0.31170654296875 +60457 -0.161346435546875 +60458 -0.197418212890625 +60459 -0.099517822265625 +60460 -0.007965087890625 +60461 0.0032958984375 +60462 0.207489013671875 +60463 0.120086669921875 +60464 0.409210205078125 +60465 0.229034423828125 +60466 0.57208251953125 +60467 0.316436767578125 +60468 0.66595458984375 +60469 0.36578369140625 +60470 0.65875244140625 +60471 0.3594970703125 +60472 0.56744384765625 +60473 0.30706787109375 +60474 0.431396484375 +60475 0.230316162109375 +60476 0.29443359375 +60477 0.153533935546875 +60478 0.182464599609375 +60479 0.091094970703125 +60480 0.06365966796875 +60481 0.025421142578125 +60482 -0.075958251953125 +60483 -0.051177978515625 +60484 -0.189422607421875 +60485 -0.11285400390625 +60486 -0.271942138671875 +60487 -0.156982421875 +60488 -0.342529296875 +60489 -0.19415283203125 +60490 -0.364166259765625 +60491 -0.204071044921875 +60492 -0.327239990234375 +60493 -0.181549072265625 +60494 -0.2769775390625 +60495 -0.15167236328125 +60496 -0.253692626953125 +60497 -0.136810302734375 +60498 -0.24365234375 +60499 -0.129486083984375 +60500 -0.1983642578125 +60501 -0.10302734375 +60502 -0.116241455078125 +60503 -0.056610107421875 +60504 -0.036834716796875 +60505 -0.012115478515625 +60506 0.034881591796875 +60507 0.02764892578125 +60508 0.09124755859375 +60509 0.0584716796875 +60510 0.10888671875 +60511 0.0675048828125 +60512 0.125518798828125 +60513 0.075592041015625 +60514 0.15771484375 +60515 0.091949462890625 +60516 0.17828369140625 +60517 0.10162353515625 +60518 0.17108154296875 +60519 0.0958251953125 +60520 0.129974365234375 +60521 0.0712890625 +60522 0.082427978515625 +60523 0.04327392578125 +60524 0.027679443359375 +60525 0.011474609375 +60526 -0.065643310546875 +60527 -0.04132080078125 +60528 -0.15936279296875 +60529 -0.093994140625 +60530 -0.21307373046875 +60531 -0.12420654296875 +60532 -0.234649658203125 +60533 -0.13629150390625 +60534 -0.2001953125 +60535 -0.117034912109375 +60536 -0.119171142578125 +60537 -0.07171630859375 +60538 -0.024749755859375 +60539 -0.0186767578125 +60540 0.085784912109375 +60541 0.043487548828125 +60542 0.178131103515625 +60543 0.09576416015625 +60544 0.215576171875 +60545 0.11785888671875 +60546 0.211456298828125 +60547 0.117034912109375 +60548 0.17523193359375 +60549 0.09844970703125 +60550 0.128753662109375 +60551 0.0740966796875 +60552 0.1019287109375 +60553 0.06036376953125 +60554 0.0743408203125 +60555 0.04595947265625 +60556 0.04327392578125 +60557 0.02935791015625 +60558 0.038177490234375 +60559 0.02679443359375 +60560 0.076263427734375 +60561 0.047760009765625 +60562 0.14105224609375 +60563 0.0831298828125 +60564 0.186431884765625 +60565 0.10748291015625 +60566 0.188812255859375 +60567 0.10784912109375 +60568 0.1390380859375 +60569 0.079254150390625 +60570 0.041778564453125 +60571 0.02435302734375 +60572 -0.079437255859375 +60573 -0.04376220703125 +60574 -0.219390869140625 +60575 -0.1221923828125 +60576 -0.367828369140625 +60577 -0.205169677734375 +60578 -0.494873046875 +60579 -0.27618408203125 +60580 -0.556243896484375 +60581 -0.31072998046875 +60582 -0.508697509765625 +60583 -0.284912109375 +60584 -0.3756103515625 +60585 -0.211639404296875 +60586 -0.218902587890625 +60587 -0.125091552734375 +60588 -0.063751220703125 +60589 -0.039154052734375 +60590 0.091552734375 +60591 0.047027587890625 +60592 0.23602294921875 +60593 0.127410888671875 +60594 0.342987060546875 +60595 0.187225341796875 +60596 0.39520263671875 +60597 0.2169189453125 +60598 0.389373779296875 +60599 0.214630126953125 +60600 0.324249267578125 +60601 0.179595947265625 +60602 0.224090576171875 +60603 0.125152587890625 +60604 0.124267578125 +60605 0.07080078125 +60606 0.037078857421875 +60607 0.023284912109375 +60608 -0.010101318359375 +60609 -0.002288818359375 +60610 -0.019439697265625 +60611 -0.00714111328125 +60612 -0.022796630859375 +60613 -0.008880615234375 +60614 -0.001556396484375 +60615 0.002716064453125 +60616 0.056304931640625 +60617 0.034332275390625 +60618 0.106719970703125 +60619 0.0616455078125 +60620 0.096893310546875 +60621 0.055572509765625 +60622 0.042694091796875 +60623 0.024932861328125 +60624 -0.018035888671875 +60625 -0.009368896484375 +60626 -0.07586669921875 +60627 -0.04205322265625 +60628 -0.11944580078125 +60629 -0.06683349609375 +60630 -0.15972900390625 +60631 -0.0897216796875 +60632 -0.202606201171875 +60633 -0.11395263671875 +60634 -0.24859619140625 +60635 -0.139739990234375 +60636 -0.30517578125 +60637 -0.17120361328125 +60638 -0.36212158203125 +60639 -0.20269775390625 +60640 -0.39141845703125 +60641 -0.21875 +60642 -0.35528564453125 +60643 -0.19854736328125 +60644 -0.249969482421875 +60645 -0.1400146484375 +60646 -0.092864990234375 +60647 -0.05279541015625 +60648 0.08905029296875 +60649 0.048187255859375 +60650 0.2352294921875 +60651 0.12945556640625 +60652 0.318817138671875 +60653 0.176177978515625 +60654 0.358642578125 +60655 0.19873046875 +60656 0.347747802734375 +60657 0.1932373046875 +60658 0.28564453125 +60659 0.159393310546875 +60660 0.223175048828125 +60661 0.125244140625 +60662 0.196746826171875 +60663 0.11083984375 +60664 0.179840087890625 +60665 0.101593017578125 +60666 0.155548095703125 +60667 0.088134765625 +60668 0.151214599609375 +60669 0.0855712890625 +60670 0.156951904296875 +60671 0.088470458984375 +60672 0.13177490234375 +60673 0.07403564453125 +60674 0.100799560546875 +60675 0.056610107421875 +60676 0.087127685546875 +60677 0.04913330078125 +60678 0.05487060546875 +60679 0.030792236328125 +60680 -0.009002685546875 +60681 -0.005889892578125 +60682 -0.10400390625 +60683 -0.06060791015625 +60684 -0.229400634765625 +60685 -0.132965087890625 +60686 -0.35552978515625 +60687 -0.205657958984375 +60688 -0.441925048828125 +60689 -0.255096435546875 +60690 -0.473846435546875 +60691 -0.27276611328125 +60692 -0.464813232421875 +60693 -0.266632080078125 +60694 -0.419097900390625 +60695 -0.2392578125 +60696 -0.334320068359375 +60697 -0.1893310546875 +60698 -0.227935791015625 +60699 -0.127044677734375 +60700 -0.12347412109375 +60701 -0.066162109375 +60702 -0.02764892578125 +60703 -0.010589599609375 +60704 0.077667236328125 +60705 0.050262451171875 +60706 0.2132568359375 +60707 0.1285400390625 +60708 0.38885498046875 +60709 0.22998046875 +60710 0.582794189453125 +60711 0.34197998046875 +60712 0.734039306640625 +60713 0.428985595703125 +60714 0.800140380859375 +60715 0.466278076171875 +60716 0.7783203125 +60717 0.452301025390625 +60718 0.6651611328125 +60719 0.3851318359375 +60720 0.45965576171875 +60721 0.264251708984375 +60722 0.199188232421875 +60723 0.111541748046875 +60724 -0.050689697265625 +60725 -0.03466796875 +60726 -0.23297119140625 +60727 -0.14111328125 +60728 -0.33013916015625 +60729 -0.19757080078125 +60730 -0.368408203125 +60731 -0.2193603515625 +60732 -0.378936767578125 +60733 -0.224700927734375 +60734 -0.376983642578125 +60735 -0.22259521484375 +60736 -0.37969970703125 +60737 -0.22314453125 +60738 -0.391510009765625 +60739 -0.228973388671875 +60740 -0.385345458984375 +60741 -0.224334716796875 +60742 -0.3419189453125 +60743 -0.197998046875 +60744 -0.28289794921875 +60745 -0.16265869140625 +60746 -0.251617431640625 +60747 -0.1436767578125 +60748 -0.266143798828125 +60749 -0.151611328125 +60750 -0.273345947265625 +60751 -0.155487060546875 +60752 -0.216796875 +60753 -0.122344970703125 +60754 -0.128265380859375 +60755 -0.07073974609375 +60756 -0.068145751953125 +60757 -0.035919189453125 +60758 -0.0430908203125 +60759 -0.021728515625 +60760 -0.024444580078125 +60761 -0.011444091796875 +60762 0.020721435546875 +60763 0.01422119140625 +60764 0.124481201171875 +60765 0.074005126953125 +60766 0.25787353515625 +60767 0.151031494140625 +60768 0.379119873046875 +60769 0.220947265625 +60770 0.47991943359375 +60771 0.27899169921875 +60772 0.5281982421875 +60773 0.30645751953125 +60774 0.511138916015625 +60775 0.2958984375 +60776 0.456207275390625 +60777 0.26336669921875 +60778 0.407470703125 +60779 0.234649658203125 +60780 0.383758544921875 +60781 0.220733642578125 +60782 0.35687255859375 +60783 0.20513916015625 +60784 0.31182861328125 +60785 0.179107666015625 +60786 0.250885009765625 +60787 0.1439208984375 +60788 0.1654052734375 +60789 0.09454345703125 +60790 0.035247802734375 +60791 0.019195556640625 +60792 -0.142059326171875 +60793 -0.0836181640625 +60794 -0.33563232421875 +60795 -0.195892333984375 +60796 -0.5345458984375 +60797 -0.311279296875 +60798 -0.72186279296875 +60799 -0.419952392578125 +60800 -0.836669921875 +60801 -0.486358642578125 +60802 -0.8326416015625 +60803 -0.483489990234375 +60804 -0.7296142578125 +60805 -0.4229736328125 +60806 -0.582550048828125 +60807 -0.336944580078125 +60808 -0.440093994140625 +60809 -0.2537841796875 +60810 -0.324310302734375 +60811 -0.186370849609375 +60812 -0.20147705078125 +60813 -0.114990234375 +60814 -0.044647216796875 +60815 -0.02386474609375 +60816 0.103973388671875 +60817 0.062347412109375 +60818 0.202392578125 +60819 0.119171142578125 +60820 0.264495849609375 +60821 0.154754638671875 +60822 0.338897705078125 +60823 0.197509765625 +60824 0.443817138671875 +60825 0.25811767578125 +60826 0.545074462890625 +60827 0.316680908203125 +60828 0.6173095703125 +60829 0.3583984375 +60830 0.6524658203125 +60831 0.378570556640625 +60832 0.66339111328125 +60833 0.384735107421875 +60834 0.6561279296875 +60835 0.38043212890625 +60836 0.606781005859375 +60837 0.3516845703125 +60838 0.501190185546875 +60839 0.29022216796875 +60840 0.352783203125 +60841 0.203857421875 +60842 0.176544189453125 +60843 0.101318359375 +60844 -0.034820556640625 +60845 -0.021636962890625 +60846 -0.258209228515625 +60847 -0.151519775390625 +60848 -0.44244384765625 +60849 -0.25848388671875 +60850 -0.5753173828125 +60851 -0.33544921875 +60852 -0.65203857421875 +60853 -0.379669189453125 +60854 -0.641632080078125 +60855 -0.373046875 +60856 -0.562164306640625 +60857 -0.326202392578125 +60858 -0.458038330078125 +60859 -0.265106201171875 +60860 -0.350555419921875 +60861 -0.202178955078125 +60862 -0.260528564453125 +60863 -0.149566650390625 +60864 -0.192108154296875 +60865 -0.109710693359375 +60866 -0.141937255859375 +60867 -0.08062744140625 +60868 -0.1021728515625 +60869 -0.057708740234375 +60870 -0.062896728515625 +60871 -0.03515625 +60872 -0.011932373046875 +60873 -0.005859375 +60874 0.062835693359375 +60875 0.03729248046875 +60876 0.148712158203125 +60877 0.0869140625 +60878 0.241729736328125 +60879 0.14068603515625 +60880 0.34912109375 +60881 0.202880859375 +60882 0.457305908203125 +60883 0.265594482421875 +60884 0.54388427734375 +60885 0.3157958984375 +60886 0.5728759765625 +60887 0.332489013671875 +60888 0.506591796875 +60889 0.293670654296875 +60890 0.351226806640625 +60891 0.202972412109375 +60892 0.146514892578125 +60893 0.08355712890625 +60894 -0.05523681640625 +60895 -0.034027099609375 +60896 -0.21624755859375 +60897 -0.127716064453125 +60898 -0.334930419921875 +60899 -0.19659423828125 +60900 -0.402984619140625 +60901 -0.23583984375 +60902 -0.4412841796875 +60903 -0.257659912109375 +60904 -0.49578857421875 +60905 -0.288909912109375 +60906 -0.5601806640625 +60907 -0.325958251953125 +60908 -0.600738525390625 +60909 -0.349151611328125 +60910 -0.584228515625 +60911 -0.339111328125 +60912 -0.47930908203125 +60913 -0.27752685546875 +60914 -0.27935791015625 +60915 -0.16058349609375 +60916 -0.0089111328125 +60917 -0.00262451171875 +60918 0.268798828125 +60919 0.159423828125 +60920 0.482818603515625 +60921 0.284149169921875 +60922 0.60369873046875 +60923 0.3543701171875 +60924 0.650421142578125 +60925 0.38116455078125 +60926 0.66400146484375 +60927 0.3885498046875 +60928 0.6414794921875 +60929 0.37457275390625 +60930 0.572540283203125 +60931 0.333343505859375 +60932 0.498138427734375 +60933 0.2899169921875 +60934 0.439453125 +60935 0.257110595703125 +60936 0.375518798828125 +60937 0.221771240234375 +60938 0.274505615234375 +60939 0.163970947265625 +60940 0.1087646484375 +60941 0.06640625 +60942 -0.099395751953125 +60943 -0.05743408203125 +60944 -0.3182373046875 +60945 -0.188201904296875 +60946 -0.5489501953125 +60947 -0.326873779296875 +60948 -0.7738037109375 +60949 -0.462677001953125 +60950 -0.86383056640625 +60951 -0.563140869140625 +60952 -0.870391845703125 +60953 -0.607818603515625 +60954 -0.86895751953125 +60955 -0.607635498046875 +60956 -0.861053466796875 +60957 -0.570648193359375 +60958 -0.765869140625 +60959 -0.486114501953125 +60960 -0.5301513671875 +60961 -0.34698486328125 +60962 -0.214691162109375 +60963 -0.157470703125 +60964 0.137359619140625 +60965 0.05609130859375 +60966 0.474822998046875 +60967 0.262298583984375 +60968 0.76239013671875 +60969 0.439453125 +60970 0.867462158203125 +60971 0.571136474609375 +60972 0.870361328125 +60973 0.65777587890625 +60974 0.86480712890625 +60975 0.692413330078125 +60976 0.831817626953125 +60977 0.678436279296875 +60978 0.677581787109375 +60979 0.630950927734375 +60980 0.495880126953125 +60981 0.55352783203125 +60982 0.30767822265625 +60983 0.45758056640625 +60984 0.116180419921875 +60985 0.34442138671875 +60986 -0.110748291015625 +60987 0.194427490234375 +60988 -0.381805419921875 +60989 0.003204345703125 +60990 -0.6572265625 +60991 -0.202972412109375 +60992 -0.857421875 +60993 -0.38739013671875 +60994 -0.870391845703125 +60995 -0.52374267578125 +60996 -0.870391845703125 +60997 -0.6077880859375 +60998 -0.86444091796875 +60999 -0.65625 +61000 -0.85723876953125 +61001 -0.69122314453125 +61002 -0.790008544921875 +61003 -0.701507568359375 +61004 -0.62847900390625 +61005 -0.65374755859375 +61006 -0.3956298828125 +61007 -0.5460205078125 +61008 -0.126708984375 +61009 -0.398529052734375 +61010 0.150115966796875 +61011 -0.2281494140625 +61012 0.424041748046875 +61013 -0.04205322265625 +61014 0.670623779296875 +61015 0.143218994140625 +61016 0.854522705078125 +61017 0.303924560546875 +61018 0.866485595703125 +61019 0.42926025390625 +61020 0.86920166015625 +61021 0.5098876953125 +61022 0.8653564453125 +61023 0.557098388671875 +61024 0.857147216796875 +61025 0.5792236328125 +61026 0.766845703125 +61027 0.574615478515625 +61028 0.628509521484375 +61029 0.546478271484375 +61030 0.462127685546875 +61031 0.49072265625 +61032 0.297210693359375 +61033 0.42327880859375 +61034 0.14862060546875 +61035 0.351776123046875 +61036 -0.00537109375 +61037 0.262176513671875 +61038 -0.15753173828125 +61039 0.1590576171875 +61040 -0.31304931640625 +61041 0.0401611328125 +61042 -0.48876953125 +61043 -0.10321044921875 +61044 -0.6416015625 +61045 -0.24224853515625 +61046 -0.751373291015625 +61047 -0.36181640625 +61048 -0.84619140625 +61049 -0.476165771484375 +61050 -0.861297607421875 +61051 -0.57635498046875 +61052 -0.863250732421875 +61053 -0.64202880859375 +61054 -0.856597900390625 +61055 -0.653778076171875 +61056 -0.7498779296875 +61057 -0.619140625 +61058 -0.624542236328125 +61059 -0.57379150390625 +61060 -0.47808837890625 +61061 -0.504180908203125 +61062 -0.253387451171875 +61063 -0.37432861328125 +61064 0.003692626953125 +61065 -0.21234130859375 +61066 0.2257080078125 +61067 -0.060302734375 +61068 0.427154541015625 +61069 0.089508056640625 +61070 0.643218994140625 +61071 0.257049560546875 +61072 0.855926513671875 +61073 0.4364013671875 +61074 0.870361328125 +61075 0.5919189453125 +61076 0.870361328125 +61077 0.69305419921875 +61078 0.862762451171875 +61079 0.744293212890625 +61080 0.79669189453125 +61081 0.74383544921875 +61082 0.595794677734375 +61083 0.6859130859375 +61084 0.362152099609375 +61085 0.58856201171875 +61086 0.1270751953125 +61087 0.469085693359375 +61088 -0.086944580078125 +61089 0.340545654296875 +61090 -0.2784423828125 +61091 0.204254150390625 +61092 -0.484832763671875 +61093 0.038818359375 +61094 -0.729583740234375 +61095 -0.16754150390625 +61096 -0.86688232421875 +61097 -0.38360595703125 +61098 -0.870391845703125 +61099 -0.57037353515625 +61100 -0.86859130859375 +61101 -0.72479248046875 +61102 -0.86279296875 +61103 -0.84552001953125 +61104 -0.817962646484375 +61105 -0.860595703125 +61106 -0.6116943359375 +61107 -0.8585205078125 +61108 -0.3128662109375 +61109 -0.78424072265625 +61110 0.039398193359375 +61111 -0.60968017578125 +61112 0.422821044921875 +61113 -0.380126953125 +61114 0.805145263671875 +61115 -0.116119384765625 +61116 0.870361328125 +61117 0.140289306640625 +61118 0.870361328125 +61119 0.353851318359375 +61120 0.860015869140625 +61121 0.5172119140625 +61122 0.727935791015625 +61123 0.62548828125 +61124 0.48114013671875 +61125 0.675079345703125 +61126 0.2059326171875 +61127 0.68072509765625 +61128 -0.06103515625 +61129 0.656219482421875 +61130 -0.29913330078125 +61131 0.607635498046875 +61132 -0.516204833984375 +61133 0.5260009765625 +61134 -0.7252197265625 +61135 0.401824951171875 +61136 -0.85980224609375 +61137 0.25054931640625 +61138 -0.870391845703125 +61139 0.09344482421875 +61140 -0.870391845703125 +61141 -0.051025390625 +61142 -0.858062744140625 +61143 -0.152587890625 +61144 -0.673004150390625 +61145 -0.20831298828125 +61146 -0.42694091796875 +61147 -0.250213623046875 +61148 -0.2100830078125 +61149 -0.30523681640625 +61150 -0.0362548828125 +61151 -0.37176513671875 +61152 0.10943603515625 +61153 -0.43157958984375 +61154 0.23516845703125 +61155 -0.472137451171875 +61156 0.373687744140625 +61157 -0.4677734375 +61158 0.517791748046875 +61159 -0.4195556640625 +61160 0.602783203125 +61161 -0.366302490234375 +61162 0.635711669921875 +61163 -0.304901123046875 +61164 0.655181884765625 +61165 -0.2149658203125 +61166 0.65948486328125 +61167 -0.102874755859375 +61168 0.651275634765625 +61169 0.026123046875 +61170 0.61846923828125 +61171 0.15655517578125 +61172 0.53753662109375 +61173 0.26519775390625 +61174 0.404144287109375 +61175 0.340576171875 +61176 0.22186279296875 +61177 0.3763427734375 +61178 0.003997802734375 +61179 0.372894287109375 +61180 -0.22100830078125 +61181 0.341064453125 +61182 -0.42449951171875 +61183 0.293365478515625 +61184 -0.579833984375 +61185 0.2431640625 +61186 -0.641876220703125 +61187 0.217437744140625 +61188 -0.6177978515625 +61189 0.211517333984375 +61190 -0.575531005859375 +61191 0.183990478515625 +61192 -0.526336669921875 +61193 0.131805419921875 +61194 -0.42645263671875 +61195 0.08892822265625 +61196 -0.2581787109375 +61197 0.073516845703125 +61198 -0.068695068359375 +61199 0.062408447265625 +61200 0.09222412109375 +61201 0.030975341796875 +61202 0.232147216796875 +61203 -0.008392333984375 +61204 0.3509521484375 +61205 -0.048858642578125 +61206 0.410064697265625 +61207 -0.109375 +61208 0.372955322265625 +61209 -0.208770751953125 +61210 0.2554931640625 +61211 -0.333343505859375 +61212 0.10711669921875 +61213 -0.449249267578125 +61214 -0.052886962890625 +61215 -0.54376220703125 +61216 -0.186279296875 +61217 -0.59344482421875 +61218 -0.23291015625 +61219 -0.562164306640625 +61220 -0.209442138671875 +61221 -0.46478271484375 +61222 -0.174163818359375 +61223 -0.344146728515625 +61224 -0.126739501953125 +61225 -0.205841064453125 +61226 -0.048126220703125 +61227 -0.043670654296875 +61228 0.0426025390625 +61229 0.123809814453125 +61230 0.10748291015625 +61231 0.26617431640625 +61232 0.1409912109375 +61233 0.374603271484375 +61234 0.19708251953125 +61235 0.479705810546875 +61236 0.273651123046875 +61237 0.576904296875 +61238 0.31768798828125 +61239 0.629852294921875 +61240 0.341094970703125 +61241 0.645599365234375 +61242 0.368011474609375 +61243 0.640472412109375 +61244 0.37249755859375 +61245 0.59954833984375 +61246 0.30072021484375 +61247 0.490936279296875 +61248 0.1517333984375 +61249 0.31793212890625 +61250 -0.01470947265625 +61251 0.123809814453125 +61252 -0.1883544921875 +61253 -0.079742431640625 +61254 -0.372711181640625 +61255 -0.2899169921875 +61256 -0.51397705078125 +61257 -0.4669189453125 +61258 -0.57177734375 +61259 -0.580047607421875 +61260 -0.53948974609375 +61261 -0.6212158203125 +61262 -0.43511962890625 +61263 -0.59906005859375 +61264 -0.2962646484375 +61265 -0.53594970703125 +61266 -0.161102294921875 +61267 -0.455718994140625 +61268 -0.0435791015625 +61269 -0.367523193359375 +61270 0.060394287109375 +61271 -0.26995849609375 +61272 0.13665771484375 +61273 -0.174346923828125 +61274 0.170135498046875 +61275 -0.093414306640625 +61276 0.16552734375 +61277 -0.027740478515625 +61278 0.15728759765625 +61279 0.04095458984375 +61280 0.150787353515625 +61281 0.11199951171875 +61282 0.12200927734375 +61283 0.165679931640625 +61284 0.080108642578125 +61285 0.20404052734375 +61286 0.05126953125 +61287 0.24066162109375 +61288 0.062896728515625 +61289 0.2906494140625 +61290 0.09271240234375 +61291 0.337554931640625 +61292 0.092987060546875 +61293 0.349395751953125 +61294 0.07855224609375 +61295 0.33563232421875 +61296 0.06427001953125 +61297 0.30657958984375 +61298 0.0347900390625 +61299 0.253814697265625 +61300 -0.01171875 +61301 0.1783447265625 +61302 -0.056060791015625 +61303 0.095428466796875 +61304 -0.055511474609375 +61305 0.03594970703125 +61306 -0.010467529296875 +61307 0.003082275390625 +61308 0.02508544921875 +61309 -0.034637451171875 +61310 0.025665283203125 +61311 -0.0904541015625 +61312 0.017333984375 +61313 -0.144561767578125 +61314 0.00189208984375 +61315 -0.193359375 +61316 -0.03173828125 +61317 -0.242218017578125 +61318 -0.071502685546875 +61319 -0.282196044921875 +61320 -0.13543701171875 +61321 -0.3245849609375 +61322 -0.219970703125 +61323 -0.36737060546875 +61324 -0.300506591796875 +61325 -0.3956298828125 +61326 -0.376312255859375 +61327 -0.4105224609375 +61328 -0.416107177734375 +61329 -0.393951416015625 +61330 -0.371124267578125 +61331 -0.316864013671875 +61332 -0.242279052734375 +61333 -0.1826171875 +61334 -0.069732666015625 +61335 -0.020111083984375 +61336 0.125640869140625 +61337 0.154327392578125 +61338 0.31268310546875 +61339 0.318023681640625 +61340 0.45501708984375 +61341 0.445220947265625 +61342 0.554779052734375 +61343 0.535614013671875 +61344 0.61065673828125 +61345 0.58721923828125 +61346 0.610931396484375 +61347 0.5919189453125 +61348 0.531463623046875 +61349 0.534149169921875 +61350 0.3883056640625 +61351 0.424957275390625 +61352 0.23468017578125 +61353 0.29998779296875 +61354 0.095245361328125 +61355 0.176910400390625 +61356 -0.00396728515625 +61357 0.074554443359375 +61358 -0.04852294921875 +61359 0.004486083984375 +61360 -0.055145263671875 +61361 -0.041748046875 +61362 -0.0758056640625 +61363 -0.095550537109375 +61364 -0.138702392578125 +61365 -0.17303466796875 +61366 -0.209197998046875 +61367 -0.249847412109375 +61368 -0.289031982421875 +61369 -0.325592041015625 +61370 -0.37884521484375 +61371 -0.399566650390625 +61372 -0.456329345703125 +61373 -0.4566650390625 +61374 -0.51641845703125 +61375 -0.493499755859375 +61376 -0.519287109375 +61377 -0.484649658203125 +61378 -0.458251953125 +61379 -0.4266357421875 +61380 -0.384796142578125 +61381 -0.354034423828125 +61382 -0.323699951171875 +61383 -0.284423828125 +61384 -0.269287109375 +61385 -0.215911865234375 +61386 -0.1951904296875 +61387 -0.133331298828125 +61388 -0.100006103515625 +61389 -0.037689208984375 +61390 -0.01055908203125 +61391 0.0517578125 +61392 0.1033935546875 +61393 0.1529541015625 +61394 0.24908447265625 +61395 0.269256591796875 +61396 0.373199462890625 +61397 0.365081787109375 +61398 0.45806884765625 +61399 0.428314208984375 +61400 0.511474609375 +61401 0.463714599609375 +61402 0.565399169921875 +61403 0.492218017578125 +61404 0.61138916015625 +61405 0.5089111328125 +61406 0.5897216796875 +61407 0.475982666015625 +61408 0.4906005859375 +61409 0.388275146484375 +61410 0.33148193359375 +61411 0.258544921875 +61412 0.147796630859375 +61413 0.11126708984375 +61414 -0.01873779296875 +61415 -0.024932861328125 +61416 -0.140289306640625 +61417 -0.130462646484375 +61418 -0.191986083984375 +61419 -0.187774658203125 +61420 -0.184295654296875 +61421 -0.20245361328125 +61422 -0.161834716796875 +61423 -0.20245361328125 +61424 -0.166595458984375 +61425 -0.21435546875 +61426 -0.19390869140625 +61427 -0.23480224609375 +61428 -0.22442626953125 +61429 -0.251251220703125 +61430 -0.279754638671875 +61431 -0.278106689453125 +61432 -0.3389892578125 +61433 -0.302459716796875 +61434 -0.3543701171875 +61435 -0.294281005859375 +61436 -0.348175048828125 +61437 -0.26910400390625 +61438 -0.32598876953125 +61439 -0.231781005859375 +61440 -0.2581787109375 +61441 -0.1644287109375 +61442 -0.139801025390625 +61443 -0.065093994140625 +61444 0.014617919921875 +61445 0.055633544921875 +61446 0.144378662109375 +61447 0.1572265625 +61448 0.221038818359375 +61449 0.220367431640625 +61450 0.27069091796875 +61451 0.261383056640625 +61452 0.294036865234375 +61453 0.280426025390625 +61454 0.311767578125 +61455 0.29083251953125 +61456 0.339141845703125 +61457 0.3028564453125 +61458 0.360260009765625 +61459 0.30694580078125 +61460 0.360504150390625 +61461 0.294189453125 +61462 0.308380126953125 +61463 0.2437744140625 +61464 0.18170166015625 +61465 0.14141845703125 +61466 0.0047607421875 +61467 0.0045166015625 +61468 -0.17559814453125 +61469 -0.134246826171875 +61470 -0.3143310546875 +61471 -0.243438720703125 +61472 -0.36785888671875 +61473 -0.29266357421875 +61474 -0.36248779296875 +61475 -0.2991943359375 +61476 -0.343536376953125 +61477 -0.2933349609375 +61478 -0.3018798828125 +61479 -0.26861572265625 +61480 -0.231414794921875 +61481 -0.220794677734375 +61482 -0.117645263671875 +61483 -0.140106201171875 +61484 0.007049560546875 +61485 -0.048828125 +61486 0.087982177734375 +61487 0.015411376953125 +61488 0.13946533203125 +61489 0.061767578125 +61490 0.17425537109375 +61491 0.0982666015625 +61492 0.188201904296875 +61493 0.121307373046875 +61494 0.171234130859375 +61495 0.123291015625 +61496 0.118438720703125 +61497 0.100128173828125 +61498 0.05706787109375 +61499 0.0697021484375 +61500 -0.010711669921875 +61501 0.032867431640625 +61502 -0.0914306640625 +61503 -0.015228271484375 +61504 -0.162322998046875 +61505 -0.059356689453125 +61506 -0.194549560546875 +61507 -0.080078125 +61508 -0.1492919921875 +61509 -0.050994873046875 +61510 -0.02166748046875 +61511 0.031341552734375 +61512 0.124053955078125 +61513 0.12359619140625 +61514 0.211151123046875 +61515 0.174041748046875 +61516 0.240447998046875 +61517 0.183807373046875 +61518 0.242218017578125 +61519 0.17401123046875 +61520 0.2257080078125 +61521 0.151611328125 +61522 0.194366455078125 +61523 0.119537353515625 +61524 0.115509033203125 +61525 0.05615234375 +61526 0.0128173828125 +61527 -0.02191162109375 +61528 -0.053802490234375 +61529 -0.073516845703125 +61530 -0.110626220703125 +61531 -0.116241455078125 +61532 -0.199493408203125 +61533 -0.17840576171875 +61534 -0.29437255859375 +61535 -0.242279052734375 +61536 -0.33221435546875 +61537 -0.26507568359375 +61538 -0.27972412109375 +61539 -0.22442626953125 +61540 -0.185333251953125 +61541 -0.153533935546875 +61542 -0.128204345703125 +61543 -0.106658935546875 +61544 -0.115692138671875 +61545 -0.089263916015625 +61546 -0.116455078125 +61547 -0.08056640625 +61548 -0.105926513671875 +61549 -0.064361572265625 +61550 -0.053955078125 +61551 -0.020660400390625 +61552 0.048797607421875 +61553 0.056427001953125 +61554 0.157318115234375 +61555 0.135955810546875 +61556 0.212005615234375 +61557 0.1771240234375 +61558 0.218475341796875 +61559 0.18359375 +61560 0.23724365234375 +61561 0.196441650390625 +61562 0.30535888671875 +61563 0.240966796875 +61564 0.38128662109375 +61565 0.289031982421875 +61566 0.404449462890625 +61567 0.2996826171875 +61568 0.3944091796875 +61569 0.286529541015625 +61570 0.3885498046875 +61571 0.275390625 +61572 0.362640380859375 +61573 0.250244140625 +61574 0.27362060546875 +61575 0.18218994140625 +61576 0.11712646484375 +61577 0.068695068359375 +61578 -0.054901123046875 +61579 -0.054534912109375 +61580 -0.19085693359375 +61581 -0.152099609375 +61582 -0.28570556640625 +61583 -0.2203369140625 +61584 -0.339263916015625 +61585 -0.25897216796875 +61586 -0.3775634765625 +61587 -0.285614013671875 +61588 -0.445709228515625 +61589 -0.330963134765625 +61590 -0.535064697265625 +61591 -0.389251708984375 +61592 -0.629058837890625 +61593 -0.449371337890625 +61594 -0.697601318359375 +61595 -0.4910888671875 +61596 -0.70391845703125 +61597 -0.489715576171875 +61598 -0.6424560546875 +61599 -0.441802978515625 +61600 -0.491241455078125 +61601 -0.332733154296875 +61602 -0.265716552734375 +61603 -0.173370361328125 +61604 -0.023712158203125 +61605 -0.00335693359375 +61606 0.201751708984375 +61607 0.154541015625 +61608 0.375823974609375 +61609 0.276397705078125 +61610 0.485076904296875 +61611 0.352935791015625 +61612 0.56884765625 +61613 0.41082763671875 +61614 0.634765625 +61615 0.45526123046875 +61616 0.63763427734375 +61617 0.45556640625 +61618 0.5660400390625 +61619 0.404083251953125 +61620 0.4720458984375 +61621 0.336395263671875 +61622 0.40692138671875 +61623 0.28759765625 +61624 0.3778076171875 +61625 0.2628173828125 +61626 0.376953125 +61627 0.257080078125 +61628 0.371978759765625 +61629 0.2486572265625 +61630 0.313140869140625 +61631 0.204010009765625 +61632 0.184417724609375 +61633 0.112457275390625 +61634 0.011199951171875 +61635 -0.008514404296875 +61636 -0.171051025390625 +61637 -0.1346435546875 +61638 -0.33740234375 +61639 -0.2489013671875 +61640 -0.47198486328125 +61641 -0.340423583984375 +61642 -0.560394287109375 +61643 -0.39947509765625 +61644 -0.58056640625 +61645 -0.411163330078125 +61646 -0.54754638671875 +61647 -0.385833740234375 +61648 -0.508575439453125 +61649 -0.355804443359375 +61650 -0.459503173828125 +61651 -0.318450927734375 +61652 -0.394378662109375 +61653 -0.269989013671875 +61654 -0.35260009765625 +61655 -0.237396240234375 +61656 -0.31170654296875 +61657 -0.20562744140625 +61658 -0.197418212890625 +61659 -0.124420166015625 +61660 -0.007965087890625 +61661 0.007232666015625 +61662 0.207489013671875 +61663 0.155792236328125 +61664 0.409210205078125 +61665 0.29412841796875 +61666 0.57208251953125 +61667 0.405120849609375 +61668 0.66595458984375 +61669 0.468292236328125 +61670 0.65875244140625 +61671 0.4619140625 +61672 0.56744384765625 +61673 0.397613525390625 +61674 0.431396484375 +61675 0.302337646484375 +61676 0.29443359375 +61677 0.2060546875 +61678 0.182464599609375 +61679 0.126556396484375 +61680 0.06365966796875 +61681 0.0423583984375 +61682 -0.075958251953125 +61683 -0.055816650390625 +61684 -0.189422607421875 +61685 -0.1358642578125 +61686 -0.271942138671875 +61687 -0.19439697265625 +61688 -0.342529296875 +61689 -0.24420166015625 +61690 -0.364166259765625 +61691 -0.26007080078125 +61692 -0.327239990234375 +61693 -0.23541259765625 +61694 -0.2769775390625 +61695 -0.20098876953125 +61696 -0.253692626953125 +61697 -0.184478759765625 +61698 -0.24365234375 +61699 -0.176361083984375 +61700 -0.1983642578125 +61701 -0.1427001953125 +61702 -0.116241455078125 +61703 -0.08258056640625 +61704 -0.036834716796875 +61705 -0.024383544921875 +61706 0.034881591796875 +61707 0.028167724609375 +61708 0.09124755859375 +61709 0.06951904296875 +61710 0.10888671875 +61711 0.082916259765625 +61712 0.125518798828125 +61713 0.095184326171875 +61714 0.15771484375 +61715 0.118133544921875 +61716 0.17828369140625 +61717 0.13238525390625 +61718 0.17108154296875 +61719 0.126495361328125 +61720 0.129974365234375 +61721 0.09619140625 +61722 0.082427978515625 +61723 0.06109619140625 +61724 0.027679443359375 +61725 0.020751953125 +61726 -0.065643310546875 +61727 -0.047088623046875 +61728 -0.15936279296875 +61729 -0.115142822265625 +61730 -0.21307373046875 +61731 -0.154571533203125 +61732 -0.234649658203125 +61733 -0.1708984375 +61734 -0.2001953125 +61735 -0.1470947265625 +61736 -0.119171142578125 +61737 -0.08984375 +61738 -0.024749755859375 +61739 -0.02276611328125 +61740 0.085784912109375 +61741 0.056060791015625 +61742 0.178131103515625 +61743 0.122222900390625 +61744 0.215576171875 +61745 0.1495361328125 +61746 0.211456298828125 +61747 0.1474609375 +61748 0.17523193359375 +61749 0.1226806640625 +61750 0.128753662109375 +61751 0.090667724609375 +61752 0.1019287109375 +61753 0.072662353515625 +61754 0.0743408203125 +61755 0.054107666015625 +61756 0.04327392578125 +61757 0.032989501953125 +61758 0.038177490234375 +61759 0.03021240234375 +61760 0.076263427734375 +61761 0.0579833984375 +61762 0.14105224609375 +61763 0.10455322265625 +61764 0.186431884765625 +61765 0.137054443359375 +61766 0.188812255859375 +61767 0.138702392578125 +61768 0.1390380859375 +61769 0.102996826171875 +61770 0.041778564453125 +61771 0.03326416015625 +61772 -0.079437255859375 +61773 -0.05364990234375 +61774 -0.219390869140625 +61775 -0.154052734375 +61776 -0.367828369140625 +61777 -0.260589599609375 +61778 -0.494873046875 +61779 -0.3519287109375 +61780 -0.556243896484375 +61781 -0.396514892578125 +61782 -0.508697509765625 +61783 -0.363494873046875 +61784 -0.3756103515625 +61785 -0.26947021484375 +61786 -0.218902587890625 +61787 -0.15850830078125 +61788 -0.063751220703125 +61789 -0.0484619140625 +61790 0.091552734375 +61791 0.061859130859375 +61792 0.23602294921875 +61793 0.164642333984375 +61794 0.342987060546875 +61795 0.24090576171875 +61796 0.39520263671875 +61797 0.278350830078125 +61798 0.389373779296875 +61799 0.274627685546875 +61800 0.324249267578125 +61801 0.22882080078125 +61802 0.224090576171875 +61803 0.158172607421875 +61804 0.124267578125 +61805 0.08782958984375 +61806 0.037078857421875 +61807 0.026458740234375 +61808 -0.010101318359375 +61809 -0.006439208984375 +61810 -0.019439697265625 +61811 -0.012451171875 +61812 -0.022796630859375 +61813 -0.0142822265625 +61814 -0.001556396484375 +61815 0.00128173828125 +61816 0.056304931640625 +61817 0.042755126953125 +61818 0.106719970703125 +61819 0.0787353515625 +61820 0.096893310546875 +61821 0.071685791015625 +61822 0.042694091796875 +61823 0.03289794921875 +61824 -0.018035888671875 +61825 -0.010650634765625 +61826 -0.07586669921875 +61827 -0.05224609375 +61828 -0.11944580078125 +61829 -0.083740234375 +61830 -0.15972900390625 +61831 -0.11297607421875 +61832 -0.202606201171875 +61833 -0.144073486328125 +61834 -0.24859619140625 +61835 -0.177337646484375 +61836 -0.30517578125 +61837 -0.21807861328125 +61838 -0.36212158203125 +61839 -0.259033203125 +61840 -0.39141845703125 +61841 -0.280242919921875 +61842 -0.35528564453125 +61843 -0.254730224609375 +61844 -0.249969482421875 +61845 -0.179840087890625 +61846 -0.092864990234375 +61847 -0.0679931640625 +61848 0.08905029296875 +61849 0.061614990234375 +61850 0.2352294921875 +61851 0.165863037109375 +61852 0.318817138671875 +61853 0.225616455078125 +61854 0.358642578125 +61855 0.2542724609375 +61856 0.347747802734375 +61857 0.246856689453125 +61858 0.28564453125 +61859 0.2030029296875 +61860 0.223175048828125 +61861 0.158905029296875 +61862 0.196746826171875 +61863 0.140472412109375 +61864 0.179840087890625 +61865 0.128814697265625 +61866 0.155548095703125 +61867 0.111846923828125 +61868 0.151214599609375 +61869 0.109039306640625 +61870 0.156951904296875 +61871 0.11334228515625 +61872 0.13177490234375 +61873 0.09552001953125 +61874 0.100799560546875 +61875 0.073486328125 +61876 0.087127685546875 +61877 0.06365966796875 +61878 0.05487060546875 +61879 0.040496826171875 +61880 -0.009002685546875 +61881 -0.0052490234375 +61882 -0.10400390625 +61883 -0.07318115234375 +61884 -0.229400634765625 +61885 -0.16278076171875 +61886 -0.35552978515625 +61887 -0.252899169921875 +61888 -0.441925048828125 +61889 -0.314697265625 +61890 -0.473846435546875 +61891 -0.33770751953125 +61892 -0.464813232421875 +61893 -0.331512451171875 +61894 -0.419097900390625 +61895 -0.29913330078125 +61896 -0.334320068359375 +61897 -0.2388916015625 +61898 -0.227935791015625 +61899 -0.1632080078125 +61900 -0.12347412109375 +61901 -0.088836669921875 +61902 -0.02764892578125 +61903 -0.020538330078125 +61904 0.077667236328125 +61905 0.0545654296875 +61906 0.2132568359375 +61907 0.151275634765625 +61908 0.38885498046875 +61909 0.2764892578125 +61910 0.582794189453125 +61911 0.414794921875 +61912 0.734039306640625 +61913 0.522705078125 +61914 0.800140380859375 +61915 0.569976806640625 +61916 0.7783203125 +61917 0.554595947265625 +61918 0.6651611328125 +61919 0.474151611328125 +61920 0.45965576171875 +61921 0.32794189453125 +61922 0.199188232421875 +61923 0.142547607421875 +61924 -0.050689697265625 +61925 -0.03533935546875 +61926 -0.23297119140625 +61927 -0.165130615234375 +61928 -0.33013916015625 +61929 -0.234375 +61930 -0.368408203125 +61931 -0.26171875 +61932 -0.378936767578125 +61933 -0.269317626953125 +61934 -0.376983642578125 +61935 -0.268035888671875 +61936 -0.37969970703125 +61937 -0.270111083984375 +61938 -0.391510009765625 +61939 -0.278656005859375 +61940 -0.385345458984375 +61941 -0.2744140625 +61942 -0.3419189453125 +61943 -0.243621826171875 +61944 -0.28289794921875 +61945 -0.20172119140625 +61946 -0.251617431640625 +61947 -0.179534912109375 +61948 -0.266143798828125 +61949 -0.189910888671875 +61950 -0.273345947265625 +61951 -0.195037841796875 +61952 -0.216796875 +61953 -0.154632568359375 +61954 -0.128265380859375 +61955 -0.091522216796875 +61956 -0.068145751953125 +61957 -0.04974365234375 +61958 -0.0430908203125 +61959 -0.034027099609375 +61960 -0.024444580078125 +61961 -0.022918701171875 +61962 0.020721435546875 +61963 0.008270263671875 +61964 0.124481201171875 +61965 0.083465576171875 +61966 0.25787353515625 +61967 0.181243896484375 +61968 0.379119873046875 +61969 0.27056884765625 +61970 0.47991943359375 +61971 0.3453369140625 +61972 0.5281982421875 +61973 0.38165283203125 +61974 0.511138916015625 +61975 0.369964599609375 +61976 0.456207275390625 +61977 0.330657958984375 +61978 0.407470703125 +61979 0.296417236328125 +61980 0.383758544921875 +61981 0.281097412109375 +61982 0.35687255859375 +61983 0.263580322265625 +61984 0.31182861328125 +61985 0.232574462890625 +61986 0.250885009765625 +61987 0.18963623046875 +61988 0.1654052734375 +61989 0.128173828125 +61990 0.035247802734375 +61991 0.03314208984375 +61992 -0.142059326171875 +61993 -0.097381591796875 +61994 -0.33563232421875 +61995 -0.240478515625 +61996 -0.5345458984375 +61997 -0.388031005859375 +61998 -0.72186279296875 +61999 -0.527496337890625 +62000 -0.836669921875 +62001 -0.613525390625 +62002 -0.8326416015625 +62003 -0.611602783203125 +62004 -0.7296142578125 +62005 -0.536407470703125 +62006 -0.582550048828125 +62007 -0.428741455078125 +62008 -0.440093994140625 +62009 -0.32470703125 +62010 -0.324310302734375 +62011 -0.2406005859375 +62012 -0.20147705078125 +62013 -0.151214599609375 +62014 -0.044647216796875 +62015 -0.036376953125 +62016 0.103973388671875 +62017 0.07257080078125 +62018 0.202392578125 +62019 0.14447021484375 +62020 0.264495849609375 +62021 0.189727783203125 +62022 0.338897705078125 +62023 0.24456787109375 +62024 0.443817138671875 +62025 0.322540283203125 +62026 0.545074462890625 +62027 0.398193359375 +62028 0.6173095703125 +62029 0.45263671875 +62030 0.6524658203125 +62031 0.479827880859375 +62032 0.66339111328125 +62033 0.4892578125 +62034 0.6561279296875 +62035 0.4853515625 +62036 0.606781005859375 +62037 0.450225830078125 +62038 0.501190185546875 +62039 0.373260498046875 +62040 0.352783203125 +62041 0.264373779296875 +62042 0.176544189453125 +62043 0.134613037109375 +62044 -0.034820556640625 +62045 -0.021484375 +62046 -0.258209228515625 +62047 -0.186798095703125 +62048 -0.44244384765625 +62049 -0.32330322265625 +62050 -0.5753173828125 +62051 -0.421905517578125 +62052 -0.65203857421875 +62053 -0.47906494140625 +62054 -0.641632080078125 +62055 -0.471710205078125 +62056 -0.562164306640625 +62057 -0.413299560546875 +62058 -0.458038330078125 +62059 -0.3367919921875 +62060 -0.350555419921875 +62061 -0.257965087890625 +62062 -0.260528564453125 +62063 -0.192230224609375 +62064 -0.192108154296875 +62065 -0.142608642578125 +62066 -0.141937255859375 +62067 -0.106536865234375 +62068 -0.1021728515625 +62069 -0.078094482421875 +62070 -0.062896728515625 +62071 -0.04986572265625 +62072 -0.011932373046875 +62073 -0.012725830078125 +62074 0.062835693359375 +62075 0.0423583984375 +62076 0.148712158203125 +62077 0.105987548828125 +62078 0.241729736328125 +62079 0.1751708984375 +62080 0.34912109375 +62081 0.25531005859375 +62082 0.457305908203125 +62083 0.336273193359375 +62084 0.54388427734375 +62085 0.4013671875 +62086 0.5728759765625 +62087 0.42376708984375 +62088 0.506591796875 +62089 0.375396728515625 +62090 0.351226806640625 +62091 0.26080322265625 +62092 0.146514892578125 +62093 0.109466552734375 +62094 -0.05523681640625 +62095 -0.03973388671875 +62096 -0.21624755859375 +62097 -0.158721923828125 +62098 -0.334930419921875 +62099 -0.246337890625 +62100 -0.402984619140625 +62101 -0.29644775390625 +62102 -0.4412841796875 +62103 -0.3245849609375 +62104 -0.49578857421875 +62105 -0.364990234375 +62106 -0.5601806640625 +62107 -0.412933349609375 +62108 -0.600738525390625 +62109 -0.443328857421875 +62110 -0.584228515625 +62111 -0.43145751953125 +62112 -0.47930908203125 +62113 -0.35394287109375 +62114 -0.27935791015625 +62115 -0.20587158203125 +62116 -0.0089111328125 +62117 -0.00543212890625 +62118 0.268798828125 +62119 0.200347900390625 +62120 0.482818603515625 +62121 0.3587646484375 +62122 0.60369873046875 +62123 0.447967529296875 +62124 0.650421142578125 +62125 0.4820556640625 +62126 0.66400146484375 +62127 0.4915771484375 +62128 0.6414794921875 +62129 0.474395751953125 +62130 0.572540283203125 +62131 0.422821044921875 +62132 0.498138427734375 +62133 0.36737060546875 +62134 0.439453125 +62135 0.32379150390625 +62136 0.375518798828125 +62137 0.2764892578125 +62138 0.274505615234375 +62139 0.201751708984375 +62140 0.1087646484375 +62141 0.0789794921875 +62142 -0.099395751953125 +62143 -0.075286865234375 +62144 -0.3182373046875 +62145 -0.2374267578125 +62146 -0.5489501953125 +62147 -0.408355712890625 +62148 -0.7738037109375 +62149 -0.574920654296875 +62150 -0.86383056640625 +62151 -0.697784423828125 +62152 -0.870391845703125 +62153 -0.752227783203125 +62154 -0.86895751953125 +62155 -0.751495361328125 +62156 -0.861053466796875 +62157 -0.705322265625 +62158 -0.765869140625 +62159 -0.600860595703125 +62160 -0.5301513671875 +62161 -0.42974853515625 +62162 -0.214691162109375 +62163 -0.197296142578125 +62164 0.137359619140625 +62165 0.064483642578125 +62166 0.474822998046875 +62167 0.31744384765625 +62168 0.76239013671875 +62169 0.535186767578125 +62170 0.867462158203125 +62171 0.6976318359375 +62172 0.870361328125 +62173 0.80517578125 +62174 0.86480712890625 +62175 0.849212646484375 +62176 0.831817626953125 +62177 0.833770751953125 +62178 0.677581787109375 +62179 0.777008056640625 +62180 0.495880126953125 +62181 0.683258056640625 +62182 0.30767822265625 +62183 0.56634521484375 +62184 0.116180419921875 +62185 0.427947998046875 +62186 -0.110748291015625 +62187 0.24444580078125 +62188 -0.381805419921875 +62189 0.010711669921875 +62190 -0.6572265625 +62191 -0.241424560546875 +62192 -0.857421875 +62193 -0.4674072265625 +62194 -0.870391845703125 +62195 -0.635284423828125 +62196 -0.870391845703125 +62197 -0.739776611328125 +62198 -0.86444091796875 +62199 -0.8009033203125 +62200 -0.85723876953125 +62201 -0.84521484375 +62202 -0.790008544921875 +62203 -0.855010986328125 +62204 -0.62847900390625 +62205 -0.802215576171875 +62206 -0.3956298828125 +62207 -0.67218017578125 +62208 -0.126708984375 +62209 -0.493408203125 +62210 0.150115966796875 +62211 -0.28631591796875 +62212 0.424041748046875 +62213 -0.059326171875 +62214 0.670623779296875 +62215 0.167266845703125 +62216 0.854522705078125 +62217 0.3638916015625 +62218 0.866485595703125 +62219 0.517333984375 +62220 0.86920166015625 +62221 0.615997314453125 +62222 0.8653564453125 +62223 0.674224853515625 +62224 0.857147216796875 +62225 0.70257568359375 +62226 0.766845703125 +62227 0.69879150390625 +62228 0.628509521484375 +62229 0.666778564453125 +62230 0.462127685546875 +62231 0.60113525390625 +62232 0.297210693359375 +62233 0.521636962890625 +62234 0.14862060546875 +62235 0.43756103515625 +62236 -0.00537109375 +62237 0.330841064453125 +62238 -0.15753173828125 +62239 0.2069091796875 +62240 -0.31304931640625 +62241 0.06256103515625 +62242 -0.48876953125 +62243 -0.1134033203125 +62244 -0.6416015625 +62245 -0.284942626953125 +62246 -0.751373291015625 +62247 -0.433135986328125 +62248 -0.84619140625 +62249 -0.57611083984375 +62250 -0.861297607421875 +62251 -0.70257568359375 +62252 -0.863250732421875 +62253 -0.78680419921875 +62254 -0.856597900390625 +62255 -0.80426025390625 +62256 -0.7498779296875 +62257 -0.7642822265625 +62258 -0.624542236328125 +62259 -0.7115478515625 +62260 -0.47808837890625 +62261 -0.6287841796875 +62262 -0.253387451171875 +62263 -0.4703369140625 +62264 0.003692626953125 +62265 -0.271331787109375 +62266 0.2257080078125 +62267 -0.084564208984375 +62268 0.427154541015625 +62269 0.0999755859375 +62270 0.643218994140625 +62271 0.30767822265625 +62272 0.855926513671875 +62273 0.531219482421875 +62274 0.870361328125 +62275 0.725830078125 +62276 0.870361328125 +62277 0.853057861328125 +62278 0.862762451171875 +62279 0.8614501953125 +62280 0.79669189453125 +62281 0.861602783203125 +62282 0.595794677734375 +62283 0.849761962890625 +62284 0.362152099609375 +62285 0.73065185546875 +62286 0.1270751953125 +62287 0.58416748046875 +62288 -0.086944580078125 +62289 0.426513671875 +62290 -0.2784423828125 +62291 0.259124755859375 +62292 -0.484832763671875 +62293 0.0548095703125 +62294 -0.729583740234375 +62295 -0.201507568359375 +62296 -0.86688232421875 +62297 -0.470703125 +62298 -0.870391845703125 +62299 -0.703765869140625 +62300 -0.86859130859375 +62301 -0.859130859375 +62302 -0.86279296875 +62303 -0.870391845703125 +62304 -0.817962646484375 +62305 -0.870391845703125 +62306 -0.6116943359375 +62307 -0.8599853515625 +62308 -0.3128662109375 +62309 -0.712371826171875 +62310 0.039398193359375 +62311 -0.4517822265625 +62312 0.422821044921875 +62313 -0.140289306640625 +62314 0.805145263671875 +62315 0.195465087890625 +62316 0.870361328125 +62317 0.5029296875 +62318 0.870361328125 +62319 0.739105224609375 +62320 0.860015869140625 +62321 0.859100341796875 +62322 0.727935791015625 +62323 0.867462158203125 +62324 0.48114013671875 +62325 0.8668212890625 +62326 0.2059326171875 +62327 0.85968017578125 +62328 -0.06103515625 +62329 0.798126220703125 +62330 -0.29913330078125 +62331 0.66748046875 +62332 -0.516204833984375 +62333 0.502532958984375 +62334 -0.7252197265625 +62335 0.29449462890625 +62336 -0.85980224609375 +62337 0.0653076171875 +62338 -0.870391845703125 +62339 -0.15643310546875 +62340 -0.870391845703125 +62341 -0.34661865234375 +62342 -0.858062744140625 +62343 -0.467132568359375 +62344 -0.673004150390625 +62345 -0.515167236328125 +62346 -0.42694091796875 +62347 -0.53265380859375 +62348 -0.2100830078125 +62349 -0.55584716796875 +62350 -0.0362548828125 +62351 -0.58551025390625 +62352 0.10943603515625 +62353 -0.60186767578125 +62354 0.23516845703125 +62355 -0.592529296875 +62356 0.373687744140625 +62357 -0.528472900390625 +62358 0.517791748046875 +62359 -0.4141845703125 +62360 0.602783203125 +62361 -0.30133056640625 +62362 0.635711669921875 +62363 -0.188262939453125 +62364 0.655181884765625 +62365 -0.05096435546875 +62366 0.65948486328125 +62367 0.101531982421875 +62368 0.651275634765625 +62369 0.26239013671875 +62370 0.61846923828125 +62371 0.41259765625 +62372 0.53753662109375 +62373 0.524078369140625 +62374 0.404144287109375 +62375 0.584014892578125 +62376 0.22186279296875 +62377 0.586578369140625 +62378 0.003997802734375 +62379 0.534820556640625 +62380 -0.22100830078125 +62381 0.44512939453125 +62382 -0.42449951171875 +62383 0.336029052734375 +62384 -0.579833984375 +62385 0.22662353515625 +62386 -0.641876220703125 +62387 0.15240478515625 +62388 -0.6177978515625 +62389 0.11029052734375 +62390 -0.575531005859375 +62391 0.0518798828125 +62392 -0.526336669921875 +62393 -0.02569580078125 +62394 -0.42645263671875 +62395 -0.08148193359375 +62396 -0.2581787109375 +62397 -0.093963623046875 +62398 -0.068695068359375 +62399 -0.091644287109375 +62400 0.09222412109375 +62401 -0.105194091796875 +62402 0.232147216796875 +62403 -0.12139892578125 +62404 0.3509521484375 +62405 -0.133941650390625 +62406 0.410064697265625 +62407 -0.167633056640625 +62408 0.372955322265625 +62409 -0.247161865234375 +62410 0.2554931640625 +62411 -0.3582763671875 +62412 0.10711669921875 +62413 -0.46246337890625 +62414 -0.052886962890625 +62415 -0.5462646484375 +62416 -0.186279296875 +62417 -0.5830078125 +62418 -0.23291015625 +62419 -0.530426025390625 +62420 -0.209442138671875 +62421 -0.40692138671875 +62422 -0.174163818359375 +62423 -0.263946533203125 +62424 -0.126739501953125 +62425 -0.10784912109375 +62426 -0.048126220703125 +62427 0.06951904296875 +62428 0.0426025390625 +62429 0.247100830078125 +62430 0.10748291015625 +62431 0.389892578125 +62432 0.1409912109375 +62433 0.48895263671875 +62434 0.19708251953125 +62435 0.582733154296875 +62436 0.273651123046875 +62437 0.66754150390625 +62438 0.31768798828125 +62439 0.701568603515625 +62440 0.341094970703125 +62441 0.694793701171875 +62442 0.368011474609375 +62443 0.66802978515625 +62444 0.37249755859375 +62445 0.6043701171875 +62446 0.30072021484375 +62447 0.466278076171875 +62448 0.1517333984375 +62449 0.2579345703125 +62450 -0.01470947265625 +62451 0.031036376953125 +62452 -0.1883544921875 +62453 -0.200958251953125 +62454 -0.372711181640625 +62455 -0.43548583984375 +62456 -0.51397705078125 +62457 -0.6259765625 +62458 -0.57177734375 +62459 -0.736968994140625 +62460 -0.53948974609375 +62461 -0.760162353515625 +62462 -0.43511962890625 +62463 -0.707427978515625 +62464 -0.2962646484375 +62465 -0.606689453125 +62466 -0.161102294921875 +62467 -0.487640380859375 +62468 -0.0435791015625 +62469 -0.362579345703125 +62470 0.060394287109375 +62471 -0.2308349609375 +62472 0.13665771484375 +62473 -0.107086181640625 +62474 0.170135498046875 +62475 -0.00738525390625 +62476 0.16552734375 +62477 0.067626953125 +62478 0.15728759765625 +62479 0.14093017578125 +62480 0.150787353515625 +62481 0.21240234375 +62482 0.12200927734375 +62483 0.25872802734375 +62484 0.080108642578125 +62485 0.283660888671875 +62486 0.05126953125 +62487 0.3052978515625 +62488 0.062896728515625 +62489 0.343536376953125 +62490 0.09271240234375 +62491 0.379425048828125 +62492 0.092987060546875 +62493 0.3746337890625 +62494 0.07855224609375 +62495 0.341796875 +62496 0.06427001953125 +62497 0.29443359375 +62498 0.0347900390625 +62499 0.22265625 +62500 -0.01171875 +62501 0.127960205078125 +62502 -0.056060791015625 +62503 0.029144287109375 +62504 -0.055511474609375 +62505 -0.035980224609375 +62506 -0.010467529296875 +62507 -0.064056396484375 +62508 0.02508544921875 +62509 -0.094818115234375 +62510 0.025665283203125 +62511 -0.145538330078125 +62512 0.017333984375 +62513 -0.19281005859375 +62514 0.00189208984375 +62515 -0.233306884765625 +62516 -0.03173828125 +62517 -0.27471923828125 +62518 -0.071502685546875 +62519 -0.30706787109375 +62520 -0.13543701171875 +62521 -0.3450927734375 +62522 -0.219970703125 +62523 -0.387054443359375 +62524 -0.300506591796875 +62525 -0.4150390625 +62526 -0.376312255859375 +62527 -0.430755615234375 +62528 -0.416107177734375 +62529 -0.411865234375 +62530 -0.371124267578125 +62531 -0.322296142578125 +62532 -0.242279052734375 +62533 -0.165771484375 +62534 -0.069732666015625 +62535 0.02264404296875 +62536 0.125640869140625 +62537 0.22357177734375 +62538 0.31268310546875 +62539 0.409820556640625 +62540 0.45501708984375 +62541 0.550537109375 +62542 0.554779052734375 +62543 0.646270751953125 +62544 0.61065673828125 +62545 0.695404052734375 +62546 0.610931396484375 +62547 0.688629150390625 +62548 0.531463623046875 +62549 0.60736083984375 +62550 0.3883056640625 +62551 0.465728759765625 +62552 0.23468017578125 +62553 0.308074951171875 +62554 0.095245361328125 +62555 0.156219482421875 +62556 -0.00396728515625 +62557 0.0333251953125 +62558 -0.04852294921875 +62559 -0.046600341796875 +62560 -0.055145263671875 +62561 -0.094451904296875 +62562 -0.0758056640625 +62563 -0.149566650390625 +62564 -0.138702392578125 +62565 -0.232513427734375 +62566 -0.209197998046875 +62567 -0.31396484375 +62568 -0.289031982421875 +62569 -0.394195556640625 +62570 -0.37884521484375 +62571 -0.473052978515625 +62572 -0.456329345703125 +62573 -0.532562255859375 +62574 -0.51641845703125 +62575 -0.569091796875 +62576 -0.519287109375 +62577 -0.551666259765625 +62578 -0.458251953125 +62579 -0.47625732421875 +62580 -0.384796142578125 +62581 -0.38568115234375 +62582 -0.323699951171875 +62583 -0.301666259765625 +62584 -0.269287109375 +62585 -0.221649169921875 +62586 -0.1951904296875 +62587 -0.1265869140625 +62588 -0.100006103515625 +62589 -0.01727294921875 +62590 -0.01055908203125 +62591 0.083038330078125 +62592 0.1033935546875 +62593 0.197113037109375 +62594 0.24908447265625 +62595 0.329681396484375 +62596 0.373199462890625 +62597 0.437408447265625 +62598 0.45806884765625 +62599 0.50592041015625 +62600 0.511474609375 +62601 0.5416259765625 +62602 0.565399169921875 +62603 0.570770263671875 +62604 0.61138916015625 +62605 0.5875244140625 +62606 0.5897216796875 +62607 0.545379638671875 +62608 0.4906005859375 +62609 0.43792724609375 +62610 0.33148193359375 +62611 0.280792236328125 +62612 0.147796630859375 +62613 0.10400390625 +62614 -0.01873779296875 +62615 -0.05743408203125 +62616 -0.140289306640625 +62617 -0.17974853515625 +62618 -0.191986083984375 +62619 -0.241790771484375 +62620 -0.184295654296875 +62621 -0.25091552734375 +62622 -0.161834716796875 +62623 -0.242156982421875 +62624 -0.166595458984375 +62625 -0.248748779296875 +62626 -0.19390869140625 +62627 -0.2669677734375 +62628 -0.22442626953125 +62629 -0.28173828125 +62630 -0.279754638671875 +62631 -0.31103515625 +62632 -0.3389892578125 +62633 -0.339111328125 +62634 -0.3543701171875 +62635 -0.3289794921875 +62636 -0.348175048828125 +62637 -0.29974365234375 +62638 -0.32598876953125 +62639 -0.257232666015625 +62640 -0.2581787109375 +62641 -0.17913818359375 +62642 -0.139801025390625 +62643 -0.062774658203125 +62644 0.014617919921875 +62645 0.07916259765625 +62646 0.144378662109375 +62647 0.1971435546875 +62648 0.221038818359375 +62649 0.267791748046875 +62650 0.27069091796875 +62651 0.311614990234375 +62652 0.294036865234375 +62653 0.3291015625 +62654 0.311767578125 +62655 0.337005615234375 +62656 0.339141845703125 +62657 0.34808349609375 +62658 0.360260009765625 +62659 0.35040283203125 +62660 0.360504150390625 +62661 0.333160400390625 +62662 0.308380126953125 +62663 0.271881103515625 +62664 0.18170166015625 +62665 0.14971923828125 +62666 0.0047607421875 +62667 -0.0125732421875 +62668 -0.17559814453125 +62669 -0.1761474609375 +62670 -0.3143310546875 +62671 -0.3037109375 +62672 -0.36785888671875 +62673 -0.359283447265625 +62674 -0.36248779296875 +62675 -0.363494873046875 +62676 -0.343536376953125 +62677 -0.352630615234375 +62678 -0.3018798828125 +62679 -0.319244384765625 +62680 -0.231414794921875 +62681 -0.258453369140625 +62682 -0.117645263671875 +62683 -0.158905029296875 +62684 0.007049560546875 +62685 -0.047271728515625 +62686 0.087982177734375 +62687 0.031585693359375 +62688 0.13946533203125 +62689 0.088409423828125 +62690 0.17425537109375 +62691 0.13262939453125 +62692 0.188201904296875 +62693 0.15997314453125 +62694 0.171234130859375 +62695 0.16143798828125 +62696 0.118438720703125 +62697 0.13226318359375 +62698 0.05706787109375 +62699 0.093780517578125 +62700 -0.010711669921875 +62701 0.04718017578125 +62702 -0.0914306640625 +62703 -0.013153076171875 +62704 -0.162322998046875 +62705 -0.0689697265625 +62706 -0.194549560546875 +62707 -0.09698486328125 +62708 -0.1492919921875 +62709 -0.06561279296875 +62710 -0.02166748046875 +62711 0.029449462890625 +62712 0.124053955078125 +62713 0.136810302734375 +62714 0.211151123046875 +62715 0.195098876953125 +62716 0.240447998046875 +62717 0.205718994140625 +62718 0.242218017578125 +62719 0.19384765625 +62720 0.2257080078125 +62721 0.168243408203125 +62722 0.194366455078125 +62723 0.132080078125 +62724 0.115509033203125 +62725 0.05780029296875 +62726 0.0128173828125 +62727 -0.03424072265625 +62728 -0.053802490234375 +62729 -0.093475341796875 +62730 -0.110626220703125 +62731 -0.141845703125 +62732 -0.199493408203125 +62733 -0.21453857421875 +62734 -0.29437255859375 +62735 -0.289825439453125 +62736 -0.33221435546875 +62737 -0.315032958984375 +62738 -0.27972412109375 +62739 -0.26263427734375 +62740 -0.185333251953125 +62741 -0.17376708984375 +62742 -0.128204345703125 +62743 -0.115478515625 +62744 -0.115692138671875 +62745 -0.094512939453125 +62746 -0.116455078125 +62747 -0.08514404296875 +62748 -0.105926513671875 +62749 -0.0672607421875 +62750 -0.053955078125 +62751 -0.016021728515625 +62752 0.048797607421875 +62753 0.0760498046875 +62754 0.157318115234375 +62755 0.1708984375 +62756 0.212005615234375 +62757 0.21832275390625 +62758 0.218475341796875 +62759 0.222991943359375 +62760 0.23724365234375 +62761 0.235870361328125 +62762 0.30535888671875 +62763 0.288299560546875 +62764 0.38128662109375 +62765 0.345703125 +62766 0.404449462890625 +62767 0.3575439453125 +62768 0.3944091796875 +62769 0.34075927734375 +62770 0.3885498046875 +62771 0.32720947265625 +62772 0.362640380859375 +62773 0.297027587890625 +62774 0.27362060546875 +62775 0.2144775390625 +62776 0.11712646484375 +62777 0.0762939453125 +62778 -0.054901123046875 +62779 -0.073486328125 +62780 -0.19085693359375 +62781 -0.1912841796875 +62782 -0.28570556640625 +62783 -0.27276611328125 +62784 -0.339263916015625 +62785 -0.317718505859375 +62786 -0.3775634765625 +62787 -0.34808349609375 +62788 -0.445709228515625 +62789 -0.401885986328125 +62790 -0.535064697265625 +62791 -0.47210693359375 +62792 -0.629058837890625 +62793 -0.54510498046875 +62794 -0.697601318359375 +62795 -0.59600830078125 +62796 -0.70391845703125 +62797 -0.594268798828125 +62798 -0.6424560546875 +62799 -0.535614013671875 +62800 -0.491241455078125 +62801 -0.4019775390625 +62802 -0.265716552734375 +62803 -0.206695556640625 +62804 -0.023712158203125 +62805 0.001373291015625 +62806 0.201751708984375 +62807 0.1942138671875 +62808 0.375823974609375 +62809 0.3424072265625 +62810 0.485076904296875 +62811 0.43463134765625 +62812 0.56884765625 +62813 0.503997802734375 +62814 0.634765625 +62815 0.556976318359375 +62816 0.63763427734375 +62817 0.555755615234375 +62818 0.5660400390625 +62819 0.490966796875 +62820 0.4720458984375 +62821 0.406646728515625 +62822 0.40692138671875 +62823 0.346160888671875 +62824 0.3778076171875 +62825 0.31585693359375 +62826 0.376953125 +62827 0.309539794921875 +62828 0.371978759765625 +62829 0.30029296875 +62830 0.313140869140625 +62831 0.246612548828125 +62832 0.184417724609375 +62833 0.135223388671875 +62834 0.011199951171875 +62835 -0.0123291015625 +62836 -0.171051025390625 +62837 -0.16619873046875 +62838 -0.33740234375 +62839 -0.305450439453125 +62840 -0.47198486328125 +62841 -0.41680908203125 +62842 -0.560394287109375 +62843 -0.48834228515625 +62844 -0.58056640625 +62845 -0.501678466796875 +62846 -0.54754638671875 +62847 -0.46966552734375 +62848 -0.508575439453125 +62849 -0.4322509765625 +62850 -0.459503173828125 +62851 -0.386199951171875 +62852 -0.394378662109375 +62853 -0.326812744140625 +62854 -0.35260009765625 +62855 -0.28741455078125 +62856 -0.31170654296875 +62857 -0.249359130859375 +62858 -0.197418212890625 +62859 -0.150421142578125 +62860 -0.007965087890625 +62861 0.0107421875 +62862 0.207489013671875 +62863 0.192718505859375 +62864 0.409210205078125 +62865 0.362091064453125 +62866 0.57208251953125 +62867 0.497802734375 +62868 0.66595458984375 +62869 0.57464599609375 +62870 0.65875244140625 +62871 0.5657958984375 +62872 0.56744384765625 +62873 0.485687255859375 +62874 0.431396484375 +62875 0.36761474609375 +62876 0.29443359375 +62877 0.24859619140625 +62878 0.182464599609375 +62879 0.150634765625 +62880 0.06365966796875 +62881 0.04718017578125 +62882 -0.075958251953125 +62883 -0.07330322265625 +62884 -0.189422607421875 +62885 -0.17120361328125 +62886 -0.271942138671875 +62887 -0.24237060546875 +62888 -0.342529296875 +62889 -0.30267333984375 +62890 -0.364166259765625 +62891 -0.321014404296875 +62892 -0.327239990234375 +62893 -0.28936767578125 +62894 -0.2769775390625 +62895 -0.245758056640625 +62896 -0.253692626953125 +62897 -0.224151611328125 +62898 -0.24365234375 +62899 -0.213104248046875 +62900 -0.1983642578125 +62901 -0.172088623046875 +62902 -0.116241455078125 +62903 -0.09991455078125 +62904 -0.036834716796875 +62905 -0.029937744140625 +62906 0.034881591796875 +62907 0.033416748046875 +62908 0.09124755859375 +62909 0.083526611328125 +62910 0.10888671875 +62911 0.100677490234375 +62912 0.125518798828125 +62913 0.116424560546875 +62914 0.15771484375 +62915 0.14459228515625 +62916 0.17828369140625 +62917 0.16229248046875 +62918 0.17108154296875 +62919 0.15594482421875 +62920 0.129974365234375 +62921 0.120452880859375 +62922 0.082427978515625 +62923 0.0789794921875 +62924 0.027679443359375 +62925 0.030975341796875 +62926 -0.065643310546875 +62927 -0.049774169921875 +62928 -0.15936279296875 +62929 -0.131072998046875 +62930 -0.21307373046875 +62931 -0.1788330078125 +62932 -0.234649658203125 +62933 -0.19952392578125 +62934 -0.2001953125 +62935 -0.172943115234375 +62936 -0.119171142578125 +62937 -0.106903076171875 +62938 -0.024749755859375 +62939 -0.0291748046875 +62940 0.085784912109375 +62941 0.062591552734375 +62942 0.178131103515625 +62943 0.139617919921875 +62944 0.215576171875 +62945 0.171112060546875 +62946 0.211456298828125 +62947 0.168212890625 +62948 0.17523193359375 +62949 0.13885498046875 +62950 0.128753662109375 +62951 0.101318359375 +62952 0.1019287109375 +62953 0.080596923828125 +62954 0.0743408203125 +62955 0.059478759765625 +62956 0.04327392578125 +62957 0.035552978515625 +62958 0.038177490234375 +62959 0.033416748046875 +62960 0.076263427734375 +62961 0.067413330078125 +62962 0.14105224609375 +62963 0.12359619140625 +62964 0.186431884765625 +62965 0.16314697265625 +62966 0.188812255859375 +62967 0.166168212890625 +62968 0.1390380859375 +62969 0.124908447265625 +62970 0.041778564453125 +62971 0.043304443359375 +62972 -0.079437255859375 +62973 -0.058837890625 +62974 -0.219390869140625 +62975 -0.177154541015625 +62976 -0.367828369140625 +62977 -0.303253173828125 +62978 -0.494873046875 +62979 -0.412445068359375 +62980 -0.556243896484375 +62981 -0.466522216796875 +62982 -0.508697509765625 +62983 -0.427398681640625 +62984 -0.3756103515625 +62985 -0.315032958984375 +62986 -0.218902587890625 +62987 -0.1829833984375 +62988 -0.063751220703125 +62989 -0.05279541015625 +62990 0.091552734375 +62991 0.07745361328125 +62992 0.23602294921875 +62993 0.19854736328125 +62994 0.342987060546875 +62995 0.28753662109375 +62996 0.39520263671875 +62997 0.329620361328125 +62998 0.389373779296875 +62999 0.322113037109375 +63000 0.324249267578125 +63001 0.264007568359375 +63002 0.224090576171875 +63003 0.176483154296875 +63004 0.124267578125 +63005 0.090362548828125 +63006 0.037078857421875 +63007 0.0162353515625 +63008 -0.010101318359375 +63009 -0.022125244140625 +63010 -0.019439697265625 +63011 -0.026824951171875 +63012 -0.022796630859375 +63013 -0.02581787109375 +63014 -0.001556396484375 +63015 -0.003143310546875 +63016 0.056304931640625 +63017 0.05145263671875 +63018 0.106719970703125 +63019 0.09930419921875 +63020 0.096893310546875 +63021 0.09417724609375 +63022 0.042694091796875 +63023 0.04974365234375 +63024 -0.018035888671875 +63025 -0.00115966796875 +63026 -0.07586669921875 +63027 -0.05035400390625 +63028 -0.11944580078125 +63029 -0.0880126953125 +63030 -0.15972900390625 +63031 -0.12371826171875 +63032 -0.202606201171875 +63033 -0.16253662109375 +63034 -0.24859619140625 +63035 -0.20477294921875 +63036 -0.30517578125 +63037 -0.256805419921875 +63038 -0.36212158203125 +63039 -0.3095703125 +63040 -0.39141845703125 +63041 -0.338470458984375 +63042 -0.35528564453125 +63043 -0.31036376953125 +63044 -0.249969482421875 +63045 -0.2218017578125 +63046 -0.092864990234375 +63047 -0.08782958984375 +63048 0.08905029296875 +63049 0.0682373046875 +63050 0.2352294921875 +63051 0.1937255859375 +63052 0.318817138671875 +63053 0.26531982421875 +63054 0.358642578125 +63055 0.299468994140625 +63056 0.347747802734375 +63057 0.290130615234375 +63058 0.28564453125 +63059 0.23687744140625 +63060 0.223175048828125 +63061 0.183929443359375 +63062 0.196746826171875 +63063 0.162933349609375 +63064 0.179840087890625 +63065 0.150665283203125 +63066 0.155548095703125 +63067 0.132232666015625 +63068 0.151214599609375 +63069 0.131317138671875 +63070 0.156951904296875 +63071 0.13916015625 +63072 0.13177490234375 +63073 0.119842529296875 +63074 0.100799560546875 +63075 0.095123291015625 +63076 0.087127685546875 +63077 0.08502197265625 +63078 0.05487060546875 +63079 0.05816650390625 +63080 -0.009002685546875 +63081 0.00311279296875 +63082 -0.10400390625 +63083 -0.079681396484375 +63084 -0.229400634765625 +63085 -0.1895751953125 +63086 -0.35552978515625 +63087 -0.3006591796875 +63088 -0.441925048828125 +63089 -0.3775634765625 +63090 -0.473846435546875 +63091 -0.4073486328125 +63092 -0.464813232421875 +63093 -0.40167236328125 +63094 -0.419097900390625 +63095 -0.3641357421875 +63096 -0.334320068359375 +63097 -0.29254150390625 +63098 -0.227935791015625 +63099 -0.201934814453125 +63100 -0.12347412109375 +63101 -0.112762451171875 +63102 -0.02764892578125 +63103 -0.030792236328125 +63104 0.077667236328125 +63105 0.05987548828125 +63106 0.2132568359375 +63107 0.177398681640625 +63108 0.38885498046875 +63109 0.330291748046875 +63110 0.582794189453125 +63111 0.499664306640625 +63112 0.734039306640625 +63113 0.63226318359375 +63114 0.800140380859375 +63115 0.6910400390625 +63116 0.7783203125 +63117 0.6734619140625 +63118 0.6651611328125 +63119 0.57647705078125 +63120 0.45965576171875 +63121 0.399139404296875 +63122 0.199188232421875 +63123 0.173919677734375 +63124 -0.050689697265625 +63125 -0.042144775390625 +63126 -0.23297119140625 +63127 -0.19940185546875 +63128 -0.33013916015625 +63129 -0.28271484375 +63130 -0.368408203125 +63131 -0.31500244140625 +63132 -0.378936767578125 +63133 -0.323455810546875 +63134 -0.376983642578125 +63135 -0.3214111328125 +63136 -0.37969970703125 +63137 -0.3238525390625 +63138 -0.391510009765625 +63139 -0.3345947265625 +63140 -0.385345458984375 +63141 -0.33001708984375 +63142 -0.3419189453125 +63143 -0.29327392578125 +63144 -0.28289794921875 +63145 -0.2431640625 +63146 -0.251617431640625 +63147 -0.217376708984375 +63148 -0.266143798828125 +63149 -0.231597900390625 +63150 -0.273345947265625 +63151 -0.239410400390625 +63152 -0.216796875 +63153 -0.1915283203125 +63154 -0.128265380859375 +63155 -0.11553955078125 +63156 -0.068145751953125 +63157 -0.064117431640625 +63158 -0.0430908203125 +63159 -0.04296875 +63160 -0.024444580078125 +63161 -0.027069091796875 +63162 0.020721435546875 +63163 0.012298583984375 +63164 0.124481201171875 +63165 0.10308837890625 +63166 0.25787353515625 +63167 0.219970703125 +63168 0.379119873046875 +63169 0.32647705078125 +63170 0.47991943359375 +63171 0.415374755859375 +63172 0.5281982421875 +63173 0.4586181640625 +63174 0.511138916015625 +63175 0.4449462890625 +63176 0.456207275390625 +63177 0.39825439453125 +63178 0.407470703125 +63179 0.356903076171875 +63180 0.383758544921875 +63181 0.3372802734375 +63182 0.35687255859375 +63183 0.314727783203125 +63184 0.31182861328125 +63185 0.276123046875 +63186 0.250885009765625 +63187 0.223388671875 +63188 0.1654052734375 +63189 0.14898681640625 +63190 0.035247802734375 +63191 0.035369873046875 +63192 -0.142059326171875 +63193 -0.119598388671875 +63194 -0.33563232421875 +63195 -0.28900146484375 +63196 -0.5345458984375 +63197 -0.463226318359375 +63198 -0.72186279296875 +63199 -0.627471923828125 +63200 -0.836669921875 +63201 -0.728546142578125 +63202 -0.8326416015625 +63203 -0.72601318359375 +63204 -0.7296142578125 +63205 -0.63714599609375 +63206 -0.582550048828125 +63207 -0.509796142578125 +63208 -0.440093994140625 +63209 -0.386322021484375 +63210 -0.324310302734375 +63211 -0.28594970703125 +63212 -0.20147705078125 +63213 -0.17926025390625 +63214 -0.044647216796875 +63215 -0.042694091796875 +63216 0.103973388671875 +63217 0.086944580078125 +63218 0.202392578125 +63219 0.173004150390625 +63220 0.264495849609375 +63221 0.22760009765625 +63222 0.338897705078125 +63223 0.2930908203125 +63224 0.443817138671875 +63225 0.385284423828125 +63226 0.545074462890625 +63227 0.474365234375 +63228 0.6173095703125 +63229 0.53814697265625 +63230 0.6524658203125 +63231 0.569580078125 +63232 0.66339111328125 +63233 0.5802001953125 +63234 0.6561279296875 +63235 0.57537841796875 +63236 0.606781005859375 +63237 0.5335693359375 +63238 0.501190185546875 +63239 0.441802978515625 +63240 0.352783203125 +63241 0.311981201171875 +63242 0.176544189453125 +63243 0.15740966796875 +63244 -0.034820556640625 +63245 -0.02880859375 +63246 -0.258209228515625 +63247 -0.22607421875 +63248 -0.44244384765625 +63249 -0.388397216796875 +63250 -0.5753173828125 +63251 -0.504974365234375 +63252 -0.65203857421875 +63253 -0.571685791015625 +63254 -0.641632080078125 +63255 -0.560638427734375 +63256 -0.562164306640625 +63257 -0.488250732421875 +63258 -0.458038330078125 +63259 -0.394683837890625 +63260 -0.350555419921875 +63261 -0.299102783203125 +63262 -0.260528564453125 +63263 -0.22021484375 +63264 -0.192108154296875 +63265 -0.16162109375 +63266 -0.141937255859375 +63267 -0.1201171875 +63268 -0.1021728515625 +63269 -0.08837890625 +63270 -0.062896728515625 +63271 -0.057159423828125 +63272 -0.011932373046875 +63273 -0.01519775390625 +63274 0.062835693359375 +63275 0.048614501953125 +63276 0.148712158203125 +63277 0.123046875 +63278 0.241729736328125 +63279 0.204620361328125 +63280 0.34912109375 +63281 0.300018310546875 +63282 0.457305908203125 +63283 0.397064208984375 +63284 0.54388427734375 +63285 0.475494384765625 +63286 0.5728759765625 +63287 0.50274658203125 +63288 0.506591796875 +63289 0.444671630859375 +63290 0.351226806640625 +63291 0.306732177734375 +63292 0.146514892578125 +63293 0.124664306640625 +63294 -0.05523681640625 +63295 -0.05438232421875 +63296 -0.21624755859375 +63297 -0.19647216796875 +63298 -0.334930419921875 +63299 -0.300323486328125 +63300 -0.402984619140625 +63301 -0.358642578125 +63302 -0.4412841796875 +63303 -0.39044189453125 +63304 -0.49578857421875 +63305 -0.437408447265625 +63306 -0.5601806640625 +63307 -0.49395751953125 +63308 -0.600738525390625 +63309 -0.5296630859375 +63310 -0.584228515625 +63311 -0.5145263671875 +63312 -0.47930908203125 +63313 -0.42022705078125 +63314 -0.27935791015625 +63315 -0.24072265625 +63316 -0.0089111328125 +63317 0.001861572265625 +63318 0.268798828125 +63319 0.250518798828125 +63320 0.482818603515625 +63321 0.441253662109375 +63322 0.60369873046875 +63323 0.547637939453125 +63324 0.650421142578125 +63325 0.586944580078125 +63326 0.66400146484375 +63327 0.596435546875 +63328 0.6414794921875 +63329 0.57354736328125 +63330 0.572540283203125 +63331 0.50909423828125 +63332 0.498138427734375 +63333 0.440216064453125 +63334 0.439453125 +63335 0.386138916015625 +63336 0.375518798828125 +63337 0.327972412109375 +63338 0.274505615234375 +63339 0.2369384765625 +63340 0.1087646484375 +63341 0.087982177734375 +63342 -0.099395751953125 +63343 -0.09881591796875 +63344 -0.3182373046875 +63345 -0.2947998046875 +63346 -0.5489501953125 +63347 -0.501190185546875 +63348 -0.7738037109375 +63349 -0.702056884765625 +63350 -0.86383056640625 +63351 -0.84967041015625 +63352 -0.870391845703125 +63353 -0.86102294921875 +63354 -0.86895751953125 +63355 -0.860748291015625 +63356 -0.861053466796875 +63357 -0.85394287109375 +63358 -0.765869140625 +63359 -0.725738525390625 +63360 -0.5301513671875 +63361 -0.516815185546875 +63362 -0.214691162109375 +63363 -0.233642578125 +63364 0.137359619140625 +63365 0.084808349609375 +63366 0.474822998046875 +63367 0.392181396484375 +63368 0.76239013671875 +63369 0.6563720703125 +63370 0.867462158203125 +63371 0.853057861328125 +63372 0.870361328125 +63373 0.86846923828125 +63374 0.86480712890625 +63375 0.870361328125 +63376 0.831817626953125 +63377 0.864654541015625 +63378 0.677581787109375 +63379 0.849761962890625 +63380 0.495880126953125 +63381 0.71282958984375 +63382 0.30767822265625 +63383 0.554840087890625 +63384 0.116180419921875 +63385 0.37847900390625 +63386 -0.110748291015625 +63387 0.1552734375 +63388 -0.381805419921875 +63389 -0.1212158203125 +63390 -0.6572265625 +63391 -0.4129638671875 +63392 -0.857421875 +63393 -0.666839599609375 +63394 -0.870391845703125 +63395 -0.8453369140625 +63396 -0.870391845703125 +63397 -0.864227294921875 +63398 -0.86444091796875 +63399 -0.8690185546875 +63400 -0.85723876953125 +63401 -0.870391845703125 +63402 -0.790008544921875 +63403 -0.868011474609375 +63404 -0.62847900390625 +63405 -0.856781005859375 +63406 -0.3956298828125 +63407 -0.689697265625 +63408 -0.126708984375 +63409 -0.4527587890625 +63410 0.150115966796875 +63411 -0.190032958984375 +63412 0.424041748046875 +63413 0.08746337890625 +63414 0.670623779296875 +63415 0.355499267578125 +63416 0.854522705078125 +63417 0.579681396484375 +63418 0.866485595703125 +63419 0.745025634765625 +63420 0.86920166015625 +63421 0.8389892578125 +63422 0.8653564453125 +63423 0.857208251953125 +63424 0.857147216796875 +63425 0.85736083984375 +63426 0.766845703125 +63427 0.842193603515625 +63428 0.628509521484375 +63429 0.7698974609375 +63430 0.462127685546875 +63431 0.659698486328125 +63432 0.297210693359375 +63433 0.5364990234375 +63434 0.14862060546875 +63435 0.412689208984375 +63436 -0.00537109375 +63437 0.268524169921875 +63438 -0.15753173828125 +63439 0.111236572265625 +63440 -0.31304931640625 +63441 -0.062347412109375 +63442 -0.48876953125 +63443 -0.265289306640625 +63444 -0.6416015625 +63445 -0.455902099609375 +63446 -0.751373291015625 +63447 -0.61285400390625 +63448 -0.84619140625 +63449 -0.758270263671875 +63450 -0.861297607421875 +63451 -0.857330322265625 +63452 -0.863250732421875 +63453 -0.864990234375 +63454 -0.856597900390625 +63455 -0.864044189453125 +63456 -0.7498779296875 +63457 -0.8558349609375 +63458 -0.624542236328125 +63459 -0.779022216796875 +63460 -0.47808837890625 +63461 -0.659759521484375 +63462 -0.253387451171875 +63463 -0.45697021484375 +63464 0.003692626953125 +63465 -0.212432861328125 +63466 0.2257080078125 +63467 0.0118408203125 +63468 0.427154541015625 +63469 0.227294921875 +63470 0.643218994140625 +63471 0.463653564453125 +63472 0.855926513671875 +63473 0.712921142578125 +63474 0.870361328125 +63475 0.862030029296875 +63476 0.870361328125 +63477 0.870361328125 +63478 0.862762451171875 +63479 0.870361328125 +63480 0.79669189453125 +63481 0.86285400390625 +63482 0.595794677734375 +63483 0.78900146484375 +63484 0.362152099609375 +63485 0.602325439453125 +63486 0.1270751953125 +63487 0.398681640625 +63488 -0.086944580078125 +63489 0.19891357421875 +63490 -0.2784423828125 +63491 0.00543212890625 +63492 -0.484832763671875 +63493 -0.215362548828125 +63494 -0.729583740234375 +63495 -0.48388671875 +63496 -0.86688232421875 +63497 -0.755859375 +63498 -0.870391845703125 +63499 -0.867706298828125 +63500 -0.86859130859375 +63501 -0.870391845703125 +63502 -0.86279296875 +63503 -0.868743896484375 +63504 -0.817962646484375 +63505 -0.86029052734375 +63506 -0.6116943359375 +63507 -0.73370361328125 +63508 -0.3128662109375 +63509 -0.464111328125 +63510 0.039398193359375 +63511 -0.134979248046875 +63512 0.422821044921875 +63513 0.23260498046875 +63514 0.805145263671875 +63515 0.607666015625 +63516 0.870361328125 +63517 0.86260986328125 +63518 0.870361328125 +63519 0.870361328125 +63520 0.860015869140625 +63521 0.8677978515625 +63522 0.727935791015625 +63523 0.8558349609375 +63524 0.48114013671875 +63525 0.680572509765625 +63526 0.2059326171875 +63527 0.4537353515625 +63528 -0.06103515625 +63529 0.219512939453125 +63530 -0.29913330078125 +63531 -0.00323486328125 +63532 -0.516204833984375 +63533 -0.221405029296875 +63534 -0.7252197265625 +63535 -0.44586181640625 +63536 -0.85980224609375 +63537 -0.652923583984375 +63538 -0.870391845703125 +63539 -0.8131103515625 +63540 -0.870391845703125 +63541 -0.859954833984375 +63542 -0.858062744140625 +63543 -0.8582763671875 +63544 -0.673004150390625 +63545 -0.7730712890625 +63546 -0.42694091796875 +63547 -0.617034912109375 +63548 -0.2100830078125 +63549 -0.474365234375 +63550 -0.0362548828125 +63551 -0.3551025390625 +63552 0.10943603515625 +63553 -0.243408203125 +63554 0.23516845703125 +63555 -0.13079833984375 +63556 0.373687744140625 +63557 0.0130615234375 +63558 0.517791748046875 +63559 0.180084228515625 +63560 0.602783203125 +63561 0.307464599609375 +63562 0.635711669921875 +63563 0.39874267578125 +63564 0.655181884765625 +63565 0.486358642578125 +63566 0.65948486328125 +63567 0.564697265625 +63568 0.651275634765625 +63569 0.632049560546875 +63570 0.61846923828125 +63571 0.6729736328125 +63572 0.53753662109375 +63573 0.661651611328125 +63574 0.404144287109375 +63575 0.590728759765625 +63576 0.22186279296875 +63577 0.460906982421875 +63578 0.003997802734375 +63579 0.282806396484375 +63580 -0.22100830078125 +63581 0.08203125 +63582 -0.42449951171875 +63583 -0.114654541015625 +63584 -0.579833984375 +63585 -0.281494140625 +63586 -0.641876220703125 +63587 -0.374603271484375 +63588 -0.6177978515625 +63589 -0.3984375 +63590 -0.575531005859375 +63591 -0.413726806640625 +63592 -0.526336669921875 +63593 -0.427764892578125 +63594 -0.42645263671875 +63595 -0.39617919921875 +63596 -0.2581787109375 +63597 -0.2989501953125 +63598 -0.068695068359375 +63599 -0.176971435546875 +63600 0.09222412109375 +63601 -0.073944091796875 +63602 0.232147216796875 +63603 0.01953125 +63604 0.3509521484375 +63605 0.1051025390625 +63606 0.410064697265625 +63607 0.147705078125 +63608 0.372955322265625 +63609 0.11346435546875 +63610 0.2554931640625 +63611 0.016845703125 +63612 0.10711669921875 +63613 -0.096923828125 +63614 -0.052886962890625 +63615 -0.2115478515625 +63616 -0.186279296875 +63617 -0.293426513671875 +63618 -0.23291015625 +63619 -0.288848876953125 +63620 -0.209442138671875 +63621 -0.2161865234375 +63622 -0.174163818359375 +63623 -0.1328125 +63624 -0.126739501953125 +63625 -0.0411376953125 +63626 -0.048126220703125 +63627 0.0740966796875 +63628 0.0426025390625 +63629 0.192962646484375 +63630 0.10748291015625 +63631 0.2783203125 +63632 0.1409912109375 +63633 0.32391357421875 +63634 0.19708251953125 +63635 0.3797607421875 +63636 0.273651123046875 +63637 0.444061279296875 +63638 0.31768798828125 +63639 0.4678955078125 +63640 0.341094970703125 +63641 0.463623046875 +63642 0.368011474609375 +63643 0.455535888671875 +63644 0.37249755859375 +63645 0.421356201171875 +63646 0.30072021484375 +63647 0.31292724609375 +63648 0.1517333984375 +63649 0.13165283203125 +63650 -0.01470947265625 +63651 -0.064208984375 +63652 -0.1883544921875 +63653 -0.262908935546875 +63654 -0.372711181640625 +63655 -0.46588134765625 +63656 -0.51397705078125 +63657 -0.62127685546875 +63658 -0.57177734375 +63659 -0.690216064453125 +63660 -0.53948974609375 +63661 -0.66595458984375 +63662 -0.43511962890625 +63663 -0.565277099609375 +63664 -0.2962646484375 +63665 -0.423828125 +63666 -0.161102294921875 +63667 -0.278167724609375 +63668 -0.0435791015625 +63669 -0.142608642578125 +63670 0.060394287109375 +63671 -0.014892578125 +63672 0.13665771484375 +63673 0.08990478515625 +63674 0.170135498046875 +63675 0.155792236328125 +63676 0.16552734375 +63677 0.18524169921875 +63678 0.15728759765625 +63679 0.208648681640625 +63680 0.150787353515625 +63681 0.229461669921875 +63682 0.12200927734375 +63683 0.223846435546875 +63684 0.080108642578125 +63685 0.199371337890625 +63686 0.05126953125 +63687 0.179901123046875 +63688 0.062896728515625 +63689 0.19091796875 +63690 0.09271240234375 +63691 0.21173095703125 +63692 0.092987060546875 +63693 0.19830322265625 +63694 0.07855224609375 +63695 0.165435791015625 +63696 0.06427001953125 +63697 0.128265380859375 +63698 0.0347900390625 +63699 0.07379150390625 +63700 -0.01171875 +63701 0.001861572265625 +63702 -0.056060791015625 +63703 -0.06793212890625 +63704 -0.055511474609375 +63705 -0.09405517578125 +63706 -0.010467529296875 +63707 -0.075439453125 +63708 0.02508544921875 +63709 -0.0614013671875 +63710 0.025665283203125 +63711 -0.074859619140625 +63712 0.017333984375 +63713 -0.0908203125 +63714 0.00189208984375 +63715 -0.107330322265625 +63716 -0.03173828125 +63717 -0.134857177734375 +63718 -0.071502685546875 +63719 -0.16253662109375 +63720 -0.13543701171875 +63721 -0.2078857421875 +63722 -0.219970703125 +63723 -0.268524169921875 +63724 -0.300506591796875 +63725 -0.322540283203125 +63726 -0.376312255859375 +63727 -0.370513916015625 +63728 -0.416107177734375 +63729 -0.384429931640625 +63730 -0.371124267578125 +63731 -0.319915771484375 +63732 -0.242279052734375 +63733 -0.17901611328125 +63734 -0.069732666015625 +63735 -0.000396728515625 +63736 0.125640869140625 +63737 0.195526123046875 +63738 0.31268310546875 +63739 0.3790283203125 +63740 0.45501708984375 +63741 0.5157470703125 +63742 0.554779052734375 +63743 0.60760498046875 +63744 0.61065673828125 +63745 0.653839111328125 +63746 0.610931396484375 +63747 0.643829345703125 +63748 0.531463623046875 +63749 0.5550537109375 +63750 0.3883056640625 +63751 0.403472900390625 +63752 0.23468017578125 +63753 0.24053955078125 +63754 0.095245361328125 +63755 0.09063720703125 +63756 -0.00396728515625 +63757 -0.02056884765625 +63758 -0.04852294921875 +63759 -0.0784912109375 +63760 -0.055145263671875 +63761 -0.098175048828125 +63762 -0.0758056640625 +63763 -0.128387451171875 +63764 -0.138702392578125 +63765 -0.19537353515625 +63766 -0.209197998046875 +63767 -0.26593017578125 +63768 -0.289031982421875 +63769 -0.34161376953125 +63770 -0.37884521484375 +63771 -0.42315673828125 +63772 -0.456329345703125 +63773 -0.489654541015625 +63774 -0.51641845703125 +63775 -0.536773681640625 +63776 -0.519287109375 +63777 -0.527313232421875 +63778 -0.458251953125 +63779 -0.45562744140625 +63780 -0.384796142578125 +63781 -0.371429443359375 +63782 -0.323699951171875 +63783 -0.299072265625 +63784 -0.269287109375 +63785 -0.233917236328125 +63786 -0.1951904296875 +63787 -0.151641845703125 +63788 -0.100006103515625 +63789 -0.051513671875 +63790 -0.01055908203125 +63791 0.040496826171875 +63792 0.1033935546875 +63793 0.152801513671875 +63794 0.24908447265625 +63795 0.292144775390625 +63796 0.373199462890625 +63797 0.407958984375 +63798 0.45806884765625 +63799 0.483642578125 +63800 0.511474609375 +63801 0.52691650390625 +63802 0.565399169921875 +63803 0.56866455078125 +63804 0.61138916015625 +63805 0.601409912109375 +63806 0.5897216796875 +63807 0.569091796875 +63808 0.4906005859375 +63809 0.4630126953125 +63810 0.33148193359375 +63811 0.300445556640625 +63812 0.147796630859375 +63813 0.11566162109375 +63814 -0.01873779296875 +63815 -0.05120849609375 +63816 -0.140289306640625 +63817 -0.173248291015625 +63818 -0.191986083984375 +63819 -0.2265625 +63820 -0.184295654296875 +63821 -0.220916748046875 +63822 -0.161834716796875 +63823 -0.198699951171875 +63824 -0.166595458984375 +63825 -0.19989013671875 +63826 -0.19390869140625 +63827 -0.220306396484375 +63828 -0.22442626953125 +63829 -0.241943359375 +63830 -0.279754638671875 +63831 -0.2857666015625 +63832 -0.3389892578125 +63833 -0.332489013671875 +63834 -0.3543701171875 +63835 -0.337249755859375 +63836 -0.348175048828125 +63837 -0.32177734375 +63838 -0.32598876953125 +63839 -0.2918701171875 +63840 -0.2581787109375 +63841 -0.2198486328125 +63842 -0.139801025390625 +63843 -0.101409912109375 +63844 0.014617919921875 +63845 0.049407958984375 +63846 0.144378662109375 +63847 0.174713134765625 +63848 0.221038818359375 +63849 0.247467041015625 +63850 0.27069091796875 +63851 0.292510986328125 +63852 0.294036865234375 +63853 0.31072998046875 +63854 0.311767578125 +63855 0.322021484375 +63856 0.339141845703125 +63857 0.34130859375 +63858 0.360260009765625 +63859 0.35406494140625 +63860 0.360504150390625 +63861 0.3468017578125 +63862 0.308380126953125 +63863 0.289337158203125 +63864 0.18170166015625 +63865 0.160491943359375 +63866 0.0047607421875 +63867 -0.015869140625 +63868 -0.17559814453125 +63869 -0.194244384765625 +63870 -0.3143310546875 +63871 -0.33087158203125 +63872 -0.36785888671875 +63873 -0.383544921875 +63874 -0.36248779296875 +63875 -0.377685546875 +63876 -0.343536376953125 +63877 -0.35723876953125 +63878 -0.3018798828125 +63879 -0.313568115234375 +63880 -0.231414794921875 +63881 -0.240966796875 +63882 -0.117645263671875 +63883 -0.12567138671875 +63884 0.007049560546875 +63885 0.00067138671875 +63886 0.087982177734375 +63887 0.084808349609375 +63888 0.13946533203125 +63889 0.14031982421875 +63890 0.17425537109375 +63891 0.179229736328125 +63892 0.188201904296875 +63893 0.197235107421875 +63894 0.171234130859375 +63895 0.184326171875 +63896 0.118438720703125 +63897 0.135650634765625 +63898 0.05706787109375 +63899 0.07745361328125 +63900 -0.010711669921875 +63901 0.011749267578125 +63902 -0.0914306640625 +63903 -0.067718505859375 +63904 -0.162322998046875 +63905 -0.13873291015625 +63906 -0.194549560546875 +63907 -0.173248291015625 +63908 -0.1492919921875 +63909 -0.133514404296875 +63910 -0.02166748046875 +63911 -0.0145263671875 +63912 0.124053955078125 +63913 0.12176513671875 +63914 0.211151123046875 +63915 0.201385498046875 +63916 0.240447998046875 +63917 0.225372314453125 +63918 0.242218017578125 +63919 0.22320556640625 +63920 0.2257080078125 +63921 0.2041015625 +63922 0.194366455078125 +63923 0.1715087890625 +63924 0.115509033203125 +63925 0.0938720703125 +63926 0.0128173828125 +63927 -0.00579833984375 +63928 -0.053802490234375 +63929 -0.069580078125 +63930 -0.110626220703125 +63931 -0.1229248046875 +63932 -0.199493408203125 +63933 -0.20648193359375 +63934 -0.29437255859375 +63935 -0.29522705078125 +63936 -0.33221435546875 +63937 -0.328277587890625 +63938 -0.27972412109375 +63939 -0.27362060546875 +63940 -0.185333251953125 +63941 -0.1783447265625 +63942 -0.128204345703125 +63943 -0.119293212890625 +63944 -0.115692138671875 +63945 -0.103759765625 +63946 -0.116455078125 +63947 -0.10162353515625 +63948 -0.105926513671875 +63949 -0.0892333984375 +63950 -0.053955078125 +63951 -0.03753662109375 +63952 0.048797607421875 +63953 0.06243896484375 +63954 0.157318115234375 +63955 0.16717529296875 +63956 0.212005615234375 +63957 0.218994140625 +63958 0.218475341796875 +63959 0.223388671875 +63960 0.23724365234375 +63961 0.239105224609375 +63962 0.30535888671875 +63963 0.302154541015625 +63964 0.38128662109375 +63965 0.372467041015625 +63966 0.404449462890625 +63967 0.3916015625 +63968 0.3944091796875 +63969 0.378662109375 +63970 0.3885498046875 +63971 0.370025634765625 +63972 0.362640380859375 +63973 0.3424072265625 +63974 0.27362060546875 +63975 0.2542724609375 +63976 0.11712646484375 +63977 0.101470947265625 +63978 -0.054901123046875 +63979 -0.065673828125 +63980 -0.19085693359375 +63981 -0.197174072265625 +63982 -0.28570556640625 +63983 -0.2882080078125 +63984 -0.339263916015625 +63985 -0.33868408203125 +63986 -0.3775634765625 +63987 -0.37384033203125 +63988 -0.445709228515625 +63989 -0.437469482421875 +63990 -0.535064697265625 +63991 -0.521392822265625 +63992 -0.629058837890625 +63993 -0.609710693359375 +63994 -0.697601318359375 +63995 -0.673431396484375 +63996 -0.70391845703125 +63997 -0.6771240234375 +63998 -0.6424560546875 +63999 -0.615509033203125 +64000 -0.491241455078125 +64001 -0.466949462890625 +64002 -0.265716552734375 +64003 -0.246307373046875 +64004 -0.023712158203125 +64005 -0.010406494140625 +64006 0.201751708984375 +64007 0.208251953125 +64008 0.375823974609375 +64009 0.37530517578125 +64010 0.485076904296875 +64011 0.477813720703125 +64012 0.56884765625 +64013 0.555511474609375 +64014 0.634765625 +64015 0.61639404296875 +64016 0.63763427734375 +64017 0.615509033203125 +64018 0.5660400390625 +64019 0.54156494140625 +64020 0.4720458984375 +64021 0.44671630859375 +64022 0.40692138671875 +64023 0.382232666015625 +64024 0.3778076171875 +64025 0.35516357421875 +64026 0.376953125 +64027 0.357574462890625 +64028 0.371978759765625 +64029 0.35687255859375 +64030 0.313140869140625 +64031 0.30303955078125 +64032 0.184417724609375 +64033 0.17974853515625 +64034 0.011199951171875 +64035 0.012054443359375 +64036 -0.171051025390625 +64037 -0.164886474609375 +64038 -0.33740234375 +64039 -0.326416015625 +64040 -0.47198486328125 +64041 -0.456939697265625 +64042 -0.560394287109375 +64043 -0.542236328125 +64044 -0.58056640625 +64045 -0.560394287109375 +64046 -0.54754638671875 +64047 -0.526519775390625 +64048 -0.508575439453125 +64049 -0.48785400390625 +64050 -0.459503173828125 +64051 -0.440216064453125 +64052 -0.394378662109375 +64053 -0.377532958984375 +64054 -0.35260009765625 +64055 -0.33905029296875 +64056 -0.31170654296875 +64057 -0.302093505859375 +64058 -0.197418212890625 +64059 -0.192169189453125 +64060 -0.007965087890625 +64061 -0.007232666015625 +64062 0.207489013671875 +64063 0.203765869140625 +64064 0.409210205078125 +64065 0.4013671875 +64066 0.57208251953125 +64067 0.560638427734375 +64068 0.66595458984375 +64069 0.651641845703125 +64070 0.65875244140625 +64071 0.642425537109375 +64072 0.56744384765625 +64073 0.550048828125 +64074 0.431396484375 +64075 0.413909912109375 +64076 0.29443359375 +64077 0.27783203125 +64078 0.182464599609375 +64079 0.167633056640625 +64080 0.06365966796875 +64081 0.051361083984375 +64082 -0.075958251953125 +64083 -0.08514404296875 +64084 -0.189422607421875 +64085 -0.195068359375 +64086 -0.271942138671875 +64087 -0.273834228515625 +64088 -0.342529296875 +64089 -0.340667724609375 +64090 -0.364166259765625 +64091 -0.3587646484375 +64092 -0.327239990234375 +64093 -0.3187255859375 +64094 -0.2769775390625 +64095 -0.265899658203125 +64096 -0.253692626953125 +64097 -0.240753173828125 +64098 -0.24365234375 +64099 -0.2296142578125 +64100 -0.1983642578125 +64101 -0.184051513671875 +64102 -0.116241455078125 +64103 -0.102447509765625 +64104 -0.036834716796875 +64105 -0.0242919921875 +64106 0.034881591796875 +64107 0.0455322265625 +64108 0.09124755859375 +64109 0.099456787109375 +64110 0.10888671875 +64111 0.114288330078125 +64112 0.125518798828125 +64113 0.127899169921875 +64114 0.15771484375 +64115 0.15704345703125 +64116 0.17828369140625 +64117 0.1746826171875 +64118 0.17108154296875 +64119 0.164825439453125 +64120 0.129974365234375 +64121 0.121490478515625 +64122 0.082427978515625 +64123 0.07220458984375 +64124 0.027679443359375 +64125 0.016326904296875 +64126 -0.065643310546875 +64127 -0.07745361328125 +64128 -0.15936279296875 +64129 -0.17095947265625 +64130 -0.21307373046875 +64131 -0.22381591796875 +64132 -0.234649658203125 +64133 -0.24395751953125 +64134 -0.2001953125 +64135 -0.20758056640625 +64136 -0.119171142578125 +64137 -0.124298095703125 +64138 -0.024749755859375 +64139 -0.02740478515625 +64140 0.085784912109375 +64141 0.085662841796875 +64142 0.178131103515625 +64143 0.18048095703125 +64144 0.215576171875 +64145 0.220184326171875 +64146 0.211456298828125 +64147 0.217987060546875 +64148 0.17523193359375 +64149 0.183258056640625 +64150 0.128753662109375 +64151 0.137786865234375 +64152 0.1019287109375 +64153 0.1114501953125 +64154 0.0743408203125 +64155 0.083831787109375 +64156 0.04327392578125 +64157 0.05224609375 +64158 0.038177490234375 +64159 0.046173095703125 +64160 0.076263427734375 +64161 0.0828857421875 +64162 0.14105224609375 +64163 0.145965576171875 +64164 0.186431884765625 +64165 0.189422607421875 +64166 0.188812255859375 +64167 0.18975830078125 +64168 0.1390380859375 +64169 0.137939453125 +64170 0.041778564453125 +64171 0.03875732421875 +64172 -0.079437255859375 +64173 -0.08416748046875 +64174 -0.219390869140625 +64175 -0.22552490234375 +64176 -0.367828369140625 +64177 -0.375 +64178 -0.494873046875 +64179 -0.502685546875 +64180 -0.556243896484375 +64181 -0.56427001953125 +64182 -0.508697509765625 +64183 -0.516510009765625 +64184 -0.3756103515625 +64185 -0.382781982421875 +64186 -0.218902587890625 +64187 -0.225067138671875 +64188 -0.063751220703125 +64189 -0.068603515625 +64190 0.091552734375 +64191 0.088226318359375 +64192 0.23602294921875 +64193 0.234375 +64194 0.342987060546875 +64195 0.343048095703125 +64196 0.39520263671875 +64197 0.39691162109375 +64198 0.389373779296875 +64199 0.392578125 +64200 0.324249267578125 +64201 0.3287353515625 +64202 0.224090576171875 +64203 0.229583740234375 +64204 0.124267578125 +64205 0.13043212890625 +64206 0.037078857421875 +64207 0.043548583984375 +64208 -0.010101318359375 +64209 -0.003692626953125 +64210 -0.019439697265625 +64211 -0.013458251953125 +64212 -0.022796630859375 +64213 -0.017547607421875 +64214 -0.001556396484375 +64215 0.002655029296875 +64216 0.056304931640625 +64217 0.05926513671875 +64218 0.106719970703125 +64219 0.1082763671875 +64220 0.096893310546875 +64221 0.09698486328125 +64222 0.042694091796875 +64223 0.041351318359375 +64224 -0.018035888671875 +64225 -0.02069091796875 +64226 -0.07586669921875 +64227 -0.07965087890625 +64228 -0.11944580078125 +64229 -0.124114990234375 +64230 -0.15972900390625 +64231 -0.165008544921875 +64232 -0.202606201171875 +64233 -0.20819091796875 +64234 -0.24859619140625 +64235 -0.254180908203125 +64236 -0.30517578125 +64237 -0.310455322265625 +64238 -0.36212158203125 +64239 -0.3668212890625 +64240 -0.39141845703125 +64241 -0.395294189453125 +64242 -0.35528564453125 +64243 -0.358154296875 +64244 -0.249969482421875 +64245 -0.251708984375 +64246 -0.092864990234375 +64247 -0.093414306640625 +64248 0.08905029296875 +64249 0.089691162109375 +64250 0.2352294921875 +64251 0.23699951171875 +64252 0.318817138671875 +64253 0.32159423828125 +64254 0.358642578125 +64255 0.36224365234375 +64256 0.348358154296875 +64257 0.351959228515625 +64258 0.288116455078125 +64259 0.29022216796875 +64260 0.227569580078125 +64261 0.22784423828125 +64262 0.201690673828125 +64263 0.20123291015625 +64264 0.184661865234375 +64265 0.183929443359375 +64266 0.1600341796875 +64267 0.159027099609375 +64268 0.15423583984375 +64269 0.1539306640625 +64270 0.157745361328125 +64271 0.158782958984375 +64272 0.1309814453125 +64273 0.13262939453125 +64274 0.098358154296875 +64275 0.10064697265625 +64276 0.082366943359375 +64277 0.08599853515625 +64278 0.0484619140625 +64279 0.0528564453125 +64280 -0.015777587890625 +64281 -0.011749267578125 +64282 -0.1097412109375 +64283 -0.1072998046875 +64284 -0.232635498046875 +64285 -0.233062744140625 +64286 -0.355682373046875 +64287 -0.359344482421875 +64288 -0.439605712890625 +64289 -0.4456787109375 +64290 -0.470184326171875 +64291 -0.47735595703125 +64292 -0.46051025390625 +64293 -0.4678955078125 +64294 -0.414764404296875 +64295 -0.421600341796875 +64296 -0.33074951171875 +64297 -0.33612060546875 +64298 -0.2254638671875 +64299 -0.22894287109375 +64300 -0.121856689453125 +64301 -0.1236572265625 +64302 -0.02655029296875 +64303 -0.027008056640625 +64304 0.077880859375 +64305 0.0791015625 +64306 0.21142578125 +64307 0.21539306640625 +64308 0.383331298828125 +64309 0.391571044921875 +64310 0.57257080078125 +64311 0.5859375 +64312 0.719970703125 +64313 0.7374267578125 +64314 0.784423828125 +64315 0.8035888671875 +64316 0.763214111328125 +64317 0.781646728515625 +64318 0.653045654296875 +64319 0.668182373046875 +64320 0.453033447265625 +64321 0.46221923828125 +64322 0.19940185546875 +64323 0.201171875 +64324 -0.0443115234375 +64325 -0.04937744140625 +64326 -0.222808837890625 +64327 -0.232391357421875 +64328 -0.319000244140625 +64329 -0.330322265625 +64330 -0.358123779296875 +64331 -0.36932373046875 +64332 -0.3702392578125 +64333 -0.380523681640625 +64334 -0.370025634765625 +64335 -0.379150390625 +64336 -0.3740234375 +64337 -0.382293701171875 +64338 -0.38641357421875 +64339 -0.394378662109375 +64340 -0.3809814453125 +64341 -0.388336181640625 +64342 -0.33905029296875 +64343 -0.344879150390625 +64344 -0.281585693359375 +64345 -0.28564453125 +64346 -0.25054931640625 +64347 -0.2540283203125 +64348 -0.263458251953125 +64349 -0.268096923828125 +64350 -0.26898193359375 +64351 -0.274749755859375 +64352 -0.212615966796875 +64353 -0.21759033203125 +64354 -0.125152587890625 +64355 -0.12841796875 +64356 -0.065216064453125 +64357 -0.06768798828125 +64358 -0.039306640625 +64359 -0.04205322265625 +64360 -0.019775390625 +64361 -0.02288818359375 +64362 0.02520751953125 +64363 0.022705078125 +64364 0.1265869140625 +64365 0.12677001953125 +64366 0.25628662109375 +64367 0.260345458984375 +64368 0.37384033203125 +64369 0.381622314453125 +64370 0.471221923828125 +64371 0.482330322265625 +64372 0.51739501953125 +64373 0.5303955078125 +64374 0.500030517578125 +64375 0.513031005859375 +64376 0.44573974609375 +64377 0.45770263671875 +64378 0.39727783203125 +64379 0.40850830078125 +64380 0.3729248046875 +64381 0.384307861328125 +64382 0.345458984375 +64383 0.356903076171875 +64384 0.300445556640625 +64385 0.311370849609375 +64386 0.240142822265625 +64387 0.249969482421875 +64388 0.15625 +64389 0.164093017578125 +64390 0.02935791015625 +64391 0.03363037109375 +64392 -0.14288330078125 +64393 -0.143890380859375 +64394 -0.33056640625 +64395 -0.33758544921875 +64396 -0.5230712890625 +64397 -0.5364990234375 +64398 -0.704010009765625 +64399 -0.723724365234375 +64400 -0.81451416015625 +64401 -0.83831787109375 +64402 -0.80975341796875 +64403 -0.834014892578125 +64404 -0.708984375 +64405 -0.73065185546875 +64406 -0.565460205078125 +64407 -0.58319091796875 +64408 -0.42633056640625 +64409 -0.4403076171875 +64410 -0.31304931640625 +64411 -0.3240966796875 +64412 -0.19305419921875 +64413 -0.20086669921875 +64414 -0.040252685546875 +64415 -0.043670654296875 +64416 0.10443115234375 +64417 0.105255126953125 +64418 0.200286865234375 +64419 0.20391845703125 +64420 0.2607421875 +64421 0.26617431640625 +64422 0.332855224609375 +64423 0.34063720703125 +64424 0.434234619140625 +64425 0.44549560546875 +64426 0.531829833984375 +64427 0.546600341796875 +64428 0.601104736328125 +64429 0.61859130859375 +64430 0.63433837890625 +64431 0.6534423828125 +64432 0.64398193359375 +64433 0.664031982421875 +64434 0.635955810546875 +64435 0.656402587890625 +64436 0.587158203125 +64437 0.606689453125 +64438 0.48394775390625 +64439 0.500732421875 +64440 0.339385986328125 +64441 0.35198974609375 +64442 0.16802978515625 +64443 0.17547607421875 +64444 -0.037139892578125 +64445 -0.036102294921875 +64446 -0.253753662109375 +64447 -0.259613037109375 +64448 -0.4322509765625 +64449 -0.443878173828125 +64450 -0.560791015625 +64451 -0.576690673828125 +64452 -0.634765625 +64453 -0.653289794921875 +64454 -0.624237060546875 +64455 -0.6427001953125 +64456 -0.54669189453125 +64457 -0.563018798828125 +64458 -0.445159912109375 +64459 -0.458648681640625 +64460 -0.34027099609375 +64461 -0.35089111328125 +64462 -0.25225830078125 +64463 -0.26055908203125 +64464 -0.1851806640625 +64465 -0.191864013671875 +64466 -0.135833740234375 +64467 -0.141448974609375 +64468 -0.0966796875 +64469 -0.101470947265625 +64470 -0.058135986328125 +64471 -0.06201171875 +64472 -0.0084228515625 +64473 -0.010894775390625 +64474 0.06414794921875 +64475 0.06396484375 +64476 0.147308349609375 +64477 0.149871826171875 +64478 0.2371826171875 +64479 0.24285888671875 +64480 0.340789794921875 +64481 0.35015869140625 +64482 0.445037841796875 +64483 0.458221435546875 +64484 0.52825927734375 +64485 0.54461669921875 +64486 0.5556640625 +64487 0.573394775390625 +64488 0.49078369140625 +64489 0.506866455078125 +64490 0.339691162109375 +64491 0.35125732421875 +64492 0.140869140625 +64493 0.146331787109375 +64494 -0.05499267578125 +64495 -0.05560302734375 +64496 -0.211334228515625 +64497 -0.216766357421875 +64498 -0.326568603515625 +64499 -0.3355712890625 +64500 -0.392669677734375 +64501 -0.403717041015625 +64502 -0.4298095703125 +64503 -0.442047119140625 +64504 -0.482513427734375 +64505 -0.49652099609375 +64506 -0.54461669921875 +64507 -0.560821533203125 +64508 -0.583526611328125 +64509 -0.60125732421875 +64510 -0.56707763671875 +64511 -0.584625244140625 +64512 -0.46527099609375 +64513 -0.47955322265625 +64514 -0.272430419921875 +64515 -0.279449462890625 +64516 -0.012481689453125 +64517 -0.00885009765625 +64518 0.254608154296875 +64519 0.26898193359375 +64520 0.461822509765625 +64521 0.483123779296875 +64522 0.581085205078125 +64523 0.6041259765625 +64524 0.62969970703125 +64525 0.65093994140625 +64526 0.645782470703125 +64527 0.664581298828125 +64528 0.62640380859375 +64529 0.64208984375 +64530 0.5618896484375 +64531 0.573150634765625 +64532 0.490631103515625 +64533 0.49871826171875 +64534 0.4326171875 +64535 0.439971923828125 +64536 0.36846923828125 +64537 0.375946044921875 +64538 0.268707275390625 +64539 0.274810791015625 +64540 0.1077880859375 +64541 0.10894775390625 +64542 -0.09307861328125 +64543 -0.099365234375 +64544 -0.30377197265625 +64545 -0.318359375 +64546 -0.525115966796875 +64547 -0.549224853515625 +64548 -0.74017333984375 +64549 -0.77423095703125 +64550 -0.859375 +64551 -0.8638916015625 +64552 -0.8671875 +64553 -0.870391845703125 +64554 -0.867279052734375 +64555 -0.868896484375 +64556 -0.8609619140625 +64557 -0.860931396484375 +64558 -0.780975341796875 +64559 -0.764373779296875 +64560 -0.563140869140625 +64561 -0.528350830078125 +64562 -0.2669677734375 +64563 -0.21270751953125 +64564 0.0670166015625 +64565 0.139404296875 +64566 0.39056396484375 +64567 0.476806640625 +64568 0.670135498046875 +64569 0.764190673828125 +64570 0.857269287109375 +64571 0.86761474609375 +64572 0.870361328125 +64573 0.870361328125 +64574 0.870361328125 +64575 0.8646240234375 +64576 0.862762451171875 +64577 0.828948974609375 +64578 0.81683349609375 +64579 0.673553466796875 +64580 0.66668701171875 +64581 0.490966796875 +64582 0.49884033203125 +64583 0.30218505859375 +64584 0.316192626953125 +64585 0.11041259765625 +64586 0.08917236328125 +64587 -0.116455078125 +64588 -0.189239501953125 +64589 -0.38714599609375 +64590 -0.480194091796875 +64591 -0.66192626953125 +64592 -0.729400634765625 +64593 -0.85784912109375 +64594 -0.859344482421875 +64595 -0.870391845703125 +64596 -0.868682861328125 +64597 -0.870391845703125 +64598 -0.870391845703125 +64599 -0.86444091796875 +64600 -0.870025634765625 +64601 -0.85723876953125 +64602 -0.8660888671875 +64603 -0.790008544921875 +64604 -0.84332275390625 +64605 -0.62847900390625 +64606 -0.644500732421875 +64607 -0.3956298828125 +64608 -0.39642333984375 +64609 -0.126708984375 +64610 -0.12567138671875 +64611 0.150115966796875 +64612 0.15655517578125 +64613 0.424041748046875 +64614 0.425537109375 +64615 0.670623779296875 +64616 0.64617919921875 +64617 0.854522705078125 +64618 0.8037109375 +64619 0.866485595703125 +64620 0.85791015625 +64621 0.86920166015625 +64622 0.860809326171875 +64623 0.8653564453125 +64624 0.85931396484375 +64625 0.857147216796875 +64626 0.84466552734375 +64627 0.766845703125 +64628 0.7576904296875 +64629 0.628509521484375 +64630 0.634002685546875 +64631 0.462127685546875 +64632 0.499786376953125 +64633 0.297210693359375 +64634 0.3681640625 +64635 0.14862060546875 +64636 0.218780517578125 +64637 -0.00537109375 +64638 0.05902099609375 +64639 -0.15753173828125 +64640 -0.114654541015625 +64641 -0.31304931640625 +64642 -0.316162109375 +64643 -0.48876953125 +64644 -0.50286865234375 +64645 -0.6416015625 +64646 -0.6533203125 +64647 -0.751373291015625 +64648 -0.7911376953125 +64649 -0.84619140625 +64650 -0.8599853515625 +64651 -0.861297607421875 +64652 -0.866607666015625 +64653 -0.863250732421875 +64654 -0.864501953125 +64655 -0.856597900390625 +64656 -0.855072021484375 +64657 -0.7498779296875 +64658 -0.76239013671875 +64659 -0.624542236328125 +64660 -0.6351318359375 +64661 -0.47808837890625 +64662 -0.424102783203125 +64663 -0.253387451171875 +64664 -0.17254638671875 +64665 0.003692626953125 +64666 0.05548095703125 +64667 0.2257080078125 +64668 0.27215576171875 +64669 0.427154541015625 +64670 0.5086669921875 +64671 0.643218994140625 +64672 0.757232666015625 +64673 0.855926513671875 +64674 0.866546630859375 +64675 0.870361328125 +64676 0.870361328125 +64677 0.870361328125 +64678 0.8665771484375 +64679 0.862762451171875 +64680 0.855560302734375 +64681 0.79669189453125 +64682 0.693359375 +64683 0.595794677734375 +64684 0.483917236328125 +64685 0.362152099609375 +64686 0.264984130859375 +64687 0.1270751953125 +64688 0.0577392578125 +64689 -0.086944580078125 +64690 -0.13580322265625 +64691 -0.2784423828125 +64692 -0.34967041015625 +64693 -0.484832763671875 +64694 -0.60455322265625 +64695 -0.729583740234375 +64696 -0.854766845703125 +64697 -0.86688232421875 +64698 -0.870391845703125 +64699 -0.870391845703125 +64700 -0.870391845703125 +64701 -0.86859130859375 +64702 -0.86614990234375 +64703 -0.86279296875 +64704 -0.855255126953125 +64705 -0.817962646484375 +64706 -0.668487548828125 +64707 -0.6116943359375 +64708 -0.38372802734375 +64709 -0.3128662109375 +64710 -0.044097900390625 +64711 0.039398193359375 +64712 0.328857421875 +64713 0.422821044921875 +64714 0.704010009765625 +64715 0.805145263671875 +64716 0.870361328125 +64717 0.870361328125 +64718 0.870361328125 +64719 0.870361328125 +64720 0.86029052734375 +64721 0.860015869140625 +64722 0.73516845703125 +64723 0.727935791015625 +64724 0.494720458984375 +64725 0.48114013671875 +64726 0.22552490234375 +64727 0.2059326171875 +64728 -0.037384033203125 +64729 -0.06103515625 +64730 -0.27398681640625 +64731 -0.29913330078125 +64732 -0.490875244140625 +64733 -0.516204833984375 +64734 -0.69940185546875 +64735 -0.7252197265625 +64736 -0.85699462890625 +64737 -0.85980224609375 +64738 -0.870025634765625 +64739 -0.870391845703125 +64740 -0.870391845703125 +64741 -0.870391845703125 +64742 -0.85882568359375 +64743 -0.858062744140625 +64744 -0.6898193359375 +64745 -0.673004150390625 +64746 -0.45257568359375 +64747 -0.42694091796875 +64748 -0.240020751953125 +64749 -0.2100830078125 +64750 -0.065643310546875 +64751 -0.0362548828125 +64752 0.083770751953125 +64753 0.10943603515625 +64754 0.21514892578125 +64755 0.23516845703125 +64756 0.358367919921875 +64757 0.373687744140625 +64758 0.505950927734375 +64759 0.517791748046875 +64760 0.5966796875 +64761 0.602783203125 +64762 0.6365966796875 +64763 0.635711669921875 +64764 0.661376953125 +64765 0.655181884765625 +64766 0.669158935546875 +64767 0.65948486328125 +64768 0.6619873046875 +64769 0.651275634765625 +64770 0.628631591796875 +64771 0.61846923828125 +64772 0.547821044921875 +64773 0.53753662109375 +64774 0.416229248046875 +64775 0.404144287109375 +64776 0.237823486328125 +64777 0.22186279296875 +64778 0.025482177734375 +64779 0.003997802734375 +64780 -0.19415283203125 +64781 -0.22100830078125 +64782 -0.394256591796875 +64783 -0.42449951171875 +64784 -0.5498046875 +64785 -0.579833984375 +64786 -0.61920166015625 +64787 -0.641876220703125 +64788 -0.608245849609375 +64789 -0.6177978515625 +64790 -0.57781982421875 +64791 -0.575531005859375 +64792 -0.53778076171875 +64793 -0.526336669921875 +64794 -0.44842529296875 +64795 -0.42645263671875 +64796 -0.29376220703125 +64797 -0.2581787109375 +64798 -0.116668701171875 +64799 -0.068695068359375 +64800 0.03741455078125 +64801 0.09222412109375 +64802 0.174774169921875 +64803 0.232147216796875 +64804 0.294677734375 +64805 0.3509521484375 +64806 0.361480712890625 +64807 0.410064697265625 +64808 0.3414306640625 +64809 0.372955322265625 +64810 0.248138427734375 +64811 0.2554931640625 +64812 0.1256103515625 +64813 0.10711669921875 +64814 -0.009307861328125 +64815 -0.052886962890625 +64816 -0.122528076171875 +64817 -0.186279296875 +64818 -0.1600341796875 +64819 -0.23291015625 +64820 -0.137054443359375 +64821 -0.209442138671875 +64822 -0.1063232421875 +64823 -0.174163818359375 +64824 -0.067352294921875 +64825 -0.126739501953125 +64826 -0.002655029296875 +64827 -0.048126220703125 +64828 0.070953369140625 +64829 0.0426025390625 +64830 0.119659423828125 +64831 0.10748291015625 +64832 0.139068603515625 +64833 0.1409912109375 +64834 0.178558349609375 +64835 0.19708251953125 +64836 0.23687744140625 +64837 0.273651123046875 +64838 0.266693115234375 +64839 0.31768798828125 +64840 0.279266357421875 +64841 0.341094970703125 +64842 0.296844482421875 +64843 0.368011474609375 +64844 0.2962646484375 +64845 0.37249755859375 +64846 0.229095458984375 +64847 0.30072021484375 +64848 0.094482421875 +64849 0.1517333984375 +64850 -0.0535888671875 +64851 -0.01470947265625 +64852 -0.206024169921875 +64853 -0.1883544921875 +64854 -0.366302490234375 +64855 -0.372711181640625 +64856 -0.486236572265625 +64857 -0.51397705078125 +64858 -0.529754638671875 +64859 -0.57177734375 +64860 -0.49139404296875 +64861 -0.53948974609375 +64862 -0.387969970703125 +64863 -0.43511962890625 +64864 -0.25390625 +64865 -0.2962646484375 +64866 -0.124176025390625 +64867 -0.161102294921875 +64868 -0.011749267578125 +64869 -0.0435791015625 +64870 0.086700439453125 +64871 0.060394287109375 +64872 0.158203125 +64873 0.13665771484375 +64874 0.1890869140625 +64875 0.170135498046875 +64876 0.18365478515625 +64877 0.16552734375 +64878 0.173095703125 +64879 0.15728759765625 +64880 0.16253662109375 +64881 0.150787353515625 +64882 0.13055419921875 +64883 0.12200927734375 +64884 0.085784912109375 +64885 0.080108642578125 +64886 0.052276611328125 +64887 0.05126953125 +64888 0.055267333984375 +64889 0.062896728515625 +64890 0.07501220703125 +64891 0.09271240234375 +64892 0.068756103515625 +64893 0.092987060546875 +64894 0.050201416015625 +64895 0.07855224609375 +64896 0.0330810546875 +64897 0.06427001953125 +64898 0.003692626953125 +64899 0.0347900390625 +64900 -0.039520263671875 +64901 -0.01171875 +64902 -0.07916259765625 +64903 -0.056060791015625 +64904 -0.076690673828125 +64905 -0.055511474609375 +64906 -0.0325927734375 +64907 -0.010467529296875 +64908 0.00408935546875 +64909 0.02508544921875 +64910 0.01007080078125 +64911 0.025665283203125 +64912 0.008575439453125 +64913 0.017333984375 +64914 0.0008544921875 +64915 0.00189208984375 +64916 -0.0234375 +64917 -0.03173828125 +64918 -0.05377197265625 +64919 -0.071502685546875 +64920 -0.106719970703125 +64921 -0.13543701171875 +64922 -0.17926025390625 +64923 -0.219970703125 +64924 -0.249359130859375 +64925 -0.300506591796875 +64926 -0.316497802734375 +64927 -0.376312255859375 +64928 -0.352386474609375 +64929 -0.416107177734375 +64930 -0.31292724609375 +64931 -0.371124267578125 +64932 -0.198822021484375 +64933 -0.242279052734375 +64934 -0.046234130859375 +64935 -0.069732666015625 +64936 0.12615966796875 +64937 0.125640869140625 +64938 0.290435791015625 +64939 0.31268310546875 +64940 0.414031982421875 +64941 0.45501708984375 +64942 0.4991455078125 +64943 0.554779052734375 +64944 0.54486083984375 +64945 0.61065673828125 +64946 0.54083251953125 +64947 0.610931396484375 +64948 0.465484619140625 +64949 0.531463623046875 +64950 0.333465576171875 +64951 0.3883056640625 +64952 0.1929931640625 +64953 0.23468017578125 +64954 0.066436767578125 +64955 0.095245361328125 +64956 -0.022674560546875 +64957 -0.00396728515625 +64958 -0.061370849609375 +64959 -0.04852294921875 +64960 -0.064849853515625 +64961 -0.055145263671875 +64962 -0.08026123046875 +64963 -0.0758056640625 +64964 -0.13330078125 +64965 -0.138702392578125 +64966 -0.192901611328125 +64967 -0.209197998046875 +64968 -0.260833740234375 +64969 -0.289031982421875 +64970 -0.337921142578125 +64971 -0.37884521484375 +64972 -0.404205322265625 +64973 -0.456329345703125 +64974 -0.455322265625 +64975 -0.51641845703125 +64976 -0.4554443359375 +64977 -0.519287109375 +64978 -0.39862060546875 +64979 -0.458251953125 +64980 -0.331451416015625 +64981 -0.384796142578125 +64982 -0.276397705078125 +64983 -0.323699951171875 +64984 -0.228240966796875 +64985 -0.269287109375 +64986 -0.1630859375 +64987 -0.1951904296875 +64988 -0.07952880859375 +64989 -0.100006103515625 +64990 -0.001678466796875 +64991 -0.01055908203125 +64992 0.09796142578125 +64993 0.1033935546875 +64994 0.22613525390625 +64995 0.24908447265625 +64996 0.334869384765625 +64997 0.373199462890625 +64998 0.40838623046875 +64999 0.45806884765625 +65000 0.453826904296875 +65001 0.511474609375 +65002 0.500274658203125 +65003 0.565399169921875 +65004 0.54022216796875 +65005 0.61138916015625 +65006 0.519744873046875 +65007 0.5897216796875 +65008 0.429962158203125 +65009 0.4906005859375 +65010 0.286712646484375 +65011 0.33148193359375 +65012 0.1219482421875 +65013 0.147796630859375 +65014 -0.026702880859375 +65015 -0.01873779296875 +65016 -0.134185791015625 +65017 -0.140289306640625 +65018 -0.178192138671875 +65019 -0.191986083984375 +65020 -0.1683349609375 +65021 -0.184295654296875 +65022 -0.145111083984375 +65023 -0.161834716796875 +65024 -0.1466064453125 +65025 -0.166595458984375 +65026 -0.16876220703125 +65027 -0.19390869140625 +65028 -0.1942138671875 +65029 -0.22442626953125 +65030 -0.242523193359375 +65031 -0.279754638671875 +65032 -0.294952392578125 +65033 -0.3389892578125 +65034 -0.30853271484375 +65035 -0.3543701171875 +65036 -0.30328369140625 +65037 -0.348175048828125 +65038 -0.2841796875 +65039 -0.32598876953125 +65040 -0.2244873046875 +65041 -0.2581787109375 +65042 -0.11968994140625 +65043 -0.139801025390625 +65044 0.01727294921875 +65045 0.014617919921875 +65046 0.131866455078125 +65047 0.144378662109375 +65048 0.19866943359375 +65049 0.221038818359375 +65050 0.241241455078125 +65051 0.27069091796875 +65052 0.260345458984375 +65053 0.294036865234375 +65054 0.27471923828125 +65055 0.311767578125 +65056 0.298065185546875 +65057 0.339141845703125 +65058 0.315765380859375 +65059 0.360260009765625 +65060 0.3148193359375 +65061 0.360504150390625 +65062 0.2679443359375 +65063 0.308380126953125 +65064 0.155975341796875 +65065 0.18170166015625 +65066 0.000274658203125 +65067 0.0047607421875 +65068 -0.158172607421875 +65069 -0.17559814453125 +65070 -0.279998779296875 +65071 -0.3143310546875 +65072 -0.327178955078125 +65073 -0.36785888671875 +65074 -0.32257080078125 +65075 -0.36248779296875 +65076 -0.30572509765625 +65077 -0.343536376953125 +65078 -0.268707275390625 +65079 -0.3018798828125 +65080 -0.20623779296875 +65081 -0.231414794921875 +65082 -0.105743408203125 +65083 -0.117645263671875 +65084 0.004425048828125 +65085 0.007049560546875 +65086 0.0765380859375 +65087 0.087982177734375 +65088 0.12298583984375 +65089 0.13946533203125 +65090 0.15478515625 +65091 0.17425537109375 +65092 0.168212890625 +65093 0.188201904296875 +65094 0.1544189453125 +65095 0.171234130859375 +65096 0.10906982421875 +65097 0.118438720703125 +65098 0.055908203125 +65099 0.05706787109375 +65100 -0.003204345703125 +65101 -0.010711669921875 +65102 -0.073974609375 +65103 -0.0914306640625 +65104 -0.136474609375 +65105 -0.162322998046875 +65106 -0.16552734375 +65107 -0.194549560546875 +65108 -0.127227783203125 +65109 -0.1492919921875 +65110 -0.0172119140625 +65111 -0.02166748046875 +65112 0.1085205078125 +65113 0.124053955078125 +65114 0.18316650390625 +65115 0.211151123046875 +65116 0.20751953125 +65117 0.240447998046875 +65118 0.2080078125 +65119 0.242218017578125 +65120 0.192779541015625 +65121 0.2257080078125 +65122 0.16485595703125 +65123 0.194366455078125 +65124 0.09576416015625 +65125 0.115509033203125 +65126 0.00616455078125 +65127 0.0128173828125 +65128 -0.05169677734375 +65129 -0.053802490234375 +65130 -0.100738525390625 +65131 -0.110626220703125 +65132 -0.177520751953125 +65133 -0.199493408203125 +65134 -0.259368896484375 +65135 -0.29437255859375 +65136 -0.291351318359375 +65137 -0.33221435546875 +65138 -0.2445068359375 +65139 -0.27972412109375 +65140 -0.161102294921875 +65141 -0.185333251953125 +65142 -0.1102294921875 +65143 -0.128204345703125 +65144 -0.098358154296875 +65145 -0.115692138671875 +65146 -0.09820556640625 +65147 -0.116455078125 +65148 -0.088409423828125 +65149 -0.105926513671875 +65150 -0.042724609375 +65151 -0.053955078125 +65152 0.046966552734375 +65153 0.048797607421875 +65154 0.141448974609375 +65155 0.157318115234375 +65156 0.188751220703125 +65157 0.212005615234375 +65158 0.19378662109375 +65159 0.218475341796875 +65160 0.209381103515625 +65161 0.23724365234375 +65162 0.267913818359375 +65163 0.30535888671875 +65164 0.333160400390625 +65165 0.38128662109375 +65166 0.35235595703125 +65167 0.404449462890625 +65168 0.342620849609375 +65169 0.3944091796875 +65170 0.33660888671875 +65171 0.3885498046875 +65172 0.31329345703125 +65173 0.362640380859375 +65174 0.235137939453125 +65175 0.27362060546875 +65176 0.098358154296875 +65177 0.11712646484375 +65178 -0.051727294921875 +65179 -0.054901123046875 +65180 -0.170135498046875 +65181 -0.19085693359375 +65182 -0.25250244140625 +65183 -0.28570556640625 +65184 -0.2987060546875 +65185 -0.339263916015625 +65186 -0.331451416015625 +65187 -0.3775634765625 +65188 -0.390106201171875 +65189 -0.445709228515625 +65190 -0.46722412109375 +65191 -0.535064697265625 +65192 -0.548370361328125 +65193 -0.629058837890625 +65194 -0.60736083984375 +65195 -0.697601318359375 +65196 -0.612152099609375 +65197 -0.70391845703125 +65198 -0.557952880859375 +65199 -0.6424560546875 +65200 -0.425628662109375 +65201 -0.491241455078125 +65202 -0.2286376953125 +65203 -0.265716552734375 +65204 -0.0174560546875 +65205 -0.023712158203125 +65206 0.179107666015625 +65207 0.201751708984375 +65208 0.3306884765625 +65209 0.375823974609375 +65210 0.42559814453125 +65211 0.485076904296875 +65212 0.498138427734375 +65213 0.56884765625 +65214 0.55499267578125 +65215 0.634765625 +65216 0.55682373046875 +65217 0.63763427734375 +65218 0.49371337890625 +65219 0.5660400390625 +65220 0.41107177734375 +65221 0.4720458984375 +65222 0.3536376953125 +65223 0.40692138671875 +65224 0.327667236328125 +65225 0.3778076171875 +65226 0.326446533203125 +65227 0.376953125 +65228 0.32177734375 +65229 0.371978759765625 +65230 0.27032470703125 +65231 0.313140869140625 +65232 0.158111572265625 +65233 0.184417724609375 +65234 0.00726318359375 +65235 0.011199951171875 +65236 -0.151336669921875 +65237 -0.171051025390625 +65238 -0.29595947265625 +65239 -0.33740234375 +65240 -0.41278076171875 +65241 -0.47198486328125 +65242 -0.489288330078125 +65243 -0.560394287109375 +65244 -0.50628662109375 +65245 -0.58056640625 +65246 -0.476898193359375 +65247 -0.54754638671875 +65248 -0.4423828125 +65249 -0.508575439453125 +65250 -0.399139404296875 +65251 -0.459503173828125 +65252 -0.342010498046875 +65253 -0.394378662109375 +65254 -0.30535888671875 +65255 -0.35260009765625 +65256 -0.26959228515625 +65257 -0.31170654296875 +65258 -0.169952392578125 +65259 -0.197418212890625 +65260 -0.0048828125 +65261 -0.007965087890625 +65262 0.1827392578125 +65263 0.207489013671875 +65264 0.3582763671875 +65265 0.409210205078125 +65266 0.499847412109375 +65267 0.57208251953125 +65268 0.581207275390625 +65269 0.66595458984375 +65270 0.57440185546875 +65271 0.65875244140625 +65272 0.4942626953125 +65273 0.56744384765625 +65274 0.375152587890625 +65275 0.431396484375 +65276 0.255340576171875 +65277 0.29443359375 +65278 0.15740966796875 +65279 0.182464599609375 +65280 0.05413818359375 +65281 0.06365966796875 +65282 -0.066650390625 +65283 -0.075958251953125 +65284 -0.16534423828125 +65285 -0.189422607421875 +65286 -0.237640380859375 +65287 -0.271942138671875 +65288 -0.29931640625 +65289 -0.342529296875 +65290 -0.31915283203125 +65291 -0.364166259765625 +65292 -0.28900146484375 +65293 -0.327239990234375 +65294 -0.246826171875 +65295 -0.2769775390625 +65296 -0.22650146484375 +65297 -0.253692626953125 +65298 -0.216522216796875 +65299 -0.24365234375 +65300 -0.176300048828125 +65301 -0.1983642578125 +65302 -0.104644775390625 +65303 -0.116241455078125 +65304 -0.034912109375 +65305 -0.036834716796875 +65306 0.02850341796875 +65307 0.034881591796875 +65308 0.0789794921875 +65309 0.09124755859375 +65310 0.09674072265625 +65311 0.10888671875 +65312 0.11328125 +65313 0.125518798828125 +65314 0.14239501953125 +65315 0.15771484375 +65316 0.1611328125 +65317 0.17828369140625 +65318 0.155853271484375 +65319 0.17108154296875 +65320 0.121429443359375 +65321 0.129974365234375 +65322 0.0809326171875 +65323 0.082427978515625 +65324 0.033782958984375 +65325 0.027679443359375 +65326 -0.046295166015625 +65327 -0.065643310546875 +65328 -0.12713623046875 +65329 -0.15936279296875 +65330 -0.174652099609375 +65331 -0.21307373046875 +65332 -0.195343017578125 +65333 -0.234649658203125 +65334 -0.168975830078125 +65335 -0.2001953125 +65336 -0.103363037109375 +65337 -0.119171142578125 +65338 -0.0262451171875 +65339 -0.024749755859375 +65340 0.06475830078125 +65341 0.085784912109375 +65342 0.14093017578125 +65343 0.178131103515625 +65344 0.1715087890625 +65345 0.215576171875 +65346 0.167694091796875 +65347 0.211456298828125 +65348 0.137451171875 +65349 0.17523193359375 +65350 0.099090576171875 +65351 0.128753662109375 +65352 0.077728271484375 +65353 0.1019287109375 +65354 0.05615234375 +65355 0.0743408203125 +65356 0.031951904296875 +65357 0.04327392578125 +65358 0.029754638671875 +65359 0.038177490234375 +65360 0.063873291015625 +65361 0.076263427734375 +65362 0.120361328125 +65363 0.14105224609375 +65364 0.160400390625 +65365 0.186431884765625 +65366 0.1640625 +65367 0.188812255859375 +65368 0.123565673828125 +65369 0.1390380859375 +65370 0.04278564453125 +65371 0.041778564453125 +65372 -0.058563232421875 +65373 -0.079437255859375 +65374 -0.176116943359375 +65375 -0.219390869140625 +65376 -0.30120849609375 +65377 -0.367828369140625 +65378 -0.40875244140625 +65379 -0.494873046875 +65380 -0.461456298828125 +65381 -0.556243896484375 +65382 -0.422943115234375 +65383 -0.508697509765625 +65384 -0.312774658203125 +65385 -0.3756103515625 +65386 -0.182891845703125 +65387 -0.218902587890625 +65388 -0.0543212890625 +65389 -0.063751220703125 +65390 0.074432373046875 +65391 0.091552734375 +65392 0.19427490234375 +65393 0.23602294921875 +65394 0.282867431640625 +65395 0.342987060546875 +65396 0.3258056640625 +65397 0.39520263671875 +65398 0.320343017578125 +65399 0.389373779296875 +65400 0.26544189453125 +65401 0.324249267578125 +65402 0.181488037109375 +65403 0.224090576171875 +65404 0.098175048828125 +65405 0.124267578125 +65406 0.025787353515625 +65407 0.037078857421875 +65408 -0.012725830078125 +65409 -0.010101318359375 +65410 -0.019256591796875 +65411 -0.019439697265625 +65412 -0.0206298828125 +65413 -0.022796630859375 +65414 -0.00128173828125 +65415 -0.001556396484375 +65416 0.048797607421875 +65417 0.056304931640625 +65418 0.092498779296875 +65419 0.106719970703125 +65420 0.085418701171875 +65421 0.096893310546875 +65422 0.04083251953125 +65423 0.042694091796875 +65424 -0.009521484375 +65425 -0.018035888671875 +65426 -0.057769775390625 +65427 -0.07586669921875 +65428 -0.0943603515625 +65429 -0.11944580078125 +65430 -0.128509521484375 +65431 -0.15972900390625 +65432 -0.165130615234375 +65433 -0.202606201171875 +65434 -0.204620361328125 +65435 -0.24859619140625 +65436 -0.253173828125 +65437 -0.30517578125 +65438 -0.30218505859375 +65439 -0.36212158203125 +65440 -0.32806396484375 +65441 -0.39141845703125 +65442 -0.298980712890625 +65443 -0.35528564453125 +65444 -0.211700439453125 +65445 -0.249969482421875 +65446 -0.080810546875 +65447 -0.092864990234375 +65448 0.07110595703125 +65449 0.08905029296875 +65450 0.1932373046875 +65451 0.2352294921875 +65452 0.2630615234375 +65453 0.318817138671875 +65454 0.29638671875 +65455 0.358642578125 +65456 0.287384033203125 +65457 0.347747802734375 +65458 0.235626220703125 +65459 0.28564453125 +65460 0.18377685546875 +65461 0.223175048828125 +65462 0.162353515625 +65463 0.196746826171875 +65464 0.149078369140625 +65465 0.179840087890625 +65466 0.129669189453125 +65467 0.155548095703125 +65468 0.1270751953125 +65469 0.151214599609375 +65470 0.132904052734375 +65471 0.156951904296875 +65472 0.1126708984375 +65473 0.13177490234375 +65474 0.087432861328125 +65475 0.100799560546875 +65476 0.076507568359375 +65477 0.087127685546875 +65478 0.049774169921875 +65479 0.05487060546875 +65480 -0.003692626953125 +65481 -0.009002685546875 +65482 -0.08349609375 +65483 -0.10400390625 +65484 -0.189056396484375 +65485 -0.229400634765625 +65486 -0.29541015625 +65487 -0.35552978515625 +65488 -0.368499755859375 +65489 -0.441925048828125 +65490 -0.39599609375 +65491 -0.473846435546875 +65492 -0.38916015625 +65493 -0.464813232421875 +65494 -0.351531982421875 +65495 -0.419097900390625 +65496 -0.281097412109375 +65497 -0.334320068359375 +65498 -0.192474365234375 +65499 -0.227935791015625 +65500 -0.105377197265625 +65501 -0.12347412109375 +65502 -0.025421142578125 +65503 -0.02764892578125 +65504 0.062652587890625 +65505 0.077667236328125 +65506 0.17633056640625 +65507 0.2132568359375 +65508 0.323760986328125 +65509 0.38885498046875 +65510 0.48675537109375 +65511 0.582794189453125 +65512 0.614044189453125 +65513 0.734039306640625 +65514 0.669952392578125 +65515 0.800140380859375 +65516 0.652099609375 +65517 0.7783203125 +65518 0.557586669921875 +65519 0.6651611328125 +65520 0.385528564453125 +65521 0.45965576171875 +65522 0.167327880859375 +65523 0.199188232421875 +65524 -0.0419921875 +65525 -0.050689697265625 +65526 -0.194549560546875 +65527 -0.23297119140625 +65528 -0.27569580078125 +65529 -0.33013916015625 +65530 -0.307464599609375 +65531 -0.368408203125 +65532 -0.3160400390625 +65533 -0.378936767578125 +65534 -0.31427001953125 +65535 -0.376983642578125 +65536 -0.316497802734375 +65537 -0.37969970703125 +65538 -0.326416015625 +65539 -0.391510009765625 +65540 -0.321868896484375 +65541 -0.385345458984375 +65542 -0.28704833984375 +65543 -0.3419189453125 +65544 -0.239288330078125 +65545 -0.28289794921875 +65546 -0.213470458984375 +65547 -0.251617431640625 +65548 -0.22412109375 +65549 -0.266143798828125 +65550 -0.228363037109375 +65551 -0.273345947265625 +65552 -0.1806640625 +65553 -0.216796875 +65554 -0.10675048828125 +65555 -0.128265380859375 +65556 -0.05560302734375 +65557 -0.068145751953125 +65558 -0.032745361328125 +65559 -0.0430908203125 +65560 -0.015167236328125 +65561 -0.024444580078125 +65562 0.023590087890625 +65563 0.020721435546875 +65564 0.10931396484375 +65565 0.124481201171875 +65566 0.218475341796875 +65567 0.25787353515625 +65568 0.3172607421875 +65569 0.379119873046875 +65570 0.398956298828125 +65571 0.47991943359375 +65572 0.437591552734375 +65573 0.5281982421875 +65574 0.4228515625 +65575 0.511138916015625 +65576 0.37701416015625 +65577 0.456207275390625 +65578 0.33575439453125 +65579 0.407470703125 +65580 0.31439208984375 +65581 0.383758544921875 +65582 0.290313720703125 +65583 0.35687255859375 +65584 0.25152587890625 +65585 0.31182861328125 +65586 0.199951171875 +65587 0.250885009765625 +65588 0.128753662109375 +65589 0.1654052734375 +65590 0.02178955078125 +65591 0.035247802734375 +65592 -0.12286376953125 +65593 -0.142059326171875 +65594 -0.2801513671875 +65595 -0.33563232421875 +65596 -0.441192626953125 +65597 -0.5345458984375 +65598 -0.59234619140625 +65599 -0.72186279296875 +65600 -0.684417724609375 +65601 -0.836669921875 +65602 -0.680023193359375 +65603 -0.8326416015625 +65604 -0.595306396484375 +65605 -0.7296142578125 +65606 -0.4747314453125 +65607 -0.582550048828125 +65608 -0.357696533203125 +65609 -0.440093994140625 +65610 -0.26214599609375 +65611 -0.324310302734375 +65612 -0.16094970703125 +65613 -0.20147705078125 +65614 -0.03240966796875 +65615 -0.044647216796875 +65616 0.089263916015625 +65617 0.103973388671875 +65618 0.1700439453125 +65619 0.202392578125 +65620 0.2210693359375 +65621 0.264495849609375 +65622 0.2816162109375 +65623 0.338897705078125 +65624 0.366363525390625 +65625 0.443817138671875 +65626 0.44775390625 +65627 0.545074462890625 +65628 0.50531005859375 +65629 0.6173095703125 +65630 0.532562255859375 +65631 0.6524658203125 +65632 0.53997802734375 +65633 0.66339111328125 +65634 0.53253173828125 +65635 0.6561279296875 +65636 0.490997314453125 +65637 0.606781005859375 +65638 0.40399169921875 +65639 0.501190185546875 +65640 0.282470703125 +65641 0.352783203125 +65642 0.138641357421875 +65643 0.176544189453125 +65644 -0.033294677734375 +65645 -0.034820556640625 +65646 -0.214599609375 +65647 -0.258209228515625 +65648 -0.363922119140625 +65649 -0.44244384765625 +65650 -0.471343994140625 +65651 -0.5753173828125 +65652 -0.53302001953125 +65653 -0.65203857421875 +65654 -0.52398681640625 +65655 -0.641632080078125 +65656 -0.4588623046875 +65657 -0.562164306640625 +65658 -0.37359619140625 +65659 -0.458038330078125 +65660 -0.285430908203125 +65661 -0.350555419921875 +65662 -0.211273193359375 +65663 -0.260528564453125 +65664 -0.154571533203125 +65665 -0.192108154296875 +65666 -0.112701416015625 +65667 -0.141937255859375 +65668 -0.07940673828125 +65669 -0.1021728515625 +65670 -0.04669189453125 +65671 -0.062896728515625 +65672 -0.004791259765625 +65673 -0.011932373046875 +65674 0.056060791015625 +65675 0.062835693359375 +65676 0.1256103515625 +65677 0.148712158203125 +65678 0.20062255859375 +65679 0.241729736328125 +65680 0.286956787109375 +65681 0.34912109375 +65682 0.373687744140625 +65683 0.457305908203125 +65684 0.4427490234375 +65685 0.54388427734375 +65686 0.46514892578125 +65687 0.5728759765625 +65688 0.41046142578125 +65689 0.506591796875 +65690 0.283782958984375 +65691 0.351226806640625 +65692 0.117279052734375 +65693 0.146514892578125 +65694 -0.0467529296875 +65695 -0.05523681640625 +65696 -0.177703857421875 +65697 -0.21624755859375 +65698 -0.27423095703125 +65699 -0.334930419921875 +65700 -0.329620361328125 +65701 -0.402984619140625 +65702 -0.3607177734375 +65703 -0.4412841796875 +65704 -0.404693603515625 +65705 -0.49578857421875 +65706 -0.4564208984375 +65707 -0.5601806640625 +65708 -0.488677978515625 +65709 -0.600738525390625 +65710 -0.474639892578125 +65711 -0.584228515625 +65712 -0.3890380859375 +65713 -0.47930908203125 +65714 -0.2265625 +65715 -0.27935791015625 +65716 -0.007110595703125 +65717 -0.0089111328125 +65718 0.218170166015625 +65719 0.268798828125 +65720 0.39190673828125 +65721 0.482818603515625 +65722 0.49029541015625 +65723 0.60369873046875 +65724 0.528564453125 +65725 0.650421142578125 +65726 0.539886474609375 +65727 0.66400146484375 +65728 0.5218505859375 +65729 0.6414794921875 +65730 0.466094970703125 +65731 0.572540283203125 +65732 0.405731201171875 +65733 0.498138427734375 +65734 0.357879638671875 +65735 0.439453125 +65736 0.3056640625 +65737 0.375518798828125 +65738 0.223358154296875 +65739 0.274505615234375 +65740 0.088714599609375 +65741 0.1087646484375 +65742 -0.080230712890625 +65743 -0.099395751953125 +65744 -0.257781982421875 +65745 -0.3182373046875 +65746 -0.444854736328125 +65747 -0.5489501953125 +65748 -0.627105712890625 +65749 -0.7738037109375 +65750 -0.76171875 +65751 -0.86383056640625 +65752 -0.82177734375 +65753 -0.870391845703125 +65754 -0.82159423828125 +65755 -0.86895751953125 +65756 -0.771759033203125 +65757 -0.861053466796875 +65758 -0.6583251953125 +65759 -0.765869140625 +65760 -0.47216796875 +65761 -0.5301513671875 +65762 -0.219085693359375 +65763 -0.214691162109375 +65764 0.066070556640625 +65765 0.137359619140625 +65766 0.341827392578125 +65767 0.474822998046875 +65768 0.5794677734375 +65769 0.76239013671875 +65770 0.75714111328125 +65771 0.867462158203125 +65772 0.856719970703125 +65773 0.870361328125 +65774 0.862091064453125 +65775 0.86480712890625 +65776 0.8603515625 +65777 0.831817626953125 +65778 0.84765625 +65779 0.677581787109375 +65780 0.7464599609375 +65781 0.495880126953125 +65782 0.619842529296875 +65783 0.30767822265625 +65784 0.4696044921875 +65785 0.116180419921875 +65786 0.2701416015625 +65787 -0.110748291015625 +65788 0.015869140625 +65789 -0.381805419921875 +65790 -0.25860595703125 +65791 -0.6572265625 +65792 -0.504974365234375 +65793 -0.857421875 +65794 -0.68865966796875 +65795 -0.870391845703125 +65796 -0.803680419921875 +65797 -0.870391845703125 +65798 -0.856292724609375 +65799 -0.86444091796875 +65800 -0.8614501953125 +65801 -0.85723876953125 +65802 -0.8629150390625 +65803 -0.790008544921875 +65804 -0.8560791015625 +65805 -0.62847900390625 +65806 -0.72833251953125 +65807 -0.3956298828125 +65808 -0.53570556640625 +65809 -0.126708984375 +65810 -0.31268310546875 +65811 0.150115966796875 +65812 -0.06878662109375 +65813 0.424041748046875 +65814 0.174591064453125 +65815 0.670623779296875 +65816 0.386962890625 +65817 0.854522705078125 +65818 0.55419921875 +65819 0.866485595703125 +65820 0.664031982421875 +65821 0.86920166015625 +65822 0.73028564453125 +65823 0.8653564453125 +65824 0.763153076171875 +65825 0.857147216796875 +65826 0.76031494140625 +65827 0.766845703125 +65828 0.72576904296875 +65829 0.628509521484375 +65830 0.65435791015625 +65831 0.462127685546875 +65832 0.566314697265625 +65833 0.297210693359375 +65834 0.47149658203125 +65835 0.14862060546875 +65836 0.352447509765625 +65837 -0.00537109375 +65838 0.215362548828125 +65839 -0.15753173828125 +65840 0.057769775390625 +65841 -0.31304931640625 +65842 -0.13079833984375 +65843 -0.48876953125 +65844 -0.313629150390625 +65845 -0.6416015625 +65846 -0.471221923828125 +65847 -0.751373291015625 +65848 -0.621246337890625 +65849 -0.84619140625 +65850 -0.752044677734375 +65851 -0.861297607421875 +65852 -0.837799072265625 +65853 -0.863250732421875 +65854 -0.853973388671875 +65855 -0.856597900390625 +65856 -0.810028076171875 +65857 -0.7498779296875 +65858 -0.750946044921875 +65859 -0.624542236328125 +65860 -0.65985107421875 +65861 -0.47808837890625 +65862 -0.49163818359375 +65863 -0.253387451171875 +65864 -0.282012939453125 +65865 0.003692626953125 +65866 -0.0843505859375 +65867 0.2257080078125 +65868 0.110748291015625 +65869 0.427154541015625 +65870 0.328094482421875 +65871 0.643218994140625 +65872 0.5599365234375 +65873 0.855926513671875 +65874 0.761016845703125 +65875 0.870361328125 +65876 0.858642578125 +65877 0.870361328125 +65878 0.865997314453125 +65879 0.862762451171875 +65880 0.866119384765625 +65881 0.79669189453125 +65882 0.85821533203125 +65883 0.595794677734375 +65884 0.764984130859375 +65885 0.362152099609375 +65886 0.612213134765625 +65887 0.1270751953125 +65888 0.446929931640625 +65889 -0.086944580078125 +65890 0.271026611328125 +65891 -0.2784423828125 +65892 0.057769775390625 +65893 -0.484832763671875 +65894 -0.2073974609375 +65895 -0.729583740234375 +65896 -0.484893798828125 +65897 -0.86688232421875 +65898 -0.725250244140625 +65899 -0.870391845703125 +65900 -0.86212158203125 +65901 -0.86859130859375 +65902 -0.870391845703125 +65903 -0.86279296875 +65904 -0.870391845703125 +65905 -0.817962646484375 +65906 -0.8599853515625 +65907 -0.6116943359375 +65908 -0.712371826171875 +65909 -0.3128662109375 +65910 -0.4517822265625 +65911 0.039398193359375 +65912 -0.140289306640625 +65913 0.422821044921875 +65914 0.195465087890625 +65915 0.805145263671875 +65916 0.502899169921875 +65917 0.870361328125 +65918 0.739044189453125 +65919 0.870361328125 +65920 0.859100341796875 +65921 0.860015869140625 +65922 0.867462158203125 +65923 0.727935791015625 +65924 0.8668212890625 +65925 0.48114013671875 +65926 0.85968017578125 +65927 0.2059326171875 +65928 0.798187255859375 +65929 -0.06103515625 +65930 0.667572021484375 +65931 -0.29913330078125 +65932 0.50262451171875 +65933 -0.516204833984375 +65934 0.294586181640625 +65935 -0.7252197265625 +65936 0.065399169921875 +65937 -0.85980224609375 +65938 -0.156341552734375 +65939 -0.870391845703125 +65940 -0.346527099609375 +65941 -0.870391845703125 +65942 -0.467071533203125 +65943 -0.858062744140625 +65944 -0.51513671875 +65945 -0.673004150390625 +65946 -0.53265380859375 +65947 -0.42694091796875 +65948 -0.555877685546875 +65949 -0.2100830078125 +65950 -0.5855712890625 +65951 -0.0362548828125 +65952 -0.601959228515625 +65953 0.10943603515625 +65954 -0.5926513671875 +65955 0.23516845703125 +65956 -0.52862548828125 +65957 0.373687744140625 +65958 -0.41436767578125 +65959 0.517791748046875 +65960 -0.301544189453125 +65961 0.602783203125 +65962 -0.1884765625 +65963 0.635711669921875 +65964 -0.051177978515625 +65965 0.655181884765625 +65966 0.101348876953125 +65967 0.65948486328125 +65968 0.262237548828125 +65969 0.651275634765625 +65970 0.4124755859375 +65971 0.61846923828125 +65972 0.52398681640625 +65973 0.53753662109375 +65974 0.583953857421875 +65975 0.404144287109375 +65976 0.5865478515625 +65977 0.22186279296875 +65978 0.534820556640625 +65979 0.003997802734375 +65980 0.445159912109375 +65981 -0.22100830078125 +65982 0.336090087890625 +65983 -0.42449951171875 +65984 0.226715087890625 +65985 -0.579833984375 +65986 0.152496337890625 +65987 -0.641876220703125 +65988 0.110382080078125 +65989 -0.6177978515625 +65990 0.051971435546875 +65991 -0.575531005859375 +65992 -0.025604248046875 +65993 -0.526336669921875 +65994 -0.081390380859375 +65995 -0.42645263671875 +65996 -0.0938720703125 +65997 -0.2581787109375 +65998 -0.091552734375 +65999 -0.068695068359375 +66000 -0.1051025390625 +66001 0.09222412109375 +66002 -0.121307373046875 +66003 0.232147216796875 +66004 -0.13385009765625 +66005 0.3509521484375 +66006 -0.16754150390625 +66007 0.410064697265625 +66008 -0.2470703125 +66009 0.372955322265625 +66010 -0.358184814453125 +66011 0.2554931640625 +66012 -0.462371826171875 +66013 0.10711669921875 +66014 -0.546173095703125 +66015 -0.052886962890625 +66016 -0.58294677734375 +66017 -0.186279296875 +66018 -0.5303955078125 +66019 -0.23291015625 +66020 -0.40692138671875 +66021 -0.209442138671875 +66022 -0.26397705078125 +66023 -0.174163818359375 +66024 -0.10791015625 +66025 -0.126739501953125 +66026 0.069427490234375 +66027 -0.048126220703125 +66028 0.246978759765625 +66029 0.0426025390625 +66030 0.389739990234375 +66031 0.10748291015625 +66032 0.488800048828125 +66033 0.1409912109375 +66034 0.58258056640625 +66035 0.19708251953125 +66036 0.667388916015625 +66037 0.273651123046875 +66038 0.701416015625 +66039 0.31768798828125 +66040 0.694671630859375 +66041 0.341094970703125 +66042 0.667938232421875 +66043 0.368011474609375 +66044 0.60430908203125 +66045 0.37249755859375 +66046 0.46624755859375 +66047 0.30072021484375 +66048 0.25775146484375 +66049 0.1517333984375 +66050 0.0303955078125 +66051 -0.01470947265625 +66052 -0.201507568359375 +66053 -0.1883544921875 +66054 -0.43499755859375 +66055 -0.372711181640625 +66056 -0.62469482421875 +66057 -0.51397705078125 +66058 -0.73602294921875 +66059 -0.57177734375 +66060 -0.76080322265625 +66061 -0.53948974609375 +66062 -0.710479736328125 +66063 -0.43511962890625 +66064 -0.61236572265625 +66065 -0.2962646484375 +66066 -0.49542236328125 +66067 -0.161102294921875 +66068 -0.371612548828125 +66069 -0.0435791015625 +66070 -0.24041748046875 +66071 0.060394287109375 +66072 -0.115875244140625 +66073 0.13665771484375 +66074 -0.013397216796875 +66075 0.170135498046875 +66076 0.066009521484375 +66077 0.16552734375 +66078 0.143463134765625 +66079 0.15728759765625 +66080 0.218414306640625 +66081 0.150787353515625 +66082 0.26861572265625 +66083 0.12200927734375 +66084 0.2972412109375 +66085 0.080108642578125 +66086 0.321014404296875 +66087 0.05126953125 +66088 0.358428955078125 +66089 0.062896728515625 +66090 0.391693115234375 +66091 0.09271240234375 +66092 0.38494873046875 +66093 0.092987060546875 +66094 0.350189208984375 +66095 0.07855224609375 +66096 0.30035400390625 +66097 0.06427001953125 +66098 0.226470947265625 +66099 0.0347900390625 +66100 0.13031005859375 +66101 -0.01171875 +66102 0.029937744140625 +66103 -0.056060791015625 +66104 -0.03875732421875 +66105 -0.055511474609375 +66106 -0.072235107421875 +66107 -0.010467529296875 +66108 -0.107330322265625 +66109 0.02508544921875 +66110 -0.159942626953125 +66111 0.025665283203125 +66112 -0.207916259765625 +66113 0.017333984375 +66114 -0.247955322265625 +66115 0.00189208984375 +66116 -0.287200927734375 +66117 -0.03173828125 +66118 -0.3162841796875 +66119 -0.071502685546875 +66120 -0.34918212890625 +66121 -0.13543701171875 +66122 -0.38446044921875 +66123 -0.219970703125 +66124 -0.40557861328125 +66125 -0.300506591796875 +66126 -0.414459228515625 +66127 -0.376312255859375 +66128 -0.3905029296875 +66129 -0.416107177734375 +66130 -0.300201416015625 +66131 -0.371124267578125 +66132 -0.147430419921875 +66133 -0.242279052734375 +66134 0.03460693359375 +66135 -0.069732666015625 +66136 0.227508544921875 +66137 0.125640869140625 +66138 0.405548095703125 +66139 0.31268310546875 +66140 0.539642333984375 +66141 0.45501708984375 +66142 0.630218505859375 +66143 0.554779052734375 +66144 0.67578125 +66145 0.61065673828125 +66146 0.66766357421875 +66147 0.610931396484375 +66148 0.588592529296875 +66149 0.531463623046875 +66150 0.451934814453125 +66151 0.3883056640625 +66152 0.29949951171875 +66153 0.23468017578125 +66154 0.152069091796875 +66155 0.095245361328125 +66156 0.031646728515625 +66157 -0.00396728515625 +66158 -0.048370361328125 +66159 -0.04852294921875 +66160 -0.097930908203125 +66161 -0.055145263671875 +66162 -0.153656005859375 +66163 -0.0758056640625 +66164 -0.234619140625 +66165 -0.138702392578125 +66166 -0.31317138671875 +66167 -0.209197998046875 +66168 -0.38946533203125 +66169 -0.289031982421875 +66170 -0.46337890625 +66171 -0.37884521484375 +66172 -0.518035888671875 +66173 -0.456329345703125 +66174 -0.5501708984375 +66175 -0.51641845703125 +66176 -0.530914306640625 +66177 -0.519287109375 +66178 -0.45660400390625 +66179 -0.458251953125 +66180 -0.367645263671875 +66181 -0.384796142578125 +66182 -0.28460693359375 +66183 -0.323699951171875 +66184 -0.205352783203125 +66185 -0.269287109375 +66186 -0.112274169921875 +66187 -0.1951904296875 +66188 -0.00628662109375 +66189 -0.100006103515625 +66190 0.09063720703125 +66191 -0.01055908203125 +66192 0.199676513671875 +66193 0.1033935546875 +66194 0.3251953125 +66195 0.24908447265625 +66196 0.426513671875 +66197 0.373199462890625 +66198 0.49017333984375 +66199 0.45806884765625 +66200 0.522247314453125 +66201 0.511474609375 +66202 0.547393798828125 +66203 0.565399169921875 +66204 0.560302734375 +66205 0.61138916015625 +66206 0.517547607421875 +66207 0.5897216796875 +66208 0.413360595703125 +66209 0.4906005859375 +66210 0.262603759765625 +66211 0.33148193359375 +66212 0.09356689453125 +66213 0.147796630859375 +66214 -0.060791015625 +66215 -0.01873779296875 +66216 -0.178009033203125 +66217 -0.140289306640625 +66218 -0.23809814453125 +66219 -0.191986083984375 +66220 -0.247894287109375 +66221 -0.184295654296875 +66222 -0.24017333984375 +66223 -0.161834716796875 +66224 -0.24609375 +66225 -0.166595458984375 +66226 -0.262237548828125 +66227 -0.19390869140625 +66228 -0.2745361328125 +66229 -0.22442626953125 +66230 -0.2999267578125 +66231 -0.279754638671875 +66232 -0.32379150390625 +66233 -0.3389892578125 +66234 -0.31158447265625 +66235 -0.3543701171875 +66236 -0.2813720703125 +66237 -0.348175048828125 +66238 -0.23876953125 +66239 -0.32598876953125 +66240 -0.16302490234375 +66241 -0.2581787109375 +66242 -0.051727294921875 +66243 -0.139801025390625 +66244 0.08306884765625 +66245 0.014617919921875 +66246 0.194854736328125 +66247 0.144378662109375 +66248 0.261688232421875 +66249 0.221038818359375 +66250 0.302764892578125 +66251 0.27069091796875 +66252 0.318572998046875 +66253 0.294036865234375 +66254 0.32489013671875 +66255 0.311767578125 +66256 0.33367919921875 +66257 0.339141845703125 +66258 0.333709716796875 +66259 0.360260009765625 +66260 0.31500244140625 +66261 0.360504150390625 +66262 0.2552490234375 +66263 0.308380126953125 +66264 0.139190673828125 +66265 0.18170166015625 +66266 -0.0137939453125 +66267 0.0047607421875 +66268 -0.167755126953125 +66269 -0.17559814453125 +66270 -0.28814697265625 +66271 -0.3143310546875 +66272 -0.3416748046875 +66273 -0.36785888671875 +66274 -0.347259521484375 +66275 -0.36248779296875 +66276 -0.338226318359375 +66277 -0.343536376953125 +66278 -0.3076171875 +66279 -0.3018798828125 +66280 -0.25103759765625 +66281 -0.231414794921875 +66282 -0.15802001953125 +66283 -0.117645263671875 +66284 -0.053253173828125 +66285 0.007049560546875 +66286 0.02178955078125 +66287 0.087982177734375 +66288 0.076873779296875 +66289 0.13946533203125 +66290 0.12054443359375 +66291 0.17425537109375 +66292 0.148681640625 +66293 0.188201904296875 +66294 0.15283203125 +66295 0.171234130859375 +66296 0.128448486328125 +66297 0.118438720703125 +66298 0.095062255859375 +66299 0.05706787109375 +66300 0.05364990234375 +66301 -0.010711669921875 +66302 -0.001007080078125 +66303 -0.0914306640625 +66304 -0.051727294921875 +66305 -0.162322998046875 +66306 -0.07720947265625 +66307 -0.194549560546875 +66308 -0.0499267578125 +66309 -0.1492919921875 +66310 0.033599853515625 +66311 -0.02166748046875 +66312 0.127838134765625 +66313 0.124053955078125 +66314 0.178558349609375 +66315 0.211151123046875 +66316 0.186920166015625 +66317 0.240447998046875 +66318 0.175048828125 +66319 0.242218017578125 +66320 0.1502685546875 +66321 0.2257080078125 +66322 0.11572265625 +66323 0.194366455078125 +66324 0.048736572265625 +66325 0.115509033203125 +66326 -0.033203125 +66327 0.0128173828125 +66328 -0.087005615234375 +66329 -0.053802490234375 +66330 -0.131072998046875 +66331 -0.110626220703125 +66332 -0.195098876953125 +66333 -0.199493408203125 +66334 -0.26055908203125 +66335 -0.29437255859375 +66336 -0.28271484375 +66337 -0.33221435546875 +66338 -0.23822021484375 +66339 -0.27972412109375 +66340 -0.161956787109375 +66341 -0.185333251953125 +66342 -0.110809326171875 +66343 -0.128204345703125 +66344 -0.09063720703125 +66345 -0.115692138671875 +66346 -0.07977294921875 +66347 -0.116455078125 +66348 -0.061370849609375 +66349 -0.105926513671875 +66350 -0.014556884765625 +66351 -0.053955078125 +66352 0.06683349609375 +66353 0.048797607421875 +66354 0.150360107421875 +66355 0.157318115234375 +66356 0.19329833984375 +66357 0.212005615234375 +66358 0.199493408203125 +66359 0.218475341796875 +66360 0.212005615234375 +66361 0.23724365234375 +66362 0.25732421875 +66363 0.30535888671875 +66364 0.306121826171875 +66365 0.38128662109375 +66366 0.315582275390625 +66367 0.404449462890625 +66368 0.300079345703125 +66369 0.3944091796875 +66370 0.2867431640625 +66371 0.3885498046875 +66372 0.25885009765625 +66373 0.362640380859375 +66374 0.186248779296875 +66375 0.27362060546875 +66376 0.06634521484375 +66377 0.11712646484375 +66378 -0.063446044921875 +66379 -0.054901123046875 +66380 -0.165985107421875 +66381 -0.19085693359375 +66382 -0.2374267578125 +66383 -0.28570556640625 +66384 -0.277496337890625 +66385 -0.339263916015625 +66386 -0.3046875 +66387 -0.3775634765625 +66388 -0.3511962890625 +66389 -0.445709228515625 +66390 -0.4110107421875 +66391 -0.535064697265625 +66392 -0.47259521484375 +66393 -0.629058837890625 +66394 -0.51483154296875 +66395 -0.697601318359375 +66396 -0.511962890625 +66397 -0.70391845703125 +66398 -0.46044921875 +66399 -0.6424560546875 +66400 -0.3450927734375 +66401 -0.491241455078125 +66402 -0.177276611328125 +66403 -0.265716552734375 +66404 0.00140380859375 +66405 -0.023712158203125 +66406 0.167144775390625 +66407 0.201751708984375 +66408 0.29486083984375 +66409 0.375823974609375 +66410 0.374847412109375 +66411 0.485076904296875 +66412 0.43499755859375 +66413 0.56884765625 +66414 0.48077392578125 +66415 0.634765625 +66416 0.480133056640625 +66417 0.63763427734375 +66418 0.42510986328125 +66419 0.5660400390625 +66420 0.35302734375 +66421 0.4720458984375 +66422 0.30072021484375 +66423 0.40692138671875 +66424 0.273651123046875 +66425 0.3778076171875 +66426 0.266632080078125 +66427 0.376953125 +66428 0.2569580078125 +66429 0.371978759765625 +66430 0.20953369140625 +66431 0.313140869140625 +66432 0.11322021484375 +66433 0.184417724609375 +66434 -0.01361083984375 +66435 0.011199951171875 +66436 -0.14556884765625 +66437 -0.171051025390625 +66438 -0.264862060546875 +66439 -0.33740234375 +66440 -0.360137939453125 +66441 -0.47198486328125 +66442 -0.421234130859375 +66443 -0.560394287109375 +66444 -0.432586669921875 +66445 -0.58056640625 +66446 -0.40509033203125 +66447 -0.54754638671875 +66448 -0.372650146484375 +66449 -0.508575439453125 +66450 -0.33258056640625 +66451 -0.459503173828125 +66452 -0.28094482421875 +66453 -0.394378662109375 +66454 -0.246063232421875 +66455 -0.35260009765625 +66456 -0.21221923828125 +66457 -0.31170654296875 +66458 -0.12677001953125 +66459 -0.197418212890625 +66460 0.01129150390625 +66461 -0.007965087890625 +66462 0.166839599609375 +66463 0.207489013671875 +66464 0.311492919921875 +66465 0.409210205078125 +66466 0.4273681640625 +66467 0.57208251953125 +66468 0.4930419921875 +66469 0.66595458984375 +66470 0.485748291015625 +66471 0.65875244140625 +66472 0.417724609375 +66473 0.56744384765625 +66474 0.317169189453125 +66475 0.431396484375 +66476 0.215545654296875 +66477 0.29443359375 +66478 0.131500244140625 +66479 0.182464599609375 +66480 0.042633056640625 +66481 0.06365966796875 +66482 -0.060760498046875 +66483 -0.075958251953125 +66484 -0.145050048828125 +66485 -0.189422607421875 +66486 -0.20660400390625 +66487 -0.271942138671875 +66488 -0.25885009765625 +66489 -0.342529296875 +66490 -0.275360107421875 +66491 -0.364166259765625 +66492 -0.249267578125 +66493 -0.327239990234375 +66494 -0.2127685546875 +66495 -0.2769775390625 +66496 -0.19464111328125 +66497 -0.253692626953125 +66498 -0.185211181640625 +66499 -0.24365234375 +66500 -0.150115966796875 +66501 -0.1983642578125 +66502 -0.08837890625 +66503 -0.116241455078125 +66504 -0.028350830078125 +66505 -0.036834716796875 +66506 0.026214599609375 +66507 0.034881591796875 +66508 0.06964111328125 +66509 0.09124755859375 +66510 0.08514404296875 +66511 0.10888671875 +66512 0.099456787109375 +66513 0.125518798828125 +66514 0.124237060546875 +66515 0.15771484375 +66516 0.1400146484375 +66517 0.17828369140625 +66518 0.13525390625 +66519 0.17108154296875 +66520 0.105621337890625 +66521 0.129974365234375 +66522 0.070709228515625 +66523 0.082427978515625 +66524 0.030059814453125 +66525 0.027679443359375 +66526 -0.038543701171875 +66527 -0.065643310546875 +66528 -0.1077880859375 +66529 -0.15936279296875 +66530 -0.148773193359375 +66531 -0.21307373046875 +66532 -0.166961669921875 +66533 -0.234649658203125 +66534 -0.1451416015625 +66535 -0.2001953125 +66536 -0.089935302734375 +66537 -0.119171142578125 +66538 -0.02484130859375 +66539 -0.024749755859375 +66540 0.052154541015625 +66541 0.085784912109375 +66542 0.116729736328125 +66543 0.178131103515625 +66544 0.142791748046875 +66545 0.215576171875 +66546 0.139862060546875 +66547 0.211456298828125 +66548 0.114654541015625 +66549 0.17523193359375 +66550 0.082672119140625 +66551 0.128753662109375 +66552 0.06512451171875 +66553 0.1019287109375 +66554 0.047454833984375 +66555 0.0743408203125 +66556 0.027557373046875 +66557 0.04327392578125 +66558 0.0262451171875 +66559 0.038177490234375 +66560 0.05511474609375 +66561 0.076263427734375 +66562 0.10186767578125 +66563 0.14105224609375 +66564 0.13446044921875 +66565 0.186431884765625 +66566 0.13690185546875 +66567 0.188812255859375 +66568 0.103057861328125 +66569 0.1390380859375 +66570 0.036224365234375 +66571 0.041778564453125 +66572 -0.04742431640625 +66573 -0.079437255859375 +66574 -0.144195556640625 +66575 -0.219390869140625 +66576 -0.2469482421875 +66577 -0.367828369140625 +66578 -0.335235595703125 +66579 -0.494873046875 +66580 -0.37884521484375 +66581 -0.556243896484375 +66582 -0.3482666015625 +66583 -0.508697509765625 +66584 -0.259307861328125 +66585 -0.3756103515625 +66586 -0.15399169921875 +66587 -0.218902587890625 +66588 -0.04937744140625 +66589 -0.063751220703125 +66590 0.055694580078125 +66591 0.091552734375 +66592 0.153778076171875 +66593 0.23602294921875 +66594 0.22674560546875 +66595 0.342987060546875 +66596 0.262847900390625 +66597 0.39520263671875 +66598 0.259796142578125 +66599 0.389373779296875 +66600 0.2166748046875 +66601 0.324249267578125 +66602 0.149932861328125 +66603 0.224090576171875 +66604 0.083526611328125 +66605 0.124267578125 +66606 0.02569580078125 +66607 0.037078857421875 +66608 -0.004974365234375 +66609 -0.010101318359375 +66610 -0.01007080078125 +66611 -0.019439697265625 +66612 -0.01129150390625 +66613 -0.022796630859375 +66614 0.003936767578125 +66615 -0.001556396484375 +66616 0.04376220703125 +66617 0.056304931640625 +66618 0.07818603515625 +66619 0.106719970703125 +66620 0.071319580078125 +66621 0.096893310546875 +66622 0.03399658203125 +66623 0.042694091796875 +66624 -0.008026123046875 +66625 -0.018035888671875 +66626 -0.04827880859375 +66627 -0.07586669921875 +66628 -0.078948974609375 +66629 -0.11944580078125 +66630 -0.10748291015625 +66631 -0.15972900390625 +66632 -0.137786865234375 +66633 -0.202606201171875 +66634 -0.170135498046875 +66635 -0.24859619140625 +66636 -0.209564208984375 +66637 -0.30517578125 +66638 -0.249114990234375 +66639 -0.36212158203125 +66640 -0.269683837890625 +66641 -0.39141845703125 +66642 -0.24554443359375 +66643 -0.35528564453125 +66644 -0.17413330078125 +66645 -0.249969482421875 +66646 -0.0672607421875 +66647 -0.092864990234375 +66648 0.05670166015625 +66649 0.08905029296875 +66650 0.156585693359375 +66651 0.2352294921875 +66652 0.214080810546875 +66653 0.318817138671875 +66654 0.241943359375 +66655 0.358642578125 +66656 0.23541259765625 +66657 0.347747802734375 +66658 0.194091796875 +66659 0.28564453125 +66660 0.152496337890625 +66661 0.223175048828125 +66662 0.135345458984375 +66663 0.196746826171875 +66664 0.12457275390625 +66665 0.179840087890625 +66666 0.108642578125 +66667 0.155548095703125 +66668 0.106109619140625 +66669 0.151214599609375 +66670 0.1102294921875 +66671 0.156951904296875 +66672 0.0931396484375 +66673 0.13177490234375 +66674 0.0718994140625 +66675 0.100799560546875 +66676 0.062225341796875 +66677 0.087127685546875 +66678 0.039764404296875 +66679 0.05487060546875 +66680 -0.004302978515625 +66681 -0.009002685546875 +66682 -0.069610595703125 +66683 -0.10400390625 +66684 -0.155609130859375 +66685 -0.229400634765625 +66686 -0.242095947265625 +66687 -0.35552978515625 +66688 -0.301513671875 +66689 -0.441925048828125 +66690 -0.323822021484375 +66691 -0.473846435546875 +66692 -0.318145751953125 +66693 -0.464813232421875 +66694 -0.287353515625 +66695 -0.419097900390625 +66696 -0.2298583984375 +66697 -0.334320068359375 +66698 -0.157501220703125 +66699 -0.227935791015625 +66700 -0.0863037109375 +66701 -0.12347412109375 +66702 -0.0208740234375 +66703 -0.02764892578125 +66704 0.051116943359375 +66705 0.077667236328125 +66706 0.143768310546875 +66707 0.2132568359375 +66708 0.263702392578125 +66709 0.38885498046875 +66710 0.396148681640625 +66711 0.582794189453125 +66712 0.499542236328125 +66713 0.734039306640625 +66714 0.545013427734375 +66715 0.800140380859375 +66716 0.5306396484375 +66717 0.7783203125 +66718 0.454071044921875 +66719 0.6651611328125 +66720 0.314605712890625 +66721 0.45965576171875 +66722 0.13763427734375 +66723 0.199188232421875 +66724 -0.032257080078125 +66725 -0.050689697265625 +66726 -0.156280517578125 +66727 -0.23297119140625 +66728 -0.2225341796875 +66729 -0.33013916015625 +66730 -0.248809814453125 +66731 -0.368408203125 +66732 -0.25628662109375 +66733 -0.378936767578125 +66734 -0.25537109375 +66735 -0.376983642578125 +66736 -0.2576904296875 +66737 -0.37969970703125 +66738 -0.26617431640625 +66739 -0.391510009765625 +66740 -0.262420654296875 +66741 -0.385345458984375 +66742 -0.2332763671875 +66743 -0.3419189453125 +66744 -0.1934814453125 +66745 -0.28289794921875 +66746 -0.172454833984375 +66747 -0.251617431640625 +66748 -0.182464599609375 +66749 -0.266143798828125 +66750 -0.187408447265625 +66751 -0.273345947265625 +66752 -0.148895263671875 +66753 -0.216796875 +66754 -0.0885009765625 +66755 -0.128265380859375 +66756 -0.04736328125 +66757 -0.068145751953125 +66758 -0.029998779296875 +66759 -0.0430908203125 +66760 -0.0169677734375 +66761 -0.024444580078125 +66762 0.014129638671875 +66763 0.020721435546875 +66764 0.085052490234375 +66765 0.124481201171875 +66766 0.176055908203125 +66767 0.25787353515625 +66768 0.25872802734375 +66769 0.379119873046875 +66770 0.32745361328125 +66771 0.47991943359375 +66772 0.36041259765625 +66773 0.5281982421875 +66774 0.348876953125 +66775 0.511138916015625 +66776 0.3115234375 +66777 0.456207275390625 +66778 0.2783203125 +66779 0.407470703125 +66780 0.2620849609375 +66781 0.383758544921875 +66782 0.243621826171875 +66783 0.35687255859375 +66784 0.2127685546875 +66785 0.31182861328125 +66786 0.171051025390625 +66787 0.250885009765625 +66788 0.112640380859375 +66789 0.1654052734375 +66790 0.023834228515625 +66791 0.035247802734375 +66792 -0.097015380859375 +66793 -0.142059326171875 +66794 -0.2288818359375 +66795 -0.33563232421875 +66796 -0.364288330078125 +66797 -0.5345458984375 +66798 -0.491729736328125 +66799 -0.72186279296875 +66800 -0.56982421875 +66801 -0.836669921875 +66802 -0.56707763671875 +66803 -0.8326416015625 +66804 -0.4969482421875 +66805 -0.7296142578125 +66806 -0.396820068359375 +66807 -0.582550048828125 +66808 -0.299774169921875 +66809 -0.440093994140625 +66810 -0.220855712890625 +66811 -0.324310302734375 +66812 -0.137115478515625 +66813 -0.20147705078125 +66814 -0.030242919921875 +66815 -0.044647216796875 +66816 0.071624755859375 +66817 0.103973388671875 +66818 0.14056396484375 +66819 0.202392578125 +66820 0.185333251953125 +66821 0.264495849609375 +66822 0.2371826171875 +66823 0.338897705078125 +66824 0.307708740234375 +66825 0.443817138671875 +66826 0.37469482421875 +66827 0.545074462890625 +66828 0.421630859375 +66829 0.6173095703125 +66830 0.443359375 +66831 0.6524658203125 +66832 0.448272705078125 +66833 0.66339111328125 +66834 0.440460205078125 +66835 0.6561279296875 +66836 0.40460205078125 +66837 0.606781005859375 +66838 0.331756591796875 +66839 0.501190185546875 +66840 0.230865478515625 +66841 0.352783203125 +66842 0.111968994140625 +66843 0.176544189453125 +66844 -0.029388427734375 +66845 -0.034820556640625 +66846 -0.178009033203125 +66847 -0.258209228515625 +66848 -0.300537109375 +66849 -0.44244384765625 +66850 -0.388916015625 +66851 -0.5753173828125 +66852 -0.439971923828125 +66853 -0.65203857421875 +66854 -0.433563232421875 +66855 -0.641632080078125 +66856 -0.381439208984375 +66857 -0.562164306640625 +66858 -0.31243896484375 +66859 -0.458038330078125 +66860 -0.24041748046875 +66861 -0.350555419921875 +66862 -0.17901611328125 +66863 -0.260528564453125 +66864 -0.131134033203125 +66865 -0.192108154296875 +66866 -0.0948486328125 +66867 -0.141937255859375 +66868 -0.06524658203125 +66869 -0.1021728515625 +66870 -0.036102294921875 +66871 -0.062896728515625 +66872 0.000244140625 +66873 -0.011932373046875 +66874 0.051483154296875 +66875 0.062835693359375 +66876 0.1092529296875 +66877 0.148712158203125 +66878 0.170867919921875 +66879 0.241729736328125 +66880 0.240966796875 +66881 0.34912109375 +66882 0.310760498046875 +66883 0.457305908203125 +66884 0.365753173828125 +66885 0.54388427734375 +66886 0.38275146484375 +66887 0.5728759765625 +66888 0.337432861328125 +66889 0.506591796875 +66890 0.233978271484375 +66891 0.351226806640625 +66892 0.098297119140625 +66893 0.146514892578125 +66894 -0.035552978515625 +66895 -0.05523681640625 +66896 -0.142913818359375 +66897 -0.21624755859375 +66898 -0.22259521484375 +66899 -0.334930419921875 +66900 -0.269073486328125 +66901 -0.402984619140625 +66902 -0.29571533203125 +66903 -0.4412841796875 +66904 -0.332244873046875 +66905 -0.49578857421875 +66906 -0.374542236328125 +66907 -0.5601806640625 +66908 -0.400726318359375 +66909 -0.600738525390625 +66910 -0.389312744140625 +66911 -0.584228515625 +66912 -0.320037841796875 +66913 -0.47930908203125 +66914 -0.188690185546875 +66915 -0.27935791015625 +66916 -0.01129150390625 +66917 -0.0089111328125 +66918 0.1710205078125 +66919 0.268798828125 +66920 0.312164306640625 +66921 0.482818603515625 +66922 0.3929443359375 +66923 0.60369873046875 +66924 0.42547607421875 +66925 0.650421142578125 +66926 0.436248779296875 +66927 0.66400146484375 +66928 0.4232177734375 +66929 0.6414794921875 +66930 0.379669189453125 +66931 0.572540283203125 +66932 0.332061767578125 +66933 0.498138427734375 +66934 0.29412841796875 +66935 0.439453125 +66936 0.252288818359375 +66937 0.375518798828125 +66938 0.185943603515625 +66939 0.274505615234375 +66940 0.07720947265625 +66941 0.1087646484375 +66942 -0.059326171875 +66943 -0.099395751953125 +66944 -0.202972412109375 +66945 -0.3182373046875 +66946 -0.35443115234375 +66947 -0.5489501953125 +66948 -0.502105712890625 +66949 -0.7738037109375 +66950 -0.611541748046875 +66951 -0.86383056640625 +66952 -0.6611328125 +66953 -0.870391845703125 +66954 -0.662261962890625 +66955 -0.86895751953125 +66956 -0.623382568359375 +66957 -0.861053466796875 +66958 -0.533203125 +66959 -0.765869140625 +66960 -0.3843994140625 +66961 -0.5301513671875 +66962 -0.181610107421875 +66963 -0.214691162109375 +66964 0.047271728515625 +66965 0.137359619140625 +66966 0.2689208984375 +66967 0.474822998046875 +66968 0.46026611328125 +66969 0.76239013671875 +66970 0.603729248046875 +66971 0.867462158203125 +66972 0.699493408203125 +66973 0.870361328125 +66974 0.739990234375 +66975 0.86480712890625 +66976 0.728607177734375 +66977 0.831817626953125 +66978 0.6810302734375 +66979 0.677581787109375 +66980 0.6009521484375 +66981 0.495880126953125 +66982 0.500335693359375 +66983 0.30767822265625 +66984 0.380584716796875 +66985 0.116180419921875 +66986 0.221099853515625 +66987 -0.110748291015625 +66988 0.01739501953125 +66989 -0.381805419921875 +66990 -0.2027587890625 +66991 -0.6572265625 +66992 -0.4005126953125 +66993 -0.857421875 +66994 -0.548004150390625 +66995 -0.870391845703125 +66996 -0.6405029296875 +66997 -0.870391845703125 +66998 -0.695404052734375 +66999 -0.86444091796875 +67000 -0.735748291015625 +67001 -0.85723876953125 +67002 -0.749542236328125 +67003 -0.790008544921875 +67004 -0.701568603515625 +67005 -0.62847900390625 +67006 -0.589691162109375 +67007 -0.3956298828125 +67008 -0.435150146484375 +67009 -0.126708984375 +67010 -0.255645751953125 +67011 0.150115966796875 +67012 -0.058746337890625 +67013 0.424041748046875 +67014 0.138031005859375 +67015 0.670623779296875 +67016 0.309600830078125 +67017 0.854522705078125 +67018 0.4444580078125 +67019 0.866485595703125 +67020 0.5325927734375 +67021 0.86920166015625 +67022 0.585662841796875 +67023 0.8653564453125 +67024 0.612274169921875 +67025 0.857147216796875 +67026 0.6104736328125 +67027 0.766845703125 +67028 0.583526611328125 +67029 0.628509521484375 +67030 0.5269775390625 +67031 0.462127685546875 +67032 0.457489013671875 +67033 0.297210693359375 +67034 0.383026123046875 +67035 0.14862060546875 +67036 0.288787841796875 +67037 -0.00537109375 +67038 0.179656982421875 +67039 -0.15753173828125 +67040 0.05328369140625 +67041 -0.31304931640625 +67042 -0.099395751953125 +67043 -0.48876953125 +67044 -0.247955322265625 +67045 -0.6416015625 +67046 -0.376312255859375 +67047 -0.751373291015625 +67048 -0.499359130859375 +67049 -0.84619140625 +67050 -0.60748291015625 +67051 -0.861297607421875 +67052 -0.679107666015625 +67053 -0.863250732421875 +67054 -0.693756103515625 +67055 -0.856597900390625 +67056 -0.659210205078125 +67057 -0.7498779296875 +67058 -0.612884521484375 +67059 -0.624542236328125 +67060 -0.540496826171875 +67061 -0.47808837890625 +67062 -0.404144287109375 +67063 -0.253387451171875 +67064 -0.233428955078125 +67065 0.003692626953125 +67066 -0.072662353515625 +67067 0.2257080078125 +67068 0.086212158203125 +67069 0.427154541015625 +67070 0.264129638671875 +67071 0.643218994140625 +67072 0.45428466796875 +67073 0.855926513671875 +67074 0.619049072265625 +67075 0.870361328125 +67076 0.726898193359375 +67077 0.870361328125 +67078 0.78216552734375 +67079 0.862762451171875 +67080 0.783111572265625 +67081 0.79669189453125 +67082 0.72412109375 +67083 0.595794677734375 +67084 0.62347412109375 +67085 0.362152099609375 +67086 0.498809814453125 +67087 0.1270751953125 +67088 0.36358642578125 +67089 -0.086944580078125 +67090 0.2196044921875 +67091 -0.2784423828125 +67092 0.045928955078125 +67093 -0.484832763671875 +67094 -0.16876220703125 +67095 -0.729583740234375 +67096 -0.392822265625 +67097 -0.86688232421875 +67098 -0.5867919921875 +67099 -0.870391845703125 +67100 -0.747222900390625 +67101 -0.86859130859375 +67102 -0.856475830078125 +67103 -0.86279296875 +67104 -0.863861083984375 +67105 -0.817962646484375 +67106 -0.8619384765625 +67107 -0.6116943359375 +67108 -0.81488037109375 +67109 -0.3128662109375 +67110 -0.63812255859375 +67111 0.039398193359375 +67112 -0.404876708984375 +67113 0.422821044921875 +67114 -0.135955810546875 +67115 0.805145263671875 +67116 0.126312255859375 +67117 0.870361328125 +67118 0.346343994140625 +67119 0.870361328125 +67120 0.516387939453125 +67121 0.860015869140625 +67122 0.631195068359375 +67123 0.727935791015625 +67124 0.68682861328125 +67125 0.48114013671875 +67126 0.69769287109375 +67127 0.2059326171875 +67128 0.677337646484375 +67129 -0.06103515625 +67130 0.631622314453125 +67131 -0.29913330078125 +67132 0.55145263671875 +67133 -0.516204833984375 +67134 0.42730712890625 +67135 -0.7252197265625 +67136 0.274658203125 +67137 -0.85980224609375 +67138 0.114898681640625 +67139 -0.870391845703125 +67140 -0.0333251953125 +67141 -0.870391845703125 +67142 -0.139495849609375 +67143 -0.858062744140625 +67144 -0.200408935546875 +67145 -0.673004150390625 +67146 -0.24774169921875 +67147 -0.42694091796875 +67148 -0.308197021484375 +67149 -0.2100830078125 +67150 -0.37982177734375 +67151 -0.0362548828125 +67152 -0.44415283203125 +67153 0.10943603515625 +67154 -0.4884033203125 +67155 0.23516845703125 +67156 -0.48675537109375 +67157 0.373687744140625 +67158 -0.440185546875 +67159 0.517791748046875 +67160 -0.38739013671875 +67161 0.602783203125 +67162 -0.325286865234375 +67163 0.635711669921875 +67164 -0.233551025390625 +67165 0.655181884765625 +67166 -0.11871337890625 +67167 0.65948486328125 +67168 0.0137939453125 +67169 0.651275634765625 +67170 0.148284912109375 +67171 0.61846923828125 +67172 0.261322021484375 +67173 0.53753662109375 +67174 0.3411865234375 +67175 0.404144287109375 +67176 0.3812255859375 +67177 0.22186279296875 +67178 0.38165283203125 +67179 0.003997802734375 +67180 0.3531494140625 +67181 -0.22100830078125 +67182 0.308013916015625 +67183 -0.42449951171875 +67184 0.259185791015625 +67185 -0.579833984375 +67186 0.232879638671875 +67187 -0.641876220703125 +67188 0.225006103515625 +67189 -0.6177978515625 +67190 0.195953369140625 +67191 -0.575531005859375 +67192 0.142730712890625 +67193 -0.526336669921875 +67194 0.09765625 +67195 -0.42645263671875 +67196 0.078094482421875 +67197 -0.2581787109375 +67198 0.06219482421875 +67199 -0.068695068359375 +67200 0.02679443359375 +67201 0.09222412109375 +67202 -0.0159912109375 +67203 0.232147216796875 +67204 -0.05938720703125 +67205 0.3509521484375 +67206 -0.12115478515625 +67207 0.410064697265625 +67208 -0.218963623046875 +67209 0.372955322265625 +67210 -0.339599609375 +67211 0.2554931640625 +67212 -0.450775146484375 +67213 0.10711669921875 +67214 -0.54034423828125 +67215 -0.052886962890625 +67216 -0.586090087890625 +67217 -0.186279296875 +67218 -0.553741455078125 +67219 -0.23291015625 +67220 -0.45758056640625 +67221 -0.209442138671875 +67222 -0.33856201171875 +67223 -0.174163818359375 +67224 -0.202239990234375 +67225 -0.126739501953125 +67226 -0.042999267578125 +67227 -0.048126220703125 +67228 0.121246337890625 +67229 0.0426025390625 +67230 0.261260986328125 +67231 0.10748291015625 +67232 0.368438720703125 +67233 0.1409912109375 +67234 0.4716796875 +67235 0.19708251953125 +67236 0.56646728515625 +67237 0.273651123046875 +67238 0.6181640625 +67239 0.31768798828125 +67240 0.633392333984375 +67241 0.341094970703125 +67242 0.627685546875 +67243 0.368011474609375 +67244 0.586944580078125 +67245 0.37249755859375 +67246 0.48095703125 +67247 0.30072021484375 +67248 0.31304931640625 +67249 0.1517333984375 +67250 0.124603271484375 +67251 -0.01470947265625 +67252 -0.073089599609375 +67253 -0.1883544921875 +67254 -0.277099609375 +67255 -0.372711181640625 +67256 -0.449371337890625 +67257 -0.51397705078125 +67258 -0.560516357421875 +67259 -0.57177734375 +67260 -0.602630615234375 +67261 -0.53948974609375 +67262 -0.58380126953125 +67263 -0.43511962890625 +67264 -0.52520751953125 +67265 -0.2962646484375 +67266 -0.44940185546875 +67267 -0.161102294921875 +67268 -0.365142822265625 +67269 -0.0435791015625 +67270 -0.2711181640625 +67271 0.060394287109375 +67272 -0.178192138671875 +67273 0.13665771484375 +67274 -0.098602294921875 +67275 0.170135498046875 +67276 -0.03302001953125 +67277 0.16552734375 +67278 0.03570556640625 +67279 0.15728759765625 +67280 0.106719970703125 +67281 0.150787353515625 +67282 0.161102294921875 +67283 0.12200927734375 +67284 0.200653076171875 +67285 0.080108642578125 +67286 0.238128662109375 +67287 0.05126953125 +67288 0.2877197265625 +67289 0.062896728515625 +67290 0.333709716796875 +67291 0.09271240234375 +67292 0.34564208984375 +67293 0.092987060546875 +67294 0.33245849609375 +67295 0.07855224609375 +67296 0.303985595703125 +67297 0.06427001953125 +67298 0.252288818359375 +67299 0.0347900390625 +67300 0.178436279296875 +67301 -0.01171875 +67302 0.09710693359375 +67303 -0.056060791015625 +67304 0.037811279296875 +67305 -0.055511474609375 +67306 0.003692626953125 +67307 -0.010467529296875 +67308 -0.035003662109375 +67309 0.02508544921875 +67310 -0.0906982421875 +67311 0.025665283203125 +67312 -0.1444091796875 +67313 0.017333984375 +67314 -0.192626953125 +67315 0.00189208984375 +67316 -0.2403564453125 +67317 -0.03173828125 +67318 -0.279052734375 +67319 -0.071502685546875 +67320 -0.31939697265625 +67321 -0.13543701171875 +67322 -0.359527587890625 +67323 -0.219970703125 +67324 -0.38531494140625 +67325 -0.300506591796875 +67326 -0.397918701171875 +67327 -0.376312255859375 +67328 -0.380340576171875 +67329 -0.416107177734375 +67330 -0.30523681640625 +67331 -0.371124267578125 +67332 -0.1759033203125 +67333 -0.242279052734375 +67334 -0.0196533203125 +67335 -0.069732666015625 +67336 0.147857666015625 +67337 0.125640869140625 +67338 0.30511474609375 +67339 0.31268310546875 +67340 0.427886962890625 +67341 0.45501708984375 +67342 0.515533447265625 +67343 0.554779052734375 +67344 0.566009521484375 +67345 0.61065673828125 +67346 0.5716552734375 +67347 0.610931396484375 +67348 0.51800537109375 +67349 0.531463623046875 +67350 0.41534423828125 +67351 0.3883056640625 +67352 0.296844482421875 +67353 0.23468017578125 +67354 0.1790771484375 +67355 0.095245361328125 +67356 0.0797119140625 +67357 -0.00396728515625 +67358 0.009735107421875 +67359 -0.04852294921875 +67360 -0.03839111328125 +67361 -0.055145263671875 +67362 -0.093414306640625 +67363 -0.0758056640625 +67364 -0.169952392578125 +67365 -0.138702392578125 +67366 -0.245208740234375 +67367 -0.209197998046875 +67368 -0.318572998046875 +67369 -0.289031982421875 +67370 -0.389251708984375 +67371 -0.37884521484375 +67372 -0.44317626953125 +67373 -0.456329345703125 +67374 -0.477203369140625 +67375 -0.51641845703125 +67376 -0.467803955078125 +67377 -0.519287109375 +67378 -0.411865234375 +67379 -0.458251953125 +67380 -0.341552734375 +67381 -0.384796142578125 +67382 -0.27337646484375 +67383 -0.323699951171875 +67384 -0.20574951171875 +67385 -0.269287109375 +67386 -0.124908447265625 +67387 -0.1951904296875 +67388 -0.032012939453125 +67389 -0.100006103515625 +67390 0.05487060546875 +67391 -0.01055908203125 +67392 0.15216064453125 +67393 0.1033935546875 +67394 0.26275634765625 +67395 0.24908447265625 +67396 0.35357666015625 +67397 0.373199462890625 +67398 0.413299560546875 +67399 0.45806884765625 +67400 0.446319580078125 +67401 0.511474609375 +67402 0.4720458984375 +67403 0.565399169921875 +67404 0.4859619140625 +67405 0.61138916015625 +67406 0.45318603515625 +67407 0.5897216796875 +67408 0.369110107421875 +67409 0.4906005859375 +67410 0.24566650390625 +67411 0.33148193359375 +67412 0.105712890625 +67413 0.147796630859375 +67414 -0.024017333984375 +67415 -0.01873779296875 +67416 -0.12518310546875 +67417 -0.140289306640625 +67418 -0.181365966796875 +67419 -0.191986083984375 +67420 -0.19757080078125 +67421 -0.184295654296875 +67422 -0.1995849609375 +67423 -0.161834716796875 +67424 -0.211883544921875 +67425 -0.166595458984375 +67426 -0.2313232421875 +67427 -0.19390869140625 +67428 -0.246307373046875 +67429 -0.22442626953125 +67430 -0.2701416015625 +67431 -0.279754638671875 +67432 -0.290985107421875 +67433 -0.3389892578125 +67434 -0.281158447265625 +67435 -0.3543701171875 +67436 -0.25518798828125 +67437 -0.348175048828125 +67438 -0.21771240234375 +67439 -0.32598876953125 +67440 -0.15234375 +67441 -0.2581787109375 +67442 -0.057464599609375 +67443 -0.139801025390625 +67444 0.056915283203125 +67445 0.014617919921875 +67446 0.153228759765625 +67447 0.144378662109375 +67448 0.2135009765625 +67449 0.221038818359375 +67450 0.25274658203125 +67451 0.27069091796875 +67452 0.271026611328125 +67453 0.294036865234375 +67454 0.2806396484375 +67455 0.311767578125 +67456 0.290924072265625 +67457 0.339141845703125 +67458 0.292633056640625 +67459 0.360260009765625 +67460 0.27777099609375 +67461 0.360504150390625 +67462 0.22894287109375 +67463 0.308380126953125 +67464 0.13433837890625 +67465 0.18170166015625 +67466 0.0093994140625 +67467 0.0047607421875 +67468 -0.117279052734375 +67469 -0.17559814453125 +67470 -0.218231201171875 +67471 -0.3143310546875 +67472 -0.26690673828125 +67473 -0.36785888671875 +67474 -0.277801513671875 +67475 -0.36248779296875 +67476 -0.2767333984375 +67477 -0.343536376953125 +67478 -0.2579345703125 +67479 -0.3018798828125 +67480 -0.2176513671875 +67481 -0.231414794921875 +67482 -0.14752197265625 +67483 -0.117645263671875 +67484 -0.066802978515625 +67485 0.007049560546875 +67486 -0.007965087890625 +67487 0.087982177734375 +67488 0.036590576171875 +67489 0.13946533203125 +67490 0.073455810546875 +67491 0.17425537109375 +67492 0.0992431640625 +67493 0.188201904296875 +67494 0.1070556640625 +67495 0.171234130859375 +67496 0.093048095703125 +67497 0.118438720703125 +67498 0.072265625 +67499 0.05706787109375 +67500 0.045135498046875 +67501 -0.010711669921875 +67502 0.007293701171875 +67503 -0.0914306640625 +67504 -0.02838134765625 +67505 -0.162322998046875 +67506 -0.045257568359375 +67507 -0.194549560546875 +67508 -0.020660400390625 +67509 -0.1492919921875 +67510 0.048431396484375 +67511 -0.02166748046875 +67512 0.124908447265625 +67513 0.124053955078125 +67514 0.164520263671875 +67515 0.211151123046875 +67516 0.16845703125 +67517 0.240447998046875 +67518 0.1551513671875 +67519 0.242218017578125 +67520 0.130859375 +67521 0.2257080078125 +67522 0.098388671875 +67523 0.194366455078125 +67524 0.039398193359375 +67525 0.115509033203125 +67526 -0.031585693359375 +67527 0.0128173828125 +67528 -0.079010009765625 +67529 -0.053802490234375 +67530 -0.11785888671875 +67531 -0.110626220703125 +67532 -0.172332763671875 +67533 -0.199493408203125 +67534 -0.227203369140625 +67535 -0.29437255859375 +67536 -0.245758056640625 +67537 -0.33221435546875 +67538 -0.208831787109375 +67539 -0.27972412109375 +67540 -0.1451416015625 +67541 -0.185333251953125 +67542 -0.1014404296875 +67543 -0.128204345703125 +67544 -0.08258056640625 +67545 -0.115692138671875 +67546 -0.07098388671875 +67547 -0.116455078125 +67548 -0.052978515625 +67549 -0.105926513671875 +67550 -0.0115966796875 +67551 -0.053955078125 +67552 0.05804443359375 +67553 0.048797607421875 +67554 0.129180908203125 +67555 0.157318115234375 +67556 0.166656494140625 +67557 0.212005615234375 +67558 0.1734619140625 +67559 0.218475341796875 +67560 0.184844970703125 +67561 0.23724365234375 +67562 0.2225341796875 +67563 0.30535888671875 +67564 0.262420654296875 +67565 0.38128662109375 +67566 0.269439697265625 +67567 0.404449462890625 +67568 0.25543212890625 +67569 0.3944091796875 +67570 0.242706298828125 +67571 0.3885498046875 +67572 0.21771240234375 +67573 0.362640380859375 +67574 0.15582275390625 +67575 0.27362060546875 +67576 0.055023193359375 +67577 0.11712646484375 +67578 -0.0538330078125 +67579 -0.054901123046875 +67580 -0.140167236328125 +67581 -0.19085693359375 +67582 -0.200714111328125 +67583 -0.28570556640625 +67584 -0.235748291015625 +67585 -0.339263916015625 +67586 -0.26007080078125 +67587 -0.3775634765625 +67588 -0.298583984375 +67589 -0.445709228515625 +67590 -0.346282958984375 +67591 -0.535064697265625 +67592 -0.39398193359375 +67593 -0.629058837890625 +67594 -0.425201416015625 +67595 -0.697601318359375 +67596 -0.41998291015625 +67597 -0.70391845703125 +67598 -0.375732421875 +67599 -0.6424560546875 +67600 -0.280914306640625 +67601 -0.491241455078125 +67602 -0.144683837890625 +67603 -0.265716552734375 +67604 0.0003662109375 +67605 -0.023712158203125 +67606 0.135345458984375 +67607 0.201751708984375 +67608 0.240447998046875 +67609 0.375823974609375 +67610 0.30780029296875 +67611 0.485076904296875 +67612 0.3587646484375 +67613 0.56884765625 +67614 0.3973388671875 +67615 0.634765625 +67616 0.398529052734375 +67617 0.63763427734375 +67618 0.3560791015625 +67619 0.5660400390625 +67620 0.298980712890625 +67621 0.4720458984375 +67622 0.255859375 +67623 0.40692138671875 +67624 0.231109619140625 +67625 0.3778076171875 +67626 0.220977783203125 +67627 0.376953125 +67628 0.2081298828125 +67629 0.371978759765625 +67630 0.165679931640625 +67631 0.313140869140625 +67632 0.0853271484375 +67633 0.184417724609375 +67634 -0.018402099609375 +67635 0.011199951171875 +67636 -0.125518798828125 +67637 -0.171051025390625 +67638 -0.221954345703125 +67639 -0.33740234375 +67640 -0.298736572265625 +67641 -0.47198486328125 +67642 -0.347869873046875 +67643 -0.560394287109375 +67644 -0.35723876953125 +67645 -0.58056640625 +67646 -0.335296630859375 +67647 -0.54754638671875 +67648 -0.308380126953125 +67649 -0.508575439453125 +67650 -0.2745361328125 +67651 -0.459503173828125 +67652 -0.23089599609375 +67653 -0.394378662109375 +67654 -0.199615478515625 +67655 -0.35260009765625 +67656 -0.16876220703125 +67657 -0.31170654296875 +67658 -0.097808837890625 +67659 -0.197418212890625 +67660 0.013824462890625 +67661 -0.007965087890625 +67662 0.13861083984375 +67663 0.207489013671875 +67664 0.254302978515625 +67665 0.409210205078125 +67666 0.34686279296875 +67667 0.57208251953125 +67668 0.3995361328125 +67669 0.66595458984375 +67670 0.3946533203125 +67671 0.65875244140625 +67672 0.3416748046875 +67673 0.56744384765625 +67674 0.26251220703125 +67675 0.431396484375 +67676 0.181640625 +67677 0.29443359375 +67678 0.113677978515625 +67679 0.182464599609375 +67680 0.041412353515625 +67681 0.06365966796875 +67682 -0.04248046875 +67683 -0.075958251953125 +67684 -0.1116943359375 +67685 -0.189422607421875 +67686 -0.1632080078125 +67687 -0.271942138671875 +67688 -0.20721435546875 +67689 -0.342529296875 +67690 -0.223052978515625 +67691 -0.364166259765625 +67692 -0.205291748046875 +67693 -0.327239990234375 +67694 -0.178741455078125 +67695 -0.2769775390625 +67696 -0.1656494140625 +67697 -0.253692626953125 +67698 -0.158447265625 +67699 -0.24365234375 +67700 -0.130523681640625 +67701 -0.1983642578125 +67702 -0.0811767578125 +67703 -0.116241455078125 +67704 -0.032501220703125 +67705 -0.036834716796875 +67706 0.012451171875 +67707 0.034881591796875 +67708 0.04913330078125 +67709 0.09124755859375 +67710 0.064361572265625 +67711 0.10888671875 +67712 0.078643798828125 +67713 0.125518798828125 +67714 0.100860595703125 +67715 0.15771484375 +67716 0.11578369140625 +67717 0.17828369140625 +67718 0.11431884765625 +67719 0.17108154296875 +67720 0.092987060546875 +67721 0.129974365234375 +67722 0.06689453125 +67723 0.082427978515625 +67724 0.03564453125 +67725 0.027679443359375 +67726 -0.0179443359375 +67727 -0.065643310546875 +67728 -0.072662353515625 +67729 -0.15936279296875 +67730 -0.106048583984375 +67731 -0.21307373046875 +67732 -0.122222900390625 +67733 -0.234649658203125 +67734 -0.10772705078125 +67735 -0.2001953125 +67736 -0.067535400390625 +67737 -0.119171142578125 +67738 -0.01971435546875 +67739 -0.024749755859375 +67740 0.037445068359375 +67741 0.085784912109375 +67742 0.085205078125 +67743 0.178131103515625 +67744 0.103485107421875 +67745 0.215576171875 +67746 0.0997314453125 +67747 0.211456298828125 +67748 0.0792236328125 +67749 0.17523193359375 +67750 0.05401611328125 +67751 0.128753662109375 +67752 0.04058837890625 +67753 0.1019287109375 +67754 0.027557373046875 +67755 0.0743408203125 +67756 0.013275146484375 +67757 0.04327392578125 +67758 0.013824462890625 +67759 0.038177490234375 +67760 0.03851318359375 +67761 0.076263427734375 +67762 0.0780029296875 +67763 0.14105224609375 +67764 0.106658935546875 +67765 0.186431884765625 +67766 0.11126708984375 +67767 0.188812255859375 +67768 0.08660888671875 +67769 0.1390380859375 +67770 0.035125732421875 +67771 0.041778564453125 +67772 -0.030303955078125 +67773 -0.079437255859375 +67774 -0.106842041015625 +67775 -0.219390869140625 +67776 -0.188812255859375 +67777 -0.367828369140625 +67778 -0.25970458984375 +67779 -0.494873046875 +67780 -0.2950439453125 +67781 -0.556243896484375 +67782 -0.2708740234375 +67783 -0.508697509765625 +67784 -0.199951171875 +67785 -0.3756103515625 +67786 -0.116302490234375 +67787 -0.218902587890625 +67788 -0.033660888671875 +67789 -0.063751220703125 +67790 0.049041748046875 +67791 0.091552734375 +67792 0.12591552734375 +67793 0.23602294921875 +67794 0.182373046875 +67795 0.342987060546875 +67796 0.20904541015625 +67797 0.39520263671875 +67798 0.204254150390625 +67799 0.389373779296875 +67800 0.167388916015625 +67801 0.324249267578125 +67802 0.111846923828125 +67803 0.224090576171875 +67804 0.057159423828125 +67805 0.124267578125 +67806 0.01007080078125 +67807 0.037078857421875 +67808 -0.014373779296875 +67809 -0.010101318359375 +67810 -0.017486572265625 +67811 -0.019439697265625 +67812 -0.0169677734375 +67813 -0.022796630859375 +67814 -0.002685546875 +67815 -0.001556396484375 +67816 0.031829833984375 +67817 0.056304931640625 +67818 0.062103271484375 +67819 0.106719970703125 +67820 0.058868408203125 +67821 0.096893310546875 +67822 0.030792236328125 +67823 0.042694091796875 +67824 -0.0013427734375 +67825 -0.018035888671875 +67826 -0.0323486328125 +67827 -0.07586669921875 +67828 -0.055999755859375 +67829 -0.11944580078125 +67830 -0.078369140625 +67831 -0.15972900390625 +67832 -0.102691650390625 +67833 -0.202606201171875 +67834 -0.129180908203125 +67835 -0.24859619140625 +67836 -0.161895751953125 +67837 -0.30517578125 +67838 -0.195098876953125 +67839 -0.36212158203125 +67840 -0.21337890625 +67841 -0.39141845703125 +67842 -0.19586181640625 +67843 -0.35528564453125 +67844 -0.14031982421875 +67845 -0.249969482421875 +67846 -0.056396484375 +67847 -0.092864990234375 +67848 0.04132080078125 +67849 0.08905029296875 +67850 0.120880126953125 +67851 0.2352294921875 +67852 0.16790771484375 +67853 0.318817138671875 +67854 0.191864013671875 +67855 0.358642578125 +67856 0.18890380859375 +67857 0.347747802734375 +67858 0.158599853515625 +67859 0.28564453125 +67860 0.12725830078125 +67861 0.223175048828125 +67862 0.113800048828125 +67863 0.196746826171875 +67864 0.1044921875 +67865 0.179840087890625 +67866 0.09063720703125 +67867 0.155548095703125 +67868 0.0865478515625 +67869 0.151214599609375 +67870 0.087249755859375 +67871 0.156951904296875 +67872 0.071563720703125 +67873 0.13177490234375 +67874 0.052734375 +67875 0.100799560546875 +67876 0.042938232421875 +67877 0.087127685546875 +67878 0.023681640625 +67879 0.05487060546875 +67880 -0.011688232421875 +67881 -0.009002685546875 +67882 -0.062744140625 +67883 -0.10400390625 +67884 -0.12908935546875 +67885 -0.229400634765625 +67886 -0.195220947265625 +67887 -0.35552978515625 +67888 -0.240081787109375 +67889 -0.441925048828125 +67890 -0.25604248046875 +67891 -0.473846435546875 +67892 -0.250152587890625 +67893 -0.464813232421875 +67894 -0.2247314453125 +67895 -0.419097900390625 +67896 -0.17864990234375 +67897 -0.334320068359375 +67898 -0.12109375 +67899 -0.227935791015625 +67900 -0.064422607421875 +67901 -0.12347412109375 +67902 -0.01226806640625 +67903 -0.02764892578125 +67904 0.044647216796875 +67905 0.077667236328125 +67906 0.11700439453125 +67907 0.2132568359375 +67908 0.20977783203125 +67909 0.38885498046875 +67910 0.311614990234375 +67911 0.582794189453125 +67912 0.3907470703125 +67913 0.734039306640625 +67914 0.425079345703125 +67915 0.800140380859375 +67916 0.413177490234375 +67917 0.7783203125 +67918 0.353363037109375 +67919 0.6651611328125 +67920 0.245147705078125 +67921 0.45965576171875 +67922 0.10809326171875 +67923 0.199188232421875 +67924 -0.023651123046875 +67925 -0.050689697265625 +67926 -0.120330810546875 +67927 -0.23297119140625 +67928 -0.1727294921875 +67929 -0.33013916015625 +67930 -0.19439697265625 +67931 -0.368408203125 +67932 -0.201416015625 +67933 -0.378936767578125 +67934 -0.20166015625 +67935 -0.376983642578125 +67936 -0.2039794921875 +67937 -0.37969970703125 +67938 -0.21063232421875 +67939 -0.391510009765625 +67940 -0.207550048828125 +67941 -0.385345458984375 +67942 -0.184661865234375 +67943 -0.3419189453125 +67944 -0.153289794921875 +67945 -0.28289794921875 +67946 -0.136016845703125 +67947 -0.251617431640625 +67948 -0.142303466796875 +67949 -0.266143798828125 +67950 -0.14459228515625 +67951 -0.273345947265625 +67952 -0.113616943359375 +67953 -0.216796875 +67954 -0.06597900390625 +67955 -0.128265380859375 +67956 -0.033172607421875 +67957 -0.068145751953125 +67958 -0.018707275390625 +67959 -0.0430908203125 +67960 -0.007781982421875 +67961 -0.024444580078125 +67962 0.016632080078125 +67963 0.020721435546875 +67964 0.071136474609375 +67965 0.124481201171875 +67966 0.140655517578125 +67967 0.25787353515625 +67968 0.2034912109375 +67969 0.379119873046875 +67970 0.25537109375 +67971 0.47991943359375 +67972 0.2796630859375 +67973 0.5281982421875 +67974 0.26971435546875 +67975 0.511138916015625 +67976 0.239898681640625 +67977 0.456207275390625 +67978 0.21319580078125 +67979 0.407470703125 +67980 0.199493408203125 +67981 0.383758544921875 +67982 0.184173583984375 +67983 0.35687255859375 +67984 0.159515380859375 +67985 0.31182861328125 +67986 0.126739501953125 +67987 0.250885009765625 +67988 0.0814208984375 +67989 0.1654052734375 +67990 0.013153076171875 +67991 0.035247802734375 +67992 -0.079315185546875 +67993 -0.142059326171875 +67994 -0.179931640625 +67995 -0.33563232421875 +67996 -0.28302001953125 +67997 -0.5345458984375 +67998 -0.3797607421875 +67999 -0.72186279296875 +68000 -0.43853759765625 +68001 -0.836669921875 +68002 -0.435333251953125 +68003 -0.8326416015625 +68004 -0.38055419921875 +68005 -0.7296142578125 +68006 -0.302825927734375 +68007 -0.582550048828125 +68008 -0.2275390625 +68009 -0.440093994140625 +68010 -0.166229248046875 +68011 -0.324310302734375 +68012 -0.101409912109375 +68013 -0.20147705078125 +68014 -0.01910400390625 +68015 -0.044647216796875 +68016 0.0587158203125 +68017 0.103973388671875 +68018 0.11016845703125 +68019 0.202392578125 +68020 0.1424560546875 +68021 0.264495849609375 +68022 0.180877685546875 +68023 0.338897705078125 +68024 0.23492431640625 +68025 0.443817138671875 +68026 0.286865234375 +68027 0.545074462890625 +68028 0.32354736328125 +68029 0.6173095703125 +68030 0.3408203125 +68031 0.6524658203125 +68032 0.345428466796875 +68033 0.66339111328125 +68034 0.340576171875 +68035 0.6561279296875 +68036 0.31390380859375 +68037 0.606781005859375 +68038 0.25811767578125 +68039 0.501190185546875 +68040 0.18023681640625 +68041 0.352783203125 +68042 0.08807373046875 +68043 0.176544189453125 +68044 -0.0220947265625 +68045 -0.034820556640625 +68046 -0.138275146484375 +68047 -0.258209228515625 +68048 -0.233856201171875 +68049 -0.44244384765625 +68050 -0.302490234375 +68051 -0.5753173828125 +68052 -0.34173583984375 +68053 -0.65203857421875 +68054 -0.335540771484375 +68055 -0.641632080078125 +68056 -0.2933349609375 +68057 -0.562164306640625 +68058 -0.23828125 +68059 -0.458038330078125 +68060 -0.181488037109375 +68061 -0.350555419921875 +68062 -0.133819580078125 +68063 -0.260528564453125 +68064 -0.097503662109375 +68065 -0.192108154296875 +68066 -0.070831298828125 +68067 -0.141937255859375 +68068 -0.04974365234375 +68069 -0.1021728515625 +68070 -0.029083251953125 +68071 -0.062896728515625 +68072 -0.002532958984375 +68073 -0.011932373046875 +68074 0.03619384765625 +68075 0.062835693359375 +68076 0.080535888671875 +68077 0.148712158203125 +68078 0.12841796875 +68079 0.241729736328125 +68080 0.18365478515625 +68081 0.34912109375 +68082 0.239227294921875 +68083 0.457305908203125 +68084 0.28350830078125 +68085 0.54388427734375 +68086 0.297821044921875 +68087 0.5728759765625 +68088 0.262603759765625 +68089 0.506591796875 +68090 0.18115234375 +68091 0.351226806640625 +68092 0.074127197265625 +68093 0.146514892578125 +68094 -0.031219482421875 +68095 -0.05523681640625 +68096 -0.114898681640625 +68097 -0.21624755859375 +68098 -0.17626953125 +68099 -0.334930419921875 +68100 -0.211883544921875 +68101 -0.402984619140625 +68102 -0.231842041015625 +68103 -0.4412841796875 +68104 -0.258575439453125 +68105 -0.49578857421875 +68106 -0.2890625 +68107 -0.5601806640625 +68108 -0.306976318359375 +68109 -0.600738525390625 +68110 -0.296234130859375 +68111 -0.584228515625 +68112 -0.24176025390625 +68113 -0.47930908203125 +68114 -0.14056396484375 +68115 -0.27935791015625 +68116 -0.00482177734375 +68117 -0.0089111328125 +68118 0.134368896484375 +68119 0.268798828125 +68120 0.2421875 +68121 0.482818603515625 +68122 0.304107666015625 +68123 0.60369873046875 +68124 0.3292236328125 +68125 0.650421142578125 +68126 0.337432861328125 +68127 0.66400146484375 +68128 0.32720947265625 +68129 0.6414794921875 +68130 0.293548583984375 +68131 0.572540283203125 +68132 0.256439208984375 +68133 0.498138427734375 +68134 0.226287841796875 +68135 0.439453125 +68136 0.192962646484375 +68137 0.375518798828125 +68138 0.14105224609375 +68139 0.274505615234375 +68140 0.0572509765625 +68141 0.1087646484375 +68142 -0.047393798828125 +68143 -0.099395751953125 +68144 -0.157196044921875 +68145 -0.3182373046875 +68146 -0.2725830078125 +68147 -0.5489501953125 +68148 -0.384735107421875 +68149 -0.7738037109375 +68150 -0.46771240234375 +68151 -0.86383056640625 +68152 -0.50518798828125 +68153 -0.870391845703125 +68154 -0.5057373046875 +68155 -0.86895751953125 +68156 -0.47576904296875 +68157 -0.861053466796875 +68158 -0.406829833984375 +68159 -0.765869140625 +68160 -0.293487548828125 +68161 -0.5301513671875 +68162 -0.1392822265625 +68163 -0.214691162109375 +68164 0.034637451171875 +68165 0.137359619140625 +68166 0.203125 +68167 0.474822998046875 +68168 0.34869384765625 +68169 0.76239013671875 +68170 0.458038330078125 +68171 0.867462158203125 +68172 0.53125 +68173 0.870361328125 +68174 0.56256103515625 +68175 0.86480712890625 +68176 0.554473876953125 +68177 0.831817626953125 +68178 0.518798828125 +68179 0.677581787109375 +68180 0.458343505859375 +68181 0.495880126953125 +68182 0.382110595703125 +68183 0.30767822265625 +68184 0.29119873046875 +68185 0.116180419921875 +68186 0.170135498046875 +68187 -0.110748291015625 +68188 0.015594482421875 +68189 -0.381805419921875 +68190 -0.15142822265625 +68191 -0.6572265625 +68192 -0.301605224609375 +68193 -0.857421875 +68194 -0.41387939453125 +68195 -0.870391845703125 +68196 -0.484649658203125 +68197 -0.870391845703125 +68198 -0.526947021484375 +68199 -0.86444091796875 +68200 -0.55804443359375 +68201 -0.85723876953125 +68202 -0.568878173828125 +68203 -0.790008544921875 +68204 -0.532928466796875 +68205 -0.62847900390625 +68206 -0.448577880859375 +68207 -0.3956298828125 +68208 -0.33184814453125 +68209 -0.126708984375 +68210 -0.19610595703125 +68211 0.150115966796875 +68212 -0.047088623046875 +68213 0.424041748046875 +68214 0.10198974609375 +68215 0.670623779296875 +68216 0.232147216796875 +68217 0.854522705078125 +68218 0.33465576171875 +68219 0.866485595703125 +68220 0.401947021484375 +68221 0.86920166015625 +68222 0.4427490234375 +68223 0.8653564453125 +68224 0.463531494140625 +68225 0.857147216796875 +68226 0.4627685546875 +68227 0.766845703125 +68228 0.442901611328125 +68229 0.628509521484375 +68230 0.400543212890625 +68231 0.462127685546875 +68232 0.348236083984375 +68233 0.297210693359375 +68234 0.2919921875 +68235 0.14862060546875 +68236 0.220672607421875 +68237 -0.00537109375 +68238 0.137939453125 +68239 -0.15753173828125 +68240 0.042083740234375 +68241 -0.31304931640625 +68242 -0.07366943359375 +68243 -0.48876953125 +68244 -0.18634033203125 +68245 -0.6416015625 +68246 -0.2838134765625 +68247 -0.751373291015625 +68248 -0.377227783203125 +68249 -0.84619140625 +68250 -0.459320068359375 +68251 -0.861297607421875 +68252 -0.513824462890625 +68253 -0.863250732421875 +68254 -0.525238037109375 +68255 -0.856597900390625 +68256 -0.499420166015625 +68257 -0.7498779296875 +68258 -0.464569091796875 +68259 -0.624542236328125 +68260 -0.409942626953125 +68261 -0.47808837890625 +68262 -0.3070068359375 +68263 -0.253387451171875 +68264 -0.17803955078125 +68265 0.003692626953125 +68266 -0.05645751953125 +68267 0.2257080078125 +68268 0.06378173828125 +68269 0.427154541015625 +68270 0.19842529296875 +68271 0.643218994140625 +68272 0.3426513671875 +68273 0.855926513671875 +68274 0.46807861328125 +68275 0.870361328125 +68276 0.5504150390625 +68277 0.870361328125 +68278 0.593048095703125 +68279 0.862762451171875 +68280 0.594512939453125 +68281 0.79669189453125 +68282 0.55010986328125 +68283 0.595794677734375 +68284 0.474029541015625 +68285 0.362152099609375 +68286 0.379974365234375 +68287 0.1270751953125 +68288 0.27825927734375 +68289 -0.086944580078125 +68290 0.169952392578125 +68291 -0.2784423828125 +68292 0.03814697265625 +68293 -0.484832763671875 +68294 -0.12646484375 +68295 -0.729583740234375 +68296 -0.299102783203125 +68297 -0.86688232421875 +68298 -0.44873046875 +68299 -0.870391845703125 +68300 -0.572845458984375 +68301 -0.86859130859375 +68302 -0.6702880859375 +68303 -0.86279296875 +68304 -0.723419189453125 +68305 -0.817962646484375 +68306 -0.7099609375 +68307 -0.6116943359375 +68308 -0.62640380859375 +68309 -0.3128662109375 +68310 -0.4891357421875 +68311 0.039398193359375 +68312 -0.30792236328125 +68313 0.422821044921875 +68314 -0.099029541015625 +68315 0.805145263671875 +68316 0.104217529296875 +68317 0.870361328125 +68318 0.273895263671875 +68319 0.870361328125 +68320 0.404144287109375 +68321 0.860015869140625 +68322 0.49102783203125 +68323 0.727935791015625 +68324 0.5316162109375 +68325 0.48114013671875 +68326 0.53753662109375 +68327 0.2059326171875 +68328 0.519622802734375 +68329 -0.06103515625 +68330 0.48260498046875 +68331 -0.29913330078125 +68332 0.4193115234375 +68333 -0.516204833984375 +68334 0.3221435546875 +68335 -0.7252197265625 +68336 0.2032470703125 +68337 -0.85980224609375 +68338 0.079437255859375 +68339 -0.870391845703125 +68340 -0.03466796875 +68341 -0.870391845703125 +68342 -0.115081787109375 +68343 -0.858062744140625 +68344 -0.159515380859375 +68345 -0.673004150390625 +68346 -0.193267822265625 +68347 -0.42694091796875 +68348 -0.2376708984375 +68349 -0.2100830078125 +68350 -0.2913818359375 +68351 -0.0362548828125 +68352 -0.339599609375 +68353 0.10943603515625 +68354 -0.372161865234375 +68355 0.23516845703125 +68356 -0.369873046875 +68357 0.373687744140625 +68358 -0.3336181640625 +68359 0.517791748046875 +68360 -0.292236328125 +68361 0.602783203125 +68362 -0.243621826171875 +68363 0.635711669921875 +68364 -0.172943115234375 +68365 0.655181884765625 +68366 -0.085205078125 +68367 0.65948486328125 +68368 0.015380859375 +68369 0.651275634765625 +68370 0.117095947265625 +68371 0.61846923828125 +68372 0.202484130859375 +68373 0.53753662109375 +68374 0.262725830078125 +68375 0.404144287109375 +68376 0.292877197265625 +68377 0.22186279296875 +68378 0.2930908203125 +68379 0.003997802734375 +68380 0.27130126953125 +68381 -0.22100830078125 +68382 0.2366943359375 +68383 -0.42449951171875 +68384 0.19891357421875 +68385 -0.579833984375 +68386 0.177459716796875 +68387 -0.641876220703125 +68388 0.16943359375 +68389 -0.6177978515625 +68390 0.1456298828125 +68391 -0.575531005859375 +68392 0.103973388671875 +68393 -0.526336669921875 +68394 0.068511962890625 +68395 -0.42645263671875 +68396 0.05218505859375 +68397 -0.2581787109375 +68398 0.0389404296875 +68399 -0.068695068359375 +68400 0.011688232421875 +68401 0.09222412109375 +68402 -0.020538330078125 +68403 0.232147216796875 +68404 -0.052703857421875 +68405 0.3509521484375 +68406 -0.097991943359375 +68407 0.410064697265625 +68408 -0.16949462890625 +68409 0.372955322265625 +68410 -0.257537841796875 +68411 0.2554931640625 +68412 -0.3382568359375 +68413 0.10711669921875 +68414 -0.402801513671875 +68415 -0.052886962890625 +68416 -0.434783935546875 +68417 -0.186279296875 +68418 -0.408935546875 +68419 -0.23291015625 +68420 -0.335968017578125 +68421 -0.209442138671875 +68422 -0.24627685546875 +68423 -0.174163818359375 +68424 -0.14404296875 +68425 -0.126739501953125 +68426 -0.02520751953125 +68427 -0.048126220703125 +68428 0.096954345703125 +68429 0.0426025390625 +68430 0.200775146484375 +68431 0.10748291015625 +68432 0.279876708984375 +68433 0.1409912109375 +68434 0.355682373046875 +68435 0.19708251953125 +68436 0.424896240234375 +68437 0.273651123046875 +68438 0.461944580078125 +68439 0.31768798828125 +68440 0.4718017578125 +68441 0.341094970703125 +68442 0.466033935546875 +68443 0.368011474609375 +68444 0.434326171875 +68445 0.37249755859375 +68446 0.354400634765625 +68447 0.30072021484375 +68448 0.228759765625 +68449 0.1517333984375 +68450 0.08807373046875 +68451 -0.01470947265625 +68452 -0.059173583984375 +68453 -0.1883544921875 +68454 -0.210784912109375 +68455 -0.372711181640625 +68456 -0.33856201171875 +68457 -0.51397705078125 +68458 -0.420745849609375 +68459 -0.57177734375 +68460 -0.451507568359375 +68461 -0.53948974609375 +68462 -0.436859130859375 +68463 -0.43511962890625 +68464 -0.392547607421875 +68465 -0.2962646484375 +68466 -0.3353271484375 +68467 -0.161102294921875 +68468 -0.271697998046875 +68469 -0.0435791015625 +68470 -0.200775146484375 +68471 0.060394287109375 +68472 -0.130706787109375 +68473 0.13665771484375 +68474 -0.070587158203125 +68475 0.170135498046875 +68476 -0.021026611328125 +68477 0.16552734375 +68478 0.0306396484375 +68479 0.15728759765625 +68480 0.083740234375 +68481 0.150787353515625 +68482 0.124237060546875 +68483 0.12200927734375 +68484 0.153472900390625 +68485 0.080108642578125 +68486 0.180908203125 +68487 0.05126953125 +68488 0.217071533203125 +68489 0.062896728515625 +68490 0.2503662109375 +68491 0.09271240234375 +68492 0.25830078125 +68493 0.092987060546875 +68494 0.247528076171875 +68495 0.07855224609375 +68496 0.22540283203125 +68497 0.06427001953125 +68498 0.18609619140625 +68499 0.0347900390625 +68500 0.130462646484375 +68501 -0.01171875 +68502 0.06939697265625 +68503 -0.056060791015625 +68504 0.0247802734375 +68505 -0.055511474609375 +68506 -0.000946044921875 +68507 -0.010467529296875 +68508 -0.02984619140625 +68509 0.02508544921875 +68510 -0.071136474609375 +68511 0.025665283203125 +68512 -0.110748291015625 +68513 0.017333984375 +68514 -0.14605712890625 +68515 0.00189208984375 +68516 -0.180816650390625 +68517 -0.03173828125 +68518 -0.208770751953125 +68519 -0.071502685546875 +68520 -0.237823486328125 +68521 -0.13543701171875 +68522 -0.26666259765625 +68523 -0.219970703125 +68524 -0.28485107421875 +68525 -0.300506591796875 +68526 -0.2933349609375 +68527 -0.376312255859375 +68528 -0.27947998046875 +68529 -0.416107177734375 +68530 -0.22296142578125 +68531 -0.371124267578125 +68532 -0.126312255859375 +68533 -0.242279052734375 +68534 -0.00994873046875 +68535 -0.069732666015625 +68536 0.114532470703125 +68537 0.125640869140625 +68538 0.231048583984375 +68539 0.31268310546875 +68540 0.321441650390625 +68541 0.45501708984375 +68542 0.385498046875 +68543 0.554779052734375 +68544 0.421783447265625 +68545 0.61065673828125 +68546 0.424591064453125 +68547 0.610931396484375 +68548 0.383026123046875 +68549 0.531463623046875 +68550 0.304901123046875 +68551 0.3883056640625 +68552 0.21539306640625 +68553 0.23468017578125 +68554 0.127044677734375 +68555 0.095245361328125 +68556 0.053192138671875 +68557 -0.00396728515625 +68558 0.002044677734375 +68559 -0.04852294921875 +68560 -0.0322265625 +68561 -0.055145263671875 +68562 -0.071624755859375 +68563 -0.0758056640625 +68564 -0.12738037109375 +68565 -0.138702392578125 +68566 -0.18231201171875 +68567 -0.209197998046875 +68568 -0.236083984375 +68569 -0.289031982421875 +68570 -0.2882080078125 +68571 -0.37884521484375 +68572 -0.328094482421875 +68573 -0.456329345703125 +68574 -0.353363037109375 +68575 -0.51641845703125 +68576 -0.346160888671875 +68577 -0.519287109375 +68578 -0.3040771484375 +68579 -0.458251953125 +68580 -0.251556396484375 +68581 -0.384796142578125 +68582 -0.2010498046875 +68583 -0.323699951171875 +68584 -0.15130615234375 +68585 -0.269287109375 +68586 -0.091705322265625 +68587 -0.1951904296875 +68588 -0.0230712890625 +68589 -0.100006103515625 +68590 0.040985107421875 +68591 -0.01055908203125 +68592 0.113037109375 +68593 0.1033935546875 +68594 0.195404052734375 +68595 0.24908447265625 +68596 0.26300048828125 +68597 0.373199462890625 +68598 0.30731201171875 +68599 0.45806884765625 +68600 0.33172607421875 +68601 0.511474609375 +68602 0.35101318359375 +68603 0.565399169921875 +68604 0.36175537109375 +68605 0.61138916015625 +68606 0.33740234375 +68607 0.5897216796875 +68608 0.274505615234375 +68609 0.4906005859375 +68610 0.182220458984375 +68611 0.33148193359375 +68612 0.077728271484375 +68613 0.147796630859375 +68614 -0.01898193359375 +68615 -0.01873779296875 +68616 -0.094207763671875 +68617 -0.140289306640625 +68618 -0.135711669921875 +68619 -0.191986083984375 +68620 -0.14727783203125 +68621 -0.184295654296875 +68622 -0.14825439453125 +68623 -0.161834716796875 +68624 -0.157012939453125 +68625 -0.166595458984375 +68626 -0.1712646484375 +68627 -0.19390869140625 +68628 -0.182281494140625 +68629 -0.22442626953125 +68630 -0.200103759765625 +68631 -0.279754638671875 +68632 -0.2158203125 +68633 -0.3389892578125 +68634 -0.20867919921875 +68635 -0.3543701171875 +68636 -0.189544677734375 +68637 -0.348175048828125 +68638 -0.161865234375 +68639 -0.32598876953125 +68640 -0.11334228515625 +68641 -0.2581787109375 +68642 -0.042755126953125 +68643 -0.139801025390625 +68644 0.042449951171875 +68645 0.014617919921875 +68646 0.1141357421875 +68647 0.144378662109375 +68648 0.158843994140625 +68649 0.221038818359375 +68650 0.1878662109375 +68651 0.27069091796875 +68652 0.201263427734375 +68653 0.294036865234375 +68654 0.208282470703125 +68655 0.311767578125 +68656 0.215911865234375 +68657 0.339141845703125 +68658 0.217010498046875 +68659 0.360260009765625 +68660 0.205657958984375 +68661 0.360504150390625 +68662 0.1693115234375 +68663 0.308380126953125 +68664 0.099517822265625 +68665 0.18170166015625 +68666 0.007598876953125 +68667 0.0047607421875 +68668 -0.085601806640625 +68669 -0.17559814453125 +68670 -0.160064697265625 +68671 -0.3143310546875 +68672 -0.19647216796875 +68673 -0.36785888671875 +68674 -0.20526123046875 +68675 -0.36248779296875 +68676 -0.205108642578125 +68677 -0.343536376953125 +68678 -0.19183349609375 +68679 -0.3018798828125 +68680 -0.16265869140625 +68681 -0.231414794921875 +68682 -0.11151123046875 +68683 -0.117645263671875 +68684 -0.05242919921875 +68685 0.007049560546875 +68686 -0.009002685546875 +68687 0.087982177734375 +68688 0.024200439453125 +68689 0.13946533203125 +68690 0.051910400390625 +68691 0.17425537109375 +68692 0.07159423828125 +68693 0.188201904296875 +68694 0.078216552734375 +68695 0.171234130859375 +68696 0.0689697265625 +68697 0.118438720703125 +68698 0.054718017578125 +68699 0.05706787109375 +68700 0.035736083984375 +68701 -0.010711669921875 +68702 0.008758544921875 +68703 -0.0914306640625 +68704 -0.016815185546875 +68705 -0.162322998046875 +68706 -0.028961181640625 +68707 -0.194549560546875 +68708 -0.011199951171875 +68709 -0.1492919921875 +68710 0.038665771484375 +68711 -0.02166748046875 +68712 0.093719482421875 +68713 0.124053955078125 +68714 0.121856689453125 +68715 0.211151123046875 +68716 0.12396240234375 +68717 0.240447998046875 +68718 0.11346435546875 +68719 0.242218017578125 +68720 0.094970703125 +68721 0.2257080078125 +68722 0.070556640625 +68723 0.194366455078125 +68724 0.026947021484375 +68725 0.115509033203125 +68726 -0.02520751953125 +68727 0.0128173828125 +68728 -0.06011962890625 +68729 -0.053802490234375 +68730 -0.088623046875 +68731 -0.110626220703125 +68732 -0.1282958984375 +68733 -0.199493408203125 +68734 -0.1680908203125 +68735 -0.29437255859375 +68736 -0.18133544921875 +68737 -0.33221435546875 +68738 -0.154144287109375 +68739 -0.27972412109375 +68740 -0.10736083984375 +68741 -0.185333251953125 +68742 -0.074981689453125 +68743 -0.128204345703125 +68744 -0.06060791015625 +68745 -0.115692138671875 +68746 -0.051483154296875 +68747 -0.116455078125 +68748 -0.0377197265625 +68749 -0.105926513671875 +68750 -0.007049560546875 +68751 -0.053955078125 +68752 0.044036865234375 +68753 0.048797607421875 +68754 0.0960693359375 +68755 0.157318115234375 +68756 0.123504638671875 +68757 0.212005615234375 +68758 0.1285400390625 +68759 0.218475341796875 +68760 0.13677978515625 +68761 0.23724365234375 +68762 0.163970947265625 +68763 0.30535888671875 +68764 0.192626953125 +68765 0.38128662109375 +68766 0.197296142578125 +68767 0.404449462890625 +68768 0.186614990234375 +68769 0.3944091796875 +68770 0.176849365234375 +68771 0.3885498046875 +68772 0.15814208984375 +68773 0.362640380859375 +68774 0.1126708984375 +68775 0.27362060546875 +68776 0.03900146484375 +68777 0.11712646484375 +68778 -0.040435791015625 +68779 -0.054901123046875 +68780 -0.103424072265625 +68781 -0.19085693359375 +68782 -0.1475830078125 +68783 -0.28570556640625 +68784 -0.17266845703125 +68785 -0.339263916015625 +68786 -0.189605712890625 +68787 -0.3775634765625 +68788 -0.217559814453125 +68789 -0.445709228515625 +68790 -0.252960205078125 +68791 -0.535064697265625 +68792 -0.2889404296875 +68793 -0.629058837890625 +68794 -0.31298828125 +68795 -0.697601318359375 +68796 -0.309814453125 +68797 -0.70391845703125 +68798 -0.27740478515625 +68799 -0.6424560546875 +68800 -0.20684814453125 +68801 -0.491241455078125 +68802 -0.10504150390625 +68803 -0.265716552734375 +68804 0.003143310546875 +68805 -0.023712158203125 +68806 0.103424072265625 +68807 0.201751708984375 +68808 0.1807861328125 +68809 0.375823974609375 +68810 0.2293701171875 +68811 0.485076904296875 +68812 0.26580810546875 +68813 0.56884765625 +68814 0.293304443359375 +68815 0.634765625 +68816 0.292755126953125 +68817 0.63763427734375 +68818 0.259490966796875 +68819 0.5660400390625 +68820 0.215728759765625 +68821 0.4720458984375 +68822 0.183441162109375 +68823 0.40692138671875 +68824 0.16595458984375 +68825 0.3778076171875 +68826 0.1602783203125 +68827 0.376953125 +68828 0.15301513671875 +68829 0.371978759765625 +68830 0.123321533203125 +68831 0.313140869140625 +68832 0.06463623046875 +68833 0.184417724609375 +68834 -0.01202392578125 +68835 0.011199951171875 +68836 -0.09149169921875 +68837 -0.171051025390625 +68838 -0.1630859375 +68839 -0.33740234375 +68840 -0.220062255859375 +68841 -0.47198486328125 +68842 -0.25634765625 +68843 -0.560394287109375 +68844 -0.2626953125 +68845 -0.58056640625 +68846 -0.245635986328125 +68847 -0.54754638671875 +68848 -0.22540283203125 +68849 -0.508575439453125 +68850 -0.200469970703125 +68851 -0.459503173828125 +68852 -0.16851806640625 +68853 -0.394378662109375 +68854 -0.146514892578125 +68855 -0.35260009765625 +68856 -0.1251220703125 +68857 -0.31170654296875 +68858 -0.073089599609375 +68859 -0.197418212890625 +68860 0.010101318359375 +68861 -0.007965087890625 +68862 0.103485107421875 +68863 0.207489013671875 +68864 0.1900634765625 +68865 0.409210205078125 +68866 0.25860595703125 +68867 0.57208251953125 +68868 0.296783447265625 +68869 0.66595458984375 +68870 0.29248046875 +68871 0.65875244140625 +68872 0.252838134765625 +68873 0.56744384765625 +68874 0.19378662109375 +68875 0.431396484375 +68876 0.133087158203125 +68877 0.29443359375 +68878 0.081451416015625 +68879 0.182464599609375 +68880 0.02691650390625 +68881 0.06365966796875 +68882 -0.035491943359375 +68883 -0.075958251953125 +68884 -0.086944580078125 +68885 -0.189422607421875 +68886 -0.12518310546875 +68887 -0.271942138671875 +68888 -0.157379150390625 +68889 -0.342529296875 +68890 -0.168853759765625 +68891 -0.364166259765625 +68892 -0.15576171875 +68893 -0.327239990234375 +68894 -0.135833740234375 +68895 -0.2769775390625 +68896 -0.12493896484375 +68897 -0.253692626953125 +68898 -0.117828369140625 +68899 -0.24365234375 +68900 -0.095733642578125 +68901 -0.1983642578125 +68902 -0.058319091796875 +68903 -0.116241455078125 +68904 -0.021392822265625 +68905 -0.036834716796875 +68906 0.012725830078125 +68907 0.034881591796875 +68908 0.040679931640625 +68909 0.09124755859375 +68910 0.053009033203125 +68911 0.10888671875 +68912 0.064239501953125 +68913 0.125518798828125 +68914 0.080596923828125 +68915 0.15771484375 +68916 0.09124755859375 +68917 0.17828369140625 +68918 0.089752197265625 +68919 0.17108154296875 +68920 0.07366943359375 +68921 0.129974365234375 +68922 0.0538330078125 +68923 0.082427978515625 +68924 0.030029296875 +68925 0.027679443359375 +68926 -0.00982666015625 +68927 -0.065643310546875 +68928 -0.050567626953125 +68929 -0.15936279296875 +68930 -0.076141357421875 +68931 -0.21307373046875 +68932 -0.089385986328125 +68933 -0.234649658203125 +68934 -0.080657958984375 +68935 -0.2001953125 +68936 -0.05340576171875 +68937 -0.119171142578125 +68938 -0.020416259765625 +68939 -0.024749755859375 +68940 0.01959228515625 +68941 0.085784912109375 +68942 0.053314208984375 +68943 0.178131103515625 +68944 0.06646728515625 +68945 0.215576171875 +68946 0.064361572265625 +68947 0.211456298828125 +68948 0.05072021484375 +68949 0.17523193359375 +68950 0.034027099609375 +68951 0.128753662109375 +68952 0.025909423828125 +68953 0.1019287109375 +68954 0.018218994140625 +68955 0.0743408203125 +68956 0.009674072265625 +68957 0.04327392578125 +68958 0.0115966796875 +68959 0.038177490234375 +68960 0.030517578125 +68961 0.076263427734375 +68962 0.05975341796875 +68963 0.14105224609375 +68964 0.081024169921875 +68965 0.186431884765625 +68966 0.08489990234375 +68967 0.188812255859375 +68968 0.067657470703125 +68969 0.1390380859375 +68970 0.031036376953125 +68971 0.041778564453125 +68972 -0.01580810546875 +68973 -0.079437255859375 +68974 -0.070831298828125 +68975 -0.219390869140625 +68976 -0.129974365234375 +68977 -0.367828369140625 +68978 -0.18145751953125 +68979 -0.494873046875 +68980 -0.207794189453125 +68981 -0.556243896484375 +68982 -0.19189453125 +68983 -0.508697509765625 +68984 -0.14276123046875 +68985 -0.3756103515625 +68986 -0.08453369140625 +68987 -0.218902587890625 +68988 -0.026885986328125 +68989 -0.063751220703125 +68990 0.030975341796875 +68991 0.091552734375 +68992 0.084930419921875 +68993 0.23602294921875 +68994 0.124664306640625 +68995 0.342987060546875 +68996 0.143524169921875 +68997 0.39520263671875 +68998 0.14031982421875 +68999 0.389373779296875 +69000 0.11456298828125 +69001 0.324249267578125 +69002 0.075775146484375 +69003 0.224090576171875 +69004 0.03778076171875 +69005 0.124267578125 +69006 0.005279541015625 +69007 0.037078857421875 +69008 -0.01104736328125 +69009 -0.010101318359375 +69010 -0.01220703125 +69011 -0.019439697265625 +69012 -0.01080322265625 +69013 -0.022796630859375 +69014 0.000244140625 +69015 -0.001556396484375 +69016 0.025482177734375 +69017 0.056304931640625 +69018 0.04754638671875 +69019 0.106719970703125 +69020 0.045623779296875 +69021 0.096893310546875 +69022 0.025848388671875 +69023 0.042694091796875 +69024 0.002960205078125 +69025 -0.018035888671875 +69026 -0.01934814453125 +69027 -0.07586669921875 +69028 -0.036651611328125 +69029 -0.11944580078125 +69030 -0.05322265625 +69031 -0.15972900390625 +69032 -0.0712890625 +69033 -0.202606201171875 +69034 -0.0909423828125 +69035 -0.24859619140625 +69036 -0.115020751953125 +69037 -0.30517578125 +69038 -0.139404296875 +69039 -0.36212158203125 +69040 -0.15301513671875 +69041 -0.39141845703125 +69042 -0.140899658203125 +69043 -0.35528564453125 +69044 -0.10150146484375 +69045 -0.249969482421875 +69046 -0.04156494140625 +69047 -0.092864990234375 +69048 0.0284423828125 +69049 0.08905029296875 +69050 0.0848388671875 +69051 0.2352294921875 +69052 0.11712646484375 +69053 0.318817138671875 +69054 0.1326904296875 +69055 0.358642578125 +69056 0.128814697265625 +69057 0.347747802734375 +69058 0.105255126953125 +69059 0.28564453125 +69060 0.081878662109375 +69061 0.223175048828125 +69062 0.072906494140625 +69063 0.196746826171875 +69064 0.06787109375 +69065 0.179840087890625 +69066 0.060028076171875 +69067 0.155548095703125 +69068 0.060028076171875 +69069 0.151214599609375 +69070 0.063873291015625 +69071 0.156951904296875 +69072 0.055419921875 +69073 0.13177490234375 +69074 0.044464111328125 +69075 0.100799560546875 +69076 0.03997802734375 +69077 0.087127685546875 +69078 0.027862548828125 +69079 0.05487060546875 +69080 0.00299072265625 +69081 -0.009002685546875 +69082 -0.034393310546875 +69083 -0.10400390625 +69084 -0.084014892578125 +69085 -0.229400634765625 +69086 -0.13421630859375 +69087 -0.35552978515625 +69088 -0.1690673828125 +69089 -0.441925048828125 +69090 -0.1827392578125 +69091 -0.473846435546875 +69092 -0.18048095703125 +69093 -0.464813232421875 +69094 -0.16387939453125 +69095 -0.419097900390625 +69096 -0.131927490234375 +69097 -0.334320068359375 +69098 -0.091400146484375 +69099 -0.227935791015625 +69100 -0.051483154296875 +69101 -0.12347412109375 +69102 -0.014739990234375 +69103 -0.02764892578125 +69104 0.025970458984375 +69105 0.077667236328125 +69106 0.078826904296875 +69107 0.2132568359375 +69108 0.14764404296875 +69109 0.38885498046875 +69110 0.223907470703125 +69111 0.582794189453125 +69112 0.283660888671875 +69113 0.734039306640625 +69114 0.31024169921875 +69115 0.800140380859375 +69116 0.302520751953125 +69117 0.7783203125 +69118 0.25909423828125 +69119 0.6651611328125 +69120 0.180023193359375 +69121 0.45965576171875 +69122 0.080474853515625 +69123 0.199188232421875 +69124 -0.01483154296875 +69125 -0.050689697265625 +69126 -0.085296630859375 +69127 -0.23297119140625 +69128 -0.12451171875 +69129 -0.33013916015625 +69130 -0.141845703125 +69131 -0.368408203125 +69132 -0.1484375 +69133 -0.378936767578125 +69134 -0.149749755859375 +69135 -0.376983642578125 +69136 -0.15191650390625 +69137 -0.37969970703125 +69138 -0.156494140625 +69139 -0.391510009765625 +69140 -0.153778076171875 +69141 -0.385345458984375 +69142 -0.136871337890625 +69143 -0.3419189453125 +69144 -0.113677978515625 +69145 -0.28289794921875 +69146 -0.09991455078125 +69147 -0.251617431640625 +69148 -0.10223388671875 +69149 -0.266143798828125 +69150 -0.1016845703125 +69151 -0.273345947265625 +69152 -0.078094482421875 +69153 -0.216796875 +69154 -0.043060302734375 +69155 -0.128265380859375 +69156 -0.01849365234375 +69157 -0.068145751953125 +69158 -0.006927490234375 +69159 -0.0430908203125 +69160 0.00177001953125 +69161 -0.024444580078125 +69162 0.0194091796875 +69163 0.020721435546875 +69164 0.05743408203125 +69165 0.124481201171875 +69166 0.10540771484375 +69167 0.25787353515625 +69168 0.1483154296875 +69169 0.379119873046875 +69170 0.1832275390625 +69171 0.47991943359375 +69172 0.198699951171875 +69173 0.5281982421875 +69174 0.19024658203125 +69175 0.511138916015625 +69176 0.16790771484375 +69177 0.456207275390625 +69178 0.147674560546875 +69179 0.407470703125 +69180 0.136474609375 +69181 0.383758544921875 +69182 0.124298095703125 +69183 0.35687255859375 +69184 0.105865478515625 +69185 0.31182861328125 +69186 0.08209228515625 +69187 0.250885009765625 +69188 0.04998779296875 +69189 0.1654052734375 +69190 0.002349853515625 +69191 0.035247802734375 +69192 -0.0616455078125 +69193 -0.142059326171875 +69194 -0.130889892578125 +69195 -0.33563232421875 +69196 -0.201507568359375 +69197 -0.5345458984375 +69198 -0.2674560546875 +69199 -0.72186279296875 +69200 -0.306915283203125 +69201 -0.836669921875 +69202 -0.30328369140625 +69203 -0.8326416015625 +69204 -0.26385498046875 +69205 -0.7296142578125 +69206 -0.20855712890625 +69207 -0.582550048828125 +69208 -0.155059814453125 +69209 -0.440093994140625 +69210 -0.111419677734375 +69211 -0.324310302734375 +69212 -0.0655517578125 +69213 -0.20147705078125 +69214 -0.007843017578125 +69215 -0.044647216796875 +69216 0.04644775390625 +69217 0.103973388671875 +69218 0.0821533203125 +69219 0.202392578125 +69220 0.104248046875 +69221 0.264495849609375 +69222 0.130279541015625 +69223 0.338897705078125 +69224 0.1668701171875 +69225 0.443817138671875 +69226 0.201812744140625 +69227 0.545074462890625 +69228 0.226043701171875 +69229 0.6173095703125 +69230 0.236785888671875 +69231 0.6524658203125 +69232 0.23876953125 +69233 0.66339111328125 +69234 0.234283447265625 +69235 0.6561279296875 +69236 0.21478271484375 +69237 0.606781005859375 +69238 0.175262451171875 +69239 0.501190185546875 +69240 0.120635986328125 +69241 0.352783203125 +69242 0.056365966796875 +69243 0.176544189453125 +69244 -0.020111083984375 +69245 -0.034820556640625 +69246 -0.1004638671875 +69247 -0.258209228515625 +69248 -0.166290283203125 +69249 -0.44244384765625 +69250 -0.21319580078125 +69251 -0.5753173828125 +69252 -0.23956298828125 +69253 -0.65203857421875 +69254 -0.23431396484375 +69255 -0.641632080078125 +69256 -0.204071044921875 +69257 -0.562164306640625 +69258 -0.164886474609375 +69259 -0.458038330078125 +69260 -0.12451171875 +69261 -0.350555419921875 +69262 -0.090545654296875 +69263 -0.260528564453125 +69264 -0.064544677734375 +69265 -0.192108154296875 +69266 -0.045379638671875 +69267 -0.141937255859375 +69268 -0.0302734375 +69269 -0.1021728515625 +69270 -0.015716552734375 +69271 -0.062896728515625 +69272 0.002655029296875 +69273 -0.011932373046875 +69274 0.02923583984375 +69275 0.062835693359375 +69276 0.059478759765625 +69277 0.148712158203125 +69278 0.09197998046875 +69279 0.241729736328125 +69280 0.12939453125 +69281 0.34912109375 +69282 0.16693115234375 +69283 0.457305908203125 +69284 0.19659423828125 +69285 0.54388427734375 +69286 0.205535888671875 +69287 0.5728759765625 +69288 0.180267333984375 +69289 0.506591796875 +69290 0.123077392578125 +69291 0.351226806640625 +69292 0.04833984375 +69293 0.146514892578125 +69294 -0.025054931640625 +69295 -0.05523681640625 +69296 -0.08343505859375 +69297 -0.21624755859375 +69298 -0.126251220703125 +69299 -0.334930419921875 +69300 -0.150482177734375 +69301 -0.402984619140625 +69302 -0.163665771484375 +69303 -0.4412841796875 +69304 -0.182403564453125 +69305 -0.49578857421875 +69306 -0.2044677734375 +69307 -0.5601806640625 +69308 -0.217803955078125 +69309 -0.600738525390625 +69310 -0.210540771484375 +69311 -0.584228515625 +69312 -0.17144775390625 +69313 -0.47930908203125 +69314 -0.098236083984375 +69315 -0.27935791015625 +69316 0.00018310546875 +69317 -0.0089111328125 +69318 0.100982666015625 +69319 0.268798828125 +69320 0.1785888671875 +69321 0.482818603515625 +69322 0.222381591796875 +69323 0.60369873046875 +69324 0.239166259765625 +69325 0.650421142578125 +69326 0.243743896484375 +69327 0.66400146484375 +69328 0.235076904296875 +69329 0.6414794921875 +69330 0.20947265625 +69331 0.572540283203125 +69332 0.1817626953125 +69333 0.498138427734375 +69334 0.159637451171875 +69335 0.439453125 +69336 0.135589599609375 +69337 0.375518798828125 +69338 0.09820556640625 +69339 0.274505615234375 +69340 0.03759765625 +69341 0.1087646484375 +69342 -0.03814697265625 +69343 -0.099395751953125 +69344 -0.1175537109375 +69345 -0.3182373046875 +69346 -0.2010498046875 +69347 -0.5489501953125 +69348 -0.282196044921875 +69349 -0.7738037109375 +69350 -0.341949462890625 +69351 -0.86383056640625 +69352 -0.36834716796875 +69353 -0.870391845703125 +69354 -0.367767333984375 +69355 -0.86895751953125 +69356 -0.345001220703125 +69357 -0.861053466796875 +69358 -0.293853759765625 +69359 -0.765869140625 +69360 -0.210296630859375 +69361 -0.5301513671875 +69362 -0.096923828125 +69363 -0.214691162109375 +69364 0.03070068359375 +69365 0.137359619140625 +69366 0.154052734375 +69367 0.474822998046875 +69368 0.26031494140625 +69369 0.76239013671875 +69370 0.3397216796875 +69371 0.867462158203125 +69372 0.392425537109375 +69373 0.870361328125 +69374 0.414215087890625 +69375 0.86480712890625 +69376 0.4068603515625 +69377 0.831817626953125 +69378 0.3790283203125 +69379 0.677581787109375 +69380 0.332916259765625 +69381 0.495880126953125 +69382 0.27496337890625 +69383 0.30767822265625 +69384 0.206329345703125 +69385 0.116180419921875 +69386 0.1170654296875 +69387 -0.110748291015625 +69388 0.005401611328125 +69389 -0.381805419921875 +69390 -0.114105224609375 +69391 -0.6572265625 +69392 -0.22137451171875 +69393 -0.857421875 +69394 -0.301910400390625 +69395 -0.870391845703125 +69396 -0.35308837890625 +69397 -0.870391845703125 +69398 -0.383514404296875 +69399 -0.86444091796875 +69400 -0.40472412109375 +69401 -0.85723876953125 +69402 -0.41070556640625 +69403 -0.790008544921875 +69404 -0.38372802734375 +69405 -0.62847900390625 +69406 -0.322906494140625 +69407 -0.3956298828125 +69408 -0.2392578125 +69409 -0.126708984375 +69410 -0.14208984375 +69411 0.150115966796875 +69412 -0.035614013671875 +69413 0.424041748046875 +69414 0.0709228515625 +69415 0.670623779296875 +69416 0.1644287109375 +69417 0.854522705078125 +69418 0.238739013671875 +69419 0.866485595703125 +69420 0.288482666015625 +69421 0.86920166015625 +69422 0.319305419921875 +69423 0.8653564453125 +69424 0.33538818359375 +69425 0.857147216796875 +69426 0.33563232421875 +69427 0.766845703125 +69428 0.3216552734375 +69429 0.628509521484375 +69430 0.291259765625 +69431 0.462127685546875 +69432 0.2530517578125 +69433 0.297210693359375 +69434 0.21124267578125 +69435 0.14862060546875 +69436 0.158599853515625 +69437 -0.00537109375 +69438 0.097869873046875 +69439 -0.15753173828125 +69440 0.028167724609375 +69441 -0.31304931640625 +69442 -0.05474853515625 +69443 -0.48876953125 +69444 -0.135162353515625 +69445 -0.6416015625 +69446 -0.20465087890625 +69447 -0.751373291015625 +69448 -0.270538330078125 +69449 -0.84619140625 +69450 -0.3277587890625 +69451 -0.861297607421875 +69452 -0.365325927734375 +69453 -0.863250732421875 +69454 -0.372802734375 +69455 -0.856597900390625 +69456 -0.354156494140625 +69457 -0.7498779296875 +69458 -0.328460693359375 +69459 -0.624542236328125 +69460 -0.28863525390625 +69461 -0.47808837890625 +69462 -0.2156982421875 +69463 -0.253387451171875 +69464 -0.124847412109375 +69465 0.003692626953125 +69466 -0.038787841796875 +69467 0.2257080078125 +69468 0.046295166015625 +69469 0.427154541015625 +69470 0.1407470703125 +69471 0.643218994140625 +69472 0.241119384765625 +69473 0.855926513671875 +69474 0.328155517578125 +69475 0.870361328125 +69476 0.385406494140625 +69477 0.870361328125 +69478 0.415069580078125 +69479 0.862762451171875 +69480 0.4161376953125 +69481 0.79669189453125 +69482 0.385467529296875 +69483 0.595794677734375 +69484 0.332672119140625 +69485 0.362152099609375 +69486 0.26708984375 +69487 0.1270751953125 +69488 0.19580078125 +69489 -0.086944580078125 +69490 0.11968994140625 +69491 -0.2784423828125 +69492 0.027587890625 +69493 -0.484832763671875 +69494 -0.0865478515625 +69495 -0.729583740234375 +69496 -0.205902099609375 +69497 -0.86688232421875 +69498 -0.309417724609375 +69499 -0.870391845703125 +69500 -0.395263671875 +69501 -0.86859130859375 +69502 -0.4625244140625 +69503 -0.86279296875 +69504 -0.499298095703125 +69505 -0.817962646484375 +69506 -0.490570068359375 +69507 -0.6116943359375 +69508 -0.4339599609375 +69509 -0.3128662109375 +69510 -0.340545654296875 +69511 0.039398193359375 +69512 -0.21697998046875 +69513 0.422821044921875 +69514 -0.074310302734375 +69515 0.805145263671875 +69516 0.06494140625 +69517 0.870361328125 +69518 0.18182373046875 +69519 0.870361328125 +69520 0.27227783203125 +69521 0.860015869140625 +69522 0.33349609375 +69523 0.727935791015625 +69524 0.363311767578125 +69525 0.48114013671875 +69526 0.369415283203125 +69527 0.2059326171875 +69528 0.3590087890625 +69529 -0.06103515625 +69530 0.335174560546875 +69531 -0.29913330078125 +69532 0.29302978515625 +69533 -0.516204833984375 +69534 0.227508544921875 +69535 -0.7252197265625 +69536 0.14678955078125 +69537 -0.85980224609375 +69538 0.062255859375 +69539 -0.870391845703125 +69540 -0.01617431640625 +69541 -0.870391845703125 +69542 -0.072296142578125 +69543 -0.858062744140625 +69544 -0.10443115234375 +69545 -0.673004150390625 +69546 -0.1295166015625 +69547 -0.42694091796875 +69548 -0.161712646484375 +69549 -0.2100830078125 +69550 -0.199981689453125 +69551 -0.0362548828125 +69552 -0.234466552734375 +69553 0.10943603515625 +69554 -0.25836181640625 +69555 0.23516845703125 +69556 -0.25787353515625 +69557 0.373687744140625 +69558 -0.233489990234375 +69559 0.517791748046875 +69560 -0.205810546875 +69561 0.602783203125 +69562 -0.17315673828125 +69563 0.635711669921875 +69564 -0.12469482421875 +69565 0.655181884765625 +69566 -0.063873291015625 +69567 0.65948486328125 +69568 0.00640869140625 +69569 0.651275634765625 +69570 0.07781982421875 +69571 0.61846923828125 +69572 0.13787841796875 +69573 0.53753662109375 +69574 0.180328369140625 +69575 0.404144287109375 +69576 0.201629638671875 +69577 0.22186279296875 +69578 0.201934814453125 +69579 0.003997802734375 +69580 0.1868896484375 +69581 -0.22100830078125 +69582 0.1630859375 +69583 -0.42449951171875 +69584 0.137359619140625 +69585 -0.579833984375 +69586 0.123626708984375 +69587 -0.641876220703125 +69588 0.1197509765625 +69589 -0.6177978515625 +69590 0.104583740234375 +69591 -0.575531005859375 +69592 0.0765380859375 +69593 -0.526336669921875 +69594 0.05279541015625 +69595 -0.42645263671875 +69596 0.042572021484375 +69597 -0.2581787109375 +69598 0.03424072265625 +69599 -0.068695068359375 +69600 0.015472412109375 +69601 0.09222412109375 +69602 -0.00732421875 +69603 0.232147216796875 +69604 -0.030487060546875 +69605 0.3509521484375 +69606 -0.0634765625 +69607 0.410064697265625 +69608 -0.11566162109375 +69609 0.372955322265625 +69610 -0.180023193359375 +69611 0.2554931640625 +69612 -0.2393798828125 +69613 0.10711669921875 +69614 -0.2872314453125 +69615 -0.052886962890625 +69616 -0.311737060546875 +69617 -0.186279296875 +69618 -0.294647216796875 +69619 -0.23291015625 +69620 -0.24359130859375 +69621 -0.209442138671875 +69622 -0.180328369140625 +69623 -0.174163818359375 +69624 -0.10784912109375 +69625 -0.126739501953125 +69626 -0.023162841796875 +69627 -0.048126220703125 +69628 0.064178466796875 +69629 0.0426025390625 +69630 0.138671875 +69631 0.10748291015625 +69632 0.195220947265625 +69633 0.1409912109375 +69634 0.24847412109375 +69635 0.19708251953125 +69636 0.29681396484375 +69637 0.273651123046875 +69638 0.32318115234375 +69639 0.31768798828125 +69640 0.330718994140625 +69641 0.341094970703125 +69642 0.326934814453125 +69643 0.368011474609375 +69644 0.30499267578125 +69645 0.37249755859375 +69646 0.250335693359375 +69647 0.30072021484375 +69648 0.16473388671875 +69649 0.1517333984375 +69650 0.06854248046875 +69651 -0.01470947265625 +69652 -0.032470703125 +69653 -0.1883544921875 +69654 -0.136627197265625 +69655 -0.372711181640625 +69656 -0.225128173828125 +69657 -0.51397705078125 +69658 -0.28338623046875 +69659 -0.57177734375 +69660 -0.307342529296875 +69661 -0.53948974609375 +69662 -0.30078125 +69663 -0.43511962890625 +69664 -0.27386474609375 +69665 -0.2962646484375 +69666 -0.237548828125 +69667 -0.161102294921875 +69668 -0.196075439453125 +69669 -0.0435791015625 +69670 -0.148834228515625 +69671 0.060394287109375 +69672 -0.10125732421875 +69673 0.13665771484375 +69674 -0.0594482421875 +69675 0.170135498046875 +69676 -0.023895263671875 +69677 0.16552734375 +69678 0.013519287109375 +69679 0.15728759765625 +69680 0.052154541015625 +69681 0.150787353515625 +69682 0.082550048828125 +69683 0.12200927734375 +69684 0.105377197265625 +69685 0.080108642578125 +69686 0.126678466796875 +69687 0.05126953125 +69688 0.153228759765625 +69689 0.062896728515625 +69690 0.17724609375 +69691 0.09271240234375 +69692 0.183807373046875 +69693 0.092987060546875 +69694 0.177276611328125 +69695 0.07855224609375 +69696 0.1624755859375 +69697 0.06427001953125 +69698 0.135589599609375 +69699 0.0347900390625 +69700 0.0972900390625 +69701 -0.01171875 +69702 0.054840087890625 +69703 -0.056060791015625 +69704 0.022796630859375 +69705 -0.055511474609375 +69706 0.00286865234375 +69707 -0.010467529296875 +69708 -0.01922607421875 +69709 0.02508544921875 +69710 -0.04937744140625 +69711 0.025665283203125 +69712 -0.07818603515625 +69713 0.017333984375 +69714 -0.103790283203125 +69715 0.00189208984375 +69716 -0.1285400390625 +69717 -0.03173828125 +69718 -0.148223876953125 +69719 -0.071502685546875 +69720 -0.167999267578125 +69721 -0.13543701171875 +69722 -0.186981201171875 +69723 -0.219970703125 +69724 -0.19830322265625 +69725 -0.300506591796875 +69726 -0.20263671875 +69727 -0.376312255859375 +69728 -0.1917724609375 +69729 -0.416107177734375 +69730 -0.152435302734375 +69731 -0.371124267578125 +69732 -0.08642578125 +69733 -0.242279052734375 +69734 -0.007293701171875 +69735 -0.069732666015625 +69736 0.0771484375 +69737 0.125640869140625 +69738 0.15618896484375 +69739 0.31268310546875 +69740 0.217742919921875 +69741 0.45501708984375 +69742 0.26153564453125 +69743 0.554779052734375 +69744 0.286590576171875 +69745 0.61065673828125 +69746 0.2890625 +69747 0.610931396484375 +69748 0.261810302734375 +69749 0.531463623046875 +69750 0.209991455078125 +69751 0.3883056640625 +69752 0.15020751953125 +69753 0.23468017578125 +69754 0.09075927734375 +69755 0.095245361328125 +69756 0.040496826171875 +69757 -0.00396728515625 +69758 0.004913330078125 +69759 -0.04852294921875 +69760 -0.01971435546875 +69761 -0.055145263671875 +69762 -0.0477294921875 +69763 -0.0758056640625 +69764 -0.086395263671875 +69765 -0.138702392578125 +69766 -0.12432861328125 +69767 -0.209197998046875 +69768 -0.16119384765625 +69769 -0.289031982421875 +69770 -0.196624755859375 +69771 -0.37884521484375 +69772 -0.223541259765625 +69773 -0.456329345703125 +69774 -0.24041748046875 +69775 -0.51641845703125 +69776 -0.2354736328125 +69777 -0.519287109375 +69778 -0.2071533203125 +69779 -0.458251953125 +69780 -0.17156982421875 +69781 -0.384796142578125 +69782 -0.136993408203125 +69783 -0.323699951171875 +69784 -0.102691650390625 +69785 -0.269287109375 +69786 -0.061767578125 +69787 -0.1951904296875 +69788 -0.014862060546875 +69789 -0.100006103515625 +69790 0.028961181640625 +69791 -0.01055908203125 +69792 0.077911376953125 +69793 0.1033935546875 +69794 0.133392333984375 +69795 0.24908447265625 +69796 0.178863525390625 +69797 0.373199462890625 +69798 0.20867919921875 +69799 0.45806884765625 +69800 0.225006103515625 +69801 0.511474609375 +69802 0.237579345703125 +69803 0.565399169921875 +69804 0.244171142578125 +69805 0.61138916015625 +69806 0.22735595703125 +69807 0.5897216796875 +69808 0.184844970703125 +69809 0.4906005859375 +69810 0.122650146484375 +69811 0.33148193359375 +69812 0.05224609375 +69813 0.147796630859375 +69814 -0.01300048828125 +69815 -0.01873779296875 +69816 -0.063873291015625 +69817 -0.140289306640625 +69818 -0.092193603515625 +69819 -0.191986083984375 +69820 -0.100433349609375 +69821 -0.184295654296875 +69822 -0.101470947265625 +69823 -0.161834716796875 +69824 -0.1075439453125 +69825 -0.166595458984375 +69826 -0.1170654296875 +69827 -0.19390869140625 +69828 -0.124298095703125 +69829 -0.22442626953125 +69830 -0.1358642578125 +69831 -0.279754638671875 +69832 -0.145904541015625 +69833 -0.3389892578125 +69834 -0.140594482421875 +69835 -0.3543701171875 +69836 -0.127197265625 +69837 -0.348175048828125 +69838 -0.10809326171875 +69839 -0.32598876953125 +69840 -0.0750732421875 +69841 -0.2581787109375 +69842 -0.027374267578125 +69843 -0.139801025390625 +69844 0.029998779296875 +69845 0.014617919921875 +69846 0.0782470703125 +69847 0.144378662109375 +69848 0.1083984375 +69849 0.221038818359375 +69850 0.127960205078125 +69851 0.27069091796875 +69852 0.136962890625 +69853 0.294036865234375 +69854 0.141571044921875 +69855 0.311767578125 +69856 0.146453857421875 +69857 0.339141845703125 +69858 0.147064208984375 +69859 0.360260009765625 +69860 0.139404296875 +69861 0.360504150390625 +69862 0.1146240234375 +69863 0.308380126953125 +69864 0.066741943359375 +69865 0.18170166015625 +69866 0.00360107421875 +69867 0.0047607421875 +69868 -0.060333251953125 +69869 -0.17559814453125 +69870 -0.11114501953125 +69871 -0.3143310546875 +69872 -0.13543701171875 +69873 -0.36785888671875 +69874 -0.140594482421875 +69875 -0.36248779296875 +69876 -0.139678955078125 +69877 -0.343536376953125 +69878 -0.12982177734375 +69879 -0.3018798828125 +69880 -0.109130859375 +69881 -0.231414794921875 +69882 -0.073394775390625 +69883 -0.117645263671875 +69884 -0.032379150390625 +69885 0.007049560546875 +69886 -0.0025634765625 +69887 0.087982177734375 +69888 0.01995849609375 +69889 0.13946533203125 +69890 0.03851318359375 +69891 0.17425537109375 +69892 0.051361083984375 +69893 0.188201904296875 +69894 0.055450439453125 +69895 0.171234130859375 +69896 0.049163818359375 +69897 0.118438720703125 +69898 0.039398193359375 +69899 0.05706787109375 +69900 0.02642822265625 +69901 -0.010711669921875 +69902 0.00836181640625 +69903 -0.0914306640625 +69904 -0.008880615234375 +69905 -0.162322998046875 +69906 -0.017730712890625 +69907 -0.194549560546875 +69908 -0.00787353515625 +69909 -0.1492919921875 +69910 0.022125244140625 +69911 -0.02166748046875 +69912 0.0555419921875 +69913 0.124053955078125 +69914 0.0723876953125 +69915 0.211151123046875 +69916 0.073272705078125 +69917 0.240447998046875 +69918 0.06658935546875 +69919 0.242218017578125 +69920 0.05517578125 +69921 0.2257080078125 +69922 0.040313720703125 +69923 0.194366455078125 +69924 0.013671875 +69925 0.115509033203125 +69926 -0.018096923828125 +69927 0.0128173828125 +69928 -0.03900146484375 +69929 -0.053802490234375 +69930 -0.05584716796875 +69931 -0.110626220703125 +69932 -0.079620361328125 +69933 -0.199493408203125 +69934 -0.103485107421875 +69935 -0.29437255859375 +69936 -0.11090087890625 +69937 -0.33221435546875 +69938 -0.093292236328125 +69939 -0.27972412109375 +69940 -0.06365966796875 +69941 -0.185333251953125 +69942 -0.043182373046875 +69943 -0.128204345703125 +69944 -0.034088134765625 +69945 -0.115692138671875 +69946 -0.0284423828125 +69947 -0.116455078125 +69948 -0.020111083984375 +69949 -0.105926513671875 +69950 -0.00140380859375 +69951 -0.053955078125 +69952 0.029876708984375 +69953 0.048797607421875 +69954 0.061614990234375 +69955 0.157318115234375 +69956 0.077972412109375 +69957 0.212005615234375 +69958 0.080322265625 +69959 0.218475341796875 +69960 0.08465576171875 +69961 0.23724365234375 +69962 0.100830078125 +69963 0.30535888671875 +69964 0.118011474609375 +69965 0.38128662109375 +69966 0.120361328125 +69967 0.404449462890625 +69968 0.11328125 +69969 0.3944091796875 +69970 0.10693359375 +69971 0.3885498046875 +69972 0.09521484375 +69973 0.362640380859375 +69974 0.0670166015625 +69975 0.27362060546875 +69976 0.021453857421875 +69977 0.11712646484375 +69978 -0.027557373046875 +69979 -0.054901123046875 +69980 -0.06622314453125 +69981 -0.19085693359375 +69982 -0.093048095703125 +69983 -0.28570556640625 +69984 -0.107940673828125 +69985 -0.339263916015625 +69986 -0.11773681640625 +69987 -0.3775634765625 +69988 -0.134429931640625 +69989 -0.445709228515625 +69990 -0.15582275390625 +69991 -0.535064697265625 +69992 -0.177703857421875 +69993 -0.629058837890625 +69994 -0.1922607421875 +69995 -0.697601318359375 +69996 -0.19000244140625 +69997 -0.70391845703125 +69998 -0.169708251953125 +69999 -0.6424560546875 +70000 -0.12579345703125 +70001 -0.491241455078125 +70002 -0.06256103515625 +70003 -0.265716552734375 +70004 0.004486083984375 +70005 -0.023712158203125 +70006 0.066497802734375 +70007 0.201751708984375 +70008 0.1141357421875 +70009 0.375823974609375 +70010 0.143798828125 +70011 0.485076904296875 +70012 0.16583251953125 +70013 0.56884765625 +70014 0.182281494140625 +70015 0.634765625 +70016 0.181304931640625 +70017 0.63763427734375 +70018 0.160003662109375 +70019 0.5660400390625 +70020 0.132293701171875 +70021 0.4720458984375 +70022 0.11187744140625 +70023 0.40692138671875 +70024 0.100799560546875 +70025 0.3778076171875 +70026 0.09722900390625 +70027 0.376953125 +70028 0.092803955078125 +70029 0.371978759765625 +70030 0.07452392578125 +70031 0.313140869140625 +70032 0.038330078125 +70033 0.184417724609375 +70034 -0.00897216796875 +70035 0.011199951171875 +70036 -0.05792236328125 +70037 -0.171051025390625 +70038 -0.1019287109375 +70039 -0.33740234375 +70040 -0.136810302734375 +70041 -0.47198486328125 +70042 -0.1588134765625 +70043 -0.560394287109375 +70044 -0.1622314453125 +70045 -0.58056640625 +70046 -0.151153564453125 +70047 -0.54754638671875 +70048 -0.138214111328125 +70049 -0.508575439453125 +70050 -0.1224365234375 +70051 -0.459503173828125 +70052 -0.1024169921875 +70053 -0.394378662109375 +70054 -0.08868408203125 +70055 -0.35260009765625 +70056 -0.075469970703125 +70057 -0.31170654296875 +70058 -0.043304443359375 +70059 -0.197418212890625 +70060 0.008148193359375 +70061 -0.007965087890625 +70062 0.065826416015625 +70063 0.207489013671875 +70064 0.119232177734375 +70065 0.409210205078125 +70066 0.1617431640625 +70067 0.57208251953125 +70068 0.185455322265625 +70069 0.66595458984375 +70070 0.1820068359375 +70071 0.65875244140625 +70072 0.15594482421875 +70073 0.56744384765625 +70074 0.1177978515625 +70075 0.431396484375 +70076 0.07928466796875 +70077 0.29443359375 +70078 0.047332763671875 +70079 0.182464599609375 +70080 0.013702392578125 +70081 0.06365966796875 +70082 -0.025177001953125 +70083 -0.075958251953125 +70084 -0.056793212890625 +70085 -0.189422607421875 +70086 -0.07977294921875 +70087 -0.271942138671875 +70088 -0.099090576171875 +70089 -0.342529296875 +70090 -0.105010986328125 +70091 -0.364166259765625 +70092 -0.094970703125 +70093 -0.327239990234375 +70094 -0.0809326171875 +70095 -0.2769775390625 +70096 -0.0736083984375 +70097 -0.253692626953125 +70098 -0.069427490234375 +70099 -0.24365234375 +70100 -0.055694580078125 +70101 -0.1983642578125 +70102 -0.032073974609375 +70103 -0.116241455078125 +70104 -0.009124755859375 +70105 -0.036834716796875 +70106 0.011688232421875 +70107 0.034881591796875 +70108 0.02825927734375 +70109 0.09124755859375 +70110 0.034332275390625 +70111 0.10888671875 +70112 0.039794921875 +70113 0.125518798828125 +70114 0.048980712890625 +70115 0.15771484375 +70116 0.054656982421875 +70117 0.17828369140625 +70118 0.052581787109375 +70119 0.17108154296875 +70120 0.041168212890625 +70121 0.129974365234375 +70122 0.027679443359375 +70123 0.082427978515625 +70124 0.011993408203125 +70125 0.027679443359375 +70126 -0.014068603515625 +70127 -0.065643310546875 +70128 -0.04034423828125 +70129 -0.15936279296875 +70130 -0.056060791015625 +70131 -0.21307373046875 +70132 -0.063262939453125 +70133 -0.234649658203125 +70134 -0.0555419921875 +70135 -0.2001953125 +70136 -0.035308837890625 +70137 -0.119171142578125 +70138 -0.01129150390625 +70139 -0.024749755859375 +70140 0.01727294921875 +70141 0.085784912109375 +70142 0.04132080078125 +70143 0.178131103515625 +70144 0.0513916015625 +70145 0.215576171875 +70146 0.0511474609375 +70147 0.211456298828125 +70148 0.043212890625 +70149 0.17523193359375 +70150 0.032684326171875 +70151 0.128753662109375 +70152 0.026519775390625 +70153 0.1019287109375 +70154 0.020050048828125 +70155 0.0743408203125 +70156 0.01263427734375 +70157 0.04327392578125 +70158 0.0111083984375 +70159 0.038177490234375 +70160 0.01953125 +70161 0.076263427734375 +70162 0.0340576171875 +70163 0.14105224609375 +70164 0.044036865234375 +70165 0.186431884765625 +70166 0.044036865234375 +70167 0.188812255859375 +70168 0.03192138671875 +70169 0.1390380859375 +70170 0.00885009765625 +70171 0.041778564453125 +70172 -0.019683837890625 +70173 -0.079437255859375 +70174 -0.052459716796875 +70175 -0.219390869140625 +70176 -0.0870361328125 +70177 -0.367828369140625 +70178 -0.116485595703125 +70179 -0.494873046875 +70180 -0.130584716796875 +70181 -0.556243896484375 +70182 -0.11932373046875 +70183 -0.508697509765625 +70184 -0.088104248046875 +70185 -0.3756103515625 +70186 -0.051361083984375 +70187 -0.218902587890625 +70188 -0.01495361328125 +70189 -0.063751220703125 +70190 0.021453857421875 +70191 0.091552734375 +70192 0.055328369140625 +70193 0.23602294921875 +70194 0.0804443359375 +70195 0.342987060546875 +70196 0.092803955078125 +70197 0.39520263671875 +70198 0.09161376953125 +70199 0.389373779296875 +70200 0.07659912109375 +70201 0.324249267578125 +70202 0.05340576171875 +70203 0.224090576171875 +70204 0.03021240234375 +70205 0.124267578125 +70206 0.0098876953125 +70207 0.037078857421875 +70208 -0.001190185546875 +70209 -0.010101318359375 +70210 -0.003509521484375 +70211 -0.019439697265625 +70212 -0.004486083984375 +70213 -0.022796630859375 +70214 0.000213623046875 +70215 -0.001556396484375 +70216 0.01336669921875 +70217 0.056304931640625 +70218 0.024749755859375 +70219 0.106719970703125 +70220 0.02215576171875 +70221 0.096893310546875 +70222 0.00927734375 +70223 0.042694091796875 +70224 -0.005035400390625 +70225 -0.018035888671875 +70226 -0.01861572265625 +70227 -0.07586669921875 +70228 -0.02880859375 +70229 -0.11944580078125 +70230 -0.03814697265625 +70231 -0.15972900390625 +70232 -0.048004150390625 +70233 -0.202606201171875 +70234 -0.0584716796875 +70235 -0.24859619140625 +70236 -0.071319580078125 +70237 -0.30517578125 +70238 -0.084197998046875 +70239 -0.36212158203125 +70240 -0.09063720703125 +70241 -0.39141845703125 +70242 -0.081878662109375 +70243 -0.35528564453125 +70244 -0.057098388671875 +70245 -0.249969482421875 +70246 -0.02032470703125 +70247 -0.092864990234375 +70248 0.0220947265625 +70249 0.08905029296875 +70250 0.056121826171875 +70251 0.2352294921875 +70252 0.0755615234375 +70253 0.318817138671875 +70254 0.084747314453125 +70255 0.358642578125 +70256 0.08209228515625 +70257 0.347747802734375 +70258 0.0675048828125 +70259 0.28564453125 +70260 0.052764892578125 +70261 0.223175048828125 +70262 0.046356201171875 +70263 0.196746826171875 +70264 0.0421142578125 +70265 0.179840087890625 +70266 0.0361328125 +70267 0.155548095703125 +70268 0.0347900390625 +70269 0.151214599609375 +70270 0.035797119140625 +70271 0.156951904296875 +70272 0.0296630859375 +70273 0.13177490234375 +70274 0.022247314453125 +70275 0.100799560546875 +70276 0.0189208984375 +70277 0.087127685546875 +70278 0.0113525390625 +70279 0.05487060546875 +70280 -0.003448486328125 +70281 -0.009002685546875 +70282 -0.025390625 +70283 -0.10400390625 +70284 -0.054290771484375 +70285 -0.229400634765625 +70286 -0.083282470703125 +70287 -0.35552978515625 +70288 -0.102996826171875 +70289 -0.441925048828125 +70290 -0.110015869140625 +70291 -0.473846435546875 +70292 -0.107513427734375 +70293 -0.464813232421875 +70294 -0.096527099609375 +70295 -0.419097900390625 +70296 -0.076507568359375 +70297 -0.334320068359375 +70298 -0.051513671875 +70299 -0.227935791015625 +70300 -0.02703857421875 +70301 -0.12347412109375 +70302 -0.004638671875 +70303 -0.02764892578125 +70304 0.019866943359375 +70305 0.077667236328125 +70306 0.051300048828125 +70307 0.2132568359375 +70308 0.0919189453125 +70309 0.38885498046875 +70310 0.13671875 +70311 0.582794189453125 +70312 0.171539306640625 +70313 0.734039306640625 +70314 0.1865234375 +70315 0.800140380859375 +70316 0.181060791015625 +70317 0.7783203125 +70318 0.154388427734375 +70319 0.6651611328125 +70320 0.1063232421875 +70321 0.45965576171875 +70322 0.0455322265625 +70323 0.199188232421875 +70324 -0.012725830078125 +70325 -0.050689697265625 +70326 -0.055206298828125 +70327 -0.23297119140625 +70328 -0.077850341796875 +70329 -0.33013916015625 +70330 -0.08673095703125 +70331 -0.368408203125 +70332 -0.089080810546875 +70333 -0.378936767578125 +70334 -0.088470458984375 +70335 -0.376983642578125 +70336 -0.0888671875 +70337 -0.37969970703125 +70338 -0.09130859375 +70339 -0.391510009765625 +70340 -0.089569091796875 +70341 -0.385345458984375 +70342 -0.07916259765625 +70343 -0.3419189453125 +70344 -0.06512451171875 +70345 -0.28289794921875 +70346 -0.057525634765625 +70347 -0.251617431640625 +70348 -0.060577392578125 +70349 -0.266143798828125 +70350 -0.061981201171875 +70351 -0.273345947265625 +70352 -0.048675537109375 +70353 -0.216796875 +70354 -0.027984619140625 +70355 -0.128265380859375 +70356 -0.013946533203125 +70357 -0.068145751953125 +70358 -0.008087158203125 +70359 -0.0430908203125 +70360 -0.0037841796875 +70361 -0.024444580078125 +70362 0.006561279296875 +70363 0.020721435546875 +70364 0.0303955078125 +70365 0.124481201171875 +70366 0.06103515625 +70367 0.25787353515625 +70368 0.08880615234375 +70369 0.379119873046875 +70370 0.111785888671875 +70371 0.47991943359375 +70372 0.12255859375 +70373 0.5281982421875 +70374 0.118194580078125 +70375 0.511138916015625 +70376 0.105072021484375 +70377 0.456207275390625 +70378 0.093414306640625 +70379 0.407470703125 +70380 0.087615966796875 +70381 0.383758544921875 +70382 0.081146240234375 +70383 0.35687255859375 +70384 0.070556640625 +70385 0.31182861328125 +70386 0.056365966796875 +70387 0.250885009765625 +70388 0.03656005859375 +70389 0.1654052734375 +70390 0.006500244140625 +70391 0.035247802734375 +70392 -0.034393310546875 +70393 -0.142059326171875 +70394 -0.0789794921875 +70395 -0.33563232421875 +70396 -0.124725341796875 +70397 -0.5345458984375 +70398 -0.167724609375 +70399 -0.72186279296875 +70400 -0.1943359375 +70401 -0.836669921875 +70402 -0.194488525390625 +70403 -0.8326416015625 +70404 -0.172210693359375 +70405 -0.7296142578125 +70406 -0.138946533203125 +70407 -0.582550048828125 +70408 -0.105010986328125 +70409 -0.440093994140625 +70410 -0.0753173828125 +70411 -0.324310302734375 +70412 -0.043670654296875 +70413 -0.20147705078125 +70414 -0.00518798828125 +70415 -0.044647216796875 +70416 0.03118896484375 +70417 0.103973388671875 +70418 0.056671142578125 +70419 0.202392578125 +70420 0.073699951171875 +70421 0.264495849609375 +70422 0.091796875 +70423 0.338897705078125 +70424 0.114471435546875 +70425 0.443817138671875 +70426 0.134857177734375 +70427 0.545074462890625 +70428 0.14794921875 +70429 0.6173095703125 +70430 0.15228271484375 +70431 0.6524658203125 +70432 0.150604248046875 +70433 0.66339111328125 +70434 0.144378662109375 +70435 0.6561279296875 +70436 0.12908935546875 +70437 0.606781005859375 +70438 0.102264404296875 +70439 0.501190185546875 +70440 0.066925048828125 +70441 0.352783203125 +70442 0.0263671875 +70443 0.176544189453125 +70444 -0.020538330078125 +70445 -0.034820556640625 +70446 -0.06890869140625 +70447 -0.258209228515625 +70448 -0.108367919921875 +70449 -0.44244384765625 +70450 -0.1363525390625 +70451 -0.5753173828125 +70452 -0.15185546875 +70453 -0.65203857421875 +70454 -0.148712158203125 +70455 -0.641632080078125 +70456 -0.13067626953125 +70457 -0.562164306640625 +70458 -0.106781005859375 +70459 -0.458038330078125 +70460 -0.081451416015625 +70461 -0.350555419921875 +70462 -0.05908203125 +70463 -0.260528564453125 +70464 -0.040740966796875 +70465 -0.192108154296875 +70466 -0.026031494140625 +70467 -0.141937255859375 +70468 -0.013641357421875 +70469 -0.1021728515625 +70470 -0.001800537109375 +70471 -0.062896728515625 +70472 0.01165771484375 +70473 -0.011932373046875 +70474 0.029022216796875 +70475 0.062835693359375 +70476 0.04766845703125 +70477 0.148712158203125 +70478 0.066741943359375 +70479 0.241729736328125 +70480 0.087677001953125 +70481 0.34912109375 +70482 0.1077880859375 +70483 0.457305908203125 +70484 0.122711181640625 +70485 0.54388427734375 +70486 0.125457763671875 +70487 0.5728759765625 +70488 0.108642578125 +70489 0.506591796875 +70490 0.07373046875 +70491 0.351226806640625 +70492 0.02886962890625 +70493 0.146514892578125 +70494 -0.015228271484375 +70495 -0.05523681640625 +70496 -0.050811767578125 +70497 -0.21624755859375 +70498 -0.077392578125 +70499 -0.334930419921875 +70500 -0.0931396484375 +70501 -0.402984619140625 +70502 -0.102142333984375 +70503 -0.4412841796875 +70504 -0.113555908203125 +70505 -0.49578857421875 +70506 -0.126129150390625 +70507 -0.5601806640625 +70508 -0.133148193359375 +70509 -0.600738525390625 +70510 -0.1280517578125 +70511 -0.584228515625 +70512 -0.104705810546875 +70513 -0.47930908203125 +70514 -0.061920166015625 +70515 -0.27935791015625 +70516 -0.0047607421875 +70517 -0.0089111328125 +70518 0.053924560546875 +70519 0.268798828125 +70520 0.0997314453125 +70521 0.482818603515625 +70522 0.12664794921875 +70523 0.60369873046875 +70524 0.138336181640625 +70525 0.650421142578125 +70526 0.142852783203125 +70527 0.66400146484375 +70528 0.139556884765625 +70529 0.6414794921875 +70530 0.1263427734375 +70531 0.572540283203125 +70532 0.111358642578125 +70533 0.498138427734375 +70534 0.098907470703125 +70535 0.439453125 +70536 0.0848388671875 +70537 0.375518798828125 +70538 0.0628662109375 +70539 0.274505615234375 +70540 0.027557373046875 +70541 0.1087646484375 +70542 -0.016448974609375 +70543 -0.099395751953125 +70544 -0.06268310546875 +70545 -0.3182373046875 +70546 -0.11126708984375 +70547 -0.5489501953125 +70548 -0.158477783203125 +70549 -0.7738037109375 +70550 -0.193603515625 +70551 -0.86383056640625 +70552 -0.209930419921875 +70553 -0.870391845703125 +70554 -0.2109375 +70555 -0.86895751953125 +70556 -0.199188232421875 +70557 -0.861053466796875 +70558 -0.171234130859375 +70559 -0.765869140625 +70560 -0.12481689453125 +70561 -0.5301513671875 +70562 -0.0614013671875 +70563 -0.214691162109375 +70564 0.010345458984375 +70565 0.137359619140625 +70566 0.080047607421875 +70567 0.474822998046875 +70568 0.1405029296875 +70569 0.76239013671875 +70570 0.18621826171875 +70571 0.867462158203125 +70572 0.2171630859375 +70573 0.870361328125 +70574 0.230926513671875 +70575 0.86480712890625 +70576 0.228485107421875 +70577 0.831817626953125 +70578 0.214630126953125 +70579 0.677581787109375 +70580 0.19049072265625 +70581 0.495880126953125 +70582 0.15972900390625 +70583 0.30767822265625 +70584 0.122772216796875 +70585 0.116180419921875 +70586 0.073272705078125 +70587 -0.110748291015625 +70588 0.009857177734375 +70589 -0.381805419921875 +70590 -0.058837890625 +70591 -0.6572265625 +70592 -0.120758056640625 +70593 -0.857421875 +70594 -0.167266845703125 +70595 -0.870391845703125 +70596 -0.196868896484375 +70597 -0.870391845703125 +70598 -0.21484375 +70599 -0.86444091796875 +70600 -0.228271484375 +70601 -0.85723876953125 +70602 -0.2333984375 +70603 -0.790008544921875 +70604 -0.21929931640625 +70605 -0.62847900390625 +70606 -0.185272216796875 +70607 -0.3956298828125 +70608 -0.13787841796875 +70609 -0.126708984375 +70610 -0.082550048828125 +70611 0.150115966796875 +70612 -0.021636962890625 +70613 0.424041748046875 +70614 0.039459228515625 +70615 0.670623779296875 +70616 0.092926025390625 +70617 0.854522705078125 +70618 0.13519287109375 +70619 0.866485595703125 +70620 0.163116455078125 +70621 0.86920166015625 +70622 0.180267333984375 +70623 0.8653564453125 +70624 0.18927001953125 +70625 0.857147216796875 +70626 0.189453125 +70627 0.766845703125 +70628 0.181793212890625 +70629 0.628509521484375 +70630 0.164886474609375 +70631 0.462127685546875 +70632 0.143829345703125 +70633 0.297210693359375 +70634 0.12109375 +70635 0.14862060546875 +70636 0.092071533203125 +70637 -0.00537109375 +70638 0.058258056640625 +70639 -0.15753173828125 +70640 0.01898193359375 +70641 -0.31304931640625 +70642 -0.028533935546875 +70643 -0.48876953125 +70644 -0.074859619140625 +70645 -0.6416015625 +70646 -0.114990234375 +70647 -0.751373291015625 +70648 -0.15350341796875 +70649 -0.84619140625 +70650 -0.187408447265625 +70651 -0.861297607421875 +70652 -0.209991455078125 +70653 -0.863250732421875 +70654 -0.21490478515625 +70655 -0.856597900390625 +70656 -0.203948974609375 +70657 -0.7498779296875 +70658 -0.187896728515625 +70659 -0.624542236328125 +70660 -0.163787841796875 +70661 -0.47808837890625 +70662 -0.1220703125 +70663 -0.253387451171875 +70664 -0.070770263671875 +70665 0.003692626953125 +70666 -0.021728515625 +70667 0.2257080078125 +70668 0.0267333984375 +70669 0.427154541015625 +70670 0.079681396484375 +70671 0.643218994140625 +70672 0.135101318359375 +70673 0.855926513671875 +70674 0.182952880859375 +70675 0.870361328125 +70676 0.21466064453125 +70677 0.870361328125 +70678 0.23126220703125 +70679 0.862762451171875 +70680 0.232177734375 +70681 0.79669189453125 +70682 0.2158203125 +70683 0.595794677734375 +70684 0.187164306640625 +70685 0.362152099609375 +70686 0.151092529296875 +70687 0.1270751953125 +70688 0.111419677734375 +70689 -0.086944580078125 +70690 0.068756103515625 +70691 -0.2784423828125 +70692 0.017608642578125 +70693 -0.484832763671875 +70694 -0.044891357421875 +70695 -0.729583740234375 +70696 -0.109893798828125 +70697 -0.86688232421875 +70698 -0.166412353515625 +70699 -0.870391845703125 +70700 -0.21331787109375 +70701 -0.86859130859375 +70702 -0.25 +70703 -0.86279296875 +70704 -0.270294189453125 +70705 -0.817962646484375 +70706 -0.26641845703125 +70707 -0.6116943359375 +70708 -0.237152099609375 +70709 -0.3128662109375 +70710 -0.188232421875 +70711 0.039398193359375 +70712 -0.123138427734375 +70713 0.422821044921875 +70714 -0.04766845703125 +70715 0.805145263671875 +70716 0.0264892578125 +70717 0.870361328125 +70718 0.0894775390625 +70719 0.870361328125 +70720 0.139007568359375 +70721 0.860015869140625 +70722 0.173492431640625 +70723 0.727935791015625 +70724 0.191650390625 +70725 0.48114013671875 +70726 0.197296142578125 +70727 0.2059326171875 +70728 0.193939208984375 +70729 -0.06103515625 +70730 0.18310546875 +70731 -0.29913330078125 +70732 0.162261962890625 +70733 -0.516204833984375 +70734 0.1287841796875 +70735 -0.7252197265625 +70736 0.086883544921875 +70737 -0.85980224609375 +70738 0.042388916015625 +70739 -0.870391845703125 +70740 0.000457763671875 +70741 -0.870391845703125 +70742 -0.03045654296875 +70743 -0.858062744140625 +70744 -0.049346923828125 +70745 -0.673004150390625 +70746 -0.06475830078125 +70747 -0.42694091796875 +70748 -0.083831787109375 +70749 -0.2100830078125 +70750 -0.10589599609375 +70751 -0.0362548828125 +70752 -0.125762939453125 +70753 0.10943603515625 +70754 -0.139801025390625 +70755 0.23516845703125 +70756 -0.140869140625 +70757 0.373687744140625 +70758 -0.129150390625 +70759 0.517791748046875 +70760 -0.11517333984375 +70761 0.602783203125 +70762 -0.098114013671875 +70763 0.635711669921875 +70764 -0.07244873046875 +70765 0.655181884765625 +70766 -0.040008544921875 +70767 0.65948486328125 +70768 -0.002349853515625 +70769 0.651275634765625 +70770 0.0361328125 +70771 0.61846923828125 +70772 0.068939208984375 +70773 0.53753662109375 +70774 0.092742919921875 +70775 0.404144287109375 +70776 0.10565185546875 +70777 0.22186279296875 +70778 0.107666015625 +70779 0.003997802734375 +70780 0.1015625 +70781 -0.22100830078125 +70782 0.090606689453125 +70783 -0.42449951171875 +70784 0.0782470703125 +70785 -0.579833984375 +70786 0.07159423828125 +70787 -0.641876220703125 +70788 0.06951904296875 +70789 -0.6177978515625 +70790 0.06121826171875 +70791 -0.575531005859375 +70792 0.0458984375 +70793 -0.526336669921875 +70794 0.032440185546875 +70795 -0.42645263671875 +70796 0.025634765625 +70797 -0.2581787109375 +70798 0.019622802734375 +70799 -0.068695068359375 +70800 0.008209228515625 +70801 0.09222412109375 +70802 -0.005218505859375 +70803 0.232147216796875 +70804 -0.0186767578125 +70805 0.3509521484375 +70806 -0.03692626953125 +70807 0.410064697265625 +70808 -0.064697265625 +70809 0.372955322265625 +70810 -0.098388671875 +70811 0.2554931640625 +70812 -0.129119873046875 +70813 0.10711669921875 +70814 -0.153564453125 +70815 -0.052886962890625 +70816 -0.165679931640625 +70817 -0.186279296875 +70818 -0.156158447265625 +70819 -0.23291015625 +70820 -0.12896728515625 +70821 -0.209442138671875 +70822 -0.095306396484375 +70823 -0.174163818359375 +70824 -0.056793212890625 +70825 -0.126739501953125 +70826 -0.011962890625 +70827 -0.048126220703125 +70828 0.034210205078125 +70829 0.0426025390625 +70830 0.07366943359375 +70831 0.10748291015625 +70832 0.10400390625 +70833 0.1409912109375 +70834 0.133026123046875 +70835 0.19708251953125 +70836 0.159454345703125 +70837 0.273651123046875 +70838 0.173858642578125 +70839 0.31768798828125 +70840 0.178009033203125 +70841 0.341094970703125 +70842 0.176177978515625 +70843 0.368011474609375 +70844 0.164520263671875 +70845 0.37249755859375 +70846 0.134857177734375 +70847 0.30072021484375 +70848 0.088134765625 +70849 0.1517333984375 +70850 0.03570556640625 +70851 -0.01470947265625 +70852 -0.019256591796875 +70853 -0.1883544921875 +70854 -0.075927734375 +70855 -0.372711181640625 +70856 -0.123870849609375 +70857 -0.51397705078125 +70858 -0.155029296875 +70859 -0.57177734375 +70860 -0.167205810546875 +70861 -0.53948974609375 +70862 -0.162567138671875 +70863 -0.43511962890625 +70864 -0.1468505859375 +70865 -0.2962646484375 +70866 -0.126220703125 +70867 -0.161102294921875 +70868 -0.103057861328125 +70869 -0.0435791015625 +70870 -0.0770263671875 +70871 0.060394287109375 +70872 -0.0511474609375 +70873 0.13665771484375 +70874 -0.028778076171875 +70875 0.170135498046875 +70876 -0.010101318359375 +70877 0.16552734375 +70878 0.009490966796875 +70879 0.15728759765625 +70880 0.029693603515625 +70881 0.150787353515625 +70882 0.0452880859375 +70883 0.12200927734375 +70884 0.0567626953125 +70885 0.080108642578125 +70886 0.067535400390625 +70887 0.05126953125 +70888 0.0814208984375 +70889 0.062896728515625 +70890 0.094146728515625 +70891 0.09271240234375 +70892 0.097442626953125 +70893 0.092987060546875 +70894 0.093719482421875 +70895 0.07855224609375 +70896 0.085662841796875 +70897 0.06427001953125 +70898 0.07110595703125 +70899 0.0347900390625 +70900 0.050384521484375 +70901 -0.01171875 +70902 0.02752685546875 +70903 -0.056060791015625 +70904 0.0106201171875 +70905 -0.055511474609375 +70906 0.000579833984375 +70907 -0.010467529296875 +70908 -0.0106201171875 +70909 0.02508544921875 +70910 -0.026336669921875 +70911 0.025665283203125 +70912 -0.041595458984375 +70913 0.017333984375 +70914 -0.055267333984375 +70915 0.00189208984375 +70916 -0.068511962890625 +70917 -0.03173828125 +70918 -0.07904052734375 +70919 -0.071502685546875 +70920 -0.089324951171875 +70921 -0.13543701171875 +70922 -0.098846435546875 +70923 -0.219970703125 +70924 -0.104156494140625 +70925 -0.300506591796875 +70926 -0.1055908203125 +70927 -0.376312255859375 +70928 -0.09912109375 +70929 -0.416107177734375 +70930 -0.07818603515625 +70931 -0.371124267578125 +70932 -0.04376220703125 +70933 -0.242279052734375 +70934 -0.00274658203125 +70935 -0.069732666015625 +70936 0.040863037109375 +70937 0.125640869140625 +70938 0.081634521484375 +70939 0.31268310546875 +70940 0.113433837890625 +70941 0.45501708984375 +70942 0.136077880859375 +70943 0.554779052734375 +70944 0.1490478515625 +70945 0.61065673828125 +70946 0.150421142578125 +70947 0.610931396484375 +70948 0.136627197265625 +70949 0.531463623046875 +70950 0.1102294921875 +70951 0.3883056640625 +70952 0.079559326171875 +70953 0.23468017578125 +70954 0.048858642578125 +70955 0.095245361328125 +70956 0.022613525390625 +70957 -0.00396728515625 +70958 0.00360107421875 +70959 -0.04852294921875 +70960 -0.00994873046875 +70961 -0.055145263671875 +70962 -0.025146484375 +70963 -0.0758056640625 +70964 -0.0455322265625 +70965 -0.138702392578125 +70966 -0.06536865234375 +70967 -0.209197998046875 +70968 -0.084442138671875 +70969 -0.289031982421875 +70970 -0.1025390625 +70971 -0.37884521484375 +70972 -0.116119384765625 +70973 -0.456329345703125 +70974 -0.1243896484375 +70975 -0.51641845703125 +70976 -0.12152099609375 +70977 -0.519287109375 +70978 -0.106781005859375 +70979 -0.458251953125 +70980 -0.0882568359375 +70981 -0.384796142578125 +70982 -0.070098876953125 +70983 -0.323699951171875 +70984 -0.051971435546875 +70985 -0.269287109375 +70986 -0.030487060546875 +70987 -0.1951904296875 +70988 -0.00604248046875 +70989 -0.100006103515625 +70990 0.016754150390625 +70991 -0.01055908203125 +70992 0.04193115234375 +70993 0.1033935546875 +70994 0.0701904296875 +70995 0.24908447265625 +70996 0.09326171875 +70997 0.373199462890625 +70998 0.1082763671875 +70999 0.45806884765625 +71000 0.1163330078125 +71001 0.511474609375 +71002 0.122283935546875 +71003 0.565399169921875 +71004 0.125091552734375 +71005 0.61138916015625 +71006 0.116058349609375 +71007 0.5897216796875 +71008 0.094085693359375 +71009 0.4906005859375 +71010 0.06219482421875 +71011 0.33148193359375 +71012 0.02618408203125 +71013 0.147796630859375 +71014 -0.007232666015625 +71015 -0.01873779296875 +71016 -0.03338623046875 +71017 -0.140289306640625 +71018 -0.048126220703125 +71019 -0.191986083984375 +71020 -0.05267333984375 +71021 -0.184295654296875 +71022 -0.053436279296875 +71023 -0.161834716796875 +71024 -0.056549072265625 +71025 -0.166595458984375 +71026 -0.061248779296875 +71027 -0.19390869140625 +71028 -0.06463623046875 +71029 -0.22442626953125 +71030 -0.070068359375 +71031 -0.279754638671875 +71032 -0.074615478515625 +71033 -0.3389892578125 +71034 -0.0714111328125 +71035 -0.3543701171875 +71036 -0.064117431640625 +71037 -0.348175048828125 +71038 -0.053924560546875 +71039 -0.32598876953125 +71040 -0.036773681640625 +71041 -0.2581787109375 +71042 -0.0123291015625 +71043 -0.139801025390625 +71044 0.016845703125 +71045 0.014617919921875 +71046 0.04132080078125 +71047 0.144378662109375 +71048 0.056610107421875 +71049 0.221038818359375 +71050 0.066436767578125 +71051 0.27069091796875 +71052 0.07086181640625 +71053 0.294036865234375 +71054 0.072967529296875 +71055 0.311767578125 +71056 0.0750732421875 +71057 0.339141845703125 +71058 0.07476806640625 +71059 0.360260009765625 +71060 0.07012939453125 +71061 0.360504150390625 +71062 0.057220458984375 +71063 0.308380126953125 +71064 0.033416748046875 +71065 0.18170166015625 +71066 0.002471923828125 +71067 0.0047607421875 +71068 -0.02880859375 +71069 -0.17559814453125 +71070 -0.053955078125 +71071 -0.3143310546875 +71072 -0.066680908203125 +71073 -0.36785888671875 +71074 -0.070281982421875 +71075 -0.36248779296875 +71076 -0.070709228515625 +71077 -0.343536376953125 +71078 -0.066619873046875 +71079 -0.3018798828125 +71080 -0.057159423828125 +71081 -0.231414794921875 +71082 -0.040374755859375 +71083 -0.117645263671875 +71084 -0.02081298828125 +71085 0.007049560546875 +71086 -0.00604248046875 +71087 0.087982177734375 +71088 0.005615234375 +71089 0.13946533203125 +71090 0.015594482421875 +71091 0.17425537109375 +71092 0.023040771484375 +71093 0.188201904296875 +71094 0.0262451171875 +71095 0.171234130859375 +71096 0.0242919921875 +71097 0.118438720703125 +71098 0.020599365234375 +71099 0.05706787109375 +71100 0.01519775390625 +71101 -0.010711669921875 +71102 0.00701904296875 +71103 -0.0914306640625 +71104 -0.00091552734375 +71105 -0.162322998046875 +71106 -0.0047607421875 +71107 -0.194549560546875 +71108 0.000732421875 +71109 -0.1492919921875 +71110 0.01629638671875 +71111 -0.02166748046875 +71112 0.0333251953125 +71113 0.124053955078125 +71114 0.04156494140625 +71115 0.211151123046875 +71116 0.041351318359375 +71117 0.240447998046875 +71118 0.037017822265625 +71119 0.242218017578125 +71120 0.030120849609375 +71121 0.2257080078125 +71122 0.0213623046875 +71123 0.194366455078125 +71124 0.006561279296875 +71125 0.115509033203125 +71126 -0.01080322265625 +71127 0.0128173828125 +71128 -0.0224609375 +71129 -0.053802490234375 +71130 -0.0318603515625 +71131 -0.110626220703125 +71132 -0.04461669921875 +71133 -0.199493408203125 +71134 -0.05718994140625 +71135 -0.29437255859375 +71136 -0.061065673828125 +71137 -0.33221435546875 +71138 -0.051788330078125 +71139 -0.27972412109375 +71140 -0.036102294921875 +71141 -0.185333251953125 +71142 -0.02496337890625 +71143 -0.128204345703125 +71144 -0.01953125 +71145 -0.115692138671875 +71146 -0.01580810546875 +71147 -0.116455078125 +71148 -0.010650634765625 +71149 -0.105926513671875 +71150 -0.0001220703125 +71151 -0.053955078125 +71152 0.016815185546875 +71153 0.048797607421875 +71154 0.033905029296875 +71155 0.157318115234375 +71156 0.042938232421875 +71157 0.212005615234375 +71158 0.044586181640625 +71159 0.218475341796875 +71160 0.047088623046875 +71161 0.23724365234375 +71162 0.05548095703125 +71163 0.30535888671875 +71164 0.064208984375 +71165 0.38128662109375 +71166 0.065093994140625 +71167 0.404449462890625 +71168 0.06036376953125 +71169 0.3944091796875 +71170 0.054656982421875 +71171 0.3885498046875 +71172 0.04583740234375 +71173 0.362640380859375 +71174 0.029937744140625 +71175 0.27362060546875 +71176 0.006988525390625 +71177 0.11712646484375 +71178 -0.017120361328125 +71179 -0.054901123046875 +71180 -0.036651611328125 +71181 -0.19085693359375 +71182 -0.05078125 +71183 -0.28570556640625 +71184 -0.05926513671875 +71185 -0.339263916015625 +71186 -0.064697265625 +71187 -0.3775634765625 +71188 -0.071685791015625 +71189 -0.445709228515625 +71190 -0.07940673828125 +71191 -0.535064697265625 +71192 -0.086273193359375 +71193 -0.629058837890625 +71194 -0.089324951171875 +71195 -0.697601318359375 +71196 -0.085052490234375 +71197 -0.70391845703125 +71198 -0.073150634765625 +71199 -0.6424560546875 +71200 -0.05169677734375 +71201 -0.491241455078125 +71202 -0.022613525390625 +71203 -0.265716552734375 +71204 0.00775146484375 +71205 -0.023712158203125 +71206 0.03570556640625 +71207 0.201751708984375 +71208 0.057373046875 +71209 0.375823974609375 +71210 0.071197509765625 +71211 0.485076904296875 +71212 0.081146240234375 +71213 0.56884765625 +71214 0.087982177734375 +71215 0.634765625 +71216 0.087066650390625 +71217 0.63763427734375 +71218 0.077301025390625 +71219 0.5660400390625 +71220 0.06427001953125 +71221 0.4720458984375 +71222 0.053466796875 +71223 0.40692138671875 +71224 0.0458984375 +71225 0.3778076171875 +71226 0.041015625 +71227 0.376953125 +71228 0.0357666015625 +71229 0.371978759765625 +71230 0.025177001953125 +71231 0.313140869140625 +71232 0.007843017578125 +71233 0.184417724609375 +71234 -0.01336669921875 +71235 0.011199951171875 +71236 -0.034576416015625 +71237 -0.171051025390625 +71238 -0.0531005859375 +71239 -0.33740234375 +71240 -0.067291259765625 +71241 -0.47198486328125 +71242 -0.075653076171875 +71243 -0.560394287109375 +71244 -0.075958251953125 +71245 -0.58056640625 +71246 -0.06988525390625 +71247 -0.54754638671875 +71248 -0.06256103515625 +71249 -0.508575439453125 +71250 -0.05377197265625 +71251 -0.459503173828125 +71252 -0.043060302734375 +71253 -0.394378662109375 +71254 -0.03472900390625 +71255 -0.35260009765625 +71256 -0.02667236328125 +71257 -0.31170654296875 +71258 -0.011383056640625 +71259 -0.197418212890625 +71260 0.011138916015625 +71261 -0.007965087890625 +71262 0.035614013671875 +71263 0.207489013671875 +71264 0.057830810546875 +71265 0.409210205078125 +71266 0.07513427734375 +71267 0.57208251953125 +71268 0.084381103515625 +71269 0.66595458984375 +71270 0.082305908203125 +71271 0.65875244140625 +71272 0.07080078125 +71273 0.56744384765625 +71274 0.054046630859375 +71275 0.431396484375 +71276 0.036773681640625 +71277 0.29443359375 +71278 0.0218505859375 +71279 0.182464599609375 +71280 0.00616455078125 +71281 0.06365966796875 +71282 -0.01153564453125 +71283 -0.075958251953125 +71284 -0.02618408203125 +71285 -0.189422607421875 +71286 -0.037109375 +71287 -0.271942138671875 +71288 -0.04620361328125 +71289 -0.342529296875 +71290 -0.049591064453125 +71291 -0.364166259765625 +71292 -0.04620361328125 +71293 -0.327239990234375 +71294 -0.04071044921875 +71295 -0.2769775390625 +71296 -0.037353515625 +71297 -0.253692626953125 +71298 -0.0347900390625 +71299 -0.24365234375 +71300 -0.028045654296875 +71301 -0.1983642578125 +71302 -0.01708984375 +71303 -0.116241455078125 +71304 -0.00616455078125 +71305 -0.036834716796875 +71306 0.003997802734375 +71307 0.034881591796875 +71308 0.012451171875 +71309 0.09124755859375 +71310 0.016632080078125 +71311 0.10888671875 +71312 0.020355224609375 +71313 0.125518798828125 +71314 0.025238037109375 +71315 0.15771484375 +71316 0.028411865234375 +71317 0.17828369140625 +71318 0.02813720703125 +71319 0.17108154296875 +71320 0.02374267578125 +71321 0.129974365234375 +71322 0.01812744140625 +71323 0.082427978515625 +71324 0.011260986328125 +71325 0.027679443359375 +71326 0.0 +71327 -0.065643310546875 +71328 -0.0115966796875 +71329 -0.15936279296875 +71330 -0.019195556640625 +71331 -0.21307373046875 +71332 -0.023529052734375 +71333 -0.234649658203125 +71334 -0.022003173828125 +71335 -0.2001953125 +71336 -0.0155029296875 +71337 -0.119171142578125 +71338 -0.007354736328125 +71339 -0.024749755859375 +71340 0.002777099609375 +71341 0.085784912109375 +71342 0.011383056640625 +71343 0.178131103515625 +71344 0.014678955078125 +71345 0.215576171875 +71346 0.01409912109375 +71347 0.211456298828125 +71348 0.0106201171875 +71349 0.17523193359375 +71350 0.006500244140625 +71351 0.128753662109375 +71352 0.004791259765625 +71353 0.1019287109375 +71354 0.003326416015625 +71355 0.0743408203125 +71356 0.001678466796875 +71357 0.04327392578125 +71358 0.002838134765625 +71359 0.038177490234375 +71360 0.00848388671875 +71361 0.076263427734375 +71362 0.01678466796875 +71363 0.14105224609375 +71364 0.02288818359375 +71365 0.186431884765625 +71366 0.024261474609375 +71367 0.188812255859375 +71368 0.019927978515625 +71369 0.1390380859375 +71370 0.010345458984375 +71371 0.041778564453125 +71372 -0.002044677734375 +71373 -0.079437255859375 +71374 -0.016693115234375 +71375 -0.219390869140625 +71376 -0.032501220703125 +71377 -0.367828369140625 +71378 -0.046356201171875 +71379 -0.494873046875 +71380 -0.053619384765625 +71381 -0.556243896484375 +71382 -0.049713134765625 +71383 -0.508697509765625 +71384 -0.037017822265625 +71385 -0.3756103515625 +71386 -0.021942138671875 +71387 -0.218902587890625 +71388 -0.00701904296875 +71389 -0.063751220703125 +71390 0.0079345703125 +71391 0.091552734375 +71392 0.0218505859375 +71393 0.23602294921875 +71394 0.03204345703125 +71395 0.342987060546875 +71396 0.0367431640625 +71397 0.39520263671875 +71398 0.03564453125 +71399 0.389373779296875 +71400 0.028656005859375 +71401 0.324249267578125 +71402 0.018341064453125 +71403 0.224090576171875 +71404 0.00836181640625 +71405 0.124267578125 +71406 -3.0517578125e-05 +71407 0.037078857421875 +71408 -0.0040283203125 +71409 -0.010101318359375 +71410 -0.003936767578125 +71411 -0.019439697265625 +71412 -0.00311279296875 +71413 -0.022796630859375 +71414 0.000274658203125 +71415 -0.001556396484375 +71416 0.00738525390625 +71417 0.056304931640625 +71418 0.013580322265625 +71419 0.106719970703125 +71420 0.013336181640625 +71421 0.096893310546875 +71422 0.008270263671875 +71423 0.042694091796875 +71424 0.002593994140625 +71425 -0.018035888671875 +71426 -0.00286865234375 +71427 -0.07586669921875 +71428 -0.007537841796875 +71429 -0.11944580078125 +71430 -0.01202392578125 +71431 -0.15972900390625 +71432 -0.0166015625 +71433 -0.202606201171875 +71434 -0.02117919921875 +71435 -0.24859619140625 +71436 -0.02618408203125 +71437 -0.30517578125 +71438 -0.030853271484375 +71439 -0.36212158203125 +71440 -0.033172607421875 +71441 -0.39141845703125 +71442 -0.030426025390625 +71443 -0.35528564453125 +71444 -0.022369384765625 +71445 -0.249969482421875 +71446 -0.010284423828125 +71447 -0.092864990234375 +71448 0.0037841796875 +71449 0.08905029296875 +71450 0.015411376953125 +71451 0.2352294921875 +71452 0.022613525390625 +71453 0.318817138671875 +71454 0.026641845703125 +71455 0.358642578125 +71456 0.026947021484375 +71457 0.347747802734375 +71458 0.0234375 +71459 0.28564453125 +71460 0.01971435546875 +71461 0.223175048828125 +71462 0.018341064453125 +71463 0.196746826171875 +71464 0.01739501953125 +71465 0.179840087890625 +71466 0.01568603515625 +71467 0.155548095703125 +71468 0.015167236328125 +71469 0.151214599609375 +71470 0.01513671875 +71471 0.156951904296875 +71472 0.0126953125 +71473 0.13177490234375 +71474 0.00970458984375 +71475 0.100799560546875 +71476 0.007843017578125 +71477 0.087127685546875 +71478 0.004608154296875 +71479 0.05487060546875 +71480 -0.000885009765625 +71481 -0.009002685546875 +71482 -0.008544921875 +71483 -0.10400390625 +71484 -0.018280029296875 +71485 -0.229400634765625 +71486 -0.027923583984375 +71487 -0.35552978515625 +71488 -0.034515380859375 +71489 -0.441925048828125 +71490 -0.037017822265625 +71491 -0.473846435546875 +71492 -0.036376953125 +71493 -0.464813232421875 +71494 -0.03289794921875 +71495 -0.419097900390625 +71496 -0.02642822265625 +71497 -0.334320068359375 +71498 -0.01824951171875 +71499 -0.227935791015625 +71500 -0.010101318359375 +71501 -0.12347412109375 +71502 -0.00250244140625 +71503 -0.02764892578125 +71504 0.00579833984375 +71505 0.077667236328125 +71506 0.0162353515625 +71507 0.2132568359375 +71508 0.02947998046875 +71509 0.38885498046875 +71510 0.0439453125 +71511 0.582794189453125 +71512 0.055206298828125 +71513 0.734039306640625 +71514 0.0601806640625 +71515 0.800140380859375 +71516 0.058685302734375 +71517 0.7783203125 +71518 0.05047607421875 +71519 0.6651611328125 +71520 0.035491943359375 +71521 0.45965576171875 +71522 0.016448974609375 +71523 0.199188232421875 +71524 -0.00189208984375 +71525 -0.050689697265625 +71526 -0.015411376953125 +71527 -0.23297119140625 +71528 -0.0228271484375 +71529 -0.33013916015625 +71530 -0.0260009765625 +71531 -0.368408203125 +71532 -0.02716064453125 +71533 -0.378936767578125 +71534 -0.027435302734375 +71535 -0.376983642578125 +71536 -0.02801513671875 +71537 -0.37969970703125 +71538 -0.0291748046875 +71539 -0.391510009765625 +71540 -0.028961181640625 +71541 -0.385345458984375 +71542 -0.025970458984375 +71543 -0.3419189453125 +71544 -0.021728515625 +71545 -0.28289794921875 +71546 -0.019378662109375 +71547 -0.251617431640625 +71548 -0.020233154296875 +71549 -0.266143798828125 +71550 -0.020477294921875 +71551 -0.273345947265625 +71552 -0.016082763671875 +71553 -0.216796875 +71554 -0.00933837890625 +71555 -0.128265380859375 +71556 -0.00457763671875 +71557 -0.068145751953125 +71558 -0.0023193359375 +71559 -0.0430908203125 +71560 -0.000518798828125 +71561 -0.024444580078125 +71562 0.00311279296875 +71563 0.020721435546875 +71564 0.0108642578125 +71565 0.124481201171875 +71566 0.0206298828125 +71567 0.25787353515625 +71568 0.0294189453125 +71569 0.379119873046875 +71570 0.03662109375 +71571 0.47991943359375 +71572 0.0399169921875 +71573 0.5281982421875 +71574 0.03839111328125 +71575 0.511138916015625 +71576 0.0340576171875 +71577 0.456207275390625 +71578 0.03009033203125 +71579 0.407470703125 +71580 0.02789306640625 +71581 0.383758544921875 +71582 0.02545166015625 +71583 0.35687255859375 +71584 0.021728515625 +71585 0.31182861328125 +71586 0.01690673828125 +71587 0.250885009765625 +71588 0.0103759765625 +71589 0.1654052734375 +71590 0.000732421875 +71591 0.035247802734375 +71592 -0.01214599609375 +71593 -0.142059326171875 +71594 -0.026031494140625 +71595 -0.33563232421875 +71596 -0.0401611328125 +71597 -0.5345458984375 +71598 -0.053314208984375 +71599 -0.72186279296875 +71600 -0.061126708984375 +71601 -0.836669921875 +71602 -0.060302734375 +71603 -0.8326416015625 +71604 -0.05230712890625 +71605 -0.7296142578125 +71606 -0.04119873046875 +71607 -0.582550048828125 +71608 -0.030487060546875 +71609 -0.440093994140625 +71610 -0.021728515625 +71611 -0.324310302734375 +71612 -0.01251220703125 +71613 -0.20147705078125 +71614 -0.00091552734375 +71615 -0.044647216796875 +71616 0.00994873046875 +71617 0.103973388671875 +71618 0.017059326171875 +71619 0.202392578125 +71620 0.02142333984375 +71621 0.264495849609375 +71622 0.02655029296875 +71623 0.338897705078125 +71624 0.03375244140625 +71625 0.443817138671875 +71626 0.04058837890625 +71627 0.545074462890625 +71628 0.0452880859375 +71629 0.6173095703125 +71630 0.047271728515625 +71631 0.6524658203125 +71632 0.047515869140625 +71633 0.66339111328125 +71634 0.046478271484375 +71635 0.6561279296875 +71636 0.04241943359375 +71637 0.606781005859375 +71638 0.034393310546875 +71639 0.501190185546875 +71640 0.02337646484375 +71641 0.352783203125 +71642 0.010467529296875 +71643 0.176544189453125 +71644 -0.004791259765625 +71645 -0.034820556640625 +71646 -0.020751953125 +71647 -0.258209228515625 +71648 -0.033721923828125 +71649 -0.44244384765625 +71650 -0.0428466796875 +71651 -0.5753173828125 +71652 -0.047821044921875 +71653 -0.65203857421875 +71654 -0.04644775390625 +71655 -0.641632080078125 +71656 -0.040130615234375 +71657 -0.562164306640625 +71658 -0.032073974609375 +71659 -0.458038330078125 +71660 -0.023834228515625 +71661 -0.350555419921875 +71662 -0.01690673828125 +71663 -0.260528564453125 +71664 -0.011627197265625 +71665 -0.192108154296875 +71666 -0.00775146484375 +71667 -0.141937255859375 +71668 -0.004730224609375 +71669 -0.1021728515625 +71670 -0.001861572265625 +71671 -0.062896728515625 +71672 0.001708984375 +71673 -0.011932373046875 +71674 0.006866455078125 +71675 0.062835693359375 +71676 0.012725830078125 +71677 0.148712158203125 +71678 0.019012451171875 +71679 0.241729736328125 +71680 0.02593994140625 +71681 0.34912109375 +71682 0.031829833984375 +71683 0.457305908203125 +71684 0.03515625 +71685 0.54388427734375 +71686 0.034881591796875 +71687 0.5728759765625 +71688 0.02984619140625 +71689 0.506591796875 +71690 0.020660400390625 +71691 0.351226806640625 +71692 0.00921630859375 +71693 0.146514892578125 +71694 -0.002105712890625 +71695 -0.05523681640625 +71696 -0.011566162109375 +71697 -0.21624755859375 +71698 -0.018951416015625 +71699 -0.334930419921875 +71700 -0.02374267578125 +71701 -0.402984619140625 +71702 -0.02667236328125 +71703 -0.4412841796875 +71704 -0.029541015625 +71705 -0.49578857421875 +71706 -0.032135009765625 +71707 -0.5601806640625 +71708 -0.03314208984375 +71709 -0.600738525390625 +71710 -0.03131103515625 +71711 -0.584228515625 +71712 -0.025482177734375 +71713 -0.47930908203125 +71714 -0.0155029296875 +71715 -0.27935791015625 +71716 -0.00250244140625 +71717 -0.0089111328125 +71718 0.0108642578125 +71719 0.268798828125 +71720 0.021575927734375 +71721 0.482818603515625 +71722 0.02838134765625 +71723 0.60369873046875 +71724 0.031890869140625 +71725 0.650421142578125 +71726 0.033721923828125 +71727 0.66400146484375 +71728 0.033660888671875 +71729 0.6414794921875 +71730 0.031280517578125 +71731 0.572540283203125 +71732 0.0281982421875 +71733 0.498138427734375 +71734 0.025299072265625 +71735 0.439453125 +71736 0.02178955078125 +71737 0.375518798828125 +71738 0.016448974609375 +71739 0.274505615234375 +71740 0.008270263671875 +71741 0.1087646484375 +71742 -0.001739501953125 +71743 -0.099395751953125 +71744 -0.012237548828125 +71745 -0.3182373046875 +71746 -0.023162841796875 +71747 -0.5489501953125 +71748 -0.033660888671875 +71749 -0.7738037109375 +71750 -0.04156494140625 +71751 -0.86383056640625 +71752 -0.045501708984375 +71753 -0.870391845703125 +71754 -0.046142578125 +71755 -0.86895751953125 +71756 -0.043975830078125 +71757 -0.861053466796875 +71758 -0.038330078125 +71759 -0.765869140625 +71760 -0.02874755859375 +71761 -0.5301513671875 +71762 -0.01556396484375 +71763 -0.214691162109375 +71764 -0.000518798828125 +71765 0.137359619140625 +71766 0.014251708984375 +71767 0.474822998046875 +71768 0.0272216796875 +71769 0.76239013671875 +71770 0.037261962890625 +71771 0.867462158203125 +71772 0.0443115234375 +71773 0.870361328125 +71774 0.047821044921875 +71775 0.86480712890625 +71776 0.0479736328125 +71777 0.831817626953125 +71778 0.045684814453125 +71779 0.677581787109375 +71780 0.041168212890625 +71781 0.495880126953125 +71782 0.03515625 +71783 0.30767822265625 +71784 0.027740478515625 +71785 0.116180419921875 +71786 0.017669677734375 +71787 -0.110748291015625 +71788 0.004669189453125 +71789 -0.381805419921875 +71790 -0.009490966796875 +71791 -0.6572265625 +71792 -0.022369384765625 +71793 -0.857421875 +71794 -0.032196044921875 +71795 -0.870391845703125 +71796 -0.03863525390625 +71797 -0.870391845703125 +71798 -0.042755126953125 +71799 -0.86444091796875 +71800 -0.045928955078125 +71801 -0.85723876953125 +71802 -0.047393798828125 +71803 -0.790008544921875 +71804 -0.044952392578125 +71805 -0.62847900390625 +71806 -0.0384521484375 +71807 -0.3956298828125 +71808 -0.0291748046875 +71809 -0.126708984375 +71810 -0.0181884765625 +71811 0.150115966796875 +71812 -0.005950927734375 +71813 0.424041748046875 +71814 0.00640869140625 +71815 0.670623779296875 +71816 0.017303466796875 +71817 0.854522705078125 +71818 0.026031494140625 +71819 0.866485595703125 +71820 0.03192138671875 +71821 0.86920166015625 +71822 0.03570556640625 +71823 0.8653564453125 +71824 0.037872314453125 +71825 0.857147216796875 +71826 0.03826904296875 +71827 0.766845703125 +71828 0.037078857421875 +71829 0.628509521484375 +71830 0.03399658203125 +71831 0.462127685546875 +71832 0.029998779296875 +71833 0.297210693359375 +71834 0.025543212890625 +71835 0.14862060546875 +71836 0.019744873046875 +71837 -0.00537109375 +71838 0.012908935546875 +71839 -0.15753173828125 +71840 0.004913330078125 +71841 -0.31304931640625 +71842 -0.0047607421875 +71843 -0.48876953125 +71844 -0.01422119140625 +71845 -0.6416015625 +71846 -0.0224609375 +71847 -0.751373291015625 +71848 -0.030364990234375 +71849 -0.84619140625 +71850 -0.03729248046875 +71851 -0.861297607421875 +71852 -0.04193115234375 +71853 -0.863250732421875 +71854 -0.042999267578125 +71855 -0.856597900390625 +71856 -0.040985107421875 +71857 -0.7498779296875 +71858 -0.038177490234375 +71859 -0.624542236328125 +71860 -0.03369140625 +71861 -0.47808837890625 +71862 -0.02520751953125 +71863 -0.253387451171875 +71864 -0.014556884765625 +71865 0.003692626953125 +71866 -0.004486083984375 +71867 0.2257080078125 +71868 0.005462646484375 +71869 0.427154541015625 +71870 0.01654052734375 +71871 0.643218994140625 +71872 0.028350830078125 +71873 0.855926513671875 +71874 0.03857421875 +71875 0.870361328125 +71876 0.045257568359375 +71877 0.870361328125 +71878 0.048675537109375 +71879 0.862762451171875 +71880 0.0487060546875 +71881 0.79669189453125 +71882 0.04498291015625 +71883 0.595794677734375 +71884 0.038665771484375 +71885 0.362152099609375 +71886 0.0308837890625 +71887 0.1270751953125 +71888 0.022491455078125 +71889 -0.086944580078125 +71890 0.013580322265625 +71891 -0.2784423828125 +71892 0.00274658203125 +71893 -0.484832763671875 +71894 -0.010711669921875 +71895 -0.729583740234375 +71896 -0.0247802734375 +71897 -0.86688232421875 +71898 -0.036956787109375 +71899 -0.870391845703125 +71900 -0.046966552734375 +71901 -0.86859130859375 +71902 -0.05474853515625 +71903 -0.86279296875 +71904 -0.058868408203125 +71905 -0.817962646484375 +71906 -0.057525634765625 +71907 -0.6116943359375 +71908 -0.050445556640625 +71909 -0.3128662109375 +71910 -0.03900146484375 +71911 0.039398193359375 +71912 -0.024017333984375 +71913 0.422821044921875 +71914 -0.006805419921875 +71915 0.805145263671875 +71916 0.00982666015625 +71917 0.870361328125 +71918 0.02362060546875 +71919 0.870361328125 +71920 0.034088134765625 +71921 0.860015869140625 +71922 0.04095458984375 +71923 0.727935791015625 +71924 0.04400634765625 +71925 0.48114013671875 +71926 0.044219970703125 +71927 0.2059326171875 +71928 0.04248046875 +71929 -0.06103515625 +71930 0.0391845703125 +71931 -0.29913330078125 +71932 0.03375244140625 +71933 -0.516204833984375 +71934 0.025634765625 +71935 -0.7252197265625 +71936 0.015625 +71937 -0.85980224609375 +71938 0.005523681640625 +71939 -0.870391845703125 +71940 -0.003387451171875 +71941 -0.870391845703125 +71942 -0.010711669921875 +71943 -0.858062744140625 +71944 -0.016326904296875 +71945 -0.673004150390625 +71946 -0.020599365234375 +71947 -0.42694091796875 +71948 -0.02386474609375 +71949 -0.2100830078125 +71950 -0.026092529296875 +71951 -0.0362548828125 +71952 -0.02703857421875 +71953 0.10943603515625 +71954 -0.026641845703125 +71955 0.23516845703125 +71956 -0.024658203125 +71957 0.373687744140625 +71958 -0.021209716796875 +71959 0.517791748046875 +71960 -0.016998291015625 +71961 0.602783203125 +71962 -0.01214599609375 +71963 0.635711669921875 +71964 -0.00665283203125 +71965 0.655181884765625 +71966 -0.00079345703125 +71967 0.65948486328125 +71968 0.00506591796875 +71969 0.651275634765625 +71970 0.010498046875 +71971 0.61846923828125 +71972 0.015045166015625 +71973 0.53753662109375 +71974 0.0184326171875 +71975 0.404144287109375 +71976 0.02044677734375 +71977 0.22186279296875 +71978 0.0211181640625 +71979 0.003997802734375 +71980 0.020538330078125 +71981 -0.22100830078125 +71982 0.018890380859375 +71983 -0.42449951171875 +71984 0.016448974609375 +71985 -0.579833984375 +71986 0.013641357421875 +71987 -0.641876220703125 +71988 0.01055908203125 +71989 -0.6177978515625 +71990 0.006866455078125 +71991 -0.575531005859375 +71992 0.002716064453125 +71993 -0.526336669921875 +71994 -0.00128173828125 +71995 -0.42645263671875 +71996 -0.00469970703125 +71997 -0.2581787109375 +71998 -0.00762939453125 +71999 -0.068695068359375 +72000 -0.010223388671875 +72001 0.09222412109375 +72002 -0.012237548828125 +72003 0.232147216796875 +72004 -0.013519287109375 +72005 0.3509521484375 +72006 -0.0142822265625 +72007 0.410064697265625 +72008 -0.0147705078125 +72009 0.372955322265625 +72010 -0.014892578125 +72011 0.2554931640625 +72012 -0.014312744140625 +72013 0.10711669921875 +72014 -0.01300048828125 +72015 -0.052886962890625 +72016 -0.01080322265625 +72017 -0.186279296875 +72018 -0.0074462890625 +72019 -0.23291015625 +72020 -0.0032958984375 +72021 -0.209442138671875 +72022 0.00091552734375 +72023 -0.174163818359375 +72024 0.004974365234375 +72025 -0.126739501953125 +72026 0.008819580078125 +72027 -0.048126220703125 +72028 0.01214599609375 +72029 0.0426025390625 +72030 0.014495849609375 +72031 0.10748291015625 +72032 0.015777587890625 +72033 0.1409912109375 +72034 0.016387939453125 +72035 0.19708251953125 +72036 0.016357421875 +72037 0.273651123046875 +72038 0.01531982421875 +72039 0.31768798828125 +72040 0.01348876953125 +72041 0.341094970703125 +72042 0.01116943359375 +72043 0.368011474609375 +72044 0.00830078125 +72045 0.37249755859375 +72046 0.004608154296875 +72047 0.30072021484375 +72048 0.000274658203125 +72049 0.1517333984375 +72050 -0.003997802734375 +72051 -0.01470947265625 +72052 -0.00799560546875 +72053 -0.1883544921875 +72054 -0.011627197265625 +72055 -0.372711181640625 +72056 -0.01434326171875 +72057 -0.51397705078125 +72058 -0.015777587890625 +72059 -0.57177734375 +72060 -0.015838623046875 +72061 -0.53948974609375 +72062 -0.0146484375 +72063 -0.43511962890625 +72064 -0.012542724609375 +72065 -0.2962646484375 +72066 -0.0098876953125 +72067 -0.161102294921875 +72068 -0.006927490234375 +72069 -0.0435791015625 +72070 -0.003753662109375 +72071 0.060394287109375 +72072 -0.0006103515625 +72073 0.13665771484375 +72074 0.002197265625 +72075 0.170135498046875 +72076 0.004608154296875 +72077 0.16552734375 +72078 0.0067138671875 +72079 0.15728759765625 +72080 0.00848388671875 +72081 0.150787353515625 +72082 0.009613037109375 +72083 0.12200927734375 +72084 0.0101318359375 +72085 0.080108642578125 +72086 0.010223388671875 +72087 0.05126953125 +72088 0.01007080078125 +72089 0.062896728515625 +72090 0.009552001953125 +72091 0.09271240234375 +72092 0.00836181640625 +72093 0.092987060546875 +72094 0.00665283203125 +72095 0.07855224609375 +72096 0.004669189453125 +72097 0.06427001953125 +72098 0.002410888671875 +72099 0.0347900390625 +72100 0.0 +72101 -0.01171875 +72102 -0.0023193359375 +72103 -0.056060791015625 +72104 -0.00408935546875 +72105 -0.055511474609375 +72106 -0.005218505859375 +72107 -0.010467529296875 +72108 -0.006103515625 +72109 0.02508544921875 +72110 -0.006866455078125 +72111 0.025665283203125 +72112 -0.00726318359375 +72113 0.017333984375 +72114 -0.007293701171875 +72115 0.00189208984375 +72116 -0.007049560546875 +72117 -0.03173828125 +72118 -0.0064697265625 +72119 -0.071502685546875 +72120 -0.005767822265625 +72121 -0.13543701171875 +72122 -0.004974365234375 +72123 -0.219970703125 +72124 -0.00396728515625 +72125 -0.300506591796875 +72126 -0.002838134765625 +72127 -0.376312255859375 +72128 -0.001434326171875 +72129 -0.416107177734375 +72130 0.000518798828125 +72131 -0.371124267578125 +72132 0.002899169921875 +72133 -0.242279052734375 +72134 0.00531005859375 +72135 -0.069732666015625 +72136 0.007537841796875 +72137 0.125640869140625 +72138 0.009307861328125 +72139 0.31268310546875 +72140 0.01031494140625 +72141 0.45501708984375 +72142 0.0106201171875 +72143 0.554779052734375 +72144 0.01025390625 +72145 0.61065673828125 +72146 0.0091552734375 +72147 0.610931396484375 +72148 0.0072021484375 +72149 0.531463623046875 +72150 0.004608154296875 +72151 0.3883056640625 +72152 0.00189208984375 +72153 0.23468017578125 +72154 -0.0006103515625 +72155 0.095245361328125 +72156 -0.00262451171875 +72157 -0.00396728515625 +72158 -0.0040283203125 +72159 -0.04852294921875 +72160 -0.0048828125 +72161 -0.055145263671875 +72162 -0.00555419921875 +72163 -0.0758056640625 +72164 -0.0062255859375 +72165 -0.138702392578125 +72166 -0.00665283203125 +72167 -0.209197998046875 +72168 -0.006866455078125 +72169 -0.289031982421875 +72170 -0.006866455078125 +72171 -0.37884521484375 +72172 -0.006561279296875 +72173 -0.456329345703125 +72174 -0.005950927734375 +72175 -0.51641845703125 +72176 -0.0047607421875 +72177 -0.519287109375 +72178 -0.003021240234375 +72179 -0.458251953125 +72180 -0.001220703125 +72181 -0.384796142578125 +72182 0.000335693359375 +72183 -0.323699951171875 +72184 0.001678466796875 +72185 -0.269287109375 +72186 0.002960205078125 +72187 -0.1951904296875 +72188 0.004150390625 +72189 -0.100006103515625 +72190 0.005035400390625 +72191 -0.01055908203125 +72192 0.00567626953125 +72193 0.1033935546875 +72194 0.006195068359375 +72195 0.24908447265625 +72196 0.00653076171875 +72197 0.373199462890625 +72198 0.006591796875 +72199 0.45806884765625 +72200 0.00634765625 +72201 0.511474609375 +72202 0.005767822265625 +72203 0.565399169921875 +72204 0.004852294921875 +72205 0.61138916015625 +72206 0.003662109375 +72207 0.5897216796875 +72208 0.00225830078125 +72209 0.4906005859375 +72210 0.000701904296875 +72211 0.33148193359375 +72212 -0.0008544921875 +72213 0.147796630859375 +72214 -0.0023193359375 +72215 -0.01873779296875 +72216 -0.00360107421875 +72217 -0.140289306640625 +72218 -0.004608154296875 +72219 -0.191986083984375 +72220 -0.00531005859375 +72221 -0.184295654296875 +72222 -0.00567626953125 +72223 -0.161834716796875 +72224 -0.005706787109375 +72225 -0.166595458984375 +72226 -0.005401611328125 +72227 -0.19390869140625 +72228 -0.004791259765625 +72229 -0.22442626953125 +72230 -0.00390625 +72231 -0.279754638671875 +72232 -0.0028076171875 +72233 -0.3389892578125 +72234 -0.001556396484375 +72235 -0.3543701171875 +72236 -0.000213623046875 +72237 -0.348175048828125 +72238 0.0010986328125 +72239 -0.32598876953125 +72240 0.0023193359375 +72241 -0.2581787109375 +72242 0.003387451171875 +72243 -0.139801025390625 +72244 0.004241943359375 +72245 0.014617919921875 +72246 0.004852294921875 +72247 0.144378662109375 +72248 0.00518798828125 +72249 0.221038818359375 +72250 0.005218505859375 +72251 0.27069091796875 +72252 0.004974365234375 +72253 0.294036865234375 +72254 0.00445556640625 +72255 0.311767578125 +72256 0.003753662109375 +72257 0.339141845703125 +72258 0.00323486328125 +72259 0.360260009765625 +72260 0.002838134765625 +72261 0.360504150390625 +72262 0.001739501953125 +72263 0.308380126953125 +72264 -0.00067138671875 +72265 0.18170166015625 +72266 -0.003875732421875 +72267 0.0047607421875 +72268 -0.00689697265625 +72269 -0.17559814453125 +72270 -0.008758544921875 +72271 -0.3143310546875 +72272 -0.008544921875 +72273 -0.36785888671875 +72274 -0.006988525390625 +72275 -0.36248779296875 +72276 -0.0052490234375 +72277 -0.343536376953125 +72278 -0.003173828125 +72279 -0.3018798828125 +72280 -0.00067138671875 +72281 -0.231414794921875 +72282 0.002532958984375 +72283 -0.117645263671875 +72284 0.005615234375 +72285 0.007049560546875 +72286 0.00732421875 +72287 0.087982177734375 +72288 0.008026123046875 +72289 0.13946533203125 +72290 0.008056640625 +72291 0.17425537109375 +72292 0.007415771484375 +72293 0.188201904296875 +72294 0.00592041015625 +72295 0.171234130859375 +72296 0.00347900390625 +72297 0.118438720703125 +72298 0.0008544921875 +72299 0.05706787109375 +72300 -0.001800537109375 +72301 -0.010711669921875 +72302 -0.004608154296875 +72303 -0.0914306640625 +72304 -0.006988525390625 +72305 -0.162322998046875 +72306 -0.00823974609375 +72307 -0.194549560546875 +72308 -0.007415771484375 +72309 -0.1492919921875 +72310 -0.004364013671875 +72311 -0.02166748046875 +72312 -0.00067138671875 +72313 0.124053955078125 +72314 0.001800537109375 +72315 0.211151123046875 +72316 0.003021240234375 +72317 0.240447998046875 +72318 0.00372314453125 +72319 0.242218017578125 +72320 0.00408935546875 +72321 0.2257080078125 +72322 0.004119873046875 +72323 0.194366455078125 +72324 0.003021240234375 +72325 0.115509033203125 +72326 0.0013427734375 +72327 0.0128173828125 +72328 0.000457763671875 +72329 -0.053802490234375 +72330 -0.000274658203125 +72331 -0.110626220703125 +72332 -0.00189208984375 +72333 -0.199493408203125 +72334 -0.003814697265625 +72335 -0.29437255859375 +72336 -0.0045166015625 +72337 -0.33221435546875 +72338 -0.00323486328125 +72339 -0.27972412109375 +72340 -0.0010986328125 +72341 -0.185333251953125 +72342 0.0 +72343 -0.128204345703125 +72344 -9.1552734375e-05 +72345 -0.115692138671875 +72346 -0.0006103515625 +72347 -0.116455078125 +72348 -0.000946044921875 +72349 -0.105926513671875 +72350 -0.000335693359375 +72351 -0.053955078125 +72352 0.00146484375 +72353 0.048797607421875 +72354 0.003387451171875 +72355 0.157318115234375 +72356 0.004058837890625 +72357 0.212005615234375 +72358 0.003631591796875 +72359 0.218475341796875 +72360 0.003570556640625 +72361 0.23724365234375 +72362 0.00482177734375 +72363 0.30535888671875 +72364 0.006378173828125 +72365 0.38128662109375 +72366 0.0068359375 +72367 0.404449462890625 +72368 0.00665283203125 +72369 0.3944091796875 +72370 0.006744384765625 +72371 0.3885498046875 +72372 0.006500244140625 +72373 0.362640380859375 +72374 0.0048828125 +72375 0.27362060546875 +72376 0.001739501953125 +72377 0.11712646484375 +72378 -0.001708984375 +72379 -0.054901123046875 +72380 -0.004241943359375 +72381 -0.19085693359375 +72382 -0.005828857421875 +72383 -0.28570556640625 +72384 -0.0064697265625 +72385 -0.339263916015625 +72386 -0.0068359375 +72387 -0.3775634765625 +72388 -0.008026123046875 +72389 -0.445709228515625 +72390 -0.00982666015625 +72391 -0.535064697265625 +72392 -0.011871337890625 +72393 -0.629058837890625 +72394 -0.013427734375 +72395 -0.697601318359375 +72396 -0.013641357421875 +72397 -0.70391845703125 +72398 -0.012359619140625 +72399 -0.6424560546875 +72400 -0.009033203125 +72401 -0.491241455078125 +72402 -0.0040283203125 +72403 -0.265716552734375 +72404 0.001220703125 +72405 -0.023712158203125 +72406 0.0059814453125 +72407 0.201751708984375 +72408 0.009429931640625 +72409 0.375823974609375 +72410 0.011322021484375 +72411 0.485076904296875 +72412 0.012664794921875 +72413 0.56884765625 +72414 0.013671875 +72415 0.634765625 +72416 0.01324462890625 +72417 0.63763427734375 +72418 0.01116943359375 +72419 0.5660400390625 +72420 0.008697509765625 +72421 0.4720458984375 +72422 0.007080078125 +72423 0.40692138671875 +72424 0.006500244140625 +72425 0.3778076171875 +72426 0.006744384765625 +72427 0.376953125 +72428 0.006988525390625 +72429 0.371978759765625 +72430 0.006011962890625 +72431 0.313140869140625 +72432 0.003387451171875 +72433 0.184417724609375 +72434 -0.000244140625 +72435 0.011199951171875 +72436 -0.0040283203125 +72437 -0.171051025390625 +72438 -0.00738525390625 +72439 -0.33740234375 +72440 -0.010009765625 +72441 -0.47198486328125 +72442 -0.0115966796875 +72443 -0.560394287109375 +72444 -0.01165771484375 +72445 -0.58056640625 +72446 -0.01055908203125 +72447 -0.54754638671875 +72448 -0.00958251953125 +72449 -0.508575439453125 +72450 -0.008392333984375 +72451 -0.459503173828125 +72452 -0.007049560546875 +72453 -0.394378662109375 +72454 -0.00762939453125 +72455 -0.35260009765625 +72456 -0.00872802734375 +72457 -0.31170654296875 +72458 -0.006011962890625 +72459 -0.197418212890625 +72460 0.00079345703125 +72461 -0.007965087890625 +72462 0.00909423828125 +72463 0.207489013671875 +72464 0.016845703125 +72465 0.409210205078125 +72466 0.0228271484375 +72467 0.57208251953125 +72468 0.0255126953125 +72469 0.66595458984375 +72470 0.023223876953125 +72471 0.65875244140625 +72472 0.016998291015625 +72473 0.56744384765625 +72474 0.00909423828125 +72475 0.431396484375 +72476 0.001953125 +72477 0.29443359375 +72478 -0.00299072265625 +72479 0.182464599609375 +72480 -0.00762939453125 +72481 0.06365966796875 +72482 -0.012847900390625 +72483 -0.075958251953125 +72484 -0.01617431640625 +72485 -0.189422607421875 +72486 -0.017486572265625 +72487 -0.271942138671875 +72488 -0.01806640625 +72489 -0.342529296875 +72490 -0.01605224609375 +72491 -0.364166259765625 +72492 -0.011077880859375 +72493 -0.327239990234375 +72494 -0.005828857421875 +72495 -0.2769775390625 +72496 -0.002655029296875 +72497 -0.253692626953125 +72498 -0.000885009765625 +72499 -0.24365234375 +72500 0.00213623046875 +72501 -0.1983642578125 +72502 0.006500244140625 +72503 -0.116241455078125 +72504 0.010009765625 +72505 -0.036834716796875 +72506 0.012451171875 +72507 0.034881591796875 +72508 0.013519287109375 +72509 0.09124755859375 +72510 0.012054443359375 +72511 0.10888671875 +72512 0.010284423828125 +72513 0.125518798828125 +72514 0.00927734375 +72515 0.15771484375 +72516 0.007659912109375 +72517 0.17828369140625 +72518 0.00469970703125 +72519 0.17108154296875 +72520 0.00018310546875 +72521 0.129974365234375 +72522 -0.00421142578125 +72523 0.082427978515625 +72524 -0.0084228515625 +72525 0.027679443359375 +72526 -0.01416015625 +72527 -0.065643310546875 +72528 -0.019287109375 +72529 -0.15936279296875 +72530 -0.021575927734375 +72531 -0.21307373046875 +72532 -0.021514892578125 +72533 -0.234649658203125 +72534 -0.01788330078125 +72535 -0.2001953125 +72536 -0.01129150390625 +72537 -0.119171142578125 +72538 -0.003753662109375 +72539 -0.024749755859375 +72540 0.0047607421875 +72541 0.085784912109375 +72542 0.01214599609375 +72543 0.178131103515625 +72544 0.016265869140625 +72545 0.215576171875 +72546 0.01776123046875 +72547 0.211456298828125 +72548 0.017120361328125 +72549 0.17523193359375 +72550 0.015472412109375 +72551 0.128753662109375 +72552 0.01446533203125 +72553 0.1019287109375 +72554 0.012939453125 +72555 0.0743408203125 +72556 0.0107421875 +72557 0.04327392578125 +72558 0.009552001953125 +72559 0.038177490234375 +72560 0.010406494140625 +72561 0.076263427734375 +72562 0.012420654296875 +72563 0.14105224609375 +72564 0.01312255859375 +72565 0.186431884765625 +72566 0.011322021484375 +72567 0.188812255859375 +72568 0.006622314453125 +72569 0.1390380859375 +72570 -0.000579833984375 +72571 0.041778564453125 +72572 -0.008880615234375 +72573 -0.079437255859375 +72574 -0.017913818359375 +72575 -0.219390869140625 +72576 -0.027008056640625 +72577 -0.367828369140625 +72578 -0.03448486328125 +72579 -0.494873046875 +72580 -0.037841796875 +72581 -0.556243896484375 +72582 -0.034698486328125 +72583 -0.508697509765625 +72584 -0.026397705078125 +72585 -0.3756103515625 +72586 -0.0164794921875 +72587 -0.218902587890625 +72588 -0.006439208984375 +72589 -0.063751220703125 +72590 0.003692626953125 +72591 0.091552734375 +72592 0.01324462890625 +72593 0.23602294921875 +72594 0.0206298828125 +72595 0.342987060546875 +72596 0.02484130859375 +72597 0.39520263671875 +72598 0.025634765625 +72599 0.389373779296875 +72600 0.022857666015625 +72601 0.324249267578125 +72602 0.017852783203125 +72603 0.224090576171875 +72604 0.0125732421875 +72605 0.124267578125 +72606 0.007720947265625 +72607 0.037078857421875 +72608 0.004791259765625 +72609 -0.010101318359375 +72610 0.003692626953125 +72611 -0.019439697265625 +72612 0.002685546875 +72613 -0.022796630859375 +72614 0.00286865234375 +72615 -0.001556396484375 +72616 0.00494384765625 +72617 0.056304931640625 +72618 0.006500244140625 +72619 0.106719970703125 +72620 0.004669189453125 +72621 0.096893310546875 +72622 0.00042724609375 +72623 0.042694091796875 +72624 -0.003997802734375 +72625 -0.018035888671875 +72626 -0.008056640625 +72627 -0.07586669921875 +72628 -0.01104736328125 +72629 -0.11944580078125 +72630 -0.0135498046875 +72631 -0.15972900390625 +72632 -0.015899658203125 +72633 -0.202606201171875 +72634 -0.01812744140625 +72635 -0.24859619140625 +72636 -0.02069091796875 +72637 -0.30517578125 +72638 -0.0230712890625 +72639 -0.36212158203125 +72640 -0.02374267578125 +72641 -0.39141845703125 +72642 -0.020660400390625 +72643 -0.35528564453125 +72644 -0.013671875 +72645 -0.249969482421875 +72646 -0.0037841796875 +72647 -0.092864990234375 +72648 0.007354736328125 +72649 0.08905029296875 +72650 0.016357421875 +72651 0.2352294921875 +72652 0.02166748046875 +72653 0.318817138671875 +72654 0.0242919921875 +72655 0.358642578125 +72656 0.023834228515625 +72657 0.347747802734375 +72658 0.020294189453125 +72659 0.28564453125 +72660 0.0164794921875 +72661 0.223175048828125 +72662 0.014495849609375 +72663 0.196746826171875 +72664 0.01287841796875 +72665 0.179840087890625 +72666 0.01068115234375 +72667 0.155548095703125 +72668 0.009521484375 +72669 0.151214599609375 +72670 0.008880615234375 +72671 0.156951904296875 +72672 0.00653076171875 +72673 0.13177490234375 +72674 0.00396728515625 +72675 0.100799560546875 +72676 0.002471923828125 +72677 0.087127685546875 +72678 9.1552734375e-05 +72679 0.05487060546875 +72680 -0.00384521484375 +72681 -0.009002685546875 +72682 -0.009307861328125 +72683 -0.10400390625 +72684 -0.0162353515625 +72685 -0.229400634765625 +72686 -0.02301025390625 +72687 -0.35552978515625 +72688 -0.02734375 +72689 -0.441925048828125 +72690 -0.028472900390625 +72691 -0.473846435546875 +72692 -0.027191162109375 +72693 -0.464813232421875 +72694 -0.023773193359375 +72695 -0.419097900390625 +72696 -0.018157958984375 +72697 -0.334320068359375 +72698 -0.0113525390625 +72699 -0.227935791015625 +72700 -0.004730224609375 +72701 -0.12347412109375 +72702 0.001251220703125 +72703 -0.02764892578125 +72704 0.007537841796875 +72705 0.077667236328125 +72706 0.015533447265625 +72707 0.2132568359375 +72708 0.026580810546875 +72709 0.38885498046875 +72710 0.039459228515625 +72711 0.582794189453125 +72712 0.04925537109375 +72713 0.734039306640625 +72714 0.0526123046875 +72715 0.800140380859375 +72716 0.04949951171875 +72717 0.7783203125 +72718 0.039703369140625 +72719 0.6651611328125 +72720 0.023101806640625 +72721 0.45965576171875 +72722 0.002899169921875 +72723 0.199188232421875 +72724 -0.015380859375 +72725 -0.050689697265625 +72726 -0.0269775390625 +72727 -0.23297119140625 +72728 -0.030670166015625 +72729 -0.33013916015625 +72730 -0.029083251953125 +72731 -0.368408203125 +72732 -0.025238037109375 +72733 -0.378936767578125 +72734 -0.02081298828125 +72735 -0.376983642578125 +72736 -0.017547607421875 +72737 -0.37969970703125 +72738 -0.016021728515625 +72739 -0.391510009765625 +72740 -0.01397705078125 +72741 -0.385345458984375 +72742 -0.009765625 +72743 -0.3419189453125 +72744 -0.005279541015625 +72745 -0.28289794921875 +72746 -0.004241943359375 +72747 -0.251617431640625 +72748 -0.008148193359375 +72749 -0.266143798828125 +72750 -0.01214599609375 +72751 -0.273345947265625 +72752 -0.011077880859375 +72753 -0.216796875 +72754 -0.00750732421875 +72755 -0.128265380859375 +72756 -0.0064697265625 +72757 -0.068145751953125 +72758 -0.008331298828125 +72759 -0.0430908203125 +72760 -0.0103759765625 +72761 -0.024444580078125 +72762 -0.009521484375 +72763 0.020721435546875 +72764 -0.002777099609375 +72765 0.124481201171875 +72766 0.00738525390625 +72767 0.25787353515625 +72768 0.017364501953125 +72769 0.379119873046875 +72770 0.02642822265625 +72771 0.47991943359375 +72772 0.031707763671875 +72773 0.5281982421875 +72774 0.032012939453125 +72775 0.511138916015625 +72776 0.029632568359375 +72777 0.456207275390625 +72778 0.028289794921875 +72779 0.407470703125 +72780 0.02947998046875 +72781 0.383758544921875 +72782 0.030517578125 +72783 0.35687255859375 +72784 0.029876708984375 +72785 0.31182861328125 +72786 0.027587890625 +72787 0.250885009765625 +72788 0.022735595703125 +72789 0.1654052734375 +72790 0.013427734375 +72791 0.035247802734375 +72792 -0.0006103515625 +72793 -0.142059326171875 +72794 -0.0167236328125 +72795 -0.33563232421875 +72796 -0.034027099609375 +72797 -0.5345458984375 +72798 -0.050994873046875 +72799 -0.72186279296875 +72800 -0.062164306640625 +72801 -0.836669921875 +72802 -0.06341552734375 +72803 -0.8326416015625 +72804 -0.056396484375 +72805 -0.7296142578125 +72806 -0.045867919921875 +72807 -0.582550048828125 +72808 -0.03594970703125 +72809 -0.440093994140625 +72810 -0.0284423828125 +72811 -0.324310302734375 +72812 -0.02020263671875 +72813 -0.20147705078125 +72814 -0.00872802734375 +72815 -0.044647216796875 +72816 0.002349853515625 +72817 0.103973388671875 +72818 0.00946044921875 +72819 0.202392578125 +72820 0.013885498046875 +72821 0.264495849609375 +72822 0.019927978515625 +72823 0.338897705078125 +72824 0.029205322265625 +72825 0.443817138671875 +72826 0.0386962890625 +72827 0.545074462890625 +72828 0.046112060546875 +72829 0.6173095703125 +72830 0.050689697265625 +72831 0.6524658203125 +72832 0.053436279296875 +72833 0.66339111328125 +72834 0.054779052734375 +72835 0.6561279296875 +72836 0.052490234375 +72837 0.606781005859375 +72838 0.045196533203125 +72839 0.501190185546875 +72840 0.034027099609375 +72841 0.352783203125 +72842 0.02020263671875 +72843 0.176544189453125 +72844 0.002960205078125 +72845 -0.034820556640625 +72846 -0.015625 +72847 -0.258209228515625 +72848 -0.0311279296875 +72849 -0.44244384765625 +72850 -0.04254150390625 +72851 -0.5753173828125 +72852 -0.0494384765625 +72853 -0.65203857421875 +72854 -0.049041748046875 +72855 -0.641632080078125 +72856 -0.04296875 +72857 -0.562164306640625 +72858 -0.035064697265625 +72859 -0.458038330078125 +72860 -0.027069091796875 +72861 -0.350555419921875 +72862 -0.020721435546875 +72863 -0.260528564453125 +72864 -0.016326904296875 +72865 -0.192108154296875 +72866 -0.013519287109375 +72867 -0.141937255859375 +72868 -0.011474609375 +72869 -0.1021728515625 +72870 -0.00927734375 +72871 -0.062896728515625 +72872 -0.005767822265625 +72873 -0.011932373046875 +72874 0.0001220703125 +72875 0.062835693359375 +72876 0.00732421875 +72877 0.148712158203125 +72878 0.0155029296875 +72879 0.241729736328125 +72880 0.0252685546875 +72881 0.34912109375 +72882 0.035400390625 +72883 0.457305908203125 +72884 0.04388427734375 +72885 0.54388427734375 +72886 0.0474853515625 +72887 0.5728759765625 +72888 0.0428466796875 +72889 0.506591796875 +72890 0.030426025390625 +72891 0.351226806640625 +72892 0.013641357421875 +72893 0.146514892578125 +72894 -0.0029296875 +72895 -0.05523681640625 +72896 -0.016021728515625 +72897 -0.21624755859375 +72898 -0.025543212890625 +72899 -0.334930419921875 +72900 -0.03082275390625 +72901 -0.402984619140625 +72902 -0.03369140625 +72903 -0.4412841796875 +72904 -0.03826904296875 +72905 -0.49578857421875 +72906 -0.043975830078125 +72907 -0.5601806640625 +72908 -0.0478515625 +72909 -0.600738525390625 +72910 -0.04693603515625 +72911 -0.584228515625 +72912 -0.0384521484375 +72913 -0.47930908203125 +72914 -0.021759033203125 +72915 -0.27935791015625 +72916 0.0009765625 +72917 -0.0089111328125 +72918 0.0242919921875 +72919 0.268798828125 +72920 0.041961669921875 +72921 0.482818603515625 +72922 0.051483154296875 +72923 0.60369873046875 +72924 0.054595947265625 +72925 0.650421142578125 +72926 0.054962158203125 +72927 0.66400146484375 +72928 0.052337646484375 +72929 0.6414794921875 +72930 0.045867919921875 +72931 0.572540283203125 +72932 0.0391845703125 +72933 0.498138427734375 +72934 0.034149169921875 +72935 0.439453125 +72936 0.028900146484375 +72937 0.375518798828125 +72938 0.020599365234375 +72939 0.274505615234375 +72940 0.00677490234375 +72941 0.1087646484375 +72942 -0.0106201171875 +72943 -0.099395751953125 +72944 -0.02886962890625 +72945 -0.3182373046875 +72946 -0.048095703125 +72947 -0.5489501953125 +72948 -0.0667724609375 +72949 -0.7738037109375 +72950 -0.080352783203125 +72951 -0.86383056640625 +72952 -0.085968017578125 +72953 -0.870391845703125 +72954 -0.085235595703125 +72955 -0.86895751953125 +72956 -0.079315185546875 +72957 -0.861053466796875 +72958 -0.06671142578125 +72959 -0.765869140625 +72960 -0.04638671875 +72961 -0.5301513671875 +72962 -0.0184326171875 +72963 -0.214691162109375 +72964 0.013153076171875 +72965 0.137359619140625 +72966 0.043243408203125 +72967 0.474822998046875 +72968 0.068450927734375 +72969 0.76239013671875 +72970 0.086212158203125 +72971 0.867462158203125 +72972 0.097076416015625 +72973 0.870361328125 +72974 0.10003662109375 +72975 0.86480712890625 +72976 0.095855712890625 +72977 0.831817626953125 +72978 0.087493896484375 +72979 0.677581787109375 +72980 0.075469970703125 +72981 0.495880126953125 +72982 0.061737060546875 +72983 0.30767822265625 +72984 0.04620361328125 +72985 0.116180419921875 +72986 0.024566650390625 +72987 -0.110748291015625 +72988 -0.00445556640625 +72989 -0.381805419921875 +72990 -0.036285400390625 +72991 -0.6572265625 +72992 -0.064208984375 +72993 -0.857421875 +72994 -0.08355712890625 +72995 -0.870391845703125 +72996 -0.093902587890625 +72997 -0.870391845703125 +72998 -0.09881591796875 +72999 -0.86444091796875 +73000 -0.102813720703125 +73001 -0.85723876953125 +73002 -0.10382080078125 +73003 -0.790008544921875 +73004 -0.0953369140625 +73005 -0.62847900390625 +73006 -0.076873779296875 +73007 -0.3956298828125 +73008 -0.05218505859375 +73009 -0.126708984375 +73010 -0.0242919921875 +73011 0.150115966796875 +73012 0.005706787109375 +73013 0.424041748046875 +73014 0.034942626953125 +73015 0.670623779296875 +73016 0.0592041015625 +73017 0.854522705078125 +73018 0.0767822265625 +73019 0.866485595703125 +73020 0.086212158203125 +73021 0.86920166015625 +73022 0.09002685546875 +73023 0.8653564453125 +73024 0.090118408203125 +73025 0.857147216796875 +73026 0.08636474609375 +73027 0.766845703125 +73028 0.079498291015625 +73029 0.628509521484375 +73030 0.068756103515625 +73031 0.462127685546875 +73032 0.05718994140625 +73033 0.297210693359375 +73034 0.046173095703125 +73035 0.14862060546875 +73036 0.032745361328125 +73037 -0.00537109375 +73038 0.017547607421875 +73039 -0.15753173828125 +73040 -9.1552734375e-05 +73041 -0.31304931640625 +73042 -0.022216796875 +73043 -0.48876953125 +73044 -0.04351806640625 +73045 -0.6416015625 +73046 -0.061370849609375 +73047 -0.751373291015625 +73048 -0.078826904296875 +73049 -0.84619140625 +73050 -0.094390869140625 +73051 -0.861297607421875 +73052 -0.104278564453125 +73053 -0.863250732421875 +73054 -0.104827880859375 +73055 -0.856597900390625 +73056 -0.097564697265625 +73057 -0.7498779296875 +73058 -0.0894775390625 +73059 -0.624542236328125 +73060 -0.077850341796875 +73061 -0.47808837890625 +73062 -0.055511474609375 +73063 -0.253387451171875 +73064 -0.02777099609375 +73065 0.003692626953125 +73066 -0.0025634765625 +73067 0.2257080078125 +73068 0.021820068359375 +73069 0.427154541015625 +73070 0.049530029296875 +73071 0.643218994140625 +73072 0.079681396484375 +73073 0.855926513671875 +73074 0.1055908203125 +73075 0.870361328125 +73076 0.121551513671875 +73077 0.870361328125 +73078 0.128631591796875 +73079 0.862762451171875 +73080 0.126617431640625 +73081 0.79669189453125 +73082 0.114471435546875 +73083 0.595794677734375 +73084 0.095733642578125 +73085 0.362152099609375 +73086 0.073699951171875 +73087 0.1270751953125 +73088 0.05084228515625 +73089 -0.086944580078125 +73090 0.027252197265625 +73091 -0.2784423828125 +73092 -0.001373291015625 +73093 -0.484832763671875 +73094 -0.037567138671875 +73095 -0.729583740234375 +73096 -0.075439453125 +73097 -0.86688232421875 +73098 -0.107666015625 +73099 -0.870391845703125 +73100 -0.13385009765625 +73101 -0.86859130859375 +73102 -0.1539306640625 +73103 -0.86279296875 +73104 -0.163787841796875 +73105 -0.817962646484375 +73106 -0.158111572265625 +73107 -0.6116943359375 +73108 -0.136138916015625 +73109 -0.3128662109375 +73110 -0.101959228515625 +73111 0.039398193359375 +73112 -0.057952880859375 +73113 0.422821044921875 +73114 -0.008087158203125 +73115 0.805145263671875 +73116 0.039520263671875 +73117 0.870361328125 +73118 0.07818603515625 +73119 0.870361328125 +73120 0.10662841796875 +73121 0.860015869140625 +73122 0.124114990234375 +73123 0.727935791015625 +73124 0.130157470703125 +73125 0.48114013671875 +73126 0.1278076171875 +73127 0.2059326171875 +73128 0.119964599609375 +73129 -0.06103515625 +73130 0.107940673828125 +73131 -0.29913330078125 +73132 0.090118408203125 +73133 -0.516204833984375 +73134 0.064788818359375 +73135 -0.7252197265625 +73136 0.03497314453125 +73137 -0.85980224609375 +73138 0.004791259765625 +73139 -0.870391845703125 +73140 -0.022186279296875 +73141 -0.870391845703125 +73142 -0.0401611328125 +73143 -0.858062744140625 +73144 -0.048675537109375 +73145 -0.673004150390625 +73146 -0.05413818359375 +73147 -0.42694091796875 +73148 -0.06195068359375 +73149 -0.2100830078125 +73150 -0.071929931640625 +73151 -0.0362548828125 +73152 -0.0806884765625 +73153 0.10943603515625 +73154 -0.0859375 +73155 0.23516845703125 +73156 -0.082794189453125 +73157 0.373687744140625 +73158 -0.07159423828125 +73159 0.517791748046875 +73160 -0.05999755859375 +73161 0.602783203125 +73162 -0.04742431640625 +73163 0.635711669921875 +73164 -0.02996826171875 +73165 0.655181884765625 +73166 -0.008819580078125 +73167 0.65948486328125 +73168 0.0150146484375 +73169 0.651275634765625 +73170 0.03863525390625 +73171 0.61846923828125 +73172 0.0576171875 +73173 0.53753662109375 +73174 0.069854736328125 +73175 0.404144287109375 +73176 0.074249267578125 +73177 0.22186279296875 +73178 0.071044921875 +73179 0.003997802734375 +73180 0.0625 +73181 -0.22100830078125 +73182 0.0511474609375 +73183 -0.42449951171875 +73184 0.039642333984375 +73185 -0.579833984375 +73186 0.033172607421875 +73187 -0.641876220703125 +73188 0.031005859375 +73189 -0.6177978515625 +73190 0.025421142578125 +73191 -0.575531005859375 +73192 0.015838623046875 +73193 -0.526336669921875 +73194 0.008453369140625 +73195 -0.42645263671875 +73196 0.00653076171875 +73197 -0.2581787109375 +73198 0.0057373046875 +73199 -0.068695068359375 +73200 0.001434326171875 +73201 0.09222412109375 +73202 -0.004150390625 +73203 0.232147216796875 +73204 -0.009857177734375 +73205 0.3509521484375 +73206 -0.019287109375 +73207 0.410064697265625 +73208 -0.036041259765625 +73209 0.372955322265625 +73210 -0.0576171875 +73211 0.2554931640625 +73212 -0.077850341796875 +73213 0.10711669921875 +73214 -0.09442138671875 +73215 -0.052886962890625 +73216 -0.10260009765625 +73217 -0.186279296875 +73218 -0.09527587890625 +73219 -0.23291015625 +73220 -0.0760498046875 +73221 -0.209442138671875 +73222 -0.054107666015625 +73223 -0.174163818359375 +73224 -0.02996826171875 +73225 -0.126739501953125 +73226 -0.00140380859375 +73227 -0.048126220703125 +73228 0.027984619140625 +73229 0.0426025390625 +73230 0.051788330078125 +73231 0.10748291015625 +73232 0.068572998046875 +73233 0.1409912109375 +73234 0.085968017578125 +73235 0.19708251953125 +73236 0.103271484375 +73237 0.273651123046875 +73238 0.1123046875 +73239 0.31768798828125 +73240 0.11480712890625 +73241 0.341094970703125 +73242 0.114532470703125 +73243 0.368011474609375 +73244 0.10791015625 +73245 0.37249755859375 +73246 0.087310791015625 +73247 0.30072021484375 +73248 0.053192138671875 +73249 0.1517333984375 +73250 0.015167236328125 +73251 -0.01470947265625 +73252 -0.024444580078125 +73253 -0.1883544921875 +73254 -0.0654296875 +73255 -0.372711181640625 +73256 -0.0989990234375 +73257 -0.51397705078125 +73258 -0.11846923828125 +73259 -0.57177734375 +73260 -0.122314453125 +73261 -0.53948974609375 +73262 -0.112823486328125 +73263 -0.43511962890625 +73264 -0.095367431640625 +73265 -0.2962646484375 +73266 -0.075592041015625 +73267 -0.161102294921875 +73268 -0.05560302734375 +73269 -0.0435791015625 +73270 -0.0350341796875 +73271 0.060394287109375 +73272 -0.016326904296875 +73273 0.13665771484375 +73274 -0.002227783203125 +73275 0.170135498046875 +73276 0.007415771484375 +73277 0.16552734375 +73278 0.017181396484375 +73279 0.15728759765625 +73280 0.027252197265625 +73281 0.150787353515625 +73282 0.033416748046875 +73283 0.12200927734375 +73284 0.0364990234375 +73285 0.080108642578125 +73286 0.039947509765625 +73287 0.05126953125 +73288 0.0474853515625 +73289 0.062896728515625 +73290 0.055511474609375 +73291 0.09271240234375 +73292 0.0567626953125 +73293 0.092987060546875 +73294 0.053436279296875 +73295 0.07855224609375 +73296 0.047882080078125 +73297 0.06427001953125 +73298 0.038055419921875 +73299 0.0347900390625 +73300 0.0240478515625 +73301 -0.01171875 +73302 0.0091552734375 +73303 -0.056060791015625 +73304 0.000274658203125 +73305 -0.055511474609375 +73306 -0.002105712890625 +73307 -0.010467529296875 +73308 -0.005584716796875 +73309 0.02508544921875 +73310 -0.013519287109375 +73311 0.025665283203125 +73312 -0.021575927734375 +73313 0.017333984375 +73314 -0.0291748046875 +73315 0.00189208984375 +73316 -0.0377197265625 +73317 -0.03173828125 +73318 -0.045257568359375 +73319 -0.071502685546875 +73320 -0.054473876953125 +73321 -0.13543701171875 +73322 -0.06488037109375 +73323 -0.219970703125 +73324 -0.072967529296875 +73325 -0.300506591796875 +73326 -0.078887939453125 +73327 -0.376312255859375 +73328 -0.07830810546875 +73329 -0.416107177734375 +73330 -0.064300537109375 +73331 -0.371124267578125 +73332 -0.03741455078125 +73333 -0.242279052734375 +73334 -0.00408935546875 +73335 -0.069732666015625 +73336 0.0321044921875 +73337 0.125640869140625 +73338 0.066131591796875 +73339 0.31268310546875 +73340 0.092193603515625 +73341 0.45501708984375 +73342 0.11041259765625 +73343 0.554779052734375 +73344 0.120452880859375 +73345 0.61065673828125 +73346 0.120513916015625 +73347 0.610931396484375 +73348 0.1070556640625 +73349 0.531463623046875 +73350 0.082611083984375 +73351 0.3883056640625 +73352 0.05535888671875 +73353 0.23468017578125 +73354 0.029296875 +73355 0.095245361328125 +73356 0.00860595703125 +73357 -0.00396728515625 +73358 -0.00421142578125 +73359 -0.04852294921875 +73360 -0.01129150390625 +73361 -0.055145263671875 +73362 -0.020111083984375 +73363 -0.0758056640625 +73364 -0.03460693359375 +73365 -0.138702392578125 +73366 -0.04931640625 +73367 -0.209197998046875 +73368 -0.064300537109375 +73369 -0.289031982421875 +73370 -0.07952880859375 +73371 -0.37884521484375 +73372 -0.091583251953125 +73373 -0.456329345703125 +73374 -0.0997314453125 +73375 -0.51641845703125 +73376 -0.09808349609375 +73377 -0.519287109375 +73378 -0.085784912109375 +73379 -0.458251953125 +73380 -0.070770263671875 +73381 -0.384796142578125 +73382 -0.056976318359375 +73383 -0.323699951171875 +73384 -0.043792724609375 +73385 -0.269287109375 +73386 -0.027557373046875 +73387 -0.1951904296875 +73388 -0.00836181640625 +73389 -0.100006103515625 +73390 0.00946044921875 +73391 -0.01055908203125 +73392 0.03021240234375 +73393 0.1033935546875 +73394 0.0548095703125 +73395 0.24908447265625 +73396 0.07513427734375 +73397 0.373199462890625 +73398 0.088470458984375 +73399 0.45806884765625 +73400 0.095977783203125 +73401 0.511474609375 +73402 0.102508544921875 +73403 0.565399169921875 +73404 0.10693359375 +73405 0.61138916015625 +73406 0.1004638671875 +73407 0.5897216796875 +73408 0.081817626953125 +73409 0.4906005859375 +73410 0.0538330078125 +73411 0.33148193359375 +73412 0.022064208984375 +73413 0.147796630859375 +73414 -0.006988525390625 +73415 -0.01873779296875 +73416 -0.0289306640625 +73417 -0.140289306640625 +73418 -0.039825439453125 +73419 -0.191986083984375 +73420 -0.04107666015625 +73421 -0.184295654296875 +73422 -0.039276123046875 +73423 -0.161834716796875 +73424 -0.040679931640625 +73425 -0.166595458984375 +73426 -0.044586181640625 +73427 -0.19390869140625 +73428 -0.048126220703125 +73429 -0.22442626953125 +73430 -0.054595947265625 +73431 -0.279754638671875 +73432 -0.06097412109375 +73433 -0.3389892578125 +73434 -0.060272216796875 +73435 -0.3543701171875 +73436 -0.055999755859375 +73437 -0.348175048828125 +73438 -0.0491943359375 +73439 -0.32598876953125 +73440 -0.035614013671875 +73441 -0.2581787109375 +73442 -0.01470947265625 +73443 -0.139801025390625 +73444 0.01116943359375 +73445 0.014617919921875 +73446 0.032745361328125 +73447 0.144378662109375 +73448 0.045684814453125 +73449 0.221038818359375 +73450 0.0538330078125 +73451 0.27069091796875 +73452 0.05731201171875 +73453 0.294036865234375 +73454 0.059234619140625 +73455 0.311767578125 +73456 0.061981201171875 +73457 0.339141845703125 +73458 0.063262939453125 +73459 0.360260009765625 +73460 0.061004638671875 +73461 0.360504150390625 +73462 0.050537109375 +73463 0.308380126953125 +73464 0.02862548828125 +73465 0.18170166015625 +73466 -0.000823974609375 +73467 0.0047607421875 +73468 -0.030609130859375 +73469 -0.17559814453125 +73470 -0.053741455078125 +73471 -0.3143310546875 +73472 -0.063140869140625 +73473 -0.36785888671875 +73474 -0.063140869140625 +73475 -0.36248779296875 +73476 -0.061187744140625 +73477 -0.343536376953125 +73478 -0.0552978515625 +73479 -0.3018798828125 +73480 -0.044097900390625 +73481 -0.231414794921875 +73482 -0.02471923828125 +73483 -0.117645263671875 +73484 -0.003021240234375 +73485 0.007049560546875 +73486 0.011016845703125 +73487 0.087982177734375 +73488 0.02008056640625 +73489 0.13946533203125 +73490 0.02655029296875 +73491 0.17425537109375 +73492 0.02960205078125 +73493 0.188201904296875 +73494 0.02734375 +73495 0.171234130859375 +73496 0.018768310546875 +73497 0.118438720703125 +73498 0.008819580078125 +73499 0.05706787109375 +73500 -0.002166748046875 +73501 -0.010711669921875 +73502 -0.0155029296875 +73503 -0.0914306640625 +73504 -0.027099609375 +73505 -0.162322998046875 +73506 -0.03173828125 +73507 -0.194549560546875 +73508 -0.0223388671875 +73509 -0.1492919921875 +73510 0.00189208984375 +73511 -0.02166748046875 +73512 0.029083251953125 +73513 0.124053955078125 +73514 0.04510498046875 +73515 0.211151123046875 +73516 0.050140380859375 +73517 0.240447998046875 +73518 0.049774169921875 +73519 0.242218017578125 +73520 0.0457763671875 +73521 0.2257080078125 +73522 0.038848876953125 +73523 0.194366455078125 +73524 0.0230712890625 +73525 0.115509033203125 +73526 0.00286865234375 +73527 0.0128173828125 +73528 -0.010650634765625 +73529 -0.053802490234375 +73530 -0.022247314453125 +73531 -0.110626220703125 +73532 -0.039581298828125 +73533 -0.199493408203125 +73534 -0.057830810546875 +73535 -0.29437255859375 +73536 -0.065338134765625 +73537 -0.33221435546875 +73538 -0.05596923828125 +73539 -0.27972412109375 +73540 -0.03863525390625 +73541 -0.185333251953125 +73542 -0.02789306640625 +73543 -0.128204345703125 +73544 -0.025115966796875 +73545 -0.115692138671875 +73546 -0.0245361328125 +73547 -0.116455078125 +73548 -0.021728515625 +73549 -0.105926513671875 +73550 -0.01116943359375 +73551 -0.053955078125 +73552 0.008758544921875 +73553 0.048797607421875 +73554 0.029754638671875 +73555 0.157318115234375 +73556 0.040740966796875 +73557 0.212005615234375 +73558 0.042724609375 +73559 0.218475341796875 +73560 0.04681396484375 +73561 0.23724365234375 +73562 0.059814453125 +73563 0.30535888671875 +73564 0.07403564453125 +73565 0.38128662109375 +73566 0.07830810546875 +73567 0.404449462890625 +73568 0.076263427734375 +73569 0.3944091796875 +73570 0.07476806640625 +73571 0.3885498046875 +73572 0.069427490234375 +73573 0.362640380859375 +73574 0.0523681640625 +73575 0.27362060546875 +73576 0.022796630859375 +73577 0.11712646484375 +73578 -0.009674072265625 +73579 -0.054901123046875 +73580 -0.03546142578125 +73581 -0.19085693359375 +73582 -0.053619384765625 +73583 -0.28570556640625 +73584 -0.064056396484375 +73585 -0.339263916015625 +73586 -0.071563720703125 +73587 -0.3775634765625 +73588 -0.084381103515625 +73589 -0.445709228515625 +73590 -0.1009521484375 +73591 -0.535064697265625 +73592 -0.11822509765625 +73593 -0.629058837890625 +73594 -0.130645751953125 +73595 -0.697601318359375 +73596 -0.131439208984375 +73597 -0.70391845703125 +73598 -0.119659423828125 +73599 -0.6424560546875 +73600 -0.091278076171875 +73601 -0.491241455078125 +73602 -0.049163818359375 +73603 -0.265716552734375 +73604 -0.003997802734375 +73605 -0.023712158203125 +73606 0.0380859375 +73607 0.201751708984375 +73608 0.070648193359375 +73609 0.375823974609375 +73610 0.0911865234375 +73611 0.485076904296875 +73612 0.106903076171875 +73613 0.56884765625 +73614 0.11920166015625 +73615 0.634765625 +73616 0.1197509765625 +73617 0.63763427734375 +73618 0.106475830078125 +73619 0.5660400390625 +73620 0.088958740234375 +73621 0.4720458984375 +73622 0.07666015625 +73623 0.40692138671875 +73624 0.070892333984375 +73625 0.3778076171875 +73626 0.070281982421875 +73627 0.376953125 +73628 0.068878173828125 +73629 0.371978759765625 +73630 0.057525634765625 +73631 0.313140869140625 +73632 0.033294677734375 +73633 0.184417724609375 +73634 0.00091552734375 +73635 0.011199951171875 +73636 -0.03302001953125 +73637 -0.171051025390625 +73638 -0.063873291015625 +73639 -0.33740234375 +73640 -0.088714599609375 +73641 -0.47198486328125 +73642 -0.10491943359375 +73643 -0.560394287109375 +73644 -0.10845947265625 +73645 -0.58056640625 +73646 -0.10211181640625 +73647 -0.54754638671875 +73648 -0.0946044921875 +73649 -0.508575439453125 +73650 -0.085174560546875 +73651 -0.459503173828125 +73652 -0.07275390625 +73653 -0.394378662109375 +73654 -0.0645751953125 +73655 -0.35260009765625 +73656 -0.056549072265625 +73657 -0.31170654296875 +73658 -0.035064697265625 +73659 -0.197418212890625 +73660 0.00018310546875 +73661 -0.007965087890625 +73662 0.04010009765625 +73663 0.207489013671875 +73664 0.077362060546875 +73665 0.409210205078125 +73666 0.10736083984375 +73667 0.57208251953125 +73668 0.124542236328125 +73669 0.66595458984375 +73670 0.123016357421875 +73671 0.65875244140625 +73672 0.105926513671875 +73673 0.56744384765625 +73674 0.080535888671875 +73675 0.431396484375 +73676 0.054931640625 +73677 0.29443359375 +73678 0.033905029296875 +73679 0.182464599609375 +73680 0.011627197265625 +73681 0.06365966796875 +73682 -0.014434814453125 +73683 -0.075958251953125 +73684 -0.035614013671875 +73685 -0.189422607421875 +73686 -0.05096435546875 +73687 -0.271942138671875 +73688 -0.06402587890625 +73689 -0.342529296875 +73690 -0.068023681640625 +73691 -0.364166259765625 +73692 -0.061187744140625 +73693 -0.327239990234375 +73694 -0.051849365234375 +73695 -0.2769775390625 +73696 -0.047393798828125 +73697 -0.253692626953125 +73698 -0.045318603515625 +73699 -0.24365234375 +73700 -0.0367431640625 +73701 -0.1983642578125 +73702 -0.0213623046875 +73703 -0.116241455078125 +73704 -0.006439208984375 +73705 -0.036834716796875 +73706 0.007049560546875 +73707 0.034881591796875 +73708 0.017669677734375 +73709 0.09124755859375 +73710 0.0211181640625 +73711 0.10888671875 +73712 0.024322509765625 +73713 0.125518798828125 +73714 0.03033447265625 +73715 0.15771484375 +73716 0.03411865234375 +73717 0.17828369140625 +73718 0.03271484375 +73719 0.17108154296875 +73720 0.024993896484375 +73721 0.129974365234375 +73722 0.01605224609375 +73723 0.082427978515625 +73724 0.0057373046875 +73725 0.027679443359375 +73726 -0.01165771484375 +73727 -0.065643310546875 +73728 -0.02874755859375 +73729 -0.15936279296875 +73730 -0.038482666015625 +73731 -0.21307373046875 +73732 -0.04296875 +73733 -0.234649658203125 +73734 -0.036651611328125 +73735 -0.2001953125 +73736 -0.021148681640625 +73737 -0.119171142578125 +73738 -0.00323486328125 +73739 -0.024749755859375 +73740 0.017974853515625 +73741 0.085784912109375 +73742 0.035308837890625 +73743 0.178131103515625 +73744 0.04107666015625 +73745 0.215576171875 +73746 0.038330078125 +73747 0.211456298828125 +73748 0.029266357421875 +73749 0.17523193359375 +73750 0.01861572265625 +73751 0.128753662109375 +73752 0.01287841796875 +73753 0.1019287109375 +73754 0.007598876953125 +73755 0.0743408203125 +73756 0.002105712890625 +73757 0.04327392578125 +73758 0.002655029296875 +73759 0.038177490234375 +73760 0.012847900390625 +73761 0.076263427734375 +73762 0.028961181640625 +73763 0.14105224609375 +73764 0.040924072265625 +73765 0.186431884765625 +73766 0.04351806640625 +73767 0.188812255859375 +73768 0.034637451171875 +73769 0.1390380859375 +73770 0.01519775390625 +73771 0.041778564453125 +73772 -0.009796142578125 +73773 -0.079437255859375 +73774 -0.039276123046875 +73775 -0.219390869140625 +73776 -0.07098388671875 +73777 -0.367828369140625 +73778 -0.0985107421875 +73779 -0.494873046875 +73780 -0.112274169921875 +73781 -0.556243896484375 +73782 -0.1029052734375 +73783 -0.508697509765625 +73784 -0.075408935546875 +73785 -0.3756103515625 +73786 -0.0430908203125 +73787 -0.218902587890625 +73788 -0.01129150390625 +73789 -0.063751220703125 +73790 0.02044677734375 +73791 0.091552734375 +73792 0.049835205078125 +73793 0.23602294921875 +73794 0.07122802734375 +73795 0.342987060546875 +73796 0.08099365234375 +73797 0.39520263671875 +73798 0.0784912109375 +73799 0.389373779296875 +73800 0.06353759765625 +73801 0.324249267578125 +73802 0.041412353515625 +73803 0.224090576171875 +73804 0.019775390625 +73805 0.124267578125 +73806 0.001251220703125 +73807 0.037078857421875 +73808 -0.00823974609375 +73809 -0.010101318359375 +73810 -0.009246826171875 +73811 -0.019439697265625 +73812 -0.0086669921875 +73813 -0.022796630859375 +73814 -0.002593994140625 +73815 -0.001556396484375 +73816 0.01141357421875 +73817 0.056304931640625 +73818 0.0238037109375 +73819 0.106719970703125 +73820 0.023101806640625 +73821 0.096893310546875 +73822 0.01263427734375 +73823 0.042694091796875 +73824 0.000518798828125 +73825 -0.018035888671875 +73826 -0.01123046875 +73827 -0.07586669921875 +73828 -0.02020263671875 +73829 -0.11944580078125 +73830 -0.028778076171875 +73831 -0.15972900390625 +73832 -0.0382080078125 +73833 -0.202606201171875 +73834 -0.048553466796875 +73835 -0.24859619140625 +73836 -0.0614013671875 +73837 -0.30517578125 +73838 -0.074493408203125 +73839 -0.36212158203125 +73840 -0.081756591796875 +73841 -0.39141845703125 +73842 -0.074981689453125 +73843 -0.35528564453125 +73844 -0.053314208984375 +73845 -0.249969482421875 +73846 -0.020477294921875 +73847 -0.092864990234375 +73848 0.01776123046875 +73849 0.08905029296875 +73850 0.04840087890625 +73851 0.2352294921875 +73852 0.065673828125 +73853 0.318817138671875 +73854 0.07366943359375 +73855 0.358642578125 +73856 0.0709228515625 +73857 0.347747802734375 +73858 0.057373046875 +73859 0.28564453125 +73860 0.04400634765625 +73861 0.223175048828125 +73862 0.038665771484375 +73863 0.196746826171875 +73864 0.03558349609375 +73865 0.179840087890625 +73866 0.03106689453125 +73867 0.155548095703125 +73868 0.030975341796875 +73869 0.151214599609375 +73870 0.033111572265625 +73871 0.156951904296875 +73872 0.028564453125 +73873 0.13177490234375 +73874 0.022735595703125 +73875 0.100799560546875 +73876 0.020538330078125 +73877 0.087127685546875 +73878 0.014190673828125 +73879 0.05487060546875 +73880 0.000885009765625 +73881 -0.009002685546875 +73882 -0.019287109375 +73883 -0.10400390625 +73884 -0.04620361328125 +73885 -0.229400634765625 +73886 -0.073455810546875 +73887 -0.35552978515625 +73888 -0.092254638671875 +73889 -0.441925048828125 +73890 -0.09942626953125 +73891 -0.473846435546875 +73892 -0.09783935546875 +73893 -0.464813232421875 +73894 -0.08843994140625 +73895 -0.419097900390625 +73896 -0.0706787109375 +73897 -0.334320068359375 +73898 -0.048309326171875 +73899 -0.227935791015625 +73900 -0.026336669921875 +73901 -0.12347412109375 +73902 -0.006195068359375 +73903 -0.02764892578125 +73904 0.016021728515625 +73905 0.077667236328125 +73906 0.044830322265625 +73907 0.2132568359375 +73908 0.082366943359375 +73909 0.38885498046875 +73910 0.123992919921875 +73911 0.582794189453125 +73912 0.156494140625 +73913 0.734039306640625 +73914 0.170684814453125 +73915 0.800140380859375 +73916 0.165985107421875 +73917 0.7783203125 +73918 0.14166259765625 +73919 0.6651611328125 +73920 0.09747314453125 +73921 0.45965576171875 +73922 0.041534423828125 +73923 0.199188232421875 +73924 -0.011993408203125 +73925 -0.050689697265625 +73926 -0.05084228515625 +73927 -0.23297119140625 +73928 -0.071258544921875 +73929 -0.33013916015625 +73930 -0.07891845703125 +73931 -0.368408203125 +73932 -0.080596923828125 +73933 -0.378936767578125 +73934 -0.079681396484375 +73935 -0.376983642578125 +73936 -0.079864501953125 +73937 -0.37969970703125 +73938 -0.082122802734375 +73939 -0.391510009765625 +73940 -0.080596923828125 +73941 -0.385345458984375 +73942 -0.0711669921875 +73943 -0.3419189453125 +73944 -0.0584716796875 +73945 -0.28289794921875 +73946 -0.0518798828125 +73947 -0.251617431640625 +73948 -0.0552978515625 +73949 -0.266143798828125 +73950 -0.057220458984375 +73951 -0.273345947265625 +73952 -0.045440673828125 +73953 -0.216796875 +73954 -0.026763916015625 +73955 -0.128265380859375 +73956 -0.01422119140625 +73957 -0.068145751953125 +73958 -0.00921630859375 +73959 -0.0430908203125 +73960 -0.00555419921875 +73961 -0.024444580078125 +73962 0.00384521484375 +73963 0.020721435546875 +73964 0.02593994140625 +73965 0.124481201171875 +73966 0.05450439453125 +73967 0.25787353515625 +73968 0.08050537109375 +73969 0.379119873046875 +73970 0.1021728515625 +73971 0.47991943359375 +73972 0.112579345703125 +73973 0.5281982421875 +73974 0.10894775390625 +73975 0.511138916015625 +73976 0.097198486328125 +73977 0.456207275390625 +73978 0.08685302734375 +73979 0.407470703125 +73980 0.08197021484375 +73981 0.383758544921875 +73982 0.076416015625 +73983 0.35687255859375 +73984 0.067474365234375 +73985 0.31182861328125 +73986 0.055908203125 +73987 0.250885009765625 +73988 0.0391845703125 +73989 0.1654052734375 +73990 0.0118408203125 +73991 0.035247802734375 +73992 -0.027191162109375 +73993 -0.142059326171875 +73994 -0.070648193359375 +73995 -0.33563232421875 +73996 -0.11614990234375 +73997 -0.5345458984375 +73998 -0.159759521484375 +73999 -0.72186279296875 +74000 -0.186553955078125 +74001 -0.836669921875 +74002 -0.18511962890625 +74003 -0.8326416015625 +74004 -0.160369873046875 +74005 -0.7296142578125 +74006 -0.125885009765625 +74007 -0.582550048828125 +74008 -0.09356689453125 +74009 -0.440093994140625 +74010 -0.06866455078125 +74011 -0.324310302734375 +74012 -0.042572021484375 +74013 -0.20147705078125 +74014 -0.008331298828125 +74015 -0.044647216796875 +74016 0.023834228515625 +74017 0.103973388671875 +74018 0.043792724609375 +74019 0.202392578125 +74020 0.055206298828125 +74021 0.264495849609375 +74022 0.070343017578125 +74023 0.338897705078125 +74024 0.0938720703125 +74025 0.443817138671875 +74026 0.117431640625 +74027 0.545074462890625 +74028 0.134796142578125 +74029 0.6173095703125 +74030 0.143951416015625 +74031 0.6524658203125 +74032 0.148040771484375 +74033 0.66339111328125 +74034 0.148468017578125 +74035 0.6561279296875 +74036 0.13916015625 +74037 0.606781005859375 +74038 0.116424560546875 +74039 0.501190185546875 +74040 0.083404541015625 +74041 0.352783203125 +74042 0.0435791015625 +74043 0.176544189453125 +74044 -0.0050048828125 +74045 -0.034820556640625 +74046 -0.05682373046875 +74047 -0.258209228515625 +74048 -0.099395751953125 +74049 -0.44244384765625 +74050 -0.129852294921875 +74051 -0.5753173828125 +74052 -0.147125244140625 +74053 -0.65203857421875 +74054 -0.14361572265625 +74055 -0.641632080078125 +74056 -0.123870849609375 +74057 -0.562164306640625 +74058 -0.098846435546875 +74059 -0.458038330078125 +74060 -0.073760986328125 +74061 -0.350555419921875 +74062 -0.05364990234375 +74063 -0.260528564453125 +74064 -0.039398193359375 +74065 -0.192108154296875 +74066 -0.030029296875 +74067 -0.141937255859375 +74068 -0.023406982421875 +74069 -0.1021728515625 +74070 -0.016876220703125 +74071 -0.062896728515625 +74072 -0.007232666015625 +74073 -0.011932373046875 +74074 0.008636474609375 +74075 0.062835693359375 +74076 0.027740478515625 +74077 0.148712158203125 +74078 0.049163818359375 +74079 0.241729736328125 +74080 0.07476806640625 +74081 0.34912109375 +74082 0.10125732421875 +74083 0.457305908203125 +74084 0.123077392578125 +74085 0.54388427734375 +74086 0.131256103515625 +74087 0.5728759765625 +74088 0.11639404296875 +74089 0.506591796875 +74090 0.07989501953125 +74091 0.351226806640625 +74092 0.031494140625 +74093 0.146514892578125 +74094 -0.015960693359375 +74095 -0.05523681640625 +74096 -0.05322265625 +74097 -0.21624755859375 +74098 -0.080047607421875 +74099 -0.334930419921875 +74100 -0.094512939453125 +74101 -0.402984619140625 +74102 -0.1019287109375 +74103 -0.4412841796875 +74104 -0.113800048828125 +74105 -0.49578857421875 +74106 -0.128662109375 +74107 -0.5601806640625 +74108 -0.13818359375 +74109 -0.600738525390625 +74110 -0.1341552734375 +74111 -0.584228515625 +74112 -0.1087646484375 +74113 -0.47930908203125 +74114 -0.060302734375 +74115 -0.27935791015625 +74116 0.00518798828125 +74117 -0.0089111328125 +74118 0.072113037109375 +74119 0.268798828125 +74120 0.12298583984375 +74121 0.482818603515625 +74122 0.150665283203125 +74123 0.60369873046875 +74124 0.15997314453125 +74125 0.650421142578125 +74126 0.16119384765625 +74127 0.66400146484375 +74128 0.153717041015625 +74129 0.6414794921875 +74130 0.13507080078125 +74131 0.572540283203125 +74132 0.115509033203125 +74133 0.498138427734375 +74134 0.100311279296875 +74135 0.439453125 +74136 0.08428955078125 +74137 0.375518798828125 +74138 0.0595703125 +74139 0.274505615234375 +74140 0.019256591796875 +74141 0.1087646484375 +74142 -0.031158447265625 +74143 -0.099395751953125 +74144 -0.0838623046875 +74145 -0.3182373046875 +74146 -0.139251708984375 +74147 -0.5489501953125 +74148 -0.193023681640625 +74149 -0.7738037109375 +74150 -0.232177734375 +74151 -0.86383056640625 +74152 -0.24859619140625 +74153 -0.870391845703125 +74154 -0.246734619140625 +74155 -0.86895751953125 +74156 -0.229949951171875 +74157 -0.861053466796875 +74158 -0.194061279296875 +74159 -0.765869140625 +74160 -0.136322021484375 +74161 -0.5301513671875 +74162 -0.058502197265625 +74163 -0.214691162109375 +74164 0.028656005859375 +74165 0.137359619140625 +74166 0.11248779296875 +74167 0.474822998046875 +74168 0.184234619140625 +74169 0.76239013671875 +74170 0.237274169921875 +74171 0.867462158203125 +74172 0.271759033203125 +74173 0.870361328125 +74174 0.284912109375 +74175 0.86480712890625 +74176 0.278167724609375 +74177 0.831817626953125 +74178 0.257659912109375 +74179 0.677581787109375 +74180 0.224945068359375 +74181 0.495880126953125 +74182 0.1846923828125 +74183 0.30767822265625 +74184 0.137542724609375 +74185 0.116180419921875 +74186 0.07568359375 +74187 -0.110748291015625 +74188 -0.0025634765625 +74189 -0.381805419921875 +74190 -0.0865478515625 +74191 -0.6572265625 +74192 -0.16143798828125 +74193 -0.857421875 +74194 -0.21661376953125 +74195 -0.870391845703125 +74196 -0.250396728515625 +74197 -0.870391845703125 +74198 -0.26953125 +74199 -0.86444091796875 +74200 -0.282958984375 +74201 -0.85723876953125 +74202 -0.28619384765625 +74203 -0.790008544921875 +74204 -0.265869140625 +74205 -0.62847900390625 +74206 -0.221282958984375 +74207 -0.3956298828125 +74208 -0.16064453125 +74209 -0.126708984375 +74210 -0.090789794921875 +74211 0.150115966796875 +74212 -0.014678955078125 +74213 0.424041748046875 +74214 0.060943603515625 +74215 0.670623779296875 +74216 0.12646484375 +74217 0.854522705078125 +74218 0.177490234375 +74219 0.866485595703125 +74220 0.210235595703125 +74221 0.86920166015625 +74222 0.229248046875 +74223 0.8653564453125 +74224 0.237884521484375 +74225 0.857147216796875 +74226 0.235504150390625 +74227 0.766845703125 +74228 0.22344970703125 +74229 0.628509521484375 +74230 0.20013427734375 +74231 0.462127685546875 +74232 0.1719970703125 +74233 0.297210693359375 +74234 0.14215087890625 +74235 0.14862060546875 +74236 0.105010986328125 +74237 -0.00537109375 +74238 0.0625 +74239 -0.15753173828125 +74240 0.0133056640625 +74241 -0.31304931640625 +74242 -0.04608154296875 +74243 -0.48876953125 +74244 -0.102691650390625 +74245 -0.6416015625 +74246 -0.150390625 +74247 -0.751373291015625 +74248 -0.1962890625 +74249 -0.84619140625 +74250 -0.236846923828125 +74251 -0.861297607421875 +74252 -0.263214111328125 +74253 -0.863250732421875 +74254 -0.266754150390625 +74255 -0.856597900390625 +74256 -0.25103759765625 +74257 -0.7498779296875 +74258 -0.232269287109375 +74259 -0.624542236328125 +74260 -0.204132080078125 +74261 -0.47808837890625 +74262 -0.1500244140625 +74263 -0.253387451171875 +74264 -0.082366943359375 +74265 0.003692626953125 +74266 -0.019927978515625 +74267 0.2257080078125 +74268 0.041168212890625 +74269 0.427154541015625 +74270 0.11041259765625 +74271 0.643218994140625 +74272 0.185516357421875 +74273 0.855926513671875 +74274 0.250640869140625 +74275 0.870361328125 +74276 0.292205810546875 +74277 0.870361328125 +74278 0.312469482421875 +74279 0.862762451171875 +74280 0.310760498046875 +74281 0.79669189453125 +74282 0.28448486328125 +74283 0.595794677734375 +74284 0.24176025390625 +74285 0.362152099609375 +74286 0.190338134765625 +74287 0.1270751953125 +74288 0.135986328125 +74289 -0.086944580078125 +74290 0.079010009765625 +74291 -0.2784423828125 +74292 0.0093994140625 +74293 -0.484832763671875 +74294 -0.0784912109375 +74295 -0.729583740234375 +74296 -0.170806884765625 +74297 -0.86688232421875 +74298 -0.250152587890625 +74299 -0.870391845703125 +74300 -0.3154296875 +74301 -0.86859130859375 +74302 -0.36627197265625 +74303 -0.86279296875 +74304 -0.392822265625 +74305 -0.817962646484375 +74306 -0.382476806640625 +74307 -0.6116943359375 +74308 -0.33331298828125 +74309 -0.3128662109375 +74310 -0.254791259765625 +74311 0.039398193359375 +74312 -0.152435302734375 +74313 0.422821044921875 +74314 -0.03546142578125 +74315 0.805145263671875 +74316 0.077178955078125 +74317 0.870361328125 +74318 0.169708251953125 +74319 0.870361328125 +74320 0.239044189453125 +74321 0.860015869140625 +74322 0.28326416015625 +74323 0.727935791015625 +74324 0.301025390625 +74325 0.48114013671875 +74326 0.29925537109375 +74327 0.2059326171875 +74328 0.284454345703125 +74329 -0.06103515625 +74330 0.25958251953125 +74331 -0.29913330078125 +74332 0.220672607421875 +74333 -0.516204833984375 +74334 0.163482666015625 +74335 -0.7252197265625 +74336 0.095062255859375 +74337 -0.85980224609375 +74338 0.024993896484375 +74339 -0.870391845703125 +74340 -0.03839111328125 +74341 -0.870391845703125 +74342 -0.08148193359375 +74343 -0.858062744140625 +74344 -0.103179931640625 +74345 -0.673004150390625 +74346 -0.118255615234375 +74347 -0.42694091796875 +74348 -0.139190673828125 +74349 -0.2100830078125 +74350 -0.165435791015625 +74351 -0.0362548828125 +74352 -0.18890380859375 +74353 0.10943603515625 +74354 -0.2041015625 +74355 0.23516845703125 +74356 -0.19952392578125 +74357 0.373687744140625 +74358 -0.17578125 +74359 0.517791748046875 +74360 -0.15057373046875 +74361 0.602783203125 +74362 -0.122528076171875 +74363 0.635711669921875 +74364 -0.082366943359375 +74365 0.655181884765625 +74366 -0.032928466796875 +74367 0.65948486328125 +74368 0.023468017578125 +74369 0.651275634765625 +74370 0.079925537109375 +74371 0.61846923828125 +74372 0.126068115234375 +74373 0.53753662109375 +74374 0.1568603515625 +74375 0.404144287109375 +74376 0.16961669921875 +74377 0.22186279296875 +74378 0.164764404296875 +74379 0.003997802734375 +74380 0.14739990234375 +74381 -0.22100830078125 +74382 0.123321533203125 +74383 -0.42449951171875 +74384 0.09857177734375 +74385 -0.579833984375 +74386 0.085174560546875 +74387 -0.641876220703125 +74388 0.081329345703125 +74389 -0.6177978515625 +74390 0.069000244140625 +74391 -0.575531005859375 +74392 0.0467529296875 +74393 -0.526336669921875 +74394 0.029144287109375 +74395 -0.42645263671875 +74396 0.02386474609375 +74397 -0.2581787109375 +74398 0.020782470703125 +74399 -0.068695068359375 +74400 0.009124755859375 +74401 0.09222412109375 +74402 -0.005828857421875 +74403 0.232147216796875 +74404 -0.021240234375 +74405 0.3509521484375 +74406 -0.04541015625 +74407 0.410064697265625 +74408 -0.086578369140625 +74409 0.372955322265625 +74410 -0.138916015625 +74411 0.2554931640625 +74412 -0.187835693359375 +74413 0.10711669921875 +74414 -0.2279052734375 +74415 -0.052886962890625 +74416 -0.248992919921875 +74417 -0.186279296875 +74418 -0.235504150390625 +74419 -0.23291015625 +74420 -0.19384765625 +74421 -0.209442138671875 +74422 -0.142486572265625 +74423 -0.174163818359375 +74424 -0.08380126953125 +74425 -0.126739501953125 +74426 -0.015045166015625 +74427 -0.048126220703125 +74428 0.05584716796875 +74429 0.0426025390625 +74430 0.11578369140625 +74431 0.10748291015625 +74432 0.16107177734375 +74433 0.1409912109375 +74434 0.204986572265625 +74435 0.19708251953125 +74436 0.245635986328125 +74437 0.273651123046875 +74438 0.26739501953125 +74439 0.31768798828125 +74440 0.27337646484375 +74441 0.341094970703125 +74442 0.270660400390625 +74443 0.368011474609375 +74444 0.2528076171875 +74445 0.37249755859375 +74446 0.2060546875 +74447 0.30072021484375 +74448 0.1318359375 +74449 0.1517333984375 +74450 0.048797607421875 +74451 -0.01470947265625 +74452 -0.0380859375 +74453 -0.1883544921875 +74454 -0.12762451171875 +74455 -0.372711181640625 +74456 -0.20269775390625 +74457 -0.51397705078125 +74458 -0.250152587890625 +74459 -0.57177734375 +74460 -0.266571044921875 +74461 -0.53948974609375 +74462 -0.255767822265625 +74463 -0.43511962890625 +74464 -0.227447509765625 +74465 -0.2962646484375 +74466 -0.19195556640625 +74467 -0.161102294921875 +74468 -0.1533203125 +74469 -0.0435791015625 +74470 -0.11090087890625 +74471 0.060394287109375 +74472 -0.069610595703125 +74473 0.13665771484375 +74474 -0.03497314453125 +74475 0.170135498046875 +74476 -0.0072021484375 +74477 0.16552734375 +74478 0.021636962890625 +74479 0.15728759765625 +74480 0.05126953125 +74481 0.150787353515625 +74482 0.073272705078125 +74483 0.12200927734375 +74484 0.088592529296875 +74485 0.080108642578125 +74486 0.103179931640625 +74487 0.05126953125 +74488 0.123626708984375 +74489 0.062896728515625 +74490 0.14288330078125 +74491 0.09271240234375 +74492 0.147186279296875 +74493 0.092987060546875 +74494 0.140655517578125 +74495 0.07855224609375 +74496 0.12762451171875 +74497 0.06427001953125 +74498 0.104522705078125 +74499 0.0347900390625 +74500 0.071868896484375 +74501 -0.01171875 +74502 0.03643798828125 +74503 -0.056060791015625 +74504 0.012298583984375 +74505 -0.055511474609375 +74506 0.000640869140625 +74507 -0.010467529296875 +74508 -0.01336669921875 +74509 0.02508544921875 +74510 -0.036041259765625 +74511 0.025665283203125 +74512 -0.058380126953125 +74513 0.017333984375 +74514 -0.078887939453125 +74515 0.00189208984375 +74516 -0.100128173828125 +74517 -0.03173828125 +74518 -0.118011474609375 +74519 -0.071502685546875 +74520 -0.137725830078125 +74521 -0.13543701171875 +74522 -0.1583251953125 +74523 -0.219970703125 +74524 -0.172821044921875 +74525 -0.300506591796875 +74526 -0.181671142578125 +74527 -0.376312255859375 +74528 -0.176361083984375 +74529 -0.416107177734375 +74530 -0.143280029296875 +74531 -0.371124267578125 +74532 -0.0838623046875 +74533 -0.242279052734375 +74534 -0.011322021484375 +74535 -0.069732666015625 +74536 0.066925048828125 +74537 0.125640869140625 +74538 0.140533447265625 +74539 0.31268310546875 +74540 0.197662353515625 +74541 0.45501708984375 +74542 0.238250732421875 +74543 0.554779052734375 +74544 0.261444091796875 +74545 0.61065673828125 +74546 0.263519287109375 +74547 0.610931396484375 +74548 0.23724365234375 +74549 0.531463623046875 +74550 0.18768310546875 +74551 0.3883056640625 +74552 0.131317138671875 +74553 0.23468017578125 +74554 0.076202392578125 +74555 0.095245361328125 +74556 0.03094482421875 +74557 -0.00396728515625 +74558 0.000762939453125 +74559 -0.04852294921875 +74560 -0.018402099609375 +74561 -0.055145263671875 +74562 -0.041168212890625 +74563 -0.0758056640625 +74564 -0.075103759765625 +74565 -0.138702392578125 +74566 -0.109039306640625 +74567 -0.209197998046875 +74568 -0.14288330078125 +74569 -0.289031982421875 +74570 -0.176361083984375 +74571 -0.37884521484375 +74572 -0.202484130859375 +74573 -0.456329345703125 +74574 -0.219696044921875 +74575 -0.51641845703125 +74576 -0.216217041015625 +74577 -0.519287109375 +74578 -0.19036865234375 +74579 -0.458251953125 +74580 -0.1580810546875 +74581 -0.384796142578125 +74582 -0.12744140625 +74583 -0.323699951171875 +74584 -0.097442626953125 +74585 -0.269287109375 +74586 -0.061004638671875 +74587 -0.1951904296875 +74588 -0.01849365234375 +74589 -0.100006103515625 +74590 0.021240234375 +74591 -0.01055908203125 +74592 0.066619873046875 +74593 0.1033935546875 +74594 0.1192626953125 +74595 0.24908447265625 +74596 0.162750244140625 +74597 0.373199462890625 +74598 0.1915283203125 +74599 0.45806884765625 +74600 0.20782470703125 +74601 0.511474609375 +74602 0.221282958984375 +74603 0.565399169921875 +74604 0.2296142578125 +74605 0.61138916015625 +74606 0.21527099609375 +74607 0.5897216796875 +74608 0.175811767578125 +74609 0.4906005859375 +74610 0.1170654296875 +74611 0.33148193359375 +74612 0.05029296875 +74613 0.147796630859375 +74614 -0.01129150390625 +74615 -0.01873779296875 +74616 -0.0587158203125 +74617 -0.140289306640625 +74618 -0.083953857421875 +74619 -0.191986083984375 +74620 -0.08966064453125 +74621 -0.184295654296875 +74622 -0.088836669921875 +74623 -0.161834716796875 +74624 -0.093780517578125 +74625 -0.166595458984375 +74626 -0.10296630859375 +74627 -0.19390869140625 +74628 -0.110626220703125 +74629 -0.22442626953125 +74630 -0.12335205078125 +74631 -0.279754638671875 +74632 -0.13519287109375 +74633 -0.3389892578125 +74634 -0.1322021484375 +74635 -0.3543701171875 +74636 -0.12152099609375 +74637 -0.348175048828125 +74638 -0.1053466796875 +74639 -0.32598876953125 +74640 -0.0753173828125 +74641 -0.2581787109375 +74642 -0.030517578125 +74643 -0.139801025390625 +74644 0.024200439453125 +74645 0.014617919921875 +74646 0.0701904296875 +74647 0.144378662109375 +74648 0.09857177734375 +74649 0.221038818359375 +74650 0.116943359375 +74651 0.27069091796875 +74652 0.125396728515625 +74653 0.294036865234375 +74654 0.130096435546875 +74655 0.311767578125 +74656 0.1357421875 +74657 0.339141845703125 +74658 0.137908935546875 +74659 0.360260009765625 +74660 0.132476806640625 +74661 0.360504150390625 +74662 0.109893798828125 +74663 0.308380126953125 +74664 0.06353759765625 +74665 0.18170166015625 +74666 0.00140380859375 +74667 0.0047607421875 +74668 -0.061553955078125 +74669 -0.17559814453125 +74670 -0.1109619140625 +74671 -0.3143310546875 +74672 -0.132904052734375 +74673 -0.36785888671875 +74674 -0.13531494140625 +74675 -0.36248779296875 +74676 -0.13214111328125 +74677 -0.343536376953125 +74678 -0.120452880859375 +74679 -0.3018798828125 +74680 -0.09832763671875 +74681 -0.231414794921875 +74682 -0.061279296875 +74683 -0.117645263671875 +74684 -0.01953125 +74685 0.007049560546875 +74686 0.0096435546875 +74687 0.087982177734375 +74688 0.030487060546875 +74689 0.13946533203125 +74690 0.04669189453125 +74691 0.17425537109375 +74692 0.056640625 +74693 0.188201904296875 +74694 0.056884765625 +74695 0.171234130859375 +74696 0.04559326171875 +74697 0.118438720703125 +74698 0.031005859375 +74699 0.05706787109375 +74700 0.013580322265625 +74701 -0.010711669921875 +74702 -0.008880615234375 +74703 -0.0914306640625 +74704 -0.029388427734375 +74705 -0.162322998046875 +74706 -0.039031982421875 +74707 -0.194549560546875 +74708 -0.02569580078125 +74709 -0.1492919921875 +74710 0.01220703125 +74711 -0.02166748046875 +74712 0.05474853515625 +74713 0.124053955078125 +74714 0.07818603515625 +74715 0.211151123046875 +74716 0.0830078125 +74717 0.240447998046875 +74718 0.07891845703125 +74719 0.242218017578125 +74720 0.069091796875 +74721 0.2257080078125 +74722 0.05487060546875 +74723 0.194366455078125 +74724 0.026275634765625 +74725 0.115509033203125 +74726 -0.009063720703125 +74727 0.0128173828125 +74728 -0.03228759765625 +74729 -0.053802490234375 +74730 -0.051513671875 +74731 -0.110626220703125 +74732 -0.079742431640625 +74733 -0.199493408203125 +74734 -0.108856201171875 +74735 -0.29437255859375 +74736 -0.119232177734375 +74737 -0.33221435546875 +74738 -0.1005859375 +74739 -0.27972412109375 +74740 -0.068206787109375 +74741 -0.185333251953125 +74742 -0.04693603515625 +74743 -0.128204345703125 +74744 -0.03924560546875 +74745 -0.115692138671875 +74746 -0.035614013671875 +74747 -0.116455078125 +74748 -0.028594970703125 +74749 -0.105926513671875 +74750 -0.00897216796875 +74751 -0.053955078125 +74752 0.02618408203125 +74753 0.048797607421875 +74754 0.0623779296875 +74755 0.157318115234375 +74756 0.079803466796875 +74757 0.212005615234375 +74758 0.08050537109375 +74759 0.218475341796875 +74760 0.085418701171875 +74761 0.23724365234375 +74762 0.10736083984375 +74763 0.30535888671875 +74764 0.132110595703125 +74765 0.38128662109375 +74766 0.138824462890625 +74767 0.404449462890625 +74768 0.13427734375 +74769 0.3944091796875 +74770 0.131378173828125 +74771 0.3885498046875 +74772 0.121826171875 +74773 0.362640380859375 +74774 0.090789794921875 +74775 0.27362060546875 +74776 0.036773681640625 +74777 0.11712646484375 +74778 -0.0223388671875 +74779 -0.054901123046875 +74780 -0.06884765625 +74781 -0.19085693359375 +74782 -0.101043701171875 +74783 -0.28570556640625 +74784 -0.118896484375 +74785 -0.339263916015625 +74786 -0.131378173828125 +74787 -0.3775634765625 +74788 -0.154052734375 +74789 -0.445709228515625 +74790 -0.183990478515625 +74791 -0.535064697265625 +74792 -0.21551513671875 +74793 -0.629058837890625 +74794 -0.238311767578125 +74795 -0.697601318359375 +74796 -0.239776611328125 +74797 -0.70391845703125 +74798 -0.218048095703125 +74799 -0.6424560546875 +74800 -0.16558837890625 +74801 -0.491241455078125 +74802 -0.087738037109375 +74803 -0.265716552734375 +74804 -0.00439453125 +74805 -0.023712158203125 +74806 0.073028564453125 +74807 0.201751708984375 +74808 0.132568359375 +74809 0.375823974609375 +74810 0.169647216796875 +74811 0.485076904296875 +74812 0.19781494140625 +74813 0.56884765625 +74814 0.2197265625 +74815 0.634765625 +74816 0.21990966796875 +74817 0.63763427734375 +74818 0.1944580078125 +74819 0.5660400390625 +74820 0.161346435546875 +74821 0.4720458984375 +74822 0.13824462890625 +74823 0.40692138671875 +74824 0.127655029296875 +74825 0.3778076171875 +74826 0.126922607421875 +74827 0.376953125 +74828 0.12493896484375 +74829 0.371978759765625 +74830 0.104583740234375 +74831 0.313140869140625 +74832 0.06036376953125 +74833 0.184417724609375 +74834 0.001007080078125 +74835 0.011199951171875 +74836 -0.061279296875 +74837 -0.171051025390625 +74838 -0.117950439453125 +74839 -0.33740234375 +74840 -0.16357421875 +74841 -0.47198486328125 +74842 -0.1932373046875 +74843 -0.560394287109375 +74844 -0.19940185546875 +74845 -0.58056640625 +74846 -0.18731689453125 +74847 -0.54754638671875 +74848 -0.173248291015625 +74849 -0.508575439453125 +74850 -0.155792236328125 +74851 -0.459503173828125 +74852 -0.132965087890625 +74853 -0.394378662109375 +74854 -0.1182861328125 +74855 -0.35260009765625 +74856 -0.104034423828125 +74857 -0.31170654296875 +74858 -0.064666748046875 +74859 -0.197418212890625 +74860 0.0003662109375 +74861 -0.007965087890625 +74862 0.07415771484375 +74863 0.207489013671875 +74864 0.14306640625 +74865 0.409210205078125 +74866 0.198486328125 +74867 0.57208251953125 +74868 0.2301025390625 +74869 0.66595458984375 +74870 0.226898193359375 +74871 0.65875244140625 +74872 0.19476318359375 +74873 0.56744384765625 +74874 0.14727783203125 +74875 0.431396484375 +74876 0.099578857421875 +74877 0.29443359375 +74878 0.060577392578125 +74879 0.182464599609375 +74880 0.019378662109375 +74881 0.06365966796875 +74882 -0.02880859375 +74883 -0.075958251953125 +74884 -0.06781005859375 +74885 -0.189422607421875 +74886 -0.095977783203125 +74887 -0.271942138671875 +74888 -0.119873046875 +74889 -0.342529296875 +74890 -0.126861572265625 +74891 -0.364166259765625 +74892 -0.113616943359375 +74893 -0.327239990234375 +74894 -0.095733642578125 +74895 -0.2769775390625 +74896 -0.087127685546875 +74897 -0.253692626953125 +74898 -0.08306884765625 +74899 -0.24365234375 +74900 -0.066925048828125 +74901 -0.1983642578125 +74902 -0.0382080078125 +74903 -0.116241455078125 +74904 -0.010498046875 +74905 -0.036834716796875 +74906 0.014434814453125 +74907 0.034881591796875 +74908 0.033935546875 +74909 0.09124755859375 +74910 0.03997802734375 +74911 0.10888671875 +74912 0.0455322265625 +74913 0.125518798828125 +74914 0.056304931640625 +74915 0.15771484375 +74916 0.062957763671875 +74917 0.17828369140625 +74918 0.059967041015625 +74919 0.17108154296875 +74920 0.0452880859375 +74921 0.129974365234375 +74922 0.02838134765625 +74923 0.082427978515625 +74924 0.009033203125 +74925 0.027679443359375 +74926 -0.02349853515625 +74927 -0.065643310546875 +74928 -0.056060791015625 +74929 -0.15936279296875 +74930 -0.074737548828125 +74931 -0.21307373046875 +74932 -0.082244873046875 +74933 -0.234649658203125 +74934 -0.07037353515625 +74935 -0.2001953125 +74936 -0.042388916015625 +74937 -0.119171142578125 +74938 -0.00970458984375 +74939 -0.024749755859375 +74940 0.028564453125 +74941 0.085784912109375 +74942 0.060577392578125 +74943 0.178131103515625 +74944 0.07373046875 +74945 0.215576171875 +74946 0.07257080078125 +74947 0.211456298828125 +74948 0.060394287109375 +74949 0.17523193359375 +74950 0.044677734375 +74951 0.128753662109375 +74952 0.03570556640625 +74953 0.1019287109375 +74954 0.02642822265625 +74955 0.0743408203125 +74956 0.015899658203125 +74957 0.04327392578125 +74958 0.014251708984375 +74959 0.038177490234375 +74960 0.027374267578125 +74961 0.076263427734375 +74962 0.049591064453125 +74963 0.14105224609375 +74964 0.065093994140625 +74965 0.186431884765625 +74966 0.06573486328125 +74967 0.188812255859375 +74968 0.048370361328125 +74969 0.1390380859375 +74970 0.0146484375 +74971 0.041778564453125 +74972 -0.027313232421875 +74973 -0.079437255859375 +74974 -0.07568359375 +74975 -0.219390869140625 +74976 -0.12689208984375 +74977 -0.367828369140625 +74978 -0.170684814453125 +74979 -0.494873046875 +74980 -0.19183349609375 +74981 -0.556243896484375 +74982 -0.175445556640625 +74983 -0.508697509765625 +74984 -0.12957763671875 +74985 -0.3756103515625 +74986 -0.0755615234375 +74987 -0.218902587890625 +74988 -0.022064208984375 +74989 -0.063751220703125 +74990 0.031463623046875 +74991 0.091552734375 +74992 0.081268310546875 +74993 0.23602294921875 +74994 0.1181640625 +74995 0.342987060546875 +74996 0.13623046875 +74997 0.39520263671875 +74998 0.134307861328125 +74999 0.389373779296875 +75000 0.111968994140625 +75001 0.324249267578125 +75002 0.077545166015625 +75003 0.224090576171875 +75004 0.043243408203125 +75005 0.124267578125 +75006 0.013275146484375 +75007 0.037078857421875 +75008 -0.00250244140625 +75009 -0.010101318359375 +75010 -0.00506591796875 +75011 -0.019439697265625 +75012 -0.00604248046875 +75013 -0.022796630859375 +75014 0.00177001953125 +75015 -0.001556396484375 +75016 0.023040771484375 +75017 0.056304931640625 +75018 0.0413818359375 +75019 0.106719970703125 +75020 0.037078857421875 +75021 0.096893310546875 +75022 0.016204833984375 +75023 0.042694091796875 +75024 -0.0069580078125 +75025 -0.018035888671875 +75026 -0.02886962890625 +75027 -0.07586669921875 +75028 -0.045257568359375 +75029 -0.11944580078125 +75030 -0.060272216796875 +75031 -0.15972900390625 +75032 -0.076171875 +75033 -0.202606201171875 +75034 -0.0931396484375 +75035 -0.24859619140625 +75036 -0.114044189453125 +75037 -0.30517578125 +75038 -0.13507080078125 +75039 -0.36212158203125 +75040 -0.145721435546875 +75041 -0.39141845703125 +75042 -0.1318359375 +75043 -0.35528564453125 +75044 -0.092041015625 +75045 -0.249969482421875 +75046 -0.03289794921875 +75047 -0.092864990234375 +75048 0.03546142578125 +75049 0.08905029296875 +75050 0.09027099609375 +75051 0.2352294921875 +75052 0.121429443359375 +75053 0.318817138671875 +75054 0.13604736328125 +75055 0.358642578125 +75056 0.13153076171875 +75057 0.347747802734375 +75058 0.10772705078125 +75059 0.28564453125 +75060 0.083770751953125 +75061 0.223175048828125 +75062 0.073394775390625 +75063 0.196746826171875 +75064 0.066650390625 +75065 0.179840087890625 +75066 0.05718994140625 +75067 0.155548095703125 +75068 0.055328369140625 +75069 0.151214599609375 +75070 0.057342529296875 +75071 0.156951904296875 +75072 0.047821044921875 +75073 0.13177490234375 +75074 0.03619384765625 +75075 0.100799560546875 +75076 0.03118896484375 +75077 0.087127685546875 +75078 0.019287109375 +75079 0.05487060546875 +75080 -0.004425048828125 +75081 -0.009002685546875 +75082 -0.039764404296875 +75083 -0.10400390625 +75084 -0.08648681640625 +75085 -0.229400634765625 +75086 -0.133453369140625 +75087 -0.35552978515625 +75088 -0.16546630859375 +75089 -0.441925048828125 +75090 -0.17706298828125 +75091 -0.473846435546875 +75092 -0.173309326171875 +75093 -0.464813232421875 +75094 -0.15582275390625 +75095 -0.419097900390625 +75096 -0.123748779296875 +75097 -0.334320068359375 +75098 -0.083648681640625 +75099 -0.227935791015625 +75100 -0.04437255859375 +75101 -0.12347412109375 +75102 -0.0084228515625 +75103 -0.02764892578125 +75104 0.031036376953125 +75105 0.077667236328125 +75106 0.081787109375 +75107 0.2132568359375 +75108 0.147491455078125 +75109 0.38885498046875 +75110 0.22003173828125 +75111 0.582794189453125 +75112 0.2764892578125 +75113 0.734039306640625 +75114 0.300933837890625 +75115 0.800140380859375 +75116 0.292327880859375 +75117 0.7783203125 +75118 0.249420166015625 +75119 0.6651611328125 +75120 0.171844482421875 +75121 0.45965576171875 +75122 0.07366943359375 +75123 0.199188232421875 +75124 -0.020416259765625 +75125 -0.050689697265625 +75126 -0.0889892578125 +75127 -0.23297119140625 +75128 -0.125457763671875 +75129 -0.33013916015625 +75130 -0.139678955078125 +75131 -0.368408203125 +75132 -0.14337158203125 +75133 -0.378936767578125 +75134 -0.142303466796875 +75135 -0.376983642578125 +75136 -0.142974853515625 +75137 -0.37969970703125 +75138 -0.14703369140625 +75139 -0.391510009765625 +75140 -0.14434814453125 +75141 -0.385345458984375 +75142 -0.127685546875 +75143 -0.3419189453125 +75144 -0.105194091796875 +75145 -0.28289794921875 +75146 -0.09320068359375 +75147 -0.251617431640625 +75148 -0.098480224609375 +75149 -0.266143798828125 +75150 -0.10107421875 +75151 -0.273345947265625 +75152 -0.079742431640625 +75153 -0.216796875 +75154 -0.04644775390625 +75155 -0.128265380859375 +75156 -0.023895263671875 +75157 -0.068145751953125 +75158 -0.014556884765625 +75159 -0.0430908203125 +75160 -0.0076904296875 +75161 -0.024444580078125 +75162 0.009063720703125 +75163 0.020721435546875 +75164 0.047760009765625 +75165 0.124481201171875 +75166 0.0975341796875 +75167 0.25787353515625 +75168 0.1427001953125 +75169 0.379119873046875 +75170 0.18017578125 +75171 0.47991943359375 +75172 0.197906494140625 +75173 0.5281982421875 +75174 0.19110107421875 +75175 0.511138916015625 +75176 0.170135498046875 +75177 0.456207275390625 +75178 0.151580810546875 +75179 0.407470703125 +75180 0.142547607421875 +75181 0.383758544921875 +75182 0.132415771484375 +75183 0.35687255859375 +75184 0.11553955078125 +75185 0.31182861328125 +75186 0.0927734375 +75187 0.250885009765625 +75188 0.06085205078125 +75189 0.1654052734375 +75190 0.01220703125 +75191 0.035247802734375 +75192 -0.054107666015625 +75193 -0.142059326171875 +75194 -0.126495361328125 +75195 -0.33563232421875 +75196 -0.20086669921875 +75197 -0.5345458984375 +75198 -0.2708740234375 +75199 -0.72186279296875 +75200 -0.3135986328125 +75201 -0.836669921875 +75202 -0.311676025390625 +75203 -0.8326416015625 +75204 -0.2725830078125 +75205 -0.7296142578125 +75206 -0.217041015625 +75207 -0.582550048828125 +75208 -0.163330078125 +75209 -0.440093994140625 +75210 -0.1197509765625 +75211 -0.324310302734375 +75212 -0.073638916015625 +75213 -0.20147705078125 +75214 -0.014801025390625 +75215 -0.044647216796875 +75216 0.04083251953125 +75217 0.103973388671875 +75218 0.0775146484375 +75219 0.202392578125 +75220 0.1004638671875 +75221 0.264495849609375 +75222 0.12799072265625 +75223 0.338897705078125 +75224 0.166961669921875 +75225 0.443817138671875 +75226 0.204559326171875 +75227 0.545074462890625 +75228 0.23126220703125 +75229 0.6173095703125 +75230 0.24407958984375 +75231 0.6524658203125 +75232 0.24786376953125 +75233 0.66339111328125 +75234 0.244903564453125 +75235 0.6561279296875 +75236 0.226226806640625 +75237 0.606781005859375 +75238 0.186492919921875 +75239 0.501190185546875 +75240 0.1307373046875 +75241 0.352783203125 +75242 0.06463623046875 +75243 0.176544189453125 +75244 -0.014556884765625 +75245 -0.034820556640625 +75246 -0.09814453125 +75247 -0.258209228515625 +75248 -0.16693115234375 +75249 -0.44244384765625 +75250 -0.21636962890625 +75251 -0.5753173828125 +75252 -0.244659423828125 +75253 -0.65203857421875 +75254 -0.240203857421875 +75255 -0.641632080078125 +75256 -0.2098388671875 +75257 -0.562164306640625 +75258 -0.170318603515625 +75259 -0.458038330078125 +75260 -0.129638671875 +75261 -0.350555419921875 +75262 -0.09564208984375 +75263 -0.260528564453125 +75264 -0.070037841796875 +75265 -0.192108154296875 +75266 -0.0516357421875 +75267 -0.141937255859375 +75268 -0.037200927734375 +75269 -0.1021728515625 +75270 -0.022857666015625 +75271 -0.062896728515625 +75272 -0.00372314453125 +75273 -0.011932373046875 +75274 0.025054931640625 +75275 0.062835693359375 +75276 0.058319091796875 +75277 0.148712158203125 +75278 0.094512939453125 +75279 0.241729736328125 +75280 0.136688232421875 +75281 0.34912109375 +75282 0.179351806640625 +75283 0.457305908203125 +75284 0.213470458984375 +75285 0.54388427734375 +75286 0.224456787109375 +75287 0.5728759765625 +75288 0.196990966796875 +75289 0.506591796875 +75290 0.133636474609375 +75291 0.351226806640625 +75292 0.05059814453125 +75293 0.146514892578125 +75294 -0.03076171875 +75295 -0.05523681640625 +75296 -0.0950927734375 +75297 -0.21624755859375 +75298 -0.141815185546875 +75299 -0.334930419921875 +75300 -0.1676025390625 +75301 -0.402984619140625 +75302 -0.181121826171875 +75303 -0.4412841796875 +75304 -0.20123291015625 +75305 -0.49578857421875 +75306 -0.2254638671875 +75307 -0.5601806640625 +75308 -0.24017333984375 +75309 -0.600738525390625 +75310 -0.231903076171875 +75311 -0.584228515625 +75312 -0.187896728515625 +75313 -0.47930908203125 +75314 -0.10552978515625 +75315 -0.27935791015625 +75316 0.005096435546875 +75317 -0.0089111328125 +75318 0.1181640625 +75319 0.268798828125 +75320 0.20477294921875 +75321 0.482818603515625 +75322 0.252960205078125 +75323 0.60369873046875 +75324 0.270538330078125 +75325 0.650421142578125 +75326 0.27435302734375 +75327 0.66400146484375 +75328 0.2633056640625 +75329 0.6414794921875 +75330 0.233306884765625 +75331 0.572540283203125 +75332 0.201141357421875 +75333 0.498138427734375 +75334 0.175537109375 +75335 0.439453125 +75336 0.148040771484375 +75337 0.375518798828125 +75338 0.105743408203125 +75339 0.274505615234375 +75340 0.03741455078125 +75341 0.1087646484375 +75342 -0.047821044921875 +75343 -0.099395751953125 +75344 -0.136993408203125 +75345 -0.3182373046875 +75346 -0.230621337890625 +75347 -0.5489501953125 +75348 -0.32147216796875 +75349 -0.7738037109375 +75350 -0.38800048828125 +75351 -0.86383056640625 +75352 -0.416717529296875 +75353 -0.870391845703125 +75354 -0.414947509765625 +75355 -0.86895751953125 +75356 -0.388153076171875 +75357 -0.861053466796875 +75358 -0.329376220703125 +75359 -0.765869140625 +75360 -0.234100341796875 +75361 -0.5301513671875 +75362 -0.10528564453125 +75363 -0.214691162109375 +75364 0.0394287109375 +75365 0.137359619140625 +75366 0.179046630859375 +75367 0.474822998046875 +75368 0.299041748046875 +75369 0.76239013671875 +75370 0.388397216796875 +75371 0.867462158203125 +75372 0.447296142578125 +75373 0.870361328125 +75374 0.471038818359375 +75375 0.86480712890625 +75376 0.461883544921875 +75377 0.831817626953125 +75378 0.429840087890625 +75379 0.677581787109375 +75380 0.377349853515625 +75381 0.495880126953125 +75382 0.31207275390625 +75383 0.30767822265625 +75384 0.2349853515625 +75385 0.116180419921875 +75386 0.1331787109375 +75387 -0.110748291015625 +75388 0.00390625 +75389 -0.381805419921875 +75390 -0.13531494140625 +75391 -0.6572265625 +75392 -0.259979248046875 +75393 -0.857421875 +75394 -0.3525390625 +75395 -0.870391845703125 +75396 -0.41009521484375 +75397 -0.870391845703125 +75398 -0.443572998046875 +75399 -0.86444091796875 +75400 -0.467559814453125 +75401 -0.85723876953125 +75402 -0.474639892578125 +75403 -0.790008544921875 +75404 -0.442718505859375 +75405 -0.62847900390625 +75406 -0.37054443359375 +75407 -0.3956298828125 +75408 -0.271575927734375 +75409 -0.126708984375 +75410 -0.157073974609375 +75411 0.150115966796875 +75412 -0.0318603515625 +75413 0.424041748046875 +75414 0.092987060546875 +75415 0.670623779296875 +75416 0.20159912109375 +75417 0.854522705078125 +75418 0.286712646484375 +75419 0.866485595703125 +75420 0.342010498046875 +75421 0.86920166015625 +75422 0.3748779296875 +75423 0.8653564453125 +75424 0.390777587890625 +75425 0.857147216796875 +75426 0.3885498046875 +75427 0.766845703125 +75428 0.370269775390625 +75429 0.628509521484375 +75430 0.333221435546875 +75431 0.462127685546875 +75432 0.287994384765625 +75433 0.297210693359375 +75434 0.239715576171875 +75435 0.14862060546875 +75436 0.179107666015625 +75437 -0.00537109375 +75438 0.1092529296875 +75439 -0.15753173828125 +75440 0.028778076171875 +75441 -0.31304931640625 +75442 -0.067962646484375 +75443 -0.48876953125 +75444 -0.161773681640625 +75445 -0.6416015625 +75446 -0.242523193359375 +75447 -0.751373291015625 +75448 -0.31964111328125 +75449 -0.84619140625 +75450 -0.3870849609375 +75451 -0.861297607421875 +75452 -0.431304931640625 +75453 -0.863250732421875 +75454 -0.439453125 +75455 -0.856597900390625 +75456 -0.416473388671875 +75457 -0.7498779296875 +75458 -0.386016845703125 +75459 -0.624542236328125 +75460 -0.339202880859375 +75461 -0.47808837890625 +75462 -0.252227783203125 +75463 -0.253387451171875 +75464 -0.143768310546875 +75465 0.003692626953125 +75466 -0.041778564453125 +75467 0.2257080078125 +75468 0.05877685546875 +75469 0.427154541015625 +75470 0.17108154296875 +75471 0.643218994140625 +75472 0.2911376953125 +75473 0.855926513671875 +75474 0.395263671875 +75475 0.870361328125 +75476 0.463165283203125 +75477 0.870361328125 +75478 0.497772216796875 +75479 0.862762451171875 +75480 0.49786376953125 +75481 0.79669189453125 +75482 0.4595947265625 +75483 0.595794677734375 +75484 0.3948974609375 +75485 0.362152099609375 +75486 0.315277099609375 +75487 0.1270751953125 +75488 0.229400634765625 +75489 -0.086944580078125 +75490 0.138214111328125 +75491 -0.2784423828125 +75492 0.027618408203125 +75493 -0.484832763671875 +75494 -0.110137939453125 +75495 -0.729583740234375 +75496 -0.25433349609375 +75497 -0.86688232421875 +75498 -0.379058837890625 +75499 -0.870391845703125 +75500 -0.48223876953125 +75501 -0.86859130859375 +75502 -0.56292724609375 +75503 -0.86279296875 +75504 -0.606414794921875 +75505 -0.817962646484375 +75506 -0.59417724609375 +75507 -0.6116943359375 +75508 -0.523284912109375 +75509 -0.3128662109375 +75510 -0.40753173828125 +75511 0.039398193359375 +75512 -0.255126953125 +75513 0.422821044921875 +75514 -0.079742431640625 +75515 0.805145263671875 +75516 0.090728759765625 +75517 0.870361328125 +75518 0.23291015625 +75519 0.870361328125 +75520 0.342071533203125 +75521 0.860015869140625 +75522 0.41448974609375 +75523 0.727935791015625 +75524 0.447357177734375 +75525 0.48114013671875 +75526 0.451080322265625 +75527 0.2059326171875 +75528 0.435302734375 +75529 -0.06103515625 +75530 0.404083251953125 +75531 -0.29913330078125 +75532 0.350738525390625 +75533 -0.516204833984375 +75534 0.26812744140625 +75535 -0.7252197265625 +75536 0.1668701171875 +75537 -0.85980224609375 +75538 0.061798095703125 +75539 -0.870391845703125 +75540 -0.0343017578125 +75541 -0.870391845703125 +75542 -0.10015869140625 +75543 -0.858062744140625 +75544 -0.134033203125 +75545 -0.673004150390625 +75546 -0.1590576171875 +75547 -0.42694091796875 +75548 -0.1947021484375 +75549 -0.2100830078125 +75550 -0.239990234375 +75551 -0.0362548828125 +75552 -0.281951904296875 +75553 0.10943603515625 +75554 -0.311614990234375 +75555 0.23516845703125 +75556 -0.310546875 +75557 0.373687744140625 +75558 -0.279388427734375 +75559 0.517791748046875 +75560 -0.245635986328125 +75561 0.602783203125 +75562 -0.206787109375 +75563 0.635711669921875 +75564 -0.14801025390625 +75565 0.655181884765625 +75566 -0.07354736328125 +75567 0.65948486328125 +75568 0.013153076171875 +75569 0.651275634765625 +75570 0.101318359375 +75571 0.61846923828125 +75572 0.174652099609375 +75573 0.53753662109375 +75574 0.22515869140625 +75575 0.404144287109375 +75576 0.2484130859375 +75577 0.22186279296875 +75578 0.24481201171875 +75579 0.003997802734375 +75580 0.22216796875 +75581 -0.22100830078125 +75582 0.189361572265625 +75583 -0.42449951171875 +75584 0.155609130859375 +75585 -0.579833984375 +75586 0.1395263671875 +75587 -0.641876220703125 +75588 0.138031005859375 +75589 -0.6177978515625 +75590 0.122528076171875 +75591 -0.575531005859375 +75592 0.090545654296875 +75593 -0.526336669921875 +75594 0.0648193359375 +75595 -0.42645263671875 +75596 0.057403564453125 +75597 -0.2581787109375 +75598 0.05230712890625 +75599 -0.068695068359375 +75600 0.032684326171875 +75601 0.09222412109375 +75602 0.006866455078125 +75603 0.232147216796875 +75604 -0.0205078125 +75605 0.3509521484375 +75606 -0.062286376953125 +75607 0.410064697265625 +75608 -0.131195068359375 +75609 0.372955322265625 +75610 -0.21783447265625 +75611 0.2554931640625 +75612 -0.299041748046875 +75613 0.10711669921875 +75614 -0.365997314453125 +75615 -0.052886962890625 +75616 -0.402618408203125 +75617 -0.186279296875 +75618 -0.38421630859375 +75619 -0.23291015625 +75620 -0.320709228515625 +75621 -0.209442138671875 +75622 -0.24102783203125 +75623 -0.174163818359375 +75624 -0.14886474609375 +75625 -0.126739501953125 +75626 -0.039947509765625 +75627 -0.048126220703125 +75628 0.07318115234375 +75629 0.0426025390625 +75630 0.169830322265625 +75631 0.10748291015625 +75632 0.2440185546875 +75633 0.1409912109375 +75634 0.316497802734375 +75635 0.19708251953125 +75636 0.38409423828125 +75637 0.273651123046875 +75638 0.422027587890625 +75639 0.31768798828125 +75640 0.4349365234375 +75641 0.341094970703125 +75642 0.43377685546875 +75643 0.368011474609375 +75644 0.4083251953125 +75645 0.37249755859375 +75646 0.3367919921875 +75647 0.30072021484375 +75648 0.221282958984375 +75649 0.1517333984375 +75650 0.091094970703125 +75651 -0.01470947265625 +75652 -0.045928955078125 +75653 -0.1883544921875 +75654 -0.18792724609375 +75655 -0.372711181640625 +75656 -0.307891845703125 +75657 -0.51397705078125 +75658 -0.384979248046875 +75659 -0.57177734375 +75660 -0.413665771484375 +75661 -0.53948974609375 +75662 -0.3997802734375 +75663 -0.43511962890625 +75664 -0.358428955078125 +75665 -0.2962646484375 +75666 -0.3056640625 +75667 -0.161102294921875 +75668 -0.247650146484375 +75669 -0.0435791015625 +75670 -0.18328857421875 +75671 0.060394287109375 +75672 -0.120208740234375 +75673 0.13665771484375 +75674 -0.066925048828125 +75675 0.170135498046875 +75676 -0.02374267578125 +75677 0.16552734375 +75678 0.02178955078125 +75679 0.15728759765625 +75680 0.06927490234375 +75681 0.150787353515625 +75682 0.105316162109375 +75683 0.12200927734375 +75684 0.131378173828125 +75685 0.080108642578125 +75686 0.156646728515625 +75687 0.05126953125 +75688 0.19134521484375 +75689 0.062896728515625 +75690 0.224273681640625 +75691 0.09271240234375 +75692 0.233642578125 +75693 0.092987060546875 +75694 0.22576904296875 +75695 0.07855224609375 +75696 0.20758056640625 +75697 0.06427001953125 +75698 0.173248291015625 +75699 0.0347900390625 +75700 0.1234130859375 +75701 -0.01171875 +75702 0.068328857421875 +75703 -0.056060791015625 +75704 0.0289306640625 +75705 -0.055511474609375 +75706 0.007354736328125 +75707 -0.010467529296875 +75708 -0.017822265625 +75709 0.02508544921875 +75710 -0.05560302734375 +75711 0.025665283203125 +75712 -0.092529296875 +75713 0.017333984375 +75714 -0.126129150390625 +75715 0.00189208984375 +75716 -0.160003662109375 +75717 -0.03173828125 +75718 -0.18804931640625 +75719 -0.071502685546875 +75720 -0.2178955078125 +75721 -0.13543701171875 +75722 -0.24810791015625 +75723 -0.219970703125 +75724 -0.268463134765625 +75725 -0.300506591796875 +75726 -0.27972412109375 +75727 -0.376312255859375 +75728 -0.269500732421875 +75729 -0.416107177734375 +75730 -0.218048095703125 +75731 -0.371124267578125 +75732 -0.127593994140625 +75733 -0.242279052734375 +75734 -0.0177001953125 +75735 -0.069732666015625 +75736 0.10052490234375 +75737 0.125640869140625 +75738 0.211639404296875 +75739 0.31268310546875 +75740 0.2982177734375 +75741 0.45501708984375 +75742 0.36004638671875 +75743 0.554779052734375 +75744 0.395721435546875 +75745 0.61065673828125 +75746 0.399688720703125 +75747 0.610931396484375 +75748 0.361328125 +75749 0.531463623046875 +75750 0.2880859375 +75751 0.3883056640625 +75752 0.20416259765625 +75753 0.23468017578125 +75754 0.121490478515625 +75755 0.095245361328125 +75756 0.05279541015625 +75757 -0.00396728515625 +75758 0.005859375 +75759 -0.04852294921875 +75760 -0.025054931640625 +75761 -0.055145263671875 +75762 -0.061279296875 +75763 -0.0758056640625 +75764 -0.11376953125 +75765 -0.138702392578125 +75766 -0.165985107421875 +75767 -0.209197998046875 +75768 -0.2176513671875 +75769 -0.289031982421875 +75770 -0.268280029296875 +75771 -0.37884521484375 +75772 -0.3076171875 +75773 -0.456329345703125 +75774 -0.33331298828125 +75775 -0.51641845703125 +75776 -0.327911376953125 +75777 -0.519287109375 +75778 -0.2889404296875 +75779 -0.458251953125 +75780 -0.240264892578125 +75781 -0.384796142578125 +75782 -0.194000244140625 +75783 -0.323699951171875 +75784 -0.148651123046875 +75785 -0.269287109375 +75786 -0.09356689453125 +75787 -0.1951904296875 +75788 -0.029296875 +75789 -0.100006103515625 +75790 0.0308837890625 +75791 -0.01055908203125 +75792 0.09954833984375 +75793 0.1033935546875 +75794 0.1790771484375 +75795 0.24908447265625 +75796 0.244842529296875 +75797 0.373199462890625 +75798 0.2884521484375 +75799 0.45806884765625 +75800 0.313262939453125 +75801 0.511474609375 +75802 0.333740234375 +75803 0.565399169921875 +75804 0.346435546875 +75805 0.61138916015625 +75806 0.32501220703125 +75807 0.5897216796875 +75808 0.26580810546875 +75809 0.4906005859375 +75810 0.17755126953125 +75811 0.33148193359375 +75812 0.077178955078125 +75813 0.147796630859375 +75814 -0.015533447265625 +75815 -0.01873779296875 +75816 -0.087066650390625 +75817 -0.140289306640625 +75818 -0.1253662109375 +75819 -0.191986083984375 +75820 -0.134368896484375 +75821 -0.184295654296875 +75822 -0.133575439453125 +75823 -0.161834716796875 +75824 -0.14141845703125 +75825 -0.166595458984375 +75826 -0.155609130859375 +75827 -0.19390869140625 +75828 -0.167449951171875 +75829 -0.22442626953125 +75830 -0.1868896484375 +75831 -0.279754638671875 +75832 -0.20489501953125 +75833 -0.3389892578125 +75834 -0.2005615234375 +75835 -0.3543701171875 +75836 -0.184600830078125 +75837 -0.348175048828125 +75838 -0.1602783203125 +75839 -0.32598876953125 +75840 -0.1151123046875 +75841 -0.2581787109375 +75842 -0.047637939453125 +75843 -0.139801025390625 +75844 0.034820556640625 +75845 0.014617919921875 +75846 0.104248046875 +75847 0.144378662109375 +75848 0.147308349609375 +75849 0.221038818359375 +75850 0.17535400390625 +75851 0.27069091796875 +75852 0.188507080078125 +75853 0.294036865234375 +75854 0.196014404296875 +75855 0.311767578125 +75856 0.20489501953125 +75857 0.339141845703125 +75858 0.20855712890625 +75859 0.360260009765625 +75860 0.200775146484375 +75861 0.360504150390625 +75862 0.167022705078125 +75863 0.308380126953125 +75864 0.097320556640625 +75865 0.18170166015625 +75866 0.003631591796875 +75867 0.0047607421875 +75868 -0.091400146484375 +75869 -0.17559814453125 +75870 -0.166015625 +75871 -0.3143310546875 +75872 -0.19921875 +75873 -0.36785888671875 +75874 -0.2030029296875 +75875 -0.36248779296875 +75876 -0.198486328125 +75877 -0.343536376953125 +75878 -0.181182861328125 +75879 -0.3018798828125 +75880 -0.14813232421875 +75881 -0.231414794921875 +75882 -0.092529296875 +75883 -0.117645263671875 +75884 -0.029815673828125 +75885 0.007049560546875 +75886 0.013916015625 +75887 0.087982177734375 +75888 0.045074462890625 +75889 0.13946533203125 +75890 0.06927490234375 +75891 0.17425537109375 +75892 0.0841064453125 +75893 0.188201904296875 +75894 0.084381103515625 +75895 0.171234130859375 +75896 0.06732177734375 +75897 0.118438720703125 +75898 0.045379638671875 +75899 0.05706787109375 +75900 0.019195556640625 +75901 -0.010711669921875 +75902 -0.01458740234375 +75903 -0.0914306640625 +75904 -0.045379638671875 +75905 -0.162322998046875 +75906 -0.0596923828125 +75907 -0.194549560546875 +75908 -0.039215087890625 +75909 -0.1492919921875 +75910 0.0184326171875 +75911 -0.02166748046875 +75912 0.083160400390625 +75913 0.124053955078125 +75914 0.118988037109375 +75915 0.211151123046875 +75916 0.126617431640625 +75917 0.240447998046875 +75918 0.120697021484375 +75919 0.242218017578125 +75920 0.105987548828125 +75921 0.2257080078125 +75922 0.08453369140625 +75923 0.194366455078125 +75924 0.041229248046875 +75925 0.115509033203125 +75926 -0.01239013671875 +75927 0.0128173828125 +75928 -0.04779052734375 +75929 -0.053802490234375 +75930 -0.077178955078125 +75931 -0.110626220703125 +75932 -0.1202392578125 +75933 -0.199493408203125 +75934 -0.1646728515625 +75935 -0.29437255859375 +75936 -0.1807861328125 +75937 -0.33221435546875 +75938 -0.15301513671875 +75939 -0.27972412109375 +75940 -0.1043701171875 +75941 -0.185333251953125 +75942 -0.072479248046875 +75943 -0.128204345703125 +75944 -0.06109619140625 +75945 -0.115692138671875 +75946 -0.055755615234375 +75947 -0.116455078125 +75948 -0.045196533203125 +75949 -0.105926513671875 +75950 -0.0155029296875 +75951 -0.053955078125 +75952 0.0374755859375 +75953 0.048797607421875 +75954 0.092254638671875 +75955 0.157318115234375 +75956 0.120513916015625 +75957 0.212005615234375 +75958 0.12481689453125 +75959 0.218475341796875 +75960 0.133697509765625 +75961 0.23724365234375 +75962 0.164703369140625 +75963 0.30535888671875 +75964 0.19830322265625 +75965 0.38128662109375 +75966 0.206024169921875 +75967 0.404449462890625 +75968 0.19732666015625 +75969 0.3944091796875 +75970 0.190093994140625 +75971 0.3885498046875 +75972 0.17315673828125 +75973 0.362640380859375 +75974 0.12646484375 +75975 0.27362060546875 +75976 0.0482177734375 +75977 0.11712646484375 +75978 -0.03680419921875 +75979 -0.054901123046875 +75980 -0.10406494140625 +75981 -0.19085693359375 +75982 -0.15106201171875 +75983 -0.28570556640625 +75984 -0.1776123046875 +75985 -0.339263916015625 +75986 -0.195953369140625 +75987 -0.3775634765625 +75988 -0.227386474609375 +75989 -0.445709228515625 +75990 -0.267913818359375 +75991 -0.535064697265625 +75992 -0.309814453125 +75993 -0.629058837890625 +75994 -0.33905029296875 +75995 -0.697601318359375 +75996 -0.338470458984375 +75997 -0.70391845703125 +75998 -0.305633544921875 +75999 -0.6424560546875 +76000 -0.230377197265625 +76001 -0.491241455078125 +76002 -0.120208740234375 +76003 -0.265716552734375 +76004 -0.002655029296875 +76005 -0.023712158203125 +76006 0.106536865234375 +76007 0.201751708984375 +76008 0.190765380859375 +76009 0.375823974609375 +76010 0.24359130859375 +76011 0.485076904296875 +76012 0.283538818359375 +76013 0.56884765625 +76014 0.314239501953125 +76015 0.634765625 +76016 0.314422607421875 +76017 0.63763427734375 +76018 0.27874755859375 +76019 0.5660400390625 +76020 0.231903076171875 +76021 0.4720458984375 +76022 0.1982421875 +76023 0.40692138671875 +76024 0.18133544921875 +76025 0.3778076171875 +76026 0.177703857421875 +76027 0.376953125 +76028 0.1722412109375 +76029 0.371978759765625 +76030 0.141632080078125 +76031 0.313140869140625 +76032 0.078216552734375 +76033 0.184417724609375 +76034 -0.006103515625 +76035 0.011199951171875 +76036 -0.09423828125 +76037 -0.171051025390625 +76038 -0.173919677734375 +76039 -0.33740234375 +76040 -0.2374267578125 +76041 -0.47198486328125 +76042 -0.277801513671875 +76043 -0.560394287109375 +76044 -0.284149169921875 +76045 -0.58056640625 +76046 -0.2642822265625 +76047 -0.54754638671875 +76048 -0.2421875 +76049 -0.508575439453125 +76050 -0.215850830078125 +76051 -0.459503173828125 +76052 -0.182373046875 +76053 -0.394378662109375 +76054 -0.16156005859375 +76055 -0.35260009765625 +76056 -0.142059326171875 +76057 -0.31170654296875 +76058 -0.08636474609375 +76059 -0.197418212890625 +76060 0.00653076171875 +76061 -0.007965087890625 +76062 0.11199951171875 +76063 0.207489013671875 +76064 0.210235595703125 +76065 0.409210205078125 +76066 0.28875732421875 +76067 0.57208251953125 +76068 0.33258056640625 +76069 0.66595458984375 +76070 0.325714111328125 +76071 0.65875244140625 +76072 0.27691650390625 +76073 0.56744384765625 +76074 0.206146240234375 +76075 0.431396484375 +76076 0.1356201171875 +76077 0.29443359375 +76078 0.07843017578125 +76079 0.182464599609375 +76080 0.0185546875 +76081 0.06365966796875 +76082 -0.051055908203125 +76083 -0.075958251953125 +76084 -0.1068115234375 +76085 -0.189422607421875 +76086 -0.1463623046875 +76087 -0.271942138671875 +76088 -0.179412841796875 +76089 -0.342529296875 +76090 -0.1875 +76091 -0.364166259765625 +76092 -0.16595458984375 +76093 -0.327239990234375 +76094 -0.1376953125 +76095 -0.2769775390625 +76096 -0.123199462890625 +76097 -0.253692626953125 +76098 -0.115692138671875 +76099 -0.24365234375 +76100 -0.090850830078125 +76101 -0.1983642578125 +76102 -0.048004150390625 +76103 -0.116241455078125 +76104 -0.00714111328125 +76105 -0.036834716796875 +76106 0.029205322265625 +76107 0.034881591796875 +76108 0.05718994140625 +76109 0.09124755859375 +76110 0.065093994140625 +76111 0.10888671875 +76112 0.07196044921875 +76113 0.125518798828125 +76114 0.08624267578125 +76115 0.15771484375 +76116 0.094329833984375 +76117 0.17828369140625 +76118 0.088226318359375 +76119 0.17108154296875 +76120 0.06500244140625 +76121 0.129974365234375 +76122 0.03863525390625 +76123 0.082427978515625 +76124 0.008880615234375 +76125 0.027679443359375 +76126 -0.039947509765625 +76127 -0.065643310546875 +76128 -0.0885009765625 +76129 -0.15936279296875 +76130 -0.11639404296875 +76131 -0.21307373046875 +76132 -0.1275634765625 +76133 -0.234649658203125 +76134 -0.109954833984375 +76135 -0.2001953125 +76136 -0.068389892578125 +76137 -0.119171142578125 +76138 -0.019622802734375 +76139 -0.024749755859375 +76140 0.037628173828125 +76141 0.085784912109375 +76142 0.0859375 +76143 0.178131103515625 +76144 0.106719970703125 +76145 0.215576171875 +76146 0.106597900390625 +76147 0.211456298828125 +76148 0.09027099609375 +76149 0.17523193359375 +76150 0.068634033203125 +76151 0.128753662109375 +76152 0.056671142578125 +76153 0.1019287109375 +76154 0.04400634765625 +76155 0.0743408203125 +76156 0.0291748046875 +76157 0.04327392578125 +76158 0.027008056640625 +76159 0.038177490234375 +76160 0.046142578125 +76161 0.076263427734375 +76162 0.078277587890625 +76163 0.14105224609375 +76164 0.100250244140625 +76165 0.186431884765625 +76166 0.1002197265625 +76167 0.188812255859375 +76168 0.07366943359375 +76169 0.1390380859375 +76170 0.023040771484375 +76171 0.041778564453125 +76172 -0.0396728515625 +76173 -0.079437255859375 +76174 -0.111785888671875 +76175 -0.219390869140625 +76176 -0.188018798828125 +76177 -0.367828369140625 +76178 -0.253265380859375 +76179 -0.494873046875 +76180 -0.28515625 +76181 -0.556243896484375 +76182 -0.2618408203125 +76183 -0.508697509765625 +76184 -0.195068359375 +76185 -0.3756103515625 +76186 -0.1160888671875 +76187 -0.218902587890625 +76188 -0.037567138671875 +76189 -0.063751220703125 +76190 0.041290283203125 +76191 0.091552734375 +76192 0.11492919921875 +76193 0.23602294921875 +76194 0.16986083984375 +76195 0.342987060546875 +76196 0.19732666015625 +76197 0.39520263671875 +76198 0.19561767578125 +76199 0.389373779296875 +76200 0.16400146484375 +76201 0.324249267578125 +76202 0.11468505859375 +76203 0.224090576171875 +76204 0.065399169921875 +76205 0.124267578125 +76206 0.022308349609375 +76207 0.037078857421875 +76208 -0.000823974609375 +76209 -0.010101318359375 +76210 -0.005126953125 +76211 -0.019439697265625 +76212 -0.006683349609375 +76213 -0.022796630859375 +76214 0.003875732421875 +76215 -0.001556396484375 +76216 0.032623291015625 +76217 0.056304931640625 +76218 0.057403564453125 +76219 0.106719970703125 +76220 0.0516357421875 +76221 0.096893310546875 +76222 0.02337646484375 +76223 0.042694091796875 +76224 -0.00823974609375 +76225 -0.018035888671875 +76226 -0.03839111328125 +76227 -0.07586669921875 +76228 -0.061309814453125 +76229 -0.11944580078125 +76230 -0.082489013671875 +76231 -0.15972900390625 +76232 -0.104827880859375 +76233 -0.202606201171875 +76234 -0.128509521484375 +76235 -0.24859619140625 +76236 -0.15728759765625 +76237 -0.30517578125 +76238 -0.18603515625 +76239 -0.36212158203125 +76240 -0.20068359375 +76241 -0.39141845703125 +76242 -0.18212890625 +76243 -0.35528564453125 +76244 -0.1285400390625 +76245 -0.249969482421875 +76246 -0.0487060546875 +76247 -0.092864990234375 +76248 0.043701171875 +76249 0.08905029296875 +76250 0.118133544921875 +76251 0.2352294921875 +76252 0.161041259765625 +76253 0.318817138671875 +76254 0.18182373046875 +76255 0.358642578125 +76256 0.176971435546875 +76257 0.347747802734375 +76258 0.14617919921875 +76259 0.28564453125 +76260 0.115081787109375 +76261 0.223175048828125 +76262 0.10198974609375 +76263 0.196746826171875 +76264 0.093536376953125 +76265 0.179840087890625 +76266 0.081207275390625 +76267 0.155548095703125 +76268 0.07879638671875 +76269 0.151214599609375 +76270 0.081329345703125 +76271 0.156951904296875 +76272 0.06817626953125 +76273 0.13177490234375 +76274 0.052001953125 +76275 0.100799560546875 +76276 0.04449462890625 +76277 0.087127685546875 +76278 0.027587890625 +76279 0.05487060546875 +76280 -0.005218505859375 +76281 -0.009002685546875 +76282 -0.053619384765625 +76283 -0.10400390625 +76284 -0.11724853515625 +76285 -0.229400634765625 +76286 -0.18115234375 +76287 -0.35552978515625 +76288 -0.225067138671875 +76289 -0.441925048828125 +76290 -0.241912841796875 +76291 -0.473846435546875 +76292 -0.238616943359375 +76293 -0.464813232421875 +76294 -0.21685791015625 +76295 -0.419097900390625 +76296 -0.174835205078125 +76297 -0.334320068359375 +76298 -0.121429443359375 +76299 -0.227935791015625 +76300 -0.06890869140625 +76301 -0.12347412109375 +76302 -0.02056884765625 +76303 -0.02764892578125 +76304 0.03350830078125 +76305 0.077667236328125 +76306 0.10455322265625 +76307 0.2132568359375 +76308 0.197845458984375 +76309 0.38885498046875 +76310 0.3017578125 +76311 0.582794189453125 +76312 0.383544921875 +76313 0.734039306640625 +76314 0.42034912109375 +76315 0.800140380859375 +76316 0.410552978515625 +76317 0.7783203125 +76318 0.3521728515625 +76319 0.6651611328125 +76320 0.244537353515625 +76321 0.45965576171875 +76322 0.107513427734375 +76323 0.199188232421875 +76324 -0.023895263671875 +76325 -0.050689697265625 +76326 -0.11932373046875 +76327 -0.23297119140625 +76328 -0.16949462890625 +76329 -0.33013916015625 +76330 -0.18853759765625 +76331 -0.368408203125 +76332 -0.1932373046875 +76333 -0.378936767578125 +76334 -0.19183349609375 +76335 -0.376983642578125 +76336 -0.193511962890625 +76337 -0.37969970703125 +76338 -0.200592041015625 +76339 -0.391510009765625 +76340 -0.198516845703125 +76341 -0.385345458984375 +76342 -0.1768798828125 +76343 -0.3419189453125 +76344 -0.147186279296875 +76345 -0.28289794921875 +76346 -0.132537841796875 +76347 -0.251617431640625 +76348 -0.14251708984375 +76349 -0.266143798828125 +76350 -0.14849853515625 +76351 -0.273345947265625 +76352 -0.1201171875 +76353 -0.216796875 +76354 -0.07427978515625 +76355 -0.128265380859375 +76356 -0.043304443359375 +76357 -0.068145751953125 +76358 -0.03070068359375 +76359 -0.0430908203125 +76360 -0.021087646484375 +76361 -0.024444580078125 +76362 0.003204345703125 +76363 0.020721435546875 +76364 0.059356689453125 +76365 0.124481201171875 +76366 0.13177490234375 +76367 0.25787353515625 +76368 0.197998046875 +76369 0.379119873046875 +76370 0.253509521484375 +76371 0.47991943359375 +76372 0.281036376953125 +76373 0.5281982421875 +76374 0.273590087890625 +76375 0.511138916015625 +76376 0.245819091796875 +76377 0.456207275390625 +76378 0.22125244140625 +76379 0.407470703125 +76380 0.20989990234375 +76381 0.383758544921875 +76382 0.196563720703125 +76383 0.35687255859375 +76384 0.17315673828125 +76385 0.31182861328125 +76386 0.140869140625 +76387 0.250885009765625 +76388 0.095062255859375 +76389 0.1654052734375 +76390 0.024993896484375 +76391 0.035247802734375 +76392 -0.070648193359375 +76393 -0.142059326171875 +76394 -0.175262451171875 +76395 -0.33563232421875 +76396 -0.282958984375 +76397 -0.5345458984375 +76398 -0.384552001953125 +76399 -0.72186279296875 +76400 -0.447357177734375 +76401 -0.836669921875 +76402 -0.44647216796875 +76403 -0.8326416015625 +76404 -0.392486572265625 +76405 -0.7296142578125 +76406 -0.31475830078125 +76407 -0.582550048828125 +76408 -0.23931884765625 +76409 -0.440093994140625 +76410 -0.177947998046875 +76411 -0.324310302734375 +76412 -0.112548828125 +76413 -0.20147705078125 +76414 -0.02862548828125 +76415 -0.044647216796875 +76416 0.0511474609375 +76417 0.103973388671875 +76418 0.104248046875 +76419 0.202392578125 +76420 0.138092041015625 +76421 0.264495849609375 +76422 0.1787109375 +76423 0.338897705078125 +76424 0.23583984375 +76425 0.443817138671875 +76426 0.29107666015625 +76427 0.545074462890625 +76428 0.330780029296875 +76429 0.6173095703125 +76430 0.3505859375 +76431 0.6524658203125 +76432 0.357330322265625 +76433 0.66339111328125 +76434 0.35418701171875 +76435 0.6561279296875 +76436 0.32830810546875 +76437 0.606781005859375 +76438 0.2720947265625 +76439 0.501190185546875 +76440 0.192718505859375 +76441 0.352783203125 +76442 0.09820556640625 +76443 0.176544189453125 +76444 -0.01531982421875 +76445 -0.034820556640625 +76446 -0.13543701171875 +76447 -0.258209228515625 +76448 -0.23468017578125 +76449 -0.44244384765625 +76450 -0.30645751953125 +76451 -0.5753173828125 +76452 -0.348236083984375 +76453 -0.65203857421875 +76454 -0.343353271484375 +76455 -0.641632080078125 +76456 -0.301483154296875 +76457 -0.562164306640625 +76458 -0.246368408203125 +76459 -0.458038330078125 +76460 -0.18939208984375 +76461 -0.350555419921875 +76462 -0.14166259765625 +76463 -0.260528564453125 +76464 -0.105377197265625 +76465 -0.192108154296875 +76466 -0.0787353515625 +76467 -0.141937255859375 +76468 -0.0574951171875 +76469 -0.1021728515625 +76470 -0.036346435546875 +76471 -0.062896728515625 +76472 -0.008758544921875 +76473 -0.011932373046875 +76474 0.031707763671875 +76475 0.062835693359375 +76476 0.0782470703125 +76477 0.148712158203125 +76478 0.128662109375 +76479 0.241729736328125 +76480 0.186798095703125 +76481 0.34912109375 +76482 0.245361328125 +76483 0.457305908203125 +76484 0.29229736328125 +76485 0.54388427734375 +76486 0.30828857421875 +76487 0.5728759765625 +76488 0.27313232421875 +76489 0.506591796875 +76490 0.19012451171875 +76491 0.351226806640625 +76492 0.08056640625 +76493 0.146514892578125 +76494 -0.027496337890625 +76495 -0.05523681640625 +76496 -0.113800048828125 +76497 -0.21624755859375 +76498 -0.177520751953125 +76499 -0.334930419921875 +76500 -0.214202880859375 +76501 -0.402984619140625 +76502 -0.235015869140625 +76503 -0.4412841796875 +76504 -0.26458740234375 +76505 -0.49578857421875 +76506 -0.299468994140625 +76507 -0.5601806640625 +76508 -0.32159423828125 +76509 -0.600738525390625 +76510 -0.3131103515625 +76511 -0.584228515625 +76512 -0.2572021484375 +76513 -0.47930908203125 +76514 -0.15032958984375 +76515 -0.27935791015625 +76516 -0.005615234375 +76517 -0.0089111328125 +76518 0.14300537109375 +76519 0.268798828125 +76520 0.257537841796875 +76521 0.482818603515625 +76522 0.322235107421875 +76523 0.60369873046875 +76524 0.347259521484375 +76525 0.650421142578125 +76526 0.354583740234375 +76527 0.66400146484375 +76528 0.3426513671875 +76529 0.6414794921875 +76530 0.305877685546875 +76531 0.572540283203125 +76532 0.266204833984375 +76533 0.498138427734375 +76534 0.2349853515625 +76535 0.439453125 +76536 0.20098876953125 +76537 0.375518798828125 +76538 0.147125244140625 +76539 0.274505615234375 +76540 0.058563232421875 +76541 0.1087646484375 +76542 -0.052734375 +76543 -0.099395751953125 +76544 -0.170257568359375 +76545 -0.3182373046875 +76546 -0.2955322265625 +76547 -0.5489501953125 +76548 -0.418792724609375 +76549 -0.7738037109375 +76550 -0.510162353515625 +76551 -0.86383056640625 +76552 -0.550872802734375 +76553 -0.870391845703125 +76554 -0.550933837890625 +76555 -0.86895751953125 +76556 -0.5177001953125 +76557 -0.861053466796875 +76558 -0.441192626953125 +76559 -0.765869140625 +76560 -0.314727783203125 +76561 -0.5301513671875 +76562 -0.14208984375 +76563 -0.214691162109375 +76564 0.052581787109375 +76565 0.137359619140625 +76566 0.240447998046875 +76567 0.474822998046875 +76568 0.40167236328125 +76569 0.76239013671875 +76570 0.521209716796875 +76571 0.867462158203125 +76572 0.59954833984375 +76573 0.870361328125 +76574 0.630340576171875 +76575 0.86480712890625 +76576 0.616790771484375 +76577 0.831817626953125 +76578 0.572845458984375 +76579 0.677581787109375 +76580 0.5018310546875 +76581 0.495880126953125 +76582 0.414215087890625 +76583 0.30767822265625 +76584 0.311126708984375 +76585 0.116180419921875 +76586 0.174407958984375 +76587 -0.110748291015625 +76588 -6.103515625e-05 +76589 -0.381805419921875 +76590 -0.188232421875 +76591 -0.6572265625 +76592 -0.3563232421875 +76593 -0.857421875 +76594 -0.480194091796875 +76595 -0.870391845703125 +76596 -0.5560302734375 +76597 -0.870391845703125 +76598 -0.599334716796875 +76599 -0.86444091796875 +76600 -0.63055419921875 +76601 -0.85723876953125 +76602 -0.639404296875 +76603 -0.790008544921875 +76604 -0.595184326171875 +76605 -0.62847900390625 +76606 -0.49609375 +76607 -0.3956298828125 +76608 -0.36077880859375 +76609 -0.126708984375 +76610 -0.2047119140625 +76611 0.150115966796875 +76612 -0.034393310546875 +76613 0.424041748046875 +76614 0.134979248046875 +76615 0.670623779296875 +76616 0.28155517578125 +76617 0.854522705078125 +76618 0.395477294921875 +76619 0.866485595703125 +76620 0.468231201171875 +76621 0.86920166015625 +76622 0.51031494140625 +76623 0.8653564453125 +76624 0.529510498046875 +76625 0.857147216796875 +76626 0.524322509765625 +76627 0.766845703125 +76628 0.497772216796875 +76629 0.628509521484375 +76630 0.44610595703125 +76631 0.462127685546875 +76632 0.384002685546875 +76633 0.297210693359375 +76634 0.318511962890625 +76635 0.14862060546875 +76636 0.23663330078125 +76637 -0.00537109375 +76638 0.142547607421875 +76639 -0.15753173828125 +76640 0.03411865234375 +76641 -0.31304931640625 +76642 -0.09674072265625 +76643 -0.48876953125 +76644 -0.2235107421875 +76645 -0.6416015625 +76646 -0.332305908203125 +76647 -0.751373291015625 +76648 -0.4364013671875 +76649 -0.84619140625 +76650 -0.527587890625 +76651 -0.861297607421875 +76652 -0.587158203125 +76653 -0.863250732421875 +76654 -0.5972900390625 +76655 -0.856597900390625 +76656 -0.564971923828125 +76657 -0.7498779296875 +76658 -0.523101806640625 +76659 -0.624542236328125 +76660 -0.459197998046875 +76661 -0.47808837890625 +76662 -0.340057373046875 +76663 -0.253387451171875 +76664 -0.1915283203125 +76665 0.003692626953125 +76666 -0.052398681640625 +76667 0.2257080078125 +76668 0.084503173828125 +76669 0.427154541015625 +76670 0.237701416015625 +76671 0.643218994140625 +76672 0.40179443359375 +76673 0.855926513671875 +76674 0.543975830078125 +76675 0.870361328125 +76676 0.63616943359375 +76677 0.870361328125 +76678 0.682525634765625 +76679 0.862762451171875 +76680 0.68145751953125 +76681 0.79669189453125 +76682 0.627685546875 +76683 0.595794677734375 +76684 0.537811279296875 +76685 0.362152099609375 +76686 0.42779541015625 +76687 0.1270751953125 +76688 0.3096923828125 +76689 -0.086944580078125 +76690 0.1846923828125 +76691 -0.2784423828125 +76692 0.032989501953125 +76693 -0.484832763671875 +76694 -0.15631103515625 +76695 -0.729583740234375 +76696 -0.3544921875 +76697 -0.86688232421875 +76698 -0.525634765625 +76699 -0.870391845703125 +76700 -0.666961669921875 +76701 -0.86859130859375 +76702 -0.77734375 +76703 -0.86279296875 +76704 -0.83636474609375 +76705 -0.817962646484375 +76706 -0.818267822265625 +76707 -0.6116943359375 +76708 -0.71905517578125 +76709 -0.3128662109375 +76710 -0.55792236328125 +76711 0.039398193359375 +76712 -0.3463134765625 +76713 0.422821044921875 +76714 -0.103179931640625 +76715 0.805145263671875 +76716 0.132720947265625 +76717 0.870361328125 +76718 0.328948974609375 +76719 0.870361328125 +76720 0.478759765625 +76721 0.860015869140625 +76722 0.577728271484375 +76723 0.727935791015625 +76724 0.62255859375 +76725 0.48114013671875 +76726 0.62689208984375 +76727 0.2059326171875 +76728 0.603485107421875 +76729 -0.06103515625 +76730 0.5579833984375 +76731 -0.29913330078125 +76732 0.482147216796875 +76733 -0.516204833984375 +76734 0.36724853515625 +76735 -0.7252197265625 +76736 0.2275390625 +76737 -0.85980224609375 +76738 0.0826416015625 +76739 -0.870391845703125 +76740 -0.0504150390625 +76741 -0.870391845703125 +76742 -0.14373779296875 +76743 -0.858062744140625 +76744 -0.19464111328125 +76745 -0.673004150390625 +76746 -0.232635498046875 +76747 -0.42694091796875 +76748 -0.28265380859375 +76749 -0.2100830078125 +76750 -0.343231201171875 +76751 -0.0362548828125 +76752 -0.3975830078125 +76753 0.10943603515625 +76754 -0.4342041015625 +76755 0.23516845703125 +76756 -0.42950439453125 +76757 0.373687744140625 +76758 -0.384490966796875 +76759 0.517791748046875 +76760 -0.3349609375 +76761 0.602783203125 +76762 -0.278076171875 +76763 0.635711669921875 +76764 -0.195068359375 +76765 0.655181884765625 +76766 -0.091796875 +76767 0.65948486328125 +76768 0.026885986328125 +76769 0.651275634765625 +76770 0.146728515625 +76771 0.61846923828125 +76772 0.246368408203125 +76773 0.53753662109375 +76774 0.31524658203125 +76775 0.404144287109375 +76776 0.3475341796875 +76777 0.22186279296875 +76778 0.3436279296875 +76779 0.003997802734375 +76780 0.3135986328125 +76781 -0.22100830078125 +76782 0.26904296875 +76783 -0.42449951171875 +76784 0.221954345703125 +76785 -0.579833984375 +76786 0.19659423828125 +76787 -0.641876220703125 +76788 0.18927001953125 +76789 -0.6177978515625 +76790 0.163421630859375 +76791 -0.575531005859375 +76792 0.116180419921875 +76793 -0.526336669921875 +76794 0.077239990234375 +76795 -0.42645263671875 +76796 0.062469482421875 +76797 -0.2581787109375 +76798 0.051513671875 +76799 -0.068695068359375 +76800 0.0233154296875 +76801 0.09222412109375 +76802 -0.010650634765625 +76803 0.232147216796875 +76804 -0.044830322265625 +76805 0.3509521484375 +76806 -0.097320556640625 +76807 0.410064697265625 +76808 -0.186004638671875 +76809 0.372955322265625 +76810 -0.29852294921875 +76811 0.2554931640625 +76812 -0.40374755859375 +76813 0.10711669921875 +76814 -0.49005126953125 +76815 -0.052886962890625 +76816 -0.535797119140625 +76817 -0.186279296875 +76818 -0.50750732421875 +76819 -0.23291015625 +76820 -0.41888427734375 +76821 -0.209442138671875 +76822 -0.309478759765625 +76823 -0.174163818359375 +76824 -0.18426513671875 +76825 -0.126739501953125 +76826 -0.037322998046875 +76827 -0.048126220703125 +76828 0.114410400390625 +76829 0.0426025390625 +76830 0.242950439453125 +76831 0.10748291015625 +76832 0.340301513671875 +76833 0.1409912109375 +76834 0.435028076171875 +76835 0.19708251953125 +76836 0.52301025390625 +76837 0.273651123046875 +76838 0.570709228515625 +76839 0.31768798828125 +76840 0.584716796875 +76841 0.341094970703125 +76842 0.580108642578125 +76843 0.368011474609375 +76844 0.543060302734375 +76845 0.37249755859375 +76846 0.4439697265625 +76847 0.30072021484375 +76848 0.285797119140625 +76849 0.1517333984375 +76850 0.108489990234375 +76851 -0.01470947265625 +76852 -0.077301025390625 +76853 -0.1883544921875 +76854 -0.269073486328125 +76855 -0.372711181640625 +76856 -0.43017578125 +76857 -0.51397705078125 +76858 -0.5323486328125 +76859 -0.57177734375 +76860 -0.56817626953125 +76861 -0.53948974609375 +76862 -0.54583740234375 +76863 -0.43511962890625 +76864 -0.486114501953125 +76865 -0.2962646484375 +76866 -0.411102294921875 +76867 -0.161102294921875 +76868 -0.329345703125 +76869 -0.0435791015625 +76870 -0.239501953125 +76871 0.060394287109375 +76872 -0.152008056640625 +76873 0.13665771484375 +76874 -0.078582763671875 +76875 0.170135498046875 +76876 -0.0196533203125 +76877 0.16552734375 +76878 0.041778564453125 +76879 0.15728759765625 +76880 0.105224609375 +76881 0.150787353515625 +76882 0.152557373046875 +76883 0.12200927734375 +76884 0.18585205078125 +76885 0.080108642578125 +76886 0.2177734375 +76887 0.05126953125 +76888 0.26239013671875 +76889 0.062896728515625 +76890 0.304595947265625 +76891 0.09271240234375 +76892 0.3148193359375 +76893 0.092987060546875 +76894 0.301788330078125 +76895 0.07855224609375 +76896 0.275115966796875 +76897 0.06427001953125 +76898 0.226959228515625 +76899 0.0347900390625 +76900 0.158203125 +76901 -0.01171875 +76902 0.0828857421875 +76903 -0.056060791015625 +76904 0.029541015625 +76905 -0.055511474609375 +76906 0.001007080078125 +76907 -0.010467529296875 +76908 -0.031982421875 +76909 0.02508544921875 +76910 -0.081787109375 +76911 0.025665283203125 +76912 -0.130157470703125 +76913 0.017333984375 +76914 -0.173858642578125 +76915 0.00189208984375 +76916 -0.217926025390625 +76917 -0.03173828125 +76918 -0.254150390625 +76919 -0.071502685546875 +76920 -0.292999267578125 +76921 -0.13543701171875 +76922 -0.3326416015625 +76923 -0.219970703125 +76924 -0.3592529296875 +76925 -0.300506591796875 +76926 -0.373870849609375 +76927 -0.376312255859375 +76928 -0.35968017578125 +76929 -0.416107177734375 +76930 -0.289703369140625 +76931 -0.371124267578125 +76932 -0.166961669921875 +76933 -0.242279052734375 +76934 -0.01812744140625 +76935 -0.069732666015625 +76936 0.141815185546875 +76937 0.125640869140625 +76938 0.291900634765625 +76939 0.31268310546875 +76940 0.40838623046875 +76941 0.45501708984375 +76942 0.491058349609375 +76943 0.554779052734375 +76944 0.538116455078125 +76945 0.61065673828125 +76946 0.54205322265625 +76947 0.610931396484375 +76948 0.48846435546875 +76949 0.531463623046875 +76950 0.387603759765625 +76951 0.3883056640625 +76952 0.2724609375 +76953 0.23468017578125 +76954 0.159332275390625 +76955 0.095245361328125 +76956 0.06561279296875 +76957 -0.00396728515625 +76958 0.001953125 +76959 -0.04852294921875 +76960 -0.039581298828125 +76961 -0.055145263671875 +76962 -0.08807373046875 +76963 -0.0758056640625 +76964 -0.1585693359375 +76965 -0.138702392578125 +76966 -0.228546142578125 +76967 -0.209197998046875 +76968 -0.297698974609375 +76969 -0.289031982421875 +76970 -0.365447998046875 +76971 -0.37884521484375 +76972 -0.417816162109375 +76973 -0.456329345703125 +76974 -0.45172119140625 +76975 -0.51641845703125 +76976 -0.443634033203125 +76977 -0.519287109375 +76978 -0.3902587890625 +76979 -0.458251953125 +76980 -0.3236083984375 +76981 -0.384796142578125 +76982 -0.25994873046875 +76983 -0.323699951171875 +76984 -0.19744873046875 +76985 -0.269287109375 +76986 -0.122039794921875 +76987 -0.1951904296875 +76988 -0.034576416015625 +76989 -0.100006103515625 +76990 0.04718017578125 +76991 -0.01055908203125 +76992 0.139892578125 +76993 0.1033935546875 +76994 0.2467041015625 +76995 0.24908447265625 +76996 0.334716796875 +76997 0.373199462890625 +76998 0.392730712890625 +76999 0.45806884765625 +77000 0.42523193359375 +77001 0.511474609375 +77002 0.451568603515625 +77003 0.565399169921875 +77004 0.467193603515625 +77005 0.61138916015625 +77006 0.437103271484375 +77007 0.5897216796875 +77008 0.35650634765625 +77009 0.4906005859375 +77010 0.237152099609375 +77011 0.33148193359375 +77012 0.10162353515625 +77013 0.147796630859375 +77014 -0.023590087890625 +77015 -0.01873779296875 +77016 -0.120391845703125 +77017 -0.140289306640625 +77018 -0.172607421875 +77019 -0.191986083984375 +77020 -0.1854248046875 +77021 -0.184295654296875 +77022 -0.184783935546875 +77023 -0.161834716796875 +77024 -0.1953125 +77025 -0.166595458984375 +77026 -0.21392822265625 +77027 -0.19390869140625 +77028 -0.22906494140625 +77029 -0.22442626953125 +77030 -0.253997802734375 +77031 -0.279754638671875 +77032 -0.27679443359375 +77033 -0.3389892578125 +77034 -0.2696533203125 +77035 -0.3543701171875 +77036 -0.246917724609375 +77037 -0.348175048828125 +77038 -0.213043212890625 +77039 -0.32598876953125 +77040 -0.15142822265625 +77041 -0.2581787109375 +77042 -0.06024169921875 +77043 -0.139801025390625 +77044 0.05072021484375 +77045 0.014617919921875 +77046 0.14404296875 +77047 0.144378662109375 +77048 0.201904296875 +77049 0.221038818359375 +77050 0.23944091796875 +77051 0.27069091796875 +77052 0.256805419921875 +77053 0.294036865234375 +77054 0.266326904296875 +77055 0.311767578125 +77056 0.2774658203125 +77057 0.339141845703125 +77058 0.281463623046875 +77059 0.360260009765625 +77060 0.270050048828125 +77061 0.360504150390625 +77062 0.223876953125 +77063 0.308380126953125 +77064 0.12957763671875 +77065 0.18170166015625 +77066 0.00323486328125 +77067 0.0047607421875 +77068 -0.12481689453125 +77069 -0.17559814453125 +77070 -0.225372314453125 +77071 -0.3143310546875 +77072 -0.270294189453125 +77073 -0.36785888671875 +77074 -0.275634765625 +77075 -0.36248779296875 +77076 -0.2696533203125 +77077 -0.343536376953125 +77078 -0.246337890625 +77079 -0.3018798828125 +77080 -0.201751708984375 +77081 -0.231414794921875 +77082 -0.12677001953125 +77083 -0.117645263671875 +77084 -0.042144775390625 +77085 0.007049560546875 +77086 0.01715087890625 +77087 0.087982177734375 +77088 0.0596923828125 +77089 0.13946533203125 +77090 0.09295654296875 +77091 0.17425537109375 +77092 0.1136474609375 +77093 0.188201904296875 +77094 0.11474609375 +77095 0.171234130859375 +77096 0.092498779296875 +77097 0.118438720703125 +77098 0.063568115234375 +77099 0.05706787109375 +77100 0.028778076171875 +77101 -0.010711669921875 +77102 -0.016326904296875 +77103 -0.0914306640625 +77104 -0.057647705078125 +77105 -0.162322998046875 +77106 -0.07708740234375 +77107 -0.194549560546875 +77108 -0.050079345703125 +77109 -0.1492919921875 +77110 0.026611328125 +77111 -0.02166748046875 +77112 0.112640380859375 +77113 0.124053955078125 +77114 0.159912109375 +77115 0.211151123046875 +77116 0.16943359375 +77117 0.240447998046875 +77118 0.160858154296875 +77119 0.242218017578125 +77120 0.140625 +77121 0.2257080078125 +77122 0.111419677734375 +77123 0.194366455078125 +77124 0.053070068359375 +77125 0.115509033203125 +77126 -0.01898193359375 +77127 0.0128173828125 +77128 -0.0665283203125 +77129 -0.053802490234375 +77130 -0.10589599609375 +77131 -0.110626220703125 +77132 -0.1634521484375 +77133 -0.199493408203125 +77134 -0.22271728515625 +77135 -0.29437255859375 +77136 -0.243927001953125 +77137 -0.33221435546875 +77138 -0.206298828125 +77139 -0.27972412109375 +77140 -0.140716552734375 +77141 -0.185333251953125 +77142 -0.097564697265625 +77143 -0.128204345703125 +77144 -0.081878662109375 +77145 -0.115692138671875 +77146 -0.074310302734375 +77147 -0.116455078125 +77148 -0.059783935546875 +77149 -0.105926513671875 +77150 -0.019683837890625 +77151 -0.053955078125 +77152 0.051513671875 +77153 0.048797607421875 +77154 0.125030517578125 +77155 0.157318115234375 +77156 0.162994384765625 +77157 0.212005615234375 +77158 0.168792724609375 +77159 0.218475341796875 +77160 0.1806640625 +77161 0.23724365234375 +77162 0.222076416015625 +77163 0.30535888671875 +77164 0.266876220703125 +77165 0.38128662109375 +77166 0.2769775390625 +77167 0.404449462890625 +77168 0.265045166015625 +77169 0.3944091796875 +77170 0.25506591796875 +77171 0.3885498046875 +77172 0.232086181640625 +77173 0.362640380859375 +77174 0.16925048828125 +77175 0.27362060546875 +77176 0.064178466796875 +77177 0.11712646484375 +77178 -0.04998779296875 +77179 -0.054901123046875 +77180 -0.14031982421875 +77181 -0.19085693359375 +77182 -0.20343017578125 +77183 -0.28570556640625 +77184 -0.239105224609375 +77185 -0.339263916015625 +77186 -0.26373291015625 +77187 -0.3775634765625 +77188 -0.30584716796875 +77189 -0.445709228515625 +77190 -0.360076904296875 +77191 -0.535064697265625 +77192 -0.416107177734375 +77193 -0.629058837890625 +77194 -0.455108642578125 +77195 -0.697601318359375 +77196 -0.454132080078125 +77197 -0.70391845703125 +77198 -0.409942626953125 +77199 -0.6424560546875 +77200 -0.3089599609375 +77201 -0.491241455078125 +77202 -0.161224365234375 +77203 -0.265716552734375 +77204 -0.003570556640625 +77205 -0.023712158203125 +77206 0.142852783203125 +77207 0.201751708984375 +77208 0.255828857421875 +77209 0.375823974609375 +77210 0.326751708984375 +77211 0.485076904296875 +77212 0.38043212890625 +77213 0.56884765625 +77214 0.42169189453125 +77215 0.634765625 +77216 0.4219970703125 +77217 0.63763427734375 +77218 0.374237060546875 +77219 0.5660400390625 +77220 0.311492919921875 +77221 0.4720458984375 +77222 0.266357421875 +77223 0.40692138671875 +77224 0.24359130859375 +77225 0.3778076171875 +77226 0.238555908203125 +77227 0.376953125 +77228 0.23101806640625 +77229 0.371978759765625 +77230 0.189788818359375 +77231 0.313140869140625 +77232 0.104949951171875 +77233 0.184417724609375 +77234 -0.00726318359375 +77235 0.011199951171875 +77236 -0.124298095703125 +77237 -0.171051025390625 +77238 -0.2303466796875 +77239 -0.33740234375 +77240 -0.315338134765625 +77241 -0.47198486328125 +77242 -0.370208740234375 +77243 -0.560394287109375 +77244 -0.381103515625 +77245 -0.58056640625 +77246 -0.357666015625 +77247 -0.54754638671875 +77248 -0.329925537109375 +77249 -0.508575439453125 +77250 -0.295440673828125 +77251 -0.459503173828125 +77252 -0.250640869140625 +77253 -0.394378662109375 +77254 -0.220611572265625 +77255 -0.35260009765625 +77256 -0.19134521484375 +77257 -0.31170654296875 +77258 -0.116058349609375 +77259 -0.197418212890625 +77260 0.00616455078125 +77261 -0.007965087890625 +77262 0.14410400390625 +77263 0.207489013671875 +77264 0.2725830078125 +77265 0.409210205078125 +77266 0.375701904296875 +77267 0.57208251953125 +77268 0.434417724609375 +77269 0.66595458984375 +77270 0.42852783203125 +77271 0.65875244140625 +77272 0.36883544921875 +77273 0.56744384765625 +77274 0.280364990234375 +77275 0.431396484375 +77276 0.190948486328125 +77277 0.29443359375 +77278 0.117156982421875 +77279 0.182464599609375 +77280 0.039031982421875 +77281 0.06365966796875 +77282 -0.052093505859375 +77283 -0.075958251953125 +77284 -0.126373291015625 +77285 -0.189422607421875 +77286 -0.180633544921875 +77287 -0.271942138671875 +77288 -0.226776123046875 +77289 -0.342529296875 +77290 -0.241363525390625 +77291 -0.364166259765625 +77292 -0.21832275390625 +77293 -0.327239990234375 +77294 -0.18621826171875 +77295 -0.2769775390625 +77296 -0.170562744140625 +77297 -0.253692626953125 +77298 -0.1627197265625 +77299 -0.24365234375 +77300 -0.132171630859375 +77301 -0.1983642578125 +77302 -0.078033447265625 +77303 -0.116241455078125 +77304 -0.025390625 +77305 -0.036834716796875 +77306 0.022430419921875 +77307 0.034881591796875 +77308 0.060455322265625 +77309 0.09124755859375 +77310 0.07379150390625 +77311 0.10888671875 +77312 0.086517333984375 +77313 0.125518798828125 +77314 0.109161376953125 +77315 0.15771484375 +77316 0.12396240234375 +77317 0.17828369140625 +77318 0.1199951171875 +77319 0.17108154296875 +77320 0.093109130859375 +77321 0.129974365234375 +77322 0.06146240234375 +77323 0.082427978515625 +77324 0.024566650390625 +77325 0.027679443359375 +77326 -0.03839111328125 +77327 -0.065643310546875 +77328 -0.101959228515625 +77329 -0.15936279296875 +77330 -0.13922119140625 +77331 -0.21307373046875 +77332 -0.155303955078125 +77333 -0.234649658203125 +77334 -0.13421630859375 +77335 -0.2001953125 +77336 -0.082122802734375 +77337 -0.119171142578125 +77338 -0.020965576171875 +77339 -0.024749755859375 +77340 0.0511474609375 +77341 0.085784912109375 +77342 0.11151123046875 +77343 0.178131103515625 +77344 0.135833740234375 +77345 0.215576171875 +77346 0.132965087890625 +77347 0.211456298828125 +77348 0.10919189453125 +77349 0.17523193359375 +77350 0.0789794921875 +77351 0.128753662109375 +77352 0.062164306640625 +77353 0.1019287109375 +77354 0.045135498046875 +77355 0.0743408203125 +77356 0.0260009765625 +77357 0.04327392578125 +77358 0.024200439453125 +77359 0.038177490234375 +77360 0.05108642578125 +77361 0.076263427734375 +77362 0.095611572265625 +77363 0.14105224609375 +77364 0.127105712890625 +77365 0.186431884765625 +77366 0.12982177734375 +77367 0.188812255859375 +77368 0.09765625 +77369 0.1390380859375 +77370 0.033660888671875 +77371 0.041778564453125 +77372 -0.04656982421875 +77373 -0.079437255859375 +77374 -0.13958740234375 +77375 -0.219390869140625 +77376 -0.238555908203125 +77377 -0.367828369140625 +77378 -0.3236083984375 +77379 -0.494873046875 +77380 -0.36529541015625 +77381 -0.556243896484375 +77382 -0.3348388671875 +77383 -0.508697509765625 +77384 -0.247711181640625 +77385 -0.3756103515625 +77386 -0.14495849609375 +77387 -0.218902587890625 +77388 -0.043212890625 +77389 -0.063751220703125 +77390 0.058685302734375 +77391 0.091552734375 +77392 0.153533935546875 +77393 0.23602294921875 +77394 0.223663330078125 +77395 0.342987060546875 +77396 0.2576904296875 +77397 0.39520263671875 +77398 0.25347900390625 +77399 0.389373779296875 +77400 0.210174560546875 +77401 0.324249267578125 +77402 0.143890380859375 +77403 0.224090576171875 +77404 0.078094482421875 +77405 0.124267578125 +77406 0.0208740234375 +77407 0.037078857421875 +77408 -0.00958251953125 +77409 -0.010101318359375 +77410 -0.014801025390625 +77411 -0.019439697265625 +77412 -0.01593017578125 +77413 -0.022796630859375 +77414 -0.000701904296875 +77415 -0.001556396484375 +77416 0.038787841796875 +77417 0.056304931640625 +77418 0.073211669921875 +77419 0.106719970703125 +77420 0.067474365234375 +77421 0.096893310546875 +77422 0.0321044921875 +77423 0.042694091796875 +77424 -0.0078125 +77425 -0.018035888671875 +77426 -0.046051025390625 +77427 -0.07586669921875 +77428 -0.075042724609375 +77429 -0.11944580078125 +77430 -0.102081298828125 +77431 -0.15972900390625 +77432 -0.13104248046875 +77433 -0.202606201171875 +77434 -0.162200927734375 +77435 -0.24859619140625 +77436 -0.20050048828125 +77437 -0.30517578125 +77438 -0.239105224609375 +77439 -0.36212158203125 +77440 -0.2593994140625 +77441 -0.39141845703125 +77442 -0.236236572265625 +77443 -0.35528564453125 +77444 -0.1671142578125 +77445 -0.249969482421875 +77446 -0.06353759765625 +77447 -0.092864990234375 +77448 0.056640625 +77449 0.08905029296875 +77450 0.15325927734375 +77451 0.2352294921875 +77452 0.20849609375 +77453 0.318817138671875 +77454 0.23486328125 +77455 0.358642578125 +77456 0.227752685546875 +77457 0.347747802734375 +77458 0.186798095703125 +77459 0.28564453125 +77460 0.145751953125 +77461 0.223175048828125 +77462 0.12872314453125 +77463 0.196746826171875 +77464 0.11810302734375 +77465 0.179840087890625 +77466 0.102630615234375 +77467 0.155548095703125 +77468 0.100433349609375 +77469 0.151214599609375 +77470 0.10491943359375 +77471 0.156951904296875 +77472 0.08880615234375 +77473 0.13177490234375 +77474 0.0687255859375 +77475 0.100799560546875 +77476 0.060028076171875 +77477 0.087127685546875 +77478 0.038848876953125 +77479 0.05487060546875 +77480 -0.003448486328125 +77481 -0.009002685546875 +77482 -0.0665283203125 +77483 -0.10400390625 +77484 -0.14990234375 +77485 -0.229400634765625 +77486 -0.23388671875 +77487 -0.35552978515625 +77488 -0.29156494140625 +77489 -0.441925048828125 +77490 -0.31317138671875 +77491 -0.473846435546875 +77492 -0.307647705078125 +77493 -0.464813232421875 +77494 -0.277801513671875 +77495 -0.419097900390625 +77496 -0.222015380859375 +77497 -0.334320068359375 +77498 -0.151824951171875 +77499 -0.227935791015625 +77500 -0.0828857421875 +77501 -0.12347412109375 +77502 -0.01959228515625 +77503 -0.02764892578125 +77504 0.050079345703125 +77505 0.077667236328125 +77506 0.13995361328125 +77507 0.2132568359375 +77508 0.256500244140625 +77509 0.38885498046875 +77510 0.38531494140625 +77511 0.582794189453125 +77512 0.485870361328125 +77513 0.734039306640625 +77514 0.529937744140625 +77515 0.800140380859375 +77516 0.51568603515625 +77517 0.7783203125 +77518 0.440826416015625 +77519 0.6651611328125 +77520 0.3046875 +77521 0.45965576171875 +77522 0.132080078125 +77523 0.199188232421875 +77524 -0.033477783203125 +77525 -0.050689697265625 +77526 -0.154144287109375 +77527 -0.23297119140625 +77528 -0.218353271484375 +77529 -0.33013916015625 +77530 -0.24346923828125 +77531 -0.368408203125 +77532 -0.250213623046875 +77533 -0.378936767578125 +77534 -0.248748779296875 +77535 -0.376983642578125 +77536 -0.250457763671875 +77537 -0.37969970703125 +77538 -0.258270263671875 +77539 -0.391510009765625 +77540 -0.254241943359375 +77541 -0.385345458984375 +77542 -0.225555419921875 +77543 -0.3419189453125 +77544 -0.18658447265625 +77545 -0.28289794921875 +77546 -0.166107177734375 +77547 -0.251617431640625 +77548 -0.176055908203125 +77549 -0.266143798828125 +77550 -0.18115234375 +77551 -0.273345947265625 +77552 -0.1439208984375 +77553 -0.216796875 +77554 -0.085418701171875 +77555 -0.128265380859375 +77556 -0.0457763671875 +77557 -0.068145751953125 +77558 -0.029327392578125 +77559 -0.0430908203125 +77560 -0.01708984375 +77561 -0.024444580078125 +77562 0.0128173828125 +77563 0.020721435546875 +77564 0.081695556640625 +77565 0.124481201171875 +77566 0.1702880859375 +77567 0.25787353515625 +77568 0.25140380859375 +77569 0.379119873046875 +77570 0.31939697265625 +77571 0.47991943359375 +77572 0.351531982421875 +77573 0.5281982421875 +77574 0.339080810546875 +77575 0.511138916015625 +77576 0.301239013671875 +77577 0.456207275390625 +77578 0.2686767578125 +77579 0.407470703125 +77580 0.25445556640625 +77581 0.383758544921875 +77582 0.23876953125 +77583 0.35687255859375 +77584 0.21099853515625 +77585 0.31182861328125 +77586 0.172454833984375 +77587 0.250885009765625 +77588 0.116912841796875 +77589 0.1654052734375 +77590 0.030120849609375 +77591 0.035247802734375 +77592 -0.08984375 +77593 -0.142059326171875 +77594 -0.2216796875 +77595 -0.33563232421875 +77596 -0.357940673828125 +77597 -0.5345458984375 +77598 -0.486907958984375 +77599 -0.72186279296875 +77600 -0.566253662109375 +77601 -0.836669921875 +77602 -0.56378173828125 +77603 -0.8326416015625 +77604 -0.4932861328125 +77605 -0.7296142578125 +77606 -0.39288330078125 +77607 -0.582550048828125 +77608 -0.29632568359375 +77609 -0.440093994140625 +77610 -0.21881103515625 +77611 -0.324310302734375 +77612 -0.13665771484375 +77613 -0.20147705078125 +77614 -0.030914306640625 +77615 -0.044647216796875 +77616 0.0692138671875 +77617 0.103973388671875 +77618 0.134674072265625 +77619 0.202392578125 +77620 0.17529296875 +77621 0.264495849609375 +77622 0.22503662109375 +77623 0.338897705078125 +77624 0.296661376953125 +77625 0.443817138671875 +77626 0.366424560546875 +77627 0.545074462890625 +77628 0.416717529296875 +77629 0.6173095703125 +77630 0.44189453125 +77631 0.6524658203125 +77632 0.450836181640625 +77633 0.66339111328125 +77634 0.447662353515625 +77635 0.6561279296875 +77636 0.415618896484375 +77637 0.606781005859375 +77638 0.3447265625 +77639 0.501190185546875 +77640 0.244171142578125 +77641 0.352783203125 +77642 0.124237060546875 +77643 0.176544189453125 +77644 -0.020294189453125 +77645 -0.034820556640625 +77646 -0.173431396484375 +77647 -0.258209228515625 +77648 -0.299713134765625 +77649 -0.44244384765625 +77650 -0.390716552734375 +77651 -0.5753173828125 +77652 -0.443206787109375 +77653 -0.65203857421875 +77654 -0.435638427734375 +77655 -0.641632080078125 +77656 -0.380615234375 +77657 -0.562164306640625 +77658 -0.30902099609375 +77659 -0.458038330078125 +77660 -0.235565185546875 +77661 -0.350555419921875 +77662 -0.1746826171875 +77663 -0.260528564453125 +77664 -0.129150390625 +77665 -0.192108154296875 +77666 -0.096527099609375 +77667 -0.141937255859375 +77668 -0.071197509765625 +77669 -0.1021728515625 +77670 -0.046142578125 +77671 -0.062896728515625 +77672 -0.012725830078125 +77673 -0.011932373046875 +77674 0.037567138671875 +77675 0.062835693359375 +77676 0.095977783203125 +77677 0.148712158203125 +77678 0.159820556640625 +77679 0.241729736328125 +77680 0.234130859375 +77681 0.34912109375 +77682 0.30950927734375 +77683 0.457305908203125 +77684 0.370330810546875 +77685 0.54388427734375 +77686 0.39154052734375 +77687 0.5728759765625 +77688 0.3468017578125 +77689 0.506591796875 +77690 0.240325927734375 +77691 0.351226806640625 +77692 0.099700927734375 +77693 0.146514892578125 +77694 -0.038787841796875 +77695 -0.05523681640625 +77696 -0.14892578125 +77697 -0.21624755859375 +77698 -0.229705810546875 +77699 -0.334930419921875 +77700 -0.275482177734375 +77701 -0.402984619140625 +77702 -0.300872802734375 +77703 -0.4412841796875 +77704 -0.337921142578125 +77705 -0.49578857421875 +77706 -0.382232666015625 +77707 -0.5601806640625 +77708 -0.410400390625 +77709 -0.600738525390625 +77710 -0.3992919921875 +77711 -0.584228515625 +77712 -0.3270263671875 +77713 -0.47930908203125 +77714 -0.18896484375 +77715 -0.27935791015625 +77716 -0.0020751953125 +77717 -0.0089111328125 +77718 0.189666748046875 +77719 0.268798828125 +77720 0.337005615234375 +77721 0.482818603515625 +77722 0.419525146484375 +77723 0.60369873046875 +77724 0.45050048828125 +77725 0.650421142578125 +77726 0.458587646484375 +77727 0.66400146484375 +77728 0.4417724609375 +77729 0.6414794921875 +77730 0.3929443359375 +77731 0.572540283203125 +77732 0.34063720703125 +77733 0.498138427734375 +77734 0.29962158203125 +77735 0.439453125 +77736 0.255279541015625 +77737 0.375518798828125 +77738 0.185455322265625 +77739 0.274505615234375 +77740 0.070892333984375 +77741 0.1087646484375 +77742 -0.072967529296875 +77743 -0.099395751953125 +77744 -0.22406005859375 +77745 -0.3182373046875 +77746 -0.38330078125 +77747 -0.5489501953125 +77748 -0.538421630859375 +77749 -0.7738037109375 +77750 -0.65264892578125 +77751 -0.86383056640625 +77752 -0.702911376953125 +77753 -0.870391845703125 +77754 -0.70159912109375 +77755 -0.86895751953125 +77756 -0.65789794921875 +77757 -0.861053466796875 +77758 -0.559783935546875 +77759 -0.765869140625 +77760 -0.399444580078125 +77761 -0.5301513671875 +77762 -0.18182373046875 +77763 -0.214691162109375 +77764 0.063079833984375 +77765 0.137359619140625 +77766 0.299591064453125 +77767 0.474822998046875 +77768 0.503021240234375 +77769 0.76239013671875 +77770 0.654632568359375 +77771 0.867462158203125 +77772 0.7547607421875 +77773 0.870361328125 +77774 0.79541015625 +77775 0.86480712890625 +77776 0.7803955078125 +77777 0.831817626953125 +77778 0.726715087890625 +77779 0.677581787109375 +77780 0.638458251953125 +77781 0.495880126953125 +77782 0.528594970703125 +77783 0.30767822265625 +77784 0.398681640625 +77785 0.116180419921875 +77786 0.2266845703125 +77787 -0.110748291015625 +77788 0.007781982421875 +77789 -0.381805419921875 +77790 -0.228179931640625 +77791 -0.6572265625 +77792 -0.43951416015625 +77793 -0.857421875 +77794 -0.59637451171875 +77795 -0.870391845703125 +77796 -0.693817138671875 +77797 -0.870391845703125 +77798 -0.750579833984375 +77799 -0.86444091796875 +77800 -0.79156494140625 +77801 -0.85723876953125 +77802 -0.804046630859375 +77803 -0.790008544921875 +77804 -0.75030517578125 +77805 -0.62847900390625 +77806 -0.628173828125 +77807 -0.3956298828125 +77808 -0.460540771484375 +77809 -0.126708984375 +77810 -0.26654052734375 +77811 0.150115966796875 +77812 -0.0543212890625 +77813 0.424041748046875 +77814 0.15728759765625 +77815 0.670623779296875 +77816 0.34130859375 +77817 0.854522705078125 +77818 0.48541259765625 +77819 0.866485595703125 +77820 0.578887939453125 +77821 0.86920166015625 +77822 0.634368896484375 +77823 0.8653564453125 +77824 0.66094970703125 +77825 0.857147216796875 +77826 0.656890869140625 +77827 0.766845703125 +77828 0.6260986328125 +77829 0.628509521484375 +77830 0.563629150390625 +77831 0.462127685546875 +77832 0.4881591796875 +77833 0.297210693359375 +77834 0.408477783203125 +77835 0.14862060546875 +77836 0.307708740234375 +77837 -0.00537109375 +77838 0.19097900390625 +77839 -0.15753173828125 +77840 0.055328369140625 +77841 -0.31304931640625 +77842 -0.109771728515625 +77843 -0.48876953125 +77844 -0.2705078125 +77845 -0.6416015625 +77846 -0.409149169921875 +77847 -0.751373291015625 +77848 -0.542724609375 +77849 -0.84619140625 +77850 -0.66064453125 +77851 -0.861297607421875 +77852 -0.738861083984375 +77853 -0.863250732421875 +77854 -0.754425048828125 +77855 -0.856597900390625 +77856 -0.71612548828125 +77857 -0.7498779296875 +77858 -0.665924072265625 +77859 -0.624542236328125 +77860 -0.587646484375 +77861 -0.47808837890625 +77862 -0.438507080078125 +77863 -0.253387451171875 +77864 -0.251495361328125 +77865 0.003692626953125 +77866 -0.07611083984375 +77867 0.2257080078125 +77868 0.09698486328125 +77869 0.427154541015625 +77870 0.2916259765625 +77871 0.643218994140625 +77872 0.501007080078125 +77873 0.855926513671875 +77874 0.68310546875 +77875 0.870361328125 +77876 0.8018798828125 +77877 0.870361328125 +77878 0.855377197265625 +77879 0.862762451171875 +77880 0.855438232421875 +77881 0.79669189453125 +77882 0.7967529296875 +77883 0.595794677734375 +77884 0.684356689453125 +77885 0.362152099609375 +77886 0.54632568359375 +77887 0.1270751953125 +77888 0.397918701171875 +77889 -0.086944580078125 +77890 0.240509033203125 +77891 -0.2784423828125 +77892 0.048614501953125 +77893 -0.484832763671875 +77894 -0.191925048828125 +77895 -0.729583740234375 +77896 -0.44439697265625 +77897 -0.86688232421875 +77898 -0.662811279296875 +77899 -0.870391845703125 +77900 -0.843658447265625 +77901 -0.86859130859375 +77902 -0.868804931640625 +77903 -0.86279296875 +77904 -0.870391845703125 +77905 -0.817962646484375 +77906 -0.86181640625 +77907 -0.6116943359375 +77908 -0.7474365234375 +77909 -0.3128662109375 +77910 -0.504974365234375 +77911 0.039398193359375 +77912 -0.210296630859375 +77913 0.422821044921875 +77914 0.111358642578125 +77915 0.805145263671875 +77916 0.410186767578125 +77917 0.870361328125 +77918 0.64520263671875 +77919 0.870361328125 +77920 0.809051513671875 +77921 0.860015869140625 +77922 0.859222412109375 +77923 0.727935791015625 +77924 0.860504150390625 +77925 0.48114013671875 +77926 0.855621337890625 +77927 0.2059326171875 +77928 0.78277587890625 +77929 -0.06103515625 +77930 0.673187255859375 +77931 -0.29913330078125 +77932 0.528472900390625 +77933 -0.516204833984375 +77934 0.3399658203125 +77935 -0.7252197265625 +77936 0.1279296875 +77937 -0.85980224609375 +77938 -0.080841064453125 +77939 -0.870391845703125 +77940 -0.26361083984375 +77941 -0.870391845703125 +77942 -0.384246826171875 +77943 -0.858062744140625 +77944 -0.439605712890625 +77945 -0.673004150390625 +77946 -0.4683837890625 +77947 -0.42694091796875 +77948 -0.503875732421875 +77949 -0.2100830078125 +77950 -0.545989990234375 +77951 -0.0362548828125 +77952 -0.575408935546875 +77953 0.10943603515625 +77954 -0.579742431640625 +77955 0.23516845703125 +77956 -0.53106689453125 +77957 0.373687744140625 +77958 -0.43304443359375 +77959 0.517791748046875 +77960 -0.33367919921875 +77961 0.602783203125 +77962 -0.23114013671875 +77963 0.635711669921875 +77964 -0.102813720703125 +77965 0.655181884765625 +77966 0.04278564453125 +77967 0.65948486328125 +77968 0.199005126953125 +77969 0.651275634765625 +77970 0.347625732421875 +77971 0.61846923828125 +77972 0.46185302734375 +77973 0.53753662109375 +77974 0.529083251953125 +77975 0.404144287109375 +77976 0.543182373046875 +77977 0.22186279296875 +77978 0.50634765625 +77979 0.003997802734375 +77980 0.433349609375 +77981 -0.22100830078125 +77982 0.34100341796875 +77983 -0.42449951171875 +77984 0.246673583984375 +77985 -0.579833984375 +77986 0.1832275390625 +77987 -0.641876220703125 +77988 0.14752197265625 +77989 -0.6177978515625 +77990 0.093994140625 +77991 -0.575531005859375 +77992 0.01995849609375 +77993 -0.526336669921875 +77994 -0.0360107421875 +77995 -0.42645263671875 +77996 -0.053436279296875 +77997 -0.2581787109375 +77998 -0.0587158203125 +77999 -0.068695068359375 +78000 -0.08013916015625 +78001 0.09222412109375 +78002 -0.10479736328125 +78003 0.232147216796875 +78004 -0.126251220703125 +78005 0.3509521484375 +78006 -0.167205810546875 +78007 0.410064697265625 +78008 -0.2503662109375 +78009 0.372955322265625 +78010 -0.3619384765625 +78011 0.2554931640625 +78012 -0.46539306640625 +78013 0.10711669921875 +78014 -0.547821044921875 +78015 -0.052886962890625 +78016 -0.58404541015625 +78017 -0.186279296875 +78018 -0.534423828125 +78019 -0.23291015625 +78020 -0.416290283203125 +78021 -0.209442138671875 +78022 -0.278076171875 +78023 -0.174163818359375 +78024 -0.126007080078125 +78025 -0.126739501953125 +78026 0.04718017578125 +78027 -0.048126220703125 +78028 0.22137451171875 +78029 0.0426025390625 +78030 0.36328125 +78031 0.10748291015625 +78032 0.464080810546875 +78033 0.1409912109375 +78034 0.559417724609375 +78035 0.19708251953125 +78036 0.645416259765625 +78037 0.273651123046875 +78038 0.68255615234375 +78039 0.31768798828125 +78040 0.679931640625 +78041 0.341094970703125 +78042 0.65692138671875 +78043 0.368011474609375 +78044 0.59759521484375 +78045 0.37249755859375 +78046 0.466766357421875 +78047 0.30072021484375 +78048 0.268463134765625 +78049 0.1517333984375 +78050 0.051361083984375 +78051 -0.01470947265625 +78052 -0.171600341796875 +78053 -0.1883544921875 +78054 -0.397705078125 +78055 -0.372711181640625 +78056 -0.582916259765625 +78057 -0.51397705078125 +78058 -0.693603515625 +78059 -0.57177734375 +78060 -0.72161865234375 +78061 -0.53948974609375 +78062 -0.677764892578125 +78063 -0.43511962890625 +78064 -0.588165283203125 +78065 -0.2962646484375 +78066 -0.480621337890625 +78067 -0.161102294921875 +78068 -0.366363525390625 +78069 -0.0435791015625 +78070 -0.244537353515625 +78071 0.060394287109375 +78072 -0.12847900390625 +78073 0.13665771484375 +78074 -0.0328369140625 +78075 0.170135498046875 +78076 0.041595458984375 +78077 0.16552734375 +78078 0.115447998046875 +78079 0.15728759765625 +78080 0.18804931640625 +78081 0.150787353515625 +78082 0.23773193359375 +78083 0.12200927734375 +78084 0.26776123046875 +78085 0.080108642578125 +78086 0.294586181640625 +78087 0.05126953125 +78088 0.336395263671875 +78089 0.062896728515625 +78090 0.375030517578125 +78091 0.09271240234375 +78092 0.374298095703125 +78093 0.092987060546875 +78094 0.3458251953125 +78095 0.07855224609375 +78096 0.302215576171875 +78097 0.06427001953125 +78098 0.23419189453125 +78099 0.0347900390625 +78100 0.14324951171875 +78101 -0.01171875 +78102 0.04718017578125 +78103 -0.056060791015625 +78104 -0.018341064453125 +78105 -0.055511474609375 +78106 -0.049896240234375 +78107 -0.010467529296875 +78108 -0.08441162109375 +78109 0.02508544921875 +78110 -0.13775634765625 +78111 0.025665283203125 +78112 -0.187652587890625 +78113 0.017333984375 +78114 -0.23065185546875 +78115 0.00189208984375 +78116 -0.27374267578125 +78117 -0.03173828125 +78118 -0.30731201171875 +78119 -0.071502685546875 +78120 -0.345062255859375 +78121 -0.13543701171875 +78122 -0.385284423828125 +78123 -0.219970703125 +78124 -0.411163330078125 +78125 -0.300506591796875 +78126 -0.42431640625 +78127 -0.376312255859375 +78128 -0.4039306640625 +78129 -0.416107177734375 +78130 -0.316375732421875 +78131 -0.371124267578125 +78132 -0.165374755859375 +78133 -0.242279052734375 +78134 0.01593017578125 +78135 -0.069732666015625 +78136 0.209136962890625 +78137 0.125640869140625 +78138 0.38848876953125 +78139 0.31268310546875 +78140 0.5247802734375 +78141 0.45501708984375 +78142 0.6182861328125 +78143 0.554779052734375 +78144 0.667327880859375 +78145 0.61065673828125 +78146 0.663055419921875 +78147 0.610931396484375 +78148 0.587982177734375 +78149 0.531463623046875 +78150 0.45526123046875 +78151 0.3883056640625 +78152 0.30645751953125 +78153 0.23468017578125 +78154 0.16217041015625 +78155 0.095245361328125 +78156 0.04425048828125 +78157 -0.00396728515625 +78158 -0.03399658203125 +78159 -0.04852294921875 +78160 -0.082611083984375 +78161 -0.055145263671875 +78162 -0.138275146484375 +78163 -0.0758056640625 +78164 -0.220001220703125 +78165 -0.138702392578125 +78166 -0.30010986328125 +78167 -0.209197998046875 +78168 -0.378631591796875 +78169 -0.289031982421875 +78170 -0.455291748046875 +78171 -0.37884521484375 +78172 -0.513092041015625 +78173 -0.456329345703125 +78174 -0.54852294921875 +78175 -0.51641845703125 +78176 -0.532501220703125 +78177 -0.519287109375 +78178 -0.46124267578125 +78179 -0.458251953125 +78180 -0.375 +78181 -0.384796142578125 +78182 -0.294189453125 +78183 -0.323699951171875 +78184 -0.216583251953125 +78185 -0.269287109375 +78186 -0.124481201171875 +78187 -0.1951904296875 +78188 -0.018768310546875 +78189 -0.100006103515625 +78190 0.078582763671875 +78191 -0.01055908203125 +78192 0.188690185546875 +78193 0.1033935546875 +78194 0.315826416015625 +78195 0.24908447265625 +78196 0.419219970703125 +78197 0.373199462890625 +78198 0.48529052734375 +78199 0.45806884765625 +78200 0.51995849609375 +78201 0.511474609375 +78202 0.547760009765625 +78203 0.565399169921875 +78204 0.563232421875 +78205 0.61138916015625 +78206 0.522796630859375 +78207 0.5897216796875 +78208 0.420562744140625 +78209 0.4906005859375 +78210 0.27130126953125 +78211 0.33148193359375 +78212 0.10321044921875 +78213 0.147796630859375 +78214 -0.05072021484375 +78215 -0.01873779296875 +78216 -0.1680908203125 +78217 -0.140289306640625 +78218 -0.2288818359375 +78219 -0.191986083984375 +78220 -0.2398681640625 +78221 -0.184295654296875 +78222 -0.2337646484375 +78223 -0.161834716796875 +78224 -0.241607666015625 +78225 -0.166595458984375 +78226 -0.2598876953125 +78227 -0.19390869140625 +78228 -0.274383544921875 +78229 -0.22442626953125 +78230 -0.301910400390625 +78231 -0.279754638671875 +78232 -0.327728271484375 +78233 -0.3389892578125 +78234 -0.31719970703125 +78235 -0.3543701171875 +78236 -0.288330078125 +78237 -0.348175048828125 +78238 -0.24664306640625 +78239 -0.32598876953125 +78240 -0.171356201171875 +78241 -0.2581787109375 +78242 -0.06005859375 +78243 -0.139801025390625 +78244 0.0751953125 +78245 0.014617919921875 +78246 0.1878662109375 +78247 0.144378662109375 +78248 0.255950927734375 +78249 0.221038818359375 +78250 0.298553466796875 +78251 0.27069091796875 +78252 0.316070556640625 +78253 0.294036865234375 +78254 0.324188232421875 +78255 0.311767578125 +78256 0.334808349609375 +78257 0.339141845703125 +78258 0.3367919921875 +78259 0.360260009765625 +78260 0.320037841796875 +78261 0.360504150390625 +78262 0.26153564453125 +78263 0.308380126953125 +78264 0.145477294921875 +78265 0.18170166015625 +78266 -0.008544921875 +78267 0.0047607421875 +78268 -0.163909912109375 +78269 -0.17559814453125 +78270 -0.28546142578125 +78271 -0.3143310546875 +78272 -0.3392333984375 +78273 -0.36785888671875 +78274 -0.3446044921875 +78275 -0.36248779296875 +78276 -0.33563232421875 +78277 -0.343536376953125 +78278 -0.305206298828125 +78279 -0.3018798828125 +78280 -0.24871826171875 +78281 -0.231414794921875 +78282 -0.155426025390625 +78283 -0.117645263671875 +78284 -0.0504150390625 +78285 0.007049560546875 +78286 0.024078369140625 +78287 0.087982177734375 +78288 0.078155517578125 +78289 0.13946533203125 +78290 0.12066650390625 +78291 0.17425537109375 +78292 0.14752197265625 +78293 0.188201904296875 +78294 0.150146484375 +78295 0.171234130859375 +78296 0.1240234375 +78297 0.118438720703125 +78298 0.089141845703125 +78299 0.05706787109375 +78300 0.0465087890625 +78301 -0.010711669921875 +78302 -0.00921630859375 +78303 -0.0914306640625 +78304 -0.0609130859375 +78305 -0.162322998046875 +78306 -0.086669921875 +78307 -0.194549560546875 +78308 -0.056854248046875 +78309 -0.1492919921875 +78310 0.032562255859375 +78311 -0.02166748046875 +78312 0.13330078125 +78313 0.124053955078125 +78314 0.1876220703125 +78315 0.211151123046875 +78316 0.1968994140625 +78317 0.240447998046875 +78318 0.184814453125 +78319 0.242218017578125 +78320 0.159210205078125 +78321 0.2257080078125 +78322 0.123382568359375 +78323 0.194366455078125 +78324 0.0531005859375 +78325 0.115509033203125 +78326 -0.033050537109375 +78327 0.0128173828125 +78328 -0.089202880859375 +78329 -0.053802490234375 +78330 -0.135101318359375 +78331 -0.110626220703125 +78332 -0.2025146484375 +78333 -0.199493408203125 +78334 -0.271728515625 +78335 -0.29437255859375 +78336 -0.294677734375 +78337 -0.33221435546875 +78338 -0.2457275390625 +78339 -0.27972412109375 +78340 -0.163177490234375 +78341 -0.185333251953125 +78342 -0.10986328125 +78343 -0.128204345703125 +78344 -0.091827392578125 +78345 -0.115692138671875 +78346 -0.084564208984375 +78347 -0.116455078125 +78348 -0.068939208984375 +78349 -0.105926513671875 +78350 -0.021392822265625 +78351 -0.053955078125 +78352 0.065185546875 +78353 0.048797607421875 +78354 0.1549072265625 +78355 0.157318115234375 +78356 0.20037841796875 +78357 0.212005615234375 +78358 0.205963134765625 +78359 0.218475341796875 +78360 0.2196044921875 +78361 0.23724365234375 +78362 0.270721435546875 +78363 0.30535888671875 +78364 0.32659912109375 +78365 0.38128662109375 +78366 0.3394775390625 +78367 0.404449462890625 +78368 0.3251953125 +78369 0.3944091796875 +78370 0.313720703125 +78371 0.3885498046875 +78372 0.286285400390625 +78373 0.362640380859375 +78374 0.2091064453125 +78375 0.27362060546875 +78376 0.079071044921875 +78377 0.11712646484375 +78378 -0.062347412109375 +78379 -0.054901123046875 +78380 -0.17401123046875 +78381 -0.19085693359375 +78382 -0.251739501953125 +78383 -0.28570556640625 +78384 -0.295318603515625 +78385 -0.339263916015625 +78386 -0.3253173828125 +78387 -0.3775634765625 +78388 -0.377532958984375 +78389 -0.445709228515625 +78390 -0.44525146484375 +78391 -0.535064697265625 +78392 -0.51556396484375 +78393 -0.629058837890625 +78394 -0.56488037109375 +78395 -0.697601318359375 +78396 -0.564361572265625 +78397 -0.70391845703125 +78398 -0.50994873046875 +78399 -0.6424560546875 +78400 -0.384552001953125 +78401 -0.491241455078125 +78402 -0.20068359375 +78403 -0.265716552734375 +78404 -0.004425048828125 +78405 -0.023712158203125 +78406 0.17779541015625 +78407 0.201751708984375 +78408 0.318206787109375 +78409 0.375823974609375 +78410 0.406097412109375 +78411 0.485076904296875 +78412 0.472564697265625 +78413 0.56884765625 +78414 0.523712158203125 +78415 0.634765625 +78416 0.5238037109375 +78417 0.63763427734375 +78418 0.46392822265625 +78419 0.5660400390625 +78420 0.385528564453125 +78421 0.4720458984375 +78422 0.3294677734375 +78423 0.40692138671875 +78424 0.301666259765625 +78425 0.3778076171875 +78426 0.2962646484375 +78427 0.376953125 +78428 0.287872314453125 +78429 0.371978759765625 +78430 0.237335205078125 +78431 0.313140869140625 +78432 0.132110595703125 +78433 0.184417724609375 +78434 -0.007476806640625 +78435 0.011199951171875 +78436 -0.153228759765625 +78437 -0.171051025390625 +78438 -0.285369873046875 +78439 -0.33740234375 +78440 -0.391326904296875 +78441 -0.47198486328125 +78442 -0.459808349609375 +78443 -0.560394287109375 +78444 -0.473419189453125 +78445 -0.58056640625 +78446 -0.4442138671875 +78447 -0.54754638671875 +78448 -0.409820556640625 +78449 -0.508575439453125 +78450 -0.36712646484375 +78451 -0.459503173828125 +78452 -0.311676025390625 +78453 -0.394378662109375 +78454 -0.27484130859375 +78455 -0.35260009765625 +78456 -0.239044189453125 +78457 -0.31170654296875 +78458 -0.1456298828125 +78459 -0.197418212890625 +78460 0.00665283203125 +78461 -0.007965087890625 +78462 0.17877197265625 +78463 0.207489013671875 +78464 0.33917236328125 +78465 0.409210205078125 +78466 0.46795654296875 +78467 0.57208251953125 +78468 0.541290283203125 +78469 0.66595458984375 +78470 0.533843994140625 +78471 0.65875244140625 +78472 0.45916748046875 +78473 0.56744384765625 +78474 0.34857177734375 +78475 0.431396484375 +78476 0.236968994140625 +78477 0.29443359375 +78478 0.145050048828125 +78479 0.182464599609375 +78480 0.04779052734375 +78481 0.06365966796875 +78482 -0.065704345703125 +78483 -0.075958251953125 +78484 -0.1580810546875 +78485 -0.189422607421875 +78486 -0.225433349609375 +78487 -0.271942138671875 +78488 -0.28271484375 +78489 -0.342529296875 +78490 -0.300567626953125 +78491 -0.364166259765625 +78492 -0.2713623046875 +78493 -0.327239990234375 +78494 -0.230926513671875 +78495 -0.2769775390625 +78496 -0.21124267578125 +78497 -0.253692626953125 +78498 -0.201507568359375 +78499 -0.24365234375 +78500 -0.1634521484375 +78501 -0.1983642578125 +78502 -0.095916748046875 +78503 -0.116241455078125 +78504 -0.030364990234375 +78505 -0.036834716796875 +78506 0.029083251953125 +78507 0.034881591796875 +78508 0.076202392578125 +78509 0.09124755859375 +78510 0.092376708984375 +78511 0.10888671875 +78512 0.10736083984375 +78513 0.125518798828125 +78514 0.134185791015625 +78515 0.15771484375 +78516 0.1512451171875 +78517 0.17828369140625 +78518 0.145721435546875 +78519 0.17108154296875 +78520 0.11279296875 +78521 0.129974365234375 +78522 0.07421875 +78523 0.082427978515625 +78524 0.029510498046875 +78525 0.027679443359375 +78526 -0.046112060546875 +78527 -0.065643310546875 +78528 -0.122283935546875 +78529 -0.15936279296875 +78530 -0.166900634765625 +78531 -0.21307373046875 +78532 -0.18609619140625 +78533 -0.234649658203125 +78534 -0.16082763671875 +78535 -0.2001953125 +78536 -0.0985107421875 +78537 -0.119171142578125 +78538 -0.02532958984375 +78539 -0.024749755859375 +78540 0.06097412109375 +78541 0.085784912109375 +78542 0.13330078125 +78543 0.178131103515625 +78544 0.16259765625 +78545 0.215576171875 +78546 0.159393310546875 +78547 0.211456298828125 +78548 0.131195068359375 +78549 0.17523193359375 +78550 0.095306396484375 +78551 0.128753662109375 +78552 0.075347900390625 +78553 0.1019287109375 +78554 0.0550537109375 +78555 0.0743408203125 +78556 0.03216552734375 +78557 0.04327392578125 +78558 0.0299072265625 +78559 0.038177490234375 +78560 0.06182861328125 +78561 0.076263427734375 +78562 0.114776611328125 +78563 0.14105224609375 +78564 0.152130126953125 +78565 0.186431884765625 +78566 0.1551513671875 +78567 0.188812255859375 +78568 0.11651611328125 +78569 0.1390380859375 +78570 0.0399169921875 +78571 0.041778564453125 +78572 -0.0560302734375 +78573 -0.079437255859375 +78574 -0.167205810546875 +78575 -0.219390869140625 +78576 -0.285430908203125 +78577 -0.367828369140625 +78578 -0.38702392578125 +78579 -0.494873046875 +78580 -0.43682861328125 +78581 -0.556243896484375 +78582 -0.400543212890625 +78583 -0.508697509765625 +78584 -0.296600341796875 +78585 -0.3756103515625 +78586 -0.1739501953125 +78587 -0.218902587890625 +78588 -0.05242919921875 +78589 -0.063751220703125 +78590 0.0693359375 +78591 0.091552734375 +78592 0.182769775390625 +78593 0.23602294921875 +78594 0.26678466796875 +78595 0.342987060546875 +78596 0.3074951171875 +78597 0.39520263671875 +78598 0.302001953125 +78599 0.389373779296875 +78600 0.249053955078125 +78601 0.324249267578125 +78602 0.168365478515625 +78603 0.224090576171875 +78604 0.0888671875 +78605 0.124267578125 +78606 0.0203857421875 +78607 0.037078857421875 +78608 -0.014739990234375 +78609 -0.010101318359375 +78610 -0.0185546875 +78611 -0.019439697265625 +78612 -0.01751708984375 +78613 -0.022796630859375 +78614 0.00347900390625 +78615 -0.001556396484375 +78616 0.054168701171875 +78617 0.056304931640625 +78618 0.09814453125 +78619 0.106719970703125 +78620 0.091796875 +78621 0.096893310546875 +78622 0.04815673828125 +78623 0.042694091796875 +78624 -0.001617431640625 +78625 -0.018035888671875 +78626 -0.04974365234375 +78627 -0.07586669921875 +78628 -0.0867919921875 +78629 -0.11944580078125 +78630 -0.12176513671875 +78631 -0.15972900390625 +78632 -0.15936279296875 +78633 -0.202606201171875 +78634 -0.199859619140625 +78635 -0.24859619140625 +78636 -0.249237060546875 +78637 -0.30517578125 +78638 -0.2989501953125 +78639 -0.36212158203125 +78640 -0.3258056640625 +78641 -0.39141845703125 +78642 -0.2984619140625 +78643 -0.35528564453125 +78644 -0.213714599609375 +78645 -0.249969482421875 +78646 -0.0858154296875 +78647 -0.092864990234375 +78648 0.063079833984375 +78649 0.08905029296875 +78650 0.18310546875 +78651 0.2352294921875 +78652 0.25213623046875 +78653 0.318817138671875 +78654 0.28564453125 +78655 0.358642578125 +78656 0.27789306640625 +78657 0.347747802734375 +78658 0.2283935546875 +78659 0.28564453125 +78660 0.178924560546875 +78661 0.223175048828125 +78662 0.15936279296875 +78663 0.196746826171875 +78664 0.147735595703125 +78665 0.179840087890625 +78666 0.1300048828125 +78667 0.155548095703125 +78668 0.1285400390625 +78669 0.151214599609375 +78670 0.135101318359375 +78671 0.156951904296875 +78672 0.115814208984375 +78673 0.13177490234375 +78674 0.09130859375 +78675 0.100799560546875 +78676 0.08056640625 +78677 0.087127685546875 +78678 0.05401611328125 +78679 0.05487060546875 +78680 0.00091552734375 +78681 -0.009002685546875 +78682 -0.0782470703125 +78683 -0.10400390625 +78684 -0.182830810546875 +78685 -0.229400634765625 +78686 -0.288330078125 +78687 -0.35552978515625 +78688 -0.36126708984375 +78689 -0.441925048828125 +78690 -0.389434814453125 +78691 -0.473846435546875 +78692 -0.38385009765625 +78693 -0.464813232421875 +78694 -0.347900390625 +78695 -0.419097900390625 +78696 -0.279571533203125 +78697 -0.334320068359375 +78698 -0.193145751953125 +78699 -0.227935791015625 +78700 -0.10797119140625 +78701 -0.12347412109375 +78702 -0.029510498046875 +78703 -0.02764892578125 +78704 0.05718994140625 +78705 0.077667236328125 +78706 0.169189453125 +78707 0.2132568359375 +78708 0.314483642578125 +78709 0.38885498046875 +78710 0.475189208984375 +78711 0.582794189453125 +78712 0.6009521484375 +78713 0.734039306640625 +78714 0.65673828125 +78715 0.800140380859375 +78716 0.640167236328125 +78717 0.7783203125 +78718 0.548370361328125 +78719 0.6651611328125 +78720 0.38043212890625 +78721 0.45965576171875 +78722 0.167083740234375 +78723 0.199188232421875 +78724 -0.0377197265625 +78725 -0.050689697265625 +78726 -0.18707275390625 +78727 -0.23297119140625 +78728 -0.2666015625 +78729 -0.33013916015625 +78730 -0.297882080078125 +78731 -0.368408203125 +78732 -0.306610107421875 +78733 -0.378936767578125 +78734 -0.30535888671875 +78735 -0.376983642578125 +78736 -0.3082275390625 +78737 -0.37969970703125 +78738 -0.318817138671875 +78739 -0.391510009765625 +78740 -0.314788818359375 +78741 -0.385345458984375 +78742 -0.280181884765625 +78743 -0.3419189453125 +78744 -0.2327880859375 +78745 -0.28289794921875 +78746 -0.208221435546875 +78747 -0.251617431640625 +78748 -0.2213134765625 +78749 -0.266143798828125 +78750 -0.228240966796875 +78751 -0.273345947265625 +78752 -0.182464599609375 +78753 -0.216796875 +78754 -0.110076904296875 +78755 -0.128265380859375 +78756 -0.06085205078125 +78757 -0.068145751953125 +78758 -0.04022216796875 +78759 -0.0430908203125 +78760 -0.02459716796875 +78761 -0.024444580078125 +78762 0.01312255859375 +78763 0.020721435546875 +78764 0.099334716796875 +78765 0.124481201171875 +78766 0.210113525390625 +78767 0.25787353515625 +78768 0.31097412109375 +78769 0.379119873046875 +78770 0.395050048828125 +78771 0.47991943359375 +78772 0.43585205078125 +78773 0.5281982421875 +78774 0.422760009765625 +78775 0.511138916015625 +78776 0.37835693359375 +78777 0.456207275390625 +78778 0.338897705078125 +78779 0.407470703125 +78780 0.319854736328125 +78781 0.383758544921875 +78782 0.2979736328125 +78783 0.35687255859375 +78784 0.26092529296875 +78785 0.31182861328125 +78786 0.210540771484375 +78787 0.250885009765625 +78788 0.139739990234375 +78789 0.1654052734375 +78790 0.031951904296875 +78791 0.035247802734375 +78792 -0.114837646484375 +78793 -0.142059326171875 +78794 -0.275115966796875 +78795 -0.33563232421875 +78796 -0.4398193359375 +78797 -0.5345458984375 +78798 -0.594940185546875 +78799 -0.72186279296875 +78800 -0.690277099609375 +78801 -0.836669921875 +78802 -0.687652587890625 +78803 -0.8326416015625 +78804 -0.603363037109375 +78805 -0.7296142578125 +78806 -0.482635498046875 +78807 -0.582550048828125 +78808 -0.36553955078125 +78809 -0.440093994140625 +78810 -0.270263671875 +78811 -0.324310302734375 +78812 -0.16900634765625 +78813 -0.20147705078125 +78814 -0.03955078125 +78815 -0.044647216796875 +78816 0.083282470703125 +78817 0.103973388671875 +78818 0.164886474609375 +78819 0.202392578125 +78820 0.216644287109375 +78821 0.264495849609375 +78822 0.278594970703125 +78823 0.338897705078125 +78824 0.365692138671875 +78825 0.443817138671875 +78826 0.44976806640625 +78827 0.545074462890625 +78828 0.509857177734375 +78829 0.6173095703125 +78830 0.539337158203125 +78831 0.6524658203125 +78832 0.548736572265625 +78833 0.66339111328125 +78834 0.54302978515625 +78835 0.6561279296875 +78836 0.50250244140625 +78837 0.606781005859375 +78838 0.41546630859375 +78839 0.501190185546875 +78840 0.292999267578125 +78841 0.352783203125 +78842 0.1474609375 +78843 0.176544189453125 +78844 -0.027130126953125 +78845 -0.034820556640625 +78846 -0.211700439453125 +78847 -0.258209228515625 +78848 -0.3638916015625 +78849 -0.44244384765625 +78850 -0.47369384765625 +78851 -0.5753173828125 +78852 -0.53704833984375 +78853 -0.65203857421875 +78854 -0.527374267578125 +78855 -0.641632080078125 +78856 -0.459991455078125 +78857 -0.562164306640625 +78858 -0.37274169921875 +78859 -0.458038330078125 +78860 -0.28363037109375 +78861 -0.350555419921875 +78862 -0.21026611328125 +78863 -0.260528564453125 +78864 -0.15594482421875 +78865 -0.192108154296875 +78866 -0.117523193359375 +78867 -0.141937255859375 +78868 -0.088043212890625 +78869 -0.1021728515625 +78870 -0.058746337890625 +78871 -0.062896728515625 +78872 -0.018951416015625 +78873 -0.011932373046875 +78874 0.041839599609375 +78875 0.062835693359375 +78876 0.1129150390625 +78877 0.148712158203125 +78878 0.19097900390625 +78879 0.241729736328125 +78880 0.28228759765625 +78881 0.34912109375 +78882 0.375213623046875 +78883 0.457305908203125 +78884 0.450531005859375 +78885 0.54388427734375 +78886 0.47735595703125 +78887 0.5728759765625 +78888 0.42327880859375 +78889 0.506591796875 +78890 0.29345703125 +78891 0.351226806640625 +78892 0.121673583984375 +78893 0.146514892578125 +78894 -0.047454833984375 +78895 -0.05523681640625 +78896 -0.181793212890625 +78897 -0.21624755859375 +78898 -0.280181884765625 +78899 -0.334930419921875 +78900 -0.335662841796875 +78901 -0.402984619140625 +78902 -0.366241455078125 +78903 -0.4412841796875 +78904 -0.411407470703125 +78905 -0.49578857421875 +78906 -0.465789794921875 +78907 -0.5601806640625 +78908 -0.50054931640625 +78909 -0.600738525390625 +78910 -0.487213134765625 +78911 -0.584228515625 +78912 -0.398834228515625 +78913 -0.47930908203125 +78914 -0.229705810546875 +78915 -0.27935791015625 +78916 -0.00067138671875 +78917 -0.0089111328125 +78918 0.2342529296875 +78919 0.268798828125 +78920 0.41455078125 +78921 0.482818603515625 +78922 0.515167236328125 +78923 0.60369873046875 +78924 0.552459716796875 +78925 0.650421142578125 +78926 0.561676025390625 +78927 0.66400146484375 +78928 0.5404052734375 +78929 0.6414794921875 +78930 0.479949951171875 +78931 0.572540283203125 +78932 0.4154052734375 +78933 0.498138427734375 +78934 0.36492919921875 +78935 0.439453125 +78936 0.310577392578125 +78937 0.375518798828125 +78938 0.225067138671875 +78939 0.274505615234375 +78940 0.08465576171875 +78941 0.1087646484375 +78942 -0.0916748046875 +78943 -0.099395751953125 +78944 -0.27679443359375 +78945 -0.3182373046875 +78946 -0.471923828125 +78947 -0.5489501953125 +78948 -0.6619873046875 +78949 -0.7738037109375 +78950 -0.801788330078125 +78951 -0.86383056640625 +78952 -0.855438232421875 +78953 -0.870391845703125 +78954 -0.855194091796875 +78955 -0.86895751953125 +78956 -0.80670166015625 +78957 -0.861053466796875 +78958 -0.685821533203125 +78959 -0.765869140625 +78960 -0.48858642578125 +78961 -0.5301513671875 +78962 -0.2210693359375 +78963 -0.214691162109375 +78964 0.07989501953125 +78965 0.137359619140625 +78966 0.37042236328125 +78967 0.474822998046875 +78968 0.620147705078125 +78969 0.76239013671875 +78970 0.806060791015625 +78971 0.867462158203125 +78972 0.862579345703125 +78973 0.870361328125 +78974 0.867950439453125 +78975 0.86480712890625 +78976 0.865875244140625 +78977 0.831817626953125 +78978 0.858642578125 +78979 0.677581787109375 +78980 0.783599853515625 +78981 0.495880126953125 +78982 0.648193359375 +78983 0.30767822265625 +78984 0.488250732421875 +78985 0.116180419921875 +78986 0.27667236328125 +78987 -0.110748291015625 +78988 0.007568359375 +78989 -0.381805419921875 +78990 -0.28240966796875 +78991 -0.6572265625 +78992 -0.54205322265625 +78993 -0.857421875 +78994 -0.734649658203125 +78995 -0.870391845703125 +78996 -0.854095458984375 +78997 -0.870391845703125 +78998 -0.862030029296875 +78999 -0.86444091796875 +79000 -0.86749267578125 +79001 -0.85723876953125 +79002 -0.869140625 +79003 -0.790008544921875 +79004 -0.86187744140625 +79005 -0.62847900390625 +79006 -0.771575927734375 +79007 -0.3956298828125 +79008 -0.565185546875 +79009 -0.126708984375 +79010 -0.326446533203125 +79011 0.150115966796875 +79012 -0.065399169921875 +79013 0.424041748046875 +79014 0.19482421875 +79015 0.670623779296875 +79016 0.421051025390625 +79017 0.854522705078125 +79018 0.59814453125 +79019 0.866485595703125 +79020 0.712890625 +79021 0.86920166015625 +79022 0.7808837890625 +79023 0.8653564453125 +79024 0.813629150390625 +79025 0.857147216796875 +79026 0.80865478515625 +79027 0.766845703125 +79028 0.7703857421875 +79029 0.628509521484375 +79030 0.693084716796875 +79031 0.462127685546875 +79032 0.59893798828125 +79033 0.297210693359375 +79034 0.498626708984375 +79035 0.14862060546875 +79036 0.372650146484375 +79037 -0.00537109375 +79038 0.22747802734375 +79039 -0.15753173828125 +79040 0.060089111328125 +79041 -0.31304931640625 +79042 -0.1414794921875 +79043 -0.48876953125 +79044 -0.337066650390625 +79045 -0.6416015625 +79046 -0.505462646484375 +79047 -0.751373291015625 +79048 -0.66644287109375 +79049 -0.84619140625 +79050 -0.807373046875 +79051 -0.861297607421875 +79052 -0.859466552734375 +79053 -0.863250732421875 +79054 -0.861328125 +79055 -0.856597900390625 +79056 -0.85614013671875 +79057 -0.7498779296875 +79058 -0.80621337890625 +79059 -0.624542236328125 +79060 -0.70892333984375 +79061 -0.47808837890625 +79062 -0.527496337890625 +79063 -0.253387451171875 +79064 -0.301055908203125 +79065 0.003692626953125 +79066 -0.08819580078125 +79067 0.2257080078125 +79068 0.12176513671875 +79069 0.427154541015625 +79070 0.356475830078125 +79071 0.643218994140625 +79072 0.60760498046875 +79073 0.855926513671875 +79074 0.82550048828125 +79075 0.870361328125 +79076 0.8668212890625 +79077 0.870361328125 +79078 0.870361328125 +79079 0.862762451171875 +79080 0.866363525390625 +79081 0.79669189453125 +79082 0.852020263671875 +79083 0.595794677734375 +79084 0.692138671875 +79085 0.362152099609375 +79086 0.509063720703125 +79087 0.1270751953125 +79088 0.3216552734375 +79089 -0.086944580078125 +79090 0.131988525390625 +79091 -0.2784423828125 +79092 -0.089874267578125 +79093 -0.484832763671875 +79094 -0.36102294921875 +79095 -0.729583740234375 +79096 -0.639129638671875 +79097 -0.86688232421875 +79098 -0.856353759765625 +79099 -0.870391845703125 +79100 -0.870391845703125 +79101 -0.86859130859375 +79102 -0.870391845703125 +79103 -0.86279296875 +79104 -0.863494873046875 +79105 -0.817962646484375 +79106 -0.77923583984375 +79107 -0.6116943359375 +79108 -0.52740478515625 +79109 -0.3128662109375 +79110 -0.21514892578125 +79111 0.039398193359375 +79112 0.1378173828125 +79113 0.422821044921875 +79114 0.5020751953125 +79115 0.805145263671875 +79116 0.81927490234375 +79117 0.870361328125 +79118 0.870361328125 +79119 0.870361328125 +79120 0.870361328125 +79121 0.860015869140625 +79122 0.860931396484375 +79123 0.727935791015625 +79124 0.74932861328125 +79125 0.48114013671875 +79126 0.540802001953125 +79127 0.2059326171875 +79128 0.319244384765625 +79129 -0.06103515625 +79130 0.10260009765625 +79131 -0.29913330078125 +79132 -0.115203857421875 +79133 -0.516204833984375 +79134 -0.343719482421875 +79135 -0.7252197265625 +79136 -0.55950927734375 +79137 -0.85980224609375 +79138 -0.7335205078125 +79139 -0.870391845703125 +79140 -0.843505859375 +79141 -0.870391845703125 +79142 -0.852508544921875 +79143 -0.858062744140625 +79144 -0.764923095703125 +79145 -0.673004150390625 +79146 -0.636871337890625 +79147 -0.42694091796875 +79148 -0.51812744140625 +79149 -0.2100830078125 +79150 -0.41741943359375 +79151 -0.0362548828125 +79152 -0.31915283203125 +79153 0.10943603515625 +79154 -0.214996337890625 +79155 0.23516845703125 +79156 -0.076141357421875 +79157 0.373687744140625 +79158 0.08941650390625 +79159 0.517791748046875 +79160 0.221588134765625 +79161 0.602783203125 +79162 0.323028564453125 +79163 0.635711669921875 +79164 0.423614501953125 +79165 0.655181884765625 +79166 0.516937255859375 +79167 0.65948486328125 +79168 0.600311279296875 +79169 0.651275634765625 +79170 0.657989501953125 +79171 0.61846923828125 +79172 0.66448974609375 +79173 0.53753662109375 +79174 0.6119384765625 +79175 0.404144287109375 +79176 0.500274658203125 +79177 0.22186279296875 +79178 0.33905029296875 +79179 0.003997802734375 +79180 0.152252197265625 +79181 -0.22100830078125 +79182 -0.034820556640625 +79183 -0.42449951171875 +79184 -0.19757080078125 +79185 -0.579833984375 +79186 -0.2940673828125 +79187 -0.641876220703125 +79188 -0.327911376953125 +79189 -0.6177978515625 +79190 -0.356048583984375 +79191 -0.575531005859375 +79192 -0.38458251953125 +79193 -0.526336669921875 +79194 -0.370574951171875 +79195 -0.42645263671875 +79196 -0.29412841796875 +79197 -0.2581787109375 +79198 -0.193206787109375 +79199 -0.068695068359375 +79200 -0.108489990234375 +79201 0.09222412109375 +79202 -0.030364990234375 +79203 0.232147216796875 +79204 0.043243408203125 +79205 0.3509521484375 +79206 0.079376220703125 +79207 0.410064697265625 +79208 0.046051025390625 +79209 0.372955322265625 +79210 -0.04302978515625 +79211 0.2554931640625 +79212 -0.145263671875 +79213 0.10711669921875 +79214 -0.245574951171875 +79215 -0.052886962890625 +79216 -0.312591552734375 +79217 -0.186279296875 +79218 -0.2960205078125 +79219 -0.23291015625 +79220 -0.214019775390625 +79221 -0.209442138671875 +79222 -0.12176513671875 +79223 -0.174163818359375 +79224 -0.022247314453125 +79225 -0.126739501953125 +79226 0.098358154296875 +79227 -0.048126220703125 +79228 0.2205810546875 +79229 0.0426025390625 +79230 0.308685302734375 +79231 0.10748291015625 +79232 0.3564453125 +79233 0.1409912109375 +79234 0.4111328125 +79235 0.19708251953125 +79236 0.47100830078125 +79237 0.273651123046875 +79238 0.48980712890625 +79239 0.31768798828125 +79240 0.479522705078125 +79241 0.341094970703125 +79242 0.463623046875 +79243 0.368011474609375 +79244 0.421478271484375 +79245 0.37249755859375 +79246 0.3079833984375 +79247 0.30072021484375 +79248 0.125091552734375 +79249 0.1517333984375 +79250 -0.071319580078125 +79251 -0.01470947265625 +79252 -0.26953125 +79253 -0.1883544921875 +79254 -0.47039794921875 +79255 -0.372711181640625 +79256 -0.62432861328125 +79257 -0.51397705078125 +79258 -0.69415283203125 +79259 -0.57177734375 +79260 -0.67327880859375 +79261 -0.53948974609375 +79262 -0.577606201171875 +79263 -0.43511962890625 +79264 -0.44097900390625 +79265 -0.2962646484375 +79266 -0.298309326171875 +79267 -0.161102294921875 +79268 -0.1634521484375 +79269 -0.0435791015625 +79270 -0.034698486328125 +79271 0.060394287109375 +79272 0.07318115234375 +79273 0.13665771484375 +79274 0.144561767578125 +79275 0.170135498046875 +79276 0.181304931640625 +79277 0.16552734375 +79278 0.211761474609375 +79279 0.15728759765625 +79280 0.23876953125 +79281 0.150787353515625 +79282 0.239349365234375 +79283 0.12200927734375 +79284 0.220367431640625 +79285 0.080108642578125 +79286 0.204345703125 +79287 0.05126953125 +79288 0.21533203125 +79289 0.062896728515625 +79290 0.2337646484375 +79291 0.09271240234375 +79292 0.21795654296875 +79293 0.092987060546875 +79294 0.182159423828125 +79295 0.07855224609375 +79296 0.14105224609375 +79297 0.06427001953125 +79298 0.082672119140625 +79299 0.0347900390625 +79300 0.007232666015625 +79301 -0.01171875 +79302 -0.066253662109375 +79303 -0.056060791015625 +79304 -0.097991943359375 +79305 -0.055511474609375 +79306 -0.08660888671875 +79307 -0.010467529296875 +79308 -0.078582763671875 +79309 0.02508544921875 +79310 -0.095367431640625 +79311 0.025665283203125 +79312 -0.11309814453125 +79313 0.017333984375 +79314 -0.12982177734375 +79315 0.00189208984375 +79316 -0.155426025390625 +79317 -0.03173828125 +79318 -0.1796875 +79319 -0.071502685546875 +79320 -0.219390869140625 +79321 -0.13543701171875 +79322 -0.272491455078125 +79323 -0.219970703125 +79324 -0.3184814453125 +79325 -0.300506591796875 +79326 -0.358184814453125 +79327 -0.376312255859375 +79328 -0.3653564453125 +79329 -0.416107177734375 +79330 -0.29827880859375 +79331 -0.371124267578125 +79332 -0.159210205078125 +79333 -0.242279052734375 +79334 0.014892578125 +79335 -0.069732666015625 +79336 0.2044677734375 +79337 0.125640869140625 +79338 0.381103515625 +79339 0.31268310546875 +79340 0.512115478515625 +79341 0.45501708984375 +79342 0.599273681640625 +79343 0.554779052734375 +79344 0.6417236328125 +79345 0.61065673828125 +79346 0.62957763671875 +79347 0.610931396484375 +79348 0.542266845703125 +79349 0.531463623046875 +79350 0.395050048828125 +79351 0.3883056640625 +79352 0.23638916015625 +79353 0.23468017578125 +79354 0.089447021484375 +79355 0.095245361328125 +79356 -0.0213623046875 +79357 -0.00396728515625 +79358 -0.08203125 +79359 -0.04852294921875 +79360 -0.1060791015625 +79361 -0.055145263671875 +79362 -0.138885498046875 +79363 -0.0758056640625 +79364 -0.205078125 +79365 -0.138702392578125 +79366 -0.273162841796875 +79367 -0.209197998046875 +79368 -0.3447265625 +79369 -0.289031982421875 +79370 -0.420562744140625 +79371 -0.37884521484375 +79372 -0.48101806640625 +79373 -0.456329345703125 +79374 -0.52227783203125 +79375 -0.51641845703125 +79376 -0.509307861328125 +79377 -0.519287109375 +79378 -0.43701171875 +79379 -0.458251953125 +79380 -0.35272216796875 +79381 -0.384796142578125 +79382 -0.27978515625 +79383 -0.323699951171875 +79384 -0.21405029296875 +79385 -0.269287109375 +79386 -0.132659912109375 +79387 -0.1951904296875 +79388 -0.035064697265625 +79389 -0.100006103515625 +79390 0.053985595703125 +79391 -0.01055908203125 +79392 0.16131591796875 +79393 0.1033935546875 +79394 0.2933349609375 +79395 0.24908447265625 +79396 0.402130126953125 +79397 0.373199462890625 +79398 0.472076416015625 +79399 0.45806884765625 +79400 0.5106201171875 +79401 0.511474609375 +79402 0.54718017578125 +79403 0.565399169921875 +79404 0.57489013671875 +79405 0.61138916015625 +79406 0.540740966796875 +79407 0.5897216796875 +79408 0.436737060546875 +79409 0.4906005859375 +79410 0.279449462890625 +79411 0.33148193359375 +79412 0.10150146484375 +79413 0.147796630859375 +79414 -0.058929443359375 +79415 -0.01873779296875 +79416 -0.176300048828125 +79417 -0.140289306640625 +79418 -0.227813720703125 +79419 -0.191986083984375 +79420 -0.222747802734375 +79421 -0.184295654296875 +79422 -0.20123291015625 +79423 -0.161834716796875 +79424 -0.20123291015625 +79425 -0.166595458984375 +79426 -0.2188720703125 +79427 -0.19390869140625 +79428 -0.237152099609375 +79429 -0.22442626953125 +79430 -0.276092529296875 +79431 -0.279754638671875 +79432 -0.317535400390625 +79433 -0.3389892578125 +79434 -0.319183349609375 +79435 -0.3543701171875 +79436 -0.3017578125 +79437 -0.348175048828125 +79438 -0.270904541015625 +79439 -0.32598876953125 +79440 -0.2005615234375 +79441 -0.2581787109375 +79442 -0.08673095703125 +79443 -0.139801025390625 +79444 0.057220458984375 +79445 0.014617919921875 +79446 0.176422119140625 +79447 0.144378662109375 +79448 0.245269775390625 +79449 0.221038818359375 +79450 0.28729248046875 +79451 0.27069091796875 +79452 0.3033447265625 +79453 0.294036865234375 +79454 0.312408447265625 +79455 0.311767578125 +79456 0.32867431640625 +79457 0.339141845703125 +79458 0.338592529296875 +79459 0.360260009765625 +79460 0.3294677734375 +79461 0.360504150390625 +79462 0.272705078125 +79463 0.308380126953125 +79464 0.1483154296875 +79465 0.18170166015625 +79466 -0.020965576171875 +79467 0.0047607421875 +79468 -0.1917724609375 +79469 -0.17559814453125 +79470 -0.322509765625 +79471 -0.3143310546875 +79472 -0.372955322265625 +79473 -0.36785888671875 +79474 -0.367340087890625 +79475 -0.36248779296875 +79476 -0.347442626953125 +79477 -0.343536376953125 +79478 -0.3050537109375 +79479 -0.3018798828125 +79480 -0.234832763671875 +79481 -0.231414794921875 +79482 -0.123748779296875 +79483 -0.117645263671875 +79484 -0.001922607421875 +79485 0.007049560546875 +79486 0.079864501953125 +79487 0.087982177734375 +79488 0.134429931640625 +79489 0.13946533203125 +79490 0.173095703125 +79491 0.17425537109375 +79492 0.191680908203125 +79493 0.188201904296875 +79494 0.180633544921875 +79495 0.171234130859375 +79496 0.135223388671875 +79497 0.118438720703125 +79498 0.08038330078125 +79499 0.05706787109375 +79500 0.01806640625 +79501 -0.010711669921875 +79502 -0.05767822265625 +79503 -0.0914306640625 +79504 -0.125762939453125 +79505 -0.162322998046875 +79506 -0.15948486328125 +79507 -0.194549560546875 +79508 -0.122894287109375 +79509 -0.1492919921875 +79510 -0.01116943359375 +79511 -0.02166748046875 +79512 0.116912841796875 +79513 0.124053955078125 +79514 0.19110107421875 +79515 0.211151123046875 +79516 0.21246337890625 +79517 0.240447998046875 +79518 0.2091064453125 +79519 0.242218017578125 +79520 0.189849853515625 +79521 0.2257080078125 +79522 0.158050537109375 +79523 0.194366455078125 +79524 0.083740234375 +79525 0.115509033203125 +79526 -0.011199951171875 +79527 0.0128173828125 +79528 -0.071685791015625 +79529 -0.053802490234375 +79530 -0.1219482421875 +79531 -0.110626220703125 +79532 -0.200653076171875 +79533 -0.199493408203125 +79534 -0.284027099609375 +79535 -0.29437255859375 +79536 -0.314300537109375 +79537 -0.33221435546875 +79538 -0.261138916015625 +79539 -0.27972412109375 +79540 -0.16937255859375 +79541 -0.185333251953125 +79542 -0.112091064453125 +79543 -0.128204345703125 +79544 -0.09625244140625 +79545 -0.115692138671875 +79546 -0.093292236328125 +79547 -0.116455078125 +79548 -0.080780029296875 +79549 -0.105926513671875 +79550 -0.031158447265625 +79551 -0.053955078125 +79552 0.064117431640625 +79553 0.048797607421875 +79554 0.16363525390625 +79555 0.157318115234375 +79556 0.212615966796875 +79557 0.212005615234375 +79558 0.21630859375 +79559 0.218475341796875 +79560 0.23052978515625 +79561 0.23724365234375 +79562 0.289581298828125 +79563 0.30535888671875 +79564 0.35540771484375 +79565 0.38128662109375 +79566 0.372528076171875 +79567 0.404449462890625 +79568 0.35919189453125 +79569 0.3944091796875 +79570 0.35003662109375 +79571 0.3885498046875 +79572 0.322967529296875 +79573 0.362640380859375 +79574 0.238525390625 +79575 0.27362060546875 +79576 0.0927734375 +79577 0.11712646484375 +79578 -0.06640625 +79579 -0.054901123046875 +79580 -0.19146728515625 +79581 -0.19085693359375 +79582 -0.27783203125 +79583 -0.28570556640625 +79584 -0.325439453125 +79585 -0.339263916015625 +79586 -0.35833740234375 +79587 -0.3775634765625 +79588 -0.41815185546875 +79589 -0.445709228515625 +79590 -0.49713134765625 +79591 -0.535064697265625 +79592 -0.5802001953125 +79593 -0.629058837890625 +79594 -0.639892578125 +79595 -0.697601318359375 +79596 -0.642547607421875 +79597 -0.70391845703125 +79598 -0.58319091796875 +79599 -0.6424560546875 +79600 -0.4417724609375 +79601 -0.491241455078125 +79602 -0.232574462890625 +79603 -0.265716552734375 +79604 -0.0089111328125 +79605 -0.023712158203125 +79606 0.19879150390625 +79607 0.201751708984375 +79608 0.358489990234375 +79609 0.375823974609375 +79610 0.457855224609375 +79611 0.485076904296875 +79612 0.533172607421875 +79613 0.56884765625 +79614 0.591583251953125 +79615 0.634765625 +79616 0.591156005859375 +79617 0.63763427734375 +79618 0.520782470703125 +79619 0.5660400390625 +79620 0.429595947265625 +79621 0.4720458984375 +79622 0.366668701171875 +79623 0.40692138671875 +79624 0.3389892578125 +79625 0.3778076171875 +79626 0.3392333984375 +79627 0.376953125 +79628 0.336578369140625 +79629 0.371978759765625 +79630 0.283599853515625 +79631 0.313140869140625 +79632 0.164825439453125 +79633 0.184417724609375 +79634 0.004241943359375 +79635 0.011199951171875 +79636 -0.164642333984375 +79637 -0.171051025390625 +79638 -0.318359375 +79639 -0.33740234375 +79640 -0.4420166015625 +79641 -0.47198486328125 +79642 -0.522186279296875 +79643 -0.560394287109375 +79644 -0.5380859375 +79645 -0.58056640625 +79646 -0.50421142578125 +79647 -0.54754638671875 +79648 -0.465667724609375 +79649 -0.508575439453125 +79650 -0.418548583984375 +79651 -0.459503173828125 +79652 -0.357177734375 +79653 -0.394378662109375 +79654 -0.319000244140625 +79655 -0.35260009765625 +79656 -0.282501220703125 +79657 -0.31170654296875 +79658 -0.17681884765625 +79659 -0.197418212890625 +79660 -9.1552734375e-05 +79661 -0.007965087890625 +79662 0.201080322265625 +79663 0.207489013671875 +79664 0.389068603515625 +79665 0.409210205078125 +79666 0.54022216796875 +79667 0.57208251953125 +79668 0.62603759765625 +79669 0.66595458984375 +79670 0.61614990234375 +79671 0.65875244140625 +79672 0.52685546875 +79673 0.56744384765625 +79674 0.395782470703125 +79675 0.431396484375 +79676 0.26470947265625 +79677 0.29443359375 +79678 0.158294677734375 +79679 0.182464599609375 +79680 0.046234130859375 +79681 0.06365966796875 +79682 -0.084869384765625 +79683 -0.075958251953125 +79684 -0.190460205078125 +79685 -0.189422607421875 +79686 -0.26611328125 +79687 -0.271942138671875 +79688 -0.330078125 +79689 -0.342529296875 +79690 -0.34735107421875 +79691 -0.364166259765625 +79692 -0.3089599609375 +79693 -0.327239990234375 +79694 -0.258087158203125 +79695 -0.2769775390625 +79696 -0.233306884765625 +79697 -0.253692626953125 +79698 -0.221649169921875 +79699 -0.24365234375 +79700 -0.177093505859375 +79701 -0.1983642578125 +79702 -0.09814453125 +79703 -0.116241455078125 +79704 -0.0224609375 +79705 -0.036834716796875 +79706 0.045196533203125 +79707 0.034881591796875 +79708 0.09759521484375 +79709 0.09124755859375 +79710 0.11260986328125 +79711 0.10888671875 +79712 0.126220703125 +79713 0.125518798828125 +79714 0.15435791015625 +79715 0.15771484375 +79716 0.1712646484375 +79717 0.17828369140625 +79718 0.161712646484375 +79719 0.17108154296875 +79720 0.120025634765625 +79721 0.129974365234375 +79722 0.072479248046875 +79723 0.082427978515625 +79724 0.01849365234375 +79725 0.027679443359375 +79726 -0.07171630859375 +79727 -0.065643310546875 +79728 -0.1617431640625 +79729 -0.15936279296875 +79730 -0.213104248046875 +79731 -0.21307373046875 +79732 -0.233306884765625 +79733 -0.234649658203125 +79734 -0.199615478515625 +79735 -0.2001953125 +79736 -0.121124267578125 +79737 -0.119171142578125 +79738 -0.029541015625 +79739 -0.024749755859375 +79740 0.077667236328125 +79741 0.085784912109375 +79742 0.167724609375 +79743 0.178131103515625 +79744 0.20556640625 +79745 0.215576171875 +79746 0.2037353515625 +79747 0.211456298828125 +79748 0.171142578125 +79749 0.17523193359375 +79750 0.128509521484375 +79751 0.128753662109375 +79752 0.104217529296875 +79753 0.1019287109375 +79754 0.07879638671875 +79755 0.0743408203125 +79756 0.049591064453125 +79757 0.04327392578125 +79758 0.044647216796875 +79759 0.038177490234375 +79760 0.080352783203125 +79761 0.076263427734375 +79762 0.141082763671875 +79763 0.14105224609375 +79764 0.183013916015625 +79765 0.186431884765625 +79766 0.183746337890625 +79767 0.188812255859375 +79768 0.1346435546875 +79769 0.1390380859375 +79770 0.040283203125 +79771 0.041778564453125 +79772 -0.07684326171875 +79773 -0.079437255859375 +79774 -0.21173095703125 +79775 -0.219390869140625 +79776 -0.3544921875 +79777 -0.367828369140625 +79778 -0.47662353515625 +79779 -0.494873046875 +79780 -0.535919189453125 +79781 -0.556243896484375 +79782 -0.49114990234375 +79783 -0.508697509765625 +79784 -0.36456298828125 +79785 -0.3756103515625 +79786 -0.215118408203125 +79787 -0.218902587890625 +79788 -0.0667724609375 +79789 -0.063751220703125 +79790 0.08203125 +79791 0.091552734375 +79792 0.22076416015625 +79793 0.23602294921875 +79794 0.323974609375 +79795 0.342987060546875 +79796 0.37518310546875 +79797 0.39520263671875 +79798 0.37115478515625 +79799 0.389373779296875 +79800 0.31060791015625 +79801 0.324249267578125 +79802 0.216552734375 +79803 0.224090576171875 +79804 0.122589111328125 +79805 0.124267578125 +79806 0.040374755859375 +79807 0.037078857421875 +79808 -0.004058837890625 +79809 -0.010101318359375 +79810 -0.012786865234375 +79811 -0.019439697265625 +79812 -0.01611328125 +79813 -0.022796630859375 +79814 0.003631591796875 +79815 -0.001556396484375 +79816 0.0579833984375 +79817 0.056304931640625 +79818 0.10504150390625 +79819 0.106719970703125 +79820 0.0946044921875 +79821 0.096893310546875 +79822 0.041839599609375 +79823 0.042694091796875 +79824 -0.017181396484375 +79825 -0.018035888671875 +79826 -0.073394775390625 +79827 -0.07586669921875 +79828 -0.115966796875 +79829 -0.11944580078125 +79830 -0.1552734375 +79831 -0.15972900390625 +79832 -0.19683837890625 +79833 -0.202606201171875 +79834 -0.241119384765625 +79835 -0.24859619140625 +79836 -0.295196533203125 +79837 -0.30517578125 +79838 -0.349365234375 +79839 -0.36212158203125 +79840 -0.376983642578125 +79841 -0.39141845703125 +79842 -0.342041015625 +79843 -0.35528564453125 +79844 -0.24102783203125 +79845 -0.249969482421875 +79846 -0.090576171875 +79847 -0.092864990234375 +79848 0.08355712890625 +79849 0.08905029296875 +79850 0.223724365234375 +79851 0.2352294921875 +79852 0.304290771484375 +79853 0.318817138671875 +79854 0.343109130859375 +79855 0.358642578125 +79856 0.333526611328125 +79857 0.347747802734375 +79858 0.275054931640625 +79859 0.28564453125 +79860 0.216033935546875 +79861 0.223175048828125 +79862 0.19110107421875 +79863 0.196746826171875 +79864 0.175018310546875 +79865 0.179840087890625 +79866 0.151702880859375 +79867 0.155548095703125 +79868 0.147186279296875 +79869 0.151214599609375 +79870 0.152099609375 +79871 0.156951904296875 +79872 0.127288818359375 +79873 0.13177490234375 +79874 0.097137451171875 +79875 0.100799560546875 +79876 0.0838623046875 +79877 0.087127685546875 +79878 0.05230712890625 +79879 0.05487060546875 +79880 -0.010223388671875 +79881 -0.009002685546875 +79882 -0.10321044921875 +79883 -0.10400390625 +79884 -0.2259521484375 +79885 -0.229400634765625 +79886 -0.349273681640625 +79887 -0.35552978515625 +79888 -0.433349609375 +79889 -0.441925048828125 +79890 -0.46380615234375 +79891 -0.473846435546875 +79892 -0.454010009765625 +79893 -0.464813232421875 +79894 -0.408233642578125 +79895 -0.419097900390625 +79896 -0.324188232421875 +79897 -0.334320068359375 +79898 -0.219085693359375 +79899 -0.227935791015625 +79900 -0.11614990234375 +79901 -0.12347412109375 +79902 -0.02197265625 +79903 -0.02764892578125 +79904 0.081298828125 +79905 0.077667236328125 +79906 0.214111328125 +79907 0.2132568359375 +79908 0.38604736328125 +79909 0.38885498046875 +79910 0.575836181640625 +79911 0.582794189453125 +79912 0.7235107421875 +79913 0.734039306640625 +79914 0.787384033203125 +79915 0.800140380859375 +79916 0.764739990234375 +79917 0.7783203125 +79918 0.65228271484375 +79919 0.6651611328125 +79920 0.4490966796875 +79921 0.45965576171875 +79922 0.192047119140625 +79923 0.199188232421875 +79924 -0.054351806640625 +79925 -0.050689697265625 +79926 -0.233978271484375 +79927 -0.23297119140625 +79928 -0.32958984375 +79929 -0.33013916015625 +79930 -0.366973876953125 +79931 -0.368408203125 +79932 -0.376800537109375 +79933 -0.378936767578125 +79934 -0.3741455078125 +79935 -0.376983642578125 +79936 -0.375946044921875 +79937 -0.37969970703125 +79938 -0.386566162109375 +79939 -0.391510009765625 +79940 -0.37945556640625 +79941 -0.385345458984375 +79942 -0.335693359375 +79943 -0.3419189453125 +79944 -0.27667236328125 +79945 -0.28289794921875 +79946 -0.24505615234375 +79947 -0.251617431640625 +79948 -0.2586669921875 +79949 -0.266143798828125 +79950 -0.265289306640625 +79951 -0.273345947265625 +79952 -0.20941162109375 +79953 -0.216796875 +79954 -0.12225341796875 +79955 -0.128265380859375 +79956 -0.06329345703125 +79957 -0.068145751953125 +79958 -0.03900146484375 +79959 -0.0430908203125 +79960 -0.021209716796875 +79961 -0.024444580078125 +79962 0.022552490234375 +79963 0.020721435546875 +79964 0.123870849609375 +79965 0.124481201171875 +79966 0.2542724609375 +79967 0.25787353515625 +79968 0.372711181640625 +79969 0.379119873046875 +79970 0.471099853515625 +79971 0.47991943359375 +79972 0.51788330078125 +79973 0.5281982421875 +79974 0.500518798828125 +79975 0.511138916015625 +79976 0.446044921875 +79977 0.456207275390625 +79978 0.3978271484375 +79979 0.407470703125 +79980 0.3743896484375 +79981 0.383758544921875 +79982 0.3480224609375 +79983 0.35687255859375 +79984 0.303985595703125 +79985 0.31182861328125 +79986 0.24444580078125 +79987 0.250885009765625 +79988 0.160858154296875 +79989 0.1654052734375 +79990 0.033416748046875 +79991 0.035247802734375 +79992 -0.140350341796875 +79993 -0.142059326171875 +79994 -0.33013916015625 +79995 -0.33563232421875 +79996 -0.52520751953125 +79997 -0.5345458984375 +79998 -0.70892333984375 +79999 -0.72186279296875 +80000 -0.821380615234375 +80001 -0.836669921875 +80002 -0.817047119140625 +80003 -0.8326416015625 +80004 -0.7154541015625 +80005 -0.7296142578125 +80006 -0.5706787109375 +80007 -0.582550048828125 +80008 -0.4305419921875 +80009 -0.440093994140625 +80010 -0.316802978515625 +80011 -0.324310302734375 +80012 -0.1962890625 +80013 -0.20147705078125 +80014 -0.04241943359375 +80015 -0.044647216796875 +80016 0.10333251953125 +80017 0.103973388671875 +80018 0.19964599609375 +80019 0.202392578125 +80020 0.260223388671875 +80021 0.264495849609375 +80022 0.33294677734375 +80023 0.338897705078125 +80024 0.43572998046875 +80025 0.443817138671875 +80026 0.53497314453125 +80027 0.545074462890625 +80028 0.605743408203125 +80029 0.6173095703125 +80030 0.64013671875 +80031 0.6524658203125 +80032 0.650787353515625 +80033 0.66339111328125 +80034 0.6436767578125 +80035 0.6561279296875 +80036 0.595245361328125 +80037 0.606781005859375 +80038 0.491546630859375 +80039 0.501190185546875 +80040 0.34576416015625 +80041 0.352783203125 +80042 0.17266845703125 +80043 0.176544189453125 +80044 -0.034942626953125 +80045 -0.034820556640625 +80046 -0.25433349609375 +80047 -0.258209228515625 +80048 -0.4351806640625 +80049 -0.44244384765625 +80050 -0.56549072265625 +80051 -0.5753173828125 +80052 -0.640625 +80053 -0.65203857421875 +80054 -0.630096435546875 +80055 -0.641632080078125 +80056 -0.551666259765625 +80057 -0.562164306640625 +80058 -0.449066162109375 +80059 -0.458038330078125 +80060 -0.343231201171875 +80061 -0.350555419921875 +80062 -0.254669189453125 +80063 -0.260528564453125 +80064 -0.187469482421875 +80065 -0.192108154296875 +80066 -0.138336181640625 +80067 -0.141937255859375 +80068 -0.099517822265625 +80069 -0.1021728515625 +80070 -0.06121826171875 +80071 -0.062896728515625 +80072 -0.011444091796875 +80073 -0.011932373046875 +80074 0.061767578125 +80075 0.062835693359375 +80076 0.145965576171875 +80077 0.148712158203125 +80078 0.2371826171875 +80079 0.241729736328125 +80080 0.34259033203125 +80081 0.34912109375 +80082 0.448822021484375 +80083 0.457305908203125 +80084 0.533843994140625 +80085 0.54388427734375 +80086 0.56231689453125 +80087 0.5728759765625 +80088 0.497100830078125 +80089 0.506591796875 +80090 0.344329833984375 +80091 0.351226806640625 +80092 0.14306640625 +80093 0.146514892578125 +80094 -0.05523681640625 +80095 -0.05523681640625 +80096 -0.213409423828125 +80097 -0.21624755859375 +80098 -0.32989501953125 +80099 -0.334930419921875 +80100 -0.39654541015625 +80101 -0.402984619140625 +80102 -0.43389892578125 +80103 -0.4412841796875 +80104 -0.487213134765625 +80105 -0.49578857421875 +80106 -0.55029296875 +80107 -0.5601806640625 +80108 -0.589996337890625 +80109 -0.600738525390625 +80110 -0.5736083984375 +80111 -0.584228515625 +80112 -0.47027587890625 +80113 -0.47930908203125 +80114 -0.273529052734375 +80115 -0.27935791015625 +80116 -0.007476806640625 +80117 -0.0089111328125 +80118 0.265625 +80119 0.268798828125 +80120 0.47601318359375 +80121 0.482818603515625 +80122 0.5947265625 +80123 0.60369873046875 +80124 0.640411376953125 +80125 0.650421142578125 +80126 0.653472900390625 +80127 0.66400146484375 +80128 0.630859375 +80129 0.6416015625 +80130 0.562530517578125 +80131 0.5728759765625 +80132 0.489349365234375 +80133 0.498199462890625 +80134 0.432342529296875 +80135 0.43853759765625 +80136 0.37042236328125 +80137 0.3734130859375 +80138 0.271636962890625 +80139 0.271636962890625 +80140 0.108184814453125 +80141 0.106170654296875 +80142 -0.097747802734375 +80143 -0.100921630859375 +80144 -0.314544677734375 +80145 -0.3182373046875 +80146 -0.54351806640625 +80147 -0.546875 +80148 -0.766998291015625 +80149 -0.769287109375 +80150 -0.86297607421875 +80151 -0.863128662109375 +80152 -0.870391845703125 +80153 -0.870391845703125 +80154 -0.869781494140625 +80155 -0.86968994140625 +80156 -0.862640380859375 +80157 -0.8624267578125 +80158 -0.786224365234375 +80159 -0.784149169921875 +80160 -0.55517578125 +80161 -0.553741455078125 +80162 -0.242889404296875 +80163 -0.24310302734375 +80164 0.10760498046875 +80165 0.105255126953125 +80166 0.445159912109375 +80167 0.4407958984375 +80168 0.73443603515625 +80169 0.72857666015625 +80170 0.86474609375 +80171 0.864044189453125 +80172 0.870361328125 +80173 0.870361328125 +80174 0.867431640625 +80175 0.8681640625 +80176 0.857025146484375 +80177 0.85845947265625 +80178 0.742645263671875 +80179 0.7611083984375 +80180 0.575775146484375 +80181 0.598388671875 +80182 0.397613525390625 +80183 0.42279052734375 +80184 0.210968017578125 +80185 0.237152099609375 +80186 -0.016387939453125 +80187 0.009857177734375 +80188 -0.292999267578125 +80189 -0.2672119140625 +80190 -0.578643798828125 +80191 -0.554168701171875 +80192 -0.81683349609375 +80193 -0.795074462890625 +80194 -0.866943359375 +80195 -0.86505126953125 +80196 -0.870391845703125 +80197 -0.870391845703125 +80198 -0.867767333984375 +80199 -0.869598388671875 +80200 -0.863616943359375 +80201 -0.8670654296875 +80202 -0.856475830078125 +80203 -0.861297607421875 +80204 -0.729736328125 +80205 -0.7840576171875 +80206 -0.509613037109375 +80207 -0.57147216796875 +80208 -0.246826171875 +80209 -0.312957763671875 +80210 0.03057861328125 +80211 -0.03619384765625 +80212 0.31158447265625 +80213 0.24761962890625 +80214 0.5711669921875 +80215 0.51336669921875 +80216 0.7735595703125 +80217 0.725189208984375 +80218 0.8599853515625 +80219 0.856048583984375 +80220 0.865386962890625 +80221 0.863006591796875 +80222 0.8643798828125 +80223 0.8636474609375 +80224 0.85894775390625 +80225 0.859832763671875 +80226 0.807159423828125 +80227 0.82916259765625 +80228 0.689849853515625 +80229 0.72393798828125 +80230 0.54052734375 +80231 0.584442138671875 +80232 0.387908935546875 +80233 0.438629150390625 +80234 0.246337890625 +80235 0.3004150390625 +80236 0.09381103515625 +80237 0.148223876953125 +80238 -0.06231689453125 +80239 -0.010498046875 +80240 -0.22686767578125 +80241 -0.180145263671875 +80242 -0.41607666015625 +80243 -0.376190185546875 +80244 -0.58599853515625 +80245 -0.55474853515625 +80246 -0.71539306640625 +80247 -0.694305419921875 +80248 -0.83123779296875 +80249 -0.820709228515625 +80250 -0.861968994140625 +80251 -0.861968994140625 +80252 -0.86614990234375 +80253 -0.86724853515625 +80254 -0.861480712890625 +80255 -0.8636474609375 +80256 -0.80999755859375 +80257 -0.8385009765625 +80258 -0.696258544921875 +80259 -0.731048583984375 +80260 -0.557159423828125 +80261 -0.59600830078125 +80262 -0.335296630859375 +80263 -0.376861572265625 +80264 -0.07647705078125 +80265 -0.118804931640625 +80266 0.151611328125 +80267 0.11126708984375 +80268 0.36297607421875 +80269 0.3267822265625 +80270 0.5921630859375 +80271 0.561309814453125 +80272 0.832244873046875 +80273 0.80743408203125 +80274 0.870361328125 +80275 0.870361328125 +80276 0.870361328125 +80277 0.870361328125 +80278 0.862762451171875 +80279 0.86279296875 +80280 0.79669189453125 +80281 0.797332763671875 +80282 0.595794677734375 +80283 0.597259521484375 +80284 0.362152099609375 +80285 0.36444091796875 +80286 0.1270751953125 +80287 0.1298828125 +80288 -0.086944580078125 +80289 -0.0841064453125 +80290 -0.2784423828125 +80291 -0.27593994140625 +80292 -0.484832763671875 +80293 -0.48223876953125 +80294 -0.729583740234375 +80295 -0.725921630859375 +80296 -0.86688232421875 +80297 -0.866302490234375 +80298 -0.870391845703125 +80299 -0.870391845703125 +80300 -0.86859130859375 +80301 -0.869110107421875 +80302 -0.86279296875 +80303 -0.86376953125 +80304 -0.817962646484375 +80305 -0.83087158203125 +80306 -0.6116943359375 +80307 -0.62841796875 +80308 -0.3128662109375 +80309 -0.33343505859375 +80310 0.039398193359375 +80311 0.0155029296875 +80312 0.422821044921875 +80313 0.39630126953125 +80314 0.805145263671875 +80315 0.7769775390625 +80316 0.870361328125 +80317 0.870361328125 +80318 0.870361328125 +80319 0.870361328125 +80320 0.860015869140625 +80321 0.860076904296875 +80322 0.727935791015625 +80323 0.729766845703125 +80324 0.48114013671875 +80325 0.484588623046875 +80326 0.2059326171875 +80327 0.21087646484375 +80328 -0.06103515625 +80329 -0.055084228515625 +80330 -0.29913330078125 +80331 -0.2928466796875 +80332 -0.516204833984375 +80333 -0.509918212890625 +80334 -0.7252197265625 +80335 -0.718841552734375 +80336 -0.85980224609375 +80337 -0.859100341796875 +80338 -0.870391845703125 +80339 -0.870391845703125 +80340 -0.870391845703125 +80341 -0.870391845703125 +80342 -0.858062744140625 +80343 -0.858184814453125 +80344 -0.673004150390625 +80345 -0.675689697265625 +80346 -0.42694091796875 +80347 -0.43121337890625 +80348 -0.2100830078125 +80349 -0.2149658203125 +80350 -0.0362548828125 +80351 -0.040679931640625 +80352 0.10943603515625 +80353 0.1060791015625 +80354 0.23516845703125 +80355 0.233184814453125 +80356 0.373687744140625 +80357 0.3726806640625 +80358 0.517791748046875 +80359 0.517303466796875 +80360 0.602783203125 +80361 0.603271484375 +80362 0.635711669921875 +80363 0.63739013671875 +80364 0.655181884765625 +80365 0.657562255859375 +80366 0.65948486328125 +80367 0.662078857421875 +80368 0.651275634765625 +80369 0.653533935546875 +80370 0.61846923828125 +80371 0.620086669921875 +80372 0.53753662109375 +80373 0.538665771484375 +80374 0.404144287109375 +80375 0.4051513671875 +80376 0.22186279296875 +80377 0.22320556640625 +80378 0.003997802734375 +80379 0.00604248046875 +80380 -0.22100830078125 +80381 -0.21820068359375 +80382 -0.42449951171875 +80383 -0.421173095703125 +80384 -0.579833984375 +80385 -0.576812744140625 +80386 -0.641876220703125 +80387 -0.641265869140625 +80388 -0.6177978515625 +80389 -0.620880126953125 +80390 -0.575531005859375 +80391 -0.58062744140625 +80392 -0.526336669921875 +80393 -0.5316162109375 +80394 -0.42645263671875 +80395 -0.432647705078125 +80396 -0.2581787109375 +80397 -0.2672119140625 +80398 -0.068695068359375 +80399 -0.080657958984375 +80400 0.09222412109375 +80401 0.079193115234375 +80402 0.232147216796875 +80403 0.219146728515625 +80404 0.3509521484375 +80405 0.3387451171875 +80406 0.410064697265625 +80407 0.40093994140625 +80408 0.372955322265625 +80409 0.370635986328125 +80410 0.2554931640625 +80411 0.262725830078125 +80412 0.10711669921875 +80413 0.1241455078125 +80414 -0.052886962890625 +80415 -0.02685546875 +80416 -0.186279296875 +80417 -0.15386962890625 +80418 -0.23291015625 +80419 -0.199615478515625 +80420 -0.209442138671875 +80421 -0.1798095703125 +80422 -0.174163818359375 +80423 -0.149749755859375 +80424 -0.126739501953125 +80425 -0.10888671875 +80426 -0.048126220703125 +80427 -0.038848876953125 +80428 0.0426025390625 +80429 0.04248046875 +80430 0.10748291015625 +80431 0.0992431640625 +80432 0.1409912109375 +80433 0.12646484375 +80434 0.19708251953125 +80435 0.17572021484375 +80436 0.273651123046875 +80437 0.2452392578125 +80438 0.31768798828125 +80439 0.28472900390625 +80440 0.341094970703125 +80441 0.30560302734375 +80442 0.368011474609375 +80443 0.3309326171875 +80444 0.37249755859375 +80445 0.335968017578125 +80446 0.30072021484375 +80447 0.269378662109375 +80448 0.1517333984375 +80449 0.130126953125 +80450 -0.01470947265625 +80451 -0.0250244140625 +80452 -0.1883544921875 +80453 -0.1865234375 +80454 -0.372711181640625 +80455 -0.35797119140625 +80456 -0.51397705078125 +80457 -0.48834228515625 +80458 -0.57177734375 +80459 -0.539398193359375 +80460 -0.53948974609375 +80461 -0.50506591796875 +80462 -0.43511962890625 +80463 -0.4027099609375 +80464 -0.2962646484375 +80465 -0.26824951171875 +80466 -0.161102294921875 +80467 -0.13812255859375 +80468 -0.0435791015625 +80469 -0.025634765625 +80470 0.060394287109375 +80471 0.07305908203125 +80472 0.13665771484375 +80473 0.14453125 +80474 0.170135498046875 +80475 0.174530029296875 +80476 0.16552734375 +80477 0.16766357421875 +80478 0.15728759765625 +80479 0.1568603515625 +80480 0.150787353515625 +80481 0.147430419921875 +80482 0.12200927734375 +80483 0.116668701171875 +80484 0.080108642578125 +80485 0.073486328125 +80486 0.05126953125 +80487 0.04296875 +80488 0.062896728515625 +80489 0.051422119140625 +80490 0.09271240234375 +80491 0.07769775390625 +80492 0.092987060546875 +80493 0.076507568359375 +80494 0.07855224609375 +80495 0.06201171875 +80496 0.06427001953125 +80497 0.04840087890625 +80498 0.0347900390625 +80499 0.02099609375 +80500 -0.01171875 +80501 -0.02197265625 +80502 -0.056060791015625 +80503 -0.062347412109375 +80504 -0.055511474609375 +80505 -0.059539794921875 +80506 -0.010467529296875 +80507 -0.014068603515625 +80508 0.02508544921875 +80509 0.02252197265625 +80510 0.025665283203125 +80511 0.02581787109375 +80512 0.017333984375 +80513 0.020477294921875 +80514 0.00189208984375 +80515 0.008087158203125 +80516 -0.03173828125 +80517 -0.022003173828125 +80518 -0.071502685546875 +80519 -0.0584716796875 +80520 -0.13543701171875 +80521 -0.118499755859375 +80522 -0.219970703125 +80523 -0.19873046875 +80524 -0.300506591796875 +80525 -0.2757568359375 +80526 -0.376312255859375 +80527 -0.34881591796875 +80528 -0.416107177734375 +80529 -0.3880615234375 +80530 -0.371124267578125 +80531 -0.34698486328125 +80532 -0.242279052734375 +80533 -0.226348876953125 +80534 -0.069732666015625 +80535 -0.06427001953125 +80536 0.125640869140625 +80537 0.119476318359375 +80538 0.31268310546875 +80539 0.29534912109375 +80540 0.45501708984375 +80541 0.428863525390625 +80542 0.554779052734375 +80543 0.52215576171875 +80544 0.61065673828125 +80545 0.574066162109375 +80546 0.610931396484375 +80547 0.573455810546875 +80548 0.531463623046875 +80549 0.497406005859375 +80550 0.3883056640625 +80551 0.3612060546875 +80552 0.23468017578125 +80553 0.215484619140625 +80554 0.095245361328125 +80555 0.083709716796875 +80556 -0.00396728515625 +80557 -0.009429931640625 +80558 -0.04852294921875 +80559 -0.05029296875 +80560 -0.055145263671875 +80561 -0.054840087890625 +80562 -0.0758056640625 +80563 -0.07269287109375 +80564 -0.138702392578125 +80565 -0.130767822265625 +80566 -0.209197998046875 +80567 -0.196197509765625 +80568 -0.289031982421875 +80569 -0.270751953125 +80570 -0.37884521484375 +80571 -0.3551025390625 +80572 -0.456329345703125 +80573 -0.42803955078125 +80574 -0.51641845703125 +80575 -0.484771728515625 +80576 -0.519287109375 +80577 -0.487396240234375 +80578 -0.458251953125 +80579 -0.4295654296875 +80580 -0.384796142578125 +80581 -0.360260009765625 +80582 -0.323699951171875 +80583 -0.30303955078125 +80584 -0.269287109375 +80585 -0.252410888671875 +80586 -0.1951904296875 +80587 -0.1832275390625 +80588 -0.100006103515625 +80589 -0.09405517578125 +80590 -0.01055908203125 +80591 -0.010345458984375 +80592 0.1033935546875 +80593 0.09674072265625 +80594 0.24908447265625 +80595 0.234161376953125 +80596 0.373199462890625 +80597 0.351226806640625 +80598 0.45806884765625 +80599 0.431182861328125 +80600 0.511474609375 +80601 0.4814453125 +80602 0.565399169921875 +80603 0.53253173828125 +80604 0.61138916015625 +80605 0.576385498046875 +80606 0.5897216796875 +80607 0.556121826171875 +80608 0.4906005859375 +80609 0.462371826171875 +80610 0.33148193359375 +80611 0.311767578125 +80612 0.147796630859375 +80613 0.137939453125 +80614 -0.01873779296875 +80615 -0.019439697265625 +80616 -0.140289306640625 +80617 -0.133941650390625 +80618 -0.191986083984375 +80619 -0.18194580078125 +80620 -0.184295654296875 +80621 -0.173492431640625 +80622 -0.161834716796875 +80623 -0.151123046875 +80624 -0.166595458984375 +80625 -0.15484619140625 +80626 -0.19390869140625 +80627 -0.18023681640625 +80628 -0.22442626953125 +80629 -0.20892333984375 +80630 -0.279754638671875 +80631 -0.261505126953125 +80632 -0.3389892578125 +80633 -0.318084716796875 +80634 -0.3543701171875 +80635 -0.333160400390625 +80636 -0.348175048828125 +80637 -0.327911376953125 +80638 -0.32598876953125 +80639 -0.3076171875 +80640 -0.2581787109375 +80641 -0.2440185546875 +80642 -0.139801025390625 +80643 -0.132354736328125 +80644 0.014617919921875 +80645 0.013580322265625 +80646 0.144378662109375 +80647 0.1361083984375 +80648 0.221038818359375 +80649 0.208282470703125 +80650 0.27069091796875 +80651 0.2548828125 +80652 0.294036865234375 +80653 0.276641845703125 +80654 0.311767578125 +80655 0.293212890625 +80656 0.339141845703125 +80657 0.31903076171875 +80658 0.360260009765625 +80659 0.338623046875 +80660 0.360504150390625 +80661 0.338226318359375 +80662 0.308380126953125 +80663 0.28900146484375 +80664 0.18170166015625 +80665 0.170745849609375 +80666 0.0047607421875 +80667 0.00604248046875 +80668 -0.17559814453125 +80669 -0.161865234375 +80670 -0.3143310546875 +80671 -0.291412353515625 +80672 -0.36785888671875 +80673 -0.342376708984375 +80674 -0.36248779296875 +80675 -0.338836669921875 +80676 -0.343536376953125 +80677 -0.322418212890625 +80678 -0.3018798828125 +80679 -0.284698486328125 +80680 -0.231414794921875 +80681 -0.22003173828125 +80682 -0.117645263671875 +80683 -0.11505126953125 +80684 0.007049560546875 +80685 0.0003662109375 +80686 0.087982177734375 +80687 0.07586669921875 +80688 0.13946533203125 +80689 0.12457275390625 +80690 0.17425537109375 +80691 0.158111572265625 +80692 0.188201904296875 +80693 0.17254638671875 +80694 0.171234130859375 +80695 0.15850830078125 +80696 0.118438720703125 +80697 0.111419677734375 +80698 0.05706787109375 +80699 0.0562744140625 +80700 -0.010711669921875 +80701 -0.0050048828125 +80702 -0.0914306640625 +80703 -0.078521728515625 +80704 -0.162322998046875 +80705 -0.143310546875 +80706 -0.194549560546875 +80707 -0.172882080078125 +80708 -0.1492919921875 +80709 -0.13153076171875 +80710 -0.02166748046875 +80711 -0.014678955078125 +80712 0.124053955078125 +80713 0.1185302734375 +80714 0.211151123046875 +80715 0.197601318359375 +80716 0.240447998046875 +80717 0.223358154296875 +80718 0.242218017578125 +80719 0.22369384765625 +80720 0.2257080078125 +80721 0.20721435546875 +80722 0.194366455078125 +80723 0.177154541015625 +80724 0.115509033203125 +80725 0.103515625 +80726 0.0128173828125 +80727 0.00811767578125 +80728 -0.053802490234375 +80729 -0.053863525390625 +80730 -0.110626220703125 +80731 -0.1065673828125 +80732 -0.199493408203125 +80733 -0.1884765625 +80734 -0.29437255859375 +80735 -0.275634765625 +80736 -0.33221435546875 +80737 -0.31005859375 +80738 -0.27972412109375 +80739 -0.261138916015625 +80740 -0.185333251953125 +80741 -0.173492431640625 +80742 -0.128204345703125 +80743 -0.1199951171875 +80744 -0.115692138671875 +80745 -0.107421875 +80746 -0.116455078125 +80747 -0.107025146484375 +80748 -0.105926513671875 +80749 -0.09625244140625 +80750 -0.053955078125 +80751 -0.047454833984375 +80752 0.048797607421875 +80753 0.04791259765625 +80754 0.157318115234375 +80755 0.148406982421875 +80756 0.212005615234375 +80757 0.19915771484375 +80758 0.218475341796875 +80759 0.205291748046875 +80760 0.23724365234375 +80761 0.222503662109375 +80762 0.30535888671875 +80763 0.284912109375 +80764 0.38128662109375 +80765 0.354278564453125 +80766 0.404449462890625 +80767 0.374908447265625 +80768 0.3944091796875 +80769 0.364837646484375 +80770 0.3885498046875 +80771 0.358551025390625 +80772 0.362640380859375 +80773 0.333831787109375 +80774 0.27362060546875 +80775 0.251068115234375 +80776 0.11712646484375 +80777 0.10626220703125 +80778 -0.054901123046875 +80779 -0.052734375 +80780 -0.19085693359375 +80781 -0.178375244140625 +80782 -0.28570556640625 +80783 -0.266021728515625 +80784 -0.339263916015625 +80785 -0.31549072265625 +80786 -0.3775634765625 +80787 -0.350738525390625 +80788 -0.445709228515625 +80789 -0.41326904296875 +80790 -0.535064697265625 +80791 -0.495147705078125 +80792 -0.629058837890625 +80793 -0.581146240234375 +80794 -0.697601318359375 +80795 -0.64361572265625 +80796 -0.70391845703125 +80797 -0.648773193359375 +80798 -0.6424560546875 +80799 -0.591522216796875 +80800 -0.491241455078125 +80801 -0.451690673828125 +80802 -0.265716552734375 +80803 -0.243499755859375 +80804 -0.023712158203125 +80805 -0.02020263671875 +80806 0.201751708984375 +80807 0.187744140625 +80808 0.375823974609375 +80809 0.3482666015625 +80810 0.485076904296875 +80811 0.449005126953125 +80812 0.56884765625 +80813 0.526153564453125 +80814 0.634765625 +80815 0.58673095703125 +80816 0.63763427734375 +80817 0.58917236328125 +80818 0.5660400390625 +80819 0.522979736328125 +80820 0.4720458984375 +80821 0.436065673828125 +80822 0.40692138671875 +80823 0.375579833984375 +80824 0.3778076171875 +80825 0.34820556640625 +80826 0.376953125 +80827 0.3468017578125 +80828 0.371978759765625 +80829 0.34161376953125 +80830 0.313140869140625 +80831 0.28692626953125 +80832 0.184417724609375 +80833 0.167999267578125 +80834 0.011199951171875 +80835 0.00823974609375 +80836 -0.171051025390625 +80837 -0.15972900390625 +80838 -0.33740234375 +80839 -0.31292724609375 +80840 -0.47198486328125 +80841 -0.436737060546875 +80842 -0.560394287109375 +80843 -0.5179443359375 +80844 -0.58056640625 +80845 -0.5362548828125 +80846 -0.54754638671875 +80847 -0.505523681640625 +80848 -0.508575439453125 +80849 -0.46923828125 +80850 -0.459503173828125 +80851 -0.423583984375 +80852 -0.394378662109375 +80853 -0.3631591796875 +80854 -0.35260009765625 +80855 -0.32421875 +80856 -0.31170654296875 +80857 -0.286102294921875 +80858 -0.197418212890625 +80859 -0.180511474609375 +80860 -0.007965087890625 +80861 -0.005828857421875 +80862 0.207489013671875 +80863 0.19268798828125 +80864 0.409210205078125 +80865 0.37847900390625 +80866 0.57208251953125 +80867 0.52838134765625 +80868 0.66595458984375 +80869 0.61468505859375 +80870 0.65875244140625 +80871 0.60791015625 +80872 0.56744384765625 +80873 0.523651123046875 +80874 0.431396484375 +80875 0.39813232421875 +80876 0.29443359375 +80877 0.271728515625 +80878 0.182464599609375 +80879 0.16827392578125 +80880 0.06365966796875 +80881 0.05853271484375 +80882 -0.075958251953125 +80883 -0.070343017578125 +80884 -0.189422607421875 +80885 -0.175140380859375 +80886 -0.271942138671875 +80887 -0.25140380859375 +80888 -0.342529296875 +80889 -0.316619873046875 +80890 -0.364166259765625 +80891 -0.336761474609375 +80892 -0.327239990234375 +80893 -0.302947998046875 +80894 -0.2769775390625 +80895 -0.25677490234375 +80896 -0.253692626953125 +80897 -0.235076904296875 +80898 -0.24365234375 +80899 -0.22540283203125 +80900 -0.1983642578125 +80901 -0.184295654296875 +80902 -0.116241455078125 +80903 -0.1102294921875 +80904 -0.036834716796875 +80905 -0.038238525390625 +80906 0.034881591796875 +80907 0.027191162109375 +80908 0.09124755859375 +80909 0.079193115234375 +80910 0.10888671875 +80911 0.096954345703125 +80912 0.125518798828125 +80913 0.11383056640625 +80914 0.15771484375 +80915 0.1444091796875 +80916 0.17828369140625 +80917 0.1644287109375 +80918 0.17108154296875 +80919 0.159454345703125 +80920 0.129974365234375 +80921 0.123992919921875 +80922 0.082427978515625 +80923 0.08233642578125 +80924 0.027679443359375 +80925 0.0338134765625 +80926 -0.065643310546875 +80927 -0.0494384765625 +80928 -0.15936279296875 +80929 -0.13348388671875 +80930 -0.21307373046875 +80931 -0.182373046875 +80932 -0.234649658203125 +80933 -0.20306396484375 +80934 -0.2001953125 +80935 -0.174224853515625 +80936 -0.119171142578125 +80937 -0.10418701171875 +80938 -0.024749755859375 +80939 -0.022308349609375 +80940 0.085784912109375 +80941 0.073944091796875 +80942 0.178131103515625 +80943 0.154205322265625 +80944 0.215576171875 +80945 0.186004638671875 +80946 0.211456298828125 +80947 0.18121337890625 +80948 0.17523193359375 +80949 0.148284912109375 +80950 0.128753662109375 +80951 0.106689453125 +80952 0.1019287109375 +80953 0.082977294921875 +80954 0.0743408203125 +80955 0.05902099609375 +80956 0.04327392578125 +80957 0.0323486328125 +80958 0.038177490234375 +80959 0.029022216796875 +80960 0.076263427734375 +80961 0.064300537109375 +80962 0.14105224609375 +80963 0.1234130859375 +80964 0.186431884765625 +80965 0.16534423828125 +80966 0.188812255859375 +80967 0.169036865234375 +80968 0.1390380859375 +80969 0.126251220703125 +80970 0.041778564453125 +80971 0.041107177734375 +80972 -0.079437255859375 +80973 -0.0655517578125 +80974 -0.219390869140625 +80975 -0.18914794921875 +80976 -0.367828369140625 +80977 -0.320587158203125 +80978 -0.494873046875 +80979 -0.433349609375 +80980 -0.556243896484375 +80981 -0.488128662109375 +80982 -0.508697509765625 +80983 -0.446502685546875 +80984 -0.3756103515625 +80985 -0.32916259765625 +80986 -0.218902587890625 +80987 -0.191070556640625 +80988 -0.063751220703125 +80989 -0.05450439453125 +80990 0.091552734375 +80991 0.08209228515625 +80992 0.23602294921875 +80993 0.209075927734375 +80994 0.342987060546875 +80995 0.30279541015625 +80996 0.39520263671875 +80997 0.3480224609375 +80998 0.389373779296875 +80999 0.3419189453125 +81000 0.324249267578125 +81001 0.28338623046875 +81002 0.224090576171875 +81003 0.194000244140625 +81004 0.124267578125 +81005 0.105224609375 +81006 0.037078857421875 +81007 0.027923583984375 +81008 -0.010101318359375 +81009 -0.013580322265625 +81010 -0.019439697265625 +81011 -0.021270751953125 +81012 -0.022796630859375 +81013 -0.0234375 +81014 -0.001556396484375 +81015 -0.003570556640625 +81016 0.056304931640625 +81017 0.048919677734375 +81018 0.106719970703125 +81019 0.09478759765625 +81020 0.096893310546875 +81021 0.087127685546875 +81022 0.042694091796875 +81023 0.040008544921875 +81024 -0.018035888671875 +81025 -0.0130615234375 +81026 -0.07586669921875 +81027 -0.063720703125 +81028 -0.11944580078125 +81029 -0.1019287109375 +81030 -0.15972900390625 +81031 -0.137451171875 +81032 -0.202606201171875 +81033 -0.175537109375 +81034 -0.24859619140625 +81035 -0.216644287109375 +81036 -0.30517578125 +81037 -0.267333984375 +81038 -0.36212158203125 +81039 -0.31854248046875 +81040 -0.39141845703125 +81041 -0.345367431640625 +81042 -0.35528564453125 +81043 -0.314178466796875 +81044 -0.249969482421875 +81045 -0.22161865234375 +81046 -0.092864990234375 +81047 -0.083099365234375 +81048 0.08905029296875 +81049 0.0775146484375 +81050 0.2352294921875 +81051 0.206512451171875 +81052 0.318817138671875 +81053 0.28009033203125 +81054 0.358642578125 +81055 0.31500244140625 +81056 0.347747802734375 +81057 0.305084228515625 +81058 0.28564453125 +81059 0.249908447265625 +81060 0.223175048828125 +81061 0.19464111328125 +81062 0.196746826171875 +81063 0.17156982421875 +81064 0.179840087890625 +81065 0.1571044921875 +81066 0.155548095703125 +81067 0.13623046875 +81068 0.151214599609375 +81069 0.133148193359375 +81070 0.156951904296875 +81071 0.139068603515625 +81072 0.13177490234375 +81073 0.117523193359375 +81074 0.100799560546875 +81075 0.09075927734375 +81076 0.087127685546875 +81077 0.079254150390625 +81078 0.05487060546875 +81079 0.051116943359375 +81080 -0.009002685546875 +81081 -0.0052490234375 +81082 -0.10400390625 +81083 -0.089385986328125 +81084 -0.229400634765625 +81085 -0.200653076171875 +81086 -0.35552978515625 +81087 -0.312713623046875 +81088 -0.441925048828125 +81089 -0.3896484375 +81090 -0.473846435546875 +81091 -0.41839599609375 +81092 -0.464813232421875 +81093 -0.410858154296875 +81094 -0.419097900390625 +81095 -0.370819091796875 +81096 -0.334320068359375 +81097 -0.296173095703125 +81098 -0.227935791015625 +81099 -0.20233154296875 +81100 -0.12347412109375 +81101 -0.11016845703125 +81102 -0.02764892578125 +81103 -0.025604248046875 +81104 0.077667236328125 +81105 0.06744384765625 +81106 0.2132568359375 +81107 0.187469482421875 +81108 0.38885498046875 +81109 0.3431396484375 +81110 0.582794189453125 +81111 0.51519775390625 +81112 0.734039306640625 +81113 0.649444580078125 +81114 0.800140380859375 +81115 0.708221435546875 +81116 0.7783203125 +81117 0.68902587890625 +81118 0.6651611328125 +81119 0.588836669921875 +81120 0.45965576171875 +81121 0.40673828125 +81122 0.199188232421875 +81123 0.1759033203125 +81124 -0.050689697265625 +81125 -0.04547119140625 +81126 -0.23297119140625 +81127 -0.206817626953125 +81128 -0.33013916015625 +81129 -0.292633056640625 +81130 -0.368408203125 +81131 -0.326171875 +81132 -0.378936767578125 +81133 -0.335113525390625 +81134 -0.376983642578125 +81135 -0.333038330078125 +81136 -0.37969970703125 +81137 -0.335205078125 +81138 -0.391510009765625 +81139 -0.345550537109375 +81140 -0.385345458984375 +81141 -0.340057373046875 +81142 -0.3419189453125 +81143 -0.301605224609375 +81144 -0.28289794921875 +81145 -0.249420166015625 +81146 -0.251617431640625 +81147 -0.221954345703125 +81148 -0.266143798828125 +81149 -0.235198974609375 +81150 -0.273345947265625 +81151 -0.24200439453125 +81152 -0.216796875 +81153 -0.192352294921875 +81154 -0.128265380859375 +81155 -0.114166259765625 +81156 -0.068145751953125 +81157 -0.060089111328125 +81158 -0.0430908203125 +81159 -0.03594970703125 +81160 -0.024444580078125 +81161 -0.01739501953125 +81162 0.020721435546875 +81163 0.023651123046875 +81164 0.124481201171875 +81165 0.114501953125 +81166 0.25787353515625 +81167 0.230224609375 +81168 0.379119873046875 +81169 0.334991455078125 +81170 0.47991943359375 +81171 0.421661376953125 +81172 0.5281982421875 +81173 0.4627685546875 +81174 0.511138916015625 +81175 0.447357177734375 +81176 0.456207275390625 +81177 0.399017333984375 +81178 0.407470703125 +81179 0.355560302734375 +81180 0.383758544921875 +81181 0.333221435546875 +81182 0.35687255859375 +81183 0.307952880859375 +81184 0.31182861328125 +81185 0.267059326171875 +81186 0.250885009765625 +81187 0.212615966796875 +81188 0.1654052734375 +81189 0.137359619140625 +81190 0.035247802734375 +81191 0.024139404296875 +81192 -0.142059326171875 +81193 -0.129058837890625 +81194 -0.33563232421875 +81195 -0.295745849609375 +81196 -0.5345458984375 +81197 -0.46649169921875 +81198 -0.72186279296875 +81199 -0.62677001953125 +81200 -0.836669921875 +81201 -0.7244873046875 +81202 -0.8326416015625 +81203 -0.72003173828125 +81204 -0.7296142578125 +81205 -0.6304931640625 +81206 -0.582550048828125 +81207 -0.502960205078125 +81208 -0.440093994140625 +81209 -0.379180908203125 +81210 -0.324310302734375 +81211 -0.278167724609375 +81212 -0.20147705078125 +81213 -0.171142578125 +81214 -0.044647216796875 +81215 -0.035125732421875 +81216 0.103973388671875 +81217 0.093658447265625 +81218 0.202392578125 +81219 0.179168701171875 +81220 0.264495849609375 +81221 0.233245849609375 +81222 0.338897705078125 +81223 0.2974853515625 +81224 0.443817138671875 +81225 0.387420654296875 +81226 0.545074462890625 +81227 0.47381591796875 +81228 0.6173095703125 +81229 0.53497314453125 +81230 0.6524658203125 +81231 0.564056396484375 +81232 0.66339111328125 +81233 0.572113037109375 +81234 0.6561279296875 +81235 0.56439208984375 +81236 0.606781005859375 +81237 0.520538330078125 +81238 0.501190185546875 +81239 0.42852783203125 +81240 0.352783203125 +81241 0.2999267578125 +81242 0.176544189453125 +81243 0.147674560546875 +81244 -0.034820556640625 +81245 -0.034423828125 +81246 -0.258209228515625 +81247 -0.226531982421875 +81248 -0.44244384765625 +81249 -0.384765625 +81250 -0.5753173828125 +81251 -0.4986572265625 +81252 -0.65203857421875 +81253 -0.56414794921875 +81254 -0.641632080078125 +81255 -0.55474853515625 +81256 -0.562164306640625 +81257 -0.485931396484375 +81258 -0.458038330078125 +81259 -0.395782470703125 +81260 -0.350555419921875 +81261 -0.302581787109375 +81262 -0.260528564453125 +81263 -0.224212646484375 +81264 -0.192108154296875 +81265 -0.164306640625 +81266 -0.141937255859375 +81267 -0.120086669921875 +81268 -0.1021728515625 +81269 -0.08489990234375 +81270 -0.062896728515625 +81271 -0.050323486328125 +81272 -0.011932373046875 +81273 -0.005950927734375 +81274 0.062835693359375 +81275 0.058563232421875 +81276 0.148712158203125 +81277 0.13232421875 +81278 0.241729736328125 +81279 0.2119140625 +81280 0.34912109375 +81281 0.30352783203125 +81282 0.457305908203125 +81283 0.395599365234375 +81284 0.54388427734375 +81285 0.46893310546875 +81286 0.5728759765625 +81287 0.492828369140625 +81288 0.506591796875 +81289 0.43505859375 +81290 0.351226806640625 +81291 0.300994873046875 +81292 0.146514892578125 +81293 0.12469482421875 +81294 -0.05523681640625 +81295 -0.048980712890625 +81296 -0.21624755859375 +81297 -0.18768310546875 +81298 -0.334930419921875 +81299 -0.289947509765625 +81300 -0.402984619140625 +81301 -0.348663330078125 +81302 -0.4412841796875 +81303 -0.381683349609375 +81304 -0.49578857421875 +81305 -0.428375244140625 +81306 -0.5601806640625 +81307 -0.483306884765625 +81308 -0.600738525390625 +81309 -0.51763916015625 +81310 -0.584228515625 +81311 -0.502960205078125 +81312 -0.47930908203125 +81313 -0.41241455078125 +81314 -0.27935791015625 +81315 -0.240447998046875 +81316 -0.0089111328125 +81317 -0.008087158203125 +81318 0.268798828125 +81319 0.23046875 +81320 0.482818603515625 +81321 0.41448974609375 +81322 0.60369873046875 +81323 0.518707275390625 +81324 0.650421142578125 +81325 0.559295654296875 +81326 0.66400146484375 +81327 0.57135009765625 +81328 0.6414794921875 +81329 0.55230712890625 +81330 0.572540283203125 +81331 0.49334716796875 +81332 0.498138427734375 +81333 0.429534912109375 +81334 0.439453125 +81335 0.378997802734375 +81336 0.375518798828125 +81337 0.323822021484375 +81338 0.274505615234375 +81339 0.236785888671875 +81340 0.1087646484375 +81341 0.09423828125 +81342 -0.099395751953125 +81343 -0.084686279296875 +81344 -0.3182373046875 +81345 -0.272735595703125 +81346 -0.5489501953125 +81347 -0.470916748046875 +81348 -0.7738037109375 +81349 -0.663970947265625 +81350 -0.86383056640625 +81351 -0.806549072265625 +81352 -0.870391845703125 +81353 -0.856231689453125 +81354 -0.86895751953125 +81355 -0.856201171875 +81356 -0.861053466796875 +81357 -0.81732177734375 +81358 -0.765869140625 +81359 -0.697235107421875 +81360 -0.5301513671875 +81361 -0.5001220703125 +81362 -0.214691162109375 +81363 -0.23211669921875 +81364 0.137359619140625 +81365 0.069915771484375 +81366 0.474822998046875 +81367 0.36199951171875 +81368 0.76239013671875 +81369 0.613677978515625 +81370 0.867462158203125 +81371 0.801849365234375 +81372 0.870361328125 +81373 0.86236572265625 +81374 0.86480712890625 +81375 0.8680419921875 +81376 0.831817626953125 +81377 0.8662109375 +81378 0.677581787109375 +81379 0.85919189453125 +81380 0.495880126953125 +81381 0.790435791015625 +81382 0.30767822265625 +81383 0.6563720703125 +81384 0.116180419921875 +81385 0.497283935546875 +81386 -0.110748291015625 +81387 0.286041259765625 +81388 -0.381805419921875 +81389 0.016754150390625 +81390 -0.6572265625 +81391 -0.27392578125 +81392 -0.857421875 +81393 -0.534698486328125 +81394 -0.870391845703125 +81395 -0.728790283203125 +81396 -0.870391845703125 +81397 -0.850006103515625 +81398 -0.86444091796875 +81399 -0.86181640625 +81400 -0.85723876953125 +81401 -0.86749267578125 +81402 -0.790008544921875 +81403 -0.86932373046875 +81404 -0.62847900390625 +81405 -0.862274169921875 +81406 -0.3956298828125 +81407 -0.776763916015625 +81408 -0.126708984375 +81409 -0.5716552734375 +81410 0.150115966796875 +81411 -0.333831787109375 +81412 0.424041748046875 +81413 -0.073638916015625 +81414 0.670623779296875 +81415 0.186065673828125 +81416 0.854522705078125 +81417 0.4127197265625 +81418 0.866485595703125 +81419 0.59124755859375 +81420 0.86920166015625 +81421 0.708526611328125 +81422 0.8653564453125 +81423 0.779205322265625 +81424 0.857147216796875 +81425 0.81414794921875 +81426 0.766845703125 +81427 0.81085205078125 +81428 0.628509521484375 +81429 0.773590087890625 +81430 0.462127685546875 +81431 0.696990966796875 +81432 0.297210693359375 +81433 0.602569580078125 +81434 0.14862060546875 +81435 0.5008544921875 +81436 -0.00537109375 +81437 0.373443603515625 +81438 -0.15753173828125 +81439 0.2269287109375 +81440 -0.31304931640625 +81441 0.05877685546875 +81442 -0.48876953125 +81443 -0.142120361328125 +81444 -0.6416015625 +81445 -0.33673095703125 +81446 -0.751373291015625 +81447 -0.50433349609375 +81448 -0.84619140625 +81449 -0.663665771484375 +81450 -0.861297607421875 +81451 -0.802398681640625 +81452 -0.863250732421875 +81453 -0.858734130859375 +81454 -0.856597900390625 +81455 -0.86053466796875 +81456 -0.7498779296875 +81457 -0.855377197265625 +81458 -0.624542236328125 +81459 -0.798858642578125 +81460 -0.47808837890625 +81461 -0.701324462890625 +81462 -0.253387451171875 +81463 -0.521881103515625 +81464 0.003692626953125 +81465 -0.2984619140625 +81466 0.2257080078125 +81467 -0.087799072265625 +81468 0.427154541015625 +81469 0.12005615234375 +81470 0.643218994140625 +81471 0.351409912109375 +81472 0.855926513671875 +81473 0.59796142578125 +81474 0.870361328125 +81475 0.8116455078125 +81476 0.870361328125 +81477 0.86505126953125 +81478 0.862762451171875 +81479 0.870361328125 +81480 0.79669189453125 +81481 0.868133544921875 +81482 0.595794677734375 +81483 0.857696533203125 +81484 0.362152099609375 +81485 0.737945556640625 +81486 0.1270751953125 +81487 0.56536865234375 +81488 -0.086944580078125 +81489 0.3843994140625 +81490 -0.2784423828125 +81491 0.197235107421875 +81492 -0.484832763671875 +81493 -0.024627685546875 +81494 -0.729583740234375 +81495 -0.297027587890625 +81496 -0.86688232421875 +81497 -0.578582763671875 +81498 -0.870391845703125 +81499 -0.817596435546875 +81500 -0.86859130859375 +81501 -0.870391845703125 +81502 -0.86279296875 +81503 -0.870391845703125 +81504 -0.817962646484375 +81505 -0.863525390625 +81506 -0.6116943359375 +81507 -0.78167724609375 +81508 -0.3128662109375 +81509 -0.534423828125 +81510 0.039398193359375 +81511 -0.228057861328125 +81512 0.422821044921875 +81513 0.11773681640625 +81514 0.805145263671875 +81515 0.47430419921875 +81516 0.870361328125 +81517 0.786285400390625 +81518 0.870361328125 +81519 0.870361328125 +81520 0.860015869140625 +81521 0.870361328125 +81522 0.727935791015625 +81523 0.861175537109375 +81524 0.48114013671875 +81525 0.755401611328125 +81526 0.2059326171875 +81527 0.55078125 +81528 -0.06103515625 +81529 0.33154296875 +81530 -0.29913330078125 +81531 0.115203857421875 +81532 -0.516204833984375 +81533 -0.10296630859375 +81534 -0.7252197265625 +81535 -0.3309326171875 +81536 -0.85980224609375 +81537 -0.546051025390625 +81538 -0.870391845703125 +81539 -0.72052001953125 +81540 -0.870391845703125 +81541 -0.833038330078125 +81542 -0.858062744140625 +81543 -0.848785400390625 +81544 -0.673004150390625 +81545 -0.77154541015625 +81546 -0.42694091796875 +81547 -0.653289794921875 +81548 -0.2100830078125 +81549 -0.540252685546875 +81550 -0.0362548828125 +81551 -0.440765380859375 +81552 0.10943603515625 +81553 -0.340789794921875 +81554 0.23516845703125 +81555 -0.233184814453125 +81556 0.373687744140625 +81557 -0.091888427734375 +81558 0.517791748046875 +81559 0.07501220703125 +81560 0.602783203125 +81561 0.21099853515625 +81562 0.635711669921875 +81563 0.317779541015625 +81564 0.655181884765625 +81565 0.42242431640625 +81566 0.65948486328125 +81567 0.5184326171875 +81568 0.651275634765625 +81569 0.602813720703125 +81570 0.61846923828125 +81571 0.66070556640625 +81572 0.53753662109375 +81573 0.668243408203125 +81574 0.404144287109375 +81575 0.618133544921875 +81576 0.22186279296875 +81577 0.510498046875 +81578 0.003997802734375 +81579 0.354461669921875 +81580 -0.22100830078125 +81581 0.172698974609375 +81582 -0.42449951171875 +81583 -0.010772705078125 +81584 -0.579833984375 +81585 -0.172576904296875 +81586 -0.641876220703125 +81587 -0.273193359375 +81588 -0.6177978515625 +81589 -0.315338134765625 +81590 -0.575531005859375 +81591 -0.35125732421875 +81592 -0.526336669921875 +81593 -0.386138916015625 +81594 -0.42645263671875 +81595 -0.37969970703125 +81596 -0.2581787109375 +81597 -0.31317138671875 +81598 -0.068695068359375 +81599 -0.22161865234375 +81600 0.09222412109375 +81601 -0.142730712890625 +81602 0.232147216796875 +81603 -0.067657470703125 +81604 0.3509521484375 +81605 0.005279541015625 +81606 0.410064697265625 +81607 0.045196533203125 +81608 0.372955322265625 +81609 0.02203369140625 +81610 0.2554931640625 +81611 -0.05194091796875 +81612 0.10711669921875 +81613 -0.1376953125 +81614 -0.052886962890625 +81615 -0.221771240234375 +81616 -0.186279296875 +81617 -0.27557373046875 +81618 -0.23291015625 +81619 -0.25286865234375 +81620 -0.209442138671875 +81621 -0.17083740234375 +81622 -0.174163818359375 +81623 -0.080963134765625 +81624 -0.126739501953125 +81625 0.01373291015625 +81626 -0.048126220703125 +81627 0.12603759765625 +81628 0.0426025390625 +81629 0.2379150390625 +81630 0.10748291015625 +81631 0.316375732421875 +81632 0.1409912109375 +81633 0.3558349609375 +81634 0.19708251953125 +81635 0.400482177734375 +81636 0.273651123046875 +81637 0.4490966796875 +81638 0.31768798828125 +81639 0.459136962890625 +81640 0.341094970703125 +81641 0.442169189453125 +81642 0.368011474609375 +81643 0.42034912109375 +81644 0.37249755859375 +81645 0.37493896484375 +81646 0.30072021484375 +81647 0.264373779296875 +81648 0.1517333984375 +81649 0.09075927734375 +81650 -0.01470947265625 +81651 -0.09393310546875 +81652 -0.1883544921875 +81653 -0.27874755859375 +81654 -0.372711181640625 +81655 -0.464447021484375 +81656 -0.51397705078125 +81657 -0.6051025390625 +81658 -0.57177734375 +81659 -0.666351318359375 +81660 -0.53948974609375 +81661 -0.642333984375 +81662 -0.43511962890625 +81663 -0.548065185546875 +81664 -0.2962646484375 +81665 -0.415557861328125 +81666 -0.161102294921875 +81667 -0.277679443359375 +81668 -0.0435791015625 +81669 -0.1474609375 +81670 0.060394287109375 +81671 -0.0235595703125 +81672 0.13665771484375 +81673 0.080596923828125 +81674 0.170135498046875 +81675 0.150726318359375 +81676 0.16552734375 +81677 0.188323974609375 +81678 0.15728759765625 +81679 0.218841552734375 +81680 0.150787353515625 +81681 0.244720458984375 +81682 0.12200927734375 +81683 0.2452392578125 +81684 0.080108642578125 +81685 0.226654052734375 +81686 0.05126953125 +81687 0.209320068359375 +81688 0.062896728515625 +81689 0.21514892578125 +81690 0.09271240234375 +81691 0.226715087890625 +81692 0.092987060546875 +81693 0.206756591796875 +81694 0.07855224609375 +81695 0.16845703125 +81696 0.06427001953125 +81697 0.125335693359375 +81698 0.0347900390625 +81699 0.06695556640625 +81700 -0.01171875 +81701 -0.006195068359375 +81702 -0.056060791015625 +81703 -0.07672119140625 +81704 -0.055511474609375 +81705 -0.108551025390625 +81706 -0.010467529296875 +81707 -0.100341796875 +81708 0.02508544921875 +81709 -0.0938720703125 +81710 0.025665283203125 +81711 -0.1085205078125 +81712 0.017333984375 +81713 -0.122802734375 +81714 0.00189208984375 +81715 -0.135101318359375 +81716 -0.03173828125 +81717 -0.15447998046875 +81718 -0.071502685546875 +81719 -0.171966552734375 +81720 -0.13543701171875 +81721 -0.20294189453125 +81722 -0.219970703125 +81723 -0.245819091796875 +81724 -0.300506591796875 +81725 -0.28240966796875 +81726 -0.376312255859375 +81727 -0.313720703125 +81728 -0.416107177734375 +81729 -0.31634521484375 +81730 -0.371124267578125 +81731 -0.25286865234375 +81732 -0.242279052734375 +81733 -0.125457763671875 +81734 -0.069732666015625 +81735 0.032470703125 +81736 0.125640869140625 +81737 0.2032470703125 +81738 0.31268310546875 +81739 0.361328125 +81740 0.45501708984375 +81741 0.47735595703125 +81742 0.554779052734375 +81743 0.553070068359375 +81744 0.61065673828125 +81745 0.58782958984375 +81746 0.610931396484375 +81747 0.572967529296875 +81748 0.531463623046875 +81749 0.49017333984375 +81750 0.3883056640625 +81751 0.353424072265625 +81752 0.23468017578125 +81753 0.206634521484375 +81754 0.095245361328125 +81755 0.07086181640625 +81756 -0.00396728515625 +81757 -0.03173828125 +81758 -0.04852294921875 +81759 -0.088409423828125 +81760 -0.055145263671875 +81761 -0.11138916015625 +81762 -0.0758056640625 +81763 -0.14141845703125 +81764 -0.138702392578125 +81765 -0.200439453125 +81766 -0.209197998046875 +81767 -0.260406494140625 +81768 -0.289031982421875 +81769 -0.322662353515625 +81770 -0.37884521484375 +81771 -0.387969970703125 +81772 -0.456329345703125 +81773 -0.43896484375 +81774 -0.51641845703125 +81775 -0.472320556640625 +81776 -0.519287109375 +81777 -0.45709228515625 +81778 -0.458251953125 +81779 -0.38897705078125 +81780 -0.384796142578125 +81781 -0.31024169921875 +81782 -0.323699951171875 +81783 -0.241851806640625 +81784 -0.269287109375 +81785 -0.180267333984375 +81786 -0.1951904296875 +81787 -0.105377197265625 +81788 -0.100006103515625 +81789 -0.016815185546875 +81790 -0.01055908203125 +81791 0.063323974609375 +81792 0.1033935546875 +81793 0.158905029296875 +81794 0.24908447265625 +81795 0.275604248046875 +81796 0.373199462890625 +81797 0.370880126953125 +81798 0.45806884765625 +81799 0.430938720703125 +81800 0.511474609375 +81801 0.4625244140625 +81802 0.565399169921875 +81803 0.491973876953125 +81804 0.61138916015625 +81805 0.5133056640625 +81806 0.5897216796875 +81807 0.479644775390625 +81808 0.4906005859375 +81809 0.384033203125 +81810 0.33148193359375 +81811 0.241363525390625 +81812 0.147796630859375 +81813 0.080780029296875 +81814 -0.01873779296875 +81815 -0.06365966796875 +81816 -0.140289306640625 +81817 -0.169158935546875 +81818 -0.191986083984375 +81819 -0.215423583984375 +81820 -0.184295654296875 +81821 -0.210662841796875 +81822 -0.161834716796875 +81823 -0.19061279296875 +81824 -0.166595458984375 +81825 -0.189056396484375 +81826 -0.19390869140625 +81827 -0.20263671875 +81828 -0.22442626953125 +81829 -0.216400146484375 +81830 -0.279754638671875 +81831 -0.248291015625 +81832 -0.3389892578125 +81833 -0.282318115234375 +81834 -0.3543701171875 +81835 -0.28106689453125 +81836 -0.348175048828125 +81837 -0.2630615234375 +81838 -0.32598876953125 +81839 -0.23345947265625 +81840 -0.2581787109375 +81841 -0.169189453125 +81842 -0.139801025390625 +81843 -0.066802978515625 +81844 0.014617919921875 +81845 0.061767578125 +81846 0.144378662109375 +81847 0.167694091796875 +81848 0.221038818359375 +81849 0.228240966796875 +81850 0.27069091796875 +81851 0.264404296875 +81852 0.294036865234375 +81853 0.277008056640625 +81854 0.311767578125 +81855 0.28302001953125 +81856 0.339141845703125 +81857 0.295135498046875 +81858 0.360260009765625 +81859 0.301116943359375 +81860 0.360504150390625 +81861 0.2899169921875 +81862 0.308380126953125 +81863 0.23724365234375 +81864 0.18170166015625 +81865 0.12615966796875 +81866 0.0047607421875 +81867 -0.0234375 +81868 -0.17559814453125 +81869 -0.173980712890625 +81870 -0.3143310546875 +81871 -0.289398193359375 +81872 -0.36785888671875 +81873 -0.3349609375 +81874 -0.36248779296875 +81875 -0.331390380859375 +81876 -0.343536376953125 +81877 -0.314605712890625 +81878 -0.3018798828125 +81879 -0.277557373046875 +81880 -0.231414794921875 +81881 -0.2156982421875 +81882 -0.117645263671875 +81883 -0.117919921875 +81884 0.007049560546875 +81885 -0.01031494140625 +81886 0.087982177734375 +81887 0.063262939453125 +81888 0.13946533203125 +81889 0.11358642578125 +81890 0.17425537109375 +81891 0.150238037109375 +81892 0.188201904296875 +81893 0.169464111328125 +81894 0.171234130859375 +81895 0.162841796875 +81896 0.118438720703125 +81897 0.126190185546875 +81898 0.05706787109375 +81899 0.080841064453125 +81900 -0.010711669921875 +81901 0.0283203125 +81902 -0.0914306640625 +81903 -0.036468505859375 +81904 -0.162322998046875 +81905 -0.09539794921875 +81906 -0.194549560546875 +81907 -0.125457763671875 +81908 -0.1492919921875 +81909 -0.095611572265625 +81910 -0.02166748046875 +81911 -0.0015869140625 +81912 0.124053955078125 +81913 0.106109619140625 +81914 0.211151123046875 +81915 0.16717529296875 +81916 0.240447998046875 +81917 0.182708740234375 +81918 0.242218017578125 +81919 0.17706298828125 +81920 0.2257080078125 +81921 0.157440185546875 +81922 0.194366455078125 +81923 0.12713623046875 +81924 0.115509033203125 +81925 0.062164306640625 +81926 0.0128173828125 +81927 -0.01922607421875 +81928 -0.053802490234375 +81929 -0.071380615234375 +81930 -0.110626220703125 +81931 -0.1142578125 +81932 -0.199493408203125 +81933 -0.179779052734375 +81934 -0.29437255859375 +81935 -0.248321533203125 +81936 -0.33221435546875 +81937 -0.272216796875 +81938 -0.27972412109375 +81939 -0.22650146484375 +81940 -0.185333251953125 +81941 -0.148345947265625 +81942 -0.128204345703125 +81943 -0.0982666015625 +81944 -0.115692138671875 +81945 -0.08221435546875 +81946 -0.116455078125 +81947 -0.07672119140625 +81948 -0.105926513671875 +81949 -0.0634765625 +81950 -0.053955078125 +81951 -0.01983642578125 +81952 0.048797607421875 +81953 0.06109619140625 +81954 0.157318115234375 +81955 0.145050048828125 +81956 0.212005615234375 +81957 0.1866455078125 +81958 0.218475341796875 +81959 0.190185546875 +81960 0.23724365234375 +81961 0.201812744140625 +81962 0.30535888671875 +81963 0.2498779296875 +81964 0.38128662109375 +81965 0.303009033203125 +81966 0.404449462890625 +81967 0.315399169921875 +81968 0.3944091796875 +81969 0.302276611328125 +81970 0.3885498046875 +81971 0.292327880859375 +81972 0.362640380859375 +81973 0.2674560546875 +81974 0.27362060546875 +81975 0.195220947265625 +81976 0.11712646484375 +81977 0.072540283203125 +81978 -0.054901123046875 +81979 -0.0609130859375 +81980 -0.19085693359375 +81981 -0.165802001953125 +81982 -0.28570556640625 +81983 -0.238250732421875 +81984 -0.339263916015625 +81985 -0.278167724609375 +81986 -0.3775634765625 +81987 -0.305389404296875 +81988 -0.445709228515625 +81989 -0.354339599609375 +81990 -0.535064697265625 +81991 -0.41864013671875 +81992 -0.629058837890625 +81993 -0.48590087890625 +81994 -0.697601318359375 +81995 -0.53350830078125 +81996 -0.70391845703125 +81997 -0.53375244140625 +81998 -0.6424560546875 +81999 -0.482666015625 +82000 -0.491241455078125 +82001 -0.36376953125 +82002 -0.265716552734375 +82003 -0.188995361328125 +82004 -0.023712158203125 +82005 -0.002471923828125 +82006 0.201751708984375 +82007 0.170562744140625 +82008 0.375823974609375 +82009 0.303558349609375 +82010 0.485076904296875 +82011 0.38629150390625 +82012 0.56884765625 +82013 0.448699951171875 +82014 0.634765625 +82015 0.496673583984375 +82016 0.63763427734375 +82017 0.49603271484375 +82018 0.5660400390625 +82019 0.438232421875 +82020 0.4720458984375 +82021 0.363037109375 +82022 0.40692138671875 +82023 0.30963134765625 +82024 0.3778076171875 +82025 0.28369140625 +82026 0.376953125 +82027 0.279510498046875 +82028 0.371978759765625 +82029 0.272674560546875 +82030 0.313140869140625 +82031 0.225555419921875 +82032 0.184417724609375 +82033 0.126068115234375 +82034 0.011199951171875 +82035 -0.006378173828125 +82036 -0.171051025390625 +82037 -0.14483642578125 +82038 -0.33740234375 +82039 -0.2703857421875 +82040 -0.47198486328125 +82041 -0.37103271484375 +82042 -0.560394287109375 +82043 -0.43597412109375 +82044 -0.58056640625 +82045 -0.448577880859375 +82046 -0.54754638671875 +82047 -0.420440673828125 +82048 -0.508575439453125 +82049 -0.38763427734375 +82050 -0.459503173828125 +82051 -0.34716796875 +82052 -0.394378662109375 +82053 -0.294708251953125 +82054 -0.35260009765625 +82055 -0.260345458984375 +82056 -0.31170654296875 +82057 -0.227142333984375 +82058 -0.197418212890625 +82059 -0.13873291015625 +82060 -0.007965087890625 +82061 0.006134033203125 +82062 0.207489013671875 +82063 0.1700439453125 +82064 0.409210205078125 +82065 0.32281494140625 +82066 0.57208251953125 +82067 0.4454345703125 +82068 0.66595458984375 +82069 0.51507568359375 +82070 0.65875244140625 +82071 0.5074462890625 +82072 0.56744384765625 +82073 0.435577392578125 +82074 0.431396484375 +82075 0.32952880859375 +82076 0.29443359375 +82077 0.2227783203125 +82078 0.182464599609375 +82079 0.135162353515625 +82080 0.06365966796875 +82081 0.0426025390625 +82082 -0.075958251953125 +82083 -0.06536865234375 +82084 -0.189422607421875 +82085 -0.152984619140625 +82086 -0.271942138671875 +82087 -0.216552734375 +82088 -0.342529296875 +82089 -0.270477294921875 +82090 -0.364166259765625 +82091 -0.286651611328125 +82092 -0.327239990234375 +82093 -0.257781982421875 +82094 -0.2769775390625 +82095 -0.218292236328125 +82096 -0.253692626953125 +82097 -0.19891357421875 +82098 -0.24365234375 +82099 -0.189300537109375 +82100 -0.1983642578125 +82101 -0.152740478515625 +82102 -0.116241455078125 +82103 -0.088134765625 +82104 -0.036834716796875 +82105 -0.025634765625 +82106 0.034881591796875 +82107 0.03082275390625 +82108 0.09124755859375 +82109 0.0753173828125 +82110 0.10888671875 +82111 0.089996337890625 +82112 0.125518798828125 +82113 0.10345458984375 +82114 0.15771484375 +82115 0.1282958984375 +82116 0.17828369140625 +82117 0.143829345703125 +82118 0.17108154296875 +82119 0.137786865234375 +82120 0.129974365234375 +82121 0.105560302734375 +82122 0.082427978515625 +82123 0.068084716796875 +82124 0.027679443359375 +82125 0.02490234375 +82126 -0.065643310546875 +82127 -0.0477294921875 +82128 -0.15936279296875 +82129 -0.1207275390625 +82130 -0.21307373046875 +82131 -0.16326904296875 +82132 -0.234649658203125 +82133 -0.1812744140625 +82134 -0.2001953125 +82135 -0.156463623046875 +82136 -0.119171142578125 +82137 -0.095977783203125 +82138 -0.024749755859375 +82139 -0.024993896484375 +82140 0.085784912109375 +82141 0.05859375 +82142 0.178131103515625 +82143 0.12872314453125 +82144 0.215576171875 +82145 0.157501220703125 +82146 0.211456298828125 +82147 0.154998779296875 +82148 0.17523193359375 +82149 0.128387451171875 +82150 0.128753662109375 +82151 0.094207763671875 +82152 0.1019287109375 +82153 0.07513427734375 +82154 0.0743408203125 +82155 0.05560302734375 +82156 0.04327392578125 +82157 0.033416748046875 +82158 0.038177490234375 +82159 0.030914306640625 +82160 0.076263427734375 +82161 0.06109619140625 +82162 0.14105224609375 +82163 0.11138916015625 +82164 0.186431884765625 +82165 0.14666748046875 +82166 0.188812255859375 +82167 0.148956298828125 +82168 0.1390380859375 +82169 0.111297607421875 +82170 0.041778564453125 +82171 0.0372314453125 +82172 -0.079437255859375 +82173 -0.0552978515625 +82174 -0.219390869140625 +82175 -0.162322998046875 +82176 -0.367828369140625 +82177 -0.275665283203125 +82178 -0.494873046875 +82179 -0.372161865234375 +82180 -0.556243896484375 +82181 -0.41900634765625 +82182 -0.508697509765625 +82183 -0.38494873046875 +82184 -0.3756103515625 +82185 -0.287261962890625 +82186 -0.218902587890625 +82187 -0.17132568359375 +82188 -0.063751220703125 +82189 -0.05572509765625 +82190 0.091552734375 +82191 0.060455322265625 +82192 0.23602294921875 +82193 0.168975830078125 +82194 0.342987060546875 +82195 0.25018310546875 +82196 0.39520263671875 +82197 0.29132080078125 +82198 0.389373779296875 +82199 0.289825439453125 +82200 0.324249267578125 +82201 0.244659423828125 +82202 0.224090576171875 +82203 0.173370361328125 +82204 0.124267578125 +82205 0.101654052734375 +82206 0.037078857421875 +82207 0.038421630859375 +82208 -0.010101318359375 +82209 0.003631591796875 +82210 -0.019439697265625 +82211 -0.00421142578125 +82212 -0.022796630859375 +82213 -0.008209228515625 +82214 -0.001556396484375 +82215 0.0052490234375 +82216 0.056304931640625 +82217 0.0450439453125 +82218 0.106719970703125 +82219 0.079254150390625 +82220 0.096893310546875 +82221 0.069610595703125 +82222 0.042694091796875 +82223 0.027801513671875 +82224 -0.018035888671875 +82225 -0.01849365234375 +82226 -0.07586669921875 +82227 -0.06231689453125 +82228 -0.11944580078125 +82229 -0.095306396484375 +82230 -0.15972900390625 +82231 -0.12542724609375 +82232 -0.202606201171875 +82233 -0.15692138671875 +82234 -0.24859619140625 +82235 -0.19012451171875 +82236 -0.30517578125 +82237 -0.23052978515625 +82238 -0.36212158203125 +82239 -0.270751953125 +82240 -0.39141845703125 +82241 -0.290496826171875 +82242 -0.35528564453125 +82243 -0.2623291015625 +82244 -0.249969482421875 +82245 -0.18365478515625 +82246 -0.092864990234375 +82247 -0.067230224609375 +82248 0.08905029296875 +82249 0.067169189453125 +82250 0.2352294921875 +82251 0.175384521484375 +82252 0.318817138671875 +82253 0.237762451171875 +82254 0.358642578125 +82255 0.267913818359375 +82256 0.347747802734375 +82257 0.2607421875 +82258 0.28564453125 +82259 0.215850830078125 +82260 0.223175048828125 +82261 0.170257568359375 +82262 0.196746826171875 +82263 0.15045166015625 +82264 0.179840087890625 +82265 0.137237548828125 +82266 0.155548095703125 +82267 0.118316650390625 +82268 0.151214599609375 +82269 0.11370849609375 +82270 0.156951904296875 +82271 0.116302490234375 +82272 0.13177490234375 +82273 0.0963134765625 +82274 0.100799560546875 +82275 0.0721435546875 +82276 0.087127685546875 +82277 0.060638427734375 +82278 0.05487060546875 +82279 0.035797119140625 +82280 -0.009002685546875 +82281 -0.01177978515625 +82282 -0.10400390625 +82283 -0.081695556640625 +82284 -0.229400634765625 +82285 -0.173370361328125 +82286 -0.35552978515625 +82287 -0.26519775390625 +82288 -0.441925048828125 +82289 -0.327728271484375 +82290 -0.473846435546875 +82291 -0.350311279296875 +82292 -0.464813232421875 +82293 -0.342803955078125 +82294 -0.419097900390625 +82295 -0.308349609375 +82296 -0.334320068359375 +82297 -0.245269775390625 +82298 -0.227935791015625 +82299 -0.1663818359375 +82300 -0.12347412109375 +82301 -0.088897705078125 +82302 -0.02764892578125 +82303 -0.01776123046875 +82304 0.077667236328125 +82305 0.060150146484375 +82306 0.2132568359375 +82307 0.159881591796875 +82308 0.38885498046875 +82309 0.2884521484375 +82310 0.582794189453125 +82311 0.4300537109375 +82312 0.734039306640625 +82313 0.54022216796875 +82314 0.800140380859375 +82315 0.58807373046875 +82316 0.7783203125 +82317 0.57159423828125 +82318 0.6651611328125 +82319 0.488372802734375 +82320 0.45965576171875 +82321 0.337738037109375 +82322 0.199188232421875 +82323 0.146942138671875 +82324 -0.050689697265625 +82325 -0.03619384765625 +82326 -0.23297119140625 +82327 -0.17010498046875 +82328 -0.33013916015625 +82329 -0.24200439453125 +82330 -0.368408203125 +82331 -0.2708740234375 +82332 -0.378936767578125 +82333 -0.279327392578125 +82334 -0.376983642578125 +82335 -0.278472900390625 +82336 -0.37969970703125 +82337 -0.280792236328125 +82338 -0.391510009765625 +82339 -0.28948974609375 +82340 -0.385345458984375 +82341 -0.28485107421875 +82342 -0.3419189453125 +82343 -0.252838134765625 +82344 -0.28289794921875 +82345 -0.209228515625 +82346 -0.251617431640625 +82347 -0.185638427734375 +82348 -0.266143798828125 +82349 -0.195281982421875 +82350 -0.273345947265625 +82351 -0.199554443359375 +82352 -0.216796875 +82353 -0.15740966796875 +82354 -0.128265380859375 +82355 -0.092010498046875 +82356 -0.068145751953125 +82357 -0.047393798828125 +82358 -0.0430908203125 +82359 -0.0284423828125 +82360 -0.024444580078125 +82361 -0.014312744140625 +82362 0.020721435546875 +82363 0.018951416015625 +82364 0.124481201171875 +82365 0.094635009765625 +82366 0.25787353515625 +82367 0.191650390625 +82368 0.379119873046875 +82369 0.27960205078125 +82370 0.47991943359375 +82371 0.35247802734375 +82372 0.5281982421875 +82373 0.386962890625 +82374 0.511138916015625 +82375 0.373779296875 +82376 0.456207275390625 +82377 0.332977294921875 +82378 0.407470703125 +82379 0.29669189453125 +82380 0.383758544921875 +82381 0.278656005859375 +82382 0.35687255859375 +82383 0.258392333984375 +82384 0.31182861328125 +82385 0.2249755859375 +82386 0.250885009765625 +82387 0.18011474609375 +82388 0.1654052734375 +82389 0.117523193359375 +82390 0.035247802734375 +82391 0.0225830078125 +82392 -0.142059326171875 +82393 -0.10650634765625 +82394 -0.33563232421875 +82395 -0.24725341796875 +82396 -0.5345458984375 +82397 -0.3917236328125 +82398 -0.72186279296875 +82399 -0.527587890625 +82400 -0.836669921875 +82401 -0.61053466796875 +82402 -0.8326416015625 +82403 -0.606903076171875 +82404 -0.7296142578125 +82405 -0.531158447265625 +82406 -0.582550048828125 +82407 -0.423370361328125 +82408 -0.440093994140625 +82409 -0.3189697265625 +82410 -0.324310302734375 +82411 -0.234100341796875 +82412 -0.20147705078125 +82413 -0.14422607421875 +82414 -0.044647216796875 +82415 -0.02972412109375 +82416 0.103973388671875 +82417 0.078643798828125 +82418 0.202392578125 +82419 0.150299072265625 +82420 0.264495849609375 +82421 0.195343017578125 +82422 0.338897705078125 +82423 0.249176025390625 +82424 0.443817138671875 +82425 0.3250732421875 +82426 0.545074462890625 +82427 0.398223876953125 +82428 0.6173095703125 +82429 0.4501953125 +82430 0.6524658203125 +82431 0.47515869140625 +82432 0.66339111328125 +82433 0.482147216796875 +82434 0.6561279296875 +82435 0.47540283203125 +82436 0.606781005859375 +82437 0.438232421875 +82438 0.501190185546875 +82439 0.3609619140625 +82440 0.352783203125 +82441 0.253143310546875 +82442 0.176544189453125 +82443 0.125518798828125 +82444 -0.034820556640625 +82445 -0.02667236328125 +82446 -0.258209228515625 +82447 -0.187042236328125 +82448 -0.44244384765625 +82449 -0.3197021484375 +82450 -0.5753173828125 +82451 -0.415863037109375 +82452 -0.65203857421875 +82453 -0.47198486328125 +82454 -0.641632080078125 +82455 -0.4664306640625 +82456 -0.562164306640625 +82457 -0.41168212890625 +82458 -0.458038330078125 +82459 -0.338653564453125 +82460 -0.350555419921875 +82461 -0.26220703125 +82462 -0.260528564453125 +82463 -0.19696044921875 +82464 -0.192108154296875 +82465 -0.145965576171875 +82466 -0.141937255859375 +82467 -0.107086181640625 +82468 -0.1021728515625 +82469 -0.075103759765625 +82470 -0.062896728515625 +82471 -0.0433349609375 +82472 -0.011932373046875 +82473 -0.003570556640625 +82474 0.062835693359375 +82475 0.052398681640625 +82476 0.148712158203125 +82477 0.11553955078125 +82478 0.241729736328125 +82479 0.182861328125 +82480 0.34912109375 +82481 0.259307861328125 +82482 0.457305908203125 +82483 0.33538818359375 +82484 0.54388427734375 +82485 0.395477294921875 +82486 0.5728759765625 +82487 0.41461181640625 +82488 0.506591796875 +82489 0.366607666015625 +82490 0.351226806640625 +82491 0.255889892578125 +82492 0.146514892578125 +82493 0.11029052734375 +82494 -0.05523681640625 +82495 -0.033599853515625 +82496 -0.21624755859375 +82497 -0.1492919921875 +82498 -0.334930419921875 +82499 -0.235443115234375 +82500 -0.402984619140625 +82501 -0.286102294921875 +82502 -0.4412841796875 +82503 -0.315643310546875 +82504 -0.49578857421875 +82505 -0.35589599609375 +82506 -0.5601806640625 +82507 -0.402374267578125 +82508 -0.600738525390625 +82509 -0.4315185546875 +82510 -0.584228515625 +82511 -0.420196533203125 +82512 -0.47930908203125 +82513 -0.3465576171875 +82514 -0.27935791015625 +82515 -0.206085205078125 +82516 -0.0089111328125 +82517 -0.01593017578125 +82518 0.268798828125 +82519 0.17974853515625 +82520 0.482818603515625 +82521 0.331451416015625 +82522 0.60369873046875 +82523 0.41851806640625 +82524 0.650421142578125 +82525 0.453948974609375 +82526 0.66400146484375 +82527 0.466156005859375 +82528 0.6414794921875 +82529 0.45294189453125 +82530 0.572540283203125 +82531 0.406982421875 +82532 0.498138427734375 +82533 0.356689453125 +82534 0.439453125 +82535 0.316741943359375 +82536 0.375518798828125 +82537 0.27252197265625 +82538 0.274505615234375 +82539 0.201873779296875 +82540 0.1087646484375 +82541 0.085601806640625 +82542 -0.099395751953125 +82543 -0.060699462890625 +82544 -0.3182373046875 +82545 -0.214813232421875 +82546 -0.5489501953125 +82547 -0.37750244140625 +82548 -0.7738037109375 +82549 -0.536285400390625 +82550 -0.86383056640625 +82551 -0.6541748046875 +82552 -0.870391845703125 +82553 -0.707916259765625 +82554 -0.86895751953125 +82555 -0.709716796875 +82556 -0.861053466796875 +82557 -0.6685791015625 +82558 -0.765869140625 +82559 -0.5723876953125 +82560 -0.5301513671875 +82561 -0.413238525390625 +82562 -0.214691162109375 +82563 -0.196014404296875 +82564 0.137359619140625 +82565 0.04925537109375 +82566 0.474822998046875 +82567 0.286865234375 +82568 0.76239013671875 +82569 0.492034912109375 +82570 0.867462158203125 +82571 0.64593505859375 +82572 0.870361328125 +82573 0.748748779296875 +82574 0.86480712890625 +82575 0.792327880859375 +82576 0.831817626953125 +82577 0.780303955078125 +82578 0.677581787109375 +82579 0.729522705078125 +82580 0.495880126953125 +82581 0.643951416015625 +82582 0.30767822265625 +82583 0.536376953125 +82584 0.116180419921875 +82585 0.40826416015625 +82586 -0.110748291015625 +82587 0.23748779296875 +82588 -0.381805419921875 +82589 0.019195556640625 +82590 -0.6572265625 +82591 -0.216796875 +82592 -0.857421875 +82593 -0.428802490234375 +82594 -0.870391845703125 +82595 -0.586883544921875 +82596 -0.870391845703125 +82597 -0.68603515625 +82598 -0.86444091796875 +82599 -0.744873046875 +82600 -0.85723876953125 +82601 -0.788177490234375 +82602 -0.790008544921875 +82603 -0.803070068359375 +82604 -0.62847900390625 +82605 -0.751708984375 +82606 -0.3956298828125 +82607 -0.631805419921875 +82608 -0.126708984375 +82609 -0.46612548828125 +82610 0.150115966796875 +82611 -0.273712158203125 +82612 0.424041748046875 +82613 -0.062652587890625 +82614 0.670623779296875 +82615 0.148284912109375 +82616 0.854522705078125 +82617 0.3321533203125 +82618 0.866485595703125 +82619 0.47662353515625 +82620 0.86920166015625 +82621 0.570953369140625 +82622 0.8653564453125 +82623 0.627685546875 +82624 0.857147216796875 +82625 0.65606689453125 +82626 0.766845703125 +82627 0.654022216796875 +82628 0.628509521484375 +82629 0.62506103515625 +82630 0.462127685546875 +82631 0.564422607421875 +82632 0.297210693359375 +82633 0.489990234375 +82634 0.14862060546875 +82635 0.41033935546875 +82636 -0.00537109375 +82637 0.309478759765625 +82638 -0.15753173828125 +82639 0.192626953125 +82640 -0.31304931640625 +82641 0.0572509765625 +82642 -0.48876953125 +82643 -0.10638427734375 +82644 -0.6416015625 +82645 -0.265625 +82646 -0.751373291015625 +82647 -0.4031982421875 +82648 -0.84619140625 +82649 -0.535125732421875 +82650 -0.861297607421875 +82651 -0.651092529296875 +82652 -0.863250732421875 +82653 -0.72796630859375 +82654 -0.856597900390625 +82655 -0.74371337890625 +82656 -0.7498779296875 +82657 -0.706695556640625 +82658 -0.624542236328125 +82659 -0.6571044921875 +82660 -0.47808837890625 +82661 -0.579620361328125 +82662 -0.253387451171875 +82663 -0.433502197265625 +82664 0.003692626953125 +82665 -0.250518798828125 +82666 0.2257080078125 +82667 -0.0782470703125 +82668 0.427154541015625 +82669 0.092041015625 +82670 0.643218994140625 +82671 0.2828369140625 +82672 0.855926513671875 +82673 0.487335205078125 +82674 0.870361328125 +82675 0.665191650390625 +82676 0.870361328125 +82677 0.78173828125 +82678 0.862762451171875 +82679 0.8419189453125 +82680 0.79669189453125 +82681 0.843597412109375 +82682 0.595794677734375 +82683 0.780120849609375 +82684 0.362152099609375 +82685 0.671722412109375 +82686 0.1270751953125 +82687 0.53790283203125 +82688 -0.086944580078125 +82689 0.392822265625 +82690 -0.2784423828125 +82691 0.237640380859375 +82692 -0.484832763671875 +82693 0.04962158203125 +82694 -0.729583740234375 +82695 -0.18304443359375 +82696 -0.86688232421875 +82697 -0.425933837890625 +82698 -0.870391845703125 +82699 -0.63629150390625 +82700 -0.86859130859375 +82701 -0.810211181640625 +82702 -0.86279296875 +82703 -0.864471435546875 +82704 -0.817962646484375 +82705 -0.870391845703125 +82706 -0.6116943359375 +82707 -0.866363525390625 +82708 -0.3128662109375 +82709 -0.83123779296875 +82710 0.039398193359375 +82711 -0.62786865234375 +82712 0.422821044921875 +82713 -0.367095947265625 +82714 0.805145263671875 +82715 -0.07183837890625 +82716 0.870361328125 +82717 0.21209716796875 +82718 0.870361328125 +82719 0.446380615234375 +82720 0.860015869140625 +82721 0.6229248046875 +82722 0.727935791015625 +82723 0.736541748046875 +82724 0.48114013671875 +82725 0.7835693359375 +82726 0.2059326171875 +82727 0.780364990234375 +82728 -0.06103515625 +82729 0.74237060546875 +82730 -0.29913330078125 +82731 0.676849365234375 +82732 -0.516204833984375 +82733 0.574859619140625 +82734 -0.7252197265625 +82735 0.427001953125 +82736 -0.85980224609375 +82737 0.250640869140625 +82738 -0.870391845703125 +82739 0.0694580078125 +82740 -0.870391845703125 +82741 -0.0960693359375 +82742 -0.858062744140625 +82743 -0.21282958984375 +82744 -0.673004150390625 +82745 -0.277374267578125 +82746 -0.42694091796875 +82747 -0.324005126953125 +82748 -0.2100830078125 +82749 -0.381805419921875 +82750 -0.0362548828125 +82751 -0.44915771484375 +82752 0.10943603515625 +82753 -0.50677490234375 +82754 0.23516845703125 +82755 -0.54156494140625 +82756 0.373687744140625 +82757 -0.526397705078125 +82758 0.517791748046875 +82759 -0.46307373046875 +82760 0.602783203125 +82761 -0.394073486328125 +82762 0.635711669921875 +82763 -0.316680908203125 +82764 0.655181884765625 +82765 -0.20953369140625 +82766 0.65948486328125 +82767 -0.079986572265625 +82768 0.651275634765625 +82769 0.065826416015625 +82770 0.61846923828125 +82771 0.210906982421875 +82772 0.53753662109375 +82773 0.330108642578125 +82774 0.404144287109375 +82775 0.41094970703125 +82776 0.22186279296875 +82777 0.446685791015625 +82778 0.003997802734375 +82779 0.43798828125 +82780 -0.22100830078125 +82781 0.39691162109375 +82782 -0.42449951171875 +82783 0.33734130859375 +82784 -0.579833984375 +82785 0.2738037109375 +82786 -0.641876220703125 +82787 0.235137939453125 +82788 -0.6177978515625 +82789 0.217529296875 +82790 -0.575531005859375 +82791 0.1787109375 +82792 -0.526336669921875 +82793 0.1158447265625 +82794 -0.42645263671875 +82795 0.063995361328125 +82796 -0.2581787109375 +82797 0.0419921875 +82798 -0.068695068359375 +82799 0.0262451171875 +82800 0.09222412109375 +82801 -0.008270263671875 +82802 0.232147216796875 +82803 -0.048858642578125 +82804 0.3509521484375 +82805 -0.088531494140625 +82806 0.410064697265625 +82807 -0.1468505859375 +82808 0.372955322265625 +82809 -0.243377685546875 +82810 0.2554931640625 +82811 -0.3643798828125 +82812 0.10711669921875 +82813 -0.47552490234375 +82814 -0.052886962890625 +82815 -0.564239501953125 +82816 -0.186279296875 +82817 -0.60693359375 +82818 -0.23291015625 +82819 -0.566986083984375 +82820 -0.209442138671875 +82821 -0.46002197265625 +82822 -0.174163818359375 +82823 -0.330352783203125 +82824 -0.126739501953125 +82825 -0.1839599609375 +82826 -0.048126220703125 +82827 -0.01470947265625 +82828 0.0426025390625 +82829 0.158294677734375 +82830 0.10748291015625 +82831 0.303802490234375 +82832 0.1409912109375 +82833 0.412841796875 +82834 0.19708251953125 +82835 0.5169677734375 +82836 0.273651123046875 +82837 0.611724853515625 +82838 0.31768798828125 +82839 0.660186767578125 +82840 0.341094970703125 +82841 0.669891357421875 +82842 0.368011474609375 +82843 0.657928466796875 +82844 0.37249755859375 +82845 0.609375 +82846 0.30072021484375 +82847 0.491912841796875 +82848 0.1517333984375 +82849 0.309234619140625 +82850 -0.01470947265625 +82851 0.105987548828125 +82852 -0.1883544921875 +82853 -0.10565185546875 +82854 -0.372711181640625 +82855 -0.32269287109375 +82856 -0.51397705078125 +82857 -0.504302978515625 +82858 -0.57177734375 +82859 -0.619049072265625 +82860 -0.53948974609375 +82861 -0.658721923828125 +82862 -0.43511962890625 +82863 -0.63238525390625 +82864 -0.2962646484375 +82865 -0.56317138671875 +82866 -0.161102294921875 +82867 -0.475799560546875 +82868 -0.0435791015625 +82869 -0.37994384765625 +82870 0.060394287109375 +82871 -0.274444580078125 +82872 0.13665771484375 +82873 -0.171234130859375 +82874 0.170135498046875 +82875 -0.0836181640625 +82876 0.16552734375 +82877 -0.012420654296875 +82878 0.15728759765625 +82879 0.0609130859375 +82880 0.150787353515625 +82881 0.135528564453125 +82882 0.12200927734375 +82883 0.191131591796875 +82884 0.080108642578125 +82885 0.2298583984375 +82886 0.05126953125 +82887 0.265716552734375 +82888 0.062896728515625 +82889 0.31427001953125 +82890 0.09271240234375 +82891 0.358856201171875 +82892 0.092987060546875 +82893 0.366943359375 +82894 0.07855224609375 +82895 0.348388671875 +82896 0.06427001953125 +82897 0.314056396484375 +82898 0.0347900390625 +82899 0.25555419921875 +82900 -0.01171875 +82901 0.174163818359375 +82902 -0.056060791015625 +82903 0.085723876953125 +82904 -0.055511474609375 +82905 0.0220947265625 +82906 -0.010467529296875 +82907 -0.01336669921875 +82908 0.02508544921875 +82909 -0.0528564453125 +82910 0.025665283203125 +82911 -0.109893798828125 +82912 0.017333984375 +82913 -0.164215087890625 +82914 0.00189208984375 +82915 -0.2122802734375 +82916 -0.03173828125 +82917 -0.259674072265625 +82918 -0.071502685546875 +82919 -0.29742431640625 +82920 -0.13543701171875 +82921 -0.3372802734375 +82922 -0.219970703125 +82923 -0.37738037109375 +82924 -0.300506591796875 +82925 -0.402679443359375 +82926 -0.376312255859375 +82927 -0.41455078125 +82928 -0.416107177734375 +82929 -0.394622802734375 +82930 -0.371124267578125 +82931 -0.313262939453125 +82932 -0.242279052734375 +82933 -0.174041748046875 +82934 -0.069732666015625 +82935 -0.006622314453125 +82936 0.125640869140625 +82937 0.1722412109375 +82938 0.31268310546875 +82939 0.33929443359375 +82940 0.45501708984375 +82941 0.46826171875 +82942 0.554779052734375 +82943 0.558929443359375 +82944 0.61065673828125 +82945 0.609161376953125 +82946 0.610931396484375 +82947 0.61090087890625 +82948 0.531463623046875 +82949 0.54901123046875 +82950 0.3883056640625 +82951 0.434844970703125 +82952 0.23468017578125 +82953 0.30450439453125 +82954 0.095245361328125 +82955 0.175994873046875 +82956 -0.00396728515625 +82957 0.0684814453125 +82958 -0.04852294921875 +82959 -0.006134033203125 +82960 -0.055145263671875 +82961 -0.056121826171875 +82962 -0.0758056640625 +82963 -0.11279296875 +82964 -0.138702392578125 +82965 -0.192169189453125 +82966 -0.209197998046875 +82967 -0.269775390625 +82968 -0.289031982421875 +82969 -0.345184326171875 +82970 -0.37884521484375 +82971 -0.41778564453125 +82972 -0.456329345703125 +82973 -0.47259521484375 +82974 -0.51641845703125 +82975 -0.50634765625 +82976 -0.519287109375 +82977 -0.493743896484375 +82978 -0.458251953125 +82979 -0.431488037109375 +82980 -0.384796142578125 +82981 -0.3544921875 +82982 -0.323699951171875 +82983 -0.280670166015625 +82984 -0.269287109375 +82985 -0.20831298828125 +82986 -0.1951904296875 +82987 -0.122406005859375 +82988 -0.100006103515625 +82989 -0.02410888671875 +82990 -0.01055908203125 +82991 0.067169189453125 +82992 0.1033935546875 +82993 0.16937255859375 +82994 0.24908447265625 +82995 0.28582763671875 +82996 0.373199462890625 +82997 0.380859375 +82998 0.45806884765625 +82999 0.44244384765625 +83000 0.511474609375 +83001 0.475494384765625 +83002 0.565399169921875 +83003 0.501129150390625 +83004 0.61138916015625 +83005 0.51458740234375 +83006 0.5897216796875 +83007 0.478179931640625 +83008 0.4906005859375 +83009 0.38690185546875 +83010 0.33148193359375 +83011 0.253692626953125 +83012 0.147796630859375 +83013 0.103271484375 +83014 -0.01873779296875 +83015 -0.0355224609375 +83016 -0.140289306640625 +83017 -0.1429443359375 +83018 -0.191986083984375 +83019 -0.2012939453125 +83020 -0.184295654296875 +83021 -0.216156005859375 +83022 -0.161834716796875 +83023 -0.215576171875 +83024 -0.166595458984375 +83025 -0.22625732421875 +83026 -0.19390869140625 +83027 -0.24493408203125 +83028 -0.22442626953125 +83029 -0.2591552734375 +83030 -0.279754638671875 +83031 -0.283447265625 +83032 -0.3389892578125 +83033 -0.3050537109375 +83034 -0.3543701171875 +83035 -0.294036865234375 +83036 -0.348175048828125 +83037 -0.26611328125 +83038 -0.32598876953125 +83039 -0.226287841796875 +83040 -0.2581787109375 +83041 -0.156768798828125 +83042 -0.139801025390625 +83043 -0.055694580078125 +83044 0.014617919921875 +83045 0.06622314453125 +83046 0.144378662109375 +83047 0.16839599609375 +83048 0.221038818359375 +83049 0.2314453125 +83050 0.27069091796875 +83051 0.271759033203125 +83052 0.294036865234375 +83053 0.28955078125 +83054 0.311767578125 +83055 0.298248291015625 +83056 0.339141845703125 +83057 0.30804443359375 +83058 0.360260009765625 +83059 0.3089599609375 +83060 0.360504150390625 +83061 0.292388916015625 +83062 0.308380126953125 +83063 0.239501953125 +83064 0.18170166015625 +83065 0.13751220703125 +83066 0.0047607421875 +83067 0.00311279296875 +83068 -0.17559814453125 +83069 -0.1328125 +83070 -0.3143310546875 +83071 -0.2406005859375 +83072 -0.36785888671875 +83073 -0.291656494140625 +83074 -0.36248779296875 +83075 -0.30169677734375 +83076 -0.343536376953125 +83077 -0.29876708984375 +83078 -0.3018798828125 +83079 -0.276763916015625 +83080 -0.231414794921875 +83081 -0.231689453125 +83082 -0.117645263671875 +83083 -0.154571533203125 +83084 0.007049560546875 +83085 -0.0662841796875 +83086 0.087982177734375 +83087 -0.00201416015625 +83088 0.13946533203125 +83089 0.046417236328125 +83090 0.17425537109375 +83091 0.08612060546875 +83092 0.188201904296875 +83093 0.113433837890625 +83094 0.171234130859375 +83095 0.1209716796875 +83096 0.118438720703125 +83097 0.104644775390625 +83098 0.05706787109375 +83099 0.080810546875 +83100 -0.010711669921875 +83101 0.050048828125 +83102 -0.0914306640625 +83103 0.00762939453125 +83104 -0.162322998046875 +83105 -0.0323486328125 +83106 -0.194549560546875 +83107 -0.051849365234375 +83108 -0.1492919921875 +83109 -0.026275634765625 +83110 -0.02166748046875 +83111 0.047698974609375 +83112 0.124053955078125 +83113 0.12994384765625 +83114 0.211151123046875 +83115 0.172607421875 +83116 0.240447998046875 +83117 0.176971435546875 +83118 0.242218017578125 +83119 0.1629638671875 +83120 0.2257080078125 +83121 0.1373291015625 +83122 0.194366455078125 +83123 0.103057861328125 +83124 0.115509033203125 +83125 0.040252685546875 +83126 0.0128173828125 +83127 -0.035430908203125 +83128 -0.053802490234375 +83129 -0.08563232421875 +83130 -0.110626220703125 +83131 -0.126556396484375 +83132 -0.199493408203125 +83133 -0.18450927734375 +83134 -0.29437255859375 +83135 -0.243011474609375 +83136 -0.33221435546875 +83137 -0.26239013671875 +83138 -0.27972412109375 +83139 -0.221954345703125 +83140 -0.185333251953125 +83141 -0.15277099609375 +83142 -0.128204345703125 +83143 -0.10546875 +83144 -0.115692138671875 +83145 -0.085296630859375 +83146 -0.116455078125 +83147 -0.07318115234375 +83148 -0.105926513671875 +83149 -0.0543212890625 +83150 -0.053955078125 +83151 -0.01031494140625 +83152 0.048797607421875 +83153 0.064178466796875 +83154 0.157318115234375 +83155 0.140228271484375 +83156 0.212005615234375 +83157 0.1798095703125 +83158 0.218475341796875 +83159 0.186279296875 +83160 0.23724365234375 +83161 0.197845458984375 +83162 0.30535888671875 +83163 0.238006591796875 +83164 0.38128662109375 +83165 0.28070068359375 +83166 0.404449462890625 +83167 0.287994384765625 +83168 0.3944091796875 +83169 0.272735595703125 +83170 0.3885498046875 +83171 0.25909423828125 +83172 0.362640380859375 +83173 0.232330322265625 +83174 0.27362060546875 +83175 0.165802001953125 +83176 0.11712646484375 +83177 0.05731201171875 +83178 -0.054901123046875 +83179 -0.059783935546875 +83180 -0.19085693359375 +83181 -0.152435302734375 +83182 -0.28570556640625 +83183 -0.2171630859375 +83184 -0.339263916015625 +83185 -0.253662109375 +83186 -0.3775634765625 +83187 -0.278289794921875 +83188 -0.445709228515625 +83189 -0.319610595703125 +83190 -0.535064697265625 +83191 -0.372314453125 +83192 -0.629058837890625 +83193 -0.42620849609375 +83194 -0.697601318359375 +83195 -0.46258544921875 +83196 -0.70391845703125 +83197 -0.458648681640625 +83198 -0.6424560546875 +83199 -0.411346435546875 +83200 -0.491241455078125 +83201 -0.3077392578125 +83202 -0.265716552734375 +83203 -0.158172607421875 +83204 -0.023712158203125 +83205 0.0010986328125 +83206 0.201751708984375 +83207 0.14935302734375 +83208 0.375823974609375 +83209 0.264892578125 +83210 0.485076904296875 +83211 0.339019775390625 +83212 0.56884765625 +83213 0.394866943359375 +83214 0.634765625 +83215 0.436798095703125 +83216 0.63763427734375 +83217 0.43768310546875 +83218 0.5660400390625 +83219 0.390777587890625 +83220 0.4720458984375 +83221 0.327667236328125 +83222 0.40692138671875 +83223 0.279541015625 +83224 0.3778076171875 +83225 0.25128173828125 +83226 0.376953125 +83227 0.2388916015625 +83228 0.371978759765625 +83229 0.2236328125 +83230 0.313140869140625 +83231 0.176361083984375 +83232 0.184417724609375 +83233 0.088104248046875 +83234 0.011199951171875 +83235 -0.025299072265625 +83236 -0.171051025390625 +83237 -0.142059326171875 +83238 -0.33740234375 +83239 -0.24688720703125 +83240 -0.47198486328125 +83241 -0.330047607421875 +83242 -0.560394287109375 +83243 -0.38287353515625 +83244 -0.58056640625 +83245 -0.3922119140625 +83246 -0.54754638671875 +83247 -0.367340087890625 +83248 -0.508575439453125 +83249 -0.3369140625 +83250 -0.459503173828125 +83251 -0.298919677734375 +83252 -0.394378662109375 +83253 -0.250274658203125 +83254 -0.35260009765625 +83255 -0.215118408203125 +83256 -0.31170654296875 +83257 -0.180572509765625 +83258 -0.197418212890625 +83259 -0.102630615234375 +83260 -0.007965087890625 +83261 0.019287109375 +83262 0.207489013671875 +83263 0.155242919921875 +83264 0.409210205078125 +83265 0.281097412109375 +83266 0.57208251953125 +83267 0.38153076171875 +83268 0.66595458984375 +83269 0.43841552734375 +83270 0.65875244140625 +83271 0.4324951171875 +83272 0.56744384765625 +83273 0.374114990234375 +83274 0.431396484375 +83275 0.28717041015625 +83276 0.29443359375 +83277 0.198272705078125 +83278 0.182464599609375 +83279 0.1234130859375 +83280 0.06365966796875 +83281 0.043914794921875 +83282 -0.075958251953125 +83283 -0.048126220703125 +83284 -0.189422607421875 +83285 -0.124114990234375 +83286 -0.271942138671875 +83287 -0.18072509765625 +83288 -0.342529296875 +83289 -0.22900390625 +83290 -0.364166259765625 +83291 -0.2464599609375 +83292 -0.327239990234375 +83293 -0.22711181640625 +83294 -0.2769775390625 +83295 -0.197998046875 +83296 -0.253692626953125 +83297 -0.183319091796875 +83298 -0.24365234375 +83299 -0.174896240234375 +83300 -0.1983642578125 +83301 -0.143829345703125 +83302 -0.116241455078125 +83303 -0.08941650390625 +83304 -0.036834716796875 +83305 -0.03570556640625 +83306 0.034881591796875 +83307 0.013946533203125 +83308 0.09124755859375 +83309 0.054595947265625 +83310 0.10888671875 +83311 0.071807861328125 +83312 0.125518798828125 +83313 0.087860107421875 +83314 0.15771484375 +83315 0.112396240234375 +83316 0.17828369140625 +83317 0.128814697265625 +83318 0.17108154296875 +83319 0.12725830078125 +83320 0.129974365234375 +83321 0.10394287109375 +83322 0.082427978515625 +83323 0.0753173828125 +83324 0.027679443359375 +83325 0.040985107421875 +83326 -0.065643310546875 +83327 -0.01776123046875 +83328 -0.15936279296875 +83329 -0.07781982421875 +83330 -0.21307373046875 +83331 -0.114715576171875 +83332 -0.234649658203125 +83333 -0.132904052734375 +83334 -0.2001953125 +83335 -0.11773681640625 +83336 -0.119171142578125 +83337 -0.074615478515625 +83338 -0.024749755859375 +83339 -0.023101806640625 +83340 0.085784912109375 +83341 0.038665771484375 +83342 0.178131103515625 +83343 0.090362548828125 +83344 0.215576171875 +83345 0.110137939453125 +83346 0.211456298828125 +83347 0.1060791015625 +83348 0.17523193359375 +83349 0.08392333984375 +83350 0.128753662109375 +83351 0.056793212890625 +83352 0.1019287109375 +83353 0.04254150390625 +83354 0.0743408203125 +83355 0.02880859375 +83356 0.04327392578125 +83357 0.0137939453125 +83358 0.038177490234375 +83359 0.014923095703125 +83360 0.076263427734375 +83361 0.04229736328125 +83362 0.14105224609375 +83363 0.08575439453125 +83364 0.186431884765625 +83365 0.117340087890625 +83366 0.188812255859375 +83367 0.1226806640625 +83368 0.1390380859375 +83369 0.0960693359375 +83370 0.041778564453125 +83371 0.040191650390625 +83372 -0.079437255859375 +83373 -0.030914306640625 +83374 -0.219390869140625 +83375 -0.114227294921875 +83376 -0.367828369140625 +83377 -0.20355224609375 +83378 -0.494873046875 +83379 -0.280975341796875 +83380 -0.556243896484375 +83381 -0.31982421875 +83382 -0.508697509765625 +83383 -0.29400634765625 +83384 -0.3756103515625 +83385 -0.217376708984375 +83386 -0.218902587890625 +83387 -0.126922607421875 +83388 -0.063751220703125 +83389 -0.03753662109375 +83390 0.091552734375 +83391 0.051971435546875 +83392 0.23602294921875 +83393 0.13525390625 +83394 0.342987060546875 +83395 0.19647216796875 +83396 0.39520263671875 +83397 0.225433349609375 +83398 0.389373779296875 +83399 0.22027587890625 +83400 0.324249267578125 +83401 0.180328369140625 +83402 0.224090576171875 +83403 0.120147705078125 +83404 0.124267578125 +83405 0.06097412109375 +83406 0.037078857421875 +83407 0.010101318359375 +83408 -0.010101318359375 +83409 -0.01611328125 +83410 -0.019439697265625 +83411 -0.019134521484375 +83412 -0.022796630859375 +83413 -0.018218994140625 +83414 -0.001556396484375 +83415 -0.002349853515625 +83416 0.056304931640625 +83417 0.03546142578125 +83418 0.106719970703125 +83419 0.068634033203125 +83420 0.096893310546875 +83421 0.0653076171875 +83422 0.042694091796875 +83423 0.034912109375 +83424 -0.018035888671875 +83425 0.0 +83426 -0.07586669921875 +83427 -0.033782958984375 +83428 -0.11944580078125 +83429 -0.059661865234375 +83430 -0.15972900390625 +83431 -0.084259033203125 +83432 -0.202606201171875 +83433 -0.11102294921875 +83434 -0.24859619140625 +83435 -0.140167236328125 +83436 -0.30517578125 +83437 -0.17608642578125 +83438 -0.36212158203125 +83439 -0.2125244140625 +83440 -0.39141845703125 +83441 -0.232574462890625 +83442 -0.35528564453125 +83443 -0.21337890625 +83444 -0.249969482421875 +83445 -0.152587890625 +83446 -0.092864990234375 +83447 -0.060516357421875 +83448 0.08905029296875 +83449 0.0467529296875 +83450 0.2352294921875 +83451 0.13299560546875 +83452 0.318817138671875 +83453 0.182159423828125 +83454 0.358642578125 +83455 0.20556640625 +83456 0.347747802734375 +83457 0.199676513671875 +83458 0.28564453125 +83459 0.164825439453125 +83460 0.223175048828125 +83461 0.130279541015625 +83462 0.196746826171875 +83463 0.116424560546875 +83464 0.179840087890625 +83465 0.107940673828125 +83466 0.155548095703125 +83467 0.095001220703125 +83468 0.151214599609375 +83469 0.093017578125 +83470 0.156951904296875 +83471 0.096282958984375 +83472 0.13177490234375 +83473 0.08148193359375 +83474 0.100799560546875 +83475 0.06292724609375 +83476 0.087127685546875 +83477 0.053802490234375 +83478 0.05487060546875 +83479 0.0338134765625 +83480 -0.009002685546875 +83481 -0.004302978515625 +83482 -0.10400390625 +83483 -0.06011962890625 +83484 -0.229400634765625 +83485 -0.133148193359375 +83486 -0.35552978515625 +83487 -0.2064208984375 +83488 -0.441925048828125 +83489 -0.2568359375 +83490 -0.473846435546875 +83491 -0.275970458984375 +83492 -0.464813232421875 +83493 -0.27142333984375 +83494 -0.419097900390625 +83495 -0.245574951171875 +83496 -0.334320068359375 +83497 -0.197113037109375 +83498 -0.227935791015625 +83499 -0.135955810546875 +83500 -0.12347412109375 +83501 -0.075531005859375 +83502 -0.02764892578125 +83503 -0.01971435546875 +83504 0.077667236328125 +83505 0.04168701171875 +83506 0.2132568359375 +83507 0.120361328125 +83508 0.38885498046875 +83509 0.22174072265625 +83510 0.582794189453125 +83511 0.333465576171875 +83512 0.734039306640625 +83513 0.420745849609375 +83514 0.800140380859375 +83515 0.45941162109375 +83516 0.7783203125 +83517 0.44781494140625 +83518 0.6651611328125 +83519 0.384002685546875 +83520 0.45965576171875 +83521 0.26739501953125 +83522 0.199188232421875 +83523 0.119232177734375 +83524 -0.050689697265625 +83525 -0.023223876953125 +83526 -0.23297119140625 +83527 -0.1275634765625 +83528 -0.33013916015625 +83529 -0.183807373046875 +83530 -0.368408203125 +83531 -0.20672607421875 +83532 -0.378936767578125 +83533 -0.2139892578125 +83534 -0.376983642578125 +83535 -0.21417236328125 +83536 -0.37969970703125 +83537 -0.21697998046875 +83538 -0.391510009765625 +83539 -0.224822998046875 +83540 -0.385345458984375 +83541 -0.2222900390625 +83542 -0.3419189453125 +83543 -0.1983642578125 +83544 -0.28289794921875 +83545 -0.165313720703125 +83546 -0.251617431640625 +83547 -0.147735595703125 +83548 -0.266143798828125 +83549 -0.1558837890625 +83550 -0.273345947265625 +83551 -0.15960693359375 +83552 -0.216796875 +83553 -0.12689208984375 +83554 -0.128265380859375 +83555 -0.0758056640625 +83556 -0.068145751953125 +83557 -0.04071044921875 +83558 -0.0430908203125 +83559 -0.025390625 +83560 -0.024444580078125 +83561 -0.013702392578125 +83562 0.020721435546875 +83563 0.013031005859375 +83564 0.124481201171875 +83565 0.07293701171875 +83566 0.25787353515625 +83567 0.149505615234375 +83568 0.379119873046875 +83569 0.218994140625 +83570 0.47991943359375 +83571 0.27667236328125 +83572 0.5281982421875 +83573 0.30426025390625 +83574 0.511138916015625 +83575 0.29449462890625 +83576 0.456207275390625 +83577 0.26300048828125 +83578 0.407470703125 +83579 0.234832763671875 +83580 0.383758544921875 +83581 0.220703125 +83582 0.35687255859375 +83583 0.204620361328125 +83584 0.31182861328125 +83585 0.178131103515625 +83586 0.250885009765625 +83587 0.142578125 +83588 0.1654052734375 +83589 0.093109130859375 +83590 0.035247802734375 +83591 0.018341064453125 +83592 -0.142059326171875 +83593 -0.08306884765625 +83594 -0.33563232421875 +83595 -0.193572998046875 +83596 -0.5345458984375 +83597 -0.306915283203125 +83598 -0.72186279296875 +83599 -0.413482666015625 +83600 -0.836669921875 +83601 -0.4786376953125 +83602 -0.8326416015625 +83603 -0.47607421875 +83604 -0.7296142578125 +83605 -0.4171142578125 +83606 -0.582550048828125 +83607 -0.332977294921875 +83608 -0.440093994140625 +83609 -0.2513427734375 +83610 -0.324310302734375 +83611 -0.184814453125 +83612 -0.20147705078125 +83613 -0.1142578125 +83614 -0.044647216796875 +83615 -0.0244140625 +83616 0.103973388671875 +83617 0.060699462890625 +83618 0.202392578125 +83619 0.1171875 +83620 0.264495849609375 +83621 0.152923583984375 +83622 0.338897705078125 +83623 0.195465087890625 +83624 0.443817138671875 +83625 0.25518798828125 +83626 0.545074462890625 +83627 0.312652587890625 +83628 0.6173095703125 +83629 0.35345458984375 +83630 0.6524658203125 +83631 0.373046875 +83632 0.66339111328125 +83633 0.378753662109375 +83634 0.6561279296875 +83635 0.3740234375 +83636 0.606781005859375 +83637 0.345306396484375 +83638 0.501190185546875 +83639 0.284637451171875 +83640 0.352783203125 +83641 0.199676513671875 +83642 0.176544189453125 +83643 0.09893798828125 +83644 -0.034820556640625 +83645 -0.0216064453125 +83646 -0.258209228515625 +83647 -0.148834228515625 +83648 -0.44244384765625 +83649 -0.253662109375 +83650 -0.5753173828125 +83651 -0.32916259765625 +83652 -0.65203857421875 +83653 -0.37261962890625 +83654 -0.641632080078125 +83655 -0.366455078125 +83656 -0.562164306640625 +83657 -0.320953369140625 +83658 -0.458038330078125 +83659 -0.261383056640625 +83660 -0.350555419921875 +83661 -0.1998291015625 +83662 -0.260528564453125 +83663 -0.14813232421875 +83664 -0.192108154296875 +83665 -0.10870361328125 +83666 -0.141937255859375 +83667 -0.079681396484375 +83668 -0.1021728515625 +83669 -0.056610107421875 +83670 -0.062896728515625 +83671 -0.033905029296875 +83672 -0.011932373046875 +83673 -0.004638671875 +83674 0.062835693359375 +83675 0.037994384765625 +83676 0.148712158203125 +83677 0.086822509765625 +83678 0.241729736328125 +83679 0.139556884765625 +83680 0.34912109375 +83681 0.200347900390625 +83682 0.457305908203125 +83683 0.261505126953125 +83684 0.54388427734375 +83685 0.310302734375 +83686 0.5728759765625 +83687 0.326324462890625 +83688 0.506591796875 +83689 0.2882080078125 +83690 0.351226806640625 +83691 0.199493408203125 +83692 0.146514892578125 +83693 0.082763671875 +83694 -0.05523681640625 +83695 -0.0322265625 +83696 -0.21624755859375 +83697 -0.123992919921875 +83698 -0.334930419921875 +83699 -0.191619873046875 +83700 -0.402984619140625 +83701 -0.23040771484375 +83702 -0.4412841796875 +83703 -0.252197265625 +83704 -0.49578857421875 +83705 -0.2830810546875 +83706 -0.5601806640625 +83707 -0.319488525390625 +83708 -0.600738525390625 +83709 -0.342254638671875 +83710 -0.584228515625 +83711 -0.33258056640625 +83712 -0.47930908203125 +83713 -0.27294921875 +83714 -0.27935791015625 +83715 -0.160308837890625 +83716 -0.0089111328125 +83717 -0.008758544921875 +83718 0.268798828125 +83719 0.14703369140625 +83720 0.482818603515625 +83721 0.268402099609375 +83722 0.60369873046875 +83723 0.339080810546875 +83724 0.650421142578125 +83725 0.368804931640625 +83726 0.66400146484375 +83727 0.37933349609375 +83728 0.6414794921875 +83729 0.368896484375 +83730 0.572540283203125 +83731 0.331939697265625 +83732 0.498138427734375 +83733 0.290496826171875 +83734 0.439453125 +83735 0.256072998046875 +83736 0.375518798828125 +83737 0.217681884765625 +83738 0.274505615234375 +83739 0.1585693359375 +83740 0.1087646484375 +83741 0.064208984375 +83742 -0.099395751953125 +83743 -0.0531005859375 +83744 -0.3182373046875 +83745 -0.175994873046875 +83746 -0.5489501953125 +83747 -0.3048095703125 +83748 -0.7738037109375 +83749 -0.429718017578125 +83750 -0.86383056640625 +83751 -0.52215576171875 +83752 -0.870391845703125 +83753 -0.5640869140625 +83754 -0.86895751953125 +83755 -0.56494140625 +83756 -0.861053466796875 +83757 -0.53173828125 +83758 -0.765869140625 +83759 -0.45526123046875 +83760 -0.5301513671875 +83761 -0.329559326171875 +83762 -0.214691162109375 +83763 -0.15863037109375 +83764 0.137359619140625 +83765 0.034210205078125 +83766 0.474822998046875 +83767 0.22125244140625 +83768 0.76239013671875 +83769 0.3831787109375 +83770 0.867462158203125 +83771 0.505279541015625 +83772 0.870361328125 +83773 0.5875244140625 +83774 0.86480712890625 +83775 0.62347412109375 +83776 0.831817626953125 +83777 0.615814208984375 +83778 0.677581787109375 +83779 0.57745361328125 +83780 0.495880126953125 +83781 0.51141357421875 +83782 0.30767822265625 +83783 0.4276123046875 +83784 0.116180419921875 +83785 0.327239990234375 +83786 -0.110748291015625 +83787 0.193389892578125 +83788 -0.381805419921875 +83789 0.022430419921875 +83790 -0.6572265625 +83791 -0.1624755859375 +83792 -0.857421875 +83793 -0.329071044921875 +83794 -0.870391845703125 +83795 -0.4541015625 +83796 -0.870391845703125 +83797 -0.53350830078125 +83798 -0.86444091796875 +83799 -0.581512451171875 +83800 -0.85723876953125 +83801 -0.6170654296875 +83802 -0.790008544921875 +83803 -0.630126953125 +83804 -0.62847900390625 +83805 -0.59149169921875 +83806 -0.3956298828125 +83807 -0.499359130859375 +83808 -0.126708984375 +83809 -0.37127685546875 +83810 0.150115966796875 +83811 -0.221923828125 +83812 0.424041748046875 +83813 -0.057647705078125 +83814 0.670623779296875 +83815 0.10699462890625 +83816 0.854522705078125 +83817 0.2510986328125 +83818 0.866485595703125 +83819 0.365020751953125 +83820 0.86920166015625 +83821 0.440338134765625 +83822 0.8653564453125 +83823 0.486572265625 +83824 0.857147216796875 +83825 0.5107421875 +83826 0.766845703125 +83827 0.511138916015625 +83828 0.628509521484375 +83829 0.490325927734375 +83830 0.462127685546875 +83831 0.444580078125 +83832 0.297210693359375 +83833 0.38763427734375 +83834 0.14862060546875 +83835 0.3260498046875 +83836 -0.00537109375 +83837 0.247589111328125 +83838 -0.15753173828125 +83839 0.15631103515625 +83840 -0.31304931640625 +83841 0.050384521484375 +83842 -0.48876953125 +83843 -0.077606201171875 +83844 -0.6416015625 +83845 -0.202362060546875 +83846 -0.751373291015625 +83847 -0.31048583984375 +83848 -0.84619140625 +83849 -0.4141845703125 +83850 -0.861297607421875 +83851 -0.50543212890625 +83852 -0.863250732421875 +83853 -0.566314697265625 +83854 -0.856597900390625 +83855 -0.5797119140625 +83856 -0.7498779296875 +83857 -0.55206298828125 +83858 -0.624542236328125 +83859 -0.5142822265625 +83860 -0.47808837890625 +83861 -0.45452880859375 +83862 -0.253387451171875 +83863 -0.341461181640625 +83864 0.003692626953125 +83865 -0.1995849609375 +83866 0.2257080078125 +83867 -0.06561279296875 +83868 0.427154541015625 +83869 0.06707763671875 +83870 0.643218994140625 +83871 0.2156982421875 +83872 0.855926513671875 +83873 0.374969482421875 +83874 0.870361328125 +83875 0.513641357421875 +83876 0.870361328125 +83877 0.60498046875 +83878 0.862762451171875 +83879 0.652679443359375 +83880 0.79669189453125 +83881 0.655029296875 +83882 0.595794677734375 +83883 0.606903076171875 +83884 0.362152099609375 +83885 0.523834228515625 +83886 0.1270751953125 +83887 0.42083740234375 +83888 -0.086944580078125 +83889 0.30926513671875 +83890 -0.2784423828125 +83891 0.19024658203125 +83892 -0.484832763671875 +83893 0.045196533203125 +83894 -0.729583740234375 +83895 -0.13604736328125 +83896 -0.86688232421875 +83897 -0.32623291015625 +83898 -0.870391845703125 +83899 -0.49127197265625 +83900 -0.86859130859375 +83901 -0.628326416015625 +83902 -0.86279296875 +83903 -0.736114501953125 +83904 -0.817962646484375 +83905 -0.795196533203125 +83906 -0.6116943359375 +83907 -0.781097412109375 +83908 -0.3128662109375 +83909 -0.689910888671875 +83910 0.039398193359375 +83911 -0.539581298828125 +83912 0.422821044921875 +83913 -0.340850830078125 +83914 0.805145263671875 +83915 -0.111572265625 +83916 0.870361328125 +83917 0.111663818359375 +83918 0.870361328125 +83919 0.298187255859375 +83920 0.860015869140625 +83921 0.441558837890625 +83922 0.727935791015625 +83923 0.53741455078125 +83924 0.48114013671875 +83925 0.58251953125 +83926 0.2059326171875 +83927 0.589599609375 +83928 -0.06103515625 +83929 0.570526123046875 +83930 -0.29913330078125 +83931 0.53045654296875 +83932 -0.516204833984375 +83933 0.461456298828125 +83934 -0.7252197265625 +83935 0.35516357421875 +83936 -0.85980224609375 +83937 0.22491455078125 +83938 -0.870391845703125 +83939 0.08917236328125 +83940 -0.870391845703125 +83941 -0.0360107421875 +83942 -0.858062744140625 +83943 -0.12432861328125 +83944 -0.673004150390625 +83945 -0.1732177734375 +83946 -0.42694091796875 +83947 -0.21051025390625 +83948 -0.2100830078125 +83949 -0.259613037109375 +83950 -0.0362548828125 +83951 -0.319000244140625 +83952 0.10943603515625 +83953 -0.37274169921875 +83954 0.23516845703125 +83955 -0.40985107421875 +83956 0.373687744140625 +83957 -0.407867431640625 +83958 0.517791748046875 +83959 -0.367645263671875 +83960 0.602783203125 +83961 -0.322845458984375 +83962 0.635711669921875 +83963 -0.27069091796875 +83964 0.655181884765625 +83965 -0.193389892578125 +83966 0.65948486328125 +83967 -0.096435546875 +83968 0.651275634765625 +83969 0.01531982421875 +83970 0.61846923828125 +83971 0.128448486328125 +83972 0.53753662109375 +83973 0.22332763671875 +83974 0.404144287109375 +83975 0.290252685546875 +83976 0.22186279296875 +83977 0.32379150390625 +83978 0.003997802734375 +83979 0.324127197265625 +83980 -0.22100830078125 +83981 0.300018310546875 +83982 -0.42449951171875 +83983 0.261688232421875 +83984 -0.579833984375 +83985 0.219818115234375 +83986 -0.641876220703125 +83987 0.19598388671875 +83988 -0.6177978515625 +83989 0.186981201171875 +83990 -0.575531005859375 +83991 0.16058349609375 +83992 -0.526336669921875 +83993 0.114471435546875 +83994 -0.42645263671875 +83995 0.075225830078125 +83996 -0.2581787109375 +83997 0.057220458984375 +83998 -0.068695068359375 +83999 0.042633056640625 +84000 0.09222412109375 +84001 0.012603759765625 +84002 0.232147216796875 +84003 -0.022918701171875 +84004 0.3509521484375 +84005 -0.058380126953125 +84006 0.410064697265625 +84007 -0.10833740234375 +84008 0.372955322265625 +84009 -0.187286376953125 +84010 0.2554931640625 +84011 -0.28448486328125 +84012 0.10711669921875 +84013 -0.37359619140625 +84014 -0.052886962890625 +84015 -0.44482421875 +84016 -0.186279296875 +84017 -0.4801025390625 +84018 -0.23291015625 +84019 -0.451507568359375 +84020 -0.209442138671875 +84021 -0.370849609375 +84022 -0.174163818359375 +84023 -0.271728515625 +84024 -0.126739501953125 +84025 -0.1588134765625 +84026 -0.048126220703125 +84027 -0.027557373046875 +84028 0.0426025390625 +84029 0.107330322265625 +84030 0.10748291015625 +84031 0.221954345703125 +84032 0.1409912109375 +84033 0.30926513671875 +84034 0.19708251953125 +84035 0.3929443359375 +84036 0.273651123046875 +84037 0.4693603515625 +84038 0.31768798828125 +84039 0.510223388671875 +84040 0.341094970703125 +84041 0.52105712890625 +84042 0.368011474609375 +84043 0.5146484375 +84044 0.37249755859375 +84045 0.47955322265625 +84046 0.30072021484375 +84047 0.39117431640625 +84048 0.1517333984375 +84049 0.252288818359375 +84050 -0.01470947265625 +84051 0.096832275390625 +84052 -0.1883544921875 +84053 -0.06585693359375 +84054 -0.372711181640625 +84055 -0.233367919921875 +84056 -0.51397705078125 +84057 -0.374542236328125 +84058 -0.57177734375 +84059 -0.46533203125 +84060 -0.53948974609375 +84061 -0.499267578125 +84062 -0.43511962890625 +84063 -0.483001708984375 +84064 -0.2962646484375 +84065 -0.433929443359375 +84066 -0.161102294921875 +84067 -0.37060546875 +84068 -0.0435791015625 +84069 -0.30023193359375 +84070 0.060394287109375 +84071 -0.2218017578125 +84072 0.13665771484375 +84073 -0.144317626953125 +84074 0.170135498046875 +84075 -0.077880859375 +84076 0.16552734375 +84077 -0.0230712890625 +84078 0.15728759765625 +84079 0.0340576171875 +84080 0.150787353515625 +84081 0.0927734375 +84082 0.12200927734375 +84083 0.1375732421875 +84084 0.080108642578125 +84085 0.169891357421875 +84086 0.05126953125 +84087 0.200164794921875 +84088 0.062896728515625 +84089 0.240081787109375 +84090 0.09271240234375 +84091 0.276824951171875 +84092 0.092987060546875 +84093 0.2855224609375 +84094 0.07855224609375 +84095 0.273529052734375 +84096 0.06427001953125 +84097 0.248992919921875 +84098 0.0347900390625 +84099 0.205474853515625 +84100 -0.01171875 +84101 0.143951416015625 +84102 -0.056060791015625 +84103 0.076446533203125 +84104 -0.055511474609375 +84105 0.02716064453125 +84106 -0.010467529296875 +84107 -0.00128173828125 +84108 0.02508544921875 +84109 -0.033233642578125 +84110 0.025665283203125 +84111 -0.078826904296875 +84112 0.017333984375 +84113 -0.12255859375 +84114 0.00189208984375 +84115 -0.16156005859375 +84116 -0.03173828125 +84117 -0.199951171875 +84118 -0.071502685546875 +84119 -0.230804443359375 +84120 -0.13543701171875 +84121 -0.26287841796875 +84122 -0.219970703125 +84123 -0.294708251953125 +84124 -0.300506591796875 +84125 -0.314788818359375 +84126 -0.376312255859375 +84127 -0.32415771484375 +84128 -0.416107177734375 +84129 -0.308837890625 +84130 -0.371124267578125 +84131 -0.24639892578125 +84132 -0.242279052734375 +84133 -0.139556884765625 +84134 -0.069732666015625 +84135 -0.01092529296875 +84136 0.125640869140625 +84137 0.126678466796875 +84138 0.31268310546875 +84139 0.2554931640625 +84140 0.45501708984375 +84141 0.355438232421875 +84142 0.554779052734375 +84143 0.426239013671875 +84144 0.61065673828125 +84145 0.466339111328125 +84146 0.610931396484375 +84147 0.46942138671875 +84148 0.531463623046875 +84149 0.423431396484375 +84150 0.3883056640625 +84151 0.3370361328125 +84152 0.23468017578125 +84153 0.238067626953125 +84154 0.095245361328125 +84155 0.140350341796875 +84156 -0.00396728515625 +84157 0.058685302734375 +84158 -0.04852294921875 +84159 0.00213623046875 +84160 -0.055145263671875 +84161 -0.035736083984375 +84162 -0.0758056640625 +84163 -0.079254150390625 +84164 -0.138702392578125 +84165 -0.140869140625 +84166 -0.209197998046875 +84167 -0.2015380859375 +84168 -0.289031982421875 +84169 -0.26092529296875 +84170 -0.37884521484375 +84171 -0.318511962890625 +84172 -0.456329345703125 +84173 -0.362548828125 +84174 -0.51641845703125 +84175 -0.39044189453125 +84176 -0.519287109375 +84177 -0.3824462890625 +84178 -0.458251953125 +84179 -0.335906982421875 +84180 -0.384796142578125 +84181 -0.27783203125 +84182 -0.323699951171875 +84183 -0.22198486328125 +84184 -0.269287109375 +84185 -0.166961669921875 +84186 -0.1951904296875 +84187 -0.101104736328125 +84188 -0.100006103515625 +84189 -0.0252685546875 +84190 -0.01055908203125 +84191 0.045501708984375 +84192 0.1033935546875 +84193 0.1251220703125 +84194 0.24908447265625 +84195 0.216094970703125 +84196 0.373199462890625 +84197 0.290740966796875 +84198 0.45806884765625 +84199 0.33966064453125 +84200 0.511474609375 +84201 0.366607666015625 +84202 0.565399169921875 +84203 0.387908935546875 +84204 0.61138916015625 +84205 0.3997802734375 +84206 0.5897216796875 +84207 0.372894287109375 +84208 0.4906005859375 +84209 0.30328369140625 +84210 0.33148193359375 +84211 0.200958251953125 +84212 0.147796630859375 +84213 0.08502197265625 +84214 -0.01873779296875 +84215 -0.02215576171875 +84216 -0.140289306640625 +84217 -0.10528564453125 +84218 -0.191986083984375 +84219 -0.150665283203125 +84220 -0.184295654296875 +84221 -0.162628173828125 +84222 -0.161834716796875 +84223 -0.16290283203125 +84224 -0.166595458984375 +84225 -0.172088623046875 +84226 -0.19390869140625 +84227 -0.187591552734375 +84228 -0.22442626953125 +84229 -0.199737548828125 +84230 -0.279754638671875 +84231 -0.219635009765625 +84232 -0.3389892578125 +84233 -0.23736572265625 +84234 -0.3543701171875 +84235 -0.22979736328125 +84236 -0.348175048828125 +84237 -0.208984375 +84238 -0.32598876953125 +84239 -0.17877197265625 +84240 -0.2581787109375 +84241 -0.125457763671875 +84242 -0.139801025390625 +84243 -0.047607421875 +84244 0.014617919921875 +84245 0.046539306640625 +84246 0.144378662109375 +84247 0.125701904296875 +84248 0.221038818359375 +84249 0.17498779296875 +84250 0.27069091796875 +84251 0.206939697265625 +84252 0.294036865234375 +84253 0.221649169921875 +84254 0.311767578125 +84255 0.229400634765625 +84256 0.339141845703125 +84257 0.2379150390625 +84258 0.360260009765625 +84259 0.239288330078125 +84260 0.360504150390625 +84261 0.226898193359375 +84262 0.308380126953125 +84263 0.186798095703125 +84264 0.18170166015625 +84265 0.10955810546875 +84266 0.0047607421875 +84267 0.00775146484375 +84268 -0.17559814453125 +84269 -0.095458984375 +84270 -0.3143310546875 +84271 -0.17779541015625 +84272 -0.36785888671875 +84273 -0.2177734375 +84274 -0.36248779296875 +84275 -0.227081298828125 +84276 -0.343536376953125 +84277 -0.226531982421875 +84278 -0.3018798828125 +84279 -0.211456298828125 +84280 -0.231414794921875 +84281 -0.178863525390625 +84282 -0.117645263671875 +84283 -0.1219482421875 +84284 0.007049560546875 +84285 -0.056304931640625 +84286 0.087982177734375 +84287 -0.00823974609375 +84288 0.13946533203125 +84289 0.028350830078125 +84290 0.17425537109375 +84291 0.05877685546875 +84292 0.188201904296875 +84293 0.08026123046875 +84294 0.171234130859375 +84295 0.087188720703125 +84296 0.118438720703125 +84297 0.076446533203125 +84298 0.05706787109375 +84299 0.06011962890625 +84300 -0.010711669921875 +84301 0.03857421875 +84302 -0.0914306640625 +84303 0.008209228515625 +84304 -0.162322998046875 +84305 -0.0205078125 +84306 -0.194549560546875 +84307 -0.0341796875 +84308 -0.1492919921875 +84309 -0.01446533203125 +84310 -0.02166748046875 +84311 0.041107177734375 +84312 0.124053955078125 +84313 0.102569580078125 +84314 0.211151123046875 +84315 0.1341552734375 +84316 0.240447998046875 +84317 0.1368408203125 +84318 0.242218017578125 +84319 0.12554931640625 +84320 0.2257080078125 +84321 0.10540771484375 +84322 0.194366455078125 +84323 0.07867431640625 +84324 0.115509033203125 +84325 0.030548095703125 +84326 0.0128173828125 +84327 -0.02716064453125 +84328 -0.053802490234375 +84329 -0.06573486328125 +84330 -0.110626220703125 +84331 -0.09722900390625 +84332 -0.199493408203125 +84333 -0.1412353515625 +84334 -0.29437255859375 +84335 -0.185455322265625 +84336 -0.33221435546875 +84337 -0.2001953125 +84338 -0.27972412109375 +84339 -0.170013427734375 +84340 -0.185333251953125 +84341 -0.118133544921875 +84342 -0.128204345703125 +84343 -0.082366943359375 +84344 -0.115692138671875 +84345 -0.066680908203125 +84346 -0.116455078125 +84347 -0.056854248046875 +84348 -0.105926513671875 +84349 -0.0418701171875 +84350 -0.053955078125 +84351 -0.008056640625 +84352 0.048797607421875 +84353 0.048492431640625 +84354 0.157318115234375 +84355 0.10614013671875 +84356 0.212005615234375 +84357 0.136474609375 +84358 0.218475341796875 +84359 0.14190673828125 +84360 0.23724365234375 +84361 0.150970458984375 +84362 0.30535888671875 +84363 0.18121337890625 +84364 0.38128662109375 +84365 0.213165283203125 +84366 0.404449462890625 +84367 0.218475341796875 +84368 0.3944091796875 +84369 0.206756591796875 +84370 0.3885498046875 +84371 0.196075439453125 +84372 0.362640380859375 +84373 0.175445556640625 +84374 0.27362060546875 +84375 0.12506103515625 +84376 0.11712646484375 +84377 0.043304443359375 +84378 -0.054901123046875 +84379 -0.04486083984375 +84380 -0.19085693359375 +84381 -0.114715576171875 +84382 -0.28570556640625 +84383 -0.16363525390625 +84384 -0.339263916015625 +84385 -0.191375732421875 +84386 -0.3775634765625 +84387 -0.210113525390625 +84388 -0.445709228515625 +84389 -0.24114990234375 +84390 -0.535064697265625 +84391 -0.280548095703125 +84392 -0.629058837890625 +84393 -0.3206787109375 +84394 -0.697601318359375 +84395 -0.34759521484375 +84396 -0.70391845703125 +84397 -0.344268798828125 +84398 -0.6424560546875 +84399 -0.3084716796875 +84400 -0.491241455078125 +84401 -0.230194091796875 +84402 -0.265716552734375 +84403 -0.11712646484375 +84404 -0.023712158203125 +84405 0.0030517578125 +84406 0.201751708984375 +84407 0.114471435546875 +84408 0.375823974609375 +84409 0.200439453125 +84410 0.485076904296875 +84411 0.25445556640625 +84412 0.56884765625 +84413 0.29498291015625 +84414 0.634765625 +84415 0.32562255859375 +84416 0.63763427734375 +84417 0.325103759765625 +84418 0.5660400390625 +84419 0.288177490234375 +84420 0.4720458984375 +84421 0.239593505859375 +84422 0.40692138671875 +84423 0.203826904296875 +84424 0.3778076171875 +84425 0.1845703125 +84426 0.376953125 +84427 0.178466796875 +84428 0.371978759765625 +84429 0.170562744140625 +84430 0.313140869140625 +84431 0.137664794921875 +84432 0.184417724609375 +84433 0.072479248046875 +84434 0.011199951171875 +84435 -0.01275634765625 +84436 -0.171051025390625 +84437 -0.10113525390625 +84438 -0.33740234375 +84439 -0.180816650390625 +84440 -0.47198486328125 +84441 -0.244293212890625 +84442 -0.560394287109375 +84443 -0.2847900390625 +84444 -0.58056640625 +84445 -0.2919921875 +84446 -0.54754638671875 +84447 -0.273162841796875 +84448 -0.508575439453125 +84449 -0.250823974609375 +84450 -0.459503173828125 +84451 -0.223236083984375 +84452 -0.394378662109375 +84453 -0.1878662109375 +84454 -0.35260009765625 +84455 -0.163543701171875 +84456 -0.31170654296875 +84457 -0.139892578125 +84458 -0.197418212890625 +84459 -0.08209228515625 +84460 -0.007965087890625 +84461 0.010467529296875 +84462 0.207489013671875 +84463 0.114410400390625 +84464 0.409210205078125 +84465 0.21087646484375 +84466 0.57208251953125 +84467 0.287994384765625 +84468 0.66595458984375 +84469 0.331573486328125 +84470 0.65875244140625 +84471 0.326507568359375 +84472 0.56744384765625 +84473 0.28094482421875 +84474 0.431396484375 +84475 0.213623046875 +84476 0.29443359375 +84477 0.1453857421875 +84478 0.182464599609375 +84479 0.088714599609375 +84480 0.06365966796875 +84481 0.029266357421875 +84482 -0.075958251953125 +84483 -0.039276123046875 +84484 -0.189422607421875 +84485 -0.095916748046875 +84486 -0.271942138671875 +84487 -0.138092041015625 +84488 -0.342529296875 +84489 -0.173797607421875 +84490 -0.364166259765625 +84491 -0.186553955078125 +84492 -0.327239990234375 +84493 -0.171966552734375 +84494 -0.2769775390625 +84495 -0.149871826171875 +84496 -0.253692626953125 +84497 -0.1380615234375 +84498 -0.24365234375 +84499 -0.130615234375 +84500 -0.1983642578125 +84501 -0.106414794921875 +84502 -0.116241455078125 +84503 -0.065032958984375 +84504 -0.036834716796875 +84505 -0.024169921875 +84506 0.034881591796875 +84507 0.013580322265625 +84508 0.09124755859375 +84509 0.044525146484375 +84510 0.10888671875 +84511 0.05804443359375 +84512 0.125518798828125 +84513 0.070404052734375 +84514 0.15771484375 +84515 0.088623046875 +84516 0.17828369140625 +84517 0.100555419921875 +84518 0.17108154296875 +84519 0.09893798828125 +84520 0.129974365234375 +84521 0.081085205078125 +84522 0.082427978515625 +84523 0.05908203125 +84524 0.027679443359375 +84525 0.03271484375 +84526 -0.065643310546875 +84527 -0.01165771484375 +84528 -0.15936279296875 +84529 -0.057037353515625 +84530 -0.21307373046875 +84531 -0.08538818359375 +84532 -0.234649658203125 +84533 -0.09991455078125 +84534 -0.2001953125 +84535 -0.08978271484375 +84536 -0.119171142578125 +84537 -0.05889892578125 +84538 -0.024749755859375 +84539 -0.021636962890625 +84540 0.085784912109375 +84541 0.023406982421875 +84542 0.178131103515625 +84543 0.061309814453125 +84544 0.215576171875 +84545 0.0760498046875 +84546 0.211456298828125 +84547 0.07354736328125 +84548 0.17523193359375 +84549 0.058013916015625 +84550 0.128753662109375 +84551 0.03900146484375 +84552 0.1019287109375 +84553 0.029571533203125 +84554 0.0743408203125 +84555 0.02056884765625 +84556 0.04327392578125 +84557 0.0106201171875 +84558 0.038177490234375 +84559 0.012451171875 +84560 0.076263427734375 +84561 0.03338623046875 +84562 0.14105224609375 +84563 0.065948486328125 +84564 0.186431884765625 +84565 0.08966064453125 +84566 0.188812255859375 +84567 0.09393310546875 +84568 0.1390380859375 +84569 0.074554443359375 +84570 0.041778564453125 +84571 0.033477783203125 +84572 -0.079437255859375 +84573 -0.01898193359375 +84574 -0.219390869140625 +84575 -0.08056640625 +84576 -0.367828369140625 +84577 -0.146728515625 +84578 -0.494873046875 +84579 -0.204254150390625 +84580 -0.556243896484375 +84581 -0.233551025390625 +84582 -0.508697509765625 +84583 -0.2154541015625 +84584 -0.3756103515625 +84585 -0.16009521484375 +84586 -0.218902587890625 +84587 -0.094512939453125 +84588 -0.063751220703125 +84589 -0.02960205078125 +84590 0.091552734375 +84591 0.0355224609375 +84592 0.23602294921875 +84593 0.096221923828125 +84594 0.342987060546875 +84595 0.140899658203125 +84596 0.39520263671875 +84597 0.162109375 +84598 0.389373779296875 +84599 0.158477783203125 +84600 0.324249267578125 +84601 0.129486083984375 +84602 0.224090576171875 +84603 0.0858154296875 +84604 0.124267578125 +84605 0.042999267578125 +84606 0.037078857421875 +84607 0.00634765625 +84608 -0.010101318359375 +84609 -0.012176513671875 +84610 -0.019439697265625 +84611 -0.013702392578125 +84612 -0.022796630859375 +84613 -0.012359619140625 +84614 -0.001556396484375 +84615 -0.0001220703125 +84616 0.056304931640625 +84617 0.028076171875 +84618 0.106719970703125 +84619 0.052703857421875 +84620 0.096893310546875 +84621 0.050445556640625 +84622 0.042694091796875 +84623 0.028167724609375 +84624 -0.018035888671875 +84625 0.00244140625 +84626 -0.07586669921875 +84627 -0.0225830078125 +84628 -0.11944580078125 +84629 -0.04193115234375 +84630 -0.15972900390625 +84631 -0.060394287109375 +84632 -0.202606201171875 +84633 -0.08050537109375 +84634 -0.24859619140625 +84635 -0.102386474609375 +84636 -0.30517578125 +84637 -0.12921142578125 +84638 -0.36212158203125 +84639 -0.1563720703125 +84640 -0.39141845703125 +84641 -0.171478271484375 +84642 -0.35528564453125 +84643 -0.157745361328125 +84644 -0.249969482421875 +84645 -0.1134033203125 +84646 -0.092864990234375 +84647 -0.0460205078125 +84648 0.08905029296875 +84649 0.0325927734375 +84650 0.2352294921875 +84651 0.095855712890625 +84652 0.318817138671875 +84653 0.13201904296875 +84654 0.358642578125 +84655 0.149383544921875 +84656 0.347747802734375 +84657 0.1448974609375 +84658 0.28564453125 +84659 0.118316650390625 +84660 0.223175048828125 +84661 0.091949462890625 +84662 0.196746826171875 +84663 0.08172607421875 +84664 0.179840087890625 +84665 0.075927734375 +84666 0.155548095703125 +84667 0.0670166015625 +84668 0.151214599609375 +84669 0.06689453125 +84670 0.156951904296875 +84671 0.071136474609375 +84672 0.13177490234375 +84673 0.06158447265625 +84674 0.100799560546875 +84675 0.04925537109375 +84676 0.087127685546875 +84677 0.04425048828125 +84678 0.05487060546875 +84679 0.030731201171875 +84680 -0.009002685546875 +84681 0.002899169921875 +84682 -0.10400390625 +84683 -0.03900146484375 +84684 -0.229400634765625 +84685 -0.094635009765625 +84686 -0.35552978515625 +84687 -0.15087890625 +84688 -0.441925048828125 +84689 -0.18988037109375 +84690 -0.473846435546875 +84691 -0.20513916015625 +84692 -0.464813232421875 +84693 -0.2025146484375 +84694 -0.419097900390625 +84695 -0.18377685546875 +84696 -0.334320068359375 +84697 -0.1478271484375 +84698 -0.227935791015625 +84699 -0.102264404296875 +84700 -0.12347412109375 +84701 -0.057373046875 +84702 -0.02764892578125 +84703 -0.01605224609375 +84704 0.077667236328125 +84705 0.0296630859375 +84706 0.2132568359375 +84707 0.0889892578125 +84708 0.38885498046875 +84709 0.166168212890625 +84710 0.582794189453125 +84711 0.251678466796875 +84712 0.734039306640625 +84713 0.31866455078125 +84714 0.800140380859375 +84715 0.348388671875 +84716 0.7783203125 +84717 0.339599609375 +84718 0.6651611328125 +84719 0.290740966796875 +84720 0.45965576171875 +84721 0.201324462890625 +84722 0.199188232421875 +84723 0.0877685546875 +84724 -0.050689697265625 +84725 -0.021148681640625 +84726 -0.23297119140625 +84727 -0.100372314453125 +84728 -0.33013916015625 +84729 -0.14227294921875 +84730 -0.368408203125 +84731 -0.158416748046875 +84732 -0.378936767578125 +84733 -0.162567138671875 +84734 -0.376983642578125 +84735 -0.161468505859375 +84736 -0.37969970703125 +84737 -0.16259765625 +84738 -0.391510009765625 +84739 -0.167877197265625 +84740 -0.385345458984375 +84741 -0.165985107421875 +84742 -0.3419189453125 +84743 -0.1488037109375 +84744 -0.28289794921875 +84745 -0.124969482421875 +84746 -0.251617431640625 +84747 -0.112030029296875 +84748 -0.266143798828125 +84749 -0.117279052734375 +84750 -0.273345947265625 +84751 -0.119049072265625 +84752 -0.216796875 +84753 -0.0943603515625 +84754 -0.128265380859375 +84755 -0.05621337890625 +84756 -0.068145751953125 +84757 -0.02935791015625 +84758 -0.0430908203125 +84759 -0.01666259765625 +84760 -0.024444580078125 +84761 -0.006591796875 +84762 0.020721435546875 +84763 0.01409912109375 +84764 0.124481201171875 +84765 0.058380126953125 +84766 0.25787353515625 +84767 0.11431884765625 +84768 0.379119873046875 +84769 0.164764404296875 +84770 0.47991943359375 +84771 0.206329345703125 +84772 0.5281982421875 +84773 0.225860595703125 +84774 0.511138916015625 +84775 0.218170166015625 +84776 0.456207275390625 +84777 0.19451904296875 +84778 0.407470703125 +84779 0.173004150390625 +84780 0.383758544921875 +84781 0.161376953125 +84782 0.35687255859375 +84783 0.148223876953125 +84784 0.31182861328125 +84785 0.1275634765625 +84786 0.250885009765625 +84787 0.1004638671875 +84788 0.1654052734375 +84789 0.063507080078125 +84790 0.035247802734375 +84791 0.00860595703125 +84792 -0.142059326171875 +84793 -0.065155029296875 +84794 -0.33563232421875 +84795 -0.14508056640625 +84796 -0.5345458984375 +84797 -0.2266845703125 +84798 -0.72186279296875 +84799 -0.30303955078125 +84800 -0.836669921875 +84801 -0.34930419921875 +84802 -0.8326416015625 +84803 -0.34661865234375 +84804 -0.7296142578125 +84805 -0.303192138671875 +84806 -0.582550048828125 +84807 -0.241546630859375 +84808 -0.440093994140625 +84809 -0.18157958984375 +84810 -0.324310302734375 +84811 -0.132415771484375 +84812 -0.20147705078125 +84813 -0.080413818359375 +84814 -0.044647216796875 +84815 -0.014678955078125 +84816 0.103973388671875 +84817 0.0474853515625 +84818 0.202392578125 +84819 0.088836669921875 +84820 0.264495849609375 +84821 0.114990234375 +84822 0.338897705078125 +84823 0.145751953125 +84824 0.443817138671875 +84825 0.18853759765625 +84826 0.545074462890625 +84827 0.22943115234375 +84828 0.6173095703125 +84829 0.258087158203125 +84830 0.6524658203125 +84831 0.27130126953125 +84832 0.66339111328125 +84833 0.274383544921875 +84834 0.6561279296875 +84835 0.269866943359375 +84836 0.606781005859375 +84837 0.24810791015625 +84838 0.501190185546875 +84839 0.203399658203125 +84840 0.352783203125 +84841 0.141326904296875 +84842 0.176544189453125 +84843 0.068084716796875 +84844 -0.034820556640625 +84845 -0.01922607421875 +84846 -0.258209228515625 +84847 -0.111114501953125 +84848 -0.44244384765625 +84849 -0.1866455078125 +84850 -0.5753173828125 +84851 -0.2408447265625 +84852 -0.65203857421875 +84853 -0.27178955078125 +84854 -0.641632080078125 +84855 -0.266845703125 +84856 -0.562164306640625 +84857 -0.23345947265625 +84858 -0.458038330078125 +84859 -0.1898193359375 +84860 -0.350555419921875 +84861 -0.1446533203125 +84862 -0.260528564453125 +84863 -0.106536865234375 +84864 -0.192108154296875 +84865 -0.0772705078125 +84866 -0.141937255859375 +84867 -0.055511474609375 +84868 -0.1021728515625 +84869 -0.03814697265625 +84870 -0.062896728515625 +84871 -0.02117919921875 +84872 -0.011932373046875 +84873 0.000274658203125 +84874 0.062835693359375 +84875 0.031158447265625 +84876 0.148712158203125 +84877 0.0662841796875 +84878 0.241729736328125 +84879 0.10400390625 +84880 0.34912109375 +84881 0.147308349609375 +84882 0.457305908203125 +84883 0.190673828125 +84884 0.54388427734375 +84885 0.22503662109375 +84886 0.5728759765625 +84887 0.235748291015625 +84888 0.506591796875 +84889 0.20751953125 +84890 0.351226806640625 +84891 0.1429443359375 +84892 0.146514892578125 +84893 0.05828857421875 +84894 -0.05523681640625 +84895 -0.0250244140625 +84896 -0.21624755859375 +84897 -0.091522216796875 +84898 -0.334930419921875 +84899 -0.140533447265625 +84900 -0.402984619140625 +84901 -0.16864013671875 +84902 -0.4412841796875 +84903 -0.184326171875 +84904 -0.49578857421875 +84905 -0.20635986328125 +84906 -0.5601806640625 +84907 -0.232208251953125 +84908 -0.600738525390625 +84909 -0.248138427734375 +84910 -0.584228515625 +84911 -0.240631103515625 +84912 -0.47930908203125 +84913 -0.196929931640625 +84914 -0.27935791015625 +84915 -0.1143798828125 +84916 -0.0089111328125 +84917 -0.0030517578125 +84918 0.268798828125 +84919 0.11114501953125 +84920 0.482818603515625 +84921 0.199249267578125 +84922 0.60369873046875 +84923 0.24920654296875 +84924 0.650421142578125 +84925 0.268707275390625 +84926 0.66400146484375 +84927 0.27447509765625 +84928 0.6414794921875 +84929 0.26531982421875 +84930 0.572540283203125 +84931 0.237030029296875 +84932 0.498138427734375 +84933 0.206329345703125 +84934 0.439453125 +84935 0.181884765625 +84936 0.375518798828125 +84937 0.155181884765625 +84938 0.274505615234375 +84939 0.113250732421875 +84940 0.1087646484375 +84941 0.04486083984375 +84942 -0.099395751953125 +84943 -0.04083251953125 +84944 -0.3182373046875 +84945 -0.130828857421875 +84946 -0.5489501953125 +84947 -0.2255859375 +84948 -0.7738037109375 +84949 -0.31781005859375 +84950 -0.86383056640625 +84951 -0.3858642578125 +84952 -0.870391845703125 +84953 -0.41619873046875 +84954 -0.86895751953125 +84955 -0.416015625 +84956 -0.861053466796875 +84957 -0.39068603515625 +84958 -0.765869140625 +84959 -0.33319091796875 +84960 -0.5301513671875 +84961 -0.23895263671875 +84962 -0.214691162109375 +84963 -0.110870361328125 +84964 0.137359619140625 +84965 0.033416748046875 +84966 0.474822998046875 +84967 0.172943115234375 +84968 0.76239013671875 +84969 0.293182373046875 +84970 0.867462158203125 +84971 0.383087158203125 +84972 0.870361328125 +84973 0.44281005859375 +84974 0.86480712890625 +84975 0.46759033203125 +84976 0.831817626953125 +84977 0.459625244140625 +84978 0.677581787109375 +84979 0.428863525390625 +84980 0.495880126953125 +84981 0.377655029296875 +84982 0.30767822265625 +84983 0.3135986328125 +84984 0.116180419921875 +84985 0.237579345703125 +84986 -0.110748291015625 +84987 0.136688232421875 +84988 -0.381805419921875 +84989 0.00811767578125 +84990 -0.6572265625 +84991 -0.130615234375 +84992 -0.857421875 +84993 -0.25518798828125 +84994 -0.870391845703125 +84995 -0.34820556640625 +84996 -0.870391845703125 +84997 -0.406585693359375 +84998 -0.86444091796875 +84999 -0.440460205078125 +85000 -0.85723876953125 +85001 -0.46337890625 +85002 -0.790008544921875 +85003 -0.46868896484375 +85004 -0.62847900390625 +85005 -0.436279296875 +85006 -0.3956298828125 +85007 -0.36529541015625 +85008 -0.126708984375 +85009 -0.26849365234375 +85010 0.150115966796875 +85011 -0.1566162109375 +85012 0.424041748046875 +85013 -0.03448486328125 +85014 0.670623779296875 +85015 0.0872802734375 +85016 0.854522705078125 +85017 0.193695068359375 +85018 0.866485595703125 +85019 0.27777099609375 +85020 0.86920166015625 +85021 0.333404541015625 +85022 0.8653564453125 +85023 0.3671875 +85024 0.857147216796875 +85025 0.384033203125 +85026 0.766845703125 +85027 0.38275146484375 +85028 0.628509521484375 +85029 0.36529541015625 +85030 0.462127685546875 +85031 0.3292236328125 +85032 0.297210693359375 +85033 0.284454345703125 +85034 0.14862060546875 +85035 0.23590087890625 +85036 -0.00537109375 +85037 0.175262451171875 +85038 -0.15753173828125 +85039 0.105712890625 +85040 -0.31304931640625 +85041 0.0262451171875 +85042 -0.48876953125 +85043 -0.068023681640625 +85044 -0.6416015625 +85045 -0.159149169921875 +85046 -0.751373291015625 +85047 -0.237548828125 +85048 -0.84619140625 +85049 -0.31170654296875 +85050 -0.861297607421875 +85051 -0.37591552734375 +85052 -0.863250732421875 +85053 -0.417633056640625 +85054 -0.856597900390625 +85055 -0.424957275390625 +85056 -0.7498779296875 +85057 -0.40252685546875 +85058 -0.624542236328125 +85059 -0.372222900390625 +85060 -0.47808837890625 +85061 -0.325958251953125 +85062 -0.253387451171875 +85063 -0.242034912109375 +85064 0.003692626953125 +85065 -0.137908935546875 +85066 0.2257080078125 +85067 -0.03955078125 +85068 0.427154541015625 +85069 0.05743408203125 +85070 0.643218994140625 +85071 0.164947509765625 +85072 0.855926513671875 +85073 0.279083251953125 +85074 0.870361328125 +85075 0.377838134765625 +85076 0.870361328125 +85077 0.4423828125 +85078 0.862762451171875 +85079 0.475311279296875 +85080 0.79669189453125 +85081 0.475494384765625 +85082 0.595794677734375 +85083 0.43939208984375 +85084 0.362152099609375 +85085 0.37811279296875 +85086 0.1270751953125 +85087 0.302337646484375 +85088 -0.086944580078125 +85089 0.220245361328125 +85090 -0.2784423828125 +85091 0.13287353515625 +85092 -0.484832763671875 +85093 0.027374267578125 +85094 -0.729583740234375 +85095 -0.103179931640625 +85096 -0.86688232421875 +85097 -0.239471435546875 +85098 -0.870391845703125 +85099 -0.357421875 +85100 -0.86859130859375 +85101 -0.4549560546875 +85102 -0.86279296875 +85103 -0.531158447265625 +85104 -0.817962646484375 +85105 -0.572357177734375 +85106 -0.6116943359375 +85107 -0.5614013671875 +85108 -0.3128662109375 +85109 -0.49566650390625 +85110 0.039398193359375 +85111 -0.38787841796875 +85112 0.422821044921875 +85113 -0.245697021484375 +85114 0.805145263671875 +85115 -0.081817626953125 +85116 0.870361328125 +85117 0.077911376953125 +85118 0.870361328125 +85119 0.2117919921875 +85120 0.860015869140625 +85121 0.315185546875 +85122 0.727935791015625 +85123 0.3848876953125 +85124 0.48114013671875 +85125 0.418487548828125 +85126 0.2059326171875 +85127 0.4248046875 +85128 -0.06103515625 +85129 0.412109375 +85130 -0.29913330078125 +85131 0.384033203125 +85132 -0.516204833984375 +85133 0.33502197265625 +85134 -0.7252197265625 +85135 0.25927734375 +85136 -0.85980224609375 +85137 0.16619873046875 +85138 -0.870391845703125 +85139 0.068878173828125 +85140 -0.870391845703125 +85141 -0.021331787109375 +85142 -0.858062744140625 +85143 -0.085845947265625 +85144 -0.673004150390625 +85145 -0.122711181640625 +85146 -0.42694091796875 +85147 -0.15130615234375 +85148 -0.2100830078125 +85149 -0.18792724609375 +85150 -0.0362548828125 +85151 -0.23138427734375 +85152 0.10943603515625 +85153 -0.2703857421875 +85154 0.23516845703125 +85155 -0.29718017578125 +85156 0.373687744140625 +85157 -0.29595947265625 +85158 0.517791748046875 +85159 -0.267364501953125 +85160 0.602783203125 +85161 -0.23504638671875 +85162 0.635711669921875 +85163 -0.197113037109375 +85164 0.655181884765625 +85165 -0.14117431640625 +85166 0.65948486328125 +85167 -0.071197509765625 +85168 0.651275634765625 +85169 0.009490966796875 +85170 0.61846923828125 +85171 0.091339111328125 +85172 0.53753662109375 +85173 0.160064697265625 +85174 0.404144287109375 +85175 0.208465576171875 +85176 0.22186279296875 +85177 0.232574462890625 +85178 0.003997802734375 +85179 0.232513427734375 +85180 -0.22100830078125 +85181 0.214813232421875 +85182 -0.42449951171875 +85183 0.187042236328125 +85184 -0.579833984375 +85185 0.157073974609375 +85186 -0.641876220703125 +85187 0.140899658203125 +85188 -0.6177978515625 +85189 0.13604736328125 +85190 -0.575531005859375 +85191 0.11834716796875 +85192 -0.526336669921875 +85193 0.085968017578125 +85194 -0.42645263671875 +85195 0.058624267578125 +85196 -0.2581787109375 +85197 0.046905517578125 +85198 -0.068695068359375 +85199 0.037445068359375 +85200 0.09222412109375 +85201 0.01611328125 +85202 0.232147216796875 +85203 -0.009735107421875 +85204 0.3509521484375 +85205 -0.03594970703125 +85206 0.410064697265625 +85207 -0.073394775390625 +85208 0.372955322265625 +85209 -0.132843017578125 +85210 0.2554931640625 +85211 -0.206268310546875 +85212 0.10711669921875 +85213 -0.273956298828125 +85214 -0.052886962890625 +85215 -0.3284912109375 +85216 -0.186279296875 +85217 -0.3563232421875 +85218 -0.23291015625 +85219 -0.3365478515625 +85220 -0.209442138671875 +85221 -0.277862548828125 +85222 -0.174163818359375 +85223 -0.205291748046875 +85224 -0.126739501953125 +85225 -0.122222900390625 +85226 -0.048126220703125 +85227 -0.025238037109375 +85228 0.0426025390625 +85229 0.07476806640625 +85230 0.10748291015625 +85231 0.15997314453125 +85232 0.1409912109375 +85233 0.22509765625 +85234 0.19708251953125 +85235 0.287811279296875 +85236 0.273651123046875 +85237 0.345367431640625 +85238 0.31768798828125 +85239 0.376617431640625 +85240 0.341094970703125 +85241 0.38568115234375 +85242 0.368011474609375 +85243 0.38201904296875 +85244 0.37249755859375 +85245 0.3570556640625 +85246 0.30072021484375 +85247 0.2923583984375 +85248 0.1517333984375 +85249 0.18975830078125 +85250 -0.01470947265625 +85251 0.074371337890625 +85252 -0.1883544921875 +85253 -0.046051025390625 +85254 -0.372711181640625 +85255 -0.169342041015625 +85256 -0.51397705078125 +85257 -0.2734375 +85258 -0.57177734375 +85259 -0.341339111328125 +85260 -0.53948974609375 +85261 -0.368377685546875 +85262 -0.43511962890625 +85263 -0.359039306640625 +85264 -0.2962646484375 +85265 -0.325347900390625 +85266 -0.161102294921875 +85267 -0.2802734375 +85268 -0.0435791015625 +85269 -0.228973388671875 +85270 0.060394287109375 +85271 -0.17095947265625 +85272 0.13665771484375 +85273 -0.112701416015625 +85274 0.170135498046875 +85275 -0.0615234375 +85276 0.16552734375 +85277 -0.018157958984375 +85278 0.15728759765625 +85279 0.02679443359375 +85280 0.150787353515625 +85281 0.072509765625 +85282 0.12200927734375 +85283 0.10797119140625 +85284 0.080108642578125 +85285 0.13397216796875 +85286 0.05126953125 +85287 0.1575927734375 +85288 0.062896728515625 +85289 0.186767578125 +85290 0.09271240234375 +85291 0.212615966796875 +85292 0.092987060546875 +85293 0.217864990234375 +85294 0.07855224609375 +85295 0.20770263671875 +85296 0.06427001953125 +85297 0.187896728515625 +85298 0.0347900390625 +85299 0.1541748046875 +85300 -0.01171875 +85301 0.107421875 +85302 -0.056060791015625 +85303 0.05621337890625 +85304 -0.055511474609375 +85305 0.017578125 +85306 -0.010467529296875 +85307 -0.006378173828125 +85308 0.02508544921875 +85309 -0.032318115234375 +85310 0.025665283203125 +85311 -0.067108154296875 +85312 0.017333984375 +85313 -0.099822998046875 +85314 0.00189208984375 +85315 -0.128387451171875 +85316 -0.03173828125 +85317 -0.155609130859375 +85318 -0.071502685546875 +85319 -0.176666259765625 +85320 -0.13543701171875 +85321 -0.19769287109375 +85322 -0.219970703125 +85323 -0.217742919921875 +85324 -0.300506591796875 +85325 -0.22894287109375 +85326 -0.376312255859375 +85327 -0.232208251953125 +85328 -0.416107177734375 +85329 -0.218048095703125 +85330 -0.371124267578125 +85331 -0.171051025390625 +85332 -0.242279052734375 +85333 -0.09332275390625 +85334 -0.069732666015625 +85335 -0.000762939453125 +85336 0.125640869140625 +85337 0.097564697265625 +85338 0.31268310546875 +85339 0.189178466796875 +85340 0.45501708984375 +85341 0.260009765625 +85342 0.554779052734375 +85343 0.309814453125 +85344 0.61065673828125 +85345 0.3375244140625 +85346 0.610931396484375 +85347 0.33880615234375 +85348 0.531463623046875 +85349 0.305328369140625 +85350 0.3883056640625 +85351 0.24322509765625 +85352 0.23468017578125 +85353 0.17193603515625 +85354 0.095245361328125 +85355 0.10125732421875 +85356 -0.00396728515625 +85357 0.041595458984375 +85358 -0.04852294921875 +85359 -0.00054931640625 +85360 -0.055145263671875 +85361 -0.029541015625 +85362 -0.0758056640625 +85363 -0.062103271484375 +85364 -0.138702392578125 +85365 -0.106781005859375 +85366 -0.209197998046875 +85367 -0.1502685546875 +85368 -0.289031982421875 +85369 -0.1922607421875 +85370 -0.37884521484375 +85371 -0.23236083984375 +85372 -0.456329345703125 +85373 -0.262451171875 +85374 -0.51641845703125 +85375 -0.28076171875 +85376 -0.519287109375 +85377 -0.27362060546875 +85378 -0.458251953125 +85379 -0.23931884765625 +85380 -0.384796142578125 +85381 -0.19671630859375 +85382 -0.323699951171875 +85383 -0.155517578125 +85384 -0.269287109375 +85385 -0.114898681640625 +85386 -0.1951904296875 +85387 -0.06683349609375 +85388 -0.100006103515625 +85389 -0.0120849609375 +85390 -0.01055908203125 +85391 0.038787841796875 +85392 0.1033935546875 +85393 0.0953369140625 +85394 0.24908447265625 +85395 0.1593017578125 +85396 0.373199462890625 +85397 0.21142578125 +85398 0.45806884765625 +85399 0.245147705078125 +85400 0.511474609375 +85401 0.26312255859375 +85402 0.565399169921875 +85403 0.276702880859375 +85404 0.61138916015625 +85405 0.283355712890625 +85406 0.5897216796875 +85407 0.2628173828125 +85408 0.4906005859375 +85409 0.212432861328125 +85410 0.33148193359375 +85411 0.1392822265625 +85412 0.147796630859375 +85413 0.0567626953125 +85414 -0.01873779296875 +85415 -0.01947021484375 +85416 -0.140289306640625 +85417 -0.078704833984375 +85418 -0.191986083984375 +85419 -0.11138916015625 +85420 -0.184295654296875 +85421 -0.120452880859375 +85422 -0.161834716796875 +85423 -0.120941162109375 +85424 -0.166595458984375 +85425 -0.127197265625 +85426 -0.19390869140625 +85427 -0.137420654296875 +85428 -0.22442626953125 +85429 -0.144927978515625 +85430 -0.279754638671875 +85431 -0.157562255859375 +85432 -0.3389892578125 +85433 -0.168487548828125 +85434 -0.3543701171875 +85435 -0.16162109375 +85436 -0.348175048828125 +85437 -0.145477294921875 +85438 -0.32598876953125 +85439 -0.122833251953125 +85440 -0.2581787109375 +85441 -0.08416748046875 +85442 -0.139801025390625 +85443 -0.028564453125 +85444 0.014617919921875 +85445 0.03814697265625 +85446 0.144378662109375 +85447 0.094024658203125 +85448 0.221038818359375 +85449 0.128631591796875 +85450 0.27069091796875 +85451 0.1507568359375 +85452 0.294036865234375 +85453 0.160491943359375 +85454 0.311767578125 +85455 0.16510009765625 +85456 0.339141845703125 +85457 0.170074462890625 +85458 0.360260009765625 +85459 0.17010498046875 +85460 0.360504150390625 +85461 0.16058349609375 +85462 0.308380126953125 +85463 0.13128662109375 +85464 0.18170166015625 +85465 0.07525634765625 +85466 0.0047607421875 +85467 0.001617431640625 +85468 -0.17559814453125 +85469 -0.07281494140625 +85470 -0.3143310546875 +85471 -0.13189697265625 +85472 -0.36785888671875 +85473 -0.1600341796875 +85474 -0.36248779296875 +85475 -0.165802001953125 +85476 -0.343536376953125 +85477 -0.164398193359375 +85478 -0.3018798828125 +85479 -0.152496337890625 +85480 -0.231414794921875 +85481 -0.1279296875 +85482 -0.117645263671875 +85483 -0.0858154296875 +85484 0.007049560546875 +85485 -0.037567138671875 +85486 0.087982177734375 +85487 -0.002288818359375 +85488 0.13946533203125 +85489 0.0244140625 +85490 0.17425537109375 +85491 0.046417236328125 +85492 0.188201904296875 +85493 0.06170654296875 +85494 0.171234130859375 +85495 0.06622314453125 +85496 0.118438720703125 +85497 0.057708740234375 +85498 0.05706787109375 +85499 0.045074462890625 +85500 -0.010711669921875 +85501 0.028594970703125 +85502 -0.0914306640625 +85503 0.005706787109375 +85504 -0.162322998046875 +85505 -0.0155029296875 +85506 -0.194549560546875 +85507 -0.025421142578125 +85508 -0.1492919921875 +85509 -0.012176513671875 +85510 -0.02166748046875 +85511 0.025482177734375 +85512 0.124053955078125 +85513 0.0673828125 +85514 0.211151123046875 +85515 0.089630126953125 +85516 0.240447998046875 +85517 0.0926513671875 +85518 0.242218017578125 +85519 0.086181640625 +85520 0.2257080078125 +85521 0.073516845703125 +85522 0.194366455078125 +85523 0.056121826171875 +85524 0.115509033203125 +85525 0.024200439453125 +85526 0.0128173828125 +85527 -0.014404296875 +85528 -0.053802490234375 +85529 -0.0406494140625 +85530 -0.110626220703125 +85531 -0.06243896484375 +85532 -0.199493408203125 +85533 -0.0926513671875 +85534 -0.29437255859375 +85535 -0.123046875 +85536 -0.33221435546875 +85537 -0.133941650390625 +85538 -0.27972412109375 +85539 -0.11505126953125 +85540 -0.185333251953125 +85541 -0.0816650390625 +85542 -0.128204345703125 +85543 -0.058685302734375 +85544 -0.115692138671875 +85545 -0.0487060546875 +85546 -0.116455078125 +85547 -0.042327880859375 +85548 -0.105926513671875 +85549 -0.032257080078125 +85550 -0.053955078125 +85551 -0.00946044921875 +85552 0.048797607421875 +85553 0.028564453125 +85554 0.157318115234375 +85555 0.0675048828125 +85556 0.212005615234375 +85557 0.0885009765625 +85558 0.218475341796875 +85559 0.0931396484375 +85560 0.23724365234375 +85561 0.100189208984375 +85562 0.30535888671875 +85563 0.121185302734375 +85564 0.38128662109375 +85565 0.1431884765625 +85566 0.404449462890625 +85567 0.147430419921875 +85568 0.3944091796875 +85569 0.140228271484375 +85570 0.3885498046875 +85571 0.133514404296875 +85572 0.362640380859375 +85573 0.120025634765625 +85574 0.27362060546875 +85575 0.08660888671875 +85576 0.11712646484375 +85577 0.032257080078125 +85578 -0.054901123046875 +85579 -0.0264892578125 +85580 -0.19085693359375 +85581 -0.07330322265625 +85582 -0.28570556640625 +85583 -0.10638427734375 +85584 -0.339263916015625 +85585 -0.12554931640625 +85586 -0.3775634765625 +85587 -0.138763427734375 +85588 -0.445709228515625 +85589 -0.16009521484375 +85590 -0.535064697265625 +85591 -0.1868896484375 +85592 -0.629058837890625 +85593 -0.21405029296875 +85594 -0.697601318359375 +85595 -0.232330322265625 +85596 -0.70391845703125 +85597 -0.230438232421875 +85598 -0.6424560546875 +85599 -0.2069091796875 +85600 -0.491241455078125 +85601 -0.155120849609375 +85602 -0.265716552734375 +85603 -0.08013916015625 +85604 -0.023712158203125 +85605 -0.000274658203125 +85606 0.201751708984375 +85607 0.073883056640625 +85608 0.375823974609375 +85609 0.13128662109375 +85610 0.485076904296875 +85611 0.1676025390625 +85612 0.56884765625 +85613 0.19500732421875 +85614 0.634765625 +85615 0.215850830078125 +85616 0.63763427734375 +85617 0.216064453125 +85618 0.5660400390625 +85619 0.192138671875 +85620 0.4720458984375 +85621 0.160430908203125 +85622 0.40692138671875 +85623 0.137054443359375 +85624 0.3778076171875 +85625 0.12445068359375 +85626 0.376953125 +85627 0.12042236328125 +85628 0.371978759765625 +85629 0.11505126953125 +85630 0.313140869140625 +85631 0.093048095703125 +85632 0.184417724609375 +85633 0.049591064453125 +85634 0.011199951171875 +85635 -0.007171630859375 +85636 -0.171051025390625 +85637 -0.066070556640625 +85638 -0.33740234375 +85639 -0.119232177734375 +85640 -0.47198486328125 +85641 -0.161651611328125 +85642 -0.560394287109375 +85643 -0.1888427734375 +85644 -0.58056640625 +85645 -0.1939697265625 +85646 -0.54754638671875 +85647 -0.18182373046875 +85648 -0.508575439453125 +85649 -0.167266845703125 +85650 -0.459503173828125 +85651 -0.149139404296875 +85652 -0.394378662109375 +85653 -0.125732421875 +85654 -0.35260009765625 +85655 -0.109527587890625 +85656 -0.31170654296875 +85657 -0.09368896484375 +85658 -0.197418212890625 +85659 -0.055206298828125 +85660 -0.007965087890625 +85661 0.00628662109375 +85662 0.207489013671875 +85663 0.075347900390625 +85664 0.409210205078125 +85665 0.13946533203125 +85666 0.57208251953125 +85667 0.190765380859375 +85668 0.66595458984375 +85669 0.2198486328125 +85670 0.65875244140625 +85671 0.21673583984375 +85672 0.56744384765625 +85673 0.186798095703125 +85674 0.431396484375 +85675 0.142425537109375 +85676 0.29443359375 +85677 0.097412109375 +85678 0.182464599609375 +85679 0.0599365234375 +85680 0.06365966796875 +85681 0.020233154296875 +85682 -0.075958251953125 +85683 -0.025909423828125 +85684 -0.189422607421875 +85685 -0.063690185546875 +85686 -0.271942138671875 +85687 -0.091461181640625 +85688 -0.342529296875 +85689 -0.11505126953125 +85690 -0.364166259765625 +85691 -0.122894287109375 +85692 -0.327239990234375 +85693 -0.111907958984375 +85694 -0.2769775390625 +85695 -0.09619140625 +85696 -0.253692626953125 +85697 -0.088348388671875 +85698 -0.24365234375 +85699 -0.0841064453125 +85700 -0.1983642578125 +85701 -0.06842041015625 +85702 -0.116241455078125 +85703 -0.040924072265625 +85704 -0.036834716796875 +85705 -0.014068603515625 +85706 0.034881591796875 +85707 0.010467529296875 +85708 0.09124755859375 +85709 0.0301513671875 +85710 0.10888671875 +85711 0.03759765625 +85712 0.125518798828125 +85713 0.044464111328125 +85714 0.15771484375 +85715 0.05584716796875 +85716 0.17828369140625 +85717 0.063201904296875 +85718 0.17108154296875 +85719 0.061431884765625 +85720 0.129974365234375 +85721 0.04864501953125 +85722 0.082427978515625 +85723 0.03338623046875 +85724 0.027679443359375 +85725 0.0155029296875 +85726 -0.065643310546875 +85727 -0.01470947265625 +85728 -0.15936279296875 +85729 -0.0452880859375 +85730 -0.21307373046875 +85731 -0.063568115234375 +85732 -0.234649658203125 +85733 -0.071929931640625 +85734 -0.2001953125 +85735 -0.06280517578125 +85736 -0.119171142578125 +85737 -0.0390625 +85738 -0.024749755859375 +85739 -0.010986328125 +85740 0.085784912109375 +85741 0.0223388671875 +85742 0.178131103515625 +85743 0.05023193359375 +85744 0.215576171875 +85745 0.061309814453125 +85746 0.211456298828125 +85747 0.059783935546875 +85748 0.17523193359375 +85749 0.048614501953125 +85750 0.128753662109375 +85751 0.034576416015625 +85752 0.1019287109375 +85753 0.0269775390625 +85754 0.0743408203125 +85755 0.019378662109375 +85756 0.04327392578125 +85757 0.010894775390625 +85758 0.038177490234375 +85759 0.010589599609375 +85760 0.076263427734375 +85761 0.02325439453125 +85762 0.14105224609375 +85763 0.043182373046875 +85764 0.186431884765625 +85765 0.05682373046875 +85766 0.188812255859375 +85767 0.05767822265625 +85768 0.1390380859375 +85769 0.0433349609375 +85770 0.041778564453125 +85771 0.0152587890625 +85772 -0.079437255859375 +85773 -0.019775390625 +85774 -0.219390869140625 +85775 -0.060211181640625 +85776 -0.367828369140625 +85777 -0.10302734375 +85778 -0.494873046875 +85779 -0.1397705078125 +85780 -0.556243896484375 +85781 -0.157989501953125 +85782 -0.508697509765625 +85783 -0.1455078125 +85784 -0.3756103515625 +85785 -0.10882568359375 +85786 -0.218902587890625 +85787 -0.06524658203125 +85788 -0.063751220703125 +85789 -0.021820068359375 +85790 0.091552734375 +85791 0.021881103515625 +85792 0.23602294921875 +85793 0.062744140625 +85794 0.342987060546875 +85795 0.093292236328125 +85796 0.39520263671875 +85797 0.108642578125 +85798 0.389373779296875 +85799 0.10784912109375 +85800 0.324249267578125 +85801 0.09051513671875 +85802 0.224090576171875 +85803 0.063385009765625 +85804 0.124267578125 +85805 0.03631591796875 +85806 0.037078857421875 +85807 0.012664794921875 +85808 -0.010101318359375 +85809 6.103515625e-05 +85810 -0.019439697265625 +85811 -0.002105712890625 +85812 -0.022796630859375 +85813 -0.00274658203125 +85814 -0.001556396484375 +85815 0.003265380859375 +85816 0.056304931640625 +85817 0.019287109375 +85818 0.106719970703125 +85819 0.03302001953125 +85820 0.096893310546875 +85821 0.02972412109375 +85822 0.042694091796875 +85823 0.01385498046875 +85824 -0.018035888671875 +85825 -0.00390625 +85826 -0.07586669921875 +85827 -0.0208740234375 +85828 -0.11944580078125 +85829 -0.0338134765625 +85830 -0.15972900390625 +85831 -0.045745849609375 +85832 -0.202606201171875 +85833 -0.058319091796875 +85834 -0.24859619140625 +85835 -0.071624755859375 +85836 -0.30517578125 +85837 -0.087738037109375 +85838 -0.36212158203125 +85839 -0.103790283203125 +85840 -0.39141845703125 +85841 -0.1119384765625 +85842 -0.35528564453125 +85843 -0.10162353515625 +85844 -0.249969482421875 +85845 -0.071807861328125 +85846 -0.092864990234375 +85847 -0.02740478515625 +85848 0.08905029296875 +85849 0.024017333984375 +85850 0.2352294921875 +85851 0.065460205078125 +85852 0.318817138671875 +85853 0.089385986328125 +85854 0.358642578125 +85855 0.10101318359375 +85856 0.347747802734375 +85857 0.098388671875 +85858 0.28564453125 +85859 0.08135986328125 +85860 0.223175048828125 +85861 0.064117431640625 +85862 0.196746826171875 +85863 0.056884765625 +85864 0.179840087890625 +85865 0.052215576171875 +85866 0.155548095703125 +85867 0.045379638671875 +85868 0.151214599609375 +85869 0.044036865234375 +85870 0.156951904296875 +85871 0.045440673828125 +85872 0.13177490234375 +85873 0.0380859375 +85874 0.100799560546875 +85875 0.029052734375 +85876 0.087127685546875 +85877 0.024810791015625 +85878 0.05487060546875 +85879 0.015350341796875 +85880 -0.009002685546875 +85881 -0.0029296875 +85882 -0.10400390625 +85883 -0.029876708984375 +85884 -0.229400634765625 +85885 -0.065277099609375 +85886 -0.35552978515625 +85887 -0.100799560546875 +85888 -0.441925048828125 +85889 -0.125091552734375 +85890 -0.473846435546875 +85891 -0.134033203125 +85892 -0.464813232421875 +85893 -0.13140869140625 +85894 -0.419097900390625 +85895 -0.118438720703125 +85896 -0.334320068359375 +85897 -0.094451904296875 +85898 -0.227935791015625 +85899 -0.0643310546875 +85900 -0.12347412109375 +85901 -0.034698486328125 +85902 -0.02764892578125 +85903 -0.007476806640625 +85904 0.077667236328125 +85905 0.022369384765625 +85906 0.2132568359375 +85907 0.060638427734375 +85908 0.38885498046875 +85909 0.11004638671875 +85910 0.582794189453125 +85911 0.164520263671875 +85912 0.734039306640625 +85913 0.206939697265625 +85914 0.800140380859375 +85915 0.22540283203125 +85916 0.7783203125 +85917 0.219146728515625 +85918 0.6651611328125 +85919 0.187286376953125 +85920 0.45965576171875 +85921 0.129547119140625 +85922 0.199188232421875 +85923 0.056365966796875 +85924 -0.050689697265625 +85925 -0.013824462890625 +85926 -0.23297119140625 +85927 -0.0650634765625 +85928 -0.33013916015625 +85929 -0.092437744140625 +85930 -0.368408203125 +85931 -0.103302001953125 +85932 -0.378936767578125 +85933 -0.106353759765625 +85934 -0.376983642578125 +85935 -0.10589599609375 +85936 -0.37969970703125 +85937 -0.10675048828125 +85938 -0.391510009765625 +85939 -0.110107421875 +85940 -0.385345458984375 +85941 -0.1083984375 +85942 -0.3419189453125 +85943 -0.09619140625 +85944 -0.28289794921875 +85945 -0.079559326171875 +85946 -0.251617431640625 +85947 -0.0706787109375 +85948 -0.266143798828125 +85949 -0.0745849609375 +85950 -0.273345947265625 +85951 -0.076416015625 +85952 -0.216796875 +85953 -0.060394287109375 +85954 -0.128265380859375 +85955 -0.035400390625 +85956 -0.068145751953125 +85957 -0.01837158203125 +85958 -0.0430908203125 +85959 -0.011138916015625 +85960 -0.024444580078125 +85961 -0.0057373046875 +85962 0.020721435546875 +85963 0.00701904296875 +85964 0.124481201171875 +85965 0.036102294921875 +85966 0.25787353515625 +85967 0.07342529296875 +85968 0.379119873046875 +85969 0.107269287109375 +85970 0.47991943359375 +85971 0.135345458984375 +85972 0.5281982421875 +85973 0.148651123046875 +85974 0.511138916015625 +85975 0.14361572265625 +85976 0.456207275390625 +85977 0.1279296875 +85978 0.407470703125 +85979 0.113983154296875 +85980 0.383758544921875 +85981 0.107025146484375 +85982 0.35687255859375 +85983 0.099212646484375 +85984 0.31182861328125 +85985 0.08636474609375 +85986 0.250885009765625 +85987 0.069122314453125 +85988 0.1654052734375 +85989 0.045074462890625 +85990 0.035247802734375 +85991 0.008575439453125 +85992 -0.142059326171875 +85993 -0.041046142578125 +85994 -0.33563232421875 +85995 -0.095123291015625 +85996 -0.5345458984375 +85997 -0.150604248046875 +85998 -0.72186279296875 +85999 -0.202789306640625 +86000 -0.836669921875 +86001 -0.234588623046875 +86002 -0.8326416015625 +86003 -0.23309326171875 +86004 -0.7296142578125 +86005 -0.203857421875 +86006 -0.582550048828125 +86007 -0.16229248046875 +86008 -0.440093994140625 +86009 -0.1220703125 +86010 -0.324310302734375 +86011 -0.089385986328125 +86012 -0.20147705078125 +86013 -0.054779052734375 +86014 -0.044647216796875 +86015 -0.010711669921875 +86016 0.103973388671875 +86017 0.03155517578125 +86018 0.202392578125 +86019 0.060882568359375 +86020 0.264495849609375 +86021 0.08050537109375 +86022 0.338897705078125 +86023 0.10223388671875 +86024 0.443817138671875 +86025 0.13043212890625 +86026 0.545074462890625 +86027 0.156524658203125 +86028 0.6173095703125 +86029 0.1741943359375 +86030 0.6524658203125 +86031 0.1815185546875 +86032 0.66339111328125 +86033 0.1817626953125 +86034 0.6561279296875 +86035 0.176605224609375 +86036 0.606781005859375 +86037 0.160308837890625 +86038 0.501190185546875 +86039 0.129638671875 +86040 0.352783203125 +86041 0.088165283203125 +86042 0.176544189453125 +86043 0.039886474609375 +86044 -0.034820556640625 +86045 -0.0167236328125 +86046 -0.258209228515625 +86047 -0.07568359375 +86048 -0.44244384765625 +86049 -0.124176025390625 +86050 -0.5753173828125 +86051 -0.159027099609375 +86052 -0.65203857421875 +86053 -0.178985595703125 +86054 -0.641632080078125 +86055 -0.176361083984375 +86056 -0.562164306640625 +86057 -0.155670166015625 +86058 -0.458038330078125 +86059 -0.128021240234375 +86060 -0.350555419921875 +86061 -0.098785400390625 +86062 -0.260528564453125 +86063 -0.073272705078125 +86064 -0.192108154296875 +86065 -0.052703857421875 +86066 -0.141937255859375 +86067 -0.036468505859375 +86068 -0.1021728515625 +86069 -0.0228271484375 +86070 -0.062896728515625 +86071 -0.009521484375 +86072 -0.011932373046875 +86073 0.006256103515625 +86074 0.062835693359375 +86075 0.02734375 +86076 0.148712158203125 +86077 0.05047607421875 +86078 0.241729736328125 +86079 0.0745849609375 +86080 0.34912109375 +86081 0.101409912109375 +86082 0.457305908203125 +86083 0.12762451171875 +86084 0.54388427734375 +86085 0.147735595703125 +86086 0.5728759765625 +86087 0.15289306640625 +86088 0.506591796875 +86089 0.1339111328125 +86090 0.351226806640625 +86091 0.092437744140625 +86092 0.146514892578125 +86093 0.03851318359375 +86094 -0.05523681640625 +86095 -0.014678955078125 +86096 -0.21624755859375 +86097 -0.057586669921875 +86098 -0.334930419921875 +86099 -0.08966064453125 +86100 -0.402984619140625 +86101 -0.10870361328125 +86102 -0.4412841796875 +86103 -0.119781494140625 +86104 -0.49578857421875 +86105 -0.134246826171875 +86106 -0.5601806640625 +86107 -0.1505126953125 +86108 -0.600738525390625 +86109 -0.160186767578125 +86110 -0.584228515625 +86111 -0.15509033203125 +86112 -0.47930908203125 +86113 -0.12750244140625 +86114 -0.27935791015625 +86115 -0.075897216796875 +86116 -0.0089111328125 +86117 -0.006500244140625 +86118 0.268798828125 +86119 0.064849853515625 +86120 0.482818603515625 +86121 0.12042236328125 +86122 0.60369873046875 +86123 0.152801513671875 +86124 0.650421142578125 +86125 0.166534423828125 +86126 0.66400146484375 +86127 0.17169189453125 +86128 0.6414794921875 +86129 0.167449951171875 +86130 0.572540283203125 +86131 0.151214599609375 +86132 0.498138427734375 +86133 0.13311767578125 +86134 0.439453125 +86135 0.118377685546875 +86136 0.375518798828125 +86137 0.101806640625 +86138 0.274505615234375 +86139 0.075592041015625 +86140 0.1087646484375 +86141 0.032958984375 +86142 -0.099395751953125 +86143 -0.02044677734375 +86144 -0.3182373046875 +86145 -0.076629638671875 +86146 -0.5489501953125 +86147 -0.13580322265625 +86148 -0.7738037109375 +86149 -0.193450927734375 +86150 -0.86383056640625 +86151 -0.236358642578125 +86152 -0.870391845703125 +86153 -0.256195068359375 +86154 -0.86895751953125 +86155 -0.25726318359375 +86156 -0.861053466796875 +86157 -0.242767333984375 +86158 -0.765869140625 +86159 -0.208404541015625 +86160 -0.5301513671875 +86161 -0.1513671875 +86162 -0.214691162109375 +86163 -0.07342529296875 +86164 0.137359619140625 +86165 0.014678955078125 +86166 0.474822998046875 +86167 0.100189208984375 +86168 0.76239013671875 +86169 0.174224853515625 +86170 0.867462158203125 +86171 0.230010986328125 +86172 0.870361328125 +86173 0.267578125 +86174 0.86480712890625 +86175 0.283966064453125 +86176 0.831817626953125 +86177 0.280426025390625 +86178 0.677581787109375 +86179 0.262908935546875 +86180 0.495880126953125 +86181 0.232818603515625 +86182 0.30767822265625 +86183 0.1947021484375 +86184 0.116180419921875 +86185 0.149078369140625 +86186 -0.110748291015625 +86187 0.08807373046875 +86188 -0.381805419921875 +86189 0.00994873046875 +86190 -0.6572265625 +86191 -0.074615478515625 +86192 -0.857421875 +86193 -0.150726318359375 +86194 -0.870391845703125 +86195 -0.207672119140625 +86196 -0.870391845703125 +86197 -0.24365234375 +86198 -0.86444091796875 +86199 -0.265289306640625 +86200 -0.85723876953125 +86201 -0.2813720703125 +86202 -0.790008544921875 +86203 -0.28729248046875 +86204 -0.62847900390625 +86205 -0.26953125 +86206 -0.3956298828125 +86207 -0.227203369140625 +86208 -0.126708984375 +86209 -0.168426513671875 +86210 0.150115966796875 +86211 -0.0999755859375 +86212 0.424041748046875 +86213 -0.024749755859375 +86214 0.670623779296875 +86215 0.050567626953125 +86216 0.854522705078125 +86217 0.116363525390625 +86218 0.866485595703125 +86219 0.168243408203125 +86220 0.86920166015625 +86221 0.202301025390625 +86222 0.8653564453125 +86223 0.2230224609375 +86224 0.857147216796875 +86225 0.233673095703125 +86226 0.766845703125 +86227 0.233489990234375 +86228 0.628509521484375 +86229 0.223663330078125 +86230 0.462127685546875 +86231 0.202484130859375 +86232 0.297210693359375 +86233 0.176300048828125 +86234 0.14862060546875 +86235 0.148101806640625 +86236 -0.00537109375 +86237 0.112213134765625 +86238 -0.15753173828125 +86239 0.070526123046875 +86240 -0.31304931640625 +86241 0.022125244140625 +86242 -0.48876953125 +86243 -0.036407470703125 +86244 -0.6416015625 +86245 -0.09344482421875 +86246 -0.751373291015625 +86247 -0.142791748046875 +86248 -0.84619140625 +86249 -0.190155029296875 +86250 -0.861297607421875 +86251 -0.2318115234375 +86252 -0.863250732421875 +86253 -0.259521484375 +86254 -0.856597900390625 +86255 -0.265380859375 +86256 -0.7498779296875 +86257 -0.25238037109375 +86258 -0.624542236328125 +86259 -0.234832763671875 +86260 -0.47808837890625 +86261 -0.207275390625 +86262 -0.253387451171875 +86263 -0.15521240234375 +86264 0.003692626953125 +86265 -0.0899658203125 +86266 0.2257080078125 +86267 -0.028472900390625 +86268 0.427154541015625 +86269 0.032318115234375 +86270 0.643218994140625 +86271 0.100433349609375 +86272 0.855926513671875 +86273 0.1729736328125 +86274 0.870361328125 +86275 0.2354736328125 +86276 0.870361328125 +86277 0.27630615234375 +86278 0.862762451171875 +86279 0.29705810546875 +86280 0.79669189453125 +86281 0.29718017578125 +86282 0.595794677734375 +86283 0.274871826171875 +86284 0.362152099609375 +86285 0.23675537109375 +86286 0.1270751953125 +86287 0.18927001953125 +86288 -0.086944580078125 +86289 0.13739013671875 +86290 -0.2784423828125 +86291 0.082061767578125 +86292 -0.484832763671875 +86293 0.0162353515625 +86294 -0.729583740234375 +86295 -0.06378173828125 +86296 -0.86688232421875 +86297 -0.146636962890625 +86298 -0.870391845703125 +86299 -0.21826171875 +86300 -0.86859130859375 +86301 -0.277252197265625 +86302 -0.86279296875 +86303 -0.322967529296875 +86304 -0.817962646484375 +86305 -0.347503662109375 +86306 -0.6116943359375 +86307 -0.34100341796875 +86308 -0.3128662109375 +86309 -0.302001953125 +86310 0.039398193359375 +86311 -0.237884521484375 +86312 0.422821044921875 +86313 -0.153228759765625 +86314 0.805145263671875 +86315 -0.055511474609375 +86316 0.870361328125 +86317 0.0401611328125 +86318 0.870361328125 +86319 0.121124267578125 +86320 0.860015869140625 +86321 0.184478759765625 +86322 0.727935791015625 +86323 0.228179931640625 +86324 0.48114013671875 +86325 0.250640869140625 +86326 0.2059326171875 +86327 0.25677490234375 +86328 -0.06103515625 +86329 0.251220703125 +86330 -0.29913330078125 +86331 0.235992431640625 +86332 -0.516204833984375 +86333 0.207855224609375 +86334 -0.7252197265625 +86335 0.163543701171875 +86336 -0.85980224609375 +86337 0.1085205078125 +86338 -0.870391845703125 +86339 0.0504150390625 +86340 -0.870391845703125 +86341 -0.004119873046875 +86342 -0.858062744140625 +86343 -0.044219970703125 +86344 -0.673004150390625 +86345 -0.068634033203125 +86346 -0.42694091796875 +86347 -0.08831787109375 +86348 -0.2100830078125 +86349 -0.1124267578125 +86350 -0.0362548828125 +86351 -0.14013671875 +86352 0.10943603515625 +86353 -0.164794921875 +86354 0.23516845703125 +86355 -0.181793212890625 +86356 0.373687744140625 +86357 -0.182037353515625 +86358 0.517791748046875 +86359 -0.165863037109375 +86360 0.602783203125 +86361 -0.1468505859375 +86362 0.635711669921875 +86363 -0.12396240234375 +86364 0.655181884765625 +86365 -0.090179443359375 +86366 0.65948486328125 +86367 -0.0478515625 +86368 0.651275634765625 +86369 0.000946044921875 +86370 0.61846923828125 +86371 0.050567626953125 +86372 0.53753662109375 +86373 0.0926513671875 +86374 0.404144287109375 +86375 0.122955322265625 +86376 0.22186279296875 +86377 0.1390380859375 +86378 0.003997802734375 +86379 0.140899658203125 +86380 -0.22100830078125 +86381 0.132171630859375 +86382 -0.42449951171875 +86383 0.117156982421875 +86384 -0.579833984375 +86385 0.100341796875 +86386 -0.641876220703125 +86387 0.090911865234375 +86388 -0.6177978515625 +86389 0.08746337890625 +86390 -0.575531005859375 +86391 0.076141357421875 +86392 -0.526336669921875 +86393 0.055938720703125 +86394 -0.42645263671875 +86395 0.038299560546875 +86396 -0.2581787109375 +86397 0.0294189453125 +86398 -0.068695068359375 +86399 0.021728515625 +86400 0.09222412109375 +86401 0.00726318359375 +86402 0.232147216796875 +86403 -0.009613037109375 +86404 0.3509521484375 +86405 -0.026397705078125 +86406 0.410064697265625 +86407 -0.04925537109375 +86408 0.372955322265625 +86409 -0.084320068359375 +86410 0.2554931640625 +86411 -0.126922607421875 +86412 0.10711669921875 +86413 -0.165740966796875 +86414 -0.052886962890625 +86415 -0.196533203125 +86416 -0.186279296875 +86417 -0.2115478515625 +86418 -0.23291015625 +86419 -0.1988525390625 +86420 -0.209442138671875 +86421 -0.163543701171875 +86422 -0.174163818359375 +86423 -0.120086669921875 +86424 -0.126739501953125 +86425 -0.070526123046875 +86426 -0.048126220703125 +86427 -0.01300048828125 +86428 0.0426025390625 +86429 0.046142578125 +86430 0.10748291015625 +86431 0.0965576171875 +86432 0.1409912109375 +86433 0.1351318359375 +86434 0.19708251953125 +86435 0.171966552734375 +86436 0.273651123046875 +86437 0.2054443359375 +86438 0.31768798828125 +86439 0.223419189453125 +86440 0.341094970703125 +86441 0.228240966796875 +86442 0.368011474609375 +86443 0.22540283203125 +86444 0.37249755859375 +86445 0.209991455078125 +86446 0.30072021484375 +86447 0.171539306640625 +86448 0.1517333984375 +86449 0.11126708984375 +86450 -0.01470947265625 +86451 0.04376220703125 +86452 -0.1883544921875 +86453 -0.02691650390625 +86454 -0.372711181640625 +86455 -0.09967041015625 +86456 -0.51397705078125 +86457 -0.161102294921875 +86458 -0.57177734375 +86459 -0.20086669921875 +86460 -0.53948974609375 +86461 -0.21612548828125 +86462 -0.43511962890625 +86463 -0.209747314453125 +86464 -0.2962646484375 +86465 -0.189117431640625 +86466 -0.161102294921875 +86467 -0.162139892578125 +86468 -0.0435791015625 +86469 -0.131927490234375 +86470 0.060394287109375 +86471 -0.09808349609375 +86472 0.13665771484375 +86473 -0.064453125 +86474 0.170135498046875 +86475 -0.035400390625 +86476 0.16552734375 +86477 -0.011260986328125 +86478 0.15728759765625 +86479 0.013916015625 +86480 0.150787353515625 +86481 0.039794921875 +86482 0.12200927734375 +86483 0.059661865234375 +86484 0.080108642578125 +86485 0.074127197265625 +86486 0.05126953125 +86487 0.087646484375 +86488 0.062896728515625 +86489 0.105194091796875 +86490 0.09271240234375 +86491 0.121246337890625 +86492 0.092987060546875 +86493 0.1251220703125 +86494 0.07855224609375 +86495 0.1199951171875 +86496 0.06427001953125 +86497 0.109344482421875 +86498 0.0347900390625 +86499 0.090423583984375 +86500 -0.01171875 +86501 0.06365966796875 +86502 -0.056060791015625 +86503 0.034210205078125 +86504 -0.055511474609375 +86505 0.012481689453125 +86506 -0.010467529296875 +86507 -0.00030517578125 +86508 0.02508544921875 +86509 -0.01458740234375 +86510 0.025665283203125 +86511 -0.03466796875 +86512 0.017333984375 +86513 -0.053863525390625 +86514 0.00189208984375 +86515 -0.0709228515625 +86516 -0.03173828125 +86517 -0.087615966796875 +86518 -0.071502685546875 +86519 -0.100921630859375 +86520 -0.13543701171875 +86521 -0.1146240234375 +86522 -0.219970703125 +86523 -0.128082275390625 +86524 -0.300506591796875 +86525 -0.1363525390625 +86526 -0.376312255859375 +86527 -0.13995361328125 +86528 -0.416107177734375 +86529 -0.13299560546875 +86530 -0.371124267578125 +86531 -0.106048583984375 +86532 -0.242279052734375 +86533 -0.060333251953125 +86534 -0.069732666015625 +86535 -0.005279541015625 +86536 0.125640869140625 +86537 0.0535888671875 +86538 0.31268310546875 +86539 0.108795166015625 +86540 0.45501708984375 +86541 0.15203857421875 +86542 0.554779052734375 +86543 0.182952880859375 +86544 0.61065673828125 +86545 0.20074462890625 +86546 0.610931396484375 +86547 0.20281982421875 +86548 0.531463623046875 +86549 0.18438720703125 +86550 0.3883056640625 +86551 0.14892578125 +86552 0.23468017578125 +86553 0.107574462890625 +86554 0.095245361328125 +86555 0.0660400390625 +86556 -0.00396728515625 +86557 0.03033447265625 +86558 -0.04852294921875 +86559 0.004241943359375 +86560 -0.055145263671875 +86561 -0.0145263671875 +86562 -0.0758056640625 +86563 -0.035400390625 +86564 -0.138702392578125 +86565 -0.063140869140625 +86566 -0.209197998046875 +86567 -0.09002685546875 +86568 -0.289031982421875 +86569 -0.115753173828125 +86570 -0.37884521484375 +86571 -0.1400146484375 +86572 -0.456329345703125 +86573 -0.1580810546875 +86574 -0.51641845703125 +86575 -0.1689453125 +86576 -0.519287109375 +86577 -0.164794921875 +86578 -0.458251953125 +86579 -0.144622802734375 +86580 -0.384796142578125 +86581 -0.119293212890625 +86582 -0.323699951171875 +86583 -0.09442138671875 +86584 -0.269287109375 +86585 -0.069580078125 +86586 -0.1951904296875 +86587 -0.040283203125 +86588 -0.100006103515625 +86589 -0.007080078125 +86590 -0.01055908203125 +86591 0.02386474609375 +86592 0.1033935546875 +86593 0.057891845703125 +86594 0.24908447265625 +86595 0.095916748046875 +86596 0.373199462890625 +86597 0.126861572265625 +86598 0.45806884765625 +86599 0.14691162109375 +86600 0.511474609375 +86601 0.157562255859375 +86602 0.565399169921875 +86603 0.165313720703125 +86604 0.61138916015625 +86605 0.168701171875 +86606 0.5897216796875 +86607 0.15618896484375 +86608 0.4906005859375 +86609 0.1263427734375 +86610 0.33148193359375 +86611 0.083251953125 +86612 0.147796630859375 +86613 0.03466796875 +86614 -0.01873779296875 +86615 -0.010406494140625 +86616 -0.140289306640625 +86617 -0.045745849609375 +86618 -0.191986083984375 +86619 -0.0657958984375 +86620 -0.184295654296875 +86621 -0.072174072265625 +86622 -0.161834716796875 +86623 -0.07342529296875 +86624 -0.166595458984375 +86625 -0.07769775390625 +86626 -0.19390869140625 +86627 -0.08392333984375 +86628 -0.22442626953125 +86629 -0.0882568359375 +86630 -0.279754638671875 +86631 -0.09521484375 +86632 -0.3389892578125 +86633 -0.10089111328125 +86634 -0.3543701171875 +86635 -0.096160888671875 +86636 -0.348175048828125 +86637 -0.0859375 +86638 -0.32598876953125 +86639 -0.071868896484375 +86640 -0.2581787109375 +86641 -0.048583984375 +86642 -0.139801025390625 +86643 -0.015594482421875 +86644 0.014617919921875 +86645 0.023681640625 +86646 0.144378662109375 +86647 0.056610107421875 +86648 0.221038818359375 +86649 0.07720947265625 +86650 0.27069091796875 +86651 0.0904541015625 +86652 0.294036865234375 +86653 0.09637451171875 +86654 0.311767578125 +86655 0.099090576171875 +86656 0.339141845703125 +86657 0.1016845703125 +86658 0.360260009765625 +86659 0.10101318359375 +86660 0.360504150390625 +86661 0.09454345703125 +86662 0.308380126953125 +86663 0.07696533203125 +86664 0.18170166015625 +86665 0.044708251953125 +86666 0.0047607421875 +86667 0.0028076171875 +86668 -0.17559814453125 +86669 -0.039520263671875 +86670 -0.3143310546875 +86671 -0.073516845703125 +86672 -0.36785888671875 +86673 -0.0906982421875 +86674 -0.36248779296875 +86675 -0.09552001953125 +86676 -0.343536376953125 +86677 -0.0960693359375 +86678 -0.3018798828125 +86679 -0.09051513671875 +86680 -0.231414794921875 +86681 -0.07763671875 +86682 -0.117645263671875 +86683 -0.054840087890625 +86684 0.007049560546875 +86685 -0.02825927734375 +86686 0.087982177734375 +86687 -0.008209228515625 +86688 0.13946533203125 +86689 0.00762939453125 +86690 0.17425537109375 +86691 0.021209716796875 +86692 0.188201904296875 +86693 0.031341552734375 +86694 0.171234130859375 +86695 0.035736083984375 +86696 0.118438720703125 +86697 0.033111572265625 +86698 0.05706787109375 +86699 0.028106689453125 +86700 -0.010711669921875 +86701 0.020782470703125 +86702 -0.0914306640625 +86703 0.009674072265625 +86704 -0.162322998046875 +86705 -0.001129150390625 +86706 -0.194549560546875 +86707 -0.006439208984375 +86708 -0.1492919921875 +86709 0.000885009765625 +86710 -0.02166748046875 +86711 0.021820068359375 +86712 0.124053955078125 +86713 0.04473876953125 +86714 0.211151123046875 +86715 0.055755615234375 +86716 0.240447998046875 +86717 0.05535888671875 +86718 0.242218017578125 +86719 0.049468994140625 +86720 0.2257080078125 +86721 0.040130615234375 +86722 0.194366455078125 +86723 0.0283203125 +86724 0.115509033203125 +86725 0.008331298828125 +86726 0.0128173828125 +86727 -0.01513671875 +86728 -0.053802490234375 +86729 -0.030853271484375 +86730 -0.110626220703125 +86731 -0.043487548828125 +86732 -0.199493408203125 +86733 -0.0606689453125 +86734 -0.29437255859375 +86735 -0.07757568359375 +86736 -0.33221435546875 +86737 -0.08270263671875 +86738 -0.27972412109375 +86739 -0.070068359375 +86740 -0.185333251953125 +86741 -0.048797607421875 +86742 -0.128204345703125 +86743 -0.033660888671875 +86744 -0.115692138671875 +86745 -0.026275634765625 +86746 -0.116455078125 +86747 -0.021209716796875 +86748 -0.105926513671875 +86749 -0.01422119140625 +86750 -0.053955078125 +86751 0.0 +86752 0.048797607421875 +86753 0.02288818359375 +86754 0.157318115234375 +86755 0.04595947265625 +86756 0.212005615234375 +86757 0.058135986328125 +86758 0.218475341796875 +86759 0.060333251953125 +86760 0.23724365234375 +86761 0.06365966796875 +86762 0.30535888671875 +86763 0.074981689453125 +86764 0.38128662109375 +86765 0.086761474609375 +86766 0.404449462890625 +86767 0.08795166015625 +86768 0.3944091796875 +86769 0.082366943359375 +86770 0.3885498046875 +86771 0.077117919921875 +86772 0.362640380859375 +86773 0.0679931640625 +86774 0.27362060546875 +86775 0.047332763671875 +86776 0.11712646484375 +86777 0.014556884765625 +86778 -0.054901123046875 +86779 -0.020538330078125 +86780 -0.19085693359375 +86781 -0.04827880859375 +86782 -0.28570556640625 +86783 -0.067626953125 +86784 -0.339263916015625 +86785 -0.079071044921875 +86786 -0.3775634765625 +86787 -0.087127685546875 +86788 -0.445709228515625 +86789 -0.098663330078125 +86790 -0.535064697265625 +86791 -0.112060546875 +86792 -0.629058837890625 +86793 -0.1246337890625 +86794 -0.697601318359375 +86795 -0.131805419921875 +86796 -0.70391845703125 +86797 -0.128082275390625 +86798 -0.6424560546875 +86799 -0.11285400390625 +86800 -0.491241455078125 +86801 -0.0831298828125 +86802 -0.265716552734375 +86803 -0.041656494140625 +86804 -0.023712158203125 +86805 0.0023193359375 +86806 0.201751708984375 +86807 0.043365478515625 +86808 0.375823974609375 +86809 0.075836181640625 +86810 0.485076904296875 +86811 0.09735107421875 +86812 0.56884765625 +86813 0.113616943359375 +86814 0.634765625 +86815 0.1256103515625 +86816 0.63763427734375 +86817 0.12640380859375 +86818 0.5660400390625 +86819 0.1142578125 +86820 0.4720458984375 +86821 0.097198486328125 +86822 0.40692138671875 +86823 0.083221435546875 +86824 0.3778076171875 +86825 0.07366943359375 +86826 0.376953125 +86827 0.06768798828125 +86828 0.371978759765625 +86829 0.060638427734375 +86830 0.313140869140625 +86831 0.045318603515625 +86832 0.184417724609375 +86833 0.0196533203125 +86834 0.011199951171875 +86835 -0.012115478515625 +86836 -0.171051025390625 +86837 -0.0443115234375 +86838 -0.33740234375 +86839 -0.07293701171875 +86840 -0.47198486328125 +86841 -0.095428466796875 +86842 -0.560394287109375 +86843 -0.109527587890625 +86844 -0.58056640625 +86845 -0.11187744140625 +86846 -0.54754638671875 +86847 -0.1048583984375 +86848 -0.508575439453125 +86849 -0.095794677734375 +86850 -0.459503173828125 +86851 -0.084259033203125 +86852 -0.394378662109375 +86853 -0.069580078125 +86854 -0.35260009765625 +86855 -0.058013916015625 +86856 -0.31170654296875 +86857 -0.046478271484375 +86858 -0.197418212890625 +86859 -0.023956298828125 +86860 -0.007965087890625 +86861 0.009521484375 +86862 0.207489013671875 +86863 0.04620361328125 +86864 0.409210205078125 +86865 0.079864501953125 +86866 0.57208251953125 +86867 0.1065673828125 +86868 0.66595458984375 +86869 0.12164306640625 +86870 0.65875244140625 +86871 0.120208740234375 +86872 0.56744384765625 +86873 0.10491943359375 +86874 0.431396484375 +86875 0.08184814453125 +86876 0.29443359375 +86877 0.057830810546875 +86878 0.182464599609375 +86879 0.0369873046875 +86880 0.06365966796875 +86881 0.014739990234375 +86882 -0.075958251953125 +86883 -0.010772705078125 +86884 -0.189422607421875 +86885 -0.032196044921875 +86886 -0.271942138671875 +86887 -0.048553466796875 +86888 -0.342529296875 +86889 -0.06256103515625 +86890 -0.364166259765625 +86891 -0.068450927734375 +86892 -0.327239990234375 +86893 -0.064666748046875 +86894 -0.2769775390625 +86895 -0.0579833984375 +86896 -0.253692626953125 +86897 -0.05450439453125 +86898 -0.24365234375 +86899 -0.0521240234375 +86900 -0.1983642578125 +86901 -0.043548583984375 +86902 -0.116241455078125 +86903 -0.028656005859375 +86904 -0.036834716796875 +86905 -0.013641357421875 +86906 0.034881591796875 +86907 0.00054931640625 +86908 0.09124755859375 +86909 0.0125732421875 +86910 0.10888671875 +86911 0.0186767578125 +86912 0.125518798828125 +86913 0.0244140625 +86914 0.15771484375 +86915 0.032135009765625 +86916 0.17828369140625 +86917 0.037567138671875 +86918 0.17108154296875 +86919 0.03814697265625 +86920 0.129974365234375 +86921 0.032867431640625 +86922 0.082427978515625 +86923 0.025848388671875 +86924 0.027679443359375 +86925 0.01702880859375 +86926 -0.065643310546875 +86927 0.001678466796875 +86928 -0.15936279296875 +86929 -0.014312744140625 +86930 -0.21307373046875 +86931 -0.024658203125 +86932 -0.234649658203125 +86933 -0.03045654296875 +86934 -0.2001953125 +86935 -0.027923583984375 +86936 -0.119171142578125 +86937 -0.01837158203125 +86938 -0.024749755859375 +86939 -0.00665283203125 +86940 0.085784912109375 +86941 0.007720947265625 +86942 0.178131103515625 +86943 0.0196533203125 +86944 0.215576171875 +86945 0.023712158203125 +86946 0.211456298828125 +86947 0.02197265625 +86948 0.17523193359375 +86949 0.015960693359375 +86950 0.128753662109375 +86951 0.009002685546875 +86952 0.1019287109375 +86953 0.005615234375 +86954 0.0743408203125 +86955 0.002655029296875 +86956 0.04327392578125 +86957 -0.0003662109375 +86958 0.038177490234375 +86959 0.000885009765625 +86960 0.076263427734375 +86961 0.0089111328125 +86962 0.14105224609375 +86963 0.02105712890625 +86964 0.186431884765625 +86965 0.030181884765625 +86966 0.188812255859375 +86967 0.0325927734375 +86968 0.1390380859375 +86969 0.02679443359375 +86970 0.041778564453125 +86971 0.013427734375 +86972 -0.079437255859375 +86973 -0.00396728515625 +86974 -0.219390869140625 +86975 -0.024658203125 +86976 -0.367828369140625 +86977 -0.047088623046875 +86978 -0.494873046875 +86979 -0.066680908203125 +86980 -0.556243896484375 +86981 -0.076690673828125 +86982 -0.508697509765625 +86983 -0.070556640625 +86984 -0.3756103515625 +86985 -0.051727294921875 +86986 -0.218902587890625 +86987 -0.029541015625 +86988 -0.063751220703125 +86989 -0.007720947265625 +86990 0.091552734375 +86991 0.0140380859375 +86992 0.23602294921875 +86993 0.0341796875 +86994 0.342987060546875 +86995 0.04876708984375 +86996 0.39520263671875 +86997 0.055267333984375 +86998 0.389373779296875 +86999 0.053253173828125 +87000 0.324249267578125 +87001 0.042572021484375 +87002 0.224090576171875 +87003 0.0269775390625 +87004 0.124267578125 +87005 0.0118408203125 +87006 0.037078857421875 +87007 -0.000946044921875 +87008 -0.010101318359375 +87009 -0.00726318359375 +87010 -0.019439697265625 +87011 -0.00750732421875 +87012 -0.022796630859375 +87013 -0.006622314453125 +87014 -0.001556396484375 +87015 -0.0018310546875 +87016 0.056304931640625 +87017 0.008514404296875 +87018 0.106719970703125 +87019 0.017669677734375 +87020 0.096893310546875 +87021 0.01751708984375 +87022 0.042694091796875 +87023 0.010406494140625 +87024 -0.018035888671875 +87025 0.002044677734375 +87026 -0.07586669921875 +87027 -0.006134033203125 +87028 -0.11944580078125 +87029 -0.012420654296875 +87030 -0.15972900390625 +87031 -0.01849365234375 +87032 -0.202606201171875 +87033 -0.025238037109375 +87034 -0.24859619140625 +87035 -0.032684326171875 +87036 -0.30517578125 +87037 -0.041961669921875 +87038 -0.36212158203125 +87039 -0.051483154296875 +87040 -0.39141845703125 +87041 -0.05706787109375 +87042 -0.35528564453125 +87043 -0.053070068359375 +87044 -0.249969482421875 +87045 -0.03875732421875 +87046 -0.092864990234375 +87047 -0.016876220703125 +87048 0.08905029296875 +87049 0.00872802734375 +87050 0.2352294921875 +87051 0.0302734375 +87052 0.318817138671875 +87053 0.04412841796875 +87054 0.358642578125 +87055 0.05218505859375 +87056 0.347747802734375 +87057 0.053375244140625 +87058 0.28564453125 +87059 0.0474853515625 +87060 0.223175048828125 +87061 0.040557861328125 +87062 0.196746826171875 +87063 0.0369873046875 +87064 0.179840087890625 +87065 0.033660888671875 +87066 0.155548095703125 +87067 0.028656005859375 +87068 0.151214599609375 +87069 0.02545166015625 +87070 0.156951904296875 +87071 0.0230712890625 +87072 0.13177490234375 +87073 0.01678466796875 +87074 0.100799560546875 +87075 0.009796142578125 +87076 0.087127685546875 +87077 0.005096435546875 +87078 0.05487060546875 +87079 -0.001434326171875 +87080 -0.009002685546875 +87081 -0.01123046875 +87082 -0.10400390625 +87083 -0.02410888671875 +87084 -0.229400634765625 +87085 -0.0399169921875 +87086 -0.35552978515625 +87087 -0.055084228515625 +87088 -0.441925048828125 +87089 -0.06475830078125 +87090 -0.473846435546875 +87091 -0.067230224609375 +87092 -0.464813232421875 +87093 -0.064239501953125 +87094 -0.419097900390625 +87095 -0.056396484375 +87096 -0.334320068359375 +87097 -0.0435791015625 +87098 -0.227935791015625 +87099 -0.02801513671875 +87100 -0.12347412109375 +87101 -0.0126953125 +87102 -0.02764892578125 +87103 0.00140380859375 +87104 0.077667236328125 +87105 0.016326904296875 +87106 0.2132568359375 +87107 0.034454345703125 +87108 0.38885498046875 +87109 0.05682373046875 +87110 0.582794189453125 +87111 0.080780029296875 +87112 0.734039306640625 +87113 0.0989990234375 +87114 0.800140380859375 +87115 0.106414794921875 +87116 0.7783203125 +87117 0.10272216796875 +87118 0.6651611328125 +87119 0.08758544921875 +87120 0.45965576171875 +87121 0.061004638671875 +87122 0.199188232421875 +87123 0.027587890625 +87124 -0.050689697265625 +87125 -0.004638671875 +87126 -0.23297119140625 +87127 -0.028717041015625 +87128 -0.33013916015625 +87129 -0.042449951171875 +87130 -0.368408203125 +87131 -0.04888916015625 +87132 -0.378936767578125 +87133 -0.051666259765625 +87134 -0.376983642578125 +87135 -0.05255126953125 +87136 -0.37969970703125 +87137 -0.053558349609375 +87138 -0.391510009765625 +87139 -0.05517578125 +87140 -0.385345458984375 +87141 -0.054168701171875 +87142 -0.3419189453125 +87143 -0.048248291015625 +87144 -0.28289794921875 +87145 -0.0400390625 +87146 -0.251617431640625 +87147 -0.03485107421875 +87148 -0.266143798828125 +87149 -0.034912109375 +87150 -0.273345947265625 +87151 -0.033966064453125 +87152 -0.216796875 +87153 -0.02532958984375 +87154 -0.128265380859375 +87155 -0.012908935546875 +87156 -0.068145751953125 +87157 -0.0040283203125 +87158 -0.0430908203125 +87159 0.000396728515625 +87160 -0.024444580078125 +87161 0.00372314453125 +87162 0.020721435546875 +87163 0.00982666015625 +87164 0.124481201171875 +87165 0.022552490234375 +87166 0.25787353515625 +87167 0.03839111328125 +87168 0.379119873046875 +87169 0.0523681640625 +87170 0.47991943359375 +87171 0.063507080078125 +87172 0.5281982421875 +87173 0.06805419921875 +87174 0.511138916015625 +87175 0.06451416015625 +87176 0.456207275390625 +87177 0.0562744140625 +87178 0.407470703125 +87179 0.048736572265625 +87180 0.383758544921875 +87181 0.044281005859375 +87182 0.35687255859375 +87183 0.03955078125 +87184 0.31182861328125 +87185 0.032867431640625 +87186 0.250885009765625 +87187 0.024566650390625 +87188 0.1654052734375 +87189 0.013641357421875 +87190 0.035247802734375 +87191 -0.00225830078125 +87192 -0.142059326171875 +87193 -0.023406982421875 +87194 -0.33563232421875 +87195 -0.046142578125 +87196 -0.5345458984375 +87197 -0.069183349609375 +87198 -0.72186279296875 +87199 -0.090545654296875 +87200 -0.836669921875 +87201 -0.102935791015625 +87202 -0.8326416015625 +87203 -0.100921630859375 +87204 -0.7296142578125 +87205 -0.08697509765625 +87206 -0.582550048828125 +87207 -0.067840576171875 +87208 -0.440093994140625 +87209 -0.04937744140625 +87210 -0.324310302734375 +87211 -0.034332275390625 +87212 -0.20147705078125 +87213 -0.0186767578125 +87214 -0.044647216796875 +87215 0.000762939453125 +87216 0.103973388671875 +87217 0.01885986328125 +87218 0.202392578125 +87219 0.03057861328125 +87220 0.264495849609375 +87221 0.03759765625 +87222 0.338897705078125 +87223 0.0457763671875 +87224 0.443817138671875 +87225 0.057373046875 +87226 0.545074462890625 +87227 0.068328857421875 +87228 0.6173095703125 +87229 0.075653076171875 +87230 0.6524658203125 +87231 0.078460693359375 +87232 0.66339111328125 +87233 0.078399658203125 +87234 0.6561279296875 +87235 0.076263427734375 +87236 0.606781005859375 +87237 0.069244384765625 +87238 0.501190185546875 +87239 0.055694580078125 +87240 0.352783203125 +87241 0.037261962890625 +87242 0.176544189453125 +87243 0.015777587890625 +87244 -0.034820556640625 +87245 -0.00958251953125 +87246 -0.258209228515625 +87247 -0.036041259765625 +87248 -0.44244384765625 +87249 -0.0574951171875 +87250 -0.5753173828125 +87251 -0.072540283203125 +87252 -0.65203857421875 +87253 -0.080657958984375 +87254 -0.641632080078125 +87255 -0.078216552734375 +87256 -0.562164306640625 +87257 -0.06744384765625 +87258 -0.458038330078125 +87259 -0.053741455078125 +87260 -0.350555419921875 +87261 -0.039703369140625 +87262 -0.260528564453125 +87263 -0.027923583984375 +87264 -0.192108154296875 +87265 -0.0189208984375 +87266 -0.141937255859375 +87267 -0.0123291015625 +87268 -0.1021728515625 +87269 -0.007232666015625 +87270 -0.062896728515625 +87271 -0.00244140625 +87272 -0.011932373046875 +87273 0.00347900390625 +87274 0.062835693359375 +87275 0.011993408203125 +87276 0.148712158203125 +87277 0.021636962890625 +87278 0.241729736328125 +87279 0.031951904296875 +87280 0.34912109375 +87281 0.043853759765625 +87282 0.457305908203125 +87283 0.0557861328125 +87284 0.54388427734375 +87285 0.065093994140625 +87286 0.5728759765625 +87287 0.067535400390625 +87288 0.506591796875 +87289 0.058624267578125 +87290 0.351226806640625 +87291 0.0391845703125 +87292 0.146514892578125 +87293 0.014007568359375 +87294 -0.05523681640625 +87295 -0.010589599609375 +87296 -0.21624755859375 +87297 -0.02972412109375 +87298 -0.334930419921875 +87299 -0.043426513671875 +87300 -0.402984619140625 +87301 -0.051513671875 +87302 -0.4412841796875 +87303 -0.0557861328125 +87304 -0.49578857421875 +87305 -0.060333251953125 +87306 -0.5601806640625 +87307 -0.064697265625 +87308 -0.600738525390625 +87309 -0.0660400390625 +87310 -0.584228515625 +87311 -0.061614990234375 +87312 -0.47930908203125 +87313 -0.04888916015625 +87314 -0.27935791015625 +87315 -0.027496337890625 +87316 -0.0089111328125 +87317 0.000152587890625 +87318 0.268798828125 +87319 0.02825927734375 +87320 0.482818603515625 +87321 0.050384521484375 +87322 0.60369873046875 +87323 0.063751220703125 +87324 0.650421142578125 +87325 0.069915771484375 +87326 0.66400146484375 +87327 0.0723876953125 +87328 0.6414794921875 +87329 0.07086181640625 +87330 0.572540283203125 +87331 0.064453125 +87332 0.498138427734375 +87333 0.05682373046875 +87334 0.439453125 +87335 0.049896240234375 +87336 0.375518798828125 +87337 0.041961669921875 +87338 0.274505615234375 +87339 0.03033447265625 +87340 0.1087646484375 +87341 0.01275634765625 +87342 -0.099395751953125 +87343 -0.00860595703125 +87344 -0.3182373046875 +87345 -0.030792236328125 +87346 -0.5489501953125 +87347 -0.05377197265625 +87348 -0.7738037109375 +87349 -0.0758056640625 +87350 -0.86383056640625 +87351 -0.0921630859375 +87352 -0.870391845703125 +87353 -0.099822998046875 +87354 -0.86895751953125 +87355 -0.100311279296875 +87356 -0.861053466796875 +87357 -0.094757080078125 +87358 -0.765869140625 +87359 -0.0816650390625 +87360 -0.5301513671875 +87361 -0.06011962890625 +87362 -0.214691162109375 +87363 -0.030853271484375 +87364 0.137359619140625 +87365 0.00225830078125 +87366 0.474822998046875 +87367 0.034576416015625 +87368 0.76239013671875 +87369 0.06280517578125 +87370 0.867462158203125 +87371 0.084442138671875 +87372 0.870361328125 +87373 0.099395751953125 +87374 0.86480712890625 +87375 0.10650634765625 +87376 0.831817626953125 +87377 0.106170654296875 +87378 0.677581787109375 +87379 0.1004638671875 +87380 0.495880126953125 +87381 0.08990478515625 +87382 0.30767822265625 +87383 0.076080322265625 +87384 0.116180419921875 +87385 0.0592041015625 +87386 -0.110748291015625 +87387 0.03656005859375 +87388 -0.381805419921875 +87389 0.007598876953125 +87390 -0.6572265625 +87391 -0.0238037109375 +87392 -0.857421875 +87393 -0.052276611328125 +87394 -0.870391845703125 +87395 -0.073944091796875 +87396 -0.870391845703125 +87397 -0.088104248046875 +87398 -0.86444091796875 +87399 -0.097015380859375 +87400 -0.85723876953125 +87401 -0.103729248046875 +87402 -0.790008544921875 +87403 -0.1065673828125 +87404 -0.62847900390625 +87405 -0.1007080078125 +87406 -0.3956298828125 +87407 -0.085845947265625 +87408 -0.126708984375 +87409 -0.0648193359375 +87410 0.150115966796875 +87411 -0.040069580078125 +87412 0.424041748046875 +87413 -0.012664794921875 +87414 0.670623779296875 +87415 0.014984130859375 +87416 0.854522705078125 +87417 0.039398193359375 +87418 0.866485595703125 +87419 0.058929443359375 +87420 0.86920166015625 +87421 0.0721435546875 +87422 0.8653564453125 +87423 0.08056640625 +87424 0.857147216796875 +87425 0.085296630859375 +87426 0.766845703125 +87427 0.08599853515625 +87428 0.628509521484375 +87429 0.083099365234375 +87430 0.462127685546875 +87431 0.075958251953125 +87432 0.297210693359375 +87433 0.066802978515625 +87434 0.14862060546875 +87435 0.056671142578125 +87436 -0.00537109375 +87437 0.0435791015625 +87438 -0.15753173828125 +87439 0.028228759765625 +87440 -0.31304931640625 +87441 0.010345458984375 +87442 -0.48876953125 +87443 -0.01123046875 +87444 -0.6416015625 +87445 -0.032318115234375 +87446 -0.751373291015625 +87447 -0.050689697265625 +87448 -0.84619140625 +87449 -0.06829833984375 +87450 -0.861297607421875 +87451 -0.083770751953125 +87452 -0.863250732421875 +87453 -0.09417724609375 +87454 -0.856597900390625 +87455 -0.096649169921875 +87456 -0.7498779296875 +87457 -0.09222412109375 +87458 -0.624542236328125 +87459 -0.08599853515625 +87460 -0.47808837890625 +87461 -0.0760498046875 +87462 -0.253387451171875 +87463 -0.0572509765625 +87464 0.003692626953125 +87465 -0.033660888671875 +87466 0.2257080078125 +87467 -0.011322021484375 +87468 0.427154541015625 +87469 0.01080322265625 +87470 0.643218994140625 +87471 0.0355224609375 +87472 0.855926513671875 +87473 0.06195068359375 +87474 0.870361328125 +87475 0.0849609375 +87476 0.870361328125 +87477 0.10015869140625 +87478 0.862762451171875 +87479 0.108123779296875 +87480 0.79669189453125 +87481 0.108612060546875 +87482 0.595794677734375 +87483 0.10076904296875 +87484 0.362152099609375 +87485 0.087127685546875 +87486 0.1270751953125 +87487 0.070159912109375 +87488 -0.086944580078125 +87489 0.051727294921875 +87490 -0.2784423828125 +87491 0.032012939453125 +87492 -0.484832763671875 +87493 0.00799560546875 +87494 -0.729583740234375 +87495 -0.02197265625 +87496 -0.86688232421875 +87497 -0.053375244140625 +87498 -0.870391845703125 +87499 -0.08062744140625 +87500 -0.86859130859375 +87501 -0.103240966796875 +87502 -0.86279296875 +87503 -0.121002197265625 +87504 -0.817962646484375 +87505 -0.130706787109375 +87506 -0.6116943359375 +87507 -0.128387451171875 +87508 -0.3128662109375 +87509 -0.113372802734375 +87510 0.039398193359375 +87511 -0.088623046875 +87512 0.422821044921875 +87513 -0.055908203125 +87514 0.805145263671875 +87515 -0.0181884765625 +87516 0.870361328125 +87517 0.018524169921875 +87518 0.870361328125 +87519 0.049163818359375 +87520 0.860015869140625 +87521 0.072723388671875 +87522 0.727935791015625 +87523 0.088470458984375 +87524 0.48114013671875 +87525 0.095855712890625 +87526 0.2059326171875 +87527 0.097015380859375 +87528 -0.06103515625 +87529 0.0938720703125 +87530 -0.29913330078125 +87531 0.0872802734375 +87532 -0.516204833984375 +87533 0.075927734375 +87534 -0.7252197265625 +87535 0.0584716796875 +87536 -0.85980224609375 +87537 0.037078857421875 +87538 -0.870391845703125 +87539 0.0147705078125 +87540 -0.870391845703125 +87541 -0.005767822265625 +87542 -0.858062744140625 +87543 -0.020233154296875 +87544 -0.673004150390625 +87545 -0.028228759765625 +87546 -0.42694091796875 +87547 -0.034332275390625 +87548 -0.2100830078125 +87549 -0.0423583984375 +87550 -0.0362548828125 +87551 -0.052093505859375 +87552 0.10943603515625 +87553 -0.060577392578125 +87554 0.23516845703125 +87555 -0.065826416015625 +87556 0.373687744140625 +87557 -0.065399169921875 +87558 0.517791748046875 +87559 -0.05950927734375 +87560 0.602783203125 +87561 -0.051849365234375 +87562 0.635711669921875 +87563 -0.042388916015625 +87564 0.655181884765625 +87565 -0.029541015625 +87566 0.65948486328125 +87567 -0.014190673828125 +87568 0.651275634765625 +87569 0.002838134765625 +87570 0.61846923828125 +87571 0.019805908203125 +87572 0.53753662109375 +87573 0.0343017578125 +87574 0.404144287109375 +87575 0.0450439453125 +87576 0.22186279296875 +87577 0.05126953125 +87578 0.003997802734375 +87579 0.05291748046875 +87580 -0.22100830078125 +87581 0.0509033203125 +87582 -0.42449951171875 +87583 0.04632568359375 +87584 -0.579833984375 +87585 0.040435791015625 +87586 -0.641876220703125 +87587 0.03570556640625 +87588 -0.6177978515625 +87589 0.03192138671875 +87590 -0.575531005859375 +87591 0.025665283203125 +87592 -0.526336669921875 +87593 0.016876220703125 +87594 -0.42645263671875 +87595 0.00872802734375 +87596 -0.2581787109375 +87597 0.00299072265625 +87598 -0.068695068359375 +87599 -0.0020751953125 +87600 0.09222412109375 +87601 -0.00836181640625 +87602 0.232147216796875 +87603 -0.014617919921875 +87604 0.3509521484375 +87605 -0.020111083984375 +87606 0.410064697265625 +87607 -0.026397705078125 +87608 0.372955322265625 +87609 -0.035064697265625 +87610 0.2554931640625 +87611 -0.044952392578125 +87612 0.10711669921875 +87613 -0.053192138671875 +87614 -0.052886962890625 +87615 -0.058807373046875 +87616 -0.186279296875 +87617 -0.059967041015625 +87618 -0.23291015625 +87619 -0.0537109375 +87620 -0.209442138671875 +87621 -0.041534423828125 +87622 -0.174163818359375 +87623 -0.02734375 +87624 -0.126739501953125 +87625 -0.011871337890625 +87626 -0.048126220703125 +87627 0.005218505859375 +87628 0.0426025390625 +87629 0.022186279296875 +87630 0.10748291015625 +87631 0.036285400390625 +87632 0.1409912109375 +87633 0.046661376953125 +87634 0.19708251953125 +87635 0.055908203125 +87636 0.273651123046875 +87637 0.063690185546875 +87638 0.31768798828125 +87639 0.066925048828125 +87640 0.341094970703125 +87641 0.066314697265625 +87642 0.368011474609375 +87643 0.063385009765625 +87644 0.37249755859375 +87645 0.0570068359375 +87646 0.30072021484375 +87647 0.044586181640625 +87648 0.1517333984375 +87649 0.026580810546875 +87650 -0.01470947265625 +87651 0.00689697265625 +87652 -0.1883544921875 +87653 -0.013275146484375 +87654 -0.372711181640625 +87655 -0.0335693359375 +87656 -0.51397705078125 +87657 -0.050445556640625 +87658 -0.57177734375 +87659 -0.061187744140625 +87660 -0.53948974609375 +87661 -0.0650634765625 +87662 -0.43511962890625 +87663 -0.06280517578125 +87664 -0.2962646484375 +87665 -0.056396484375 +87666 -0.161102294921875 +87667 -0.047943115234375 +87668 -0.0435791015625 +87669 -0.038360595703125 +87670 0.060394287109375 +87671 -0.02764892578125 +87672 0.13665771484375 +87673 -0.01690673828125 +87674 0.170135498046875 +87675 -0.00738525390625 +87676 0.16552734375 +87677 0.000732421875 +87678 0.15728759765625 +87679 0.008880615234375 +87680 0.150787353515625 +87681 0.016876220703125 +87682 0.12200927734375 +87683 0.022918701171875 +87684 0.080108642578125 +87685 0.027130126953125 +87686 0.05126953125 +87687 0.030670166015625 +87688 0.062896728515625 +87689 0.034820556640625 +87690 0.09271240234375 +87691 0.038177490234375 +87692 0.092987060546875 +87693 0.038055419921875 +87694 0.07855224609375 +87695 0.03533935546875 +87696 0.06427001953125 +87697 0.031005859375 +87698 0.0347900390625 +87699 0.0244140625 +87700 -0.01171875 +87701 0.015777587890625 +87702 -0.056060791015625 +87703 0.00653076171875 +87704 -0.055511474609375 +87705 -0.000518798828125 +87706 -0.010467529296875 +87707 -0.0050048828125 +87708 0.02508544921875 +87709 -0.009521484375 +87710 0.025665283203125 +87711 -0.01519775390625 +87712 0.017333984375 +87713 -0.020263671875 +87714 0.00189208984375 +87715 -0.0244140625 +87716 -0.03173828125 +87717 -0.02813720703125 +87718 -0.071502685546875 +87719 -0.03070068359375 +87720 -0.13543701171875 +87721 -0.033111572265625 +87722 -0.219970703125 +87723 -0.0352783203125 +87724 -0.300506591796875 +87725 -0.035980224609375 +87726 -0.376312255859375 +87727 -0.035430908203125 +87728 -0.416107177734375 +87729 -0.03216552734375 +87730 -0.371124267578125 +87731 -0.0238037109375 +87732 -0.242279052734375 +87733 -0.0107421875 +87734 -0.069732666015625 +87735 0.004425048828125 +87736 0.125640869140625 +87737 0.020263671875 +87738 0.31268310546875 +87739 0.0347900390625 +87740 0.45501708984375 +87741 0.04571533203125 +87742 0.554779052734375 +87743 0.05303955078125 +87744 0.61065673828125 +87745 0.056640625 +87746 0.610931396484375 +87747 0.055908203125 +87748 0.531463623046875 +87749 0.049560546875 +87750 0.3883056640625 +87751 0.038604736328125 +87752 0.23468017578125 +87753 0.0262451171875 +87754 0.095245361328125 +87755 0.014129638671875 +87756 -0.00396728515625 +87757 0.003936767578125 +87758 -0.04852294921875 +87759 -0.0032958984375 +87760 -0.055145263671875 +87761 -0.008209228515625 +87762 -0.0758056640625 +87763 -0.01348876953125 +87764 -0.138702392578125 +87765 -0.020477294921875 +87766 -0.209197998046875 +87767 -0.027069091796875 +87768 -0.289031982421875 +87769 -0.033233642578125 +87770 -0.37884521484375 +87771 -0.0389404296875 +87772 -0.456329345703125 +87773 -0.04296875 +87774 -0.51641845703125 +87775 -0.0450439453125 +87776 -0.519287109375 +87777 -0.04302978515625 +87778 -0.458251953125 +87779 -0.036712646484375 +87780 -0.384796142578125 +87781 -0.029144287109375 +87782 -0.323699951171875 +87783 -0.02191162109375 +87784 -0.269287109375 +87785 -0.014923095703125 +87786 -0.1951904296875 +87787 -0.00689697265625 +87788 -0.100006103515625 +87789 0.001983642578125 +87790 -0.01055908203125 +87791 0.010040283203125 +87792 0.1033935546875 +87793 0.018798828125 +87794 0.24908447265625 +87795 0.028533935546875 +87796 0.373199462890625 +87797 0.03619384765625 +87798 0.45806884765625 +87799 0.040802001953125 +87800 0.511474609375 +87801 0.042816162109375 +87802 0.565399169921875 +87803 0.044097900390625 +87804 0.61138916015625 +87805 0.0443115234375 +87806 0.5897216796875 +87807 0.040252685546875 +87808 0.4906005859375 +87809 0.031646728515625 +87810 0.33148193359375 +87811 0.019775390625 +87812 0.147796630859375 +87813 0.006683349609375 +87814 -0.01873779296875 +87815 -0.005340576171875 +87816 -0.140289306640625 +87817 -0.014739990234375 +87818 -0.191986083984375 +87819 -0.020111083984375 +87820 -0.184295654296875 +87821 -0.021820068359375 +87822 -0.161834716796875 +87823 -0.02203369140625 +87824 -0.166595458984375 +87825 -0.022796630859375 +87826 -0.19390869140625 +87827 -0.02386474609375 +87828 -0.22442626953125 +87829 -0.024322509765625 +87830 -0.279754638671875 +87831 -0.025299072265625 +87832 -0.3389892578125 +87833 -0.025909423828125 +87834 -0.3543701171875 +87835 -0.02386474609375 +87836 -0.348175048828125 +87837 -0.02044677734375 +87838 -0.32598876953125 +87839 -0.016143798828125 +87840 -0.2581787109375 +87841 -0.0096435546875 +87842 -0.139801025390625 +87843 -0.000885009765625 +87844 0.014617919921875 +87845 0.00927734375 +87846 0.144378662109375 +87847 0.01763916015625 +87848 0.221038818359375 +87849 0.022735595703125 +87850 0.27069091796875 +87851 0.025787353515625 +87852 0.294036865234375 +87853 0.02685546875 +87854 0.311767578125 +87855 0.0269775390625 +87856 0.339141845703125 +87857 0.026885986328125 +87858 0.360260009765625 +87859 0.02557373046875 +87860 0.360504150390625 +87861 0.022552490234375 +87862 0.308380126953125 +87863 0.01739501953125 +87864 0.18170166015625 +87865 0.009857177734375 +87866 0.0047607421875 +87867 0.000885009765625 +87868 -0.17559814453125 +87869 -0.008056640625 +87870 -0.3143310546875 +87871 -0.015625 +87872 -0.36785888671875 +87873 -0.0205078125 +87874 -0.36248779296875 +87875 -0.023162841796875 +87876 -0.343536376953125 +87877 -0.024566650390625 +87878 -0.3018798828125 +87879 -0.0244140625 +87880 -0.231414794921875 +87881 -0.022552490234375 +87882 -0.117645263671875 +87883 -0.0186767578125 +87884 0.007049560546875 +87885 -0.013671875 +87886 0.087982177734375 +87887 -0.00897216796875 +87888 0.13946533203125 +87889 -0.004425048828125 +87890 0.17425537109375 +87891 6.103515625e-05 +87892 0.188201904296875 +87893 0.004180908203125 +87894 0.171234130859375 +87895 0.007476806640625 +87896 0.118438720703125 +87897 0.0096435546875 +87898 0.05706787109375 +87899 0.01116943359375 +87900 -0.010711669921875 +87901 0.011962890625 +87902 -0.0914306640625 +87903 0.01171875 +87904 -0.162322998046875 +87905 0.010894775390625 +87906 -0.194549560546875 +87907 0.010162353515625 +87908 -0.1492919921875 +87909 0.010467529296875 +87910 -0.02166748046875 +87911 0.011993408203125 +87912 0.124053955078125 +87913 0.0133056640625 +87914 0.211151123046875 +87915 0.012664794921875 +87916 0.240447998046875 +87917 0.010284423828125 +87918 0.242218017578125 +87919 0.007049560546875 +87920 0.2257080078125 +87921 0.00341796875 +87922 0.194366455078125 +87923 -0.000335693359375 +87924 0.115509033203125 +87925 -0.00482177734375 +87926 0.0128173828125 +87927 -0.00933837890625 +87928 -0.053802490234375 +87929 -0.012359619140625 +87930 -0.110626220703125 +87931 -0.01446533203125 +87932 -0.199493408203125 +87933 -0.016632080078125 +87934 -0.29437255859375 +87935 -0.018280029296875 +87936 -0.33221435546875 +87937 -0.0179443359375 +87938 -0.27972412109375 +87939 -0.014923095703125 +87940 -0.185333251953125 +87941 -0.010467529296875 +87942 -0.128204345703125 +87943 -0.006591796875 +87944 -0.115692138671875 +87945 -0.003631591796875 +87946 -0.116455078125 +87947 -0.001007080078125 +87948 -0.105926513671875 +87949 0.001708984375 +87950 -0.053955078125 +87951 0.005126953125 +87952 0.048797607421875 +87953 0.009368896484375 +87954 0.157318115234375 +87955 0.01324462890625 +87956 0.212005615234375 +87957 0.015289306640625 +87958 0.218475341796875 +87959 0.015594482421875 +87960 0.23724365234375 +87961 0.015594482421875 +87962 0.30535888671875 +87963 0.016265869140625 +87964 0.38128662109375 +87965 0.016632080078125 +87966 0.404449462890625 +87967 0.015380859375 +87968 0.3944091796875 +87969 0.0130615234375 +87970 0.3885498046875 +87971 0.010711669921875 +87972 0.362640380859375 +87973 0.00787353515625 +87974 0.27362060546875 +87975 0.003662109375 +87976 0.11712646484375 +87977 -0.00189208984375 +87978 -0.054901123046875 +87979 -0.007476806640625 +87980 -0.19085693359375 +87981 -0.01177978515625 +87982 -0.28570556640625 +87983 -0.014678955078125 +87984 -0.339263916015625 +87985 -0.01611328125 +87986 -0.3775634765625 +87987 -0.0167236328125 +87988 -0.445709228515625 +87989 -0.017608642578125 +87990 -0.535064697265625 +87991 -0.01861572265625 +87992 -0.629058837890625 +87993 -0.0194091796875 +87994 -0.697601318359375 +87995 -0.019317626953125 +87996 -0.70391845703125 +87997 -0.017608642578125 +87998 -0.6424560546875 +87999 -0.014251708984375 +88000 -0.491241455078125 +88001 -0.008819580078125 +88002 -0.265716552734375 +88003 -0.001800537109375 +88004 -0.023712158203125 +88005 0.005279541015625 +88006 0.201751708984375 +88007 0.0115966796875 +88008 0.375823974609375 +88009 0.0162353515625 +88010 0.485076904296875 +88011 0.0189208984375 +88012 0.56884765625 +88013 0.0206298828125 +88014 0.634765625 +88015 0.02154541015625 +88016 0.63763427734375 +88017 0.020599365234375 +88018 0.5660400390625 +88019 0.017608642578125 +88020 0.4720458984375 +88021 0.013885498046875 +88022 0.40692138671875 +88023 0.010772705078125 +88024 0.3778076171875 +88025 0.008514404296875 +88026 0.376953125 +88027 0.00701904296875 +88028 0.371978759765625 +88029 0.005584716796875 +88030 0.313140869140625 +88031 0.0030517578125 +88032 0.184417724609375 +88033 -0.000885009765625 +88034 0.011199951171875 +88035 -0.00555419921875 +88036 -0.171051025390625 +88037 -0.010040283203125 +88038 -0.33740234375 +88039 -0.013763427734375 +88040 -0.47198486328125 +88041 -0.016387939453125 +88042 -0.560394287109375 +88043 -0.01763916015625 +88044 -0.58056640625 +88045 -0.01702880859375 +88046 -0.54754638671875 +88047 -0.014984130859375 +88048 -0.508575439453125 +88049 -0.012725830078125 +88050 -0.459503173828125 +88051 -0.010223388671875 +88052 -0.394378662109375 +88053 -0.00738525390625 +88054 -0.35260009765625 +88055 -0.005218505859375 +88056 -0.31170654296875 +88057 -0.00323486328125 +88058 -0.197418212890625 +88059 0.000274658203125 +88060 -0.007965087890625 +88061 0.00531005859375 +88062 0.207489013671875 +88063 0.0106201171875 +88064 0.409210205078125 +88065 0.0152587890625 +88066 0.57208251953125 +88067 0.018341064453125 +88068 0.66595458984375 +88069 0.0194091796875 +88070 0.65875244140625 +88071 0.0184326171875 +88072 0.56744384765625 +88073 0.015838623046875 +88074 0.431396484375 +88075 0.012176513671875 +88076 0.29443359375 +88077 0.008056640625 +88078 0.182464599609375 +88079 0.00390625 +88080 0.06365966796875 +88081 -0.000244140625 +88082 -0.075958251953125 +88083 -0.00433349609375 +88084 -0.189422607421875 +88085 -0.0078125 +88086 -0.271942138671875 +88087 -0.010528564453125 +88088 -0.342529296875 +88089 -0.012542724609375 +88090 -0.364166259765625 +88091 -0.01348876953125 +88092 -0.327239990234375 +88093 -0.013275146484375 +88094 -0.2769775390625 +88095 -0.012298583984375 +88096 -0.253692626953125 +88097 -0.010955810546875 +88098 -0.24365234375 +88099 -0.009246826171875 +88100 -0.1983642578125 +88101 -0.0068359375 +88102 -0.116241455078125 +88103 -0.003875732421875 +88104 -0.036834716796875 +88105 -0.000823974609375 +88106 0.034881591796875 +88107 0.00213623046875 +88108 0.09124755859375 +88109 0.004791259765625 +88110 0.10888671875 +88111 0.006866455078125 +88112 0.125518798828125 +88113 0.008544921875 +88114 0.15771484375 +88115 0.0098876953125 +88116 0.17828369140625 +88117 0.010650634765625 +88118 0.17108154296875 +88119 0.010650634765625 +88120 0.129974365234375 +88121 0.009857177734375 +88122 0.082427978515625 +88123 0.008544921875 +88124 0.027679443359375 +88125 0.00677490234375 +88126 -0.065643310546875 +88127 0.004425048828125 +88128 -0.15936279296875 +88129 0.001861572265625 +88130 -0.21307373046875 +88131 -0.000457763671875 +88132 -0.234649658203125 +88133 -0.00250244140625 +88134 -0.2001953125 +88135 -0.003997802734375 +88136 -0.119171142578125 +88137 -0.00494384765625 +88138 -0.024749755859375 +88139 -0.0054931640625 +88140 0.085784912109375 +88141 -0.005615234375 +88142 0.178131103515625 +88143 -0.0054931640625 +88144 0.215576171875 +88145 -0.005401611328125 +88146 0.211456298828125 +88147 -0.005218505859375 +88148 0.17523193359375 +88149 -0.004913330078125 +88150 0.128753662109375 +88151 -0.004302978515625 +88152 0.1019287109375 +88153 -0.003204345703125 +88154 0.0743408203125 +88155 -0.001861572265625 +88156 0.04327392578125 +88157 -0.00042724609375 +88158 0.038177490234375 +88159 0.001190185546875 +88160 0.076263427734375 +88161 0.003021240234375 +88162 0.14105224609375 +88163 0.0048828125 +88164 0.186431884765625 +88165 0.00634765625 +88166 0.188812255859375 +88167 0.007171630859375 +88168 0.1390380859375 +88169 0.00726318359375 +88170 0.041778564453125 +88171 0.006622314453125 +88172 -0.079437255859375 +88173 0.005462646484375 +88174 -0.219390869140625 +88175 0.00384521484375 +88176 -0.367828369140625 +88177 0.00189208984375 +88178 -0.494873046875 +88179 -9.1552734375e-05 +88180 -0.556243896484375 +88181 -0.001678466796875 +88182 -0.508697509765625 +88183 -0.002471923828125 +88184 -0.3756103515625 +88185 -0.002593994140625 +88186 -0.218902587890625 +88187 -0.002471923828125 +88188 -0.063751220703125 +88189 -0.0023193359375 +88190 0.091552734375 +88191 -0.002044677734375 +88192 0.23602294921875 +88193 -0.001678466796875 +88194 0.342987060546875 +88195 -0.001373291015625 +88196 0.39520263671875 +88197 -0.001251220703125 +88198 0.389373779296875 +88199 -0.001312255859375 +88200 0.324249267578125 +88201 -0.001556396484375 +88202 0.224090576171875 +88203 -0.001800537109375 +88204 0.124267578125 +88205 -0.001800537109375 +88206 0.037078857421875 +88207 -0.00152587890625 +88208 -0.010101318359375 +88209 -0.000823974609375 +88210 -0.019439697265625 +88211 0.00018310546875 +88212 -0.022796630859375 +88213 0.001190185546875 +88214 -0.001556396484375 +88215 0.002288818359375 +88216 0.056304931640625 +88217 0.003509521484375 +88218 0.106719970703125 +88219 0.004486083984375 +88220 0.096893310546875 +88221 0.004730224609375 +88222 0.042694091796875 +88223 0.00439453125 +88224 -0.018035888671875 +88225 0.0037841796875 +88226 -0.07586669921875 +88227 0.00299072265625 +88228 -0.11944580078125 +88229 0.002105712890625 +88230 -0.15972900390625 +88231 0.0010986328125 +88232 -0.202606201171875 +88233 0.0 +88234 -0.24859619140625 +88235 -0.001129150390625 +88236 -0.30517578125 +88237 -0.0023193359375 +88238 -0.36212158203125 +88239 -0.00347900390625 +88240 -0.39141845703125 +88241 -0.00433349609375 +88242 -0.35528564453125 +88243 -0.00457763671875 +88244 -0.249969482421875 +88245 -0.004119873046875 +88246 -0.092864990234375 +88247 -0.003082275390625 +88248 0.08905029296875 +88249 -0.001708984375 +88250 0.2352294921875 +88251 -0.000457763671875 +88252 0.318817138671875 +88253 0.00042724609375 +88254 0.358642578125 +88255 0.001068115234375 +88256 0.347747802734375 +88257 0.00140380859375 +88258 0.28564453125 +88259 0.001373291015625 +88260 0.223175048828125 +88261 0.0013427734375 +88262 0.196746826171875 +88263 0.0015869140625 +88264 0.179840087890625 +88265 0.001922607421875 +88266 0.155548095703125 +88267 0.002166748046875 +88268 0.151214599609375 +88269 0.00250244140625 +88270 0.156951904296875 +88271 0.002838134765625 +88272 0.13177490234375 +88273 0.002838134765625 +88274 0.100799560546875 +88275 0.002685546875 +88276 0.087127685546875 +88277 0.0025634765625 +88278 0.05487060546875 +88279 0.002197265625 +88280 -0.009002685546875 +88281 0.001495361328125 +88282 -0.10400390625 +88283 0.000457763671875 +88284 -0.229400634765625 +88285 -0.0008544921875 +88286 -0.35552978515625 +88287 -0.002197265625 +88288 -0.441925048828125 +88289 -0.003204345703125 +88290 -0.473846435546875 +88291 -0.0037841796875 +88292 -0.464813232421875 +88293 -0.003997802734375 +88294 -0.419097900390625 +88295 -0.003875732421875 +88296 -0.334320068359375 +88297 -0.00335693359375 +88298 -0.227935791015625 +88299 -0.002593994140625 +88300 -0.12347412109375 +88301 -0.00177001953125 +88302 -0.02764892578125 +88303 -0.000946044921875 +88304 0.077667236328125 +88305 0.0 +88306 0.2132568359375 +88307 0.001220703125 +88308 0.38885498046875 +88309 0.002777099609375 +88310 0.582794189453125 +88311 0.004486083984375 +88312 0.734039306640625 +88313 0.005828857421875 +88314 0.800140380859375 +88315 0.0064697265625 +88316 0.7783203125 +88317 0.006378173828125 +88318 0.6651611328125 +88319 0.00555419921875 +88320 0.45965576171875 +88321 0.003509521484375 +88322 0.199188232421875 +88323 0.0 +88324 -0.050689697265625 +88325 -0.00347900390625 +88326 -0.23297119140625 +88327 -0.00482177734375 +88328 -0.33013916015625 +88329 -0.003509521484375 +88330 -0.368408203125 +88331 -0.000732421875 +88332 -0.378936767578125 +88333 0.002105712890625 +88334 -0.376983642578125 +88335 0.00433349609375 +88336 -0.37969970703125 +88337 0.005218505859375 +88338 -0.391510009765625 +88339 0.004608154296875 +88340 -0.385345458984375 +88341 0.003662109375 +88342 -0.3419189453125 +88343 0.003265380859375 +88344 -0.28289794921875 +88345 0.002716064453125 +88346 -0.251617431640625 +88347 0.00042724609375 +88348 -0.266143798828125 +88349 -0.004058837890625 +88350 -0.273345947265625 +88351 -0.0084228515625 +88352 -0.216796875 +88353 -0.010223388671875 +88354 -0.128265380859375 +88355 -0.010498046875 +88356 -0.068145751953125 +88357 -0.011444091796875 +88358 -0.0430908203125 +88359 -0.013153076171875 +88360 -0.024444580078125 +88361 -0.014373779296875 +88362 0.020721435546875 +88363 -0.013702392578125 +88364 0.124481201171875 +88365 -0.00982666015625 +88366 0.25787353515625 +88367 -0.003936767578125 +88368 0.379119873046875 +88369 0.002197265625 +88370 0.47991943359375 +88371 0.0081787109375 +88372 0.5281982421875 +88373 0.012603759765625 +88374 0.511138916015625 +88375 0.01483154296875 +88376 0.456207275390625 +88377 0.0157470703125 +88378 0.407470703125 +88379 0.0169677734375 +88380 0.383758544921875 +88381 0.019073486328125 +88382 0.35687255859375 +88383 0.020721435546875 +88384 0.31182861328125 +88385 0.02117919921875 +88386 0.250885009765625 +88387 0.02044677734375 +88388 0.1654052734375 +88389 0.01812744140625 +88390 0.035247802734375 +88391 0.013336181640625 +88392 -0.142059326171875 +88393 0.006011962890625 +88394 -0.33563232421875 +88395 -0.0025634765625 +88396 -0.5345458984375 +88397 -0.011871337890625 +88398 -0.72186279296875 +88399 -0.021148681640625 +88400 -0.836669921875 +88401 -0.02783203125 +88402 -0.8326416015625 +88403 -0.02996826171875 +88404 -0.7296142578125 +88405 -0.028228759765625 +88406 -0.582550048828125 +88407 -0.024688720703125 +88408 -0.440093994140625 +88409 -0.02117919921875 +88410 -0.324310302734375 +88411 -0.018463134765625 +88412 -0.20147705078125 +88413 -0.01507568359375 +88414 -0.044647216796875 +88415 -0.009857177734375 +88416 0.103973388671875 +88417 -0.00445556640625 +88418 0.202392578125 +88419 -0.00054931640625 +88420 0.264495849609375 +88421 0.00238037109375 +88422 0.338897705078125 +88423 0.0062255859375 +88424 0.443817138671875 +88425 0.01165771484375 +88426 0.545074462890625 +88427 0.0172119140625 +88428 0.6173095703125 +88429 0.021820068359375 +88430 0.6524658203125 +88431 0.025054931640625 +88432 0.66339111328125 +88433 0.027313232421875 +88434 0.6561279296875 +88435 0.02874755859375 +88436 0.606781005859375 +88437 0.028289794921875 +88438 0.501190185546875 +88439 0.025299072265625 +88440 0.352783203125 +88441 0.020263671875 +88442 0.176544189453125 +88443 0.013763427734375 +88444 -0.034820556640625 +88445 0.0054931640625 +88446 -0.258209228515625 +88447 -0.003570556640625 +88448 -0.44244384765625 +88449 -0.011383056640625 +88450 -0.5753173828125 +88451 -0.017425537109375 +88452 -0.65203857421875 +88453 -0.021484375 +88454 -0.641632080078125 +88455 -0.022247314453125 +88456 -0.562164306640625 +88457 -0.020416259765625 +88458 -0.458038330078125 +88459 -0.017669677734375 +88460 -0.350555419921875 +88461 -0.014739990234375 +88462 -0.260528564453125 +88463 -0.01239013671875 +88464 -0.192108154296875 +88465 -0.0107421875 +88466 -0.141937255859375 +88467 -0.00958251953125 +88468 -0.1021728515625 +88469 -0.008544921875 +88470 -0.062896728515625 +88471 -0.00726318359375 +88472 -0.011932373046875 +88473 -0.005218505859375 +88474 0.062835693359375 +88475 -0.001953125 +88476 0.148712158203125 +88477 0.00201416015625 +88478 0.241729736328125 +88479 0.0064697265625 +88480 0.34912109375 +88481 0.01165771484375 +88482 0.457305908203125 +88483 0.0169677734375 +88484 0.54388427734375 +88485 0.02142333984375 +88486 0.5728759765625 +88487 0.0235595703125 +88488 0.506591796875 +88489 0.021820068359375 +88490 0.351226806640625 +88491 0.016387939453125 +88492 0.146514892578125 +88493 0.008819580078125 +88494 -0.05523681640625 +88495 0.001190185546875 +88496 -0.21624755859375 +88497 -0.004974365234375 +88498 -0.334930419921875 +88499 -0.009613037109375 +88500 -0.402984619140625 +88501 -0.01239013671875 +88502 -0.4412841796875 +88503 -0.014129638671875 +88504 -0.49578857421875 +88505 -0.016693115234375 +88506 -0.5601806640625 +88507 -0.019775390625 +88508 -0.600738525390625 +88509 -0.02197265625 +88510 -0.584228515625 +88511 -0.02197265625 +88512 -0.47930908203125 +88513 -0.018463134765625 +88514 -0.27935791015625 +88515 -0.01116943359375 +88516 -0.0089111328125 +88517 -0.001007080078125 +88518 0.268798828125 +88519 0.009490966796875 +88520 0.482818603515625 +88521 0.01751708984375 +88522 0.60369873046875 +88523 0.021881103515625 +88524 0.650421142578125 +88525 0.023406982421875 +88526 0.66400146484375 +88527 0.023773193359375 +88528 0.6414794921875 +88529 0.022857666015625 +88530 0.572540283203125 +88531 0.020233154296875 +88532 0.498138427734375 +88533 0.01751708984375 +88534 0.439453125 +88535 0.01556396484375 +88536 0.375518798828125 +88537 0.01348876953125 +88538 0.274505615234375 +88539 0.010009765625 +88540 0.1087646484375 +88541 0.00396728515625 +88542 -0.099395751953125 +88543 -0.00372314453125 +88544 -0.3182373046875 +88545 -0.0118408203125 +88546 -0.5489501953125 +88547 -0.020477294921875 +88548 -0.7738037109375 +88549 -0.028900146484375 +88550 -0.86383056640625 +88551 -0.035064697265625 +88552 -0.870391845703125 +88553 -0.03765869140625 +88554 -0.86895751953125 +88555 -0.03741455078125 +88556 -0.861053466796875 +88557 -0.034881591796875 +88558 -0.765869140625 +88559 -0.02935791015625 +88560 -0.5301513671875 +88561 -0.020416259765625 +88562 -0.214691162109375 +88563 -0.00830078125 +88564 0.137359619140625 +88565 0.005279541015625 +88566 0.474822998046875 +88567 0.018310546875 +88568 0.76239013671875 +88569 0.0294189453125 +88570 0.867462158203125 +88571 0.03753662109375 +88572 0.870361328125 +88573 0.042724609375 +88574 0.86480712890625 +88575 0.044525146484375 +88576 0.831817626953125 +88577 0.0433349609375 +88578 0.677581787109375 +88579 0.040252685546875 +88580 0.495880126953125 +88581 0.035491943359375 +88582 0.30767822265625 +88583 0.03009033203125 +88584 0.116180419921875 +88585 0.023834228515625 +88586 -0.110748291015625 +88587 0.014007568359375 +88588 -0.381805419921875 +88589 -0.000335693359375 +88590 -0.6572265625 +88591 -0.0166015625 +88592 -0.857421875 +88593 -0.030914306640625 +88594 -0.870391845703125 +88595 -0.04058837890625 +88596 -0.870391845703125 +88597 -0.045440673828125 +88598 -0.86444091796875 +88599 -0.047637939453125 +88600 -0.85723876953125 +88601 -0.0499267578125 +88602 -0.790008544921875 +88603 -0.051055908203125 +88604 -0.62847900390625 +88605 -0.04705810546875 +88606 -0.3956298828125 +88607 -0.03759765625 +88608 -0.126708984375 +88609 -0.024810791015625 +88610 0.150115966796875 +88611 -0.0103759765625 +88612 0.424041748046875 +88613 0.005157470703125 +88614 0.670623779296875 +88615 0.02020263671875 +88616 0.854522705078125 +88617 0.032379150390625 +88618 0.866485595703125 +88619 0.040771484375 +88620 0.86920166015625 +88621 0.04461669921875 +88622 0.8653564453125 +88623 0.0455322265625 +88624 0.857147216796875 +88625 0.044708251953125 +88626 0.766845703125 +88627 0.0421142578125 +88628 0.628509521484375 +88629 0.038177490234375 +88630 0.462127685546875 +88631 0.03240966796875 +88632 0.297210693359375 +88633 0.026611328125 +88634 0.14862060546875 +88635 0.021514892578125 +88636 -0.00537109375 +88637 0.0152587890625 +88638 -0.15753173828125 +88639 0.008148193359375 +88640 -0.31304931640625 +88641 -0.0003662109375 +88642 -0.48876953125 +88643 -0.0115966796875 +88644 -0.6416015625 +88645 -0.0224609375 +88646 -0.751373291015625 +88647 -0.031494140625 +88648 -0.84619140625 +88649 -0.040618896484375 +88650 -0.861297607421875 +88651 -0.048980712890625 +88652 -0.863250732421875 +88653 -0.05438232421875 +88654 -0.856597900390625 +88655 -0.05462646484375 +88656 -0.7498779296875 +88657 -0.050628662109375 +88658 -0.624542236328125 +88659 -0.046539306640625 +88660 -0.47808837890625 +88661 -0.0406494140625 +88662 -0.253387451171875 +88663 -0.02862548828125 +88664 0.003692626953125 +88665 -0.013580322265625 +88666 0.2257080078125 +88667 -0.00018310546875 +88668 0.427154541015625 +88669 0.0126953125 +88670 0.643218994140625 +88671 0.02764892578125 +88672 0.855926513671875 +88673 0.044219970703125 +88674 0.870361328125 +88675 0.058502197265625 +88676 0.870361328125 +88677 0.067108154296875 +88678 0.862762451171875 +88679 0.070709228515625 +88680 0.79669189453125 +88681 0.0692138671875 +88682 0.595794677734375 +88683 0.062042236328125 +88684 0.362152099609375 +88685 0.051239013671875 +88686 0.1270751953125 +88687 0.038818359375 +88688 -0.086944580078125 +88689 0.02618408203125 +88690 -0.2784423828125 +88691 0.0133056640625 +88692 -0.484832763671875 +88693 -0.00244140625 +88694 -0.729583740234375 +88695 -0.022674560546875 +88696 -0.86688232421875 +88697 -0.043975830078125 +88698 -0.870391845703125 +88699 -0.061981201171875 +88700 -0.86859130859375 +88701 -0.076507568359375 +88702 -0.86279296875 +88703 -0.087615966796875 +88704 -0.817962646484375 +88705 -0.092864990234375 +88706 -0.6116943359375 +88707 -0.089111328125 +88708 -0.3128662109375 +88709 -0.075897216796875 +88710 0.039398193359375 +88711 -0.0556640625 +88712 0.422821044921875 +88713 -0.02984619140625 +88714 0.805145263671875 +88715 -0.000762939453125 +88716 0.870361328125 +88717 0.026763916015625 +88718 0.870361328125 +88719 0.04876708984375 +88720 0.860015869140625 +88721 0.0645751953125 +88722 0.727935791015625 +88723 0.07379150390625 +88724 0.48114013671875 +88725 0.076202392578125 +88726 0.2059326171875 +88727 0.07373046875 +88728 -0.06103515625 +88729 0.068145751953125 +88730 -0.29913330078125 +88731 0.060302734375 +88732 -0.516204833984375 +88733 0.04925537109375 +88734 -0.7252197265625 +88735 0.033966064453125 +88736 -0.85980224609375 +88737 0.016265869140625 +88738 -0.870391845703125 +88739 -0.001373291015625 +88740 -0.870391845703125 +88741 -0.016845703125 +88742 -0.858062744140625 +88743 -0.026702880859375 +88744 -0.673004150390625 +88745 -0.03076171875 +88746 -0.42694091796875 +88747 -0.032928466796875 +88748 -0.2100830078125 +88749 -0.0364990234375 +88750 -0.0362548828125 +88751 -0.041412353515625 +88752 0.10943603515625 +88753 -0.04571533203125 +88754 0.23516845703125 +88755 -0.048065185546875 +88756 0.373687744140625 +88757 -0.04559326171875 +88758 0.517791748046875 +88759 -0.03851318359375 +88760 0.602783203125 +88761 -0.03143310546875 +88762 0.635711669921875 +88763 -0.02398681640625 +88764 0.655181884765625 +88765 -0.013824462890625 +88766 0.65948486328125 +88767 -0.00164794921875 +88768 0.651275634765625 +88769 0.011962890625 +88770 0.61846923828125 +88771 0.0252685546875 +88772 0.53753662109375 +88773 0.035675048828125 +88774 0.404144287109375 +88775 0.041961669921875 +88776 0.22186279296875 +88777 0.043548583984375 +88778 0.003997802734375 +88779 0.040679931640625 +88780 -0.22100830078125 +88781 0.034759521484375 +88782 -0.42449951171875 +88783 0.02734375 +88784 -0.579833984375 +88785 0.02001953125 +88786 -0.641876220703125 +88787 0.01593017578125 +88788 -0.6177978515625 +88789 0.0146484375 +88790 -0.575531005859375 +88791 0.01153564453125 +88792 -0.526336669921875 +88793 0.006195068359375 +88794 -0.42645263671875 +88795 0.002349853515625 +88796 -0.2581787109375 +88797 0.00189208984375 +88798 -0.068695068359375 +88799 0.002197265625 +88800 0.09222412109375 +88801 0.00042724609375 +88802 0.232147216796875 +88803 -0.0020751953125 +88804 0.3509521484375 +88805 -0.00469970703125 +88806 0.410064697265625 +88807 -0.0096435546875 +88808 0.372955322265625 +88809 -0.019073486328125 +88810 0.2554931640625 +88811 -0.03155517578125 +88812 0.10711669921875 +88813 -0.04339599609375 +88814 -0.052886962890625 +88815 -0.053192138671875 +88816 -0.186279296875 +88817 -0.058380126953125 +88818 -0.23291015625 +88819 -0.054962158203125 +88820 -0.209442138671875 +88821 -0.044586181640625 +88822 -0.174163818359375 +88823 -0.031982421875 +88824 -0.126739501953125 +88825 -0.0177001953125 +88826 -0.048126220703125 +88827 -0.001007080078125 +88828 0.0426025390625 +88829 0.016082763671875 +88830 0.10748291015625 +88831 0.030303955078125 +88832 0.1409912109375 +88833 0.04119873046875 +88834 0.19708251953125 +88835 0.05303955078125 +88836 0.273651123046875 +88837 0.0645751953125 +88838 0.31768798828125 +88839 0.070465087890625 +88840 0.341094970703125 +88841 0.071990966796875 +88842 0.368011474609375 +88843 0.071746826171875 +88844 0.37249755859375 +88845 0.0673828125 +88846 0.30072021484375 +88847 0.05389404296875 +88848 0.1517333984375 +88849 0.031585693359375 +88850 -0.01470947265625 +88851 0.006866455078125 +88852 -0.1883544921875 +88853 -0.01873779296875 +88854 -0.372711181640625 +88855 -0.04510498046875 +88856 -0.51397705078125 +88857 -0.066436767578125 +88858 -0.57177734375 +88859 -0.078338623046875 +88860 -0.53948974609375 +88861 -0.079833984375 +88862 -0.43511962890625 +88863 -0.072509765625 +88864 -0.2962646484375 +88865 -0.060028076171875 +88866 -0.161102294921875 +88867 -0.046173095703125 +88868 -0.0435791015625 +88869 -0.03240966796875 +88870 0.060394287109375 +88871 -0.01849365234375 +88872 0.13665771484375 +88873 -0.006103515625 +88874 0.170135498046875 +88875 0.0029296875 +88876 0.16552734375 +88877 0.008758544921875 +88878 0.15728759765625 +88879 0.01446533203125 +88880 0.150787353515625 +88881 0.020233154296875 +88882 0.12200927734375 +88883 0.0233154296875 +88884 0.080108642578125 +88885 0.0242919921875 +88886 0.05126953125 +88887 0.025543212890625 +88888 0.062896728515625 +88889 0.02960205078125 +88890 0.09271240234375 +88891 0.03411865234375 +88892 0.092987060546875 +88893 0.0343017578125 +88894 0.07855224609375 +88895 0.031646728515625 +88896 0.06427001953125 +88897 0.027740478515625 +88898 0.0347900390625 +88899 0.021209716796875 +88900 -0.01171875 +88901 0.012115478515625 +88902 -0.056060791015625 +88903 0.002655029296875 +88904 -0.055511474609375 +88905 -0.002593994140625 +88906 -0.010467529296875 +88907 -0.003387451171875 +88908 0.02508544921875 +88909 -0.00482177734375 +88910 0.025665283203125 +88911 -0.009185791015625 +88912 0.017333984375 +88913 -0.013641357421875 +88914 0.00189208984375 +88915 -0.017822265625 +88916 -0.03173828125 +88917 -0.022735595703125 +88918 -0.071502685546875 +88919 -0.027130126953125 +88920 -0.13543701171875 +88921 -0.0328369140625 +88922 -0.219970703125 +88923 -0.03955078125 +88924 -0.300506591796875 +88925 -0.044891357421875 +88926 -0.376312255859375 +88927 -0.048980712890625 +88928 -0.416107177734375 +88929 -0.048919677734375 +88930 -0.371124267578125 +88931 -0.0400390625 +88932 -0.242279052734375 +88933 -0.022705078125 +88934 -0.069732666015625 +88935 -0.001190185546875 +88936 0.125640869140625 +88937 0.02215576171875 +88938 0.31268310546875 +88939 0.044036865234375 +88940 0.45501708984375 +88941 0.060638427734375 +88942 0.554779052734375 +88943 0.072052001953125 +88944 0.61065673828125 +88945 0.078125 +88946 0.610931396484375 +88947 0.07769775390625 +88948 0.531463623046875 +88949 0.068389892578125 +88950 0.3883056640625 +88951 0.051910400390625 +88952 0.23468017578125 +88953 0.03375244140625 +88954 0.095245361328125 +88955 0.016571044921875 +88956 -0.00396728515625 +88957 0.003143310546875 +88958 -0.04852294921875 +88959 -0.0048828125 +88960 -0.055145263671875 +88961 -0.009002685546875 +88962 -0.0758056640625 +88963 -0.014190673828125 +88964 -0.138702392578125 +88965 -0.023101806640625 +88966 -0.209197998046875 +88967 -0.03216552734375 +88968 -0.289031982421875 +88969 -0.041473388671875 +88970 -0.37884521484375 +88971 -0.051055908203125 +88972 -0.456329345703125 +88973 -0.05865478515625 +88974 -0.51641845703125 +88975 -0.06378173828125 +88976 -0.519287109375 +88977 -0.062530517578125 +88978 -0.458251953125 +88979 -0.0543212890625 +88980 -0.384796142578125 +88981 -0.044464111328125 +88982 -0.323699951171875 +88983 -0.035552978515625 +88984 -0.269287109375 +88985 -0.02716064453125 +88986 -0.1951904296875 +88987 -0.016815185546875 +88988 -0.100006103515625 +88989 -0.00457763671875 +88990 -0.01055908203125 +88991 0.0067138671875 +88992 0.1033935546875 +88993 0.01995849609375 +88994 0.24908447265625 +88995 0.035797119140625 +88996 0.373199462890625 +88997 0.048858642578125 +88998 0.45806884765625 +88999 0.057342529296875 +89000 0.511474609375 +89001 0.062042236328125 +89002 0.565399169921875 +89003 0.066192626953125 +89004 0.61138916015625 +89005 0.069061279296875 +89006 0.5897216796875 +89007 0.064788818359375 +89008 0.4906005859375 +89009 0.052520751953125 +89010 0.33148193359375 +89011 0.03411865234375 +89012 0.147796630859375 +89013 0.013275146484375 +89014 -0.01873779296875 +89015 -0.00567626953125 +89016 -0.140289306640625 +89017 -0.01983642578125 +89018 -0.191986083984375 +89019 -0.026611328125 +89020 -0.184295654296875 +89021 -0.027008056640625 +89022 -0.161834716796875 +89023 -0.025421142578125 +89024 -0.166595458984375 +89025 -0.0260009765625 +89026 -0.19390869140625 +89027 -0.028289794921875 +89028 -0.22442626953125 +89029 -0.0303955078125 +89030 -0.279754638671875 +89031 -0.0345458984375 +89032 -0.3389892578125 +89033 -0.038726806640625 +89034 -0.3543701171875 +89035 -0.03826904296875 +89036 -0.348175048828125 +89037 -0.0355224609375 +89038 -0.32598876953125 +89039 -0.03118896484375 +89040 -0.2581787109375 +89041 -0.02239990234375 +89042 -0.139801025390625 +89043 -0.008758544921875 +89044 0.014617919921875 +89045 0.008148193359375 +89046 0.144378662109375 +89047 0.02215576171875 +89048 0.221038818359375 +89049 0.0303955078125 +89050 0.27069091796875 +89051 0.03546142578125 +89052 0.294036865234375 +89053 0.03741455078125 +89054 0.311767578125 +89055 0.038360595703125 +89056 0.339141845703125 +89057 0.0399169921875 +89058 0.360260009765625 +89059 0.040618896484375 +89060 0.360504150390625 +89061 0.039093017578125 +89062 0.308380126953125 +89063 0.032135009765625 +89064 0.18170166015625 +89065 0.01751708984375 +89066 0.0047607421875 +89067 -0.00213623046875 +89068 -0.17559814453125 +89069 -0.02191162109375 +89070 -0.3143310546875 +89071 -0.037109375 +89072 -0.36785888671875 +89073 -0.04315185546875 +89074 -0.36248779296875 +89075 -0.042755126953125 +89076 -0.343536376953125 +89077 -0.0406494140625 +89078 -0.3018798828125 +89079 -0.035919189453125 +89080 -0.231414794921875 +89081 -0.0279541015625 +89082 -0.117645263671875 +89083 -0.015289306640625 +89084 0.007049560546875 +89085 -0.0013427734375 +89086 0.087982177734375 +89087 0.00811767578125 +89088 0.13946533203125 +89089 0.014495849609375 +89090 0.17425537109375 +89091 0.01910400390625 +89092 0.188201904296875 +89093 0.021514892578125 +89094 0.171234130859375 +89095 0.020172119140625 +89096 0.118438720703125 +89097 0.014251708984375 +89098 0.05706787109375 +89099 0.00732421875 +89100 -0.010711669921875 +89101 -0.00048828125 +89102 -0.0914306640625 +89103 -0.010162353515625 +89104 -0.162322998046875 +89105 -0.018707275390625 +89106 -0.194549560546875 +89107 -0.022247314453125 +89108 -0.1492919921875 +89109 -0.01556396484375 +89110 -0.02166748046875 +89111 0.001983642578125 +89112 0.124053955078125 +89113 0.021636962890625 +89114 0.211151123046875 +89115 0.032989501953125 +89116 0.240447998046875 +89117 0.036224365234375 +89118 0.242218017578125 +89119 0.0355224609375 +89120 0.2257080078125 +89121 0.032196044921875 +89122 0.194366455078125 +89123 0.02679443359375 +89124 0.115509033203125 +89125 0.01495361328125 +89126 0.0128173828125 +89127 0.0 +89128 -0.053802490234375 +89129 -0.009857177734375 +89130 -0.110626220703125 +89131 -0.0181884765625 +89132 -0.199493408203125 +89133 -0.030670166015625 +89134 -0.29437255859375 +89135 -0.043731689453125 +89136 -0.33221435546875 +89137 -0.048797607421875 +89138 -0.27972412109375 +89139 -0.041351318359375 +89140 -0.185333251953125 +89141 -0.02801513671875 +89142 -0.128204345703125 +89143 -0.01959228515625 +89144 -0.115692138671875 +89145 -0.017120361328125 +89146 -0.116455078125 +89147 -0.016387939453125 +89148 -0.105926513671875 +89149 -0.01409912109375 +89150 -0.053955078125 +89151 -0.006195068359375 +89152 0.048797607421875 +89153 0.008514404296875 +89154 0.157318115234375 +89155 0.023895263671875 +89156 0.212005615234375 +89157 0.03179931640625 +89158 0.218475341796875 +89159 0.032958984375 +89160 0.23724365234375 +89161 0.035614013671875 +89162 0.30535888671875 +89163 0.0447998046875 +89164 0.38128662109375 +89165 0.05487060546875 +89166 0.404449462890625 +89167 0.05755615234375 +89168 0.3944091796875 +89169 0.055572509765625 +89170 0.3885498046875 +89171 0.054046630859375 +89172 0.362640380859375 +89173 0.049774169921875 +89174 0.27362060546875 +89175 0.03692626953125 +89176 0.11712646484375 +89177 0.01495361328125 +89178 -0.054901123046875 +89179 -0.009002685546875 +89180 -0.19085693359375 +89181 -0.027923583984375 +89182 -0.28570556640625 +89183 -0.041107177734375 +89184 -0.339263916015625 +89185 -0.04852294921875 +89186 -0.3775634765625 +89187 -0.0537109375 +89188 -0.445709228515625 +89189 -0.06280517578125 +89190 -0.535064697265625 +89191 -0.074615478515625 +89192 -0.629058837890625 +89193 -0.086944580078125 +89194 -0.697601318359375 +89195 -0.095703125 +89196 -0.70391845703125 +89197 -0.095947265625 +89198 -0.6424560546875 +89199 -0.086944580078125 +89200 -0.491241455078125 +89201 -0.06573486328125 +89202 -0.265716552734375 +89203 -0.03448486328125 +89204 -0.023712158203125 +89205 -0.001068115234375 +89206 0.201751708984375 +89207 0.02996826171875 +89208 0.375823974609375 +89209 0.053863525390625 +89210 0.485076904296875 +89211 0.06878662109375 +89212 0.56884765625 +89213 0.080078125 +89214 0.634765625 +89215 0.088775634765625 +89216 0.63763427734375 +89217 0.088775634765625 +89218 0.5660400390625 +89219 0.07855224609375 +89220 0.4720458984375 +89221 0.06524658203125 +89222 0.40692138671875 +89223 0.055816650390625 +89224 0.3778076171875 +89225 0.05126953125 +89226 0.376953125 +89227 0.05059814453125 +89228 0.371978759765625 +89229 0.049407958984375 +89230 0.313140869140625 +89231 0.04095458984375 +89232 0.184417724609375 +89233 0.0230712890625 +89234 0.011199951171875 +89235 -0.000701904296875 +89236 -0.171051025390625 +89237 -0.025543212890625 +89238 -0.33740234375 +89239 -0.04803466796875 +89240 -0.47198486328125 +89241 -0.0660400390625 +89242 -0.560394287109375 +89243 -0.07763671875 +89244 -0.58056640625 +89245 -0.079864501953125 +89246 -0.54754638671875 +89247 -0.074798583984375 +89248 -0.508575439453125 +89249 -0.06890869140625 +89250 -0.459503173828125 +89251 -0.061676025390625 +89252 -0.394378662109375 +89253 -0.05230712890625 +89254 -0.35260009765625 +89255 -0.046173095703125 +89256 -0.31170654296875 +89257 -0.04022216796875 +89258 -0.197418212890625 +89259 -0.024383544921875 +89260 -0.007965087890625 +89261 0.00152587890625 +89262 0.207489013671875 +89263 0.03082275390625 +89264 0.409210205078125 +89265 0.05810546875 +89266 0.57208251953125 +89267 0.0799560546875 +89268 0.66595458984375 +89269 0.092315673828125 +89270 0.65875244140625 +89271 0.090850830078125 +89272 0.56744384765625 +89273 0.077880859375 +89274 0.431396484375 +89275 0.058807373046875 +89276 0.29443359375 +89277 0.039642333984375 +89278 0.182464599609375 +89279 0.023895263671875 +89280 0.06365966796875 +89281 0.007293701171875 +89282 -0.075958251953125 +89283 -0.01202392578125 +89284 -0.189422607421875 +89285 -0.027679443359375 +89286 -0.271942138671875 +89287 -0.038970947265625 +89288 -0.342529296875 +89289 -0.048492431640625 +89290 -0.364166259765625 +89291 -0.051239013671875 +89292 -0.327239990234375 +89293 -0.045928955078125 +89294 -0.2769775390625 +89295 -0.038726806640625 +89296 -0.253692626953125 +89297 -0.035125732421875 +89298 -0.24365234375 +89299 -0.03326416015625 +89300 -0.1983642578125 +89301 -0.026580810546875 +89302 -0.116241455078125 +89303 -0.014892578125 +89304 -0.036834716796875 +89305 -0.003631591796875 +89306 0.034881591796875 +89307 0.006500244140625 +89308 0.09124755859375 +89309 0.014434814453125 +89310 0.10888671875 +89311 0.016998291015625 +89312 0.125518798828125 +89313 0.019287109375 +89314 0.15771484375 +89315 0.0235595703125 +89316 0.17828369140625 +89317 0.026123046875 +89318 0.17108154296875 +89319 0.024810791015625 +89320 0.129974365234375 +89321 0.018798828125 +89322 0.082427978515625 +89323 0.011871337890625 +89324 0.027679443359375 +89325 0.003936767578125 +89326 -0.065643310546875 +89327 -0.009185791015625 +89328 -0.15936279296875 +89329 -0.02227783203125 +89330 -0.21307373046875 +89331 -0.029876708984375 +89332 -0.234649658203125 +89333 -0.03302001953125 +89334 -0.2001953125 +89335 -0.028472900390625 +89336 -0.119171142578125 +89337 -0.017486572265625 +89338 -0.024749755859375 +89339 -0.00457763671875 +89340 0.085784912109375 +89341 0.010589599609375 +89342 0.178131103515625 +89343 0.0233154296875 +89344 0.215576171875 +89345 0.02838134765625 +89346 0.211456298828125 +89347 0.0274658203125 +89348 0.17523193359375 +89349 0.021759033203125 +89350 0.128753662109375 +89351 0.01483154296875 +89352 0.1019287109375 +89353 0.0115966796875 +89354 0.0743408203125 +89355 0.008544921875 +89356 0.04327392578125 +89357 0.005096435546875 +89358 0.038177490234375 +89359 0.006072998046875 +89360 0.076263427734375 +89361 0.014251708984375 +89362 0.14105224609375 +89363 0.0267333984375 +89364 0.186431884765625 +89365 0.035675048828125 +89366 0.188812255859375 +89367 0.037078857421875 +89368 0.1390380859375 +89369 0.029388427734375 +89370 0.041778564453125 +89371 0.013336181640625 +89372 -0.079437255859375 +89373 -0.007080078125 +89374 -0.219390869140625 +89375 -0.030975341796875 +89376 -0.367828369140625 +89377 -0.0565185546875 +89378 -0.494873046875 +89379 -0.078704833984375 +89380 -0.556243896484375 +89381 -0.090057373046875 +89382 -0.508697509765625 +89383 -0.083251953125 +89384 -0.3756103515625 +89385 -0.0621337890625 +89386 -0.218902587890625 +89387 -0.03704833984375 +89388 -0.063751220703125 +89389 -0.01214599609375 +89390 0.091552734375 +89391 0.01287841796875 +89392 0.23602294921875 +89393 0.0362548828125 +89394 0.342987060546875 +89395 0.053497314453125 +89396 0.39520263671875 +89397 0.061767578125 +89398 0.389373779296875 +89399 0.060546875 +89400 0.324249267578125 +89401 0.049652099609375 +89402 0.224090576171875 +89403 0.033172607421875 +89404 0.124267578125 +89405 0.016998291015625 +89406 0.037078857421875 +89407 0.003143310546875 +89408 -0.010101318359375 +89409 -0.003814697265625 +89410 -0.019439697265625 +89411 -0.004302978515625 +89412 -0.022796630859375 +89413 -0.003753662109375 +89414 -0.001556396484375 +89415 0.000885009765625 +89416 0.056304931640625 +89417 0.01153564453125 +89418 0.106719970703125 +89419 0.020782470703125 +89420 0.096893310546875 +89421 0.019744873046875 +89422 0.042694091796875 +89423 0.01104736328125 +89424 -0.018035888671875 +89425 0.001007080078125 +89426 -0.07586669921875 +89427 -0.00872802734375 +89428 -0.11944580078125 +89429 -0.016265869140625 +89430 -0.15972900390625 +89431 -0.023406982421875 +89432 -0.202606201171875 +89433 -0.0311279296875 +89434 -0.24859619140625 +89435 -0.039459228515625 +89436 -0.30517578125 +89437 -0.049652099609375 +89438 -0.36212158203125 +89439 -0.0599365234375 +89440 -0.39141845703125 +89441 -0.065582275390625 +89442 -0.35528564453125 +89443 -0.0601806640625 +89444 -0.249969482421875 +89445 -0.0430908203125 +89446 -0.092864990234375 +89447 -0.0172119140625 +89448 0.08905029296875 +89449 0.012939453125 +89450 0.2352294921875 +89451 0.037200927734375 +89452 0.318817138671875 +89453 0.05108642578125 +89454 0.358642578125 +89455 0.057769775390625 +89456 0.347747802734375 +89457 0.056060791015625 +89458 0.28564453125 +89459 0.045867919921875 +89460 0.223175048828125 +89461 0.035736083984375 +89462 0.196746826171875 +89463 0.03173828125 +89464 0.179840087890625 +89465 0.029388427734375 +89466 0.155548095703125 +89467 0.02581787109375 +89468 0.151214599609375 +89469 0.025604248046875 +89470 0.156951904296875 +89471 0.027069091796875 +89472 0.13177490234375 +89473 0.023284912109375 +89474 0.100799560546875 +89475 0.018463134765625 +89476 0.087127685546875 +89477 0.016448974609375 +89478 0.05487060546875 +89479 0.011199951171875 +89480 -0.009002685546875 +89481 0.00054931640625 +89482 -0.10400390625 +89483 -0.01544189453125 +89484 -0.229400634765625 +89485 -0.03662109375 +89486 -0.35552978515625 +89487 -0.0579833984375 +89488 -0.441925048828125 +89489 -0.072723388671875 +89490 -0.473846435546875 +89491 -0.078369140625 +89492 -0.464813232421875 +89493 -0.077178955078125 +89494 -0.419097900390625 +89495 -0.069854736328125 +89496 -0.334320068359375 +89497 -0.05596923828125 +89498 -0.227935791015625 +89499 -0.038421630859375 +89500 -0.12347412109375 +89501 -0.021148681640625 +89502 -0.02764892578125 +89503 -0.0052490234375 +89504 0.077667236328125 +89505 0.01226806640625 +89506 0.2132568359375 +89507 0.034912109375 +89508 0.38885498046875 +89509 0.0643310546875 +89510 0.582794189453125 +89511 0.096893310546875 +89512 0.734039306640625 +89513 0.122344970703125 +89514 0.800140380859375 +89515 0.133514404296875 +89516 0.7783203125 +89517 0.129974365234375 +89518 0.6651611328125 +89519 0.111114501953125 +89520 0.45965576171875 +89521 0.0767822265625 +89522 0.199188232421875 +89523 0.03326416015625 +89524 -0.050689697265625 +89525 -0.008453369140625 +89526 -0.23297119140625 +89527 -0.038787841796875 +89528 -0.33013916015625 +89529 -0.054840087890625 +89530 -0.368408203125 +89531 -0.061004638671875 +89532 -0.378936767578125 +89533 -0.062530517578125 +89534 -0.376983642578125 +89535 -0.062042236328125 +89536 -0.37969970703125 +89537 -0.062408447265625 +89538 -0.391510009765625 +89539 -0.064361572265625 +89540 -0.385345458984375 +89541 -0.0633544921875 +89542 -0.3419189453125 +89543 -0.056121826171875 +89544 -0.28289794921875 +89545 -0.046295166015625 +89546 -0.251617431640625 +89547 -0.041168212890625 +89548 -0.266143798828125 +89549 -0.04376220703125 +89550 -0.273345947265625 +89551 -0.045135498046875 +89552 -0.216796875 +89553 -0.03582763671875 +89554 -0.128265380859375 +89555 -0.0211181640625 +89556 -0.068145751953125 +89557 -0.011138916015625 +89558 -0.0430908203125 +89559 -0.007049560546875 +89560 -0.024444580078125 +89561 -0.003997802734375 +89562 0.020721435546875 +89563 0.003509521484375 +89564 0.124481201171875 +89565 0.020843505859375 +89566 0.25787353515625 +89567 0.04315185546875 +89568 0.379119873046875 +89569 0.06341552734375 +89570 0.47991943359375 +89571 0.08026123046875 +89572 0.5281982421875 +89573 0.08831787109375 +89574 0.511138916015625 +89575 0.08538818359375 +89576 0.456207275390625 +89577 0.07611083984375 +89578 0.407470703125 +89579 0.067901611328125 +89580 0.383758544921875 +89581 0.063934326171875 +89582 0.35687255859375 +89583 0.0594482421875 +89584 0.31182861328125 +89585 0.051910400390625 +89586 0.250885009765625 +89587 0.04168701171875 +89588 0.1654052734375 +89589 0.027374267578125 +89590 0.035247802734375 +89591 0.005584716796875 +89592 -0.142059326171875 +89593 -0.024078369140625 +89594 -0.33563232421875 +89595 -0.056427001953125 +89596 -0.5345458984375 +89597 -0.089630126953125 +89598 -0.72186279296875 +89599 -0.120849609375 +89600 -0.836669921875 +89601 -0.139404296875 +89602 -0.8326416015625 +89603 -0.13690185546875 +89604 -0.7296142578125 +89605 -0.117279052734375 +89606 -0.582550048828125 +89607 -0.09112548828125 +89608 -0.440093994140625 +89609 -0.067657470703125 +89610 -0.324310302734375 +89611 -0.050750732421875 +89612 -0.20147705078125 +89613 -0.033111572265625 +89614 -0.044647216796875 +89615 -0.00885009765625 +89616 0.103973388671875 +89617 0.0140380859375 +89618 0.202392578125 +89619 0.027557373046875 +89620 0.264495849609375 +89621 0.0347900390625 +89622 0.338897705078125 +89623 0.045745849609375 +89624 0.443817138671875 +89625 0.064208984375 +89626 0.545074462890625 +89627 0.08343505859375 +89628 0.6173095703125 +89629 0.09832763671875 +89630 0.6524658203125 +89631 0.10723876953125 +89632 0.66339111328125 +89633 0.112548828125 +89634 0.6561279296875 +89635 0.115264892578125 +89636 0.606781005859375 +89637 0.110321044921875 +89638 0.501190185546875 +89639 0.094573974609375 +89640 0.352783203125 +89641 0.070404052734375 +89642 0.176544189453125 +89643 0.04052734375 +89644 -0.034820556640625 +89645 0.003204345703125 +89646 -0.258209228515625 +89647 -0.03717041015625 +89648 -0.44244384765625 +89649 -0.070587158203125 +89650 -0.5753173828125 +89651 -0.09478759765625 +89652 -0.65203857421875 +89653 -0.108917236328125 +89654 -0.641632080078125 +89655 -0.106781005859375 +89656 -0.562164306640625 +89657 -0.092010498046875 +89658 -0.458038330078125 +89659 -0.073394775390625 +89660 -0.350555419921875 +89661 -0.055023193359375 +89662 -0.260528564453125 +89663 -0.040863037109375 +89664 -0.192108154296875 +89665 -0.031524658203125 +89666 -0.141937255859375 +89667 -0.02606201171875 +89668 -0.1021728515625 +89669 -0.02264404296875 +89670 -0.062896728515625 +89671 -0.01904296875 +89672 -0.011932373046875 +89673 -0.012603759765625 +89674 0.062835693359375 +89675 -0.000701904296875 +89676 0.148712158203125 +89677 0.014251708984375 +89678 0.241729736328125 +89679 0.031524658203125 +89680 0.34912109375 +89681 0.052642822265625 +89682 0.457305908203125 +89683 0.07489013671875 +89684 0.54388427734375 +89685 0.09368896484375 +89686 0.5728759765625 +89687 0.101776123046875 +89688 0.506591796875 +89689 0.0914306640625 +89690 0.351226806640625 +89691 0.063720703125 +89692 0.146514892578125 +89693 0.026397705078125 +89694 -0.05523681640625 +89695 -0.01025390625 +89696 -0.21624755859375 +89697 -0.03887939453125 +89698 -0.334930419921875 +89699 -0.059356689453125 +89700 -0.402984619140625 +89701 -0.070159912109375 +89702 -0.4412841796875 +89703 -0.07562255859375 +89704 -0.49578857421875 +89705 -0.085052490234375 +89706 -0.5601806640625 +89707 -0.097259521484375 +89708 -0.600738525390625 +89709 -0.105499267578125 +89710 -0.584228515625 +89711 -0.10308837890625 +89712 -0.47930908203125 +89713 -0.083709716796875 +89714 -0.27935791015625 +89715 -0.045928955078125 +89716 -0.0089111328125 +89717 0.005462646484375 +89718 0.268798828125 +89719 0.0579833984375 +89720 0.482818603515625 +89721 0.09759521484375 +89722 0.60369873046875 +89723 0.118621826171875 +89724 0.650421142578125 +89725 0.125 +89726 0.66400146484375 +89727 0.125091552734375 +89728 0.6414794921875 +89729 0.118438720703125 +89730 0.572540283203125 +89731 0.103118896484375 +89732 0.498138427734375 +89733 0.087371826171875 +89734 0.439453125 +89735 0.075469970703125 +89736 0.375518798828125 +89737 0.063201904296875 +89738 0.274505615234375 +89739 0.044158935546875 +89740 0.1087646484375 +89741 0.012725830078125 +89742 -0.099395751953125 +89743 -0.026702880859375 +89744 -0.3182373046875 +89745 -0.06793212890625 +89746 -0.5489501953125 +89747 -0.111358642578125 +89748 -0.7738037109375 +89749 -0.153533935546875 +89750 -0.86383056640625 +89751 -0.184051513671875 +89752 -0.870391845703125 +89753 -0.1964111328125 +89754 -0.86895751953125 +89755 -0.194305419921875 +89756 -0.861053466796875 +89757 -0.180450439453125 +89758 -0.765869140625 +89759 -0.151458740234375 +89760 -0.5301513671875 +89761 -0.1051025390625 +89762 -0.214691162109375 +89763 -0.042816162109375 +89764 0.137359619140625 +89765 0.02679443359375 +89766 0.474822998046875 +89767 0.093536376953125 +89768 0.76239013671875 +89769 0.150390625 +89770 0.867462158203125 +89771 0.19207763671875 +89772 0.870361328125 +89773 0.21881103515625 +89774 0.86480712890625 +89775 0.2283935546875 +89776 0.831817626953125 +89777 0.222015380859375 +89778 0.677581787109375 +89779 0.2047119140625 +89780 0.495880126953125 +89781 0.177764892578125 +89782 0.30767822265625 +89783 0.14495849609375 +89784 0.116180419921875 +89785 0.1068115234375 +89786 -0.110748291015625 +89787 0.057037353515625 +89788 -0.381805419921875 +89789 -0.005706787109375 +89790 -0.6572265625 +89791 -0.072906494140625 +89792 -0.857421875 +89793 -0.132598876953125 +89794 -0.870391845703125 +89795 -0.176300048828125 +89796 -0.870391845703125 +89797 -0.202667236328125 +89798 -0.86444091796875 +89799 -0.217193603515625 +89800 -0.85723876953125 +89801 -0.227142333984375 +89802 -0.790008544921875 +89803 -0.228973388671875 +89804 -0.62847900390625 +89805 -0.2119140625 +89806 -0.3956298828125 +89807 -0.1754150390625 +89808 -0.126708984375 +89809 -0.12615966796875 +89810 0.150115966796875 +89811 -0.069671630859375 +89812 0.424041748046875 +89813 -0.008331298828125 +89814 0.670623779296875 +89815 0.05242919921875 +89816 0.854522705078125 +89817 0.1048583984375 +89818 0.866485595703125 +89819 0.145477294921875 +89820 0.86920166015625 +89821 0.171234130859375 +89822 0.8653564453125 +89823 0.18585205078125 +89824 0.857147216796875 +89825 0.19207763671875 +89826 0.766845703125 +89827 0.18939208984375 +89828 0.628509521484375 +89829 0.178955078125 +89830 0.462127685546875 +89831 0.159515380859375 +89832 0.297210693359375 +89833 0.13629150390625 +89834 0.14862060546875 +89835 0.111846923828125 +89836 -0.00537109375 +89837 0.081695556640625 +89838 -0.15753173828125 +89839 0.04736328125 +89840 -0.31304931640625 +89841 0.0081787109375 +89842 -0.48876953125 +89843 -0.038665771484375 +89844 -0.6416015625 +89845 -0.083770751953125 +89846 -0.751373291015625 +89847 -0.12225341796875 +89848 -0.84619140625 +89849 -0.158782958984375 +89850 -0.861297607421875 +89851 -0.190460205078125 +89852 -0.863250732421875 +89853 -0.210723876953125 +89854 -0.856597900390625 +89855 -0.213348388671875 +89856 -0.7498779296875 +89857 -0.201446533203125 +89858 -0.624542236328125 +89859 -0.187469482421875 +89860 -0.47808837890625 +89861 -0.165618896484375 +89862 -0.253387451171875 +89863 -0.122100830078125 +89864 0.003692626953125 +89865 -0.067230224609375 +89866 0.2257080078125 +89867 -0.016571044921875 +89868 0.427154541015625 +89869 0.033111572265625 +89870 0.643218994140625 +89871 0.0897216796875 +89872 0.855926513671875 +89873 0.1513671875 +89874 0.870361328125 +89875 0.20489501953125 +89876 0.870361328125 +89877 0.239044189453125 +89878 0.862762451171875 +89879 0.25567626953125 +89880 0.79669189453125 +89881 0.254241943359375 +89882 0.595794677734375 +89883 0.232574462890625 +89884 0.362152099609375 +89885 0.19744873046875 +89886 0.1270751953125 +89887 0.1552734375 +89888 -0.086944580078125 +89889 0.11077880859375 +89890 -0.2784423828125 +89891 0.064178466796875 +89892 -0.484832763671875 +89893 0.007171630859375 +89894 -0.729583740234375 +89895 -0.06500244140625 +89896 -0.86688232421875 +89897 -0.140869140625 +89898 -0.870391845703125 +89899 -0.2060546875 +89900 -0.86859130859375 +89901 -0.259613037109375 +89902 -0.86279296875 +89903 -0.301300048828125 +89904 -0.817962646484375 +89905 -0.322967529296875 +89906 -0.6116943359375 +89907 -0.314208984375 +89908 -0.3128662109375 +89909 -0.2734375 +89910 0.039398193359375 +89911 -0.20849609375 +89912 0.422821044921875 +89913 -0.123931884765625 +89914 0.805145263671875 +89915 -0.027374267578125 +89916 0.870361328125 +89917 0.06549072265625 +89918 0.870361328125 +89919 0.1416015625 +89920 0.860015869140625 +89921 0.198486328125 +89922 0.727935791015625 +89923 0.23455810546875 +89924 0.48114013671875 +89925 0.24871826171875 +89926 0.2059326171875 +89927 0.24676513671875 +89928 -0.06103515625 +89929 0.234100341796875 +89930 -0.29913330078125 +89931 0.21319580078125 +89932 -0.516204833984375 +89933 0.180755615234375 +89934 -0.7252197265625 +89935 0.13330078125 +89936 -0.85980224609375 +89937 0.07666015625 +89938 -0.870391845703125 +89939 0.018768310546875 +89940 -0.870391845703125 +89941 -0.03350830078125 +89942 -0.858062744140625 +89943 -0.06890869140625 +89944 -0.673004150390625 +89945 -0.08648681640625 +89946 -0.42694091796875 +89947 -0.0985107421875 +89948 -0.2100830078125 +89949 -0.1153564453125 +89950 -0.0362548828125 +89951 -0.136627197265625 +89952 0.10943603515625 +89953 -0.155609130859375 +89954 0.23516845703125 +89955 -0.16778564453125 +89956 0.373687744140625 +89957 -0.16363525390625 +89958 0.517791748046875 +89959 -0.143707275390625 +89960 0.602783203125 +89961 -0.1226806640625 +89962 0.635711669921875 +89963 -0.09942626953125 +89964 0.655181884765625 +89965 -0.066253662109375 +89966 0.65948486328125 +89967 -0.0255126953125 +89968 0.651275634765625 +89969 0.020904541015625 +89970 0.61846923828125 +89971 0.06732177734375 +89972 0.53753662109375 +89973 0.105133056640625 +89974 0.404144287109375 +89975 0.13018798828125 +89976 0.22186279296875 +89977 0.14031982421875 +89978 0.003997802734375 +89979 0.1358642578125 +89980 -0.22100830078125 +89981 0.121063232421875 +89982 -0.42449951171875 +89983 0.10076904296875 +89984 -0.579833984375 +89985 0.08001708984375 +89986 -0.641876220703125 +89987 0.068756103515625 +89988 -0.6177978515625 +89989 0.065521240234375 +89990 -0.575531005859375 +89991 0.05535888671875 +89992 -0.526336669921875 +89993 0.037078857421875 +89994 -0.42645263671875 +89995 0.022735595703125 +89996 -0.2581787109375 +89997 0.0186767578125 +89998 -0.068695068359375 +89999 0.0164794921875 +90000 0.09222412109375 +90001 0.0072021484375 +90002 0.232147216796875 +90003 -0.00482177734375 +90004 0.3509521484375 +90005 -0.017242431640625 +90006 0.410064697265625 +90007 -0.036956787109375 +90008 0.372955322265625 +90009 -0.07080078125 +90010 0.2554931640625 +90011 -0.113922119140625 +90012 0.10711669921875 +90013 -0.154296875 +90014 -0.052886962890625 +90015 -0.1873779296875 +90016 -0.186279296875 +90017 -0.204803466796875 +90018 -0.23291015625 +90019 -0.19366455078125 +90020 -0.209442138671875 +90021 -0.159271240234375 +90022 -0.174163818359375 +90023 -0.116912841796875 +90024 -0.126739501953125 +90025 -0.068511962890625 +90026 -0.048126220703125 +90027 -0.011810302734375 +90028 0.0426025390625 +90029 0.046630859375 +90030 0.10748291015625 +90031 0.095977783203125 +90032 0.1409912109375 +90033 0.1331787109375 +90034 0.19708251953125 +90035 0.16925048828125 +90036 0.273651123046875 +90037 0.202667236328125 +90038 0.31768798828125 +90039 0.220489501953125 +90040 0.341094970703125 +90041 0.225311279296875 +90042 0.368011474609375 +90043 0.222991943359375 +90044 0.37249755859375 +90045 0.208221435546875 +90046 0.30072021484375 +90047 0.169586181640625 +90048 0.1517333984375 +90049 0.10821533203125 +90050 -0.01470947265625 +90051 0.039581298828125 +90052 -0.1883544921875 +90053 -0.03216552734375 +90054 -0.372711181640625 +90055 -0.1060791015625 +90056 -0.51397705078125 +90057 -0.16802978515625 +90058 -0.57177734375 +90059 -0.20709228515625 +90060 -0.53948974609375 +90061 -0.220428466796875 +90062 -0.43511962890625 +90063 -0.211212158203125 +90064 -0.2962646484375 +90065 -0.187530517578125 +90066 -0.161102294921875 +90067 -0.157958984375 +90068 -0.0435791015625 +90069 -0.125823974609375 +90070 0.060394287109375 +90071 -0.09063720703125 +90072 0.13665771484375 +90073 -0.056488037109375 +90074 0.170135498046875 +90075 -0.02789306640625 +90076 0.16552734375 +90077 -0.005035400390625 +90078 0.15728759765625 +90079 0.018646240234375 +90080 0.150787353515625 +90081 0.04296875 +90082 0.12200927734375 +90083 0.060943603515625 +90084 0.080108642578125 +90085 0.073394775390625 +90086 0.05126953125 +90087 0.08526611328125 +90088 0.062896728515625 +90089 0.10198974609375 +90090 0.09271240234375 +90091 0.11773681640625 +90092 0.092987060546875 +90093 0.121124267578125 +90094 0.07855224609375 +90095 0.1156005859375 +90096 0.06427001953125 +90097 0.104888916015625 +90098 0.0347900390625 +90099 0.0859375 +90100 -0.01171875 +90101 0.05914306640625 +90102 -0.056060791015625 +90103 0.029937744140625 +90104 -0.055511474609375 +90105 0.00933837890625 +90106 -0.010467529296875 +90107 -0.00152587890625 +90108 0.02508544921875 +90109 -0.01397705078125 +90110 0.025665283203125 +90111 -0.0328369140625 +90112 0.017333984375 +90113 -0.050872802734375 +90114 0.00189208984375 +90115 -0.066986083984375 +90116 -0.03173828125 +90117 -0.083404541015625 +90118 -0.071502685546875 +90119 -0.096923828125 +90120 -0.13543701171875 +90121 -0.112030029296875 +90122 -0.219970703125 +90123 -0.128082275390625 +90124 -0.300506591796875 +90125 -0.139312744140625 +90126 -0.376312255859375 +90127 -0.146148681640625 +90128 -0.416107177734375 +90129 -0.141571044921875 +90130 -0.371124267578125 +90131 -0.114227294921875 +90132 -0.242279052734375 +90133 -0.06524658203125 +90134 -0.069732666015625 +90135 -0.005615234375 +90136 0.125640869140625 +90137 0.05853271484375 +90138 0.31268310546875 +90139 0.118621826171875 +90140 0.45501708984375 +90141 0.1649169921875 +90142 0.554779052734375 +90143 0.197418212890625 +90144 0.61065673828125 +90145 0.21551513671875 +90146 0.610931396484375 +90147 0.216156005859375 +90148 0.531463623046875 +90149 0.193389892578125 +90150 0.3883056640625 +90151 0.1514892578125 +90152 0.23468017578125 +90153 0.10418701171875 +90154 0.095245361328125 +90155 0.0582275390625 +90156 -0.00396728515625 +90157 0.02081298828125 +90158 -0.04852294921875 +90159 -0.003753662109375 +90160 -0.055145263671875 +90161 -0.018890380859375 +90162 -0.0758056640625 +90163 -0.036865234375 +90164 -0.138702392578125 +90165 -0.06402587890625 +90166 -0.209197998046875 +90167 -0.09112548828125 +90168 -0.289031982421875 +90169 -0.118133544921875 +90170 -0.37884521484375 +90171 -0.1448974609375 +90172 -0.456329345703125 +90173 -0.165679931640625 +90174 -0.51641845703125 +90175 -0.179229736328125 +90176 -0.519287109375 +90177 -0.17578125 +90178 -0.458251953125 +90179 -0.153961181640625 +90180 -0.384796142578125 +90181 -0.127044677734375 +90182 -0.323699951171875 +90183 -0.10174560546875 +90184 -0.269287109375 +90185 -0.07720947265625 +90186 -0.1951904296875 +90187 -0.047515869140625 +90188 -0.100006103515625 +90189 -0.012908935546875 +90190 -0.01055908203125 +90191 0.019287109375 +90192 0.1033935546875 +90193 0.056121826171875 +90194 0.24908447265625 +90195 0.0989990234375 +90196 0.373199462890625 +90197 0.13427734375 +90198 0.45806884765625 +90199 0.15740966796875 +90200 0.511474609375 +90201 0.170257568359375 +90202 0.565399169921875 +90203 0.180938720703125 +90204 0.61138916015625 +90205 0.18756103515625 +90206 0.5897216796875 +90207 0.175537109375 +90208 0.4906005859375 +90209 0.142791748046875 +90210 0.33148193359375 +90211 0.09417724609375 +90212 0.147796630859375 +90213 0.0390625 +90214 -0.01873779296875 +90215 -0.0115966796875 +90216 -0.140289306640625 +90217 -0.05035400390625 +90218 -0.191986083984375 +90219 -0.070526123046875 +90220 -0.184295654296875 +90221 -0.07440185546875 +90222 -0.161834716796875 +90223 -0.0728759765625 +90224 -0.166595458984375 +90225 -0.07623291015625 +90226 -0.19390869140625 +90227 -0.083251953125 +90228 -0.22442626953125 +90229 -0.089141845703125 +90230 -0.279754638671875 +90231 -0.099456787109375 +90232 -0.3389892578125 +90233 -0.109222412109375 +90234 -0.3543701171875 +90235 -0.1068115234375 +90236 -0.348175048828125 +90237 -0.098175048828125 +90238 -0.32598876953125 +90239 -0.085113525390625 +90240 -0.2581787109375 +90241 -0.060638427734375 +90242 -0.139801025390625 +90243 -0.02392578125 +90244 0.014617919921875 +90245 0.02099609375 +90246 0.144378662109375 +90247 0.058624267578125 +90248 0.221038818359375 +90249 0.08160400390625 +90250 0.27069091796875 +90251 0.096282958984375 +90252 0.294036865234375 +90253 0.102783203125 +90254 0.311767578125 +90255 0.106292724609375 +90256 0.339141845703125 +90257 0.1107177734375 +90258 0.360260009765625 +90259 0.112457275390625 +90260 0.360504150390625 +90261 0.1080322265625 +90262 0.308380126953125 +90263 0.089324951171875 +90264 0.18170166015625 +90265 0.050750732421875 +90266 0.0047607421875 +90267 -0.0009765625 +90268 -0.17559814453125 +90269 -0.05328369140625 +90270 -0.3143310546875 +90271 -0.09405517578125 +90272 -0.36785888671875 +90273 -0.111602783203125 +90274 -0.36248779296875 +90275 -0.112701416015625 +90276 -0.343536376953125 +90277 -0.109222412109375 +90278 -0.3018798828125 +90279 -0.09869384765625 +90280 -0.231414794921875 +90281 -0.079498291015625 +90282 -0.117645263671875 +90283 -0.047882080078125 +90284 0.007049560546875 +90285 -0.01251220703125 +90286 0.087982177734375 +90287 0.011993408203125 +90288 0.13946533203125 +90289 0.02923583984375 +90290 0.17425537109375 +90291 0.0423583984375 +90292 0.188201904296875 +90293 0.050079345703125 +90294 0.171234130859375 +90295 0.04949951171875 +90296 0.118438720703125 +90297 0.03912353515625 +90298 0.05706787109375 +90299 0.025970458984375 +90300 -0.010711669921875 +90301 0.01043701171875 +90302 -0.0914306640625 +90303 -0.00927734375 +90304 -0.162322998046875 +90305 -0.0272216796875 +90306 -0.194549560546875 +90307 -0.035797119140625 +90308 -0.1492919921875 +90309 -0.02471923828125 +90310 -0.02166748046875 +90311 0.00732421875 +90312 0.124053955078125 +90313 0.043487548828125 +90314 0.211151123046875 +90315 0.063629150390625 +90316 0.240447998046875 +90317 0.068145751953125 +90318 0.242218017578125 +90319 0.065185546875 +90320 0.2257080078125 +90321 0.05743408203125 +90322 0.194366455078125 +90323 0.045989990234375 +90324 0.115509033203125 +90325 0.022369384765625 +90326 0.0128173828125 +90327 -0.0069580078125 +90328 -0.053802490234375 +90329 -0.026092529296875 +90330 -0.110626220703125 +90331 -0.04193115234375 +90332 -0.199493408203125 +90333 -0.065460205078125 +90334 -0.29437255859375 +90335 -0.08984375 +90336 -0.33221435546875 +90337 -0.0985107421875 +90338 -0.27972412109375 +90339 -0.082794189453125 +90340 -0.185333251953125 +90341 -0.055572509765625 +90342 -0.128204345703125 +90343 -0.037872314453125 +90344 -0.115692138671875 +90345 -0.031768798828125 +90346 -0.116455078125 +90347 -0.029144287109375 +90348 -0.105926513671875 +90349 -0.023712158203125 +90350 -0.053955078125 +90351 -0.00762939453125 +90352 0.048797607421875 +90353 0.02142333984375 +90354 0.157318115234375 +90355 0.051483154296875 +90356 0.212005615234375 +90357 0.066741943359375 +90358 0.218475341796875 +90359 0.068634033203125 +90360 0.23724365234375 +90361 0.07318115234375 +90362 0.30535888671875 +90363 0.090179443359375 +90364 0.38128662109375 +90365 0.108734130859375 +90366 0.404449462890625 +90367 0.112945556640625 +90368 0.3944091796875 +90369 0.10870361328125 +90370 0.3885498046875 +90371 0.10662841796875 +90372 0.362640380859375 +90373 0.0994873046875 +90374 0.27362060546875 +90375 0.0743408203125 +90376 0.11712646484375 +90377 0.029693603515625 +90378 -0.054901123046875 +90379 -0.01922607421875 +90380 -0.19085693359375 +90381 -0.05731201171875 +90382 -0.28570556640625 +90383 -0.083251953125 +90384 -0.339263916015625 +90385 -0.097137451171875 +90386 -0.3775634765625 +90387 -0.106781005859375 +90388 -0.445709228515625 +90389 -0.1256103515625 +90390 -0.535064697265625 +90391 -0.151153564453125 +90392 -0.629058837890625 +90393 -0.17852783203125 +90394 -0.697601318359375 +90395 -0.19879150390625 +90396 -0.70391845703125 +90397 -0.2010498046875 +90398 -0.6424560546875 +90399 -0.183624267578125 +90400 -0.491241455078125 +90401 -0.13995361328125 +90402 -0.265716552734375 +90403 -0.074554443359375 +90404 -0.023712158203125 +90405 -0.00445556640625 +90406 0.201751708984375 +90407 0.060638427734375 +90408 0.375823974609375 +90409 0.110504150390625 +90410 0.485076904296875 +90411 0.141265869140625 +90412 0.56884765625 +90413 0.1646728515625 +90414 0.634765625 +90415 0.18304443359375 +90416 0.63763427734375 +90417 0.18304443359375 +90418 0.5660400390625 +90419 0.161346435546875 +90420 0.4720458984375 +90421 0.133392333984375 +90422 0.40692138671875 +90423 0.11431884765625 +90424 0.3778076171875 +90425 0.106231689453125 +90426 0.376953125 +90427 0.1068115234375 +90428 0.371978759765625 +90429 0.106414794921875 +90430 0.313140869140625 +90431 0.090240478515625 +90432 0.184417724609375 +90433 0.053436279296875 +90434 0.011199951171875 +90435 0.00347900390625 +90436 -0.171051025390625 +90437 -0.04913330078125 +90438 -0.33740234375 +90439 -0.09710693359375 +90440 -0.47198486328125 +90441 -0.135833740234375 +90442 -0.560394287109375 +90443 -0.1611328125 +90444 -0.58056640625 +90445 -0.16650390625 +90446 -0.54754638671875 +90447 -0.156402587890625 +90448 -0.508575439453125 +90449 -0.144866943359375 +90450 -0.459503173828125 +90451 -0.130645751953125 +90452 -0.394378662109375 +90453 -0.1119384765625 +90454 -0.35260009765625 +90455 -0.100341796875 +90456 -0.31170654296875 +90457 -0.08917236328125 +90458 -0.197418212890625 +90459 -0.056365966796875 +90460 -0.007965087890625 +90461 -0.001373291015625 +90462 0.207489013671875 +90463 0.061279296875 +90464 0.409210205078125 +90465 0.119873046875 +90466 0.57208251953125 +90467 0.16705322265625 +90468 0.66595458984375 +90469 0.193939208984375 +90470 0.65875244140625 +90471 0.191131591796875 +90472 0.56744384765625 +90473 0.163665771484375 +90474 0.431396484375 +90475 0.123199462890625 +90476 0.29443359375 +90477 0.082733154296875 +90478 0.182464599609375 +90479 0.0499267578125 +90480 0.06365966796875 +90481 0.01531982421875 +90482 -0.075958251953125 +90483 -0.025238037109375 +90484 -0.189422607421875 +90485 -0.05792236328125 +90486 -0.271942138671875 +90487 -0.081329345703125 +90488 -0.342529296875 +90489 -0.101165771484375 +90490 -0.364166259765625 +90491 -0.1065673828125 +90492 -0.327239990234375 +90493 -0.0947265625 +90494 -0.2769775390625 +90495 -0.079071044921875 +90496 -0.253692626953125 +90497 -0.071563720703125 +90498 -0.24365234375 +90499 -0.068145751953125 +90500 -0.1983642578125 +90501 -0.05450439453125 +90502 -0.116241455078125 +90503 -0.030181884765625 +90504 -0.036834716796875 +90505 -0.006866455078125 +90506 0.034881591796875 +90507 0.013946533203125 +90508 0.09124755859375 +90509 0.030029296875 +90510 0.10888671875 +90511 0.034515380859375 +90512 0.125518798828125 +90513 0.038604736328125 +90514 0.15771484375 +90515 0.047271728515625 +90516 0.17828369140625 +90517 0.052490234375 +90518 0.17108154296875 +90519 0.04949951171875 +90520 0.129974365234375 +90521 0.03656005859375 +90522 0.082427978515625 +90523 0.021820068359375 +90524 0.027679443359375 +90525 0.005126953125 +90526 -0.065643310546875 +90527 -0.02276611328125 +90528 -0.15936279296875 +90529 -0.050537109375 +90530 -0.21307373046875 +90531 -0.0662841796875 +90532 -0.234649658203125 +90533 -0.07232666015625 +90534 -0.2001953125 +90535 -0.061614990234375 +90536 -0.119171142578125 +90537 -0.0369873046875 +90538 -0.024749755859375 +90539 -0.00830078125 +90540 0.085784912109375 +90541 0.025177001953125 +90542 0.178131103515625 +90543 0.05322265625 +90544 0.215576171875 +90545 0.06494140625 +90546 0.211456298828125 +90547 0.06427001953125 +90548 0.17523193359375 +90549 0.05401611328125 +90550 0.128753662109375 +90551 0.040618896484375 +90552 0.1019287109375 +90553 0.03289794921875 +90554 0.0743408203125 +90555 0.024810791015625 +90556 0.04327392578125 +90557 0.015533447265625 +90558 0.038177490234375 +90559 0.0137939453125 +90560 0.076263427734375 +90561 0.024688720703125 +90562 0.14105224609375 +90563 0.043365478515625 +90564 0.186431884765625 +90565 0.05621337890625 +90566 0.188812255859375 +90567 0.0562744140625 +90568 0.1390380859375 +90569 0.0408935546875 +90570 0.041778564453125 +90571 0.011505126953125 +90572 -0.079437255859375 +90573 -0.02490234375 +90574 -0.219390869140625 +90575 -0.066741943359375 +90576 -0.367828369140625 +90577 -0.1109619140625 +90578 -0.494873046875 +90579 -0.148681640625 +90580 -0.556243896484375 +90581 -0.16680908203125 +90582 -0.508697509765625 +90583 -0.152557373046875 +90584 -0.3756103515625 +90585 -0.11285400390625 +90586 -0.218902587890625 +90587 -0.066070556640625 +90588 -0.063751220703125 +90589 -0.019683837890625 +90590 0.091552734375 +90591 0.026763916015625 +90592 0.23602294921875 +90593 0.07000732421875 +90594 0.342987060546875 +90595 0.10211181640625 +90596 0.39520263671875 +90597 0.11798095703125 +90598 0.389373779296875 +90599 0.116607666015625 +90600 0.324249267578125 +90601 0.097625732421875 +90602 0.224090576171875 +90603 0.068206787109375 +90604 0.124267578125 +90605 0.038787841796875 +90606 0.037078857421875 +90607 0.01300048828125 +90608 -0.010101318359375 +90609 -0.00103759765625 +90610 -0.019439697265625 +90611 -0.00396728515625 +90612 -0.022796630859375 +90613 -0.00518798828125 +90614 -0.001556396484375 +90615 0.000762939453125 +90616 0.056304931640625 +90617 0.017486572265625 +90618 0.106719970703125 +90619 0.031951904296875 +90620 0.096893310546875 +90621 0.028564453125 +90622 0.042694091796875 +90623 0.012054443359375 +90624 -0.018035888671875 +90625 -0.006622314453125 +90626 -0.07586669921875 +90627 -0.02447509765625 +90628 -0.11944580078125 +90629 -0.037506103515625 +90630 -0.15972900390625 +90631 -0.049468994140625 +90632 -0.202606201171875 +90633 -0.062469482421875 +90634 -0.24859619140625 +90635 -0.076690673828125 +90636 -0.30517578125 +90637 -0.094696044921875 +90638 -0.36212158203125 +90639 -0.1131591796875 +90640 -0.39141845703125 +90641 -0.122894287109375 +90642 -0.35528564453125 +90643 -0.11151123046875 +90644 -0.249969482421875 +90645 -0.077728271484375 +90646 -0.092864990234375 +90647 -0.0272216796875 +90648 0.08905029296875 +90649 0.03125 +90650 0.2352294921875 +90651 0.077911376953125 +90652 0.318817138671875 +90653 0.104034423828125 +90654 0.358642578125 +90655 0.1158447265625 +90656 0.347747802734375 +90657 0.11114501953125 +90658 0.28564453125 +90659 0.08984375 +90660 0.223175048828125 +90661 0.06866455078125 +90662 0.196746826171875 +90663 0.0595703125 +90664 0.179840087890625 +90665 0.053863525390625 +90666 0.155548095703125 +90667 0.0460205078125 +90668 0.151214599609375 +90669 0.045013427734375 +90670 0.156951904296875 +90671 0.04754638671875 +90672 0.13177490234375 +90673 0.040130615234375 +90674 0.100799560546875 +90675 0.03094482421875 +90676 0.087127685546875 +90677 0.02752685546875 +90678 0.05487060546875 +90679 0.01806640625 +90680 -0.009002685546875 +90681 -0.00177001953125 +90682 -0.10400390625 +90683 -0.031890869140625 +90684 -0.229400634765625 +90685 -0.072113037109375 +90686 -0.35552978515625 +90687 -0.112762451171875 +90688 -0.441925048828125 +90689 -0.14056396484375 +90690 -0.473846435546875 +90691 -0.150726318359375 +90692 -0.464813232421875 +90693 -0.147674560546875 +90694 -0.419097900390625 +90695 -0.132843017578125 +90696 -0.334320068359375 +90697 -0.105438232421875 +90698 -0.227935791015625 +90699 -0.071136474609375 +90700 -0.12347412109375 +90701 -0.037628173828125 +90702 -0.02764892578125 +90703 -0.007049560546875 +90704 0.077667236328125 +90705 0.026580810546875 +90706 0.2132568359375 +90707 0.070098876953125 +90708 0.38885498046875 +90709 0.12677001953125 +90710 0.582794189453125 +90711 0.18951416015625 +90712 0.734039306640625 +90713 0.238372802734375 +90714 0.800140380859375 +90715 0.259429931640625 +90716 0.7783203125 +90717 0.2518310546875 +90718 0.6651611328125 +90719 0.2144775390625 +90720 0.45965576171875 +90721 0.14703369140625 +90722 0.199188232421875 +90723 0.061767578125 +90724 -0.050689697265625 +90725 -0.019805908203125 +90726 -0.23297119140625 +90727 -0.079010009765625 +90728 -0.33013916015625 +90729 -0.11016845703125 +90730 -0.368408203125 +90731 -0.121917724609375 +90732 -0.378936767578125 +90733 -0.124481201171875 +90734 -0.376983642578125 +90735 -0.12298583984375 +90736 -0.37969970703125 +90737 -0.123077392578125 +90738 -0.391510009765625 +90739 -0.126251220703125 +90740 -0.385345458984375 +90741 -0.123626708984375 +90742 -0.3419189453125 +90743 -0.10894775390625 +90744 -0.28289794921875 +90745 -0.089324951171875 +90746 -0.251617431640625 +90747 -0.078948974609375 +90748 -0.266143798828125 +90749 -0.083770751953125 +90750 -0.273345947265625 +90751 -0.086395263671875 +90752 -0.216796875 +90753 -0.0682373046875 +90754 -0.128265380859375 +90755 -0.039703369140625 +90756 -0.068145751953125 +90757 -0.02056884765625 +90758 -0.0430908203125 +90759 -0.01300048828125 +90760 -0.024444580078125 +90761 -0.007537841796875 +90762 0.020721435546875 +90763 0.006622314453125 +90764 0.124481201171875 +90765 0.040008544921875 +90766 0.25787353515625 +90767 0.083160400390625 +90768 0.379119873046875 +90769 0.122406005859375 +90770 0.47991943359375 +90771 0.155059814453125 +90772 0.5281982421875 +90773 0.170654296875 +90774 0.511138916015625 +90775 0.164947509765625 +90776 0.456207275390625 +90777 0.14697265625 +90778 0.407470703125 +90779 0.13116455078125 +90780 0.383758544921875 +90781 0.123687744140625 +90782 0.35687255859375 +90783 0.115264892578125 +90784 0.31182861328125 +90785 0.1009521484375 +90786 0.250885009765625 +90787 0.081451416015625 +90788 0.1654052734375 +90789 0.053924560546875 +90790 0.035247802734375 +90791 0.011749267578125 +90792 -0.142059326171875 +90793 -0.045867919921875 +90794 -0.33563232421875 +90795 -0.108856201171875 +90796 -0.5345458984375 +90797 -0.17364501953125 +90798 -0.72186279296875 +90799 -0.234710693359375 +90800 -0.836669921875 +90801 -0.272064208984375 +90802 -0.8326416015625 +90803 -0.27056884765625 +90804 -0.7296142578125 +90805 -0.236724853515625 +90806 -0.582550048828125 +90807 -0.188568115234375 +90808 -0.440093994140625 +90809 -0.142059326171875 +90810 -0.324310302734375 +90811 -0.10443115234375 +90812 -0.20147705078125 +90813 -0.0645751953125 +90814 -0.044647216796875 +90815 -0.013580322265625 +90816 0.103973388671875 +90817 0.034698486328125 +90818 0.202392578125 +90819 0.066497802734375 +90820 0.264495849609375 +90821 0.08636474609375 +90822 0.338897705078125 +90823 0.11029052734375 +90824 0.443817138671875 +90825 0.144287109375 +90826 0.545074462890625 +90827 0.177154541015625 +90828 0.6173095703125 +90829 0.20062255859375 +90830 0.6524658203125 +90831 0.2120361328125 +90832 0.66339111328125 +90833 0.215606689453125 +90834 0.6561279296875 +90835 0.21331787109375 +90836 0.606781005859375 +90837 0.197296142578125 +90838 0.501190185546875 +90839 0.16290283203125 +90840 0.352783203125 +90841 0.114532470703125 +90842 0.176544189453125 +90843 0.05706787109375 +90844 -0.034820556640625 +90845 -0.0118408203125 +90846 -0.258209228515625 +90847 -0.08465576171875 +90848 -0.44244384765625 +90849 -0.14459228515625 +90850 -0.5753173828125 +90851 -0.18768310546875 +90852 -0.65203857421875 +90853 -0.21240234375 +90854 -0.641632080078125 +90855 -0.2086181640625 +90856 -0.562164306640625 +90857 -0.18231201171875 +90858 -0.458038330078125 +90859 -0.148040771484375 +90860 -0.350555419921875 +90861 -0.112762451171875 +90862 -0.260528564453125 +90863 -0.083343505859375 +90864 -0.192108154296875 +90865 -0.061126708984375 +90866 -0.141937255859375 +90867 -0.04498291015625 +90868 -0.1021728515625 +90869 -0.032318115234375 +90870 -0.062896728515625 +90871 -0.019866943359375 +90872 -0.011932373046875 +90873 -0.003570556640625 +90874 0.062835693359375 +90875 0.020538330078125 +90876 0.148712158203125 +90877 0.048309326171875 +90878 0.241729736328125 +90879 0.078460693359375 +90880 0.34912109375 +90881 0.113677978515625 +90882 0.457305908203125 +90883 0.150299072265625 +90884 0.54388427734375 +90885 0.180877685546875 +90886 0.5728759765625 +90887 0.192138671875 +90888 0.506591796875 +90889 0.170196533203125 +90890 0.351226806640625 +90891 0.116943359375 +90892 0.146514892578125 +90893 0.04638671875 +90894 -0.05523681640625 +90895 -0.02288818359375 +90896 -0.21624755859375 +90897 -0.0775146484375 +90898 -0.334930419921875 +90899 -0.11712646484375 +90900 -0.402984619140625 +90901 -0.138885498046875 +90902 -0.4412841796875 +90903 -0.15045166015625 +90904 -0.49578857421875 +90905 -0.16845703125 +90906 -0.5601806640625 +90907 -0.190704345703125 +90908 -0.600738525390625 +90909 -0.205047607421875 +90910 -0.584228515625 +90911 -0.199493408203125 +90912 -0.47930908203125 +90913 -0.162689208984375 +90914 -0.27935791015625 +90915 -0.092193603515625 +90916 -0.0089111328125 +90917 0.00323486328125 +90918 0.268798828125 +90919 0.1009521484375 +90920 0.482818603515625 +90921 0.175567626953125 +90922 0.60369873046875 +90923 0.216644287109375 +90924 0.650421142578125 +90925 0.231109619140625 +90926 0.66400146484375 +90927 0.23388671875 +90928 0.6414794921875 +90929 0.2239990234375 +90930 0.572540283203125 +90931 0.19781494140625 +90932 0.498138427734375 +90933 0.170166015625 +90934 0.439453125 +90935 0.148712158203125 +90936 0.375518798828125 +90937 0.12591552734375 +90938 0.274505615234375 +90939 0.09027099609375 +90940 0.1087646484375 +90941 0.031768798828125 +90942 -0.099395751953125 +90943 -0.0416259765625 +90944 -0.3182373046875 +90945 -0.118560791015625 +90946 -0.5489501953125 +90947 -0.199615478515625 +90948 -0.7738037109375 +90949 -0.278472900390625 +90950 -0.86383056640625 +90951 -0.336212158203125 +90952 -0.870391845703125 +90953 -0.3609619140625 +90954 -0.86895751953125 +90955 -0.35919189453125 +90956 -0.861053466796875 +90957 -0.335723876953125 +90958 -0.765869140625 +90959 -0.284393310546875 +90960 -0.5301513671875 +90961 -0.201171875 +90962 -0.214691162109375 +90963 -0.088592529296875 +90964 0.137359619140625 +90965 0.037811279296875 +90966 0.474822998046875 +90967 0.15960693359375 +90968 0.76239013671875 +90969 0.2640380859375 +90970 0.867462158203125 +90971 0.341461181640625 +90972 0.870361328125 +90973 0.39215087890625 +90974 0.86480712890625 +90975 0.4119873046875 +90976 0.831817626953125 +90977 0.40301513671875 +90978 0.677581787109375 +90979 0.374114990234375 +90980 0.495880126953125 +90981 0.32745361328125 +90982 0.30767822265625 +90983 0.269805908203125 +90984 0.116180419921875 +90985 0.2020263671875 +90986 -0.110748291015625 +90987 0.11273193359375 +90988 -0.381805419921875 +90989 -0.000518798828125 +90990 -0.6572265625 +90991 -0.122314453125 +90992 -0.857421875 +90993 -0.231109619140625 +90994 -0.870391845703125 +90995 -0.3115234375 +90996 -0.870391845703125 +90997 -0.361053466796875 +90998 -0.86444091796875 +90999 -0.389434814453125 +91000 -0.85723876953125 +91001 -0.40960693359375 +91002 -0.790008544921875 +91003 -0.4150390625 +91004 -0.62847900390625 +91005 -0.38629150390625 +91006 -0.3956298828125 +91007 -0.322265625 +91008 -0.126708984375 +91009 -0.23486328125 +91010 0.150115966796875 +91011 -0.134002685546875 +91012 0.424041748046875 +91013 -0.023956298828125 +91014 0.670623779296875 +91015 0.085540771484375 +91016 0.854522705078125 +91017 0.180511474609375 +91018 0.866485595703125 +91019 0.254638671875 +91020 0.86920166015625 +91021 0.302398681640625 +91022 0.8653564453125 +91023 0.33038330078125 +91024 0.857147216796875 +91025 0.34344482421875 +91026 0.766845703125 +91027 0.340576171875 +91028 0.628509521484375 +91029 0.323699951171875 +91030 0.462127685546875 +91031 0.29046630859375 +91032 0.297210693359375 +91033 0.250213623046875 +91034 0.14862060546875 +91035 0.20745849609375 +91036 -0.00537109375 +91037 0.154022216796875 +91038 -0.15753173828125 +91039 0.092681884765625 +91040 -0.31304931640625 +91041 0.022186279296875 +91042 -0.48876953125 +91043 -0.0625 +91044 -0.6416015625 +91045 -0.144500732421875 +91046 -0.751373291015625 +91047 -0.21490478515625 +91048 -0.84619140625 +91049 -0.28204345703125 +91050 -0.861297607421875 +91051 -0.340667724609375 +91052 -0.863250732421875 +91053 -0.378875732421875 +91054 -0.856597900390625 +91055 -0.385345458984375 +91056 -0.7498779296875 +91057 -0.364501953125 +91058 -0.624542236328125 +91059 -0.33721923828125 +91060 -0.47808837890625 +91061 -0.295684814453125 +91062 -0.253387451171875 +91063 -0.218902587890625 +91064 0.003692626953125 +91065 -0.12335205078125 +91066 0.2257080078125 +91067 -0.03369140625 +91068 0.427154541015625 +91069 0.054534912109375 +91070 0.643218994140625 +91071 0.152984619140625 +91072 0.855926513671875 +91073 0.2581787109375 +91074 0.870361328125 +91075 0.3492431640625 +91076 0.870361328125 +91077 0.4083251953125 +91078 0.862762451171875 +91079 0.43804931640625 +91080 0.79669189453125 +91081 0.437408447265625 +91082 0.595794677734375 +91083 0.403076171875 +91084 0.362152099609375 +91085 0.3455810546875 +91086 0.1270751953125 +91087 0.27508544921875 +91088 -0.086944580078125 +91089 0.19927978515625 +91090 -0.2784423828125 +91091 0.118927001953125 +91092 -0.484832763671875 +91093 0.021575927734375 +91094 -0.729583740234375 +91095 -0.099609375 +91096 -0.86688232421875 +91097 -0.226348876953125 +91098 -0.870391845703125 +91099 -0.3358154296875 +91100 -0.86859130859375 +91101 -0.426177978515625 +91102 -0.86279296875 +91103 -0.496673583984375 +91104 -0.817962646484375 +91105 -0.534393310546875 +91106 -0.6116943359375 +91107 -0.52301025390625 +91108 -0.3128662109375 +91109 -0.459991455078125 +91110 0.039398193359375 +91111 -0.35748291015625 +91112 0.422821044921875 +91113 -0.2227783203125 +91114 0.805145263671875 +91115 -0.067901611328125 +91116 0.870361328125 +91117 0.082489013671875 +91118 0.870361328125 +91119 0.207794189453125 +91120 0.860015869140625 +91121 0.303680419921875 +91122 0.727935791015625 +91123 0.367279052734375 +91124 0.48114013671875 +91125 0.396453857421875 +91126 0.2059326171875 +91127 0.39984130859375 +91128 -0.06103515625 +91129 0.385498046875 +91130 -0.29913330078125 +91131 0.35699462890625 +91132 -0.516204833984375 +91133 0.30908203125 +91134 -0.7252197265625 +91135 0.236236572265625 +91136 -0.85980224609375 +91137 0.147674560546875 +91138 -0.870391845703125 +91139 0.055419921875 +91140 -0.870391845703125 +91141 -0.029754638671875 +91142 -0.858062744140625 +91143 -0.088653564453125 +91144 -0.673004150390625 +91145 -0.11944580078125 +91146 -0.42694091796875 +91147 -0.142547607421875 +91148 -0.2100830078125 +91149 -0.175140380859375 +91150 -0.0362548828125 +91151 -0.2161865234375 +91152 0.10943603515625 +91153 -0.254058837890625 +91154 0.23516845703125 +91155 -0.28070068359375 +91156 0.373687744140625 +91157 -0.2796630859375 +91158 0.517791748046875 +91159 -0.251556396484375 +91160 0.602783203125 +91161 -0.22088623046875 +91162 0.635711669921875 +91163 -0.18548583984375 +91164 0.655181884765625 +91165 -0.1322021484375 +91166 0.65948486328125 +91167 -0.06488037109375 +91168 0.651275634765625 +91169 0.0133056640625 +91170 0.61846923828125 +91171 0.092742919921875 +91172 0.53753662109375 +91173 0.1588134765625 +91174 0.404144287109375 +91175 0.204345703125 +91176 0.22186279296875 +91177 0.22540283203125 +91178 0.003997802734375 +91179 0.222320556640625 +91180 -0.22100830078125 +91181 0.202056884765625 +91182 -0.42449951171875 +91183 0.172515869140625 +91184 -0.579833984375 +91185 0.141937255859375 +91186 -0.641876220703125 +91187 0.12689208984375 +91188 -0.6177978515625 +91189 0.12469482421875 +91190 -0.575531005859375 +91191 0.109954833984375 +91192 -0.526336669921875 +91193 0.08050537109375 +91194 -0.42645263671875 +91195 0.056640625 +91196 -0.2581787109375 +91197 0.0491943359375 +91198 -0.068695068359375 +91199 0.043975830078125 +91200 0.09222412109375 +91201 0.025970458984375 +91202 0.232147216796875 +91203 0.00262451171875 +91204 0.3509521484375 +91205 -0.021881103515625 +91206 0.410064697265625 +91207 -0.05902099609375 +91208 0.372955322265625 +91209 -0.1201171875 +91210 0.2554931640625 +91211 -0.196807861328125 +91212 0.10711669921875 +91213 -0.268524169921875 +91214 -0.052886962890625 +91215 -0.32745361328125 +91216 -0.186279296875 +91217 -0.35931396484375 +91218 -0.23291015625 +91219 -0.34210205078125 +91220 -0.209442138671875 +91221 -0.284759521484375 +91222 -0.174163818359375 +91223 -0.213104248046875 +91224 -0.126739501953125 +91225 -0.13043212890625 +91226 -0.048126220703125 +91227 -0.032958984375 +91228 0.0426025390625 +91229 0.068115234375 +91230 0.10748291015625 +91231 0.15435791015625 +91232 0.1409912109375 +91233 0.220428466796875 +91234 0.19708251953125 +91235 0.284820556640625 +91236 0.273651123046875 +91237 0.344696044921875 +91238 0.31768798828125 +91239 0.3780517578125 +91240 0.341094970703125 +91241 0.3890380859375 +91242 0.368011474609375 +91243 0.387420654296875 +91244 0.37249755859375 +91245 0.364105224609375 +91246 0.30072021484375 +91247 0.299713134765625 +91248 0.1517333984375 +91249 0.1961669921875 +91250 -0.01470947265625 +91251 0.079620361328125 +91252 -0.1883544921875 +91253 -0.04290771484375 +91254 -0.372711181640625 +91255 -0.16973876953125 +91256 -0.51397705078125 +91257 -0.276824951171875 +91258 -0.57177734375 +91259 -0.3455810546875 +91260 -0.53948974609375 +91261 -0.37103271484375 +91262 -0.43511962890625 +91263 -0.358428955078125 +91264 -0.2962646484375 +91265 -0.32122802734375 +91266 -0.161102294921875 +91267 -0.2738037109375 +91268 -0.0435791015625 +91269 -0.22161865234375 +91270 0.060394287109375 +91271 -0.16375732421875 +91272 0.13665771484375 +91273 -0.10699462890625 +91274 0.170135498046875 +91275 -0.058990478515625 +91276 0.16552734375 +91277 -0.020050048828125 +91278 0.15728759765625 +91279 0.02093505859375 +91280 0.150787353515625 +91281 0.063568115234375 +91282 0.12200927734375 +91283 0.095916748046875 +91284 0.080108642578125 +91285 0.119232177734375 +91286 0.05126953125 +91287 0.1417236328125 +91288 0.062896728515625 +91289 0.1724853515625 +91290 0.09271240234375 +91291 0.201568603515625 +91292 0.092987060546875 +91293 0.209564208984375 +91294 0.07855224609375 +91295 0.2021484375 +91296 0.06427001953125 +91297 0.18548583984375 +91298 0.0347900390625 +91299 0.154449462890625 +91300 -0.01171875 +91301 0.109588623046875 +91302 -0.056060791015625 +91303 0.060089111328125 +91304 -0.055511474609375 +91305 0.024627685546875 +91306 -0.010467529296875 +91307 0.005096435546875 +91308 0.02508544921875 +91309 -0.017547607421875 +91310 0.025665283203125 +91311 -0.051300048828125 +91312 0.017333984375 +91313 -0.084197998046875 +91314 0.00189208984375 +91315 -0.114044189453125 +91316 -0.03173828125 +91317 -0.14404296875 +91318 -0.071502685546875 +91319 -0.16876220703125 +91320 -0.13543701171875 +91321 -0.195037841796875 +91322 -0.219970703125 +91323 -0.221588134765625 +91324 -0.300506591796875 +91325 -0.239349365234375 +91326 -0.376312255859375 +91327 -0.2490234375 +91328 -0.416107177734375 +91329 -0.239593505859375 +91330 -0.371124267578125 +91331 -0.193450927734375 +91332 -0.242279052734375 +91333 -0.11260986328125 +91334 -0.069732666015625 +91335 -0.0145263671875 +91336 0.125640869140625 +91337 0.0909423828125 +91338 0.31268310546875 +91339 0.190032958984375 +91340 0.45501708984375 +91341 0.267181396484375 +91342 0.554779052734375 +91343 0.322174072265625 +91344 0.61065673828125 +91345 0.353790283203125 +91346 0.610931396484375 +91347 0.357086181640625 +91348 0.531463623046875 +91349 0.3226318359375 +91350 0.3883056640625 +91351 0.257080078125 +91352 0.23468017578125 +91353 0.181976318359375 +91354 0.095245361328125 +91355 0.10797119140625 +91356 -0.00396728515625 +91357 0.04644775390625 +91358 -0.04852294921875 +91359 0.004364013671875 +91360 -0.055145263671875 +91361 -0.023406982421875 +91362 -0.0758056640625 +91363 -0.055877685546875 +91364 -0.138702392578125 +91365 -0.102752685546875 +91366 -0.209197998046875 +91367 -0.1492919921875 +91368 -0.289031982421875 +91369 -0.19525146484375 +91370 -0.37884521484375 +91371 -0.240234375 +91372 -0.456329345703125 +91373 -0.27508544921875 +91374 -0.51641845703125 +91375 -0.2977294921875 +91376 -0.519287109375 +91377 -0.292755126953125 +91378 -0.458251953125 +91379 -0.258026123046875 +91380 -0.384796142578125 +91381 -0.214447021484375 +91382 -0.323699951171875 +91383 -0.17266845703125 +91384 -0.269287109375 +91385 -0.131500244140625 +91386 -0.1951904296875 +91387 -0.08172607421875 +91388 -0.100006103515625 +91389 -0.02398681640625 +91390 -0.01055908203125 +91391 0.03009033203125 +91392 0.1033935546875 +91393 0.09149169921875 +91394 0.24908447265625 +91395 0.162200927734375 +91396 0.373199462890625 +91397 0.220306396484375 +91398 0.45806884765625 +91399 0.25848388671875 +91400 0.511474609375 +91401 0.27978515625 +91402 0.565399169921875 +91403 0.29718017578125 +91404 0.61138916015625 +91405 0.30767822265625 +91406 0.5897216796875 +91407 0.287933349609375 +91408 0.4906005859375 +91409 0.234710693359375 +91410 0.33148193359375 +91411 0.15582275390625 +91412 0.147796630859375 +91413 0.066314697265625 +91414 -0.01873779296875 +91415 -0.0162353515625 +91416 -0.140289306640625 +91417 -0.079833984375 +91418 -0.191986083984375 +91419 -0.113739013671875 +91420 -0.184295654296875 +91421 -0.1214599609375 +91422 -0.161834716796875 +91423 -0.120330810546875 +91424 -0.166595458984375 +91425 -0.126800537109375 +91426 -0.19390869140625 +91427 -0.13885498046875 +91428 -0.22442626953125 +91429 -0.1488037109375 +91430 -0.279754638671875 +91431 -0.16552734375 +91432 -0.3389892578125 +91433 -0.1810302734375 +91434 -0.3543701171875 +91435 -0.176727294921875 +91436 -0.348175048828125 +91437 -0.16217041015625 +91438 -0.32598876953125 +91439 -0.140289306640625 +91440 -0.2581787109375 +91441 -0.100006103515625 +91442 -0.139801025390625 +91443 -0.0400390625 +91444 0.014617919921875 +91445 0.033111572265625 +91446 0.144378662109375 +91447 0.09454345703125 +91448 0.221038818359375 +91449 0.132476806640625 +91450 0.27069091796875 +91451 0.156982421875 +91452 0.294036865234375 +91453 0.168182373046875 +91454 0.311767578125 +91455 0.17431640625 +91456 0.339141845703125 +91457 0.181732177734375 +91458 0.360260009765625 +91459 0.184600830078125 +91460 0.360504150390625 +91461 0.177398681640625 +91462 0.308380126953125 +91463 0.1470947265625 +91464 0.18170166015625 +91465 0.08465576171875 +91466 0.0047607421875 +91467 0.0008544921875 +91468 -0.17559814453125 +91469 -0.084014892578125 +91470 -0.3143310546875 +91471 -0.15045166015625 +91472 -0.36785888671875 +91473 -0.179595947265625 +91474 -0.36248779296875 +91475 -0.18231201171875 +91476 -0.343536376953125 +91477 -0.177581787109375 +91478 -0.3018798828125 +91479 -0.16143798828125 +91480 -0.231414794921875 +91481 -0.1312255859375 +91482 -0.117645263671875 +91483 -0.08087158203125 +91484 0.007049560546875 +91485 -0.024261474609375 +91486 0.087982177734375 +91487 0.01513671875 +91488 0.13946533203125 +91489 0.0430908203125 +91490 0.17425537109375 +91491 0.064666748046875 +91492 0.188201904296875 +91493 0.07769775390625 +91494 0.171234130859375 +91495 0.0775146484375 +91496 0.118438720703125 +91497 0.061676025390625 +91498 0.05706787109375 +91499 0.041412353515625 +91500 -0.010711669921875 +91501 0.017333984375 +91502 -0.0914306640625 +91503 -0.0135498046875 +91504 -0.162322998046875 +91505 -0.041717529296875 +91506 -0.194549560546875 +91507 -0.055023193359375 +91508 -0.1492919921875 +91509 -0.036956787109375 +91510 -0.02166748046875 +91511 0.014617919921875 +91512 0.124053955078125 +91513 0.0726318359375 +91514 0.211151123046875 +91515 0.10479736328125 +91516 0.240447998046875 +91517 0.11175537109375 +91518 0.242218017578125 +91519 0.10662841796875 +91520 0.2257080078125 +91521 0.093719482421875 +91522 0.194366455078125 +91523 0.074798583984375 +91524 0.115509033203125 +91525 0.036285400390625 +91526 0.0128173828125 +91527 -0.011444091796875 +91528 -0.053802490234375 +91529 -0.042816162109375 +91530 -0.110626220703125 +91531 -0.068817138671875 +91532 -0.199493408203125 +91533 -0.107147216796875 +91534 -0.29437255859375 +91535 -0.14678955078125 +91536 -0.33221435546875 +91537 -0.161041259765625 +91538 -0.27972412109375 +91539 -0.13592529296875 +91540 -0.185333251953125 +91541 -0.0921630859375 +91542 -0.128204345703125 +91543 -0.063568115234375 +91544 -0.115692138671875 +91545 -0.053466796875 +91546 -0.116455078125 +91547 -0.048858642578125 +91548 -0.105926513671875 +91549 -0.03961181640625 +91550 -0.053955078125 +91551 -0.013214111328125 +91552 0.048797607421875 +91553 0.0340576171875 +91554 0.157318115234375 +91555 0.082916259765625 +91556 0.212005615234375 +91557 0.108001708984375 +91558 0.218475341796875 +91559 0.111602783203125 +91560 0.23724365234375 +91561 0.119384765625 +91562 0.30535888671875 +91563 0.147064208984375 +91564 0.38128662109375 +91565 0.1771240234375 +91566 0.404449462890625 +91567 0.183990478515625 +91568 0.3944091796875 +91569 0.176177978515625 +91570 0.3885498046875 +91571 0.16973876953125 +91572 0.362640380859375 +91573 0.154632568359375 +91574 0.27362060546875 +91575 0.11285400390625 +91576 0.11712646484375 +91577 0.042755126953125 +91578 -0.054901123046875 +91579 -0.033416748046875 +91580 -0.19085693359375 +91581 -0.0936279296875 +91582 -0.28570556640625 +91583 -0.1356201171875 +91584 -0.339263916015625 +91585 -0.159271240234375 +91586 -0.3775634765625 +91587 -0.175537109375 +91588 -0.445709228515625 +91589 -0.20361328125 +91590 -0.535064697265625 +91591 -0.239898681640625 +91592 -0.629058837890625 +91593 -0.2774658203125 +91594 -0.697601318359375 +91595 -0.303680419921875 +91596 -0.70391845703125 +91597 -0.303131103515625 +91598 -0.6424560546875 +91599 -0.273651123046875 +91600 -0.491241455078125 +91601 -0.206146240234375 +91602 -0.265716552734375 +91603 -0.107330322265625 +91604 -0.023712158203125 +91605 -0.00189208984375 +91606 0.201751708984375 +91607 0.095977783203125 +91608 0.375823974609375 +91609 0.171417236328125 +91610 0.485076904296875 +91611 0.218658447265625 +91612 0.56884765625 +91613 0.254364013671875 +91614 0.634765625 +91615 0.281768798828125 +91616 0.63763427734375 +91617 0.281768798828125 +91618 0.5660400390625 +91619 0.2496337890625 +91620 0.4720458984375 +91621 0.20751953125 +91622 0.40692138671875 +91623 0.177276611328125 +91624 0.3778076171875 +91625 0.162109375 +91626 0.376953125 +91627 0.158905029296875 +91628 0.371978759765625 +91629 0.15411376953125 +91630 0.313140869140625 +91631 0.12677001953125 +91632 0.184417724609375 +91633 0.070159912109375 +91634 0.011199951171875 +91635 -0.004791259765625 +91636 -0.171051025390625 +91637 -0.082977294921875 +91638 -0.33740234375 +91639 -0.15380859375 +91640 -0.47198486328125 +91641 -0.210540771484375 +91642 -0.560394287109375 +91643 -0.247100830078125 +91644 -0.58056640625 +91645 -0.25421142578125 +91646 -0.54754638671875 +91647 -0.238372802734375 +91648 -0.508575439453125 +91649 -0.2198486328125 +91650 -0.459503173828125 +91651 -0.19677734375 +91652 -0.394378662109375 +91653 -0.166961669921875 +91654 -0.35260009765625 +91655 -0.14837646484375 +91656 -0.31170654296875 +91657 -0.1307373046875 +91658 -0.197418212890625 +91659 -0.080169677734375 +91660 -0.007965087890625 +91661 0.004180908203125 +91662 0.207489013671875 +91663 0.100006103515625 +91664 0.409210205078125 +91665 0.189300537109375 +91666 0.57208251953125 +91667 0.260772705078125 +91668 0.66595458984375 +91669 0.30084228515625 +91670 0.65875244140625 +91671 0.2950439453125 +91672 0.56744384765625 +91673 0.251251220703125 +91674 0.431396484375 +91675 0.1875 +91676 0.29443359375 +91677 0.123870849609375 +91678 0.182464599609375 +91679 0.072265625 +91680 0.06365966796875 +91681 0.018157958984375 +91682 -0.075958251953125 +91683 -0.044830322265625 +91684 -0.189422607421875 +91685 -0.0953369140625 +91686 -0.271942138671875 +91687 -0.131256103515625 +91688 -0.342529296875 +91689 -0.161346435546875 +91690 -0.364166259765625 +91691 -0.168914794921875 +91692 -0.327239990234375 +91693 -0.149688720703125 +91694 -0.2769775390625 +91695 -0.124420166015625 +91696 -0.253692626953125 +91697 -0.111602783203125 +91698 -0.24365234375 +91699 -0.105072021484375 +91700 -0.1983642578125 +91701 -0.082855224609375 +91702 -0.116241455078125 +91703 -0.0443115234375 +91704 -0.036834716796875 +91705 -0.007476806640625 +91706 0.034881591796875 +91707 0.02532958984375 +91708 0.09124755859375 +91709 0.050628662109375 +91710 0.10888671875 +91711 0.05780029296875 +91712 0.125518798828125 +91713 0.0640869140625 +91714 0.15771484375 +91715 0.0771484375 +91716 0.17828369140625 +91717 0.084686279296875 +91718 0.17108154296875 +91719 0.07940673828125 +91720 0.129974365234375 +91721 0.05865478515625 +91722 0.082427978515625 +91723 0.035064697265625 +91724 0.027679443359375 +91725 0.008392333984375 +91726 -0.065643310546875 +91727 -0.035552978515625 +91728 -0.15936279296875 +91729 -0.07928466796875 +91730 -0.21307373046875 +91731 -0.104339599609375 +91732 -0.234649658203125 +91733 -0.11431884765625 +91734 -0.2001953125 +91735 -0.098358154296875 +91736 -0.119171142578125 +91737 -0.060760498046875 +91738 -0.024749755859375 +91739 -0.0167236328125 +91740 0.085784912109375 +91741 0.034912109375 +91742 0.178131103515625 +91743 0.07843017578125 +91744 0.215576171875 +91745 0.097015380859375 +91746 0.211456298828125 +91747 0.0966796875 +91748 0.17523193359375 +91749 0.0816650390625 +91750 0.128753662109375 +91751 0.06182861328125 +91752 0.1019287109375 +91753 0.050750732421875 +91754 0.0743408203125 +91755 0.0390625 +91756 0.04327392578125 +91757 0.025482177734375 +91758 0.038177490234375 +91759 0.0234375 +91760 0.076263427734375 +91761 0.040740966796875 +91762 0.14105224609375 +91763 0.06988525390625 +91764 0.186431884765625 +91765 0.089874267578125 +91766 0.188812255859375 +91767 0.089996337890625 +91768 0.1390380859375 +91769 0.066131591796875 +91770 0.041778564453125 +91771 0.0205078125 +91772 -0.079437255859375 +91773 -0.036041259765625 +91774 -0.219390869140625 +91775 -0.101104736328125 +91776 -0.367828369140625 +91777 -0.169921875 +91778 -0.494873046875 +91779 -0.228790283203125 +91780 -0.556243896484375 +91781 -0.257476806640625 +91782 -0.508697509765625 +91783 -0.236236572265625 +91784 -0.3756103515625 +91785 -0.17572021484375 +91786 -0.218902587890625 +91787 -0.10418701171875 +91788 -0.063751220703125 +91789 -0.033111572265625 +91790 0.091552734375 +91791 0.038238525390625 +91792 0.23602294921875 +91793 0.10479736328125 +91794 0.342987060546875 +91795 0.154388427734375 +91796 0.39520263671875 +91797 0.179107666015625 +91798 0.389373779296875 +91799 0.177398681640625 +91800 0.324249267578125 +91801 0.148651123046875 +91802 0.224090576171875 +91803 0.1038818359375 +91804 0.124267578125 +91805 0.05914306640625 +91806 0.037078857421875 +91807 0.019989013671875 +91808 -0.010101318359375 +91809 -0.0010986328125 +91810 -0.019439697265625 +91811 -0.005157470703125 +91812 -0.022796630859375 +91813 -0.006683349609375 +91814 -0.001556396484375 +91815 0.002777099609375 +91816 0.056304931640625 +91817 0.02874755859375 +91818 0.106719970703125 +91819 0.0511474609375 +91820 0.096893310546875 +91821 0.045928955078125 +91822 0.042694091796875 +91823 0.020416259765625 +91824 -0.018035888671875 +91825 -0.008087158203125 +91826 -0.07586669921875 +91827 -0.035247802734375 +91828 -0.11944580078125 +91829 -0.055816650390625 +91830 -0.15972900390625 +91831 -0.07476806640625 +91832 -0.202606201171875 +91833 -0.094757080078125 +91834 -0.24859619140625 +91835 -0.115966796875 +91836 -0.30517578125 +91837 -0.141815185546875 +91838 -0.36212158203125 +91839 -0.16766357421875 +91840 -0.39141845703125 +91841 -0.1807861328125 +91842 -0.35528564453125 +91843 -0.1639404296875 +91844 -0.249969482421875 +91845 -0.115447998046875 +91846 -0.092864990234375 +91847 -0.04327392578125 +91848 0.08905029296875 +91849 0.040252685546875 +91850 0.2352294921875 +91851 0.107513427734375 +91852 0.318817138671875 +91853 0.146209716796875 +91854 0.358642578125 +91855 0.164886474609375 +91856 0.347747802734375 +91857 0.16033935546875 +91858 0.28564453125 +91859 0.13232421875 +91860 0.223175048828125 +91861 0.10400390625 +91862 0.196746826171875 +91863 0.09197998046875 +91864 0.179840087890625 +91865 0.084197998046875 +91866 0.155548095703125 +91867 0.07293701171875 +91868 0.151214599609375 +91869 0.0706787109375 +91870 0.156951904296875 +91871 0.07293701171875 +91872 0.13177490234375 +91873 0.061004638671875 +91874 0.100799560546875 +91875 0.04638671875 +91876 0.087127685546875 +91877 0.039642333984375 +91878 0.05487060546875 +91879 0.02447509765625 +91880 -0.009002685546875 +91881 -0.00506591796875 +91882 -0.10400390625 +91883 -0.0487060546875 +91884 -0.229400634765625 +91885 -0.106109619140625 +91886 -0.35552978515625 +91887 -0.16375732421875 +91888 -0.441925048828125 +91889 -0.203155517578125 +91890 -0.473846435546875 +91891 -0.217620849609375 +91892 -0.464813232421875 +91893 -0.21331787109375 +91894 -0.419097900390625 +91895 -0.19219970703125 +91896 -0.334320068359375 +91897 -0.1531982421875 +91898 -0.227935791015625 +91899 -0.104278564453125 +91900 -0.12347412109375 +91901 -0.05621337890625 +91902 -0.02764892578125 +91903 -0.0120849609375 +91904 0.077667236328125 +91905 0.036285400390625 +91906 0.2132568359375 +91907 0.098602294921875 +91908 0.38885498046875 +91909 0.18011474609375 +91910 0.582794189453125 +91911 0.2708740234375 +91912 0.734039306640625 +91913 0.341583251953125 +91914 0.800140380859375 +91915 0.371856689453125 +91916 0.7783203125 +91917 0.36053466796875 +91918 0.6651611328125 +91919 0.30596923828125 +91920 0.45965576171875 +91921 0.207611083984375 +91922 0.199188232421875 +91923 0.083587646484375 +91924 -0.050689697265625 +91925 -0.034332275390625 +91926 -0.23297119140625 +91927 -0.118621826171875 +91928 -0.33013916015625 +91929 -0.16107177734375 +91930 -0.368408203125 +91931 -0.174774169921875 +91932 -0.378936767578125 +91933 -0.17523193359375 +91934 -0.376983642578125 +91935 -0.17022705078125 +91936 -0.37969970703125 +91937 -0.1683349609375 +91938 -0.391510009765625 +91939 -0.171844482421875 +91940 -0.385345458984375 +91941 -0.167694091796875 +91942 -0.3419189453125 +91943 -0.146484375 +91944 -0.28289794921875 +91945 -0.118804931640625 +91946 -0.251617431640625 +91947 -0.105682373046875 +91948 -0.266143798828125 +91949 -0.11578369140625 +91950 -0.273345947265625 +91951 -0.12298583984375 +91952 -0.216796875 +91953 -0.099517822265625 +91954 -0.128265380859375 +91955 -0.060638427734375 +91956 -0.068145751953125 +91957 -0.03558349609375 +91958 -0.0430908203125 +91959 -0.027374267578125 +91960 -0.024444580078125 +91961 -0.021820068359375 +91962 0.020721435546875 +91963 -0.00262451171875 +91964 0.124481201171875 +91965 0.04595947265625 +91966 0.25787353515625 +91967 0.10986328125 +91968 0.379119873046875 +91969 0.168731689453125 +91970 0.47991943359375 +91971 0.218536376953125 +91972 0.5281982421875 +91973 0.2435302734375 +91974 0.511138916015625 +91975 0.23736572265625 +91976 0.456207275390625 +91977 0.21331787109375 +91978 0.407470703125 +91979 0.192718505859375 +91980 0.383758544921875 +91981 0.1845703125 +91982 0.35687255859375 +91983 0.1749267578125 +91984 0.31182861328125 +91985 0.156280517578125 +91986 0.250885009765625 +91987 0.1295166015625 +91988 0.1654052734375 +91989 0.090301513671875 +91990 0.035247802734375 +91991 0.0286865234375 +91992 -0.142059326171875 +91993 -0.056610107421875 +91994 -0.33563232421875 +91995 -0.150543212890625 +91996 -0.5345458984375 +91997 -0.247772216796875 +91998 -0.72186279296875 +91999 -0.34002685546875 +92000 -0.836669921875 +92001 -0.39752197265625 +92002 -0.8326416015625 +92003 -0.397552490234375 +92004 -0.7296142578125 +92005 -0.34967041015625 +92006 -0.582550048828125 +92007 -0.28057861328125 +92008 -0.440093994140625 +92009 -0.213836669921875 +92010 -0.324310302734375 +92011 -0.160064697265625 +92012 -0.20147705078125 +92013 -0.102630615234375 +92014 -0.044647216796875 +92015 -0.02825927734375 +92016 0.103973388671875 +92017 0.042510986328125 +92018 0.202392578125 +92019 0.089263916015625 +92020 0.264495849609375 +92021 0.118865966796875 +92022 0.338897705078125 +92023 0.155059814453125 +92024 0.443817138671875 +92025 0.206695556640625 +92026 0.545074462890625 +92027 0.257049560546875 +92028 0.6173095703125 +92029 0.293701171875 +92030 0.6524658203125 +92031 0.312652587890625 +92032 0.66339111328125 +92033 0.320037841796875 +92034 0.6561279296875 +92035 0.31866455078125 +92036 0.606781005859375 +92037 0.2967529296875 +92038 0.501190185546875 +92039 0.247283935546875 +92040 0.352783203125 +92041 0.17669677734375 +92042 0.176544189453125 +92043 0.09222412109375 +92044 -0.034820556640625 +92045 -0.009735107421875 +92046 -0.258209228515625 +92047 -0.117950439453125 +92048 -0.44244384765625 +92049 -0.207489013671875 +92050 -0.5753173828125 +92051 -0.27239990234375 +92052 -0.65203857421875 +92053 -0.310333251953125 +92054 -0.641632080078125 +92055 -0.30615234375 +92056 -0.562164306640625 +92057 -0.268646240234375 +92058 -0.458038330078125 +92059 -0.219390869140625 +92060 -0.350555419921875 +92061 -0.168670654296875 +92062 -0.260528564453125 +92063 -0.12652587890625 +92064 -0.192108154296875 +92065 -0.09490966796875 +92066 -0.141937255859375 +92067 -0.072052001953125 +92068 -0.1021728515625 +92069 -0.054046630859375 +92070 -0.062896728515625 +92071 -0.035980224609375 +92072 -0.011932373046875 +92073 -0.011871337890625 +92074 0.062835693359375 +92075 0.024200439453125 +92076 0.148712158203125 +92077 0.066070556640625 +92078 0.241729736328125 +92079 0.11175537109375 +92080 0.34912109375 +92081 0.164764404296875 +92082 0.457305908203125 +92083 0.21844482421875 +92084 0.54388427734375 +92085 0.261810302734375 +92086 0.5728759765625 +92087 0.277252197265625 +92088 0.506591796875 +92089 0.246307373046875 +92090 0.351226806640625 +92091 0.171905517578125 +92092 0.146514892578125 +92093 0.0733642578125 +92094 -0.05523681640625 +92095 -0.02386474609375 +92096 -0.21624755859375 +92097 -0.1014404296875 +92098 -0.334930419921875 +92099 -0.158599853515625 +92100 -0.402984619140625 +92101 -0.191314697265625 +92102 -0.4412841796875 +92103 -0.20977783203125 +92104 -0.49578857421875 +92105 -0.2364501953125 +92106 -0.5601806640625 +92107 -0.268218994140625 +92108 -0.600738525390625 +92109 -0.288604736328125 +92110 -0.584228515625 +92111 -0.2813720703125 +92112 -0.47930908203125 +92113 -0.23114013671875 +92114 -0.27935791015625 +92115 -0.1346435546875 +92116 -0.0089111328125 +92117 -0.0037841796875 +92118 0.268798828125 +92119 0.130615234375 +92120 0.482818603515625 +92121 0.2340087890625 +92122 0.60369873046875 +92123 0.292083740234375 +92124 0.650421142578125 +92125 0.314117431640625 +92126 0.66400146484375 +92127 0.3201904296875 +92128 0.6414794921875 +92129 0.308868408203125 +92130 0.572540283203125 +92131 0.275146484375 +92132 0.498138427734375 +92133 0.23895263671875 +92134 0.439453125 +92135 0.210662841796875 +92136 0.375518798828125 +92137 0.180023193359375 +92138 0.274505615234375 +92139 0.1314697265625 +92140 0.1087646484375 +92141 0.05145263671875 +92142 -0.099395751953125 +92143 -0.049224853515625 +92144 -0.3182373046875 +92145 -0.155059814453125 +92146 -0.5489501953125 +92147 -0.2667236328125 +92148 -0.7738037109375 +92149 -0.375579833984375 +92150 -0.86383056640625 +92151 -0.455841064453125 +92152 -0.870391845703125 +92153 -0.4913330078125 +92154 -0.86895751953125 +92155 -0.49072265625 +92156 -0.861053466796875 +92157 -0.46044921875 +92158 -0.765869140625 +92159 -0.392059326171875 +92160 -0.5301513671875 +92161 -0.27996826171875 +92162 -0.214691162109375 +92163 -0.127105712890625 +92164 0.137359619140625 +92165 0.045318603515625 +92166 0.474822998046875 +92167 0.211639404296875 +92168 0.76239013671875 +92169 0.354217529296875 +92170 0.867462158203125 +92171 0.459747314453125 +92172 0.870361328125 +92173 0.5289306640625 +92174 0.86480712890625 +92175 0.55609130859375 +92176 0.831817626953125 +92177 0.544158935546875 +92178 0.677581787109375 +92179 0.50579833984375 +92180 0.495880126953125 +92181 0.44384765625 +92182 0.30767822265625 +92183 0.36767578125 +92184 0.116180419921875 +92185 0.278045654296875 +92186 -0.110748291015625 +92187 0.157989501953125 +92188 -0.381805419921875 +92189 0.00335693359375 +92190 -0.6572265625 +92191 -0.164093017578125 +92192 -0.857421875 +92193 -0.313720703125 +92194 -0.870391845703125 +92195 -0.42364501953125 +92196 -0.870391845703125 +92197 -0.490570068359375 +92198 -0.86444091796875 +92199 -0.52880859375 +92200 -0.85723876953125 +92201 -0.55712890625 +92202 -0.790008544921875 +92203 -0.56610107421875 +92204 -0.62847900390625 +92205 -0.52752685546875 +92206 -0.3956298828125 +92207 -0.439605712890625 +92208 -0.126708984375 +92209 -0.3192138671875 +92210 0.150115966796875 +92211 -0.180328369140625 +92212 0.424041748046875 +92213 -0.0286865234375 +92214 0.670623779296875 +92215 0.1220703125 +92216 0.854522705078125 +92217 0.252166748046875 +92218 0.866485595703125 +92219 0.352783203125 +92220 0.86920166015625 +92221 0.41632080078125 +92222 0.8653564453125 +92223 0.4525146484375 +92224 0.857147216796875 +92225 0.468597412109375 +92226 0.766845703125 +92227 0.463287353515625 +92228 0.628509521484375 +92229 0.439361572265625 +92230 0.462127685546875 +92231 0.393341064453125 +92232 0.297210693359375 +92233 0.33856201171875 +92234 0.14862060546875 +92235 0.281341552734375 +92236 -0.00537109375 +92237 0.2095947265625 +92238 -0.15753173828125 +92239 0.126983642578125 +92240 -0.31304931640625 +92241 0.03131103515625 +92242 -0.48876953125 +92243 -0.084991455078125 +92244 -0.6416015625 +92245 -0.1978759765625 +92246 -0.751373291015625 +92247 -0.294769287109375 +92248 -0.84619140625 +92249 -0.387969970703125 +92250 -0.861297607421875 +92251 -0.47003173828125 +92252 -0.863250732421875 +92253 -0.523895263671875 +92254 -0.856597900390625 +92255 -0.533233642578125 +92256 -0.7498779296875 +92257 -0.504425048828125 +92258 -0.624542236328125 +92259 -0.467559814453125 +92260 -0.47808837890625 +92261 -0.411102294921875 +92262 -0.253387451171875 +92263 -0.304534912109375 +92264 0.003692626953125 +92265 -0.17138671875 +92266 0.2257080078125 +92267 -0.0469970703125 +92268 0.427154541015625 +92269 0.075408935546875 +92270 0.643218994140625 +92271 0.212921142578125 +92272 0.855926513671875 +92273 0.360748291015625 +92274 0.870361328125 +92275 0.48895263671875 +92276 0.870361328125 +92277 0.571929931640625 +92278 0.862762451171875 +92279 0.61358642578125 +92280 0.79669189453125 +92281 0.612457275390625 +92282 0.595794677734375 +92283 0.563690185546875 +92284 0.362152099609375 +92285 0.482452392578125 +92286 0.1270751953125 +92287 0.383270263671875 +92288 -0.086944580078125 +92289 0.277069091796875 +92290 -0.2784423828125 +92291 0.164825439453125 +92292 -0.484832763671875 +92293 0.0283203125 +92294 -0.729583740234375 +92295 -0.142547607421875 +92296 -0.86688232421875 +92297 -0.3216552734375 +92298 -0.870391845703125 +92299 -0.47625732421875 +92300 -0.86859130859375 +92301 -0.603912353515625 +92302 -0.86279296875 +92303 -0.70361328125 +92304 -0.817962646484375 +92305 -0.75677490234375 +92306 -0.6116943359375 +92307 -0.7398681640625 +92308 -0.3128662109375 +92309 -0.64923095703125 +92310 0.039398193359375 +92311 -0.502410888671875 +92312 0.422821044921875 +92313 -0.309783935546875 +92314 0.805145263671875 +92315 -0.088623046875 +92316 0.870361328125 +92317 0.125640869140625 +92318 0.870361328125 +92319 0.30340576171875 +92320 0.860015869140625 +92321 0.4385986328125 +92322 0.727935791015625 +92323 0.52728271484375 +92324 0.48114013671875 +92325 0.566558837890625 +92326 0.2059326171875 +92327 0.569000244140625 +92328 -0.06103515625 +92329 0.546356201171875 +92330 -0.29913330078125 +92331 0.503875732421875 +92332 -0.516204833984375 +92333 0.43402099609375 +92334 -0.7252197265625 +92335 0.328857421875 +92336 -0.85980224609375 +92337 0.201385498046875 +92338 -0.870391845703125 +92339 0.069549560546875 +92340 -0.870391845703125 +92341 -0.051116943359375 +92342 -0.858062744140625 +92343 -0.13519287109375 +92344 -0.673004150390625 +92345 -0.1802978515625 +92346 -0.42694091796875 +92347 -0.213531494140625 +92348 -0.2100830078125 +92349 -0.257781982421875 +92350 -0.0362548828125 +92351 -0.311767578125 +92352 0.10943603515625 +92353 -0.360260009765625 +92354 0.23516845703125 +92355 -0.392791748046875 +92356 0.373687744140625 +92357 -0.38775634765625 +92358 0.517791748046875 +92359 -0.34613037109375 +92360 0.602783203125 +92361 -0.30072021484375 +92362 0.635711669921875 +92363 -0.248870849609375 +92364 0.655181884765625 +92365 -0.17340087890625 +92366 0.65948486328125 +92367 -0.07965087890625 +92368 0.651275634765625 +92369 0.027984619140625 +92370 0.61846923828125 +92371 0.136505126953125 +92372 0.53753662109375 +92373 0.226470947265625 +92374 0.404144287109375 +92375 0.288238525390625 +92376 0.22186279296875 +92377 0.316558837890625 +92378 0.003997802734375 +92379 0.3118896484375 +92380 -0.22100830078125 +92381 0.28350830078125 +92382 -0.42449951171875 +92383 0.242034912109375 +92384 -0.579833984375 +92385 0.198516845703125 +92386 -0.641876220703125 +92387 0.1751708984375 +92388 -0.6177978515625 +92389 0.1685791015625 +92390 -0.575531005859375 +92391 0.145263671875 +92392 -0.526336669921875 +92393 0.10260009765625 +92394 -0.42645263671875 +92395 0.067718505859375 +92396 -0.2581787109375 +92397 0.055084228515625 +92398 -0.068695068359375 +92399 0.046051025390625 +92400 0.09222412109375 +92401 0.020782470703125 +92402 0.232147216796875 +92403 -0.010772705078125 +92404 0.3509521484375 +92405 -0.0430908203125 +92406 0.410064697265625 +92407 -0.0914306640625 +92408 0.372955322265625 +92409 -0.1708984375 +92410 0.2554931640625 +92411 -0.270477294921875 +92412 0.10711669921875 +92413 -0.363006591796875 +92414 -0.052886962890625 +92415 -0.43829345703125 +92416 -0.186279296875 +92417 -0.47711181640625 +92418 -0.23291015625 +92419 -0.450042724609375 +92420 -0.209442138671875 +92421 -0.369903564453125 +92422 -0.174163818359375 +92423 -0.27239990234375 +92424 -0.126739501953125 +92425 -0.1614990234375 +92426 -0.048126220703125 +92427 -0.031280517578125 +92428 0.0426025390625 +92429 0.103179931640625 +92430 0.10748291015625 +92431 0.21661376953125 +92432 0.1409912109375 +92433 0.302032470703125 +92434 0.19708251953125 +92435 0.3858642578125 +92436 0.273651123046875 +92437 0.464508056640625 +92438 0.31768798828125 +92439 0.50726318359375 +92440 0.341094970703125 +92441 0.520172119140625 +92442 0.368011474609375 +92443 0.51702880859375 +92444 0.37249755859375 +92445 0.48504638671875 +92446 0.30072021484375 +92447 0.396942138671875 +92448 0.1517333984375 +92449 0.25518798828125 +92450 -0.01470947265625 +92451 0.096221923828125 +92452 -0.1883544921875 +92453 -0.070404052734375 +92454 -0.372711181640625 +92455 -0.242645263671875 +92456 -0.51397705078125 +92457 -0.387115478515625 +92458 -0.57177734375 +92459 -0.47802734375 +92460 -0.53948974609375 +92461 -0.508758544921875 +92462 -0.43511962890625 +92463 -0.48687744140625 +92464 -0.2962646484375 +92465 -0.4315185546875 +92466 -0.161102294921875 +92467 -0.362945556640625 +92468 -0.0435791015625 +92469 -0.2889404296875 +92470 0.060394287109375 +92471 -0.20819091796875 +92472 0.13665771484375 +92473 -0.130157470703125 +92474 0.170135498046875 +92475 -0.065460205078125 +92476 0.16552734375 +92477 -0.01434326171875 +92478 0.15728759765625 +92479 0.038970947265625 +92480 0.150787353515625 +92481 0.09417724609375 +92482 0.12200927734375 +92483 0.13482666015625 +92484 0.080108642578125 +92485 0.1629638671875 +92486 0.05126953125 +92487 0.190338134765625 +92488 0.062896728515625 +92489 0.229888916015625 +92490 0.09271240234375 +92491 0.267852783203125 +92492 0.092987060546875 +92493 0.277130126953125 +92494 0.07855224609375 +92495 0.2657470703125 +92496 0.06427001953125 +92497 0.242431640625 +92498 0.0347900390625 +92499 0.19989013671875 +92500 -0.01171875 +92501 0.13885498046875 +92502 -0.056060791015625 +92503 0.07208251953125 +92504 -0.055511474609375 +92505 0.025604248046875 +92506 -0.010467529296875 +92507 0.001861572265625 +92508 0.02508544921875 +92509 -0.026092529296875 +92510 0.025665283203125 +92511 -0.0697021484375 +92512 0.017333984375 +92513 -0.11236572265625 +92514 0.00189208984375 +92515 -0.15118408203125 +92516 -0.03173828125 +92517 -0.190826416015625 +92518 -0.071502685546875 +92519 -0.223785400390625 +92520 -0.13543701171875 +92521 -0.2596435546875 +92522 -0.219970703125 +92523 -0.29669189453125 +92524 -0.300506591796875 +92525 -0.32220458984375 +92526 -0.376312255859375 +92527 -0.337066650390625 +92528 -0.416107177734375 +92529 -0.325775146484375 +92530 -0.371124267578125 +92531 -0.263519287109375 +92532 -0.242279052734375 +92533 -0.152984619140625 +92534 -0.069732666015625 +92535 -0.0184326171875 +92536 0.125640869140625 +92537 0.126434326171875 +92538 0.31268310546875 +92539 0.26251220703125 +92540 0.45501708984375 +92541 0.368133544921875 +92542 0.554779052734375 +92543 0.443115234375 +92544 0.61065673828125 +92545 0.485870361328125 +92546 0.610931396484375 +92547 0.489532470703125 +92548 0.531463623046875 +92549 0.44085693359375 +92550 0.3883056640625 +92551 0.349212646484375 +92552 0.23468017578125 +92553 0.244781494140625 +92554 0.095245361328125 +92555 0.142425537109375 +92556 -0.00396728515625 +92557 0.05804443359375 +92558 -0.04852294921875 +92559 0.00128173828125 +92560 -0.055145263671875 +92561 -0.035186767578125 +92562 -0.0758056640625 +92563 -0.07818603515625 +92564 -0.138702392578125 +92565 -0.141510009765625 +92566 -0.209197998046875 +92567 -0.204620361328125 +92568 -0.289031982421875 +92569 -0.26727294921875 +92570 -0.37884521484375 +92571 -0.328948974609375 +92572 -0.456329345703125 +92573 -0.37689208984375 +92574 -0.51641845703125 +92575 -0.40826416015625 +92576 -0.519287109375 +92577 -0.40142822265625 +92578 -0.458251953125 +92579 -0.353363037109375 +92580 -0.384796142578125 +92581 -0.293365478515625 +92582 -0.323699951171875 +92583 -0.236236572265625 +92584 -0.269287109375 +92585 -0.18023681640625 +92586 -0.1951904296875 +92587 -0.112396240234375 +92588 -0.100006103515625 +92589 -0.033447265625 +92590 -0.01055908203125 +92591 0.0404052734375 +92592 0.1033935546875 +92593 0.12451171875 +92594 0.24908447265625 +92595 0.22174072265625 +92596 0.373199462890625 +92597 0.301971435546875 +92598 0.45806884765625 +92599 0.35498046875 +92600 0.511474609375 +92601 0.384857177734375 +92602 0.565399169921875 +92603 0.40936279296875 +92604 0.61138916015625 +92605 0.424285888671875 +92606 0.5897216796875 +92607 0.397491455078125 +92608 0.4906005859375 +92609 0.32452392578125 +92610 0.33148193359375 +92611 0.21612548828125 +92612 0.147796630859375 +92613 0.09295654296875 +92614 -0.01873779296875 +92615 -0.020751953125 +92616 -0.140289306640625 +92617 -0.108489990234375 +92618 -0.191986083984375 +92619 -0.155487060546875 +92620 -0.184295654296875 +92621 -0.166534423828125 +92622 -0.161834716796875 +92623 -0.16546630859375 +92624 -0.166595458984375 +92625 -0.17486572265625 +92626 -0.19390869140625 +92627 -0.191925048828125 +92628 -0.22442626953125 +92629 -0.206024169921875 +92630 -0.279754638671875 +92631 -0.229339599609375 +92632 -0.3389892578125 +92633 -0.250885009765625 +92634 -0.3543701171875 +92635 -0.2451171875 +92636 -0.348175048828125 +92637 -0.22515869140625 +92638 -0.32598876953125 +92639 -0.19500732421875 +92640 -0.2581787109375 +92641 -0.139434814453125 +92642 -0.139801025390625 +92643 -0.05670166015625 +92644 0.014617919921875 +92645 0.04425048828125 +92646 0.144378662109375 +92647 0.129180908203125 +92648 0.221038818359375 +92649 0.18182373046875 +92650 0.27069091796875 +92651 0.21600341796875 +92652 0.294036865234375 +92653 0.23187255859375 +92654 0.311767578125 +92655 0.240753173828125 +92656 0.339141845703125 +92657 0.251220703125 +92658 0.360260009765625 +92659 0.2548828125 +92660 0.360504150390625 +92661 0.2442626953125 +92662 0.308380126953125 +92663 0.202606201171875 +92664 0.18170166015625 +92665 0.118408203125 +92666 0.0047607421875 +92667 0.00592041015625 +92668 -0.17559814453125 +92669 -0.108184814453125 +92670 -0.3143310546875 +92671 -0.198272705078125 +92672 -0.36785888671875 +92673 -0.23919677734375 +92674 -0.36248779296875 +92675 -0.245269775390625 +92676 -0.343536376953125 +92677 -0.24169921875 +92678 -0.3018798828125 +92679 -0.222625732421875 +92680 -0.231414794921875 +92681 -0.18408203125 +92682 -0.117645263671875 +92683 -0.117462158203125 +92684 0.007049560546875 +92685 -0.04168701171875 +92686 0.087982177734375 +92687 0.011077880859375 +92688 0.13946533203125 +92689 0.048858642578125 +92690 0.17425537109375 +92691 0.078582763671875 +92692 0.188201904296875 +92693 0.09722900390625 +92694 0.171234130859375 +92695 0.09832763671875 +92696 0.118438720703125 +92697 0.078369140625 +92698 0.05706787109375 +92699 0.05267333984375 +92700 -0.010711669921875 +92701 0.02191162109375 +92702 -0.0914306640625 +92703 -0.0181884765625 +92704 -0.162322998046875 +92705 -0.05462646484375 +92706 -0.194549560546875 +92707 -0.07080078125 +92708 -0.1492919921875 +92709 -0.04412841796875 +92710 -0.02166748046875 +92711 0.02825927734375 +92712 0.124053955078125 +92713 0.109039306640625 +92714 0.211151123046875 +92715 0.1536865234375 +92716 0.240447998046875 +92717 0.163116455078125 +92718 0.242218017578125 +92719 0.155426025390625 +92720 0.2257080078125 +92721 0.13653564453125 +92722 0.194366455078125 +92723 0.1090087890625 +92724 0.115509033203125 +92725 0.054229736328125 +92726 0.0128173828125 +92727 -0.013427734375 +92728 -0.053802490234375 +92729 -0.05865478515625 +92730 -0.110626220703125 +92731 -0.096466064453125 +92732 -0.199493408203125 +92733 -0.151092529296875 +92734 -0.29437255859375 +92735 -0.207275390625 +92736 -0.33221435546875 +92737 -0.228179931640625 +92738 -0.27972412109375 +92739 -0.194488525390625 +92740 -0.185333251953125 +92741 -0.134735107421875 +92742 -0.128204345703125 +92743 -0.095428466796875 +92744 -0.115692138671875 +92745 -0.0811767578125 +92746 -0.116455078125 +92747 -0.074127197265625 +92748 -0.105926513671875 +92749 -0.06036376953125 +92750 -0.053955078125 +92751 -0.022705078125 +92752 0.048797607421875 +92753 0.043914794921875 +92754 0.157318115234375 +92755 0.112884521484375 +92756 0.212005615234375 +92757 0.149139404296875 +92758 0.218475341796875 +92759 0.155731201171875 +92760 0.23724365234375 +92761 0.167877197265625 +92762 0.30535888671875 +92763 0.20721435546875 +92764 0.38128662109375 +92765 0.24951171875 +92766 0.404449462890625 +92767 0.25958251953125 +92768 0.3944091796875 +92769 0.24908447265625 +92770 0.3885498046875 +92771 0.240142822265625 +92772 0.362640380859375 +92773 0.21893310546875 +92774 0.27362060546875 +92775 0.16064453125 +92776 0.11712646484375 +92777 0.063079833984375 +92778 -0.054901123046875 +92779 -0.043060302734375 +92780 -0.19085693359375 +92781 -0.127349853515625 +92782 -0.28570556640625 +92783 -0.186614990234375 +92784 -0.339263916015625 +92785 -0.2205810546875 +92786 -0.3775634765625 +92787 -0.24432373046875 +92788 -0.445709228515625 +92789 -0.284149169921875 +92790 -0.535064697265625 +92791 -0.335052490234375 +92792 -0.629058837890625 +92793 -0.387451171875 +92794 -0.697601318359375 +92795 -0.423919677734375 +92796 -0.70391845703125 +92797 -0.423248291015625 +92798 -0.6424560546875 +92799 -0.3824462890625 +92800 -0.491241455078125 +92801 -0.288970947265625 +92802 -0.265716552734375 +92803 -0.152099609375 +92804 -0.023712158203125 +92805 -0.00592041015625 +92806 0.201751708984375 +92807 0.130035400390625 +92808 0.375823974609375 +92809 0.23516845703125 +92810 0.485076904296875 +92811 0.301513671875 +92812 0.56884765625 +92813 0.351898193359375 +92814 0.634765625 +92815 0.3907470703125 +92816 0.63763427734375 +92817 0.391693115234375 +92818 0.5660400390625 +92819 0.34808349609375 +92820 0.4720458984375 +92821 0.290496826171875 +92822 0.40692138671875 +92823 0.2490234375 +92824 0.3778076171875 +92825 0.228057861328125 +92826 0.376953125 +92827 0.223297119140625 +92828 0.371978759765625 +92829 0.216094970703125 +92830 0.313140869140625 +92831 0.1776123046875 +92832 0.184417724609375 +92833 0.09869384765625 +92834 0.011199951171875 +92835 -0.005584716796875 +92836 -0.171051025390625 +92837 -0.114349365234375 +92838 -0.33740234375 +92839 -0.21295166015625 +92840 -0.47198486328125 +92841 -0.29205322265625 +92842 -0.560394287109375 +92843 -0.34326171875 +92844 -0.58056640625 +92845 -0.353759765625 +92846 -0.54754638671875 +92847 -0.332427978515625 +92848 -0.508575439453125 +92849 -0.3070068359375 +92850 -0.459503173828125 +92851 -0.275238037109375 +92852 -0.394378662109375 +92853 -0.233795166015625 +92854 -0.35260009765625 +92855 -0.205902099609375 +92856 -0.31170654296875 +92857 -0.1785888671875 +92858 -0.197418212890625 +92859 -0.108673095703125 +92860 -0.007965087890625 +92861 0.00469970703125 +92862 0.207489013671875 +92863 0.132659912109375 +92864 0.409210205078125 +92865 0.25189208984375 +92866 0.57208251953125 +92867 0.347686767578125 +92868 0.66595458984375 +92869 0.402435302734375 +92870 0.65875244140625 +92871 0.39739990234375 +92872 0.56744384765625 +92873 0.34259033203125 +92874 0.431396484375 +92875 0.2611083984375 +92876 0.29443359375 +92877 0.17864990234375 +92878 0.182464599609375 +92879 0.1104736328125 +92880 0.06365966796875 +92881 0.038177490234375 +92882 -0.075958251953125 +92883 -0.046234130859375 +92884 -0.189422607421875 +92885 -0.11517333984375 +92886 -0.271942138671875 +92887 -0.165679931640625 +92888 -0.342529296875 +92889 -0.208770751953125 +92890 -0.364166259765625 +92891 -0.222747802734375 +92892 -0.327239990234375 +92893 -0.201934814453125 +92894 -0.2769775390625 +92895 -0.1727294921875 +92896 -0.253692626953125 +92897 -0.15869140625 +92898 -0.24365234375 +92899 -0.15179443359375 +92900 -0.1983642578125 +92901 -0.123809814453125 +92902 -0.116241455078125 +92903 -0.07391357421875 +92904 -0.036834716796875 +92905 -0.025299072265625 +92906 0.034881591796875 +92907 0.018951416015625 +92908 0.09124755859375 +92909 0.05426025390625 +92910 0.10888671875 +92911 0.06683349609375 +92912 0.125518798828125 +92913 0.078582763671875 +92914 0.15771484375 +92915 0.099090576171875 +92916 0.17828369140625 +92917 0.11236572265625 +92918 0.17108154296875 +92919 0.108917236328125 +92920 0.129974365234375 +92921 0.08514404296875 +92922 0.082427978515625 +92923 0.057098388671875 +92924 0.027679443359375 +92925 0.024383544921875 +92926 -0.065643310546875 +92927 -0.03125 +92928 -0.15936279296875 +92929 -0.0870361328125 +92930 -0.21307373046875 +92931 -0.1197509765625 +92932 -0.234649658203125 +92933 -0.134552001953125 +92934 -0.2001953125 +92935 -0.1162109375 +92936 -0.119171142578125 +92937 -0.070037841796875 +92938 -0.024749755859375 +92939 -0.016021728515625 +92940 0.085784912109375 +92941 0.047943115234375 +92942 0.178131103515625 +92943 0.101043701171875 +92944 0.215576171875 +92945 0.1209716796875 +92946 0.211456298828125 +92947 0.116119384765625 +92948 0.17523193359375 +92949 0.09246826171875 +92950 0.128753662109375 +92951 0.06353759765625 +92952 0.1019287109375 +92953 0.0477294921875 +92954 0.0743408203125 +92955 0.032379150390625 +92956 0.04327392578125 +92957 0.01568603515625 +92958 0.038177490234375 +92959 0.015594482421875 +92960 0.076263427734375 +92961 0.042510986328125 +92962 0.14105224609375 +92963 0.086029052734375 +92964 0.186431884765625 +92965 0.1175537109375 +92966 0.188812255859375 +92967 0.122344970703125 +92968 0.1390380859375 +92969 0.094573974609375 +92970 0.041778564453125 +92971 0.0369873046875 +92972 -0.079437255859375 +92973 -0.0360107421875 +92974 -0.219390869140625 +92975 -0.121307373046875 +92976 -0.367828369140625 +92977 -0.21258544921875 +92978 -0.494873046875 +92979 -0.291473388671875 +92980 -0.556243896484375 +92981 -0.330596923828125 +92982 -0.508697509765625 +92983 -0.30322265625 +92984 -0.3756103515625 +92985 -0.223663330078125 +92986 -0.218902587890625 +92987 -0.129913330078125 +92988 -0.063751220703125 +92989 -0.03729248046875 +92990 0.091552734375 +92991 0.055389404296875 +92992 0.23602294921875 +92993 0.14154052734375 +92994 0.342987060546875 +92995 0.204864501953125 +92996 0.39520263671875 +92997 0.234893798828125 +92998 0.389373779296875 +92999 0.229705810546875 +93000 0.324249267578125 +93001 0.1885986328125 +93002 0.224090576171875 +93003 0.126556396484375 +93004 0.124267578125 +93005 0.06536865234375 +93006 0.037078857421875 +93007 0.012542724609375 +93008 -0.010101318359375 +93009 -0.015106201171875 +93010 -0.019439697265625 +93011 -0.019012451171875 +93012 -0.022796630859375 +93013 -0.018890380859375 +93014 -0.001556396484375 +93015 -0.00341796875 +93016 0.056304931640625 +93017 0.03466796875 +93018 0.106719970703125 +93019 0.068115234375 +93020 0.096893310546875 +93021 0.06427001953125 +93022 0.042694091796875 +93023 0.032806396484375 +93024 -0.018035888671875 +93025 -0.00311279296875 +93026 -0.07586669921875 +93027 -0.0377197265625 +93028 -0.11944580078125 +93029 -0.064056396484375 +93030 -0.15972900390625 +93031 -0.088897705078125 +93032 -0.202606201171875 +93033 -0.1158447265625 +93034 -0.24859619140625 +93035 -0.145172119140625 +93036 -0.30517578125 +93037 -0.181365966796875 +93038 -0.36212158203125 +93039 -0.218109130859375 +93040 -0.39141845703125 +93041 -0.238037109375 +93042 -0.35528564453125 +93043 -0.217742919921875 +93044 -0.249969482421875 +93045 -0.15484619140625 +93046 -0.092864990234375 +93047 -0.0599365234375 +93048 0.08905029296875 +93049 0.05047607421875 +93050 0.2352294921875 +93051 0.13916015625 +93052 0.318817138671875 +93053 0.18963623046875 +93054 0.358642578125 +93055 0.21356201171875 +93056 0.347747802734375 +93057 0.2066650390625 +93058 0.28564453125 +93059 0.16864013671875 +93060 0.223175048828125 +93061 0.13079833984375 +93062 0.196746826171875 +93063 0.115478515625 +93064 0.179840087890625 +93065 0.1063232421875 +93066 0.155548095703125 +93067 0.09283447265625 +93068 0.151214599609375 +93069 0.091766357421875 +93070 0.156951904296875 +93071 0.096923828125 +93072 0.13177490234375 +93073 0.08294677734375 +93074 0.100799560546875 +93075 0.06524658203125 +93076 0.087127685546875 +93077 0.058013916015625 +93078 0.05487060546875 +93079 0.039093017578125 +93080 -0.009002685546875 +93081 0.0003662109375 +93082 -0.10400390625 +93083 -0.057861328125 +93084 -0.229400634765625 +93085 -0.135162353515625 +93086 -0.35552978515625 +93087 -0.2132568359375 +93088 -0.441925048828125 +93089 -0.26715087890625 +93090 -0.473846435546875 +93091 -0.287750244140625 +93092 -0.464813232421875 +93093 -0.283294677734375 +93094 -0.419097900390625 +93095 -0.25634765625 +93096 -0.334320068359375 +93097 -0.20538330078125 +93098 -0.227935791015625 +93099 -0.141082763671875 +93100 -0.12347412109375 +93101 -0.077880859375 +93102 -0.02764892578125 +93103 -0.01983642578125 +93104 0.077667236328125 +93105 0.04425048828125 +93106 0.2132568359375 +93107 0.127197265625 +93108 0.38885498046875 +93109 0.23504638671875 +93110 0.582794189453125 +93111 0.35443115234375 +93112 0.734039306640625 +93113 0.447784423828125 +93114 0.800140380859375 +93115 0.4888916015625 +93116 0.7783203125 +93117 0.476043701171875 +93118 0.6651611328125 +93119 0.4071044921875 +93120 0.45965576171875 +93121 0.281402587890625 +93122 0.199188232421875 +93123 0.1219482421875 +93124 -0.050689697265625 +93125 -0.030975341796875 +93126 -0.23297119140625 +93127 -0.14227294921875 +93128 -0.33013916015625 +93129 -0.20123291015625 +93130 -0.368408203125 +93131 -0.224029541015625 +93132 -0.378936767578125 +93133 -0.229888916015625 +93134 -0.376983642578125 +93135 -0.228271484375 +93136 -0.37969970703125 +93137 -0.229766845703125 +93138 -0.391510009765625 +93139 -0.237091064453125 +93140 -0.385345458984375 +93141 -0.23358154296875 +93142 -0.3419189453125 +93143 -0.20733642578125 +93144 -0.28289794921875 +93145 -0.171630859375 +93146 -0.251617431640625 +93147 -0.153106689453125 +93148 -0.266143798828125 +93149 -0.162841796875 +93150 -0.273345947265625 +93151 -0.168121337890625 +93152 -0.216796875 +93153 -0.13409423828125 +93154 -0.128265380859375 +93155 -0.080291748046875 +93156 -0.068145751953125 +93157 -0.04388427734375 +93158 -0.0430908203125 +93159 -0.028900146484375 +93160 -0.024444580078125 +93161 -0.0177001953125 +93162 0.020721435546875 +93163 0.009979248046875 +93164 0.124481201171875 +93165 0.07391357421875 +93166 0.25787353515625 +93167 0.15625 +93168 0.379119873046875 +93169 0.231201171875 +93170 0.47991943359375 +93171 0.293670654296875 +93172 0.5281982421875 +93173 0.3238525390625 +93174 0.511138916015625 +93175 0.313873291015625 +93176 0.456207275390625 +93177 0.280609130859375 +93178 0.407470703125 +93179 0.251190185546875 +93180 0.383758544921875 +93181 0.237152099609375 +93182 0.35687255859375 +93183 0.221099853515625 +93184 0.31182861328125 +93185 0.19427490234375 +93186 0.250885009765625 +93187 0.158355712890625 +93188 0.1654052734375 +93189 0.10736083984375 +93190 0.035247802734375 +93191 0.02777099609375 +93192 -0.142059326171875 +93193 -0.08245849609375 +93194 -0.33563232421875 +93195 -0.203704833984375 +93196 -0.5345458984375 +93197 -0.329193115234375 +93198 -0.72186279296875 +93199 -0.448211669921875 +93200 -0.836669921875 +93201 -0.52142333984375 +93202 -0.8326416015625 +93203 -0.51885986328125 +93204 -0.7296142578125 +93205 -0.453369140625 +93206 -0.582550048828125 +93207 -0.360443115234375 +93208 -0.440093994140625 +93209 -0.27142333984375 +93210 -0.324310302734375 +93211 -0.200439453125 +93212 -0.20147705078125 +93213 -0.125335693359375 +93214 -0.044647216796875 +93215 -0.02838134765625 +93216 0.103973388671875 +93217 0.063323974609375 +93218 0.202392578125 +93219 0.122833251953125 +93220 0.264495849609375 +93221 0.15936279296875 +93222 0.338897705078125 +93223 0.204620361328125 +93224 0.443817138671875 +93225 0.27056884765625 +93226 0.545074462890625 +93227 0.335113525390625 +93228 0.6173095703125 +93229 0.381866455078125 +93230 0.6524658203125 +93231 0.405609130859375 +93232 0.66339111328125 +93233 0.414581298828125 +93234 0.6561279296875 +93235 0.41253662109375 +93236 0.606781005859375 +93237 0.383819580078125 +93238 0.501190185546875 +93239 0.319061279296875 +93240 0.352783203125 +93241 0.22674560546875 +93242 0.176544189453125 +93243 0.11639404296875 +93244 -0.034820556640625 +93245 -0.01690673828125 +93246 -0.258209228515625 +93247 -0.15838623046875 +93248 -0.44244384765625 +93249 -0.275054931640625 +93250 -0.5753173828125 +93251 -0.359130859375 +93252 -0.65203857421875 +93253 -0.4075927734375 +93254 -0.641632080078125 +93255 -0.40045166015625 +93256 -0.562164306640625 +93257 -0.34942626953125 +93258 -0.458038330078125 +93259 -0.283233642578125 +93260 -0.350555419921875 +93261 -0.215545654296875 +93262 -0.260528564453125 +93263 -0.15972900390625 +93264 -0.192108154296875 +93265 -0.118316650390625 +93266 -0.141937255859375 +93267 -0.088958740234375 +93268 -0.1021728515625 +93269 -0.06640625 +93270 -0.062896728515625 +93271 -0.0440673828125 +93272 -0.011932373046875 +93273 -0.01385498046875 +93274 0.062835693359375 +93275 0.032196044921875 +93276 0.148712158203125 +93277 0.08599853515625 +93278 0.241729736328125 +93279 0.14501953125 +93280 0.34912109375 +93281 0.214019775390625 +93282 0.457305908203125 +93283 0.28424072265625 +93284 0.54388427734375 +93285 0.341094970703125 +93286 0.5728759765625 +93287 0.36126708984375 +93288 0.506591796875 +93289 0.3201904296875 +93290 0.351226806640625 +93291 0.221771240234375 +93292 0.146514892578125 +93293 0.091644287109375 +93294 -0.05523681640625 +93295 -0.03643798828125 +93296 -0.21624755859375 +93297 -0.138153076171875 +93298 -0.334930419921875 +93299 -0.21258544921875 +93300 -0.402984619140625 +93301 -0.2545166015625 +93302 -0.4412841796875 +93303 -0.277557373046875 +93304 -0.49578857421875 +93305 -0.31158447265625 +93306 -0.5601806640625 +93307 -0.352569580078125 +93308 -0.600738525390625 +93309 -0.378662109375 +93310 -0.584228515625 +93311 -0.36834716796875 +93312 -0.47930908203125 +93313 -0.301300048828125 +93314 -0.27935791015625 +93315 -0.17315673828125 +93316 -0.0089111328125 +93317 0.000244140625 +93318 0.268798828125 +93319 0.17803955078125 +93320 0.482818603515625 +93321 0.314422607421875 +93322 0.60369873046875 +93323 0.39044189453125 +93324 0.650421142578125 +93325 0.418487548828125 +93326 0.66400146484375 +93327 0.42529296875 +93328 0.6414794921875 +93329 0.409027099609375 +93330 0.572540283203125 +93331 0.36309814453125 +93332 0.498138427734375 +93333 0.3140869140625 +93334 0.439453125 +93335 0.2757568359375 +93336 0.375518798828125 +93337 0.234527587890625 +93338 0.274505615234375 +93339 0.16973876953125 +93340 0.1087646484375 +93341 0.06341552734375 +93342 -0.099395751953125 +93343 -0.070037841796875 +93344 -0.3182373046875 +93345 -0.210113525390625 +93346 -0.5489501953125 +93347 -0.35772705078125 +93348 -0.7738037109375 +93349 -0.50146484375 +93350 -0.86383056640625 +93351 -0.60711669921875 +93352 -0.870391845703125 +93353 -0.65325927734375 +93354 -0.86895751953125 +93355 -0.651458740234375 +93356 -0.861053466796875 +93357 -0.610321044921875 +93358 -0.765869140625 +93359 -0.5186767578125 +93360 -0.5301513671875 +93361 -0.369232177734375 +93362 -0.214691162109375 +93363 -0.1666259765625 +93364 0.137359619140625 +93365 0.061248779296875 +93366 0.474822998046875 +93367 0.281158447265625 +93368 0.76239013671875 +93369 0.47015380859375 +93370 0.867462158203125 +93371 0.610809326171875 +93372 0.870361328125 +93373 0.703460693359375 +93374 0.86480712890625 +93375 0.74072265625 +93376 0.831817626953125 +93377 0.726165771484375 +93378 0.677581787109375 +93379 0.6756591796875 +93380 0.495880126953125 +93381 0.593048095703125 +93382 0.30767822265625 +93383 0.490386962890625 +93384 0.116180419921875 +93385 0.36920166015625 +93386 -0.110748291015625 +93387 0.208953857421875 +93388 -0.381805419921875 +93389 0.005157470703125 +93390 -0.6572265625 +93391 -0.21441650390625 +93392 -0.857421875 +93393 -0.410980224609375 +93394 -0.870391845703125 +93395 -0.556732177734375 +93396 -0.870391845703125 +93397 -0.647064208984375 +93398 -0.86444091796875 +93399 -0.699493408203125 +93400 -0.85723876953125 +93401 -0.737213134765625 +93402 -0.790008544921875 +93403 -0.748382568359375 +93404 -0.62847900390625 +93405 -0.697906494140625 +93406 -0.3956298828125 +93407 -0.583770751953125 +93408 -0.126708984375 +93409 -0.4273681640625 +93410 0.150115966796875 +93411 -0.2464599609375 +93412 0.424041748046875 +93413 -0.0487060546875 +93414 0.670623779296875 +93415 0.14837646484375 +93416 0.854522705078125 +93417 0.319671630859375 +93418 0.866485595703125 +93419 0.453704833984375 +93420 0.86920166015625 +93421 0.54052734375 +93422 0.8653564453125 +93423 0.591888427734375 +93424 0.857147216796875 +93425 0.61651611328125 +93426 0.766845703125 +93427 0.612548828125 +93428 0.628509521484375 +93429 0.5833740234375 +93430 0.462127685546875 +93431 0.524658203125 +93432 0.297210693359375 +93433 0.45318603515625 +93434 0.14862060546875 +93435 0.377044677734375 +93436 -0.00537109375 +93437 0.281494140625 +93438 -0.15753173828125 +93439 0.171478271484375 +93440 -0.31304931640625 +93441 0.04425048828125 +93442 -0.48876953125 +93443 -0.10931396484375 +93444 -0.6416015625 +93445 -0.25750732421875 +93446 -0.751373291015625 +93447 -0.384246826171875 +93448 -0.84619140625 +93449 -0.505889892578125 +93450 -0.861297607421875 +93451 -0.6129150390625 +93452 -0.863250732421875 +93453 -0.683197021484375 +93454 -0.856597900390625 +93455 -0.69549560546875 +93456 -0.7498779296875 +93457 -0.658172607421875 +93458 -0.624542236328125 +93459 -0.61053466796875 +93460 -0.47808837890625 +93461 -0.5374755859375 +93462 -0.253387451171875 +93463 -0.39898681640625 +93464 0.003692626953125 +93465 -0.225799560546875 +93466 0.2257080078125 +93467 -0.064056396484375 +93468 0.427154541015625 +93469 0.09515380859375 +93470 0.643218994140625 +93471 0.27423095703125 +93472 0.855926513671875 +93473 0.467010498046875 +93474 0.870361328125 +93475 0.6343994140625 +93476 0.870361328125 +93477 0.742919921875 +93478 0.862762451171875 +93479 0.797637939453125 +93480 0.79669189453125 +93481 0.796661376953125 +93482 0.595794677734375 +93483 0.733612060546875 +93484 0.362152099609375 +93485 0.6282958984375 +93486 0.1270751953125 +93487 0.499664306640625 +93488 -0.086944580078125 +93489 0.361907958984375 +93490 -0.2784423828125 +93491 0.216278076171875 +93492 -0.484832763671875 +93493 0.038848876953125 +93494 -0.729583740234375 +93495 -0.183685302734375 +93496 -0.86688232421875 +93497 -0.41717529296875 +93498 -0.870391845703125 +93499 -0.618804931640625 +93500 -0.86859130859375 +93501 -0.785430908203125 +93502 -0.86279296875 +93503 -0.8612060546875 +93504 -0.817962646484375 +93505 -0.868804931640625 +93506 -0.6116943359375 +93507 -0.866455078125 +93508 -0.3128662109375 +93509 -0.84600830078125 +93510 0.039398193359375 +93511 -0.65478515625 +93512 0.422821044921875 +93513 -0.403778076171875 +93514 0.805145263671875 +93515 -0.11553955078125 +93516 0.870361328125 +93517 0.1636962890625 +93518 0.870361328125 +93519 0.395294189453125 +93520 0.860015869140625 +93521 0.57135009765625 +93522 0.727935791015625 +93523 0.68670654296875 +93524 0.48114013671875 +93525 0.737579345703125 +93526 0.2059326171875 +93527 0.740478515625 +93528 -0.06103515625 +93529 0.710784912109375 +93530 -0.29913330078125 +93531 0.65533447265625 +93532 -0.516204833984375 +93533 0.56427001953125 +93534 -0.7252197265625 +93535 0.42718505859375 +93536 -0.85980224609375 +93537 0.26104736328125 +93538 -0.870391845703125 +93539 0.08929443359375 +93540 -0.870391845703125 +93541 -0.06781005859375 +93542 -0.858062744140625 +93543 -0.176971435546875 +93544 -0.673004150390625 +93545 -0.23516845703125 +93546 -0.42694091796875 +93547 -0.27789306640625 +93548 -0.2100830078125 +93549 -0.33514404296875 +93550 -0.0362548828125 +93551 -0.405303955078125 +93552 0.10943603515625 +93553 -0.468414306640625 +93554 0.23516845703125 +93555 -0.51080322265625 +93556 0.373687744140625 +93557 -0.504241943359375 +93558 0.517791748046875 +93559 -0.45001220703125 +93560 0.602783203125 +93561 -0.390960693359375 +93562 0.635711669921875 +93563 -0.32366943359375 +93564 0.655181884765625 +93565 -0.2255859375 +93566 0.65948486328125 +93567 -0.103668212890625 +93568 0.651275634765625 +93569 0.036376953125 +93570 0.61846923828125 +93571 0.177642822265625 +93572 0.53753662109375 +93573 0.29473876953125 +93574 0.404144287109375 +93575 0.375091552734375 +93576 0.22186279296875 +93577 0.41180419921875 +93578 0.003997802734375 +93579 0.405487060546875 +93580 -0.22100830078125 +93581 0.368255615234375 +93582 -0.42449951171875 +93583 0.314056396484375 +93584 -0.579833984375 +93585 0.25732421875 +93586 -0.641876220703125 +93587 0.227081298828125 +93588 -0.6177978515625 +93589 0.2188720703125 +93590 -0.575531005859375 +93591 0.188873291015625 +93592 -0.526336669921875 +93593 0.13360595703125 +93594 -0.42645263671875 +93595 0.088531494140625 +93596 -0.2581787109375 +93597 0.07257080078125 +93598 -0.068695068359375 +93599 0.061248779296875 +93600 0.09222412109375 +93601 0.028656005859375 +93602 0.232147216796875 +93603 -0.012237548828125 +93604 0.3509521484375 +93605 -0.05426025390625 +93606 0.410064697265625 +93607 -0.117340087890625 +93608 0.372955322265625 +93609 -0.22125244140625 +93610 0.2554931640625 +93611 -0.35162353515625 +93612 0.10711669921875 +93613 -0.472900390625 +93614 -0.052886962890625 +93615 -0.571746826171875 +93616 -0.186279296875 +93617 -0.62353515625 +93618 -0.23291015625 +93619 -0.590362548828125 +93620 -0.209442138671875 +93621 -0.48785400390625 +93622 -0.174163818359375 +93623 -0.3609619140625 +93624 -0.126739501953125 +93625 -0.215545654296875 +93626 -0.048126220703125 +93627 -0.04510498046875 +93628 0.0426025390625 +93629 0.130889892578125 +93630 0.10748291015625 +93631 0.280487060546875 +93632 0.1409912109375 +93633 0.3944091796875 +93634 0.19708251953125 +93635 0.5047607421875 +93636 0.273651123046875 +93637 0.60675048828125 +93638 0.31768798828125 +93639 0.662261962890625 +93640 0.341094970703125 +93641 0.678680419921875 +93642 0.368011474609375 +93643 0.673126220703125 +93644 0.37249755859375 +93645 0.62994384765625 +93646 0.30072021484375 +93647 0.51568603515625 +93648 0.1517333984375 +93649 0.333831787109375 +93650 -0.01470947265625 +93651 0.12982177734375 +93652 -0.1883544921875 +93653 -0.0841064453125 +93654 -0.372711181640625 +93655 -0.304962158203125 +93656 -0.51397705078125 +93657 -0.490966796875 +93658 -0.57177734375 +93659 -0.609893798828125 +93660 -0.53948974609375 +93661 -0.6531982421875 +93662 -0.43511962890625 +93663 -0.6300048828125 +93664 -0.2962646484375 +93665 -0.56378173828125 +93666 -0.161102294921875 +93667 -0.4794921875 +93668 -0.0435791015625 +93669 -0.38677978515625 +93670 0.060394287109375 +93671 -0.2841796875 +93672 0.13665771484375 +93673 -0.18359375 +93674 0.170135498046875 +93675 -0.098388671875 +93676 0.16552734375 +93677 -0.0291748046875 +93678 0.15728759765625 +93679 0.043182373046875 +93680 0.150787353515625 +93681 0.11798095703125 +93682 0.12200927734375 +93683 0.17449951171875 +93684 0.080108642578125 +93685 0.214935302734375 +93686 0.05126953125 +93687 0.253509521484375 +93688 0.062896728515625 +93689 0.3060302734375 +93690 0.09271240234375 +93691 0.35528564453125 +93692 0.092987060546875 +93693 0.367706298828125 +93694 0.07855224609375 +93695 0.353179931640625 +93696 0.06427001953125 +93697 0.322418212890625 +93698 0.0347900390625 +93699 0.2666015625 +93700 -0.01171875 +93701 0.18695068359375 +93702 -0.056060791015625 +93703 0.099700927734375 +93704 -0.055511474609375 +93705 0.0379638671875 +93706 -0.010467529296875 +93707 0.004974365234375 +93708 0.02508544921875 +93709 -0.033477783203125 +93710 0.025665283203125 +93711 -0.09185791015625 +93712 0.017333984375 +93713 -0.148834228515625 +93714 0.00189208984375 +93715 -0.200592041015625 +93716 -0.03173828125 +93717 -0.252960205078125 +93718 -0.071502685546875 +93719 -0.296295166015625 +93720 -0.13543701171875 +93721 -0.34271240234375 +93722 -0.219970703125 +93723 -0.390045166015625 +93724 -0.300506591796875 +93725 -0.42205810546875 +93726 -0.376312255859375 +93727 -0.43994140625 +93728 -0.416107177734375 +93729 -0.423980712890625 +93730 -0.371124267578125 +93731 -0.342681884765625 +93732 -0.242279052734375 +93733 -0.199554443359375 +93734 -0.069732666015625 +93735 -0.025726318359375 +93736 0.125640869140625 +93737 0.161285400390625 +93738 0.31268310546875 +93739 0.337005615234375 +93740 0.45501708984375 +93741 0.47369384765625 +93742 0.554779052734375 +93743 0.571044921875 +93744 0.61065673828125 +93745 0.626922607421875 +93746 0.610931396484375 +93747 0.632537841796875 +93748 0.531463623046875 +93749 0.571044921875 +93750 0.3883056640625 +93751 0.45428466796875 +93752 0.23468017578125 +93753 0.320709228515625 +93754 0.095245361328125 +93755 0.189300537109375 +93756 -0.00396728515625 +93757 0.080322265625 +93758 -0.04852294921875 +93759 0.00616455078125 +93760 -0.055145263671875 +93761 -0.042388916015625 +93762 -0.0758056640625 +93763 -0.09930419921875 +93764 -0.138702392578125 +93765 -0.182037353515625 +93766 -0.209197998046875 +93767 -0.26434326171875 +93768 -0.289031982421875 +93769 -0.345794677734375 +93770 -0.37884521484375 +93771 -0.4256591796875 +93772 -0.456329345703125 +93773 -0.48760986328125 +93774 -0.51641845703125 +93775 -0.527984619140625 +93776 -0.519287109375 +93777 -0.519256591796875 +93778 -0.458251953125 +93779 -0.45758056640625 +93780 -0.384796142578125 +93781 -0.38031005859375 +93782 -0.323699951171875 +93783 -0.306365966796875 +93784 -0.269287109375 +93785 -0.233642578125 +93786 -0.1951904296875 +93787 -0.14569091796875 +93788 -0.100006103515625 +93789 -0.04351806640625 +93790 -0.01055908203125 +93791 0.052154541015625 +93792 0.1033935546875 +93793 0.1607666015625 +93794 0.24908447265625 +93795 0.28594970703125 +93796 0.373199462890625 +93797 0.3892822265625 +93798 0.45806884765625 +93799 0.45770263671875 +93800 0.511474609375 +93801 0.496337890625 +93802 0.565399169921875 +93803 0.527740478515625 +93804 0.61138916015625 +93805 0.546600341796875 +93806 0.5897216796875 +93807 0.51202392578125 +93808 0.4906005859375 +93809 0.41839599609375 +93810 0.33148193359375 +93811 0.279388427734375 +93812 0.147796630859375 +93813 0.121368408203125 +93814 -0.01873779296875 +93815 -0.0247802734375 +93816 -0.140289306640625 +93817 -0.137939453125 +93818 -0.191986083984375 +93819 -0.19921875 +93820 -0.184295654296875 +93821 -0.214691162109375 +93822 -0.161834716796875 +93823 -0.21453857421875 +93824 -0.166595458984375 +93825 -0.227447509765625 +93826 -0.19390869140625 +93827 -0.24981689453125 +93828 -0.22442626953125 +93829 -0.268096923828125 +93830 -0.279754638671875 +93831 -0.29779052734375 +93832 -0.3389892578125 +93833 -0.32489013671875 +93834 -0.3543701171875 +93835 -0.31695556640625 +93836 -0.348175048828125 +93837 -0.290679931640625 +93838 -0.32598876953125 +93839 -0.25128173828125 +93840 -0.2581787109375 +93841 -0.17938232421875 +93842 -0.139801025390625 +93843 -0.072845458984375 +93844 0.014617919921875 +93845 0.056915283203125 +93846 0.144378662109375 +93847 0.166229248046875 +93848 0.221038818359375 +93849 0.23431396484375 +93850 0.27069091796875 +93851 0.27874755859375 +93852 0.294036865234375 +93853 0.29962158203125 +93854 0.311767578125 +93855 0.31134033203125 +93856 0.339141845703125 +93857 0.324798583984375 +93858 0.360260009765625 +93859 0.329437255859375 +93860 0.360504150390625 +93861 0.315704345703125 +93862 0.308380126953125 +93863 0.261962890625 +93864 0.18170166015625 +93865 0.153350830078125 +93866 0.0047607421875 +93867 0.00823974609375 +93868 -0.17559814453125 +93869 -0.138946533203125 +93870 -0.3143310546875 +93871 -0.25518798828125 +93872 -0.36785888671875 +93873 -0.308563232421875 +93874 -0.36248779296875 +93875 -0.317047119140625 +93876 -0.343536376953125 +93877 -0.31231689453125 +93878 -0.3018798828125 +93879 -0.287506103515625 +93880 -0.231414794921875 +93881 -0.23809814453125 +93882 -0.117645263671875 +93883 -0.153839111328125 +93884 0.007049560546875 +93885 -0.058074951171875 +93886 0.087982177734375 +93887 0.009735107421875 +93888 0.13946533203125 +93889 0.059173583984375 +93890 0.17425537109375 +93891 0.09857177734375 +93892 0.188201904296875 +93893 0.12408447265625 +93894 0.171234130859375 +93895 0.127685546875 +93896 0.118438720703125 +93897 0.105010986328125 +93898 0.05706787109375 +93899 0.074676513671875 +93900 -0.010711669921875 +93901 0.03753662109375 +93902 -0.0914306640625 +93903 -0.0115966796875 +93904 -0.162322998046875 +93905 -0.056884765625 +93906 -0.194549560546875 +93907 -0.0780029296875 +93908 -0.1492919921875 +93909 -0.04730224609375 +93910 -0.02166748046875 +93911 0.038848876953125 +93912 0.124053955078125 +93913 0.13507080078125 +93914 0.211151123046875 +93915 0.18719482421875 +93916 0.240447998046875 +93917 0.196441650390625 +93918 0.242218017578125 +93919 0.18505859375 +93920 0.2257080078125 +93921 0.160369873046875 +93922 0.194366455078125 +93923 0.125518798828125 +93924 0.115509033203125 +93925 0.057891845703125 +93926 0.0128173828125 +93927 -0.024993896484375 +93928 -0.053802490234375 +93929 -0.080047607421875 +93930 -0.110626220703125 +93931 -0.1256103515625 +93932 -0.199493408203125 +93933 -0.1912841796875 +93934 -0.29437255859375 +93935 -0.258453369140625 +93936 -0.33221435546875 +93937 -0.2823486328125 +93938 -0.27972412109375 +93939 -0.239532470703125 +93940 -0.185333251953125 +93941 -0.164825439453125 +93942 -0.128204345703125 +93943 -0.115081787109375 +93944 -0.115692138671875 +93945 -0.096038818359375 +93946 -0.116455078125 +93947 -0.085968017578125 +93948 -0.105926513671875 +93949 -0.0679931640625 +93950 -0.053955078125 +93951 -0.021209716796875 +93952 0.048797607421875 +93953 0.06072998046875 +93954 0.157318115234375 +93955 0.145050048828125 +93956 0.212005615234375 +93957 0.1878662109375 +93958 0.218475341796875 +93959 0.193328857421875 +93960 0.23724365234375 +93961 0.206451416015625 +93962 0.30535888671875 +93963 0.254913330078125 +93964 0.38128662109375 +93965 0.30792236328125 +93966 0.404449462890625 +93967 0.320587158203125 +93968 0.3944091796875 +93969 0.3077392578125 +93970 0.3885498046875 +93971 0.297454833984375 +93972 0.362640380859375 +93973 0.272064208984375 +93974 0.27362060546875 +93975 0.1998291015625 +93976 0.11712646484375 +93977 0.07781982421875 +93978 -0.054901123046875 +93979 -0.0550537109375 +93980 -0.19085693359375 +93981 -0.160125732421875 +93982 -0.28570556640625 +93983 -0.2335205078125 +93984 -0.339263916015625 +93985 -0.274993896484375 +93986 -0.3775634765625 +93987 -0.3038330078125 +93988 -0.445709228515625 +93989 -0.353607177734375 +93990 -0.535064697265625 +93991 -0.417999267578125 +93992 -0.629058837890625 +93993 -0.48480224609375 +93994 -0.697601318359375 +93995 -0.531829833984375 +93996 -0.70391845703125 +93997 -0.531951904296875 +93998 -0.6424560546875 +93999 -0.4813232421875 +94000 -0.491241455078125 +94001 -0.3638916015625 +94002 -0.265716552734375 +94003 -0.19140625 +94004 -0.023712158203125 +94005 -0.007110595703125 +94006 0.201751708984375 +94007 0.1641845703125 +94008 0.375823974609375 +94009 0.296356201171875 +94010 0.485076904296875 +94011 0.37933349609375 +94012 0.56884765625 +94013 0.442291259765625 +94014 0.634765625 +94015 0.49090576171875 +94016 0.63763427734375 +94017 0.491607666015625 +94018 0.5660400390625 +94019 0.436004638671875 +94020 0.4720458984375 +94021 0.36297607421875 +94022 0.40692138671875 +94023 0.31085205078125 +94024 0.3778076171875 +94025 0.285186767578125 +94026 0.376953125 +94027 0.280426025390625 +94028 0.371978759765625 +94029 0.272705078125 +94030 0.313140869140625 +94031 0.225250244140625 +94032 0.184417724609375 +94033 0.1263427734375 +94034 0.011199951171875 +94035 -0.004974365234375 +94036 -0.171051025390625 +94037 -0.1422119140625 +94038 -0.33740234375 +94039 -0.266754150390625 +94040 -0.47198486328125 +94041 -0.36676025390625 +94042 -0.560394287109375 +94043 -0.431549072265625 +94044 -0.58056640625 +94045 -0.444793701171875 +94046 -0.54754638671875 +94047 -0.417816162109375 +94048 -0.508575439453125 +94049 -0.385894775390625 +94050 -0.459503173828125 +94051 -0.34613037109375 +94052 -0.394378662109375 +94053 -0.294281005859375 +94054 -0.35260009765625 +94055 -0.259857177734375 +94056 -0.31170654296875 +94057 -0.226287841796875 +94058 -0.197418212890625 +94059 -0.13848876953125 +94060 -0.007965087890625 +94061 0.004669189453125 +94062 0.207489013671875 +94063 0.16650390625 +94064 0.409210205078125 +94065 0.3173828125 +94066 0.57208251953125 +94067 0.4385986328125 +94068 0.66595458984375 +94069 0.507781982421875 +94070 0.65875244140625 +94071 0.5010986328125 +94072 0.56744384765625 +94073 0.4312744140625 +94074 0.431396484375 +94075 0.327728271484375 +94076 0.29443359375 +94077 0.22320556640625 +94078 0.182464599609375 +94079 0.137115478515625 +94080 0.06365966796875 +94081 0.045928955078125 +94082 -0.075958251953125 +94083 -0.060577392578125 +94084 -0.189422607421875 +94085 -0.147308349609375 +94086 -0.271942138671875 +94087 -0.2105712890625 +94088 -0.342529296875 +94089 -0.264434814453125 +94090 -0.364166259765625 +94091 -0.281341552734375 +94092 -0.327239990234375 +94093 -0.25408935546875 +94094 -0.2769775390625 +94095 -0.21630859375 +94096 -0.253692626953125 +94097 -0.19805908203125 +94098 -0.24365234375 +94099 -0.189178466796875 +94100 -0.1983642578125 +94101 -0.1536865234375 +94102 -0.116241455078125 +94103 -0.09051513671875 +94104 -0.036834716796875 +94105 -0.0291748046875 +94106 0.034881591796875 +94107 0.026458740234375 +94108 0.09124755859375 +94109 0.070587158203125 +94110 0.10888671875 +94111 0.085723876953125 +94112 0.125518798828125 +94113 0.09979248046875 +94114 0.15771484375 +94115 0.125030517578125 +94116 0.17828369140625 +94117 0.141143798828125 +94118 0.17108154296875 +94119 0.1361083984375 +94120 0.129974365234375 +94121 0.105377197265625 +94122 0.082427978515625 +94123 0.069366455078125 +94124 0.027679443359375 +94125 0.027587890625 +94126 -0.065643310546875 +94127 -0.043243408203125 +94128 -0.15936279296875 +94129 -0.114593505859375 +94130 -0.21307373046875 +94131 -0.15631103515625 +94132 -0.234649658203125 +94133 -0.1741943359375 +94134 -0.2001953125 +94135 -0.150360107421875 +94136 -0.119171142578125 +94137 -0.09173583984375 +94138 -0.024749755859375 +94139 -0.02294921875 +94140 0.085784912109375 +94141 0.058135986328125 +94142 0.178131103515625 +94143 0.12603759765625 +94144 0.215576171875 +94145 0.153472900390625 +94146 0.211456298828125 +94147 0.150360107421875 +94148 0.17523193359375 +94149 0.123748779296875 +94150 0.128753662109375 +94151 0.08984375 +94152 0.1019287109375 +94153 0.07086181640625 +94154 0.0743408203125 +94155 0.051605224609375 +94156 0.04327392578125 +94157 0.0299072265625 +94158 0.038177490234375 +94159 0.027618408203125 +94160 0.076263427734375 +94161 0.057464599609375 +94162 0.14105224609375 +94163 0.107086181640625 +94164 0.186431884765625 +94165 0.142120361328125 +94166 0.188812255859375 +94167 0.144927978515625 +94168 0.1390380859375 +94169 0.108642578125 +94170 0.041778564453125 +94171 0.0367431640625 +94172 -0.079437255859375 +94173 -0.05328369140625 +94174 -0.219390869140625 +94175 -0.157562255859375 +94176 -0.367828369140625 +94177 -0.2684326171875 +94178 -0.494873046875 +94179 -0.3636474609375 +94180 -0.556243896484375 +94181 -0.41021728515625 +94182 -0.508697509765625 +94183 -0.37591552734375 +94184 -0.3756103515625 +94185 -0.278045654296875 +94186 -0.218902587890625 +94187 -0.162628173828125 +94188 -0.063751220703125 +94189 -0.04833984375 +94190 0.091552734375 +94191 0.06610107421875 +94192 0.23602294921875 +94193 0.172607421875 +94194 0.342987060546875 +94195 0.25140380859375 +94196 0.39520263671875 +94197 0.289703369140625 +94198 0.389373779296875 +94199 0.28509521484375 +94200 0.324249267578125 +94201 0.23663330078125 +94202 0.224090576171875 +94203 0.162353515625 +94204 0.124267578125 +94205 0.088531494140625 +94206 0.037078857421875 +94207 0.0242919921875 +94208 -0.010101318359375 +94209 -0.00958251953125 +94210 -0.019439697265625 +94211 -0.01495361328125 +94212 -0.022796630859375 +94213 -0.0162353515625 +94214 -0.001556396484375 +94215 0.00115966796875 +94216 0.056304931640625 +94217 0.046661376953125 +94218 0.106719970703125 +94219 0.086181640625 +94220 0.096893310546875 +94221 0.078826904296875 +94222 0.042694091796875 +94223 0.036956787109375 +94224 -0.018035888671875 +94225 -0.01007080078125 +94226 -0.07586669921875 +94227 -0.054931640625 +94228 -0.11944580078125 +94229 -0.088836669921875 +94230 -0.15972900390625 +94231 -0.12030029296875 +94232 -0.202606201171875 +94233 -0.15386962890625 +94234 -0.24859619140625 +94235 -0.18994140625 +94236 -0.30517578125 +94237 -0.234283447265625 +94238 -0.36212158203125 +94239 -0.27899169921875 +94240 -0.39141845703125 +94241 -0.302337646484375 +94242 -0.35528564453125 +94243 -0.274932861328125 +94244 -0.249969482421875 +94245 -0.19384765625 +94246 -0.092864990234375 +94247 -0.07257080078125 +94248 0.08905029296875 +94249 0.0679931640625 +94250 0.2352294921875 +94251 0.180877685546875 +94252 0.318817138671875 +94253 0.24530029296875 +94254 0.358642578125 +94255 0.27587890625 +94256 0.347747802734375 +94257 0.267242431640625 +94258 0.28564453125 +94259 0.219024658203125 +94260 0.223175048828125 +94261 0.170684814453125 +94262 0.196746826171875 +94263 0.150421142578125 +94264 0.179840087890625 +94265 0.137664794921875 +94266 0.155548095703125 +94267 0.119293212890625 +94268 0.151214599609375 +94269 0.116485595703125 +94270 0.156951904296875 +94271 0.121551513671875 +94272 0.13177490234375 +94273 0.10260009765625 +94274 0.100799560546875 +94275 0.0791015625 +94276 0.087127685546875 +94277 0.068939208984375 +94278 0.05487060546875 +94279 0.044281005859375 +94280 -0.009002685546875 +94281 -0.0050048828125 +94282 -0.10400390625 +94283 -0.07855224609375 +94284 -0.229400634765625 +94285 -0.175811767578125 +94286 -0.35552978515625 +94287 -0.27374267578125 +94288 -0.441925048828125 +94289 -0.3409423828125 +94290 -0.473846435546875 +94291 -0.365997314453125 +94292 -0.464813232421875 +94293 -0.359344482421875 +94294 -0.419097900390625 +94295 -0.32427978515625 +94296 -0.334320068359375 +94297 -0.2589111328125 +94298 -0.227935791015625 +94299 -0.1767578125 +94300 -0.12347412109375 +94301 -0.0960693359375 +94302 -0.02764892578125 +94303 -0.022064208984375 +94304 0.077667236328125 +94305 0.059356689453125 +94306 0.2132568359375 +94307 0.164337158203125 +94308 0.38885498046875 +94309 0.3004150390625 +94310 0.582794189453125 +94311 0.4508056640625 +94312 0.734039306640625 +94313 0.568115234375 +94314 0.800140380859375 +94315 0.61944580078125 +94316 0.7783203125 +94317 0.60260009765625 +94318 0.6651611328125 +94319 0.51495361328125 +94320 0.45965576171875 +94321 0.355712890625 +94322 0.199188232421875 +94323 0.15386962890625 +94324 -0.050689697265625 +94325 -0.039703369140625 +94326 -0.23297119140625 +94327 -0.180816650390625 +94328 -0.33013916015625 +94329 -0.255889892578125 +94330 -0.368408203125 +94331 -0.2852783203125 +94332 -0.378936767578125 +94333 -0.293182373046875 +94334 -0.376983642578125 +94335 -0.291473388671875 +94336 -0.37969970703125 +94337 -0.29345703125 +94338 -0.391510009765625 +94339 -0.30255126953125 +94340 -0.385345458984375 +94341 -0.297760009765625 +94342 -0.3419189453125 +94343 -0.264129638671875 +94344 -0.28289794921875 +94345 -0.218475341796875 +94346 -0.251617431640625 +94347 -0.19439697265625 +94348 -0.266143798828125 +94349 -0.205902099609375 +94350 -0.273345947265625 +94351 -0.211761474609375 +94352 -0.216796875 +94353 -0.16815185546875 +94354 -0.128265380859375 +94355 -0.099700927734375 +94356 -0.068145751953125 +94357 -0.053253173828125 +94358 -0.0430908203125 +94359 -0.033966064453125 +94360 -0.024444580078125 +94361 -0.019622802734375 +94362 0.020721435546875 +94363 0.015350341796875 +94364 0.124481201171875 +94365 0.095855712890625 +94366 0.25787353515625 +94367 0.199371337890625 +94368 0.379119873046875 +94369 0.293487548828125 +94370 0.47991943359375 +94371 0.371795654296875 +94372 0.5281982421875 +94373 0.40936279296875 +94374 0.511138916015625 +94375 0.396240234375 +94376 0.456207275390625 +94377 0.353729248046875 +94378 0.407470703125 +94379 0.3160400390625 +94380 0.383758544921875 +94381 0.29779052734375 +94382 0.35687255859375 +94383 0.277069091796875 +94384 0.31182861328125 +94385 0.24224853515625 +94386 0.250885009765625 +94387 0.195037841796875 +94388 0.1654052734375 +94389 0.128753662109375 +94390 0.035247802734375 +94391 0.02777099609375 +94392 -0.142059326171875 +94393 -0.109832763671875 +94394 -0.33563232421875 +94395 -0.26007080078125 +94396 -0.5345458984375 +94397 -0.414459228515625 +94398 -0.72186279296875 +94399 -0.559814453125 +94400 -0.836669921875 +94401 -0.64892578125 +94402 -0.8326416015625 +94403 -0.64581298828125 +94404 -0.7296142578125 +94405 -0.56591796875 +94406 -0.582550048828125 +94407 -0.451873779296875 +94408 -0.440093994140625 +94409 -0.341400146484375 +94410 -0.324310302734375 +94411 -0.251617431640625 +94412 -0.20147705078125 +94413 -0.1563720703125 +94414 -0.044647216796875 +94415 -0.03472900390625 +94416 0.103973388671875 +94417 0.08056640625 +94418 0.202392578125 +94419 0.15692138671875 +94420 0.264495849609375 +94421 0.205078125 +94422 0.338897705078125 +94423 0.2628173828125 +94424 0.443817138671875 +94425 0.34423828125 +94426 0.545074462890625 +94427 0.422821044921875 +94428 0.6173095703125 +94429 0.478851318359375 +94430 0.6524658203125 +94431 0.506103515625 +94432 0.66339111328125 +94433 0.514556884765625 +94434 0.6561279296875 +94435 0.5089111328125 +94436 0.606781005859375 +94437 0.470611572265625 +94438 0.501190185546875 +94439 0.388671875 +94440 0.352783203125 +94441 0.273529052734375 +94442 0.176544189453125 +94443 0.13677978515625 +94444 -0.034820556640625 +94445 -0.027191162109375 +94446 -0.258209228515625 +94447 -0.200439453125 +94448 -0.44244384765625 +94449 -0.343292236328125 +94450 -0.5753173828125 +94451 -0.446258544921875 +94452 -0.65203857421875 +94453 -0.505645751953125 +94454 -0.641632080078125 +94455 -0.4974365234375 +94456 -0.562164306640625 +94457 -0.4356689453125 +94458 -0.458038330078125 +94459 -0.35479736328125 +94460 -0.350555419921875 +94461 -0.271331787109375 +94462 -0.260528564453125 +94463 -0.201446533203125 +94464 -0.192108154296875 +94465 -0.1485595703125 +94466 -0.141937255859375 +94467 -0.110107421875 +94468 -0.1021728515625 +94469 -0.0797119140625 +94470 -0.062896728515625 +94471 -0.049530029296875 +94472 -0.011932373046875 +94473 -0.00982666015625 +94474 0.062835693359375 +94475 0.049102783203125 +94476 0.148712158203125 +94477 0.11700439453125 +94478 0.241729736328125 +94479 0.190704345703125 +94480 0.34912109375 +94481 0.276123046875 +94482 0.457305908203125 +94483 0.362396240234375 +94484 0.54388427734375 +94485 0.431488037109375 +94486 0.5728759765625 +94487 0.45440673828125 +94488 0.506591796875 +94489 0.400726318359375 +94490 0.351226806640625 +94491 0.275482177734375 +94492 0.146514892578125 +94493 0.110748291015625 +94494 -0.05523681640625 +94495 -0.051239013671875 +94496 -0.21624755859375 +94497 -0.17999267578125 +94498 -0.334930419921875 +94499 -0.2742919921875 +94500 -0.402984619140625 +94501 -0.3275146484375 +94502 -0.4412841796875 +94503 -0.35662841796875 +94504 -0.49578857421875 +94505 -0.39886474609375 +94506 -0.5601806640625 +94507 -0.449188232421875 +94508 -0.600738525390625 +94509 -0.480499267578125 +94510 -0.584228515625 +94511 -0.46600341796875 +94512 -0.47930908203125 +94513 -0.380401611328125 +94514 -0.27935791015625 +94515 -0.218414306640625 +94516 -0.0089111328125 +94517 9.1552734375e-05 +94518 0.268798828125 +94519 0.22406005859375 +94520 0.482818603515625 +94521 0.396209716796875 +94522 0.60369873046875 +94523 0.4927978515625 +94524 0.650421142578125 +94525 0.529205322265625 +94526 0.66400146484375 +94527 0.5386962890625 +94528 0.6414794921875 +94529 0.5189208984375 +94530 0.572540283203125 +94531 0.461669921875 +94532 0.498138427734375 +94533 0.40008544921875 +94534 0.439453125 +94535 0.351348876953125 +94536 0.375518798828125 +94537 0.298614501953125 +94538 0.274505615234375 +94539 0.2161865234375 +94540 0.1087646484375 +94541 0.081787109375 +94542 -0.099395751953125 +94543 -0.0865478515625 +94544 -0.3182373046875 +94545 -0.26312255859375 +94546 -0.5489501953125 +94547 -0.448974609375 +94548 -0.7738037109375 +94549 -0.62982177734375 +94550 -0.86383056640625 +94551 -0.762908935546875 +94552 -0.870391845703125 +94553 -0.8214111328125 +94554 -0.86895751953125 +94555 -0.819732666015625 +94556 -0.861053466796875 +94557 -0.7685546875 +94558 -0.765869140625 +94559 -0.65399169921875 +94560 -0.5301513671875 +94561 -0.46697998046875 +94562 -0.214691162109375 +94563 -0.213348388671875 +94564 0.137359619140625 +94565 0.07208251953125 +94566 0.474822998046875 +94567 0.3477783203125 +94568 0.76239013671875 +94569 0.584991455078125 +94570 0.867462158203125 +94571 0.761932373046875 +94572 0.870361328125 +94573 0.857147216796875 +94574 0.86480712890625 +94575 0.86236572265625 +94576 0.831817626953125 +94577 0.860504150390625 +94578 0.677581787109375 +94579 0.847625732421875 +94580 0.495880126953125 +94581 0.745147705078125 +94582 0.30767822265625 +94583 0.61737060546875 +94584 0.116180419921875 +94585 0.466156005859375 +94586 -0.110748291015625 +94587 0.26593017578125 +94588 -0.381805419921875 +94589 0.011138916015625 +94590 -0.6572265625 +94591 -0.263580322265625 +94592 -0.857421875 +94593 -0.509765625 +94594 -0.870391845703125 +94595 -0.692718505859375 +94596 -0.870391845703125 +94597 -0.806640625 +94598 -0.86444091796875 +94599 -0.8565673828125 +94600 -0.85723876953125 +94601 -0.86181640625 +94602 -0.790008544921875 +94603 -0.863433837890625 +94604 -0.62847900390625 +94605 -0.856658935546875 +94606 -0.3956298828125 +94607 -0.732574462890625 +94608 -0.126708984375 +94609 -0.537872314453125 +94610 0.150115966796875 +94611 -0.312347412109375 +94612 0.424041748046875 +94613 -0.0655517578125 +94614 0.670623779296875 +94615 0.1806640625 +94616 0.854522705078125 +94617 0.394927978515625 +94618 0.866485595703125 +94619 0.562896728515625 +94620 0.86920166015625 +94621 0.672088623046875 +94622 0.8653564453125 +94623 0.737152099609375 +94624 0.857147216796875 +94625 0.7689208984375 +94626 0.766845703125 +94627 0.7650146484375 +94628 0.628509521484375 +94629 0.729583740234375 +94630 0.462127685546875 +94631 0.657196044921875 +94632 0.297210693359375 +94633 0.5687255859375 +94634 0.14862060546875 +94635 0.474212646484375 +94636 -0.00537109375 +94637 0.35528564453125 +94638 -0.15753173828125 +94639 0.218048095703125 +94640 -0.31304931640625 +94641 0.059661865234375 +94642 -0.48876953125 +94643 -0.13116455078125 +94644 -0.6416015625 +94645 -0.316436767578125 +94646 -0.751373291015625 +94647 -0.47613525390625 +94648 -0.84619140625 +94649 -0.62884521484375 +94650 -0.861297607421875 +94651 -0.76263427734375 +94652 -0.863250732421875 +94653 -0.850677490234375 +94654 -0.856597900390625 +94655 -0.855926513671875 +94656 -0.7498779296875 +94657 -0.8228759765625 +94658 -0.624542236328125 +94659 -0.76361083984375 +94660 -0.47808837890625 +94661 -0.671966552734375 +94662 -0.253387451171875 +94663 -0.500732421875 +94664 0.003692626953125 +94665 -0.286865234375 +94666 0.2257080078125 +94667 -0.085662841796875 +94668 0.427154541015625 +94669 0.112884521484375 +94670 0.643218994140625 +94671 0.334869384765625 +94672 0.855926513671875 +94673 0.572418212890625 +94674 0.870361328125 +94675 0.778656005859375 +94676 0.870361328125 +94677 0.86090087890625 +94678 0.862762451171875 +94679 0.868438720703125 +94680 0.79669189453125 +94681 0.8685302734375 +94682 0.595794677734375 +94683 0.860321044921875 +94684 0.362152099609375 +94685 0.780853271484375 +94686 0.1270751953125 +94687 0.624053955078125 +94688 -0.086944580078125 +94689 0.45489501953125 +94690 -0.2784423828125 +94691 0.275177001953125 +94692 -0.484832763671875 +94693 0.056854248046875 +94694 -0.729583740234375 +94695 -0.215423583984375 +94696 -0.86688232421875 +94697 -0.500640869140625 +94698 -0.870391845703125 +94699 -0.747528076171875 +94700 -0.86859130859375 +94701 -0.865142822265625 +94702 -0.86279296875 +94703 -0.870391845703125 +94704 -0.817962646484375 +94705 -0.868621826171875 +94706 -0.6116943359375 +94707 -0.8564453125 +94708 -0.3128662109375 +94709 -0.663543701171875 +94710 0.039398193359375 +94711 -0.38836669921875 +94712 0.422821044921875 +94713 -0.064788818359375 +94714 0.805145263671875 +94715 0.279632568359375 +94716 0.870361328125 +94717 0.590606689453125 +94718 0.870361328125 +94719 0.823974609375 +94720 0.860015869140625 +94721 0.867462158203125 +94722 0.727935791015625 +94723 0.870361328125 +94724 0.48114013671875 +94725 0.86407470703125 +94726 0.2059326171875 +94727 0.827606201171875 +94728 -0.06103515625 +94729 0.6807861328125 +94730 -0.29913330078125 +94731 0.516021728515625 +94732 -0.516204833984375 +94733 0.325958251953125 +94734 -0.7252197265625 +94735 0.10137939453125 +94736 -0.85980224609375 +94737 -0.134368896484375 +94738 -0.870391845703125 +94739 -0.351348876953125 +94740 -0.870391845703125 +94741 -0.525054931640625 +94742 -0.858062744140625 +94743 -0.6162109375 +94744 -0.673004150390625 +94745 -0.624114990234375 +94746 -0.42694091796875 +94747 -0.596649169921875 +94748 -0.2100830078125 +94749 -0.575653076171875 +94750 -0.0362548828125 +94751 -0.564422607421875 +94752 0.10943603515625 +94753 -0.54388427734375 +94754 0.23516845703125 +94755 -0.50250244140625 +94756 0.373687744140625 +94757 -0.410369873046875 +94758 0.517791748046875 +94759 -0.273345947265625 +94760 0.602783203125 +94761 -0.147796630859375 +94762 0.635711669921875 +94763 -0.031829833984375 +94764 0.655181884765625 +94765 0.10113525390625 +94766 0.65948486328125 +94767 0.242462158203125 +94768 0.651275634765625 +94769 0.38629150390625 +94770 0.61846923828125 +94771 0.51385498046875 +94772 0.53753662109375 +94773 0.596832275390625 +94774 0.404144287109375 +94775 0.623504638671875 +94776 0.22186279296875 +94777 0.58966064453125 +94778 0.003997802734375 +94779 0.500518798828125 +94780 -0.22100830078125 +94781 0.375579833984375 +94782 -0.42449951171875 +94783 0.23626708984375 +94784 -0.579833984375 +94785 0.104156494140625 +94786 -0.641876220703125 +94787 0.0181884765625 +94788 -0.6177978515625 +94789 -0.024810791015625 +94790 -0.575531005859375 +94791 -0.07763671875 +94792 -0.526336669921875 +94793 -0.14422607421875 +94794 -0.42645263671875 +94795 -0.181396484375 +94796 -0.2581787109375 +94797 -0.167266845703125 +94798 -0.068695068359375 +94799 -0.13433837890625 +94800 0.09222412109375 +94801 -0.1175537109375 +94802 0.232147216796875 +94803 -0.104339599609375 +94804 0.3509521484375 +94805 -0.089508056640625 +94806 0.410064697265625 +94807 -0.101409912109375 +94808 0.372955322265625 +94809 -0.16802978515625 +94810 0.2554931640625 +94811 -0.27484130859375 +94812 0.10711669921875 +94813 -0.380706787109375 +94814 -0.052886962890625 +94815 -0.471221923828125 +94816 -0.186279296875 +94817 -0.517333984375 +94818 -0.23291015625 +94819 -0.4727783203125 +94820 -0.209442138671875 +94821 -0.356658935546875 +94822 -0.174163818359375 +94823 -0.223541259765625 +94824 -0.126739501953125 +94825 -0.0789794921875 +94826 -0.048126220703125 +94827 0.087249755859375 +94828 0.0426025390625 +94829 0.253814697265625 +94830 0.10748291015625 +94831 0.384185791015625 +94832 0.1409912109375 +94833 0.470001220703125 +94834 0.19708251953125 +94835 0.553955078125 +94836 0.273651123046875 +94837 0.63287353515625 +94838 0.31768798828125 +94839 0.66204833984375 +94840 0.341094970703125 +94841 0.652587890625 +94842 0.368011474609375 +94843 0.626953125 +94844 0.37249755859375 +94845 0.5665283203125 +94846 0.30072021484375 +94847 0.4300537109375 +94848 0.1517333984375 +94849 0.221221923828125 +94850 -0.01470947265625 +94851 -0.004974365234375 +94852 -0.1883544921875 +94853 -0.235137939453125 +94854 -0.372711181640625 +94855 -0.467681884765625 +94856 -0.51397705078125 +94857 -0.65338134765625 +94858 -0.57177734375 +94859 -0.75494384765625 +94860 -0.53948974609375 +94861 -0.764312744140625 +94862 -0.43511962890625 +94863 -0.69512939453125 +94864 -0.2962646484375 +94865 -0.5784912109375 +94866 -0.161102294921875 +94867 -0.446990966796875 +94868 -0.0435791015625 +94869 -0.313812255859375 +94870 0.060394287109375 +94871 -0.177886962890625 +94872 0.13665771484375 +94873 -0.054168701171875 +94874 0.170135498046875 +94875 0.041107177734375 +94876 0.16552734375 +94877 0.108062744140625 +94878 0.15728759765625 +94879 0.171600341796875 +94880 0.150787353515625 +94881 0.232421875 +94882 0.12200927734375 +94883 0.266876220703125 +94884 0.080108642578125 +94885 0.2796630859375 +94886 0.05126953125 +94887 0.290435791015625 +94888 0.062896728515625 +94889 0.32073974609375 +94890 0.09271240234375 +94891 0.351104736328125 +94892 0.092987060546875 +94893 0.341644287109375 +94894 0.07855224609375 +94895 0.30572509765625 +94896 0.06427001953125 +94897 0.257537841796875 +94898 0.0347900390625 +94899 0.1865234375 +94900 -0.01171875 +94901 0.093902587890625 +94902 -0.056060791015625 +94903 -0.001007080078125 +94904 -0.055511474609375 +94905 -0.059051513671875 +94906 -0.010467529296875 +94907 -0.077362060546875 +94908 0.02508544921875 +94909 -0.0982666015625 +94910 0.025665283203125 +94911 -0.140533447265625 +94912 0.017333984375 +94913 -0.18017578125 +94914 0.00189208984375 +94915 -0.214202880859375 +94916 -0.03173828125 +94917 -0.251129150390625 +94918 -0.071502685546875 +94919 -0.280731201171875 +94920 -0.13543701171875 +94921 -0.3187255859375 +94922 -0.219970703125 +94923 -0.36328125 +94924 -0.300506591796875 +94925 -0.3955078125 +94926 -0.376312255859375 +94927 -0.416961669921875 +94928 -0.416107177734375 +94929 -0.40386962890625 +94930 -0.371124267578125 +94931 -0.31793212890625 +94932 -0.242279052734375 +94933 -0.162567138671875 +94934 -0.069732666015625 +94935 0.02587890625 +94936 0.125640869140625 +94937 0.22760009765625 +94938 0.31268310546875 +94939 0.41455078125 +94940 0.45501708984375 +94941 0.5548095703125 +94942 0.554779052734375 +94943 0.649322509765625 +94944 0.61065673828125 +94945 0.696685791015625 +94946 0.610931396484375 +94947 0.68731689453125 +94948 0.531463623046875 +94949 0.601776123046875 +94950 0.3883056640625 +94951 0.454803466796875 +94952 0.23468017578125 +94953 0.29278564453125 +94954 0.095245361328125 +94955 0.138458251953125 +94956 -0.00396728515625 +94957 0.015777587890625 +94958 -0.04852294921875 +94959 -0.060882568359375 +94960 -0.055145263671875 +94961 -0.103424072265625 +94962 -0.0758056640625 +94963 -0.15362548828125 +94964 -0.138702392578125 +94965 -0.23345947265625 +94966 -0.209197998046875 +94967 -0.312530517578125 +94968 -0.289031982421875 +94969 -0.391387939453125 +94970 -0.37884521484375 +94971 -0.47021484375 +94972 -0.456329345703125 +94973 -0.5302734375 +94974 -0.51641845703125 +94975 -0.56787109375 +94976 -0.519287109375 +94977 -0.55029296875 +94978 -0.458251953125 +94979 -0.47320556640625 +94980 -0.384796142578125 +94981 -0.381805419921875 +94982 -0.323699951171875 +94983 -0.298797607421875 +94984 -0.269287109375 +94985 -0.221099853515625 +94986 -0.1951904296875 +94987 -0.128021240234375 +94988 -0.100006103515625 +94989 -0.01995849609375 +94990 -0.01055908203125 +94991 0.078857421875 +94992 0.1033935546875 +94993 0.193023681640625 +94994 0.24908447265625 +94995 0.327911376953125 +94996 0.373199462890625 +94997 0.43780517578125 +94998 0.45806884765625 +94999 0.50762939453125 +95000 0.511474609375 +95001 0.5443115234375 +95002 0.565399169921875 +95003 0.575714111328125 +95004 0.61138916015625 +95005 0.59564208984375 +95006 0.5897216796875 +95007 0.554473876953125 +95008 0.4906005859375 +95009 0.4451904296875 +95010 0.33148193359375 +95011 0.28411865234375 +95012 0.147796630859375 +95013 0.102752685546875 +95014 -0.01873779296875 +95015 -0.062042236328125 +95016 -0.140289306640625 +95017 -0.1854248046875 +95018 -0.191986083984375 +95019 -0.2452392578125 +95020 -0.184295654296875 +95021 -0.2496337890625 +95022 -0.161834716796875 +95023 -0.236083984375 +95024 -0.166595458984375 +95025 -0.240142822265625 +95026 -0.19390869140625 +95027 -0.25799560546875 +95028 -0.22442626953125 +95029 -0.273651123046875 +95030 -0.279754638671875 +95031 -0.30615234375 +95032 -0.3389892578125 +95033 -0.338653564453125 +95034 -0.3543701171875 +95035 -0.331634521484375 +95036 -0.348175048828125 +95037 -0.305206298828125 +95038 -0.32598876953125 +95039 -0.2652587890625 +95040 -0.2581787109375 +95041 -0.18780517578125 +95042 -0.139801025390625 +95043 -0.06964111328125 +95044 0.014617919921875 +95045 0.07598876953125 +95046 0.144378662109375 +95047 0.19677734375 +95048 0.221038818359375 +95049 0.268096923828125 +95050 0.27069091796875 +95051 0.3118896484375 +95052 0.294036865234375 +95053 0.328826904296875 +95054 0.311767578125 +95055 0.3367919921875 +95056 0.339141845703125 +95057 0.349334716796875 +95058 0.360260009765625 +95059 0.3538818359375 +95060 0.360504150390625 +95061 0.338775634765625 +95062 0.308380126953125 +95063 0.277313232421875 +95064 0.18170166015625 +95065 0.15093994140625 +95066 0.0047607421875 +95067 -0.01824951171875 +95068 -0.17559814453125 +95069 -0.188720703125 +95070 -0.3143310546875 +95071 -0.320587158203125 +95072 -0.36785888671875 +95073 -0.375335693359375 +95074 -0.36248779296875 +95075 -0.37554931640625 +95076 -0.343536376953125 +95077 -0.360565185546875 +95078 -0.3018798828125 +95079 -0.322479248046875 +95080 -0.231414794921875 +95081 -0.256134033203125 +95082 -0.117645263671875 +95083 -0.149200439453125 +95084 0.007049560546875 +95085 -0.030426025390625 +95086 0.087982177734375 +95087 0.0518798828125 +95088 0.13946533203125 +95089 0.1094970703125 +95090 0.17425537109375 +95091 0.152862548828125 +95092 0.188201904296875 +95093 0.1776123046875 +95094 0.171234130859375 +95095 0.174285888671875 +95096 0.118438720703125 +95097 0.138031005859375 +95098 0.05706787109375 +95099 0.092132568359375 +95100 -0.010711669921875 +95101 0.0380859375 +95102 -0.0914306640625 +95103 -0.02996826171875 +95104 -0.162322998046875 +95105 -0.09222412109375 +95106 -0.194549560546875 +95107 -0.123443603515625 +95108 -0.1492919921875 +95109 -0.08953857421875 +95110 -0.02166748046875 +95111 0.01409912109375 +95112 0.124053955078125 +95113 0.131927490234375 +95114 0.211151123046875 +95115 0.1976318359375 +95116 0.240447998046875 +95117 0.2125244140625 +95118 0.242218017578125 +95119 0.20355224609375 +95120 0.2257080078125 +95121 0.17938232421875 +95122 0.194366455078125 +95123 0.143524169921875 +95124 0.115509033203125 +95125 0.067901611328125 +95126 0.0128173828125 +95127 -0.0264892578125 +95128 -0.053802490234375 +95129 -0.087249755859375 +95130 -0.110626220703125 +95131 -0.137176513671875 +95132 -0.199493408203125 +95133 -0.21282958984375 +95134 -0.29437255859375 +95135 -0.291656494140625 +95136 -0.33221435546875 +95137 -0.31890869140625 +95138 -0.27972412109375 +95139 -0.265960693359375 +95140 -0.185333251953125 +95141 -0.175506591796875 +95142 -0.128204345703125 +95143 -0.11700439453125 +95144 -0.115692138671875 +95145 -0.09735107421875 +95146 -0.116455078125 +95147 -0.0897216796875 +95148 -0.105926513671875 +95149 -0.0731201171875 +95150 -0.053955078125 +95151 -0.021636962890625 +95152 0.048797607421875 +95153 0.07257080078125 +95154 0.157318115234375 +95155 0.1700439453125 +95156 0.212005615234375 +95157 0.21868896484375 +95158 0.218475341796875 +95159 0.223419189453125 +95160 0.23724365234375 +95161 0.23712158203125 +95162 0.30535888671875 +95163 0.29229736328125 +95164 0.38128662109375 +95165 0.35296630859375 +95166 0.404449462890625 +95167 0.36663818359375 +95168 0.3944091796875 +95169 0.35076904296875 +95170 0.3885498046875 +95171 0.338348388671875 +95172 0.362640380859375 +95173 0.308685302734375 +95174 0.27362060546875 +95175 0.224609375 +95176 0.11712646484375 +95177 0.0826416015625 +95178 -0.054901123046875 +95179 -0.071624755859375 +95180 -0.19085693359375 +95181 -0.1929931640625 +95182 -0.28570556640625 +95183 -0.2769775390625 +95184 -0.339263916015625 +95185 -0.32342529296875 +95186 -0.3775634765625 +95187 -0.355072021484375 +95188 -0.445709228515625 +95189 -0.411376953125 +95190 -0.535064697265625 +95191 -0.485015869140625 +95192 -0.629058837890625 +95193 -0.56182861328125 +95194 -0.697601318359375 +95195 -0.615875244140625 +95196 -0.70391845703125 +95197 -0.615386962890625 +95198 -0.6424560546875 +95199 -0.555877685546875 +95200 -0.491241455078125 +95201 -0.41851806640625 +95202 -0.265716552734375 +95203 -0.217010498046875 +95204 -0.023712158203125 +95205 -0.0020751953125 +95206 0.201751708984375 +95207 0.197296142578125 +95208 0.375823974609375 +95209 0.350616455078125 +95210 0.485076904296875 +95211 0.446136474609375 +95212 0.56884765625 +95213 0.518157958984375 +95214 0.634765625 +95215 0.57342529296875 +95216 0.63763427734375 +95217 0.572723388671875 +95218 0.5660400390625 +95219 0.50628662109375 +95220 0.4720458984375 +95221 0.419708251953125 +95222 0.40692138671875 +95223 0.35797119140625 +95224 0.3778076171875 +95225 0.327606201171875 +95226 0.376953125 +95227 0.322113037109375 +95228 0.371978759765625 +95229 0.31353759765625 +95230 0.313140869140625 +95231 0.25872802734375 +95232 0.184417724609375 +95233 0.143646240234375 +95234 0.011199951171875 +95235 -0.009674072265625 +95236 -0.171051025390625 +95237 -0.1700439453125 +95238 -0.33740234375 +95239 -0.31524658203125 +95240 -0.47198486328125 +95241 -0.4312744140625 +95242 -0.560394287109375 +95243 -0.505462646484375 +95244 -0.58056640625 +95245 -0.518218994140625 +95246 -0.54754638671875 +95247 -0.483428955078125 +95248 -0.508575439453125 +95249 -0.444091796875 +95250 -0.459503173828125 +95251 -0.396636962890625 +95252 -0.394378662109375 +95253 -0.3358154296875 +95254 -0.35260009765625 +95255 -0.297332763671875 +95256 -0.31170654296875 +95257 -0.260833740234375 +95258 -0.197418212890625 +95259 -0.159149169921875 +95260 -0.007965087890625 +95261 0.00946044921875 +95262 0.207489013671875 +95263 0.20074462890625 +95264 0.409210205078125 +95265 0.37896728515625 +95266 0.57208251953125 +95267 0.52166748046875 +95268 0.66595458984375 +95269 0.60186767578125 +95270 0.65875244140625 +95271 0.5908203125 +95272 0.56744384765625 +95273 0.504119873046875 +95274 0.431396484375 +95275 0.3775634765625 +95276 0.29443359375 +95277 0.2509765625 +95278 0.182464599609375 +95279 0.14788818359375 +95280 0.06365966796875 +95281 0.03961181640625 +95282 -0.075958251953125 +95283 -0.086456298828125 +95284 -0.189422607421875 +95285 -0.18792724609375 +95286 -0.271942138671875 +95287 -0.26055908203125 +95288 -0.342529296875 +95289 -0.3216552734375 +95290 -0.364166259765625 +95291 -0.337921142578125 +95292 -0.327239990234375 +95293 -0.3009033203125 +95294 -0.2769775390625 +95295 -0.251678466796875 +95296 -0.253692626953125 +95297 -0.22686767578125 +95298 -0.24365234375 +95299 -0.214263916015625 +95300 -0.1983642578125 +95301 -0.17022705078125 +95302 -0.116241455078125 +95303 -0.093505859375 +95304 -0.036834716796875 +95305 -0.019927978515625 +95306 0.034881591796875 +95307 0.0458984375 +95308 0.09124755859375 +95309 0.0970458984375 +95310 0.10888671875 +95311 0.1124267578125 +95312 0.125518798828125 +95313 0.126129150390625 +95314 0.15771484375 +95315 0.15325927734375 +95316 0.17828369140625 +95317 0.1693115234375 +95318 0.17108154296875 +95319 0.15985107421875 +95320 0.129974365234375 +95321 0.11956787109375 +95322 0.082427978515625 +95323 0.073455810546875 +95324 0.027679443359375 +95325 0.02099609375 +95326 -0.065643310546875 +95327 -0.066009521484375 +95328 -0.15936279296875 +95329 -0.15289306640625 +95330 -0.21307373046875 +95331 -0.20306396484375 +95332 -0.234649658203125 +95333 -0.22357177734375 +95334 -0.2001953125 +95335 -0.192779541015625 +95336 -0.119171142578125 +95337 -0.119232177734375 +95338 -0.024749755859375 +95339 -0.032958984375 +95340 0.085784912109375 +95341 0.06842041015625 +95342 0.178131103515625 +95343 0.15380859375 +95344 0.215576171875 +95345 0.189910888671875 +95346 0.211456298828125 +95347 0.188629150390625 +95348 0.17523193359375 +95349 0.15838623046875 +95350 0.128753662109375 +95351 0.118804931640625 +95352 0.1019287109375 +95353 0.0968017578125 +95354 0.0743408203125 +95355 0.07379150390625 +95356 0.04327392578125 +95357 0.047210693359375 +95358 0.038177490234375 +95359 0.043609619140625 +95360 0.076263427734375 +95361 0.078521728515625 +95362 0.14105224609375 +95363 0.137054443359375 +95364 0.186431884765625 +95365 0.177520751953125 +95366 0.188812255859375 +95367 0.17864990234375 +95368 0.1390380859375 +95369 0.1322021484375 +95370 0.041778564453125 +95371 0.04254150390625 +95372 -0.079437255859375 +95373 -0.0689697265625 +95374 -0.219390869140625 +95375 -0.197509765625 +95376 -0.367828369140625 +95377 -0.33367919921875 +95378 -0.494873046875 +95379 -0.450408935546875 +95380 -0.556243896484375 +95381 -0.507537841796875 +95382 -0.508697509765625 +95383 -0.465911865234375 +95384 -0.3756103515625 +95385 -0.3465576171875 +95386 -0.218902587890625 +95387 -0.2054443359375 +95388 -0.063751220703125 +95389 -0.0653076171875 +95390 0.091552734375 +95391 0.07537841796875 +95392 0.23602294921875 +95393 0.2066650390625 +95394 0.342987060546875 +95395 0.30438232421875 +95396 0.39520263671875 +95397 0.352874755859375 +95398 0.389373779296875 +95399 0.34912109375 +95400 0.324249267578125 +95401 0.291900634765625 +95402 0.224090576171875 +95403 0.203033447265625 +95404 0.124267578125 +95405 0.114410400390625 +95406 0.037078857421875 +95407 0.037017822265625 +95408 -0.010101318359375 +95409 -0.00445556640625 +95410 -0.019439697265625 +95411 -0.011993408203125 +95412 -0.022796630859375 +95413 -0.014434814453125 +95414 -0.001556396484375 +95415 0.004974365234375 +95416 0.056304931640625 +95417 0.05712890625 +95418 0.106719970703125 +95419 0.102203369140625 +95420 0.096893310546875 +95421 0.092529296875 +95422 0.042694091796875 +95423 0.04248046875 +95424 -0.018035888671875 +95425 -0.013671875 +95426 -0.07586669921875 +95427 -0.067291259765625 +95428 -0.11944580078125 +95429 -0.108062744140625 +95430 -0.15972900390625 +95431 -0.145843505859375 +95432 -0.202606201171875 +95433 -0.18585205078125 +95434 -0.24859619140625 +95435 -0.228485107421875 +95436 -0.30517578125 +95437 -0.280426025390625 +95438 -0.36212158203125 +95439 -0.332427978515625 +95440 -0.39141845703125 +95441 -0.359130859375 +95442 -0.35528564453125 +95443 -0.32635498046875 +95444 -0.249969482421875 +95445 -0.230743408203125 +95446 -0.092864990234375 +95447 -0.088104248046875 +95448 0.08905029296875 +95449 0.077178955078125 +95450 0.2352294921875 +95451 0.2103271484375 +95452 0.318817138671875 +95453 0.287017822265625 +95454 0.358642578125 +95455 0.32415771484375 +95456 0.347747802734375 +95457 0.3154296875 +95458 0.28564453125 +95459 0.260345458984375 +95460 0.223175048828125 +95461 0.204803466796875 +95462 0.196746826171875 +95463 0.181640625 +95464 0.179840087890625 +95465 0.1668701171875 +95466 0.155548095703125 +95467 0.145172119140625 +95468 0.151214599609375 +95469 0.141265869140625 +95470 0.156951904296875 +95471 0.146209716796875 +95472 0.13177490234375 +95473 0.122955322265625 +95474 0.100799560546875 +95475 0.094268798828125 +95476 0.087127685546875 +95477 0.0810546875 +95478 0.05487060546875 +95479 0.050933837890625 +95480 -0.009002685546875 +95481 -0.007781982421875 +95482 -0.10400390625 +95483 -0.0946044921875 +95484 -0.229400634765625 +95485 -0.2088623046875 +95486 -0.35552978515625 +95487 -0.32366943359375 +95488 -0.441925048828125 +95489 -0.402587890625 +95490 -0.473846435546875 +95491 -0.4326171875 +95492 -0.464813232421875 +95493 -0.426055908203125 +95494 -0.419097900390625 +95495 -0.386260986328125 +95496 -0.334320068359375 +95497 -0.31048583984375 +95498 -0.227935791015625 +95499 -0.214569091796875 +95500 -0.12347412109375 +95501 -0.120208740234375 +95502 -0.02764892578125 +95503 -0.03338623046875 +95504 0.077667236328125 +95505 0.063079833984375 +95506 0.2132568359375 +95507 0.188720703125 +95508 0.38885498046875 +95509 0.352691650390625 +95510 0.582794189453125 +95511 0.53466796875 +95512 0.734039306640625 +95513 0.677398681640625 +95514 0.800140380859375 +95515 0.7410888671875 +95516 0.7783203125 +95517 0.72296142578125 +95518 0.6651611328125 +95519 0.619659423828125 +95520 0.45965576171875 +95521 0.4300537109375 +95522 0.199188232421875 +95523 0.18896484375 +95524 -0.050689697265625 +95525 -0.04241943359375 +95526 -0.23297119140625 +95527 -0.21087646484375 +95528 -0.33013916015625 +95529 -0.300140380859375 +95530 -0.368408203125 +95531 -0.33477783203125 +95532 -0.378936767578125 +95533 -0.344024658203125 +95534 -0.376983642578125 +95535 -0.342193603515625 +95536 -0.37969970703125 +95537 -0.345306396484375 +95538 -0.391510009765625 +95539 -0.357452392578125 +95540 -0.385345458984375 +95541 -0.353271484375 +95542 -0.3419189453125 +95543 -0.314605712890625 +95544 -0.28289794921875 +95545 -0.2615966796875 +95546 -0.251617431640625 +95547 -0.234649658203125 +95548 -0.266143798828125 +95549 -0.25054931640625 +95550 -0.273345947265625 +95551 -0.25946044921875 +95552 -0.216796875 +95553 -0.20843505859375 +95554 -0.128265380859375 +95555 -0.127105712890625 +95556 -0.068145751953125 +95557 -0.07196044921875 +95558 -0.0430908203125 +95559 -0.049163818359375 +95560 -0.024444580078125 +95561 -0.0318603515625 +95562 0.020721435546875 +95563 0.010772705078125 +95564 0.124481201171875 +95565 0.108734130859375 +95566 0.25787353515625 +95567 0.23480224609375 +95568 0.379119873046875 +95569 0.349822998046875 +95570 0.47991943359375 +95571 0.445953369140625 +95572 0.5281982421875 +95573 0.4930419921875 +95574 0.511138916015625 +95575 0.47900390625 +95576 0.456207275390625 +95577 0.429443359375 +95578 0.407470703125 +95579 0.385498046875 +95580 0.383758544921875 +95581 0.36468505859375 +95582 0.35687255859375 +95583 0.340576171875 +95584 0.31182861328125 +95585 0.299102783203125 +95586 0.250885009765625 +95587 0.2423095703125 +95588 0.1654052734375 +95589 0.162139892578125 +95590 0.035247802734375 +95591 0.03973388671875 +95592 -0.142059326171875 +95593 -0.127166748046875 +95594 -0.33563232421875 +95595 -0.3095703125 +95596 -0.5345458984375 +95597 -0.4971923828125 +95598 -0.72186279296875 +95599 -0.674072265625 +95600 -0.836669921875 +95601 -0.783111572265625 +95602 -0.8326416015625 +95603 -0.7808837890625 +95604 -0.7296142578125 +95605 -0.685882568359375 +95606 -0.582550048828125 +95607 -0.549468994140625 +95608 -0.440093994140625 +95609 -0.417083740234375 +95610 -0.324310302734375 +95611 -0.30938720703125 +95612 -0.20147705078125 +95613 -0.194732666015625 +95614 -0.044647216796875 +95615 -0.04791259765625 +95616 0.103973388671875 +95617 0.091583251953125 +95618 0.202392578125 +95619 0.18438720703125 +95620 0.264495849609375 +95621 0.243438720703125 +95622 0.338897705078125 +95623 0.314239501953125 +95624 0.443817138671875 +95625 0.413726806640625 +95626 0.545074462890625 +95627 0.509857177734375 +95628 0.6173095703125 +95629 0.57879638671875 +95630 0.6524658203125 +95631 0.612945556640625 +95632 0.66339111328125 +95633 0.624237060546875 +95634 0.6561279296875 +95635 0.6182861328125 +95636 0.606781005859375 +95637 0.572662353515625 +95638 0.501190185546875 +95639 0.47412109375 +95640 0.352783203125 +95641 0.335174560546875 +95642 0.176544189453125 +95643 0.169921875 +95644 -0.034820556640625 +95645 -0.0284423828125 +95646 -0.258209228515625 +95647 -0.23828125 +95648 -0.44244384765625 +95649 -0.411651611328125 +95650 -0.5753173828125 +95651 -0.53704833984375 +95652 -0.65203857421875 +95653 -0.60992431640625 +95654 -0.641632080078125 +95655 -0.601226806640625 +95656 -0.562164306640625 +95657 -0.52783203125 +95658 -0.458038330078125 +95659 -0.431243896484375 +95660 -0.350555419921875 +95661 -0.331329345703125 +95662 -0.260528564453125 +95663 -0.24755859375 +95664 -0.192108154296875 +95665 -0.183807373046875 +95666 -0.141937255859375 +95667 -0.13690185546875 +95668 -0.1021728515625 +95669 -0.099517822265625 +95670 -0.062896728515625 +95671 -0.0623779296875 +95672 -0.011932373046875 +95673 -0.01409912109375 +95674 0.062835693359375 +95675 0.056610107421875 +95676 0.148712158203125 +95677 0.137847900390625 +95678 0.241729736328125 +95679 0.225799560546875 +95680 0.34912109375 +95681 0.32720947265625 +95682 0.457305908203125 +95683 0.4293212890625 +95684 0.54388427734375 +95685 0.5111083984375 +95686 0.5728759765625 +95687 0.53887939453125 +95688 0.506591796875 +95689 0.477294921875 +95690 0.351226806640625 +95691 0.3321533203125 +95692 0.146514892578125 +95693 0.140625 +95694 -0.05523681640625 +95695 -0.048309326171875 +95696 -0.21624755859375 +95697 -0.19927978515625 +95698 -0.334930419921875 +95699 -0.310760498046875 +95700 -0.402984619140625 +95701 -0.375 +95702 -0.4412841796875 +95703 -0.4114990234375 +95704 -0.49578857421875 +95705 -0.463226318359375 +95706 -0.5601806640625 +95707 -0.52423095703125 +95708 -0.600738525390625 +95709 -0.56292724609375 +95710 -0.584228515625 +95711 -0.548126220703125 +95712 -0.47930908203125 +95713 -0.450469970703125 +95714 -0.27935791015625 +95715 -0.263763427734375 +95716 -0.0089111328125 +95717 -0.01092529296875 +95718 0.268798828125 +95719 0.24884033203125 +95720 0.482818603515625 +95721 0.44915771484375 +95722 0.60369873046875 +95723 0.562469482421875 +95724 0.650421142578125 +95725 0.60650634765625 +95726 0.66400146484375 +95727 0.61962890625 +95728 0.6414794921875 +95729 0.599029541015625 +95730 0.572540283203125 +95731 0.5350341796875 +95732 0.498138427734375 +95733 0.465972900390625 +95734 0.439453125 +95735 0.41162109375 +95736 0.375518798828125 +95737 0.352325439453125 +95738 0.274505615234375 +95739 0.258270263671875 +95740 0.1087646484375 +95741 0.103546142578125 +95742 -0.099395751953125 +95743 -0.09100341796875 +95744 -0.3182373046875 +95745 -0.296142578125 +95746 -0.5489501953125 +95747 -0.51385498046875 +95748 -0.7738037109375 +95749 -0.727325439453125 +95750 -0.86383056640625 +95751 -0.857879638671875 +95752 -0.870391845703125 +95753 -0.8656005859375 +95754 -0.86895751953125 +95755 -0.865631103515625 +95756 -0.861053466796875 +95757 -0.859344482421875 +95758 -0.765869140625 +95759 -0.7667236328125 +95760 -0.5301513671875 +95761 -0.548583984375 +95762 -0.214691162109375 +95763 -0.251129150390625 +95764 0.137359619140625 +95765 0.084320068359375 +95766 0.474822998046875 +95767 0.408416748046875 +95768 0.76239013671875 +95769 0.68707275390625 +95770 0.867462158203125 +95771 0.85882568359375 +95772 0.870361328125 +95773 0.870361328125 +95774 0.86480712890625 +95775 0.870361328125 +95776 0.831817626953125 +95777 0.862701416015625 +95778 0.677581787109375 +95779 0.816070556640625 +95780 0.495880126953125 +95781 0.665863037109375 +95782 0.30767822265625 +95783 0.498504638671875 +95784 0.116180419921875 +95785 0.316619873046875 +95786 -0.110748291015625 +95787 0.089202880859375 +95788 -0.381805419921875 +95789 -0.19140625 +95790 -0.6572265625 +95791 -0.485443115234375 +95792 -0.857421875 +95793 -0.737091064453125 +95794 -0.870391845703125 +95795 -0.860260009765625 +95796 -0.870391845703125 +95797 -0.869537353515625 +95798 -0.86444091796875 +95799 -0.870391845703125 +95800 -0.85723876953125 +95801 -0.86932373046875 +95802 -0.790008544921875 +95803 -0.864837646484375 +95804 -0.62847900390625 +95805 -0.826568603515625 +95806 -0.3956298828125 +95807 -0.622161865234375 +95808 -0.126708984375 +95809 -0.369171142578125 +95810 0.150115966796875 +95811 -0.0948486328125 +95812 0.424041748046875 +95813 0.1895751953125 +95814 0.670623779296875 +95815 0.459014892578125 +95816 0.854522705078125 +95817 0.677703857421875 +95818 0.866485595703125 +95819 0.830902099609375 +95820 0.86920166015625 +95821 0.86016845703125 +95822 0.8653564453125 +95823 0.862213134765625 +95824 0.857147216796875 +95825 0.85986328125 +95826 0.766845703125 +95827 0.84197998046875 +95828 0.628509521484375 +95829 0.748138427734375 +95830 0.462127685546875 +95831 0.61834716796875 +95832 0.297210693359375 +95833 0.479736328125 +95834 0.14862060546875 +95835 0.3458251953125 +95836 -0.00537109375 +95837 0.19537353515625 +95838 -0.15753173828125 +95839 0.0357666015625 +95840 -0.31304931640625 +95841 -0.136993408203125 +95842 -0.48876953125 +95843 -0.337738037109375 +95844 -0.6416015625 +95845 -0.5228271484375 +95846 -0.751373291015625 +95847 -0.67047119140625 +95848 -0.84619140625 +95849 -0.805572509765625 +95850 -0.861297607421875 +95851 -0.86126708984375 +95852 -0.863250732421875 +95853 -0.8675537109375 +95854 -0.856597900390625 +95855 -0.86492919921875 +95856 -0.7498779296875 +95857 -0.854949951171875 +95858 -0.624542236328125 +95859 -0.757598876953125 +95860 -0.47808837890625 +95861 -0.627227783203125 +95862 -0.253387451171875 +95863 -0.41180419921875 +95864 0.003692626953125 +95865 -0.155853271484375 +95866 0.2257080078125 +95867 0.07464599609375 +95868 0.427154541015625 +95869 0.2926025390625 +95870 0.643218994140625 +95871 0.5306396484375 +95872 0.855926513671875 +95873 0.78106689453125 +95874 0.870361328125 +95875 0.869232177734375 +95876 0.870361328125 +95877 0.870361328125 +95878 0.862762451171875 +95879 0.8638916015625 +95880 0.79669189453125 +95881 0.817047119140625 +95882 0.595794677734375 +95883 0.6256103515625 +95884 0.362152099609375 +95885 0.39971923828125 +95886 0.1270751953125 +95887 0.169769287109375 +95888 -0.086944580078125 +95889 -0.042266845703125 +95890 -0.2784423828125 +95891 -0.23468017578125 +95892 -0.484832763671875 +95893 -0.443206787109375 +95894 -0.729583740234375 +95895 -0.6900634765625 +95896 -0.86688232421875 +95897 -0.862884521484375 +95898 -0.870391845703125 +95899 -0.870391845703125 +95900 -0.86859130859375 +95901 -0.870391845703125 +95902 -0.86279296875 +95903 -0.8662109375 +95904 -0.817962646484375 +95905 -0.8553466796875 +95906 -0.6116943359375 +95907 -0.667633056640625 +95908 -0.3128662109375 +95909 -0.379302978515625 +95910 0.039398193359375 +95911 -0.0350341796875 +95912 0.422821044921875 +95913 0.34332275390625 +95914 0.805145263671875 +95915 0.723968505859375 +95916 0.870361328125 +95917 0.870361328125 +95918 0.870361328125 +95919 0.870361328125 +95920 0.860015869140625 +95921 0.86016845703125 +95922 0.727935791015625 +95923 0.7315673828125 +95924 0.48114013671875 +95925 0.48797607421875 +95926 0.2059326171875 +95927 0.215789794921875 +95928 -0.06103515625 +95929 -0.04913330078125 +95930 -0.29913330078125 +95931 -0.2864990234375 +95932 -0.516204833984375 +95933 -0.503509521484375 +95934 -0.7252197265625 +95935 -0.712310791015625 +95936 -0.85980224609375 +95937 -0.8583984375 +95938 -0.870391845703125 +95939 -0.870391845703125 +95940 -0.870391845703125 +95941 -0.870391845703125 +95942 -0.858062744140625 +95943 -0.8582763671875 +95944 -0.673004150390625 +95945 -0.6783447265625 +95946 -0.42694091796875 +95947 -0.435394287109375 +95948 -0.2100830078125 +95949 -0.219696044921875 +95950 -0.0362548828125 +95951 -0.044921875 +95952 0.10943603515625 +95953 0.10296630859375 +95954 0.23516845703125 +95955 0.23150634765625 +95956 0.373687744140625 +95957 0.37200927734375 +95958 0.517791748046875 +95959 0.51715087890625 +95960 0.602783203125 +95961 0.604034423828125 +95962 0.635711669921875 +95963 0.639312744140625 +95964 0.655181884765625 +95965 0.66015625 +95966 0.65948486328125 +95967 0.66485595703125 +95968 0.651275634765625 +95969 0.655975341796875 +95970 0.61846923828125 +95971 0.62188720703125 +95972 0.53753662109375 +95973 0.540008544921875 +95974 0.404144287109375 +95975 0.4063720703125 +95976 0.22186279296875 +95977 0.224700927734375 +95978 0.003997802734375 +95979 0.008209228515625 +95980 -0.22100830078125 +95981 -0.21527099609375 +95982 -0.42449951171875 +95983 -0.417724609375 +95984 -0.579833984375 +95985 -0.57305908203125 +95986 -0.641876220703125 +95987 -0.637298583984375 +95988 -0.6177978515625 +95989 -0.617156982421875 +95990 -0.575531005859375 +95991 -0.578277587890625 +95992 -0.526336669921875 +95993 -0.531463623046875 +95994 -0.42645263671875 +95995 -0.43438720703125 +95996 -0.2581787109375 +95997 -0.2698974609375 +95998 -0.068695068359375 +95999 -0.083831787109375 +96000 0.09222412109375 +96001 0.075958251953125 +96002 0.232147216796875 +96003 0.2171630859375 +96004 0.3509521484375 +96005 0.3388671875 +96006 0.410064697265625 +96007 0.401947021484375 +96008 0.372955322265625 +96009 0.369384765625 +96010 0.2554931640625 +96011 0.256622314453125 +96012 0.10711669921875 +96013 0.11273193359375 +96014 -0.052886962890625 +96015 -0.0433349609375 +96016 -0.186279296875 +96017 -0.173553466796875 +96018 -0.23291015625 +96019 -0.21795654296875 +96020 -0.209442138671875 +96021 -0.19329833984375 +96022 -0.174163818359375 +96023 -0.15789794921875 +96024 -0.126739501953125 +96025 -0.111358642578125 +96026 -0.048126220703125 +96027 -0.0345458984375 +96028 0.0426025390625 +96029 0.0535888671875 +96030 0.10748291015625 +96031 0.11529541015625 +96032 0.1409912109375 +96033 0.145233154296875 +96034 0.19708251953125 +96035 0.197601318359375 +96036 0.273651123046875 +96037 0.270538330078125 +96038 0.31768798828125 +96039 0.311248779296875 +96040 0.341094970703125 +96041 0.331787109375 +96042 0.368011474609375 +96043 0.356414794921875 +96044 0.37249755859375 +96045 0.359283447265625 +96046 0.30072021484375 +96047 0.286651611328125 +96048 0.1517333984375 +96049 0.1375732421875 +96050 -0.01470947265625 +96051 -0.0281982421875 +96052 -0.1883544921875 +96053 -0.200439453125 +96054 -0.372711181640625 +96055 -0.38275146484375 +96056 -0.51397705078125 +96057 -0.521484375 +96058 -0.57177734375 +96059 -0.576416015625 +96060 -0.53948974609375 +96061 -0.541107177734375 +96062 -0.43511962890625 +96063 -0.4337158203125 +96064 -0.2962646484375 +96065 -0.292022705078125 +96066 -0.161102294921875 +96067 -0.154327392578125 +96068 -0.0435791015625 +96069 -0.034698486328125 +96070 0.060394287109375 +96071 0.070831298828125 +96072 0.13665771484375 +96073 0.148040771484375 +96074 0.170135498046875 +96075 0.18182373046875 +96076 0.16552734375 +96077 0.1768798828125 +96078 0.15728759765625 +96079 0.16766357421875 +96080 0.150787353515625 +96081 0.15966796875 +96082 0.12200927734375 +96083 0.12896728515625 +96084 0.080108642578125 +96085 0.084808349609375 +96086 0.05126953125 +96087 0.05352783203125 +96088 0.062896728515625 +96089 0.06268310546875 +96090 0.09271240234375 +96091 0.090118408203125 +96092 0.092987060546875 +96093 0.088226318359375 +96094 0.07855224609375 +96095 0.071929931640625 +96096 0.06427001953125 +96097 0.05621337890625 +96098 0.0347900390625 +96099 0.025787353515625 +96100 -0.01171875 +96101 -0.021148681640625 +96102 -0.056060791015625 +96103 -0.06536865234375 +96104 -0.055511474609375 +96105 -0.064208984375 +96106 -0.010467529296875 +96107 -0.018096923828125 +96108 0.02508544921875 +96109 0.0189208984375 +96110 0.025665283203125 +96111 0.021270751953125 +96112 0.017333984375 +96113 0.014923095703125 +96114 0.00189208984375 +96115 0.00152587890625 +96116 -0.03173828125 +96117 -0.03009033203125 +96118 -0.071502685546875 +96119 -0.0679931640625 +96120 -0.13543701171875 +96121 -0.13031005859375 +96122 -0.219970703125 +96123 -0.21356201171875 +96124 -0.300506591796875 +96125 -0.293182373046875 +96126 -0.376312255859375 +96127 -0.368499755859375 +96128 -0.416107177734375 +96129 -0.408233642578125 +96130 -0.371124267578125 +96131 -0.363616943359375 +96132 -0.242279052734375 +96133 -0.23553466796875 +96134 -0.069732666015625 +96135 -0.0640869140625 +96136 0.125640869140625 +96137 0.129913330078125 +96138 0.31268310546875 +96139 0.31536865234375 +96140 0.45501708984375 +96141 0.456024169921875 +96142 0.554779052734375 +96143 0.554107666015625 +96144 0.61065673828125 +96145 0.6083984375 +96146 0.610931396484375 +96147 0.607269287109375 +96148 0.531463623046875 +96149 0.526641845703125 +96150 0.3883056640625 +96151 0.382598876953125 +96152 0.23468017578125 +96153 0.228424072265625 +96154 0.095245361328125 +96155 0.08880615234375 +96156 -0.00396728515625 +96157 -0.010223388671875 +96158 -0.04852294921875 +96159 -0.05426025390625 +96160 -0.055145263671875 +96161 -0.06005859375 +96162 -0.0758056640625 +96163 -0.07965087890625 +96164 -0.138702392578125 +96165 -0.14129638671875 +96166 -0.209197998046875 +96167 -0.21044921875 +96168 -0.289031982421875 +96169 -0.288909912109375 +96170 -0.37884521484375 +96171 -0.377410888671875 +96172 -0.456329345703125 +96173 -0.45367431640625 +96174 -0.51641845703125 +96175 -0.512725830078125 +96176 -0.519287109375 +96177 -0.514801025390625 +96178 -0.458251953125 +96179 -0.4532470703125 +96180 -0.384796142578125 +96181 -0.379547119140625 +96182 -0.323699951171875 +96183 -0.3184814453125 +96184 -0.269287109375 +96185 -0.264373779296875 +96186 -0.1951904296875 +96187 -0.19085693359375 +96188 -0.100006103515625 +96189 -0.096466064453125 +96190 -0.01055908203125 +96191 -0.007965087890625 +96192 0.1033935546875 +96193 0.10491943359375 +96194 0.24908447265625 +96195 0.249481201171875 +96196 0.373199462890625 +96197 0.372467041015625 +96198 0.45806884765625 +96199 0.456298828125 +96200 0.511474609375 +96201 0.5087890625 +96202 0.565399169921875 +96203 0.561981201171875 +96204 0.61138916015625 +96205 0.607452392578125 +96206 0.5897216796875 +96207 0.58551025390625 +96208 0.4906005859375 +96209 0.486328125 +96210 0.33148193359375 +96211 0.327392578125 +96212 0.147796630859375 +96213 0.14410400390625 +96214 -0.01873779296875 +96215 -0.0218505859375 +96216 -0.140289306640625 +96217 -0.142669677734375 +96218 -0.191986083984375 +96219 -0.193511962890625 +96220 -0.184295654296875 +96221 -0.184906005859375 +96222 -0.161834716796875 +96223 -0.1614990234375 +96224 -0.166595458984375 +96225 -0.16534423828125 +96226 -0.19390869140625 +96227 -0.19183349609375 +96228 -0.22442626953125 +96229 -0.2216796875 +96230 -0.279754638671875 +96231 -0.2764892578125 +96232 -0.3389892578125 +96233 -0.33538818359375 +96234 -0.3543701171875 +96235 -0.35064697265625 +96236 -0.348175048828125 +96237 -0.34454345703125 +96238 -0.32598876953125 +96239 -0.322662353515625 +96240 -0.2581787109375 +96241 -0.255340576171875 +96242 -0.139801025390625 +96243 -0.137603759765625 +96244 0.014617919921875 +96245 0.016082763671875 +96246 0.144378662109375 +96247 0.145050048828125 +96248 0.221038818359375 +96249 0.220916748046875 +96250 0.27069091796875 +96251 0.269805908203125 +96252 0.294036865234375 +96253 0.29248046875 +96254 0.311767578125 +96255 0.309661865234375 +96256 0.33905029296875 +96257 0.33660888671875 +96258 0.359588623046875 +96259 0.357452392578125 +96260 0.35888671875 +96261 0.357574462890625 +96262 0.306671142578125 +96263 0.30548095703125 +96264 0.18170166015625 +96265 0.178985595703125 +96266 0.00775146484375 +96267 0.00238037109375 +96268 -0.16961669921875 +96269 -0.177520751953125 +96270 -0.306640625 +96271 -0.315704345703125 +96272 -0.3609619140625 +96273 -0.368621826171875 +96274 -0.357879638671875 +96275 -0.36260986328125 +96276 -0.341156005859375 +96277 -0.343017578125 +96278 -0.3018798828125 +96279 -0.30078125 +96280 -0.234100341796875 +96281 -0.22979736328125 +96282 -0.123809814453125 +96283 -0.1156005859375 +96284 -0.002349853515625 +96285 0.0093994140625 +96286 0.0772705078125 +96287 0.09051513671875 +96288 0.1287841796875 +96289 0.14202880859375 +96290 0.164459228515625 +96291 0.176727294921875 +96292 0.18011474609375 +96293 0.1904296875 +96294 0.1658935546875 +96295 0.173095703125 +96296 0.116943359375 +96297 0.119842529296875 +96298 0.05950927734375 +96299 0.057952880859375 +96300 -0.004425048828125 +96301 -0.0103759765625 +96302 -0.081298828125 +96303 -0.091644287109375 +96304 -0.149078369140625 +96305 -0.163055419921875 +96306 -0.179901123046875 +96307 -0.19573974609375 +96308 -0.13623046875 +96309 -0.15087890625 +96310 -0.0133056640625 +96311 -0.0235595703125 +96312 0.126739501953125 +96313 0.121978759765625 +96314 0.209686279296875 +96315 0.209014892578125 +96316 0.2364501953125 +96317 0.238372802734375 +96318 0.23638916015625 +96319 0.24029541015625 +96320 0.218597412109375 +96321 0.22406005859375 +96322 0.186492919921875 +96323 0.193084716796875 +96324 0.108551025390625 +96325 0.114654541015625 +96326 0.00775146484375 +96327 0.012420654296875 +96328 -0.057830810546875 +96329 -0.053741455078125 +96330 -0.113555908203125 +96331 -0.110107421875 +96332 -0.199951171875 +96333 -0.198577880859375 +96334 -0.29180908203125 +96335 -0.293121337890625 +96336 -0.32806396484375 +96337 -0.3306884765625 +96338 -0.27655029296875 +96339 -0.27801513671875 +96340 -0.184173583984375 +96341 -0.18353271484375 +96342 -0.12762451171875 +96343 -0.12640380859375 +96344 -0.11407470703125 +96345 -0.113983154296875 +96346 -0.11328125 +96347 -0.11492919921875 +96348 -0.1015625 +96349 -0.104644775390625 +96350 -0.049835205078125 +96351 -0.052978515625 +96352 0.05084228515625 +96353 0.0494384765625 +96354 0.156890869140625 +96355 0.157623291015625 +96356 0.2105712890625 +96357 0.21197509765625 +96358 0.217254638671875 +96359 0.218109130859375 +96360 0.23553466796875 +96361 0.236572265625 +96362 0.30126953125 +96363 0.304443359375 +96364 0.374237060546875 +96365 0.380157470703125 +96366 0.395843505859375 +96367 0.403167724609375 +96368 0.38507080078125 +96369 0.393035888671875 +96370 0.378173828125 +96371 0.38714599609375 +96372 0.351806640625 +96373 0.361297607421875 +96374 0.264373779296875 +96375 0.27239990234375 +96376 0.1116943359375 +96377 0.1160888671875 +96378 -0.055877685546875 +96379 -0.055694580078125 +96380 -0.188323974609375 +96381 -0.19134521484375 +96382 -0.28076171875 +96383 -0.285858154296875 +96384 -0.3330078125 +96385 -0.339080810546875 +96386 -0.370208740234375 +96387 -0.3770751953125 +96388 -0.43603515625 +96389 -0.4449462890625 +96390 -0.52215576171875 +96391 -0.534088134765625 +96392 -0.612548828125 +96393 -0.6279296875 +96394 -0.678131103515625 +96395 -0.696380615234375 +96396 -0.683349609375 +96397 -0.70269775390625 +96398 -0.62286376953125 +96399 -0.64129638671875 +96400 -0.4754638671875 +96401 -0.490203857421875 +96402 -0.25616455078125 +96403 -0.264862060546875 +96404 -0.02099609375 +96405 -0.0230712890625 +96406 0.198028564453125 +96407 0.2021484375 +96408 0.36712646484375 +96409 0.3759765625 +96410 0.473297119140625 +96411 0.4849853515625 +96412 0.554595947265625 +96413 0.568511962890625 +96414 0.618408203125 +96415 0.63421630859375 +96416 0.6209716796875 +96417 0.636932373046875 +96418 0.551239013671875 +96419 0.565216064453125 +96420 0.45965576171875 +96421 0.47113037109375 +96422 0.3958740234375 +96423 0.40594482421875 +96424 0.36688232421875 +96425 0.376800537109375 +96426 0.36517333984375 +96427 0.375946044921875 +96428 0.3594970703125 +96429 0.37103271484375 +96430 0.3017578125 +96431 0.31231689453125 +96432 0.17645263671875 +96433 0.183746337890625 +96434 0.008209228515625 +96435 0.010711669921875 +96436 -0.168609619140625 +96437 -0.17132568359375 +96438 -0.329864501953125 +96439 -0.33746337890625 +96440 -0.460174560546875 +96441 -0.471832275390625 +96442 -0.54559326171875 +96443 -0.560028076171875 +96444 -0.5648193359375 +96445 -0.58001708984375 +96446 -0.53240966796875 +96447 -0.546844482421875 +96448 -0.494140625 +96449 -0.507781982421875 +96450 -0.44598388671875 +96451 -0.458648681640625 +96452 -0.38226318359375 +96453 -0.393524169921875 +96454 -0.34112548828125 +96455 -0.351806640625 +96456 -0.30084228515625 +96457 -0.311004638671875 +96458 -0.1895751953125 +96459 -0.19683837890625 +96460 -0.005645751953125 +96461 -0.007537841796875 +96462 0.203338623046875 +96463 0.207733154296875 +96464 0.398834228515625 +96465 0.409271240234375 +96466 0.556549072265625 +96467 0.57196044921875 +96468 0.647308349609375 +96469 0.6656494140625 +96470 0.64007568359375 +96471 0.65826416015625 +96472 0.551300048828125 +96473 0.566802978515625 +96474 0.41912841796875 +96475 0.430633544921875 +96476 0.2860107421875 +96477 0.2935791015625 +96478 0.17706298828125 +96479 0.18157958984375 +96480 0.061492919921875 +96481 0.062774658203125 +96482 -0.074188232421875 +96483 -0.076812744140625 +96484 -0.18450927734375 +96485 -0.190185546875 +96486 -0.2647705078125 +96487 -0.2725830078125 +96488 -0.3333740234375 +96489 -0.343017578125 +96490 -0.354522705078125 +96491 -0.364501953125 +96492 -0.31890869140625 +96493 -0.327423095703125 +96494 -0.270263671875 +96495 -0.277008056640625 +96496 -0.24761962890625 +96497 -0.253570556640625 +96498 -0.2376708984375 +96499 -0.243377685546875 +96500 -0.19354248046875 +96501 -0.197967529296875 +96502 -0.11370849609375 +96503 -0.115753173828125 +96504 -0.036407470703125 +96505 -0.036285400390625 +96506 0.033477783203125 +96507 0.03546142578125 +96508 0.0885009765625 +96509 0.091827392578125 +96510 0.10601806640625 +96511 0.10943603515625 +96512 0.12213134765625 +96513 0.126007080078125 +96514 0.152740478515625 +96515 0.15814208984375 +96516 0.1719970703125 +96517 0.178619384765625 +96518 0.1649169921875 +96519 0.171295166015625 +96520 0.12591552734375 +96521 0.13006591796875 +96522 0.080780029296875 +96523 0.0823974609375 +96524 0.02886962890625 +96525 0.02752685546875 +96526 -0.059173583984375 +96527 -0.06591796875 +96528 -0.147552490234375 +96529 -0.15972900390625 +96530 -0.198455810546875 +96531 -0.2135009765625 +96532 -0.219207763671875 +96533 -0.235107421875 +96534 -0.18743896484375 +96535 -0.200653076171875 +96536 -0.11199951171875 +96537 -0.119598388671875 +96538 -0.023956298828125 +96539 -0.025115966796875 +96540 0.0792236328125 +96541 0.085479736328125 +96542 0.16546630859375 +96543 0.17791748046875 +96544 0.200408935546875 +96545 0.2154541015625 +96546 0.196533203125 +96547 0.21142578125 +96548 0.16265869140625 +96549 0.17529296875 +96550 0.1192626953125 +96551 0.12890625 +96552 0.094329833984375 +96553 0.1021728515625 +96554 0.068756103515625 +96555 0.074676513671875 +96556 0.03997802734375 +96557 0.043701171875 +96558 0.0355224609375 +96559 0.038665771484375 +96560 0.071502685546875 +96561 0.0767822265625 +96562 0.1324462890625 +96563 0.141571044921875 +96564 0.175201416015625 +96565 0.186920166015625 +96566 0.17767333984375 +96567 0.189239501953125 +96568 0.131256103515625 +96569 0.139373779296875 +96570 0.04034423828125 +96571 0.042022705078125 +96572 -0.07305908203125 +96573 -0.07928466796875 +96574 -0.204071044921875 +96575 -0.219329833984375 +96576 -0.343109130859375 +96577 -0.36785888671875 +96578 -0.462188720703125 +96579 -0.4949951171875 +96580 -0.51983642578125 +96581 -0.55645751953125 +96582 -0.4755859375 +96583 -0.509002685546875 +96584 -0.351287841796875 +96585 -0.3759765625 +96586 -0.20489501953125 +96587 -0.21929931640625 +96588 -0.059967041015625 +96589 -0.06414794921875 +96590 0.085113525390625 +96591 0.091156005859375 +96592 0.2200927734375 +96593 0.23565673828125 +96594 0.32000732421875 +96595 0.3426513671875 +96596 0.368743896484375 +96597 0.3948974609375 +96598 0.36322021484375 +96599 0.38909912109375 +96600 0.302276611328125 +96601 0.324005126953125 +96602 0.208587646484375 +96603 0.223907470703125 +96604 0.115264892578125 +96605 0.1241455078125 +96606 0.0338134765625 +96607 0.037017822265625 +96608 -0.0101318359375 +96609 -0.010101318359375 +96610 -0.018646240234375 +96611 -0.019378662109375 +96612 -0.02154541015625 +96613 -0.022674560546875 +96614 -0.00140380859375 +96615 -0.001373291015625 +96616 0.053009033203125 +96617 0.0565185546875 +96618 0.10040283203125 +96619 0.10693359375 +96620 0.091400146484375 +96621 0.097076416015625 +96622 0.04083251953125 +96623 0.0428466796875 +96624 -0.015899658203125 +96625 -0.017913818359375 +96626 -0.069976806640625 +96627 -0.075775146484375 +96628 -0.11077880859375 +96629 -0.119384765625 +96630 -0.148590087890625 +96631 -0.159698486328125 +96632 -0.188873291015625 +96633 -0.202606201171875 +96634 -0.232086181640625 +96635 -0.248626708984375 +96636 -0.285186767578125 +96637 -0.305206298828125 +96638 -0.338653564453125 +96639 -0.362152099609375 +96640 -0.36627197265625 +96641 -0.391448974609375 +96642 -0.3326416015625 +96643 -0.355316162109375 +96644 -0.234222412109375 +96645 -0.25 +96646 -0.087310791015625 +96647 -0.0928955078125 +96648 0.08282470703125 +96649 0.089019775390625 +96650 0.219573974609375 +96651 0.235198974609375 +96652 0.297760009765625 +96653 0.31878662109375 +96654 0.33502197265625 +96655 0.358612060546875 +96656 0.3248291015625 +96657 0.34771728515625 +96658 0.2667236328125 +96659 0.285614013671875 +96660 0.20831298828125 +96661 0.22314453125 +96662 0.18365478515625 +96663 0.19671630859375 +96664 0.167938232421875 +96665 0.1798095703125 +96666 0.14532470703125 +96667 0.155517578125 +96668 0.141448974609375 +96669 0.15118408203125 +96670 0.147003173828125 +96671 0.15692138671875 +96672 0.12359619140625 +96673 0.131744384765625 +96674 0.0947265625 +96675 0.10076904296875 +96676 0.082000732421875 +96677 0.08709716796875 +96678 0.051849365234375 +96679 0.054840087890625 +96680 -0.007904052734375 +96681 -0.009033203125 +96682 -0.0968017578125 +96683 -0.104034423828125 +96684 -0.214202880859375 +96685 -0.22943115234375 +96686 -0.33233642578125 +96687 -0.355560302734375 +96688 -0.41326904296875 +96689 -0.44195556640625 +96690 -0.4432373046875 +96691 -0.473876953125 +96692 -0.43487548828125 +96693 -0.46484375 +96694 -0.392181396484375 +96695 -0.41912841796875 +96696 -0.31292724609375 +96697 -0.3343505859375 +96698 -0.213409423828125 +96699 -0.22796630859375 +96700 -0.115692138671875 +96701 -0.123504638671875 +96702 -0.026031494140625 +96703 -0.027679443359375 +96704 0.072540283203125 +96705 0.07763671875 +96706 0.199462890625 +96707 0.213226318359375 +96708 0.363861083984375 +96709 0.388824462890625 +96710 0.54541015625 +96711 0.582763671875 +96712 0.68701171875 +96713 0.7340087890625 +96714 0.748931884765625 +96715 0.80010986328125 +96716 0.72857666015625 +96717 0.778289794921875 +96718 0.622711181640625 +96719 0.665130615234375 +96720 0.430419921875 +96721 0.459625244140625 +96722 0.186676025390625 +96723 0.199188232421875 +96724 -0.04718017578125 +96725 -0.0506591796875 +96726 -0.2177734375 +96727 -0.23291015625 +96728 -0.3087158203125 +96729 -0.330078125 +96730 -0.344512939453125 +96731 -0.36834716796875 +96732 -0.3543701171875 +96733 -0.378875732421875 +96734 -0.3525390625 +96735 -0.376922607421875 +96736 -0.355133056640625 +96737 -0.379638671875 +96738 -0.366241455078125 +96739 -0.391448974609375 +96740 -0.36053466796875 +96741 -0.385284423828125 +96742 -0.3199462890625 +96743 -0.34185791015625 +96744 -0.2647705078125 +96745 -0.2828369140625 +96746 -0.235565185546875 +96747 -0.251556396484375 +96748 -0.24920654296875 +96749 -0.266082763671875 +96750 -0.2559814453125 +96751 -0.273284912109375 +96752 -0.20306396484375 +96753 -0.21673583984375 +96754 -0.12017822265625 +96755 -0.128204345703125 +96756 -0.063873291015625 +96757 -0.068084716796875 +96758 -0.040374755859375 +96759 -0.04302978515625 +96760 -0.02288818359375 +96761 -0.024383544921875 +96762 0.019439697265625 +96763 0.020782470703125 +96764 0.116607666015625 +96765 0.124542236328125 +96766 0.24151611328125 +96767 0.2579345703125 +96768 0.3544921875 +96769 0.379150390625 +96770 0.447967529296875 +96771 0.47991943359375 +96772 0.4932861328125 +96773 0.528167724609375 +96774 0.4786376953125 +96775 0.5111083984375 +96776 0.42877197265625 +96777 0.4561767578125 +96778 0.383544921875 +96779 0.407440185546875 +96780 0.36004638671875 +96781 0.38372802734375 +96782 0.332916259765625 +96783 0.356842041015625 +96784 0.288787841796875 +96785 0.311798095703125 +96786 0.229888916015625 +96787 0.2508544921875 +96788 0.148681640625 +96789 0.165374755859375 +96790 0.027191162109375 +96791 0.03521728515625 +96792 -0.1365966796875 +96793 -0.14208984375 +96794 -0.3145751953125 +96795 -0.335662841796875 +96796 -0.4967041015625 +96797 -0.534576416015625 +96798 -0.667572021484375 +96799 -0.721893310546875 +96800 -0.772003173828125 +96801 -0.836669921875 +96802 -0.76812744140625 +96803 -0.8326416015625 +96804 -0.6739501953125 +96805 -0.7296142578125 +96806 -0.5391845703125 +96807 -0.582550048828125 +96808 -0.407958984375 +96809 -0.440093994140625 +96810 -0.30035400390625 +96811 -0.324310302734375 +96812 -0.18609619140625 +96813 -0.20147705078125 +96814 -0.04095458984375 +96815 -0.044647216796875 +96816 0.096710205078125 +96817 0.103973388671875 +96818 0.188751220703125 +96819 0.202392578125 +96820 0.24755859375 +96821 0.264495849609375 +96822 0.31695556640625 +96823 0.338897705078125 +96824 0.41326904296875 +96825 0.443817138671875 +96826 0.505584716796875 +96827 0.545074462890625 +96828 0.5709228515625 +96829 0.6173095703125 +96830 0.60205078125 +96831 0.6524658203125 +96832 0.610626220703125 +96833 0.66339111328125 +96834 0.602203369140625 +96835 0.6561279296875 +96836 0.555267333984375 +96837 0.606781005859375 +96838 0.457183837890625 +96839 0.501190185546875 +96840 0.32025146484375 +96841 0.352783203125 +96842 0.15814208984375 +96843 0.176544189453125 +96844 -0.035552978515625 +96845 -0.034820556640625 +96846 -0.23980712890625 +96847 -0.258209228515625 +96848 -0.40826416015625 +96849 -0.44244384765625 +96850 -0.529754638671875 +96851 -0.5753173828125 +96852 -0.59991455078125 +96853 -0.65203857421875 +96854 -0.590728759765625 +96855 -0.641632080078125 +96856 -0.518524169921875 +96857 -0.562164306640625 +96858 -0.423492431640625 +96859 -0.458038330078125 +96860 -0.32489013671875 +96861 -0.350555419921875 +96862 -0.24163818359375 +96863 -0.260528564453125 +96864 -0.177642822265625 +96865 -0.192108154296875 +96866 -0.1300048828125 +96867 -0.141937255859375 +96868 -0.091766357421875 +96869 -0.1021728515625 +96870 -0.0540771484375 +96871 -0.062896728515625 +96872 -0.006011962890625 +96873 -0.011932373046875 +96874 0.063262939453125 +96875 0.062835693359375 +96876 0.142181396484375 +96877 0.148712158203125 +96878 0.227081298828125 +96879 0.241729736328125 +96880 0.324493408203125 +96881 0.34912109375 +96882 0.422119140625 +96883 0.457305908203125 +96884 0.499725341796875 +96885 0.54388427734375 +96886 0.524871826171875 +96887 0.5728759765625 +96888 0.463531494140625 +96889 0.506591796875 +96890 0.321441650390625 +96891 0.351226806640625 +96892 0.13458251953125 +96893 0.146514892578125 +96894 -0.0496826171875 +96895 -0.05523681640625 +96896 -0.19708251953125 +96897 -0.21624755859375 +96898 -0.3060302734375 +96899 -0.334930419921875 +96900 -0.368988037109375 +96901 -0.402984619140625 +96902 -0.404754638671875 +96903 -0.4412841796875 +96904 -0.454803466796875 +96905 -0.49578857421875 +96906 -0.513397216796875 +96907 -0.5601806640625 +96908 -0.550018310546875 +96909 -0.600738525390625 +96910 -0.53466796875 +96911 -0.584228515625 +96912 -0.43902587890625 +96913 -0.47930908203125 +96914 -0.2572021484375 +96915 -0.27935791015625 +96916 -0.011444091796875 +96917 -0.0089111328125 +96918 0.240997314453125 +96919 0.268798828125 +96920 0.435943603515625 +96921 0.482818603515625 +96922 0.54669189453125 +96923 0.60369873046875 +96924 0.59027099609375 +96925 0.650421142578125 +96926 0.603729248046875 +96927 0.66400146484375 +96928 0.584320068359375 +96929 0.6414794921875 +96930 0.522705078125 +96931 0.572540283203125 +96932 0.455841064453125 +96933 0.498138427734375 +96934 0.402862548828125 +96935 0.439453125 +96936 0.3448486328125 +96937 0.375518798828125 +96938 0.253021240234375 +96939 0.274505615234375 +96940 0.1024169921875 +96941 0.1087646484375 +96942 -0.086761474609375 +96943 -0.099395751953125 +96944 -0.28570556640625 +96945 -0.3182373046875 +96946 -0.495452880859375 +96947 -0.5489501953125 +96948 -0.69989013671875 +96949 -0.7738037109375 +96950 -0.851104736328125 +96951 -0.86383056640625 +96952 -0.861541748046875 +96953 -0.870391845703125 +96954 -0.861602783203125 +96955 -0.86895751953125 +96956 -0.8555908203125 +96957 -0.861053466796875 +96958 -0.738067626953125 +96959 -0.765869140625 +96960 -0.53033447265625 +96961 -0.5301513671875 +96962 -0.247589111328125 +96963 -0.214691162109375 +96964 0.071197509765625 +96965 0.137359619140625 +96966 0.379638671875 +96967 0.474822998046875 +96968 0.64556884765625 +96969 0.76239013671875 +96970 0.844512939453125 +96971 0.867462158203125 +96972 0.867828369140625 +96973 0.870361328125 +96974 0.870361328125 +96975 0.86480712890625 +96976 0.865264892578125 +96977 0.831817626953125 +96978 0.85516357421875 +96979 0.677581787109375 +96980 0.7283935546875 +96981 0.495880126953125 +96982 0.573974609375 +96983 0.30767822265625 +96984 0.4000244140625 +96985 0.116180419921875 +96986 0.177978515625 +96987 -0.110748291015625 +96988 -0.098602294921875 +96989 -0.381805419921875 +96990 -0.39166259765625 +96991 -0.6572265625 +96992 -0.647979736328125 +96993 -0.857421875 +96994 -0.829864501953125 +96995 -0.870391845703125 +96996 -0.86297607421875 +96997 -0.870391845703125 +96998 -0.8682861328125 +96999 -0.86444091796875 +97000 -0.870391845703125 +97001 -0.85723876953125 +97002 -0.86871337890625 +97003 -0.790008544921875 +97004 -0.858123779296875 +97005 -0.62847900390625 +97006 -0.7071533203125 +97007 -0.3956298828125 +97008 -0.474212646484375 +97009 -0.126708984375 +97010 -0.214202880859375 +97011 0.150115966796875 +97012 0.061981201171875 +97013 0.424041748046875 +97014 0.33013916015625 +97015 0.670623779296875 +97016 0.555816650390625 +97017 0.854522705078125 +97018 0.723907470703125 +97019 0.866485595703125 +97020 0.821685791015625 +97021 0.86920166015625 +97022 0.8558349609375 +97023 0.8653564453125 +97024 0.8565673828125 +97025 0.857147216796875 +97026 0.840728759765625 +97027 0.766845703125 +97028 0.77374267578125 +97029 0.628509521484375 +97030 0.66845703125 +97031 0.462127685546875 +97032 0.548797607421875 +97033 0.297210693359375 +97034 0.4268798828125 +97035 0.14862060546875 +97036 0.283782958984375 +97037 -0.00537109375 +97038 0.126739501953125 +97039 -0.15753173828125 +97040 -0.046966552734375 +97041 -0.31304931640625 +97042 -0.249542236328125 +97043 -0.48876953125 +97044 -0.440399169921875 +97045 -0.6416015625 +97046 -0.59857177734375 +97047 -0.751373291015625 +97048 -0.745025634765625 +97049 -0.84619140625 +97050 -0.855987548828125 +97051 -0.861297607421875 +97052 -0.863800048828125 +97053 -0.863250732421875 +97054 -0.863189697265625 +97055 -0.856597900390625 +97056 -0.855438232421875 +97057 -0.7498779296875 +97058 -0.778289794921875 +97059 -0.624542236328125 +97060 -0.661590576171875 +97061 -0.47808837890625 +97062 -0.462982177734375 +97063 -0.253387451171875 +97064 -0.222991943359375 +97065 0.003692626953125 +97066 -0.00164794921875 +97067 0.2257080078125 +97068 0.2117919921875 +97069 0.427154541015625 +97070 0.445648193359375 +97071 0.643218994140625 +97072 0.691864013671875 +97073 0.855926513671875 +97074 0.8594970703125 +97075 0.870361328125 +97076 0.870361328125 +97077 0.870361328125 +97078 0.870361328125 +97079 0.862762451171875 +97080 0.8629150390625 +97081 0.79669189453125 +97082 0.790863037109375 +97083 0.595794677734375 +97084 0.6055908203125 +97085 0.362152099609375 +97086 0.402740478515625 +97087 0.1270751953125 +97088 0.2022705078125 +97089 -0.086944580078125 +97090 0.006622314453125 +97091 -0.2784423828125 +97092 -0.214813232421875 +97093 -0.484832763671875 +97094 -0.4798583984375 +97095 -0.729583740234375 +97096 -0.7462158203125 +97097 -0.86688232421875 +97098 -0.86614990234375 +97099 -0.870391845703125 +97100 -0.870391845703125 +97101 -0.86859130859375 +97102 -0.870147705078125 +97103 -0.86279296875 +97104 -0.863006591796875 +97105 -0.817962646484375 +97106 -0.77215576171875 +97107 -0.6116943359375 +97108 -0.5177001953125 +97109 -0.3128662109375 +97110 -0.203094482421875 +97111 0.039398193359375 +97112 0.15142822265625 +97113 0.422821044921875 +97114 0.5162353515625 +97115 0.805145263671875 +97116 0.83343505859375 +97117 0.870361328125 +97118 0.870361328125 +97119 0.870361328125 +97120 0.870361328125 +97121 0.860015869140625 +97122 0.860992431640625 +97123 0.727935791015625 +97124 0.75042724609375 +97125 0.48114013671875 +97126 0.542449951171875 +97127 0.2059326171875 +97128 0.320953369140625 +97129 -0.06103515625 +97130 0.1038818359375 +97131 -0.29913330078125 +97132 -0.114471435546875 +97133 -0.516204833984375 +97134 -0.343231201171875 +97135 -0.7252197265625 +97136 -0.55914306640625 +97137 -0.85980224609375 +97138 -0.733428955078125 +97139 -0.870391845703125 +97140 -0.844024658203125 +97141 -0.870391845703125 +97142 -0.8544921875 +97143 -0.858062744140625 +97144 -0.769134521484375 +97145 -0.673004150390625 +97146 -0.64306640625 +97147 -0.42694091796875 +97148 -0.52520751953125 +97149 -0.2100830078125 +97150 -0.424163818359375 +97151 -0.0362548828125 +97152 -0.324798583984375 +97153 0.10943603515625 +97154 -0.219085693359375 +97155 0.23516845703125 +97156 -0.078948974609375 +97157 0.373687744140625 +97158 0.087554931640625 +97159 0.517791748046875 +97160 0.221160888671875 +97161 0.602783203125 +97162 0.32427978515625 +97163 0.635711669921875 +97164 0.42608642578125 +97165 0.655181884765625 +97166 0.5201416015625 +97167 0.65948486328125 +97168 0.603668212890625 +97169 0.651275634765625 +97170 0.661163330078125 +97171 0.61846923828125 +97172 0.667572021484375 +97173 0.53753662109375 +97174 0.615203857421875 +97175 0.404144287109375 +97176 0.5040283203125 +97177 0.22186279296875 +97178 0.343505859375 +97179 0.003997802734375 +97180 0.157379150390625 +97181 -0.22100830078125 +97182 -0.02935791015625 +97183 -0.42449951171875 +97184 -0.192413330078125 +97185 -0.579833984375 +97186 -0.2904052734375 +97187 -0.641876220703125 +97188 -0.326690673828125 +97189 -0.6177978515625 +97190 -0.357025146484375 +97191 -0.575531005859375 +97192 -0.387298583984375 +97193 -0.526336669921875 +97194 -0.37518310546875 +97195 -0.42645263671875 +97196 -0.30108642578125 +97197 -0.2581787109375 +97198 -0.202239990234375 +97199 -0.068695068359375 +97200 -0.11859130859375 +97201 0.09222412109375 +97202 -0.040740966796875 +97203 0.232147216796875 +97204 0.033233642578125 +97205 0.3509521484375 +97206 0.07086181640625 +97207 0.410064697265625 +97208 0.040618896484375 +97209 0.372955322265625 +97210 -0.044189453125 +97211 0.2554931640625 +97212 -0.14190673828125 +97213 0.10711669921875 +97214 -0.23785400390625 +97215 -0.052886962890625 +97216 -0.3013916015625 +97217 -0.186279296875 +97218 -0.283233642578125 +97219 -0.23291015625 +97220 -0.20123291015625 +97221 -0.209442138671875 +97222 -0.10968017578125 +97223 -0.174163818359375 +97224 -0.011566162109375 +97225 -0.126739501953125 +97226 0.106658935546875 +97227 -0.048126220703125 +97228 0.225921630859375 +97229 0.0426025390625 +97230 0.311187744140625 +97231 0.10748291015625 +97232 0.35638427734375 +97233 0.1409912109375 +97234 0.4080810546875 +97235 0.19708251953125 +97236 0.464691162109375 +97237 0.273651123046875 +97238 0.48089599609375 +97239 0.31768798828125 +97240 0.4686279296875 +97241 0.341094970703125 +97242 0.4510498046875 +97243 0.368011474609375 +97244 0.407989501953125 +97245 0.37249755859375 +97246 0.29522705078125 +97247 0.30072021484375 +97248 0.11474609375 +97249 0.1517333984375 +97250 -0.07855224609375 +97251 -0.01470947265625 +97252 -0.27313232421875 +97253 -0.1883544921875 +97254 -0.469879150390625 +97255 -0.372711181640625 +97256 -0.620147705078125 +97257 -0.51397705078125 +97258 -0.687469482421875 +97259 -0.57177734375 +97260 -0.66546630859375 +97261 -0.53948974609375 +97262 -0.569793701171875 +97263 -0.43511962890625 +97264 -0.433807373046875 +97265 -0.2962646484375 +97266 -0.2918701171875 +97267 -0.161102294921875 +97268 -0.15771484375 +97269 -0.0435791015625 +97270 -0.029754638671875 +97271 0.060394287109375 +97272 0.07745361328125 +97273 0.13665771484375 +97274 0.148468017578125 +97275 0.170135498046875 +97276 0.185089111328125 +97277 0.16552734375 +97278 0.21514892578125 +97279 0.15728759765625 +97280 0.241607666015625 +97281 0.150787353515625 +97282 0.241943359375 +97283 0.12200927734375 +97284 0.222625732421875 +97285 0.080108642578125 +97286 0.205413818359375 +97287 0.05126953125 +97288 0.213592529296875 +97289 0.062896728515625 +97290 0.2286376953125 +97291 0.09271240234375 +97292 0.2108154296875 +97293 0.092987060546875 +97294 0.1739501953125 +97295 0.07855224609375 +97296 0.132232666015625 +97297 0.06427001953125 +97298 0.0743408203125 +97299 0.0347900390625 +97300 0.000518798828125 +97301 -0.01171875 +97302 -0.070953369140625 +97303 -0.056060791015625 +97304 -0.10198974609375 +97305 -0.055511474609375 +97306 -0.09124755859375 +97307 -0.010467529296875 +97308 -0.083221435546875 +97309 0.02508544921875 +97310 -0.0985107421875 +97311 0.025665283203125 +97312 -0.11431884765625 +97313 0.017333984375 +97314 -0.128875732421875 +97315 0.00189208984375 +97316 -0.151702880859375 +97317 -0.03173828125 +97318 -0.17315673828125 +97319 -0.071502685546875 +97320 -0.209381103515625 +97321 -0.13543701171875 +97322 -0.25848388671875 +97323 -0.219970703125 +97324 -0.30096435546875 +97325 -0.300506591796875 +97326 -0.337677001953125 +97327 -0.376312255859375 +97328 -0.343597412109375 +97329 -0.416107177734375 +97330 -0.278778076171875 +97331 -0.371124267578125 +97332 -0.145416259765625 +97333 -0.242279052734375 +97334 0.021087646484375 +97335 -0.069732666015625 +97336 0.201995849609375 +97337 0.125640869140625 +97338 0.370208740234375 +97339 0.31268310546875 +97340 0.494476318359375 +97341 0.45501708984375 +97342 0.57659912109375 +97343 0.554779052734375 +97344 0.615753173828125 +97345 0.61065673828125 +97346 0.602630615234375 +97347 0.610931396484375 +97348 0.517578125 +97349 0.531463623046875 +97350 0.37530517578125 +97351 0.3883056640625 +97352 0.22222900390625 +97353 0.23468017578125 +97354 0.08062744140625 +97355 0.095245361328125 +97356 -0.026092529296875 +97357 -0.00396728515625 +97358 -0.08447265625 +97359 -0.04852294921875 +97360 -0.107635498046875 +97361 -0.055145263671875 +97362 -0.138916015625 +97363 -0.0758056640625 +97364 -0.20166015625 +97365 -0.138702392578125 +97366 -0.266021728515625 +97367 -0.209197998046875 +97368 -0.3333740234375 +97369 -0.289031982421875 +97370 -0.404449462890625 +97371 -0.37884521484375 +97372 -0.460662841796875 +97373 -0.456329345703125 +97374 -0.4984130859375 +97375 -0.51641845703125 +97376 -0.484649658203125 +97377 -0.519287109375 +97378 -0.4146728515625 +97379 -0.458251953125 +97380 -0.33331298828125 +97381 -0.384796142578125 +97382 -0.26263427734375 +97383 -0.323699951171875 +97384 -0.198822021484375 +97385 -0.269287109375 +97386 -0.12042236328125 +97387 -0.1951904296875 +97388 -0.027008056640625 +97389 -0.100006103515625 +97390 0.0579833984375 +97391 -0.01055908203125 +97392 0.159881591796875 +97393 0.1033935546875 +97394 0.28466796875 +97395 0.24908447265625 +97396 0.387115478515625 +97397 0.373199462890625 +97398 0.452484130859375 +97399 0.45806884765625 +97400 0.48785400390625 +97401 0.511474609375 +97402 0.52105712890625 +97403 0.565399169921875 +97404 0.545684814453125 +97405 0.61138916015625 +97406 0.511810302734375 +97407 0.5897216796875 +97408 0.411956787109375 +97409 0.4906005859375 +97410 0.2618408203125 +97411 0.33148193359375 +97412 0.09234619140625 +97413 0.147796630859375 +97414 -0.06036376953125 +97415 -0.01873779296875 +97416 -0.172088623046875 +97417 -0.140289306640625 +97418 -0.221282958984375 +97419 -0.191986083984375 +97420 -0.2166748046875 +97421 -0.184295654296875 +97422 -0.196197509765625 +97423 -0.161834716796875 +97424 -0.1956787109375 +97425 -0.166595458984375 +97426 -0.21148681640625 +97427 -0.19390869140625 +97428 -0.227691650390625 +97429 -0.22442626953125 +97430 -0.26324462890625 +97431 -0.279754638671875 +97432 -0.301055908203125 +97433 -0.3389892578125 +97434 -0.30126953125 +97435 -0.3543701171875 +97436 -0.28350830078125 +97437 -0.348175048828125 +97438 -0.253173828125 +97439 -0.32598876953125 +97440 -0.185699462890625 +97441 -0.2581787109375 +97442 -0.077362060546875 +97443 -0.139801025390625 +97444 0.05914306640625 +97445 0.014617919921875 +97446 0.171966552734375 +97447 0.144378662109375 +97448 0.236907958984375 +97449 0.221038818359375 +97450 0.276214599609375 +97451 0.27069091796875 +97452 0.290740966796875 +97453 0.294036865234375 +97454 0.298431396484375 +97455 0.311767578125 +97456 0.31268310546875 +97457 0.339141845703125 +97458 0.320404052734375 +97459 0.360260009765625 +97460 0.309783935546875 +97461 0.360504150390625 +97462 0.2550048828125 +97463 0.308380126953125 +97464 0.1380615234375 +97465 0.18170166015625 +97466 -0.019989013671875 +97467 0.0047607421875 +97468 -0.1793212890625 +97469 -0.17559814453125 +97470 -0.301727294921875 +97471 -0.3143310546875 +97472 -0.350311279296875 +97473 -0.36785888671875 +97474 -0.3470458984375 +97475 -0.36248779296875 +97476 -0.329986572265625 +97477 -0.343536376953125 +97478 -0.2916259765625 +97479 -0.3018798828125 +97480 -0.227081298828125 +97481 -0.231414794921875 +97482 -0.12451171875 +97483 -0.117645263671875 +97484 -0.011505126953125 +97485 0.007049560546875 +97486 0.06549072265625 +97487 0.087982177734375 +97488 0.117950439453125 +97489 0.13946533203125 +97490 0.156097412109375 +97491 0.17425537109375 +97492 0.175933837890625 +97493 0.188201904296875 +97494 0.1685791015625 +97495 0.171234130859375 +97496 0.12957763671875 +97497 0.118438720703125 +97498 0.081573486328125 +97499 0.05706787109375 +97500 0.026214599609375 +97501 -0.010711669921875 +97502 -0.041961669921875 +97503 -0.0914306640625 +97504 -0.103759765625 +97505 -0.162322998046875 +97506 -0.134796142578125 +97507 -0.194549560546875 +97508 -0.102203369140625 +97509 -0.1492919921875 +97510 -0.00152587890625 +97511 -0.02166748046875 +97512 0.1136474609375 +97513 0.124053955078125 +97514 0.17926025390625 +97515 0.211151123046875 +97516 0.196441650390625 +97517 0.240447998046875 +97518 0.191009521484375 +97519 0.242218017578125 +97520 0.171112060546875 +97521 0.2257080078125 +97522 0.139923095703125 +97523 0.194366455078125 +97524 0.070220947265625 +97525 0.115509033203125 +97526 -0.017913818359375 +97527 0.0128173828125 +97528 -0.074127197265625 +97529 -0.053802490234375 +97530 -0.12054443359375 +97531 -0.110626220703125 +97532 -0.192413330078125 +97533 -0.199493408203125 +97534 -0.26806640625 +97535 -0.29437255859375 +97536 -0.295135498046875 +97537 -0.33221435546875 +97538 -0.246734619140625 +97539 -0.27972412109375 +97540 -0.162811279296875 +97541 -0.185333251953125 +97542 -0.108062744140625 +97543 -0.128204345703125 +97544 -0.089111328125 +97545 -0.115692138671875 +97546 -0.081298828125 +97547 -0.116455078125 +97548 -0.06536865234375 +97549 -0.105926513671875 +97550 -0.017364501953125 +97551 -0.053955078125 +97552 0.06988525390625 +97553 0.048797607421875 +97554 0.159881591796875 +97555 0.157318115234375 +97556 0.204376220703125 +97557 0.212005615234375 +97558 0.207977294921875 +97559 0.218475341796875 +97560 0.219757080078125 +97561 0.23724365234375 +97562 0.2698974609375 +97563 0.30535888671875 +97564 0.32513427734375 +97565 0.38128662109375 +97566 0.3369140625 +97567 0.404449462890625 +97568 0.32147216796875 +97569 0.3944091796875 +97570 0.3094482421875 +97571 0.3885498046875 +97572 0.281707763671875 +97573 0.362640380859375 +97574 0.203765869140625 +97575 0.27362060546875 +97576 0.072418212890625 +97577 0.11712646484375 +97578 -0.070098876953125 +97579 -0.054901123046875 +97580 -0.181915283203125 +97581 -0.19085693359375 +97582 -0.258941650390625 +97583 -0.28570556640625 +97584 -0.30108642578125 +97585 -0.339263916015625 +97586 -0.329437255859375 +97587 -0.3775634765625 +97588 -0.380645751953125 +97589 -0.445709228515625 +97590 -0.447998046875 +97591 -0.535064697265625 +97592 -0.51837158203125 +97593 -0.629058837890625 +97594 -0.567779541015625 +97595 -0.697601318359375 +97596 -0.56683349609375 +97597 -0.70391845703125 +97598 -0.51141357421875 +97599 -0.6424560546875 +97600 -0.384063720703125 +97601 -0.491241455078125 +97602 -0.197479248046875 +97603 -0.265716552734375 +97604 0.0013427734375 +97605 -0.023712158203125 +97606 0.185577392578125 +97607 0.201751708984375 +97608 0.326995849609375 +97609 0.375823974609375 +97610 0.414764404296875 +97611 0.485076904296875 +97612 0.480712890625 +97613 0.56884765625 +97614 0.5311279296875 +97615 0.634765625 +97616 0.529693603515625 +97617 0.63763427734375 +97618 0.4674072265625 +97619 0.5660400390625 +97620 0.3865966796875 +97621 0.4720458984375 +97622 0.328948974609375 +97623 0.40692138671875 +97624 0.300537109375 +97625 0.3778076171875 +97626 0.29534912109375 +97627 0.376953125 +97628 0.287445068359375 +97629 0.371978759765625 +97630 0.236846923828125 +97631 0.313140869140625 +97632 0.1307373046875 +97633 0.184417724609375 +97634 -0.010223388671875 +97635 0.011199951171875 +97636 -0.157379150390625 +97637 -0.171051025390625 +97638 -0.290618896484375 +97639 -0.33740234375 +97640 -0.397216796875 +97641 -0.47198486328125 +97642 -0.465728759765625 +97643 -0.560394287109375 +97644 -0.478485107421875 +97645 -0.58056640625 +97646 -0.447845458984375 +97647 -0.54754638671875 +97648 -0.412200927734375 +97649 -0.508575439453125 +97650 -0.368438720703125 +97651 -0.459503173828125 +97652 -0.311981201171875 +97653 -0.394378662109375 +97654 -0.27484130859375 +97655 -0.35260009765625 +97656 -0.239044189453125 +97657 -0.31170654296875 +97658 -0.14471435546875 +97659 -0.197418212890625 +97660 0.00946044921875 +97661 -0.007965087890625 +97662 0.1837158203125 +97663 0.207489013671875 +97664 0.345977783203125 +97665 0.409210205078125 +97666 0.47601318359375 +97667 0.57208251953125 +97668 0.549560546875 +97669 0.66595458984375 +97670 0.540863037109375 +97671 0.65875244140625 +97672 0.463836669921875 +97673 0.56744384765625 +97674 0.3504638671875 +97675 0.431396484375 +97676 0.236358642578125 +97677 0.29443359375 +97678 0.14263916015625 +97679 0.182464599609375 +97680 0.04376220703125 +97681 0.06365966796875 +97682 -0.0714111328125 +97683 -0.075958251953125 +97684 -0.16485595703125 +97685 -0.189422607421875 +97686 -0.23260498046875 +97687 -0.271942138671875 +97688 -0.28997802734375 +97689 -0.342529296875 +97690 -0.307098388671875 +97691 -0.364166259765625 +97692 -0.276214599609375 +97693 -0.327239990234375 +97694 -0.233917236328125 +97695 -0.2769775390625 +97696 -0.212921142578125 +97697 -0.253692626953125 +97698 -0.20220947265625 +97699 -0.24365234375 +97700 -0.162811279296875 +97701 -0.1983642578125 +97702 -0.093597412109375 +97703 -0.116241455078125 +97704 -0.026641845703125 +97705 -0.036834716796875 +97706 0.033843994140625 +97707 0.034881591796875 +97708 0.08154296875 +97709 0.09124755859375 +97710 0.09747314453125 +97711 0.10888671875 +97712 0.112030029296875 +97713 0.125518798828125 +97714 0.1385498046875 +97715 0.15771484375 +97716 0.155029296875 +97717 0.17828369140625 +97718 0.148468017578125 +97719 0.17108154296875 +97720 0.113983154296875 +97721 0.129974365234375 +97722 0.073822021484375 +97723 0.082427978515625 +97724 0.02752685546875 +97725 0.027679443359375 +97726 -0.050140380859375 +97727 -0.065643310546875 +97728 -0.128173828125 +97729 -0.15936279296875 +97730 -0.173828125 +97731 -0.21307373046875 +97732 -0.193359375 +97733 -0.234649658203125 +97734 -0.1673583984375 +97735 -0.2001953125 +97736 -0.103363037109375 +97737 -0.119171142578125 +97738 -0.02813720703125 +97739 -0.024749755859375 +97740 0.060577392578125 +97741 0.085784912109375 +97742 0.135101318359375 +97743 0.178131103515625 +97744 0.165771484375 +97745 0.215576171875 +97746 0.163299560546875 +97747 0.211456298828125 +97748 0.13525390625 +97749 0.17523193359375 +97750 0.099212646484375 +97751 0.128753662109375 +97752 0.079254150390625 +97753 0.1019287109375 +97754 0.058807373046875 +97755 0.0743408203125 +97756 0.035552978515625 +97757 0.04327392578125 +97758 0.033203125 +97759 0.038177490234375 +97760 0.065582275390625 +97761 0.076263427734375 +97762 0.119293212890625 +97763 0.14105224609375 +97764 0.157012939453125 +97765 0.186431884765625 +97766 0.15960693359375 +97767 0.188812255859375 +97768 0.11962890625 +97769 0.1390380859375 +97770 0.040863037109375 +97771 0.041778564453125 +97772 -0.0576171875 +97773 -0.079437255859375 +97774 -0.17156982421875 +97775 -0.219390869140625 +97776 -0.29266357421875 +97777 -0.367828369140625 +97778 -0.396697998046875 +97779 -0.494873046875 +97780 -0.447784423828125 +97781 -0.556243896484375 +97782 -0.410919189453125 +97783 -0.508697509765625 +97784 -0.304901123046875 +97785 -0.3756103515625 +97786 -0.179656982421875 +97787 -0.218902587890625 +97788 -0.05548095703125 +97789 -0.063751220703125 +97790 0.06903076171875 +97791 0.091552734375 +97792 0.18499755859375 +97793 0.23602294921875 +97794 0.27093505859375 +97795 0.342987060546875 +97796 0.313232421875 +97797 0.39520263671875 +97798 0.309539794921875 +97799 0.389373779296875 +97800 0.259063720703125 +97801 0.324249267578125 +97802 0.180816650390625 +97803 0.224090576171875 +97804 0.1024169921875 +97805 0.124267578125 +97806 0.033538818359375 +97807 0.037078857421875 +97808 -0.004425048828125 +97809 -0.010101318359375 +97810 -0.013092041015625 +97811 -0.019439697265625 +97812 -0.017059326171875 +97813 -0.022796630859375 +97814 -0.0018310546875 +97815 -0.001556396484375 +97816 0.0419921875 +97817 0.056304931640625 +97818 0.080230712890625 +97819 0.106719970703125 +97820 0.07196044921875 +97821 0.096893310546875 +97822 0.029510498046875 +97823 0.042694091796875 +97824 -0.017791748046875 +97825 -0.018035888671875 +97826 -0.062591552734375 +97827 -0.07586669921875 +97828 -0.096099853515625 +97829 -0.11944580078125 +97830 -0.12689208984375 +97831 -0.15972900390625 +97832 -0.1595458984375 +97833 -0.202606201171875 +97834 -0.194488525390625 +97835 -0.24859619140625 +97836 -0.237548828125 +97837 -0.30517578125 +97838 -0.280853271484375 +97839 -0.36212158203125 +97840 -0.302734375 +97841 -0.39141845703125 +97842 -0.273895263671875 +97843 -0.35528564453125 +97844 -0.191497802734375 +97845 -0.249969482421875 +97846 -0.069091796875 +97847 -0.092864990234375 +97848 0.0723876953125 +97849 0.08905029296875 +97850 0.185943603515625 +97851 0.2352294921875 +97852 0.250732421875 +97853 0.318817138671875 +97854 0.2813720703125 +97855 0.358642578125 +97856 0.272491455078125 +97857 0.347747802734375 +97858 0.2237548828125 +97859 0.28564453125 +97860 0.174652099609375 +97861 0.223175048828125 +97862 0.1534423828125 +97863 0.196746826171875 +97864 0.139617919921875 +97865 0.179840087890625 +97866 0.120086669921875 +97867 0.155548095703125 +97868 0.116119384765625 +97869 0.151214599609375 +97870 0.12005615234375 +97871 0.156951904296875 +97872 0.10009765625 +97873 0.13177490234375 +97874 0.075775146484375 +97875 0.100799560546875 +97876 0.06500244140625 +97877 0.087127685546875 +97878 0.03997802734375 +97879 0.05487060546875 +97880 -0.009429931640625 +97881 -0.009002685546875 +97882 -0.08282470703125 +97883 -0.10400390625 +97884 -0.1796875 +97885 -0.229400634765625 +97886 -0.27703857421875 +97887 -0.35552978515625 +97888 -0.343505859375 +97889 -0.441925048828125 +97890 -0.367706298828125 +97891 -0.473846435546875 +97892 -0.360137939453125 +97893 -0.464813232421875 +97894 -0.324127197265625 +97895 -0.419097900390625 +97896 -0.25787353515625 +97897 -0.334320068359375 +97898 -0.1749267578125 +97899 -0.227935791015625 +97900 -0.093597412109375 +97901 -0.12347412109375 +97902 -0.019073486328125 +97903 -0.02764892578125 +97904 0.06268310546875 +97905 0.077667236328125 +97906 0.167816162109375 +97907 0.2132568359375 +97908 0.303863525390625 +97909 0.38885498046875 +97910 0.45404052734375 +97911 0.582794189453125 +97912 0.57098388671875 +97913 0.734039306640625 +97914 0.621795654296875 +97915 0.800140380859375 +97916 0.604339599609375 +97917 0.7783203125 +97918 0.5159912109375 +97919 0.6651611328125 +97920 0.35601806640625 +97921 0.45965576171875 +97922 0.1534423828125 +97923 0.199188232421875 +97924 -0.040802001953125 +97925 -0.050689697265625 +97926 -0.1824951171875 +97927 -0.23297119140625 +97928 -0.258056640625 +97929 -0.33013916015625 +97930 -0.287811279296875 +97931 -0.368408203125 +97932 -0.295928955078125 +97933 -0.378936767578125 +97934 -0.294281005859375 +97935 -0.376983642578125 +97936 -0.296173095703125 +97937 -0.37969970703125 +97938 -0.305023193359375 +97939 -0.391510009765625 +97940 -0.29986572265625 +97941 -0.385345458984375 +97942 -0.2657470703125 +97943 -0.3419189453125 +97944 -0.219512939453125 +97945 -0.28289794921875 +97946 -0.194793701171875 +97947 -0.251617431640625 +97948 -0.205657958984375 +97949 -0.266143798828125 +97950 -0.210906982421875 +97951 -0.273345947265625 +97952 -0.166748046875 +97953 -0.216796875 +97954 -0.09783935546875 +97955 -0.128265380859375 +97956 -0.051055908203125 +97957 -0.068145751953125 +97958 -0.031585693359375 +97959 -0.0430908203125 +97960 -0.017181396484375 +97961 -0.024444580078125 +97962 0.0177001953125 +97963 0.020721435546875 +97964 0.097991943359375 +97965 0.124481201171875 +97966 0.201202392578125 +97967 0.25787353515625 +97968 0.294921875 +97969 0.379119873046875 +97970 0.37274169921875 +97971 0.47991943359375 +97972 0.4097900390625 +97973 0.5281982421875 +97974 0.396148681640625 +97975 0.511138916015625 +97976 0.3531494140625 +97977 0.456207275390625 +97978 0.31500244140625 +97979 0.407470703125 +97980 0.296356201171875 +97981 0.383758544921875 +97982 0.27532958984375 +97983 0.35687255859375 +97984 0.240325927734375 +97985 0.31182861328125 +97986 0.19305419921875 +97987 0.250885009765625 +97988 0.1268310546875 +97989 0.1654052734375 +97990 0.026031494140625 +97991 0.035247802734375 +97992 -0.111297607421875 +97993 -0.142059326171875 +97994 -0.261199951171875 +97995 -0.33563232421875 +97996 -0.415191650390625 +97997 -0.5345458984375 +97998 -0.56011962890625 +97999 -0.72186279296875 +98000 -0.648773193359375 +98001 -0.836669921875 +98002 -0.645233154296875 +98003 -0.8326416015625 +98004 -0.56494140625 +98005 -0.7296142578125 +98006 -0.4505615234375 +98007 -0.582550048828125 +98008 -0.339813232421875 +98009 -0.440093994140625 +98010 -0.249847412109375 +98011 -0.324310302734375 +98012 -0.154510498046875 +98013 -0.20147705078125 +98014 -0.032867431640625 +98015 -0.044647216796875 +98016 0.08233642578125 +98017 0.103973388671875 +98018 0.15850830078125 +98019 0.202392578125 +98020 0.2064208984375 +98021 0.264495849609375 +98022 0.263824462890625 +98023 0.338897705078125 +98024 0.3448486328125 +98025 0.443817138671875 +98026 0.42303466796875 +98027 0.545074462890625 +98028 0.478668212890625 +98029 0.6173095703125 +98030 0.50555419921875 +98031 0.6524658203125 +98032 0.513702392578125 +98033 0.66339111328125 +98034 0.5078125 +98035 0.6561279296875 +98036 0.469329833984375 +98037 0.606781005859375 +98038 0.38726806640625 +98039 0.501190185546875 +98040 0.272064208984375 +98041 0.352783203125 +98042 0.135345458984375 +98043 0.176544189453125 +98044 -0.028533935546875 +98045 -0.034820556640625 +98046 -0.201629638671875 +98047 -0.258209228515625 +98048 -0.344451904296875 +98049 -0.44244384765625 +98050 -0.4473876953125 +98051 -0.5753173828125 +98052 -0.50689697265625 +98053 -0.65203857421875 +98054 -0.5 +98055 -0.641632080078125 +98056 -0.440277099609375 +98057 -0.562164306640625 +98058 -0.36090087890625 +98059 -0.458038330078125 +98060 -0.277923583984375 +98061 -0.350555419921875 +98062 -0.20709228515625 +98063 -0.260528564453125 +98064 -0.15179443359375 +98065 -0.192108154296875 +98066 -0.109771728515625 +98067 -0.141937255859375 +98068 -0.075469970703125 +98069 -0.1021728515625 +98070 -0.041748046875 +98071 -0.062896728515625 +98072 0.00018310546875 +98073 -0.011932373046875 +98074 0.059173583984375 +98075 0.062835693359375 +98076 0.125640869140625 +98077 0.148712158203125 +98078 0.19647216796875 +98079 0.241729736328125 +98080 0.277008056640625 +98081 0.34912109375 +98082 0.357177734375 +98083 0.457305908203125 +98084 0.42034912109375 +98085 0.54388427734375 +98086 0.439849853515625 +98087 0.5728759765625 +98088 0.387786865234375 +98089 0.506591796875 +98090 0.268951416015625 +98091 0.351226806640625 +98092 0.11309814453125 +98093 0.146514892578125 +98094 -0.040679931640625 +98095 -0.05523681640625 +98096 -0.1640625 +98097 -0.21624755859375 +98098 -0.255645751953125 +98099 -0.334930419921875 +98100 -0.30908203125 +98101 -0.402984619140625 +98102 -0.33978271484375 +98103 -0.4412841796875 +98104 -0.3818359375 +98105 -0.49578857421875 +98106 -0.43048095703125 +98107 -0.5601806640625 +98108 -0.460601806640625 +98109 -0.600738525390625 +98110 -0.447509765625 +98111 -0.584228515625 +98112 -0.367950439453125 +98113 -0.47930908203125 +98114 -0.21710205078125 +98115 -0.27935791015625 +98116 -0.01336669921875 +98117 -0.0089111328125 +98118 0.196044921875 +98119 0.268798828125 +98120 0.35821533203125 +98121 0.482818603515625 +98122 0.451080322265625 +98123 0.60369873046875 +98124 0.488555908203125 +98125 0.650421142578125 +98126 0.50103759765625 +98127 0.66400146484375 +98128 0.486175537109375 +98129 0.6414794921875 +98130 0.436248779296875 +98131 0.572540283203125 +98132 0.38165283203125 +98133 0.498138427734375 +98134 0.338104248046875 +98135 0.439453125 +98136 0.2900390625 +98137 0.375518798828125 +98138 0.21380615234375 +98139 0.274505615234375 +98140 0.08892822265625 +98141 0.1087646484375 +98142 -0.067901611328125 +98143 -0.099395751953125 +98144 -0.232940673828125 +98145 -0.3182373046875 +98146 -0.406982421875 +98147 -0.5489501953125 +98148 -0.57666015625 +98149 -0.7738037109375 +98150 -0.702423095703125 +98151 -0.86383056640625 +98152 -0.759429931640625 +98153 -0.870391845703125 +98154 -0.760772705078125 +98155 -0.86895751953125 +98156 -0.716156005859375 +98157 -0.861053466796875 +98158 -0.612640380859375 +98159 -0.765869140625 +98160 -0.441802978515625 +98161 -0.5301513671875 +98162 -0.208953857421875 +98163 -0.214691162109375 +98164 0.0538330078125 +98165 0.137359619140625 +98166 0.308349609375 +98167 0.474822998046875 +98168 0.528106689453125 +98169 0.76239013671875 +98170 0.692901611328125 +98171 0.867462158203125 +98172 0.802978515625 +98173 0.870361328125 +98174 0.849609375 +98175 0.86480712890625 +98176 0.836669921875 +98177 0.831817626953125 +98178 0.78216552734375 +98179 0.677581787109375 +98180 0.690338134765625 +98181 0.495880126953125 +98182 0.574920654296875 +98183 0.30767822265625 +98184 0.4375 +98185 0.116180419921875 +98186 0.254425048828125 +98187 -0.110748291015625 +98188 0.02056884765625 +98189 -0.381805419921875 +98190 -0.232208251953125 +98191 -0.6572265625 +98192 -0.459320068359375 +98193 -0.857421875 +98194 -0.62872314453125 +98195 -0.870391845703125 +98196 -0.73504638671875 +98197 -0.870391845703125 +98198 -0.7982177734375 +98199 -0.86444091796875 +98200 -0.84466552734375 +98201 -0.85723876953125 +98202 -0.855194091796875 +98203 -0.790008544921875 +98204 -0.80572509765625 +98205 -0.62847900390625 +98206 -0.677398681640625 +98207 -0.3956298828125 +98208 -0.50006103515625 +98209 -0.126708984375 +98210 -0.294036865234375 +98211 0.150115966796875 +98212 -0.068023681640625 +98213 0.424041748046875 +98214 0.15789794921875 +98215 0.670623779296875 +98216 0.354888916015625 +98217 0.854522705078125 +98218 0.509765625 +98219 0.866485595703125 +98220 0.610992431640625 +98221 0.86920166015625 +98222 0.6719970703125 +98223 0.8653564453125 +98224 0.702667236328125 +98225 0.857147216796875 +98226 0.700714111328125 +98227 0.766845703125 +98228 0.669891357421875 +98229 0.628509521484375 +98230 0.605072021484375 +98231 0.462127685546875 +98232 0.525390625 +98233 0.297210693359375 +98234 0.44000244140625 +98235 0.14862060546875 +98236 0.3319091796875 +98237 -0.00537109375 +98238 0.2066650390625 +98239 -0.15753173828125 +98240 0.06158447265625 +98241 -0.31304931640625 +98242 -0.11370849609375 +98243 -0.48876953125 +98244 -0.2843017578125 +98245 -0.6416015625 +98246 -0.431732177734375 +98247 -0.751373291015625 +98248 -0.573089599609375 +98249 -0.84619140625 +98250 -0.69732666015625 +98251 -0.861297607421875 +98252 -0.779693603515625 +98253 -0.863250732421875 +98254 -0.796600341796875 +98255 -0.856597900390625 +98256 -0.75701904296875 +98257 -0.7498779296875 +98258 -0.703948974609375 +98259 -0.624542236328125 +98260 -0.620941162109375 +98261 -0.47808837890625 +98262 -0.464508056640625 +98263 -0.253387451171875 +98264 -0.268585205078125 +98265 0.003692626953125 +98266 -0.08404541015625 +98267 0.2257080078125 +98268 0.098358154296875 +98269 0.427154541015625 +98270 0.30267333984375 +98271 0.643218994140625 +98272 0.5216064453125 +98273 0.855926513671875 +98274 0.71197509765625 +98275 0.870361328125 +98276 0.836761474609375 +98277 0.870361328125 +98278 0.859588623046875 +98279 0.862762451171875 +98280 0.859771728515625 +98281 0.79669189453125 +98282 0.835174560546875 +98283 0.595794677734375 +98284 0.719207763671875 +98285 0.362152099609375 +98286 0.57598876953125 +98287 0.1270751953125 +98288 0.4212646484375 +98289 -0.086944580078125 +98290 0.256622314453125 +98291 -0.2784423828125 +98292 0.056243896484375 +98293 -0.484832763671875 +98294 -0.19403076171875 +98295 -0.729583740234375 +98296 -0.45648193359375 +98297 -0.86688232421875 +98298 -0.68389892578125 +98299 -0.870391845703125 +98300 -0.856475830078125 +98301 -0.86859130859375 +98302 -0.870391845703125 +98303 -0.86279296875 +98304 -0.870391845703125 +98305 -0.817962646484375 +98306 -0.860198974609375 +98307 -0.6116943359375 +98308 -0.718719482421875 +98309 -0.3128662109375 +98310 -0.463897705078125 +98311 0.039398193359375 +98312 -0.159515380859375 +98313 0.422821044921875 +98314 0.1685791015625 +98315 0.805145263671875 +98316 0.470794677734375 +98317 0.870361328125 +98318 0.706451416015625 +98319 0.870361328125 +98320 0.85595703125 +98321 0.860015869140625 +98322 0.8651123046875 +98323 0.727935791015625 +98324 0.8656005859375 +98325 0.48114013671875 +98326 0.859619140625 +98327 0.2059326171875 +98328 0.8074951171875 +98329 -0.06103515625 +98330 0.684539794921875 +98331 -0.29913330078125 +98332 0.526153564453125 +98333 -0.516204833984375 +98334 0.324798583984375 +98335 -0.7252197265625 +98336 0.101287841796875 +98337 -0.85980224609375 +98338 -0.1173095703125 +98339 -0.870391845703125 +98340 -0.3079833984375 +98341 -0.870391845703125 +98342 -0.434814453125 +98343 -0.858062744140625 +98344 -0.494354248046875 +98345 -0.673004150390625 +98346 -0.52423095703125 +98347 -0.42694091796875 +98348 -0.5570068359375 +98349 -0.2100830078125 +98350 -0.592803955078125 +98351 -0.0362548828125 +98352 -0.613128662109375 +98353 0.10943603515625 +98354 -0.60638427734375 +98355 0.23516845703125 +98356 -0.54595947265625 +98357 0.373687744140625 +98358 -0.4361572265625 +98359 0.517791748046875 +98360 -0.324737548828125 +98361 0.602783203125 +98362 -0.210723876953125 +98363 0.635711669921875 +98364 -0.072723388671875 +98365 0.655181884765625 +98366 0.080322265625 +98367 0.65948486328125 +98368 0.241363525390625 +98369 0.651275634765625 +98370 0.3922119140625 +98371 0.61846923828125 +98372 0.50640869140625 +98373 0.53753662109375 +98374 0.571563720703125 +98375 0.404144287109375 +98376 0.581817626953125 +98377 0.22186279296875 +98378 0.53961181640625 +98379 0.003997802734375 +98380 0.459808349609375 +98381 -0.22100830078125 +98382 0.359344482421875 +98383 -0.42449951171875 +98384 0.255828857421875 +98385 -0.579833984375 +98386 0.18206787109375 +98387 -0.641876220703125 +98388 0.1356201171875 +98389 -0.6177978515625 +98390 0.07257080078125 +98391 -0.575531005859375 +98392 -0.0091552734375 +98393 -0.526336669921875 +98394 -0.071380615234375 +98395 -0.42645263671875 +98396 -0.093719482421875 +98397 -0.2581787109375 +98398 -0.101776123046875 +98399 -0.068695068359375 +98400 -0.123138427734375 +98401 0.09222412109375 +98402 -0.145233154296875 +98403 0.232147216796875 +98404 -0.161895751953125 +98405 0.3509521484375 +98406 -0.1956787109375 +98407 0.410064697265625 +98408 -0.2691650390625 +98409 0.372955322265625 +98410 -0.36932373046875 +98411 0.2554931640625 +98412 -0.4609375 +98413 0.10711669921875 +98414 -0.531951904296875 +98415 -0.052886962890625 +98416 -0.55828857421875 +98417 -0.186279296875 +98418 -0.501617431640625 +98419 -0.23291015625 +98420 -0.379302978515625 +98421 -0.209442138671875 +98422 -0.239044189453125 +98423 -0.174163818359375 +98424 -0.087188720703125 +98425 -0.126739501953125 +98426 0.083282470703125 +98427 -0.048126220703125 +98428 0.252685546875 +98429 0.0426025390625 +98430 0.3885498046875 +98431 0.10748291015625 +98432 0.48248291015625 +98433 0.1409912109375 +98434 0.56964111328125 +98435 0.19708251953125 +98436 0.646636962890625 +98437 0.273651123046875 +98438 0.675201416015625 +98439 0.31768798828125 +98440 0.6646728515625 +98441 0.341094970703125 +98442 0.634429931640625 +98443 0.368011474609375 +98444 0.569305419921875 +98445 0.37249755859375 +98446 0.435272216796875 +98447 0.30072021484375 +98448 0.236572265625 +98449 0.1517333984375 +98450 0.02105712890625 +98451 -0.01470947265625 +98452 -0.198486328125 +98453 -0.1883544921875 +98454 -0.41937255859375 +98455 -0.372711181640625 +98456 -0.598602294921875 +98457 -0.51397705078125 +98458 -0.703460693359375 +98459 -0.57177734375 +98460 -0.726165771484375 +98461 -0.53948974609375 +98462 -0.677581787109375 +98463 -0.43511962890625 +98464 -0.583648681640625 +98465 -0.2962646484375 +98466 -0.471893310546875 +98467 -0.161102294921875 +98468 -0.353668212890625 +98469 -0.0435791015625 +98470 -0.228515625 +98471 0.060394287109375 +98472 -0.1097412109375 +98473 0.13665771484375 +98474 -0.011962890625 +98475 0.170135498046875 +98476 0.0638427734375 +98477 0.16552734375 +98478 0.137725830078125 +98479 0.15728759765625 +98480 0.209136962890625 +98481 0.150787353515625 +98482 0.2569580078125 +98483 0.12200927734375 +98484 0.284210205078125 +98485 0.080108642578125 +98486 0.3067626953125 +98487 0.05126953125 +98488 0.3421630859375 +98489 0.062896728515625 +98490 0.37353515625 +98491 0.09271240234375 +98492 0.3668212890625 +98493 0.092987060546875 +98494 0.333465576171875 +98495 0.07855224609375 +98496 0.2857666015625 +98497 0.06427001953125 +98498 0.215240478515625 +98499 0.0347900390625 +98500 0.12359619140625 +98501 -0.01171875 +98502 0.0279541015625 +98503 -0.056060791015625 +98504 -0.037567138671875 +98505 -0.055511474609375 +98506 -0.069580078125 +98507 -0.010467529296875 +98508 -0.10308837890625 +98509 0.02508544921875 +98510 -0.153167724609375 +98511 0.025665283203125 +98512 -0.198760986328125 +98513 0.017333984375 +98514 -0.23675537109375 +98515 0.00189208984375 +98516 -0.27392578125 +98517 -0.03173828125 +98518 -0.3013916015625 +98519 -0.071502685546875 +98520 -0.332427978515625 +98521 -0.13543701171875 +98522 -0.36566162109375 +98523 -0.219970703125 +98524 -0.38543701171875 +98525 -0.300506591796875 +98526 -0.393585205078125 +98527 -0.376312255859375 +98528 -0.370513916015625 +98529 -0.416107177734375 +98530 -0.284515380859375 +98531 -0.371124267578125 +98532 -0.13922119140625 +98533 -0.242279052734375 +98534 0.033843994140625 +98535 -0.069732666015625 +98536 0.2171630859375 +98537 0.125640869140625 +98538 0.38629150390625 +98539 0.31268310546875 +98540 0.513641357421875 +98541 0.45501708984375 +98542 0.599578857421875 +98543 0.554779052734375 +98544 0.6427001953125 +98545 0.61065673828125 +98546 0.634796142578125 +98547 0.610931396484375 +98548 0.559478759765625 +98549 0.531463623046875 +98550 0.42950439453125 +98551 0.3883056640625 +98552 0.2845458984375 +98553 0.23468017578125 +98554 0.144317626953125 +98555 0.095245361328125 +98556 0.02972412109375 +98557 -0.00396728515625 +98558 -0.046478271484375 +98559 -0.04852294921875 +98560 -0.09393310546875 +98561 -0.055145263671875 +98562 -0.14727783203125 +98563 -0.0758056640625 +98564 -0.22430419921875 +98565 -0.138702392578125 +98566 -0.299041748046875 +98567 -0.209197998046875 +98568 -0.37139892578125 +98569 -0.289031982421875 +98570 -0.441131591796875 +98571 -0.37884521484375 +98572 -0.492462158203125 +98573 -0.456329345703125 +98574 -0.52227783203125 +98575 -0.51641845703125 +98576 -0.50360107421875 +98577 -0.519287109375 +98578 -0.43310546875 +98579 -0.458251953125 +98580 -0.348541259765625 +98581 -0.384796142578125 +98582 -0.269195556640625 +98583 -0.323699951171875 +98584 -0.19317626953125 +98585 -0.269287109375 +98586 -0.104156494140625 +98587 -0.1951904296875 +98588 -0.003173828125 +98589 -0.100006103515625 +98590 0.08917236328125 +98591 -0.01055908203125 +98592 0.192535400390625 +98593 0.1033935546875 +98594 0.310882568359375 +98595 0.24908447265625 +98596 0.406219482421875 +98597 0.373199462890625 +98598 0.4659423828125 +98599 0.45806884765625 +98600 0.495697021484375 +98601 0.511474609375 +98602 0.518524169921875 +98603 0.565399169921875 +98604 0.529541015625 +98605 0.61138916015625 +98606 0.48828125 +98607 0.5897216796875 +98608 0.389404296875 +98609 0.4906005859375 +98610 0.24688720703125 +98611 0.33148193359375 +98612 0.087249755859375 +98613 0.147796630859375 +98614 -0.05859375 +98615 -0.01873779296875 +98616 -0.16961669921875 +98617 -0.140289306640625 +98618 -0.227081298828125 +98619 -0.191986083984375 +98620 -0.2373046875 +98621 -0.184295654296875 +98622 -0.2308349609375 +98623 -0.161834716796875 +98624 -0.236724853515625 +98625 -0.166595458984375 +98626 -0.25177001953125 +98627 -0.19390869140625 +98628 -0.262847900390625 +98629 -0.22442626953125 +98630 -0.285797119140625 +98631 -0.279754638671875 +98632 -0.307037353515625 +98633 -0.3389892578125 +98634 -0.29437255859375 +98635 -0.3543701171875 +98636 -0.264739990234375 +98637 -0.348175048828125 +98638 -0.223480224609375 +98639 -0.32598876953125 +98640 -0.151275634765625 +98641 -0.2581787109375 +98642 -0.04595947265625 +98643 -0.139801025390625 +98644 0.081146240234375 +98645 0.014617919921875 +98646 0.186553955078125 +98647 0.144378662109375 +98648 0.249725341796875 +98649 0.221038818359375 +98650 0.288543701171875 +98651 0.27069091796875 +98652 0.303436279296875 +98653 0.294036865234375 +98654 0.30914306640625 +98655 0.311767578125 +98656 0.316802978515625 +98657 0.339141845703125 +98658 0.315765380859375 +98659 0.360260009765625 +98660 0.296875 +98661 0.360504150390625 +98662 0.239898681640625 +98663 0.308380126953125 +98664 0.131072998046875 +98665 0.18170166015625 +98666 -0.011688232421875 +98667 0.0047607421875 +98668 -0.155303955078125 +98669 -0.17559814453125 +98670 -0.268035888671875 +98671 -0.3143310546875 +98672 -0.319305419921875 +98673 -0.36785888671875 +98674 -0.326263427734375 +98675 -0.36248779296875 +98676 -0.319305419921875 +98677 -0.343536376953125 +98678 -0.29205322265625 +98679 -0.3018798828125 +98680 -0.24041748046875 +98681 -0.231414794921875 +98682 -0.154876708984375 +98683 -0.117645263671875 +98684 -0.058013916015625 +98685 0.007049560546875 +98686 0.012176513671875 +98687 0.087982177734375 +98688 0.06451416015625 +98689 0.13946533203125 +98690 0.106658935546875 +98691 0.17425537109375 +98692 0.134735107421875 +98693 0.188201904296875 +98694 0.140869140625 +98695 0.171234130859375 +98696 0.120819091796875 +98697 0.118438720703125 +98698 0.09228515625 +98699 0.05706787109375 +98700 0.056060791015625 +98701 -0.010711669921875 +98702 0.00726318359375 +98703 -0.0914306640625 +98704 -0.038787841796875 +98705 -0.162322998046875 +98706 -0.0625 +98707 -0.194549560546875 +98708 -0.03729248046875 +98709 -0.1492919921875 +98710 0.04058837890625 +98711 -0.02166748046875 +98712 0.128021240234375 +98713 0.124053955078125 +98714 0.173553466796875 +98715 0.211151123046875 +98716 0.17852783203125 +98717 0.240447998046875 +98718 0.16436767578125 +98719 0.242218017578125 +98720 0.13824462890625 +98721 0.2257080078125 +98722 0.103302001953125 +98723 0.194366455078125 +98724 0.03802490234375 +98725 0.115509033203125 +98726 -0.0408935546875 +98727 0.0128173828125 +98728 -0.09228515625 +98729 -0.053802490234375 +98730 -0.1337890625 +98731 -0.110626220703125 +98732 -0.19378662109375 +98733 -0.199493408203125 +98734 -0.254730224609375 +98735 -0.29437255859375 +98736 -0.27398681640625 +98737 -0.33221435546875 +98738 -0.229400634765625 +98739 -0.27972412109375 +98740 -0.154449462890625 +98741 -0.185333251953125 +98742 -0.10357666015625 +98743 -0.128204345703125 +98744 -0.08245849609375 +98745 -0.115692138671875 +98746 -0.07049560546875 +98747 -0.116455078125 +98748 -0.051666259765625 +98749 -0.105926513671875 +98750 -0.006072998046875 +98751 -0.053955078125 +98752 0.07208251953125 +98753 0.048797607421875 +98754 0.15179443359375 +98755 0.157318115234375 +98756 0.192291259765625 +98757 0.212005615234375 +98758 0.197265625 +98759 0.218475341796875 +98760 0.207916259765625 +98761 0.23724365234375 +98762 0.2496337890625 +98763 0.30535888671875 +98764 0.29449462890625 +98765 0.38128662109375 +98766 0.301727294921875 +98767 0.404449462890625 +98768 0.28515625 +98769 0.3944091796875 +98770 0.270782470703125 +98771 0.3885498046875 +98772 0.24273681640625 +98773 0.362640380859375 +98774 0.172271728515625 +98775 0.27362060546875 +98776 0.056976318359375 +98777 0.11712646484375 +98778 -0.0673828125 +98779 -0.054901123046875 +98780 -0.16534423828125 +98781 -0.19085693359375 +98782 -0.233245849609375 +98783 -0.28570556640625 +98784 -0.270843505859375 +98785 -0.339263916015625 +98786 -0.29583740234375 +98787 -0.3775634765625 +98788 -0.339019775390625 +98789 -0.445709228515625 +98790 -0.394775390625 +98791 -0.535064697265625 +98792 -0.452117919921875 +98793 -0.629058837890625 +98794 -0.490997314453125 +98795 -0.697601318359375 +98796 -0.48687744140625 +98797 -0.70391845703125 +98798 -0.43646240234375 +98799 -0.6424560546875 +98800 -0.32525634765625 +98801 -0.491241455078125 +98802 -0.164215087890625 +98803 -0.265716552734375 +98804 0.00689697265625 +98805 -0.023712158203125 +98806 0.165313720703125 +98807 0.201751708984375 +98808 0.287078857421875 +98809 0.375823974609375 +98810 0.362945556640625 +98811 0.485076904296875 +98812 0.419647216796875 +98813 0.56884765625 +98814 0.462432861328125 +98815 0.634765625 +98816 0.461212158203125 +98817 0.63763427734375 +98818 0.409210205078125 +98819 0.5660400390625 +98820 0.341064453125 +98821 0.4720458984375 +98822 0.290252685546875 +98823 0.40692138671875 +98824 0.26177978515625 +98825 0.3778076171875 +98826 0.251068115234375 +98827 0.376953125 +98828 0.237640380859375 +98829 0.371978759765625 +98830 0.18975830078125 +98831 0.313140869140625 +98832 0.0975341796875 +98833 0.184417724609375 +98834 -0.022125244140625 +98835 0.011199951171875 +98836 -0.1458740234375 +98837 -0.171051025390625 +98838 -0.257293701171875 +98839 -0.33740234375 +98840 -0.345977783203125 +98841 -0.47198486328125 +98842 -0.402557373046875 +98843 -0.560394287109375 +98844 -0.412841796875 +98845 -0.58056640625 +98846 -0.38677978515625 +98847 -0.54754638671875 +98848 -0.35528564453125 +98849 -0.508575439453125 +98850 -0.3160400390625 +98851 -0.459503173828125 +98852 -0.265625 +98853 -0.394378662109375 +98854 -0.230010986328125 +98855 -0.35260009765625 +98856 -0.195098876953125 +98857 -0.31170654296875 +98858 -0.113250732421875 +98859 -0.197418212890625 +98860 0.016265869140625 +98861 -0.007965087890625 +98862 0.1612548828125 +98863 0.207489013671875 +98864 0.29571533203125 +98865 0.409210205078125 +98866 0.403228759765625 +98867 0.57208251953125 +98868 0.4642333984375 +98869 0.66595458984375 +98870 0.45794677734375 +98871 0.65875244140625 +98872 0.3955078125 +98873 0.56744384765625 +98874 0.302642822265625 +98875 0.431396484375 +98876 0.208038330078125 +98877 0.29443359375 +98878 0.128875732421875 +98879 0.182464599609375 +98880 0.044891357421875 +98881 0.06365966796875 +98882 -0.05255126953125 +98883 -0.075958251953125 +98884 -0.132659912109375 +98885 -0.189422607421875 +98886 -0.19195556640625 +98887 -0.271942138671875 +98888 -0.242462158203125 +98889 -0.342529296875 +98890 -0.260009765625 +98891 -0.364166259765625 +98892 -0.238189697265625 +98893 -0.327239990234375 +98894 -0.20623779296875 +98895 -0.2769775390625 +98896 -0.1903076171875 +98897 -0.253692626953125 +98898 -0.181549072265625 +98899 -0.24365234375 +98900 -0.14874267578125 +98901 -0.1983642578125 +98902 -0.091064453125 +98903 -0.116241455078125 +98904 -0.034393310546875 +98905 -0.036834716796875 +98906 0.0177001953125 +98907 0.034881591796875 +98908 0.0599365234375 +98909 0.09124755859375 +98910 0.076904296875 +98911 0.10888671875 +98912 0.092681884765625 +98913 0.125518798828125 +98914 0.117767333984375 +98915 0.15771484375 +98916 0.13433837890625 +98917 0.17828369140625 +98918 0.13177490234375 +98919 0.17108154296875 +98920 0.106048583984375 +98921 0.129974365234375 +98922 0.074920654296875 +98923 0.082427978515625 +98924 0.037994384765625 +98925 0.027679443359375 +98926 -0.024932861328125 +98927 -0.065643310546875 +98928 -0.0889892578125 +98929 -0.15936279296875 +98930 -0.127777099609375 +98931 -0.21307373046875 +98932 -0.14617919921875 +98933 -0.234649658203125 +98934 -0.12847900390625 +98935 -0.2001953125 +98936 -0.08050537109375 +98937 -0.119171142578125 +98938 -0.0235595703125 +98939 -0.024749755859375 +98940 0.04437255859375 +98941 0.085784912109375 +98942 0.101226806640625 +98943 0.178131103515625 +98944 0.123382568359375 +98945 0.215576171875 +98946 0.119537353515625 +98947 0.211456298828125 +98948 0.09588623046875 +98949 0.17523193359375 +98950 0.066558837890625 +98951 0.128753662109375 +98952 0.05084228515625 +98953 0.1019287109375 +98954 0.035430908203125 +98955 0.0743408203125 +98956 0.01837158203125 +98957 0.04327392578125 +98958 0.01861572265625 +98959 0.038177490234375 +98960 0.047088623046875 +98961 0.076263427734375 +98962 0.0928955078125 +98963 0.14105224609375 +98964 0.12591552734375 +98965 0.186431884765625 +98966 0.13067626953125 +98967 0.188812255859375 +98968 0.101104736328125 +98969 0.1390380859375 +98970 0.040069580078125 +98971 0.041778564453125 +98972 -0.0372314453125 +98973 -0.079437255859375 +98974 -0.12750244140625 +98975 -0.219390869140625 +98976 -0.224029541015625 +98977 -0.367828369140625 +98978 -0.30743408203125 +98979 -0.494873046875 +98980 -0.348968505859375 +98981 -0.556243896484375 +98982 -0.32049560546875 +98983 -0.508697509765625 +98984 -0.23699951171875 +98985 -0.3756103515625 +98986 -0.13848876953125 +98987 -0.218902587890625 +98988 -0.04107666015625 +98989 -0.063751220703125 +98990 0.056488037109375 +98991 0.091552734375 +98992 0.14727783203125 +98993 0.23602294921875 +98994 0.214141845703125 +98995 0.342987060546875 +98996 0.246063232421875 +98997 0.39520263671875 +98998 0.240997314453125 +98999 0.389373779296875 +99000 0.19818115234375 +99001 0.324249267578125 +99002 0.133331298828125 +99003 0.224090576171875 +99004 0.0693359375 +99005 0.124267578125 +99006 0.01409912109375 +99007 0.037078857421875 +99008 -0.014678955078125 +99009 -0.010101318359375 +99010 -0.0185546875 +99011 -0.019439697265625 +99012 -0.018280029296875 +99013 -0.022796630859375 +99014 -0.001953125 +99015 -0.001556396484375 +99016 0.038055419921875 +99017 0.056304931640625 +99018 0.07305908203125 +99019 0.106719970703125 +99020 0.068756103515625 +99021 0.096893310546875 +99022 0.035308837890625 +99023 0.042694091796875 +99024 -0.002838134765625 +99025 -0.018035888671875 +99026 -0.03961181640625 +99027 -0.07586669921875 +99028 -0.06768798828125 +99029 -0.11944580078125 +99030 -0.094146728515625 +99031 -0.15972900390625 +99032 -0.122772216796875 +99033 -0.202606201171875 +99034 -0.15380859375 +99035 -0.24859619140625 +99036 -0.1920166015625 +99037 -0.30517578125 +99038 -0.230743408203125 +99039 -0.36212158203125 +99040 -0.251708984375 +99041 -0.39141845703125 +99042 -0.23028564453125 +99043 -0.35528564453125 +99044 -0.163970947265625 +99045 -0.249969482421875 +99046 -0.06396484375 +99047 -0.092864990234375 +99048 0.0523681640625 +99049 0.08905029296875 +99050 0.145904541015625 +99051 0.2352294921875 +99052 0.199249267578125 +99053 0.318817138671875 +99054 0.22467041015625 +99055 0.358642578125 +99056 0.2176513671875 +99057 0.347747802734375 +99058 0.1778564453125 +99059 0.28564453125 +99060 0.138214111328125 +99061 0.223175048828125 +99062 0.122222900390625 +99063 0.196746826171875 +99064 0.1126708984375 +99065 0.179840087890625 +99066 0.0985107421875 +99067 0.155548095703125 +99068 0.097381591796875 +99069 0.151214599609375 +99070 0.102783203125 +99071 0.156951904296875 +99072 0.08819580078125 +99073 0.13177490234375 +99074 0.069366455078125 +99075 0.100799560546875 +99076 0.06103515625 +99077 0.087127685546875 +99078 0.040924072265625 +99079 0.05487060546875 +99080 0.000885009765625 +99081 -0.009002685546875 +99082 -0.0587158203125 +99083 -0.10400390625 +99084 -0.137420654296875 +99085 -0.229400634765625 +99086 -0.216888427734375 +99087 -0.35552978515625 +99088 -0.272064208984375 +99089 -0.441925048828125 +99090 -0.293792724609375 +99091 -0.473846435546875 +99092 -0.29022216796875 +99093 -0.464813232421875 +99094 -0.26385498046875 +99095 -0.419097900390625 +99096 -0.213104248046875 +99097 -0.334320068359375 +99098 -0.14862060546875 +99099 -0.227935791015625 +99100 -0.084869384765625 +99101 -0.12347412109375 +99102 -0.02593994140625 +99103 -0.02764892578125 +99104 0.039337158203125 +99105 0.077667236328125 +99106 0.12371826171875 +99107 0.2132568359375 +99108 0.233154296875 +99109 0.38885498046875 +99110 0.354217529296875 +99111 0.582794189453125 +99112 0.44921875 +99113 0.734039306640625 +99114 0.49188232421875 +99115 0.800140380859375 +99116 0.480377197265625 +99117 0.7783203125 +99118 0.412506103515625 +99119 0.6651611328125 +99120 0.287567138671875 +99121 0.45965576171875 +99122 0.128509521484375 +99123 0.199188232421875 +99124 -0.024383544921875 +99125 -0.050689697265625 +99126 -0.13604736328125 +99127 -0.23297119140625 +99128 -0.195709228515625 +99129 -0.33013916015625 +99130 -0.219482421875 +99131 -0.368408203125 +99132 -0.226531982421875 +99133 -0.378936767578125 +99134 -0.22625732421875 +99135 -0.376983642578125 +99136 -0.229156494140625 +99137 -0.37969970703125 +99138 -0.237884521484375 +99139 -0.391510009765625 +99140 -0.235687255859375 +99141 -0.385345458984375 +99142 -0.2105712890625 +99143 -0.3419189453125 +99144 -0.175811767578125 +99145 -0.28289794921875 +99146 -0.15802001953125 +99147 -0.251617431640625 +99148 -0.168212890625 +99149 -0.266143798828125 +99150 -0.17364501953125 +99151 -0.273345947265625 +99152 -0.13946533203125 +99153 -0.216796875 +99154 -0.085205078125 +99155 -0.128265380859375 +99156 -0.048095703125 +99157 -0.068145751953125 +99158 -0.0322265625 +99159 -0.0430908203125 +99160 -0.02001953125 +99161 -0.024444580078125 +99162 0.0087890625 +99163 0.020721435546875 +99164 0.073883056640625 +99165 0.124481201171875 +99166 0.1573486328125 +99167 0.25787353515625 +99168 0.23333740234375 +99169 0.379119873046875 +99170 0.296722412109375 +99171 0.47991943359375 +99172 0.32763671875 +99173 0.5281982421875 +99174 0.318145751953125 +99175 0.511138916015625 +99176 0.285125732421875 +99177 0.456207275390625 +99178 0.255706787109375 +99179 0.407470703125 +99180 0.241424560546875 +99181 0.383758544921875 +99182 0.224884033203125 +99183 0.35687255859375 +99184 0.1968994140625 +99185 0.31182861328125 +99186 0.158843994140625 +99187 0.250885009765625 +99188 0.105438232421875 +99189 0.1654052734375 +99190 0.02435302734375 +99191 0.035247802734375 +99192 -0.085906982421875 +99193 -0.142059326171875 +99194 -0.20623779296875 +99195 -0.33563232421875 +99196 -0.329803466796875 +99197 -0.5345458984375 +99198 -0.446136474609375 +99199 -0.72186279296875 +99200 -0.5177001953125 +99201 -0.836669921875 +99202 -0.515899658203125 +99203 -0.8326416015625 +99204 -0.452911376953125 +99205 -0.7296142578125 +99206 -0.36260986328125 +99207 -0.582550048828125 +99208 -0.274932861328125 +99209 -0.440093994140625 +99210 -0.203460693359375 +99211 -0.324310302734375 +99212 -0.12744140625 +99213 -0.20147705078125 +99214 -0.0302734375 +99215 -0.044647216796875 +99216 0.061981201171875 +99217 0.103973388671875 +99218 0.1234130859375 +99219 0.202392578125 +99220 0.16253662109375 +99221 0.264495849609375 +99222 0.209228515625 +99223 0.338897705078125 +99224 0.274658203125 +99225 0.443817138671875 +99226 0.337738037109375 +99227 0.545074462890625 +99228 0.382781982421875 +99229 0.6173095703125 +99230 0.40484619140625 +99231 0.6524658203125 +99232 0.41180419921875 +99233 0.66339111328125 +99234 0.4073486328125 +99235 0.6561279296875 +99236 0.376800537109375 +99237 0.606781005859375 +99238 0.311431884765625 +99239 0.501190185546875 +99240 0.21954345703125 +99241 0.352783203125 +99242 0.110382080078125 +99243 0.176544189453125 +99244 -0.020477294921875 +99245 -0.034820556640625 +99246 -0.15875244140625 +99247 -0.258209228515625 +99248 -0.27288818359375 +99249 -0.44244384765625 +99250 -0.355316162109375 +99251 -0.5753173828125 +99252 -0.403076171875 +99253 -0.65203857421875 +99254 -0.397064208984375 +99255 -0.641632080078125 +99256 -0.348388671875 +99257 -0.562164306640625 +99258 -0.284393310546875 +99259 -0.458038330078125 +99260 -0.21820068359375 +99261 -0.350555419921875 +99262 -0.162628173828125 +99263 -0.260528564453125 +99264 -0.120269775390625 +99265 -0.192108154296875 +99266 -0.08905029296875 +99267 -0.141937255859375 +99268 -0.06414794921875 +99269 -0.1021728515625 +99270 -0.03948974609375 +99271 -0.062896728515625 +99272 -0.007568359375 +99273 -0.011932373046875 +99274 0.03900146484375 +99275 0.062835693359375 +99276 0.0924072265625 +99277 0.148712158203125 +99278 0.150146484375 +99279 0.241729736328125 +99280 0.2166748046875 +99281 0.34912109375 +99282 0.283599853515625 +99283 0.457305908203125 +99284 0.33709716796875 +99285 0.54388427734375 +99286 0.355010986328125 +99287 0.5728759765625 +99288 0.31414794921875 +99289 0.506591796875 +99290 0.218292236328125 +99291 0.351226806640625 +99292 0.0919189453125 +99293 0.146514892578125 +99294 -0.032684326171875 +99295 -0.05523681640625 +99296 -0.132232666015625 +99297 -0.21624755859375 +99298 -0.205718994140625 +99299 -0.334930419921875 +99300 -0.248016357421875 +99301 -0.402984619140625 +99302 -0.27197265625 +99303 -0.4412841796875 +99304 -0.305908203125 +99305 -0.49578857421875 +99306 -0.345855712890625 +99307 -0.5601806640625 +99308 -0.371063232421875 +99309 -0.600738525390625 +99310 -0.361053466796875 +99311 -0.584228515625 +99312 -0.2965087890625 +99313 -0.47930908203125 +99314 -0.173370361328125 +99315 -0.27935791015625 +99316 -0.006744384765625 +99317 -0.0089111328125 +99318 0.164398193359375 +99319 0.268798828125 +99320 0.29638671875 +99321 0.482818603515625 +99322 0.371063232421875 +99323 0.60369873046875 +99324 0.40008544921875 +99325 0.650421142578125 +99326 0.408721923828125 +99327 0.66400146484375 +99328 0.395355224609375 +99329 0.6414794921875 +99330 0.353546142578125 +99331 0.572540283203125 +99332 0.307373046875 +99333 0.498138427734375 +99334 0.26947021484375 +99335 0.439453125 +99336 0.227874755859375 +99337 0.375518798828125 +99338 0.164276123046875 +99339 0.274505615234375 +99340 0.06280517578125 +99341 0.1087646484375 +99342 -0.063201904296875 +99343 -0.099395751953125 +99344 -0.1949462890625 +99345 -0.3182373046875 +99346 -0.33294677734375 +99347 -0.5489501953125 +99348 -0.4666748046875 +99349 -0.7738037109375 +99350 -0.56512451171875 +99351 -0.86383056640625 +99352 -0.60882568359375 +99353 -0.870391845703125 +99354 -0.608154296875 +99355 -0.86895751953125 +99356 -0.570831298828125 +99357 -0.861053466796875 +99358 -0.486846923828125 +99359 -0.765869140625 +99360 -0.349761962890625 +99361 -0.5301513671875 +99362 -0.163909912109375 +99363 -0.214691162109375 +99364 0.045379638671875 +99365 0.137359619140625 +99366 0.2479248046875 +99367 0.474822998046875 +99368 0.422760009765625 +99369 0.76239013671875 +99370 0.553924560546875 +99371 0.867462158203125 +99372 0.641510009765625 +99373 0.870361328125 +99374 0.678619384765625 +99375 0.86480712890625 +99376 0.668304443359375 +99377 0.831817626953125 +99378 0.624725341796875 +99379 0.677581787109375 +99380 0.55126953125 +99381 0.495880126953125 +99382 0.458831787109375 +99383 0.30767822265625 +99384 0.3487548828125 +99385 0.116180419921875 +99386 0.20263671875 +99387 -0.110748291015625 +99388 0.01654052734375 +99389 -0.381805419921875 +99390 -0.184326171875 +99391 -0.6572265625 +99392 -0.364837646484375 +99393 -0.857421875 +99394 -0.499755859375 +99395 -0.870391845703125 +99396 -0.584747314453125 +99397 -0.870391845703125 +99398 -0.635406494140625 +99399 -0.86444091796875 +99400 -0.67242431640625 +99401 -0.85723876953125 +99402 -0.68499755859375 +99403 -0.790008544921875 +99404 -0.641387939453125 +99405 -0.62847900390625 +99406 -0.539703369140625 +99407 -0.3956298828125 +99408 -0.39910888671875 +99409 -0.126708984375 +99410 -0.23565673828125 +99411 0.150115966796875 +99412 -0.0562744140625 +99413 0.424041748046875 +99414 0.123138427734375 +99415 0.670623779296875 +99416 0.279815673828125 +99417 0.854522705078125 +99418 0.403289794921875 +99419 0.866485595703125 +99420 0.48443603515625 +99421 0.86920166015625 +99422 0.53369140625 +99423 0.8653564453125 +99424 0.558746337890625 +99425 0.857147216796875 +99426 0.55780029296875 +99427 0.766845703125 +99428 0.533721923828125 +99429 0.628509521484375 +99430 0.482513427734375 +99431 0.462127685546875 +99432 0.41925048828125 +99433 0.297210693359375 +99434 0.351165771484375 +99435 0.14862060546875 +99436 0.26495361328125 +99437 -0.00537109375 +99438 0.16510009765625 +99439 -0.15753173828125 +99440 0.049560546875 +99441 -0.31304931640625 +99442 -0.0897216796875 +99443 -0.48876953125 +99444 -0.2252197265625 +99445 -0.6416015625 +99446 -0.34234619140625 +99447 -0.751373291015625 +99448 -0.4544677734375 +99449 -0.84619140625 +99450 -0.5528564453125 +99451 -0.861297607421875 +99452 -0.6180419921875 +99453 -0.863250732421875 +99454 -0.631500244140625 +99455 -0.856597900390625 +99456 -0.60028076171875 +99457 -0.7498779296875 +99458 -0.558135986328125 +99459 -0.624542236328125 +99460 -0.492218017578125 +99461 -0.47808837890625 +99462 -0.368408203125 +99463 -0.253387451171875 +99464 -0.21343994140625 +99465 0.003692626953125 +99466 -0.06732177734375 +99467 0.2257080078125 +99468 0.077178955078125 +99469 0.427154541015625 +99470 0.23883056640625 +99471 0.643218994140625 +99472 0.411865234375 +99473 0.855926513671875 +99474 0.56231689453125 +99475 0.870361328125 +99476 0.66107177734375 +99477 0.870361328125 +99478 0.712188720703125 +99479 0.862762451171875 +99480 0.7138671875 +99481 0.79669189453125 +99482 0.6605224609375 +99483 0.595794677734375 +99484 0.5692138671875 +99485 0.362152099609375 +99486 0.456298828125 +99487 0.1270751953125 +99488 0.33416748046875 +99489 -0.086944580078125 +99490 0.2041015625 +99491 -0.2784423828125 +99492 0.04583740234375 +99493 -0.484832763671875 +99494 -0.15167236328125 +99495 -0.729583740234375 +99496 -0.358734130859375 +99497 -0.86688232421875 +99498 -0.538238525390625 +99499 -0.870391845703125 +99500 -0.687103271484375 +99501 -0.86859130859375 +99502 -0.803955078125 +99503 -0.86279296875 +99504 -0.85595703125 +99505 -0.817962646484375 +99506 -0.851593017578125 +99507 -0.6116943359375 +99508 -0.751495361328125 +99509 -0.3128662109375 +99510 -0.5870361328125 +99511 0.039398193359375 +99512 -0.369903564453125 +99513 0.422821044921875 +99514 -0.119598388671875 +99515 0.805145263671875 +99516 0.1240234375 +99517 0.870361328125 +99518 0.3275146484375 +99519 0.870361328125 +99520 0.48382568359375 +99521 0.860015869140625 +99522 0.588226318359375 +99523 0.727935791015625 +99524 0.637176513671875 +99525 0.48114013671875 +99526 0.644561767578125 +99527 0.2059326171875 +99528 0.62335205078125 +99529 -0.06103515625 +99530 0.579193115234375 +99531 -0.29913330078125 +99532 0.503448486328125 +99533 -0.516204833984375 +99534 0.3870849609375 +99535 -0.7252197265625 +99536 0.24462890625 +99537 -0.85980224609375 +99538 0.096221923828125 +99539 -0.870391845703125 +99540 -0.0406494140625 +99541 -0.870391845703125 +99542 -0.13726806640625 +99543 -0.858062744140625 +99544 -0.190826416015625 +99545 -0.673004150390625 +99546 -0.231597900390625 +99547 -0.42694091796875 +99548 -0.285125732421875 +99549 -0.2100830078125 +99550 -0.3497314453125 +99551 -0.0362548828125 +99552 -0.4080810546875 +99553 0.10943603515625 +99554 -0.448211669921875 +99555 0.23516845703125 +99556 -0.4456787109375 +99557 0.373687744140625 +99558 -0.40142822265625 +99559 0.517791748046875 +99560 -0.352142333984375 +99561 0.602783203125 +99562 -0.294830322265625 +99563 0.635711669921875 +99564 -0.21014404296875 +99565 0.655181884765625 +99566 -0.104095458984375 +99567 0.65948486328125 +99568 0.018341064453125 +99569 0.651275634765625 +99570 0.142486572265625 +99571 0.61846923828125 +99572 0.246307373046875 +99573 0.53753662109375 +99574 0.318817138671875 +99575 0.404144287109375 +99576 0.353912353515625 +99577 0.22186279296875 +99578 0.351959228515625 +99579 0.003997802734375 +99580 0.32318115234375 +99581 -0.22100830078125 +99582 0.279327392578125 +99583 -0.42449951171875 +99584 0.23236083984375 +99585 -0.579833984375 +99586 0.206451416015625 +99587 -0.641876220703125 +99588 0.19830322265625 +99589 -0.6177978515625 +99590 0.17205810546875 +99591 -0.575531005859375 +99592 0.124725341796875 +99593 -0.526336669921875 +99594 0.084991455078125 +99595 -0.42645263671875 +99596 0.068267822265625 +99597 -0.2581787109375 +99598 0.0548095703125 +99599 -0.068695068359375 +99600 0.023773193359375 +99601 0.09222412109375 +99602 -0.014068603515625 +99603 0.232147216796875 +99604 -0.052642822265625 +99605 0.3509521484375 +99606 -0.107879638671875 +99607 0.410064697265625 +99608 -0.19561767578125 +99609 0.372955322265625 +99610 -0.303955078125 +99611 0.2554931640625 +99612 -0.4039306640625 +99613 0.10711669921875 +99614 -0.484588623046875 +99615 -0.052886962890625 +99616 -0.52593994140625 +99617 -0.186279296875 +99618 -0.497314453125 +99619 -0.23291015625 +99620 -0.411468505859375 +99621 -0.209442138671875 +99622 -0.3050537109375 +99623 -0.174163818359375 +99624 -0.183013916015625 +99625 -0.126739501953125 +99626 -0.040313720703125 +99627 -0.048126220703125 +99628 0.106964111328125 +99629 0.0426025390625 +99630 0.232635498046875 +99631 0.10748291015625 +99632 0.32891845703125 +99633 0.1409912109375 +99634 0.4217529296875 +99635 0.19708251953125 +99636 0.507049560546875 +99637 0.273651123046875 +99638 0.553741455078125 +99639 0.31768798828125 +99640 0.567779541015625 +99641 0.341094970703125 +99642 0.56304931640625 +99643 0.368011474609375 +99644 0.526885986328125 +99645 0.37249755859375 +99646 0.432220458984375 +99647 0.30072021484375 +99648 0.282012939453125 +99649 0.1517333984375 +99650 0.113311767578125 +99651 -0.01470947265625 +99652 -0.063751220703125 +99653 -0.1883544921875 +99654 -0.24658203125 +99655 -0.372711181640625 +99656 -0.401092529296875 +99657 -0.51397705078125 +99658 -0.50091552734375 +99659 -0.57177734375 +99660 -0.5389404296875 +99661 -0.53948974609375 +99662 -0.52239990234375 +99663 -0.43511962890625 +99664 -0.470245361328125 +99665 -0.2962646484375 +99666 -0.4027099609375 +99667 -0.161102294921875 +99668 -0.32757568359375 +99669 -0.0435791015625 +99670 -0.24365234375 +99671 0.060394287109375 +99672 -0.16064453125 +99673 0.13665771484375 +99674 -0.089508056640625 +99675 0.170135498046875 +99676 -0.0308837890625 +99677 0.16552734375 +99678 0.0306396484375 +99679 0.15728759765625 +99680 0.09429931640625 +99681 0.150787353515625 +99682 0.14312744140625 +99683 0.12200927734375 +99684 0.1787109375 +99685 0.080108642578125 +99686 0.212493896484375 +99687 0.05126953125 +99688 0.25714111328125 +99689 0.062896728515625 +99690 0.298583984375 +99691 0.09271240234375 +99692 0.309539794921875 +99693 0.092987060546875 +99694 0.2979736328125 +99695 0.07855224609375 +99696 0.272735595703125 +99697 0.06427001953125 +99698 0.2266845703125 +99699 0.0347900390625 +99700 0.1607666015625 +99701 -0.01171875 +99702 0.08807373046875 +99703 -0.056060791015625 +99704 0.0350341796875 +99705 -0.055511474609375 +99706 0.0045166015625 +99707 -0.010467529296875 +99708 -0.030181884765625 +99709 0.02508544921875 +99710 -0.0802001953125 +99711 0.025665283203125 +99712 -0.128509521484375 +99713 0.017333984375 +99714 -0.17193603515625 +99715 0.00189208984375 +99716 -0.214935302734375 +99717 -0.03173828125 +99718 -0.249847412109375 +99719 -0.071502685546875 +99720 -0.2862548828125 +99721 -0.13543701171875 +99722 -0.322479248046875 +99723 -0.219970703125 +99724 -0.3458251953125 +99725 -0.300506591796875 +99726 -0.357330322265625 +99727 -0.376312255859375 +99728 -0.341644287109375 +99729 -0.416107177734375 +99730 -0.27410888671875 +99731 -0.371124267578125 +99732 -0.157745361328125 +99733 -0.242279052734375 +99734 -0.017242431640625 +99735 -0.069732666015625 +99736 0.133392333984375 +99737 0.125640869140625 +99738 0.274688720703125 +99739 0.31268310546875 +99740 0.3846435546875 +99741 0.45501708984375 +99742 0.462921142578125 +99743 0.554779052734375 +99744 0.507781982421875 +99745 0.61065673828125 +99746 0.512237548828125 +99747 0.610931396484375 +99748 0.4630126953125 +99749 0.531463623046875 +99750 0.36956787109375 +99751 0.3883056640625 +99752 0.262298583984375 +99753 0.23468017578125 +99754 0.15631103515625 +99755 0.095245361328125 +99756 0.06768798828125 +99757 -0.00396728515625 +99758 0.006378173828125 +99759 -0.04852294921875 +99760 -0.03472900390625 +99761 -0.055145263671875 +99762 -0.082275390625 +99763 -0.0758056640625 +99764 -0.149871826171875 +99765 -0.138702392578125 +99766 -0.216705322265625 +99767 -0.209197998046875 +99768 -0.2823486328125 +99769 -0.289031982421875 +99770 -0.346160888671875 +99771 -0.37884521484375 +99772 -0.395263671875 +99773 -0.456329345703125 +99774 -0.4267578125 +99775 -0.51641845703125 +99776 -0.418975830078125 +99777 -0.519287109375 +99778 -0.368988037109375 +99779 -0.458251953125 +99780 -0.3062744140625 +99781 -0.384796142578125 +99782 -0.245880126953125 +99783 -0.323699951171875 +99784 -0.186248779296875 +99785 -0.269287109375 +99786 -0.114532470703125 +99787 -0.1951904296875 +99788 -0.03167724609375 +99789 -0.100006103515625 +99790 0.04583740234375 +99791 -0.01055908203125 +99792 0.13323974609375 +99793 0.1033935546875 +99794 0.233306884765625 +99795 0.24908447265625 +99796 0.315673828125 +99797 0.373199462890625 +99798 0.370025634765625 +99799 0.45806884765625 +99800 0.400390625 +99801 0.511474609375 +99802 0.424591064453125 +99803 0.565399169921875 +99804 0.43841552734375 +99805 0.61138916015625 +99806 0.40972900390625 +99807 0.5897216796875 +99808 0.334136962890625 +99809 0.4906005859375 +99810 0.222564697265625 +99811 0.33148193359375 +99812 0.095947265625 +99813 0.147796630859375 +99814 -0.021240234375 +99815 -0.01873779296875 +99816 -0.112274169921875 +99817 -0.140289306640625 +99818 -0.162139892578125 +99819 -0.191986083984375 +99820 -0.175537109375 +99821 -0.184295654296875 +99822 -0.176239013671875 +99823 -0.161834716796875 +99824 -0.18682861328125 +99825 -0.166595458984375 +99826 -0.204437255859375 +99827 -0.19390869140625 +99828 -0.218414306640625 +99829 -0.22442626953125 +99830 -0.240997314453125 +99831 -0.279754638671875 +99832 -0.26123046875 +99833 -0.3389892578125 +99834 -0.253570556640625 +99835 -0.3543701171875 +99836 -0.231292724609375 +99837 -0.348175048828125 +99838 -0.198577880859375 +99839 -0.32598876953125 +99840 -0.1402587890625 +99841 -0.2581787109375 +99842 -0.054779052734375 +99843 -0.139801025390625 +99844 0.04876708984375 +99845 0.014617919921875 +99846 0.135955810546875 +99847 0.144378662109375 +99848 0.1904296875 +99849 0.221038818359375 +99850 0.225921630859375 +99851 0.27069091796875 +99852 0.24249267578125 +99853 0.294036865234375 +99854 0.25146484375 +99855 0.311767578125 +99856 0.261322021484375 +99857 0.339141845703125 +99858 0.263336181640625 +99859 0.360260009765625 +99860 0.250213623046875 +99861 0.360504150390625 +99862 0.20654296875 +99863 0.308380126953125 +99864 0.121856689453125 +99865 0.18170166015625 +99866 0.010009765625 +99867 0.0047607421875 +99868 -0.10345458984375 +99869 -0.17559814453125 +99870 -0.194000244140625 +99871 -0.3143310546875 +99872 -0.238006591796875 +99873 -0.36785888671875 +99874 -0.248321533203125 +99875 -0.36248779296875 +99876 -0.247894287109375 +99877 -0.343536376953125 +99878 -0.2315673828125 +99879 -0.3018798828125 +99880 -0.19598388671875 +99881 -0.231414794921875 +99882 -0.133697509765625 +99883 -0.117645263671875 +99884 -0.06182861328125 +99885 0.007049560546875 +99886 -0.009307861328125 +99887 0.087982177734375 +99888 0.030609130859375 +99889 0.13946533203125 +99890 0.06378173828125 +99891 0.17425537109375 +99892 0.087158203125 +99893 0.188201904296875 +99894 0.094573974609375 +99895 0.171234130859375 +99896 0.08258056640625 +99897 0.118438720703125 +99898 0.064544677734375 +99899 0.05706787109375 +99900 0.040863037109375 +99901 -0.010711669921875 +99902 0.007568359375 +99903 -0.0914306640625 +99904 -0.023834228515625 +99905 -0.162322998046875 +99906 -0.03857421875 +99907 -0.194549560546875 +99908 -0.0164794921875 +99909 -0.1492919921875 +99910 0.045135498046875 +99911 -0.02166748046875 +99912 0.11322021484375 +99913 0.124053955078125 +99914 0.14837646484375 +99915 0.211151123046875 +99916 0.151641845703125 +99917 0.240447998046875 +99918 0.13946533203125 +99919 0.242218017578125 +99920 0.117431640625 +99921 0.2257080078125 +99922 0.08807373046875 +99923 0.194366455078125 +99924 0.03509521484375 +99925 0.115509033203125 +99926 -0.028533935546875 +99927 0.0128173828125 +99928 -0.0711669921875 +99929 -0.053802490234375 +99930 -0.1060791015625 +99931 -0.110626220703125 +99932 -0.15484619140625 +99933 -0.199493408203125 +99934 -0.203887939453125 +99935 -0.29437255859375 +99936 -0.220458984375 +99937 -0.33221435546875 +99938 -0.187530517578125 +99939 -0.27972412109375 +99940 -0.13067626953125 +99941 -0.185333251953125 +99942 -0.091522216796875 +99943 -0.128204345703125 +99944 -0.074462890625 +99945 -0.115692138671875 +99946 -0.0638427734375 +99947 -0.116455078125 +99948 -0.047454833984375 +99949 -0.105926513671875 +99950 -0.01025390625 +99951 -0.053955078125 +99952 0.052093505859375 +99953 0.048797607421875 +99954 0.115753173828125 +99955 0.157318115234375 +99956 0.14935302734375 +99957 0.212005615234375 +99958 0.155609130859375 +99959 0.218475341796875 +99960 0.165863037109375 +99961 0.23724365234375 +99962 0.199432373046875 +99963 0.30535888671875 +99964 0.234893798828125 +99965 0.38128662109375 +99966 0.24102783203125 +99967 0.404449462890625 +99968 0.228363037109375 +99969 0.3944091796875 +99970 0.216827392578125 +99971 0.3885498046875 +99972 0.194305419921875 +99973 0.362640380859375 +99974 0.138916015625 +99975 0.27362060546875 +99976 0.04888916015625 +99977 0.11712646484375 +99978 -0.04827880859375 +99979 -0.054901123046875 +99980 -0.125335693359375 +99981 -0.19085693359375 +99982 -0.17938232421875 +99983 -0.28570556640625 +99984 -0.21014404296875 +99985 -0.339263916015625 +99986 -0.23101806640625 +99987 -0.3775634765625 +99988 -0.2655029296875 +99989 -0.445709228515625 +99990 -0.309173583984375 +99991 -0.535064697265625 +99992 -0.3536376953125 +99993 -0.629058837890625 +99994 -0.383514404296875 +99995 -0.697601318359375 +99996 -0.38006591796875 +99997 -0.70391845703125 +99998 -0.340789794921875 +99999 -0.6424560546875 +100000 -0.254669189453125 +100001 -0.491241455078125 +100002 -0.130157470703125 +100003 -0.265716552734375 +100004 0.00225830078125 +100005 -0.023712158203125 +100006 0.125091552734375 +100007 0.201751708984375 +100008 0.219940185546875 +100009 0.375823974609375 +100010 0.27960205078125 +100011 0.485076904296875 +100012 0.324432373046875 +100013 0.56884765625 +100014 0.3583984375 +100015 0.634765625 +100016 0.3580322265625 +100017 0.63763427734375 +100018 0.317535400390625 +100019 0.5660400390625 +100020 0.26422119140625 +100021 0.4720458984375 +100022 0.225006103515625 +100023 0.40692138671875 +100024 0.203948974609375 +100025 0.3778076171875 +100026 0.197357177734375 +100027 0.376953125 +100028 0.188720703125 +100029 0.371978759765625 +100030 0.15252685546875 +100031 0.313140869140625 +100032 0.0806884765625 +100033 0.184417724609375 +100034 -0.0133056640625 +100035 0.011199951171875 +100036 -0.110809326171875 +100037 -0.171051025390625 +100038 -0.198760986328125 +100039 -0.33740234375 +100040 -0.268829345703125 +100041 -0.47198486328125 +100042 -0.3135986328125 +100043 -0.560394287109375 +100044 -0.321685791015625 +100045 -0.58056640625 +100046 -0.30108642578125 +100047 -0.54754638671875 +100048 -0.276580810546875 +100049 -0.508575439453125 +100050 -0.24627685546875 +100051 -0.459503173828125 +100052 -0.207366943359375 +100053 -0.394378662109375 +100054 -0.18060302734375 +100055 -0.35260009765625 +100056 -0.154571533203125 +100057 -0.31170654296875 +100058 -0.090911865234375 +100059 -0.197418212890625 +100060 0.01104736328125 +100061 -0.007965087890625 +100062 0.125579833984375 +100063 0.207489013671875 +100064 0.23193359375 +100065 0.409210205078125 +100066 0.3170166015625 +100067 0.57208251953125 +100068 0.365142822265625 +100069 0.66595458984375 +100070 0.359710693359375 +100071 0.65875244140625 +100072 0.30963134765625 +100073 0.56744384765625 +100074 0.235565185546875 +100075 0.431396484375 +100076 0.1605224609375 +100077 0.29443359375 +100078 0.098175048828125 +100079 0.182464599609375 +100080 0.0322265625 +100081 0.06365966796875 +100082 -0.044342041015625 +100083 -0.075958251953125 +100084 -0.10693359375 +100085 -0.189422607421875 +100086 -0.152862548828125 +100087 -0.271942138671875 +100088 -0.19183349609375 +100089 -0.342529296875 +100090 -0.204559326171875 +100091 -0.364166259765625 +100092 -0.18597412109375 +100093 -0.327239990234375 +100094 -0.159576416015625 +100095 -0.2769775390625 +100096 -0.146087646484375 +100097 -0.253692626953125 +100098 -0.138702392578125 +100099 -0.24365234375 +100100 -0.1134033203125 +100101 -0.1983642578125 +100102 -0.069488525390625 +100103 -0.116241455078125 +100104 -0.026336669921875 +100105 -0.036834716796875 +100106 0.013427734375 +100107 0.034881591796875 +100108 0.04583740234375 +100109 0.09124755859375 +100110 0.059234619140625 +100111 0.10888671875 +100112 0.071746826171875 +100113 0.125518798828125 +100114 0.09124755859375 +100115 0.15771484375 +100116 0.104248046875 +100117 0.17828369140625 +100118 0.10272216796875 +100119 0.17108154296875 +100120 0.083587646484375 +100121 0.129974365234375 +100122 0.060211181640625 +100123 0.082427978515625 +100124 0.032257080078125 +100125 0.027679443359375 +100126 -0.015472412109375 +100127 -0.065643310546875 +100128 -0.064178466796875 +100129 -0.15936279296875 +100130 -0.093994140625 +100131 -0.21307373046875 +100132 -0.108551025390625 +100133 -0.234649658203125 +100134 -0.095947265625 +100135 -0.2001953125 +100136 -0.060577392578125 +100137 -0.119171142578125 +100138 -0.018402099609375 +100139 -0.024749755859375 +100140 0.032073974609375 +100141 0.085784912109375 +100142 0.074310302734375 +100143 0.178131103515625 +100144 0.09051513671875 +100145 0.215576171875 +100146 0.0872802734375 +100147 0.211456298828125 +100148 0.06927490234375 +100149 0.17523193359375 +100150 0.04718017578125 +100151 0.128753662109375 +100152 0.0355224609375 +100153 0.1019287109375 +100154 0.02423095703125 +100155 0.0743408203125 +100156 0.0118408203125 +100157 0.04327392578125 +100158 0.012542724609375 +100159 0.038177490234375 +100160 0.034576416015625 +100161 0.076263427734375 +100162 0.069671630859375 +100163 0.14105224609375 +100164 0.09515380859375 +100165 0.186431884765625 +100166 0.099334716796875 +100167 0.188812255859375 +100168 0.07757568359375 +100169 0.1390380859375 +100170 0.03204345703125 +100171 0.041778564453125 +100172 -0.025848388671875 +100173 -0.079437255859375 +100174 -0.093597412109375 +100175 -0.219390869140625 +100176 -0.16619873046875 +100177 -0.367828369140625 +100178 -0.229034423828125 +100179 -0.494873046875 +100180 -0.260467529296875 +100181 -0.556243896484375 +100182 -0.239288330078125 +100183 -0.508697509765625 +100184 -0.176788330078125 +100185 -0.3756103515625 +100186 -0.10302734375 +100187 -0.218902587890625 +100188 -0.030120849609375 +100189 -0.063751220703125 +100190 0.042877197265625 +100191 0.091552734375 +100192 0.110748291015625 +100193 0.23602294921875 +100194 0.160614013671875 +100195 0.342987060546875 +100196 0.1842041015625 +100197 0.39520263671875 +100198 0.17999267578125 +100199 0.389373779296875 +100200 0.147430419921875 +100201 0.324249267578125 +100202 0.098388671875 +100203 0.224090576171875 +100204 0.050140380859375 +100205 0.124267578125 +100206 0.00860595703125 +100207 0.037078857421875 +100208 -0.012908935546875 +100209 -0.010101318359375 +100210 -0.01556396484375 +100211 -0.019439697265625 +100212 -0.0150146484375 +100213 -0.022796630859375 +100214 -0.002288818359375 +100215 -0.001556396484375 +100216 0.0283203125 +100217 0.056304931640625 +100218 0.05517578125 +100219 0.106719970703125 +100220 0.05242919921875 +100221 0.096893310546875 +100222 0.027679443359375 +100223 0.042694091796875 +100224 -0.00067138671875 +100225 -0.018035888671875 +100226 -0.028076171875 +100227 -0.07586669921875 +100228 -0.04901123046875 +100229 -0.11944580078125 +100230 -0.06884765625 +100231 -0.15972900390625 +100232 -0.0904541015625 +100233 -0.202606201171875 +100234 -0.113983154296875 +100235 -0.24859619140625 +100236 -0.143035888671875 +100237 -0.30517578125 +100238 -0.17254638671875 +100239 -0.36212158203125 +100240 -0.188720703125 +100241 -0.39141845703125 +100242 -0.173004150390625 +100243 -0.35528564453125 +100244 -0.12347412109375 +100245 -0.249969482421875 +100246 -0.04852294921875 +100247 -0.092864990234375 +100248 0.03875732421875 +100249 0.08905029296875 +100250 0.10888671875 +100251 0.2352294921875 +100252 0.148834228515625 +100253 0.318817138671875 +100254 0.167816162109375 +100255 0.358642578125 +100256 0.162445068359375 +100257 0.347747802734375 +100258 0.132476806640625 +100259 0.28564453125 +100260 0.102691650390625 +100261 0.223175048828125 +100262 0.090789794921875 +100263 0.196746826171875 +100264 0.08380126953125 +100265 0.179840087890625 +100266 0.073394775390625 +100267 0.155548095703125 +100268 0.07281494140625 +100269 0.151214599609375 +100270 0.0771484375 +100271 0.156951904296875 +100272 0.066314697265625 +100273 0.13177490234375 +100274 0.052520751953125 +100275 0.100799560546875 +100276 0.04693603515625 +100277 0.087127685546875 +100278 0.032012939453125 +100279 0.05487060546875 +100280 0.0013427734375 +100281 -0.009002685546875 +100282 -0.044830322265625 +100283 -0.10400390625 +100284 -0.10614013671875 +100285 -0.229400634765625 +100286 -0.1680908203125 +100287 -0.35552978515625 +100288 -0.210906982421875 +100289 -0.441925048828125 +100290 -0.227386474609375 +100291 -0.473846435546875 +100292 -0.22406005859375 +100293 -0.464813232421875 +100294 -0.202911376953125 +100295 -0.419097900390625 +100296 -0.1627197265625 +100297 -0.334320068359375 +100298 -0.111968994140625 +100299 -0.227935791015625 +100300 -0.06207275390625 +100301 -0.12347412109375 +100302 -0.0162353515625 +100303 -0.02764892578125 +100304 0.034423828125 +100305 0.077667236328125 +100306 0.100067138671875 +100307 0.2132568359375 +100308 0.185455322265625 +100309 0.38885498046875 +100310 0.280029296875 +100311 0.582794189453125 +100312 0.35400390625 +100313 0.734039306640625 +100314 0.38665771484375 +100315 0.800140380859375 +100316 0.3765869140625 +100317 0.7783203125 +100318 0.322113037109375 +100319 0.6651611328125 +100320 0.222686767578125 +100321 0.45965576171875 +100322 0.09649658203125 +100323 0.199188232421875 +100324 -0.024505615234375 +100325 -0.050689697265625 +100326 -0.112548828125 +100327 -0.23297119140625 +100328 -0.159149169921875 +100329 -0.33013916015625 +100330 -0.177093505859375 +100331 -0.368408203125 +100332 -0.181640625 +100333 -0.378936767578125 +100334 -0.1802978515625 +100335 -0.376983642578125 +100336 -0.18145751953125 +100337 -0.37969970703125 +100338 -0.187255859375 +100339 -0.391510009765625 +100340 -0.1844482421875 +100341 -0.385345458984375 +100342 -0.16363525390625 +100343 -0.3419189453125 +100344 -0.1353759765625 +100345 -0.28289794921875 +100346 -0.12078857421875 +100347 -0.251617431640625 +100348 -0.12860107421875 +100349 -0.266143798828125 +100350 -0.13287353515625 +100351 -0.273345947265625 +100352 -0.106170654296875 +100353 -0.216796875 +100354 -0.06365966796875 +100355 -0.128265380859375 +100356 -0.0338134765625 +100357 -0.068145751953125 +100358 -0.019805908203125 +100359 -0.0430908203125 +100360 -0.008697509765625 +100361 -0.024444580078125 +100362 0.01434326171875 +100363 0.020721435546875 +100364 0.06378173828125 +100365 0.124481201171875 +100366 0.126312255859375 +100367 0.25787353515625 +100368 0.182769775390625 +100369 0.379119873046875 +100370 0.229339599609375 +100371 0.47991943359375 +100372 0.251373291015625 +100373 0.5281982421875 +100374 0.243011474609375 +100375 0.511138916015625 +100376 0.216827392578125 +100377 0.456207275390625 +100378 0.193023681640625 +100379 0.407470703125 +100380 0.1802978515625 +100381 0.383758544921875 +100382 0.1658935546875 +100383 0.35687255859375 +100384 0.143096923828125 +100385 0.31182861328125 +100386 0.113037109375 +100387 0.250885009765625 +100388 0.071929931640625 +100389 0.1654052734375 +100390 0.010711669921875 +100391 0.035247802734375 +100392 -0.071624755859375 +100393 -0.142059326171875 +100394 -0.160919189453125 +100395 -0.33563232421875 +100396 -0.252166748046875 +100397 -0.5345458984375 +100398 -0.337615966796875 +100399 -0.72186279296875 +100400 -0.389495849609375 +100401 -0.836669921875 +100402 -0.386749267578125 +100403 -0.8326416015625 +100404 -0.3385009765625 +100405 -0.7296142578125 +100406 -0.2698974609375 +100407 -0.582550048828125 +100408 -0.20318603515625 +100409 -0.440093994140625 +100410 -0.1485595703125 +100411 -0.324310302734375 +100412 -0.0906982421875 +100413 -0.20147705078125 +100414 -0.017425537109375 +100415 -0.044647216796875 +100416 0.051910400390625 +100417 0.103973388671875 +100418 0.098052978515625 +100419 0.202392578125 +100420 0.12725830078125 +100421 0.264495849609375 +100422 0.16168212890625 +100423 0.338897705078125 +100424 0.209625244140625 +100425 0.443817138671875 +100426 0.2554931640625 +100427 0.545074462890625 +100428 0.287750244140625 +100429 0.6173095703125 +100430 0.302764892578125 +100431 0.6524658203125 +100432 0.30645751953125 +100433 0.66339111328125 +100434 0.301666259765625 +100435 0.6561279296875 +100436 0.277587890625 +100437 0.606781005859375 +100438 0.22784423828125 +100439 0.501190185546875 +100440 0.158660888671875 +100441 0.352783203125 +100442 0.076934814453125 +100443 0.176544189453125 +100444 -0.020538330078125 +100445 -0.034820556640625 +100446 -0.1231689453125 +100447 -0.258209228515625 +100448 -0.20758056640625 +100449 -0.44244384765625 +100450 -0.268218994140625 +100451 -0.5753173828125 +100452 -0.30291748046875 +100453 -0.65203857421875 +100454 -0.297576904296875 +100455 -0.641632080078125 +100456 -0.260467529296875 +100457 -0.562164306640625 +100458 -0.2119140625 +100459 -0.458038330078125 +100460 -0.16168212890625 +100461 -0.350555419921875 +100462 -0.11932373046875 +100463 -0.260528564453125 +100464 -0.086822509765625 +100465 -0.192108154296875 +100466 -0.062713623046875 +100467 -0.141937255859375 +100468 -0.043487548828125 +100469 -0.1021728515625 +100470 -0.024658203125 +100471 -0.062896728515625 +100472 -0.000701904296875 +100473 -0.011932373046875 +100474 0.033843994140625 +100475 0.062835693359375 +100476 0.07318115234375 +100477 0.148712158203125 +100478 0.115478515625 +100479 0.241729736328125 +100480 0.164031982421875 +100481 0.34912109375 +100482 0.212677001953125 +100483 0.457305908203125 +100484 0.251251220703125 +100485 0.54388427734375 +100486 0.263427734375 +100487 0.5728759765625 +100488 0.232086181640625 +100489 0.506591796875 +100490 0.16009521484375 +100491 0.351226806640625 +100492 0.065643310546875 +100493 0.146514892578125 +100494 -0.02734375 +100495 -0.05523681640625 +100496 -0.101593017578125 +100497 -0.21624755859375 +100498 -0.156341552734375 +100499 -0.334930419921875 +100500 -0.187774658203125 +100501 -0.402984619140625 +100502 -0.20538330078125 +100503 -0.4412841796875 +100504 -0.230133056640625 +100505 -0.49578857421875 +100506 -0.2591552734375 +100507 -0.5601806640625 +100508 -0.277099609375 +100509 -0.600738525390625 +100510 -0.268829345703125 +100511 -0.584228515625 +100512 -0.220123291015625 +100513 -0.47930908203125 +100514 -0.128021240234375 +100515 -0.27935791015625 +100516 -0.003753662109375 +100517 -0.0089111328125 +100518 0.123748779296875 +100519 0.268798828125 +100520 0.222137451171875 +100521 0.482818603515625 +100522 0.277923583984375 +100523 0.60369873046875 +100524 0.299713134765625 +100525 0.650421142578125 +100526 0.30621337890625 +100527 0.66400146484375 +100528 0.296051025390625 +100529 0.6414794921875 +100530 0.2645263671875 +100531 0.572540283203125 +100532 0.230316162109375 +100533 0.498138427734375 +100534 0.203094482421875 +100535 0.439453125 +100536 0.173370361328125 +100537 0.375518798828125 +100538 0.12664794921875 +100539 0.274505615234375 +100540 0.05035400390625 +100541 0.1087646484375 +100542 -0.0452880859375 +100543 -0.099395751953125 +100544 -0.145782470703125 +100545 -0.3182373046875 +100546 -0.251617431640625 +100547 -0.5489501953125 +100548 -0.35467529296875 +100549 -0.7738037109375 +100550 -0.4307861328125 +100551 -0.86383056640625 +100552 -0.464752197265625 +100553 -0.870391845703125 +100554 -0.46466064453125 +100555 -0.86895751953125 +100556 -0.436492919921875 +100557 -0.861053466796875 +100558 -0.37237548828125 +100559 -0.765869140625 +100560 -0.26715087890625 +100561 -0.5301513671875 +100562 -0.124114990234375 +100563 -0.214691162109375 +100564 0.037078857421875 +100565 0.137359619140625 +100566 0.1929931640625 +100567 0.474822998046875 +100568 0.327362060546875 +100569 0.76239013671875 +100570 0.427825927734375 +100571 0.867462158203125 +100572 0.49456787109375 +100573 0.870361328125 +100574 0.522308349609375 +100575 0.86480712890625 +100576 0.513458251953125 +100577 0.831817626953125 +100578 0.4791259765625 +100579 0.677581787109375 +100580 0.42193603515625 +100581 0.495880126953125 +100582 0.35040283203125 +100583 0.30767822265625 +100584 0.2655029296875 +100585 0.116180419921875 +100586 0.152801513671875 +100587 -0.110748291015625 +100588 0.009185791015625 +100589 -0.381805419921875 +100590 -0.14581298828125 +100591 -0.6572265625 +100592 -0.28485107421875 +100593 -0.857421875 +100594 -0.388336181640625 +100595 -0.870391845703125 +100596 -0.4530029296875 +100597 -0.870391845703125 +100598 -0.4910888671875 +100599 -0.86444091796875 +100600 -0.518829345703125 +100601 -0.85723876953125 +100602 -0.52783203125 +100603 -0.790008544921875 +100604 -0.49334716796875 +100605 -0.62847900390625 +100606 -0.413909912109375 +100607 -0.3956298828125 +100608 -0.3045654296875 +100609 -0.126708984375 +100610 -0.17779541015625 +100611 0.150115966796875 +100612 -0.039276123046875 +100613 0.424041748046875 +100614 0.098876953125 +100615 0.670623779296875 +100616 0.21966552734375 +100617 0.854522705078125 +100618 0.315093994140625 +100619 0.866485595703125 +100620 0.37823486328125 +100621 0.86920166015625 +100622 0.41650390625 +100623 0.8653564453125 +100624 0.4354248046875 +100625 0.857147216796875 +100626 0.433685302734375 +100627 0.766845703125 +100628 0.413543701171875 +100629 0.628509521484375 +100630 0.372314453125 +100631 0.462127685546875 +100632 0.3211669921875 +100633 0.297210693359375 +100634 0.265716552734375 +100635 0.14862060546875 +100636 0.1966552734375 +100637 -0.00537109375 +100638 0.11761474609375 +100639 -0.15753173828125 +100640 0.027496337890625 +100641 -0.31304931640625 +100642 -0.079193115234375 +100643 -0.48876953125 +100644 -0.182220458984375 +100645 -0.6416015625 +100646 -0.270751953125 +100647 -0.751373291015625 +100648 -0.35430908203125 +100649 -0.84619140625 +100650 -0.426513671875 +100651 -0.861297607421875 +100652 -0.47320556640625 +100653 -0.863250732421875 +100654 -0.480987548828125 +100655 -0.856597900390625 +100656 -0.455108642578125 +100657 -0.7498779296875 +100658 -0.420318603515625 +100659 -0.624542236328125 +100660 -0.367523193359375 +100661 -0.47808837890625 +100662 -0.27227783203125 +100663 -0.253387451171875 +100664 -0.154266357421875 +100665 0.003692626953125 +100666 -0.042877197265625 +100667 0.2257080078125 +100668 0.066802978515625 +100669 0.427154541015625 +100670 0.188201904296875 +100671 0.643218994140625 +100672 0.31695556640625 +100673 0.855926513671875 +100674 0.42822265625 +100675 0.870361328125 +100676 0.500823974609375 +100677 0.870361328125 +100678 0.537689208984375 +100679 0.862762451171875 +100680 0.53753662109375 +100681 0.79669189453125 +100682 0.496429443359375 +100683 0.595794677734375 +100684 0.4268798828125 +100685 0.362152099609375 +100686 0.340972900390625 +100687 0.1270751953125 +100688 0.2479248046875 +100689 -0.086944580078125 +100690 0.148956298828125 +100691 -0.2784423828125 +100692 0.02960205078125 +100693 -0.484832763671875 +100694 -0.117889404296875 +100695 -0.729583740234375 +100696 -0.27178955078125 +100697 -0.86688232421875 +100698 -0.404937744140625 +100699 -0.870391845703125 +100700 -0.514984130859375 +100701 -0.86859130859375 +100702 -0.600830078125 +100703 -0.86279296875 +100704 -0.6470947265625 +100705 -0.817962646484375 +100706 -0.634490966796875 +100707 -0.6116943359375 +100708 -0.56005859375 +100709 -0.3128662109375 +100710 -0.43817138671875 +100711 0.039398193359375 +100712 -0.2774658203125 +100713 0.422821044921875 +100714 -0.092254638671875 +100715 0.805145263671875 +100716 0.0882568359375 +100717 0.870361328125 +100718 0.239593505859375 +100719 0.870361328125 +100720 0.356475830078125 +100721 0.860015869140625 +100722 0.435302734375 +100723 0.727935791015625 +100724 0.473358154296875 +100725 0.48114013671875 +100726 0.480560302734375 +100727 0.2059326171875 +100728 0.46624755859375 +100729 -0.06103515625 +100730 0.43450927734375 +100731 -0.29913330078125 +100732 0.37908935546875 +100733 -0.516204833984375 +100734 0.29345703125 +100735 -0.7252197265625 +100736 0.188262939453125 +100737 -0.85980224609375 +100738 0.0782470703125 +100739 -0.870391845703125 +100740 -0.023773193359375 +100741 -0.870391845703125 +100742 -0.0968017578125 +100743 -0.858062744140625 +100744 -0.138641357421875 +100745 -0.673004150390625 +100746 -0.171112060546875 +100747 -0.42694091796875 +100748 -0.212615966796875 +100749 -0.2100830078125 +100750 -0.26177978515625 +100751 -0.0362548828125 +100752 -0.305877685546875 +100753 0.10943603515625 +100754 -0.336151123046875 +100755 0.23516845703125 +100756 -0.334808349609375 +100757 0.373687744140625 +100758 -0.302520751953125 +100759 0.517791748046875 +100760 -0.2659912109375 +100761 0.602783203125 +100762 -0.22308349609375 +100763 0.635711669921875 +100764 -0.15985107421875 +100765 0.655181884765625 +100766 -0.080718994140625 +100767 0.65948486328125 +100768 0.010498046875 +100769 0.651275634765625 +100770 0.10302734375 +100771 0.61846923828125 +100772 0.180755615234375 +100773 0.53753662109375 +100774 0.235565185546875 +100775 0.404144287109375 +100776 0.262939453125 +100777 0.22186279296875 +100778 0.263031005859375 +100779 0.003997802734375 +100780 0.243194580078125 +100781 -0.22100830078125 +100782 0.2119140625 +100783 -0.42449951171875 +100784 0.1781005859375 +100785 -0.579833984375 +100786 0.159820556640625 +100787 -0.641876220703125 +100788 0.154266357421875 +100789 -0.6177978515625 +100790 0.134185791015625 +100791 -0.575531005859375 +100792 0.097503662109375 +100793 -0.526336669921875 +100794 0.06646728515625 +100795 -0.42645263671875 +100796 0.053009033203125 +100797 -0.2581787109375 +100798 0.0421142578125 +100799 -0.068695068359375 +100800 0.017852783203125 +100801 0.09222412109375 +100802 -0.011474609375 +100803 0.232147216796875 +100804 -0.041168212890625 +100805 0.3509521484375 +100806 -0.08349609375 +100807 0.410064697265625 +100808 -0.150604248046875 +100809 0.372955322265625 +100810 -0.23345947265625 +100811 0.2554931640625 +100812 -0.309814453125 +100813 0.10711669921875 +100814 -0.371337890625 +100815 -0.052886962890625 +100816 -0.4027099609375 +100817 -0.186279296875 +100818 -0.380340576171875 +100819 -0.23291015625 +100820 -0.3140869140625 +100821 -0.209442138671875 +100822 -0.232147216796875 +100823 -0.174163818359375 +100824 -0.138336181640625 +100825 -0.126739501953125 +100826 -0.02880859375 +100827 -0.048126220703125 +100828 0.084136962890625 +100829 0.0426025390625 +100830 0.180389404296875 +100831 0.10748291015625 +100832 0.2540283203125 +100833 0.1409912109375 +100834 0.32489013671875 +100835 0.19708251953125 +100836 0.389923095703125 +100837 0.273651123046875 +100838 0.42529296875 +100839 0.31768798828125 +100840 0.43560791015625 +100841 0.341094970703125 +100842 0.4315185546875 +100843 0.368011474609375 +100844 0.403350830078125 +100845 0.37249755859375 +100846 0.330322265625 +100847 0.30072021484375 +100848 0.2147216796875 +100849 0.1517333984375 +100850 0.08502197265625 +100851 -0.01470947265625 +100852 -0.05096435546875 +100853 -0.1883544921875 +100854 -0.191253662109375 +100855 -0.372711181640625 +100856 -0.309661865234375 +100857 -0.51397705078125 +100858 -0.385986328125 +100859 -0.57177734375 +100860 -0.414794921875 +100861 -0.53948974609375 +100862 -0.40167236328125 +100863 -0.43511962890625 +100864 -0.3614501953125 +100865 -0.2962646484375 +100866 -0.309814453125 +100867 -0.161102294921875 +100868 -0.252593994140625 +100869 -0.0435791015625 +100870 -0.188812255859375 +100871 0.060394287109375 +100872 -0.125457763671875 +100873 0.13665771484375 +100874 -0.070465087890625 +100875 0.170135498046875 +100876 -0.02435302734375 +100877 0.16552734375 +100878 0.023895263671875 +100879 0.15728759765625 +100880 0.0736083984375 +100881 0.150787353515625 +100882 0.1123046875 +100883 0.12200927734375 +100884 0.1409912109375 +100885 0.080108642578125 +100886 0.16778564453125 +100887 0.05126953125 +100888 0.201751708984375 +100889 0.062896728515625 +100890 0.23260498046875 +100891 0.09271240234375 +100892 0.240509033203125 +100893 0.092987060546875 +100894 0.231292724609375 +100895 0.07855224609375 +100896 0.21136474609375 +100897 0.06427001953125 +100898 0.1756591796875 +100899 0.0347900390625 +100900 0.125 +100901 -0.01171875 +100902 0.069061279296875 +100903 -0.056060791015625 +100904 0.027191162109375 +100905 -0.055511474609375 +100906 0.001617431640625 +100907 -0.010467529296875 +100908 -0.02679443359375 +100909 0.02508544921875 +100910 -0.06591796875 +100911 0.025665283203125 +100912 -0.103302001953125 +100913 0.017333984375 +100914 -0.13653564453125 +100915 0.00189208984375 +100916 -0.16876220703125 +100917 -0.03173828125 +100918 -0.19439697265625 +100919 -0.071502685546875 +100920 -0.220367431640625 +100921 -0.13543701171875 +100922 -0.245513916015625 +100923 -0.219970703125 +100924 -0.26068115234375 +100925 -0.300506591796875 +100926 -0.266754150390625 +100927 -0.376312255859375 +100928 -0.252777099609375 +100929 -0.416107177734375 +100930 -0.2010498046875 +100931 -0.371124267578125 +100932 -0.113861083984375 +100933 -0.242279052734375 +100934 -0.00927734375 +100935 -0.069732666015625 +100936 0.102386474609375 +100937 0.125640869140625 +100938 0.206878662109375 +100939 0.31268310546875 +100940 0.288177490234375 +100941 0.45501708984375 +100942 0.345947265625 +100943 0.554779052734375 +100944 0.37890625 +100945 0.61065673828125 +100946 0.381988525390625 +100947 0.610931396484375 +100948 0.3455810546875 +100949 0.531463623046875 +100950 0.276580810546875 +100951 0.3883056640625 +100952 0.1971435546875 +100953 0.23468017578125 +100954 0.1182861328125 +100955 0.095245361328125 +100956 0.05181884765625 +100957 -0.00396728515625 +100958 0.00506591796875 +100959 -0.04852294921875 +100960 -0.027008056640625 +100961 -0.055145263671875 +100962 -0.063568115234375 +100963 -0.0758056640625 +100964 -0.1143798828125 +100965 -0.138702392578125 +100966 -0.164276123046875 +100967 -0.209197998046875 +100968 -0.212860107421875 +100969 -0.289031982421875 +100970 -0.259674072265625 +100971 -0.37884521484375 +100972 -0.295318603515625 +100973 -0.456329345703125 +100974 -0.31768798828125 +100975 -0.51641845703125 +100976 -0.3111572265625 +100977 -0.519287109375 +100978 -0.27362060546875 +100979 -0.458251953125 +100980 -0.2265625 +100981 -0.384796142578125 +100982 -0.18096923828125 +100983 -0.323699951171875 +100984 -0.13580322265625 +100985 -0.269287109375 +100986 -0.081878662109375 +100987 -0.1951904296875 +100988 -0.019989013671875 +100989 -0.100006103515625 +100990 0.037841796875 +100991 -0.01055908203125 +100992 0.1025390625 +100993 0.1033935546875 +100994 0.176055908203125 +100995 0.24908447265625 +100996 0.236328125 +100997 0.373199462890625 +100998 0.275848388671875 +100999 0.45806884765625 +101000 0.297576904296875 +101001 0.511474609375 +101002 0.314422607421875 +101003 0.565399169921875 +101004 0.32342529296875 +101005 0.61138916015625 +101006 0.30133056640625 +101007 0.5897216796875 +101008 0.24505615234375 +101009 0.4906005859375 +101010 0.16259765625 +101011 0.33148193359375 +101012 0.0692138671875 +101013 0.147796630859375 +101014 -0.01727294921875 +101015 -0.01873779296875 +101016 -0.084625244140625 +101017 -0.140289306640625 +101018 -0.121917724609375 +101019 -0.191986083984375 +101020 -0.13250732421875 +101021 -0.184295654296875 +101022 -0.133575439453125 +101023 -0.161834716796875 +101024 -0.141448974609375 +101025 -0.166595458984375 +101026 -0.154083251953125 +101027 -0.19390869140625 +101028 -0.163726806640625 +101029 -0.22442626953125 +101030 -0.179290771484375 +101031 -0.279754638671875 +101032 -0.192901611328125 +101033 -0.3389892578125 +101034 -0.1861572265625 +101035 -0.3543701171875 +101036 -0.168731689453125 +101037 -0.348175048828125 +101038 -0.143707275390625 +101039 -0.32598876953125 +101040 -0.100189208984375 +101041 -0.2581787109375 +101042 -0.037078857421875 +101043 -0.139801025390625 +101044 0.038970947265625 +101045 0.014617919921875 +101046 0.1029052734375 +101047 0.144378662109375 +101048 0.142822265625 +101049 0.221038818359375 +101050 0.168701171875 +101051 0.27069091796875 +101052 0.18060302734375 +101053 0.294036865234375 +101054 0.186737060546875 +101055 0.311767578125 +101056 0.193328857421875 +101057 0.339141845703125 +101058 0.194305419921875 +101059 0.360260009765625 +101060 0.184295654296875 +101061 0.360504150390625 +101062 0.151611328125 +101063 0.308380126953125 +101064 0.088348388671875 +101065 0.18170166015625 +101066 0.004852294921875 +101067 0.0047607421875 +101068 -0.0797119140625 +101069 -0.17559814453125 +101070 -0.146942138671875 +101071 -0.3143310546875 +101072 -0.179107666015625 +101073 -0.36785888671875 +101074 -0.185943603515625 +101075 -0.36248779296875 +101076 -0.184783935546875 +101077 -0.343536376953125 +101078 -0.17181396484375 +101079 -0.3018798828125 +101080 -0.144500732421875 +101081 -0.231414794921875 +101082 -0.097259521484375 +101083 -0.117645263671875 +101084 -0.042999267578125 +101085 0.007049560546875 +101086 -0.0035400390625 +101087 0.087982177734375 +101088 0.026214599609375 +101089 0.13946533203125 +101090 0.05072021484375 +101091 0.17425537109375 +101092 0.06768798828125 +101093 0.188201904296875 +101094 0.072540283203125 +101095 0.171234130859375 +101096 0.062744140625 +101097 0.118438720703125 +101098 0.04840087890625 +101099 0.05706787109375 +101100 0.02984619140625 +101101 -0.010711669921875 +101102 0.004119873046875 +101103 -0.0914306640625 +101104 -0.02008056640625 +101105 -0.162322998046875 +101106 -0.031585693359375 +101107 -0.194549560546875 +101108 -0.015167236328125 +101109 -0.1492919921875 +101110 0.031219482421875 +101111 -0.02166748046875 +101112 0.0826416015625 +101113 0.124053955078125 +101114 0.109375 +101115 0.211151123046875 +101116 0.112213134765625 +101117 0.240447998046875 +101118 0.103515625 +101119 0.242218017578125 +101120 0.086944580078125 +101121 0.2257080078125 +101122 0.06463623046875 +101123 0.194366455078125 +101124 0.025970458984375 +101125 0.115509033203125 +101126 -0.019927978515625 +101127 0.0128173828125 +101128 -0.05108642578125 +101129 -0.053802490234375 +101130 -0.076629638671875 +101131 -0.110626220703125 +101132 -0.111480712890625 +101133 -0.199493408203125 +101134 -0.146148681640625 +101135 -0.29437255859375 +101136 -0.15802001953125 +101137 -0.33221435546875 +101138 -0.13531494140625 +101139 -0.27972412109375 +101140 -0.095703125 +101141 -0.185333251953125 +101142 -0.06805419921875 +101143 -0.128204345703125 +101144 -0.055450439453125 +101145 -0.115692138671875 +101146 -0.047088623046875 +101147 -0.116455078125 +101148 -0.03460693359375 +101149 -0.105926513671875 +101150 -0.00762939453125 +101151 -0.053955078125 +101152 0.0367431640625 +101153 0.048797607421875 +101154 0.081939697265625 +101155 0.157318115234375 +101156 0.106201171875 +101157 0.212005615234375 +101158 0.111328125 +101159 0.218475341796875 +101160 0.1190185546875 +101161 0.23724365234375 +101162 0.142608642578125 +101163 0.30535888671875 +101164 0.167236328125 +101165 0.38128662109375 +101166 0.1712646484375 +101167 0.404449462890625 +101168 0.16204833984375 +101169 0.3944091796875 +101170 0.153411865234375 +101171 0.3885498046875 +101172 0.13702392578125 +101173 0.362640380859375 +101174 0.0977783203125 +101175 0.27362060546875 +101176 0.034515380859375 +101177 0.11712646484375 +101178 -0.03369140625 +101179 -0.054901123046875 +101180 -0.087921142578125 +101181 -0.19085693359375 +101182 -0.126129150390625 +101183 -0.28570556640625 +101184 -0.148101806640625 +101185 -0.339263916015625 +101186 -0.163055419921875 +101187 -0.3775634765625 +101188 -0.187225341796875 +101189 -0.445709228515625 +101190 -0.217559814453125 +101191 -0.535064697265625 +101192 -0.248260498046875 +101193 -0.629058837890625 +101194 -0.2686767578125 +101195 -0.697601318359375 +101196 -0.26580810546875 +101197 -0.70391845703125 +101198 -0.23797607421875 +101199 -0.6424560546875 +101200 -0.1776123046875 +101201 -0.491241455078125 +101202 -0.090606689453125 +101203 -0.265716552734375 +101204 0.00189208984375 +101205 -0.023712158203125 +101206 0.08770751953125 +101207 0.201751708984375 +101208 0.154052734375 +101209 0.375823974609375 +101210 0.1959228515625 +101211 0.485076904296875 +101212 0.227386474609375 +101213 0.56884765625 +101214 0.25115966796875 +101215 0.634765625 +101216 0.2509765625 +101217 0.63763427734375 +101218 0.22283935546875 +101219 0.5660400390625 +101220 0.185638427734375 +101221 0.4720458984375 +101222 0.158050537109375 +101223 0.40692138671875 +101224 0.1429443359375 +101225 0.3778076171875 +101226 0.137786865234375 +101227 0.376953125 +101228 0.13116455078125 +101229 0.371978759765625 +101230 0.10540771484375 +101231 0.313140869140625 +101232 0.055023193359375 +101233 0.184417724609375 +101234 -0.0106201171875 +101235 0.011199951171875 +101236 -0.078582763671875 +101237 -0.171051025390625 +101238 -0.139801025390625 +101239 -0.33740234375 +101240 -0.18853759765625 +101241 -0.47198486328125 +101242 -0.2196044921875 +101243 -0.560394287109375 +101244 -0.225128173828125 +101245 -0.58056640625 +101246 -0.210662841796875 +101247 -0.54754638671875 +101248 -0.193389892578125 +101249 -0.508575439453125 +101250 -0.1719970703125 +101251 -0.459503173828125 +101252 -0.144561767578125 +101253 -0.394378662109375 +101254 -0.125457763671875 +101255 -0.35260009765625 +101256 -0.106842041015625 +101257 -0.31170654296875 +101258 -0.06219482421875 +101259 -0.197418212890625 +101260 0.0089111328125 +101261 -0.007965087890625 +101262 0.088653564453125 +101263 0.207489013671875 +101264 0.16259765625 +101265 0.409210205078125 +101266 0.2216796875 +101267 0.57208251953125 +101268 0.25506591796875 +101269 0.66595458984375 +101270 0.251251220703125 +101271 0.65875244140625 +101272 0.2164306640625 +101273 0.56744384765625 +101274 0.164886474609375 +101275 0.431396484375 +101276 0.112579345703125 +101277 0.29443359375 +101278 0.069000244140625 +101279 0.182464599609375 +101280 0.02288818359375 +101281 0.06365966796875 +101282 -0.03057861328125 +101283 -0.075958251953125 +101284 -0.0743408203125 +101285 -0.189422607421875 +101286 -0.10650634765625 +101287 -0.271942138671875 +101288 -0.1337890625 +101289 -0.342529296875 +101290 -0.142822265625 +101291 -0.364166259765625 +101292 -0.130096435546875 +101293 -0.327239990234375 +101294 -0.111846923828125 +101295 -0.2769775390625 +101296 -0.1026611328125 +101297 -0.253692626953125 +101298 -0.097625732421875 +101299 -0.24365234375 +101300 -0.079376220703125 +101301 -0.1983642578125 +101302 -0.0474853515625 +101303 -0.116241455078125 +101304 -0.01629638671875 +101305 -0.036834716796875 +101306 0.01220703125 +101307 0.034881591796875 +101308 0.035125732421875 +101309 0.09124755859375 +101310 0.043914794921875 +101311 0.10888671875 +101312 0.052001953125 +101313 0.125518798828125 +101314 0.065277099609375 +101315 0.15771484375 +101316 0.0738525390625 +101317 0.17828369140625 +101318 0.071868896484375 +101319 0.17108154296875 +101320 0.057098388671875 +101321 0.129974365234375 +101322 0.039459228515625 +101323 0.082427978515625 +101324 0.018707275390625 +101325 0.027679443359375 +101326 -0.016357421875 +101327 -0.065643310546875 +101328 -0.0518798828125 +101329 -0.15936279296875 +101330 -0.0732421875 +101331 -0.21307373046875 +101332 -0.0831298828125 +101333 -0.234649658203125 +101334 -0.072845458984375 +101335 -0.2001953125 +101336 -0.045684814453125 +101337 -0.119171142578125 +101338 -0.013458251953125 +101339 -0.024749755859375 +101340 0.024871826171875 +101341 0.085784912109375 +101342 0.0570068359375 +101343 0.178131103515625 +101344 0.06976318359375 +101345 0.215576171875 +101346 0.0679931640625 +101347 0.211456298828125 +101348 0.05511474609375 +101349 0.17523193359375 +101350 0.038970947265625 +101351 0.128753662109375 +101352 0.030303955078125 +101353 0.1019287109375 +101354 0.021697998046875 +101355 0.0743408203125 +101356 0.012054443359375 +101357 0.04327392578125 +101358 0.01190185546875 +101359 0.038177490234375 +101360 0.027374267578125 +101361 0.076263427734375 +101362 0.052398681640625 +101363 0.14105224609375 +101364 0.070281982421875 +101365 0.186431884765625 +101366 0.07244873046875 +101367 0.188812255859375 +101368 0.055572509765625 +101369 0.1390380859375 +101370 0.02130126953125 +101371 0.041778564453125 +101372 -0.021942138671875 +101373 -0.079437255859375 +101374 -0.072296142578125 +101375 -0.219390869140625 +101376 -0.125701904296875 +101377 -0.367828369140625 +101378 -0.170928955078125 +101379 -0.494873046875 +101380 -0.192962646484375 +101381 -0.556243896484375 +101382 -0.1778564453125 +101383 -0.508697509765625 +101384 -0.133514404296875 +101385 -0.3756103515625 +101386 -0.080535888671875 +101387 -0.218902587890625 +101388 -0.027435302734375 +101389 -0.063751220703125 +101390 0.02606201171875 +101391 0.091552734375 +101392 0.07611083984375 +101393 0.23602294921875 +101394 0.113800048828125 +101395 0.342987060546875 +101396 0.13330078125 +101397 0.39520263671875 +101398 0.133392333984375 +101399 0.389373779296875 +101400 0.11358642578125 +101401 0.324249267578125 +101402 0.081787109375 +101403 0.224090576171875 +101404 0.049560546875 +101405 0.124267578125 +101406 0.02093505859375 +101407 0.037078857421875 +101408 0.0048828125 +101409 -0.010101318359375 +101410 0.000732421875 +101411 -0.019439697265625 +101412 -0.0018310546875 +101413 -0.022796630859375 +101414 0.003387451171875 +101415 -0.001556396484375 +101416 0.02044677734375 +101417 0.056304931640625 +101418 0.035003662109375 +101419 0.106719970703125 +101420 0.02984619140625 +101421 0.096893310546875 +101422 0.01031494140625 +101423 0.042694091796875 +101424 -0.011077880859375 +101425 -0.018035888671875 +101426 -0.031158447265625 +101427 -0.07586669921875 +101428 -0.046173095703125 +101429 -0.11944580078125 +101430 -0.0596923828125 +101431 -0.15972900390625 +101432 -0.073638916015625 +101433 -0.202606201171875 +101434 -0.088165283203125 +101435 -0.24859619140625 +101436 -0.10577392578125 +101437 -0.30517578125 +101438 -0.123199462890625 +101439 -0.36212158203125 +101440 -0.131317138671875 +101441 -0.39141845703125 +101442 -0.117828369140625 +101443 -0.35528564453125 +101444 -0.08160400390625 +101445 -0.249969482421875 +101446 -0.028472900390625 +101447 -0.092864990234375 +101448 0.032623291015625 +101449 0.08905029296875 +101450 0.081756591796875 +101451 0.2352294921875 +101452 0.110076904296875 +101453 0.318817138671875 +101454 0.12371826171875 +101455 0.358642578125 +101456 0.120391845703125 +101457 0.347747802734375 +101458 0.09991455078125 +101459 0.28564453125 +101460 0.0789794921875 +101461 0.223175048828125 +101462 0.069549560546875 +101463 0.196746826171875 +101464 0.06298828125 +101465 0.179840087890625 +101466 0.053802490234375 +101467 0.155548095703125 +101468 0.051055908203125 +101469 0.151214599609375 +101470 0.05157470703125 +101471 0.156951904296875 +101472 0.041961669921875 +101473 0.13177490234375 +101474 0.030548095703125 +101475 0.100799560546875 +101476 0.02496337890625 +101477 0.087127685546875 +101478 0.013519287109375 +101479 0.05487060546875 +101480 -0.00799560546875 +101481 -0.009002685546875 +101482 -0.039398193359375 +101483 -0.10400390625 +101484 -0.0804443359375 +101485 -0.229400634765625 +101486 -0.121429443359375 +101487 -0.35552978515625 +101488 -0.14910888671875 +101489 -0.441925048828125 +101490 -0.15869140625 +101491 -0.473846435546875 +101492 -0.1546630859375 +101493 -0.464813232421875 +101494 -0.13848876953125 +101495 -0.419097900390625 +101496 -0.109466552734375 +101497 -0.334320068359375 +101498 -0.0733642578125 +101499 -0.227935791015625 +101500 -0.0379638671875 +101501 -0.12347412109375 +101502 -0.00555419921875 +101503 -0.02764892578125 +101504 0.029754638671875 +101505 0.077667236328125 +101506 0.074737548828125 +101507 0.2132568359375 +101508 0.132568359375 +101509 0.38885498046875 +101510 0.196136474609375 +101511 0.582794189453125 +101512 0.24542236328125 +101513 0.734039306640625 +101514 0.266510009765625 +101515 0.800140380859375 +101516 0.258544921875 +101517 0.7783203125 +101518 0.220458984375 +101519 0.6651611328125 +101520 0.1519775390625 +101521 0.45965576171875 +101522 0.0654296875 +101523 0.199188232421875 +101524 -0.017608642578125 +101525 -0.050689697265625 +101526 -0.078338623046875 +101527 -0.23297119140625 +101528 -0.11102294921875 +101529 -0.33013916015625 +101530 -0.12420654296875 +101531 -0.368408203125 +101532 -0.1280517578125 +101533 -0.378936767578125 +101534 -0.127593994140625 +101535 -0.376983642578125 +101536 -0.128448486328125 +101537 -0.37969970703125 +101538 -0.132080078125 +101539 -0.391510009765625 +101540 -0.129608154296875 +101541 -0.385345458984375 +101542 -0.11474609375 +101543 -0.3419189453125 +101544 -0.094635009765625 +101545 -0.28289794921875 +101546 -0.08349609375 +101547 -0.251617431640625 +101548 -0.087310791015625 +101549 -0.266143798828125 +101550 -0.0887451171875 +101551 -0.273345947265625 +101552 -0.069305419921875 +101553 -0.216796875 +101554 -0.039459228515625 +101555 -0.128265380859375 +101556 -0.01904296875 +101557 -0.068145751953125 +101558 -0.01031494140625 +101559 -0.0430908203125 +101560 -0.003875732421875 +101561 -0.024444580078125 +101562 0.01104736328125 +101563 0.020721435546875 +101564 0.044921875 +101565 0.124481201171875 +101566 0.088287353515625 +101567 0.25787353515625 +101568 0.127471923828125 +101569 0.379119873046875 +101570 0.1597900390625 +101571 0.47991943359375 +101572 0.174774169921875 +101573 0.5281982421875 +101574 0.16827392578125 +101575 0.511138916015625 +101576 0.14935302734375 +101577 0.456207275390625 +101578 0.13250732421875 +101579 0.407470703125 +101580 0.12396240234375 +101581 0.383758544921875 +101582 0.114471435546875 +101583 0.35687255859375 +101584 0.099151611328125 +101585 0.31182861328125 +101586 0.078765869140625 +101587 0.250885009765625 +101588 0.050506591796875 +101589 0.1654052734375 +101590 0.0078125 +101591 0.035247802734375 +101592 -0.05010986328125 +101593 -0.142059326171875 +101594 -0.1131591796875 +101595 -0.33563232421875 +101596 -0.17779541015625 +101597 -0.5345458984375 +101598 -0.23846435546875 +101599 -0.72186279296875 +101600 -0.275238037109375 +101601 -0.836669921875 +101602 -0.272979736328125 +101603 -0.8326416015625 +101604 -0.238250732421875 +101605 -0.7296142578125 +101606 -0.18914794921875 +101607 -0.582550048828125 +101608 -0.14166259765625 +101609 -0.440093994140625 +101610 -0.10308837890625 +101611 -0.324310302734375 +101612 -0.0623779296875 +101613 -0.20147705078125 +101614 -0.01068115234375 +101615 -0.044647216796875 +101616 0.038116455078125 +101617 0.103973388671875 +101618 0.070220947265625 +101619 0.202392578125 +101620 0.090179443359375 +101621 0.264495849609375 +101622 0.113983154296875 +101623 0.338897705078125 +101624 0.14764404296875 +101625 0.443817138671875 +101626 0.17999267578125 +101627 0.545074462890625 +101628 0.202789306640625 +101629 0.6173095703125 +101630 0.21343994140625 +101631 0.6524658203125 +101632 0.2158203125 +101633 0.66339111328125 +101634 0.211822509765625 +101635 0.6561279296875 +101636 0.194244384765625 +101637 0.606781005859375 +101638 0.15911865234375 +101639 0.501190185546875 +101640 0.11065673828125 +101641 0.352783203125 +101642 0.053619384765625 +101643 0.176544189453125 +101644 -0.013824462890625 +101645 -0.034820556640625 +101646 -0.08453369140625 +101647 -0.258209228515625 +101648 -0.14312744140625 +101649 -0.44244384765625 +101650 -0.18572998046875 +101651 -0.5753173828125 +101652 -0.210784912109375 +101653 -0.65203857421875 +101654 -0.209014892578125 +101655 -0.641632080078125 +101656 -0.18572998046875 +101657 -0.562164306640625 +101658 -0.154083251953125 +101659 -0.458038330078125 +101660 -0.12042236328125 +101661 -0.350555419921875 +101662 -0.091064453125 +101663 -0.260528564453125 +101664 -0.067413330078125 +101665 -0.192108154296875 +101666 -0.04864501953125 +101667 -0.141937255859375 +101668 -0.03265380859375 +101669 -0.1021728515625 +101670 -0.016754150390625 +101671 -0.062896728515625 +101672 0.00238037109375 +101673 -0.011932373046875 +101674 0.02813720703125 +101675 0.062835693359375 +101676 0.05657958984375 +101677 0.148712158203125 +101678 0.086334228515625 +101679 0.241729736328125 +101680 0.119476318359375 +101681 0.34912109375 +101682 0.151947021484375 +101683 0.457305908203125 +101684 0.177093505859375 +101685 0.54388427734375 +101686 0.184326171875 +101687 0.5728759765625 +101688 0.16259765625 +101689 0.506591796875 +101690 0.1138916015625 +101691 0.351226806640625 +101692 0.05010986328125 +101693 0.146514892578125 +101694 -0.013031005859375 +101695 -0.05523681640625 +101696 -0.064178466796875 +101697 -0.21624755859375 +101698 -0.102630615234375 +101699 -0.334930419921875 +101700 -0.12579345703125 +101701 -0.402984619140625 +101702 -0.1396484375 +101703 -0.4412841796875 +101704 -0.15771484375 +101705 -0.49578857421875 +101706 -0.17803955078125 +101707 -0.5601806640625 +101708 -0.190582275390625 +101709 -0.600738525390625 +101710 -0.18548583984375 +101711 -0.584228515625 +101712 -0.15350341796875 +101713 -0.47930908203125 +101714 -0.0927734375 +101715 -0.27935791015625 +101716 -0.010650634765625 +101717 -0.0089111328125 +101718 0.073974609375 +101719 0.268798828125 +101720 0.139984130859375 +101721 0.482818603515625 +101722 0.178497314453125 +101723 0.60369873046875 +101724 0.194976806640625 +101725 0.650421142578125 +101726 0.201416015625 +101727 0.66400146484375 +101728 0.19683837890625 +101729 0.6414794921875 +101730 0.178070068359375 +101731 0.572540283203125 +101732 0.15716552734375 +101733 0.498138427734375 +101734 0.140380859375 +101735 0.439453125 +101736 0.1214599609375 +101737 0.375518798828125 +101738 0.09100341796875 +101739 0.274505615234375 +101740 0.0408935546875 +101741 0.1087646484375 +101742 -0.022186279296875 +101743 -0.099395751953125 +101744 -0.0887451171875 +101745 -0.3182373046875 +101746 -0.1590576171875 +101747 -0.5489501953125 +101748 -0.22772216796875 +101749 -0.7738037109375 +101750 -0.2789306640625 +101751 -0.86383056640625 +101752 -0.302764892578125 +101753 -0.870391845703125 +101754 -0.304351806640625 +101755 -0.86895751953125 +101756 -0.287506103515625 +101757 -0.861053466796875 +101758 -0.247039794921875 +101759 -0.765869140625 +101760 -0.179595947265625 +101761 -0.5301513671875 +101762 -0.087249755859375 +101763 -0.214691162109375 +101764 0.017242431640625 +101765 0.137359619140625 +101766 0.118682861328125 +101767 0.474822998046875 +101768 0.206512451171875 +101769 0.76239013671875 +101770 0.27264404296875 +101771 0.867462158203125 +101772 0.317138671875 +101773 0.870361328125 +101774 0.33648681640625 +101775 0.86480712890625 +101776 0.3321533203125 +101777 0.831817626953125 +101778 0.311279296875 +101779 0.677581787109375 +101780 0.2755126953125 +101781 0.495880126953125 +101782 0.23028564453125 +101783 0.30767822265625 +101784 0.17620849609375 +101785 0.116180419921875 +101786 0.103851318359375 +101787 -0.110748291015625 +101788 0.0111083984375 +101789 -0.381805419921875 +101790 -0.08929443359375 +101791 -0.6572265625 +101792 -0.179595947265625 +101793 -0.857421875 +101794 -0.247100830078125 +101795 -0.870391845703125 +101796 -0.289642333984375 +101797 -0.870391845703125 +101798 -0.315155029296875 +101799 -0.86444091796875 +101800 -0.3341064453125 +101801 -0.85723876953125 +101802 -0.34100341796875 +101803 -0.790008544921875 +101804 -0.3197021484375 +101805 -0.62847900390625 +101806 -0.26922607421875 +101807 -0.3956298828125 +101808 -0.199249267578125 +101809 -0.126708984375 +101810 -0.1177978515625 +101811 0.150115966796875 +101812 -0.0283203125 +101813 0.424041748046875 +101814 0.061187744140625 +101815 0.670623779296875 +101816 0.1392822265625 +101817 0.854522705078125 +101818 0.200714111328125 +101819 0.866485595703125 +101820 0.240936279296875 +101821 0.86920166015625 +101822 0.2652587890625 +101823 0.8653564453125 +101824 0.277618408203125 +101825 0.857147216796875 +101826 0.277099609375 +101827 0.766845703125 +101828 0.265167236328125 +101829 0.628509521484375 +101830 0.239776611328125 +101831 0.462127685546875 +101832 0.208526611328125 +101833 0.297210693359375 +101834 0.175018310546875 +101835 0.14862060546875 +101836 0.1324462890625 +101837 -0.00537109375 +101838 0.0830078125 +101839 -0.15753173828125 +101840 0.025634765625 +101841 -0.31304931640625 +101842 -0.0438232421875 +101843 -0.48876953125 +101844 -0.111480712890625 +101845 -0.6416015625 +101846 -0.16998291015625 +101847 -0.751373291015625 +101848 -0.22613525390625 +101849 -0.84619140625 +101850 -0.275543212890625 +101851 -0.861297607421875 +101852 -0.308380126953125 +101853 -0.863250732421875 +101854 -0.31524658203125 +101855 -0.856597900390625 +101856 -0.2996826171875 +101857 -0.7498779296875 +101858 -0.278778076171875 +101859 -0.624542236328125 +101860 -0.246002197265625 +101861 -0.47808837890625 +101862 -0.184051513671875 +101863 -0.253387451171875 +101864 -0.106414794921875 +101865 0.003692626953125 +101866 -0.0333251953125 +101867 0.2257080078125 +101868 0.038909912109375 +101869 0.427154541015625 +101870 0.119873046875 +101871 0.643218994140625 +101872 0.206695556640625 +101873 0.855926513671875 +101874 0.282196044921875 +101875 0.870361328125 +101876 0.3316650390625 +101877 0.870361328125 +101878 0.357208251953125 +101879 0.862762451171875 +101880 0.35791015625 +101881 0.79669189453125 +101882 0.330963134765625 +101883 0.595794677734375 +101884 0.28497314453125 +101885 0.362152099609375 +101886 0.22821044921875 +101887 0.1270751953125 +101888 0.166351318359375 +101889 -0.086944580078125 +101890 0.0997314453125 +101891 -0.2784423828125 +101892 0.01947021484375 +101893 -0.484832763671875 +101894 -0.078582763671875 +101895 -0.729583740234375 +101896 -0.1802978515625 +101897 -0.86688232421875 +101898 -0.268310546875 +101899 -0.870391845703125 +101900 -0.3408203125 +101901 -0.86859130859375 +101902 -0.3968505859375 +101903 -0.86279296875 +101904 -0.426727294921875 +101905 -0.817962646484375 +101906 -0.418426513671875 +101907 -0.6116943359375 +101908 -0.37017822265625 +101909 -0.3128662109375 +101910 -0.291107177734375 +101911 0.039398193359375 +101912 -0.186798095703125 +101913 0.422821044921875 +101914 -0.066497802734375 +101915 0.805145263671875 +101916 0.051300048828125 +101917 0.870361328125 +101918 0.15106201171875 +101919 0.870361328125 +101920 0.2291259765625 +101921 0.860015869140625 +101922 0.282958984375 +101923 0.727935791015625 +101924 0.310638427734375 +101925 0.48114013671875 +101926 0.318145751953125 +101927 0.2059326171875 +101928 0.3111572265625 +101929 -0.06103515625 +101930 0.292083740234375 +101931 -0.29913330078125 +101932 0.257049560546875 +101933 -0.516204833984375 +101934 0.202056884765625 +101935 -0.7252197265625 +101936 0.13385009765625 +101937 -0.85980224609375 +101938 0.061798095703125 +101939 -0.870391845703125 +101940 -0.005889892578125 +101941 -0.870391845703125 +101942 -0.055877685546875 +101943 -0.858062744140625 +101944 -0.0865478515625 +101945 -0.673004150390625 +101946 -0.111236572265625 +101947 -0.42694091796875 +101948 -0.141143798828125 +101949 -0.2100830078125 +101950 -0.17523193359375 +101951 -0.0362548828125 +101952 -0.205413818359375 +101953 0.10943603515625 +101954 -0.226043701171875 +101955 0.23516845703125 +101956 -0.225982666015625 +101957 0.373687744140625 +101958 -0.2056884765625 +101959 0.517791748046875 +101960 -0.181793212890625 +101961 0.602783203125 +101962 -0.153076171875 +101963 0.635711669921875 +101964 -0.1109619140625 +101965 0.655181884765625 +101966 -0.05841064453125 +101967 0.65948486328125 +101968 0.00201416015625 +101969 0.651275634765625 +101970 0.06341552734375 +101971 0.61846923828125 +101972 0.115509033203125 +101973 0.53753662109375 +101974 0.153076171875 +101975 0.404144287109375 +101976 0.173095703125 +101977 0.22186279296875 +101978 0.175537109375 +101979 0.003997802734375 +101980 0.16485595703125 +101981 -0.22100830078125 +101982 0.14630126953125 +101983 -0.42449951171875 +101984 0.125335693359375 +101985 -0.579833984375 +101986 0.113250732421875 +101987 -0.641876220703125 +101988 0.108367919921875 +101989 -0.6177978515625 +101990 0.09381103515625 +101991 -0.575531005859375 +101992 0.06842041015625 +101993 -0.526336669921875 +101994 0.04620361328125 +101995 -0.42645263671875 +101996 0.03472900390625 +101997 -0.2581787109375 +101998 0.02484130859375 +101999 -0.068695068359375 +102000 0.006805419921875 +102001 0.09222412109375 +102002 -0.0140380859375 +102003 0.232147216796875 +102004 -0.034637451171875 +102005 0.3509521484375 +102006 -0.062530517578125 +102007 0.410064697265625 +102008 -0.105224609375 +102009 0.372955322265625 +102010 -0.157073974609375 +102011 0.2554931640625 +102012 -0.2042236328125 +102013 0.10711669921875 +102014 -0.241485595703125 +102015 -0.052886962890625 +102016 -0.2593994140625 +102017 -0.186279296875 +102018 -0.243438720703125 +102019 -0.23291015625 +102020 -0.1998291015625 +102021 -0.209442138671875 +102022 -0.146270751953125 +102023 -0.174163818359375 +102024 -0.085296630859375 +102025 -0.126739501953125 +102026 -0.014617919921875 +102027 -0.048126220703125 +102028 0.05792236328125 +102029 0.0426025390625 +102030 0.11968994140625 +102031 0.10748291015625 +102032 0.166900634765625 +102033 0.1409912109375 +102034 0.211883544921875 +102035 0.19708251953125 +102036 0.252685546875 +102037 0.273651123046875 +102038 0.27447509765625 +102039 0.31768798828125 +102040 0.2801513671875 +102041 0.341094970703125 +102042 0.27642822265625 +102043 0.368011474609375 +102044 0.25732421875 +102045 0.37249755859375 +102046 0.209991455078125 +102047 0.30072021484375 +102048 0.135955810546875 +102049 0.1517333984375 +102050 0.053070068359375 +102051 -0.01470947265625 +102052 -0.03369140625 +102053 -0.1883544921875 +102054 -0.122955322265625 +102055 -0.372711181640625 +102056 -0.198333740234375 +102057 -0.51397705078125 +102058 -0.24713134765625 +102059 -0.57177734375 +102060 -0.26593017578125 +102061 -0.53948974609375 +102062 -0.258148193359375 +102063 -0.43511962890625 +102064 -0.232879638671875 +102065 -0.2962646484375 +102066 -0.199798583984375 +102067 -0.161102294921875 +102068 -0.162689208984375 +102069 -0.0435791015625 +102070 -0.121063232421875 +102071 0.060394287109375 +102072 -0.079681396484375 +102073 0.13665771484375 +102074 -0.04388427734375 +102075 0.170135498046875 +102076 -0.0140380859375 +102077 0.16552734375 +102078 0.017120361328125 +102079 0.15728759765625 +102080 0.049102783203125 +102081 0.150787353515625 +102082 0.07373046875 +102083 0.12200927734375 +102084 0.091705322265625 +102085 0.080108642578125 +102086 0.108428955078125 +102087 0.05126953125 +102088 0.129974365234375 +102089 0.062896728515625 +102090 0.14959716796875 +102091 0.09271240234375 +102092 0.154266357421875 +102093 0.092987060546875 +102094 0.1478271484375 +102095 0.07855224609375 +102096 0.13458251953125 +102097 0.06427001953125 +102098 0.111175537109375 +102099 0.0347900390625 +102100 0.078125 +102101 -0.01171875 +102102 0.041839599609375 +102103 -0.056060791015625 +102104 0.0150146484375 +102105 -0.055511474609375 +102106 -0.000885009765625 +102107 -0.010467529296875 +102108 -0.0185546875 +102109 0.02508544921875 +102110 -0.04327392578125 +102111 0.025665283203125 +102112 -0.066864013671875 +102113 0.017333984375 +102114 -0.087799072265625 +102115 0.00189208984375 +102116 -0.10821533203125 +102117 -0.03173828125 +102118 -0.12445068359375 +102119 -0.071502685546875 +102120 -0.14111328125 +102121 -0.13543701171875 +102122 -0.157470703125 +102123 -0.219970703125 +102124 -0.16748046875 +102125 -0.300506591796875 +102126 -0.171722412109375 +102127 -0.376312255859375 +102128 -0.1629638671875 +102129 -0.416107177734375 +102130 -0.12945556640625 +102131 -0.371124267578125 +102132 -0.072662353515625 +102133 -0.242279052734375 +102134 -0.004486083984375 +102135 -0.069732666015625 +102136 0.06829833984375 +102137 0.125640869140625 +102138 0.136322021484375 +102139 0.31268310546875 +102140 0.189056396484375 +102141 0.45501708984375 +102142 0.226348876953125 +102143 0.554779052734375 +102144 0.247161865234375 +102145 0.61065673828125 +102146 0.24835205078125 +102147 0.610931396484375 +102148 0.224212646484375 +102149 0.531463623046875 +102150 0.179229736328125 +102151 0.3883056640625 +102152 0.12738037109375 +102153 0.23468017578125 +102154 0.07574462890625 +102155 0.095245361328125 +102156 0.0318603515625 +102157 -0.00396728515625 +102158 0.000396728515625 +102159 -0.04852294921875 +102160 -0.021636962890625 +102161 -0.055145263671875 +102162 -0.046112060546875 +102163 -0.0758056640625 +102164 -0.079071044921875 +102165 -0.138702392578125 +102166 -0.1109619140625 +102167 -0.209197998046875 +102168 -0.14154052734375 +102169 -0.289031982421875 +102170 -0.170501708984375 +102171 -0.37884521484375 +102172 -0.1920166015625 +102173 -0.456329345703125 +102174 -0.204864501953125 +102175 -0.51641845703125 +102176 -0.199310302734375 +102177 -0.519287109375 +102178 -0.174163818359375 +102179 -0.458251953125 +102180 -0.142913818359375 +102181 -0.384796142578125 +102182 -0.112548828125 +102183 -0.323699951171875 +102184 -0.082489013671875 +102185 -0.269287109375 +102186 -0.047149658203125 +102187 -0.1951904296875 +102188 -0.007080078125 +102189 -0.100006103515625 +102190 0.030120849609375 +102191 -0.01055908203125 +102192 0.07122802734375 +102193 0.1033935546875 +102194 0.117431640625 +102195 0.24908447265625 +102196 0.15496826171875 +102197 0.373199462890625 +102198 0.17913818359375 +102199 0.45806884765625 +102200 0.191802978515625 +102201 0.511474609375 +102202 0.20111083984375 +102203 0.565399169921875 +102204 0.205291748046875 +102205 0.61138916015625 +102206 0.189910888671875 +102207 0.5897216796875 +102208 0.153106689453125 +102209 0.4906005859375 +102210 0.100006103515625 +102211 0.33148193359375 +102212 0.04022216796875 +102213 0.147796630859375 +102214 -0.015045166015625 +102215 -0.01873779296875 +102216 -0.058074951171875 +102217 -0.140289306640625 +102218 -0.082000732421875 +102219 -0.191986083984375 +102220 -0.088897705078125 +102221 -0.184295654296875 +102222 -0.089508056640625 +102223 -0.161834716796875 +102224 -0.094024658203125 +102225 -0.166595458984375 +102226 -0.1011962890625 +102227 -0.19390869140625 +102228 -0.10626220703125 +102229 -0.22442626953125 +102230 -0.114837646484375 +102231 -0.279754638671875 +102232 -0.1220703125 +102233 -0.3389892578125 +102234 -0.11651611328125 +102235 -0.3543701171875 +102236 -0.10430908203125 +102237 -0.348175048828125 +102238 -0.087432861328125 +102239 -0.32598876953125 +102240 -0.059112548828125 +102241 -0.2581787109375 +102242 -0.01873779296875 +102243 -0.139801025390625 +102244 0.029449462890625 +102245 0.014617919921875 +102246 0.069793701171875 +102247 0.144378662109375 +102248 0.09478759765625 +102249 0.221038818359375 +102250 0.110687255859375 +102251 0.27069091796875 +102252 0.117584228515625 +102253 0.294036865234375 +102254 0.12066650390625 +102255 0.311767578125 +102256 0.123809814453125 +102257 0.339141845703125 +102258 0.123077392578125 +102259 0.360260009765625 +102260 0.115264892578125 +102261 0.360504150390625 +102262 0.093658447265625 +102263 0.308380126953125 +102264 0.0537109375 +102265 0.18170166015625 +102266 0.001739501953125 +102267 0.0047607421875 +102268 -0.05072021484375 +102269 -0.17559814453125 +102270 -0.0926513671875 +102271 -0.3143310546875 +102272 -0.113433837890625 +102273 -0.36785888671875 +102274 -0.118743896484375 +102275 -0.36248779296875 +102276 -0.1187744140625 +102277 -0.343536376953125 +102278 -0.111236572265625 +102279 -0.3018798828125 +102280 -0.09466552734375 +102281 -0.231414794921875 +102282 -0.0657958984375 +102283 -0.117645263671875 +102284 -0.032318115234375 +102285 0.007049560546875 +102286 -0.007232666015625 +102287 0.087982177734375 +102288 0.012359619140625 +102289 0.13946533203125 +102290 0.028961181640625 +102291 0.17425537109375 +102292 0.041107177734375 +102293 0.188201904296875 +102294 0.04595947265625 +102295 0.171234130859375 +102296 0.041900634765625 +102297 0.118438720703125 +102298 0.034881591796875 +102299 0.05706787109375 +102300 0.02496337890625 +102301 -0.010711669921875 +102302 0.0103759765625 +102303 -0.0914306640625 +102304 -0.00372314453125 +102305 -0.162322998046875 +102306 -0.0107421875 +102307 -0.194549560546875 +102308 -0.001678466796875 +102309 -0.1492919921875 +102310 0.02471923828125 +102311 -0.02166748046875 +102312 0.053802490234375 +102313 0.124053955078125 +102314 0.068023681640625 +102315 0.211151123046875 +102316 0.067962646484375 +102317 0.240447998046875 +102318 0.061065673828125 +102319 0.242218017578125 +102320 0.049896240234375 +102321 0.2257080078125 +102322 0.035614013671875 +102323 0.194366455078125 +102324 0.011016845703125 +102325 0.115509033203125 +102326 -0.01800537109375 +102327 0.0128173828125 +102328 -0.037322998046875 +102329 -0.053802490234375 +102330 -0.0528564453125 +102331 -0.110626220703125 +102332 -0.074249267578125 +102333 -0.199493408203125 +102334 -0.095458984375 +102335 -0.29437255859375 +102336 -0.101959228515625 +102337 -0.33221435546875 +102338 -0.086181640625 +102339 -0.27972412109375 +102340 -0.059600830078125 +102341 -0.185333251953125 +102342 -0.0408935546875 +102343 -0.128204345703125 +102344 -0.032073974609375 +102345 -0.115692138671875 +102346 -0.02618408203125 +102347 -0.116455078125 +102348 -0.01788330078125 +102349 -0.105926513671875 +102350 -0.00048828125 +102351 -0.053955078125 +102352 0.02789306640625 +102353 0.048797607421875 +102354 0.05657958984375 +102355 0.157318115234375 +102356 0.071563720703125 +102357 0.212005615234375 +102358 0.074066162109375 +102359 0.218475341796875 +102360 0.078125 +102361 0.23724365234375 +102362 0.092376708984375 +102363 0.30535888671875 +102364 0.1072998046875 +102365 0.38128662109375 +102366 0.1090087890625 +102367 0.404449462890625 +102368 0.102294921875 +102369 0.3944091796875 +102370 0.0960693359375 +102371 0.3885498046875 +102372 0.08502197265625 +102373 0.362640380859375 +102374 0.0594482421875 +102375 0.27362060546875 +102376 0.018585205078125 +102377 0.11712646484375 +102378 -0.0252685546875 +102379 -0.054901123046875 +102380 -0.0599365234375 +102381 -0.19085693359375 +102382 -0.084075927734375 +102383 -0.28570556640625 +102384 -0.097564697265625 +102385 -0.339263916015625 +102386 -0.106414794921875 +102387 -0.3775634765625 +102388 -0.121124267578125 +102389 -0.445709228515625 +102390 -0.139801025390625 +102391 -0.535064697265625 +102392 -0.15875244140625 +102393 -0.629058837890625 +102394 -0.171142578125 +102395 -0.697601318359375 +102396 -0.168670654296875 +102397 -0.70391845703125 +102398 -0.150238037109375 +102399 -0.6424560546875 diff --git a/tests/cmdline/cmd_compile_only.py b/tests/cmdline/cmd_compile_only.py new file mode 100644 index 00000000000..89964c1b5bd --- /dev/null +++ b/tests/cmdline/cmd_compile_only.py @@ -0,0 +1,13 @@ +# cmdline: -X compile-only +# test compile-only functionality +print("This should not be printed") +x = 1 + 2 + + +def hello(): + return "world" + + +class TestClass: + def __init__(self): + self.value = 42 diff --git a/tests/cmdline/cmd_compile_only.py.exp b/tests/cmdline/cmd_compile_only.py.exp new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/cmdline/cmd_compile_only.py.exp @@ -0,0 +1 @@ + diff --git a/tests/cmdline/cmd_compile_only_error.py b/tests/cmdline/cmd_compile_only_error.py new file mode 100644 index 00000000000..326937a5c07 --- /dev/null +++ b/tests/cmdline/cmd_compile_only_error.py @@ -0,0 +1,6 @@ +# cmdline: -X compile-only +# test compile-only with syntax error +print("This should not be printed") +def broken_syntax( + # Missing closing parenthesis + return "error" diff --git a/tests/cmdline/cmd_compile_only_error.py.exp b/tests/cmdline/cmd_compile_only_error.py.exp new file mode 100644 index 00000000000..3911f71d624 --- /dev/null +++ b/tests/cmdline/cmd_compile_only_error.py.exp @@ -0,0 +1 @@ +CRASH \ No newline at end of file diff --git a/tests/cmdline/cmd_file_variable.py b/tests/cmdline/cmd_file_variable.py new file mode 100644 index 00000000000..6cac6744d90 --- /dev/null +++ b/tests/cmdline/cmd_file_variable.py @@ -0,0 +1,5 @@ +# Test that __file__ is set correctly for script execution +try: + print("__file__ =", __file__) +except NameError: + print("__file__ not defined") diff --git a/tests/cmdline/cmd_file_variable.py.exp b/tests/cmdline/cmd_file_variable.py.exp new file mode 100644 index 00000000000..6807569f662 --- /dev/null +++ b/tests/cmdline/cmd_file_variable.py.exp @@ -0,0 +1 @@ +__file__ = cmdline/cmd_file_variable.py diff --git a/tests/cmdline/cmd_module_atexit.py b/tests/cmdline/cmd_module_atexit.py new file mode 100644 index 00000000000..100bc112777 --- /dev/null +++ b/tests/cmdline/cmd_module_atexit.py @@ -0,0 +1,16 @@ +# cmdline: -m cmdline.cmd_module_atexit +# +# Test running as a module and using sys.atexit. + +import sys + +if not hasattr(sys, "atexit"): + print("SKIP") + raise SystemExit + +# Verify we ran as a module. +print(sys.argv) + +sys.atexit(lambda: print("done")) + +print("start") diff --git a/tests/cmdline/cmd_module_atexit.py.exp b/tests/cmdline/cmd_module_atexit.py.exp new file mode 100644 index 00000000000..2a0f756b1e7 --- /dev/null +++ b/tests/cmdline/cmd_module_atexit.py.exp @@ -0,0 +1,3 @@ +['cmdline.cmd_module_atexit', 'cmdline/cmd_module_atexit.py'] +start +done diff --git a/tests/cmdline/cmd_module_atexit_exc.py b/tests/cmdline/cmd_module_atexit_exc.py new file mode 100644 index 00000000000..88940a7741f --- /dev/null +++ b/tests/cmdline/cmd_module_atexit_exc.py @@ -0,0 +1,19 @@ +# cmdline: -m cmdline.cmd_module_atexit_exc +# +# Test running as a module and using sys.atexit, with script completion via sys.exit. + +import sys + +if not hasattr(sys, "atexit"): + print("SKIP") + raise SystemExit + +# Verify we ran as a module. +print(sys.argv) + +sys.atexit(lambda: print("done")) + +print("start") + +# This will raise SystemExit to finish the script, and atexit should still be run. +sys.exit(0) diff --git a/tests/cmdline/cmd_module_atexit_exc.py.exp b/tests/cmdline/cmd_module_atexit_exc.py.exp new file mode 100644 index 00000000000..6320d9d2d30 --- /dev/null +++ b/tests/cmdline/cmd_module_atexit_exc.py.exp @@ -0,0 +1,3 @@ +['cmdline.cmd_module_atexit_exc', 'cmdline/cmd_module_atexit_exc.py'] +start +done diff --git a/tests/cmdline/cmd_sys_exit_0.py b/tests/cmdline/cmd_sys_exit_0.py new file mode 100644 index 00000000000..1294b739e8f --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_0.py @@ -0,0 +1,5 @@ +# cmdline: +# test sys.exit(0) - success exit code +import sys + +sys.exit(0) diff --git a/tests/cmdline/cmd_sys_exit_0.py.exp b/tests/cmdline/cmd_sys_exit_0.py.exp new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_0.py.exp @@ -0,0 +1 @@ + diff --git a/tests/cmdline/cmd_sys_exit_error.py b/tests/cmdline/cmd_sys_exit_error.py new file mode 100644 index 00000000000..ecac15e94f1 --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_error.py @@ -0,0 +1,5 @@ +# cmdline: +# test sys.exit() functionality and exit codes +import sys + +sys.exit(123) diff --git a/tests/cmdline/cmd_sys_exit_error.py.exp b/tests/cmdline/cmd_sys_exit_error.py.exp new file mode 100644 index 00000000000..3911f71d624 --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_error.py.exp @@ -0,0 +1 @@ +CRASH \ No newline at end of file diff --git a/tests/cmdline/cmd_sys_exit_none.py b/tests/cmdline/cmd_sys_exit_none.py new file mode 100644 index 00000000000..66e19666589 --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_none.py @@ -0,0 +1,5 @@ +# cmdline: +# test sys.exit(None) - should exit with code 0 +import sys + +sys.exit(None) diff --git a/tests/cmdline/cmd_sys_exit_none.py.exp b/tests/cmdline/cmd_sys_exit_none.py.exp new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_none.py.exp @@ -0,0 +1 @@ + diff --git a/tests/cmdline/repl_autocomplete.py.exp b/tests/cmdline/repl_autocomplete.py.exp index 2e2397bb028..7840e52e8a4 100644 --- a/tests/cmdline/repl_autocomplete.py.exp +++ b/tests/cmdline/repl_autocomplete.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # tests for autocompletion >>> import sys >>> not_exist. @@ -11,4 +11,4 @@ Use \.\+ >>> i.lower('ABC') 'abc' >>> None. ->>> +>>> \$ diff --git a/tests/cmdline/repl_autocomplete_underscore.py b/tests/cmdline/repl_autocomplete_underscore.py new file mode 100644 index 00000000000..e685a7fe7ff --- /dev/null +++ b/tests/cmdline/repl_autocomplete_underscore.py @@ -0,0 +1,33 @@ +# Test REPL autocompletion filtering of underscore attributes + +# Start paste mode +{\x05} +class TestClass: + def __init__(self): + self.public_attr = 1 + self._private_attr = 2 + self.__very_private = 3 + + def public_method(self): + pass + + def _private_method(self): + pass + + @property + def public_property(self): + return 42 + + @property + def _private_property(self): + return 99 + +{\x04} +# Paste executed + +# Create an instance +obj = TestClass() + +# Test tab completion on the instance +# The tab character after `obj.` and 'a' below triggers the completions +obj.{\x09}{\x09}a{\x09} diff --git a/tests/cmdline/repl_autocomplete_underscore.py.exp b/tests/cmdline/repl_autocomplete_underscore.py.exp new file mode 100644 index 00000000000..98e6c2aeb05 --- /dev/null +++ b/tests/cmdline/repl_autocomplete_underscore.py.exp @@ -0,0 +1,41 @@ + +Adafruit CircuitPython \.\+ version +>>> # Test REPL autocompletion filtering of underscore attributes +>>> \$ +>>> # Start paste mode +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== class TestClass: +=== def __init__(self): +=== self.public_attr = 1 +=== self._private_attr = 2 +=== self.__very_private = 3 +=== \$ +=== def public_method(self): +=== pass +=== \$ +=== def _private_method(self): +=== pass +=== \$ +=== @property +=== def public_property(self): +=== return 42 +=== \$ +=== @property +=== def _private_property(self): +=== return 99 +=== \$ +=== \$ +>>> # Paste executed +>>> \$ +>>> # Create an instance +>>> obj = TestClass() +>>> \$ +>>> # Test tab completion on the instance +>>> # The tab character after `obj.` and 'a' below triggers the completions +>>> obj.public_ +public_attr public_method public_property +>>> obj.public_attr +1 +>>> \$ diff --git a/tests/cmdline/repl_autoindent.py.exp b/tests/cmdline/repl_autoindent.py.exp index 9ff83a92870..04f00686b20 100644 --- a/tests/cmdline/repl_autoindent.py.exp +++ b/tests/cmdline/repl_autoindent.py.exp @@ -1,22 +1,22 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # tests for autoindent >>> if 1: ... print(1) -... -... -... +... \$ +... \$ +... \$ 1 >>> if 0: ...  print(2) ... else: ... print(3) -... +... \$ 3 >>> if 0: ... print(4) ... else: ... print(5) -... +... \$ 5 ->>> +>>> \$ diff --git a/tests/cmdline/repl_basic.py.exp b/tests/cmdline/repl_basic.py.exp index 26442b64455..5bdcc9d6d32 100644 --- a/tests/cmdline/repl_basic.py.exp +++ b/tests/cmdline/repl_basic.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # basic REPL tests >>> print(1) 1 @@ -7,4 +7,4 @@ Use \.\+ 1 >>> 2 2 ->>> +>>> \$ diff --git a/tests/cmdline/repl_cont.py.exp b/tests/cmdline/repl_cont.py.exp index 6eed4a3e02c..41f2436ac18 100644 --- a/tests/cmdline/repl_cont.py.exp +++ b/tests/cmdline/repl_cont.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # check REPL allows to continue input >>> 1 \\\\ ... + 2 @@ -54,4 +54,4 @@ two >>> if1 = 2 >>> print(if1) 2 ->>> +>>> \$ diff --git a/tests/cmdline/repl_emacs_keys.py.exp b/tests/cmdline/repl_emacs_keys.py.exp index 2e8667a8e6c..4979f8bbfc3 100644 --- a/tests/cmdline/repl_emacs_keys.py.exp +++ b/tests/cmdline/repl_emacs_keys.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # REPL tests of GNU-ish readline navigation >>> # history buffer navigation >>> 1 @@ -16,4 +16,4 @@ Use \.\+ >>> t = 121 >>> \.\+ 'foobar' ->>> +>>> \$ diff --git a/tests/cmdline/repl_inspect.py.exp b/tests/cmdline/repl_inspect.py.exp index 8ece5ffc37f..30257f31aab 100644 --- a/tests/cmdline/repl_inspect.py.exp +++ b/tests/cmdline/repl_inspect.py.exp @@ -1,6 +1,6 @@ test -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # cmdline: -i -c print("test") >>> # -c option combined with -i option results in REPL ->>> +>>> \$ diff --git a/tests/cmdline/repl_lock.py b/tests/cmdline/repl_lock.py new file mode 100644 index 00000000000..77e2e932740 --- /dev/null +++ b/tests/cmdline/repl_lock.py @@ -0,0 +1,7 @@ +import micropython +micropython.heap_lock() +1+1 +micropython.heap_lock() +None # Cause the repl's line storage to be enlarged ---------------- +micropython.heap_lock() +raise SystemExit diff --git a/tests/cmdline/repl_lock.py.exp b/tests/cmdline/repl_lock.py.exp new file mode 100644 index 00000000000..e6d63fcf200 --- /dev/null +++ b/tests/cmdline/repl_lock.py.exp @@ -0,0 +1,10 @@ + +Adafruit CircuitPython \.\+ version +>>> import micropython +>>> micropython.heap_lock() +>>> 1+1 +2 +>>> micropython.heap_lock() +>>> None # Cause the repl's line storage to be enlarged ---------------- +>>> micropython.heap_lock() +>>> raise SystemExit diff --git a/tests/cmdline/repl_micropyinspect.py.exp b/tests/cmdline/repl_micropyinspect.py.exp index 3c9cbc030c0..36bef37c62c 100644 --- a/tests/cmdline/repl_micropyinspect.py.exp +++ b/tests/cmdline/repl_micropyinspect.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # cmdline: cmdline/repl_micropyinspect >>> # setting MICROPYINSPECT environment variable before program exit triggers REPL ->>> +>>> \$ diff --git a/tests/cmdline/repl_paste.py b/tests/cmdline/repl_paste.py new file mode 100644 index 00000000000..7cec450fce7 --- /dev/null +++ b/tests/cmdline/repl_paste.py @@ -0,0 +1,90 @@ +# Test REPL paste mode functionality + +# Basic paste mode with a simple function +{\x05} +def hello(): + print('Hello from paste mode!') +hello() +{\x04} + +# Paste mode with multiple indentation levels +{\x05} +def calculate(n): + if n > 0: + for i in range(n): + if i % 2 == 0: + print(f'Even: {i}') + else: + print(f'Odd: {i}') + else: + print('n must be positive') + +calculate(5) +{\x04} + +# Paste mode with blank lines +{\x05} +def function_with_blanks(): + print('First line') + + print('After blank line') + + + print('After two blank lines') + +function_with_blanks() +{\x04} + +# Paste mode with class definition and multiple methods +{\x05} +class TestClass: + def __init__(self, value): + self.value = value + + def display(self): + print(f'Value is: {self.value}') + + def double(self): + self.value *= 2 + return self.value + +obj = TestClass(21) +obj.display() +print(f'Doubled: {obj.double()}') +obj.display() +{\x04} + +# Paste mode with exception handling +{\x05} +try: + x = 1 / 0 +except ZeroDivisionError: + print('Caught division by zero') +finally: + print('Finally block executed') +{\x04} + +# Cancel paste mode with Ctrl-C +{\x05} +print('This should not execute') +{\x03} + +# Normal REPL still works after cancelled paste +print('Back to normal REPL') + +# Paste mode with syntax error +{\x05} +def bad_syntax(: + print('Missing parameter') +{\x04} + +# Paste mode with runtime error +{\x05} +def will_error(): + undefined_variable + +will_error() +{\x04} + +# Final test to show REPL is still functioning +1 + 2 + 3 diff --git a/tests/cmdline/repl_paste.py.exp b/tests/cmdline/repl_paste.py.exp new file mode 100644 index 00000000000..cc5ac2f0800 --- /dev/null +++ b/tests/cmdline/repl_paste.py.exp @@ -0,0 +1,133 @@ + +Adafruit CircuitPython \.\+ version +>>> # Test REPL paste mode functionality +>>> \$ +>>> # Basic paste mode with a simple function +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def hello(): +=== print('Hello from paste mode!') +=== hello() +=== \$ +Hello from paste mode! +>>> \$ +>>> # Paste mode with multiple indentation levels +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def calculate(n): +=== if n > 0: +=== for i in range(n): +=== if i % 2 == 0: +=== print(f'Even: {i}') +=== else: +=== print(f'Odd: {i}') +=== else: +=== print('n must be positive') +=== \$ +=== calculate(5) +=== \$ +Even: 0 +Odd: 1 +Even: 2 +Odd: 3 +Even: 4 +>>> \$ +>>> # Paste mode with blank lines +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def function_with_blanks(): +=== print('First line') +=== \$ +=== print('After blank line') +=== \$ +=== \$ +=== print('After two blank lines') +=== \$ +=== function_with_blanks() +=== \$ +First line +After blank line +After two blank lines +>>> \$ +>>> # Paste mode with class definition and multiple methods +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== class TestClass: +=== def __init__(self, value): +=== self.value = value +=== \$ +=== def display(self): +=== print(f'Value is: {self.value}') +=== \$ +=== def double(self): +=== self.value *= 2 +=== return self.value +=== \$ +=== obj = TestClass(21) +=== obj.display() +=== print(f'Doubled: {obj.double()}') +=== obj.display() +=== \$ +Value is: 21 +Doubled: 42 +Value is: 42 +>>> \$ +>>> # Paste mode with exception handling +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== try: +=== x = 1 / 0 +=== except ZeroDivisionError: +=== print('Caught division by zero') +=== finally: +=== print('Finally block executed') +=== \$ +Caught division by zero +Finally block executed +>>> \$ +>>> # Cancel paste mode with Ctrl-C +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== print('This should not execute') +=== \$ +>>> \$ +>>> \$ +>>> # Normal REPL still works after cancelled paste +>>> print('Back to normal REPL') +Back to normal REPL +>>> \$ +>>> # Paste mode with syntax error +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def bad_syntax(: +=== print('Missing parameter') +=== \$ +Traceback (most recent call last): + File "", line 2 +SyntaxError: invalid syntax +>>> \$ +>>> # Paste mode with runtime error +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def will_error(): +=== undefined_variable +=== \$ +=== will_error() +=== \$ +Traceback (most recent call last): + File "", line 5, in + File "", line 3, in will_error +NameError: name 'undefined_variable' isn't defined +>>> \$ +>>> # Final test to show REPL is still functioning +>>> 1 + 2 + 3 +6 +>>> \$ diff --git a/tests/cmdline/repl_sys_ps1_ps2.py.exp b/tests/cmdline/repl_sys_ps1_ps2.py.exp index 452a54fe5ae..d4bcf7a44d5 100644 --- a/tests/cmdline/repl_sys_ps1_ps2.py.exp +++ b/tests/cmdline/repl_sys_ps1_ps2.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # test changing ps1/ps2 >>> import sys >>> sys.ps1 = "PS1" diff --git a/tests/cmdline/repl_words_move.py.exp b/tests/cmdline/repl_words_move.py.exp index ba5c3648cff..41ad3d8e733 100644 --- a/tests/cmdline/repl_words_move.py.exp +++ b/tests/cmdline/repl_words_move.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # word movement >>> # backward-word, start in word >>> \.\+ @@ -19,7 +19,7 @@ Use \.\+ >>> # forward-word on eol. if cursor is moved, this will result in a SyntaxError >>> \.\+ 6 ->>> +>>> \$ >>> # kill word >>> # backward-kill-word, start in word >>> \.\+ @@ -33,7 +33,7 @@ Use \.\+ >>> # forward-kill-word, don't start in word >>> \.\+ 3 ->>> +>>> \$ >>> # extra move/kill shortcuts >>> # ctrl-left >>> \.\+ @@ -44,4 +44,4 @@ Use \.\+ >>> # ctrl-w >>> \.\+ 1 ->>> +>>> \$ diff --git a/tests/cpydiff/core_class_initsubclass.py b/tests/cpydiff/core_class_initsubclass.py new file mode 100644 index 00000000000..8683271dcb0 --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass.py @@ -0,0 +1,21 @@ +""" +categories: Core,Classes +description: ``__init_subclass__`` isn't automatically called. +cause: MicroPython does not currently implement PEP 487. +workaround: Manually call ``__init_subclass__`` after class creation if needed. e.g.:: + + class A(Base): + pass + A.__init_subclass__() + +""" + + +class Base: + @classmethod + def __init_subclass__(cls): + print(f"Base.__init_subclass__({cls.__name__})") + + +class A(Base): + pass diff --git a/tests/cpydiff/core_class_initsubclass_autoclassmethod.py b/tests/cpydiff/core_class_initsubclass_autoclassmethod.py new file mode 100644 index 00000000000..b2f7628976c --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass_autoclassmethod.py @@ -0,0 +1,31 @@ +""" +categories: Core,Classes +description: ``__init_subclass__`` isn't an implicit classmethod. +cause: MicroPython does not currently implement PEP 487. ``__init_subclass__`` is not currently in the list of special-cased class/static methods. +workaround: Decorate declarations of ``__init_subclass__`` with ``@classmethod``. +""" + + +def regularize_spelling(text, prefix="bound_"): + # for regularizing across the CPython "method" vs MicroPython "bound_method" spelling for the type of a bound classmethod + if text.startswith(prefix): + return text[len(prefix) :] + return text + + +class A: + def __init_subclass__(cls): + pass + + @classmethod + def manual_decorated(cls): + pass + + +a = type(A.__init_subclass__).__name__ +b = type(A.manual_decorated).__name__ + +print(regularize_spelling(a)) +print(regularize_spelling(b)) +if a != b: + print("FAIL") diff --git a/tests/cpydiff/core_class_initsubclass_kwargs.py b/tests/cpydiff/core_class_initsubclass_kwargs.py new file mode 100644 index 00000000000..ed5157afeae --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass_kwargs.py @@ -0,0 +1,22 @@ +""" +categories: Core,Classes +description: MicroPython doesn't support parameterized ``__init_subclass__`` class customization. +cause: MicroPython does not currently implement PEP 487. The MicroPython syntax tree does not include a kwargs node after the class inheritance list. +workaround: Use class variables or another mechanism to specify base-class customizations. +""" + + +class Base: + @classmethod + def __init_subclass__(cls, arg=None, **kwargs): + cls.init_subclass_was_called = True + print(f"Base.__init_subclass__({cls.__name__}, {arg=!r}, {kwargs=!r})") + + +class A(Base, arg="arg"): + pass + + +# Regularize across MicroPython not automatically calling __init_subclass__ either. +if not getattr(A, "init_subclass_was_called", False): + A.__init_subclass__() diff --git a/tests/cpydiff/core_class_initsubclass_super.py b/tests/cpydiff/core_class_initsubclass_super.py new file mode 100644 index 00000000000..d18671a74bf --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass_super.py @@ -0,0 +1,22 @@ +""" +categories: Core,Classes +description: ``__init_subclass__`` can't be defined a cooperatively-recursive way. +cause: MicroPython does not currently implement PEP 487. The base object type does not have an ``__init_subclass__`` implementation. +workaround: Omit the recursive ``__init_subclass__`` call unless it's known that the grandparent also defines it. +""" + + +class Base: + @classmethod + def __init_subclass__(cls, **kwargs): + cls.init_subclass_was_called = True + super().__init_subclass__(**kwargs) + + +class A(Base): + pass + + +# Regularize across MicroPython not automatically calling __init_subclass__ either. +if not getattr(A, "init_subclass_was_called", False): + A.__init_subclass__() diff --git a/tests/cpydiff/core_fstring_concat.py b/tests/cpydiff/core_fstring_concat.py index 3daa13d7536..2fbe1b961a1 100644 --- a/tests/cpydiff/core_fstring_concat.py +++ b/tests/cpydiff/core_fstring_concat.py @@ -1,5 +1,5 @@ """ -categories: Core +categories: Core,f-strings description: f-strings don't support concatenation with adjacent literals if the adjacent literals contain braces cause: MicroPython is optimised for code space. workaround: Use the + operator between literal strings when they are not both f-strings diff --git a/tests/cpydiff/core_fstring_parser.py b/tests/cpydiff/core_fstring_parser.py index 87cf1e63ed8..4964b9707ac 100644 --- a/tests/cpydiff/core_fstring_parser.py +++ b/tests/cpydiff/core_fstring_parser.py @@ -1,5 +1,5 @@ """ -categories: Core +categories: Core,f-strings description: f-strings cannot support expressions that require parsing to resolve unbalanced nested braces and brackets cause: MicroPython is optimised for code space. workaround: Always use balanced braces and brackets in expressions inside f-strings diff --git a/tests/cpydiff/core_fstring_repr.py b/tests/cpydiff/core_fstring_repr.py index d37fb48db75..2589a34b7e3 100644 --- a/tests/cpydiff/core_fstring_repr.py +++ b/tests/cpydiff/core_fstring_repr.py @@ -1,5 +1,5 @@ """ -categories: Core +categories: Core,f-strings description: f-strings don't support !a conversions cause: MicropPython does not implement ascii() workaround: None diff --git a/tests/cpydiff/core_import_all.py b/tests/cpydiff/core_import_all.py deleted file mode 100644 index 0fbe9d4d4ec..00000000000 --- a/tests/cpydiff/core_import_all.py +++ /dev/null @@ -1,10 +0,0 @@ -""" -categories: Core,import -description: __all__ is unsupported in __init__.py in MicroPython. -cause: Not implemented. -workaround: Manually import the sub-modules directly in __init__.py using ``from . import foo, bar``. -""" - -from modules3 import * - -foo.hello() diff --git a/tests/cpydiff/modules3/__init__.py b/tests/cpydiff/modules3/__init__.py deleted file mode 100644 index 27a2bf2ad90..00000000000 --- a/tests/cpydiff/modules3/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__all__ = ["foo"] diff --git a/tests/cpydiff/modules3/foo.py b/tests/cpydiff/modules3/foo.py deleted file mode 100644 index dd9b9d4ddd4..00000000000 --- a/tests/cpydiff/modules3/foo.py +++ /dev/null @@ -1,2 +0,0 @@ -def hello(): - print("hello") diff --git a/tests/cpydiff/modules_errno_enotsup.py b/tests/cpydiff/modules_errno_enotsup.py new file mode 100644 index 00000000000..80e5ad9d032 --- /dev/null +++ b/tests/cpydiff/modules_errno_enotsup.py @@ -0,0 +1,10 @@ +""" +categories: Modules,errno +description: MicroPython does not include ``ENOTSUP`` as a name for errno 95. +cause: MicroPython does not implement the ``ENOTSUP`` canonical alias for ``EOPNOTSUPP`` added in CPython 3.2. +workaround: Use ``errno.EOPNOTSUPP`` in place of ``errno.ENOTSUP``. +""" + +import errno + +print(f"{errno.errorcode[errno.EOPNOTSUPP]=!s}") diff --git a/tests/cpydiff/modules_struct_fewargs.py b/tests/cpydiff/modules_struct_fewargs.py index 49b2a3213c8..f6346a67938 100644 --- a/tests/cpydiff/modules_struct_fewargs.py +++ b/tests/cpydiff/modules_struct_fewargs.py @@ -1,6 +1,6 @@ """ categories: Modules,struct -description: Struct pack with too few args, not checked by uPy +description: Struct pack with too few args, not checked by MicroPython cause: Unknown workaround: Unknown """ diff --git a/tests/cpydiff/modules_struct_manyargs.py b/tests/cpydiff/modules_struct_manyargs.py index e3b78930f21..b2ea93b6c93 100644 --- a/tests/cpydiff/modules_struct_manyargs.py +++ b/tests/cpydiff/modules_struct_manyargs.py @@ -1,6 +1,6 @@ """ categories: Modules,struct -description: Struct pack with too many args, not checked by uPy +description: Struct pack with too many args, not checked by MicroPython cause: Unknown workaround: Unknown """ diff --git a/tests/cpydiff/modules_struct_whitespace_in_format.py b/tests/cpydiff/modules_struct_whitespace_in_format.py index a7a1d2facdf..8b609425eb0 100644 --- a/tests/cpydiff/modules_struct_whitespace_in_format.py +++ b/tests/cpydiff/modules_struct_whitespace_in_format.py @@ -1,6 +1,6 @@ """ categories: Modules,struct -description: Struct pack with whitespace in format, whitespace ignored by CPython, error on uPy +description: Struct pack with whitespace in format, whitespace ignored by CPython, error on MicroPython cause: MicroPython is optimised for code size. workaround: Don't use spaces in format strings. """ diff --git a/tests/cpydiff/syntax_arg_unpacking.py b/tests/cpydiff/syntax_arg_unpacking.py index e54832ddb91..7133a8a2827 100644 --- a/tests/cpydiff/syntax_arg_unpacking.py +++ b/tests/cpydiff/syntax_arg_unpacking.py @@ -1,5 +1,5 @@ """ -categories: Syntax +categories: Syntax,Unpacking description: Argument unpacking does not work if the argument being unpacked is the nth or greater argument where n is the number of bits in an MP_SMALL_INT. cause: The implementation uses an MP_SMALL_INT to flag args that need to be unpacked. workaround: Use fewer arguments. diff --git a/tests/cpydiff/syntax_literal_underscore.py b/tests/cpydiff/syntax_literal_underscore.py new file mode 100644 index 00000000000..4b1406e9f3f --- /dev/null +++ b/tests/cpydiff/syntax_literal_underscore.py @@ -0,0 +1,19 @@ +""" +categories: Syntax,Literals +description: MicroPython accepts underscores in numeric literals where CPython doesn't +cause: Different parser implementation + +MicroPython's tokenizer ignores underscores in numeric literals, while CPython +rejects multiple consecutive underscores and underscores after the last digit. + +workaround: Remove the underscores not accepted by CPython. +""" + +try: + print(eval("1__1")) +except SyntaxError: + print("Should not work") +try: + print(eval("1_")) +except SyntaxError: + print("Should not work") diff --git a/tests/cpydiff/syntax_spaces.py b/tests/cpydiff/syntax_spaces.py index 03d25d56199..670cefdeac2 100644 --- a/tests/cpydiff/syntax_spaces.py +++ b/tests/cpydiff/syntax_spaces.py @@ -1,8 +1,15 @@ """ -categories: Syntax,Spaces -description: uPy requires spaces between literal numbers and keywords, CPy doesn't -cause: Unknown -workaround: Unknown +categories: Syntax,Literals +description: MicroPython requires spaces between literal numbers and keywords or ".", CPython doesn't +cause: Different parser implementation + +MicroPython's tokenizer treats a sequence like ``1and`` as a single token, while CPython treats it as two tokens. + +Since CPython 3.11, when the literal number is followed by a token, this syntax causes a ``SyntaxWarning`` for an "invalid literal". When a literal number is followed by a "." denoting attribute access, CPython does not warn. + +workaround: Add a space between the integer literal and the intended next token. + +This also fixes the ``SyntaxWarning`` in CPython. """ try: @@ -17,3 +24,7 @@ print(eval("1if 1else 0")) except SyntaxError: print("Should have worked") +try: + print(eval("0x1.to_bytes(1)")) +except SyntaxError: + print("Should have worked") diff --git a/tests/cpydiff/types_complex_parser.py b/tests/cpydiff/types_complex_parser.py new file mode 100644 index 00000000000..4a012987d9e --- /dev/null +++ b/tests/cpydiff/types_complex_parser.py @@ -0,0 +1,14 @@ +""" +categories: Types,complex +description: MicroPython's complex() accepts certain incorrect values that CPython rejects +cause: MicroPython is highly optimized for memory usage. +workaround: Do not use non-standard complex literals as argument to complex() + +MicroPython's ``complex()`` function accepts literals that contain a space and +no sign between the real and imaginary parts, and interprets it as a plus. +""" + +try: + print(complex("1 1j")) +except ValueError: + print("ValueError") diff --git a/tests/cpydiff/types_float_implicit_conversion.py b/tests/cpydiff/types_float_implicit_conversion.py index 3726839fac6..764c9e4e6ed 100644 --- a/tests/cpydiff/types_float_implicit_conversion.py +++ b/tests/cpydiff/types_float_implicit_conversion.py @@ -1,6 +1,6 @@ """ categories: Types,float -description: uPy allows implicit conversion of objects in maths operations while CPython does not. +description: MicroPython allows implicit conversion of objects in maths operations while CPython does not. cause: Unknown workaround: Objects should be wrapped in ``float(obj)`` for compatibility with CPython. """ diff --git a/tests/cpydiff/types_float_rounding.py b/tests/cpydiff/types_float_rounding.py deleted file mode 100644 index 206e359ed9b..00000000000 --- a/tests/cpydiff/types_float_rounding.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -categories: Types,float -description: uPy and CPython outputs formats may differ -cause: Unknown -workaround: Unknown -""" - -print("%.1g" % -9.9) diff --git a/tests/cpydiff/types_oserror_errnomap.py b/tests/cpydiff/types_oserror_errnomap.py new file mode 100644 index 00000000000..6627bd2af4a --- /dev/null +++ b/tests/cpydiff/types_oserror_errnomap.py @@ -0,0 +1,48 @@ +""" +categories: Types,OSError +description: OSError constructor returns a plain OSError for all errno values, rather than a relevant subtype. +cause: MicroPython does not include the CPython-standard OSError subclasses. +workaround: Catch OSError and use its errno attribute to discriminate the cause. +""" + +import errno + +errno_list = [ # i.e. the set implemented by micropython + errno.EPERM, + errno.ENOENT, + errno.EIO, + errno.EBADF, + errno.EAGAIN, + errno.ENOMEM, + errno.EACCES, + errno.EEXIST, + errno.ENODEV, + errno.EISDIR, + errno.EINVAL, + errno.EOPNOTSUPP, + errno.EADDRINUSE, + errno.ECONNABORTED, + errno.ECONNRESET, + errno.ENOBUFS, + errno.ENOTCONN, + errno.ETIMEDOUT, + errno.ECONNREFUSED, + errno.EHOSTUNREACH, + errno.EALREADY, + errno.EINPROGRESS, +] + + +def errno_output_type(n): + try: + raise OSError(n, "") + except OSError as e: + return f"{type(e).__name__}" + except Exception as e: + return f"non-OSError {type(e).__name__}" + else: + return "no error" + + +for n in errno_list: + print(errno.errorcode[n], "=", errno_output_type(n)) diff --git a/tests/cpydiff/types_range_limits.py b/tests/cpydiff/types_range_limits.py new file mode 100644 index 00000000000..e53d5fd4088 --- /dev/null +++ b/tests/cpydiff/types_range_limits.py @@ -0,0 +1,26 @@ +""" +categories: Types,range +description: Range objects with large start or stop arguments misbehave. +cause: Intermediate calculations overflow the C mp_int_t type +workaround: Avoid using such ranges +""" + +from sys import maxsize + +# A range including `maxsize-1` cannot be created +try: + print(range(-maxsize - 1, 0)) +except OverflowError: + print("OverflowError") + +# A range with `stop-start` exceeding sys.maxsize has incorrect len(), while CPython cannot calculate len(). +try: + print(len(range(-maxsize, maxsize))) +except OverflowError: + print("OverflowError") + +# A range with `stop-start` exceeding sys.maxsize has incorrect len() +try: + print(len(range(-maxsize, maxsize, maxsize))) +except OverflowError: + print("OverflowError") diff --git a/tests/cpydiff/types_str_formatsep.py b/tests/cpydiff/types_str_formatsep.py new file mode 100644 index 00000000000..05d0b8d3d2c --- /dev/null +++ b/tests/cpydiff/types_str_formatsep.py @@ -0,0 +1,19 @@ +""" +categories: Types,str +description: MicroPython accepts the "," grouping option with any radix, unlike CPython +cause: To reduce code size, MicroPython does not issue an error for this combination +workaround: Do not use a format string like ``{:,b}`` if CPython compatibility is required. +""" + +try: + print("{:,b}".format(99)) +except ValueError: + print("ValueError") +try: + print("{:,x}".format(99)) +except ValueError: + print("ValueError") +try: + print("{:,o}".format(99)) +except ValueError: + print("ValueError") diff --git a/tests/cpydiff/types_str_formatsep_float.py b/tests/cpydiff/types_str_formatsep_float.py new file mode 100644 index 00000000000..b487cd3758e --- /dev/null +++ b/tests/cpydiff/types_str_formatsep_float.py @@ -0,0 +1,11 @@ +""" +categories: Types,str +description: MicroPython accepts but does not properly implement the "," or "_" grouping character for float values +cause: To reduce code size, MicroPython does not implement this combination. Grouping characters will not appear in the number's significant digits and will appear at incorrect locations in leading zeros. +workaround: Do not use a format string like ``{:,f}`` if exact CPython compatibility is required. +""" + +print("{:,f}".format(3141.159)) +print("{:_f}".format(3141.159)) +print("{:011,.2f}".format(3141.159)) +print("{:011_.2f}".format(3141.159)) diff --git a/tests/extmod/asyncio_basic.py.exp b/tests/extmod/asyncio_basic.py.exp deleted file mode 100644 index 478e22abc8f..00000000000 --- a/tests/extmod/asyncio_basic.py.exp +++ /dev/null @@ -1,6 +0,0 @@ -start -after sleep -short -long -negative -took 200 400 0 diff --git a/tests/extmod/asyncio_event_queue.py b/tests/extmod/asyncio_event_queue.py new file mode 100644 index 00000000000..e0125b1aefe --- /dev/null +++ b/tests/extmod/asyncio_event_queue.py @@ -0,0 +1,64 @@ +# Ensure that an asyncio task can wait on an Event when the +# _task_queue is empty +# https://github.com/micropython/micropython/issues/16569 + +try: + import asyncio +except ImportError: + print("SKIP") + raise SystemExit + +# This test requires checking that the asyncio scheduler +# remains active "indefinitely" when the task queue is empty. +# +# To check this, we need another independent scheduler that +# can wait for a certain amount of time. So we have to +# create one using micropython.schedule() and time.ticks_ms() +# +# Technically, this code breaks the rules, as it is clearly +# documented that Event.set() should _NOT_ be called from a +# schedule (soft IRQ) because in some cases, a race condition +# can occur, resulting in a crash. However: +# - since the risk of a race condition in that specific +# case has been analysed and excluded +# - given that there is no other simple alternative to +# write this test case, +# an exception to the rule was deemed acceptable. See +# https://github.com/micropython/micropython/pull/16772 + +import micropython, time + +try: + micropython.schedule +except AttributeError: + print("SKIP") + raise SystemExit + + +evt = asyncio.Event() + + +def schedule_watchdog(end_ticks): + if time.ticks_diff(end_ticks, time.ticks_ms()) <= 0: + print("asyncio still pending, unlocking event") + # Caution: about to call Event.set() from a schedule + # (see the note in the comment above) + evt.set() + return + micropython.schedule(schedule_watchdog, end_ticks) + + +async def foo(): + print("foo waiting") + schedule_watchdog(time.ticks_add(time.ticks_ms(), 100)) + await evt.wait() + print("foo done") + + +async def main(): + print("main started") + await foo() + print("main done") + + +asyncio.run(main()) diff --git a/tests/extmod/asyncio_event_queue.py.exp b/tests/extmod/asyncio_event_queue.py.exp new file mode 100644 index 00000000000..ee42c96d83e --- /dev/null +++ b/tests/extmod/asyncio_event_queue.py.exp @@ -0,0 +1,5 @@ +main started +foo waiting +asyncio still pending, unlocking event +foo done +main done diff --git a/tests/extmod/asyncio_heaplock.py b/tests/extmod/asyncio_heaplock.py index 8326443f0e6..9e9908de1cb 100644 --- a/tests/extmod/asyncio_heaplock.py +++ b/tests/extmod/asyncio_heaplock.py @@ -4,7 +4,11 @@ # - StreamWriter.write, stream is blocked and data to write is a bytes object # - StreamWriter.write, when stream is not blocked -import micropython +try: + import asyncio, micropython +except ImportError: + print("SKIP") + raise SystemExit # strict stackless builds can't call functions without allocating a frame on the heap try: @@ -24,12 +28,6 @@ def f(x): print("SKIP") raise SystemExit -try: - import asyncio -except ImportError: - print("SKIP") - raise SystemExit - class TestStream: def __init__(self, blocked): diff --git a/tests/extmod/asyncio_iterator_event.py b/tests/extmod/asyncio_iterator_event.py new file mode 100644 index 00000000000..f61fefcf051 --- /dev/null +++ b/tests/extmod/asyncio_iterator_event.py @@ -0,0 +1,86 @@ +# Ensure that an asyncio task can wait on an Event when the +# _task_queue is empty, in the context of an async iterator +# https://github.com/micropython/micropython/issues/16318 + +try: + import asyncio +except ImportError: + print("SKIP") + raise SystemExit + +# This test requires checking that the asyncio scheduler +# remains active "indefinitely" when the task queue is empty. +# +# To check this, we need another independent scheduler that +# can wait for a certain amount of time. So we have to +# create one using micropython.schedule() and time.ticks_ms() +# +# Technically, this code breaks the rules, as it is clearly +# documented that Event.set() should _NOT_ be called from a +# schedule (soft IRQ) because in some cases, a race condition +# can occur, resulting in a crash. However: +# - since the risk of a race condition in that specific +# case has been analysed and excluded +# - given that there is no other simple alternative to +# write this test case, +# an exception to the rule was deemed acceptable. See +# https://github.com/micropython/micropython/pull/16772 + +import micropython, time + +try: + micropython.schedule +except AttributeError: + print("SKIP") + raise SystemExit + +ai = None + + +def schedule_watchdog(end_ticks): + if time.ticks_diff(end_ticks, time.ticks_ms()) <= 0: + print("good: asyncio iterator is still pending, exiting") + # Caution: ai.fetch_data() will invoke Event.set() + # (see the note in the comment above) + ai.fetch_data(None) + return + micropython.schedule(schedule_watchdog, end_ticks) + + +async def test(ai): + for x in range(3): + await asyncio.sleep(0.1) + ai.fetch_data("bar {}".format(x)) + + +class AsyncIterable: + def __init__(self): + self.message = None + self.evt = asyncio.Event() + + def __aiter__(self): + return self + + async def __anext__(self): + await self.evt.wait() + self.evt.clear() + if self.message is None: + raise StopAsyncIteration + return self.message + + def fetch_data(self, message): + self.message = message + self.evt.set() + + +async def main(): + global ai + ai = AsyncIterable() + asyncio.create_task(test(ai)) + schedule_watchdog(time.ticks_add(time.ticks_ms(), 500)) + async for message in ai: + print(message) + print("end main") + + +asyncio.run(main()) diff --git a/tests/extmod/asyncio_iterator_event.py.exp b/tests/extmod/asyncio_iterator_event.py.exp new file mode 100644 index 00000000000..a1893197d02 --- /dev/null +++ b/tests/extmod/asyncio_iterator_event.py.exp @@ -0,0 +1,5 @@ +bar 0 +bar 1 +bar 2 +good: asyncio iterator is still pending, exiting +end main diff --git a/tests/extmod/asyncio_lock.py.exp b/tests/extmod/asyncio_lock.py.exp deleted file mode 100644 index a37dfcbd2e5..00000000000 --- a/tests/extmod/asyncio_lock.py.exp +++ /dev/null @@ -1,41 +0,0 @@ -False -True -False -have lock ----- -task start 1 -task start 2 -task start 3 -task have 1 0 -task have 2 0 -task have 3 0 -task have 1 1 -task have 2 1 -task have 3 1 -task have 1 2 -task end 1 -task have 2 2 -task end 2 -task have 3 2 -task end 3 ----- -task have True -task release False -task have True -task release False -task have again -task have again ----- -task got 0 -task release 0 -task cancel 1 -task got 2 -task release 2 -False ----- -task got 0 -task cancel 1 -task release 0 -task got 2 -task cancel 2 -False diff --git a/tests/extmod/asyncio_set_exception_handler.py b/tests/extmod/asyncio_set_exception_handler.py index 5935f0f4ebe..0ac4a624224 100644 --- a/tests/extmod/asyncio_set_exception_handler.py +++ b/tests/extmod/asyncio_set_exception_handler.py @@ -12,7 +12,7 @@ def custom_handler(loop, context): async def task(i): - # Raise with 2 args so exception prints the same in uPy and CPython + # Raise with 2 args so exception prints the same in MicroPython and CPython raise ValueError(i, i + 1) diff --git a/tests/extmod/asyncio_wait_for_linked_task.py b/tests/extmod/asyncio_wait_for_linked_task.py new file mode 100644 index 00000000000..4dda62d5476 --- /dev/null +++ b/tests/extmod/asyncio_wait_for_linked_task.py @@ -0,0 +1,66 @@ +# Test asyncio.wait_for, with dependent tasks +# https://github.com/micropython/micropython/issues/16759 + +try: + import asyncio +except ImportError: + print("SKIP") + raise SystemExit + + +# CPython 3.12 deprecated calling get_event_loop() when there is no current event +# loop, so to make this test run on CPython requires setting the event loop. +if hasattr(asyncio, "set_event_loop"): + asyncio.set_event_loop(asyncio.new_event_loop()) + + +class Worker: + def __init__(self): + self._eventLoop = None + self._tasks = [] + + def launchTask(self, asyncJob): + if self._eventLoop is None: + self._eventLoop = asyncio.get_event_loop() + return self._eventLoop.create_task(asyncJob) + + async def job(self, prerequisite, taskName): + if prerequisite: + await prerequisite + await asyncio.sleep(0.1) + print(taskName, "work completed") + + def planTasks(self): + self._tasks.append(self.launchTask(self.job(None, "task0"))) + self._tasks.append(self.launchTask(self.job(self._tasks[0], "task1"))) + self._tasks.append(self.launchTask(self.job(self._tasks[1], "task2"))) + + async def waitForTask(self, taskIdx): + return await self._tasks[taskIdx] + + def syncWaitForTask(self, taskIdx): + return self._eventLoop.run_until_complete(self._tasks[taskIdx]) + + +async def async_test(): + print("--- async test") + worker = Worker() + worker.planTasks() + await worker.waitForTask(0) + print("-> task0 done") + await worker.waitForTask(2) + print("-> task2 done") + + +def sync_test(): + print("--- sync test") + worker = Worker() + worker.planTasks() + worker.syncWaitForTask(0) + print("-> task0 done") + worker.syncWaitForTask(2) + print("-> task2 done") + + +asyncio.get_event_loop().run_until_complete(async_test()) +sync_test() diff --git a/tests/extmod/asyncio_wait_task.py.exp b/tests/extmod/asyncio_wait_task.py.exp deleted file mode 100644 index 514a4342233..00000000000 --- a/tests/extmod/asyncio_wait_task.py.exp +++ /dev/null @@ -1,12 +0,0 @@ -start -task 1 -task 2 ----- -start -hello -world -took 200 200 -task_raise -ValueError -task_raise -ValueError diff --git a/tests/extmod/binascii_hexlify.py b/tests/extmod/binascii_hexlify.py index d06029aabaf..ae90b673365 100644 --- a/tests/extmod/binascii_hexlify.py +++ b/tests/extmod/binascii_hexlify.py @@ -1,5 +1,5 @@ try: - import binascii + from binascii import hexlify except ImportError: print("SKIP") raise SystemExit @@ -10,10 +10,10 @@ b"\x7f\x80\xff", b"1234ABCDabcd", ): - print(binascii.hexlify(x)) + print(hexlify(x)) # Two-argument version (now supported in CPython) -print(binascii.hexlify(b"123", ":")) +print(hexlify(b"123", ":")) # zero length buffer -print(binascii.hexlify(b"", b":")) +print(hexlify(b"", b":")) diff --git a/tests/extmod/binascii_unhexlify.py b/tests/extmod/binascii_unhexlify.py index 731b6a2bd4d..b08704cba65 100644 --- a/tests/extmod/binascii_unhexlify.py +++ b/tests/extmod/binascii_unhexlify.py @@ -1,5 +1,5 @@ try: - import binascii + from binascii import unhexlify except ImportError: print("SKIP") raise SystemExit @@ -10,18 +10,18 @@ b"7f80ff", b"313233344142434461626364", ): - print(binascii.unhexlify(x)) + print(unhexlify(x)) # CIRCUITPY-CHANGE # Unicode strings can be decoded -print(binascii.unhexlify("313233344142434461626364")) +print(unhexlify("313233344142434461626364")) try: - a = binascii.unhexlify(b"0") # odd buffer length + a = unhexlify(b"0") # odd buffer length except ValueError: print("ValueError") try: - a = binascii.unhexlify(b"gg") # digit not hex + a = unhexlify(b"gg") # digit not hex except ValueError: print("ValueError") diff --git a/tests/extmod/framebuf_blit.py b/tests/extmod/framebuf_blit.py new file mode 100644 index 00000000000..b1d98b330a8 --- /dev/null +++ b/tests/extmod/framebuf_blit.py @@ -0,0 +1,68 @@ +# Test FrameBuffer.blit method. + +try: + import framebuf +except ImportError: + print("SKIP") + raise SystemExit + + +def printbuf(): + print("--8<--") + for y in range(h): + for x in range(w): + print("%02x" % buf[(x + y * w)], end="") + print() + print("-->8--") + + +w = 5 +h = 4 +buf = bytearray(w * h) +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8) + +fbuf2 = framebuf.FrameBuffer(bytearray(4), 2, 2, framebuf.GS8) +fbuf2.fill(0xFF) + +# Blit another FrameBuffer, at various locations. +for x, y in ((-1, -1), (0, 0), (1, 1), (4, 3)): + fbuf.fill(0) + fbuf.blit(fbuf2, x, y) + printbuf() + +# Blit a bytes object. +fbuf.fill(0) +image = (b"\x10\x11\x12\x13", 2, 2, framebuf.GS8) +fbuf.blit(image, 1, 1) +printbuf() + +# Blit a bytes object that has a stride. +fbuf.fill(0) +image = (b"\x20\x21\xff\x22\x23\xff", 2, 2, framebuf.GS8, 3) +fbuf.blit(image, 1, 1) +printbuf() + +# Blit a bytes object with a bytes palette. +fbuf.fill(0) +image = (b"\x00\x01\x01\x00", 2, 2, framebuf.GS8) +palette = (b"\xa1\xa2", 2, 1, framebuf.GS8) +fbuf.blit(image, 1, 1, -1, palette) +printbuf() + +# Not enough elements in the tuple. +try: + fbuf.blit((0, 0, 0), 0, 0) +except ValueError: + print("ValueError") + +# Too many elements in the tuple. +try: + fbuf.blit((0, 0, 0, 0, 0, 0), 0, 0) +except ValueError: + print("ValueError") + +# Bytes too small. +try: + fbuf.blit((b"", 1, 1, framebuf.GS8), 0, 0) +except ValueError: + print("ValueError") diff --git a/tests/extmod/framebuf_blit.py.exp b/tests/extmod/framebuf_blit.py.exp new file mode 100644 index 00000000000..e340f1990c7 --- /dev/null +++ b/tests/extmod/framebuf_blit.py.exp @@ -0,0 +1,45 @@ +--8<-- +ff00000000 +0000000000 +0000000000 +0000000000 +-->8-- +--8<-- +ffff000000 +ffff000000 +0000000000 +0000000000 +-->8-- +--8<-- +0000000000 +00ffff0000 +00ffff0000 +0000000000 +-->8-- +--8<-- +0000000000 +0000000000 +0000000000 +00000000ff +-->8-- +--8<-- +0000000000 +0010110000 +0012130000 +0000000000 +-->8-- +--8<-- +0000000000 +0020210000 +0022230000 +0000000000 +-->8-- +--8<-- +0000000000 +00a1a20000 +00a2a10000 +0000000000 +-->8-- +ValueError +ValueError +ValueError diff --git a/tests/extmod/hashlib_md5.py b/tests/extmod/hashlib_md5.py index 5f925fc97d0..ebbe9155e04 100644 --- a/tests/extmod/hashlib_md5.py +++ b/tests/extmod/hashlib_md5.py @@ -1,8 +1,7 @@ try: import hashlib except ImportError: - # This is neither uPy, nor cPy, so must be uPy with - # hashlib module disabled. + # MicroPython with hashlib module disabled. print("SKIP") raise SystemExit diff --git a/tests/extmod/hashlib_sha1.py b/tests/extmod/hashlib_sha1.py index af23033a591..46ffb73fcbe 100644 --- a/tests/extmod/hashlib_sha1.py +++ b/tests/extmod/hashlib_sha1.py @@ -1,8 +1,7 @@ try: import hashlib except ImportError: - # This is neither uPy, nor cPy, so must be uPy with - # hashlib module disabled. + # MicroPython with hashlib module disabled. print("SKIP") raise SystemExit diff --git a/tests/extmod/hashlib_sha256.py b/tests/extmod/hashlib_sha256.py index 95cd301d160..209fcb39877 100644 --- a/tests/extmod/hashlib_sha256.py +++ b/tests/extmod/hashlib_sha256.py @@ -1,8 +1,7 @@ try: import hashlib except ImportError: - # This is neither uPy, nor cPy, so must be uPy with - # hashlib module disabled. + # MicroPython with hashlib module disabled. print("SKIP") raise SystemExit diff --git a/tests/extmod/json_dump.py b/tests/extmod/json_dump.py index 897d33cc812..0beb4f5f856 100644 --- a/tests/extmod/json_dump.py +++ b/tests/extmod/json_dump.py @@ -16,11 +16,11 @@ # dump to a small-int not allowed try: json.dump(123, 1) -except (AttributeError, OSError): # CPython and uPy have different errors +except (AttributeError, OSError): # CPython and MicroPython have different errors print("Exception") # dump to an object not allowed try: json.dump(123, {}) -except (AttributeError, OSError): # CPython and uPy have different errors +except (AttributeError, OSError): # CPython and MicroPython have different errors print("Exception") diff --git a/tests/extmod/json_dump_iobase.py b/tests/extmod/json_dump_iobase.py index 94d317b8796..81105e36dcc 100644 --- a/tests/extmod/json_dump_iobase.py +++ b/tests/extmod/json_dump_iobase.py @@ -18,7 +18,7 @@ def __init__(self): def write(self, buf): if type(buf) == bytearray: - # uPy passes a bytearray, CPython passes a str + # MicroPython passes a bytearray, CPython passes a str buf = str(buf, "ascii") self.buf += buf return len(buf) diff --git a/tests/extmod/json_dump_separators.py b/tests/extmod/json_dump_separators.py index 4f8e56dceb5..ce39294820f 100644 --- a/tests/extmod/json_dump_separators.py +++ b/tests/extmod/json_dump_separators.py @@ -25,20 +25,20 @@ # dump to a small-int not allowed try: json.dump(123, 1, separators=sep) - except (AttributeError, OSError): # CPython and uPy have different errors + except (AttributeError, OSError): # CPython and MicroPython have different errors print("Exception") # dump to an object not allowed try: json.dump(123, {}, separators=sep) - except (AttributeError, OSError): # CPython and uPy have different errors + except (AttributeError, OSError): # CPython and MicroPython have different errors print("Exception") try: s = StringIO() json.dump(False, s, separators={"a": 1}) -except (TypeError, ValueError): # CPython and uPy have different errors +except (TypeError, ValueError): # CPython and MicroPython have different errors print("Exception") # invalid separator types diff --git a/tests/extmod/json_dumps_extra.py b/tests/extmod/json_dumps_extra.py index a410b0ee0ef..70efc866451 100644 --- a/tests/extmod/json_dumps_extra.py +++ b/tests/extmod/json_dumps_extra.py @@ -1,4 +1,4 @@ -# test uPy json behaviour that's not valid in CPy +# test MicroPython json behaviour that's not valid in CPy # CIRCUITPY-CHANGE: This behavior matches CPython print("SKIP") raise SystemExit diff --git a/tests/extmod/json_dumps_separators.py b/tests/extmod/json_dumps_separators.py index a3a9ec308f0..0a95f489a08 100644 --- a/tests/extmod/json_dumps_separators.py +++ b/tests/extmod/json_dumps_separators.py @@ -39,7 +39,7 @@ try: json.dumps(False, separators={"a": 1}) -except (TypeError, ValueError): # CPython and uPy have different errors +except (TypeError, ValueError): # CPython and MicroPython have different errors print("Exception") # invalid separator types diff --git a/tests/extmod/json_loads.py b/tests/extmod/json_loads.py index f9073c121e2..092402d715d 100644 --- a/tests/extmod/json_loads.py +++ b/tests/extmod/json_loads.py @@ -71,3 +71,27 @@ def my_print(o): my_print(json.loads("[null] a")) except ValueError: print("ValueError") + +# incomplete object declaration +try: + my_print(json.loads('{"a":0,')) +except ValueError: + print("ValueError") + +# incomplete nested array declaration +try: + my_print(json.loads('{"a":0, [')) +except ValueError: + print("ValueError") + +# incomplete array declaration +try: + my_print(json.loads("[0,")) +except ValueError: + print("ValueError") + +# incomplete nested object declaration +try: + my_print(json.loads('[0, {"a":0, ')) +except ValueError: + print("ValueError") diff --git a/tests/extmod/json_loads_bytes.py.exp b/tests/extmod/json_loads_bytes.py.exp deleted file mode 100644 index c2735a99052..00000000000 --- a/tests/extmod/json_loads_bytes.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -[1, 2] -[None] diff --git a/tests/extmod/json_loads_int_64.py b/tests/extmod/json_loads_int_64.py new file mode 100644 index 00000000000..f6236f1904a --- /dev/null +++ b/tests/extmod/json_loads_int_64.py @@ -0,0 +1,16 @@ +# Parse 64-bit integers from JSON payloads. +# +# This also exercises parsing integers from strings +# where the value may not be null terminated (last line) +try: + import json +except ImportError: + print("SKIP") + raise SystemExit + + +print(json.loads("9111222333444555666")) +print(json.loads("-9111222333444555666")) +print(json.loads("9111222333444555666")) +print(json.loads("-9111222333444555666")) +print(json.loads('["9111222333444555666777",9111222333444555666]')) diff --git a/tests/extmod/machine_hard_timer.py b/tests/extmod/machine_hard_timer.py new file mode 100644 index 00000000000..8fe42ea8508 --- /dev/null +++ b/tests/extmod/machine_hard_timer.py @@ -0,0 +1,45 @@ +import sys + +try: + from machine import Timer + from time import sleep_ms +except: + print("SKIP") + raise SystemExit + +if sys.platform == "esp8266": + timer = Timer(0) +else: + # Hardware timers are not implemented. + print("SKIP") + raise SystemExit + +# Test both hard and soft IRQ handlers and both one-shot and periodic +# timers. We adjust period in tests/extmod/machine_soft_timer.py, so try +# adjusting freq here instead. The heap should be locked in hard callbacks +# and unlocked in soft callbacks. + + +def callback(t): + print("callback", mode[1], kind[1], freq, end=" ") + try: + allocate = bytearray(1) + print("unlocked") + except MemoryError: + print("locked") + + +modes = [(Timer.ONE_SHOT, "one-shot"), (Timer.PERIODIC, "periodic")] +kinds = [(False, "soft"), (True, "hard")] + +for mode in modes: + for kind in kinds: + for freq in 50, 25: + timer.init( + mode=mode[0], + freq=freq, + hard=kind[0], + callback=callback, + ) + sleep_ms(90) + timer.deinit() diff --git a/tests/extmod/machine_hard_timer.py.exp b/tests/extmod/machine_hard_timer.py.exp new file mode 100644 index 00000000000..26cdc644fdd --- /dev/null +++ b/tests/extmod/machine_hard_timer.py.exp @@ -0,0 +1,16 @@ +callback one-shot soft 50 unlocked +callback one-shot soft 25 unlocked +callback one-shot hard 50 locked +callback one-shot hard 25 locked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 25 unlocked +callback periodic soft 25 unlocked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 25 locked +callback periodic hard 25 locked diff --git a/tests/extmod/machine_timer.py b/tests/extmod/machine_timer.py new file mode 100644 index 00000000000..ef97ea4e949 --- /dev/null +++ b/tests/extmod/machine_timer.py @@ -0,0 +1,48 @@ +import sys + +try: + from machine import Timer + from time import sleep_ms +except: + print("SKIP") + raise SystemExit + +if sys.platform in ("esp32", "esp8266", "nrf"): + # Software timers aren't implemented on the esp32 and esp8266 ports. + # The nrf port doesn't support selection of hard and soft callbacks, + # and only allows Timer(period=N), not Timer(freq=N). + print("SKIP") + raise SystemExit +else: + timer_id = -1 + +# Test both hard and soft IRQ handlers and both one-shot and periodic +# timers. We adjust period in tests/extmod/machine_soft_timer.py, so try +# adjusting freq here instead. The heap should be locked in hard callbacks +# and unlocked in soft callbacks. + + +def callback(t): + print("callback", mode[1], kind[1], freq, end=" ") + try: + allocate = bytearray(1) + print("unlocked") + except MemoryError: + print("locked") + + +modes = [(Timer.ONE_SHOT, "one-shot"), (Timer.PERIODIC, "periodic")] +kinds = [(False, "soft"), (True, "hard")] + +for mode in modes: + for kind in kinds: + for freq in 50, 25: + timer = Timer( + timer_id, + mode=mode[0], + freq=freq, + hard=kind[0], + callback=callback, + ) + sleep_ms(90) + timer.deinit() diff --git a/tests/extmod/machine_timer.py.exp b/tests/extmod/machine_timer.py.exp new file mode 100644 index 00000000000..26cdc644fdd --- /dev/null +++ b/tests/extmod/machine_timer.py.exp @@ -0,0 +1,16 @@ +callback one-shot soft 50 unlocked +callback one-shot soft 25 unlocked +callback one-shot hard 50 locked +callback one-shot hard 25 locked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 25 unlocked +callback periodic soft 25 unlocked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 25 locked +callback periodic hard 25 locked diff --git a/tests/extmod/platform_basic.py b/tests/extmod/platform_basic.py new file mode 100644 index 00000000000..eb6f2be13c1 --- /dev/null +++ b/tests/extmod/platform_basic.py @@ -0,0 +1,8 @@ +try: + import platform +except ImportError: + print("SKIP") + raise SystemExit + +print(type(platform.python_compiler())) +print(type(platform.libc_ver())) diff --git a/tests/extmod/random_extra_float.py b/tests/extmod/random_extra_float.py index 3b37ed8dcef..03973c58349 100644 --- a/tests/extmod/random_extra_float.py +++ b/tests/extmod/random_extra_float.py @@ -1,12 +1,8 @@ try: import random -except ImportError: - print("SKIP") - raise SystemExit -try: - random.randint -except AttributeError: + random.random +except (ImportError, AttributeError): print("SKIP") raise SystemExit diff --git a/tests/extmod/re_error.py b/tests/extmod/re_error.py index f61d0913289..bd678c9d251 100644 --- a/tests/extmod/re_error.py +++ b/tests/extmod/re_error.py @@ -11,7 +11,7 @@ def test_re(r): try: re.compile(r) print("OK") - except: # uPy and CPy use different errors, so just ignore the type + except: # MPy and CPy use different errors, so just ignore the type print("Error") diff --git a/tests/extmod/re_start_end_pos.py b/tests/extmod/re_start_end_pos.py new file mode 100644 index 00000000000..bd16584374b --- /dev/null +++ b/tests/extmod/re_start_end_pos.py @@ -0,0 +1,78 @@ +# test start and end pos specification + +try: + import re +except ImportError: + print("SKIP") + raise SystemExit + + +def print_groups(match): + print("----") + try: + if match is not None: + i = 0 + while True: + print(match.group(i)) + i += 1 + except IndexError: + pass + + +p = re.compile(r"o") +m = p.match("dog") +print_groups(m) + +m = p.match("dog", 1) +print_groups(m) + +m = p.match("dog", 2) +print_groups(m) + +# No match past end of input +m = p.match("dog", 5) +print_groups(m) + +m = p.match("dog", 0, 1) +print_groups(m) + +# Caret only matches the actual beginning +p = re.compile(r"^o") +m = p.match("dog", 1) +print_groups(m) + +# End at beginning means searching empty string +p = re.compile(r"o") +m = p.match("dog", 1, 1) +print_groups(m) + +# End before the beginning doesn't match anything +m = p.match("dog", 2, 1) +print_groups(m) + +# Negative starting values don't crash +m = p.search("dog", -2) +print_groups(m) + +m = p.search("dog", -2, -5) +print_groups(m) + +# Search also works +print("--search") + +p = re.compile(r"o") +m = p.search("dog") +print_groups(m) + +m = p.search("dog", 1) +print_groups(m) + +m = p.search("dog", 2) +print_groups(m) + +# Negative starting values don't crash +m = p.search("dog", -2) +print_groups(m) + +m = p.search("dog", -2, -5) +print_groups(m) diff --git a/tests/extmod/re_sub.py b/tests/extmod/re_sub.py index 3959949724d..bb9aa111287 100644 --- a/tests/extmod/re_sub.py +++ b/tests/extmod/re_sub.py @@ -62,7 +62,7 @@ def A(): except: print("invalid group") -# invalid group with very large number (to test overflow in uPy) +# invalid group with very large number (to test overflow in MicroPython) try: re.sub("(a)", "b\\199999999999999999999999999999999999999", "a") except: diff --git a/tests/extmod/re_sub_unmatched.py.exp b/tests/extmod/re_sub_unmatched.py.exp deleted file mode 100644 index 1e5f0fda055..00000000000 --- a/tests/extmod/re_sub_unmatched.py.exp +++ /dev/null @@ -1 +0,0 @@ -1-a2 diff --git a/tests/extmod/socket_badconstructor.py b/tests/extmod/socket_badconstructor.py new file mode 100644 index 00000000000..4a9d2668c7f --- /dev/null +++ b/tests/extmod/socket_badconstructor.py @@ -0,0 +1,22 @@ +# Test passing in bad values to socket.socket constructor. + +try: + import socket +except: + print("SKIP") + raise SystemExit + +try: + s = socket.socket(None) +except TypeError: + print("TypeError") + +try: + s = socket.socket(socket.AF_INET, None) +except TypeError: + print("TypeError") + +try: + s = socket.socket(socket.AF_INET, socket.SOCK_RAW, None) +except TypeError: + print("TypeError") diff --git a/tests/extmod/socket_fileno.py b/tests/extmod/socket_fileno.py new file mode 100644 index 00000000000..da15825e3d5 --- /dev/null +++ b/tests/extmod/socket_fileno.py @@ -0,0 +1,17 @@ +# Test socket.fileno() functionality + +try: + import socket +except ImportError: + print("SKIP") + raise SystemExit + +if not hasattr(socket.socket, "fileno"): + print("SKIP") + raise SystemExit + +s = socket.socket() +print(s.fileno() >= 0) + +s.close() +print(s.fileno()) # should print -1 diff --git a/tests/extmod/time_mktime.py b/tests/extmod/time_mktime.py new file mode 100644 index 00000000000..7fc643dc3cb --- /dev/null +++ b/tests/extmod/time_mktime.py @@ -0,0 +1,120 @@ +# test conversion from date tuple to timestamp and back + +try: + import time + + time.localtime +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +# Range of date expected to work on all MicroPython platforms +MIN_YEAR = 1970 +MAX_YEAR = 2099 +# CPython properly supported date range: +# - on Windows: year 1970 to 3000+ +# - on Unix: year 1583 to 3000+ + +# Start test from Jan 1, 2001 13:00 (Feb 2000 might already be broken) +SAFE_DATE = (2001, 1, 1, 13, 0, 0, 0, 0, -1) + + +# mktime function that checks that the result is reversible +def safe_mktime(date_tuple): + try: + res = time.mktime(date_tuple) + chk = time.localtime(res) + except OverflowError: + print("safe_mktime:", date_tuple, "overflow error") + return None + if chk[0:5] != date_tuple[0:5]: + print("safe_mktime:", date_tuple[0:5], " -> ", res, " -> ", chk[0:5]) + return None + return res + + +# localtime function that checks that the result is reversible +def safe_localtime(timestamp): + try: + res = time.localtime(timestamp) + chk = time.mktime(res) + except OverflowError: + print("safe_localtime:", timestamp, "overflow error") + return None + if chk != timestamp: + print("safe_localtime:", timestamp, " -> ", res, " -> ", chk) + return None + return res + + +# look for smallest valid timestamps by iterating backwards on tuple +def test_bwd(date_tuple): + curr_stamp = safe_mktime(date_tuple) + year = date_tuple[0] + month = date_tuple[1] - 1 + if month < 1: + year -= 1 + month = 12 + while year >= MIN_YEAR: + while month >= 1: + next_tuple = (year, month) + date_tuple[2:] + next_stamp = safe_mktime(next_tuple) + # at this stage, only test consistency and monotonicity + if next_stamp is None or next_stamp >= curr_stamp: + return date_tuple + date_tuple = next_tuple + curr_stamp = next_stamp + month -= 1 + year -= 1 + month = 12 + return date_tuple + + +# test day-by-day to ensure that every date is properly converted +def test_fwd(start_date): + DAYS_PER_MONTH = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) + curr_stamp = safe_mktime(start_date) + curr_date = safe_localtime(curr_stamp) + while curr_date[0] <= MAX_YEAR: + if curr_date[2] < 15: + skip_days = 13 + else: + skip_days = 1 + next_stamp = curr_stamp + skip_days * 86400 + next_date = safe_localtime(next_stamp) + if next_date is None: + return curr_date + if next_date[2] != curr_date[2] + skip_days: + # next month + if next_date[2] != 1: + print("wrong day of month:", next_date) + return curr_date + # check the number of days in previous month + month_days = DAYS_PER_MONTH[curr_date[1]] + if month_days == 28 and curr_date[0] % 4 == 0: + if curr_date[0] % 100 != 0 or curr_date[0] % 400 == 0: + month_days += 1 + if curr_date[2] != month_days: + print("wrong day count in prev month:", curr_date[2], "vs", month_days) + return curr_date + if next_date[1] != curr_date[1] + 1: + # next year + if curr_date[1] != 12: + print("wrong month count in prev year:", curr_date[1]) + return curr_date + if next_date[1] != 1: + print("wrong month:", next_date) + return curr_date + if next_date[0] != curr_date[0] + 1: + print("wrong year:", next_date) + return curr_date + curr_stamp = next_stamp + curr_date = next_date + return curr_date + + +small_date = test_bwd(SAFE_DATE) +large_date = test_fwd(small_date) +print("tested from", small_date[0:3], "to", large_date[0:3]) +print(small_date[0:3], "wday is", small_date[6]) +print(large_date[0:3], "wday is", large_date[6]) diff --git a/tests/extmod/time_res.py b/tests/extmod/time_res.py index 548bef1f174..ef20050b914 100644 --- a/tests/extmod/time_res.py +++ b/tests/extmod/time_res.py @@ -37,9 +37,12 @@ def test(): time.sleep_ms(100) for func_name, _ in EXPECTED_MAP: try: - time_func = getattr(time, func_name, None) or globals()[func_name] + if func_name.endswith("_time"): + time_func = globals()[func_name] + else: + time_func = getattr(time, func_name) now = time_func() # may raise AttributeError - except (KeyError, AttributeError): + except AttributeError: continue try: results_map[func_name].add(now) diff --git a/tests/extmod/tls_dtls.py b/tests/extmod/tls_dtls.py index b2d716769d3..753ab2fee4f 100644 --- a/tests/extmod/tls_dtls.py +++ b/tests/extmod/tls_dtls.py @@ -34,9 +34,19 @@ def ioctl(self, req, arg): # Wrap the DTLS Server dtls_server_ctx = SSLContext(PROTOCOL_DTLS_SERVER) dtls_server_ctx.verify_mode = CERT_NONE -dtls_server = dtls_server_ctx.wrap_socket(server_socket, do_handshake_on_connect=False) +dtls_server = dtls_server_ctx.wrap_socket( + server_socket, do_handshake_on_connect=False, client_id=b"dummy_client_id" +) print("Wrapped DTLS Server") +# wrap DTLS server with invalid client_id +try: + dtls_server = dtls_server_ctx.wrap_socket( + server_socket, do_handshake_on_connect=False, client_id=4 + ) +except OSError: + print("Failed to wrap DTLS Server with invalid client_id") + # Wrap the DTLS Client dtls_client_ctx = SSLContext(PROTOCOL_DTLS_CLIENT) dtls_client_ctx.verify_mode = CERT_NONE diff --git a/tests/extmod/tls_dtls.py.exp b/tests/extmod/tls_dtls.py.exp index 78d72bff188..dbd005d0edf 100644 --- a/tests/extmod/tls_dtls.py.exp +++ b/tests/extmod/tls_dtls.py.exp @@ -1,3 +1,4 @@ Wrapped DTLS Server +Failed to wrap DTLS Server with invalid client_id Wrapped DTLS Client OK diff --git a/tests/extmod/ssl_noleak.py b/tests/extmod/tls_noleak.py similarity index 100% rename from tests/extmod/ssl_noleak.py rename to tests/extmod/tls_noleak.py diff --git a/tests/extmod/tls_threads.py b/tests/extmod/tls_threads.py new file mode 100644 index 00000000000..1e0c3d23d2f --- /dev/null +++ b/tests/extmod/tls_threads.py @@ -0,0 +1,58 @@ +# Ensure that SSL sockets can be allocated from multiple +# threads without thread safety issues + +try: + import _thread + import io + import tls + import time +except ImportError: + print("SKIP") + raise SystemExit + +import unittest + + +class TestSocket(io.IOBase): + def write(self, buf): + return len(buf) + + def readinto(self, buf): + return 0 + + def ioctl(self, cmd, arg): + return 0 + + def setblocking(self, value): + pass + + +ITERS = 256 + + +class TLSThreads(unittest.TestCase): + def test_sslsocket_threaded(self): + self.done = False + # only run in two threads: too much RAM demand otherwise, and rp2 only + # supports two anyhow + _thread.start_new_thread(self._alloc_many_sockets, (True,)) + self._alloc_many_sockets(False) + while not self.done: + time.sleep(0.1) + print("done") + + def _alloc_many_sockets(self, set_done_flag): + print("start", _thread.get_ident()) + ctx = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT) + ctx.verify_mode = tls.CERT_NONE + for n in range(ITERS): + s = TestSocket() + s = ctx.wrap_socket(s, do_handshake_on_connect=False) + s.close() # Free associated resources now from thread, not in a GC pass + print("done", _thread.get_ident()) + if set_done_flag: + self.done = True + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod/uctypes_addressof.py b/tests/extmod/uctypes_addressof.py index c83089d0f72..213fcc05eee 100644 --- a/tests/extmod/uctypes_addressof.py +++ b/tests/extmod/uctypes_addressof.py @@ -12,5 +12,8 @@ print(uctypes.addressof(uctypes.bytearray_at(1 << i, 8))) # Test address that is bigger than the greatest small-int but still within the address range. -large_addr = maxsize + 1 -print(uctypes.addressof(uctypes.bytearray_at(large_addr, 8)) == large_addr) +try: + large_addr = maxsize + 1 + print(uctypes.addressof(uctypes.bytearray_at(large_addr, 8)) == large_addr) +except OverflowError: + print(True) # systems with 64-bit bigints will overflow on the above operation diff --git a/tests/extmod/uctypes_array_load_store.py b/tests/extmod/uctypes_array_load_store.py index 9de07999856..695352da579 100644 --- a/tests/extmod/uctypes_array_load_store.py +++ b/tests/extmod/uctypes_array_load_store.py @@ -6,6 +6,13 @@ print("SKIP") raise SystemExit +# 'int' needs to be able to represent UINT64 for this test +try: + int("FF" * 8, 16) +except OverflowError: + print("SKIP") + raise SystemExit + N = 5 for endian in ("NATIVE", "LITTLE_ENDIAN", "BIG_ENDIAN"): diff --git a/tests/extmod/vfs_blockdev_invalid.py b/tests/extmod/vfs_blockdev_invalid.py index 4d00f4b0027..29d6bd6b2f9 100644 --- a/tests/extmod/vfs_blockdev_invalid.py +++ b/tests/extmod/vfs_blockdev_invalid.py @@ -70,8 +70,8 @@ def test(vfs_class): try: with fs.open("test", "r") as f: print("opened") - except OSError as e: - print("OSError", e) + except Exception as e: + print(type(e), e) # This variant should succeed on open, may fail on read # unless the filesystem cached the contents already @@ -81,8 +81,8 @@ def test(vfs_class): bdev.read_res = res print("read 1", f.read(1)) print("read rest", f.read()) - except OSError as e: - print("OSError", e) + except Exception as e: + print(type(e), e) test(vfs.VfsLfs2) diff --git a/tests/extmod/vfs_blockdev_invalid.py.exp b/tests/extmod/vfs_blockdev_invalid.py.exp index 13695e0d889..0ea0353501d 100644 --- a/tests/extmod/vfs_blockdev_invalid.py.exp +++ b/tests/extmod/vfs_blockdev_invalid.py.exp @@ -2,27 +2,27 @@ opened read 1 a read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -OSError [Errno 5] EIO + [Errno 5] EIO read 1 a read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -OSError [Errno 22] EINVAL + [Errno 22] EINVAL read 1 a read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -OSError [Errno 22] EINVAL + [Errno 22] EINVAL read 1 a read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -OSError [Errno 22] EINVAL + can't convert str to int read 1 a read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa opened read 1 a read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -OSError [Errno 5] EIO -OSError [Errno 5] EIO -OSError [Errno 5] EIO -OSError [Errno 5] EIO -OSError [Errno 5] EIO -OSError [Errno 5] EIO -OSError [Errno 5] EIO -OSError [Errno 5] EIO + [Errno 5] EIO + [Errno 5] EIO + [Errno 5] EIO + [Errno 5] EIO + [Errno 5] EIO + [Errno 5] EIO + can't convert str to int + can't convert str to int diff --git a/tests/extmod/vfs_fat_ilistdir_del.py b/tests/extmod/vfs_fat_ilistdir_del.py index a6e24ec92f3..964e6b12868 100644 --- a/tests/extmod/vfs_fat_ilistdir_del.py +++ b/tests/extmod/vfs_fat_ilistdir_del.py @@ -1,8 +1,7 @@ # Test ilistdir __del__ for VfsFat using a RAM device. -import gc try: - import os, vfs + import gc, os, vfs vfs.VfsFat except (ImportError, AttributeError): diff --git a/tests/extmod/vfs_lfs.py b/tests/extmod/vfs_lfs.py index 3ad57fd9c38..40d58e9c9f7 100644 --- a/tests/extmod/vfs_lfs.py +++ b/tests/extmod/vfs_lfs.py @@ -136,7 +136,7 @@ def test(bdev, vfs_class): print(fs.getcwd()) fs.chdir("../testdir") print(fs.getcwd()) - fs.chdir("../..") + fs.chdir("..") print(fs.getcwd()) fs.chdir(".//testdir") print(fs.getcwd()) diff --git a/tests/extmod/vfs_lfs_error.py b/tests/extmod/vfs_lfs_error.py index 2ac7629bfa8..73cdf343733 100644 --- a/tests/extmod/vfs_lfs_error.py +++ b/tests/extmod/vfs_lfs_error.py @@ -1,7 +1,7 @@ # Test for VfsLittle using a RAM device, testing error handling try: - import vfs + import errno, vfs vfs.VfsLfs1 vfs.VfsLfs2 @@ -41,14 +41,14 @@ def test(bdev, vfs_class): # mkfs with too-small block device try: vfs_class.mkfs(RAMBlockDevice(1)) - except OSError: - print("mkfs OSError") + except OSError as er: + print("mkfs OSError", er.errno > 0) # mount with invalid filesystem try: vfs_class(bdev) - except OSError: - print("mount OSError") + except OSError as er: + print("mount OSError", er.errno > 0) # set up for following tests vfs_class.mkfs(bdev) @@ -60,60 +60,60 @@ def test(bdev, vfs_class): # ilistdir try: fs.ilistdir("noexist") - except OSError: - print("ilistdir OSError") + except OSError as er: + print("ilistdir OSError", er) # remove try: fs.remove("noexist") - except OSError: - print("remove OSError") + except OSError as er: + print("remove OSError", er) # rmdir try: fs.rmdir("noexist") - except OSError: - print("rmdir OSError") + except OSError as er: + print("rmdir OSError", er) # rename try: fs.rename("noexist", "somethingelse") - except OSError: - print("rename OSError") + except OSError as er: + print("rename OSError", er) # mkdir try: fs.mkdir("testdir") - except OSError: - print("mkdir OSError") + except OSError as er: + print("mkdir OSError", er) # chdir to nonexistent try: fs.chdir("noexist") - except OSError: - print("chdir OSError") + except OSError as er: + print("chdir OSError", er) print(fs.getcwd()) # check still at root # chdir to file try: fs.chdir("testfile") - except OSError: - print("chdir OSError") + except OSError as er: + print("chdir OSError", er) print(fs.getcwd()) # check still at root # stat try: fs.stat("noexist") - except OSError: - print("stat OSError") + except OSError as er: + print("stat OSError", er) # error during seek with fs.open("testfile", "r") as f: f.seek(1 << 30) # SEEK_SET try: f.seek(1 << 30, 1) # SEEK_CUR - except OSError: - print("seek OSError") + except OSError as er: + print("seek OSError", er) bdev = RAMBlockDevice(30) diff --git a/tests/extmod/vfs_lfs_error.py.exp b/tests/extmod/vfs_lfs_error.py.exp index f4327f6962e..440607ed84b 100644 --- a/tests/extmod/vfs_lfs_error.py.exp +++ b/tests/extmod/vfs_lfs_error.py.exp @@ -1,28 +1,28 @@ test -mkfs OSError -mount OSError -ilistdir OSError -remove OSError -rmdir OSError -rename OSError -mkdir OSError -chdir OSError +mkfs OSError True +mount OSError True +ilistdir OSError [Errno 2] ENOENT +remove OSError [Errno 2] ENOENT +rmdir OSError [Errno 2] ENOENT +rename OSError [Errno 2] ENOENT +mkdir OSError [Errno 17] EEXIST +chdir OSError [Errno 2] ENOENT / -chdir OSError +chdir OSError [Errno 2] ENOENT / -stat OSError -seek OSError +stat OSError [Errno 2] ENOENT +seek OSError [Errno 22] EINVAL test -mkfs OSError -mount OSError -ilistdir OSError -remove OSError -rmdir OSError -rename OSError -mkdir OSError -chdir OSError +mkfs OSError True +mount OSError True +ilistdir OSError [Errno 2] ENOENT +remove OSError [Errno 2] ENOENT +rmdir OSError [Errno 2] ENOENT +rename OSError [Errno 2] ENOENT +mkdir OSError [Errno 17] EEXIST +chdir OSError [Errno 2] ENOENT / -chdir OSError +chdir OSError [Errno 2] ENOENT / -stat OSError -seek OSError +stat OSError [Errno 2] ENOENT +seek OSError [Errno 22] EINVAL diff --git a/tests/extmod/vfs_lfs_ilistdir_del.py b/tests/extmod/vfs_lfs_ilistdir_del.py index 7b59bc412d9..828c85a2588 100644 --- a/tests/extmod/vfs_lfs_ilistdir_del.py +++ b/tests/extmod/vfs_lfs_ilistdir_del.py @@ -1,8 +1,7 @@ # Test ilistdir __del__ for VfsLittle using a RAM device. -import gc try: - import vfs + import gc, vfs vfs.VfsLfs2 except (ImportError, AttributeError): @@ -71,5 +70,10 @@ def test(bdev, vfs_class): fs.open("/test", "w").close() -bdev = RAMBlockDevice(30) +try: + bdev = RAMBlockDevice(30) +except MemoryError: + print("SKIP") + raise SystemExit + test(bdev, vfs.VfsLfs2) diff --git a/tests/extmod/vfs_mountinfo.py b/tests/extmod/vfs_mountinfo.py index f674e807634..b31dc60ce76 100644 --- a/tests/extmod/vfs_mountinfo.py +++ b/tests/extmod/vfs_mountinfo.py @@ -5,7 +5,6 @@ except ImportError: print("SKIP") raise SystemExit -import errno class Filesystem: diff --git a/tests/extmod/vfs_posix.py b/tests/extmod/vfs_posix.py index d060c0b9c84..b3ca2753ba9 100644 --- a/tests/extmod/vfs_posix.py +++ b/tests/extmod/vfs_posix.py @@ -29,7 +29,21 @@ print(type(os.stat("/"))) # listdir and ilistdir -print(type(os.listdir("/"))) +target = "/" +try: + import platform + + # On Android non-root users are permitted full filesystem access only to + # selected directories. To let this test pass on bionic, the internal + # user-accessible storage area root is enumerated instead of the + # filesystem root. "/storage/emulated/0" should be there on pretty much + # any recent-ish device; querying the proper location requires a JNI + # round-trip, not really worth it. + if platform.platform().startswith("Android-"): + target = "/storage/emulated/0" +except ImportError: + pass +print(type(os.listdir(target))) # mkdir os.mkdir(temp_dir) diff --git a/tests/extmod/vfs_posix_ilistdir_del.py b/tests/extmod/vfs_posix_ilistdir_del.py index 78d7c854c54..8b5984cd81c 100644 --- a/tests/extmod/vfs_posix_ilistdir_del.py +++ b/tests/extmod/vfs_posix_ilistdir_del.py @@ -1,8 +1,7 @@ # Test ilistdir __del__ for VfsPosix. -import gc try: - import os, vfs + import gc, os, vfs vfs.VfsPosix except (ImportError, AttributeError): diff --git a/tests/extmod/vfs_posix_paths.py b/tests/extmod/vfs_posix_paths.py index b4fedc6716f..c06318748a3 100644 --- a/tests/extmod/vfs_posix_paths.py +++ b/tests/extmod/vfs_posix_paths.py @@ -31,7 +31,7 @@ fs.mkdir("subdir/one") print('listdir("/"):', sorted(i[0] for i in fs.ilistdir("/"))) print('listdir("."):', sorted(i[0] for i in fs.ilistdir("."))) -print('getcwd() in {"", "/"}:', fs.getcwd() in {"", "/"}) +print('getcwd() in ("", "/"):', fs.getcwd() in ("", "/")) print('chdir("subdir"):', fs.chdir("subdir")) print("getcwd():", fs.getcwd()) print('mkdir("two"):', fs.mkdir("two")) diff --git a/tests/extmod/vfs_posix_paths.py.exp b/tests/extmod/vfs_posix_paths.py.exp index ecc13222aaa..d6a0960efd2 100644 --- a/tests/extmod/vfs_posix_paths.py.exp +++ b/tests/extmod/vfs_posix_paths.py.exp @@ -1,6 +1,6 @@ listdir("/"): ['subdir'] listdir("."): ['subdir'] -getcwd() in {"", "/"}: True +getcwd() in ("", "/"): True chdir("subdir"): None getcwd(): /subdir mkdir("two"): None diff --git a/tests/extmod/vfs_posix_readonly.py b/tests/extmod/vfs_posix_readonly.py new file mode 100644 index 00000000000..e7821381006 --- /dev/null +++ b/tests/extmod/vfs_posix_readonly.py @@ -0,0 +1,99 @@ +# Test for VfsPosix + +try: + import gc, os, vfs, errno + + vfs.VfsPosix +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +# We need a directory for testing that doesn't already exist. +# Skip the test if it does exist. +temp_dir = "vfs_posix_readonly_test_dir" +try: + os.stat(temp_dir) + raise SystemExit("Target directory {} exists".format(temp_dir)) +except OSError: + pass + +# mkdir (skip test if whole filesystem is readonly) +try: + os.mkdir(temp_dir) +except OSError as e: + if e.errno == errno.EROFS: + print("SKIP") + raise SystemExit + +fs_factory = lambda: vfs.VfsPosix(temp_dir) + +# mount +fs = fs_factory() +vfs.mount(fs, "/vfs") + +with open("/vfs/file", "w") as f: + f.write("content") + +# test reading works +with open("/vfs/file") as f: + print("file:", f.read()) + +os.mkdir("/vfs/emptydir") + +# umount +vfs.umount("/vfs") + +# mount read-only +fs = fs_factory() +vfs.mount(fs, "/vfs", readonly=True) + +# test reading works +with open("/vfs/file") as f: + print("file 2:", f.read()) + +# test writing fails +try: + with open("/vfs/test_write", "w"): + pass + print("opened") +except OSError as er: + print(repr(er)) + +# test removing fails +try: + os.unlink("/vfs/file") + print("unlinked") +except OSError as er: + print(repr(er)) + +# test renaming fails +try: + os.rename("/vfs/file2", "/vfs/renamed") + print("renamed") +except OSError as er: + print(repr(er)) + +# test removing directory fails +try: + os.rmdir("/vfs/emptydir") + print("rmdir'd") +except OSError as er: + print(repr(er)) + +# test creating directory fails +try: + os.mkdir("/vfs/emptydir2") + print("mkdir'd") +except OSError as er: + print(repr(er)) + +# umount +vfs.umount("/vfs") + +fs = fs_factory() +vfs.mount(fs, "/vfs") + +os.rmdir("/vfs/emptydir") +os.unlink("/vfs/file") + +os.rmdir(temp_dir) diff --git a/tests/extmod/vfs_posix_readonly.py.exp b/tests/extmod/vfs_posix_readonly.py.exp new file mode 100644 index 00000000000..40e4316775f --- /dev/null +++ b/tests/extmod/vfs_posix_readonly.py.exp @@ -0,0 +1,7 @@ +file: content +file 2: content +OSError(30,) +OSError(30,) +OSError(30,) +OSError(30,) +OSError(30,) diff --git a/tests/extmod/vfs_rom.py b/tests/extmod/vfs_rom.py index 770b6863b9c..18ae1f5cf96 100644 --- a/tests/extmod/vfs_rom.py +++ b/tests/extmod/vfs_rom.py @@ -25,7 +25,7 @@ # An mpy file with four constant objects: str, bytes, long-int, float. test_mpy = ( # header - b"M\x06\x00\x1f" # mpy file header + b"M\x06\x00\x1e" # mpy file header, -msmall-int-bits=30 b"\x06" # n_qstr b"\x05" # n_obj # qstrs @@ -394,6 +394,7 @@ class TestMounted(TestBase): def setUp(self): self.orig_sys_path = list(sys.path) self.orig_cwd = os.getcwd() + sys.path = [] vfs.mount(vfs.VfsRom(self.romfs), "/test_rom") def tearDown(self): diff --git a/tests/extmod/websocket_toobig.py b/tests/extmod/websocket_toobig.py new file mode 100644 index 00000000000..f4c5a74bbce --- /dev/null +++ b/tests/extmod/websocket_toobig.py @@ -0,0 +1,28 @@ +try: + import io + import errno + import websocket +except ImportError: + print("SKIP") + raise SystemExit + +try: + buf = "x" * 65536 +except MemoryError: + print("SKIP") + raise SystemExit + + +# do a websocket write and then return the raw data from the stream +def ws_write(msg, sz): + s = io.BytesIO() + ws = websocket.websocket(s) + ws.write(msg) + s.seek(0) + return s.read(sz) + + +try: + print(ws_write(buf, 1)) +except OSError as e: + print("ioctl: ENOBUFS:", e.errno == errno.ENOBUFS) diff --git a/tests/extmod/websocket_toobig.py.exp b/tests/extmod/websocket_toobig.py.exp new file mode 100644 index 00000000000..3bbd95282fd --- /dev/null +++ b/tests/extmod/websocket_toobig.py.exp @@ -0,0 +1 @@ +ioctl: ENOBUFS: True diff --git a/tests/extmod_hardware/machine_counter.py b/tests/extmod_hardware/machine_counter.py new file mode 100644 index 00000000000..62ac1fed47c --- /dev/null +++ b/tests/extmod_hardware/machine_counter.py @@ -0,0 +1,90 @@ +# Test machine.Counter implementation +# +# IMPORTANT: This test requires hardware connections: the out_pin and in_pin +# must be wired together. + +try: + from machine import Counter +except ImportError: + print("SKIP") + raise SystemExit + +import sys +from machine import Pin + +if "esp32" in sys.platform: + id = 0 + out_pin = 4 + in_pin = 5 +else: + print("Please add support for this test on this platform.") + raise SystemExit + +import unittest + +out_pin = Pin(out_pin, mode=Pin.OUT) +in_pin = Pin(in_pin, mode=Pin.IN) + + +def toggle(times): + for _ in range(times): + out_pin(1) + out_pin(0) + + +class TestCounter(unittest.TestCase): + def setUp(self): + out_pin(0) + self.counter = Counter(id, in_pin) + + def tearDown(self): + self.counter.deinit() + + def assertCounter(self, value): + self.assertEqual(self.counter.value(), value) + + def test_connections(self): + # Test the hardware connections are correct. If this test fails, all tests will fail. + out_pin(1) + self.assertEqual(1, in_pin()) + out_pin(0) + self.assertEqual(0, in_pin()) + + def test_count_rising(self): + self.assertCounter(0) + toggle(100) + self.assertCounter(100) + out_pin(1) + self.assertEqual(self.counter.value(0), 101) + self.assertCounter(0) # calling value(0) resets + out_pin(0) + self.assertCounter(0) # no rising edge + out_pin(1) + self.assertCounter(1) + + def test_change_directions(self): + self.assertCounter(0) + toggle(100) + self.assertCounter(100) + self.counter.init(in_pin, direction=Counter.DOWN) + self.assertCounter(0) # calling init() zeroes the counter + self.counter.value(100) # need to manually reset the value + self.assertCounter(100) + toggle(25) + self.assertCounter(75) + + def test_count_falling(self): + self.counter.init(in_pin, direction=Counter.UP, edge=Counter.FALLING) + toggle(20) + self.assertCounter(20) + out_pin(1) + self.assertCounter(20) # no falling edge + out_pin(0) + self.assertCounter(21) + self.counter.value(-(2**24)) + toggle(20) + self.assertCounter(-(2**24 - 20)) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod_hardware/machine_encoder.py b/tests/extmod_hardware/machine_encoder.py new file mode 100644 index 00000000000..c218c8bfb64 --- /dev/null +++ b/tests/extmod_hardware/machine_encoder.py @@ -0,0 +1,153 @@ +# Test machine.Encoder implementation +# +# IMPORTANT: This test requires hardware connections: +# - out0_pin and in0_pin must be wired together. +# - out1_pin and in1_pin must be wired together. + +try: + from machine import Encoder +except ImportError: + print("SKIP") + raise SystemExit + +import sys +import unittest +from machine import Pin +from target_wiring import encoder_loopback_id, encoder_loopback_out_pins, encoder_loopback_in_pins + +PRINT = False +PIN_INIT_VALUE = 1 + +id = encoder_loopback_id +out0_pin, out1_pin = encoder_loopback_out_pins +in0_pin, in1_pin = encoder_loopback_in_pins + +out0_pin = Pin(out0_pin, mode=Pin.OUT) +in0_pin = Pin(in0_pin, mode=Pin.IN) +out1_pin = Pin(out1_pin, mode=Pin.OUT) +in1_pin = Pin(in1_pin, mode=Pin.IN) + + +class TestEncoder(unittest.TestCase): + def setUp(self): + out0_pin(PIN_INIT_VALUE) + out1_pin(PIN_INIT_VALUE) + self.enc = Encoder(id, in0_pin, in1_pin, phases=1) + self.enc2 = Encoder(id + 1, in0_pin, in1_pin, phases=2) + self.enc4 = Encoder(id + 2, in0_pin, in1_pin, phases=4) + self.pulses = 0 # track the expected encoder position in software + if PRINT: + print( + "\nout0_pin() out1_pin() enc.value() enc2.value() enc4.value() |", + out0_pin(), + out1_pin(), + "|", + self.enc.value(), + self.enc2.value(), + self.enc4.value(), + ) + + def tearDown(self): + self.enc.deinit() + try: + self.enc2.deinit() + except: + pass + try: + self.enc4.deinit() + except: + pass + + def rotate(self, pulses): + for _ in range(abs(pulses)): + self.pulses += 1 if (pulses > 0) else -1 + if pulses > 0: + if self.pulses % 2: + out0_pin(not out0_pin()) + else: + out1_pin(not out1_pin()) + else: + if self.pulses % 2: + out1_pin(not out1_pin()) + else: + out0_pin(not out0_pin()) + if PRINT: + print( + "out0_pin() out1_pin() enc.value() enc2.value() enc4.value() pulses self.pulses |", + out0_pin(), + out1_pin(), + "|", + self.enc.value(), + self.enc2.value(), + self.enc4.value(), + "|", + pulses, + self.pulses, + ) + + def assertPosition(self, value, value2=None, value4=None): + self.assertEqual(self.enc.value(), value) + if not value2 is None: + self.assertEqual(self.enc2.value(), value2) + if not value4 is None: + self.assertEqual(self.enc4.value(), value4) + pass + + @unittest.skipIf(sys.platform == "mimxrt", "cannot read back the pin") + def test_connections(self): + # Test the hardware connections are correct. If this test fails, all tests will fail. + for ch, outp, inp in ((0, out0_pin, in0_pin), (1, out1_pin, in1_pin)): + print("Testing channel ", ch) + outp(1) + self.assertEqual(1, inp()) + outp(0) + self.assertEqual(0, inp()) + + def test_basics(self): + self.assertPosition(0) + self.rotate(100) + self.assertPosition(100 // 4, 100 // 2, 100) + self.rotate(-100) + self.assertPosition(0) + + def test_partial(self): + # With phase=1 (default), need 4x pulses to count a rotation + self.assertPosition(0) + self.rotate(1) + self.assertPosition(1, 1, 1) + self.rotate(1) + self.assertPosition(1, 1, 2) + self.rotate(1) + self.assertPosition(1, 2, 3) + self.rotate(1) + self.assertPosition(1, 2, 4) # +4 + self.rotate(1) + self.assertPosition(2, 3, 5) + self.rotate(1) + self.assertPosition(2, 3, 6) + self.rotate(1) + self.assertPosition(2, 4, 7) + self.rotate(1) + self.assertPosition(2, 4, 8) # +4 + self.rotate(-1) + self.assertPosition(2, 4, 7) + self.rotate(-3) + self.assertPosition(1, 2, 4) # -4 + self.rotate(-4) + self.assertPosition(0, 0, 0) # -4 + self.rotate(-1) + self.assertPosition(0, 0, -1) + self.rotate(-1) + self.assertPosition(0, -1, -2) + self.rotate(-1) + self.assertPosition(0, -1, -3) + self.rotate(-1) + self.assertPosition(-1, -2, -4) # -4 + self.rotate(-1) + self.assertPosition(-1, -2, -5) + self.rotate(-3) + self.assertPosition(-2, -4, -8) # -4 + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod_hardware/machine_i2c_target.py b/tests/extmod_hardware/machine_i2c_target.py new file mode 100644 index 00000000000..763e6f4771e --- /dev/null +++ b/tests/extmod_hardware/machine_i2c_target.py @@ -0,0 +1,307 @@ +# Test machine.I2CTarget. +# +# IMPORTANT: This test requires hardware connections: a SoftI2C instance must be +# wired to a hardware I2C target. See pin definitions below. + +import sys + +try: + from machine import Pin, SoftI2C, I2CTarget +except ImportError: + print("SKIP") + raise SystemExit + +import unittest + +ADDR = 67 + +kwargs_target = {} + +# Configure pins based on the target. +if sys.platform == "alif" and sys.implementation._build == "ALIF_ENSEMBLE": + args_controller = {"scl": "P1_1", "sda": "P1_0"} + args_target = (0,) # on pins P0_3/P0_2 +elif sys.platform == "esp32": + args_controller = {"scl": 5, "sda": 6} + args_target = (0,) # on pins 9/8 for C3 and S3, 18/19 for others + kwargs_target = {"scl": 9, "sda": 8} +elif sys.platform == "rp2": + args_controller = {"scl": 5, "sda": 4} + args_target = (1,) +elif sys.platform == "pyboard": + if sys.implementation._build == "NUCLEO_WB55": + args_controller = {"scl": "B8", "sda": "B9"} + args_target = (3,) + else: + args_controller = {"scl": "X1", "sda": "X2"} + args_target = ("X",) +elif "zephyr-nucleo_wb55rg" in sys.implementation._machine: + # PB8=I2C1_SCL, PB9=I2C1_SDA (on Arduino header D15/D14) + # PC0=I2C3_SCL, PC1=I2C3_SDA (on Arduino header A0/A1) + args_controller = {"scl": Pin(("gpiob", 8)), "sda": Pin(("gpiob", 9))} + args_target = ("i2c3",) +elif "zephyr-rpi_pico" in sys.implementation._machine: + args_controller = {"scl": Pin(("gpio0", 5)), "sda": Pin(("gpio0", 4))} + args_target = ("i2c1",) # on gpio7/gpio6 +elif sys.platform == "mimxrt": + if "Teensy" in sys.implementation._machine: + args_controller = {"scl": "A6", "sda": "A3"} # D20/D17 + else: + args_controller = {"scl": "D0", "sda": "D1"} + args_target = (0,) # pins 19/18 On Teensy 4.x +elif sys.platform == "samd": + args_controller = {"scl": "D5", "sda": "D1"} + args_target = () +else: + print("Please add support for this test on this platform.") + raise SystemExit + + +def config_pull_up(): + Pin(args_controller["scl"], Pin.OPEN_DRAIN, Pin.PULL_UP) + Pin(args_controller["sda"], Pin.OPEN_DRAIN, Pin.PULL_UP) + + +class TestMemory(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.mem = bytearray(8) + cls.i2c = SoftI2C(**args_controller) + cls.i2c_target = I2CTarget(*args_target, **kwargs_target, addr=ADDR, mem=cls.mem) + config_pull_up() + + @classmethod + def tearDownClass(cls): + cls.i2c_target.deinit() + + def test_scan(self): + self.assertIn(ADDR, self.i2c.scan()) + + def test_write(self): + self.mem[:] = b"01234567" + self.i2c.writeto_mem(ADDR, 0, b"test") + self.assertEqual(self.mem, bytearray(b"test4567")) + self.i2c.writeto_mem(ADDR, 4, b"TEST") + self.assertEqual(self.mem, bytearray(b"testTEST")) + + def test_write_wrap(self): + self.mem[:] = b"01234567" + self.i2c.writeto_mem(ADDR, 6, b"test") + self.assertEqual(self.mem, bytearray(b"st2345te")) + + @unittest.skipIf(sys.platform == "esp32", "write lengths larger than buffer unsupported") + def test_write_wrap_large(self): + self.mem[:] = b"01234567" + self.i2c.writeto_mem(ADDR, 0, b"testTESTmore") + self.assertEqual(self.mem, bytearray(b"moreTEST")) + + def test_read(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.readfrom_mem(ADDR, 0, 4), b"0123") + self.assertEqual(self.i2c.readfrom_mem(ADDR, 4, 4), b"4567") + + def test_read_wrap(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.readfrom_mem(ADDR, 0, 4), b"0123") + self.assertEqual(self.i2c.readfrom_mem(ADDR, 2, 4), b"2345") + self.assertEqual(self.i2c.readfrom_mem(ADDR, 6, 4), b"6701") + + @unittest.skipIf(sys.platform == "esp32", "read lengths larger than buffer unsupported") + def test_read_wrap_large(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.readfrom_mem(ADDR, 0, 12), b"012345670123") + + def test_write_read(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.writeto(ADDR, b"\x02"), 1) + self.assertEqual(self.i2c.readfrom(ADDR, 4), b"2345") + + @unittest.skipIf(sys.platform == "esp32", "read after read unsupported") + def test_write_read_read(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.writeto(ADDR, b"\x02"), 1) + self.assertEqual(self.i2c.readfrom(ADDR, 4), b"2345") + self.assertEqual(self.i2c.readfrom(ADDR, 4), b"7012") + + +@unittest.skipUnless(hasattr(I2CTarget, "IRQ_END_READ"), "IRQ unsupported") +class TestMemoryIRQ(unittest.TestCase): + @staticmethod + def irq_handler(i2c_target): + flags = i2c_target.irq().flags() + TestMemoryIRQ.events[TestMemoryIRQ.num_events] = flags + TestMemoryIRQ.events[TestMemoryIRQ.num_events + 1] = i2c_target.memaddr + TestMemoryIRQ.num_events += 2 + + @classmethod + def setUpClass(cls): + cls.mem = bytearray(8) + cls.events = [0] * 8 + cls.num_events = 0 + cls.i2c = SoftI2C(**args_controller) + cls.i2c_target = I2CTarget(*args_target, **kwargs_target, addr=ADDR, mem=cls.mem) + cls.i2c_target.irq(TestMemoryIRQ.irq_handler) + config_pull_up() + + @classmethod + def tearDownClass(cls): + cls.i2c_target.deinit() + + @unittest.skipIf(sys.platform == "esp32", "scan doesn't trigger IRQ_END_WRITE") + def test_scan(self): + TestMemoryIRQ.num_events = 0 + self.i2c.scan() + self.assertEqual(self.events[: self.num_events], [I2CTarget.IRQ_END_WRITE, 0]) + + def test_write(self): + TestMemoryIRQ.num_events = 0 + self.mem[:] = b"01234567" + self.i2c.writeto_mem(ADDR, 2, b"test") + self.assertEqual(self.mem, bytearray(b"01test67")) + self.assertEqual(self.events[: self.num_events], [I2CTarget.IRQ_END_WRITE, 2]) + + def test_read(self): + TestMemoryIRQ.num_events = 0 + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.readfrom_mem(ADDR, 2, 4), b"2345") + self.assertEqual(self.events[: self.num_events], [I2CTarget.IRQ_END_READ, 2]) + + +@unittest.skipUnless(hasattr(I2CTarget, "IRQ_WRITE_REQ"), "IRQ unsupported") +@unittest.skipIf(sys.platform == "mimxrt", "not working") +@unittest.skipIf(sys.platform == "pyboard", "can't queue more than one byte") +@unittest.skipIf(sys.platform == "samd", "not working") +@unittest.skipIf(sys.platform == "zephyr", "must call readinto/write in IRQ handler") +class TestPolling(unittest.TestCase): + @staticmethod + def irq_handler(i2c_target, buf=bytearray(1)): + flags = i2c_target.irq().flags() + if flags & I2CTarget.IRQ_READ_REQ: + i2c_target.write(b"0123") + + @classmethod + def setUpClass(cls): + cls.i2c = SoftI2C(**args_controller) + cls.i2c_target = I2CTarget(*args_target, addr=ADDR) + cls.i2c_target.irq( + TestPolling.irq_handler, + I2CTarget.IRQ_WRITE_REQ | I2CTarget.IRQ_READ_REQ, + hard=True, + ) + config_pull_up() + + @classmethod + def tearDownClass(cls): + cls.i2c_target.deinit() + + def test_read(self): + # Can't write data up front, must wait until IRQ_READ_REQ. + # self.assertEqual(self.i2c_target.write(b"abcd"), 4) + self.assertEqual(self.i2c.readfrom(ADDR, 4), b"0123") + + def test_write(self): + # Can do the read outside the IRQ, but requires IRQ_WRITE_REQ trigger to be set. + self.assertEqual(self.i2c.writeto(ADDR, b"0123"), 4) + buf = bytearray(8) + self.assertEqual(self.i2c_target.readinto(buf), 4) + self.assertEqual(buf, b"0123\x00\x00\x00\x00") + + +@unittest.skipUnless(hasattr(I2CTarget, "IRQ_ADDR_MATCH_READ"), "IRQ unsupported") +class TestIRQ(unittest.TestCase): + @staticmethod + def irq_handler(i2c_target, buf=bytearray(1)): + flags = i2c_target.irq().flags() + TestIRQ.events[TestIRQ.num_events] = flags + TestIRQ.num_events += 1 + if flags & I2CTarget.IRQ_READ_REQ: + i2c_target.write(b"Y") + if flags & I2CTarget.IRQ_WRITE_REQ: + i2c_target.readinto(buf) + TestIRQ.events[TestIRQ.num_events] = buf[0] + TestIRQ.num_events += 1 + + @classmethod + def setUpClass(cls): + cls.events = [0] * 8 + cls.num_events = 0 + cls.i2c = SoftI2C(**args_controller) + cls.i2c_target = I2CTarget(*args_target, addr=ADDR) + cls.i2c_target.irq( + TestIRQ.irq_handler, + I2CTarget.IRQ_ADDR_MATCH_READ + | I2CTarget.IRQ_ADDR_MATCH_WRITE + | I2CTarget.IRQ_WRITE_REQ + | I2CTarget.IRQ_READ_REQ + | I2CTarget.IRQ_END_READ + | I2CTarget.IRQ_END_WRITE, + hard=True, + ) + config_pull_up() + + @classmethod + def tearDownClass(cls): + cls.i2c_target.deinit() + + def test_scan(self): + TestIRQ.num_events = 0 + self.i2c.scan() + self.assertEqual( + self.events[: self.num_events], + [ + I2CTarget.IRQ_ADDR_MATCH_WRITE, + I2CTarget.IRQ_END_WRITE, + ], + ) + + def test_write(self): + TestIRQ.num_events = 0 + self.i2c.writeto(ADDR, b"XYZ") + self.assertEqual( + self.events[: self.num_events], + [ + I2CTarget.IRQ_ADDR_MATCH_WRITE, + I2CTarget.IRQ_WRITE_REQ, + ord(b"X"), + I2CTarget.IRQ_WRITE_REQ, + ord(b"Y"), + I2CTarget.IRQ_WRITE_REQ, + ord(b"Z"), + I2CTarget.IRQ_END_WRITE, + ], + ) + + def test_read(self): + TestIRQ.num_events = 0 + self.assertEqual(self.i2c.readfrom(ADDR, 1), b"Y") + self.assertEqual( + self.events[: self.num_events], + [ + I2CTarget.IRQ_ADDR_MATCH_READ, + I2CTarget.IRQ_READ_REQ, + I2CTarget.IRQ_READ_REQ, + I2CTarget.IRQ_END_READ, + ], + ) + + def test_write_read(self): + TestIRQ.num_events = 0 + self.i2c.writeto(ADDR, b"X", False) + self.assertEqual(self.i2c.readfrom(ADDR, 1), b"Y") + self.assertEqual( + self.events[: self.num_events], + [ + I2CTarget.IRQ_ADDR_MATCH_WRITE, + I2CTarget.IRQ_WRITE_REQ, + ord(b"X"), + I2CTarget.IRQ_END_WRITE, + I2CTarget.IRQ_ADDR_MATCH_READ, + I2CTarget.IRQ_READ_REQ, + I2CTarget.IRQ_READ_REQ, + I2CTarget.IRQ_END_READ, + ], + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/feature_check/float.py b/tests/feature_check/float.py deleted file mode 100644 index d6d2a99d242..00000000000 --- a/tests/feature_check/float.py +++ /dev/null @@ -1,13 +0,0 @@ -# detect how many bits of precision the floating point implementation has - -try: - float -except NameError: - print(0) -else: - if float("1.0000001") == float("1.0"): - print(30) - elif float("1e300") == float("inf"): - print(32) - else: - print(64) diff --git a/tests/feature_check/float.py.exp b/tests/feature_check/float.py.exp deleted file mode 100644 index 900731ffd51..00000000000 --- a/tests/feature_check/float.py.exp +++ /dev/null @@ -1 +0,0 @@ -64 diff --git a/tests/feature_check/inlineasm_rv32_zba.py b/tests/feature_check/inlineasm_rv32_zba.py new file mode 100644 index 00000000000..81228819042 --- /dev/null +++ b/tests/feature_check/inlineasm_rv32_zba.py @@ -0,0 +1,10 @@ +# check if RISC-V 32 inline asm supported Zba opcodes + + +@micropython.asm_rv32 +def f(): + sh1add(a0, a0, a0) + + +f() +print("rv32_zba") diff --git a/tests/feature_check/inlineasm_rv32_zba.py.exp b/tests/feature_check/inlineasm_rv32_zba.py.exp new file mode 100644 index 00000000000..fde22f5f400 --- /dev/null +++ b/tests/feature_check/inlineasm_rv32_zba.py.exp @@ -0,0 +1 @@ +rv32_zba diff --git a/tests/feature_check/int_64.py b/tests/feature_check/int_64.py new file mode 100644 index 00000000000..4d053782ca8 --- /dev/null +++ b/tests/feature_check/int_64.py @@ -0,0 +1,2 @@ +# Check whether 64-bit long integers are supported +print(1 << 62) diff --git a/tests/feature_check/int_64.py.exp b/tests/feature_check/int_64.py.exp new file mode 100644 index 00000000000..aef5454e662 --- /dev/null +++ b/tests/feature_check/int_64.py.exp @@ -0,0 +1 @@ +4611686018427387904 diff --git a/tests/feature_check/io_module.py b/tests/feature_check/io_module.py deleted file mode 100644 index 9094e605316..00000000000 --- a/tests/feature_check/io_module.py +++ /dev/null @@ -1,6 +0,0 @@ -try: - import io - - print("io") -except ImportError: - print("no") diff --git a/tests/feature_check/repl_emacs_check.py.exp b/tests/feature_check/repl_emacs_check.py.exp index 82a4e28ee4f..5fe8ba1cd2d 100644 --- a/tests/feature_check/repl_emacs_check.py.exp +++ b/tests/feature_check/repl_emacs_check.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # Check for emacs keys in REPL >>> t = \.\+ >>> t == 2 diff --git a/tests/feature_check/repl_words_move_check.py.exp b/tests/feature_check/repl_words_move_check.py.exp index 82a4e28ee4f..5fe8ba1cd2d 100644 --- a/tests/feature_check/repl_words_move_check.py.exp +++ b/tests/feature_check/repl_words_move_check.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # Check for emacs keys in REPL >>> t = \.\+ >>> t == 2 diff --git a/tests/feature_check/target_info.py b/tests/feature_check/target_info.py index f60f3b31919..e95530023d7 100644 --- a/tests/feature_check/target_info.py +++ b/tests/feature_check/target_info.py @@ -19,5 +19,21 @@ "xtensa", "xtensawin", "rv32imc", -][sys_mpy >> 10] -print(platform, arch) + "rv64imc", +][(sys_mpy >> 10) & 0x0F] +arch_flags = sys_mpy >> 16 +build = getattr(sys.implementation, "_build", "unknown") +thread = getattr(sys.implementation, "_thread", None) + +# Detect how many bits of precision the floating point implementation has. +try: + if float("1.0000001") == float("1.0"): + float_prec = 30 + elif float("1e300") == float("inf"): + float_prec = 32 + else: + float_prec = 64 +except NameError: + float_prec = 0 + +print(platform, arch, arch_flags, build, thread, float_prec, len("α") == 1) diff --git a/tests/float/cmath_fun.py b/tests/float/cmath_fun.py index 39011733b02..0037d7c6559 100644 --- a/tests/float/cmath_fun.py +++ b/tests/float/cmath_fun.py @@ -51,6 +51,9 @@ print("%.5g" % ret) elif type(ret) == tuple: print("%.5g %.5g" % ret) + elif f_name == "exp": + # exp amplifies REPR_C inaccuracies, so we need to check one digit less + print("complex(%.4g, %.4g)" % (real, ret.imag)) else: # some test (eg cmath.sqrt(-0.5)) disagree with CPython with tiny real part real = ret.real diff --git a/tests/float/float_array.py b/tests/float/float_array.py index 3d128da8381..cfff3b220c6 100644 --- a/tests/float/float_array.py +++ b/tests/float/float_array.py @@ -19,4 +19,10 @@ def test(a): test(array("f")) test(array("d")) -print("{:.4f}".format(array("f", bytes(array("I", [0x3DCCCCCC])))[0])) +# hand-crafted floats, including non-standard nan +for float_hex in (0x3DCCCCCC, 0x7F800024, 0x7FC00004): + f = array("f", bytes(array("I", [float_hex])))[0] + if type(f) is float: + print("{:.4e}".format(f)) + else: + print(f) diff --git a/tests/float/float_format.py b/tests/float/float_format.py index 98ed0eb096f..0eb8b232b06 100644 --- a/tests/float/float_format.py +++ b/tests/float/float_format.py @@ -2,14 +2,25 @@ # general rounding for val in (116, 1111, 1234, 5010, 11111): - print("%.0f" % val) - print("%.1f" % val) - print("%.3f" % val) + print("Test on %d / 1000:" % val) + for fmt in ("%.5e", "%.3e", "%.1e", "%.0e", "%.3f", "%.1f", "%.0f", "%.3g", "%.1g", "%.0g"): + print(fmt, fmt % (val / 1000)) + +# make sure round-up to the next unit is handled properly +for val in range(4, 9): + divi = 10**val + print("Test on 99994 / (10 ** %d):" % val) + for fmt in ("%.5e", "%.3e", "%.1e", "%.0e", "%.3f", "%.1f", "%.0f", "%.3g", "%.1g", "%.0g"): + print(fmt, fmt % (99994 / divi)) # make sure rounding is done at the correct precision for prec in range(8): print(("%%.%df" % prec) % 6e-5) +# make sure trailing zeroes are added properly +for prec in range(8): + print(("%%.%df" % prec) % 1e19) + # check certain cases that had a digit value of 10 render as a ":" character print("%.2e" % float("9" * 51 + "e-39")) print("%.2e" % float("9" * 40 + "e-21")) diff --git a/tests/float/float_format_accuracy.py b/tests/float/float_format_accuracy.py new file mode 100644 index 00000000000..f9467f9c05d --- /dev/null +++ b/tests/float/float_format_accuracy.py @@ -0,0 +1,73 @@ +# Test accuracy of `repr` conversions. +# This test also increases code coverage for corner cases. + +try: + import array, math, random +except ImportError: + print("SKIP") + raise SystemExit + +# The largest errors come from seldom used very small numbers, near the +# limit of the representation. So we keep them out of this test to keep +# the max relative error display useful. +if float("1e-100") == 0.0: + # single-precision + float_type = "f" + float_size = 4 + # testing range + min_expo = -96 # i.e. not smaller than 1.0e-29 + # Expected results (given >=50'000 samples): + # - MICROPY_FLTCONV_IMPL_EXACT: 100% exact conversions + # - MICROPY_FLTCONV_IMPL_APPROX: >=98.53% exact conversions, max relative error <= 1.01e-7 + min_success = 0.980 # with only 1200 samples, the success rate is lower + max_rel_err = 1.1e-7 + # REPR_C is typically used with FORMAT_IMPL_BASIC, which has a larger error + is_REPR_C = float("1.0000001") == float("1.0") + if is_REPR_C: # REPR_C + min_success = 0.83 + max_rel_err = 5.75e-07 +else: + # double-precision + float_type = "d" + float_size = 8 + # testing range + min_expo = -845 # i.e. not smaller than 1.0e-254 + # Expected results (given >=200'000 samples): + # - MICROPY_FLTCONV_IMPL_EXACT: 100% exact conversions + # - MICROPY_FLTCONV_IMPL_APPROX: >=99.83% exact conversions, max relative error <= 2.7e-16 + min_success = 0.997 # with only 1200 samples, the success rate is lower + max_rel_err = 2.7e-16 + + +# Deterministic pseudorandom generator. Designed to be uniform +# on mantissa values and exponents, not on the represented number +def pseudo_randfloat(): + rnd_buff = bytearray(float_size) + for _ in range(float_size): + rnd_buff[_] = random.getrandbits(8) + return array.array(float_type, rnd_buff)[0] + + +random.seed(42) +stats = 0 +N = 1200 +max_err = 0 +for _ in range(N): + f = pseudo_randfloat() + while type(f) is not float or math.isinf(f) or math.isnan(f) or math.frexp(f)[1] <= min_expo: + f = pseudo_randfloat() + + str_f = repr(f) + f2 = float(str_f) + if f2 == f: + stats += 1 + else: + error = abs((f2 - f) / f) + if max_err < error: + max_err = error + +print(N, "values converted") +if stats / N >= min_success and max_err <= max_rel_err: + print("float format accuracy OK") +else: + print("FAILED: repr rate=%.3f%% max_err=%.3e" % (100 * stats / N, max_err)) diff --git a/tests/float/float_format_ints.py b/tests/float/float_format_ints.py index df4444166c5..7b7b30c4b34 100644 --- a/tests/float/float_format_ints.py +++ b/tests/float/float_format_ints.py @@ -12,14 +12,42 @@ print(title, "with format", f_fmt, "gives", f_fmt.format(f)) print(title, "with format", g_fmt, "gives", g_fmt.format(f)) +# The tests below check border cases involving all mantissa bits. +# In case of REPR_C, where the mantissa is missing two bits, the +# the string representation for such numbers might not always be exactly +# the same but nevertheless be correct, so we must allow a few exceptions. +is_REPR_C = float("1.0000001") == float("1.0") + # 16777215 is 2^24 - 1, the largest integer that can be completely held # in a float32. -print("{:f}".format(16777215)) +val_str = "{:f}".format(16777215) + +# When using REPR_C, 16777215.0 is the same as 16777212.0 or 16777214.4 +# (depending on the implementation of pow() function, the result may differ) +if is_REPR_C and (val_str == "16777212.000000" or val_str == "16777214.400000"): + val_str = "16777215.000000" + +print(val_str) + # 4294967040 = 16777215 * 128 is the largest integer that is exactly # represented by a float32 and that will also fit within a (signed) int32. # The upper bound of our integer-handling code is actually double this, # but that constant might cause trouble on systems using 32 bit ints. -print("{:f}".format(2147483520)) +val_str = "{:f}".format(2147483520) + +# When using FLOAT_IMPL_FLOAT, 2147483520.0 == 2147483500.0 +# Both representations are valid, the second being "simpler" +is_float32 = float("1e300") == float("inf") +if is_float32 and val_str == "2147483500.000000": + val_str = "2147483520.000000" + +# When using REPR_C, 2147483520.0 is the same as 2147483200.0 +# Both representations are valid, the second being "simpler" +if is_REPR_C and val_str == "2147483200.000000": + val_str = "2147483520.000000" + +print(val_str) + # Very large positive integers can be a test for precision and resolution. # This is a weird way to represent 1e38 (largest power of 10 for float32). print("{:.6e}".format(float("9" * 30 + "e8"))) diff --git a/tests/float/float_parse_doubleprec.py b/tests/float/float_parse_doubleprec.py index 81fcadcee88..c1b0b4823b0 100644 --- a/tests/float/float_parse_doubleprec.py +++ b/tests/float/float_parse_doubleprec.py @@ -19,3 +19,9 @@ print(float("1.00000000000000000000e-307")) print(float("10.0000000000000000000e-308")) print(float("100.000000000000000000e-309")) + +# ensure repr() adds an extra digit when needed for accurate parsing +print(float(repr(float("2.0") ** 100)) == float("2.0") ** 100) + +# ensure repr does not add meaningless extra digits (1.234999999999) +print(repr(1.2345)) diff --git a/tests/float/float_struct_e.py b/tests/float/float_struct_e.py index 403fbc5db4c..ba4134f3393 100644 --- a/tests/float/float_struct_e.py +++ b/tests/float/float_struct_e.py @@ -32,7 +32,7 @@ for i in (j, -j): x = struct.pack("", "=", "^"): for fill in ("", " ", "0", "@"): for sign in ("", "+", "-", " "): - # An empty precision defaults to 6, but when uPy is + # An empty precision defaults to 6, but when MicroPython is # configured to use a float, we can only use a # precision of 6 with numbers less than 10 and still # get results that compare to CPython (which uses @@ -164,7 +164,7 @@ def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg): for alignment in ("", "<", ">", "=", "^"): for fill in ("", " ", "0", "@"): for sign in ("", "+", "-", " "): - # An empty precision defaults to 6, but when uPy is + # An empty precision defaults to 6, but when MicroPython is # configured to use a float, we can only use a # precision of 6 with numbers less than 10 and still # get results that compare to CPython (which uses diff --git a/tests/float/string_format_fp30.py b/tests/float/string_format_fp30.py deleted file mode 100644 index 5f0b213daa3..00000000000 --- a/tests/float/string_format_fp30.py +++ /dev/null @@ -1,42 +0,0 @@ -def test(fmt, *args): - print("{:8s}".format(fmt) + ">" + fmt.format(*args) + "<") - - -test("{:10.4}", 123.456) -test("{:10.4e}", 123.456) -test("{:10.4e}", -123.456) -# test("{:10.4f}", 123.456) -# test("{:10.4f}", -123.456) -test("{:10.4g}", 123.456) -test("{:10.4g}", -123.456) -test("{:10.4n}", 123.456) -test("{:e}", 100) -test("{:f}", 200) -test("{:g}", 300) - -test("{:10.4E}", 123.456) -test("{:10.4E}", -123.456) -# test("{:10.4F}", 123.456) -# test("{:10.4F}", -123.456) -test("{:10.4G}", 123.456) -test("{:10.4G}", -123.456) - -test("{:06e}", float("inf")) -test("{:06e}", float("-inf")) -test("{:06e}", float("nan")) - -# The following fails right now -# test("{:10.1}", 0.0) - -print("%.0f" % (1.750000 % 0.08333333333)) -# Below isn't compatible with single-precision float -# print("%.1f" % (1.750000 % 0.08333333333)) -# print("%.2f" % (1.750000 % 0.08333333333)) -# print("%.12f" % (1.750000 % 0.08333333333)) - -# tests for errors in format string - -try: - "{:10.1b}".format(0.0) -except ValueError: - print("ValueError") diff --git a/tests/float/string_format_modulo.py b/tests/float/string_format_modulo.py index 3c206b73935..55314643351 100644 --- a/tests/float/string_format_modulo.py +++ b/tests/float/string_format_modulo.py @@ -6,7 +6,7 @@ print("%u" % 1.0) # these 3 have different behaviour in Python 3.x versions -# uPy raises a TypeError, following Python 3.5 (earlier versions don't) +# MicroPython raises a TypeError, following Python 3.5 (earlier versions don't) # print("%x" % 18.0) # print("%o" % 18.0) # print("%X" % 18.0) diff --git a/tests/float/string_format_modulo3.py b/tests/float/string_format_modulo3.py index f9d9c43cdf4..f8aeeda20f2 100644 --- a/tests/float/string_format_modulo3.py +++ b/tests/float/string_format_modulo3.py @@ -1,3 +1,3 @@ -# uPy and CPython outputs differ for the following +# Test corner cases where MicroPython and CPython outputs used to differ in the past print("%.1g" % -9.9) # round up 'g' with '-' sign print("%.2g" % 99.9) # round up diff --git a/tests/float/string_format_modulo3.py.exp b/tests/float/string_format_modulo3.py.exp deleted file mode 100644 index 71432b34045..00000000000 --- a/tests/float/string_format_modulo3.py.exp +++ /dev/null @@ -1,2 +0,0 @@ --10 -100 diff --git a/tests/frozen/frozentest.py b/tests/frozen/frozentest.py index 78cdd60bf04..74bdfb3b267 100644 --- a/tests/frozen/frozentest.py +++ b/tests/frozen/frozentest.py @@ -1,4 +1,4 @@ -print("uPy") +print("interned") print("a long string that is not interned") print("a string that has unicode αβγ chars") print(b"bytes 1234\x01") diff --git a/tests/import/builtin_ext.py b/tests/import/builtin_ext.py index 9d2344d400d..79ee901ea67 100644 --- a/tests/import/builtin_ext.py +++ b/tests/import/builtin_ext.py @@ -1,3 +1,9 @@ +try: + import uos, utime +except ImportError: + print("SKIP") + raise SystemExit + # Verify that sys is a builtin. import sys diff --git a/tests/import/builtin_import.py b/tests/import/builtin_import.py index 734498d1be4..364b0bae912 100644 --- a/tests/import/builtin_import.py +++ b/tests/import/builtin_import.py @@ -20,3 +20,12 @@ __import__("xyz", None, None, None, -1) except ValueError: print("ValueError") + +# globals is not checked for level=0 +__import__("builtins", "globals") + +# globals must be a dict (or None) for level>0 +try: + __import__("builtins", "globals", None, None, 1) +except TypeError: + print("TypeError") diff --git a/tests/import/import_broken.py b/tests/import/import_broken.py index 3c7cf4a4985..440922157ef 100644 --- a/tests/import/import_broken.py +++ b/tests/import/import_broken.py @@ -1,3 +1,9 @@ +try: + Exception.__class__ +except AttributeError: + print("SKIP") + raise SystemExit + import sys, pkg # Modules we import are usually added to sys.modules. diff --git a/tests/import/import_file.py b/tests/import/import_file.py index 90ec4e41e77..4cf307641c6 100644 --- a/tests/import/import_file.py +++ b/tests/import/import_file.py @@ -1,3 +1,7 @@ +if "__file__" not in globals(): + print("SKIP") + raise SystemExit + import import1b print(import1b.__file__) diff --git a/tests/import/import_override.py b/tests/import/import_override.py index 029ebe54c1f..0144e78cb9f 100644 --- a/tests/import/import_override.py +++ b/tests/import/import_override.py @@ -2,6 +2,10 @@ def custom_import(name, globals, locals, fromlist, level): + # CPython always tries to import _io, so just let that through as-is. + if name == "_io": + return orig_import(name, globals, locals, fromlist, level) + print("import", name, fromlist, level) class M: diff --git a/tests/import/import_override.py.exp b/tests/import/import_override.py.exp deleted file mode 100644 index 365248da6d8..00000000000 --- a/tests/import/import_override.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -import import1b None 0 -456 diff --git a/tests/import/import_override2.py b/tests/import/import_override2.py new file mode 100644 index 00000000000..25aac44fe98 --- /dev/null +++ b/tests/import/import_override2.py @@ -0,0 +1,18 @@ +# test overriding __import__ combined with importing from the filesystem + + +def custom_import(name, globals, locals, fromlist, level): + if level > 0: + print("import", name, fromlist, level) + return orig_import(name, globals, locals, fromlist, level) + + +orig_import = __import__ +try: + __import__("builtins").__import__ = custom_import +except AttributeError: + print("SKIP") + raise SystemExit + +# import calls __import__ behind the scenes +import pkg7.subpkg1.subpkg2.mod3 diff --git a/tests/import/import_pkg7.py.exp b/tests/import/import_pkg7.py.exp deleted file mode 100644 index 8f21a615f6a..00000000000 --- a/tests/import/import_pkg7.py.exp +++ /dev/null @@ -1,8 +0,0 @@ -pkg __name__: pkg7 -pkg __name__: pkg7.subpkg1 -pkg __name__: pkg7.subpkg1.subpkg2 -mod1 -mod2 -mod1.foo -mod2.bar -ImportError diff --git a/tests/import/import_pkg9.py b/tests/import/import_pkg9.py index 4de028494f1..c2e0b618b69 100644 --- a/tests/import/import_pkg9.py +++ b/tests/import/import_pkg9.py @@ -13,4 +13,4 @@ import pkg9.mod2 pkg9.mod1() -print(pkg9.mod2.__name__, type(pkg9.mod2).__name__) +print(pkg9.mod2.__name__, type(pkg9.mod2)) diff --git a/tests/import/import_shared_name.py b/tests/import/import_shared_name.py new file mode 100644 index 00000000000..b76695f671e --- /dev/null +++ b/tests/import/import_shared_name.py @@ -0,0 +1,7 @@ +# https://github.com/adafruit/circuitpython/issues/10614 +# When a directory `shared_name/` (no __init__.py) and a module `shared_name.py` +# share a name, `import shared_name` must pick the .py module per PEP 420 +# precedence: regular package > module > namespace package. +import shared_name + +print("done") diff --git a/tests/import/import_star.py b/tests/import/import_star.py new file mode 100644 index 00000000000..2cb21b877d7 --- /dev/null +++ b/tests/import/import_star.py @@ -0,0 +1,59 @@ +# test `from package import *` conventions, including __all__ support +# +# This test requires MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_BASIC_FEATURES + +try: + next(iter([]), 42) +except TypeError: + # 2-argument version of next() not supported + # we are probably not at MICROPY_CONFIG_ROM_LEVEL_BASIC_FEATURES + print("SKIP") + raise SystemExit + +# 1. test default visibility +from pkgstar_default import * + +print("visibleFun" in globals()) +print("VisibleClass" in globals()) +print("_hiddenFun" in globals()) +print("_HiddenClass" in globals()) +print(visibleFun()) + +# 2. test explicit visibility as defined by __all__ (as an array) +from pkgstar_all_array import * + +print("publicFun" in globals()) +print("PublicClass" in globals()) +print("unlistedFun" in globals()) +print("UnlistedClass" in globals()) +print("_privateFun" in globals()) +print("_PrivateClass" in globals()) +print(publicFun()) +# test dynamic import as used in asyncio +print("dynamicFun" in globals()) +print(dynamicFun()) + +# 3. test explicit visibility as defined by __all__ (as an tuple) +from pkgstar_all_tuple import * + +print("publicFun2" in globals()) +print("PublicClass2" in globals()) +print("unlistedFun2" in globals()) +print("UnlistedClass2" in globals()) +print(publicFun2()) + +# 4. test reporting of missing entries in __all__ +try: + from pkgstar_all_miss import * + + print("missed detection of incorrect __all__ definition") +except AttributeError as er: + print("AttributeError triggered for bad __all__ definition") + +# 5. test reporting of invalid __all__ definition +try: + from pkgstar_all_inval import * + + print("missed detection of incorrect __all__ definition") +except TypeError as er: + print("TypeError triggered for bad __all__ definition") diff --git a/tests/import/import_star_error.py b/tests/import/import_star_error.py index 9e1757b6ef5..73d9c863d6f 100644 --- a/tests/import/import_star_error.py +++ b/tests/import/import_star_error.py @@ -1,5 +1,10 @@ # test errors with import * +if not hasattr(object, "__init__"): + # target doesn't have MICROPY_CPYTHON_COMPAT enabled, so doesn't check for "import *" + print("SKIP") + raise SystemExit + # 'import *' is not allowed in function scope try: exec("def foo(): from x import *") diff --git a/tests/import/module_getattr.py.exp b/tests/import/module_getattr.py.exp deleted file mode 100644 index bc59c12aa16..00000000000 --- a/tests/import/module_getattr.py.exp +++ /dev/null @@ -1 +0,0 @@ -False diff --git a/tests/import/pkg7/subpkg1/subpkg2/mod3.py b/tests/import/pkg7/subpkg1/subpkg2/mod3.py index b0f4279fcf5..f7f4c1e65f4 100644 --- a/tests/import/pkg7/subpkg1/subpkg2/mod3.py +++ b/tests/import/pkg7/subpkg1/subpkg2/mod3.py @@ -5,7 +5,9 @@ print(bar) # attempted relative import beyond top-level package +# On older versions of CPython (eg 3.8) this is a ValueError, but on +# newer CPython (eg 3.11) and MicroPython it's an ImportError. try: from .... import mod1 -except ImportError: +except (ImportError, ValueError): print("ImportError") diff --git a/tests/import/pkgstar_all_array/__init__.py b/tests/import/pkgstar_all_array/__init__.py new file mode 100644 index 00000000000..03b012123fe --- /dev/null +++ b/tests/import/pkgstar_all_array/__init__.py @@ -0,0 +1,49 @@ +__all__ = ["publicFun", "PublicClass", "dynamicFun"] + + +# Definitions below should always be imported by a star import +def publicFun(): + return 1 + + +class PublicClass: + def __init__(self): + self._val = 1 + + +# If __all__ support is enabled, definitions below +# should not be imported by a star import +def unlistedFun(): + return 0 + + +class UnlistedClass: + def __init__(self): + self._val = 0 + + +# Definitions below should be not be imported by a star import +# (they start with an underscore, and are not listed in __all__) +def _privateFun(): + return -1 + + +class _PrivateClass: + def __init__(self): + self._val = -1 + + +# Test lazy loaded function, as used by extmod/asyncio: +# Works with a star import only if __all__ support is enabled +_attrs = { + "dynamicFun": "funcs", +} + + +def __getattr__(attr): + mod = _attrs.get(attr, None) + if mod is None: + raise AttributeError(attr) + value = getattr(__import__(mod, globals(), locals(), True, 1), attr) + globals()[attr] = value + return value diff --git a/tests/import/pkgstar_all_array/funcs.py b/tests/import/pkgstar_all_array/funcs.py new file mode 100644 index 00000000000..7540d70f66b --- /dev/null +++ b/tests/import/pkgstar_all_array/funcs.py @@ -0,0 +1,2 @@ +def dynamicFun(): + return 777 diff --git a/tests/import/pkgstar_all_inval/__init__.py b/tests/import/pkgstar_all_inval/__init__.py new file mode 100644 index 00000000000..7022476c19b --- /dev/null +++ b/tests/import/pkgstar_all_inval/__init__.py @@ -0,0 +1 @@ +__all__ = 42 diff --git a/tests/import/pkgstar_all_miss/__init__.py b/tests/import/pkgstar_all_miss/__init__.py new file mode 100644 index 00000000000..f9bbb538072 --- /dev/null +++ b/tests/import/pkgstar_all_miss/__init__.py @@ -0,0 +1,8 @@ +__all__ = ("existingFun", "missingFun") + + +def existingFun(): + return None + + +# missingFun is not defined, should raise an error on import diff --git a/tests/import/pkgstar_all_tuple/__init__.py b/tests/import/pkgstar_all_tuple/__init__.py new file mode 100644 index 00000000000..433ddc8e976 --- /dev/null +++ b/tests/import/pkgstar_all_tuple/__init__.py @@ -0,0 +1,22 @@ +__all__ = ("publicFun2", "PublicClass2") + + +# Definitions below should always be imported by a star import +def publicFun2(): + return 2 + + +class PublicClass2: + def __init__(self): + self._val = 2 + + +# If __all__ support is enabled, definitions below +# should not be imported by a star import +def unlistedFun2(): + return 0 + + +class UnlistedClass2: + def __init__(self): + self._val = 0 diff --git a/tests/import/pkgstar_default/__init__.py b/tests/import/pkgstar_default/__init__.py new file mode 100644 index 00000000000..4947e4ce7f1 --- /dev/null +++ b/tests/import/pkgstar_default/__init__.py @@ -0,0 +1,20 @@ +# When __all__ is undefined, star import should only +# show objects that do not start with an underscore + + +def visibleFun(): + return 42 + + +class VisibleClass: + def __init__(self): + self._val = 42 + + +def _hiddenFun(): + return -1 + + +class _HiddenClass: + def __init__(self): + self._val = -1 diff --git a/tests/import/shared_name.py b/tests/import/shared_name.py new file mode 100644 index 00000000000..0ba98242ed9 --- /dev/null +++ b/tests/import/shared_name.py @@ -0,0 +1 @@ +print("hello shared_name.py") diff --git a/tests/import/shared_name/spritesheet.bmp b/tests/import/shared_name/spritesheet.bmp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/inlineasm/rv32/asmzba.py b/tests/inlineasm/rv32/asmzba.py new file mode 100644 index 00000000000..75f3573c864 --- /dev/null +++ b/tests/inlineasm/rv32/asmzba.py @@ -0,0 +1,18 @@ +@micropython.asm_rv32 +def test_sh1add(a0, a1): + sh1add(a0, a0, a1) + + +@micropython.asm_rv32 +def test_sh2add(a0, a1): + sh2add(a0, a0, a1) + + +@micropython.asm_rv32 +def test_sh3add(a0, a1): + sh3add(a0, a0, a1) + + +print(hex(test_sh1add(10, 20))) +print(hex(test_sh2add(10, 20))) +print(hex(test_sh3add(10, 20))) diff --git a/tests/inlineasm/rv32/asmzba.py.exp b/tests/inlineasm/rv32/asmzba.py.exp new file mode 100644 index 00000000000..5f56bd95642 --- /dev/null +++ b/tests/inlineasm/rv32/asmzba.py.exp @@ -0,0 +1,3 @@ +0x28 +0x3c +0x64 diff --git a/tests/inlineasm/thumb/asmerrors.py b/tests/inlineasm/thumb/asmerrors.py new file mode 100644 index 00000000000..a26f9322540 --- /dev/null +++ b/tests/inlineasm/thumb/asmerrors.py @@ -0,0 +1,4 @@ +try: + exec("@micropython.asm_thumb\ndef l():\n a = di(a2, a2, -1)") +except SyntaxError as e: + print(e) diff --git a/tests/inlineasm/thumb/asmerrors.py.exp b/tests/inlineasm/thumb/asmerrors.py.exp new file mode 100644 index 00000000000..7590f171e51 --- /dev/null +++ b/tests/inlineasm/thumb/asmerrors.py.exp @@ -0,0 +1 @@ +expecting an assembler instruction diff --git a/tests/inlineasm/xtensa/asmargs.py b/tests/inlineasm/xtensa/asmargs.py new file mode 100644 index 00000000000..2bfccfcc69b --- /dev/null +++ b/tests/inlineasm/xtensa/asmargs.py @@ -0,0 +1,44 @@ +# test passing arguments + + +@micropython.asm_xtensa +def arg0(): + movi(a2, 1) + + +print(arg0()) + + +@micropython.asm_xtensa +def arg1(a2): + addi(a2, a2, 1) + + +print(arg1(1)) + + +@micropython.asm_xtensa +def arg2(a2, a3): + add(a2, a2, a3) + + +print(arg2(1, 2)) + + +@micropython.asm_xtensa +def arg3(a2, a3, a4): + add(a2, a2, a3) + add(a2, a2, a4) + + +print(arg3(1, 2, 3)) + + +@micropython.asm_xtensa +def arg4(a2, a3, a4, a5): + add(a2, a2, a3) + add(a2, a2, a4) + add(a2, a2, a5) + + +print(arg4(1, 2, 3, 4)) diff --git a/tests/inlineasm/xtensa/asmargs.py.exp b/tests/inlineasm/xtensa/asmargs.py.exp new file mode 100644 index 00000000000..e33a6964f46 --- /dev/null +++ b/tests/inlineasm/xtensa/asmargs.py.exp @@ -0,0 +1,5 @@ +1 +2 +3 +6 +10 diff --git a/tests/inlineasm/xtensa/asmarith.py b/tests/inlineasm/xtensa/asmarith.py new file mode 100644 index 00000000000..1c0934eb7a6 --- /dev/null +++ b/tests/inlineasm/xtensa/asmarith.py @@ -0,0 +1,119 @@ +@micropython.asm_xtensa +def f1(a2): + abs_(a2, a2) + + +for value in (10, -10, 0): + print(f1(value)) + + +ADDMI_TEMPLATE = """ +@micropython.asm_xtensa +def f1(a2) -> int: + addmi(a2, a2, {}) +print(f1(0)) +""" + +for value in (-32768, -32767, 32512, 32513, 0): + try: + exec(ADDMI_TEMPLATE.format(value)) + except SyntaxError as error: + print(error) + + +@micropython.asm_xtensa +def a2(a2, a3) -> int: + addx2(a2, a2, a3) + + +@micropython.asm_xtensa +def a4(a2, a3) -> int: + addx4(a2, a2, a3) + + +@micropython.asm_xtensa +def a8(a2, a3) -> int: + addx8(a2, a2, a3) + + +@micropython.asm_xtensa +def s2(a2, a3) -> int: + subx2(a2, a2, a3) + + +@micropython.asm_xtensa +def s4(a2, a3) -> int: + subx4(a2, a2, a3) + + +@micropython.asm_xtensa +def s8(a2, a3) -> int: + subx8(a2, a2, a3) + + +for first, second in ((100, 100), (-100, 100), (-100, -100), (100, -100)): + print("a2", a2(first, second)) + print("a4", a4(first, second)) + print("a8", a8(first, second)) + print("s2", s2(first, second)) + print("s4", s4(first, second)) + print("s8", s8(first, second)) + + +@micropython.asm_xtensa +def f5(a2) -> int: + neg(a2, a2) + + +for value in (0, -100, 100): + print(f5(value)) + + +@micropython.asm_xtensa +def f6(): + movi(a2, 0x100) + movi(a3, 1) + add(a2, a2, a3) + addi(a2, a2, 1) + addi(a2, a2, -2) + sub(a2, a2, a3) + + +print(hex(f6())) + + +@micropython.asm_xtensa +def f7(): + movi(a2, 0x10FF) + movi(a3, 1) + and_(a4, a2, a3) + or_(a4, a4, a3) + movi(a3, 0x200) + xor(a2, a4, a3) + + +print(hex(f7())) + + +@micropython.asm_xtensa +def f8(a2, a3): + add_n(a2, a2, a3) + + +print(f8(100, 200)) + + +@micropython.asm_xtensa +def f9(a2): + addi_n(a2, a2, 1) + + +print(f9(100)) + + +@micropython.asm_xtensa +def f10(a2, a3) -> uint: + mull(a2, a2, a3) + + +print(hex(f10(0xC0000000, 2))) diff --git a/tests/inlineasm/xtensa/asmarith.py.exp b/tests/inlineasm/xtensa/asmarith.py.exp new file mode 100644 index 00000000000..7aba46a27d9 --- /dev/null +++ b/tests/inlineasm/xtensa/asmarith.py.exp @@ -0,0 +1,40 @@ +10 +10 +0 +-32768 +-32767 is not a multiple of 256 +32512 +'addmi' integer 32513 isn't within range -32768..32512 +0 +a2 300 +a4 500 +a8 900 +s2 100 +s4 300 +s8 700 +a2 -100 +a4 -300 +a8 -700 +s2 -300 +s4 -500 +s8 -900 +a2 -300 +a4 -500 +a8 -900 +s2 -100 +s4 -300 +s8 -700 +a2 100 +a4 300 +a8 700 +s2 300 +s4 500 +s8 900 +0 +100 +-100 +0xff +0x201 +300 +101 +0x80000000 diff --git a/tests/inlineasm/xtensa/asmbranch.py b/tests/inlineasm/xtensa/asmbranch.py new file mode 100644 index 00000000000..22bcd5a7c71 --- /dev/null +++ b/tests/inlineasm/xtensa/asmbranch.py @@ -0,0 +1,299 @@ +# test branch instructions + + +@micropython.asm_xtensa +def tball(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + ball(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tball(0xFFFFFFFF, 0xFFFFFFFF)) +print(tball(0xFFFEFFFF, 0xFFFFFFFF)) +print(tball(0x00000000, 0xFFFFFFFF)) +print(tball(0xFFFFFFFF, 0x01010101)) + + +@micropython.asm_xtensa +def tbany(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bany(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbany(0xFFFFFFFF, 0xFFFFFFFF)) +print(tbany(0xFFFEFFFF, 0xFFFFFFFF)) +print(tbany(0x00000000, 0xFFFFFFFF)) +print(tbany(0xFFFFFFFF, 0x01010101)) + + +@micropython.asm_xtensa +def tbbc(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bbc(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbbc(0xFFFFFFFF, 4)) +print(tbbc(0xFFFEFFFF, 16)) +print(tbbc(0x00000000, 1)) + + +BBCI_TEMPLATE = """ +@micropython.asm_xtensa +def tbbci(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bbci(a3, {}, end) + movi(a2, -1) + label(end) + +print(tbbci({})) +""" + + +for value, bit in ((0xFFFFFFFF, 4), (0xFFFEFFFF, 16), (0x00000000, 1)): + try: + exec(BBCI_TEMPLATE.format(bit, value)) + except SyntaxError as error: + print(error) + + +@micropython.asm_xtensa +def tbbs(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bbs(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbbs(0x00000000, 4)) +print(tbbs(0x00010000, 16)) +print(tbbs(0xFFFFFFFF, 1)) + + +BBSI_TEMPLATE = """ +@micropython.asm_xtensa +def tbbsi(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bbsi(a3, {}, end) + movi(a2, -1) + label(end) + +print(tbbsi({})) +""" + + +for value, bit in ((0x00000000, 4), (0x00010000, 16), (0xFFFFFFFF, 1)): + try: + exec(BBSI_TEMPLATE.format(bit, value)) + except SyntaxError as error: + print(error) + + +@micropython.asm_xtensa +def tbeq(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + beq(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbeq(0x00000000, 0x00000000)) +print(tbeq(0x00010000, 0x00000000)) +print(tbeq(0xFFFFFFFF, 0xFFFFFFFF)) + + +@micropython.asm_xtensa +def tbeqz(a2) -> int: + mov(a3, a2) + movi(a2, 0) + beqz(a3, end) + movi(a2, -1) + label(end) + + +print(tbeqz(0)) +print(tbeqz(0x12345678)) +print(tbeqz(-1)) + + +@micropython.asm_xtensa +def tbge(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bge(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbge(0x00000000, 0x00000000)) +print(tbge(0x00010000, 0x00000000)) +print(tbge(0xF0000000, 0xFFFFFFFF)) + + +@micropython.asm_xtensa +def tbgeu(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bgeu(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbgeu(0x00000000, 0x00000000)) +print(tbgeu(0x00010000, 0x00000000)) +print(tbgeu(0xF0000000, 0xFFFFFFFF)) +print(tbgeu(0xFFFFFFFF, 0xF0000000)) + + +@micropython.asm_xtensa +def tbgez(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bgez(a3, end) + movi(a2, -1) + label(end) + + +print(tbgez(0)) +print(tbgez(0x12345678)) +print(tbgez(-1)) + + +@micropython.asm_xtensa +def tblt(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + blt(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tblt(0x00000000, 0x00000000)) +print(tblt(0x00010000, 0x00000000)) +print(tblt(0xF0000000, 0xFFFFFFFF)) + + +@micropython.asm_xtensa +def tbltu(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bltu(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbltu(0x00000000, 0x00000000)) +print(tbltu(0x00010000, 0x00000000)) +print(tbltu(0xF0000000, 0xFFFFFFFF)) +print(tbltu(0xFFFFFFFF, 0xF0000000)) + + +@micropython.asm_xtensa +def tbltz(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bltz(a3, end) + movi(a2, -1) + label(end) + + +print(tbltz(0)) +print(tbltz(0x12345678)) +print(tbltz(-1)) + + +@micropython.asm_xtensa +def tbnall(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bnall(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbnall(0xFFFFFFFF, 0xFFFFFFFF)) +print(tbnall(0xFFFEFFFF, 0xFFFFFFFF)) +print(tbnall(0x00000000, 0xFFFFFFFF)) +print(tbnall(0xFFFFFFFF, 0x01010101)) + + +@micropython.asm_xtensa +def tbne(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bne(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbne(0x00000000, 0x00000000)) +print(tbne(0x00010000, 0x00000000)) +print(tbne(0xFFFFFFFF, 0xFFFFFFFF)) + + +@micropython.asm_xtensa +def tbnez(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bnez(a3, end) + movi(a2, -1) + label(end) + + +print(tbnez(0)) +print(tbnez(0x12345678)) +print(tbnez(-1)) + + +@micropython.asm_xtensa +def tbnone(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bnone(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbnone(0xFFFFFFFF, 0xFFFFFFFF)) +print(tbnone(0xFFFEFFFF, 0xFFFFFFFF)) +print(tbnone(0x00000000, 0xFFFFFFFF)) +print(tbnone(0x10101010, 0x01010101)) + + +@micropython.asm_xtensa +def tbeqz_n(a2) -> int: + mov(a3, a2) + movi(a2, 0) + beqz_n(a3, end) + movi(a2, -1) + label(end) + + +print(tbeqz_n(0)) +print(tbeqz_n(0x12345678)) +print(tbeqz_n(-1)) + + +@micropython.asm_xtensa +def tbnez_n(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bnez(a3, end) + movi(a2, -1) + label(end) + + +print(tbnez_n(0)) +print(tbnez_n(0x12345678)) +print(tbnez_n(-1)) diff --git a/tests/inlineasm/xtensa/asmbranch.py.exp b/tests/inlineasm/xtensa/asmbranch.py.exp new file mode 100644 index 00000000000..319a4b435ef --- /dev/null +++ b/tests/inlineasm/xtensa/asmbranch.py.exp @@ -0,0 +1,66 @@ +0 +-1 +-1 +0 +0 +0 +-1 +0 +-1 +0 +0 +-1 +0 +0 +-1 +0 +0 +-1 +0 +0 +0 +-1 +0 +0 +-1 +-1 +0 +0 +-1 +0 +0 +-1 +0 +0 +0 +-1 +-1 +-1 +0 +-1 +-1 +0 +-1 +-1 +-1 +0 +-1 +0 +0 +-1 +-1 +0 +-1 +-1 +0 +0 +-1 +-1 +0 +0 +0 +-1 +-1 +-1 +0 +0 diff --git a/tests/inlineasm/xtensa/asmjump.py b/tests/inlineasm/xtensa/asmjump.py new file mode 100644 index 00000000000..f41c9482319 --- /dev/null +++ b/tests/inlineasm/xtensa/asmjump.py @@ -0,0 +1,26 @@ +@micropython.asm_xtensa +def jump() -> int: + movi(a2, 0) + j(NEXT) + addi(a2, a2, 1) + j(DONE) + label(NEXT) + addi(a2, a2, 2) + label(DONE) + + +print(jump()) + + +@micropython.asm_xtensa +def jumpx() -> int: + call0(ENTRY) + label(ENTRY) + movi(a2, 0) + addi(a3, a0, 12) + jx(a3) + movi(a2, 1) + movi(a2, 2) + + +print(jumpx()) diff --git a/tests/inlineasm/xtensa/asmjump.py.exp b/tests/inlineasm/xtensa/asmjump.py.exp new file mode 100644 index 00000000000..51993f072d5 --- /dev/null +++ b/tests/inlineasm/xtensa/asmjump.py.exp @@ -0,0 +1,2 @@ +2 +2 diff --git a/tests/inlineasm/xtensa/asmloadstore.py b/tests/inlineasm/xtensa/asmloadstore.py new file mode 100644 index 00000000000..b185e30520c --- /dev/null +++ b/tests/inlineasm/xtensa/asmloadstore.py @@ -0,0 +1,98 @@ +import array + +# On the 8266 the generated code gets put into the IRAM segment, which is only +# word-addressable. Therefore, to test byte and halfword load/store opcodes +# some memory must be reserved in the DRAM segment. + +BYTE_DATA = array.array("B", (0x11, 0x22, 0x33, 0x44)) +WORD_DATA = array.array("h", (100, 200, -100, -200)) +DWORD_DATA = array.array("i", (100_000, -200_000, 300_000, -400_000)) + + +@micropython.asm_xtensa +def tl32r() -> int: + nop() + j(CODE) + align(4) + label(DATA) + data(1, 1, 2, 3, 4, 5, 6, 7) + align(4) + label(CODE) + nop_n() + nop_n() + l32r(a2, DATA) + + +print(hex(tl32r())) + + +@micropython.asm_xtensa +def tl32i() -> uint: + call0(ENTRY) + label(ENTRY) + l32i(a2, a0, 0) + + +print(hex(tl32i())) + + +@micropython.asm_xtensa +def tl8ui(a2) -> uint: + mov(a3, a2) + l8ui(a2, a3, 1) + + +print(hex(tl8ui(BYTE_DATA))) + + +@micropython.asm_xtensa +def tl16ui(a2) -> uint: + mov(a3, a2) + l16ui(a2, a3, 2) + + +print(tl16ui(WORD_DATA)) + + +@micropython.asm_xtensa +def tl16si(a2) -> int: + mov(a3, a2) + l16si(a2, a3, 6) + + +print(tl16si(WORD_DATA)) + + +@micropython.asm_xtensa +def ts8i(a2, a3): + s8i(a3, a2, 1) + + +ts8i(BYTE_DATA, 0xFF) +print(BYTE_DATA) + + +@micropython.asm_xtensa +def ts16i(a2, a3): + s16i(a3, a2, 2) + + +ts16i(WORD_DATA, -123) +print(WORD_DATA) + + +@micropython.asm_xtensa +def ts32i(a2, a3) -> uint: + s32i(a3, a2, 4) + + +ts32i(DWORD_DATA, -123456) +print(DWORD_DATA) + + +@micropython.asm_xtensa +def tl32i_n(a2) -> uint: + l32i_n(a2, a2, 8) + + +print(tl32i_n(DWORD_DATA)) diff --git a/tests/inlineasm/xtensa/asmloadstore.py.exp b/tests/inlineasm/xtensa/asmloadstore.py.exp new file mode 100644 index 00000000000..e6672df6f81 --- /dev/null +++ b/tests/inlineasm/xtensa/asmloadstore.py.exp @@ -0,0 +1,9 @@ +0x4030201 +0xf8002022 +0x22 +200 +-200 +array('B', [17, 255, 51, 68]) +array('h', [100, -123, -100, -200]) +array('i', [100000, -123456, 300000, -400000]) +300000 diff --git a/tests/inlineasm/xtensa/asmmisc.py b/tests/inlineasm/xtensa/asmmisc.py new file mode 100644 index 00000000000..271ab836625 --- /dev/null +++ b/tests/inlineasm/xtensa/asmmisc.py @@ -0,0 +1,25 @@ +@micropython.asm_xtensa +def tnop(a2, a3, a4, a5): + nop() + + +out2 = tnop(0x100, 0x200, 0x300, 0x400) +print(out2 == 0x100) + + +@micropython.asm_xtensa +def tnop_n(a2, a3, a4, a5): + nop_n() + + +out2 = tnop_n(0x100, 0x200, 0x300, 0x400) +print(out2 == 0x100) + + +@micropython.asm_xtensa +def tmov_n(a2, a3): + mov_n(a4, a3) + add(a2, a4, a3) + + +print(tmov_n(0, 1)) diff --git a/tests/inlineasm/xtensa/asmmisc.py.exp b/tests/inlineasm/xtensa/asmmisc.py.exp new file mode 100644 index 00000000000..eefaa35daf0 --- /dev/null +++ b/tests/inlineasm/xtensa/asmmisc.py.exp @@ -0,0 +1,3 @@ +True +True +2 diff --git a/tests/inlineasm/xtensa/asmshift.py b/tests/inlineasm/xtensa/asmshift.py new file mode 100644 index 00000000000..271ca1ccd49 --- /dev/null +++ b/tests/inlineasm/xtensa/asmshift.py @@ -0,0 +1,137 @@ +@micropython.asm_xtensa +def lsl1(a2): + slli(a2, a2, 1) + + +print(hex(lsl1(0x123))) + + +@micropython.asm_xtensa +def lsl23(a2): + slli(a2, a2, 23) + + +print(hex(lsl23(1))) + + +@micropython.asm_xtensa +def lsr1(a2): + srli(a2, a2, 1) + + +print(hex(lsr1(0x123))) + + +@micropython.asm_xtensa +def lsr15(a2): + srli(a2, a2, 15) + + +print(hex(lsr15(0x80000000))) + + +@micropython.asm_xtensa +def asr1(a2): + srai(a2, a2, 1) + + +print(hex(asr1(0x123))) + + +@micropython.asm_xtensa +def asr31(a2): + srai(a2, a2, 31) + + +print(hex(asr31(0x80000000))) + + +@micropython.asm_xtensa +def lsl1r(a2): + movi(a3, 1) + ssl(a3) + sll(a2, a2) + + +print(hex(lsl1r(0x123))) + + +@micropython.asm_xtensa +def lsr1r(a2): + movi(a3, 1) + ssr(a3) + srl(a2, a2) + + +print(hex(lsr1r(0x123))) + + +@micropython.asm_xtensa +def asr1r(a2): + movi(a3, 1) + ssr(a3) + sra(a2, a2) + + +print(hex(asr1r(0x123))) + + +@micropython.asm_xtensa +def sll9(a2): + ssai(9) + sll(a2, a2) + + +print(hex(sll9(1))) + + +@micropython.asm_xtensa +def srlr(a2, a3): + ssa8l(a3) + srl(a2, a2) + + +print(hex(srlr(0x12340000, 2))) + + +@micropython.asm_xtensa +def sllr(a2, a3): + ssa8b(a3) + sll(a2, a2) + + +print(hex(sllr(0x1234, 2))) + + +@micropython.asm_xtensa +def srcr(a2, a3, a4): + ssr(a4) + src(a2, a2, a3) + + +print(hex(srcr(0x00000001, 0x80000000, 2))) + + +@micropython.asm_xtensa +def srai24(a2): + srai(a2, a2, 24) + + +print(hex(srai24(0x12345678))) + + +@micropython.asm_xtensa +def nsar(a2, a3): + nsa(a2, a3) + + +print(nsar(0x12345678, 0)) +print(nsar(0x12345678, -1)) + + +@micropython.asm_xtensa +def nsaur(a2, a3): + nsau(a2, a3) + + +print(nsaur(0x12345678, 0)) diff --git a/tests/inlineasm/xtensa/asmshift.py.exp b/tests/inlineasm/xtensa/asmshift.py.exp new file mode 100644 index 00000000000..3e2bb3b4aef --- /dev/null +++ b/tests/inlineasm/xtensa/asmshift.py.exp @@ -0,0 +1,17 @@ +0x246 +0x800000 +0x91 +0x10000 +0x91 +-0x1 +0x246 +0x91 +0x91 +0x800000 +0x1234 +0x12340000 +0x60000000 +0x12 +31 +31 +32 diff --git a/tests/internal_bench/class_create-0-empty.py b/tests/internal_bench/class_create-0-empty.py new file mode 100644 index 00000000000..1fd8ccd9257 --- /dev/null +++ b/tests/internal_bench/class_create-0-empty.py @@ -0,0 +1,11 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-1-slots.py b/tests/internal_bench/class_create-1-slots.py new file mode 100644 index 00000000000..9b3e4b9570d --- /dev/null +++ b/tests/internal_bench/class_create-1-slots.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + l = ["x"] + for i in range(num // 40): + + class X: + __slots__ = l + + +bench.run(test) diff --git a/tests/internal_bench/class_create-1.1-slots5.py b/tests/internal_bench/class_create-1.1-slots5.py new file mode 100644 index 00000000000..ccac77dec9d --- /dev/null +++ b/tests/internal_bench/class_create-1.1-slots5.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + l = ["a", "b", "c", "d", "x"] + for i in range(num // 40): + + class X: + __slots__ = l + + +bench.run(test) diff --git a/tests/internal_bench/class_create-2-classattr.py b/tests/internal_bench/class_create-2-classattr.py new file mode 100644 index 00000000000..049a7dab170 --- /dev/null +++ b/tests/internal_bench/class_create-2-classattr.py @@ -0,0 +1,11 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + x = 1 + + +bench.run(test) diff --git a/tests/internal_bench/class_create-2.1-classattr5.py b/tests/internal_bench/class_create-2.1-classattr5.py new file mode 100644 index 00000000000..5051e7dcca7 --- /dev/null +++ b/tests/internal_bench/class_create-2.1-classattr5.py @@ -0,0 +1,15 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + a = 0 + b = 0 + c = 0 + d = 0 + x = 1 + + +bench.run(test) diff --git a/tests/internal_bench/class_create-2.3-classattr5objs.py b/tests/internal_bench/class_create-2.3-classattr5objs.py new file mode 100644 index 00000000000..74540865dcd --- /dev/null +++ b/tests/internal_bench/class_create-2.3-classattr5objs.py @@ -0,0 +1,20 @@ +import bench + + +class Class: + pass + + +def test(num): + instance = Class() + for i in range(num // 40): + + class X: + a = instance + b = instance + c = instance + d = instance + x = instance + + +bench.run(test) diff --git a/tests/internal_bench/class_create-3-instancemethod.py b/tests/internal_bench/class_create-3-instancemethod.py new file mode 100644 index 00000000000..e8c201cb2c3 --- /dev/null +++ b/tests/internal_bench/class_create-3-instancemethod.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + def x(self): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-4-classmethod.py b/tests/internal_bench/class_create-4-classmethod.py new file mode 100644 index 00000000000..f34962bc671 --- /dev/null +++ b/tests/internal_bench/class_create-4-classmethod.py @@ -0,0 +1,13 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + @classmethod + def x(cls): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-4.1-classmethod_implicit.py b/tests/internal_bench/class_create-4.1-classmethod_implicit.py new file mode 100644 index 00000000000..f2d1fcfd188 --- /dev/null +++ b/tests/internal_bench/class_create-4.1-classmethod_implicit.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + def __new__(cls): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-5-staticmethod.py b/tests/internal_bench/class_create-5-staticmethod.py new file mode 100644 index 00000000000..06335566675 --- /dev/null +++ b/tests/internal_bench/class_create-5-staticmethod.py @@ -0,0 +1,13 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + @staticmethod + def x(): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-6-getattribute.py b/tests/internal_bench/class_create-6-getattribute.py new file mode 100644 index 00000000000..10a4fe7ce8d --- /dev/null +++ b/tests/internal_bench/class_create-6-getattribute.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + def __getattribute__(self, name): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-6.1-getattr.py b/tests/internal_bench/class_create-6.1-getattr.py new file mode 100644 index 00000000000..b4b9ba2f552 --- /dev/null +++ b/tests/internal_bench/class_create-6.1-getattr.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + def __getattr__(self, name): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-6.2-property.py b/tests/internal_bench/class_create-6.2-property.py new file mode 100644 index 00000000000..cf847b6dc9c --- /dev/null +++ b/tests/internal_bench/class_create-6.2-property.py @@ -0,0 +1,13 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + @property + def x(self): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-6.3-descriptor.py b/tests/internal_bench/class_create-6.3-descriptor.py new file mode 100644 index 00000000000..7b0a6357263 --- /dev/null +++ b/tests/internal_bench/class_create-6.3-descriptor.py @@ -0,0 +1,17 @@ +import bench + + +class D: + def __get__(self, instance, owner=None): + pass + + +def test(num): + descriptor = D() + for i in range(num // 40): + + class X: + x = descriptor + + +bench.run(test) diff --git a/tests/internal_bench/class_create-7-inherit.py b/tests/internal_bench/class_create-7-inherit.py new file mode 100644 index 00000000000..f48fb215e0a --- /dev/null +++ b/tests/internal_bench/class_create-7-inherit.py @@ -0,0 +1,14 @@ +import bench + + +def test(num): + class B: + pass + + for i in range(num // 40): + + class X(B): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-7.1-inherit_initsubclass.py b/tests/internal_bench/class_create-7.1-inherit_initsubclass.py new file mode 100644 index 00000000000..0660fa86258 --- /dev/null +++ b/tests/internal_bench/class_create-7.1-inherit_initsubclass.py @@ -0,0 +1,16 @@ +import bench + + +def test(num): + class B: + @classmethod + def __init_subclass__(cls): + pass + + for i in range(num // 40): + + class X(B): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-8-metaclass_setname.py b/tests/internal_bench/class_create-8-metaclass_setname.py new file mode 100644 index 00000000000..e4515b54279 --- /dev/null +++ b/tests/internal_bench/class_create-8-metaclass_setname.py @@ -0,0 +1,17 @@ +import bench + + +class D: + def __set_name__(self, owner, name): + pass + + +def test(num): + descriptor = D() + for i in range(num // 40): + + class X: + x = descriptor + + +bench.run(test) diff --git a/tests/internal_bench/class_create-8.1-metaclass_setname5.py b/tests/internal_bench/class_create-8.1-metaclass_setname5.py new file mode 100644 index 00000000000..5daa3f8471b --- /dev/null +++ b/tests/internal_bench/class_create-8.1-metaclass_setname5.py @@ -0,0 +1,21 @@ +import bench + + +class D: + def __set_name__(self, owner, name): + pass + + +def test(num): + descriptor = D() + for i in range(num // 40): + + class X: + a = descriptor + b = descriptor + c = descriptor + d = descriptor + x = descriptor + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-0-object.py b/tests/internal_bench/class_instance-0-object.py new file mode 100644 index 00000000000..401c8ea7e3c --- /dev/null +++ b/tests/internal_bench/class_instance-0-object.py @@ -0,0 +1,11 @@ +import bench + +X = object + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-0.1-object-gc.py b/tests/internal_bench/class_instance-0.1-object-gc.py new file mode 100644 index 00000000000..7c475963a8e --- /dev/null +++ b/tests/internal_bench/class_instance-0.1-object-gc.py @@ -0,0 +1,13 @@ +import bench +import gc + +X = object + + +def test(num): + for i in range(num // 5): + x = X() + gc.collect() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-1-empty.py b/tests/internal_bench/class_instance-1-empty.py new file mode 100644 index 00000000000..617d47a86e9 --- /dev/null +++ b/tests/internal_bench/class_instance-1-empty.py @@ -0,0 +1,13 @@ +import bench + + +class X: + pass + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-1.1-classattr.py b/tests/internal_bench/class_instance-1.1-classattr.py new file mode 100644 index 00000000000..4e667533d4a --- /dev/null +++ b/tests/internal_bench/class_instance-1.1-classattr.py @@ -0,0 +1,13 @@ +import bench + + +class X: + x = 0 + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-1.2-func.py b/tests/internal_bench/class_instance-1.2-func.py new file mode 100644 index 00000000000..21bf7a1ac48 --- /dev/null +++ b/tests/internal_bench/class_instance-1.2-func.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def f(self): + pass + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-1.3-empty-gc.py b/tests/internal_bench/class_instance-1.3-empty-gc.py new file mode 100644 index 00000000000..a5108ef8e81 --- /dev/null +++ b/tests/internal_bench/class_instance-1.3-empty-gc.py @@ -0,0 +1,15 @@ +import bench +import gc + + +class X: + pass + + +def test(num): + for i in range(num // 5): + x = X() + gc.collect() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-2-init.py b/tests/internal_bench/class_instance-2-init.py new file mode 100644 index 00000000000..86619d31548 --- /dev/null +++ b/tests/internal_bench/class_instance-2-init.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def __init__(self): + pass + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-2.1-init_super.py b/tests/internal_bench/class_instance-2.1-init_super.py new file mode 100644 index 00000000000..38bca5fef87 --- /dev/null +++ b/tests/internal_bench/class_instance-2.1-init_super.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def __init__(self): + return super().__init__() + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-2.2-new.py b/tests/internal_bench/class_instance-2.2-new.py new file mode 100644 index 00000000000..dc5e78ea5ef --- /dev/null +++ b/tests/internal_bench/class_instance-2.2-new.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def __new__(cls): + return super().__new__(cls) + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-3-del.py b/tests/internal_bench/class_instance-3-del.py new file mode 100644 index 00000000000..af700f72a94 --- /dev/null +++ b/tests/internal_bench/class_instance-3-del.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def __del__(self): + pass + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-3.1-del-gc.py b/tests/internal_bench/class_instance-3.1-del-gc.py new file mode 100644 index 00000000000..311c71c3571 --- /dev/null +++ b/tests/internal_bench/class_instance-3.1-del-gc.py @@ -0,0 +1,16 @@ +import bench +import gc + + +class X: + def __del__(self): + pass + + +def test(num): + for i in range(num // 5): + x = X() + gc.collect() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-4-slots.py b/tests/internal_bench/class_instance-4-slots.py new file mode 100644 index 00000000000..51b067fedf0 --- /dev/null +++ b/tests/internal_bench/class_instance-4-slots.py @@ -0,0 +1,13 @@ +import bench + + +class X: + __slots__ = ["x"] + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-4.1-slots5.py b/tests/internal_bench/class_instance-4.1-slots5.py new file mode 100644 index 00000000000..8f5c2ecb456 --- /dev/null +++ b/tests/internal_bench/class_instance-4.1-slots5.py @@ -0,0 +1,13 @@ +import bench + + +class X: + __slots__ = ["a", "b", "c", "d", "x"] + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/var-6.2-instance-speciallookup.py b/tests/internal_bench/var-6.2-instance-speciallookup.py new file mode 100644 index 00000000000..fee12b2f930 --- /dev/null +++ b/tests/internal_bench/var-6.2-instance-speciallookup.py @@ -0,0 +1,19 @@ +import bench + + +class Foo: + def __init__(self): + self.num = 20000000 + + def __delattr__(self, name): # just trigger the 'special lookups' flag on the class + pass + + +def test(num): + o = Foo() + i = 0 + while i < o.num: + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-6.3-instance-property.py b/tests/internal_bench/var-6.3-instance-property.py new file mode 100644 index 00000000000..b4426ef7928 --- /dev/null +++ b/tests/internal_bench/var-6.3-instance-property.py @@ -0,0 +1,17 @@ +import bench + + +class Foo: + @property + def num(self): + return 20000000 + + +def test(num): + o = Foo() + i = 0 + while i < o.num: + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-6.4-instance-descriptor.py b/tests/internal_bench/var-6.4-instance-descriptor.py new file mode 100644 index 00000000000..b4df69f878f --- /dev/null +++ b/tests/internal_bench/var-6.4-instance-descriptor.py @@ -0,0 +1,20 @@ +import bench + + +class Descriptor: + def __get__(self, instance, owner=None): + return 20000000 + + +class Foo: + num = Descriptor() + + +def test(num): + o = Foo() + i = 0 + while i < o.num: + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-6.5-instance-getattr.py b/tests/internal_bench/var-6.5-instance-getattr.py new file mode 100644 index 00000000000..3b2ef672110 --- /dev/null +++ b/tests/internal_bench/var-6.5-instance-getattr.py @@ -0,0 +1,16 @@ +import bench + + +class Foo: + def __getattr__(self, name): + return 20000000 + + +def test(num): + o = Foo() + i = 0 + while i < o.num: + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-6.6-instance-builtin_ordered.py b/tests/internal_bench/var-6.6-instance-builtin_ordered.py new file mode 100644 index 00000000000..02d75252301 --- /dev/null +++ b/tests/internal_bench/var-6.6-instance-builtin_ordered.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + i = 0 + o = set() # object with largest rom-frozen ordered locals_dict + n = "__contains__" # last element in that dict for longest lookup + while i < num: + i += hasattr(o, n) # True, converts to 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9-getattr.py b/tests/internal_bench/var-9-getattr.py new file mode 100644 index 00000000000..69d2bfed2e0 --- /dev/null +++ b/tests/internal_bench/var-9-getattr.py @@ -0,0 +1,16 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + o.num = num + i = 0 + while i < getattr(o, "num", num): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.1-getattr_default.py b/tests/internal_bench/var-9.1-getattr_default.py new file mode 100644 index 00000000000..e803d39b326 --- /dev/null +++ b/tests/internal_bench/var-9.1-getattr_default.py @@ -0,0 +1,15 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + i = 0 + while i < getattr(o, "num", num): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.2-getattr_default_special.py b/tests/internal_bench/var-9.2-getattr_default_special.py new file mode 100644 index 00000000000..c48ec0742cf --- /dev/null +++ b/tests/internal_bench/var-9.2-getattr_default_special.py @@ -0,0 +1,16 @@ +import bench + + +class Foo: + def __delattr__(self, name): # just trigger the 'special lookups' flag on the class + pass + + +def test(num): + o = Foo() + i = 0 + while i < getattr(o, "num", num): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.3-except_ok.py b/tests/internal_bench/var-9.3-except_ok.py new file mode 100644 index 00000000000..efc1a8f858c --- /dev/null +++ b/tests/internal_bench/var-9.3-except_ok.py @@ -0,0 +1,23 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + o.num = num + + def get(): + try: + return o.num + except AttributeError: + return num + + i = 0 + while i < get(): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.4-except_selfinduced.py b/tests/internal_bench/var-9.4-except_selfinduced.py new file mode 100644 index 00000000000..544609ca4b6 --- /dev/null +++ b/tests/internal_bench/var-9.4-except_selfinduced.py @@ -0,0 +1,22 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + + def get(): + try: + raise AttributeError + except AttributeError: + return num + + i = 0 + while i < get(): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.5-except_error.py b/tests/internal_bench/var-9.5-except_error.py new file mode 100644 index 00000000000..caf83fa46ab --- /dev/null +++ b/tests/internal_bench/var-9.5-except_error.py @@ -0,0 +1,22 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + + def get(): + try: + return o.num + except AttributeError: + return num + + i = 0 + while i < get(): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.6-except_error_special.py b/tests/internal_bench/var-9.6-except_error_special.py new file mode 100644 index 00000000000..8bc395b4d7e --- /dev/null +++ b/tests/internal_bench/var-9.6-except_error_special.py @@ -0,0 +1,23 @@ +import bench + + +class Foo: + def __delattr__(self, name): # just trigger the 'special lookups' flag on the class + pass + + +def test(num): + o = Foo() + + def get(): + try: + return o.num + except AttributeError: + return num + + i = 0 + while i < get(): + i += 1 + + +bench.run(test) diff --git a/tests/io/builtin_print_file.py b/tests/io/builtin_print_file.py index 822356a6cc3..e00f58635a9 100644 --- a/tests/io/builtin_print_file.py +++ b/tests/io/builtin_print_file.py @@ -13,5 +13,5 @@ try: print(file=1) -except (AttributeError, OSError): # CPython and uPy differ in error message +except (AttributeError, OSError): # CPython and MicroPython differ in error message print("Error") diff --git a/tests/io/file_seek.py b/tests/io/file_seek.py index 3990df84090..b9f9593786f 100644 --- a/tests/io/file_seek.py +++ b/tests/io/file_seek.py @@ -30,5 +30,5 @@ try: f.seek(1) except (OSError, ValueError): - # CPy raises ValueError, uPy raises OSError + # CPy raises ValueError, MPy raises OSError print("OSError or ValueError") diff --git a/tests/micropython/builtin_execfile.py b/tests/micropython/builtin_execfile.py index 75a867bb940..4fd4d66d4ee 100644 --- a/tests/micropython/builtin_execfile.py +++ b/tests/micropython/builtin_execfile.py @@ -75,3 +75,24 @@ def open(self, file, mode): # Unmount the VFS object. vfs.umount(fs) + + +class EvilFilesystem: + def mount(self, readonly, mkfs): + print("mount", readonly, mkfs) + + def umount(self): + print("umount") + + def open(self, file, mode): + return None + + +fs = EvilFilesystem() +vfs.mount(fs, "/test_mnt") +try: + execfile("/test_mnt/test.py") + print("ExecFile succeeded") +except OSError: + print("OSError") +vfs.umount(fs) diff --git a/tests/micropython/builtin_execfile.py.exp b/tests/micropython/builtin_execfile.py.exp index 49703d57076..d93dee547b6 100644 --- a/tests/micropython/builtin_execfile.py.exp +++ b/tests/micropython/builtin_execfile.py.exp @@ -5,3 +5,6 @@ open /test.py rb 123 TypeError umount +mount False False +OSError +umount diff --git a/tests/micropython/const_error.py b/tests/micropython/const_error.py index d35be530a7c..950360e4dc7 100644 --- a/tests/micropython/const_error.py +++ b/tests/micropython/const_error.py @@ -18,8 +18,6 @@ def test_syntax(code): # these operations are not supported within const test_syntax("A = const(1 @ 2)") -test_syntax("A = const(1 / 2)") -test_syntax("A = const(1 ** -2)") test_syntax("A = const(1 << -2)") test_syntax("A = const(1 >> -2)") test_syntax("A = const(1 % 0)") diff --git a/tests/micropython/const_error.py.exp b/tests/micropython/const_error.py.exp index 3edc3efe9c3..bef69eb32ea 100644 --- a/tests/micropython/const_error.py.exp +++ b/tests/micropython/const_error.py.exp @@ -5,5 +5,3 @@ SyntaxError SyntaxError SyntaxError SyntaxError -SyntaxError -SyntaxError diff --git a/tests/micropython/const_float.py b/tests/micropython/const_float.py new file mode 100644 index 00000000000..c3a0df0276b --- /dev/null +++ b/tests/micropython/const_float.py @@ -0,0 +1,23 @@ +# test constant optimisation, with consts that are floats + +from micropython import const + +# check we can make consts from floats +F1 = const(2.5) +F2 = const(-0.3) +print(type(F1), F1) +print(type(F2), F2) + +# check arithmetic with floats +F3 = const(F1 + F2) +F4 = const(F1**2) +print(F3, F4) + +# check int operations with float results +F5 = const(1 / 2) +F6 = const(2**-2) +print(F5, F6) + +# note: we also test float expression folding when +# we're compiling test cases in tests/float, as +# many expressions are resolved at compile time. diff --git a/tests/micropython/const_float.py.exp b/tests/micropython/const_float.py.exp new file mode 100644 index 00000000000..17a86a6d936 --- /dev/null +++ b/tests/micropython/const_float.py.exp @@ -0,0 +1,4 @@ + 2.5 + -0.3 +2.2 6.25 +0.5 0.25 diff --git a/tests/micropython/const_math.py b/tests/micropython/const_math.py new file mode 100644 index 00000000000..7ee5edc6d32 --- /dev/null +++ b/tests/micropython/const_math.py @@ -0,0 +1,18 @@ +# Test expressions based on math module constants +try: + import math +except ImportError: + print("SKIP") + raise SystemExit + +from micropython import const + +# check that we can make consts from math constants +# (skip if the target has MICROPY_COMP_MODULE_CONST disabled) +try: + exec("two_pi = const(2.0 * math.pi)") +except SyntaxError: + print("SKIP") + raise SystemExit + +print(math.cos(two_pi)) diff --git a/tests/micropython/const_math.py.exp b/tests/micropython/const_math.py.exp new file mode 100644 index 00000000000..d3827e75a5c --- /dev/null +++ b/tests/micropython/const_math.py.exp @@ -0,0 +1 @@ +1.0 diff --git a/tests/micropython/decorator_error.py b/tests/micropython/decorator_error.py index 94772ac1e5f..b5eae65b292 100644 --- a/tests/micropython/decorator_error.py +++ b/tests/micropython/decorator_error.py @@ -1,4 +1,4 @@ -# test syntax errors for uPy-specific decorators +# test syntax errors for MicroPython-specific decorators def test_syntax(code): diff --git a/tests/micropython/emg_exc.py b/tests/micropython/emg_exc.py index a74757d028f..cf918b3dc8a 100644 --- a/tests/micropython/emg_exc.py +++ b/tests/micropython/emg_exc.py @@ -1,10 +1,9 @@ # test that emergency exceptions work -import micropython import sys try: - import io + import io, micropython except ImportError: print("SKIP") raise SystemExit diff --git a/tests/micropython/emg_exc.py.native.exp b/tests/micropython/emg_exc.py.native.exp new file mode 100644 index 00000000000..879fa7ef5b9 --- /dev/null +++ b/tests/micropython/emg_exc.py.native.exp @@ -0,0 +1 @@ +ValueError(1,) diff --git a/tests/micropython/extreme_exc.py b/tests/micropython/extreme_exc.py index ad819e408fd..17323b566d3 100644 --- a/tests/micropython/extreme_exc.py +++ b/tests/micropython/extreme_exc.py @@ -1,6 +1,10 @@ # test some extreme cases of allocating exceptions and tracebacks -import micropython +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit # Check for stackless build, which can't call functions without # allocating a frame on the heap. diff --git a/tests/micropython/heap_lock.py b/tests/micropython/heap_lock.py index f2892a6dc58..209a3143461 100644 --- a/tests/micropython/heap_lock.py +++ b/tests/micropython/heap_lock.py @@ -1,6 +1,10 @@ # check that heap_lock/heap_unlock work as expected -import micropython +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit l = [] l2 = list(range(100)) diff --git a/tests/micropython/heap_locked.py b/tests/micropython/heap_locked.py index d9e5b5d4090..d9d99493dd6 100644 --- a/tests/micropython/heap_locked.py +++ b/tests/micropython/heap_locked.py @@ -1,8 +1,10 @@ # test micropython.heap_locked() -import micropython +try: + import micropython -if not hasattr(micropython, "heap_locked"): + micropython.heap_locked +except (AttributeError, ImportError): print("SKIP") raise SystemExit diff --git a/tests/micropython/heapalloc.py b/tests/micropython/heapalloc.py index e19f8d0255d..010bf878a07 100644 --- a/tests/micropython/heapalloc.py +++ b/tests/micropython/heapalloc.py @@ -1,6 +1,10 @@ # check that we can do certain things without allocating heap memory -import micropython +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit # Check for stackless build, which can't call functions without # allocating a frame on heap. diff --git a/tests/micropython/heapalloc_exc_compressed.py b/tests/micropython/heapalloc_exc_compressed.py index aa071d641c2..96fe3ca4f7e 100644 --- a/tests/micropython/heapalloc_exc_compressed.py +++ b/tests/micropython/heapalloc_exc_compressed.py @@ -1,4 +1,10 @@ -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # Tests both code paths for built-in exception raising. # mp_obj_new_exception_msg_varg (exception requires decompression at raise-time to format) diff --git a/tests/micropython/heapalloc_exc_compressed_emg_exc.py b/tests/micropython/heapalloc_exc_compressed_emg_exc.py index 48ce9dd69e6..31d937b8f93 100644 --- a/tests/micropython/heapalloc_exc_compressed_emg_exc.py +++ b/tests/micropython/heapalloc_exc_compressed_emg_exc.py @@ -1,4 +1,10 @@ -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # Does the full test from heapalloc_exc_compressed.py but while the heap is # locked (this can only work when the emergency exception buf is enabled). diff --git a/tests/micropython/heapalloc_exc_raise.py b/tests/micropython/heapalloc_exc_raise.py index 99810e00750..917ccf42f1e 100644 --- a/tests/micropython/heapalloc_exc_raise.py +++ b/tests/micropython/heapalloc_exc_raise.py @@ -1,6 +1,12 @@ # Test that we can raise and catch (preallocated) exception # without memory allocation. -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit e = ValueError("error") diff --git a/tests/micropython/heapalloc_fail_bytearray.py b/tests/micropython/heapalloc_fail_bytearray.py index 1bf7ddd600b..9ee73d1c583 100644 --- a/tests/micropython/heapalloc_fail_bytearray.py +++ b/tests/micropython/heapalloc_fail_bytearray.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with bytearray -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit class GetSlice: diff --git a/tests/micropython/heapalloc_fail_dict.py b/tests/micropython/heapalloc_fail_dict.py index ce2d158bd09..04c79183578 100644 --- a/tests/micropython/heapalloc_fail_dict.py +++ b/tests/micropython/heapalloc_fail_dict.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with dict -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # create dict x = 1 diff --git a/tests/micropython/heapalloc_fail_list.py b/tests/micropython/heapalloc_fail_list.py index 9a2e9a555f3..7afb6dc1019 100644 --- a/tests/micropython/heapalloc_fail_list.py +++ b/tests/micropython/heapalloc_fail_list.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with list -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit class GetSlice: diff --git a/tests/micropython/heapalloc_fail_memoryview.py b/tests/micropython/heapalloc_fail_memoryview.py index da2d1abffa6..17e3e126247 100644 --- a/tests/micropython/heapalloc_fail_memoryview.py +++ b/tests/micropython/heapalloc_fail_memoryview.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with memoryview -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit class GetSlice: diff --git a/tests/micropython/heapalloc_fail_set.py b/tests/micropython/heapalloc_fail_set.py index 3c347660ad7..0c4d85eef62 100644 --- a/tests/micropython/heapalloc_fail_set.py +++ b/tests/micropython/heapalloc_fail_set.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with set -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # create set x = 1 diff --git a/tests/micropython/heapalloc_fail_tuple.py b/tests/micropython/heapalloc_fail_tuple.py index de79385e3e3..11718a8107b 100644 --- a/tests/micropython/heapalloc_fail_tuple.py +++ b/tests/micropython/heapalloc_fail_tuple.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with tuple -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # create tuple x = 1 diff --git a/tests/micropython/heapalloc_inst_call.py b/tests/micropython/heapalloc_inst_call.py index 14d8826bf06..f78aa3cf877 100644 --- a/tests/micropython/heapalloc_inst_call.py +++ b/tests/micropython/heapalloc_inst_call.py @@ -1,6 +1,13 @@ # Test that calling clazz.__call__() with up to at least 3 arguments # doesn't require heap allocation. -import micropython + +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit class Foo0: diff --git a/tests/micropython/heapalloc_int_from_bytes.py b/tests/micropython/heapalloc_int_from_bytes.py index 5fe50443ae3..3310ea95d14 100644 --- a/tests/micropython/heapalloc_int_from_bytes.py +++ b/tests/micropython/heapalloc_int_from_bytes.py @@ -1,6 +1,13 @@ # Test that int.from_bytes() for small number of bytes generates # small int. -import micropython + +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit micropython.heap_lock() print(int.from_bytes(b"1", "little")) diff --git a/tests/micropython/heapalloc_slice.py b/tests/micropython/heapalloc_slice.py new file mode 100644 index 00000000000..62d96595c71 --- /dev/null +++ b/tests/micropython/heapalloc_slice.py @@ -0,0 +1,18 @@ +# slice operations that don't require allocation +try: + from micropython import heap_lock, heap_unlock +except (ImportError, AttributeError): + heap_lock = heap_unlock = lambda: 0 + +b = bytearray(range(10)) + +m = memoryview(b) + +heap_lock() + +b[3:5] = b"aa" +m[5:7] = b"bb" + +heap_unlock() + +print(b) diff --git a/tests/micropython/heapalloc_str.py b/tests/micropython/heapalloc_str.py index 39aa56ccd78..6372df5d37b 100644 --- a/tests/micropython/heapalloc_str.py +++ b/tests/micropython/heapalloc_str.py @@ -1,5 +1,12 @@ # String operations which don't require allocation -import micropython + +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit micropython.heap_lock() diff --git a/tests/micropython/heapalloc_super.py b/tests/micropython/heapalloc_super.py index 51afae3d83d..6839eee330a 100644 --- a/tests/micropython/heapalloc_super.py +++ b/tests/micropython/heapalloc_super.py @@ -1,5 +1,12 @@ # test super() operations which don't require allocation -import micropython + +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # Check for stackless build, which can't call functions without # allocating a frame on heap. diff --git a/tests/micropython/heapalloc_traceback.py.native.exp b/tests/micropython/heapalloc_traceback.py.native.exp new file mode 100644 index 00000000000..d6ac26aa829 --- /dev/null +++ b/tests/micropython/heapalloc_traceback.py.native.exp @@ -0,0 +1,3 @@ +StopIteration +StopIteration: + diff --git a/tests/micropython/heapalloc_yield_from.py b/tests/micropython/heapalloc_yield_from.py index 95071718908..9d4f8c6940f 100644 --- a/tests/micropython/heapalloc_yield_from.py +++ b/tests/micropython/heapalloc_yield_from.py @@ -1,6 +1,12 @@ # Check that yield-from can work without heap allocation -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # Yielding from a function generator diff --git a/tests/micropython/import_mpy_native.py b/tests/micropython/import_mpy_native.py index ad63e025db2..59181b203bb 100644 --- a/tests/micropython/import_mpy_native.py +++ b/tests/micropython/import_mpy_native.py @@ -54,12 +54,13 @@ def open(self, path, mode): # these are the test .mpy files # CIRCUITPY-CHANGE -valid_header = bytes([ord("C"), 6, mpy_arch, 31]) +small_int_bits = 31 +valid_header = bytes([77, 6, (mpy_arch & 0x3F), small_int_bits]) # fmt: off user_files = { # bad architecture (mpy_arch needed for sub-version) # CIRCUITPY-CHANGE - '/mod0.mpy': bytes([ord('C'), 6, 0xfc | mpy_arch, 31]), + '/mod0.mpy': bytes([ord('C'), 6, 0xfc | (mpy_arch & 3), small_int_bits]), # test loading of viper and asm '/mod1.mpy': valid_header + ( diff --git a/tests/micropython/import_mpy_native_gc.py b/tests/micropython/import_mpy_native_gc.py index 0d5b79f0a8d..5159cc9e9f9 100644 --- a/tests/micropython/import_mpy_native_gc.py +++ b/tests/micropython/import_mpy_native_gc.py @@ -57,9 +57,13 @@ def open(self, path, mode): # CIRCUITPY-CHANGE: 'C' instead of 'M' mpy marker. features0_file_contents = { # -march=x64 - 0x806: b'C\x06\n\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x8a\x02\xe93\x00\x00\x00\xf3\x0f\x1e\xfaSH\x8b\x1d\x7f\x00\x00\x00\xbe\x02\x00\x00\x00\xffS\x18\xbf\x01\x00\x00\x00H\x85\xc0u\x0cH\x8bC \xbe\x02\x00\x00\x00[\xff\xe0H\x0f\xaf\xf8H\xff\xc8\xeb\xe6\xf3\x0f\x1e\xfaATUSH\x8b\x1dI\x00\x00\x00H\x8bG\x08L\x8bc(H\x8bx\x08A\xff\xd4H\x8d5#\x00\x00\x00H\x89\xc5H\x8b\x051\x00\x00\x00\x0f\xb7x\x02\xffShH\x89\xefA\xff\xd4H\x8b\x03[]A\\\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x11$\r&\xa5 \x01"\xff', + 0x806: b"C\x06\x0b\x1f\x03\x002build/test_x64.native.mpy\x00\x08add1\x00\x0cunused\x00\x91B\xe9I\x00\x00\x00H\x8b\x05\xf4\x00\x00\x00H\x8b\x00\xc3H\x8b\x05\xf9\x00\x00\x00\xbe\x02\x00\x00\x00\x8b8H\x8b\x05\xdb\x00\x00\x00H\x8b@ \xff\xe0H\x8b\x05\xce\x00\x00\x00S\xbe\x02\x00\x00\x00H\x8bX \xffP\x18\xbe\x02\x00\x00\x00H\x8dx\x01H\x89\xd8[\xff\xe0AVAUATUSH\x8b\x1d\xa3\x00\x00\x00H\x8bG\x08L\x8bk(H\x8bx\x08A\xff\xd5L\x8b5\x95\x00\x00\x00L\x8bchH\x8d5r\x00\x00\x00H\x89\xc5H\x8b\x05\x88\x00\x00\x00A\x0f\xb7~\x04\xc7\x00@\xe2\x01\x00A\xff\xd4H\x8d5C\x00\x00\x00\xbfV\x00\x00\x00A\xff\xd4A\x0f\xb7~\x02H\x8d5\x1f\x00\x00\x00A\xff\xd4H\x89\xefA\xff\xd5H\x8b\x03[]A\\A]A^\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x04\x11@\rB\tD\xaf4\x016\xad8\x01:\xaf<\x01>\xff", # -march=armv6m - 0x1006: b"C\x06\x12\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x88\x02\x18\xe0\x00\x00\x10\xb5\tK\tJ{D\x9cX\x02!\xe3h\x98G\x03\x00\x01 \x00+\x02\xd0XC\x01;\xfa\xe7\x02!#i\x98G\x10\xbd\xc0Fj\x00\x00\x00\x00\x00\x00\x00\xf8\xb5\nN\nK~D\xf4XChgiXh\xb8G\x05\x00\x07K\x08I\xf3XyDX\x88ck\x98G(\x00\xb8G h\xf8\xbd\xc0F:\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x11<\r>\xa58\x01:\xff", + 0x1006: b"C\x06\x13\x1f\x03\x008build/test_armv6m.native.mpy\x00\x08add1\x00\x0cunused\x00\x8eb0\xe0\x00\x00\x00\x00\x00\x00\x02K\x03J{D\x9bX\x18hpG\xd0\x00\x00\x00\x00\x00\x00\x00\x10\xb5\x05K\x05I\x06J{D\x9aX[X\x10h\x02!\x1bi\x98G\x10\xbd\xb8\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x10\xb5\x06K\x06J{D\x9bX\x02!\x1ci\xdbh\x98G\x02!\x010\xa0G\x10\xbd\xc0F\x96\x00\x00\x00\x00\x00\x00\x00\xf7\xb5\x12O\x12K\x7fD\xfdX\x12Lki|D\x00\x93ChXh\x00\x9b\x98G\x0fK\x01\x90\x0fJ\xfbXnk\x1a`\x0eK!\x00\xffX\xb8\x88\xb0G!\x00V \x081\xb0G!\x00x\x88\x101\xb0G\x01\x98\x00\x9b\x98G(h\xfe\xbd\xc0Fr\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x08\x00\x00\x00@\xe2\x01\x00\x04\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x04\x11p\rr\tt\xafd\x01f\xadh\x01j\xafl\x01n\xff", + # -march=xtensawin + 0x2806: b"C\x06+\x1f\x03\x00>build/test_xtensawin.native.mpy\x00\x08add1\x00\x0cunused\x00\x8a\x12\x06\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x006A\x00\x81\xf9\xff(\x08\x1d\xf0\x00\x006A\x00\x91\xfb\xff\x81\xf5\xff\xa8\t\x88H\x0c+\xe0\x08\x00-\n\x1d\xf0\x00\x006A\x00\x81\xf0\xff\xad\x02xH\x888\x0c+\xe0\x08\x00\x0c+\x1b\xaa\xe0\x07\x00-\n\x1d\xf06A\x00a\xe9\xff\x88\x122&\x05\xa2(\x01\xe0\x03\x00q\xe6\xff\x81\xea\xff\x92\xa7\x89\xa0\x99\x11H\xd6]\n\xb1\xe3\xff\xa2\x17\x02\x99\x08\xe0\x04\x00\xb1\xe2\xff\\j\xe0\x04\x00\xb1\xe1\xff\xa2\x17\x01\xe0\x04\x00\xad\x05\xe0\x03\x00(\x06\x1d\xf0p\x18\x04\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x11\x02\r\x04\x07\x06\x03\t\x0c\xaf\x01\x01\x03\xad\x05\x01\x07\xaf\t\x01\x0b\xff", + # -march=rv32imc + 0x2C06: b'C\x06/\x1f\x03\x00:build/test_rv32imc.native.mpy\x00\x08add1\x00\x0cunused\x00\x8fb\x97\x0f\x00\x00g\x80\x0f\x05\x97\x07\x00\x00\x83\xa7\x07\x0e\x88C\x82\x80\x97\x07\x00\x00\x83\xa7G\r\x17\x07\x00\x00\x03\'\xc7\r\x9cK\x08C\x89E\x82\x87A\x11\x97\x07\x00\x00\x83\xa7\xa7\x0b"\xc4\x80K\xdcG\x06\xc6\x89E\x82\x97\xa2\x87"D\xb2@\x89E\x05\x05A\x01\x82\x87\\A\x01\x11"\xcc\x17\x04\x00\x00\x03$$\tN\xc6\xc8C\x83)D\x01\x06\xce&\xcaJ\xc8R\xc4\x82\x99\x17\n\x00\x00\x03*\xca\x07\x03)D\x03\xaa\x84\xf9g\x03UJ\x00\x93\x87\x07$\x17\x07\x00\x00\x03\'\x07\x07\x1c\xc3\x97\x05\x00\x00\x93\x85\xe5\x03\x02\x99\x97\x05\x00\x00\x93\x85\xc5\x03\x13\x05`\x05\x02\x99\x03U*\x00\x97\x05\x00\x00\x93\x85%\x03\x02\x99&\x85\x82\x99\x08@\xf2@bD\xd2DBI\xb2I"J\x05a\x82\x80\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x04\x11t\rv\xafx\xadz\t|\xafh\x01j\xadl\x01n\xafp\x01r\xff', } # Populate armv7m-derived archs based on armv6m. @@ -67,7 +71,7 @@ def open(self, path, mode): features0_file_contents[arch] = features0_file_contents[0x1006] # Check that a .mpy exists for the target (ignore sub-version in lookup). -sys_implementation_mpy = sys.implementation._mpy & ~(3 << 8) +sys_implementation_mpy = (sys.implementation._mpy & ~(3 << 8)) & 0xFFFF if sys_implementation_mpy not in features0_file_contents: print("SKIP") raise SystemExit diff --git a/tests/micropython/kbd_intr.py b/tests/micropython/kbd_intr.py index 81977aaa52f..e1ed7185ef0 100644 --- a/tests/micropython/kbd_intr.py +++ b/tests/micropython/kbd_intr.py @@ -1,10 +1,10 @@ # test the micropython.kbd_intr() function -import micropython - try: + import micropython + micropython.kbd_intr -except AttributeError: +except (ImportError, AttributeError): print("SKIP") raise SystemExit diff --git a/tests/micropython/meminfo.py b/tests/micropython/meminfo.py index 9df341fbb83..f4dd8fdb604 100644 --- a/tests/micropython/meminfo.py +++ b/tests/micropython/meminfo.py @@ -1,12 +1,14 @@ # tests meminfo functions in micropython module -import micropython +try: + import micropython -# these functions are not always available -if not hasattr(micropython, "mem_info"): + micropython.mem_info +except (ImportError, AttributeError): print("SKIP") -else: - micropython.mem_info() - micropython.mem_info(1) - micropython.qstr_info() - micropython.qstr_info(1) + raise SystemExit + +micropython.mem_info() +micropython.mem_info(1) +micropython.qstr_info() +micropython.qstr_info(1) diff --git a/tests/micropython/memstats.py b/tests/micropython/memstats.py index dee3a4ce2f2..0e2e7b1c0b3 100644 --- a/tests/micropython/memstats.py +++ b/tests/micropython/memstats.py @@ -1,17 +1,19 @@ # tests meminfo functions in micropython module -import micropython +try: + import micropython -# these functions are not always available -if not hasattr(micropython, "mem_total"): + micropython.mem_total +except (ImportError, AttributeError): print("SKIP") -else: - t = micropython.mem_total() - c = micropython.mem_current() - p = micropython.mem_peak() + raise SystemExit - l = list(range(10000)) +t = micropython.mem_total() +c = micropython.mem_current() +p = micropython.mem_peak() - print(micropython.mem_total() > t) - print(micropython.mem_current() > c) - print(micropython.mem_peak() > p) +l = list(range(10000)) + +print(micropython.mem_total() > t) +print(micropython.mem_current() > c) +print(micropython.mem_peak() > p) diff --git a/tests/micropython/opt_level.py b/tests/micropython/opt_level.py index dd5493a7a3c..789197d8825 100644 --- a/tests/micropython/opt_level.py +++ b/tests/micropython/opt_level.py @@ -1,4 +1,10 @@ -import micropython as micropython +# test micropython.opt_level() + +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit # check we can get and set the level micropython.opt_level(0) diff --git a/tests/micropython/opt_level_lineno.py b/tests/micropython/opt_level_lineno.py index 40650b68192..4ca76625de4 100644 --- a/tests/micropython/opt_level_lineno.py +++ b/tests/micropython/opt_level_lineno.py @@ -1,7 +1,24 @@ -import micropython as micropython +# test micropython.opt_level() and line numbers + +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit # check that level 3 doesn't store line numbers # the expected output is that any line is printed as "line 1" micropython.opt_level(3) -# CIRCUITPY-CHANGE: use traceback.print_exception() instead of sys.print_exception() -exec("try:\n xyz\nexcept NameError as er:\n import traceback\n traceback.print_exception(er)") + +# force bytecode emitter, because native emitter doesn't store line numbers +exec(""" +@micropython.bytecode +def f(): + try: + xyz + except NameError as er: + # CIRCUITPY-CHANGE: use traceback.print_exception() instead of sys.print_exception() + import traceback + traceback.print_exception(er) +f() +""") diff --git a/tests/micropython/opt_level_lineno.py.exp b/tests/micropython/opt_level_lineno.py.exp index 469b90ba793..b50f0628c81 100644 --- a/tests/micropython/opt_level_lineno.py.exp +++ b/tests/micropython/opt_level_lineno.py.exp @@ -1,3 +1,3 @@ Traceback (most recent call last): - File "", line 1, in + File "", line 1, in f NameError: name 'xyz' isn't defined diff --git a/tests/micropython/ringio_big.py b/tests/micropython/ringio_big.py new file mode 100644 index 00000000000..ddbbae12a63 --- /dev/null +++ b/tests/micropython/ringio_big.py @@ -0,0 +1,29 @@ +# Check that micropython.RingIO works correctly. + +try: + import micropython + + micropython.RingIO +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +try: + # The maximum possible size + micropython.RingIO(bytearray(65535)) + micropython.RingIO(65534) + + try: + # Buffer may not be too big + micropython.RingIO(bytearray(65536)) + except ValueError as ex: + print(type(ex)) + + try: + # Size may not be too big + micropython.RingIO(65535) + except ValueError as ex: + print(type(ex)) +except MemoryError: + print("SKIP") + raise SystemExit diff --git a/tests/micropython/ringio_big.py.exp b/tests/micropython/ringio_big.py.exp new file mode 100644 index 00000000000..72af34b3838 --- /dev/null +++ b/tests/micropython/ringio_big.py.exp @@ -0,0 +1,2 @@ + + diff --git a/tests/micropython/schedule.py b/tests/micropython/schedule.py index 6a91459ea3d..f3dd3266126 100644 --- a/tests/micropython/schedule.py +++ b/tests/micropython/schedule.py @@ -1,10 +1,10 @@ # test micropython.schedule() function -import micropython - try: + import micropython + micropython.schedule -except AttributeError: +except (ImportError, AttributeError): print("SKIP") raise SystemExit diff --git a/tests/micropython/stack_use.py b/tests/micropython/stack_use.py index 266885d9d18..5d36fdca2fe 100644 --- a/tests/micropython/stack_use.py +++ b/tests/micropython/stack_use.py @@ -1,7 +1,11 @@ # tests stack_use function in micropython module -import micropython -if not hasattr(micropython, "stack_use"): +try: + import micropython + + micropython.stack_use +except (ImportError, AttributeError): print("SKIP") -else: - print(type(micropython.stack_use())) # output varies + raise SystemExit + +print(type(micropython.stack_use())) # output varies diff --git a/tests/micropython/test_normalize_newlines.py b/tests/micropython/test_normalize_newlines.py new file mode 100644 index 00000000000..f19aaa69a3f --- /dev/null +++ b/tests/micropython/test_normalize_newlines.py @@ -0,0 +1,14 @@ +# Test for normalize_newlines functionality +# This test verifies that test framework handles various newline combinations correctly + +# Note: This is more of an integration test since normalize_newlines is in the test framework +# The actual testing happens when this test is run through run-tests.py + +print("Testing newline handling") +print("Line 1\r\nLine 2") # Windows-style line ending - should be normalized +print("Line 3") # Normal line +print("Line 4") # Normal line +print("Line 5\nLine 6") # Unix-style line ending - already normalized + +# Test that literal \r in strings is preserved +print(repr("test\rstring")) # Should show 'test\rstring' not 'test\nstring' diff --git a/tests/micropython/test_normalize_newlines.py.exp b/tests/micropython/test_normalize_newlines.py.exp new file mode 100644 index 00000000000..c4395468cf1 --- /dev/null +++ b/tests/micropython/test_normalize_newlines.py.exp @@ -0,0 +1,8 @@ +Testing newline handling +Line 1 +Line 2 +Line 3 +Line 4 +Line 5 +Line 6 +'test\rstring' diff --git a/tests/micropython/viper_large_jump.py b/tests/micropython/viper_large_jump.py new file mode 100644 index 00000000000..1c5913dec1e --- /dev/null +++ b/tests/micropython/viper_large_jump.py @@ -0,0 +1,20 @@ +COUNT = 600 + + +try: + code = """ +@micropython.viper +def f() -> int: + x = 0 + while x < 10: +""" + for i in range(COUNT): + code += " x += 1\n" + code += " return x" + exec(code) +except MemoryError: + print("SKIP-TOO-LARGE") + raise SystemExit + + +print(f()) diff --git a/tests/micropython/viper_large_jump.py.exp b/tests/micropython/viper_large_jump.py.exp new file mode 100644 index 00000000000..e9f960cf4ac --- /dev/null +++ b/tests/micropython/viper_large_jump.py.exp @@ -0,0 +1 @@ +600 diff --git a/tests/micropython/viper_ptr16_load_boundary.py b/tests/micropython/viper_ptr16_load_boundary.py new file mode 100644 index 00000000000..0d4c3105b68 --- /dev/null +++ b/tests/micropython/viper_ptr16_load_boundary.py @@ -0,0 +1,39 @@ +# Test boundary conditions for various architectures + +GET_TEMPLATE = """ +@micropython.viper +def get{off}(src: ptr16) -> uint: + return uint(src[{off}]) +print(hex(get{off}(buffer))) +""" + + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 2 + + +@micropython.viper +def get_index(src: ptr16, i: int) -> int: + return src[i] + + +def data(start, len): + output = bytearray(len) + for idx in range(len): + output[idx] = (start + idx) & 0xFF + return output + + +buffer = bytearray((((1 << max(BIT_THRESHOLDS)) + 1) // 1024) * 1024) +val = 0 +for bit in BIT_THRESHOLDS: + print("---", bit) + pre, idx, post = ((1 << bit) - (2 * SIZE), (1 << bit) - (1 * SIZE), 1 << bit) + buffer[pre:post] = data(val, 3 * SIZE) + val = val + (3 * SIZE) + + pre, idx, post = pre // SIZE, idx // SIZE, post // SIZE + print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post))) + exec(GET_TEMPLATE.format(off=pre)) + exec(GET_TEMPLATE.format(off=idx)) + exec(GET_TEMPLATE.format(off=post)) diff --git a/tests/micropython/viper_ptr16_load_boundary.py.exp b/tests/micropython/viper_ptr16_load_boundary.py.exp new file mode 100644 index 00000000000..56f1d322904 --- /dev/null +++ b/tests/micropython/viper_ptr16_load_boundary.py.exp @@ -0,0 +1,20 @@ +--- 5 +0x100 0x302 0x504 +0x100 +0x302 +0x504 +--- 8 +0x706 0x908 0xb0a +0x706 +0x908 +0xb0a +--- 11 +0xd0c 0xf0e 0x1110 +0xd0c +0xf0e +0x1110 +--- 12 +0x1312 0x1514 0x1716 +0x1312 +0x1514 +0x1716 diff --git a/tests/micropython/viper_ptr16_store_boundary.py b/tests/micropython/viper_ptr16_store_boundary.py new file mode 100644 index 00000000000..7c774d4d1ca --- /dev/null +++ b/tests/micropython/viper_ptr16_store_boundary.py @@ -0,0 +1,63 @@ +# Test boundary conditions for various architectures + +SET_TEMPLATE = """ +@micropython.viper +def set{off}(dest: ptr16): + saved = dest + dest[{off}] = {val} + assert int(saved) == int(dest) +""" + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 2 +MASK = (1 << (8 * SIZE)) - 1 + +next_int = 1 +test_buffer = bytearray(SIZE) + + +def next_value() -> uint: + global next_int + global test_buffer + for index in range(1, SIZE): + test_buffer[index - 1] = test_buffer[index] + test_buffer[SIZE - 1] = next_int + next_int += 1 + output = 0 + for byte in test_buffer: + output = (output << 8) | byte + return output & MASK + + +def get_index(src, i): + return src[i * SIZE] + (src[(i * SIZE) + 1] << 8) + + +@micropython.viper +def set_index(dest: ptr16, i: int, val: uint): + saved = dest + dest[i] = val + assert int(saved) == int(dest) + + +try: + buffer = bytearray((((1 << max(BIT_THRESHOLDS)) // 1024) + 1) * 1024) + + for bit in BIT_THRESHOLDS: + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + exec(SET_TEMPLATE.format(off=(offset + index) // SIZE, val=next_value())) +except MemoryError: + print("SKIP-TOO-LARGE") + raise SystemExit + + +for bit in BIT_THRESHOLDS: + print("---", bit) + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + globals()["set{}".format((offset + index) // SIZE)](buffer) + print(hex(get_index(buffer, (offset + index) // SIZE))) + for index in range(0, 3 * SIZE, SIZE): + set_index(buffer, (offset + index) // SIZE, next_value()) + print(hex(get_index(buffer, (offset + index) // SIZE))) diff --git a/tests/micropython/viper_ptr16_store_boundary.py.exp b/tests/micropython/viper_ptr16_store_boundary.py.exp new file mode 100644 index 00000000000..007a50b3eda --- /dev/null +++ b/tests/micropython/viper_ptr16_store_boundary.py.exp @@ -0,0 +1,28 @@ +--- 5 +0x1 +0x102 +0x203 +0xc0d +0xd0e +0xe0f +--- 8 +0x304 +0x405 +0x506 +0xf10 +0x1011 +0x1112 +--- 11 +0x607 +0x708 +0x809 +0x1213 +0x1314 +0x1415 +--- 12 +0x90a +0xa0b +0xb0c +0x1516 +0x1617 +0x1718 diff --git a/tests/micropython/viper_ptr32_load_boundary.py b/tests/micropython/viper_ptr32_load_boundary.py new file mode 100644 index 00000000000..971d1113c49 --- /dev/null +++ b/tests/micropython/viper_ptr32_load_boundary.py @@ -0,0 +1,39 @@ +# Test boundary conditions for various architectures + +GET_TEMPLATE = """ +@micropython.viper +def get{off}(src: ptr32) -> uint: + return uint(src[{off}]) +print(hex(get{off}(buffer))) +""" + + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 4 + + +@micropython.viper +def get_index(src: ptr32, i: int) -> int: + return src[i] + + +def data(start, len): + output = bytearray(len) + for idx in range(len): + output[idx] = (start + idx) & 0xFF + return output + + +buffer = bytearray((((1 << max(BIT_THRESHOLDS)) + 1) // 1024) * 1024) +val = 0 +for bit in BIT_THRESHOLDS: + print("---", bit) + pre, idx, post = (((1 << bit) - (2 * SIZE)), ((1 << bit) - (1 * SIZE)), (1 << bit)) + buffer[pre:post] = data(val, 3 * SIZE) + val = val + (3 * SIZE) + + pre, idx, post = pre // SIZE, idx // SIZE, post // SIZE + print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post))) + exec(GET_TEMPLATE.format(off=pre)) + exec(GET_TEMPLATE.format(off=idx)) + exec(GET_TEMPLATE.format(off=post)) diff --git a/tests/micropython/viper_ptr32_load_boundary.py.exp b/tests/micropython/viper_ptr32_load_boundary.py.exp new file mode 100644 index 00000000000..1e22a8b3613 --- /dev/null +++ b/tests/micropython/viper_ptr32_load_boundary.py.exp @@ -0,0 +1,20 @@ +--- 5 +0x3020100 0x7060504 0xb0a0908 +0x3020100 +0x7060504 +0xb0a0908 +--- 8 +0xf0e0d0c 0x13121110 0x17161514 +0xf0e0d0c +0x13121110 +0x17161514 +--- 11 +0x1b1a1918 0x1f1e1d1c 0x23222120 +0x1b1a1918 +0x1f1e1d1c +0x23222120 +--- 12 +0x27262524 0x2b2a2928 0x2f2e2d2c +0x27262524 +0x2b2a2928 +0x2f2e2d2c diff --git a/tests/micropython/viper_ptr32_store_boundary.py b/tests/micropython/viper_ptr32_store_boundary.py new file mode 100644 index 00000000000..96ca74ad3ca --- /dev/null +++ b/tests/micropython/viper_ptr32_store_boundary.py @@ -0,0 +1,68 @@ +# Test boundary conditions for various architectures + +SET_TEMPLATE = """ +@micropython.viper +def set{off}(dest: ptr32): + saved = dest + dest[{off}] = {val} + assert int(saved) == int(dest) +""" + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 4 +MASK = (1 << (8 * SIZE)) - 1 + +next_int = 1 +test_buffer = bytearray(SIZE) + + +def next_value() -> uint: + global next_int + global test_buffer + for index in range(1, SIZE): + test_buffer[index - 1] = test_buffer[index] + test_buffer[SIZE - 1] = next_int + next_int += 1 + output = 0 + for byte in test_buffer: + output = (output << 8) | byte + return output & MASK + + +def get_index(src, i): + return ( + src[i * SIZE] + + (src[(i * SIZE) + 1] << 8) + + (src[(i * SIZE) + 2] << 16) + + (src[(i * SIZE) + 3] << 24) + ) + + +@micropython.viper +def set_index(dest: ptr32, i: int, val: uint): + saved = dest + dest[i] = val + assert int(dest) == int(saved) + + +try: + buffer = bytearray((((1 << max(BIT_THRESHOLDS)) // 1024) + 1) * 1024) + + for bit in BIT_THRESHOLDS: + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + exec(SET_TEMPLATE.format(off=(offset + index) // SIZE, val=next_value())) +except MemoryError: + print("SKIP-TOO-LARGE") + raise SystemExit + + +for bit in BIT_THRESHOLDS: + print("---", bit) + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + globals()["set{}".format((offset + index) // SIZE)](buffer) + print(hex(get_index(buffer, (offset + index) // SIZE))) + for index in range(0, 3 * SIZE, SIZE): + set_index(buffer, (offset + index) // SIZE, next_value()) + print(hex(get_index(buffer, (offset + index) // SIZE))) diff --git a/tests/micropython/viper_ptr32_store_boundary.py.exp b/tests/micropython/viper_ptr32_store_boundary.py.exp new file mode 100644 index 00000000000..7a9a5162474 --- /dev/null +++ b/tests/micropython/viper_ptr32_store_boundary.py.exp @@ -0,0 +1,28 @@ +--- 5 +0x1 +0x102 +0x10203 +0xa0b0c0d +0xb0c0d0e +0xc0d0e0f +--- 8 +0x1020304 +0x2030405 +0x3040506 +0xd0e0f10 +0xe0f1011 +0xf101112 +--- 11 +0x4050607 +0x5060708 +0x6070809 +0x10111213 +0x11121314 +0x12131415 +--- 12 +0x708090a +0x8090a0b +0x90a0b0c +0x13141516 +0x14151617 +0x15161718 diff --git a/tests/micropython/viper_ptr8_load_boundary.py b/tests/micropython/viper_ptr8_load_boundary.py new file mode 100644 index 00000000000..57e06da5709 --- /dev/null +++ b/tests/micropython/viper_ptr8_load_boundary.py @@ -0,0 +1,38 @@ +# Test boundary conditions for various architectures + +GET_TEMPLATE = """ +@micropython.viper +def get{off}(src: ptr8) -> uint: + return uint(src[{off}]) +print(hex(get{off}(buffer))) +""" + + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 1 + + +@micropython.viper +def get_index(src: ptr8, i: int) -> int: + return src[i] + + +def data(start, len): + output = bytearray(len) + for idx in range(len): + output[idx] = (start + idx) & 0xFF + return output + + +buffer = bytearray((((1 << max(BIT_THRESHOLDS)) + 1) // 1024) * 1024) +val = 0 +for bit in BIT_THRESHOLDS: + print("---", bit) + pre, idx, post = (((1 << bit) - (2 * SIZE)), ((1 << bit) - (1 * SIZE)), (1 << bit)) + buffer[pre:post] = data(val, 3 * SIZE) + val = val + (3 * SIZE) + + print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post))) + exec(GET_TEMPLATE.format(off=pre)) + exec(GET_TEMPLATE.format(off=idx)) + exec(GET_TEMPLATE.format(off=post)) diff --git a/tests/micropython/viper_ptr8_load_boundary.py.exp b/tests/micropython/viper_ptr8_load_boundary.py.exp new file mode 100644 index 00000000000..a0e423686b8 --- /dev/null +++ b/tests/micropython/viper_ptr8_load_boundary.py.exp @@ -0,0 +1,20 @@ +--- 5 +0x0 0x1 0x2 +0x0 +0x1 +0x2 +--- 8 +0x3 0x4 0x5 +0x3 +0x4 +0x5 +--- 11 +0x6 0x7 0x8 +0x6 +0x7 +0x8 +--- 12 +0x9 0xa 0xb +0x9 +0xa +0xb diff --git a/tests/micropython/viper_ptr8_store_boundary.py b/tests/micropython/viper_ptr8_store_boundary.py new file mode 100644 index 00000000000..68b76fd598b --- /dev/null +++ b/tests/micropython/viper_ptr8_store_boundary.py @@ -0,0 +1,63 @@ +# Test boundary conditions for various architectures + +SET_TEMPLATE = """ +@micropython.viper +def set{off}(dest: ptr8): + saved = dest + dest[{off}] = {val} + assert int(saved) == int(dest) +""" + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 1 +MASK = (1 << (8 * SIZE)) - 1 + +next_int = 1 +test_buffer = bytearray(SIZE) + + +def next_value() -> uint: + global next_int + global test_buffer + for index in range(1, SIZE): + test_buffer[index - 1] = test_buffer[index] + test_buffer[SIZE - 1] = next_int + next_int += 1 + output = 0 + for byte in test_buffer: + output = (output << 8) | byte + return output & MASK + + +def get_index(src: ptr8, i: int): + return src[i] + + +@micropython.viper +def set_index(dest: ptr8, i: int, val: uint): + saved = dest + dest[i] = val + assert int(dest) == int(saved) + + +try: + buffer = bytearray((((1 << max(BIT_THRESHOLDS)) // 1024) + 1) * 1024) + + for bit in BIT_THRESHOLDS: + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + exec(SET_TEMPLATE.format(off=(offset + index) // SIZE, val=next_value())) +except MemoryError: + print("SKIP-TOO-LARGE") + raise SystemExit + + +for bit in BIT_THRESHOLDS: + print("---", bit) + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + globals()["set{}".format((offset + index) // SIZE)](buffer) + print(hex(get_index(buffer, (offset + index) // SIZE))) + for index in range(0, 3 * SIZE, SIZE): + set_index(buffer, (offset + index) // SIZE, next_value()) + print(hex(get_index(buffer, (offset + index) // SIZE))) diff --git a/tests/micropython/viper_ptr8_store_boundary.py.exp b/tests/micropython/viper_ptr8_store_boundary.py.exp new file mode 100644 index 00000000000..621295d81a8 --- /dev/null +++ b/tests/micropython/viper_ptr8_store_boundary.py.exp @@ -0,0 +1,28 @@ +--- 5 +0x1 +0x2 +0x3 +0xd +0xe +0xf +--- 8 +0x4 +0x5 +0x6 +0x10 +0x11 +0x12 +--- 11 +0x7 +0x8 +0x9 +0x13 +0x14 +0x15 +--- 12 +0xa +0xb +0xc +0x16 +0x17 +0x18 diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index 31c9fa17c3b..8608f2322f8 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -39,7 +39,7 @@ except NotImplementedError: print("NotImplementedError") -# uPy raises TypeError, should be ValueError +# MicroPython raises TypeError, should be ValueError try: "%c" % b"\x01\x02" except (TypeError, ValueError): @@ -100,10 +100,10 @@ print("NotImplementedError") # CIRCUITPY-CHANGE: We do check these. -# struct pack with too many args, not checked by uPy +# struct pack with too many args, not checked by MicroPython # print(struct.pack("bb", 1, 2, 3)) -# struct pack with too few args, not checked by uPy +# struct pack with too few args, not checked by MicroPython # print(struct.pack("bb", 1)) # array slice assignment with unsupported RHS diff --git a/tests/misc/non_compliant_lexer.py b/tests/misc/non_compliant_lexer.py index e1c21f3d713..04c605953e7 100644 --- a/tests/misc/non_compliant_lexer.py +++ b/tests/misc/non_compliant_lexer.py @@ -11,7 +11,7 @@ def test(code): print("NotImplementedError") -# uPy requires spaces between literal numbers and keywords, CPy doesn't +# MPy requires spaces between literal numbers and keywords, CPy doesn't try: eval("1and 0") except SyntaxError: diff --git a/tests/misc/print_exception.py.native.exp b/tests/misc/print_exception.py.native.exp new file mode 100644 index 00000000000..59e856ae3c4 --- /dev/null +++ b/tests/misc/print_exception.py.native.exp @@ -0,0 +1,18 @@ +caught +Exception: msg + +caught +Exception: fail + +finally +caught +Exception: fail + +reraise +Exception: fail + +caught +Exception: fail + +AttributeError: 'function' object has no attribute 'X' + diff --git a/tests/misc/rge_sm.py b/tests/misc/rge_sm.py index 5e071687c49..33aa4edb742 100644 --- a/tests/misc/rge_sm.py +++ b/tests/misc/rge_sm.py @@ -39,14 +39,6 @@ def solve(self, finishtime): if not self.iterate(): break - def solveNSteps(self, nSteps): - for i in range(nSteps): - if not self.iterate(): - break - - def series(self): - return zip(*self.Trajectory) - # 1-loop RGES for the main parameters of the SM # couplings are: g1, g2, g3 of U(1), SU(2), SU(3); yt (top Yukawa), lambda (Higgs quartic) @@ -55,70 +47,36 @@ def series(self): lambda *a: 41.0 / 96.0 / math.pi**2 * a[1] ** 3, # g1 lambda *a: -19.0 / 96.0 / math.pi**2 * a[2] ** 3, # g2 lambda *a: -42.0 / 96.0 / math.pi**2 * a[3] ** 3, # g3 - lambda *a: 1.0 - / 16.0 - / math.pi**2 - * ( - 9.0 / 2.0 * a[4] ** 3 - - 8.0 * a[3] ** 2 * a[4] - - 9.0 / 4.0 * a[2] ** 2 * a[4] - - 17.0 / 12.0 * a[1] ** 2 * a[4] + lambda *a: ( + 1.0 + / 16.0 + / math.pi**2 + * ( + 9.0 / 2.0 * a[4] ** 3 + - 8.0 * a[3] ** 2 * a[4] + - 9.0 / 4.0 * a[2] ** 2 * a[4] + - 17.0 / 12.0 * a[1] ** 2 * a[4] + ) ), # yt - lambda *a: 1.0 - / 16.0 - / math.pi**2 - * ( - 24.0 * a[5] ** 2 - + 12.0 * a[4] ** 2 * a[5] - - 9.0 * a[5] * (a[2] ** 2 + 1.0 / 3.0 * a[1] ** 2) - - 6.0 * a[4] ** 4 - + 9.0 / 8.0 * a[2] ** 4 - + 3.0 / 8.0 * a[1] ** 4 - + 3.0 / 4.0 * a[2] ** 2 * a[1] ** 2 + lambda *a: ( + 1.0 + / 16.0 + / math.pi**2 + * ( + 24.0 * a[5] ** 2 + + 12.0 * a[4] ** 2 * a[5] + - 9.0 * a[5] * (a[2] ** 2 + 1.0 / 3.0 * a[1] ** 2) + - 6.0 * a[4] ** 4 + + 9.0 / 8.0 * a[2] ** 4 + + 3.0 / 8.0 * a[1] ** 4 + + 3.0 / 4.0 * a[2] ** 2 * a[1] ** 2 + ) ), # lambda ) -def drange(start, stop, step): - r = start - while r < stop: - yield r - r += step - - -def phaseDiagram(system, trajStart, trajPlot, h=0.1, tend=1.0, range=1.0): - tstart = 0.0 - for i in drange(0, range, 0.1 * range): - for j in drange(0, range, 0.1 * range): - rk = RungeKutta(system, trajStart(i, j), tstart, h) - rk.solve(tend) - # draw the line - for tr in rk.Trajectory: - x, y = trajPlot(tr) - print(x, y) - print() - # draw the arrow - continue - l = (len(rk.Trajectory) - 1) / 3 - if l > 0 and 2 * l < len(rk.Trajectory): - p1 = rk.Trajectory[l] - p2 = rk.Trajectory[2 * l] - x1, y1 = trajPlot(p1) - x2, y2 = trajPlot(p2) - dx = -0.5 * (y2 - y1) # orthogonal to line - dy = 0.5 * (x2 - x1) # orthogonal to line - # l = math.sqrt(dx*dx + dy*dy) - # if abs(l) > 1e-3: - # l = 0.1 / l - # dx *= l - # dy *= l - print(x1 + dx, y1 + dy) - print(x2, y2) - print(x1 - dx, y1 - dy) - print() - - def singleTraj(system, trajStart, h=0.02, tend=1.0): + is_REPR_C = float("1.0000001") == float("1.0") tstart = 0.0 # compute the trajectory @@ -130,10 +88,15 @@ def singleTraj(system, trajStart, h=0.02, tend=1.0): for i in range(len(rk.Trajectory)): tr = rk.Trajectory[i] - print(" ".join(["{:.4f}".format(t) for t in tr])) - + tr_str = " ".join(["{:.4f}".format(t) for t in tr]) + if is_REPR_C: + # allow two small deviations for REPR_C + if tr_str == "1.0000 0.3559 0.6485 1.1944 0.9271 0.1083": + tr_str = "1.0000 0.3559 0.6485 1.1944 0.9272 0.1083" + if tr_str == "16.0000 0.3894 0.5793 0.7017 0.5686 -0.0168": + tr_str = "16.0000 0.3894 0.5793 0.7017 0.5686 -0.0167" + print(tr_str) -# phaseDiagram(sysSM, (lambda i, j: [0.354, 0.654, 1.278, 0.8 + 0.2 * i, 0.1 + 0.1 * j]), (lambda a: (a[4], a[5])), h=0.1, tend=math.log(10**17)) # initial conditions at M_Z singleTraj(sysSM, [0.354, 0.654, 1.278, 0.983, 0.131], h=0.5, tend=math.log(10**17)) # true values diff --git a/tests/misc/sys_exc_info.py b/tests/misc/sys_exc_info.py index d7e8a2d943b..c076dd572b0 100644 --- a/tests/misc/sys_exc_info.py +++ b/tests/misc/sys_exc_info.py @@ -8,13 +8,14 @@ def f(): - print(sys.exc_info()[0:2]) + e = sys.exc_info() + print(e[0], e[1]) try: raise ValueError("value", 123) except: - print(sys.exc_info()[0:2]) + print(sys.exc_info()[0], sys.exc_info()[1]) f() # Outside except block, sys.exc_info() should be back to None's diff --git a/tests/misc/sys_settrace_cov.py b/tests/misc/sys_settrace_cov.py new file mode 100644 index 00000000000..579c8a4a25e --- /dev/null +++ b/tests/misc/sys_settrace_cov.py @@ -0,0 +1,23 @@ +import sys + +try: + sys.settrace +except AttributeError: + print("SKIP") + raise SystemExit + + +def trace_tick_handler(frame, event, arg): + print("FRAME", frame) + print("LASTI", frame.f_lasti) + return None + + +def f(): + x = 3 + return x + + +sys.settrace(trace_tick_handler) +f() +sys.settrace(None) diff --git a/tests/misc/sys_settrace_cov.py.exp b/tests/misc/sys_settrace_cov.py.exp new file mode 100644 index 00000000000..423d78ec42b --- /dev/null +++ b/tests/misc/sys_settrace_cov.py.exp @@ -0,0 +1,2 @@ +FRAME +LASTI \\d\+ diff --git a/tests/multi_extmod/machine_i2c_target_irq.py b/tests/multi_extmod/machine_i2c_target_irq.py new file mode 100644 index 00000000000..eafd9dfdca8 --- /dev/null +++ b/tests/multi_extmod/machine_i2c_target_irq.py @@ -0,0 +1,137 @@ +# Test I2CTarget IRQs and clock stretching. +# +# Requires two instances with their SCL and SDA lines connected together. +# Any combination of the below supported boards can be used. +# +# Notes: +# - pull-up resistors may be needed +# - alif use 1.8V signalling + +import sys +import time +from machine import I2C, I2CTarget + +if not hasattr(I2CTarget, "IRQ_ADDR_MATCH_READ"): + print("SKIP") + raise SystemExit + +ADDR = 67 +clock_stretch_us = 200 + +# Configure pins based on the target. +if sys.platform == "alif": + i2c_args = (1,) # pins P3_7/P3_6 + i2c_kwargs = {} +elif sys.platform == "mimxrt": + i2c_args = (0,) # pins 19/18 on Teensy 4.x + i2c_kwargs = {} + clock_stretch_us = 50 # mimxrt cannot delay too long in the IRQ handler +elif sys.platform == "rp2": + i2c_args = (0,) + i2c_kwargs = {"scl": 9, "sda": 8} +elif sys.platform == "pyboard": + i2c_args = ("Y",) + i2c_kwargs = {} +elif sys.platform == "samd": + i2c_args = () # pins SCL/SDA + i2c_kwargs = {} +elif "zephyr-rpi_pico" in sys.implementation._machine: + i2c_args = ("i2c1",) # on gpio7/gpio6 + i2c_kwargs = {} +else: + print("Please add support for this test on this platform.") + raise SystemExit + + +def simple_irq(i2c_target): + flags = i2c_target.irq().flags() + if flags & I2CTarget.IRQ_ADDR_MATCH_READ: + print("IRQ_ADDR_MATCH_READ") + if flags & I2CTarget.IRQ_ADDR_MATCH_WRITE: + print("IRQ_ADDR_MATCH_WRITE") + + # Force clock stretching. + time.sleep_us(clock_stretch_us) + + +class I2CTargetMemory: + def __init__(self, i2c_target, mem): + self.buf1 = bytearray(1) + self.mem = mem + self.memaddr = 0 + self.state = 0 + i2c_target.irq( + self.irq, + I2CTarget.IRQ_ADDR_MATCH_WRITE | I2CTarget.IRQ_READ_REQ | I2CTarget.IRQ_WRITE_REQ, + hard=True, + ) + + def irq(self, i2c_target): + # Force clock stretching. + time.sleep_us(clock_stretch_us) + + flags = i2c_target.irq().flags() + if flags & I2CTarget.IRQ_ADDR_MATCH_WRITE: + self.state = 0 + if flags & I2CTarget.IRQ_READ_REQ: + self.buf1[0] = self.mem[self.memaddr] + self.memaddr += 1 + i2c_target.write(self.buf1) + if flags & I2CTarget.IRQ_WRITE_REQ: + i2c_target.readinto(self.buf1) + if self.state == 0: + self.state = 1 + self.memaddr = self.buf1[0] + else: + self.mem[self.memaddr] = self.buf1[0] + self.memaddr += 1 + self.memaddr %= len(self.mem) + + # Force clock stretching. + time.sleep_us(clock_stretch_us) + + +# I2C controller +def instance0(): + i2c = I2C(*i2c_args, **i2c_kwargs) + multitest.next() + for iteration in range(2): + print("controller iteration", iteration) + multitest.wait("target stage 1") + i2c.writeto_mem(ADDR, 2, "0123") + multitest.broadcast("controller stage 2") + multitest.wait("target stage 3") + print(i2c.readfrom_mem(ADDR, 2, 4)) + multitest.broadcast("controller stage 4") + print("done") + + +# I2C target +def instance1(): + multitest.next() + + for iteration in range(2): + print("target iteration", iteration) + buf = bytearray(b"--------") + if iteration == 0: + # Use built-in memory capability of I2CTarget. + i2c_target = I2CTarget(*i2c_args, **i2c_kwargs, addr=ADDR, mem=buf) + i2c_target.irq( + simple_irq, + I2CTarget.IRQ_ADDR_MATCH_READ | I2CTarget.IRQ_ADDR_MATCH_WRITE, + hard=True, + ) + else: + # Implement a memory device by hand. + i2c_target = I2CTarget(*i2c_args, **i2c_kwargs, addr=ADDR) + I2CTargetMemory(i2c_target, buf) + + multitest.broadcast("target stage 1") + multitest.wait("controller stage 2") + print(buf) + multitest.broadcast("target stage 3") + multitest.wait("controller stage 4") + + i2c_target.deinit() + + print("done") diff --git a/tests/multi_extmod/machine_i2c_target_irq.py.exp b/tests/multi_extmod/machine_i2c_target_irq.py.exp new file mode 100644 index 00000000000..a17c8f43858 --- /dev/null +++ b/tests/multi_extmod/machine_i2c_target_irq.py.exp @@ -0,0 +1,15 @@ +--- instance0 --- +controller iteration 0 +b'0123' +controller iteration 1 +b'0123' +done +--- instance1 --- +target iteration 0 +IRQ_ADDR_MATCH_WRITE +bytearray(b'--0123--') +IRQ_ADDR_MATCH_WRITE +IRQ_ADDR_MATCH_READ +target iteration 1 +bytearray(b'--0123--') +done diff --git a/tests/multi_extmod/machine_i2c_target_memory.py b/tests/multi_extmod/machine_i2c_target_memory.py new file mode 100644 index 00000000000..6b3f0d03eb7 --- /dev/null +++ b/tests/multi_extmod/machine_i2c_target_memory.py @@ -0,0 +1,79 @@ +# Test basic use of I2CTarget and a memory buffer. +# +# Requires two instances with their SCL and SDA lines connected together. +# Any combination of the below supported boards can be used. +# +# Notes: +# - pull-up resistors may be needed +# - alif use 1.8V signalling + +import sys +from machine import I2C, I2CTarget + +ADDR = 67 + +# Configure pins based on the target. +if sys.platform == "alif": + i2c_args = (1,) # pins P3_7/P3_6 + i2c_kwargs = {} +elif sys.platform == "esp32": + i2c_args = (1,) # on pins 9/8 + i2c_kwargs = {} +elif sys.platform == "mimxrt": + i2c_args = (0,) # pins 19/18 on Teensy 4.x + i2c_kwargs = {} +elif sys.platform == "rp2": + i2c_args = (0,) + i2c_kwargs = {"scl": 9, "sda": 8} +elif sys.platform == "pyboard": + i2c_args = ("Y",) + i2c_kwargs = {} +elif sys.platform == "samd": + i2c_args = () # pins SCL/SDA + i2c_kwargs = {} +elif "zephyr-rpi_pico" in sys.implementation._machine: + i2c_args = ("i2c1",) # on gpio7/gpio6 + i2c_kwargs = {} +else: + print("Please add support for this test on this platform.") + raise SystemExit + + +def simple_irq(i2c_target): + flags = i2c_target.irq().flags() + if flags & I2CTarget.IRQ_END_READ: + print("IRQ_END_READ", i2c_target.memaddr) + if flags & I2CTarget.IRQ_END_WRITE: + print("IRQ_END_WRITE", i2c_target.memaddr) + + +# I2C controller +def instance0(): + i2c = I2C(*i2c_args, **i2c_kwargs) + multitest.next() + for iteration in range(2): + print("controller iteration", iteration) + multitest.wait("target stage 1") + i2c.writeto_mem(ADDR, 2 + iteration, "0123") + multitest.broadcast("controller stage 2") + multitest.wait("target stage 3") + print(i2c.readfrom_mem(ADDR, 2 + iteration, 4)) + multitest.broadcast("controller stage 4") + print("done") + + +# I2C target +def instance1(): + buf = bytearray(b"--------") + i2c_target = I2CTarget(*i2c_args, **i2c_kwargs, addr=ADDR, mem=buf) + i2c_target.irq(simple_irq) + multitest.next() + for iteration in range(2): + print("target iteration", iteration) + multitest.broadcast("target stage 1") + multitest.wait("controller stage 2") + print(buf) + multitest.broadcast("target stage 3") + multitest.wait("controller stage 4") + i2c_target.deinit() + print("done") diff --git a/tests/multi_extmod/machine_i2c_target_memory.py.exp b/tests/multi_extmod/machine_i2c_target_memory.py.exp new file mode 100644 index 00000000000..71386cfe769 --- /dev/null +++ b/tests/multi_extmod/machine_i2c_target_memory.py.exp @@ -0,0 +1,16 @@ +--- instance0 --- +controller iteration 0 +b'0123' +controller iteration 1 +b'0123' +done +--- instance1 --- +target iteration 0 +IRQ_END_WRITE 2 +bytearray(b'--0123--') +IRQ_END_READ 2 +target iteration 1 +IRQ_END_WRITE 3 +bytearray(b'--00123-') +IRQ_END_READ 3 +done diff --git a/tests/perf_bench/bm_fft.py b/tests/perf_bench/bm_fft.py index 9a2d03d11b9..e35c1216c13 100644 --- a/tests/perf_bench/bm_fft.py +++ b/tests/perf_bench/bm_fft.py @@ -15,7 +15,7 @@ def reverse(x, bits): # Initialization n = len(vector) - levels = int(math.log(n) / math.log(2)) + levels = int(round(math.log(n) / math.log(2))) coef = (2 if inverse else -2) * cmath.pi / n exptable = [cmath.rect(1, i * coef) for i in range(n // 2)] vector = [vector[reverse(i, levels)] for i in range(n)] # Copy with bit-reversed permutation diff --git a/tests/perf_bench/bm_pidigits.py b/tests/perf_bench/bm_pidigits.py index bdaa73cec7e..c935f103c5b 100644 --- a/tests/perf_bench/bm_pidigits.py +++ b/tests/perf_bench/bm_pidigits.py @@ -5,6 +5,12 @@ # This benchmark stresses big integer arithmetic. # Adapted from code on: http://benchmarksgame.alioth.debian.org/ +try: + int("0x10000000000000000", 16) +except: + print("SKIP") # No support for >64-bit integers + raise SystemExit + def compose(a, b): aq, ar, as_, at = a diff --git a/tests/perf_bench/core_import_mpy_multi.py b/tests/perf_bench/core_import_mpy_multi.py index 8affa157fa0..67deec05088 100644 --- a/tests/perf_bench/core_import_mpy_multi.py +++ b/tests/perf_bench/core_import_mpy_multi.py @@ -6,7 +6,7 @@ print("SKIP") raise SystemExit -# This is the test.py file that is compiled to test.mpy below. +# This is the test.py file that is compiled to test.mpy below. mpy-cross must be invoked with `-msmall-int-bits=30`. """ class A: def __init__(self, arg): @@ -23,7 +23,7 @@ def f(): x = ("const tuple", None, False, True, 1, 2, 3) result = 123 """ -file_data = b'M\x06\x00\x1f\x14\x03\x0etest.py\x00\x0f\x02A\x00\x02f\x00\x0cresult\x00/-5#\x82I\x81{\x81w\x82/\x81\x05\x81\x17Iom\x82\x13\x06arg\x00\x05\x1cthis will be a string object\x00\x06\x1bthis will be a bytes object\x00\n\x07\x05\x0bconst tuple\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\x81\\\x10\n\x01\x89\x07d`T2\x00\x10\x024\x02\x16\x022\x01\x16\x03"\x80{\x16\x04Qc\x02\x81d\x00\x08\x02(DD\x11\x05\x16\x06\x10\x02\x16\x072\x00\x16\x082\x01\x16\t2\x02\x16\nQc\x03`\x1a\x08\x08\x12\x13@\xb1\xb0\x18\x13Qc@\t\x08\t\x12` Qc@\t\x08\n\x12``Qc\x82@ \x0e\x03\x80\x08+)##\x12\x0b\x12\x0c\x12\r\x12\x0e*\x04Y\x12\x0f\x12\x10\x12\x11*\x03Y#\x00\xc0#\x01\xc0#\x02\xc0Qc' +file_data = b'M\x06\x00\x1e\x14\x03\x0etest.py\x00\x0f\x02A\x00\x02f\x00\x0cresult\x00/-5#\x82I\x81{\x81w\x82/\x81\x05\x81\x17Iom\x82\x13\x06arg\x00\x05\x1cthis will be a string object\x00\x06\x1bthis will be a bytes object\x00\n\x07\x05\x0bconst tuple\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\x81\\\x10\n\x01\x89\x07d`T2\x00\x10\x024\x02\x16\x022\x01\x16\x03"\x80{\x16\x04Qc\x02\x81d\x00\x08\x02(DD\x11\x05\x16\x06\x10\x02\x16\x072\x00\x16\x082\x01\x16\t2\x02\x16\nQc\x03`\x1a\x08\x08\x12\x13@\xb1\xb0\x18\x13Qc@\t\x08\t\x12` Qc@\t\x08\n\x12``Qc\x82@ \x0e\x03\x80\x08+)##\x12\x0b\x12\x0c\x12\r\x12\x0e*\x04Y\x12\x0f\x12\x10\x12\x11*\x03Y#\x00\xc0#\x01\xc0#\x02\xc0Qc' class File(io.IOBase): diff --git a/tests/perf_bench/core_import_mpy_single.py b/tests/perf_bench/core_import_mpy_single.py index 4d9aa67bf2f..f472bb64762 100644 --- a/tests/perf_bench/core_import_mpy_single.py +++ b/tests/perf_bench/core_import_mpy_single.py @@ -8,7 +8,7 @@ print("SKIP") raise SystemExit -# This is the test.py file that is compiled to test.mpy below. +# This is the test.py file that is compiled to test.mpy below. mpy-cross must be invoked with `-msmall-int-bits=30`. # Many known and unknown names/strings are included to test the linking process. """ class A0: @@ -78,7 +78,7 @@ def f1(): x = ("const tuple 9", None, False, True, 1, 2, 3) result = 123 """ -file_data = b"M\x06\x00\x1f\x81=\x1e\x0etest.py\x00\x0f\x04A0\x00\x04A1\x00\x04f0\x00\x04f1\x00\x0cresult\x00/-5\x04a0\x00\x04a1\x00\x04a2\x00\x04a3\x00\x13\x15\x17\x19\x1b\x1d\x1f!#%')+1379;=?ACEGIKMOQSUWY[]_acegikmoqsuwy{}\x7f\x81\x01\x81\x03\x81\x05\x81\x07\x81\t\x81\x0b\x81\r\x81\x0f\x81\x11\x81\x13\x81\x15\x81\x17\x81\x19\x81\x1b\x81\x1d\x81\x1f\x81!\x81#\x81%\x81'\x81)\x81+\x81-\x81/\x811\x813\x815\x817\x819\x81;\x81=\x81?\x81A\x81C\x81E\x81G\x81I\x81K\x81M\x81O\x81Q\x81S\x81U\x81W\x81Y\x81[\x81]\x81_\x81a\x81c\x81e\x81g\x81i\x81k\x81m\x81o\x81q\x81s\x81u\x81w\x81y\x81{\x81}\x81\x7f\x82\x01\x82\x03\x82\x05\x82\x07\x82\t\x82\x0b\x82\r\x82\x0f\x82\x11\x82\x13\x82\x15\x82\x17\x82\x19\x82\x1b\x82\x1d\x82\x1f\x82!\x82#\x82%\x82'\x82)\x82+\x82-\x82/\x821\x823\x825\x827\x829\x82;\x82=\x82?\x82A\x82E\x82G\x82I\x82K\nname0\x00\nname1\x00\nname2\x00\nname3\x00\nname4\x00\nname5\x00\nname6\x00\nname7\x00\nname8\x00\nname9\x00$quite_a_long_name0\x00$quite_a_long_name1\x00$quite_a_long_name2\x00$quite_a_long_name3\x00$quite_a_long_name4\x00$quite_a_long_name5\x00$quite_a_long_name6\x00$quite_a_long_name7\x00$quite_a_long_name8\x00$quite_a_long_name9\x00&quite_a_long_name10\x00&quite_a_long_name11\x00\x05\x1ethis will be a string object 0\x00\x05\x1ethis will be a string object 1\x00\x05\x1ethis will be a string object 2\x00\x05\x1ethis will be a string object 3\x00\x05\x1ethis will be a string object 4\x00\x05\x1ethis will be a string object 5\x00\x05\x1ethis will be a string object 6\x00\x05\x1ethis will be a string object 7\x00\x05\x1ethis will be a string object 8\x00\x05\x1ethis will be a string object 9\x00\x06\x1dthis will be a bytes object 0\x00\x06\x1dthis will be a bytes object 1\x00\x06\x1dthis will be a bytes object 2\x00\x06\x1dthis will be a bytes object 3\x00\x06\x1dthis will be a bytes object 4\x00\x06\x1dthis will be a bytes object 5\x00\x06\x1dthis will be a bytes object 6\x00\x06\x1dthis will be a bytes object 7\x00\x06\x1dthis will be a bytes object 8\x00\x06\x1dthis will be a bytes object 9\x00\n\x07\x05\rconst tuple 0\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 1\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 2\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 3\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 4\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 5\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 6\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 7\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 8\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 9\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\x82d\x10\x12\x01i@i@\x84\x18\x84\x1fT2\x00\x10\x024\x02\x16\x02T2\x01\x10\x034\x02\x16\x032\x02\x16\x042\x03\x16\x05\"\x80{\x16\x06Qc\x04\x82\x0c\x00\n\x02($$$\x11\x07\x16\x08\x10\x02\x16\t2\x00\x16\n2\x01\x16\x0b2\x02\x16\x0c2\x03\x16\rQc\x04@\t\x08\n\x81\x0b Qc@\t\x08\x0b\x81\x0b@Qc@\t\x08\x0c\x81\x0b`QcH\t\n\r\x81\x0b` Qc\x82\x14\x00\x0c\x03h`$$$\x11\x07\x16\x08\x10\x03\x16\t2\x00\x16\n2\x01\x16\x0b2\x02\x16\x0c2\x03\x16\rQc\x04H\t\n\n\x81\x0b``QcH\t\n\x0b\x81\x0b\x80\x07QcH\t\n\x0c\x81\x0b\x80\x08QcH\t\n\r\x81\x0b\x80\tQc\xa08P:\x04\x80\x0b13///---997799<\x1f%\x1f\"\x1f%)\x1f\"//\x12\x0e\x12\x0f\x12\x10\x12\x11\x12\x12\x12\x13\x12\x14*\x07Y\x12\x15\x12\x16\x12\x17\x12\x18\x12\x19\x12\x1a\x12\x08\x12\x07*\x08Y\x12\x1b\x12\x1c\x12\t\x12\x1d\x12\x1e\x12\x1f*\x06Y\x12 \x12!\x12\"\x12#\x12$\x12%*\x06Y\x12&\x12'\x12(\x12)\x12*\x12+*\x06Y\x12,\x12-\x12.\x12/\x120*\x05Y\x121\x122\x123\x124\x125*\x05Y\x126\x127\x128\x129\x12:*\x05Y\x12;\x12<\x12=\x12>\x12?\x12@\x12A\x12B\x12C\x12D\x12E*\x0bY\x12F\x12G\x12H\x12I\x12J\x12K\x12L\x12M\x12N\x12O\x12P*\x0bY\x12Q\x12R\x12S\x12T\x12U\x12V\x12W\x12X\x12Y\x12Z*\nY\x12[\x12\\\x12]\x12^\x12_\x12`\x12a\x12b\x12c\x12d*\nY\x12e\x12f\x12g\x12h\x12i\x12j\x12k\x12l\x12m\x12n\x12o*\x0bY\x12p\x12q\x12r\x12s\x12t\x12u\x12v\x12w\x12x\x12y\x12z*\x0bY\x12{\x12|\x12}\x12~\x12\x7f\x12\x81\x00\x12\x81\x01\x12\x81\x02\x12\x81\x03\x12\x81\x04*\nY\x12\x81\x05\x12\x81\x06\x12\x81\x07\x12\x81\x08\x12\x81\t\x12\x81\n\x12\x81\x0b\x12\x81\x0c\x12\x81\r\x12\x81\x0e\x12\x81\x0f*\x0bY\x12\x81\x10\x12\x81\x11\x12\x81\x12\x12\x81\x13\x12\x81\x14\x12\x81\x15\x12\x81\x16\x12\x81\x17\x12\x81\x18\x12\x81\x19*\nY\x12\x81\x1a\x12\x81\x1b\x12\x81\x1c\x12\x81\x1d\x12\x81\x1e\x12\x81\x1f\x12\x81 \x12\x81!\x12\x81\"\x12\x81#\x12\x81$*\x0bY\x12\x81%\x12\x81&*\x02Y\x12\x81'\x12\x81(\x12\x81)\x12\x81*\x12\x81+\x12\x81,\x12\x81-\x12\x81.\x12\x81/\x12\x810*\nY\x12\x811\x12\x812\x12\x813\x12\x814*\x04Y\x12\x815\x12\x816\x12\x817\x12\x818*\x04Y\x12\x819\x12\x81:\x12\x81;\x12\x81<*\x04YQc\x87p\x08@\x05\x80###############################\x00\xc0#\x01\xc0#\x02\xc0#\x03\xc0#\x04\xc0#\x05\xc0#\x06\xc0#\x07\xc0#\x08\xc0#\t\xc0#\n\xc0#\x0b\xc0#\x0c\xc0#\r\xc0#\x0e\xc0#\x0f\xc0#\x10\xc0#\x11\xc0#\x12\xc0#\x13\xc0#\x14\xc0#\x15\xc0#\x16\xc0#\x17\xc0#\x18\xc0#\x19\xc0#\x1a\xc0#\x1b\xc0#\x1c\xc0#\x1d\xc0Qc" +file_data = b"M\x06\x00\x1e\x81=\x1e\x0etest.py\x00\x0f\x04A0\x00\x04A1\x00\x04f0\x00\x04f1\x00\x0cresult\x00/-5\x04a0\x00\x04a1\x00\x04a2\x00\x04a3\x00\x13\x15\x17\x19\x1b\x1d\x1f!#%')+1379;=?ACEGIKMOQSUWY[]_acegikmoqsuwy{}\x7f\x81\x01\x81\x03\x81\x05\x81\x07\x81\t\x81\x0b\x81\r\x81\x0f\x81\x11\x81\x13\x81\x15\x81\x17\x81\x19\x81\x1b\x81\x1d\x81\x1f\x81!\x81#\x81%\x81'\x81)\x81+\x81-\x81/\x811\x813\x815\x817\x819\x81;\x81=\x81?\x81A\x81C\x81E\x81G\x81I\x81K\x81M\x81O\x81Q\x81S\x81U\x81W\x81Y\x81[\x81]\x81_\x81a\x81c\x81e\x81g\x81i\x81k\x81m\x81o\x81q\x81s\x81u\x81w\x81y\x81{\x81}\x81\x7f\x82\x01\x82\x03\x82\x05\x82\x07\x82\t\x82\x0b\x82\r\x82\x0f\x82\x11\x82\x13\x82\x15\x82\x17\x82\x19\x82\x1b\x82\x1d\x82\x1f\x82!\x82#\x82%\x82'\x82)\x82+\x82-\x82/\x821\x823\x825\x827\x829\x82;\x82=\x82?\x82A\x82E\x82G\x82I\x82K\nname0\x00\nname1\x00\nname2\x00\nname3\x00\nname4\x00\nname5\x00\nname6\x00\nname7\x00\nname8\x00\nname9\x00$quite_a_long_name0\x00$quite_a_long_name1\x00$quite_a_long_name2\x00$quite_a_long_name3\x00$quite_a_long_name4\x00$quite_a_long_name5\x00$quite_a_long_name6\x00$quite_a_long_name7\x00$quite_a_long_name8\x00$quite_a_long_name9\x00&quite_a_long_name10\x00&quite_a_long_name11\x00\x05\x1ethis will be a string object 0\x00\x05\x1ethis will be a string object 1\x00\x05\x1ethis will be a string object 2\x00\x05\x1ethis will be a string object 3\x00\x05\x1ethis will be a string object 4\x00\x05\x1ethis will be a string object 5\x00\x05\x1ethis will be a string object 6\x00\x05\x1ethis will be a string object 7\x00\x05\x1ethis will be a string object 8\x00\x05\x1ethis will be a string object 9\x00\x06\x1dthis will be a bytes object 0\x00\x06\x1dthis will be a bytes object 1\x00\x06\x1dthis will be a bytes object 2\x00\x06\x1dthis will be a bytes object 3\x00\x06\x1dthis will be a bytes object 4\x00\x06\x1dthis will be a bytes object 5\x00\x06\x1dthis will be a bytes object 6\x00\x06\x1dthis will be a bytes object 7\x00\x06\x1dthis will be a bytes object 8\x00\x06\x1dthis will be a bytes object 9\x00\n\x07\x05\rconst tuple 0\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 1\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 2\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 3\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 4\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 5\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 6\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 7\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 8\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 9\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\x82d\x10\x12\x01i@i@\x84\x18\x84\x1fT2\x00\x10\x024\x02\x16\x02T2\x01\x10\x034\x02\x16\x032\x02\x16\x042\x03\x16\x05\"\x80{\x16\x06Qc\x04\x82\x0c\x00\n\x02($$$\x11\x07\x16\x08\x10\x02\x16\t2\x00\x16\n2\x01\x16\x0b2\x02\x16\x0c2\x03\x16\rQc\x04@\t\x08\n\x81\x0b Qc@\t\x08\x0b\x81\x0b@Qc@\t\x08\x0c\x81\x0b`QcH\t\n\r\x81\x0b` Qc\x82\x14\x00\x0c\x03h`$$$\x11\x07\x16\x08\x10\x03\x16\t2\x00\x16\n2\x01\x16\x0b2\x02\x16\x0c2\x03\x16\rQc\x04H\t\n\n\x81\x0b``QcH\t\n\x0b\x81\x0b\x80\x07QcH\t\n\x0c\x81\x0b\x80\x08QcH\t\n\r\x81\x0b\x80\tQc\xa08P:\x04\x80\x0b13///---997799<\x1f%\x1f\"\x1f%)\x1f\"//\x12\x0e\x12\x0f\x12\x10\x12\x11\x12\x12\x12\x13\x12\x14*\x07Y\x12\x15\x12\x16\x12\x17\x12\x18\x12\x19\x12\x1a\x12\x08\x12\x07*\x08Y\x12\x1b\x12\x1c\x12\t\x12\x1d\x12\x1e\x12\x1f*\x06Y\x12 \x12!\x12\"\x12#\x12$\x12%*\x06Y\x12&\x12'\x12(\x12)\x12*\x12+*\x06Y\x12,\x12-\x12.\x12/\x120*\x05Y\x121\x122\x123\x124\x125*\x05Y\x126\x127\x128\x129\x12:*\x05Y\x12;\x12<\x12=\x12>\x12?\x12@\x12A\x12B\x12C\x12D\x12E*\x0bY\x12F\x12G\x12H\x12I\x12J\x12K\x12L\x12M\x12N\x12O\x12P*\x0bY\x12Q\x12R\x12S\x12T\x12U\x12V\x12W\x12X\x12Y\x12Z*\nY\x12[\x12\\\x12]\x12^\x12_\x12`\x12a\x12b\x12c\x12d*\nY\x12e\x12f\x12g\x12h\x12i\x12j\x12k\x12l\x12m\x12n\x12o*\x0bY\x12p\x12q\x12r\x12s\x12t\x12u\x12v\x12w\x12x\x12y\x12z*\x0bY\x12{\x12|\x12}\x12~\x12\x7f\x12\x81\x00\x12\x81\x01\x12\x81\x02\x12\x81\x03\x12\x81\x04*\nY\x12\x81\x05\x12\x81\x06\x12\x81\x07\x12\x81\x08\x12\x81\t\x12\x81\n\x12\x81\x0b\x12\x81\x0c\x12\x81\r\x12\x81\x0e\x12\x81\x0f*\x0bY\x12\x81\x10\x12\x81\x11\x12\x81\x12\x12\x81\x13\x12\x81\x14\x12\x81\x15\x12\x81\x16\x12\x81\x17\x12\x81\x18\x12\x81\x19*\nY\x12\x81\x1a\x12\x81\x1b\x12\x81\x1c\x12\x81\x1d\x12\x81\x1e\x12\x81\x1f\x12\x81 \x12\x81!\x12\x81\"\x12\x81#\x12\x81$*\x0bY\x12\x81%\x12\x81&*\x02Y\x12\x81'\x12\x81(\x12\x81)\x12\x81*\x12\x81+\x12\x81,\x12\x81-\x12\x81.\x12\x81/\x12\x810*\nY\x12\x811\x12\x812\x12\x813\x12\x814*\x04Y\x12\x815\x12\x816\x12\x817\x12\x818*\x04Y\x12\x819\x12\x81:\x12\x81;\x12\x81<*\x04YQc\x87p\x08@\x05\x80###############################\x00\xc0#\x01\xc0#\x02\xc0#\x03\xc0#\x04\xc0#\x05\xc0#\x06\xc0#\x07\xc0#\x08\xc0#\t\xc0#\n\xc0#\x0b\xc0#\x0c\xc0#\r\xc0#\x0e\xc0#\x0f\xc0#\x10\xc0#\x11\xc0#\x12\xc0#\x13\xc0#\x14\xc0#\x15\xc0#\x16\xc0#\x17\xc0#\x18\xc0#\x19\xc0#\x1a\xc0#\x1b\xc0#\x1c\xc0#\x1d\xc0Qc" class File(io.IOBase): diff --git a/tests/run-internalbench.py b/tests/run-internalbench.py index c9f783e474c..99c6304afe9 100755 --- a/tests/run-internalbench.py +++ b/tests/run-internalbench.py @@ -8,6 +8,10 @@ from glob import glob from collections import defaultdict +run_tests_module = __import__("run-tests") +sys.path.append(run_tests_module.base_path("../tools")) +import pyboard + if os.name == "nt": MICROPYTHON = os.getenv( "MICROPY_MICROPYTHON", "../ports/windows/build-standard/micropython.exe" @@ -15,13 +19,39 @@ else: MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython") +injected_bench_code = b""" +import time + +class bench_class: + ITERS = 20000000 + + @staticmethod + def run(test): + t = time.ticks_us() + test(bench_class.ITERS) + t = time.ticks_diff(time.ticks_us(), t) + s, us = divmod(t, 1_000_000) + print("{}.{:06}".format(s, us)) + +import sys +sys.modules['bench'] = bench_class +""" + -def run_tests(pyb, test_dict): +def execbench(pyb, filename, iters): + with open(filename, "rb") as f: + pyfile = f.read() + code = (injected_bench_code + pyfile).replace(b"20000000", str(iters).encode("utf-8")) + return pyb.exec(code).replace(b"\r\n", b"\n") + + +def run_tests(pyb, test_dict, iters): test_count = 0 testcase_count = 0 for base_test, tests in sorted(test_dict.items()): print(base_test + ":") + baseline = None for test_file in tests: # run MicroPython if pyb is None: @@ -36,20 +66,25 @@ def run_tests(pyb, test_dict): # run on pyboard pyb.enter_raw_repl() try: - output_mupy = pyb.execfile(test_file).replace(b"\r\n", b"\n") + output_mupy = execbench(pyb, test_file[0], iters) except pyboard.PyboardError: output_mupy = b"CRASH" - output_mupy = float(output_mupy.strip()) + try: + output_mupy = float(output_mupy.strip()) + except ValueError: + output_mupy = -1 test_file[1] = output_mupy testcase_count += 1 - test_count += 1 - baseline = None - for t in tests: if baseline is None: - baseline = t[1] - print(" %.3fs (%+06.2f%%) %s" % (t[1], (t[1] * 100 / baseline) - 100, t[0])) + baseline = test_file[1] + print( + " %.3fs (%+06.2f%%) %s" + % (test_file[1], (test_file[1] * 100 / baseline) - 100, test_file[0]) + ) + + test_count += 1 print("{} tests performed ({} individual testcases)".format(test_count, testcase_count)) @@ -58,27 +93,47 @@ def run_tests(pyb, test_dict): def main(): - cmd_parser = argparse.ArgumentParser(description="Run tests for MicroPython.") - cmd_parser.add_argument("--pyboard", action="store_true", help="run the tests on the pyboard") + cmd_parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=f"""Run and manage tests for MicroPython. + +{run_tests_module.test_instance_description} +{run_tests_module.test_directory_description} +""", + epilog=run_tests_module.test_instance_epilog, + ) + cmd_parser.add_argument( + "-t", "--test-instance", default="unix", help="the MicroPython instance to test" + ) + cmd_parser.add_argument( + "-b", "--baudrate", default=115200, help="the baud rate of the serial device" + ) + cmd_parser.add_argument("-u", "--user", default="micro", help="the telnet login username") + cmd_parser.add_argument("-p", "--password", default="python", help="the telnet login password") + cmd_parser.add_argument( + "-d", "--test-dirs", nargs="*", help="input test directories (if no files given)" + ) + cmd_parser.add_argument( + "-I", + "--iters", + type=int, + default=200_000, + help="number of test iterations, only for remote instances (default 200,000)", + ) cmd_parser.add_argument("files", nargs="*", help="input test files") args = cmd_parser.parse_args() # Note pyboard support is copied over from run-tests.py, not tests, and likely needs revamping - if args.pyboard: - import pyboard - - pyb = pyboard.Pyboard("/dev/ttyACM0") - pyb.enter_raw_repl() - else: - pyb = None + pyb = run_tests_module.get_test_instance( + args.test_instance, args.baudrate, args.user, args.password + ) if len(args.files) == 0: - if pyb is None: - # run PC tests - test_dirs = ("internal_bench",) + if args.test_dirs: + test_dirs = tuple(args.test_dirs) else: - # run pyboard tests - test_dirs = ("basics", "float", "pyb") + test_dirs = ("internal_bench",) + tests = sorted( test_file for test_files in (glob("{}/*.py".format(dir)) for dir in test_dirs) @@ -95,7 +150,7 @@ def main(): continue test_dict[m.group(1)].append([t, None]) - if not run_tests(pyb, test_dict): + if not run_tests(pyb, test_dict, args.iters): sys.exit(1) diff --git a/tests/run-multitests.py b/tests/run-multitests.py index 387eec7018b..e5458ffe0d0 100755 --- a/tests/run-multitests.py +++ b/tests/run-multitests.py @@ -15,6 +15,8 @@ import subprocess import tempfile +run_tests_module = __import__("run-tests") + test_dir = os.path.abspath(os.path.dirname(__file__)) if os.path.abspath(sys.path[0]) == test_dir: @@ -130,6 +132,11 @@ def get_host_ip(_ip_cache=[]): return _ip_cache[0] +def decode(output): + # Convenience function to convert raw process or serial output to ASCII + return str(output, "ascii", "backslashreplace") + + class PyInstance: def __init__(self): pass @@ -188,7 +195,7 @@ def run_script(self, script): output = p.stdout except subprocess.CalledProcessError as er: err = er - return str(output.strip(), "ascii"), err + return decode(output.strip()), err def start_script(self, script): self.popen = subprocess.Popen( @@ -215,7 +222,7 @@ def readline(self): self.finished = self.popen.poll() is not None return None, None else: - return str(out.rstrip(), "ascii"), None + return decode(out.rstrip()), None def write(self, data): self.popen.stdin.write(data) @@ -227,21 +234,12 @@ def is_finished(self): def wait_finished(self): self.popen.wait() out = self.popen.stdout.read() - return str(out, "ascii"), "" + return decode(out), "" class PyInstancePyboard(PyInstance): - @staticmethod - def map_device_shortcut(device): - if device[0] == "a" and device[1:].isdigit(): - return "/dev/ttyACM" + device[1:] - elif device[0] == "u" and device[1:].isdigit(): - return "/dev/ttyUSB" + device[1:] - else: - return device - def __init__(self, device): - device = self.map_device_shortcut(device) + device = device self.device = device self.pyb = pyboard.Pyboard(device) self.pyb.enter_raw_repl() @@ -262,7 +260,7 @@ def run_script(self, script): output = self.pyb.exec_(script) except pyboard.PyboardError as er: err = er - return str(output.strip(), "ascii"), err + return decode(output.strip()), err def start_script(self, script): self.pyb.enter_raw_repl() @@ -281,13 +279,13 @@ def readline(self): if out.endswith(b"\x04"): self.finished = True out = out[:-1] - err = str(self.pyb.read_until(1, b"\x04"), "ascii") + err = decode(self.pyb.read_until(1, b"\x04")) err = err[:-1] if not out and not err: return None, None else: err = None - return str(out.rstrip(), "ascii"), err + return decode(out.rstrip()), err def write(self, data): self.pyb.serial.write(data) @@ -297,7 +295,7 @@ def is_finished(self): def wait_finished(self): out, err = self.pyb.follow(10, None) - return str(out, "ascii"), str(err, "ascii") + return decode(out), decode(err) def prepare_test_file_list(test_files): @@ -488,9 +486,7 @@ def print_diff(a, b): def run_tests(test_files, instances_truth, instances_test): - skipped_tests = [] - passed_tests = [] - failed_tests = [] + test_results = [] for test_file, num_instances in test_files: instances_str = "|".join(str(instances_test[i]) for i in range(num_instances)) @@ -526,13 +522,13 @@ def run_tests(test_files, instances_truth, instances_test): # Print result of test if skip: print("skip") - skipped_tests.append(test_file) + test_results.append((test_file, "skip", "")) elif output_test == output_truth: print("pass") - passed_tests.append(test_file) + test_results.append((test_file, "pass", "")) else: print("FAIL") - failed_tests.append(test_file) + test_results.append((test_file, "fail", "")) if not cmd_args.show_output: print("### TEST ###") print(output_test, end="") @@ -549,15 +545,7 @@ def run_tests(test_files, instances_truth, instances_test): if cmd_args.show_output: print() - print("{} tests performed".format(len(skipped_tests) + len(passed_tests) + len(failed_tests))) - print("{} tests passed".format(len(passed_tests))) - - if skipped_tests: - print("{} tests skipped: {}".format(len(skipped_tests), " ".join(skipped_tests))) - if failed_tests: - print("{} tests failed: {}".format(len(failed_tests), " ".join(failed_tests))) - - return not failed_tests + return test_results def main(): @@ -565,16 +553,24 @@ def main(): cmd_parser = argparse.ArgumentParser( description="Run network tests for MicroPython", + epilog=( + run_tests_module.test_instance_epilog + + "Each instance arg can optionally have custom env provided, eg. ,ENV=VAR,ENV=VAR...\n" + ), formatter_class=argparse.RawTextHelpFormatter, ) cmd_parser.add_argument( "-s", "--show-output", action="store_true", help="show test output after running" ) cmd_parser.add_argument( - "-t", "--trace-output", action="store_true", help="trace test output while running" + "-c", "--trace-output", action="store_true", help="trace test output while running" ) cmd_parser.add_argument( - "-i", "--instance", action="append", default=[], help="instance(s) to run the tests on" + "-t", + "--test-instance", + action="append", + default=[], + help="instance(s) to run the tests on", ) cmd_parser.add_argument( "-p", @@ -583,13 +579,11 @@ def main(): default=1, help="repeat the test with this many permutations of the instance order", ) - cmd_parser.epilog = ( - "Supported instance types:\r\n" - " -i pyb: physical device (eg. pyboard) on provided repl port.\n" - " -i micropython unix micropython instance, path customised with MICROPY_MICROPYTHON env.\n" - " -i cpython desktop python3 instance, path customised with MICROPY_CPYTHON3 env.\n" - " -i exec: custom program run on provided path.\n" - "Each instance arg can optionally have custom env provided, eg. ,ENV=VAR,ENV=VAR...\n" + cmd_parser.add_argument( + "-r", + "--result-dir", + default=run_tests_module.base_path("results"), + help="directory for test results", ) cmd_parser.add_argument("files", nargs="+", help="input test files") cmd_args = cmd_parser.parse_args() @@ -603,33 +597,36 @@ def main(): instances_truth = [PyInstanceSubProcess([PYTHON_TRUTH]) for _ in range(max_instances)] instances_test = [] - for i in cmd_args.instance: + for i in cmd_args.test_instance: # Each instance arg is ,ENV=VAR,ENV=VAR... i = i.split(",") cmd = i[0] env = i[1:] if cmd.startswith("exec:"): instances_test.append(PyInstanceSubProcess([cmd[len("exec:") :]], env)) - elif cmd == "micropython": + elif cmd == "unix": instances_test.append(PyInstanceSubProcess([MICROPYTHON], env)) elif cmd == "cpython": instances_test.append(PyInstanceSubProcess([CPYTHON3], env)) - elif cmd.startswith("pyb:"): - instances_test.append(PyInstancePyboard(cmd[len("pyb:") :])) + elif cmd == "webassembly" or cmd.startswith("execpty:"): + print("unsupported instance string: {}".format(cmd), file=sys.stderr) + sys.exit(2) else: - print("unknown instance string: {}".format(cmd), file=sys.stderr) - sys.exit(1) + device = run_tests_module.convert_device_shortcut_to_real_device(cmd) + instances_test.append(PyInstancePyboard(device)) for _ in range(max_instances - len(instances_test)): instances_test.append(PyInstanceSubProcess([MICROPYTHON])) + os.makedirs(cmd_args.result_dir, exist_ok=True) all_pass = True try: for i, instances_test_permutation in enumerate(itertools.permutations(instances_test)): if i >= cmd_args.permutations: break - all_pass &= run_tests(test_files, instances_truth, instances_test_permutation) + test_results = run_tests(test_files, instances_truth, instances_test_permutation) + all_pass &= run_tests_module.create_test_report(cmd_args, test_results) finally: for i in instances_truth: diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py index 340a7f004b0..6d2a975b82a 100755 --- a/tests/run-natmodtests.py +++ b/tests/run-natmodtests.py @@ -9,7 +9,7 @@ import sys import argparse -# CIRCUITPY-CHANGE: no pyboard +run_tests_module = __import__("run-tests") # Paths for host executables CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") @@ -72,6 +72,7 @@ def open(self, path, mode): # CIRCUITPY-CHANGE: no vfs, but still have os os.mount(__FS(), '/__remote') sys.path.insert(0, '/__remote') +{import_prelude} sys.modules['{}'] = __import__('__injected') """ @@ -108,7 +109,7 @@ def run_script(self, script): output = self.pyb.exec_(script) output = output.replace(b"\r\n", b"\n") return output, None - except pyboard.PyboardError as er: + except run_tests_module.pyboard.PyboardError as er: return b"", er @@ -131,7 +132,15 @@ def detect_architecture(target): return platform, arch, None -def run_tests(target_truth, target, args, stats, resolved_arch): +def run_tests(target_truth, target, args, resolved_arch): + global injected_import_hook_code + + prelude = "" + if args.begin: + prelude = args.begin.read() + injected_import_hook_code = injected_import_hook_code.replace("{import_prelude}", prelude) + + test_results = [] for test_file in args.files: # Find supported test test_file_basename = os.path.basename(test_file) @@ -154,9 +163,11 @@ def run_tests(target_truth, target, args, stats, resolved_arch): with open(NATMOD_EXAMPLE_DIR + test_mpy, "rb") as f: test_script += b"__buf=" + bytes(repr(f.read()), "ascii") + b"\n" except OSError: - print("---- {} - mpy file not compiled".format(test_file)) + test_results.append((test_file, "skip", "mpy file not compiled")) + print("skip {} - mpy file not compiled".format(test_file)) continue test_script += bytes(injected_import_hook_code.format(test_module), "ascii") + test_script += b"print('START TEST')\n" test_script += test_file_data # Run test under MicroPython @@ -164,8 +175,18 @@ def run_tests(target_truth, target, args, stats, resolved_arch): # Work out result of test extra = "" + result_out = result_out.removeprefix(b"START TEST\n") if error is None and result_out == b"SKIP\n": result = "SKIP" + elif ( + error is not None + and error.args[0] == "exception" + and error.args[1] == b"" + and b"MemoryError" in error.args[2] + ): + # Test had a MemoryError before anything (should be at least "START TEST") + # was printed, so the test is too big for the target. + result = "LRGE" elif error is not None: result = "FAIL" extra = " - " + str(error) @@ -186,40 +207,63 @@ def run_tests(target_truth, target, args, stats, resolved_arch): result = "pass" # Accumulate statistics - stats["total"] += 1 if result == "pass": - stats["pass"] += 1 + test_results.append((test_file, "pass", "")) elif result == "SKIP": - stats["skip"] += 1 + test_results.append((test_file, "skip", "")) + elif result == "LRGE": + test_results.append((test_file, "skip", "too large")) else: - stats["fail"] += 1 + test_results.append((test_file, "fail", "")) # Print result print("{:4} {}{}".format(result, test_file, extra)) + return test_results + def main(): cmd_parser = argparse.ArgumentParser( - description="Run dynamic-native-module tests under MicroPython" + description="Run dynamic-native-module tests under MicroPython", + epilog=run_tests_module.test_instance_epilog, + formatter_class=argparse.RawDescriptionHelpFormatter, ) cmd_parser.add_argument( - "-p", "--pyboard", action="store_true", help="run tests via pyboard.py" + "-t", "--test-instance", default="unix", help="the MicroPython instance to test" ) + cmd_parser.add_argument("--baudrate", default=115200, help="baud rate of the serial device") + cmd_parser.add_argument("--user", default="micro", help="telnet login username") + cmd_parser.add_argument("--password", default="python", help="telnet login password") cmd_parser.add_argument( - "-d", "--device", default="/dev/ttyACM0", help="the device for pyboard.py" + "-a", "--arch", choices=AVAILABLE_ARCHS, help="override native architecture of the target" ) cmd_parser.add_argument( - "-a", "--arch", choices=AVAILABLE_ARCHS, help="override native architecture of the target" + "-b", + "--begin", + type=argparse.FileType("rt"), + default=None, + help="prologue python file to execute before module import", + ) + cmd_parser.add_argument( + "-r", + "--result-dir", + default=run_tests_module.base_path("results"), + help="directory for test results", ) cmd_parser.add_argument("files", nargs="*", help="input test files") args = cmd_parser.parse_args() target_truth = TargetSubprocess([CPYTHON3]) - if args.pyboard: - target = TargetPyboard(pyboard.Pyboard(args.device)) - else: + target = run_tests_module.get_test_instance( + args.test_instance, args.baudrate, args.user, args.password + ) + if target is None: + # Use the unix port of MicroPython. target = TargetSubprocess([MICROPYTHON]) + else: + # Use a remote target. + target = TargetPyboard(target) if hasattr(args, "arch") and args.arch is not None: target_arch = args.arch @@ -235,20 +279,14 @@ def main(): print("platform={} ".format(target_platform), end="") print("arch={}".format(target_arch)) - stats = {"total": 0, "pass": 0, "fail": 0, "skip": 0} - run_tests(target_truth, target, args, stats, target_arch) + os.makedirs(args.result_dir, exist_ok=True) + test_results = run_tests(target_truth, target, args, target_arch) + res = run_tests_module.create_test_report(args, test_results) target.close() target_truth.close() - print("{} tests performed".format(stats["total"])) - print("{} tests passed".format(stats["pass"])) - if stats["fail"]: - print("{} tests failed".format(stats["fail"])) - if stats["skip"]: - print("{} tests skipped".format(stats["skip"])) - - if stats["fail"]: + if not res: sys.exit(1) diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py index 81d873c4599..039d11a3611 100755 --- a/tests/run-perfbench.py +++ b/tests/run-perfbench.py @@ -10,10 +10,9 @@ import argparse from glob import glob -sys.path.append("../tools") -import pyboard +run_tests_module = __import__("run-tests") -prepare_script_for_target = __import__("run-tests").prepare_script_for_target +prepare_script_for_target = run_tests_module.prepare_script_for_target # Paths for host executables if os.name == "nt": @@ -45,12 +44,12 @@ def run_script_on_target(target, script): output = b"" err = None - if isinstance(target, pyboard.Pyboard): + if hasattr(target, "enter_raw_repl"): # Run via pyboard interface try: target.enter_raw_repl() output = target.exec_(script) - except pyboard.PyboardError as er: + except run_tests_module.pyboard.PyboardError as er: err = er else: # Run local executable @@ -90,9 +89,9 @@ def run_benchmark_on_target(target, script): def run_benchmarks(args, target, param_n, param_m, n_average, test_list): + test_results = [] skip_complex = run_feature_test(target, "complex") != "complex" skip_native = run_feature_test(target, "native_check") != "native" - target_had_error = False for test_file in sorted(test_list): print(test_file + ": ", end="") @@ -105,6 +104,7 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list): and test_file.find("viper_") != -1 ) if skip: + test_results.append((test_file, "skip", "")) print("SKIP") continue @@ -122,9 +122,10 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list): f.write(test_script) # Process script through mpy-cross if needed - if isinstance(target, pyboard.Pyboard) or args.via_mpy: + if hasattr(target, "enter_raw_repl") or args.via_mpy: crash, test_script_target = prepare_script_for_target(args, script_text=test_script) if crash: + test_results.append((test_file, "fail", "preparation")) print("CRASH:", test_script_target) continue else: @@ -162,10 +163,13 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list): error = "FAIL truth" if error is not None: - if not error.startswith("SKIP"): - target_had_error = True + if error.startswith("SKIP"): + test_results.append((test_file, "skip", error)) + else: + test_results.append((test_file, "fail", error)) print(error) else: + test_results.append((test_file, "pass", "")) t_avg, t_sd = compute_stats(times) s_avg, s_sd = compute_stats(scores) print( @@ -179,7 +183,7 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list): sys.stdout.flush() - return target_had_error + return test_results def parse_output(filename): @@ -190,7 +194,13 @@ def parse_output(filename): m = int(m.split("=")[1]) data = [] for l in f: - if ": " in l and ": SKIP" not in l and "CRASH: " not in l: + if ( + ": " in l + and ": SKIP" not in l + and "CRASH: " not in l + and "skipped: " not in l + and "failed: " not in l + ): name, values = l.strip().split(": ") values = tuple(float(v) for v in values.split()) data.append((name,) + values) @@ -246,17 +256,17 @@ def compute_diff(file1, file2, diff_score): def main(): cmd_parser = argparse.ArgumentParser(description="Run benchmarks for MicroPython") cmd_parser.add_argument( - "-t", "--diff-time", action="store_true", help="diff time outputs from a previous run" + "-m", "--diff-time", action="store_true", help="diff time outputs from a previous run" ) cmd_parser.add_argument( "-s", "--diff-score", action="store_true", help="diff score outputs from a previous run" ) cmd_parser.add_argument( - "-p", "--pyboard", action="store_true", help="run tests via pyboard.py" - ) - cmd_parser.add_argument( - "-d", "--device", default="/dev/ttyACM0", help="the device for pyboard.py" + "-t", "--test-instance", default="unix", help="the MicroPython instance to test" ) + cmd_parser.add_argument("--baudrate", default=115200, help="baud rate of the serial device") + cmd_parser.add_argument("--user", default="micro", help="telnet login username") + cmd_parser.add_argument("--password", default="python", help="telnet login password") cmd_parser.add_argument("-a", "--average", default="8", help="averaging number") cmd_parser.add_argument( "--emit", default="bytecode", help="MicroPython emitter to use (bytecode or native)" @@ -264,6 +274,12 @@ def main(): cmd_parser.add_argument("--heapsize", help="heapsize to use (use default if not specified)") cmd_parser.add_argument("--via-mpy", action="store_true", help="compile code to .mpy first") cmd_parser.add_argument("--mpy-cross-flags", default="", help="flags to pass to mpy-cross") + cmd_parser.add_argument( + "-r", + "--result-dir", + default=run_tests_module.base_path("results"), + help="directory for test results", + ) cmd_parser.add_argument( "N", nargs=1, help="N parameter (approximate target CPU frequency in MHz)" ) @@ -282,15 +298,18 @@ def main(): M = int(args.M[0]) n_average = int(args.average) - if args.pyboard: - if not args.mpy_cross_flags: - args.mpy_cross_flags = "-march=armv7m" - target = pyboard.Pyboard(args.device) - target.enter_raw_repl() - else: + target = run_tests_module.get_test_instance( + args.test_instance, args.baudrate, args.user, args.password + ) + if target is None: + # Use the unix port of MicroPython. target = [MICROPYTHON, "-X", "emit=" + args.emit] if args.heapsize is not None: target.extend(["-X", "heapsize=" + args.heapsize]) + else: + # Use a remote target. + if not args.mpy_cross_flags: + args.mpy_cross_flags = "-march=armv7m" if len(args.files) == 0: tests_skip = ("benchrun.py",) @@ -307,13 +326,15 @@ def main(): print("N={} M={} n_average={}".format(N, M, n_average)) - target_had_error = run_benchmarks(args, target, N, M, n_average, tests) + os.makedirs(args.result_dir, exist_ok=True) + test_results = run_benchmarks(args, target, N, M, n_average, tests) + res = run_tests_module.create_test_report(args, test_results) - if isinstance(target, pyboard.Pyboard): + if hasattr(target, "exit_raw_repl"): target.exit_raw_repl() target.close() - if target_had_error: + if not res: sys.exit(1) diff --git a/tests/run-tests.py b/tests/run-tests.py index cb839ae23dc..71570292ce7 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -15,13 +15,15 @@ import threading import tempfile -# Maximum time to run a PC-based test, in seconds. -TEST_TIMEOUT = 30 +# Maximum time to run a single test, in seconds. +TEST_TIMEOUT = float(os.environ.get("MICROPY_TEST_TIMEOUT", 30)) # See stackoverflow.com/questions/2632199: __file__ nor sys.argv[0] # are guaranteed to always work, this one should though. BASEPATH = os.path.dirname(os.path.abspath(inspect.getsourcefile(lambda: None))) +RV32_ARCH_FLAGS = {"zba": 1 << 0} + def base_path(*p): return os.path.abspath(os.path.join(BASEPATH, *p)).replace("\\", "/") @@ -58,6 +60,23 @@ def base_path(*p): # Set PYTHONIOENCODING so that CPython will use utf-8 on systems which set another encoding in the locale os.environ["PYTHONIOENCODING"] = "utf-8" + +def normalize_newlines(data): + """Normalize newline variations to \\n. + + Only normalizes actual line endings, not literal \\r characters in strings. + Handles \\r\\r\\n and \\r\\n cases to ensure consistent comparison + across different platforms and terminals. + """ + if isinstance(data, bytes): + # Handle PTY double-newline issue first + data = data.replace(b"\r\r\n", b"\n") + # Then handle standard Windows line endings + data = data.replace(b"\r\n", b"\n") + # Don't convert standalone \r as it might be literal content + return data + + # Code to allow a target MicroPython to import an .mpy from RAM # Note: the module is named `__injected_test` but it needs to have `__name__` set to # `__main__` so that the test sees itself as the main module, eg so unittest works. @@ -88,31 +107,82 @@ def getcwd(self): return "" def stat(self, path): if path == '__injected_test.mpy': - return tuple(0 for _ in range(10)) + return (0,0,0,0,0,0,0,0,0,0) else: - raise OSError(-2) # ENOENT + raise OSError(2) # ENOENT def open(self, path, mode): + self.stat(path) return __File() vfs.mount(__FS(), '/__vfstest') os.chdir('/__vfstest') +{import_prologue} __import__('__injected_test') """ # Platforms associated with the unix port, values of `sys.platform`. PC_PLATFORMS = ("darwin", "linux", "win32") +# Mapping from `sys.platform` to the port name, for special cases. +# See `platform_to_port()` function. +platform_to_port_map = {"pyboard": "stm32", "WiPy": "cc3200"} +platform_to_port_map.update({p: "unix" for p in PC_PLATFORMS}) + +# Tests to skip for values of the `--via-mpy` argument. +via_mpy_tests_to_skip = { + # Skip the following when mpy is enabled. + True: ( + # These print out the filename and that's expected to match the .py name. + "import/import_file.py", + "io/argv.py", + "misc/sys_settrace_features.py", + "misc/sys_settrace_generator.py", + "misc/sys_settrace_loop.py", + ), +} + +# Tests to skip for specific emitters. +emitter_tests_to_skip = { + # Some tests are known to fail with native emitter. + # Remove them from the below when they work. + "native": ( + # These require raise_varargs. + "basics/gen_yield_from_close.py", + "basics/try_finally_return2.py", + "basics/try_reraise.py", + "basics/try_reraise2.py", + "misc/features.py", + # These require checking for unbound local. + "basics/annotate_var.py", + "basics/del_deref.py", + "basics/del_local.py", + "basics/scope_implicit.py", + "basics/unboundlocal.py", + # These require "raise from". + "basics/exception_chain.py", + # These require stack-allocated slice optimisation. + "micropython/heapalloc_slice.py", + # These require running the scheduler. + "micropython/schedule.py", + "extmod/asyncio_event_queue.py", + "extmod/asyncio_iterator_event.py", + # These require sys.exc_info(). + "misc/sys_exc_info.py", + # These require sys.settrace(). + "misc/sys_settrace_cov.py", + "misc/sys_settrace_features.py", + "misc/sys_settrace_generator.py", + "misc/sys_settrace_loop.py", + # These are bytecode-specific tests. + "stress/bytecode_limit.py", + ), +} + # Tests to skip on specific targets. # These are tests that are difficult to detect that they should not be run on the given target. platform_tests_to_skip = { - "esp8266": ( - "micropython/viper_args.py", # too large - "micropython/viper_binop_arith.py", # too large - "misc/rge_sm.py", # too large - ), "minimal": ( "basics/class_inplace_op.py", # all special methods not supported "basics/subclass_native_init.py", # native subclassing corner cases not support - "misc/rge_sm.py", # too large "micropython/opt_level.py", # don't assume line numbers are stored ), "nrf": ( @@ -140,14 +210,6 @@ def open(self, path, mode): "thread/thread_lock3.py", "thread/thread_shared2.py", ), - "qemu": ( - # Skip tests that require Cortex-M4. - "inlineasm/thumb/asmfpaddsub.py", - "inlineasm/thumb/asmfpcmp.py", - "inlineasm/thumb/asmfpldrstr.py", - "inlineasm/thumb/asmfpmuldiv.py", - "inlineasm/thumb/asmfpsqrt.py", - ), "webassembly": ( "basics/string_format_modulo.py", # can't print nulls to stdout "basics/string_strip.py", # can't print nulls to stdout @@ -162,6 +224,9 @@ def open(self, path, mode): "extmod/asyncio_new_event_loop.py", "extmod/asyncio_threadsafeflag.py", "extmod/asyncio_wait_for_fwd.py", + "extmod/asyncio_event_queue.py", + "extmod/asyncio_iterator_event.py", + "extmod/asyncio_wait_for_linked_task.py", "extmod/binascii_a2b_base64.py", "extmod/deflate_compress_memory_error.py", # tries to allocate unlimited memory "extmod/re_stack_overflow.py", @@ -184,6 +249,89 @@ def open(self, path, mode): ), } +# These tests don't test float explicitly but rather use it to perform the test. +tests_requiring_float = ( + "extmod/asyncio_basic.py", + "extmod/asyncio_basic2.py", + "extmod/asyncio_cancel_task.py", + "extmod/asyncio_event.py", + "extmod/asyncio_fair.py", + "extmod/asyncio_gather.py", + "extmod/asyncio_gather_notimpl.py", + "extmod/asyncio_get_event_loop.py", + "extmod/asyncio_iterator_event.py", + "extmod/asyncio_lock.py", + "extmod/asyncio_task_done.py", + "extmod/asyncio_wait_for.py", + "extmod/asyncio_wait_for_fwd.py", + "extmod/asyncio_wait_for_linked_task.py", + "extmod/asyncio_wait_task.py", + "extmod/json_dumps_float.py", + "extmod/json_loads_float.py", + "extmod/random_extra_float.py", + "extmod/select_poll_eintr.py", + "extmod/tls_threads.py", + "extmod/uctypes_le_float.py", + "extmod/uctypes_native_float.py", + "extmod/uctypes_sizeof_float.py", + "misc/rge_sm.py", + "ports/unix/ffi_float.py", + "ports/unix/ffi_float2.py", +) + +# These tests don't test slice explicitly but rather use it to perform the test. +tests_requiring_slice = ( + "basics/builtin_range.py", + "basics/bytearray1.py", + "basics/class_super.py", + "basics/containment.py", + "basics/errno1.py", + "basics/fun_str.py", + "basics/generator1.py", + "basics/globals_del.py", + "basics/memoryview1.py", + "basics/memoryview_gc.py", + "basics/object1.py", + "basics/python34.py", + "basics/struct_endian.py", + "extmod/btree1.py", + "extmod/deflate_decompress.py", + "extmod/framebuf16.py", + "extmod/framebuf4.py", + "extmod/machine1.py", + "extmod/time_mktime.py", + "extmod/time_res.py", + "extmod/tls_sslcontext_ciphers.py", + "extmod/vfs_fat_fileio1.py", + "extmod/vfs_fat_finaliser.py", + "extmod/vfs_fat_more.py", + "extmod/vfs_fat_ramdisk.py", + "extmod/vfs_fat_ramdisklarge.py", + "extmod/vfs_lfs.py", + "extmod/vfs_rom.py", + "float/string_format_modulo.py", + "micropython/builtin_execfile.py", + "micropython/extreme_exc.py", + "micropython/heapalloc_fail_bytearray.py", + "micropython/heapalloc_fail_list.py", + "micropython/heapalloc_fail_memoryview.py", + "micropython/import_mpy_invalid.py", + "micropython/import_mpy_native.py", + "micropython/import_mpy_native_gc.py", + "misc/non_compliant.py", + "misc/rge_sm.py", +) + +# Tests that require `import target_wiring` to work. +tests_requiring_target_wiring = ( + "extmod/machine_uart_irq_txidle.py", + "extmod/machine_uart_tx.py", + "extmod_hardware/machine_encoder.py", + "extmod_hardware/machine_uart_irq_break.py", + "extmod_hardware/machine_uart_irq_rx.py", + "extmod_hardware/machine_uart_irq_rxidle.py", +) + def rm_f(fname): if os.path.exists(fname): @@ -210,22 +358,31 @@ def convert_regex_escapes(line): return bytes("".join(cs), "utf8") +def platform_to_port(platform): + return platform_to_port_map.get(platform, platform) + + +def convert_device_shortcut_to_real_device(device): + if device.startswith("port:"): + return device.split(":", 1)[1] + elif device.startswith("a") and device[1:].isdigit(): + return "/dev/ttyACM" + device[1:] + elif device.startswith("u") and device[1:].isdigit(): + return "/dev/ttyUSB" + device[1:] + elif device.startswith("c") and device[1:].isdigit(): + return "COM" + device[1:] + else: + return device + + def get_test_instance(test_instance, baudrate, user, password): - if test_instance.startswith("port:"): - _, port = test_instance.split(":", 1) - elif test_instance == "unix": + if test_instance == "unix": return None elif test_instance == "webassembly": return PyboardNodeRunner() - elif test_instance.startswith("a") and test_instance[1:].isdigit(): - port = "/dev/ttyACM" + test_instance[1:] - elif test_instance.startswith("u") and test_instance[1:].isdigit(): - port = "/dev/ttyUSB" + test_instance[1:] - elif test_instance.startswith("c") and test_instance[1:].isdigit(): - port = "COM" + test_instance[1:] else: # Assume it's a device path. - port = test_instance + port = convert_device_shortcut_to_real_device(test_instance) global pyboard sys.path.append(base_path("../tools")) @@ -245,46 +402,114 @@ def detect_inline_asm_arch(pyb, args): return None +def map_rv32_arch_flags(flags): + mapped_flags = [] + for extension, bit in RV32_ARCH_FLAGS.items(): + if flags & bit: + mapped_flags.append(extension) + flags &= ~bit + if flags: + raise Exception("Unexpected flag bits set in value {}".format(flags)) + return mapped_flags + + def detect_test_platform(pyb, args): # Run a script to detect various bits of information about the target test instance. output = run_feature_check(pyb, args, "target_info.py") if output.endswith(b"CRASH"): raise ValueError("cannot detect platform: {}".format(output)) - platform, arch = str(output, "ascii").strip().split() + platform, arch, arch_flags, build, thread, float_prec, unicode = ( + str(output, "ascii").strip().split() + ) if arch == "None": arch = None inlineasm_arch = detect_inline_asm_arch(pyb, args) + if thread == "None": + thread = None + float_prec = int(float_prec) + unicode = unicode == "True" + if arch == "rv32imc": + arch_flags = map_rv32_arch_flags(int(arch_flags)) + else: + arch_flags = None args.platform = platform args.arch = arch + args.arch_flags = arch_flags if arch and not args.mpy_cross_flags: args.mpy_cross_flags = "-march=" + arch + if arch_flags: + args.mpy_cross_flags += " -march-flags=" + ",".join(arch_flags) args.inlineasm_arch = inlineasm_arch + args.build = build + args.thread = thread + args.float_prec = float_prec + args.unicode = unicode + # Print the detected information about the target. print("platform={}".format(platform), end="") if arch: print(" arch={}".format(arch), end="") + if arch_flags: + print(" arch_flags={}".format(",".join(arch_flags)), end="") if inlineasm_arch: print(" inlineasm={}".format(inlineasm_arch), end="") - print() - - -def prepare_script_for_target(args, *, script_filename=None, script_text=None, force_plain=False): + if thread: + print(" thread={}".format(thread), end="") + if float_prec: + print(" float={}-bit".format(float_prec), end="") + if unicode: + print(" unicode", end="") + + +def detect_target_wiring_script(pyb, args): + tw_data = b"" + tw_source = None + if args.target_wiring: + # A target_wiring path is explicitly provided, so use that. + tw_source = args.target_wiring + with open(tw_source, "rb") as f: + tw_data = f.read() + elif hasattr(pyb, "exec_raw") and pyb.exec_raw("import target_wiring") == (b"", b""): + # The board already has a target_wiring module available, so use that. + tw_source = "on-device" + else: + port = platform_to_port(args.platform) + build = args.build + tw_board_exact = None + tw_board_partial = None + tw_port = None + for file in os.listdir("target_wiring"): + file_base = file.removesuffix(".py") + if file_base == build: + # A file matching the target's board/build name. + tw_board_exact = file + elif file_base.endswith("x") and build.startswith(file_base.removesuffix("x")): + # A file with a partial match to the target's board/build name. + tw_board_partial = file + elif file_base == port: + # A file matching the target's port. + tw_port = file + tw_source = tw_board_exact or tw_board_partial or tw_port + if tw_source: + with open("target_wiring/" + tw_source, "rb") as f: + tw_data = f.read() + if tw_source: + print(" target_wiring={}".format(tw_source), end="") + pyb.target_wiring_script = tw_data + + +def prepare_script_for_target(args, *, script_text=None, force_plain=False): if force_plain or (not args.via_mpy and args.emit == "bytecode"): - if script_filename is not None: - with open(script_filename, "rb") as f: - script_text = f.read() + # A plain test to run as-is, no processing needed. + pass elif args.via_mpy: tempname = tempfile.mktemp(dir="") mpy_filename = tempname + ".mpy" - if script_filename is None: - script_filename = tempname + ".py" - cleanup_script_filename = True - with open(script_filename, "wb") as f: - f.write(script_text) - else: - cleanup_script_filename = False + script_filename = tempname + ".py" + with open(script_filename, "wb") as f: + f.write(script_text) try: subprocess.check_output( @@ -300,8 +525,7 @@ def prepare_script_for_target(args, *, script_filename=None, script_text=None, f script_text = b"__buf=" + bytes(repr(f.read()), "ascii") + b"\n" rm_f(mpy_filename) - if cleanup_script_filename: - rm_f(script_filename) + rm_f(script_filename) script_text += bytes(injected_import_hook_code, "ascii") else: @@ -312,34 +536,61 @@ def prepare_script_for_target(args, *, script_filename=None, script_text=None, f def run_script_on_remote_target(pyb, args, test_file, is_special): - had_crash, script = prepare_script_for_target( - args, script_filename=test_file, force_plain=is_special - ) + with open(test_file, "rb") as f: + script = f.read() + + # If the test is not a special test, prepend it with a print to indicate that it started. + # If the print does not execute this means that the test did not even start, eg it was + # too large for the target. + prepend_start_test = not is_special + if prepend_start_test: + if script.startswith(b"#"): + script = b"print('START TEST')" + script + else: + script = b"print('START TEST')\n" + script + + had_crash, script = prepare_script_for_target(args, script_text=script, force_plain=is_special) + if had_crash: return True, script try: had_crash = False pyb.enter_raw_repl() - output_mupy = pyb.exec_(script) + if test_file.endswith(tests_requiring_target_wiring) and pyb.target_wiring_script: + pyb.exec_( + "import sys;sys.modules['target_wiring']=__build_class__(lambda:exec(" + + repr(pyb.target_wiring_script) + + "),'target_wiring')" + ) + output_mupy = pyb.exec_(script, timeout=TEST_TIMEOUT) except pyboard.PyboardError as e: had_crash = True if not is_special and e.args[0] == "exception": - output_mupy = e.args[1] + e.args[2] + b"CRASH" + if prepend_start_test and e.args[1] == b"" and b"MemoryError" in e.args[2]: + output_mupy = b"SKIP-TOO-LARGE\n" + else: + output_mupy = e.args[1] + e.args[2] + b"CRASH" else: output_mupy = bytes(e.args[0], "ascii") + b"\nCRASH" + + if prepend_start_test: + if output_mupy.startswith(b"START TEST\r\n"): + output_mupy = output_mupy.removeprefix(b"START TEST\r\n") + else: + had_crash = True + return had_crash, output_mupy -special_tests = [ +tests_with_regex_output = [ base_path(file) for file in ( + # CIRCUITPY-CHANGE: removal and additions "micropython/meminfo.py", "basics/bytes_compare3.py", "basics/builtin_help.py", "thread/thread_exc2.py", - # CIRCUITPY-CHANGE: removal and additions - # REMOVE "esp32/partition_ota.py", "circuitpython/traceback_test.py", "circuitpython/traceback_test_chained.py", ) @@ -350,10 +601,7 @@ def run_micropython(pyb, args, test_file, test_file_abspath, is_special=False): had_crash = False if pyb is None: # run on PC - if ( - test_file_abspath.startswith((base_path("cmdline/"), base_path("feature_check/"))) - or test_file_abspath in special_tests - ): + if test_file_abspath.startswith((base_path("cmdline/"), base_path("feature_check/"))): # special handling for tests of the unix cmdline program is_special = True @@ -392,6 +640,10 @@ def get(required=False): return rv def send_get(what): + # Detect {\x00} pattern and convert to ctrl-key codes. + ctrl_code = lambda m: bytes([int(m.group(1))]) + what = re.sub(rb"{\\x(\d\d)}", ctrl_code, what) + os.write(master, what) return get() @@ -471,17 +723,17 @@ def send_get(what): ) # canonical form for all ports/platforms is to use \n for end-of-line - output_mupy = output_mupy.replace(b"\r\n", b"\n") + output_mupy = normalize_newlines(output_mupy) # don't try to convert the output if we should skip this test - if had_crash or output_mupy in (b"SKIP\n", b"CRASH"): + if had_crash or output_mupy in (b"SKIP\n", b"SKIP-TOO-LARGE\n", b"CRASH"): return output_mupy # skipped special tests will output "SKIP" surrounded by other interpreter debug output if is_special and not had_crash and b"\nSKIP\n" in output_mupy: return b"SKIP\n" - if is_special or test_file_abspath in special_tests: + if is_special or test_file_abspath in tests_with_regex_output: # convert parts of the output that are not stable across runs with open(test_file + ".exp", "rb") as f: lines_exp = [] @@ -603,30 +855,25 @@ def run_script_on_remote_target(self, args, test_file, is_special): def run_tests(pyb, tests, args, result_dir, num_threads=1): - test_count = ThreadSafeCounter() testcase_count = ThreadSafeCounter() - passed_count = ThreadSafeCounter() - failed_tests = ThreadSafeCounter([]) - skipped_tests = ThreadSafeCounter([]) + test_results = ThreadSafeCounter([]) skip_tests = set() skip_native = False skip_int_big = False + skip_int_64 = False skip_bytearray = False skip_set_type = False skip_slice = False skip_async = False skip_const = False skip_revops = False - skip_io_module = False skip_fstring = False skip_endian = False skip_inlineasm = False has_complex = True has_coverage = False - upy_float_precision = 32 - if True: # Even if we run completely different tests in a different directory, # we need to access feature_checks from the same directory as the @@ -642,6 +889,11 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): if output != b"1000000000000000000000000000000000000000000000\n": skip_int_big = True + # Check if 'long long' precision integers are supported, even if arbitrary precision is not + output = run_feature_check(pyb, args, "int_64.py") + if output != b"4611686018427387904\n": + skip_int_64 = True + # Check if bytearray is supported, and skip such tests if it's not output = run_feature_check(pyb, args, "bytearray.py") if output != b"bytearray\n": @@ -672,11 +924,6 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): if output == b"TypeError\n": skip_revops = True - # Check if io module exists, and skip such tests if it doesn't - output = run_feature_check(pyb, args, "io_module.py") - if output != b"io\n": - skip_io_module = True - # Check if fstring feature is enabled, and skip such tests if it doesn't output = run_feature_check(pyb, args, "fstring.py") if output != b"a=1\n": @@ -690,13 +937,20 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): skip_tests.add("inlineasm/thumb/asmbitops.py") skip_tests.add("inlineasm/thumb/asmconst.py") skip_tests.add("inlineasm/thumb/asmdiv.py") + skip_tests.add("inlineasm/thumb/asmit.py") + skip_tests.add("inlineasm/thumb/asmspecialregs.py") + if args.arch not in ("armv7emsp", "armv7emdp"): skip_tests.add("inlineasm/thumb/asmfpaddsub.py") skip_tests.add("inlineasm/thumb/asmfpcmp.py") skip_tests.add("inlineasm/thumb/asmfpldrstr.py") skip_tests.add("inlineasm/thumb/asmfpmuldiv.py") skip_tests.add("inlineasm/thumb/asmfpsqrt.py") - skip_tests.add("inlineasm/thumb/asmit.py") - skip_tests.add("inlineasm/thumb/asmspecialregs.py") + + if args.inlineasm_arch == "rv32": + # Check if @micropython.asm_rv32 supports Zba instructions, and skip such tests if it doesn't + output = run_feature_check(pyb, args, "inlineasm_rv32_zba.py") + if output != b"rv32_zba\n": + skip_tests.add("inlineasm/rv32/asmzba.py") # Check if emacs repl is supported, and skip such tests if it's not t = run_feature_check(pyb, args, "repl_emacs_check.py") @@ -709,11 +963,6 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): skip_tests.add("cmdline/repl_words_move.py") upy_byteorder = run_feature_check(pyb, args, "byteorder.py") - upy_float_precision = run_feature_check(pyb, args, "float.py") - try: - upy_float_precision = int(upy_float_precision) - except ValueError: - upy_float_precision = 0 has_complex = run_feature_check(pyb, args, "complex.py") == b"complex\n" has_coverage = run_feature_check(pyb, args, "coverage.py") == b"coverage\n" cpy_byteorder = subprocess.check_output( @@ -723,24 +972,6 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): skip_inlineasm = args.inlineasm_arch is None - # These tests don't test slice explicitly but rather use it to perform the test - misc_slice_tests = ( - "builtin_range", - "bytearray1", - "class_super", - "containment", - "errno1", - "fun_str", - "generator1", - "globals_del", - "memoryview1", - "memoryview_gc", - "object1", - "python34", - "string_format_modulo", - "struct_endian", - ) - # Some tests shouldn't be run on GitHub Actions if os.getenv("GITHUB_ACTIONS") == "true": skip_tests.add("thread/stress_schedule.py") # has reliability issues @@ -749,30 +980,31 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): # fails with stack overflow on Debug builds skip_tests.add("misc/sys_settrace_features.py") - if upy_float_precision == 0: - skip_tests.add("extmod/uctypes_le_float.py") - skip_tests.add("extmod/uctypes_native_float.py") - skip_tests.add("extmod/uctypes_sizeof_float.py") - skip_tests.add("extmod/json_dumps_float.py") - skip_tests.add("extmod/json_loads_float.py") - skip_tests.add("extmod/random_extra_float.py") - skip_tests.add("misc/rge_sm.py") - if upy_float_precision < 32: + if args.float_prec == 0: + skip_tests.update(tests_requiring_float) + if args.float_prec < 32: skip_tests.add( "float/float2int_intbig.py" ) # requires fp32, there's float2int_fp30_intbig.py instead skip_tests.add( - "float/string_format.py" - ) # requires fp32, there's string_format_fp30.py instead + "float/float_struct_e.py" + ) # requires fp32, there's float_struct_e_fp30.py instead skip_tests.add("float/bytes_construct.py") # requires fp32 skip_tests.add("float/bytearray_construct.py") # requires fp32 skip_tests.add("float/float_format_ints_power10.py") # requires fp32 - if upy_float_precision < 64: + if args.float_prec < 64: skip_tests.add("float/float_divmod.py") # tested by float/float_divmod_relaxed.py instead skip_tests.add("float/float2int_doubleprec_intbig.py") + skip_tests.add("float/float_struct_e_doubleprec.py") skip_tests.add("float/float_format_ints_doubleprec.py") skip_tests.add("float/float_parse_doubleprec.py") + if not args.unicode: + skip_tests.add("extmod/json_loads.py") # tests loading a utf-8 character + + if skip_slice: + skip_tests.update(tests_requiring_slice) + if not has_complex: skip_tests.add("float/complex1.py") skip_tests.add("float/complex1_intbig.py") @@ -788,8 +1020,8 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): skip_tests.add("cmdline/repl_sys_ps1_ps2.py") skip_tests.add("extmod/ssl_poll.py") - # Skip thread mutation tests on targets that don't have the GIL. - if args.platform in PC_PLATFORMS + ("rp2",): + # Skip thread mutation tests on targets that have unsafe threading behaviour. + if args.thread == "unsafe": for t in tests: if t.startswith("thread/mutate_"): skip_tests.add(t) @@ -798,6 +1030,15 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): if args.platform not in PC_PLATFORMS: skip_tests.add("basics/exception_chain.py") # warning is not printed skip_tests.add("micropython/meminfo.py") # output is very different to PC output + skip_tests.add("unicode/file1.py") # requires local file access + skip_tests.add("unicode/file2.py") # requires local file access + skip_tests.add("unicode/file_invalid.py") # requires local file access + + # Skip certain tests when going via a .mpy file. + skip_tests.update(via_mpy_tests_to_skip.get(args.via_mpy, ())) + + # Skip emitter-specific tests. + skip_tests.update(emitter_tests_to_skip.get(args.emit, ())) # Skip platform-specific tests. skip_tests.update(platform_tests_to_skip.get(args.platform, ())) @@ -812,49 +1053,6 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): # Works but CPython uses '\' path separator skip_tests.add("import/import_file.py") - # Some tests are known to fail with native emitter - # Remove them from the below when they work - if args.emit == "native": - skip_tests.add("basics/gen_yield_from_close.py") # require raise_varargs - skip_tests.update( - {"basics/%s.py" % t for t in "try_reraise try_reraise2".split()} - ) # require raise_varargs - skip_tests.add("basics/annotate_var.py") # requires checking for unbound local - skip_tests.add("basics/del_deref.py") # requires checking for unbound local - skip_tests.add("basics/del_local.py") # requires checking for unbound local - skip_tests.add("basics/exception_chain.py") # raise from is not supported - skip_tests.add("basics/scope_implicit.py") # requires checking for unbound local - skip_tests.add("basics/sys_tracebacklimit.py") # requires traceback info - skip_tests.add("basics/try_finally_return2.py") # requires raise_varargs - skip_tests.add("basics/unboundlocal.py") # requires checking for unbound local - skip_tests.add("misc/features.py") # requires raise_varargs - # CIRCUITPY-CHANGE - skip_tests.update( - ( - "basics/chained_exception.py", - "circuitpython/traceback_test.py", - "circuitpython/traceback_test_chained.py", - ) - ) # because native doesn't have proper traceback info - skip_tests.add( - "misc/print_exception.py" - ) # because native doesn't have proper traceback info - skip_tests.add("misc/sys_exc_info.py") # sys.exc_info() is not supported for native - skip_tests.add("misc/sys_settrace_features.py") # sys.settrace() not supported - skip_tests.add("misc/sys_settrace_generator.py") # sys.settrace() not supported - skip_tests.add("misc/sys_settrace_loop.py") # sys.settrace() not supported - skip_tests.add( - "micropython/emg_exc.py" - ) # because native doesn't have proper traceback info - skip_tests.add( - "micropython/heapalloc_traceback.py" - ) # because native doesn't have proper traceback info - skip_tests.add( - "micropython/opt_level_lineno.py" - ) # native doesn't have proper traceback info - skip_tests.add("micropython/schedule.py") # native code doesn't check pending events - skip_tests.add("stress/bytecode_limit.py") # bytecode specific test - def run_one_test(test_file): test_file = test_file.replace("\\", "/") test_file_abspath = os.path.abspath(test_file).replace("\\", "/") @@ -870,19 +1068,19 @@ def run_one_test(test_file): test_basename = test_file.replace("..", "_").replace("./", "").replace("/", "_") test_name = os.path.splitext(os.path.basename(test_file))[0] - is_native = ( - test_name.startswith("native_") - or test_name.startswith("viper_") - or args.emit == "native" - ) + is_native = test_name.startswith("native_") or test_name.startswith("viper_") is_endian = test_name.endswith("_endian") - is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig") + is_int_big = ( + test_name.startswith("int_big") + or test_name.endswith("_intbig") + or test_name.startswith("ffi_int") # these tests contain large integer literals + ) + is_int_64 = test_name.startswith("int_64") or test_name.endswith("_int64") is_bytearray = test_name.startswith("bytearray") or test_name.endswith("_bytearray") is_set_type = test_name.startswith(("set_", "frozenset")) or test_name.endswith("_set") - is_slice = test_name.find("slice") != -1 or test_name in misc_slice_tests - is_async = test_name.startswith(("async_", "asyncio_")) + is_slice = test_name.find("slice") != -1 + is_async = test_name.startswith(("async_", "asyncio_")) or test_name.endswith("_async") is_const = test_name.startswith("const") - is_io_module = test_name.startswith("io_") is_fstring = test_name.startswith("string_fstring") is_inlineasm = test_name.startswith("asm") @@ -890,19 +1088,19 @@ def run_one_test(test_file): skip_it |= skip_native and is_native skip_it |= skip_endian and is_endian skip_it |= skip_int_big and is_int_big + skip_it |= skip_int_64 and is_int_64 skip_it |= skip_bytearray and is_bytearray skip_it |= skip_set_type and is_set_type skip_it |= skip_slice and is_slice skip_it |= skip_async and is_async skip_it |= skip_const and is_const skip_it |= skip_revops and "reverse_op" in test_name - skip_it |= skip_io_module and is_io_module skip_it |= skip_fstring and is_fstring skip_it |= skip_inlineasm and is_inlineasm if skip_it: print("skip ", test_file) - skipped_tests.append(test_name) + test_results.append((test_file, "skip", "")) return # Run the test on the MicroPython target. @@ -917,7 +1115,11 @@ def run_one_test(test_file): # start-up code (eg boot.py) when preparing to run the next test. pyb.read_until(1, b"raw REPL; CTRL-B to exit\r\n") print("skip ", test_file) - skipped_tests.append(test_name) + test_results.append((test_file, "skip", "")) + return + elif output_mupy == b"SKIP-TOO-LARGE\n": + print("lrge ", test_file) + test_results.append((test_file, "skip", "too large")) return # Look at the output of the test to see if unittest was used. @@ -954,7 +1156,11 @@ def run_one_test(test_file): # Expected output is result of running unittest. output_expected = None else: - test_file_expected = test_file + ".exp" + # Prefer emitter-specific expected output. + test_file_expected = test_file + "." + args.emit + ".exp" + if not os.path.isfile(test_file_expected): + # Fall back to generic expected output. + test_file_expected = test_file + ".exp" if os.path.isfile(test_file_expected): # Expected output given by a file, so read that in. with open(test_file_expected, "rb") as f: @@ -1012,7 +1218,7 @@ def run_one_test(test_file): # Print test summary, update counters, and save .exp/.out files if needed. if test_passed: print("pass ", test_file, extra_info) - passed_count.increment() + test_results.append((test_file, "pass", "")) rm_f(filename_expected) rm_f(filename_mupy) else: @@ -1024,9 +1230,7 @@ def run_one_test(test_file): rm_f(filename_expected) # in case left over from previous failed run with open(filename_mupy, "wb") as f: f.write(output_mupy) - failed_tests.append((test_name, test_file)) - - test_count.increment() + test_results.append((test_file, "fail", "")) # Print a note if this looks like it might have been a misfired unittest if not uses_unittest and not test_passed: @@ -1053,17 +1257,49 @@ def run_one_test(test_file): print(line) sys.exit(1) - print( - "{} tests performed ({} individual testcases)".format( - test_count.value, testcase_count.value - ) + # Return test results. + return test_results.value, testcase_count.value + + +# Print a summary of the results and save them to a JSON file. +# Returns True if everything succeeded, False otherwise. +def create_test_report(args, test_results, testcase_count=None): + passed_tests = list(r for r in test_results if r[1] == "pass") + skipped_tests = list(r for r in test_results if r[1] == "skip" and r[2] != "too large") + skipped_tests_too_large = list( + r for r in test_results if r[1] == "skip" and r[2] == "too large" ) - print("{} tests passed".format(passed_count.value)) + failed_tests = list(r for r in test_results if r[1] == "fail") + + num_tests_performed = len(passed_tests) + len(failed_tests) + + testcase_count_info = "" + if testcase_count is not None: + testcase_count_info = " ({} individual testcases)".format(testcase_count) + print("{} tests performed{}".format(num_tests_performed, testcase_count_info)) + + print("{} tests passed".format(len(passed_tests))) - skipped_tests = sorted(skipped_tests.value) if len(skipped_tests) > 0: - print("{} tests skipped: {}".format(len(skipped_tests), " ".join(skipped_tests))) - failed_tests = sorted(failed_tests.value) + print( + "{} tests skipped: {}".format( + len(skipped_tests), " ".join(test[0] for test in skipped_tests) + ) + ) + + if len(skipped_tests_too_large) > 0: + print( + "{} tests skipped because they are too large: {}".format( + len(skipped_tests_too_large), " ".join(test[0] for test in skipped_tests_too_large) + ) + ) + + if len(failed_tests) > 0: + print( + "{} tests failed: {}".format( + len(failed_tests), " ".join(test[0] for test in failed_tests) + ) + ) # Serialize regex added by append_filter. def to_json(obj): @@ -1071,23 +1307,22 @@ def to_json(obj): return obj.pattern return obj - with open(os.path.join(result_dir, RESULTS_FILE), "w") as f: + with open(os.path.join(args.result_dir, RESULTS_FILE), "w") as f: json.dump( - {"args": vars(args), "failed_tests": [test[1] for test in failed_tests]}, + { + # The arguments passed on the command-line. + "args": vars(args), + # A list of all results of the form [(test, result, reason), ...]. + "results": list(test for test in test_results), + # A list of failed tests. This is deprecated, use the "results" above instead. + "failed_tests": [test[0] for test in failed_tests], + }, f, default=to_json, ) - if len(failed_tests) > 0: - print( - "{} tests failed: {}".format( - len(failed_tests), " ".join(test[0] for test in failed_tests) - ) - ) - return False - - # all tests succeeded - return True + # Return True only if all tests succeeded. + return len(failed_tests) == 0 class append_filter(argparse.Action): @@ -1104,27 +1339,11 @@ def __call__(self, parser, args, value, option): args.filters.append((option, re.compile(value))) -def main(): - cmd_parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description="""Run and manage tests for MicroPython. - +test_instance_description = """\ By default the tests are run against the unix port of MicroPython. To run it against something else, use the -t option. See below for details. - -Tests are discovered by scanning test directories for .py files or using the -specified test files. If test files nor directories are specified, the script -expects to be ran in the tests directory (where this file is located) and the -builtin tests suitable for the target platform are ran. - -When running tests, run-tests.py compares the MicroPython output of the test with the output -produced by running the test through CPython unless a .exp file is found, in which -case it is used as comparison. - -If a test fails, run-tests.py produces a pair of .out and .exp files in the result -directory with the MicroPython output and the expectations, respectively. -""", - epilog="""\ +""" +test_instance_epilog = """\ The -t option accepts the following for the test instance: - unix - use the unix port of MicroPython, specified by the MICROPY_MICROPYTHON environment variable (which defaults to the standard variant of either the unix @@ -1140,7 +1359,35 @@ def main(): - execpty: - execute a command and attach to the printed /dev/pts/ device - ... - connect to the given IPv4 address - anything else specifies a serial port +""" + +test_directory_description = """\ +Tests are discovered by scanning test directories for .py files or using the +specified test files. If test files nor directories are specified, the script +expects to be ran in the tests directory (where this file is located) and the +builtin tests suitable for the target platform are ran. +""" + +def main(): + global injected_import_hook_code + + cmd_parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=f"""Run and manage tests for MicroPython. + +{test_instance_description} +{test_directory_description} + +When running tests, run-tests.py compares the MicroPython output of the test with the output +produced by running the test through CPython unless a .exp file is found (or a +.native.exp file when using the native emitter), in which case it is used as comparison. + +If a test fails, run-tests.py produces a pair of .out and .exp files in the result +directory with the MicroPython output and the expectations, respectively. +""", + epilog=f"""\ +{test_instance_epilog} Options -i and -e can be multiple and processed in the order given. Regex "search" (vs "match") operation is used. An action (include/exclude) of the last matching regex is used: @@ -1214,8 +1461,25 @@ def main(): action="store_true", help="re-run only the failed tests", ) + cmd_parser.add_argument( + "--begin", + metavar="PROLOGUE", + default=None, + help="prologue python file to execute before module import", + ) + cmd_parser.add_argument( + "--target-wiring", + default=None, + help="force the given script to be used as target_wiring.py", + ) args = cmd_parser.parse_args() + prologue = "" + if args.begin: + with open(args.begin, "rt") as source: + prologue = source.read() + injected_import_hook_code = injected_import_hook_code.replace("{import_prologue}", prologue) + if args.print_failures: for out in glob(os.path.join(args.result_dir, "*.out")): testbase = out[:-4] @@ -1256,7 +1520,7 @@ def main(): results_file = os.path.join(args.result_dir, RESULTS_FILE) if os.path.exists(results_file): with open(results_file, "r") as f: - tests = json.load(f)["failed_tests"] + tests = list(test[0] for test in json.load(f)["results"] if test[1] == "fail") else: tests = [] elif len(args.files) == 0: @@ -1267,47 +1531,27 @@ def main(): if args.test_dirs is None: test_dirs = ( "basics", - "circuitpython", # CIRCUITPY-CHANGE "micropython", "misc", "extmod", + "stress", ) if args.inlineasm_arch is not None: test_dirs += ("inlineasm/{}".format(args.inlineasm_arch),) - if args.platform == "pyboard": - # run pyboard tests - test_dirs += ("float", "stress", "ports/stm32") - elif args.platform == "mimxrt": - test_dirs += ("float", "stress") - elif args.platform == "renesas-ra": - test_dirs += ("float", "ports/renesas-ra") - elif args.platform == "rp2": - test_dirs += ("float", "stress", "thread", "ports/rp2") - elif args.platform == "esp32": - test_dirs += ("float", "stress", "thread") - elif args.platform in ("esp8266", "minimal", "samd", "nrf"): + if args.thread is not None: + test_dirs += ("thread",) + if args.float_prec > 0: test_dirs += ("float",) - elif args.platform == "WiPy": - # run WiPy tests - test_dirs += ("ports/cc3200",) - elif args.platform in PC_PLATFORMS: + if args.unicode: + test_dirs += ("unicode",) + port_specific_test_dir = "ports/{}".format(platform_to_port(args.platform)) + if os.path.isdir(port_specific_test_dir): + test_dirs += (port_specific_test_dir,) + if args.platform in PC_PLATFORMS: # run PC tests - test_dirs += ( - "float", - "import", - "io", - "stress", - "unicode", - "cmdline", - "ports/unix", - ) - elif args.platform == "qemu": - test_dirs += ( - "float", - "ports/qemu", - ) - elif args.platform == "webassembly": - test_dirs += ("float", "ports/webassembly") + test_dirs += ("import",) + if args.build != "minimal": + test_dirs += ("cmdline", "io") else: # run tests from these directories test_dirs = args.test_dirs @@ -1322,6 +1566,13 @@ def main(): # tests explicitly given tests = args.files + # If any tests need it, prepare the target_wiring script for the target. + if pyb and any(test.endswith(tests_requiring_target_wiring) for test in tests): + detect_target_wiring_script(pyb, args) + + # End the target information line. + print() + if not args.keep_path: # Clear search path to make sure tests use only builtin modules, those in # extmod, and a path to unittest in case it's needed. @@ -1342,7 +1593,8 @@ def main(): try: os.makedirs(args.result_dir, exist_ok=True) - res = run_tests(pyb, tests, args, args.result_dir, args.jobs) + test_results, testcase_count = run_tests(pyb, tests, args, args.result_dir, args.jobs) + res = create_test_report(args, test_results, testcase_count) finally: if pyb: pyb.close() diff --git a/tests/serial_test.py b/tests/serial_test.py new file mode 100755 index 00000000000..3b5940d91a9 --- /dev/null +++ b/tests/serial_test.py @@ -0,0 +1,338 @@ +#!/usr/bin/env python +# +# Performance and reliability test for serial port communication. +# +# Basic usage: +# serial_test.py [-t serial-device] +# +# The `serial-device` will default to /dev/ttyACM0. + +import argparse +import random +import serial +import sys +import time + +run_tests_module = __import__("run-tests") + +echo_test_script = """ +import sys +bytes_min=%u +bytes_max=%u +repeat=%u +b=memoryview(bytearray(bytes_max)) +for n in range(bytes_min,bytes_max+1): + for _ in range(repeat): + n2 = sys.stdin.readinto(b[:n]) + sys.stdout.write(b[:n2]) +""" + +read_test_script = """ +bin = True +try: + wr=__import__("pyb").USB_VCP(0).send +except: + import sys + if hasattr(sys.stdout,'buffer'): + wr=sys.stdout.buffer.write + else: + wr=sys.stdout.write + bin = False +b=bytearray(%u) +if bin: + wr('BIN') + for i in range(len(b)): + b[i] = i & 0xff +else: + wr('TXT') + for i in range(len(b)): + b[i] = 0x20 + (i & 0x3f) +for _ in range(%d): + wr(b) +""" + + +write_test_script_verified = """ +import sys +try: + rd=__import__("pyb").USB_VCP(0).recv +except: + rd=sys.stdin.readinto +b=bytearray(%u) +for _ in range(%u): + n = rd(b) + fail = 0 + for i in range(n): + if b[i] != 32 + (i & 0x3f): + fail += 1 + if fail: + sys.stdout.write(b'ER%%05u' %% fail) + else: + sys.stdout.write(b'OK%%05u' %% n) +""" + +write_test_script_unverified = """ +import sys +try: + rd=__import__("pyb").USB_VCP(0).recv +except: + rd=sys.stdin.readinto +b=bytearray(%u) +for _ in range(%u): + n = rd(b) + if n != len(b): + sys.stdout.write(b'ER%%05u' %% n) + else: + sys.stdout.write(b'OK%%05u' %% n) +""" + + +class TestError(Exception): + pass + + +def drain_input(ser): + time.sleep(0.1) + while ser.inWaiting() > 0: + data = ser.read(ser.inWaiting()) + time.sleep(0.1) + + +def send_script(ser, script): + ser.write(b"\x03\x01\x04") # break, raw-repl, soft-reboot + drain_input(ser) + chunk_size = 32 + for i in range(0, len(script), chunk_size): + ser.write(script[i : i + chunk_size]) + time.sleep(0.01) + ser.write(b"\x04") # eof + ser.flush() + response = ser.read(2) + if response != b"OK": + response += ser.read(ser.inWaiting()) + raise TestError("could not send script", response) + + +def echo_test(ser_repl, ser_data): + global test_passed + + # Make the test data deterministic. + random.seed(0) + + # Set parameters for the test. + # Go just a bit above the size of a USB high-speed packet. + bytes_min = 1 + bytes_max = 520 + num_repeat = 1 + + # Load and run the write_test_script. + script = bytes(echo_test_script % (bytes_min, bytes_max, num_repeat), "ascii") + send_script(ser_repl, script) + + # A selection of printable bytes for echo data. + printable_bytes = list(range(48, 58)) + list(range(65, 91)) + list(range(97, 123)) + + # Write data to the device and record the echo'd data. + # Use a different selection of random printable characters for each + # echo, to make it easier to debug when the echo doesn't match. + num_errors = 0 + echo_results = [] + for num_bytes in range(bytes_min, bytes_max + 1): + print(f"DATA ECHO: {num_bytes} / {bytes_max}", end="\r") + for repeat in range(num_repeat): + rand_bytes = list(random.choice(printable_bytes) for _ in range(8)) + buf = bytes(random.choice(rand_bytes) for _ in range(num_bytes)) + ser_data.write(buf) + buf2 = ser_data.read(len(buf)) + match = buf == buf2 + num_errors += not match + echo_results.append((match, buf, buf2)) + if num_errors > 8: + # Stop early if there are too many errors. + break + ser_repl.write(b"\x03") + + # Print results. + if all(match for match, _, _ in echo_results): + print("DATA ECHO: OK for {}-{} bytes at a time".format(bytes_min, bytes_max)) + else: + test_passed = False + print("DATA ECHO: FAIL ") + for match, buf, buf2 in echo_results: + print(" sent", len(buf), buf) + if match: + print(" echo match") + else: + print(" echo", len(buf), buf2) + + +def read_test(ser_repl, ser_data, bufsize, nbuf): + global test_passed + + assert bufsize % 256 == 0 # for verify to work + + # how long to wait for data from device + # (if UART TX is also enabled then it can take 1.4s to send + # out a 16KB butter at 115200bps) + READ_TIMEOUT_S = 2 + + # Load and run the read_test_script. + script = bytes(read_test_script % (bufsize, nbuf), "ascii") + send_script(ser_repl, script) + + # Read from the device the type of data that it will send (BIN or TXT). + data_type = ser_data.read(3) + + # Read data from the device, check it is correct, and measure throughput. + n = 0 + last_byte = None + t_start = time.time() + remain = nbuf * bufsize + total_data = bytearray(remain) + while remain: + t0 = time.monotonic_ns() + while ser_data.inWaiting() == 0: + if time.monotonic_ns() - t0 > READ_TIMEOUT_S * 1e9: + # timeout waiting for data from device + break + time.sleep(0.0001) + if not ser_data.inWaiting(): + test_passed = False + print("ERROR: timeout waiting for data") + print(total_data[:n]) + return 0 + to_read = min(ser_data.inWaiting(), remain) + data = ser_data.read(to_read) + remain -= len(data) + print(f"{n} / {nbuf * bufsize}", end="\r") + total_data[n : n + len(data)] = data + n += len(data) + t_end = time.time() + for i in range(0, len(total_data)): + if data_type == b"BIN": + wanted = i & 0xFF + else: + wanted = 0x20 + (i & 0x3F) + if total_data[i] != wanted: + test_passed = False + print("ERROR: data mismatch:", i, wanted, total_data[i]) + ser_repl.write(b"\x03") # break + t = t_end - t_start + + # Print results. + print( + "DATA IN: bufsize=%u, read %u bytes in %.2f msec = %.2f kibytes/sec = %.2f MBits/sec" + % (bufsize, n, t * 1000, n / 1024 / t, n * 8 / 1000000 / t) + ) + + return n / t + + +def write_test(ser_repl, ser_data, bufsize, nbuf, verified): + global test_passed + + # Load and run the write_test_script. + if verified: + script = write_test_script_verified + else: + script = write_test_script_unverified + script = bytes(script % (bufsize, nbuf), "ascii") + send_script(ser_repl, script) + drain_input(ser_repl) + + # Write data to the device, check it is correct, and measure throughput. + n = 0 + t_start = time.time() + buf = bytearray(bufsize) + for i in range(len(buf)): + buf[i] = 32 + (i & 0x3F) # don't want to send ctrl chars! + for i in range(nbuf): + ser_data.write(buf) + n += len(buf) + print(f"{n} / {nbuf * bufsize}", end="\r") + response = ser_repl.read(7) + if response != b"OK%05u" % bufsize: + test_passed = False + print("ERROR: bad response, expecting OK%05u, got %r" % (bufsize, response)) + t_end = time.time() + ser_repl.write(b"\x03") # break + t = t_end - t_start + + # Print results. + print( + "DATA OUT: verify=%d, bufsize=%u, wrote %u bytes in %.2f msec = %.2f kibytes/sec = %.2f MBits/sec" + % (verified, bufsize, n, t * 1000, n / 1024 / t, n * 8 / 1000000 / t) + ) + + return n / t + + +def do_test(dev_repl, dev_data=None, time_per_subtest=1): + if dev_data is None: + print("REPL and data on", dev_repl) + ser_repl = serial.Serial(dev_repl, baudrate=115200, timeout=1) + ser_data = ser_repl + else: + print("REPL on", dev_repl) + print("data on", dev_data) + ser_repl = serial.Serial(dev_repl, baudrate=115200, timeout=1) + ser_data = serial.Serial(dev_data, baudrate=115200, timeout=1) + + # Do echo test first, and abort if it doesn't pass. + echo_test(ser_repl, ser_data) + if not test_passed: + return + + # Do read and write throughput test. + for test_func, test_args, bufsize in ( + (read_test, (), 256), + (write_test, (True,), 128), + (write_test, (False,), 128), + ): + nbuf = 128 + while bufsize <= 16384: + rate = test_func(ser_repl, ser_data, bufsize, nbuf, *test_args) + bufsize *= 2 + if rate: + # Adjust the amount of data based on the rate, to keep each subtest + # at around time_per_subtest seconds long. + nbuf = max(min(128, int(rate * time_per_subtest / bufsize)), 1) + + ser_repl.close() + ser_data.close() + + +def main(): + global test_passed + + cmd_parser = argparse.ArgumentParser( + description="Test performance and reliability of serial port communication.", + epilog=run_tests_module.test_instance_epilog, + formatter_class=argparse.RawTextHelpFormatter, + ) + cmd_parser.add_argument( + "-t", + "--test-instance", + default="a0", + help="MicroPython instance to test", + ) + cmd_parser.add_argument( + "--time-per-subtest", default="1", help="approximate time to take per subtest (in seconds)" + ) + args = cmd_parser.parse_args() + + dev_repl = run_tests_module.convert_device_shortcut_to_real_device(args.test_instance) + + test_passed = True + try: + do_test(dev_repl, None, float(args.time_per_subtest)) + except TestError as er: + test_passed = False + print("ERROR:", er) + + if not test_passed: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/tests/stress/bytecode_limit.py b/tests/stress/bytecode_limit.py index 948d7668da5..0a72b66fa05 100644 --- a/tests/stress/bytecode_limit.py +++ b/tests/stress/bytecode_limit.py @@ -1,19 +1,29 @@ # Test the limits of bytecode generation. +import sys + +# Tune the test parameters based on the target's bytecode generator. +if hasattr(sys.implementation, "_mpy"): + # Target can load .mpy files so generated bytecode uses 1 byte per qstr. + number_of_body_copies = (433, 432, 431, 399) +else: + # Target can't load .mpy files so generated bytecode uses 2 bytes per qstr. + number_of_body_copies = (401, 400, 399, 398) + body = " with f()()() as a:\n try:\n f()()()\n except Exception:\n pass\n" # Test overflow of jump offset. # Print results at the end in case an intermediate value of n fails with MemoryError. results = [] -for n in (433, 432, 431, 430): +for n in number_of_body_copies: try: exec("cond = 0\nif cond:\n" + body * n + "else:\n print('cond false')\n") - results.append((n, "ok")) + results.append("ok") except MemoryError: print("SKIP") raise SystemExit - except RuntimeError: - results.append((n, "RuntimeError")) + except RuntimeError as er: + results.append(repr(er)) print(results) # Test changing size of code info (source line/bytecode mapping) due to changing diff --git a/tests/stress/bytecode_limit.py.exp b/tests/stress/bytecode_limit.py.exp index cda52b1b973..50511665f00 100644 --- a/tests/stress/bytecode_limit.py.exp +++ b/tests/stress/bytecode_limit.py.exp @@ -1,4 +1,4 @@ cond false cond false -[(433, 'RuntimeError'), (432, 'RuntimeError'), (431, 'ok'), (430, 'ok')] +["RuntimeError('bytecode overflow',)", "RuntimeError('bytecode overflow',)", 'ok', 'ok'] [123] diff --git a/tests/stress/dict_copy.py b/tests/stress/dict_copy.py index 73d3a5b51d6..f9b742e20f7 100644 --- a/tests/stress/dict_copy.py +++ b/tests/stress/dict_copy.py @@ -1,6 +1,11 @@ # copying a large dictionary -a = {i: 2 * i for i in range(1000)} +try: + a = {i: 2 * i for i in range(1000)} +except MemoryError: + print("SKIP") + raise SystemExit + b = a.copy() for i in range(1000): print(i, b[i]) diff --git a/tests/stress/dict_create.py b/tests/stress/dict_create.py index e9db40a8e6c..91a83a12f9d 100644 --- a/tests/stress/dict_create.py +++ b/tests/stress/dict_create.py @@ -3,6 +3,10 @@ d = {} x = 1 while x < 1000: - d[x] = x + try: + d[x] = x + except MemoryError: + print("SKIP") + raise SystemExit x += 1 print(d[500]) diff --git a/tests/stress/fun_call_limit.py b/tests/stress/fun_call_limit.py index b802aadd558..69f8aa5aec4 100644 --- a/tests/stress/fun_call_limit.py +++ b/tests/stress/fun_call_limit.py @@ -16,14 +16,16 @@ def test(n): # If the port has at least 32-bits then this test should pass. -print(test(29)) +print(test(28)) # This test should fail on all ports (overflows a small int). print(test(70)) -# Check that there is a correct transition to the limit of too many args before *args. +# 28 is the biggest number that will pass on a 32-bit port using object +# representation B, which has 1<<28 still fitting in a positive small int. reached_limit = False -for i in range(30, 70): +any_test_succeeded = False +for i in range(28, 70): result = test(i) if reached_limit: if result != "SyntaxError": @@ -34,3 +36,5 @@ def test(n): else: if result != i + 4: print("FAIL") + any_test_succeeded = True +assert any_test_succeeded # At least one iteration must have passed diff --git a/tests/stress/fun_call_limit.py.exp b/tests/stress/fun_call_limit.py.exp index 53d2b280430..491abbfa8be 100644 --- a/tests/stress/fun_call_limit.py.exp +++ b/tests/stress/fun_call_limit.py.exp @@ -1,2 +1,2 @@ -33 +32 SyntaxError diff --git a/tests/stress/qstr_limit.py b/tests/stress/qstr_limit.py index 08b10a039f5..c7bd437f3ad 100644 --- a/tests/stress/qstr_limit.py +++ b/tests/stress/qstr_limit.py @@ -12,8 +12,8 @@ def make_id(n, base="a"): var = make_id(l) try: exec(var + "=1", g) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) continue print(var in g) @@ -26,16 +26,16 @@ def f(**k): for l in range(254, 259): try: exec("f({}=1)".format(make_id(l))) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) # type construction for l in range(254, 259): id = make_id(l) try: - print(type(id, (), {}).__name__) - except RuntimeError: - print("RuntimeError", l) + print(type(id, (), {})) + except RuntimeError as er: + print("RuntimeError", er, l) # hasattr, setattr, getattr @@ -48,28 +48,20 @@ class A: a = A() try: setattr(a, id, 123) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) try: print(hasattr(a, id), getattr(a, id)) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) # format with keys for l in range(254, 259): id = make_id(l) try: print(("{" + id + "}").format(**{id: l})) - except RuntimeError: - print("RuntimeError", l) - -# modulo format with keys -for l in range(254, 259): - id = make_id(l) - try: - print(("%(" + id + ")d") % {id: l}) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) # import module # (different OS's have different results so only run those that are consistent) @@ -78,8 +70,8 @@ class A: __import__(make_id(l)) except ImportError: print("ok", l) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) # import package for l in (100, 101, 102, 128, 129): @@ -87,5 +79,5 @@ class A: exec("import " + make_id(l) + "." + make_id(l, "A")) except ImportError: print("ok", l) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) diff --git a/tests/stress/qstr_limit.py.exp b/tests/stress/qstr_limit.py.exp index 455761bc71e..2349adf220f 100644 --- a/tests/stress/qstr_limit.py.exp +++ b/tests/stress/qstr_limit.py.exp @@ -1,43 +1,38 @@ True True -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 {'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst': 1} {'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu': 1} -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 -abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst -abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 + + +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 True 123 True 123 -RuntimeError 256 -RuntimeError 256 -RuntimeError 257 -RuntimeError 257 -RuntimeError 258 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 257 +RuntimeError name too long 258 +RuntimeError name too long 258 254 255 -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 -254 -255 -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 ok 100 ok 101 -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 ok 100 ok 101 ok 102 -RuntimeError 128 -RuntimeError 129 +RuntimeError name too long 128 +RuntimeError name too long 129 diff --git a/tests/stress/qstr_limit_str_modulo.py b/tests/stress/qstr_limit_str_modulo.py new file mode 100644 index 00000000000..90b9f4364ec --- /dev/null +++ b/tests/stress/qstr_limit_str_modulo.py @@ -0,0 +1,21 @@ +# Test interning qstrs that go over the qstr length limit (255 bytes in default configuration). +# The tests here are specifically for str formatting with %. + +try: + "" % () +except TypeError: + print("SKIP") + raise SystemExit + + +def make_id(n, base="a"): + return "".join(chr(ord(base) + i % 26) for i in range(n)) + + +# modulo format with keys +for l in range(254, 259): + id = make_id(l) + try: + print(("%(" + id + ")d") % {id: l}) + except RuntimeError as er: + print("RuntimeError", er, l) diff --git a/tests/stress/qstr_limit_str_modulo.py.exp b/tests/stress/qstr_limit_str_modulo.py.exp new file mode 100644 index 00000000000..3632c85bffe --- /dev/null +++ b/tests/stress/qstr_limit_str_modulo.py.exp @@ -0,0 +1,5 @@ +254 +255 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 diff --git a/tests/stress/recursive_iternext.py b/tests/stress/recursive_iternext.py index bbc389e7262..c737f1e36d7 100644 --- a/tests/stress/recursive_iternext.py +++ b/tests/stress/recursive_iternext.py @@ -1,4 +1,8 @@ # This tests that recursion with iternext doesn't lead to segfault. +# +# This test segfaults CPython, but that's not a bug as CPython doesn't enforce +# limits on C recursion - see +# https://github.com/python/cpython/issues/58218#issuecomment-1093570209 try: enumerate filter @@ -9,49 +13,25 @@ print("SKIP") raise SystemExit -# We need to pick an N that is large enough to hit the recursion -# limit, but not too large that we run out of heap memory. -try: - # large stack/heap, eg unix - [0] * 80000 - N = 5000 -except: - try: - # medium, eg pyboard - [0] * 10000 - N = 1000 - except: - # small, eg esp8266 - N = 100 - -try: - x = (1, 2) - for i in range(N): - x = enumerate(x) - tuple(x) -except RuntimeError: - print("RuntimeError") -try: +# Progressively build a bigger nested iterator structure (10 at a time for speed), +# and then try to evaluate it via tuple(x) which makes deep recursive function calls. +# +# Eventually this should raise a RuntimeError as MicroPython runs out of stack. +# It shouldn't ever raise a MemoryError, if it does then somehow MicroPython has +# run out of heap (for the nested structure) before running out of stack. +def recurse_iternext(nested_fn): x = (1, 2) - for i in range(N): - x = filter(None, x) - tuple(x) -except RuntimeError: - print("RuntimeError") + while True: + for _ in range(10): + x = nested_fn(x) + try: + tuple(x) + except RuntimeError: + print("RuntimeError") + break -try: - x = (1, 2) - for i in range(N): - x = map(max, x, ()) - tuple(x) -except RuntimeError: - print("RuntimeError") -try: - x = (1, 2) - for i in range(N): - x = zip(x) - tuple(x) -except RuntimeError: - print("RuntimeError") +# Test on various nested iterator structures +for nested_fn in [enumerate, lambda x: filter(None, x), lambda x: map(max, x, ()), zip]: + recurse_iternext(nested_fn) diff --git a/tests/target_wiring/EK_RA6M2.py b/tests/target_wiring/EK_RA6M2.py new file mode 100644 index 00000000000..7d4a8cbbd64 --- /dev/null +++ b/tests/target_wiring/EK_RA6M2.py @@ -0,0 +1,8 @@ +# Target wiring for EK_RA6M2. +# +# Connect: +# - P601 to P602 + +# UART(9) is on P602/P601. +uart_loopback_args = (9,) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/NUCLEO_WB55.py b/tests/target_wiring/NUCLEO_WB55.py new file mode 100644 index 00000000000..ad7c120d377 --- /dev/null +++ b/tests/target_wiring/NUCLEO_WB55.py @@ -0,0 +1,8 @@ +# Target wiring for NUCLEO_WB55. +# +# Connect: +# - PA2 to PA3 + +# LPUART(1) is on PA2/PA3. +uart_loopback_args = ("LP1",) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/PYBx.py b/tests/target_wiring/PYBx.py new file mode 100644 index 00000000000..10ce520ef0a --- /dev/null +++ b/tests/target_wiring/PYBx.py @@ -0,0 +1,8 @@ +# Target wiring for PYBV10, PYBV11, PYBLITEV10, PYBD_SF2, PYBD_SF3, PYBD_SF6. +# +# Connect: +# - X1 to X2 + +# UART("XA") is on X1/X2 (usually UART(4) on PA0/PA1). +uart_loopback_args = ("XA",) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/ZEPHYR_NUCLEO_WB55RG.py b/tests/target_wiring/ZEPHYR_NUCLEO_WB55RG.py new file mode 100644 index 00000000000..c7ca2ac26f7 --- /dev/null +++ b/tests/target_wiring/ZEPHYR_NUCLEO_WB55RG.py @@ -0,0 +1,7 @@ +# Target wiring for zephyr nucleo_wb55rg. +# +# Connect: +# - TX=PC0 to RX=PC1 + +uart_loopback_args = ("lpuart1",) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/alif.py b/tests/target_wiring/alif.py new file mode 100644 index 00000000000..18f3cbe7e5e --- /dev/null +++ b/tests/target_wiring/alif.py @@ -0,0 +1,7 @@ +# Target wiring for general alif board. +# +# Connect: +# - UART1 TX and RX, usually P0_5 and P0_4 + +uart_loopback_args = (1,) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/esp32.py b/tests/target_wiring/esp32.py new file mode 100644 index 00000000000..2767cd5acb2 --- /dev/null +++ b/tests/target_wiring/esp32.py @@ -0,0 +1,12 @@ +# Target wiring for general esp32 board. +# +# Connect: +# - GPIO4 to GPIO5 +# - GPIO12 to GPIO13 + +uart_loopback_args = (1,) +uart_loopback_kwargs = {"tx": 4, "rx": 5} + +encoder_loopback_id = 0 +encoder_loopback_out_pins = (4, 12) +encoder_loopback_in_pins = (5, 13) diff --git a/tests/target_wiring/mimxrt.py b/tests/target_wiring/mimxrt.py new file mode 100644 index 00000000000..669e9095990 --- /dev/null +++ b/tests/target_wiring/mimxrt.py @@ -0,0 +1,7 @@ +# Target wiring for general mimxrt board. +# +# Connect: +# - UART1 TX and RX, usually D0 and D1 + +uart_loopback_args = (1,) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/nrf.py b/tests/target_wiring/nrf.py new file mode 100644 index 00000000000..6979dd28ee5 --- /dev/null +++ b/tests/target_wiring/nrf.py @@ -0,0 +1,7 @@ +# Target wiring for general nrf board. +# +# Connect: +# - UART0 TX and RX + +uart_loopback_args = (0,) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/rp2.py b/tests/target_wiring/rp2.py new file mode 100644 index 00000000000..cb0fa0d6263 --- /dev/null +++ b/tests/target_wiring/rp2.py @@ -0,0 +1,7 @@ +# Target wiring for general rp2 board. +# +# Connect: +# - GPIO0 to GPIO1 + +uart_loopback_args = (0,) +uart_loopback_kwargs = {"tx": "GPIO0", "rx": "GPIO1"} diff --git a/tests/target_wiring/samd.py b/tests/target_wiring/samd.py new file mode 100644 index 00000000000..887c43a242f --- /dev/null +++ b/tests/target_wiring/samd.py @@ -0,0 +1,7 @@ +# Target wiring for general samd board. +# +# Connect: +# - D0 to D1 + +uart_loopback_args = () +uart_loopback_kwargs = {"tx": "D1", "rx": "D0"} diff --git a/tests/thread/disable_irq.py b/tests/thread/disable_irq.py index 3f1ac74f308..596e3e477b9 100644 --- a/tests/thread/disable_irq.py +++ b/tests/thread/disable_irq.py @@ -1,8 +1,14 @@ # Ensure that disabling IRQs creates mutual exclusion between threads # (also tests nesting of disable_irq across threads) -import machine -import time -import _thread + +# CIRCUITPY-CHANGE: no machine +try: + import machine + import time + import _thread +except ImportError: + print("SKIP") + raise SystemExit if not hasattr(machine, "disable_irq"): print("SKIP") diff --git a/tests/thread/mutate_bytearray.py b/tests/thread/mutate_bytearray.py index b4664781a15..7116d291cfe 100644 --- a/tests/thread/mutate_bytearray.py +++ b/tests/thread/mutate_bytearray.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread # the shared bytearray @@ -36,7 +37,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check bytearray has correct contents print(len(ba)) diff --git a/tests/thread/mutate_dict.py b/tests/thread/mutate_dict.py index 3777af66248..dd5f69e6c5d 100644 --- a/tests/thread/mutate_dict.py +++ b/tests/thread/mutate_dict.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread # the shared dict @@ -38,7 +39,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check dict has correct contents print(sorted(di.items())) diff --git a/tests/thread/mutate_instance.py b/tests/thread/mutate_instance.py index 306ad91c95c..63f7fb1e23d 100644 --- a/tests/thread/mutate_instance.py +++ b/tests/thread/mutate_instance.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -40,7 +41,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check user instance has correct contents print(user.a, user.b, user.c) diff --git a/tests/thread/mutate_list.py b/tests/thread/mutate_list.py index 6f1e8812541..d7398a2f1e0 100644 --- a/tests/thread/mutate_list.py +++ b/tests/thread/mutate_list.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread # the shared list @@ -39,7 +40,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check list has correct contents li.sort() diff --git a/tests/thread/mutate_set.py b/tests/thread/mutate_set.py index 2d9a3e0ce9e..7dcefa1d113 100644 --- a/tests/thread/mutate_set.py +++ b/tests/thread/mutate_set.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread # the shared set @@ -33,7 +34,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check set has correct contents print(sorted(se)) diff --git a/tests/thread/stress_aes.py b/tests/thread/stress_aes.py index d8d0acd568a..ca25f8ad2fd 100644 --- a/tests/thread/stress_aes.py +++ b/tests/thread/stress_aes.py @@ -277,7 +277,7 @@ def thread_entry(n_loop): n_thread = 2 n_loop = 2 else: - n_thread = 20 + n_thread = 10 n_loop = 5 for i in range(n_thread): _thread.start_new_thread(thread_entry, (n_loop,)) diff --git a/tests/thread/stress_recurse.py b/tests/thread/stress_recurse.py index 73b3a40f33d..ec8b43fe8fc 100644 --- a/tests/thread/stress_recurse.py +++ b/tests/thread/stress_recurse.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -24,5 +25,5 @@ def thread_entry(): # busy wait for thread to finish while not finished: - pass + time.sleep(0) print("done") diff --git a/tests/thread/stress_schedule.py b/tests/thread/stress_schedule.py index 97876f0f77c..362d71aa12e 100644 --- a/tests/thread/stress_schedule.py +++ b/tests/thread/stress_schedule.py @@ -27,6 +27,8 @@ def task(x): n += 1 +# This function must always use the bytecode emitter so it bounces the GIL when running. +@micropython.bytecode def thread(): while thread_run: try: @@ -46,7 +48,7 @@ def thread(): # Wait up to 10 seconds for 10000 tasks to be scheduled. t = time.ticks_ms() while n < _NUM_TASKS and time.ticks_diff(time.ticks_ms(), t) < _TIMEOUT_MS: - pass + time.sleep(0) # Stop all threads. thread_run = False diff --git a/tests/thread/thread_coop.py b/tests/thread/thread_coop.py index aefc4af074d..85cda789c93 100644 --- a/tests/thread/thread_coop.py +++ b/tests/thread/thread_coop.py @@ -7,6 +7,7 @@ import _thread import sys from time import ticks_ms, ticks_diff, sleep_ms +import micropython done = False @@ -21,6 +22,8 @@ MAX_DELTA = 100 +# This function must always use the bytecode emitter so the VM can bounce the GIL when running. +@micropython.bytecode def busy_thread(): while not done: pass diff --git a/tests/thread/thread_exc1.py b/tests/thread/thread_exc1.py index cd877409291..cd6599983c1 100644 --- a/tests/thread/thread_exc1.py +++ b/tests/thread/thread_exc1.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -34,5 +35,5 @@ def thread_entry(): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) print("done") diff --git a/tests/thread/thread_exc2.py.native.exp b/tests/thread/thread_exc2.py.native.exp new file mode 100644 index 00000000000..9b2e715ef8d --- /dev/null +++ b/tests/thread/thread_exc2.py.native.exp @@ -0,0 +1,3 @@ +Unhandled exception in thread started by +ValueError: +done diff --git a/tests/thread/thread_gc1.py b/tests/thread/thread_gc1.py index b36ea9d4c84..45c17cc17be 100644 --- a/tests/thread/thread_gc1.py +++ b/tests/thread/thread_gc1.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import gc import _thread @@ -44,6 +45,6 @@ def thread_entry(n): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) print(n_correct == n_finished) diff --git a/tests/thread/thread_ident1.py b/tests/thread/thread_ident1.py index 2a3732eff53..08cfd3eb36e 100644 --- a/tests/thread/thread_ident1.py +++ b/tests/thread/thread_ident1.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -27,6 +28,6 @@ def thread_entry(): new_tid = _thread.start_new_thread(thread_entry, ()) while not finished: - pass + time.sleep(0) print("done", type(new_tid) == int, new_tid == tid) diff --git a/tests/thread/thread_lock3.py b/tests/thread/thread_lock3.py index a927dc6829e..c5acfa21b7d 100644 --- a/tests/thread/thread_lock3.py +++ b/tests/thread/thread_lock3.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread lock = _thread.allocate_lock() @@ -26,4 +27,4 @@ def thread_entry(idx): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) diff --git a/tests/thread/thread_lock4.py b/tests/thread/thread_lock4_intbig.py similarity index 100% rename from tests/thread/thread_lock4.py rename to tests/thread/thread_lock4_intbig.py diff --git a/tests/thread/thread_shared1.py b/tests/thread/thread_shared1.py index 251e26fae6c..c2e33abcec7 100644 --- a/tests/thread/thread_shared1.py +++ b/tests/thread/thread_shared1.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -40,5 +41,5 @@ def thread_entry(n, tup): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) print(tup) diff --git a/tests/thread/thread_shared2.py b/tests/thread/thread_shared2.py index a1223c2b94f..4ce9057ca01 100644 --- a/tests/thread/thread_shared2.py +++ b/tests/thread/thread_shared2.py @@ -3,6 +3,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -31,5 +32,5 @@ def thread_entry(n, lst, idx): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) print(lst) diff --git a/tests/thread/thread_stacksize1.py b/tests/thread/thread_stacksize1.py index 140d165cb34..75e1da9642f 100644 --- a/tests/thread/thread_stacksize1.py +++ b/tests/thread/thread_stacksize1.py @@ -3,6 +3,7 @@ # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import sys +import time import _thread # different implementations have different minimum sizes @@ -51,5 +52,5 @@ def thread_entry(): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) print("done") diff --git a/tests/thread/thread_stdin.py b/tests/thread/thread_stdin.py index a469933f19b..498b0a3a270 100644 --- a/tests/thread/thread_stdin.py +++ b/tests/thread/thread_stdin.py @@ -5,6 +5,7 @@ # This is a regression test for https://github.com/micropython/micropython/issues/15230 # on rp2, but doubles as a general property to test across all ports. import sys +import time import _thread try: @@ -38,7 +39,7 @@ def is_done(self): # have run yet. The actual delay is <20ms but spinning here instead of # sleep(0.1) means the test can run on MP builds without float support. while not thread_waiter.is_done(): - pass + time.sleep(0) # The background thread should have completed its wait by now. print(thread_waiter.is_done()) diff --git a/tests/unix/extra_coverage.py b/tests/unix/extra_coverage.py index 0ea8f7886bf..ec10a44ff39 100644 --- a/tests/unix/extra_coverage.py +++ b/tests/unix/extra_coverage.py @@ -6,6 +6,16 @@ import errno import io +import uctypes + +# create an int-like variable used for coverage of `mp_obj_get_ll` +buf = bytearray(b"\xde\xad\xbe\xef") +struct = uctypes.struct( + uctypes.addressof(buf), + {"f32": uctypes.UINT32 | 0}, + uctypes.BIG_ENDIAN, +) +deadbeef = struct.f32 data = extra_coverage() @@ -23,6 +33,7 @@ print(stream.read(1)) # read 1 byte encounters non-blocking error print(stream.readline()) # readline encounters non-blocking error print(stream.readinto(bytearray(10))) # readinto encounters non-blocking error +print(stream.readinto1(bytearray(10))) # readinto1 encounters non-blocking error print(stream.write(b"1")) # write encounters non-blocking error print(stream.write1(b"1")) # write1 encounters non-blocking error stream.set_buf(b"123") @@ -38,6 +49,28 @@ stream.set_error(0) print(stream.ioctl(0, bytearray(10))) # successful ioctl call +print("# stream.readinto") + +# stream.readinto will read 3 bytes then try to read more to fill the buffer, +# but on the second attempt will encounter EIO and should raise that error. +stream.set_error(errno.EIO) +stream.set_buf(b"123") +buf = bytearray(4) +try: + stream.readinto(buf) +except OSError as er: + print("OSError", er.errno == errno.EIO) +print(buf) + +# stream.readinto1 will read 3 bytes then should return them immediately, and +# not encounter the EIO. +stream.set_error(errno.EIO) +stream.set_buf(b"123") +buf = bytearray(4) +print(stream.readinto1(buf), buf) + +print("# stream textio") + stream2 = data[3] # is textio print(stream2.read(1)) # read 1 byte encounters non-blocking error with textio stream @@ -92,7 +125,7 @@ print(returns_NULL()) -# test for freeze_mpy +# test for freeze_mpy (importing prints several lines) import frozentest print(frozentest.__file__) diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 4cd8b8666d2..cdb11455694 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -2,25 +2,41 @@ -123 +123 123 -0123 123 -123 -1ABCDEF +123f +123F +7fffffffffffffff +7FFFFFFFFFFFFFFF +18446744073709551615 +789f +789F ab abc ' abc' ' True' 'Tru' false true (null) -2147483648 2147483648 -80000000 -80000000 +8000000f +8000000F abc % +.a . +<%> + + +<43690> +<43690> +<43690> + +<1000.000000> + +<9223372036854775807> # GC -0x0 -0x0 +0 +0 # GC part 2 pass # tracked allocation -m_tracked_head = 0x0 +m_tracked_head = 0 0 1 1 1 2 1 @@ -37,7 +53,7 @@ m_tracked_head = 0x0 5 1 6 1 7 1 -m_tracked_head = 0x0 +m_tracked_head = 0 # vstr tests sts @@ -91,6 +107,16 @@ data 12345 6 -1 +0 +1 +0 +0.000000 +deadbeef +c0ffee777c0ffee +deadbeef +0deadbeef +c0ffee +000c0ffee # runtime utils TypeError: unsupported type for __abs__: 'str' TypeError: unsupported types for __divmod__: 'str', 'str' @@ -99,12 +125,10 @@ TypeError: unsupported types for __divmod__: 'str', 'str' 2 OverflowError: overflow converting long int to machine word OverflowError: overflow converting long int to machine word +TypeError: can't convert NoneType to int +TypeError: can't convert NoneType to int ValueError: Warning: test -# format float -? -+1e+00 -+1e+00 # binary 123 456 @@ -124,6 +148,13 @@ unlocked KeyboardInterrupt: KeyboardInterrupt: 10 +loop +scheduled function +loop +scheduled function +loop +scheduled function +scheduled function # ringbuf 99 0 98 1 @@ -185,11 +216,17 @@ None None None None +None b'123' b'123' b'123' OSError 0 +# stream.readinto +OSError True +bytearray(b'123\x00') +3 bytearray(b'123\x00') +# stream textio None None cpp None @@ -215,7 +252,7 @@ b'\x00\xff' frzmpy4 1 frzmpy4 2 NULL -uPy +interned a long string that is not interned a string that has unicode αβγ chars b'bytes 1234\x01' diff --git a/tests/unix/ffi_float2.py b/tests/unix/ffi_float2.py index bbed6966627..eac6cd106cf 100644 --- a/tests/unix/ffi_float2.py +++ b/tests/unix/ffi_float2.py @@ -29,4 +29,5 @@ def ffi_open(names): for fun in (tgammaf,): for val in (0.5, 1, 1.0, 1.5, 4, 4.0): - print("%.6f" % fun(val)) + # limit to 5 decimals in order to pass with REPR_C with FORMAT_IMPL_BASIC + print("%.5f" % fun(val)) diff --git a/tests/unix/ffi_float2.py.exp b/tests/unix/ffi_float2.py.exp index 58fc6a01acb..4c750e223a3 100644 --- a/tests/unix/ffi_float2.py.exp +++ b/tests/unix/ffi_float2.py.exp @@ -1,6 +1,6 @@ -1.772454 -1.000000 -1.000000 -0.886227 -6.000000 -6.000000 +1.77245 +1.00000 +1.00000 +0.88623 +6.00000 +6.00000 diff --git a/tests/unix/mod_os.py b/tests/unix/mod_os.py index f69fa45b2b2..468f6badd1e 100644 --- a/tests/unix/mod_os.py +++ b/tests/unix/mod_os.py @@ -1,6 +1,9 @@ # This module is not entirely compatible with CPython import os +if not hasattr(os, "getenv"): + print("SKIP") + raise SystemExit os.putenv("TEST_VARIABLE", "TEST_VALUE") diff --git a/tests/unix/time_mktime_localtime.py b/tests/unix/time_mktime_localtime.py index d1c03c103d7..df5d6cda690 100644 --- a/tests/unix/time_mktime_localtime.py +++ b/tests/unix/time_mktime_localtime.py @@ -1,4 +1,8 @@ -import time +try: + import time +except ImportError: + print("SKIP") + raise SystemExit DAYS_PER_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] diff --git a/tools/analyze_heap_dump.py b/tools/analyze_heap_dump.py index ac1bb0c8ce5..a7be95db7d9 100755 --- a/tools/analyze_heap_dump.py +++ b/tools/analyze_heap_dump.py @@ -82,7 +82,7 @@ help="Draw the ownership graph of blocks on the heap", ) @click.option("--analyze-snapshots", default="last", type=click.Choice(["all", "last"])) -def do_all_the_things( # noqa: C901: too complex +def do_all_the_things( # noqa: C901 too complex ram_filename, bin_filename, map_filename, diff --git a/tools/boardgen.py b/tools/boardgen.py index 39bedf71cd0..3723e7ce31b 100644 --- a/tools/boardgen.py +++ b/tools/boardgen.py @@ -108,6 +108,10 @@ def add_board_pin_name(self, board_pin_name, hidden=False): ) ) + # Iterate over board pin names in consistent sorted order. + def board_pin_names(self): + return sorted(self._board_pin_names, key=lambda x: x[0]) + # Override this to handle an af specified in af.csv. def add_af(self, af_idx, af_name, af): raise NotImplementedError @@ -295,7 +299,7 @@ def print_board_locals_dict(self, out_source): file=out_source, ) for pin in self.available_pins(): - for board_pin_name, board_hidden in pin._board_pin_names: + for board_pin_name, board_hidden in pin.board_pin_names(): if board_hidden: # Don't include hidden pins in Pins.board. continue @@ -389,7 +393,7 @@ def print_defines(self, out_header, cpu=True, board=True): # #define pin_BOARDNAME (pin_CPUNAME) if board: - for board_pin_name, _board_hidden in pin._board_pin_names: + for board_pin_name, _board_hidden in pin.board_pin_names(): # Note: Hidden board pins are still available to C via the macro. # Note: The RHS isn't wrapped in (), which is necessary to make the # STATIC_AF_ macro work on STM32. diff --git a/tools/cc1 b/tools/cc1 index 827d5886a04..aa2534f01e7 100755 --- a/tools/cc1 +++ b/tools/cc1 @@ -23,8 +23,8 @@ import re # TODO somehow make them externally configurable # this is the path to the true C compiler -cc1_path = '/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/cc1' -#cc1_path = '/usr/lib/gcc/arm-none-eabi/5.3.0/cc1' +cc1_path = "/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/cc1" +# cc1_path = '/usr/lib/gcc/arm-none-eabi/5.3.0/cc1' # this must be the same as MICROPY_QSTR_BYTES_IN_HASH bytes_in_qstr_hash = 2 @@ -41,11 +41,16 @@ print_debug = False ################################################################################ # precompile regexs -re_preproc_line = re.compile(r'# [0-9]+ ') -re_map_entry = re.compile(r'\{.+?\(MP_QSTR_([A-Za-z0-9_]+)\).+\},') -re_mp_obj_dict_t = re.compile(r'(?P(static )?const mp_obj_dict_t (?P[a-z0-9_]+) = \{ \.base = \{&mp_type_dict\}, \.map = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$') -re_mp_map_t = re.compile(r'(?P(static )?const mp_map_t (?P[a-z0-9_]+) = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$') -re_mp_rom_map_elem_t = re.compile(r'static const mp_rom_map_elem_t [a-z_0-9]+\[\] = {$') +re_preproc_line = re.compile(r"# [0-9]+ ") +re_map_entry = re.compile(r"\{.+?\(MP_QSTR_([A-Za-z0-9_]+)\).+\},") +re_mp_obj_dict_t = re.compile( + r"(?P(static )?const mp_obj_dict_t (?P[a-z0-9_]+) = \{ \.base = \{&mp_type_dict\}, \.map = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$" +) +re_mp_map_t = re.compile( + r"(?P(static )?const mp_map_t (?P[a-z0-9_]+) = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$" +) +re_mp_rom_map_elem_t = re.compile(r"static const mp_rom_map_elem_t [a-z_0-9]+\[\] = {$") + # this must match the equivalent function in qstr.c def compute_hash(qstr): @@ -55,18 +60,19 @@ def compute_hash(qstr): # Make sure that valid hash is never zero, zero means "hash not computed" return (hash & ((1 << (8 * bytes_in_qstr_hash)) - 1)) or 1 + # this algo must match the equivalent in map.c def hash_insert(map, key, value): hash = compute_hash(key) pos = hash % len(map) start_pos = pos if print_debug: - print(' insert %s: start at %u/%u -- ' % (key, pos, len(map)), end='') + print(" insert %s: start at %u/%u -- " % (key, pos, len(map)), end="") while True: if map[pos] is None: # found empty slot, so key is not in table if print_debug: - print('put at %u' % pos) + print("put at %u" % pos) map[pos] = (key, value) return else: @@ -76,6 +82,7 @@ def hash_insert(map, key, value): pos = (pos + 1) % len(map) assert pos != start_pos + def hash_find(map, key): hash = compute_hash(key) pos = hash % len(map) @@ -92,6 +99,7 @@ def hash_find(map, key): if pos == start_pos: return attempts, None + def process_map_table(file, line, output): output.append(line) @@ -101,7 +109,7 @@ def process_map_table(file, line, output): while True: line = file.readline() if len(line) == 0: - print('unexpected end of input') + print("unexpected end of input") sys.exit(1) line = line.strip() if len(line) == 0: @@ -110,38 +118,38 @@ def process_map_table(file, line, output): if re_preproc_line.match(line): # preprocessor line number comment continue - if line == '};': + if line == "};": # end of table (we assume it appears on a single line) break table_contents.append(line) # make combined string of entries - entries_str = ''.join(table_contents) + entries_str = "".join(table_contents) # split into individual entries entries = [] while entries_str: # look for single entry, by matching nested braces match = None - if entries_str[0] == '{': + if entries_str[0] == "{": nested_braces = 0 for i in range(len(entries_str)): - if entries_str[i] == '{': + if entries_str[i] == "{": nested_braces += 1 - elif entries_str[i] == '}': + elif entries_str[i] == "}": nested_braces -= 1 if nested_braces == 0: - match = re_map_entry.match(entries_str[:i + 2]) + match = re_map_entry.match(entries_str[: i + 2]) break if not match: - print('unknown line in table:', entries_str) + print("unknown line in table:", entries_str) sys.exit(1) # extract single entry line = match.group(0) qstr = match.group(1) - entries_str = entries_str[len(line):].lstrip() + entries_str = entries_str[len(line) :].lstrip() # add the qstr and the whole line to list of all entries entries.append((qstr, line)) @@ -164,28 +172,28 @@ def process_map_table(file, line, output): attempts, line = hash_find(map, qstr) assert line is not None if print_debug: - print(' %s lookup took %u attempts' % (qstr, attempts)) + print(" %s lookup took %u attempts" % (qstr, attempts)) total_attempts += attempts - if len(entries): + if entries: stats = len(map), len(entries) / len(map), total_attempts / len(entries) else: stats = 0, 0, 0 if print_debug: - print(' table stats: size=%d, load=%.2f, avg_lookups=%.1f' % stats) + print(" table stats: size=%d, load=%.2f, avg_lookups=%.1f" % stats) # output hash table for row in map: if row is None: - output.append('{ 0, 0 },\n') + output.append("{ 0, 0 },\n") else: - output.append(row[1] + '\n') - output.append('};\n') + output.append(row[1] + "\n") + output.append("};\n") # skip to next non-blank line while True: line = file.readline() if len(line) == 0: - print('unexpected end of input') + print("unexpected end of input") sys.exit(1) line = line.strip() if len(line) == 0: @@ -197,19 +205,20 @@ def process_map_table(file, line, output): if match is None: match = re_mp_map_t.match(line) if match is None: - print('expecting mp_obj_dict_t or mp_map_t definition') + print("expecting mp_obj_dict_t or mp_map_t definition") print(output[0]) print(line) sys.exit(1) - line = match.group('head') + '0' + match.group('tail') + '\n' + line = match.group("head") + "0" + match.group("tail") + "\n" output.append(line) - return (match.group('id'),) + stats + return (match.group("id"),) + stats + def process_file(filename): output = [] file_changed = False - with open(filename, 'rt') as f: + with open(filename, "rt") as f: while True: line = f.readline() if not line: @@ -218,39 +227,41 @@ def process_file(filename): file_changed = True stats = process_map_table(f, line, output) if print_stats: - print(' [%s: size=%d, load=%.2f, avg_lookups=%.1f]' % stats) + print(" [%s: size=%d, load=%.2f, avg_lookups=%.1f]" % stats) else: output.append(line) if file_changed: if print_debug: - print(' modifying static maps in', output[0].strip()) - with open(filename, 'wt') as f: + print(" modifying static maps in", output[0].strip()) + with open(filename, "wt") as f: for line in output: f.write(line) + def main(): # run actual C compiler # need to quote args that have special characters in them def quote(s): - if s.find('<') != -1 or s.find('>') != -1: + if s.find("<") != -1 or s.find(">") != -1: return "'" + s + "'" else: return s - ret = os.system(cc1_path + ' ' + ' '.join(quote(s) for s in sys.argv[1:])) + + ret = os.system(cc1_path + " " + " ".join(quote(s) for s in sys.argv[1:])) if ret != 0: - ret = (ret & 0x7f) or 127 # make it in range 0-127, but non-zero + ret = (ret & 0x7F) or 127 # make it in range 0-127, but non-zero sys.exit(ret) - if sys.argv[1] == '-E': + if sys.argv[1] == "-E": # CPP has been run, now do our processing stage for i, arg in enumerate(sys.argv): - if arg == '-o': + if arg == "-o": return process_file(sys.argv[i + 1]) print('%s: could not find "-o" option' % (sys.argv[0],)) sys.exit(1) - elif sys.argv[1] == '-fpreprocessed': + elif sys.argv[1] == "-fpreprocessed": # compiler has been run, nothing more to do return else: @@ -258,5 +269,6 @@ def main(): print('%s: unknown first option "%s"' % (sys.argv[0], sys.argv[1])) sys.exit(1) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/tools/chart_code_size.py b/tools/chart_code_size.py index cd62074fd0d..f3d9c5bdc40 100644 --- a/tools/chart_code_size.py +++ b/tools/chart_code_size.py @@ -24,7 +24,7 @@ def parse_hex(h): @click.command() @click.argument("elf_filename") -def do_all_the_things(elf_filename): # noqa: C901: too complex +def do_all_the_things(elf_filename): # noqa: C901 too complex symbol = None last_address = 0 all_symbols = {} diff --git a/tools/ci.sh b/tools/ci.sh index cfc9754837f..132fbd8f81c 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -9,15 +9,20 @@ fi # Ensure known OPEN_MAX (NO_FILES) limit. ulimit -n 1024 +# Fail on some things which are warnings otherwise +export MICROPY_MAINTAINER_BUILD=1 + ######################################################################################## # general helper functions function ci_gcc_arm_setup { + sudo apt-get update sudo apt-get install gcc-arm-none-eabi libnewlib-arm-none-eabi arm-none-eabi-gcc --version } function ci_gcc_riscv_setup { + sudo apt-get update sudo apt-get install gcc-riscv64-unknown-elf picolibc-riscv64-unknown-elf riscv64-unknown-elf-gcc --version } @@ -35,6 +40,7 @@ function ci_picotool_setup { # c code formatting function ci_c_code_formatting_setup { + sudo apt-get update sudo apt-get install uncrustify uncrustify --version } @@ -74,42 +80,69 @@ function ci_code_size_setup { ci_picotool_setup } +function _ci_is_git_merge { + [[ $(git log -1 --format=%P "$1" | wc -w) > 1 ]] +} + function ci_code_size_build { # check the following ports for the change in their code size - PORTS_TO_CHECK=bmusxpdv + # Override the list by setting PORTS_TO_CHECK in the environment before invoking ci. + : ${PORTS_TO_CHECK:=bmusxpdv} + SUBMODULES="lib/asf4 lib/berkeley-db-1.xx lib/btstack lib/cyw43-driver lib/lwip lib/mbedtls lib/micropython-lib lib/nxp_driver lib/pico-sdk lib/stm32lib lib/tinyusb" # Default GitHub pull request sets HEAD to a generated merge commit # between PR branch (HEAD^2) and base branch (i.e. master) (HEAD^1). # # We want to compare this generated commit with the base branch, to see what - # the code size impact would be if we merged this PR. - REFERENCE=$(git rev-parse --short HEAD^1) - COMPARISON=$(git rev-parse --short HEAD) + # the code size impact would be if we merged this PR. During CI we are at a merge commit, + # so this tests the merged PR against its merge base. + # Override the refs by setting REFERENCE and/or COMPARISON in the environment before invoking ci. + : ${COMPARISON:=$(git rev-parse --short HEAD)} + : ${REFERENCE:=$(git rev-parse --short ${COMPARISON}^1)} echo "Comparing sizes of reference ${REFERENCE} to ${COMPARISON}..." git log --oneline $REFERENCE..$COMPARISON - function code_size_build_step { - COMMIT=$1 - OUTFILE=$2 - IGNORE_ERRORS=$3 - - echo "Building ${COMMIT}..." - git checkout --detach $COMMIT - git submodule update --init $SUBMODULES - git show -s - tools/metrics.py clean $PORTS_TO_CHECK - tools/metrics.py build $PORTS_TO_CHECK | tee $OUTFILE || $IGNORE_ERRORS - } - - # build reference, save to size0 - # ignore any errors with this build, in case master is failing - code_size_build_step $REFERENCE ~/size0 true - # build PR/branch, save to size1 - code_size_build_step $COMPARISON ~/size1 false - - unset -f code_size_build_step + OLD_BRANCH="$(git rev-parse --abbrev-ref HEAD)" + + ( # Execute in a subshell so the trap & code_size_build_step doesn't leak + function code_size_build_step { + if [ ! -z "$OLD_BRANCH" ]; then + trap 'git checkout "$OLD_BRANCH"' RETURN EXIT ERR + fi + + COMMIT=$1 + OUTFILE=$2 + IGNORE_ERRORS=$3 + + git checkout --detach $COMMIT + git submodule update --init $SUBMODULES + git show -s + tools/metrics.py clean "$PORTS_TO_CHECK" + # Allow errors from tools/metrics.py to propagate out of the pipe below. + set -o pipefail + tools/metrics.py build "$PORTS_TO_CHECK" | tee -a $OUTFILE || $IGNORE_ERRORS + return $? + } + + # build reference, save to size0 + # ignore any errors with this build, in case master is failing + echo "BUILDING $(git log --format='%s [%h]' -1 ${REFERENCE})" > ~/size0 + code_size_build_step $REFERENCE ~/size0 true + # build PR/branch, save to size1 + if _ci_is_git_merge "$COMPARISON"; then + echo "BUILDING $(git log --oneline -1 --format='%s [merge of %h]' ${COMPARISON}^2)" + else + echo "BUILDING $(git log --oneline -1 --formta='%s [%h]' ${COMPARISON})" + fi > ~/size1 + code_size_build_step $COMPARISON ~/size1 false + ) +} + +function ci_code_size_report { + # Allow errors from tools/metrics.py to propagate out of the pipe above. + (set -o pipefail; tools/metrics.py diff ~/size0 ~/size1 | tee diff) } ######################################################################################## @@ -117,15 +150,12 @@ function ci_code_size_build { function ci_mpy_format_setup { sudo apt-get update - sudo apt-get install python2.7 sudo pip3 install pyelftools - python2.7 --version python3 --version } function ci_mpy_format_test { # Test mpy-tool.py dump feature on bytecode - python2.7 ./tools/mpy-tool.py -xd tests/frozen/frozentest.mpy python3 ./tools/mpy-tool.py -xd tests/frozen/frozentest.mpy # Build MicroPython @@ -143,6 +173,15 @@ function ci_mpy_format_test { $micropython ./tools/mpy-tool.py -x -d examples/natmod/features1/features1.mpy } +function ci_mpy_cross_debug_emitter { + make ${MAKEOPTS} -C mpy-cross + mpy_cross=./mpy-cross/build/mpy-cross + + # Make sure the debug emitter does not crash or fail for simple files + $mpy_cross -X emit=native -march=debug ./tests/basics/0prelim.py | \ + grep -E "ENTRY|EXIT" | wc -l | grep "^2$" +} + ######################################################################################## # ports/cc3200 @@ -158,14 +197,17 @@ function ci_cc3200_build { ######################################################################################## # ports/esp32 -# GitHub tag of ESP-IDF to use for CI (note: must be a tag or a branch) -IDF_VER=v5.2.2 +# GitHub tag of ESP-IDF to use for CI, extracted from the esp32 dependency lockfile +# This should end up as a tag name like vX.Y.Z +# (note: This hacky parsing can be replaced with 'yq' once Ubuntu >=24.04 is in use) +IDF_VER=v$(grep -A10 "idf:" ports/esp32/lockfiles/dependencies.lock.esp32 | grep "version:" | head -n1 | sed -E 's/ +version: //') PYTHON=$(command -v python3 2> /dev/null) PYTHON_VER=$(${PYTHON:-python} --version | cut -d' ' -f2) export IDF_CCACHE_ENABLE=1 function ci_esp32_idf_setup { + echo "Using ESP-IDF version $IDF_VER" git clone --depth 1 --branch $IDF_VER https://github.com/espressif/esp-idf.git # doing a treeless clone isn't quite as good as --shallow-submodules, but it # is smaller than full clones and works when the submodule commit isn't a head. @@ -204,13 +246,28 @@ function ci_esp32_build_s3_c3 { make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_C3 } +function ci_esp32_build_c2_c5_c6 { + ci_esp32_build_common + + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_C2 + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_C5 + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_C6 +} + +function ci_esp32_build_p4 { + ci_esp32_build_common + + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_P4 + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_P4 BOARD_VARIANT=C6_WIFI +} + ######################################################################################## # ports/esp8266 function ci_esp8266_setup { sudo pip3 install pyserial esptool==3.3.1 pyelftools ar - wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz - zcat xtensa-lx106-elf-standalone.tar.gz | tar x + wget https://micropython.org/resources/xtensa-lx106-elf-standalone.tar.gz + (set -o pipefail; zcat xtensa-lx106-elf-standalone.tar.gz | tar x) # Remove this esptool.py so pip version is used instead rm xtensa-lx106-elf/bin/esptool.py } @@ -317,17 +374,52 @@ function ci_qemu_setup_rv32 { qemu-system-riscv32 --version } -function ci_qemu_build_arm { +function ci_qemu_setup_rv64 { + ci_gcc_riscv_setup + sudo apt-get update + sudo apt-get install qemu-system + qemu-system-riscv64 --version +} + +function ci_qemu_build_arm_prepare { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/qemu submodules +} + +function ci_qemu_build_arm_bigendian { + ci_qemu_build_arm_prepare make ${MAKEOPTS} -C ports/qemu CFLAGS_EXTRA=-DMP_ENDIANNESS_BIG=1 - make ${MAKEOPTS} -C ports/qemu clean - make ${MAKEOPTS} -C ports/qemu test_full +} + +function ci_qemu_build_arm_sabrelite { + ci_qemu_build_arm_prepare make ${MAKEOPTS} -C ports/qemu BOARD=SABRELITE test_full +} - # Test building and running native .mpy with armv7m architecture. +function ci_qemu_build_arm_thumb_softfp { + ci_qemu_build_arm_prepare + make BOARD=MPS2_AN385 ${MAKEOPTS} -C ports/qemu test_full + + # Test building native .mpy with ARM-M softfp architectures. + ci_native_mpy_modules_build armv6m ci_native_mpy_modules_build armv7m - make ${MAKEOPTS} -C ports/qemu test_natmod + + # Test running native .mpy with all ARM-M architectures. + make BOARD=MPS2_AN385 ${MAKEOPTS} -C ports/qemu test_natmod RUN_TESTS_EXTRA="--arch armv6m" + make BOARD=MPS2_AN385 ${MAKEOPTS} -C ports/qemu test_natmod RUN_TESTS_EXTRA="--arch armv7m" +} + +function ci_qemu_build_arm_thumb_hardfp { + ci_qemu_build_arm_prepare + make BOARD=MPS2_AN500 ${MAKEOPTS} -C ports/qemu test_full + + # Test building native .mpy with all ARM-M hardfp architectures. + ci_native_mpy_modules_build armv7emsp + ci_native_mpy_modules_build armv7emdp + + # Test running native .mpy with all ARM-M hardfp architectures. + make BOARD=MPS2_AN500 ${MAKEOPTS} -C ports/qemu test_natmod RUN_TESTS_EXTRA="--arch armv7emsp" + make BOARD=MPS2_AN500 ${MAKEOPTS} -C ports/qemu test_natmod RUN_TESTS_EXTRA="--arch armv7emdp" } function ci_qemu_build_rv32 { @@ -340,6 +432,12 @@ function ci_qemu_build_rv32 { make ${MAKEOPTS} -C ports/qemu BOARD=VIRT_RV32 test_natmod } +function ci_qemu_build_rv64 { + make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/qemu BOARD=VIRT_RV64 submodules + make ${MAKEOPTS} -C ports/qemu BOARD=VIRT_RV64 test +} + ######################################################################################## # ports/renesas-ra @@ -403,13 +501,22 @@ function ci_samd_build { # ports/stm32 function ci_stm32_setup { - ci_gcc_arm_setup + # Use a recent version of the ARM toolchain, to work with Cortex-M55. + wget https://developer.arm.com/-/media/Files/downloads/gnu/14.3.rel1/binrel/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi.tar.xz + xzcat arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi.tar.xz | tar x + pip3 install pyelftools pip3 install ar pip3 install pyhy } +function ci_stm32_path { + echo $(pwd)/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin +} + function ci_stm32_pyb_build { + # This function builds the following MCU families: F4, F7. + make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/stm32 MICROPY_PY_NETWORK_WIZNET5K=5200 submodules make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 submodules @@ -421,20 +528,18 @@ function ci_stm32_pyb_build { make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBV10 CFLAGS_EXTRA='-DMBOOT_FSLOAD=1 -DMBOOT_VFS_LFS2=1' make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBD_SF6 make ${MAKEOPTS} -C ports/stm32/mboot BOARD=STM32F769DISC CFLAGS_EXTRA='-DMBOOT_ADDRESS_SPACE_64BIT=1 -DMBOOT_SDCARD_ADDR=0x100000000ULL -DMBOOT_SDCARD_BYTE_SIZE=0x400000000ULL -DMBOOT_FSLOAD=1 -DMBOOT_VFS_FAT=1' - - # Test building native .mpy with armv7emsp architecture. - git submodule update --init lib/berkeley-db-1.xx - ci_native_mpy_modules_build armv7emsp } function ci_stm32_nucleo_build { + # This function builds the following MCU families: F0, H5, H7, L0, L4, WB. + make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI submodules git submodule update --init lib/mynewt-nimble # Test building various MCU families, some with additional options. make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_F091RC - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32H573I_DK + make ${MAKEOPTS} -C ports/stm32 BOARD=STM32H573I_DK CFLAGS_EXTRA='-DMICROPY_HW_TINYUSB_STACK=1' make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI COPT=-O2 CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L073RZ make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L476RG DEBUG=1 @@ -454,21 +559,22 @@ function ci_stm32_nucleo_build { } function ci_stm32_misc_build { + # This function builds the following MCU families: G0, G4, H7, L1, N6, U5, WL. + make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/stm32 BOARD=ARDUINO_GIGA submodules make ${MAKEOPTS} -C ports/stm32 BOARD=ARDUINO_GIGA + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_G0B1RE + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_G474RE + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L152RE + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_N657X0 + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_U5A5ZJ_Q + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_WL55 } ######################################################################################## # ports/unix -CI_UNIX_OPTS_SYS_SETTRACE=( - MICROPY_PY_BTREE=0 - MICROPY_PY_FFI=0 - MICROPY_PY_SSL=0 - CFLAGS_EXTRA="-DMICROPY_PY_SYS_SETTRACE=1" -) - CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS=( MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 @@ -494,6 +600,26 @@ CI_UNIX_OPTS_QEMU_RISCV64=( MICROPY_STANDALONE=1 ) +CI_UNIX_OPTS_SANITIZE_ADDRESS=( + # Macro MP_ASAN allows detecting ASan on gcc<=13 + CFLAGS_EXTRA="-fsanitize=address --param asan-use-after-return=0 -DMP_ASAN=1" + LDFLAGS_EXTRA="-fsanitize=address --param asan-use-after-return=0" +) + +CI_UNIX_OPTS_SANITIZE_UNDEFINED=( + # Macro MP_UBSAN allows detecting UBSan on gcc<=13 + CFLAGS_EXTRA="-fsanitize=undefined -fno-sanitize=nonnull-attribute -DMP_UBSAN=1" + LDFLAGS_EXTRA="-fsanitize=undefined -fno-sanitize=nonnull-attribute" +) + +CI_UNIX_OPTS_REPR_B=( + VARIANT=standard + CFLAGS_EXTRA="-DMICROPY_OBJ_REPR=MICROPY_OBJ_REPR_B -DMICROPY_PY_UCTYPES=0 -Dmp_int_t=int32_t -Dmp_uint_t=uint32_t" + MICROPY_FORCE_32BIT=1 + RUN_TESTS_MPY_CROSS_FLAGS="--mpy-cross-flags=\"-march=x86 -msmall-int-bits=30\"" + +) + function ci_unix_build_helper { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/unix "$@" submodules @@ -509,13 +635,26 @@ function ci_unix_run_tests_helper { make -C ports/unix "$@" test } +function ci_unix_run_tests_full_extra { + micropython=$1 + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-multitests.py multi_net/*.py) + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-perfbench.py --average 1 1000 1000) +} + +function ci_unix_run_tests_full_no_native_helper { + variant=$1 + shift + micropython=../ports/unix/build-$variant/micropython + make -C ports/unix VARIANT=$variant "$@" test_full_no_native + ci_unix_run_tests_full_extra $micropython +} + function ci_unix_run_tests_full_helper { variant=$1 shift micropython=../ports/unix/build-$variant/micropython make -C ports/unix VARIANT=$variant "$@" test_full - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-multitests.py multi_net/*.py) - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-perfbench.py 1000 1000) + ci_unix_run_tests_full_extra $micropython } function ci_native_mpy_modules_build { @@ -524,40 +663,19 @@ function ci_native_mpy_modules_build { else arch=$1 fi - for natmod in features1 features3 features4 heapq re + for natmod in btree deflate features1 features3 features4 framebuf heapq random re do - make -C examples/natmod/$natmod clean + make -C examples/natmod/$natmod ARCH=$arch clean make -C examples/natmod/$natmod ARCH=$arch done - # deflate, framebuf, and random currently cannot build on xtensa due to - # some symbols that have been removed from the compiler's runtime, in - # favour of being provided from ROM. - if [ $arch != "xtensa" ]; then - for natmod in deflate framebuf random - do - make -C examples/natmod/$natmod clean - make -C examples/natmod/$natmod ARCH=$arch - done - fi - - # features2 requires soft-float on armv7m, rv32imc, and xtensa. On armv6m - # the compiler generates absolute relocations in the object file - # referencing soft-float functions, which is not supported at the moment. - make -C examples/natmod/features2 clean - if [ $arch = "rv32imc" ] || [ $arch = "armv7m" ] || [ $arch = "xtensa" ]; then + # features2 requires soft-float on rv32imc and xtensa. + make -C examples/natmod/features2 ARCH=$arch clean + if [ $arch = "rv32imc" ] || [ $arch = "xtensa" ]; then make -C examples/natmod/features2 ARCH=$arch MICROPY_FLOAT_IMPL=float - elif [ $arch != "armv6m" ]; then + else make -C examples/natmod/features2 ARCH=$arch fi - - # btree requires thread local storage support on rv32imc, whilst on xtensa - # it relies on symbols that are provided from ROM but not exposed to - # natmods at the moment. - if [ $arch != "rv32imc" ] && [ $arch != "xtensa" ]; then - make -C examples/natmod/btree clean - make -C examples/natmod/btree ARCH=$arch - fi } function ci_native_mpy_modules_32bit_build { @@ -569,7 +687,7 @@ function ci_unix_minimal_build { } function ci_unix_minimal_run_tests { - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/build-minimal/micropython ./run-tests.py -e exception_chain -e self_type_check -e subclass_native_init -d basics) + make -C ports/unix VARIANT=minimal test } function ci_unix_standard_build { @@ -591,9 +709,9 @@ function ci_unix_standard_v2_run_tests { } function ci_unix_coverage_setup { - sudo pip3 install setuptools - sudo pip3 install pyelftools - sudo pip3 install ar + pip3 install setuptools + pip3 install pyelftools + pip3 install ar gcc --version python3 --version } @@ -604,7 +722,7 @@ function ci_unix_coverage_build { } function ci_unix_coverage_run_tests { - ci_unix_run_tests_full_helper coverage + MICROPY_TEST_TIMEOUT=60 ci_unix_run_tests_full_helper coverage } function ci_unix_coverage_run_mpy_merge_tests { @@ -639,12 +757,11 @@ function ci_unix_coverage_run_native_mpy_tests { function ci_unix_32bit_setup { sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install gcc-multilib g++-multilib libffi-dev:i386 python2.7 + sudo apt-get install gcc-multilib g++-multilib libffi-dev:i386 sudo pip3 install setuptools sudo pip3 install pyelftools sudo pip3 install ar gcc --version - python2.7 --version python3 --version } @@ -662,13 +779,20 @@ function ci_unix_coverage_32bit_run_native_mpy_tests { } function ci_unix_nanbox_build { - # Use Python 2 to check that it can run the build scripts - ci_unix_build_helper PYTHON=python2.7 VARIANT=nanbox CFLAGS_EXTRA="-DMICROPY_PY_MATH_CONSTANTS=1" + ci_unix_build_helper VARIANT=nanbox CFLAGS_EXTRA="-DMICROPY_PY_MATH_CONSTANTS=1" ci_unix_build_ffi_lib_helper gcc -m32 } function ci_unix_nanbox_run_tests { - ci_unix_run_tests_full_helper nanbox PYTHON=python2.7 + ci_unix_run_tests_full_no_native_helper nanbox +} + +function ci_unix_longlong_build { + ci_unix_build_helper VARIANT=longlong "${CI_UNIX_OPTS_SANITIZE_UNDEFINED[@]}" +} + +function ci_unix_longlong_run_tests { + ci_unix_run_tests_full_helper longlong } function ci_unix_float_build { @@ -681,7 +805,17 @@ function ci_unix_float_run_tests { ci_unix_run_tests_helper CFLAGS_EXTRA="-DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT" } +function ci_unix_gil_enabled_build { + ci_unix_build_helper VARIANT=standard MICROPY_PY_THREAD_GIL=1 + ci_unix_build_ffi_lib_helper gcc +} + +function ci_unix_gil_enabled_run_tests { + ci_unix_run_tests_full_helper standard MICROPY_PY_THREAD_GIL=1 +} + function ci_unix_clang_setup { + sudo apt-get update sudo apt-get install clang clang --version } @@ -693,7 +827,8 @@ function ci_unix_stackless_clang_build { } function ci_unix_stackless_clang_run_tests { - ci_unix_run_tests_helper CC=clang + # Timeout needs to be increased for thread/stress_aes.py test. + MICROPY_TEST_TIMEOUT=90 ci_unix_run_tests_helper CC=clang } function ci_unix_float_clang_build { @@ -706,24 +841,36 @@ function ci_unix_float_clang_run_tests { ci_unix_run_tests_helper CC=clang } -function ci_unix_settrace_build { +function ci_unix_settrace_stackless_build { + make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/unix submodules + make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" +} + +function ci_unix_settrace_stackless_run_tests { + ci_unix_run_tests_full_helper standard "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" +} + +function ci_unix_sanitize_undefined_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE[@]}" + make ${MAKEOPTS} -C ports/unix VARIANT=coverage "${CI_UNIX_OPTS_SANITIZE_UNDEFINED[@]}" + ci_unix_build_ffi_lib_helper gcc } -function ci_unix_settrace_run_tests { - ci_unix_run_tests_full_helper standard "${CI_UNIX_OPTS_SYS_SETTRACE[@]}" +function ci_unix_sanitize_undefined_run_tests { + MICROPY_TEST_TIMEOUT=60 ci_unix_run_tests_full_helper coverage VARIANT=coverage "${CI_UNIX_OPTS_SANITIZE_UNDEFINED[@]}" } -function ci_unix_settrace_stackless_build { +function ci_unix_sanitize_address_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" + make ${MAKEOPTS} -C ports/unix VARIANT=coverage "${CI_UNIX_OPTS_SANITIZE_ADDRESS[@]}" + ci_unix_build_ffi_lib_helper gcc } -function ci_unix_settrace_stackless_run_tests { - ci_unix_run_tests_full_helper standard "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" +function ci_unix_sanitize_address_run_tests { + MICROPY_TEST_TIMEOUT=60 ci_unix_run_tests_full_helper coverage VARIANT=coverage "${CI_UNIX_OPTS_SANITIZE_ADDRESS[@]}" } function ci_unix_macos_build { @@ -740,7 +887,9 @@ function ci_unix_macos_run_tests { # Issues with macOS tests: # - float_parse and float_parse_doubleprec parse/print floats out by a few mantissa bits # - ffi_callback crashes for an unknown reason - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-standard/micropython ./run-tests.py --exclude '(float_parse|float_parse_doubleprec|ffi_callback).py') + # - thread/stress_heap.py is flaky + # - thread/thread_gc1.py is flaky + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-standard/micropython ./run-tests.py --exclude '(float_parse|float_parse_doubleprec|ffi_callback|thread/stress_heap|thread/thread_gc1).py') } function ci_unix_qemu_mips_setup { @@ -758,8 +907,12 @@ function ci_unix_qemu_mips_build { } function ci_unix_qemu_mips_run_tests { + # Issues with MIPS tests: + # - thread/stress_aes.py takes around 50 seconds + # - thread/stress_recurse.py is flaky + # - thread/thread_gc1.py is flaky file ./ports/unix/build-coverage/micropython - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py) + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython MICROPY_TEST_TIMEOUT=90 ./run-tests.py --exclude 'thread/stress_recurse.py|thread/thread_gc1.py') } function ci_unix_qemu_arm_setup { @@ -779,8 +932,11 @@ function ci_unix_qemu_arm_build { function ci_unix_qemu_arm_run_tests { # Issues with ARM tests: # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) + # - thread/stress_aes.py takes around 70 seconds + # - thread/stress_recurse.py is flaky + # - thread/thread_gc1.py is flaky file ./ports/unix/build-coverage/micropython - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.*\.py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython MICROPY_TEST_TIMEOUT=90 ./run-tests.py --exclude 'vfs_posix.*\.py|thread/stress_recurse.py|thread/thread_gc1.py') } function ci_unix_qemu_riscv64_setup { @@ -798,14 +954,30 @@ function ci_unix_qemu_riscv64_build { } function ci_unix_qemu_riscv64_run_tests { + # Issues with RISCV-64 tests: + # - thread/stress_aes.py takes around 140 seconds + # - thread/stress_recurse.py is flaky + # - thread/thread_gc1.py is flaky file ./ports/unix/build-coverage/micropython - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py) + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython MICROPY_TEST_TIMEOUT=180 ./run-tests.py --exclude 'thread/stress_recurse.py|thread/thread_gc1.py') +} + +function ci_unix_repr_b_build { + ci_unix_build_helper "${CI_UNIX_OPTS_REPR_B[@]}" + ci_unix_build_ffi_lib_helper gcc -m32 +} + +function ci_unix_repr_b_run_tests { + # ci_unix_run_tests_full_no_native_helper is not used due to + # https://github.com/micropython/micropython/issues/18105 + ci_unix_run_tests_helper "${CI_UNIX_OPTS_REPR_B[@]}" } ######################################################################################## # ports/windows function ci_windows_setup { + sudo apt-get update sudo apt-get install gcc-mingw-w64 } @@ -813,14 +985,15 @@ function ci_windows_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/windows submodules make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=i686-w64-mingw32- + make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=x86_64-w64-mingw32- BUILD=build-standard-w64 } ######################################################################################## # ports/zephyr -ZEPHYR_DOCKER_VERSION=v0.26.13 -ZEPHYR_SDK_VERSION=0.16.8 -ZEPHYR_VERSION=v3.7.0 +ZEPHYR_DOCKER_VERSION=v0.28.1 +ZEPHYR_SDK_VERSION=0.17.2 +ZEPHYR_VERSION=v4.2.0 function ci_zephyr_setup { IMAGE=ghcr.io/zephyrproject-rtos/ci:${ZEPHYR_DOCKER_VERSION} @@ -859,6 +1032,7 @@ function ci_zephyr_install { } function ci_zephyr_build { + git submodule update --init lib/micropython-lib docker exec zephyr-ci west build -p auto -b qemu_x86 -- -DCONF_FILE=prj_minimal.conf docker exec zephyr-ci west build -p auto -b frdm_k64f docker exec zephyr-ci west build -p auto -b mimxrt1050_evk @@ -867,9 +1041,7 @@ function ci_zephyr_build { function ci_zephyr_run_tests { docker exec zephyr-ci west build -p auto -b qemu_cortex_m3 -- -DCONF_FILE=prj_minimal.conf - # Issues with zephyr tests: - # - inf_nan_arith fails pow(-1, nan) test - (cd tests && ./run-tests.py -t execpty:"qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -monitor null -serial pty -kernel ../ports/zephyr/build/zephyr/zephyr.elf" -d basics float --exclude inf_nan_arith) + (cd tests && ./run-tests.py -t execpty:"qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -monitor null -serial pty -kernel ../ports/zephyr/build/zephyr/zephyr.elf") } ######################################################################################## @@ -886,3 +1058,86 @@ function ci_alif_ae3_build { make ${MAKEOPTS} -C ports/alif BOARD=OPENMV_AE3 MCU_CORE=M55_DUAL make ${MAKEOPTS} -C ports/alif BOARD=ALIF_ENSEMBLE MCU_CORE=M55_DUAL } + +function _ci_help { + # Note: these lines must be indented with tab characters (required by bash <<-EOF) + cat <<-EOF + ci.sh: Script fragments used during CI + + When invoked as a script, runs a sequence of ci steps, + stopping after the first error. + + Usage: + ${BASH_SOURCE} step1 step2... + + Steps: + EOF + if type -path column > /dev/null 2>&1; then + grep '^function ci_' $0 | awk '{print $2}' | sed 's/^ci_//' | column + else + grep '^function ci_' $0 | awk '{print $2}' | sed 's/^ci_//' + fi + exit +} + +function _ci_bash_completion { + echo "alias ci=\"$(readlink -f "$0")\"; complete -W '$(grep '^function ci_' $0 | awk '{print $2}' | sed 's/^ci_//')' ci" +} + +function _ci_zsh_completion { + echo "alias ci=\"$(readlink -f "$0"\"); _complete_mpy_ci_zsh() { compadd $(grep '^function ci_' $0 | awk '{sub(/^ci_/,"",$2); print $2}' | tr '\n' ' ') }; autoload -Uz compinit; compinit; compdef _complete_mpy_ci_zsh $(readlink -f "$0")" +} + +function _ci_fish_completion { + echo "alias ci=\"$(readlink -f "$0"\"); complete -c ci -p $(readlink -f "$0") -f -a '$(grep '^function ci_' $(readlink -f "$0") | awk '{sub(/^ci_/,"",$2); print $2}' | tr '\n' ' ')'" +} + +function _ci_main { + case "$1" in + (-h|-?|--help) + _ci_help + ;; + (--bash-completion) + _ci_bash_completion + ;; + (--zsh-completion) + _ci_zsh_completion + ;; + (--fish-completion) + _ci_fish_completion + ;; + (-*) + echo "Unknown option: $1" 1>&2 + exit 1 + ;; + (*) + set -e + cd $(dirname "$0")/.. + while [ $# -ne 0 ]; do + ci_$1 + shift + done + ;; + esac +} + +# https://stackoverflow.com/questions/2683279/how-to-detect-if-a-script-is-being-sourced +sourced=0 +if [ -n "$ZSH_VERSION" ]; then + case $ZSH_EVAL_CONTEXT in *:file) sourced=1;; esac +elif [ -n "$KSH_VERSION" ]; then + [ "$(cd -- "$(dirname -- "$0")" && pwd -P)/$(basename -- "$0")" != "$(cd -- "$(dirname -- "${.sh.file}")" && pwd -P)/$(basename -- "${.sh.file}")" ] && sourced=1 +elif [ -n "$BASH_VERSION" ]; then + (return 0 2>/dev/null) && sourced=1 +else # All other shells: examine $0 for known shell binary filenames. + # Detects `sh` and `dash`; add additional shell filenames as needed. + case ${0##*/} in sh|-sh|dash|-dash) sourced=1;; esac +fi + +if [ $sourced -eq 0 ]; then + # invoked as a command + if [ "$#" -eq 0 ]; then + set -- --help + fi + _ci_main "$@" +fi diff --git a/tools/ci_fetch_deps.py b/tools/ci_fetch_deps.py index be190ad6606..05559ac2d12 100644 --- a/tools/ci_fetch_deps.py +++ b/tools/ci_fetch_deps.py @@ -59,6 +59,7 @@ def _all_submodules(): "espressif": [ "extmod/ulab/", "lib/certificates/", + "lib/mp3/", "lib/protomatter/", "lib/quirc/", "lib/tlsf", @@ -68,6 +69,7 @@ def _all_submodules(): "mimxrt10xx": ["extmod/ulab/", "lib/tinyusb/", "lib/tlsf", "data/nvm.toml/"], "nordic": [ "extmod/ulab/", + "lib/mbedtls/", "lib/mp3/", "lib/protomatter/", "lib/tinyusb/", diff --git a/tools/ci_set_idf_constraint.py b/tools/ci_set_idf_constraint.py new file mode 100644 index 00000000000..49c187f4587 --- /dev/null +++ b/tools/ci_set_idf_constraint.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 Adafruit Industries LLC +# +# SPDX-License-Identifier: MIT + +"""Set IDF_CONSTRAINT_FILE for CI. + +CI installs requirements-dev.txt for all ports, but on Espressif builds we must +also apply the matching ESP-IDF constraints file so pip does not upgrade shared +packages (for example click) beyond what ESP-IDF allows. This script derives the +active ESP-IDF major.minor version from version.cmake and exports the exact +constraints file path into GITHUB_ENV for later install steps. +""" + +import os +import pathlib +import re + +TOP = pathlib.Path(__file__).resolve().parent.parent + + +def main() -> None: + version_cmake = TOP / "ports" / "espressif" / "esp-idf" / "tools" / "cmake" / "version.cmake" + data = version_cmake.read_text(encoding="utf-8") + + major = re.search(r"IDF_VERSION_MAJOR\s+(\d+)", data) + minor = re.search(r"IDF_VERSION_MINOR\s+(\d+)", data) + if major is None or minor is None: + raise RuntimeError(f"Unable to parse IDF version from {version_cmake}") + + idf_tools_path = os.environ.get("IDF_TOOLS_PATH") + if not idf_tools_path: + raise RuntimeError("IDF_TOOLS_PATH is not set") + + constraint = ( + pathlib.Path(idf_tools_path) / f"espidf.constraints.v{major.group(1)}.{minor.group(1)}.txt" + ) + + github_env = os.environ.get("GITHUB_ENV") + if github_env: + with open(github_env, "a", encoding="utf-8") as f: + f.write(f"IDF_CONSTRAINT_FILE={constraint}\n") + + print(f"Set IDF_CONSTRAINT_FILE={constraint}") + + +if __name__ == "__main__": + main() diff --git a/tools/codeformat.py b/tools/codeformat.py index a648d401ec3..cf91049a731 100644 --- a/tools/codeformat.py +++ b/tools/codeformat.py @@ -231,7 +231,7 @@ def batch(cmd, files, N=200, check=False): command = ["python3", "tools/ruff_bindings.py"] batch(command, bindings_files(), check=True) - # Format Python files with black. + # Format Python files with "ruff format" (using config in pyproject.toml). if format_py: command = ["ruff", "format"] if args.v: diff --git a/tools/file2h.py b/tools/file2h.py index df9cc02fdab..2707d4a16e5 100644 --- a/tools/file2h.py +++ b/tools/file2h.py @@ -9,8 +9,6 @@ # ; # This script simply prints the escaped string straight to stdout -from __future__ import print_function - import sys # Can either be set explicitly, or left blank to auto-detect diff --git a/tools/insert-usb-ids.py b/tools/insert-usb-ids.py index 4691d5a710c..1b043e1fef0 100644 --- a/tools/insert-usb-ids.py +++ b/tools/insert-usb-ids.py @@ -6,8 +6,6 @@ # inserts those values into the template file specified by sys.argv[2], # printing the result to stdout -from __future__ import print_function - import sys import re import string diff --git a/tools/makemanifest.py b/tools/makemanifest.py index e076a03e0be..860935397af 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -24,7 +24,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from __future__ import print_function import sys import os import subprocess diff --git a/tools/manifestfile.py b/tools/manifestfile.py index beaa36d0f5f..9c7a6e140f9 100644 --- a/tools/manifestfile.py +++ b/tools/manifestfile.py @@ -25,7 +25,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from __future__ import print_function import contextlib import os import sys diff --git a/tools/metrics.py b/tools/metrics.py index f6189e65abb..8bb96ba119a 100755 --- a/tools/metrics.py +++ b/tools/metrics.py @@ -43,20 +43,23 @@ """ -import collections, sys, re, subprocess +import collections, os, sys, re, shlex, subprocess, multiprocessing -MAKE_FLAGS = ["-j3", "CFLAGS_EXTRA=-DNDEBUG"] +MAKE_FLAGS = ["-j{}".format(multiprocessing.cpu_count()), "CFLAGS_EXTRA=-DNDEBUG"] class PortData: - def __init__(self, name, dir, output, make_flags=None): + def __init__(self, name, dir, output, make_flags=None, pre_cmd=None): self.name = name self.dir = dir self.output = output self.make_flags = make_flags self.needs_mpy_cross = dir not in ("bare-arm", "minimal") + self.pre_cmd = pre_cmd +mpy_cross_output = "mpy-cross/build/mpy-cross" + port_data = { "b": PortData("bare-arm", "bare-arm", "build/firmware.elf"), "m": PortData("minimal x86", "minimal", "build/firmware.elf"), @@ -65,7 +68,12 @@ def __init__(self, name, dir, output, make_flags=None): "s": PortData("stm32", "stm32", "build-PYBV10/firmware.elf", "BOARD=PYBV10"), "c": PortData("cc3200", "cc3200", "build/WIPY/release/application.axf", "BTARGET=application"), "8": PortData("esp8266", "esp8266", "build-ESP8266_GENERIC/firmware.elf"), - "3": PortData("esp32", "esp32", "build-ESP32_GENERIC/micropython.elf"), + "3": PortData( + "esp32", + "esp32", + "build-ESP32_GENERIC/micropython.elf", + pre_cmd=". esp-idf/export.sh", + ), "x": PortData("mimxrt", "mimxrt", "build-TEENSY40/firmware.elf"), "e": PortData("renesas-ra", "renesas-ra", "build-EK_RA6M2/firmware.elf"), "r": PortData("nrf", "nrf", "build-PCA10040/firmware.elf"), @@ -74,8 +82,15 @@ def __init__(self, name, dir, output, make_flags=None): "v": PortData("qemu rv32", "qemu", "build-VIRT_RV32/firmware.elf", "BOARD=VIRT_RV32"), } +for port_letter, port in port_data.items(): + port.pre_cmd = os.environ.get(f"PRE_CMD_{port_letter}", port.pre_cmd) + + +def quoted(args): + return " ".join(shlex.quote(word) for word in args) -def syscmd(*args): + +def syscmd(*args, pre_cmd=None): sys.stdout.flush() a2 = [] for a in args: @@ -83,6 +98,10 @@ def syscmd(*args): a2.append(a) elif a: a2.extend(a) + if pre_cmd is not None: + a2_quoted = quoted(a2) + a2 = ["bash", "-c", "{} && {}".format(pre_cmd, a2_quoted)] + print(a2) subprocess.check_call(a2) @@ -108,6 +127,8 @@ def read_build_log(filename): with open(filename) as f: for line in f: line = line.strip() + if line.startswith("BUILDING ") and "_ref" not in data: + data["_ref"] = line.removeprefix("BUILDING ") if line.strip() == "COMPUTING SIZES": found_sizes = True elif found_sizes: @@ -139,9 +160,15 @@ def do_diff(args): data1 = read_build_log(args[0]) data2 = read_build_log(args[1]) + ref1 = data1.pop("_ref", "(unknown ref)") + ref2 = data2.pop("_ref", "(unknown ref)") + print(f"Reference: {ref1}") + print(f"Comparison: {ref2}") max_delta = None for key, value1 in data1.items(): value2 = data2[key] + if key == mpy_cross_output: + name = "mpy-cross" for port in port_data.values(): if key == "ports/{}/{}".format(port.dir, port.output): name = port.name @@ -181,8 +208,19 @@ def do_clean(args): ports = parse_port_list(args) print("CLEANING") + + if any(port.needs_mpy_cross for port in ports): + syscmd("make", "-C", "mpy-cross", "clean") + for port in ports: - syscmd("make", "-C", "ports/{}".format(port.dir), port.make_flags, "clean") + syscmd( + "make", + "-C", + "ports/{}".format(port.dir), + port.make_flags, + "clean", + pre_cmd=port.pre_cmd, + ) def do_build(args): @@ -196,7 +234,14 @@ def do_build(args): print("BUILDING PORTS") for port in ports: - syscmd("make", "-C", "ports/{}".format(port.dir), MAKE_FLAGS, port.make_flags) + syscmd( + "make", + "-C", + "ports/{}".format(port.dir), + MAKE_FLAGS, + port.make_flags, + pre_cmd=port.pre_cmd, + ) do_sizes(args) @@ -207,6 +252,10 @@ def do_sizes(args): ports = parse_port_list(args) print("COMPUTING SIZES") + + if any(port.needs_mpy_cross for port in ports): + syscmd("size", mpy_cross_output) + for port in ports: syscmd("size", "ports/{}/{}".format(port.dir, port.output)) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 8849f2f1e59..bf0b89018e4 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -24,40 +24,21 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -# Python 2/3/MicroPython compatibility code -from __future__ import print_function +import io +import struct import sys +from binascii import hexlify -if sys.version_info[0] == 2: - from binascii import hexlify as hexlify_py2 - - str_cons = lambda val, enc=None: str(val) - bytes_cons = lambda val, enc=None: bytearray(val) - is_str_type = lambda o: isinstance(o, str) - is_bytes_type = lambda o: type(o) is bytearray - is_int_type = lambda o: isinstance(o, int) or isinstance(o, long) # noqa: F821 - - def hexlify_to_str(b): - x = hexlify_py2(b) - return ":".join(x[i : i + 2] for i in range(0, len(x), 2)) - -elif sys.version_info[0] == 3: # Also handles MicroPython - from binascii import hexlify - - str_cons = str - bytes_cons = bytes - is_str_type = lambda o: isinstance(o, str) - is_bytes_type = lambda o: isinstance(o, bytes) - is_int_type = lambda o: isinstance(o, int) - - def hexlify_to_str(b): - return str(hexlify(b, ":"), "ascii") +str_cons = str +bytes_cons = bytes +is_str_type = lambda o: isinstance(o, str) +is_bytes_type = lambda o: isinstance(o, bytes) +is_int_type = lambda o: isinstance(o, int) -# end compatibility code +def hexlify_to_str(b): + return str(hexlify(b, ":"), "ascii") -import sys -import struct sys.path.append(sys.path[0] + "/../py") import makeqstrdata as qstrutil @@ -114,6 +95,23 @@ class Config: MP_NATIVE_ARCH_XTENSA = 9 MP_NATIVE_ARCH_XTENSAWIN = 10 MP_NATIVE_ARCH_RV32IMC = 11 +MP_NATIVE_ARCH_RV64IMC = 12 + +MP_NATIVE_ARCH_NAMES = [ + "NONE", + "X86", + "X64", + "ARMV6", + "ARMV6M", + "ARMV7M", + "ARMV7EM", + "ARMV7EMSP", + "ARMV7EMDP", + "XTENSA", + "XTENSAWIN", + "RV32IMC", + "RV64IMC", +] MP_PERSISTENT_OBJ_FUN_TABLE = 0 MP_PERSISTENT_OBJ_NONE = 1 @@ -142,6 +140,8 @@ class Config: MP_BC_FORMAT_VAR_UINT = 2 MP_BC_FORMAT_OFFSET = 3 +MP_NATIVE_ARCH_FLAGS_PRESENT = 0x40 + mp_unary_op_method_name = ( "__pos__", "__neg__", @@ -306,6 +306,25 @@ class Opcode: MP_BC_POP_JUMP_IF_TRUE, MP_BC_POP_JUMP_IF_FALSE, ) + ALL_OFFSET = ( + MP_BC_UNWIND_JUMP, + MP_BC_JUMP, + MP_BC_POP_JUMP_IF_TRUE, + MP_BC_POP_JUMP_IF_FALSE, + MP_BC_JUMP_IF_TRUE_OR_POP, + MP_BC_JUMP_IF_FALSE_OR_POP, + MP_BC_SETUP_WITH, + MP_BC_SETUP_EXCEPT, + MP_BC_SETUP_FINALLY, + MP_BC_POP_EXCEPT_JUMP, + MP_BC_FOR_ITER, + ) + ALL_WITH_CHILD = ( + MP_BC_MAKE_FUNCTION, + MP_BC_MAKE_FUNCTION_DEFARGS, + MP_BC_MAKE_CLOSURE, + MP_BC_MAKE_CLOSURE_DEFARGS, + ) # Create a dict mapping opcode value to opcode name. mapping = ["unknown" for _ in range(256)] @@ -562,6 +581,7 @@ def __init__( mpy_source_file, mpy_segments, header, + arch_flags, qstr_table, obj_table, raw_code, @@ -574,6 +594,7 @@ def __init__( self.mpy_segments = mpy_segments self.source_file = qstr_table[0] self.header = header + self.arch_flags = arch_flags self.qstr_table = qstr_table self.obj_table = obj_table self.raw_code = raw_code @@ -651,6 +672,14 @@ def disassemble(self): print("mpy_source_file:", self.mpy_source_file) print("source_file:", self.source_file.str) print("header:", hexlify_to_str(self.header)) + arch_index = (self.header[2] >> 2) & 0x2F + if arch_index >= len(MP_NATIVE_ARCH_NAMES): + arch_name = "UNKNOWN" + else: + arch_name = MP_NATIVE_ARCH_NAMES[arch_index] + print("arch:", arch_name) + if self.header[2] & MP_NATIVE_ARCH_FLAGS_PRESENT != 0: + print("arch_flags:", hex(self.arch_flags)) print("qstr_table[%u]:" % len(self.qstr_table)) for q in self.qstr_table: print(" %s" % q.str) @@ -888,7 +917,7 @@ def __init__(self, parent_name, qstr_table, fun_data, prelude_offset, code_kind) self.escaped_name = unique_escaped_name def disassemble_children(self): - print(" children:", [rc.simple_name.str for rc in self.children]) + self.print_children_annotated() for rc in self.children: rc.disassemble() @@ -980,6 +1009,75 @@ def freeze_raw_code(self, prelude_ptr=None, type_sig=0): raw_code_count += 1 raw_code_content += 4 * 4 + @staticmethod + def decode_lineinfo(line_info: memoryview) -> "tuple[int, int, memoryview]": + c = line_info[0] + if (c & 0x80) == 0: + # 0b0LLBBBBB encoding + return (c & 0x1F), (c >> 5), line_info[1:] + else: + # 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) + return (c & 0xF), (((c << 4) & 0x700) | line_info[1]), line_info[2:] + + def get_source_annotation(self, ip: int, file=None) -> dict: + bc_offset = ip - self.offset_opcodes + try: + line_info = memoryview(self.fun_data)[self.offset_line_info : self.offset_opcodes] + except AttributeError: + return {"file": file, "line": None} + + source_line = 1 + while line_info: + bc_increment, line_increment, line_info = self.decode_lineinfo(line_info) + if bc_offset >= bc_increment: + bc_offset -= bc_increment + source_line += line_increment + else: + break + + return {"file": file, "line": source_line} + + def get_label(self, ip: "int | None" = None, child_num: "int | None" = None) -> str: + if ip is not None: + assert child_num is None + return "%s.%d" % (self.escaped_name, ip) + elif child_num is not None: + return "%s.child%d" % (self.escaped_name, child_num) + else: + return "%s" % self.escaped_name + + def print_children_annotated(self) -> None: + """ + Equivalent to `print(" children:", [child.simple_name.str for child in self.children])`, + but also includes json markers for the start and end of each one's name in that line. + """ + + labels = ["%s.children" % self.escaped_name] + annotation_labels = [] + output = io.StringIO() + output.write(" children: [") + sep = ", " + for i, child in enumerate(self.children): + if i != 0: + output.write(sep) + start_col = output.tell() + 1 + output.write(child.simple_name.str) + end_col = output.tell() + 1 + labels.append(self.get_label(child_num=i)) + annotation_labels.append( + { + "name": self.get_label(child_num=i), + "target": child.get_label(), + "range": { + "startCol": start_col, + "endCol": end_col, + }, + }, + ) + output.write("]") + + print(output.getvalue(), annotations={"labels": annotation_labels}, labels=labels) + class RawCodeBytecode(RawCode): def __init__(self, parent_name, qstr_table, obj_table, fun_data): @@ -988,9 +1086,58 @@ def __init__(self, parent_name, qstr_table, obj_table, fun_data): parent_name, qstr_table, fun_data, 0, MP_CODE_BYTECODE ) + def get_opcode_annotations_labels( + self, opcode: int, ip: int, arg: int, sz: int, arg_pos: int, arg_len: int + ) -> "tuple[dict, list[str]]": + annotations = { + "source": self.get_source_annotation(ip), + "disassembly": Opcode.mapping[opcode], + } + labels = [self.get_label(ip)] + + if opcode in Opcode.ALL_OFFSET: + annotations["link"] = { + "offset": arg_pos, + "length": arg_len, + "to": ip + arg + sz, + } + annotations["labels"] = [ + { + "name": self.get_label(ip), + "target": self.get_label(ip + arg + sz), + "range": { + "startCol": arg_pos + 1, + "endCol": arg_pos + arg_len + 1, + }, + }, + ] + + elif opcode in Opcode.ALL_WITH_CHILD: + try: + child = self.children[arg] + except IndexError: + # link out-of-range child to the child array itself + target = "%s.children" % self.escaped_name + else: + # link resolvable child to the actual child + target = child.get_label() + + annotations["labels"] = [ + { + "name": self.get_label(ip), + "target": target, + "range": { + "startCol": arg_pos + 1, + "endCol": arg_pos + arg_len + 1, + }, + }, + ] + + return annotations, labels + def disassemble(self): bc = self.fun_data - print("simple_name:", self.simple_name.str) + print("simple_name:", self.simple_name.str, labels=[self.get_label()]) print(" raw bytecode:", len(bc), hexlify_to_str(bc)) print(" prelude:", self.prelude_signature) print(" args:", [self.qstr_table[i].str for i in self.names[1:]]) @@ -1006,9 +1153,22 @@ def disassemble(self): pass else: arg = "" - print( - " %-11s %s %s" % (hexlify_to_str(bc[ip : ip + sz]), Opcode.mapping[bc[ip]], arg) + + pre_arg_part = " %-11s %s" % ( + hexlify_to_str(bc[ip : ip + sz]), + Opcode.mapping[bc[ip]], + ) + arg_part = "%s" % arg + annotations, labels = self.get_opcode_annotations_labels( + opcode=bc[ip], + ip=ip, + arg=arg, + sz=sz, + arg_pos=len(pre_arg_part) + 1, + arg_len=len(arg_part), ) + + print(pre_arg_part, arg_part, annotations=annotations, labels=labels) ip += sz self.disassemble_children() @@ -1085,6 +1245,7 @@ def __init__( MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN, MP_NATIVE_ARCH_RV32IMC, + MP_NATIVE_ARCH_RV64IMC, ): self.fun_data_attributes = '__attribute__((section(".text,\\"ax\\",@progbits # ")))' else: @@ -1102,13 +1263,13 @@ def __init__( self.fun_data_attributes += " __attribute__ ((aligned (4)))" elif ( MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP - ) or config.native_arch == MP_NATIVE_ARCH_RV32IMC: - # ARMVxxM or RV32IMC -- two byte align. + ) or MP_NATIVE_ARCH_RV32IMC <= config.native_arch <= MP_NATIVE_ARCH_RV64IMC: + # ARMVxxM or RV{32,64}IMC -- two byte align. self.fun_data_attributes += " __attribute__ ((aligned (2)))" def disassemble(self): fun_data = self.fun_data - print("simple_name:", self.simple_name.str) + print("simple_name:", self.simple_name.str, labels=[self.get_label()]) print( " raw data:", len(fun_data), @@ -1362,7 +1523,7 @@ def read_mpy(filename): if header[1] != config.MPY_VERSION: raise MPYReadError(filename, "incompatible .mpy version") feature_byte = header[2] - mpy_native_arch = feature_byte >> 2 + mpy_native_arch = (feature_byte >> 2) & 0x2F if mpy_native_arch != MP_NATIVE_ARCH_NONE: mpy_sub_version = feature_byte & 3 if mpy_sub_version != config.MPY_SUB_VERSION: @@ -1373,6 +1534,11 @@ def read_mpy(filename): raise MPYReadError(filename, "native architecture mismatch") config.mp_small_int_bits = header[3] + arch_flags = 0 + # Read the architecture-specific flag bits if present. + if (feature_byte & MP_NATIVE_ARCH_FLAGS_PRESENT) != 0: + arch_flags = reader.read_uint() + # Read number of qstrs, and number of objects. n_qstr = reader.read_uint() n_obj = reader.read_uint() @@ -1401,6 +1567,7 @@ def read_mpy(filename): filename, segments, header, + arch_flags, qstr_table, obj_table, raw_code, @@ -1696,26 +1863,40 @@ def merge_mpy(compiled_modules, output_file): merged_mpy.extend(f.read()) else: main_cm_idx = None + arch_flags = 0 for idx, cm in enumerate(compiled_modules): feature_byte = cm.header[2] - mpy_native_arch = feature_byte >> 2 + mpy_native_arch = (feature_byte >> 2) & 0x2F if mpy_native_arch: # Must use qstr_table and obj_table from this raw_code if main_cm_idx is not None: raise Exception("can't merge files when more than one contains native code") main_cm_idx = idx + arch_flags = cm.arch_flags if main_cm_idx is not None: # Shift main_cm to front of list. compiled_modules.insert(0, compiled_modules.pop(main_cm_idx)) + if config.arch_flags is not None: + arch_flags = config.arch_flags + header = bytearray(4) ## CIRCUITPY-CHANGE: "C" is used for CircuitPython header[0] = ord("C") header[1] = config.MPY_VERSION - header[2] = config.native_arch << 2 | config.MPY_SUB_VERSION if config.native_arch else 0 + header[2] = ( + (MP_NATIVE_ARCH_FLAGS_PRESENT if arch_flags != 0 else 0) + | config.native_arch << 2 + | config.MPY_SUB_VERSION + if config.native_arch + else 0 + ) header[3] = config.mp_small_int_bits merged_mpy.extend(header) + if arch_flags != 0: + merged_mpy.extend(mp_encode_uint(arch_flags)) + n_qstr = 0 n_obj = 0 for cm in compiled_modules: @@ -1771,6 +1952,138 @@ def copy_section(file, offset, offset2): f.write(merged_mpy) +def extract_segments(compiled_modules, basename, kinds_arg): + import re + + kind_str = ("META", "QSTR", "OBJ", "CODE") + kinds = set() + if kinds_arg is not None: + for kind in kinds_arg.upper().split(","): + if kind in kind_str: + kinds.add(kind) + else: + raise Exception('unknown segment kind "%s"' % (kind,)) + segments = [] + for module in compiled_modules: + for segment in module.mpy_segments: + if not kinds or kind_str[segment.kind] in kinds: + segments.append((module.mpy_source_file, module.source_file.str, segment)) + count_len = len(str(len(segments))) + sanitiser = re.compile("[^a-zA-Z0-9_.-]") + for counter, entry in enumerate(segments): + file_name, source_file, segment = entry + output_name = ( + basename + + "_" + + str(counter).rjust(count_len, "0") + + "_" + + sanitiser.sub("_", source_file) + + "_" + + kind_str[segment.kind] + + "_" + + sanitiser.sub("_", str(segment.name)) + + ".bin" + ) + with open(file_name, "rb") as source: + with open(output_name, "wb") as output: + source.seek(segment.start) + output.write(source.read(segment.end - segment.start)) + + +class PrintShim: + """Base class for interposing extra functionality onto the global `print` method.""" + + def __init__(self): + self.wrapped_print = None + + def __enter__(self): + global print + + if self.wrapped_print is not None: + raise RecursionError + + self.wrapped_print = print + print = self + + return self + + def __exit__(self, exc_type, exc_value, traceback): + global print + + if self.wrapped_print is None: + return + + print = self.wrapped_print + self.wrapped_print = None + + self.on_exit() + + def on_exit(self): + pass + + def __call__(self, *a, **k): + return self.wrapped_print(*a, **k) + + +class PrintIgnoreExtraArgs(PrintShim): + """Just strip the `annotations` and `labels` kwargs and pass down to the underlying print.""" + + def __call__(self, *a, annotations: dict = {}, labels: "list[str]" = (), **k): + return super().__call__(*a, **k) + + +class PrintJson(PrintShim): + """Output lines as godbolt-compatible JSON with extra annotation info from `annotations` and `labels`, rather than plain text.""" + + def __init__(self, fp=sys.stdout, language_id: str = "mpy"): + super().__init__() + self.fp = fp + self.asm = { + "asm": [], + "labelDefinitions": {}, + "languageId": language_id, + } + self.line_number: int = 0 + self.buf: "io.StringIO | None" = None + + def on_exit(self): + import json + + if self.buf is not None: + # flush last partial line + self.__call__() + + json.dump(self.asm, self.fp) + + def __call__(self, *a, annotations: dict = {}, labels: "list[str]" = (), **k): + # ignore prints directed to an explicit output + if "file" in k: + return super().__call__(*a, **k) + + if self.buf is None: + self.buf = io.StringIO() + + super().__call__(*a, file=sys.stderr, **k) + + if "end" in k: + # buffer partial-line prints to collect into a single AsmResultLine + return super().__call__(*a, file=self.buf, **k) + else: + retval = super().__call__(*a, file=self.buf, end="", **k) + output = self.buf.getvalue() + self.buf = None + + asm_line = {"text": output} + asm_line.update(annotations) + self.asm["asm"].append(asm_line) + + self.line_number += 1 + for label in labels: + self.asm["labelDefinitions"][label] = self.line_number + + return retval + + def main(args=None): global global_qstrs @@ -1784,9 +2097,23 @@ def main(args=None): "-d", "--disassemble", action="store_true", help="output disassembled contents of files" ) cmd_parser.add_argument("-f", "--freeze", action="store_true", help="freeze files") + cmd_parser.add_argument( + "-j", + "--json", + action="store_true", + help="output hexdump, disassembly, and frozen code as JSON with extra metadata", + ) cmd_parser.add_argument( "--merge", action="store_true", help="merge multiple .mpy files into one" ) + cmd_parser.add_argument( + "-e", "--extract", metavar="BASE", type=str, help="write segments into separate files" + ) + cmd_parser.add_argument( + "--extract-only", + metavar="KIND[,...]", + help="extract only segments of the given type (meta, qstr, obj, code)", + ) cmd_parser.add_argument("-q", "--qstr-header", help="qstr header file to freeze against") cmd_parser.add_argument( "-mlongint-impl", @@ -1801,6 +2128,12 @@ def main(args=None): default=16, help="mpz digit size used by target (default 16)", ) + cmd_parser.add_argument( + "-march-flags", + metavar="F", + type=int, + help="architecture flags value to set in the output file (strips existing flags if not present)", + ) cmd_parser.add_argument("-o", "--output", default=None, help="output file") cmd_parser.add_argument("files", nargs="+", help="input .mpy files") args = cmd_parser.parse_args(args) @@ -1813,6 +2146,7 @@ def main(args=None): }[args.mlongint_impl] config.MPZ_DIG_SIZE = args.mmpz_dig_size config.native_arch = MP_NATIVE_ARCH_NONE + config.arch_flags = args.march_flags # set config values for qstrs, and get the existing base set of qstrs # already in the firmware @@ -1836,24 +2170,40 @@ def main(args=None): print(er, file=sys.stderr) sys.exit(1) - if args.hexdump: - hexdump_mpy(compiled_modules) + if args.json: + if args.freeze: + print_shim = PrintJson(sys.stdout, language_id="c") + elif args.hexdump: + print_shim = PrintJson(sys.stdout, language_id="stderr") + elif args.disassemble: + print_shim = PrintJson(sys.stdout, language_id="mpy") + else: + print_shim = PrintJson(sys.stdout) + else: + print_shim = PrintIgnoreExtraArgs() - if args.disassemble: + with print_shim: if args.hexdump: - print() - disassemble_mpy(compiled_modules) + hexdump_mpy(compiled_modules) - if args.freeze: - try: - freeze_mpy(firmware_qstr_idents, compiled_modules) - except FreezeError as er: - print(er, file=sys.stderr) - sys.exit(1) + if args.disassemble: + if args.hexdump: + print() + disassemble_mpy(compiled_modules) + + if args.freeze: + try: + freeze_mpy(firmware_qstr_idents, compiled_modules) + except FreezeError as er: + print(er, file=sys.stderr) + sys.exit(1) if args.merge: merge_mpy(compiled_modules, args.output) + if args.extract: + extract_segments(compiled_modules, args.extract, args.extract_only) + if __name__ == "__main__": main() diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py index 219cd1a7468..26db0726163 100755 --- a/tools/mpy_ld.py +++ b/tools/mpy_ld.py @@ -402,6 +402,7 @@ def __init__(self, arch): self.known_syms = {} # dict of symbols that are defined self.unresolved_syms = [] # list of unresolved symbols self.mpy_relocs = [] # list of relocations needed in the output .mpy file + self.externs = {} # dict of externally-defined symbols def check_arch(self, arch_name): if arch_name != self.arch.name: @@ -491,10 +492,14 @@ def populate_got(env): sym = got_entry.sym if hasattr(sym, "resolved"): sym = sym.resolved - sec = sym.section - addr = sym["st_value"] - got_entry.sec_name = sec.name - got_entry.link_addr += sec.addr + addr + if sym.name in env.externs: + got_entry.sec_name = ".external.fixed_addr" + got_entry.link_addr = env.externs[sym.name] + else: + sec = sym.section + addr = sym["st_value"] + got_entry.sec_name = sec.name + got_entry.link_addr += sec.addr + addr # Get sorted GOT, sorted by external, text, rodata, bss so relocations can be combined got_list = sorted( @@ -520,6 +525,9 @@ def populate_got(env): dest = int(got_entry.name.split("+")[1], 16) // env.arch.word_size elif got_entry.sec_name == ".external.mp_fun_table": dest = got_entry.sym.mp_fun_table_offset + elif got_entry.sec_name == ".external.fixed_addr": + # Fixed-address symbols should not be relocated. + continue elif got_entry.sec_name.startswith(".text"): dest = ".text" elif got_entry.sec_name.startswith(".rodata"): @@ -703,8 +711,9 @@ def do_relocation_text(env, text_addr, r): (addr, value) = process_riscv32_relocation(env, text_addr, r) elif env.arch.name == "EM_ARM" and r_info_type == R_ARM_ABS32: - # happens for soft-float on armv6m - raise ValueError("Absolute relocations not supported on ARM") + # Absolute relocation, handled as a data relocation. + do_relocation_data(env, text_addr, r) + return else: # Unknown/unsupported relocation @@ -773,9 +782,9 @@ def do_relocation_data(env, text_addr, r): ): # Relocation in data.rel.ro to internal/external symbol if env.arch.word_size == 4: - struct_type = "/). + + symbols = {} + + LINE_REGEX = re.compile( + r"^(?PPROVIDE\()?" # optional weak marker start + r"(?P[a-zA-Z_]\w*)" # symbol name + r"=0x(?P
[\da-fA-F]{1,8})*" # symbol address + r"(?(weak)\));$", # optional weak marker end and line terminator + re.ASCII, + ) + + inside_comment = False + for line in (line.strip() for line in source.readlines()): + if line.startswith("/*") and not inside_comment: + if not line.endswith("*/"): + inside_comment = True + continue + if inside_comment: + if line.endswith("*/"): + inside_comment = False + continue + if line.startswith("//"): + continue + match = LINE_REGEX.match("".join(line.split())) + if not match: + continue + tokens = match.groupdict() + symbol = tokens["symbol"] + address = int(tokens["address"], 16) + if symbol in symbols: + raise ValueError(f"Symbol {symbol} already defined") + symbols[symbol] = address + return symbols + + def main(): import argparse @@ -1501,6 +1569,13 @@ def main(): cmd_parser.add_argument( "--output", "-o", default=None, help="output .mpy file (default to input with .o->.mpy)" ) + cmd_parser.add_argument( + "--externs", + "-e", + type=argparse.FileType("rt"), + default=None, + help="linkerscript providing fixed-address symbols to augment symbol resolution", + ) cmd_parser.add_argument("files", nargs="+", help="input files") args = cmd_parser.parse_args() diff --git a/tools/pyboard.py b/tools/pyboard.py index 20310ba7081..c9f65d5d873 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -248,14 +248,22 @@ def inWaiting(self): class Pyboard: def __init__( - self, device, baudrate=115200, user="micro", password="python", wait=0, exclusive=True + self, + device, + baudrate=115200, + user="micro", + password="python", + wait=0, + exclusive=True, + timeout=None, + write_timeout=5, ): self.in_raw_repl = False self.use_raw_paste = True if device.startswith("exec:"): self.serial = ProcessToSerial(device[len("exec:") :]) elif device.startswith("execpty:"): - self.serial = ProcessPtyToTerminal(device[len("qemupty:") :]) + self.serial = ProcessPtyToTerminal(device[len("execpty:") :]) elif device and device[0].isdigit() and device[-1].isdigit() and device.count(".") == 3: # device looks like an IP address self.serial = TelnetToSerial(device, user, password, read_timeout=10) @@ -264,7 +272,12 @@ def __init__( import serial.tools.list_ports # Set options, and exclusive if pyserial supports it - serial_kwargs = {"baudrate": baudrate, "interCharTimeout": 1} + serial_kwargs = { + "baudrate": baudrate, + "timeout": timeout, + "write_timeout": write_timeout, + "interCharTimeout": 1, + } if serial.__version__ >= "3.3": serial_kwargs["exclusive"] = exclusive @@ -304,14 +317,25 @@ def __init__( def close(self): self.serial.close() - def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): - # if data_consumer is used then data is not accumulated and the ending must be 1 byte long + def read_until( + self, min_num_bytes, ending, timeout=10, data_consumer=None, timeout_overall=None + ): + """ + min_num_bytes: Obsolete. + ending: Return if 'ending' matches. + timeout [s]: Return if timeout between characters. None: Infinite timeout. + timeout_overall [s]: Return not later than timeout_overall. None: Infinite timeout. + data_consumer: Use callback for incoming characters. + If data_consumer is used then data is not accumulated and the ending must be 1 byte long + + It is not visible to the caller why the function returned. It could be ending or timeout. + """ assert data_consumer is None or len(ending) == 1 + assert isinstance(timeout, (type(None), int, float)) + assert isinstance(timeout_overall, (type(None), int, float)) - data = self.serial.read(min_num_bytes) - if data_consumer: - data_consumer(data) - timeout_count = 0 + data = b"" + begin_overall_s = begin_char_s = time.monotonic() while True: if data.endswith(ending): break @@ -322,15 +346,25 @@ def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): data = new_data else: data = data + new_data - timeout_count = 0 + begin_char_s = time.monotonic() else: - timeout_count += 1 - if timeout is not None and timeout_count >= 100 * timeout: + if timeout is not None and time.monotonic() >= begin_char_s + timeout: + break + if ( + timeout_overall is not None + and time.monotonic() >= begin_overall_s + timeout_overall + ): break time.sleep(0.01) return data - def enter_raw_repl(self, soft_reset=True): + def enter_raw_repl(self, soft_reset=True, timeout_overall=10): + try: + self._enter_raw_repl_unprotected(soft_reset, timeout_overall) + except OSError as er: + raise PyboardError("could not enter raw repl: {}".format(er)) + + def _enter_raw_repl_unprotected(self, soft_reset, timeout_overall): self.serial.write(b"\r\x03") # ctrl-C: interrupt any running program # flush input (without relying on serial.flushInput()) @@ -342,7 +376,9 @@ def enter_raw_repl(self, soft_reset=True): self.serial.write(b"\r\x01") # ctrl-A: enter raw REPL if soft_reset: - data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n>") + data = self.read_until( + 1, b"raw REPL; CTRL-B to exit\r\n>", timeout_overall=timeout_overall + ) if not data.endswith(b"raw REPL; CTRL-B to exit\r\n>"): print(data) raise PyboardError("could not enter raw repl") @@ -352,12 +388,12 @@ def enter_raw_repl(self, soft_reset=True): # Waiting for "soft reboot" independently to "raw REPL" (done below) # allows boot.py to print, which will show up after "soft reboot" # and before "raw REPL". - data = self.read_until(1, b"soft reboot\r\n") + data = self.read_until(1, b"soft reboot\r\n", timeout_overall=timeout_overall) if not data.endswith(b"soft reboot\r\n"): print(data) raise PyboardError("could not enter raw repl") - data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n") + data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n", timeout_overall=timeout_overall) if not data.endswith(b"raw REPL; CTRL-B to exit\r\n"): print(data) raise PyboardError("could not enter raw repl") @@ -475,8 +511,8 @@ def eval(self, expression, parse=False): return ret # In Python3, call as pyboard.exec(), see the setattr call below. - def exec_(self, command, data_consumer=None): - ret, ret_err = self.exec_raw(command, data_consumer=data_consumer) + def exec_(self, command, timeout=10, data_consumer=None): + ret, ret_err = self.exec_raw(command, timeout, data_consumer) if ret_err: raise PyboardError("exception", ret, ret_err) return ret diff --git a/tools/pydfu.py b/tools/pydfu.py index cd7354818cd..376c697cbd5 100755 --- a/tools/pydfu.py +++ b/tools/pydfu.py @@ -11,8 +11,6 @@ See document UM0391 for a description of the DFuse file. """ -from __future__ import print_function - import argparse import collections import inspect @@ -75,11 +73,7 @@ # USB DFU interface __DFU_INTERFACE = 0 -# Python 3 deprecated getargspec in favour of getfullargspec, but -# Python 2 doesn't have the latter, so detect which one to use -getargspec = getattr(inspect, "getfullargspec", getattr(inspect, "getargspec", None)) - -if "length" in getargspec(usb.util.get_string).args: +if "length" in inspect.getfullargspec(usb.util.get_string).args: # PyUSB 1.0.0.b1 has the length argument def get_string(dev, index): return usb.util.get_string(dev, 255, index) diff --git a/tools/verifygitlog.py b/tools/verifygitlog.py index 67215d5c5d0..dba6ebd6de5 100755 --- a/tools/verifygitlog.py +++ b/tools/verifygitlog.py @@ -96,20 +96,47 @@ def verify_message_body(raw_body, err): if len(subject_line) >= 73: err.error("Subject line must be 72 or fewer characters: " + subject_line) + # Do additional checks on the prefix of the subject line. + verify_subject_line_prefix(subject_line.split(": ")[0], err) + # Second one divides subject and body. if len(raw_body) > 1 and raw_body[1]: err.error("Second message line must be empty: " + raw_body[1]) # Message body lines. for line in raw_body[2:]: - # Long lines with URLs are exempt from the line length rule. - if len(line) >= 76 and "://" not in line: + # Long lines with URLs or human names are exempt from the line length rule. + if len(line) >= 76 and not ( + "://" in line + or line.startswith("Co-authored-by: ") + or line.startswith("Signed-off-by: ") + ): err.error("Message lines should be 75 or less characters: " + line) if not raw_body[-1].startswith("Signed-off-by: ") or "@" not in raw_body[-1]: err.error('Message must be signed-off. Use "git commit -s".') +def verify_subject_line_prefix(prefix, err): + ext = (".c", ".h", ".cpp", ".js", ".rst", ".md") + + if prefix.startswith((".", "/")): + err.error('Subject prefix cannot begin with "." or "/".') + + if prefix.endswith("/"): + err.error('Subject prefix cannot end with "/".') + + if prefix.startswith("ports/"): + err.error( + 'Subject prefix cannot begin with "ports/", start with the name of the port instead.' + ) + + if prefix.endswith(ext): + err.error( + "Subject prefix cannot end with a file extension, use the main part of the filename without the extension." + ) + + def run(args): verbose("run", *args)