diff --git a/.circleci/config.yml b/.circleci/config.yml index 957f3979b110..fe4e6dabaffd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,11 +8,11 @@ parameters: distribution-scripts-version: description: "Git ref for version of https://github.com/crystal-lang/distribution-scripts/" type: string - default: "e15cbd3b6b3e1bac1b16905f1b1a15ba6ae4e554" + default: "535aedb8b09d77caaa1583700f371cd04343b7e8" previous_crystal_base_url: description: "Prefix for URLs to Crystal bootstrap compiler" type: string - default: "https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1" + default: "https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1" defaults: environment: &env @@ -39,7 +39,7 @@ defaults: jobs: test_linux: machine: - image: ubuntu-2004:202201-02 + image: default environment: <<: *env TRAVIS_OS_NAME: linux @@ -70,7 +70,7 @@ jobs: test_alpine: machine: - image: ubuntu-2004:202201-02 + image: default environment: <<: *env TRAVIS_OS_NAME: linux @@ -115,7 +115,8 @@ jobs: test_preview_mt: machine: - image: ubuntu-2004:202201-02 + image: default + resource_class: large environment: <<: *env TRAVIS_OS_NAME: linux @@ -263,7 +264,7 @@ jobs: dist_linux: machine: - image: ubuntu-2004:202201-02 + image: default steps: - attach_workspace: at: /tmp/workspace @@ -346,7 +347,7 @@ jobs: dist_docker: machine: - image: ubuntu-2004:202201-02 + image: default steps: - attach_workspace: at: /tmp/workspace @@ -362,7 +363,7 @@ jobs: publish_docker: machine: - image: ubuntu-2004:202201-02 + image: default steps: - attach_workspace: at: /tmp/workspace @@ -417,7 +418,7 @@ jobs: dist_docs: machine: - image: ubuntu-2004:202201-02 + image: default steps: - attach_workspace: at: /tmp/workspace @@ -463,7 +464,7 @@ jobs: test_dist_linux_on_docker: machine: - image: ubuntu-2004:202201-02 + image: default environment: <<: *env TRAVIS_OS_NAME: linux diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md index 756c4cfd2816..e6665a621eaa 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -10,3 +10,7 @@ labels: kind:feature - Describe the feature you would like, optionally illustrated by examples, and how it will solve the above problem. - Describe considered alternative solutions, and the reasons why you have not proposed them as a solution here. - Does it break backward compatibility, if yes then what's the migration path? + +In case this proposal includes a substantial change to the language, we ask you to go through an [RFC process](https://github.com/crystal-lang/rfcs). + +The best place to start an open discussion about potential changes is the [Crystal forum](https://forum.crystal-lang.org/c/crystal-contrib/6). diff --git a/.github/renovate.json b/.github/renovate.json index 4e18234dc0ec..39932ec1f648 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -12,5 +12,6 @@ "matchManagers": ["github-actions"], "schedule": ["after 5am and before 8am on Wednesday"] } - ] + ], + "labels": ["topic:infrastructure/ci"] } diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index 2671fe5d61d6..da252904fa37 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -18,7 +18,7 @@ jobs: with: args: make crystal - name: Upload Crystal executable - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: crystal-aarch64-musl path: | @@ -32,7 +32,7 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-aarch64-musl - name: Mark downloaded compiler as executable @@ -49,7 +49,7 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-aarch64-musl - name: Mark downloaded compiler as executable @@ -69,7 +69,7 @@ jobs: with: args: make crystal - name: Upload Crystal executable - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: crystal-aarch64-gnu path: | @@ -83,7 +83,7 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-aarch64-gnu - name: Mark downloaded compiler as executable @@ -100,7 +100,7 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-aarch64-gnu - name: Mark downloaded compiler as executable diff --git a/.github/workflows/interpreter.yml b/.github/workflows/interpreter.yml index bf9dc3808479..81b7b8ec05ba 100644 --- a/.github/workflows/interpreter.yml +++ b/.github/workflows/interpreter.yml @@ -13,7 +13,7 @@ jobs: test-interpreter_spec: runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.10.1-build + image: crystallang/crystal:1.11.2-build name: "Test Interpreter" steps: - uses: actions/checkout@v4 @@ -24,7 +24,7 @@ jobs: build-interpreter: runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.10.1-build + image: crystallang/crystal:1.11.2-build name: Build interpreter steps: - uses: actions/checkout@v4 @@ -33,7 +33,7 @@ jobs: run: make interpreter=1 release=1 - name: Upload compiler artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: crystal-interpreter path: | @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 15 container: - image: crystallang/crystal:1.10.1-build + image: crystallang/crystal:1.11.2-build strategy: matrix: part: [0, 1, 2, 3] @@ -53,7 +53,7 @@ jobs: - uses: actions/checkout@v4 - name: Download compiler artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-interpreter path: .build/ diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 9ef73a9fe23c..3d85af22e5a3 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1] + crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1, 1.11.2] flags: [""] include: # libffi is only available starting from the 1.2.2 build images diff --git a/.github/workflows/llvm.yml b/.github/workflows/llvm.yml index f361896768d8..887ede290fe3 100644 --- a/.github/workflows/llvm.yml +++ b/.github/workflows/llvm.yml @@ -33,7 +33,7 @@ jobs: - name: Cache LLVM id: cache-llvm - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ./llvm key: llvm-${{ matrix.llvm_version }} @@ -56,7 +56,7 @@ jobs: - name: Install Crystal uses: crystal-lang/install-crystal@v1 with: - crystal: "1.10.1" + crystal: "1.11.2" - name: Build libllvm_ext run: make -B deps diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index dbab5f5bc93c..765595ce2d09 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -17,12 +17,12 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v24 + - uses: cachix/install-nix-action@v25 with: install_url: https://releases.nixos.org/nix/nix-2.9.2/install extra_nix_config: | experimental-features = nix-command - - uses: cachix/cachix-action@v13 + - uses: cachix/cachix-action@v14 with: name: crystal-ci signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' diff --git a/.github/workflows/openssl.yml b/.github/workflows/openssl.yml index 07e2d7e94558..65766c6325c2 100644 --- a/.github/workflows/openssl.yml +++ b/.github/workflows/openssl.yml @@ -10,7 +10,7 @@ jobs: openssl3: runs-on: ubuntu-latest name: "OpenSSL 3.0" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -27,7 +27,7 @@ jobs: openssl111: runs-on: ubuntu-latest name: "OpenSSL 1.1.1" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -42,7 +42,7 @@ jobs: libressl34: runs-on: ubuntu-latest name: "LibreSSL 3.4" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/regex-engine.yml b/.github/workflows/regex-engine.yml index a7ad3afbbb65..d7d9c2655584 100644 --- a/.github/workflows/regex-engine.yml +++ b/.github/workflows/regex-engine.yml @@ -10,7 +10,7 @@ jobs: pcre: runs-on: ubuntu-latest name: "PCRE" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -25,7 +25,7 @@ jobs: pcre2: runs-on: ubuntu-latest name: "PCRE2" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/wasm32.yml b/.github/workflows/wasm32.yml index 0d4f32f4c044..c8f2058ebea0 100644 --- a/.github/workflows/wasm32.yml +++ b/.github/workflows/wasm32.yml @@ -12,7 +12,7 @@ env: jobs: wasm32-test: runs-on: ubuntu-latest - container: crystallang/crystal:1.10.1-build + container: crystallang/crystal:1.11.2-build steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index 90ed0e0c980d..3ef4cccb8739 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -7,7 +7,7 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: - CI_LLVM_VERSION: "17.0.2" + CI_LLVM_VERSION: "18.1.0-rc1" jobs: x86_64-windows-libs: @@ -18,14 +18,14 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Download Crystal source uses: actions/checkout@v4 - name: Cache libraries id: cache-libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | # openssl and llvm take much longer to build so they are cached separately libs/pcre.lib @@ -68,7 +68,7 @@ jobs: - name: Cache OpenSSL id: cache-openssl - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | libs/crypto.lib @@ -77,7 +77,7 @@ jobs: key: win-openssl-libs-3.1.0-${{ hashFiles('etc/win-ci/build-openssl.ps1') }}-msvc - name: Set up NASM if: steps.cache-openssl.outputs.cache-hit != 'true' - uses: ilammy/setup-nasm@321e6ed62a1fc77024a3bd853deb33645e8b22c4 # v1.4.0 + uses: ilammy/setup-nasm@13cbeb366c45c4379d3478cdcbadd8295feb5028 # v1.5.1 - name: Build OpenSSL if: steps.cache-openssl.outputs.cache-hit != 'true' run: .\etc\win-ci\build-openssl.ps1 -BuildTree deps\openssl -Version 3.1.0 @@ -90,14 +90,14 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Download Crystal source uses: actions/checkout@v4 - name: Cache libraries id: cache-dlls - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | # openssl and llvm take much longer to build so they are cached separately libs/pcre-dynamic.lib @@ -149,7 +149,7 @@ jobs: - name: Cache OpenSSL id: cache-openssl-dlls - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | libs/crypto-dynamic.lib @@ -159,7 +159,7 @@ jobs: key: win-openssl-dlls-3.1.0-${{ hashFiles('etc/win-ci/build-openssl.ps1') }}-msvc - name: Set up NASM if: steps.cache-openssl-dlls.outputs.cache-hit != 'true' - uses: ilammy/setup-nasm@321e6ed62a1fc77024a3bd853deb33645e8b22c4 # v1.4.0 + uses: ilammy/setup-nasm@13cbeb366c45c4379d3478cdcbadd8295feb5028 # v1.5.1 - name: Build OpenSSL if: steps.cache-openssl-dlls.outputs.cache-hit != 'true' run: .\etc\win-ci\build-openssl.ps1 -BuildTree deps\openssl -Version 3.1.0 -Dynamic @@ -168,39 +168,22 @@ jobs: runs-on: windows-2022 steps: - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Cache LLVM id: cache-llvm-libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: llvm key: llvm-libs-${{ env.CI_LLVM_VERSION }}-msvc - - name: Download LLVM - if: steps.cache-llvm-libs.outputs.cache-hit != 'true' - run: | - iwr https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ env.CI_LLVM_VERSION }}/llvm-${{ env.CI_LLVM_VERSION }}.src.tar.xz -OutFile llvm.tar.xz - (Get-FileHash -Algorithm SHA256 .\llvm.tar.xz).hash -eq "D820E63BC3A6F4F833EC69A1EF49A2E81992E90BC23989F98946914B061AB6C7" - 7z x llvm.tar.xz - 7z x llvm.tar - mv llvm-* llvm-src - - - name: Download LLVM's CMake files - if: steps.cache-llvm-libs.outputs.cache-hit != 'true' - run: | - iwr https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ env.CI_LLVM_VERSION }}/cmake-${{ env.CI_LLVM_VERSION }}.src.tar.xz -OutFile cmake.tar.xz - (Get-FileHash -Algorithm SHA256 .\cmake.tar.xz).hash -eq "B6D83C91F12757030D8361DEDC5DD84357B3EDB8DA406B5D0850DF8B6F7798B1" - 7z x cmake.tar.xz - 7z x cmake.tar - mv cmake-* cmake - - name: Build LLVM if: steps.cache-llvm-libs.outputs.cache-hit != 'true' run: | + git clone --config core.autocrlf=false -b llvmorg-${{ env.CI_LLVM_VERSION }} --depth 1 https://github.com/llvm/llvm-project.git mkdir llvm-build cd llvm-build - cmake ..\llvm-src -Thost=x64 -DLLVM_TARGETS_TO_BUILD="X86;AArch64" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DBUILD_SHARED_LIBS=OFF -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_ZSTD=OFF + cmake ..\llvm-project\llvm -Thost=x64 -DLLVM_TARGETS_TO_BUILD="X86;AArch64" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DBUILD_SHARED_LIBS=OFF -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_ZSTD=OFF cmake --build . --config Release cmake "-DCMAKE_INSTALL_PREFIX=$(pwd)\..\llvm" -P cmake_install.cmake @@ -212,14 +195,14 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Download Crystal source uses: actions/checkout@v4 - name: Cache LLVM id: cache-llvm-dlls - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | libs/llvm_VERSION @@ -235,7 +218,7 @@ jobs: uses: ./.github/workflows/win_build_portable.yml with: release: false - llvm_version: "17.0.2" + llvm_version: "18.1.0-rc1" x86_64-windows-test: runs-on: windows-2022 @@ -246,19 +229,19 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Download Crystal source uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal path: build - name: Restore LLVM - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: llvm key: llvm-libs-${{ env.CI_LLVM_VERSION }}-msvc @@ -288,7 +271,7 @@ jobs: uses: ./.github/workflows/win_build_portable.yml with: release: true - llvm_version: "17.0.2" + llvm_version: "18.1.0-rc1" x86_64-windows-installer: if: github.repository_owner == 'crystal-lang' && (startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/ci/')) @@ -303,13 +286,13 @@ jobs: uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-release path: etc/win-ci/portable - name: Restore LLVM - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: llvm key: llvm-libs-${{ env.CI_LLVM_VERSION }}-msvc @@ -329,7 +312,7 @@ jobs: iscc.exe crystal.iss - name: Upload Crystal installer - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: crystal-installer path: etc/win-ci/Output/crystal-setup.exe diff --git a/.github/workflows/win_build_portable.yml b/.github/workflows/win_build_portable.yml index 18eea4f1f317..bab89e04685e 100644 --- a/.github/workflows/win_build_portable.yml +++ b/.github/workflows/win_build_portable.yml @@ -19,18 +19,18 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Install Crystal uses: crystal-lang/install-crystal@v1 with: - crystal: "1.10.1" + crystal: "1.11.2" - name: Download Crystal source uses: actions/checkout@v4 - name: Restore libraries - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/pcre.lib @@ -45,7 +45,7 @@ jobs: key: win-libs-${{ hashFiles('.github/workflows/win.yml', 'etc/win-ci/*.ps1') }}-msvc fail-on-cache-miss: true - name: Restore OpenSSL - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/crypto.lib @@ -54,7 +54,7 @@ jobs: key: win-openssl-libs-3.1.0-${{ hashFiles('etc/win-ci/build-openssl.ps1') }}-msvc fail-on-cache-miss: true - name: Restore DLLs - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/pcre-dynamic.lib @@ -78,7 +78,7 @@ jobs: key: win-dlls-${{ hashFiles('.github/workflows/win.yml', 'etc/win-ci/*.ps1') }}-msvc fail-on-cache-miss: true - name: Restore OpenSSL DLLs - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/crypto-dynamic.lib @@ -88,13 +88,13 @@ jobs: key: win-openssl-dlls-3.1.0-${{ hashFiles('etc/win-ci/build-openssl.ps1') }}-msvc fail-on-cache-miss: true - name: Restore LLVM - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: llvm key: llvm-libs-${{ inputs.llvm_version }}-msvc fail-on-cache-miss: true - name: Restore LLVM DLLs - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/llvm_VERSION @@ -120,7 +120,7 @@ jobs: uses: actions/checkout@v4 with: repository: crystal-lang/shards - ref: v0.17.3 + ref: v0.17.4 path: shards - name: Download molinillo release @@ -144,7 +144,7 @@ jobs: cp README.md crystal/ - name: Upload Crystal binaries - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ inputs.release && 'crystal-release' || 'crystal' }} path: crystal diff --git a/.gitignore b/.gitignore index 5d74450c533f..987e8a649620 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # Build artifacts /.build/ +/samples/.build/ /docs/ /src/llvm/ext/llvm_ext.o /src/llvm/ext/llvm_ext.obj diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d2c17878c9d..4e152e9ad2d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,297 @@ # Changelog +## [1.11.2] (2024-01-18) + +[1.11.2]: https://github.com/crystal-lang/crystal/releases/1.11.2 + +### Bugfixes + +#### stdlib + +- *(files)* Fix missing `cause` parameter from `IO::Error#initialize` ([#14242](https://github.com/crystal-lang/crystal/pull/14242), thanks @straight-shoota) +- *(runtime)* Always use `%p` for pointers in `Crystal::System.print_error` ([#14186](https://github.com/crystal-lang/crystal/pull/14186), thanks @HertzDevil) +- *(runtime)* Fixup for always use `%p` for pointers in `Crystal::System.print_error` ([#14221](https://github.com/crystal-lang/crystal/pull/14221), thanks @HertzDevil) + +### Infrastructure + +- Changelog for 1.11.2 ([#14249](https://github.com/crystal-lang/crystal/pull/14249), thanks @straight-shoota) + +## [1.11.1] (2024-01-11) + +[1.11.1]: https://github.com/crystal-lang/crystal/releases/1.11.1 + +### Bugfixes + +#### stdlib + +- *(crypto)* Revert "Fix OpenSSL error handling for EOF (support for OpenSSL 3.2) (#14169)" ([#14217](https://github.com/crystal-lang/crystal/pull/14217), thanks @straight-shoota) + +#### compiler + +- *(interpreter)* Remove pkg-config name for libgc as workaround for interpreter loader ([#14198](https://github.com/crystal-lang/crystal/pull/14198), thanks @straight-shoota) +- *(semantic)* Revert "Add `ReferenceStorage` for manual allocation of references (#14106)" ([#14207](https://github.com/crystal-lang/crystal/pull/14207), thanks @straight-shoota) + +### Infrastructure + +- Changelog for 1.11.1 ([#14208](https://github.com/crystal-lang/crystal/pull/14208), thanks @straight-shoota) +- Bump VERSION to 1.11.1-dev ([#14197](https://github.com/crystal-lang/crystal/pull/14197), thanks @straight-shoota) + +## [1.11.0] (2024-01-08) + +[1.11.0]: https://github.com/crystal-lang/crystal/releases/1.11.0 + +### Features + +#### lang + +- **[breaking]** Support `alignof` and `instance_alignof` ([#14087](https://github.com/crystal-lang/crystal/pull/14087), thanks @HertzDevil) +- *(annotations)* Support `dll` parameter in `@[Link]` ([#14131](https://github.com/crystal-lang/crystal/pull/14131), thanks @HertzDevil) +- *(macros)* Expose macro `Call` context via new `@caller` macro ivar ([#14048](https://github.com/crystal-lang/crystal/pull/14048), thanks @Blacksmoke16) + +#### stdlib + +- *(collection)* Add `Enumerable#present?` ([#13866](https://github.com/crystal-lang/crystal/pull/13866), thanks @straight-shoota) +- *(collection)* Add `Enumerable#each_step` and `Iterable#each_step` ([#13610](https://github.com/crystal-lang/crystal/pull/13610), thanks @baseballlover723) +- *(collection)* Add `Enumerable(T)#to_set(& : T -> U) : Set(U) forall U` ([#12654](https://github.com/crystal-lang/crystal/pull/12654), thanks @caspiano) +- *(collection)* Add `Enumerable(T)#to_a(& : T -> U) forall U` ([#12653](https://github.com/crystal-lang/crystal/pull/12653), thanks @caspiano) +- *(files)* Add `IO::Error#target` ([#13865](https://github.com/crystal-lang/crystal/pull/13865), thanks @straight-shoota) +- *(llvm)* Add `LLVM::OperandBundleDef#dispose` ([#14095](https://github.com/crystal-lang/crystal/pull/14095), thanks @HertzDevil) +- *(llvm)* Windows: Use local configuration for LLVM when linking dynamically ([#14101](https://github.com/crystal-lang/crystal/pull/14101), thanks @HertzDevil) +- *(macros)* Add `CharLiteral#ord` ([#13910](https://github.com/crystal-lang/crystal/pull/13910), thanks @refi64) +- *(macros)* Add macro methods for `MacroIf` and `MacroFor` nodes ([#13902](https://github.com/crystal-lang/crystal/pull/13902), thanks @sbsoftware) +- *(macros)* Expose doc comments on `ASTNode` when generating docs ([#14050](https://github.com/crystal-lang/crystal/pull/14050), thanks @Blacksmoke16) +- *(macros)* Add macro methods for `ModuleDef` ([#14063](https://github.com/crystal-lang/crystal/pull/14063), thanks @HertzDevil) +- *(macros)* Add macro methods for `Include` and `Extend` ([#14064](https://github.com/crystal-lang/crystal/pull/14064), thanks @HertzDevil) +- *(macros)* Add macro methods for `ClassDef`, `EnumDef`, `AnnotationDef` ([#14072](https://github.com/crystal-lang/crystal/pull/14072), thanks @HertzDevil) +- *(numeric)* Implement `BigRational`'s rounding modes ([#13871](https://github.com/crystal-lang/crystal/pull/13871), thanks @HertzDevil) +- *(numeric)* Support full exponent range in `BigFloat#**(BigInt)` ([#13881](https://github.com/crystal-lang/crystal/pull/13881), thanks @HertzDevil) +- *(numeric)* Add `Math.fma` ([#13934](https://github.com/crystal-lang/crystal/pull/13934), thanks @HertzDevil) +- *(numeric)* Add `Number#integer?` ([#13936](https://github.com/crystal-lang/crystal/pull/13936), thanks @HertzDevil) +- *(numeric)* Publish `Int::Primitive#abs_unsigned` and `#neg_signed` ([#13938](https://github.com/crystal-lang/crystal/pull/13938), thanks @HertzDevil) +- *(numeric)* Add `Int::Primitive#to_signed`, `#to_signed!`, `#to_unsigned`, `#to_unsigned!` ([#13960](https://github.com/crystal-lang/crystal/pull/13960), thanks @HertzDevil) +- *(numeric)* Support `BigFloat#**` for all `Int::Primitive` arguments ([#13971](https://github.com/crystal-lang/crystal/pull/13971), thanks @HertzDevil) +- *(numeric)* Add `Float32::MIN_SUBNORMAL` and `Float64::MIN_SUBNORMAL` ([#13961](https://github.com/crystal-lang/crystal/pull/13961), thanks @HertzDevil) +- *(numeric)* Add `Float::Primitive.parse_hexfloat`, `.parse_hexfloat?`, `#to_hexfloat` ([#14027](https://github.com/crystal-lang/crystal/pull/14027), thanks @HertzDevil) +- *(numeric)* Implement `sprintf "%f"` in Crystal using Ryu Printf ([#14067](https://github.com/crystal-lang/crystal/pull/14067), thanks @HertzDevil) +- *(numeric)* Implement `sprintf "%e"` in Crystal ([#14084](https://github.com/crystal-lang/crystal/pull/14084), thanks @HertzDevil) +- *(numeric)* Implement `sprintf "%a"` in Crystal ([#14102](https://github.com/crystal-lang/crystal/pull/14102), thanks @HertzDevil) +- *(numeric)* Implement `sprintf "%g"` in Crystal ([#14123](https://github.com/crystal-lang/crystal/pull/14123), thanks @HertzDevil) +- *(runtime)* Add `Crystal::HOST_TRIPLE` and `TARGET_TRIPLE` ([#13823](https://github.com/crystal-lang/crystal/pull/13823), thanks @HertzDevil) +- *(runtime)* **[experimental]** Add `Reference.pre_initialize` and `.unsafe_construct` ([#14108](https://github.com/crystal-lang/crystal/pull/14108), thanks @HertzDevil) +- *(runtime)* **[experimental]** Add `ReferenceStorage` for manual allocation of references ([#14106](https://github.com/crystal-lang/crystal/pull/14106), thanks @HertzDevil) +- *(serialization)* Fix `StaticArray#to_json` ([#14104](https://github.com/crystal-lang/crystal/pull/14104), thanks @Vendicated) +- *(specs)* Add `crystal spec --dry-run` ([#13804](https://github.com/crystal-lang/crystal/pull/13804), thanks @nobodywasishere) +- *(specs)* Add `crystal spec --list-tags` ([#13616](https://github.com/crystal-lang/crystal/pull/13616), thanks @baseballlover723) +- *(system)* Respect Windows `Path` directory separators in `File.match?` ([#13912](https://github.com/crystal-lang/crystal/pull/13912), thanks @HertzDevil) +- *(text)* Support Unicode 15.1.0 ([#13812](https://github.com/crystal-lang/crystal/pull/13812), thanks @HertzDevil) +- *(text)* Add `UUID.v1`, `.v2`, `.v3`, `.v4`, `.v5` ([#13693](https://github.com/crystal-lang/crystal/pull/13693), thanks @threez) +- *(text)* Add `String` and `Char` patterns to `StringScanner` ([#13806](https://github.com/crystal-lang/crystal/pull/13806), thanks @funny-falcon) +- *(text)* Add `EOL`constant (End-Of-Line) ([#11303](https://github.com/crystal-lang/crystal/pull/11303), thanks @postmodern) +- *(text)* Add `Char::Reader#current_char?`, `#next_char?`, `#previous_char?` ([#14012](https://github.com/crystal-lang/crystal/pull/14012), thanks @HertzDevil) +- *(text)* Add `String#matches_full?` ([#13968](https://github.com/crystal-lang/crystal/pull/13968), thanks @straight-shoota) +- *(text)* Change `Regex::MatchData#to_s` to return matched substring ([#14115](https://github.com/crystal-lang/crystal/pull/14115), thanks @Vendicated) + +#### compiler + +- *(codegen)* Add incremental optimization levels ([#13464](https://github.com/crystal-lang/crystal/pull/13464), thanks @kostya) +- *(debugger)* Support debug information for 64-bit or unsigned enums ([#14081](https://github.com/crystal-lang/crystal/pull/14081), thanks @HertzDevil) +- *(interpreter)* Support `instance_sizeof(T)` in the interpreter ([#14031](https://github.com/crystal-lang/crystal/pull/14031), thanks @HertzDevil) +- *(interpreter)* Support `-dynamic.lib` in Windows interpreter ([#14143](https://github.com/crystal-lang/crystal/pull/14143), thanks @HertzDevil) +- *(interpreter)* Support absolute paths in `CRYSTAL_INTERPRETER_LOADER_INFO` ([#14147](https://github.com/crystal-lang/crystal/pull/14147), thanks @HertzDevil) +- *(interpreter)* Add `Crystal::Repl#parse_and_interpret` ([#14138](https://github.com/crystal-lang/crystal/pull/14138), thanks @bcardiff) +- *(semantic)* Change short_reference for top-level methods to `::foo` ([#14071](https://github.com/crystal-lang/crystal/pull/14071), thanks @keshavbiswa) + +#### tools + +- *(docs-generator)* Expose inherited macros in generated API docs ([#13810](https://github.com/crystal-lang/crystal/pull/13810), thanks @Blacksmoke16) +- *(docs-generator)* Order macros below class methods in generated docs ([#14024](https://github.com/crystal-lang/crystal/pull/14024), thanks @Blacksmoke16) +- *(formatter)* Do not remove trailing comma from multi-line macro/def parameters (not yet enabled) ([#14075](https://github.com/crystal-lang/crystal/pull/14075), thanks @Blacksmoke16) +- *(unreachable)* Add `--check` flag to `crystal tool unreachable` ([#13930](https://github.com/crystal-lang/crystal/pull/13930), thanks @straight-shoota) +- *(unreachable)* Add annotations to output of `crystal tool unreachable` ([#13927](https://github.com/crystal-lang/crystal/pull/13927), thanks @straight-shoota) +- *(unreachable)* Print relative paths in `crystal tool unreachable` ([#13929](https://github.com/crystal-lang/crystal/pull/13929), thanks @straight-shoota) +- *(unreachable)* Add CSV output format to `crystal tool unreachable` ([#13926](https://github.com/crystal-lang/crystal/pull/13926), thanks @straight-shoota) +- *(unreachable)* Add `--tallies` option to `crystal tool unreachable` ([#13969](https://github.com/crystal-lang/crystal/pull/13969), thanks @straight-shoota) + +### Bugfixes + +#### stdlib + +- Fix `Box(T?)` crashing on `nil` ([#13893](https://github.com/crystal-lang/crystal/pull/13893), thanks @HertzDevil) +- Fix typos in src ([#14053](https://github.com/crystal-lang/crystal/pull/14053), thanks @kojix2) +- *(collection)* Fix `Indexable#each_repeated_combination(n)` when `n > size` ([#14092](https://github.com/crystal-lang/crystal/pull/14092), thanks @HertzDevil) +- *(concurrency)* Make `Process#wait` asynchronous on Windows ([#13908](https://github.com/crystal-lang/crystal/pull/13908), thanks @HertzDevil) +- *(concurrency)* Fix math overflow after spawning `Int32::MAX + 1` fibers ([#14096](https://github.com/crystal-lang/crystal/pull/14096), thanks @ysbaddaden) +- *(concurrency)* Fix `can't resume a running fiber` ([#14128](https://github.com/crystal-lang/crystal/pull/14128), thanks @ysbaddaden) +- *(crypto)* Fix OpenSSL error handling for EOF (support for OpenSSL 3.2) ([#14169](https://github.com/crystal-lang/crystal/pull/14169), thanks @straight-shoota) +- *(files)* Fix `Globber.constant_entry?` matching patterns ([#13955](https://github.com/crystal-lang/crystal/pull/13955), thanks @GeopJr) +- *(files)* Fix `String::Buffer` and `IO::Memory` capacity to grow beyond 1GB ([#13989](https://github.com/crystal-lang/crystal/pull/13989), thanks @straight-shoota) +- *(llvm)* Fix a typo ([#13914](https://github.com/crystal-lang/crystal/pull/13914), thanks @kojix2) +- *(numeric)* Make `String#to_f(whitespace: false)` work with infinity and NaN ([#13875](https://github.com/crystal-lang/crystal/pull/13875), thanks @HertzDevil) +- *(numeric)* Use `LibGMP::SI` and `UI` for size checks, not `Long` and `ULong` ([#13874](https://github.com/crystal-lang/crystal/pull/13874), thanks @HertzDevil) +- *(numeric)* Fix integral part extraction in `Number#format` ([#14061](https://github.com/crystal-lang/crystal/pull/14061), thanks @HertzDevil) +- *(numeric)* Fix out-of-bounds access in `Int128::MIN.to_s(base: 2)` ([#14119](https://github.com/crystal-lang/crystal/pull/14119), thanks @HertzDevil) +- *(numeric)* Avoid double rounding in `Float#format` for nonnegative `decimal_place` ([#14129](https://github.com/crystal-lang/crystal/pull/14129), thanks @HertzDevil) +- *(runtime)* Avoid `@[ThreadLocal]` on Android ([#14025](https://github.com/crystal-lang/crystal/pull/14025), thanks @HertzDevil) +- *(runtime)* Never use string interpolation in `Crystal::System.print_error` ([#14114](https://github.com/crystal-lang/crystal/pull/14114), thanks @HertzDevil) +- *(runtime)* Fix segfault with next boehm gc (after v8.2.4) ([#14130](https://github.com/crystal-lang/crystal/pull/14130), thanks @ysbaddaden) +- *(specs)* Skip spec execution on error exit ([#13986](https://github.com/crystal-lang/crystal/pull/13986), thanks @straight-shoota) +- *(system)* Fix `FileUtils.ln_sf` to override special file types ([#13896](https://github.com/crystal-lang/crystal/pull/13896), thanks @straight-shoota) +- *(system)* Fix `Process.exists?` throwing errors on EPERM ([#13911](https://github.com/crystal-lang/crystal/pull/13911), thanks @refi64) +- *(system)* Fix portable shell command arguments in `Process#prepare_args` ([#13942](https://github.com/crystal-lang/crystal/pull/13942), thanks @GeopJr) +- *(system)* Windows: Do not close process handle in `Process#close` ([#13997](https://github.com/crystal-lang/crystal/pull/13997), thanks @HertzDevil) +- *(system)* Windows: clear `Crystal::System::Process#@completion_key` after use ([#14068](https://github.com/crystal-lang/crystal/pull/14068), thanks @HertzDevil) +- *(system)* Fix UTF-8 console input on Windows ([#13758](https://github.com/crystal-lang/crystal/pull/13758), thanks @erdian718) +- *(text)* Fix invalid UTF-8 handling in `Char::Reader#previous_char` ([#14013](https://github.com/crystal-lang/crystal/pull/14013), thanks @HertzDevil) +- *(text)* Fix `options` parameter for `String#split`, `#scan` ([#14183](https://github.com/crystal-lang/crystal/pull/14183), thanks @straight-shoota) +- *(time)* Fix time span overflow on `Int#milliseconds` and `Int#microseconds` ([#14105](https://github.com/crystal-lang/crystal/pull/14105), thanks @bcardiff) + +#### compiler + +- *(cli)* Remove unnecessary file check for CLI arguments ([#13853](https://github.com/crystal-lang/crystal/pull/13853), thanks @straight-shoota) +- *(cli)* Check for invalid integers in compiler's CLI ([#13959](https://github.com/crystal-lang/crystal/pull/13959), thanks @HertzDevil) +- *(cli)* Fix compiler error message for invalid source file ([#14157](https://github.com/crystal-lang/crystal/pull/14157), thanks @straight-shoota) +- *(codegen)* Fix a typo in compiler source ([#14054](https://github.com/crystal-lang/crystal/pull/14054), thanks @kojix2) +- *(codegen)* Fix codegen error when discarding `is_a?` or `responds_to?`'s result ([#14148](https://github.com/crystal-lang/crystal/pull/14148), thanks @HertzDevil) +- *(interpreter)* Fix element alignment of `Tuple` and `NamedTuple` casts ([#14040](https://github.com/crystal-lang/crystal/pull/14040), thanks @HertzDevil) +- *(interpreter)* `Crystal::Loader`: Skip second linker member on Windows if absent ([#14111](https://github.com/crystal-lang/crystal/pull/14111), thanks @HertzDevil) +- *(parser)* Support `%r` and `%x` when not followed by delimiter start ([#13933](https://github.com/crystal-lang/crystal/pull/13933), thanks @HertzDevil) +- *(parser)* Fix location of global `Path` nodes in certain constructs ([#13932](https://github.com/crystal-lang/crystal/pull/13932), thanks @HertzDevil) +- *(parser)* Fix `ToSVisitor` for expanded string interpolation in backticks ([#13943](https://github.com/crystal-lang/crystal/pull/13943), thanks @straight-shoota) +- *(parser)* Fix location for "invalid trailing comma in call" errors ([#13964](https://github.com/crystal-lang/crystal/pull/13964), thanks @HertzDevil) +- *(semantic)* Fix check for file type ([#13760](https://github.com/crystal-lang/crystal/pull/13760), thanks @straight-shoota) +- *(semantic)* Fix private type definitions with namespaced `Path`s ([#13931](https://github.com/crystal-lang/crystal/pull/13931), thanks @HertzDevil) +- *(semantic)* Fix missing param count in compilation error message ([#13985](https://github.com/crystal-lang/crystal/pull/13985), thanks @koffeinfrei) +- *(semantic)* Fix `ReadInstanceVar` on typedefs ([#14044](https://github.com/crystal-lang/crystal/pull/14044), thanks @HertzDevil) +- *(semantic)* Fix global `Path` lookup inside macro when def has free variables ([#14073](https://github.com/crystal-lang/crystal/pull/14073), thanks @HertzDevil) +- *(semantic)* Add location information to implicit flag enum members ([#14127](https://github.com/crystal-lang/crystal/pull/14127), thanks @Blacksmoke16) + +#### tools + +- *(docs-generator)* Fix `crystal docs` check `File.exists?` for `shard.yml` ([#13937](https://github.com/crystal-lang/crystal/pull/13937), thanks @straight-shoota) +- *(docs-generator)* Fix version sorting in API docs ([#13994](https://github.com/crystal-lang/crystal/pull/13994), thanks @m-o-e) +- *(docs-generator)* Strip whitespace in doc comment before determining summary line ([#14049](https://github.com/crystal-lang/crystal/pull/14049), thanks @Blacksmoke16) +- *(docs-generator)* Skip `Crystal::Macros` unless generating docs ([#13970](https://github.com/crystal-lang/crystal/pull/13970), thanks @straight-shoota) +- *(init)* Fix tool init error message when target exists but not a dir ([#13869](https://github.com/crystal-lang/crystal/pull/13869), thanks @straight-shoota) +- *(unreachable)* Fix infinite recursion of expanded nodes in `UnreachableVisitor` ([#13922](https://github.com/crystal-lang/crystal/pull/13922), thanks @straight-shoota) + +### Chores + +#### lang + +- *(macros)* **[deprecation]** Deprecate the splat operators in macro expressions ([#13939](https://github.com/crystal-lang/crystal/pull/13939), thanks @HertzDevil) + +#### stdlib + +- *(llvm)* **[deprecation]** Deprecate `LLVM.start_multithreaded` and `.stop_multithreaded` ([#13949](https://github.com/crystal-lang/crystal/pull/13949), thanks @HertzDevil) + +### Performance + +#### stdlib + +- *(concurrency)* Skip indirections in `Crystal::Scheduler` ([#14098](https://github.com/crystal-lang/crystal/pull/14098), thanks @ysbaddaden) +- *(numeric)* Optimize `BigInt#&`, `#|`, `#^` with `Int::Primitive` arguments ([#14006](https://github.com/crystal-lang/crystal/pull/14006), thanks @HertzDevil) +- *(numeric)* Optimize `BigInt#bit` ([#13980](https://github.com/crystal-lang/crystal/pull/13980), thanks @HertzDevil) +- *(numeric)* Use `#trailing_zeros_count` in `Int#gcd` ([#14069](https://github.com/crystal-lang/crystal/pull/14069), thanks @HertzDevil) +- *(serialization)* Optimize `JSON::Builder#string` with byte-based algorithm ([#13915](https://github.com/crystal-lang/crystal/pull/13915), thanks @straight-shoota) +- *(serialization)* Improve performance of `JSON::Builder#string` with direct stringification ([#13950](https://github.com/crystal-lang/crystal/pull/13950), thanks @straight-shoota) +- *(text)* Refactor `HTML.unescape` in native Crystal ([#13844](https://github.com/crystal-lang/crystal/pull/13844), thanks @straight-shoota) +- *(text)* Refactor some uses of the blockless `String#split` ([#14001](https://github.com/crystal-lang/crystal/pull/14001), thanks @HertzDevil) + +### Refactor + +#### stdlib + +- *(concurrency)* Add `Crystal::System::Thread` ([#13814](https://github.com/crystal-lang/crystal/pull/13814), thanks @HertzDevil) +- *(concurrency)* Move `Thread#set_current_thread` to `Fiber` ([#14099](https://github.com/crystal-lang/crystal/pull/14099), thanks @ysbaddaden) +- *(files)* Use `IO.copy` in `IO#gets_to_end` ([#13990](https://github.com/crystal-lang/crystal/pull/13990), thanks @straight-shoota) +- *(files)* Do not use `pointerof(Path)` in the standard library ([#14144](https://github.com/crystal-lang/crystal/pull/14144), thanks @HertzDevil) +- *(llvm)* **[deprecation]** Remove `LLVMExtSetCurrentDebugLocation` from `llvm_ext.cc` for LLVM 9+ ([#13965](https://github.com/crystal-lang/crystal/pull/13965), thanks @HertzDevil) +- *(llvm)* Replace some deprecated LLVM bindings ([#13953](https://github.com/crystal-lang/crystal/pull/13953), thanks @HertzDevil) +- *(llvm)* Split `LibLLVM` by C headers ([#13948](https://github.com/crystal-lang/crystal/pull/13948), thanks @HertzDevil) +- *(llvm)* Support `LLVMSetTargetMachineGlobalISel` from LLVM 18 ([#14079](https://github.com/crystal-lang/crystal/pull/14079), thanks @HertzDevil) +- *(llvm)* Support the operand bundle API from LLVM 18 ([#14082](https://github.com/crystal-lang/crystal/pull/14082), thanks @HertzDevil) +- *(numeric)* Simplify `String::Formatter` when Ryu Printf is available ([#14132](https://github.com/crystal-lang/crystal/pull/14132), thanks @HertzDevil) +- *(runtime)* Implement most of `Crystal::System.print_error` in native Crystal ([#14116](https://github.com/crystal-lang/crystal/pull/14116), thanks @HertzDevil) +- *(text)* Drop `Char::Reader#@end` ([#13920](https://github.com/crystal-lang/crystal/pull/13920), thanks @straight-shoota) +- *(text)* Generate `src/html/entities.cr` automatically ([#13998](https://github.com/crystal-lang/crystal/pull/13998), thanks @HertzDevil) +- *(time)* Refactor leap year to use `divisible_by?` ([#13982](https://github.com/crystal-lang/crystal/pull/13982), thanks @meatball133) + +#### compiler + +- Remove relative path to vendored shards `markd` and `reply` ([#13992](https://github.com/crystal-lang/crystal/pull/13992), thanks @nobodywasishere) +- *(cli)* Generalize allowed values for compiler CLI `--format` option ([#13940](https://github.com/crystal-lang/crystal/pull/13940), thanks @straight-shoota) +- *(parser)* Use `Char#to_i?` in lexer ([#13841](https://github.com/crystal-lang/crystal/pull/13841), thanks @straight-shoota) + +#### tools + +- *(unreachable)* Refactor `UnreachablePresenter` ([#13941](https://github.com/crystal-lang/crystal/pull/13941), thanks @straight-shoota) + +### Documentation + +#### lang + +- *(macros)* Add reference to book how merging macro expansion and call docs ([#14139](https://github.com/crystal-lang/crystal/pull/14139), thanks @Blacksmoke16) + +#### stdlib + +- *(collection)* Fix documentation of `Hash#put_if_absent` ([#13898](https://github.com/crystal-lang/crystal/pull/13898), thanks @ilmanzo) +- *(collection)* Improve docs on initial/default values passed to `Array.new` and `Hash.new` ([#13962](https://github.com/crystal-lang/crystal/pull/13962), thanks @straight-shoota) +- *(collection)* Improve docs for `Iterator` step-by-step iteration ([#13967](https://github.com/crystal-lang/crystal/pull/13967), thanks @straight-shoota) +- *(macros)* Document `Crystal::Macros::MagicConstant` ([#14070](https://github.com/crystal-lang/crystal/pull/14070), thanks @HertzDevil) +- *(serialization)* Add docs and explicit type restriction for indent parameter of `JSON.build` ([#14140](https://github.com/crystal-lang/crystal/pull/14140), thanks @syeopite) +- *(text)* Add note about `Char::Reader`'s value semantics ([#14008](https://github.com/crystal-lang/crystal/pull/14008), thanks @HertzDevil) +- *(text)* Fix documentation for `String#index!` ([#14038](https://github.com/crystal-lang/crystal/pull/14038), thanks @gettalong) + +#### compiler + +- *(cli)* Add optimization levels to manpage ([#14162](https://github.com/crystal-lang/crystal/pull/14162), thanks @straight-shoota) +- *(cli)* Add `unreachable` options to manpage ([#14164](https://github.com/crystal-lang/crystal/pull/14164), thanks @straight-shoota) +- *(cli)* Fix formatting in manpage ([#14163](https://github.com/crystal-lang/crystal/pull/14163), thanks @straight-shoota) + +### Specs + +#### stdlib + +- Add `pending_wasm32` ([#14086](https://github.com/crystal-lang/crystal/pull/14086), thanks @HertzDevil) +- *(concurrency)* Workaround regular timeouts in `HTTP::Server` specs with MT ([#14097](https://github.com/crystal-lang/crystal/pull/14097), thanks @ysbaddaden) +- *(files)* Fix `File::AccessDeniedError` expectations in `File` specs ([#14029](https://github.com/crystal-lang/crystal/pull/14029), thanks @HertzDevil) +- *(text)* Refactor specs for `HTML.unescape` ([#13842](https://github.com/crystal-lang/crystal/pull/13842), thanks @straight-shoota) +- *(text)* Fix spec for `String#encode` and `String.new` on DragonFlyBSD ([#13944](https://github.com/crystal-lang/crystal/pull/13944), thanks @GeopJr) + +#### compiler + +- *(codegen)* Remove `LLVMExtCreateMCJITCompilerForModule` from `llvm_ext.cc` ([#13966](https://github.com/crystal-lang/crystal/pull/13966), thanks @HertzDevil) +- *(interpreter)* Disable `mkfifo` spec for interpreter ([#14051](https://github.com/crystal-lang/crystal/pull/14051), thanks @HertzDevil) +- *(interpreter)* Fix interpreter specs on Windows ([#14145](https://github.com/crystal-lang/crystal/pull/14145), thanks @HertzDevil) + +#### tools + +- *(docs-generator)* Use `top_level_semantic` in doc spec instead of `semantic` ([#9352](https://github.com/crystal-lang/crystal/pull/9352), thanks @makenowjust) + +### Infrastructure + +- Changelog for 1.11.0 ([#14158](https://github.com/crystal-lang/crystal/pull/14158), thanks @straight-shoota) +- Update previous Crystal release - 1.10.0 ([#13878](https://github.com/crystal-lang/crystal/pull/13878), thanks @straight-shoota) +- Allow to specify git fork of distribution-scripts in CI ([#13976](https://github.com/crystal-lang/crystal/pull/13976), thanks @miry) +- Extract `generate_data` to separate Makefile ([#14015](https://github.com/crystal-lang/crystal/pull/14015), thanks @straight-shoota) +- Windows: Run specs in random order by default ([#14041](https://github.com/crystal-lang/crystal/pull/14041), thanks @HertzDevil) +- Update shards 0.17.4 ([#14133](https://github.com/crystal-lang/crystal/pull/14133), thanks @straight-shoota) +- Update distribution-scripts ([#14136](https://github.com/crystal-lang/crystal/pull/14136), thanks @straight-shoota) +- Update GH Actions to v4 ([#14120](https://github.com/crystal-lang/crystal/pull/14120), thanks @renovate) +- Embed logo image into repository and upgrade to SVG ([#14137](https://github.com/crystal-lang/crystal/pull/14137), thanks @straight-shoota) +- Improvements for `github-changelog` script ([#14160](https://github.com/crystal-lang/crystal/pull/14160), thanks @straight-shoota) +- Add `scripts/generate_llvm_version_info.cr` ([#14112](https://github.com/crystal-lang/crystal/pull/14112), thanks @HertzDevil) +- Fix `make clean` to remove zipped manpages ([#14135](https://github.com/crystal-lang/crystal/pull/14135), thanks @straight-shoota) +- Make `scripts/*.cr` all executable ([#13999](https://github.com/crystal-lang/crystal/pull/13999), thanks @HertzDevil) +- Reformat changelog release headings ([#13663](https://github.com/crystal-lang/crystal/pull/13663), thanks @straight-shoota) +- Merge `samples/.gitignore` into `.gitignore` ([#14134](https://github.com/crystal-lang/crystal/pull/14134), thanks @straight-shoota) +- *(ci)* Update GH Actions ([#13801](https://github.com/crystal-lang/crystal/pull/13801), thanks @renovate) +- *(ci)* Update LLVM patch version to LLVM 17.0.6 ([#14080](https://github.com/crystal-lang/crystal/pull/14080), thanks @straight-shoota) +- *(ci)* Configure Renovate Bot to add label `topic:infrastructure/ci` on PRs ([#14166](https://github.com/crystal-lang/crystal/pull/14166), thanks @straight-shoota) +- *(ci)* Update GH Actions ([#14165](https://github.com/crystal-lang/crystal/pull/14165), thanks @renovate) +- *(ci)* Distribute LLVM DLLs on Windows CI ([#14110](https://github.com/crystal-lang/crystal/pull/14110), thanks @HertzDevil) +- *(ci)* Use `CMAKE_MSVC_RUNTIME_LIBRARY` flag in win.yml ([#13900](https://github.com/crystal-lang/crystal/pull/13900), thanks @HertzDevil) + ## [1.10.1] (2023-10-13) [1.10.1]: https://github.com/crystal-lang/crystal/releases/1.10.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77ad67860f4b..640c980909ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,6 +15,10 @@ there's no more room for discussion. We'll anyway close the issue after some day If something is missing from the language it might be that it's not yet implemented or that it was purposely left out. If in doubt, just ask. +Substantial changes go through an [RFC process](https://github.com/crystal-lang/rfcs). + +The best place to start an open discussion about potential changes is the [Crystal forum](https://forum.crystal-lang.org/c/crystal-contrib/6). + ### What's needed right now You can find a list of tasks that we consider suitable for a first time contribution at diff --git a/Makefile b/Makefile index 7e8070d16921..461ee56bd5e5 100644 --- a/Makefile +++ b/Makefile @@ -127,6 +127,7 @@ samples: ## Build example programs docs: ## Generate standard library documentation $(call check_llvm_config) ./bin/crystal docs src/docs_main.cr $(DOCS_OPTIONS) --project-name=Crystal --project-version=$(CRYSTAL_VERSION) --source-refname=$(CRYSTAL_CONFIG_BUILD_COMMIT) + cp -av doc/ docs/ .PHONY: crystal crystal: $(O)/crystal ## Build the compiler @@ -182,7 +183,6 @@ install_docs: docs ## Install docs at DESTDIR cp -av docs "$(DATADIR)/docs" cp -av samples "$(DATADIR)/examples" - rm -rf "$(DATADIR)/examples/.gitignore" .PHONY: uninstall_docs uninstall_docs: ## Uninstall docs from DESTDIR @@ -230,6 +230,7 @@ man/%.gz: man/% .PHONY: clean clean: clean_crystal ## Clean up built directories and files rm -rf $(LLVM_EXT_OBJ) + rm -rf man/*.gz .PHONY: clean_crystal clean_crystal: ## Clean up crystal built files diff --git a/Makefile.win b/Makefile.win index e2b18741657e..da1d9fc8328a 100644 --- a/Makefile.win +++ b/Makefile.win @@ -171,7 +171,6 @@ install_docs: docs ## Install docs at prefix $(call MKDIR,"$(DATADIR)") $(call INSTALLDIR,docs,"$(DATADIR)\docs") $(call INSTALLDIR,samples,"$(DATADIR)\examples") - $(call RM,"$(DATADIR)\examples\.gitignore") .PHONY: uninstall_docs uninstall_docs: ## Uninstall docs from prefix diff --git a/README.md b/README.md index 67bf031ed038..19d8e09ee853 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ --- -[![Crystal - Born and raised at Manas](https://cloud.githubusercontent.com/assets/209371/13291809/022e2360-daf8-11e5-8be7-d02c1c8b38fb.png)](https://manas.tech/) +[![Crystal - Born and raised at Manas](doc/assets/crystal-born-and-raised.svg)](https://manas.tech/) Crystal is a programming language with the following goals: @@ -40,7 +40,7 @@ Project Status Within a major version, language features won't be removed or changed in any way that could prevent a Crystal program written with that version from compiling and working. The built-in standard library might be enriched, but it will always be done with backwards compatibility in mind. -Development of the Crystal language is possible thanks to the community's effort and the continued support of [84codes](https://www.84codes.com/), [Nikola Motor Company](https://nikolamotor.com/) and every other [sponsor](https://crystal-lang.org/sponsors). +Development of the Crystal language is possible thanks to the community's effort and the continued support of [84codes](https://www.84codes.com/) and every other [sponsor](https://crystal-lang.org/sponsors). Installing ---------- diff --git a/bin/ci b/bin/ci index 8e9f7a5ddadf..9d0b73507f24 100755 --- a/bin/ci +++ b/bin/ci @@ -135,8 +135,8 @@ format() { prepare_build() { on_linux verify_linux_environment - on_osx curl -L https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1-darwin-universal.tar.gz -o ~/crystal.tar.gz - on_osx 'pushd ~;gunzip -c ~/crystal.tar.gz | tar xopf -;mv crystal-1.10.1-1 crystal;popd' + on_osx curl -L https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1-darwin-universal.tar.gz -o ~/crystal.tar.gz + on_osx 'pushd ~;gunzip -c ~/crystal.tar.gz | tar xopf -;mv crystal-1.11.2-1 crystal;popd' # These commands may take a few minutes to run due to the large size of the repositories. # This restriction has been made on GitHub's request because updating shallow @@ -189,7 +189,7 @@ with_build_env() { on_linux verify_linux_environment - export DOCKER_TEST_PREFIX="${DOCKER_TEST_PREFIX:=crystallang/crystal:1.10.1}" + export DOCKER_TEST_PREFIX="${DOCKER_TEST_PREFIX:=crystallang/crystal:1.11.2}" case $ARCH in x86_64) diff --git a/doc/assets/crystal-born-and-raised.svg b/doc/assets/crystal-born-and-raised.svg new file mode 100644 index 000000000000..98e85d9b46b2 --- /dev/null +++ b/doc/assets/crystal-born-and-raised.svg @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etc/completion.bash b/etc/completion.bash index d8731c65bff7..9263289b5b4e 100644 --- a/etc/completion.bash +++ b/etc/completion.bash @@ -66,7 +66,7 @@ _crystal() _crystal_compgen_options "${opts}" "${cur}" else if [[ "${prev}" == "tool" ]] ; then - local subcommands="context dependencies format hierarchy implementations types" + local subcommands="context dependencies flags format hierarchy implementations types" _crystal_compgen_options "${subcommands}" "${cur}" else _crystal_compgen_sources "${cur}" diff --git a/etc/completion.fish b/etc/completion.fish index 150dd37108d8..64fc6a97b45a 100644 --- a/etc/completion.fish +++ b/etc/completion.fish @@ -1,5 +1,5 @@ set -l crystal_commands init build clear_cache docs env eval i interactive play run spec tool help version -set -l tool_subcommands context expand format hierarchy implementations types +set -l tool_subcommands context expand flags format hierarchy implementations types complete -c crystal -s h -l help -d "Show help" -x @@ -173,6 +173,8 @@ complete -c crystal -n "__fish_seen_subcommand_from expand" -s p -l progress -d complete -c crystal -n "__fish_seen_subcommand_from expand" -s t -l time -d "Enable execution time output" complete -c crystal -n "__fish_seen_subcommand_from expand" -l stdin-filename -d "Source file name to be read from STDIN" +complete -c crystal -n "__fish_seen_subcommand_from tool; and not __fish_seen_subcommand_from $tool_subcommands" -a "flags" -d "print all macro 'flag?' values" -x + complete -c crystal -n "__fish_seen_subcommand_from tool; and not __fish_seen_subcommand_from $tool_subcommands" -a "format" -d "format project, directories and/or files" -x complete -c crystal -n "__fish_seen_subcommand_from format" -l check -d "Checks that formatting code produces no changes" complete -c crystal -n "__fish_seen_subcommand_from format" -s i -l include -d "Include path" diff --git a/etc/completion.zsh b/etc/completion.zsh index bf57d80208df..ffa12798ca18 100644 --- a/etc/completion.zsh +++ b/etc/completion.zsh @@ -165,6 +165,7 @@ _crystal-tool() { "context:show context for given location" "dependencies:show tree of required source files" "expand:show macro expansion for given location" + "flags:print all macro 'flag?' values" "format:format project, directories and/or files" "hierarchy:show type hierarchy" "implementations:show implementations for given call in location" @@ -211,6 +212,12 @@ _crystal-tool() { $cursor_args ;; + (flags) + _arguments \ + $programfile \ + $help_args + ;; + (format) _arguments \ $programfile \ diff --git a/etc/win-ci/build-llvm.ps1 b/etc/win-ci/build-llvm.ps1 index b544e9eba784..9335cfe9abe4 100644 --- a/etc/win-ci/build-llvm.ps1 +++ b/etc/win-ci/build-llvm.ps1 @@ -16,7 +16,7 @@ if (-not $Dynamic) { Setup-Git -Path $BuildTree -Url https://github.com/llvm/llvm-project.git -Ref llvmorg-$Version Run-InDirectory $BuildTree\build { - $args = "-Thost=x64 -DLLVM_TARGETS_TO_BUILD=""$($TargetsToBuild -join ';')"" -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_ZSTD=OFF" + $args = "-Thost=x64 -DLLVM_TARGETS_TO_BUILD=$($TargetsToBuild -join ';') -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_ZSTD=OFF" if ($Dynamic) { $args = "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL $args" } else { diff --git a/man/crystal.1 b/man/crystal.1 index 5f08ce29d07e..15fed461c26c 100644 --- a/man/crystal.1 +++ b/man/crystal.1 @@ -117,6 +117,8 @@ Generate the output without any symbolic debug symbols. Define a compile-time flag. This is useful to conditionally define types, methods, or commands based on flags available at compile time. The default flags are from the target triple given with --target-triple or the hosts default, if none is given. .It Fl -emit Op asm|llvm-bc|llvm-ir|obj Comma separated list of types of output for the compiler to emit. You can use this to see the generated LLVM IR, LLVM bitcode, assembly, and object files. +.It Fl -frame-pointers Op auto|always|non-leaf +Control the preservation of frame pointers. The default value, --frame-pointers=auto, will preserve frame pointers on debug builds and try to omit them on release builds (certain platforms require them to stay enabled). --frame-pointers=always will always preserve them, and non-leaf will only force their preservation on non-leaf functions. .It Fl f Ar text|json, Fl -format Ar text|json Format of output. Defaults to text. The json format can be used to get a more parser-friendly output. .It Fl -error-trace @@ -130,7 +132,7 @@ Specify a specific CPU to generate code for. This will pass a -mcpu flag to LLVM Passing --mcpu native will pass the host CPU name to tune performance for the host. .It Fl -mattr Ar CPU Override or control specific attributes of the target, such as whether SIMD operations are enabled or not. The default set of attributes is set by the current CPU. This will pass a -mattr flag to LLVM, and is only intended to be used for cross-compilation. For a list of available attributes, invoke "llvm-as < /dev/null | llc -march=xyz -mattr=help". -.It Fl -mcmodel default|kernel|small|medium|large +.It Fl -mcmodel Ar default|kernel|small|medium|large Specifies a specific code model to generate code for. This will pass a --code-model flag to LLVM. .It Fl -no-color Disable colored output. @@ -140,8 +142,14 @@ Don't do code generation, just parse the file. Specify filename of output. .It Fl -prelude Specify prelude to use. The default one initializes the garbage collector. You can also use --prelude=empty to use no preludes. This can be useful for checking code generation for a specific source code file. +.It Fl O Ar LEVEL +Optimization mode: 0 (default), 1, 2, 3. See +.Sy OPTIMIZATIONS +for details. .It Fl -release -Turn on optimizations for the generated code, which are disabled by default. +Compile in release mode. Equivalent to +.Fl O3 +.Fl -single-module .It Fl -error-trace Show full stack trace. Disabled by default, as the full trace usually makes error messages less readable and not always deliver relevant information. .It Fl s, -stats @@ -152,6 +160,9 @@ Print statistics about the progress for the current build. Print statistics about the execution time. .It Fl -single-module Generate a single LLVM module. +By default, one LLVM module is created for each type in a program. +.Fl -release +implies this option. .It Fl -threads Ar NUM Maximum number of threads to use for code generation. The default is 8 threads. .It Fl -target Ar TRIPLE @@ -265,8 +276,14 @@ Generate the output without any symbolic debug symbols. Define a compile-time flag. This is useful to conditionally define types, methods, or commands based on flags available at compile time. The default flags are from the target triple given with --target-triple or the hosts default, if none is given. .It Fl -error-trace Show full error trace. +.It Fl O Ar LEVEL +Optimization mode: 0 (default), 1, 2, 3. See +.Sy OPTIMIZATIONS +for details. .It Fl -release -Turn on optimizations for the generated code, which are disabled by default. +Compile in release mode. Equivalent to +.Fl O3 +.Fl -single-module .It Fl s, -stats Print statistics about the different compiler stages for the current build. Output time and used memory for each compiler process. .It Fl p, -progress @@ -326,8 +343,14 @@ Generate the output without any symbolic debug symbols. Define a compile-time flag. This is useful to conditionally define types, methods, or commands based on flags available at compile time. The default flags are from the target triple given with --target-triple or the hosts default, if none is given. .It Fl -error-trace Show full error trace. +.It Fl O Ar LEVEL +Optimization mode: 0 (default), 1, 2, 3. See +.Sy OPTIMIZATIONS +for details. .It Fl -release -Turn on optimizations for the generated code, which are disabled by default. +Compile in release mode. Equivalent to +.Fl O3 +.Fl -single-module .It Fl s, -stats Print statistics about the different compiler stages for the current build. Output time and used memory for each compiler process. .It Fl p, -progress @@ -346,7 +369,7 @@ Disable colored output. .Op -- .Op arguments .Pp -Run a tool. The available tools are: context, dependencies, format, hierarchy, implementations, and types. +Run a tool. The available tools are: context, dependencies, flags, format, hierarchy, implementations, and types. .Pp Tools: .Bl -tag -offset indent @@ -375,6 +398,8 @@ Show skipped and heads of filtered paths .El .It Cm expand Show macro expansion for given location. +.It Cm flags +Print all macro 'flag?' values .It Cm format Format project, directories and/or files with the coding style used in the standard library. You can use the .Fl -check @@ -386,13 +411,53 @@ flag. .It Cm implementations Show implementations for a given call. Use .Fl -cursor -to specify the cursor position. The format for the cursor position is file:line:column. + to specify the cursor position. The format for the cursor position is file:line:column. .It Cm types Show type of main variables of file. .It Cm unreachable -Show methods that are never called. The output is a list of lines with columns -separated by tab. The first column is the location of the def, the second column -its reference name and the third column is the length in lines. +Show methods that are never called. The text output is a list of lines with columns +separated by tab. + +.Pp +Output fields: + +.Bl -tag -width "1234567890" -compact +.Pp +.It Cm count +sum of all calls to this method (only with +.Fl -tallies + option; otherwise skipped) +.It Cm location +pathname, line and column, all separated by colon +.It Cm name +.It Cm lines +length of the def in lines +.It Cm annotations +.El + +.Pp +Options: +.Bl -tag -width "12345678" -compact +.Pp +.It Fl D Ar FLAG, Fl -define= Ar FLAG +Define a compile-time flag. This is useful to conditionally define types, methods, or commands based on flags available at compile time. The default flags are from the target triple given with --target-triple or the hosts default, if none is given. +.It Fl f Ar FORMAT, Fl -format= Ar FORMAT +Output format 'text' (default), 'json', or 'csv'. +.It Fl -tallies +Print reachable methods and their call counts as well. +.It Fl -check +Exit with error if there is any unreachable code. +.It Fl i Ar PATH, Fl -include= Ar PATH +Include path in output. +.It Fl e Ar PATH, Fl -exclude= Ar PATH +Exclude path in output (default: +.Sy lib +). +.It Fl -error-trace +Show full error trace. +.It Fl -prelude +Specify prelude to use. The default one initializes the garbage collector. You can also use --prelude=empty to use no preludes. This can be useful for checking code generation for a specific source code file. +.El .El .Pp .It @@ -410,7 +475,29 @@ Show help. Option --help or -h can also be added to each command for command-spe Show version. .El . -.Sh ENVIRONMENT VARIABLES +.Sh OPTIMIZATIONS +.Bl -tag -width "12345678" -compact +.Pp +The optimization level specifies the codegen effort for producing optimal code. +It's a trade-off between compilation performance (decreasing per optimization level) and runtime performance (increasing per optimization level). +.Pp +Production builds should usually have the highest optimization level. +Best results are achieved with +.Fl -release + which also implies +.Fl -single-module +.Pp +.It +.It Fl O0 +No optimization (default) +.It Fl O1 +Low optimization +.It Fl O2 +Middle optimization +.It Fl O3 +High optimization +. +.Sh ENVIRONMENT\ VARIABLES .Bl -tag -width "12345678" -compact .Pp .It diff --git a/samples/.gitignore b/samples/.gitignore deleted file mode 100644 index 0e03e15f2420..000000000000 --- a/samples/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/.build/ diff --git a/samples/compiler/visitor_example.cr b/samples/compiler/visitor_example.cr index ec063a832efa..d9be4da91baf 100644 --- a/samples/compiler/visitor_example.cr +++ b/samples/compiler/visitor_example.cr @@ -15,6 +15,7 @@ class Counter < Crystal::Visitor def visit(node : Crystal::NumberLiteral) @count += 1 + false end def visit(node : Crystal::ASTNode) diff --git a/scripts/github-changelog.cr b/scripts/github-changelog.cr index b46adb9c656b..f2d277f258e7 100755 --- a/scripts/github-changelog.cr +++ b/scripts/github-changelog.cr @@ -31,6 +31,10 @@ def query_prs(api_token, repository, milestone) repository(owner: $owner, name: $repository) { milestones(query: $milestone, first: 1) { nodes { + closedAt + description + dueOn + title pullRequests(first: 300) { nodes { number @@ -81,6 +85,28 @@ module LabelNameConverter end end +record Milestone, + closed_at : Time?, + description : String, + due_on : Time?, + title : String, + pull_requests : Array(PullRequest) do + include JSON::Serializable + + @[JSON::Field(key: "dueOn")] + @due_on : Time? + + @[JSON::Field(key: "closedAt")] + @closed_at : Time? + + @[JSON::Field(key: "pullRequests", root: "nodes")] + @pull_requests : Array(PullRequest) + + def release_date + closed_at || due_on + end +end + record PullRequest, number : Int32, title : String, @@ -110,10 +136,13 @@ record PullRequest, if labels.includes?("breaking-change") io << "**[breaking]** " end + if experimental? + io << "**[experimental]** " + end if deprecated? io << "**[deprecation]** " end - io << title.sub(/^#{type}: /i, "") << " (" + io << title.sub(/^\[?(?:#{type}|#{sub_topic})(?::|\]:?) /i, "") << " (" io << "[#" << number << "](" << permalink << ")" if author = self.author io << ", thanks @" << author @@ -152,9 +181,26 @@ record PullRequest, end def topic - labels.find { |label| - label.starts_with?("topic:") && label != "topic:multithreading" - }.try(&.lchop("topic:").split(/:|\//)) + topics.fetch(0) do + STDERR.puts "Missing topic for ##{number}" + nil + end + end + + def topics + topics = labels.compact_map { |label| + label.lchop?("topic:").try(&.split(/:|\//)) + } + topics.reject! &.[0].==("multithreading") + + topics.sort_by! { |parts| + topic_priority = case parts[0] + when "tools" then 2 + when "lang" then 1 + else 0 + end + {-topic_priority, parts[0]} + } end def deprecated? @@ -165,6 +211,10 @@ record PullRequest, labels.includes?("kind:breaking") end + def experimental? + labels.includes?("experimental") + end + def feature? labels.includes?("kind:feature") end @@ -173,6 +223,10 @@ record PullRequest, labels.includes?("kind:bug") end + def chore? + labels.includes?("kind:chore") + end + def refactor? labels.includes?("kind:refactor") end @@ -196,9 +250,10 @@ record PullRequest, def type case when feature? then "feature" - when fix? then "fix" when docs? then "docs" when specs? then "specs" + when fix? then "fix" + when chore? then "chore" when performance? then "performance" when refactor? then "refactor" else nil @@ -216,42 +271,46 @@ end response = query_prs(api_token, repository, milestone) parser = JSON::PullParser.new(response.body) -array = parser.on_key! "data" do +milestone = parser.on_key! "data" do parser.on_key! "repository" do parser.on_key! "milestones" do parser.on_key! "nodes" do parser.read_begin_array - a = parser.on_key! "pullRequests" do - parser.on_key! "nodes" do - Array(PullRequest).new(parser) - end - end + milestone = Milestone.new(parser) parser.read_end_array - a + milestone end end end end -changelog = File.read("CHANGELOG.md") -array.select! { |pr| pr.merged_at && !changelog.index(pr.permalink) } - -sections = array.group_by(&.section) +sections = milestone.pull_requests.group_by(&.section) SECTION_TITLES = { "breaking" => "Breaking changes", "feature" => "Features", "fix" => "Bugfixes", + "chore" => "Chores", "performance" => "Performance", "refactor" => "Refactor", "docs" => "Documentation", "specs" => "Specs", "infra" => "Infrastructure", - "" => "Chores", + "" => "other", } TOPIC_ORDER = %w[lang stdlib compiler tools other] +puts "## [#{milestone.title}] (#{milestone.release_date.try(&.to_s("%F")) || "unreleased"})" +if description = milestone.description.presence + puts + print "_", description + puts "_" +end +puts +puts "[#{milestone.title}]: https://github.com/crystal-lang/crystal/releases/#{milestone.title}" +puts + SECTION_TITLES.each do |id, title| prs = sections[id]? || next puts "### #{title}" diff --git a/shell.nix b/shell.nix index ab90080aca13..aef4211f280a 100644 --- a/shell.nix +++ b/shell.nix @@ -52,18 +52,18 @@ let # Hashes obtained using `nix-prefetch-url --unpack ` latestCrystalBinary = genericBinary ({ x86_64-darwin = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1-darwin-universal.tar.gz"; - sha256 = "sha256:08k8sixhnk9ld99nyrya11rkpp34zamsg3lk9h50ppbmzfixjyyc"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1-darwin-universal.tar.gz"; + sha256 = "sha256:0qcdr8yl6k7il0x63z2gyqbkjp89m77nq7x1h3m80y1imfg0z1q9"; }; aarch64-darwin = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1-darwin-universal.tar.gz"; - sha256 = "sha256:08k8sixhnk9ld99nyrya11rkpp34zamsg3lk9h50ppbmzfixjyyc"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1-darwin-universal.tar.gz"; + sha256 = "sha256:0qcdr8yl6k7il0x63z2gyqbkjp89m77nq7x1h3m80y1imfg0z1q9"; }; x86_64-linux = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1-linux-x86_64.tar.gz"; - sha256 = "sha256:02hzslzgv0xxsal3fkbcdrnrrnzf9lraamy36p36sjf8n14v45a2"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1-linux-x86_64.tar.gz"; + sha256 = "sha256:01l9cq8d3p7p3ijkrg0xpchj0l21z3sjvd5f6zw1pnms647a6hdr"; }; }.${pkgs.stdenv.system}); diff --git a/spec/compiler/codegen/asm_spec.cr b/spec/compiler/codegen/asm_spec.cr index 2c6b0707699e..05eb3b895032 100644 --- a/spec/compiler/codegen/asm_spec.cr +++ b/spec/compiler/codegen/asm_spec.cr @@ -3,6 +3,14 @@ require "../../spec_helper" describe "Code gen: asm" do # TODO: arm asm tests {% if flag?(:i386) || flag?(:x86_64) %} + it "passes correct string length to LLVM" do + run <<-CRYSTAL + asm("// 😂😂 + nop + nop") + CRYSTAL + end + it "codegens without inputs" do run(%( dst = uninitialized Int32 @@ -44,5 +52,13 @@ describe "Code gen: asm" do c )).to_i.should eq(42) end + + it "codegens with intel dialect" do + run(<<-CRYSTAL).to_i.should eq(1234) + dst = uninitialized Int32 + asm("mov dword ptr [$0], 1234" :: "r"(pointerof(dst)) :: "intel") + dst + CRYSTAL + end {% end %} end diff --git a/spec/compiler/codegen/cast_spec.cr b/spec/compiler/codegen/cast_spec.cr index 32b265ea0415..dd6653f036c9 100644 --- a/spec/compiler/codegen/cast_spec.cr +++ b/spec/compiler/codegen/cast_spec.cr @@ -77,6 +77,68 @@ describe "Code gen: cast" do )).to_b.should be_true end + it "upcasts from union to union with different alignment" do + run(<<-CRYSTAL).to_i.should eq(1) + require "prelude" + + a = 1 || 2_i64 + a.as(Int32 | Int64 | Int128) + CRYSTAL + end + + it "downcasts from union to union with different alignment" do + run(<<-CRYSTAL).to_i.should eq(1) + require "prelude" + + a = 1 || 2_i64 || 3_i128 + a.as(Int32 | Int64) + CRYSTAL + end + + it "sidecasts from union to union with different alignment" do + run(<<-CRYSTAL).to_i.should eq(1) + require "prelude" + + a = 1 || 2_i64 + a.as(Int32 | Int128) + CRYSTAL + end + + it "doesn't corrupt stack when downcasting union to union with different alignment (#14285)" do + run(<<-CRYSTAL).to_b.should be_true + struct Time2 + def initialize(@seconds : Int64) + @nanoseconds = uninitialized UInt32[3] + end + + def <(other : Time2) : Bool + @seconds < other.@seconds + end + end + + class Constraints::Range + def initialize(@min : Int128 | Time2 | Nil) + end + end + + def validate(value : Time2, constraint) : Bool + min = constraint.@min + if min.is_a?(Time2?) + if min + if value < min + return false + end + end + end + true + end + + value = Time2.new(123) + constraint = Constraints::Range.new(Time2.new(45)) + validate(value, constraint) + CRYSTAL + end + it "casts from virtual to single type" do run(%( require "prelude" diff --git a/spec/compiler/codegen/is_a_spec.cr b/spec/compiler/codegen/is_a_spec.cr index 97d72378be42..86ed570afe20 100644 --- a/spec/compiler/codegen/is_a_spec.cr +++ b/spec/compiler/codegen/is_a_spec.cr @@ -45,6 +45,16 @@ describe "Codegen: is_a?" do run("1.is_a?(Object)").to_b.should be_true end + it "doesn't error if result is discarded (#14113)" do + run(<<-CRYSTAL).to_i.should eq(1) + class Foo + end + + (Foo.new || "").is_a?(Foo) + 1 + CRYSTAL + end + it "evaluate method on filtered type" do run("a = 1; a = 'a'; if a.is_a?(Char); a.ord; else; 0; end").to_i.chr.should eq('a') end diff --git a/spec/compiler/codegen/responds_to_spec.cr b/spec/compiler/codegen/responds_to_spec.cr index e10f024f3682..0384c3e0d838 100644 --- a/spec/compiler/codegen/responds_to_spec.cr +++ b/spec/compiler/codegen/responds_to_spec.cr @@ -51,6 +51,18 @@ describe "Codegen: responds_to?" do )).to_b.should be_false end + it "doesn't error if result is discarded (#14113)" do + run(<<-CRYSTAL).to_i.should eq(1) + class Foo + def foo + end + end + + (Foo.new || "").responds_to?(:foo) + 1 + CRYSTAL + end + it "works with virtual type" do run(%( class Foo diff --git a/spec/compiler/codegen/sizeof_spec.cr b/spec/compiler/codegen/sizeof_spec.cr index 8139db8bc426..e90553d0b3c1 100644 --- a/spec/compiler/codegen/sizeof_spec.cr +++ b/spec/compiler/codegen/sizeof_spec.cr @@ -279,6 +279,16 @@ describe "Code gen: sizeof" do alignof(Foo) CRYSTAL end + + it "gets alignof union" do + run("alignof(Int32 | Int8)").to_i.should eq(8) + run("alignof(Int32 | Int64)").to_i.should eq(8) + end + + it "alignof mixed union is not less than alignof its variant types" do + # NOTE: `alignof(Int128) == 16` is not guaranteed + run("alignof(Int32 | Int128) >= alignof(Int128)").to_b.should be_true + end end describe "instance_alignof" do diff --git a/spec/compiler/crystal/tools/flags_spec.cr b/spec/compiler/crystal/tools/flags_spec.cr new file mode 100644 index 000000000000..c295439e0547 --- /dev/null +++ b/spec/compiler/crystal/tools/flags_spec.cr @@ -0,0 +1,44 @@ +require "../../../spec_helper" +include Crystal + +private def parse_flags(source) + Crystal::Command::FlagsVisitor.new.tap do |visitor| + Parser.parse(source).accept(visitor) + end +end + +describe Crystal::Command::FlagsVisitor do + it "different flags" do + visitor = parse_flags <<-CRYSTAL + {% + flag?(:foo) + flag?("bar") + flag?(1) + flag?(true) + %} + CRYSTAL + visitor.flag_names.should eq %w[1 bar foo true] + end + + it "unique flags" do + visitor = parse_flags <<-CRYSTAL + {% + flag?(:foo) + flag?("foo") + flag?(:foo) + %} + CRYSTAL + visitor.flag_names.should eq %w[foo] + end + + it "only macro" do + visitor = parse_flags <<-CRYSTAL + flag?(:flag) + f.flag?(:foo) + F.flag?(:bar) + {% f.flag?(:baz) %} + {% f.flag?(:qux, other: true) %} + CRYSTAL + visitor.flag_names.should eq %w[] + end +end diff --git a/spec/compiler/crystal/tools/repl_spec.cr b/spec/compiler/crystal/tools/repl_spec.cr new file mode 100644 index 000000000000..3a1e1275ef12 --- /dev/null +++ b/spec/compiler/crystal/tools/repl_spec.cr @@ -0,0 +1,20 @@ +{% skip_file if flag?(:without_interpreter) %} + +require "../../../spec_helper" + +private def success_value(result : Crystal::Repl::EvalResult) : Crystal::Repl::Value + result.warnings.infos.should be_empty + result.value.should_not be_nil +end + +describe Crystal::Repl do + it "can parse and evaluate snippets" do + repl = Crystal::Repl.new + repl.prelude = "primitives" + repl.load_prelude + + success_value(repl.parse_and_interpret("1 + 2")).value.should eq(3) + success_value(repl.parse_and_interpret("def foo; 1 + 2; end")).value.should eq(nil) + success_value(repl.parse_and_interpret("foo")).value.should eq(3) + end +end diff --git a/spec/compiler/crystal/tools/unreachable_spec.cr b/spec/compiler/crystal/tools/unreachable_spec.cr index 6fffb17e4ca6..12ed82499740 100644 --- a/spec/compiler/crystal/tools/unreachable_spec.cr +++ b/spec/compiler/crystal/tools/unreachable_spec.cr @@ -15,28 +15,37 @@ def processed_unreachable_visitor(code) end private def assert_unreachable(code, file = __FILE__, line = __LINE__) - expected_locations = [] of Location + expected = Hash(String, Int32).new code.lines.each_with_index do |line, line_number_0| - if column_number = line.index('༓') - expected_locations << Location.new(".", line_number_0 + 1, column_number + 1) + if match = line.match(/༓(?:\[(\d+)\])?/) + location = Location.new(".", line_number_0 + 1, match.begin + 1) + expected[location.to_s] = (match[1]? || 0).to_i end end - code = code.gsub('༓', "") + code = code.gsub(/༓(?:\[(\d+)\])?/, "") - defs = processed_unreachable_visitor(code) + tallies = processed_unreachable_visitor(code) - result_location = defs.try &.compact_map(&.location).sort_by! do |loc| + processed_results = [] of {Location, Int32} + tallies.each do |k, v| + location = k.location.not_nil! + next unless v.zero? || expected.has_key?(location.to_s) + processed_results << {location, v} + end + + processed_results = processed_results.sort_by! do |loc, v| {loc.filename.as(String), loc.line_number, loc.column_number} - end.map(&.to_s) + end.map { |k, v| {k.to_s, v} } - result_location.should eq(expected_locations.map(&.to_s)), file: file, line: line + processed_results.should eq(expected.to_a), file: file, line: line end # References # # ༓ marks the expected unreachable code to be found +# ༓[n] marks the expected code to be called n times # describe "unreachable" do it "finds top level methods" do @@ -424,4 +433,23 @@ describe "unreachable" do {% end %} CRYSTAL end + + it "tallies calls" do + assert_unreachable <<-CRYSTAL + ༓def foo + 1 + end + + ༓[2]def bar + 2 + end + + ༓[1]def baz + bar + end + + bar + baz + CRYSTAL + end end diff --git a/spec/compiler/ffi/ffi_spec.cr b/spec/compiler/ffi/ffi_spec.cr index ac16cfc425f2..ec644e45870d 100644 --- a/spec/compiler/ffi/ffi_spec.cr +++ b/spec/compiler/ffi/ffi_spec.cr @@ -19,6 +19,22 @@ private record TestStruct, d : Float64, p : Pointer(Void) +private def dll_search_paths + {% if flag?(:msvc) %} + [SPEC_CRYSTAL_LOADER_LIB_PATH] + {% else %} + nil + {% end %} +end + +{% if flag?(:unix) %} + class Crystal::Loader + def self.new(search_paths : Array(String), *, dll_search_paths : Nil) + new(search_paths) + end + end +{% end %} + describe Crystal::FFI::CallInterface do before_all do FileUtils.mkdir_p(SPEC_CRYSTAL_LOADER_LIB_PATH) @@ -33,7 +49,7 @@ describe Crystal::FFI::CallInterface do it "simple call" do call_interface = Crystal::FFI::CallInterface.new Crystal::FFI::Type.sint64, [] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("answer") return_value = 0_i64 @@ -48,7 +64,7 @@ describe Crystal::FFI::CallInterface do Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32, ] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum") @@ -71,7 +87,7 @@ describe Crystal::FFI::CallInterface do Crystal::FFI::Type.pointer, ] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_primitive_types") @@ -109,7 +125,7 @@ describe Crystal::FFI::CallInterface do ] call_interface = Crystal::FFI::CallInterface.new Crystal::FFI::Type.struct(struct_fields), struct_fields - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("make_struct") @@ -145,7 +161,7 @@ describe Crystal::FFI::CallInterface do ]), ] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_struct") @@ -183,7 +199,7 @@ describe Crystal::FFI::CallInterface do ]), ] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_array") @@ -208,7 +224,7 @@ describe Crystal::FFI::CallInterface do it "basic" do call_interface = Crystal::FFI::CallInterface.variadic Crystal::FFI::Type.sint64, [Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32] of Crystal::FFI::Type, 1 - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_variadic") @@ -224,7 +240,7 @@ describe Crystal::FFI::CallInterface do it "zero varargs" do call_interface = Crystal::FFI::CallInterface.variadic Crystal::FFI::Type.sint64, [Crystal::FFI::Type.sint32] of Crystal::FFI::Type, 1 - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_variadic") diff --git a/spec/compiler/formatter/formatter_spec.cr b/spec/compiler/formatter/formatter_spec.cr index 4567638f0fd8..bd992b78fa4a 100644 --- a/spec/compiler/formatter/formatter_spec.cr +++ b/spec/compiler/formatter/formatter_spec.cr @@ -1629,6 +1629,14 @@ describe Crystal::Formatter do assert_format "->( x : Int32 , y ) { x }", "->(x : Int32, y) { x }" assert_format "->{}" + # #13232 + assert_format "->{}", "-> { }", flags: %w[proc_literal_whitespace] + assert_format "->(){}", "-> { }", flags: %w[proc_literal_whitespace] + assert_format "->{1}", "-> { 1 }", flags: %w[proc_literal_whitespace] + assert_format "->(x : Int32) {}", "->(x : Int32) { }", flags: %w[proc_literal_whitespace] + assert_format "-> : Int32 {}", "-> : Int32 { }", flags: %w[proc_literal_whitespace] + assert_format "->do\nend", "-> do\nend", flags: %w[proc_literal_whitespace] + assert_format "-> : Int32 {}" assert_format "-> : Int32 | String { 1 }" assert_format "-> : Array(Int32) {}" @@ -1687,6 +1695,44 @@ describe Crystal::Formatter do assert_format %(asm("a" : "b"(c) : "d"(e)\n : "f",\n "g")) assert_format %(asm("a" ::: "a"\n : "volatile",\n "intel")) + assert_format <<-CRYSTAL, <<-CRYSTAL + asm( + # foo + "nop" + # bar + ) + CRYSTAL + asm( + # foo + "nop" + # bar + ) + CRYSTAL + + assert_format <<-CRYSTAL, <<-CRYSTAL + asm( + # the assembly template string, following the + # syntax for LLVM's integrated assembler + "nop" : # output operands + "=r"(foo), "=r"(bar) : # input operands + "r"(1), "r"(baz) : # names of clobbered registers + "eax", "memory" : # optional flags, corresponding to the LLVM IR + # sideeffect / alignstack / inteldialect / unwind attributes + "volatile", "alignstack", "intel", "unwind" + ) + CRYSTAL + asm( + # the assembly template string, following the + # syntax for LLVM's integrated assembler + "nop" : # output operands + "=r"(foo), "=r"(bar) : # input operands + "r"(1), "r"(baz) : # names of clobbered registers + "eax", "memory" : # optional flags, corresponding to the LLVM IR + # sideeffect / alignstack / inteldialect / unwind attributes + "volatile", "alignstack", "intel", "unwind" + ) + CRYSTAL + assert_format "1 # foo\n1234 # bar", "1 # foo\n1234 # bar" assert_format "1234 # foo\n1 # bar", "1234 # foo\n1 # bar" assert_format "1#foo", "1 # foo" @@ -1953,6 +1999,13 @@ describe Crystal::Formatter do assert_format "foo.[] = 1" assert_format "foo.[1, 2] = 3" + %w(<= == >= != []= ===).each do |operator| + assert_format "1.#{operator} { 3 }" + assert_format "1.#{operator}() { 3 }" + assert_format "1.#{operator}(2) { 3 }" + assert_format "1.#{operator} do\nend" + end + assert_format "@foo : Int32 # comment\n\ndef foo\nend" assert_format "getter foo # comment\n\ndef foo\nend" assert_format "getter foo : Int32 # comment\n\ndef foo\nend" diff --git a/spec/compiler/interpreter/lib_spec.cr b/spec/compiler/interpreter/lib_spec.cr index 98e1da7fd294..2c1798645645 100644 --- a/spec/compiler/interpreter/lib_spec.cr +++ b/spec/compiler/interpreter/lib_spec.cr @@ -2,6 +2,22 @@ require "./spec_helper" require "../loader/spec_helper" +private def ldflags + {% if flag?(:win32) %} + "/LIBPATH:#{SPEC_CRYSTAL_LOADER_LIB_PATH} sum.lib" + {% else %} + "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -lsum" + {% end %} +end + +private def ldflags_with_backtick + {% if flag?(:win32) %} + "/LIBPATH:#{SPEC_CRYSTAL_LOADER_LIB_PATH} `powershell.exe -C Write-Host -NoNewline sum.lib`" + {% else %} + "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -l`echo sum`" + {% end %} +end + describe Crystal::Repl::Interpreter do context "variadic calls" do before_all do @@ -11,7 +27,7 @@ describe Crystal::Repl::Interpreter do it "promotes float" do interpret(<<-CRYSTAL).should eq 3.5 - @[Link(ldflags: "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -lsum")] + @[Link(ldflags: #{ldflags.inspect})] lib LibSum fun sum_float(count : Int32, ...) : Float32 end @@ -22,7 +38,7 @@ describe Crystal::Repl::Interpreter do it "promotes int" do interpret(<<-CRYSTAL).should eq 5 - @[Link(ldflags: "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -lsum")] + @[Link(ldflags: #{ldflags.inspect})] lib LibSum fun sum_int(count : Int32, ...) : Int32 end @@ -33,7 +49,7 @@ describe Crystal::Repl::Interpreter do it "promotes enum" do interpret(<<-CRYSTAL).should eq 5 - @[Link(ldflags: "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -lsum")] + @[Link(ldflags: #{ldflags.inspect})] lib LibSum fun sum_int(count : Int32, ...) : Int32 end @@ -63,7 +79,7 @@ describe Crystal::Repl::Interpreter do it "expands ldflags" do interpret(<<-CRYSTAL).should eq 4 - @[Link(ldflags: "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -l`echo sum`")] + @[Link(ldflags: #{ldflags_with_backtick.inspect})] lib LibSum fun simple_sum_int(a : Int32, b : Int32) : Int32 end diff --git a/spec/compiler/interpreter/spec_helper.cr b/spec/compiler/interpreter/spec_helper.cr index c3b0dcaca8cd..3c6f88ab1679 100644 --- a/spec/compiler/interpreter/spec_helper.cr +++ b/spec/compiler/interpreter/spec_helper.cr @@ -5,6 +5,7 @@ require "compiler/crystal/interpreter/*" def interpret(code, *, prelude = "primitives", file = __FILE__, line = __LINE__) if prelude == "primitives" context, value = interpret_with_context(code) + context.loader?.try &.close_all value.value else interpret_in_separate_process(code, prelude, file: file, line: line) @@ -23,18 +24,20 @@ end # In a nutshell, `interpret_in_separate_process` below calls this same process with an extra option that causes # the interpretation of the code from stdin, reading the output from stdout. That string is used as the result of # the program being tested. -def Spec.option_parser - option_parser = previous_def - option_parser.on("", "--interpret-code PRELUDE", "Execute interpreted code") do |prelude| - code = STDIN.gets_to_end - - repl = Crystal::Repl.new - repl.prelude = prelude - - print repl.run_code(code) - exit +class Spec::CLI + def option_parser + option_parser = previous_def + option_parser.on("", "--interpret-code PRELUDE", "Execute interpreted code") do |prelude| + code = STDIN.gets_to_end + + repl = Crystal::Repl.new + repl.prelude = prelude + + print repl.run_code(code) + exit + end + option_parser end - option_parser end def interpret_in_separate_process(code, prelude, file = __FILE__, line = __LINE__) diff --git a/spec/compiler/loader/msvc_spec.cr b/spec/compiler/loader/msvc_spec.cr index fedb21c352c4..e62ba0bd620c 100644 --- a/spec/compiler/loader/msvc_spec.cr +++ b/spec/compiler/loader/msvc_spec.cr @@ -45,7 +45,7 @@ describe Crystal::Loader do describe "#load_file?" do it "finds function symbol" do - loader = Crystal::Loader.new([] of String) + loader = Crystal::Loader.new([] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_file?(File.join(SPEC_CRYSTAL_LOADER_LIB_PATH, Crystal::Loader.library_filename("foo"))).should be_true loader.find_symbol?("foo").should_not be_nil ensure @@ -55,7 +55,7 @@ describe Crystal::Loader do describe "#load_library?" do it "library name" do - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_library?("foo").should be_true loader.find_symbol?("foo").should_not be_nil ensure @@ -63,7 +63,7 @@ describe Crystal::Loader do end it "full path" do - loader = Crystal::Loader.new([] of String) + loader = Crystal::Loader.new([] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_library?(File.join(SPEC_CRYSTAL_LOADER_LIB_PATH, Crystal::Loader.library_filename("foo"))).should be_true loader.find_symbol?("foo").should_not be_nil ensure @@ -72,7 +72,7 @@ describe Crystal::Loader do it "does not implicitly find dependencies" do build_c_dynlib(compiler_datapath("loader", "bar.c")) - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_library?("bar").should be_true loader.find_symbol?("bar").should_not be_nil loader.find_symbol?("foo").should be_nil @@ -83,23 +83,23 @@ describe Crystal::Loader do it "lookup in order" do build_c_dynlib(compiler_datapath("loader", "foo2.c")) - help_loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + help_loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) help_loader1.load_library?("foo").should be_true foo_address = help_loader1.find_symbol?("foo").should_not be_nil - help_loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + help_loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) help_loader2.load_library?("foo2").should be_true foo2_address = help_loader2.find_symbol?("foo").should_not be_nil foo_address.should_not eq foo2_address - loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader1.load_library("foo") loader1.load_library("foo2") loader1.find_symbol?("foo").should eq foo_address - loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader2.load_library("foo2") loader2.load_library("foo") @@ -114,15 +114,82 @@ describe Crystal::Loader do end it "does not find global symbols" do - loader = Crystal::Loader.new([] of String) + loader = Crystal::Loader.new([] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.find_symbol?("__crystal_main").should be_nil end it "validate that lib handles are properly closed" do - loader = Crystal::Loader.new([] of String) + loader = Crystal::Loader.new([] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) expect_raises(Crystal::Loader::LoadError, "undefined reference to `foo'") do loader.find_symbol("foo") end end end + + describe "dll_search_paths" do + it "supports an arbitrary path different from lib search path" do + with_tempfile("loader-dll_search_paths") do |path| + FileUtils.mkdir_p(SPEC_CRYSTAL_LOADER_LIB_PATH) + FileUtils.mkdir_p(path) + + build_c_dynlib(compiler_datapath("loader", "foo.c")) + File.rename(File.join(SPEC_CRYSTAL_LOADER_LIB_PATH, "foo.dll"), File.join(path, "foo.dll")) + + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String, dll_search_paths: [path]) + loader.load_library?("foo").should be_true + ensure + loader.try &.close_all + + FileUtils.rm_rf(path) + FileUtils.rm_rf(SPEC_CRYSTAL_LOADER_LIB_PATH) + end + end + + it "doesn't load DLLs outside dll_search_path or Windows' default search paths" do + with_tempfile("loader-dll_search_paths") do |path| + FileUtils.mkdir_p(SPEC_CRYSTAL_LOADER_LIB_PATH) + FileUtils.mkdir_p(path) + + build_c_dynlib(compiler_datapath("loader", "foo.c")) + File.rename(File.join(SPEC_CRYSTAL_LOADER_LIB_PATH, "foo.dll"), File.join(path, "foo.dll")) + + loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader1.load_library?("foo").should be_false + loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader2.load_library?("foo").should be_false + ensure + loader2.try &.close_all + loader1.try &.close_all + + FileUtils.rm_rf(path) + FileUtils.rm_rf(SPEC_CRYSTAL_LOADER_LIB_PATH) + end + end + end + + describe "lib suffix" do + before_all do + FileUtils.mkdir_p(SPEC_CRYSTAL_LOADER_LIB_PATH) + end + + after_all do + FileUtils.rm_rf(SPEC_CRYSTAL_LOADER_LIB_PATH) + end + + it "respects -dynamic" do + build_c_dynlib(compiler_datapath("loader", "foo.c"), lib_name: "foo-dynamic") + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader.load_library?("foo").should be_true + ensure + loader.close_all if loader + end + + it "ignores -static" do + build_c_dynlib(compiler_datapath("loader", "foo.c"), lib_name: "bar-static") + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader.load_library?("bar").should be_false + ensure + loader.close_all if loader + end + end end diff --git a/spec/compiler/loader/spec_helper.cr b/spec/compiler/loader/spec_helper.cr index 282af7871f81..0db69dc19752 100644 --- a/spec/compiler/loader/spec_helper.cr +++ b/spec/compiler/loader/spec_helper.cr @@ -2,8 +2,8 @@ require "spec" SPEC_CRYSTAL_LOADER_LIB_PATH = File.join(SPEC_TEMPFILE_PATH, "loader") -def build_c_dynlib(c_filename, target_dir = SPEC_CRYSTAL_LOADER_LIB_PATH) - o_filename = File.join(target_dir, Crystal::Loader.library_filename(File.basename(c_filename, ".c"))) +def build_c_dynlib(c_filename, *, lib_name = nil, target_dir = SPEC_CRYSTAL_LOADER_LIB_PATH) + o_filename = File.join(target_dir, Crystal::Loader.library_filename(lib_name || File.basename(c_filename, ".c"))) {% if flag?(:msvc) %} o_basename = o_filename.rchop(".lib") diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 9d6304e81f01..76d5f795903c 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -1,4 +1,5 @@ require "../../spec_helper" +require "../../support/env" private def declare_class_var(container : ClassVarContainer, name, var_type : Type, annotations = nil) var = MetaTypeVar.new(name) @@ -2504,6 +2505,13 @@ module Crystal end end + describe Primitive do + it "executes name" do + assert_macro %({{x.name}}), %(:abc), {x: Primitive.new("abc")} + assert_macro %({{x.name}}), %(:"x.y.z"), {x: Primitive.new("x.y.z")} + end + end + describe "macro methods" do it "executes name" do assert_macro %({{x.name}}), "some_macro", {x: Macro.new("some_macro")} @@ -2610,6 +2618,18 @@ module Crystal end end + describe Alias do + node = Alias.new("Foo".path, Generic.new(Path.new(["Bar", "Baz"], global: true), ["T".path] of ASTNode)) + + it "executes name" do + assert_macro %({{x.name}}), %(Foo), {x: node} + end + + it "executes type" do + assert_macro %({{x.type}}), %(::Bar::Baz(T)), {x: node} + end + end + describe "visibility modifier methods" do node = VisibilityModifier.new(Visibility::Protected, Def.new("some_def")) @@ -2762,6 +2782,12 @@ module Crystal end end + describe TypeOf do + it "executes args" do + assert_macro %({{x.args}}), "[1, 'a', Foo]", {x: TypeOf.new([1.int32, CharLiteral.new('a'), "Foo".path])} + end + end + describe "case methods" do describe "when" do case_node = Case.new(1.int32, [When.new([2.int32, 3.int32] of ASTNode, 4.int32)], 5.int32, exhaustive: false) @@ -3279,16 +3305,207 @@ module Crystal end end + describe LibDef do + lib_def = LibDef.new(Path.new("Foo", "Bar", global: true), FunDef.new("foo")) + + it "executes kind" do + assert_macro %({{x.kind}}), %(lib), {x: lib_def} + end + + it "executes name" do + assert_macro %({{x.name}}), %(::Foo::Bar), {x: lib_def} + assert_macro %({{x.name(generic_args: true)}}), %(::Foo::Bar), {x: lib_def} + assert_macro %({{x.name(generic_args: false)}}), %(::Foo::Bar), {x: lib_def} + assert_macro_error %({{x.name(generic_args: 99)}}), "named argument 'generic_args' to LibDef#name must be a BoolLiteral, not NumberLiteral", {x: lib_def} + end + + it "executes body" do + assert_macro %({{x.body}}), %(fun foo), {x: lib_def} + end + end + + describe CStructOrUnionDef do + c_struct_def = CStructOrUnionDef.new("Foo", TypeDeclaration.new("x".var, "Int".path)) + c_union_def = CStructOrUnionDef.new("Bar", Include.new("Foo".path), union: true) + + it "executes kind" do + assert_macro %({{x.kind}}), %(struct), {x: c_struct_def} + assert_macro %({{x.kind}}), %(union), {x: c_union_def} + end + + it "executes name" do + assert_macro %({{x.name}}), %(Foo), {x: c_struct_def} + assert_macro %({{x.name(generic_args: true)}}), %(Foo), {x: c_struct_def} + assert_macro %({{x.name(generic_args: false)}}), %(Foo), {x: c_struct_def} + assert_macro_error %({{x.name(generic_args: 99)}}), "named argument 'generic_args' to CStructOrUnionDef#name must be a BoolLiteral, not NumberLiteral", {x: c_struct_def} + end + + it "executes body" do + assert_macro %({{x.body}}), %(x : Int), {x: c_struct_def} + assert_macro %({{x.body}}), %(include Foo), {x: c_union_def} + end + + it "executes union?" do + assert_macro %({{x.union?}}), %(false), {x: c_struct_def} + assert_macro %({{x.union?}}), %(true), {x: c_union_def} + end + end + + describe FunDef do + lib_fun = FunDef.new("foo") + top_level_fun = FunDef.new("bar", [Arg.new("x", restriction: "Int32".path), Arg.new("", restriction: "Char".path)], "Void".path, true, 1.int32, "y.z") + top_level_fun2 = FunDef.new("baz", body: Nop.new) + + it "executes name" do + assert_macro %({{x.name}}), %(foo), {x: lib_fun} + assert_macro %({{x.name}}), %(bar), {x: top_level_fun} + end + + it "executes real_name" do + assert_macro %({{x.real_name}}), %(), {x: lib_fun} + assert_macro %({{x.real_name}}), %("y.z"), {x: top_level_fun} + end + + it "executes args" do + assert_macro %({{x.args}}), %([]), {x: lib_fun} + assert_macro %({{x.args}}), %([x : Int32, : Char]), {x: top_level_fun} + end + + it "executes variadic?" do + assert_macro %({{x.variadic?}}), %(false), {x: lib_fun} + assert_macro %({{x.variadic?}}), %(true), {x: top_level_fun} + end + + it "executes return_type" do + assert_macro %({{x.return_type}}), %(), {x: lib_fun} + assert_macro %({{x.return_type}}), %(Void), {x: top_level_fun} + end + + it "executes body" do + assert_macro %({{x.body}}), %(), {x: lib_fun} + assert_macro %({{x.body}}), %(1), {x: top_level_fun} + assert_macro %({{x.body}}), %(), {x: top_level_fun2} + end + + it "executes has_body?" do + assert_macro %({{x.has_body?}}), %(false), {x: lib_fun} + assert_macro %({{x.has_body?}}), %(true), {x: top_level_fun} + assert_macro %({{x.has_body?}}), %(true), {x: top_level_fun2} + end + end + + describe TypeDef do + type_def = TypeDef.new("Foo", Path.new("Bar", "Baz", global: true)) + + it "executes name" do + assert_macro %({{x.name}}), %(Foo), {x: type_def} + end + + it "executes type" do + assert_macro %({{x.type}}), %(::Bar::Baz), {x: type_def} + end + end + + describe ExternalVar do + external_var1 = ExternalVar.new("foo", Path.new("Bar", "Baz")) + external_var2 = ExternalVar.new("X", Generic.new(Path.global("Pointer"), ["Char".path] of ASTNode), real_name: "y.z") + + it "executes name" do + assert_macro %({{x.name}}), %(foo), {x: external_var1} + assert_macro %({{x.name}}), %(X), {x: external_var2} + end + + it "executes real_name" do + assert_macro %({{x.real_name}}), %(), {x: external_var1} + assert_macro %({{x.real_name}}), %("y.z"), {x: external_var2} + end + + it "executes type" do + assert_macro %({{x.type}}), %(Bar::Baz), {x: external_var1} + assert_macro %({{x.type}}), %(::Pointer(Char)), {x: external_var2} + end + end + + describe Asm do + asm1 = Asm.new("nop") + asm2 = Asm.new( + text: "foo", + outputs: [AsmOperand.new("=r", "x".var), AsmOperand.new("=r", "y".var)], + inputs: [AsmOperand.new("i", 1.int32), AsmOperand.new("r", 2.int32)], + clobbers: %w(rax memory), + volatile: true, + alignstack: true, + intel: true, + can_throw: true, + ) + + it "executes text" do + assert_macro %({{x.text}}), %("nop"), {x: asm1} + assert_macro %({{x.text}}), %("foo"), {x: asm2} + end + + it "executes outputs" do + assert_macro %({{x.outputs}}), %([] of ::NoReturn), {x: asm1} + assert_macro %({{x.outputs}}), %(["=r"(x), "=r"(y)]), {x: asm2} + end + + it "executes inputs" do + assert_macro %({{x.inputs}}), %([] of ::NoReturn), {x: asm1} + assert_macro %({{x.inputs}}), %(["i"(1), "r"(2)]), {x: asm2} + end + + it "executes clobbers" do + assert_macro %({{x.clobbers}}), %([] of ::NoReturn), {x: asm1} + assert_macro %({{x.clobbers}}), %(["rax", "memory"]), {x: asm2} + end + + it "executes volatile?" do + assert_macro %({{x.volatile?}}), %(false), {x: asm1} + assert_macro %({{x.volatile?}}), %(true), {x: asm2} + end + + it "executes alignstack?" do + assert_macro %({{x.alignstack?}}), %(false), {x: asm1} + assert_macro %({{x.alignstack?}}), %(true), {x: asm2} + end + + it "executes intel?" do + assert_macro %({{x.intel?}}), %(false), {x: asm1} + assert_macro %({{x.intel?}}), %(true), {x: asm2} + end + + it "executes can_throw?" do + assert_macro %({{x.can_throw?}}), %(false), {x: asm1} + assert_macro %({{x.can_throw?}}), %(true), {x: asm2} + end + end + + describe AsmOperand do + asm_operand1 = AsmOperand.new("=r", "x".var) + asm_operand2 = AsmOperand.new("i", 1.int32) + + it "executes constraint" do + assert_macro %({{x.constraint}}), %("=r"), {x: asm_operand1} + assert_macro %({{x.constraint}}), %("i"), {x: asm_operand2} + end + + it "executes exp" do + assert_macro %({{x.exp}}), %(x), {x: asm_operand1} + assert_macro %({{x.exp}}), %(1), {x: asm_operand2} + end + end + describe "env" do it "has key" do - ENV["FOO"] = "foo" - assert_macro %({{env("FOO")}}), %("foo") - ENV.delete "FOO" + with_env("FOO": "foo") do + assert_macro %({{env("FOO")}}), %("foo") + end end it "doesn't have key" do - ENV.delete "FOO" - assert_macro %({{env("FOO")}}), %(nil) + with_env("FOO": nil) do + assert_macro %({{env("FOO")}}), %(nil) + end end end @@ -3565,7 +3782,7 @@ module Crystal # there are no macro methods with required named parameters it "uses correct name for top-level macro methods" do - assert_macro_error %({{flag?}}), "wrong number of arguments for top-level macro 'flag?' (given 0, expected 1)" + assert_macro_error %({{flag?}}), "wrong number of arguments for macro '::flag?' (given 0, expected 1)" end end diff --git a/spec/compiler/normalize/string_interpolation_spec.cr b/spec/compiler/normalize/string_interpolation_spec.cr index 1347792170b0..f92e6c2a200f 100644 --- a/spec/compiler/normalize/string_interpolation_spec.cr +++ b/spec/compiler/normalize/string_interpolation_spec.cr @@ -52,43 +52,4 @@ describe "Normalize: string interpolation" do string = node.should be_a(StringLiteral) string.value.should eq("hello world") end - - it "replaces char constant" do - result = semantic(%( - def String.interpolation(*args); ""; end - - OBJ = 'l' - - "hello wor\#{OBJ}d" - )) - node = result.node.as(Expressions).last - string = node.should be_a(StringLiteral) - string.value.should eq("hello world") - end - - it "replaces number constant" do - result = semantic(%( - def String.interpolation(*args); ""; end - - OBJ = 9_f32 - - "nine as a float: \#{OBJ}" - )) - node = result.node.as(Expressions).last - string = node.should be_a(StringLiteral) - string.value.should eq("nine as a float: 9.0") - end - - it "replaces boolean constant" do - result = semantic(%( - def String.interpolation(*args); ""; end - - OBJ = false - - "boolean false: \#{OBJ}" - )) - node = result.node.as(Expressions).last - string = node.should be_a(StringLiteral) - string.value.should eq("boolean false: false") - end end diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 41fad5cc3a89..ea230d4e36ac 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -290,9 +290,13 @@ module Crystal assert_syntax_error "def foo=(*args); end", "setter method 'foo=' cannot have more than one parameter" assert_syntax_error "def foo=(**kwargs); end", "setter method 'foo=' cannot have more than one parameter" assert_syntax_error "def foo=(&block); end", "setter method 'foo=' cannot have a block" - assert_syntax_error "def []=(&block); end", "setter method '[]=' cannot have a block" - assert_syntax_error "f.[]= do |a| end", "setter method '[]=' cannot be called with a block" - assert_syntax_error "f.[]= { |bar| }", "setter method '[]=' cannot be called with a block" + + # #10397 + %w(<= >= == != []= ===).each do |operator| + it_parses "def #{operator}(other, file = 1); end", Def.new(operator, ["other".arg, Arg.new("file", 1.int32)]) + it_parses "def #{operator}(*args, **opts); end", Def.new(operator, ["args".arg], splat_index: 0, double_splat: "opts".arg) + it_parses "def #{operator}(*args, **opts, &); end", Def.new(operator, ["args".arg], splat_index: 0, double_splat: "opts".arg, block_arg: Arg.new(""), block_arity: 0) + end # #5895, #6042, #5997 %w( @@ -624,10 +628,12 @@ module Crystal it_parses "->Foo.#{op}(Int32)", ProcPointer.new("Foo".path, op, ["Int32".path] of ASTNode) end - ["bar", "+", "-", "*", "/", "<", "<=", "==", ">", ">=", "%", "|", "&", "^", "**", "===", "=~", "!~"].each do |name| + ["bar", "+", "-", "*", "/", "<", "<=", "==", ">", ">=", "%", "|", "&", "^", "**", "===", "=~", "!=", "[]=", "!~"].each do |name| it_parses "foo.#{name}", Call.new("foo".call, name) it_parses "foo.#{name} 1, 2", Call.new("foo".call, name, 1.int32, 2.int32) it_parses "foo.#{name}(1, 2)", Call.new("foo".call, name, 1.int32, 2.int32) + it_parses "foo.#{name}(1, 2) { 3 }", Call.new("foo".call, name, args: [1.int32, 2.int32] of ASTNode, block: Block.new(body: 3.int32)) + it_parses "foo.#{name} do end", Call.new("foo".call, name, block: Block.new) end ["+", "-", "*", "/", "//", "%", "|", "&", "^", "**", "<<", ">>", "&+", "&-", "&*"].each do |op| @@ -2246,6 +2252,7 @@ module Crystal assert_end_location "class Foo; end" assert_end_location "struct Foo; end" assert_end_location "module Foo; end" + assert_end_location "alias Foo = Bar" assert_end_location "->{ }" assert_end_location "macro foo;end" assert_end_location "macro foo; 123; end" @@ -2499,6 +2506,24 @@ module Crystal name_location.column_number.should eq(12) end + it "sets location of top-level fun name" do + parser = Parser.new("fun foo; end") + node = parser.parse.as(FunDef) + + name_location = node.name_location.should_not be_nil + name_location.line_number.should eq(1) + name_location.column_number.should eq(5) + end + + it "sets location of lib fun name" do + parser = Parser.new("lib Foo; fun foo; end") + node = parser.parse.as(LibDef).body.as(FunDef) + + name_location = node.name_location.should_not be_nil + name_location.line_number.should eq(1) + name_location.column_number.should eq(14) + end + it "sets correct location of proc literal" do parser = Parser.new("->(\n x : Int32,\n y : String\n) { }") node = parser.parse.as(ProcLiteral) diff --git a/spec/compiler/parser/to_s_spec.cr b/spec/compiler/parser/to_s_spec.cr index 752bece45374..63da166aba45 100644 --- a/spec/compiler/parser/to_s_spec.cr +++ b/spec/compiler/parser/to_s_spec.cr @@ -143,10 +143,30 @@ describe "ASTNode#to_s" do expect_to_s %(@[Foo(1, 2, a: 1, b: 2)]) expect_to_s %(lib Foo\nend) expect_to_s %(lib LibC\n fun getchar(Int, Float)\nend) - expect_to_s %(fun foo(a : Void, b : Void, ...) : Void\n\nend) + expect_to_s %(fun foo(a : Void, b : Void, ...) : Void\nend) + expect_to_s %(fun foo\nend) expect_to_s %(lib Foo\n struct Foo\n a : Void\n b : Void\n end\nend) expect_to_s %(lib Foo\n union Foo\n a : Int\n b : Int32\n end\nend) expect_to_s %(lib Foo\n FOO = 0\nend) + expect_to_s <<-CRYSTAL, <<-CRYSTAL + lib Foo + A = Pointer(Void).new(0) + struct B + x : Void* + y : Int[1] + end + fun c(Void*) : Char[2]* + end + CRYSTAL + lib Foo + A = Pointer(Void).new(0) + struct B + x : ::Pointer(Void) + y : ::StaticArray(Int, 1) + end + fun c(::Pointer(Void)) : ::Pointer(::StaticArray(Char, 2)) + end + CRYSTAL expect_to_s %(lib LibC\n fun getch = "get.char"\nend) expect_to_s %(lib Foo::Bar\nend) expect_to_s %(enum Foo\n A = 0\n B\nend) diff --git a/spec/compiler/semantic/doc_spec.cr b/spec/compiler/semantic/doc_spec.cr index 9b38339b6485..3338f920a938 100644 --- a/spec/compiler/semantic/doc_spec.cr +++ b/spec/compiler/semantic/doc_spec.cr @@ -353,6 +353,24 @@ describe "Semantic: doc" do a.locations.not_nil!.size.should eq(1) end + it "stores location for implicit flag enum members" do + result = semantic %( + @[Flags] + enum Foo + A = 1 + B = 2 + end + ), wants_doc: true + program = result.program + foo = program.types["Foo"] + + a_loc = foo.types["All"].locations.should_not be_nil + a_loc.should_not be_empty + + b_loc = foo.types["None"].locations.should_not be_nil + b_loc.should_not be_empty + end + it "stores doc for constant" do result = semantic %( # Hello diff --git a/spec/compiler/semantic/lib_spec.cr b/spec/compiler/semantic/lib_spec.cr index 1ee3c7aa99c6..92526402177d 100644 --- a/spec/compiler/semantic/lib_spec.cr +++ b/spec/compiler/semantic/lib_spec.cr @@ -345,7 +345,55 @@ describe "Semantic: lib" do lib LibFoo end ), - "unknown link argument: 'boo' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config', 'framework', and 'wasm_import_module')" + "unknown link argument: 'boo' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config', 'framework', 'wasm_import_module', and 'dll')" + end + + it "allows dll argument" do + assert_no_errors <<-CRYSTAL + @[Link(dll: "foo.dll")] + lib LibFoo + end + CRYSTAL + + assert_no_errors <<-CRYSTAL + @[Link(dll: "BAR.DLL")] + lib LibFoo + end + CRYSTAL + end + + it "errors if dll argument contains directory separators" do + assert_error <<-CRYSTAL, "'dll' link argument must not include directory separators" + @[Link(dll: "foo/bar.dll")] + lib LibFoo + end + CRYSTAL + + assert_error <<-CRYSTAL, "'dll' link argument must not include directory separators" + @[Link(dll: %q(foo\\bar.dll))] + lib LibFoo + end + CRYSTAL + end + + it "errors if dll argument does not end with '.dll'" do + assert_error <<-CRYSTAL, "'dll' link argument must use a '.dll' file extension" + @[Link(dll: "foo")] + lib LibFoo + end + CRYSTAL + + assert_error <<-CRYSTAL, "'dll' link argument must use a '.dll' file extension" + @[Link(dll: "foo.dylib")] + lib LibFoo + end + CRYSTAL + + assert_error <<-CRYSTAL, "'dll' link argument must use a '.dll' file extension" + @[Link(dll: "")] + lib LibFoo + end + CRYSTAL end it "errors if lib already specified with positional argument" do diff --git a/spec/compiler/semantic/reference_storage_spec.cr b/spec/compiler/semantic/reference_storage_spec.cr new file mode 100644 index 000000000000..a0c0f2343260 --- /dev/null +++ b/spec/compiler/semantic/reference_storage_spec.cr @@ -0,0 +1,72 @@ +require "../../spec_helper" + +describe "Semantic: ReferenceStorage" do + it "errors if T is a struct type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = Foo (T must be a reference type)" + @[Primitive(:ReferenceStorageType)] + struct ReferenceStorage(T) < Value + end + + struct Foo + @x = 1 + end + + ReferenceStorage(Foo) + CRYSTAL + end + + it "errors if T is a value type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = Int32 (T must be a reference type)" + @[Primitive(:ReferenceStorageType)] + struct ReferenceStorage(T) < Value + end + + ReferenceStorage(Int32) + CRYSTAL + end + + it "errors if T is a union type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = (Bar | Foo) (T must be a reference type)" + @[Primitive(:ReferenceStorageType)] + struct ReferenceStorage(T) < Value + end + + class Foo + end + + class Bar + end + + ReferenceStorage(Foo | Bar) + CRYSTAL + end + + it "errors if T is a nilable type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = (Foo | Nil) (T must be a reference type)" + @[Primitive(:ReferenceStorageType)] + struct ReferenceStorage(T) < Value + end + + class Foo + end + + ReferenceStorage(Foo?) + CRYSTAL + end + + it "allows a different name" do + assert_type(<<-CRYSTAL) { types["Foo"].metaclass } + @[Primitive(:ReferenceStorageType)] + struct MyRef(U) < Value + def u + U + end + end + + class Foo + end + + MyRef(Foo).new.u + CRYSTAL + end +end diff --git a/spec/compiler/semantic/restrictions_augmenter_spec.cr b/spec/compiler/semantic/restrictions_augmenter_spec.cr index b3798dc257c0..5095f8613943 100644 --- a/spec/compiler/semantic/restrictions_augmenter_spec.cr +++ b/spec/compiler/semantic/restrictions_augmenter_spec.cr @@ -272,7 +272,7 @@ describe "Semantic: restrictions augmenter" do it "augments typedef" do before = <<-CRYSTAL lib LibFoo - type X = Void* + type X = Int32 end class Foo @x : LibFoo::X @@ -284,7 +284,7 @@ describe "Semantic: restrictions augmenter" do after = <<-CRYSTAL lib LibFoo - type X = Void* + type X = Int32 end class Foo @x : LibFoo::X diff --git a/spec/interpreter_std_spec.cr b/spec/interpreter_std_spec.cr index dee5e0fb75ad..318a4159facf 100644 --- a/spec/interpreter_std_spec.cr +++ b/spec/interpreter_std_spec.cr @@ -72,6 +72,7 @@ require "./std/env_spec.cr" require "./std/errno_spec.cr" # require "./std/exception/call_stack_spec.cr" (failed to run) require "./std/exception_spec.cr" +require "./std/fiber_spec.cr" require "./std/file_spec.cr" require "./std/file/tempfile_spec.cr" require "./std/file_utils_spec.cr" diff --git a/spec/primitives/reference_spec.cr b/spec/primitives/reference_spec.cr index b73553748b65..52f179296ee8 100644 --- a/spec/primitives/reference_spec.cr +++ b/spec/primitives/reference_spec.cr @@ -43,9 +43,7 @@ describe "Primitives: reference" do end it "works when address is on the stack" do - # suitably aligned, sufficient storage for type ID + i64 + ptr - # TODO: use `ReferenceStorage` instead - foo_buffer = uninitialized UInt64[3] + foo_buffer = uninitialized ReferenceStorage(Foo) foo = Foo.pre_initialize(pointerof(foo_buffer)) pointerof(foo_buffer).as(typeof(Foo.crystal_instance_type_id)*).value.should eq(Foo.crystal_instance_type_id) foo.str.should eq("abc") diff --git a/spec/std/crystal/system_spec.cr b/spec/std/crystal/system_spec.cr new file mode 100644 index 000000000000..06bc789055d4 --- /dev/null +++ b/spec/std/crystal/system_spec.cr @@ -0,0 +1,46 @@ +require "spec" + +private def print_error_to_s(format, *args) + io = IO::Memory.new + Crystal::System.print_error(format, *args) do |bytes| + io.write_string(bytes) + end + io.to_s +end + +describe "Crystal::System" do + describe ".print_error" do + it "works" do + print_error_to_s("abcde").should eq("abcde") + end + + it "supports %d" do + print_error_to_s("%d,%d,%d,%d,%d", 0, 1234, Int32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,2147483647,-2147483648,-1") + end + + it "supports %u" do + print_error_to_s("%u,%u,%u,%u,%u", 0, 1234, UInt32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,4294967295,2147483648,4294967295") + end + + it "supports %x" do + print_error_to_s("%x,%x,%x,%x,%x", 0, 0x1234, UInt32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,ffffffff,80000000,ffffffff") + end + + it "supports %p" do + print_error_to_s("%p,%p,%p", Pointer(Void).new(0x0), Pointer(Void).new(0x1234), Pointer(Void).new(UInt64::MAX)).should eq("0x0,0x1234,0xffffffffffffffff") + end + + it "supports %s" do + print_error_to_s("%s,%s,%s", "abc\0def", "ghi".to_unsafe, Pointer(UInt8).null).should eq("abc\0def,ghi,(null)") + end + + it "supports %l width" do + values = {LibC::Long::MIN, LibC::Long::MAX, LibC::LongLong::MIN, LibC::LongLong::MAX} + print_error_to_s("%ld,%ld,%lld,%lld", *values).should eq(values.join(',')) + + values = {LibC::ULong::MIN, LibC::ULong::MAX, LibC::ULongLong::MIN, LibC::ULongLong::MAX} + print_error_to_s("%lu,%lu,%llu,%llu", *values).should eq(values.join(',')) + print_error_to_s("%lx,%lx,%llx,%llx", *values).should eq(values.join(',', &.to_s(16))) + end + end +end diff --git a/spec/std/dir_spec.cr b/spec/std/dir_spec.cr index f0721ef66abb..f0c01d613570 100644 --- a/spec/std/dir_spec.cr +++ b/spec/std/dir_spec.cr @@ -3,25 +3,9 @@ require "../support/env" private def unset_tempdir(&) {% if flag?(:windows) %} - old_tempdirs = {ENV["TMP"]?, ENV["TEMP"]?, ENV["USERPROFILE"]?} - begin - ENV.delete("TMP") - ENV.delete("TEMP") - ENV.delete("USERPROFILE") - - yield - ensure - ENV["TMP"], ENV["TEMP"], ENV["USERPROFILE"] = old_tempdirs - end + with_env("TMP": nil, "TEMP": nil, "USERPROFILE": nil) { yield } {% else %} - begin - old_tempdir = ENV["TMPDIR"]? - ENV.delete("TMPDIR") - - yield - ensure - ENV["TMPDIR"] = old_tempdir - end + with_env("TMPDIR": nil) { yield } {% end %} end diff --git a/spec/std/enumerable_spec.cr b/spec/std/enumerable_spec.cr index 04d46c7976a3..0bcbac725cb5 100644 --- a/spec/std/enumerable_spec.cr +++ b/spec/std/enumerable_spec.cr @@ -131,6 +131,16 @@ describe "Enumerable" do end end + describe "to_a" do + context "with a block" do + SpecEnumerable.new.to_a { |e| e*2 }.should eq [2, 4, 6] + end + + context "without a block" do + SpecEnumerable.new.to_a.should eq [1, 2, 3] + end + end + describe "#to_set" do context "without block" do it "creates a Set from the unique elements of the collection" do diff --git a/spec/std/env_spec.cr b/spec/std/env_spec.cr index 8342494b10f6..038bdc74b9b1 100644 --- a/spec/std/env_spec.cr +++ b/spec/std/env_spec.cr @@ -2,6 +2,23 @@ require "spec" require "./spec_helper" describe "ENV" do + # Preserves the existing environment for each spec. + # To avoid potential circular definitions, this has to use the system methods + # directly, rather than `ENV` or `with_env`. + around_each do |example| + old_env = {} of String => String + Crystal::System::Env.each { |key, value| old_env[key] = value } + + begin + example.run + ensure + keys = [] of String + Crystal::System::Env.each { |key| keys << key } + keys.each { |key| Crystal::System::Env.set(key, nil) } + old_env.each { |key, value| Crystal::System::Env.set(key, value) } + end + end + it "gets non existent key raises" do expect_raises KeyError, "Missing ENV key: \"NON-EXISTENT\"" do ENV["NON-EXISTENT"] @@ -16,8 +33,6 @@ describe "ENV" do (ENV["FOO"] = "1").should eq("1") ENV["FOO"].should eq("1") ENV["FOO"]?.should eq("1") - ensure - ENV.delete("FOO") end {% if flag?(:win32) %} @@ -25,15 +40,11 @@ describe "ENV" do (ENV["FOO"] = "1").should eq("1") ENV["Foo"].should eq("1") ENV["foo"]?.should eq("1") - ensure - ENV.delete("FOO") end {% else %} it "sets and gets case-sensitive" do ENV["FOO"] = "1" ENV["foo"]?.should be_nil - ensure - ENV.delete("FOO") end {% end %} @@ -47,16 +58,12 @@ describe "ENV" do it "sets to empty string" do (ENV["FOO_EMPTY"] = "").should eq "" ENV["FOO_EMPTY"]?.should eq "" - ensure - ENV.delete("FOO_EMPTY") end it "does has_key?" do ENV["FOO"] = "1" ENV.has_key?("NON_EXISTENT").should be_false ENV.has_key?("FOO").should be_true - ensure - ENV.delete("FOO") end it "deletes a key" do @@ -70,9 +77,6 @@ describe "ENV" do %w(FOO BAR).each { |k| ENV.keys.should_not contain(k) } ENV["FOO"] = ENV["BAR"] = "1" %w(FOO BAR).each { |k| ENV.keys.should contain(k) } - ensure - ENV.delete("FOO") - ENV.delete("BAR") end it "does not have an empty key" do @@ -86,9 +90,6 @@ describe "ENV" do ENV["FOO"] = "SOMEVALUE_1" ENV["BAR"] = "SOMEVALUE_2" [1, 2].each { |i| ENV.values.should contain("SOMEVALUE_#{i}") } - ensure - ENV.delete("FOO") - ENV.delete("BAR") end describe "[]=" do @@ -115,16 +116,12 @@ describe "ENV" do it "fetches with one argument" do ENV["1"] = "2" ENV.fetch("1").should eq("2") - ensure - ENV.delete("1") end it "fetches with default value" do ENV["1"] = "2" ENV.fetch("1", "3").should eq("2") ENV.fetch("2", "3").should eq("3") - ensure - ENV.delete("1") end it "fetches with block" do @@ -132,8 +129,6 @@ describe "ENV" do ENV.fetch("1") { |k| k + "block" }.should eq("2") ENV.fetch("2") { |k| k + "block" }.should eq("2block") ENV.fetch("3") { 4 }.should eq(4) - ensure - ENV.delete("1") end it "fetches and raises" do @@ -141,8 +136,6 @@ describe "ENV" do expect_raises KeyError, "Missing ENV key: \"2\"" do ENV.fetch("2") end - ensure - ENV.delete("1") end end @@ -162,16 +155,11 @@ describe "ENV" do "TEST_UNICODE_1" => "bar\u{d7ff}\u{10000}", "TEST_UNICODE_2" => "\u{1234}", }) - ensure - ENV.delete("TEST_UNICODE_1") - ENV.delete("TEST_UNICODE_2") end it "#to_h" do ENV["FOO"] = "foo" ENV.to_h["FOO"].should eq "foo" - ensure - ENV.delete("FOO") end {% if flag?(:win32) %} diff --git a/spec/std/fiber_spec.cr b/spec/std/fiber_spec.cr new file mode 100644 index 000000000000..5c85d1a7475d --- /dev/null +++ b/spec/std/fiber_spec.cr @@ -0,0 +1,21 @@ +require "spec" + +describe Fiber do + it "#resumable?" do + done = false + resumable = nil + + fiber = spawn do + resumable = Fiber.current.resumable? + done = true + end + + fiber.resumable?.should be_true + + until done + Fiber.yield + end + + resumable.should be_false + end +end diff --git a/spec/std/float_printer/ryu_printf_spec.cr b/spec/std/float_printer/ryu_printf_spec.cr index d4ba77bffd94..02ac2944a37d 100644 --- a/spec/std/float_printer/ryu_printf_spec.cr +++ b/spec/std/float_printer/ryu_printf_spec.cr @@ -1,9 +1,9 @@ -# FIXME: this leads to an OOB on wasm32 (#13918) -{% skip_file if flag?(:wasm32) %} +{% skip_file unless String::Formatter::HAS_RYU_PRINTF %} # This file contains test cases derived from: # # * https://github.com/ulfjack/ryu +# * https://github.com/microsoft/STL/tree/main/tests/std/tests/P0067R5_charconv # # The following is their license: # @@ -25,6 +25,7 @@ # KIND, either express or implied. require "spec" +require "../../support/number" require "float/printer/ryu_printf" require "big" require "./ryu_printf_test_cases" @@ -118,6 +119,10 @@ private macro expect_exp(float, precision, string) Float::Printer::RyuPrintf.d2exp({{ float }}, {{ precision }}).should eq({{ string }}) end +private macro expect_gen(float, precision, string, *, file = __FILE__, line = __LINE__) + Float::Printer::RyuPrintf.d2gen({{ float }}, {{ precision }}).should eq({{ string }}), file: {{ file }}, line: {{ line }} +end + describe Float::Printer::RyuPrintf do describe ".d2fixed" do it "Basic" do @@ -491,4 +496,945 @@ describe Float::Printer::RyuPrintf do expect_exp(1e+83, 1, "1.0e+83") end end + + describe ".d2gen" do + it "Basic" do + expect_gen(0.0, 4, "0") + expect_gen(1.729, 4, "1.729") + end + + it "corner cases" do + expect_gen(Float64::MIN_SUBNORMAL, 1000, + "4.940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625e-324") + expect_gen(Float64::MIN_POSITIVE.prev_float, 1000, + "2.2250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375e-308") + expect_gen(Float64::MIN_POSITIVE, 1000, + "2.225073858507201383090232717332404064219215980462331830553327416887204434813918195854283159012511020564067339731035811005152434161553460108856012385377718821130777993532002330479610147442583636071921565046942503734208375250806650616658158948720491179968591639648500635908770118304874799780887753749949451580451605050915399856582470818645113537935804992115981085766051992433352114352390148795699609591288891602992641511063466313393663477586513029371762047325631781485664350872122828637642044846811407613911477062801689853244110024161447421618567166150540154285084716752901903161322778896729707373123334086988983175067838846926092773977972858659654941091369095406136467568702398678315290680984617210924625396728515625e-308") + expect_gen(Float64::MAX, 1000, + "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368") + + expect_gen(Float64::MIN_SUBNORMAL, 6, "4.94066e-324") + expect_gen(Float64::MIN_POSITIVE.prev_float, 6, "2.22507e-308") + expect_gen(Float64::MIN_POSITIVE, 6, "2.22507e-308") + expect_gen(Float64::MAX, 6, "1.79769e+308") + end + + it "maximum-length output" do + expect_gen(hexfloat("0x1.fffffffffffffp-1022"), 1000, + "4.4501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375e-308") + expect_gen(hexfloat("0x1.fffffffffffffp-14"), 1000, + "0.000122070312499999986447472843931194574906839989125728607177734375") + end + + it "varying precision" do + expect_gen(hexfloat("0x1.b04p0"), 0, "2") + expect_gen(hexfloat("0x1.b04p0"), 1, "2") # fixed notation trims decimal point + expect_gen(hexfloat("0x1.b04p0"), 2, "1.7") + expect_gen(hexfloat("0x1.b04p0"), 3, "1.69") + expect_gen(hexfloat("0x1.b04p0"), 4, "1.688") + expect_gen(hexfloat("0x1.b04p0"), 5, "1.6885") + expect_gen(hexfloat("0x1.b04p0"), 6, "1.68848") + expect_gen(hexfloat("0x1.b04p0"), 7, "1.688477") + expect_gen(hexfloat("0x1.b04p0"), 8, "1.6884766") + expect_gen(hexfloat("0x1.b04p0"), 9, "1.68847656") + expect_gen(hexfloat("0x1.b04p0"), 10, "1.688476562") # round to even + expect_gen(hexfloat("0x1.b04p0"), 11, "1.6884765625") # exact + expect_gen(hexfloat("0x1.b04p0"), 12, "1.6884765625") # trim trailing zeros + expect_gen(hexfloat("0x1.b04p0"), 13, "1.6884765625") + + expect_gen(hexfloat("0x1.8p-15"), 0, "5e-5") + expect_gen(hexfloat("0x1.8p-15"), 1, "5e-5") # scientific notation trims decimal point + expect_gen(hexfloat("0x1.8p-15"), 2, "4.6e-5") + expect_gen(hexfloat("0x1.8p-15"), 3, "4.58e-5") + expect_gen(hexfloat("0x1.8p-15"), 4, "4.578e-5") + expect_gen(hexfloat("0x1.8p-15"), 5, "4.5776e-5") + expect_gen(hexfloat("0x1.8p-15"), 6, "4.57764e-5") + expect_gen(hexfloat("0x1.8p-15"), 7, "4.577637e-5") + expect_gen(hexfloat("0x1.8p-15"), 8, "4.5776367e-5") + expect_gen(hexfloat("0x1.8p-15"), 9, "4.57763672e-5") + expect_gen(hexfloat("0x1.8p-15"), 10, "4.577636719e-5") + expect_gen(hexfloat("0x1.8p-15"), 11, "4.5776367188e-5") # round to even + expect_gen(hexfloat("0x1.8p-15"), 12, "4.57763671875e-5") # exact + expect_gen(hexfloat("0x1.8p-15"), 13, "4.57763671875e-5") # trim trailing zeros + expect_gen(hexfloat("0x1.8p-15"), 14, "4.57763671875e-5") + end + + it "trim trailing zeros" do + expect_gen(hexfloat("0x1.80015p0"), 1, "2") # fixed notation trims decimal point + expect_gen(hexfloat("0x1.80015p0"), 2, "1.5") + expect_gen(hexfloat("0x1.80015p0"), 3, "1.5") # general trims trailing zeros + expect_gen(hexfloat("0x1.80015p0"), 4, "1.5") + expect_gen(hexfloat("0x1.80015p0"), 5, "1.5") + expect_gen(hexfloat("0x1.80015p0"), 6, "1.50002") + expect_gen(hexfloat("0x1.80015p0"), 7, "1.50002") + expect_gen(hexfloat("0x1.80015p0"), 8, "1.50002") + expect_gen(hexfloat("0x1.80015p0"), 9, "1.50002003") + expect_gen(hexfloat("0x1.80015p0"), 10, "1.500020027") + expect_gen(hexfloat("0x1.80015p0"), 11, "1.5000200272") + expect_gen(hexfloat("0x1.80015p0"), 12, "1.50002002716") + expect_gen(hexfloat("0x1.80015p0"), 13, "1.500020027161") + expect_gen(hexfloat("0x1.80015p0"), 14, "1.5000200271606") + expect_gen(hexfloat("0x1.80015p0"), 15, "1.50002002716064") + expect_gen(hexfloat("0x1.80015p0"), 16, "1.500020027160645") + expect_gen(hexfloat("0x1.80015p0"), 17, "1.5000200271606445") + expect_gen(hexfloat("0x1.80015p0"), 18, "1.50002002716064453") + expect_gen(hexfloat("0x1.80015p0"), 19, "1.500020027160644531") + expect_gen(hexfloat("0x1.80015p0"), 20, "1.5000200271606445312") # round to even + expect_gen(hexfloat("0x1.80015p0"), 21, "1.50002002716064453125") # exact + end + + it "trim trailing zeros and decimal point" do + expect_gen(hexfloat("0x1.00015p0"), 1, "1") # fixed notation trims decimal point + expect_gen(hexfloat("0x1.00015p0"), 2, "1") # general trims decimal point and trailing zeros + expect_gen(hexfloat("0x1.00015p0"), 3, "1") + expect_gen(hexfloat("0x1.00015p0"), 4, "1") + expect_gen(hexfloat("0x1.00015p0"), 5, "1") + expect_gen(hexfloat("0x1.00015p0"), 6, "1.00002") + expect_gen(hexfloat("0x1.00015p0"), 7, "1.00002") + expect_gen(hexfloat("0x1.00015p0"), 8, "1.00002") + expect_gen(hexfloat("0x1.00015p0"), 9, "1.00002003") + expect_gen(hexfloat("0x1.00015p0"), 10, "1.000020027") + expect_gen(hexfloat("0x1.00015p0"), 11, "1.0000200272") + expect_gen(hexfloat("0x1.00015p0"), 12, "1.00002002716") + expect_gen(hexfloat("0x1.00015p0"), 13, "1.000020027161") + expect_gen(hexfloat("0x1.00015p0"), 14, "1.0000200271606") + expect_gen(hexfloat("0x1.00015p0"), 15, "1.00002002716064") + expect_gen(hexfloat("0x1.00015p0"), 16, "1.000020027160645") + expect_gen(hexfloat("0x1.00015p0"), 17, "1.0000200271606445") + expect_gen(hexfloat("0x1.00015p0"), 18, "1.00002002716064453") + expect_gen(hexfloat("0x1.00015p0"), 19, "1.000020027160644531") + expect_gen(hexfloat("0x1.00015p0"), 20, "1.0000200271606445312") # round to even + expect_gen(hexfloat("0x1.00015p0"), 21, "1.00002002716064453125") # exact + end + + it "trim trailing zeros, scientific notation" do + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 1, "1e-6") # scientific notation trims decimal point + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 2, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 3, "1.3e-6") # general trims trailing zeros + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 4, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 5, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 6, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 7, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 8, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 9, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 10, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 11, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 12, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 13, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 14, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 15, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 16, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 17, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 18, "1.30000000000000005e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 19, "1.300000000000000047e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 20, "1.3000000000000000471e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 21, "1.30000000000000004705e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 22, "1.300000000000000047052e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 23, "1.3000000000000000470517e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 24, "1.30000000000000004705166e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 25, "1.300000000000000047051664e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 26, "1.3000000000000000470516638e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 27, "1.30000000000000004705166378e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 28, "1.30000000000000004705166378e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 29, "1.3000000000000000470516637804e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 30, "1.30000000000000004705166378044e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 31, "1.30000000000000004705166378044e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 32, "1.3000000000000000470516637804397e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 33, "1.30000000000000004705166378043968e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 34, "1.300000000000000047051663780439679e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 35, "1.3000000000000000470516637804396787e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 36, "1.30000000000000004705166378043967867e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 37, "1.300000000000000047051663780439678675e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 38, "1.3000000000000000470516637804396786748e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 39, "1.30000000000000004705166378043967867484e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 40, "1.300000000000000047051663780439678674838e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 41, "1.3000000000000000470516637804396786748384e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 42, "1.30000000000000004705166378043967867483843e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 43, "1.300000000000000047051663780439678674838433e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 44, "1.3000000000000000470516637804396786748384329e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 45, "1.30000000000000004705166378043967867483843293e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 46, "1.300000000000000047051663780439678674838432926e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 47, "1.3000000000000000470516637804396786748384329258e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 48, "1.30000000000000004705166378043967867483843292575e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 49, "1.300000000000000047051663780439678674838432925753e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 50, "1.3000000000000000470516637804396786748384329257533e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 51, "1.3000000000000000470516637804396786748384329257533e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 52, "1.300000000000000047051663780439678674838432925753295e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 53, "1.3000000000000000470516637804396786748384329257532954e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 54, "1.30000000000000004705166378043967867483843292575329542e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 55, "1.300000000000000047051663780439678674838432925753295422e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 56, "1.3000000000000000470516637804396786748384329257532954216e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 57, "1.3000000000000000470516637804396786748384329257532954216e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 58, "1.3000000000000000470516637804396786748384329257532954216e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 59, "1.3000000000000000470516637804396786748384329257532954216003e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 60, "1.30000000000000004705166378043967867483843292575329542160034e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 61, "1.300000000000000047051663780439678674838432925753295421600342e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 62, "1.3000000000000000470516637804396786748384329257532954216003418e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 63, "1.3000000000000000470516637804396786748384329257532954216003418e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 64, "1.300000000000000047051663780439678674838432925753295421600341797e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 65, "1.3000000000000000470516637804396786748384329257532954216003417969e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 66, "1.30000000000000004705166378043967867483843292575329542160034179688e-6") # round to even + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 67, "1.300000000000000047051663780439678674838432925753295421600341796875e-6") # exact + end + + it "trim trailing zeros and decimal point, scientific notation" do + expect_gen(hexfloat("0x1.92a737110e454p-19"), 1, "3e-6") # scientific notation trims decimal point + expect_gen(hexfloat("0x1.92a737110e454p-19"), 2, "3e-6") # general trims decimal point and trailing zeros + expect_gen(hexfloat("0x1.92a737110e454p-19"), 3, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 4, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 5, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 6, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 7, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 8, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 9, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 10, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 11, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 12, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 13, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 14, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 15, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 16, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 17, "3.0000000000000001e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 18, "3.00000000000000008e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 19, "3.000000000000000076e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 20, "3.000000000000000076e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 21, "3.000000000000000076e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 22, "3.000000000000000076003e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 23, "3.0000000000000000760026e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 24, "3.00000000000000007600257e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 25, "3.000000000000000076002572e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 26, "3.0000000000000000760025723e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 27, "3.00000000000000007600257229e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 28, "3.000000000000000076002572291e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 29, "3.0000000000000000760025722912e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 30, "3.00000000000000007600257229123e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 31, "3.000000000000000076002572291234e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 32, "3.0000000000000000760025722912339e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 33, "3.00000000000000007600257229123386e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 34, "3.000000000000000076002572291233861e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 35, "3.0000000000000000760025722912338608e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 36, "3.00000000000000007600257229123386082e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 37, "3.000000000000000076002572291233860824e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 38, "3.0000000000000000760025722912338608239e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 39, "3.00000000000000007600257229123386082392e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 40, "3.000000000000000076002572291233860823922e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 41, "3.0000000000000000760025722912338608239224e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 42, "3.00000000000000007600257229123386082392244e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 43, "3.000000000000000076002572291233860823922441e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 44, "3.0000000000000000760025722912338608239224413e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 45, "3.00000000000000007600257229123386082392244134e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 46, "3.000000000000000076002572291233860823922441341e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 47, "3.000000000000000076002572291233860823922441341e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 48, "3.00000000000000007600257229123386082392244134098e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 49, "3.000000000000000076002572291233860823922441340983e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 50, "3.0000000000000000760025722912338608239224413409829e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 51, "3.00000000000000007600257229123386082392244134098291e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 52, "3.000000000000000076002572291233860823922441340982914e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 53, "3.000000000000000076002572291233860823922441340982914e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 54, "3.00000000000000007600257229123386082392244134098291397e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 55, "3.000000000000000076002572291233860823922441340982913971e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 56, "3.0000000000000000760025722912338608239224413409829139709e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 57, "3.00000000000000007600257229123386082392244134098291397095e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 58, "3.000000000000000076002572291233860823922441340982913970947e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 59, "3.0000000000000000760025722912338608239224413409829139709473e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 60, "3.00000000000000007600257229123386082392244134098291397094727e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 61, "3.000000000000000076002572291233860823922441340982913970947266e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 62, "3.0000000000000000760025722912338608239224413409829139709472656e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 63, "3.00000000000000007600257229123386082392244134098291397094726562e-6") # round to even + expect_gen(hexfloat("0x1.92a737110e454p-19"), 64, "3.000000000000000076002572291233860823922441340982913970947265625e-6") # exact + end + + it "large precision with fixed notation and scientific notation" do + expect_gen(hexfloat("0x1.ba9fbe76c8b44p+0"), 5000, "1.72900000000000009237055564881302416324615478515625") + expect_gen(hexfloat("0x1.d01ff9abb93d1p-20"), 5000, "1.729000000000000090107283613749533657255597063340246677398681640625e-6") + end + + it "transitions between fixed notation and scientific notation" do + expect_gen(5555555.0, 1, "6e+6") + expect_gen(555555.0, 1, "6e+5") + expect_gen(55555.0, 1, "6e+4") + expect_gen(5555.0, 1, "6e+3") + expect_gen(555.0, 1, "6e+2") + expect_gen(55.0, 1, "6e+1") # round to even + expect_gen(5.0, 1, "5") + expect_gen(hexfloat("0x1p-3"), 1, "0.1") # 0.125 + expect_gen(hexfloat("0x1p-6"), 1, "0.02") # 0.015625 + expect_gen(hexfloat("0x1p-9"), 1, "0.002") # 0.001953125 + expect_gen(hexfloat("0x1p-13"), 1, "0.0001") # 0.0001220703125 + expect_gen(hexfloat("0x1p-16"), 1, "2e-5") # 1.52587890625e-5 + expect_gen(hexfloat("0x1p-19"), 1, "2e-6") # 1.9073486328125e-6 + + expect_gen(5555555.0, 2, "5.6e+6") + expect_gen(555555.0, 2, "5.6e+5") + expect_gen(55555.0, 2, "5.6e+4") + expect_gen(5555.0, 2, "5.6e+3") + expect_gen(555.0, 2, "5.6e+2") # round to even + expect_gen(55.0, 2, "55") + expect_gen(5.0, 2, "5") + expect_gen(hexfloat("0x1p-3"), 2, "0.12") # round to even + expect_gen(hexfloat("0x1p-6"), 2, "0.016") + expect_gen(hexfloat("0x1p-9"), 2, "0.002") + expect_gen(hexfloat("0x1p-13"), 2, "0.00012") + expect_gen(hexfloat("0x1p-16"), 2, "1.5e-5") + expect_gen(hexfloat("0x1p-19"), 2, "1.9e-6") + + expect_gen(5555555.0, 3, "5.56e+6") + expect_gen(555555.0, 3, "5.56e+5") + expect_gen(55555.0, 3, "5.56e+4") + expect_gen(5555.0, 3, "5.56e+3") # round to even + expect_gen(555.0, 3, "555") + expect_gen(55.0, 3, "55") + expect_gen(5.0, 3, "5") + expect_gen(hexfloat("0x1p-3"), 3, "0.125") + expect_gen(hexfloat("0x1p-6"), 3, "0.0156") + expect_gen(hexfloat("0x1p-9"), 3, "0.00195") + expect_gen(hexfloat("0x1p-13"), 3, "0.000122") + expect_gen(hexfloat("0x1p-16"), 3, "1.53e-5") + expect_gen(hexfloat("0x1p-19"), 3, "1.91e-6") + + expect_gen(5555555.0, 4, "5.556e+6") + expect_gen(555555.0, 4, "5.556e+5") + expect_gen(55555.0, 4, "5.556e+4") # round to even + expect_gen(5555.0, 4, "5555") + expect_gen(555.0, 4, "555") + expect_gen(55.0, 4, "55") + expect_gen(5.0, 4, "5") + expect_gen(hexfloat("0x1p-3"), 4, "0.125") + expect_gen(hexfloat("0x1p-6"), 4, "0.01562") # round to even + expect_gen(hexfloat("0x1p-9"), 4, "0.001953") + expect_gen(hexfloat("0x1p-13"), 4, "0.0001221") + expect_gen(hexfloat("0x1p-16"), 4, "1.526e-5") + expect_gen(hexfloat("0x1p-19"), 4, "1.907e-6") + + expect_gen(5555555.0, 5, "5.5556e+6") + expect_gen(555555.0, 5, "5.5556e+5") # round to even + expect_gen(55555.0, 5, "55555") + expect_gen(5555.0, 5, "5555") + expect_gen(555.0, 5, "555") + expect_gen(55.0, 5, "55") + expect_gen(5.0, 5, "5") + expect_gen(hexfloat("0x1p-3"), 5, "0.125") + expect_gen(hexfloat("0x1p-6"), 5, "0.015625") + expect_gen(hexfloat("0x1p-9"), 5, "0.0019531") + expect_gen(hexfloat("0x1p-13"), 5, "0.00012207") + expect_gen(hexfloat("0x1p-16"), 5, "1.5259e-5") + expect_gen(hexfloat("0x1p-19"), 5, "1.9073e-6") + end + + it "tricky corner cases" do + expect_gen(999.999, 1, "1e+3") # "%.0e" is "1e+3"; X == 3 + expect_gen(999.999, 2, "1e+3") # "%.1e" is "1.0e+3"; X == 3 + expect_gen(999.999, 3, "1e+3") # "%.2e" is "1.00e+3"; X == 3 + expect_gen(999.999, 4, "1000") # "%.3e" is "1.000e+3"; X == 3 + expect_gen(999.999, 5, "1000") # "%.4e" is "1.0000e+3"; X == 3 + expect_gen(999.999, 6, "999.999") # "%.5e" is "9.99999e+2"; X == 2 + + expect_gen(999.99, 1, "1e+3") + expect_gen(999.99, 2, "1e+3") + expect_gen(999.99, 3, "1e+3") + expect_gen(999.99, 4, "1000") + expect_gen(999.99, 5, "999.99") + expect_gen(999.99, 6, "999.99") + + # C11's Standardese is slightly vague about how to perform the trial formatting in scientific notation, + # but the intention is to use precision P - 1, which is what's used when scientific notation is actually chosen. + # This example verifies this behavior. Here, P == 3 performs trial formatting with "%.2e", triggering rounding. + # That increases X to 3, forcing scientific notation to be chosen. + # If P == 3 performed trial formatting with "%.3e", rounding wouldn't happen, + # X would be 2, and fixed notation would be chosen. + expect_gen(999.9, 1, "1e+3") # "%.0e" is "1e+3"; X == 3 + expect_gen(999.9, 2, "1e+3") # "%.1e" is "1.0e+3"; X == 3 + expect_gen(999.9, 3, "1e+3") # "%.2e" is "1.00e+3"; X == 3; SPECIAL CORNER CASE + expect_gen(999.9, 4, "999.9") # "%.3e" is "9.999e+2"; X == 2 + expect_gen(999.9, 5, "999.9") # "%.4e" is "9.9990e+2"; X == 2 + expect_gen(999.9, 6, "999.9") # "%.5e" is "9.99900e+2"; X == 2 + + expect_gen(999.0, 1, "1e+3") + expect_gen(999.0, 2, "1e+3") + expect_gen(999.0, 3, "999") + expect_gen(999.0, 4, "999") + expect_gen(999.0, 5, "999") + expect_gen(999.0, 6, "999") + + expect_gen(99.9999, 1, "1e+2") + expect_gen(99.9999, 2, "1e+2") + expect_gen(99.9999, 3, "100") + expect_gen(99.9999, 4, "100") + expect_gen(99.9999, 5, "100") + expect_gen(99.9999, 6, "99.9999") + + expect_gen(99.999, 1, "1e+2") + expect_gen(99.999, 2, "1e+2") + expect_gen(99.999, 3, "100") + expect_gen(99.999, 4, "100") + expect_gen(99.999, 5, "99.999") + expect_gen(99.999, 6, "99.999") + + expect_gen(99.99, 1, "1e+2") + expect_gen(99.99, 2, "1e+2") + expect_gen(99.99, 3, "100") + expect_gen(99.99, 4, "99.99") + expect_gen(99.99, 5, "99.99") + expect_gen(99.99, 6, "99.99") + + expect_gen(99.9, 1, "1e+2") + expect_gen(99.9, 2, "1e+2") + expect_gen(99.9, 3, "99.9") + expect_gen(99.9, 4, "99.9") + expect_gen(99.9, 5, "99.9") + expect_gen(99.9, 6, "99.9") + + expect_gen(99.0, 1, "1e+2") + expect_gen(99.0, 2, "99") + expect_gen(99.0, 3, "99") + expect_gen(99.0, 4, "99") + expect_gen(99.0, 5, "99") + expect_gen(99.0, 6, "99") + + expect_gen(9.99999, 1, "1e+1") + expect_gen(9.99999, 2, "10") + expect_gen(9.99999, 3, "10") + expect_gen(9.99999, 4, "10") + expect_gen(9.99999, 5, "10") + expect_gen(9.99999, 6, "9.99999") + + expect_gen(9.9999, 1, "1e+1") + expect_gen(9.9999, 2, "10") + expect_gen(9.9999, 3, "10") + expect_gen(9.9999, 4, "10") + expect_gen(9.9999, 5, "9.9999") + expect_gen(9.9999, 6, "9.9999") + + expect_gen(9.999, 1, "1e+1") + expect_gen(9.999, 2, "10") + expect_gen(9.999, 3, "10") + expect_gen(9.999, 4, "9.999") + expect_gen(9.999, 5, "9.999") + expect_gen(9.999, 6, "9.999") + + expect_gen(9.99, 1, "1e+1") + expect_gen(9.99, 2, "10") + expect_gen(9.99, 3, "9.99") + expect_gen(9.99, 4, "9.99") + expect_gen(9.99, 5, "9.99") + expect_gen(9.99, 6, "9.99") + + expect_gen(9.9, 1, "1e+1") + expect_gen(9.9, 2, "9.9") + expect_gen(9.9, 3, "9.9") + expect_gen(9.9, 4, "9.9") + expect_gen(9.9, 5, "9.9") + expect_gen(9.9, 6, "9.9") + + expect_gen(9.0, 1, "9") + expect_gen(9.0, 2, "9") + expect_gen(9.0, 3, "9") + expect_gen(9.0, 4, "9") + expect_gen(9.0, 5, "9") + expect_gen(9.0, 6, "9") + + expect_gen(0.999999, 1, "1") + expect_gen(0.999999, 2, "1") + expect_gen(0.999999, 3, "1") + expect_gen(0.999999, 4, "1") + expect_gen(0.999999, 5, "1") + expect_gen(0.999999, 6, "0.999999") + + expect_gen(0.99999, 1, "1") + expect_gen(0.99999, 2, "1") + expect_gen(0.99999, 3, "1") + expect_gen(0.99999, 4, "1") + expect_gen(0.99999, 5, "0.99999") + expect_gen(0.99999, 6, "0.99999") + + expect_gen(0.9999, 1, "1") + expect_gen(0.9999, 2, "1") + expect_gen(0.9999, 3, "1") + expect_gen(0.9999, 4, "0.9999") + expect_gen(0.9999, 5, "0.9999") + expect_gen(0.9999, 6, "0.9999") + + expect_gen(0.999, 1, "1") + expect_gen(0.999, 2, "1") + expect_gen(0.999, 3, "0.999") + expect_gen(0.999, 4, "0.999") + expect_gen(0.999, 5, "0.999") + expect_gen(0.999, 6, "0.999") + + expect_gen(0.99, 1, "1") + expect_gen(0.99, 2, "0.99") + expect_gen(0.99, 3, "0.99") + expect_gen(0.99, 4, "0.99") + expect_gen(0.99, 5, "0.99") + expect_gen(0.99, 6, "0.99") + + expect_gen(0.9, 1, "0.9") + expect_gen(0.9, 2, "0.9") + expect_gen(0.9, 3, "0.9") + expect_gen(0.9, 4, "0.9") + expect_gen(0.9, 5, "0.9") + expect_gen(0.9, 6, "0.9") + + expect_gen(0.0999999, 1, "0.1") + expect_gen(0.0999999, 2, "0.1") + expect_gen(0.0999999, 3, "0.1") + expect_gen(0.0999999, 4, "0.1") + expect_gen(0.0999999, 5, "0.1") + expect_gen(0.0999999, 6, "0.0999999") + + expect_gen(0.099999, 1, "0.1") + expect_gen(0.099999, 2, "0.1") + expect_gen(0.099999, 3, "0.1") + expect_gen(0.099999, 4, "0.1") + expect_gen(0.099999, 5, "0.099999") + expect_gen(0.099999, 6, "0.099999") + + expect_gen(0.09999, 1, "0.1") + expect_gen(0.09999, 2, "0.1") + expect_gen(0.09999, 3, "0.1") + expect_gen(0.09999, 4, "0.09999") + expect_gen(0.09999, 5, "0.09999") + expect_gen(0.09999, 6, "0.09999") + + expect_gen(0.0999, 1, "0.1") + expect_gen(0.0999, 2, "0.1") + expect_gen(0.0999, 3, "0.0999") + expect_gen(0.0999, 4, "0.0999") + expect_gen(0.0999, 5, "0.0999") + expect_gen(0.0999, 6, "0.0999") + + expect_gen(0.099, 1, "0.1") + expect_gen(0.099, 2, "0.099") + expect_gen(0.099, 3, "0.099") + expect_gen(0.099, 4, "0.099") + expect_gen(0.099, 5, "0.099") + expect_gen(0.099, 6, "0.099") + + expect_gen(0.09, 1, "0.09") + expect_gen(0.09, 2, "0.09") + expect_gen(0.09, 3, "0.09") + expect_gen(0.09, 4, "0.09") + expect_gen(0.09, 5, "0.09") + expect_gen(0.09, 6, "0.09") + + expect_gen(0.00999999, 1, "0.01") + expect_gen(0.00999999, 2, "0.01") + expect_gen(0.00999999, 3, "0.01") + expect_gen(0.00999999, 4, "0.01") + expect_gen(0.00999999, 5, "0.01") + expect_gen(0.00999999, 6, "0.00999999") + + expect_gen(0.0099999, 1, "0.01") + expect_gen(0.0099999, 2, "0.01") + expect_gen(0.0099999, 3, "0.01") + expect_gen(0.0099999, 4, "0.01") + expect_gen(0.0099999, 5, "0.0099999") + expect_gen(0.0099999, 6, "0.0099999") + + expect_gen(0.009999, 1, "0.01") + expect_gen(0.009999, 2, "0.01") + expect_gen(0.009999, 3, "0.01") + expect_gen(0.009999, 4, "0.009999") + expect_gen(0.009999, 5, "0.009999") + expect_gen(0.009999, 6, "0.009999") + + expect_gen(0.00999, 1, "0.01") + expect_gen(0.00999, 2, "0.01") + expect_gen(0.00999, 3, "0.00999") + expect_gen(0.00999, 4, "0.00999") + expect_gen(0.00999, 5, "0.00999") + expect_gen(0.00999, 6, "0.00999") + + expect_gen(0.0099, 1, "0.01") + expect_gen(0.0099, 2, "0.0099") + expect_gen(0.0099, 3, "0.0099") + expect_gen(0.0099, 4, "0.0099") + expect_gen(0.0099, 5, "0.0099") + expect_gen(0.0099, 6, "0.0099") + + expect_gen(0.009, 1, "0.009") + expect_gen(0.009, 2, "0.009") + expect_gen(0.009, 3, "0.009") + expect_gen(0.009, 4, "0.009") + expect_gen(0.009, 5, "0.009") + expect_gen(0.009, 6, "0.009") + + expect_gen(0.000999999, 1, "0.001") + expect_gen(0.000999999, 2, "0.001") + expect_gen(0.000999999, 3, "0.001") + expect_gen(0.000999999, 4, "0.001") + expect_gen(0.000999999, 5, "0.001") + expect_gen(0.000999999, 6, "0.000999999") + + expect_gen(0.00099999, 1, "0.001") + expect_gen(0.00099999, 2, "0.001") + expect_gen(0.00099999, 3, "0.001") + expect_gen(0.00099999, 4, "0.001") + expect_gen(0.00099999, 5, "0.00099999") + expect_gen(0.00099999, 6, "0.00099999") + + expect_gen(0.0009999, 1, "0.001") + expect_gen(0.0009999, 2, "0.001") + expect_gen(0.0009999, 3, "0.001") + expect_gen(0.0009999, 4, "0.0009999") + expect_gen(0.0009999, 5, "0.0009999") + expect_gen(0.0009999, 6, "0.0009999") + + expect_gen(0.000999, 1, "0.001") + expect_gen(0.000999, 2, "0.001") + expect_gen(0.000999, 3, "0.000999") + expect_gen(0.000999, 4, "0.000999") + expect_gen(0.000999, 5, "0.000999") + expect_gen(0.000999, 6, "0.000999") + + expect_gen(0.00099, 1, "0.001") + expect_gen(0.00099, 2, "0.00099") + expect_gen(0.00099, 3, "0.00099") + expect_gen(0.00099, 4, "0.00099") + expect_gen(0.00099, 5, "0.00099") + expect_gen(0.00099, 6, "0.00099") + + expect_gen(0.0009, 1, "0.0009") + expect_gen(0.0009, 2, "0.0009") + expect_gen(0.0009, 3, "0.0009") + expect_gen(0.0009, 4, "0.0009") + expect_gen(0.0009, 5, "0.0009") + expect_gen(0.0009, 6, "0.0009") + + # Having a scientific exponent X == -5 triggers scientific notation. + # If rounding adjusts this to X == -4, then fixed notation will be selected. + expect_gen(0.0000999999, 1, "0.0001") + expect_gen(0.0000999999, 2, "0.0001") + expect_gen(0.0000999999, 3, "0.0001") + expect_gen(0.0000999999, 4, "0.0001") + expect_gen(0.0000999999, 5, "0.0001") + expect_gen(0.0000999999, 6, "9.99999e-5") + + expect_gen(0.000099999, 1, "0.0001") + expect_gen(0.000099999, 2, "0.0001") + expect_gen(0.000099999, 3, "0.0001") + expect_gen(0.000099999, 4, "0.0001") + expect_gen(0.000099999, 5, "9.9999e-5") + expect_gen(0.000099999, 6, "9.9999e-5") + + expect_gen(0.00009999, 1, "0.0001") + expect_gen(0.00009999, 2, "0.0001") + expect_gen(0.00009999, 3, "0.0001") + expect_gen(0.00009999, 4, "9.999e-5") + expect_gen(0.00009999, 5, "9.999e-5") + expect_gen(0.00009999, 6, "9.999e-5") + + expect_gen(0.0000999, 1, "0.0001") + expect_gen(0.0000999, 2, "0.0001") + expect_gen(0.0000999, 3, "9.99e-5") + expect_gen(0.0000999, 4, "9.99e-5") + expect_gen(0.0000999, 5, "9.99e-5") + expect_gen(0.0000999, 6, "9.99e-5") + + expect_gen(0.000099, 1, "0.0001") + expect_gen(0.000099, 2, "9.9e-5") + expect_gen(0.000099, 3, "9.9e-5") + expect_gen(0.000099, 4, "9.9e-5") + expect_gen(0.000099, 5, "9.9e-5") + expect_gen(0.000099, 6, "9.9e-5") + + expect_gen(0.00009, 1, "9e-5") + expect_gen(0.00009, 2, "9e-5") + expect_gen(0.00009, 3, "9e-5") + expect_gen(0.00009, 4, "9e-5") + expect_gen(0.00009, 5, "9e-5") + expect_gen(0.00009, 6, "9e-5") + + # Rounding test cases without exponent-adjusting behavior. + expect_gen(2999.999, 1, "3e+3") + expect_gen(2999.999, 2, "3e+3") + expect_gen(2999.999, 3, "3e+3") + expect_gen(2999.999, 4, "3000") + expect_gen(2999.999, 5, "3000") + expect_gen(2999.999, 6, "3000") + + expect_gen(2999.99, 1, "3e+3") + expect_gen(2999.99, 2, "3e+3") + expect_gen(2999.99, 3, "3e+3") + expect_gen(2999.99, 4, "3000") + expect_gen(2999.99, 5, "3000") + expect_gen(2999.99, 6, "2999.99") + + expect_gen(2999.9, 1, "3e+3") + expect_gen(2999.9, 2, "3e+3") + expect_gen(2999.9, 3, "3e+3") + expect_gen(2999.9, 4, "3000") + expect_gen(2999.9, 5, "2999.9") + expect_gen(2999.9, 6, "2999.9") + + expect_gen(2999.0, 1, "3e+3") + expect_gen(2999.0, 2, "3e+3") + expect_gen(2999.0, 3, "3e+3") + expect_gen(2999.0, 4, "2999") + expect_gen(2999.0, 5, "2999") + expect_gen(2999.0, 6, "2999") + + expect_gen(299.999, 1, "3e+2") + expect_gen(299.999, 2, "3e+2") + expect_gen(299.999, 3, "300") + expect_gen(299.999, 4, "300") + expect_gen(299.999, 5, "300") + expect_gen(299.999, 6, "299.999") + + expect_gen(299.99, 1, "3e+2") + expect_gen(299.99, 2, "3e+2") + expect_gen(299.99, 3, "300") + expect_gen(299.99, 4, "300") + expect_gen(299.99, 5, "299.99") + expect_gen(299.99, 6, "299.99") + + expect_gen(299.9, 1, "3e+2") + expect_gen(299.9, 2, "3e+2") + expect_gen(299.9, 3, "300") + expect_gen(299.9, 4, "299.9") + expect_gen(299.9, 5, "299.9") + expect_gen(299.9, 6, "299.9") + + expect_gen(299.0, 1, "3e+2") + expect_gen(299.0, 2, "3e+2") + expect_gen(299.0, 3, "299") + expect_gen(299.0, 4, "299") + expect_gen(299.0, 5, "299") + expect_gen(299.0, 6, "299") + + expect_gen(29.999, 1, "3e+1") + expect_gen(29.999, 2, "30") + expect_gen(29.999, 3, "30") + expect_gen(29.999, 4, "30") + expect_gen(29.999, 5, "29.999") + expect_gen(29.999, 6, "29.999") + + expect_gen(29.99, 1, "3e+1") + expect_gen(29.99, 2, "30") + expect_gen(29.99, 3, "30") + expect_gen(29.99, 4, "29.99") + expect_gen(29.99, 5, "29.99") + expect_gen(29.99, 6, "29.99") + + expect_gen(29.9, 1, "3e+1") + expect_gen(29.9, 2, "30") + expect_gen(29.9, 3, "29.9") + expect_gen(29.9, 4, "29.9") + expect_gen(29.9, 5, "29.9") + expect_gen(29.9, 6, "29.9") + + expect_gen(29.0, 1, "3e+1") + expect_gen(29.0, 2, "29") + expect_gen(29.0, 3, "29") + expect_gen(29.0, 4, "29") + expect_gen(29.0, 5, "29") + expect_gen(29.0, 6, "29") + + expect_gen(2.999, 1, "3") + expect_gen(2.999, 2, "3") + expect_gen(2.999, 3, "3") + expect_gen(2.999, 4, "2.999") + expect_gen(2.999, 5, "2.999") + expect_gen(2.999, 6, "2.999") + + expect_gen(2.99, 1, "3") + expect_gen(2.99, 2, "3") + expect_gen(2.99, 3, "2.99") + expect_gen(2.99, 4, "2.99") + expect_gen(2.99, 5, "2.99") + expect_gen(2.99, 6, "2.99") + + expect_gen(2.9, 1, "3") + expect_gen(2.9, 2, "2.9") + expect_gen(2.9, 3, "2.9") + expect_gen(2.9, 4, "2.9") + expect_gen(2.9, 5, "2.9") + expect_gen(2.9, 6, "2.9") + + expect_gen(2.0, 1, "2") + expect_gen(2.0, 2, "2") + expect_gen(2.0, 3, "2") + expect_gen(2.0, 4, "2") + expect_gen(2.0, 5, "2") + expect_gen(2.0, 6, "2") + + expect_gen(0.2999, 1, "0.3") + expect_gen(0.2999, 2, "0.3") + expect_gen(0.2999, 3, "0.3") + expect_gen(0.2999, 4, "0.2999") + expect_gen(0.2999, 5, "0.2999") + expect_gen(0.2999, 6, "0.2999") + + expect_gen(0.299, 1, "0.3") + expect_gen(0.299, 2, "0.3") + expect_gen(0.299, 3, "0.299") + expect_gen(0.299, 4, "0.299") + expect_gen(0.299, 5, "0.299") + expect_gen(0.299, 6, "0.299") + + expect_gen(0.29, 1, "0.3") + expect_gen(0.29, 2, "0.29") + expect_gen(0.29, 3, "0.29") + expect_gen(0.29, 4, "0.29") + expect_gen(0.29, 5, "0.29") + expect_gen(0.29, 6, "0.29") + + expect_gen(0.2, 1, "0.2") + expect_gen(0.2, 2, "0.2") + expect_gen(0.2, 3, "0.2") + expect_gen(0.2, 4, "0.2") + expect_gen(0.2, 5, "0.2") + expect_gen(0.2, 6, "0.2") + + expect_gen(0.02999, 1, "0.03") + expect_gen(0.02999, 2, "0.03") + expect_gen(0.02999, 3, "0.03") + expect_gen(0.02999, 4, "0.02999") + expect_gen(0.02999, 5, "0.02999") + expect_gen(0.02999, 6, "0.02999") + + expect_gen(0.0299, 1, "0.03") + expect_gen(0.0299, 2, "0.03") + expect_gen(0.0299, 3, "0.0299") + expect_gen(0.0299, 4, "0.0299") + expect_gen(0.0299, 5, "0.0299") + expect_gen(0.0299, 6, "0.0299") + + expect_gen(0.029, 1, "0.03") + expect_gen(0.029, 2, "0.029") + expect_gen(0.029, 3, "0.029") + expect_gen(0.029, 4, "0.029") + expect_gen(0.029, 5, "0.029") + expect_gen(0.029, 6, "0.029") + + expect_gen(0.02, 1, "0.02") + expect_gen(0.02, 2, "0.02") + expect_gen(0.02, 3, "0.02") + expect_gen(0.02, 4, "0.02") + expect_gen(0.02, 5, "0.02") + expect_gen(0.02, 6, "0.02") + + expect_gen(0.002999, 1, "0.003") + expect_gen(0.002999, 2, "0.003") + expect_gen(0.002999, 3, "0.003") + expect_gen(0.002999, 4, "0.002999") + expect_gen(0.002999, 5, "0.002999") + expect_gen(0.002999, 6, "0.002999") + + expect_gen(0.00299, 1, "0.003") + expect_gen(0.00299, 2, "0.003") + expect_gen(0.00299, 3, "0.00299") + expect_gen(0.00299, 4, "0.00299") + expect_gen(0.00299, 5, "0.00299") + expect_gen(0.00299, 6, "0.00299") + + expect_gen(0.0029, 1, "0.003") + expect_gen(0.0029, 2, "0.0029") + expect_gen(0.0029, 3, "0.0029") + expect_gen(0.0029, 4, "0.0029") + expect_gen(0.0029, 5, "0.0029") + expect_gen(0.0029, 6, "0.0029") + + expect_gen(0.002, 1, "0.002") + expect_gen(0.002, 2, "0.002") + expect_gen(0.002, 3, "0.002") + expect_gen(0.002, 4, "0.002") + expect_gen(0.002, 5, "0.002") + expect_gen(0.002, 6, "0.002") + + expect_gen(0.0002999, 1, "0.0003") + expect_gen(0.0002999, 2, "0.0003") + expect_gen(0.0002999, 3, "0.0003") + expect_gen(0.0002999, 4, "0.0002999") + expect_gen(0.0002999, 5, "0.0002999") + expect_gen(0.0002999, 6, "0.0002999") + + expect_gen(0.000299, 1, "0.0003") + expect_gen(0.000299, 2, "0.0003") + expect_gen(0.000299, 3, "0.000299") + expect_gen(0.000299, 4, "0.000299") + expect_gen(0.000299, 5, "0.000299") + expect_gen(0.000299, 6, "0.000299") + + expect_gen(0.00029, 1, "0.0003") + expect_gen(0.00029, 2, "0.00029") + expect_gen(0.00029, 3, "0.00029") + expect_gen(0.00029, 4, "0.00029") + expect_gen(0.00029, 5, "0.00029") + expect_gen(0.00029, 6, "0.00029") + + expect_gen(0.0002, 1, "0.0002") + expect_gen(0.0002, 2, "0.0002") + expect_gen(0.0002, 3, "0.0002") + expect_gen(0.0002, 4, "0.0002") + expect_gen(0.0002, 5, "0.0002") + expect_gen(0.0002, 6, "0.0002") + + expect_gen(0.00002999, 1, "3e-5") + expect_gen(0.00002999, 2, "3e-5") + expect_gen(0.00002999, 3, "3e-5") + expect_gen(0.00002999, 4, "2.999e-5") + expect_gen(0.00002999, 5, "2.999e-5") + expect_gen(0.00002999, 6, "2.999e-5") + + expect_gen(0.0000299, 1, "3e-5") + expect_gen(0.0000299, 2, "3e-5") + expect_gen(0.0000299, 3, "2.99e-5") + expect_gen(0.0000299, 4, "2.99e-5") + expect_gen(0.0000299, 5, "2.99e-5") + expect_gen(0.0000299, 6, "2.99e-5") + + expect_gen(0.000029, 1, "3e-5") + expect_gen(0.000029, 2, "2.9e-5") + expect_gen(0.000029, 3, "2.9e-5") + expect_gen(0.000029, 4, "2.9e-5") + expect_gen(0.000029, 5, "2.9e-5") + expect_gen(0.000029, 6, "2.9e-5") + + expect_gen(0.00002, 1, "2e-5") + expect_gen(0.00002, 2, "2e-5") + expect_gen(0.00002, 3, "2e-5") + expect_gen(0.00002, 4, "2e-5") + expect_gen(0.00002, 5, "2e-5") + expect_gen(0.00002, 6, "2e-5") + end + + it "transitions between values of the scientific exponent X" do + {% for tc in GEN_TRANSITIONS %} + expect_gen(hexfloat({{ tc[0] }}), {{ tc[1] }}, {{ tc[2] }}, file: {{ tc.filename }}, line: {{ tc.line_number }}) + {% end %} + end + + it "UCRT had trouble with rounding this value" do + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 105, "109995565999999994887854821710219658911365648587951921896774663603198787416706536331386569598149846892544") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 19, "1.099955659999999949e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 18, "1.09995565999999995e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 17, "1.0999556599999999e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 16, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 15, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 14, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 13, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 12, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 11, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 10, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 9, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 8, "1.0999557e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 7, "1.099956e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 6, "1.09996e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 5, "1.1e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 4, "1.1e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 3, "1.1e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 2, "1.1e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 1, "1e+104") + end + + it "more cases that the UCRT had trouble with (e.g. DevCom-1093399)" do + expect_gen(hexfloat("0x1.8p+62"), 17, "6.9175290276410819e+18") + expect_gen(hexfloat("0x1.0a2742p+17"), 6, "136271") + expect_gen(hexfloat("0x1.f8b0f962cdffbp+205"), 14, "1.0137595739223e+62") + expect_gen(hexfloat("0x1.f8b0f962cdffbp+205"), 17, "1.0137595739222531e+62") + expect_gen(hexfloat("0x1.f8b0f962cdffbp+205"), 51, "1.01375957392225305727423222620636224221808910954041e+62") + expect_gen(hexfloat("0x1.f8b0f962cdffbp+205"), 55, "1.013759573922253057274232226206362242218089109540405973e+62") + end + end end diff --git a/spec/std/float_printer/ryu_printf_test_cases.cr b/spec/std/float_printer/ryu_printf_test_cases.cr index 6c1a3a155692..32448af3bc4d 100644 --- a/spec/std/float_printer/ryu_printf_test_cases.cr +++ b/spec/std/float_printer/ryu_printf_test_cases.cr @@ -2695,3 +2695,1673 @@ ALL_BINARY_EXPONENTS = [ {6.123699292104195e+307, 0, 307}, {1.7026387749989901e+308, 0, 308}, ] of _ + +# For brevity, we avoid testing all possible combinations of P and X. Instead, we test: +# * All values of P where some X can be affected by rounding. (For double, this is [1, 15].) +# * P == 25, which is arbitrary. +# * P == numeric_limits::max_exponent10 + 1. This selects fixed notation for numeric_limits::max(), +# so it's the largest interesting value of P. +# * Finally, we test the transitions around X == P - 1, ensuring that we can recognize every value of X. +GEN_TRANSITIONS = [ + {"0x1.8e757928e0c9dp-14", 1, "9e-5"}, + {"0x1.8e757928e0c9ep-14", 1, "0.0001"}, + {"0x1.f212d77318fc5p-11", 1, "0.0009"}, + {"0x1.f212d77318fc6p-11", 1, "0.001"}, + {"0x1.374bc6a7ef9dbp-7", 1, "0.009"}, + {"0x1.374bc6a7ef9dcp-7", 1, "0.01"}, + {"0x1.851eb851eb851p-4", 1, "0.09"}, + {"0x1.851eb851eb852p-4", 1, "0.1"}, + {"0x1.e666666666666p-1", 1, "0.9"}, + {"0x1.e666666666667p-1", 1, "1"}, + {"0x1.2ffffffffffffp+3", 1, "9"}, + {"0x1.3000000000000p+3", 1, "1e+1"}, + {"0x1.a1554fbdad751p-14", 2, "9.9e-5"}, + {"0x1.a1554fbdad752p-14", 2, "0.0001"}, + {"0x1.04d551d68c692p-10", 2, "0.00099"}, + {"0x1.04d551d68c693p-10", 2, "0.001"}, + {"0x1.460aa64c2f837p-7", 2, "0.0099"}, + {"0x1.460aa64c2f838p-7", 2, "0.01"}, + {"0x1.978d4fdf3b645p-4", 2, "0.099"}, + {"0x1.978d4fdf3b646p-4", 2, "0.1"}, + {"0x1.fd70a3d70a3d7p-1", 2, "0.99"}, + {"0x1.fd70a3d70a3d8p-1", 2, "1"}, + {"0x1.3e66666666666p+3", 2, "9.9"}, + {"0x1.3e66666666667p+3", 2, "10"}, + {"0x1.8dfffffffffffp+6", 2, "99"}, + {"0x1.8e00000000000p+6", 2, "1e+2"}, + {"0x1.a3387ecc8eb96p-14", 3, "9.99e-5"}, + {"0x1.a3387ecc8eb97p-14", 3, "0.0001"}, + {"0x1.06034f3fd933ep-10", 3, "0.000999"}, + {"0x1.06034f3fd933fp-10", 3, "0.001"}, + {"0x1.4784230fcf80dp-7", 3, "0.00999"}, + {"0x1.4784230fcf80ep-7", 3, "0.01"}, + {"0x1.99652bd3c3611p-4", 3, "0.0999"}, + {"0x1.99652bd3c3612p-4", 3, "0.1"}, + {"0x1.ffbe76c8b4395p-1", 3, "0.999"}, + {"0x1.ffbe76c8b4396p-1", 3, "1"}, + {"0x1.3fd70a3d70a3dp+3", 3, "9.99"}, + {"0x1.3fd70a3d70a3ep+3", 3, "10"}, + {"0x1.8fcccccccccccp+6", 3, "99.9"}, + {"0x1.8fccccccccccdp+6", 3, "100"}, + {"0x1.f3bffffffffffp+9", 3, "999"}, + {"0x1.f3c0000000000p+9", 3, "1e+3"}, + {"0x1.a368d04e0ba6ap-14", 4, "9.999e-5"}, + {"0x1.a368d04e0ba6bp-14", 4, "0.0001"}, + {"0x1.06218230c7482p-10", 4, "0.0009999"}, + {"0x1.06218230c7483p-10", 4, "0.001"}, + {"0x1.47a9e2bcf91a3p-7", 4, "0.009999"}, + {"0x1.47a9e2bcf91a4p-7", 4, "0.01"}, + {"0x1.99945b6c3760bp-4", 4, "0.09999"}, + {"0x1.99945b6c3760cp-4", 4, "0.1"}, + {"0x1.fff972474538ep-1", 4, "0.9999"}, + {"0x1.fff972474538fp-1", 4, "1"}, + {"0x1.3ffbe76c8b439p+3", 4, "9.999"}, + {"0x1.3ffbe76c8b43ap+3", 4, "10"}, + {"0x1.8ffae147ae147p+6", 4, "99.99"}, + {"0x1.8ffae147ae148p+6", 4, "100"}, + {"0x1.f3f9999999999p+9", 4, "999.9"}, + {"0x1.f3f999999999ap+9", 4, "1000"}, + {"0x1.387bfffffffffp+13", 4, "9999"}, + {"0x1.387c000000000p+13", 4, "1e+4"}, + {"0x1.a36da54164f19p-14", 5, "9.9999e-5"}, + {"0x1.a36da54164f1ap-14", 5, "0.0001"}, + {"0x1.06248748df16fp-10", 5, "0.00099999"}, + {"0x1.06248748df170p-10", 5, "0.001"}, + {"0x1.47ada91b16dcbp-7", 5, "0.0099999"}, + {"0x1.47ada91b16dccp-7", 5, "0.01"}, + {"0x1.99991361dc93ep-4", 5, "0.099999"}, + {"0x1.99991361dc93fp-4", 5, "0.1"}, + {"0x1.ffff583a53b8ep-1", 5, "0.99999"}, + {"0x1.ffff583a53b8fp-1", 5, "1"}, + {"0x1.3fff972474538p+3", 5, "9.9999"}, + {"0x1.3fff972474539p+3", 5, "10"}, + {"0x1.8fff7ced91687p+6", 5, "99.999"}, + {"0x1.8fff7ced91688p+6", 5, "100"}, + {"0x1.f3ff5c28f5c28p+9", 5, "999.99"}, + {"0x1.f3ff5c28f5c29p+9", 5, "1000"}, + {"0x1.387f999999999p+13", 5, "9999.9"}, + {"0x1.387f99999999ap+13", 5, "10000"}, + {"0x1.869f7ffffffffp+16", 5, "99999"}, + {"0x1.869f800000000p+16", 5, "1e+5"}, + {"0x1.a36e20f35445dp-14", 6, "9.99999e-5"}, + {"0x1.a36e20f35445ep-14", 6, "0.0001"}, + {"0x1.0624d49814abap-10", 6, "0.000999999"}, + {"0x1.0624d49814abbp-10", 6, "0.001"}, + {"0x1.47ae09be19d69p-7", 6, "0.00999999"}, + {"0x1.47ae09be19d6ap-7", 6, "0.01"}, + {"0x1.99998c2da04c3p-4", 6, "0.0999999"}, + {"0x1.99998c2da04c4p-4", 6, "0.1"}, + {"0x1.ffffef39085f4p-1", 6, "0.999999"}, + {"0x1.ffffef39085f5p-1", 6, "1"}, + {"0x1.3ffff583a53b8p+3", 6, "9.99999"}, + {"0x1.3ffff583a53b9p+3", 6, "10"}, + {"0x1.8ffff2e48e8a7p+6", 6, "99.9999"}, + {"0x1.8ffff2e48e8a8p+6", 6, "100"}, + {"0x1.f3ffef9db22d0p+9", 6, "999.999"}, + {"0x1.f3ffef9db22d1p+9", 6, "1000"}, + {"0x1.387ff5c28f5c2p+13", 6, "9999.99"}, + {"0x1.387ff5c28f5c3p+13", 6, "10000"}, + {"0x1.869ff33333333p+16", 6, "99999.9"}, + {"0x1.869ff33333334p+16", 6, "100000"}, + {"0x1.e847effffffffp+19", 6, "999999"}, + {"0x1.e847f00000000p+19", 6, "1e+6"}, + {"0x1.a36e2d51ec34bp-14", 7, "9.999999e-5"}, + {"0x1.a36e2d51ec34cp-14", 7, "0.0001"}, + {"0x1.0624dc5333a0ep-10", 7, "0.0009999999"}, + {"0x1.0624dc5333a0fp-10", 7, "0.001"}, + {"0x1.47ae136800892p-7", 7, "0.009999999"}, + {"0x1.47ae136800893p-7", 7, "0.01"}, + {"0x1.9999984200ab7p-4", 7, "0.09999999"}, + {"0x1.9999984200ab8p-4", 7, "0.1"}, + {"0x1.fffffe5280d65p-1", 7, "0.9999999"}, + {"0x1.fffffe5280d66p-1", 7, "1"}, + {"0x1.3ffffef39085fp+3", 7, "9.999999"}, + {"0x1.3ffffef390860p+3", 7, "10"}, + {"0x1.8ffffeb074a77p+6", 7, "99.99999"}, + {"0x1.8ffffeb074a78p+6", 7, "100"}, + {"0x1.f3fffe5c91d14p+9", 7, "999.9999"}, + {"0x1.f3fffe5c91d15p+9", 7, "1000"}, + {"0x1.387ffef9db22dp+13", 7, "9999.999"}, + {"0x1.387ffef9db22ep+13", 7, "10000"}, + {"0x1.869ffeb851eb8p+16", 7, "99999.99"}, + {"0x1.869ffeb851eb9p+16", 7, "100000"}, + {"0x1.e847fe6666666p+19", 7, "999999.9"}, + {"0x1.e847fe6666667p+19", 7, "1000000"}, + {"0x1.312cfefffffffp+23", 7, "9999999"}, + {"0x1.312cff0000000p+23", 7, "1e+7"}, + {"0x1.a36e2e8e94ffcp-14", 8, "9.9999999e-5"}, + {"0x1.a36e2e8e94ffdp-14", 8, "0.0001"}, + {"0x1.0624dd191d1fdp-10", 8, "0.00099999999"}, + {"0x1.0624dd191d1fep-10", 8, "0.001"}, + {"0x1.47ae145f6467dp-7", 8, "0.0099999999"}, + {"0x1.47ae145f6467ep-7", 8, "0.01"}, + {"0x1.999999773d81cp-4", 8, "0.099999999"}, + {"0x1.999999773d81dp-4", 8, "0.1"}, + {"0x1.ffffffd50ce23p-1", 8, "0.99999999"}, + {"0x1.ffffffd50ce24p-1", 8, "1"}, + {"0x1.3fffffe5280d6p+3", 8, "9.9999999"}, + {"0x1.3fffffe5280d7p+3", 8, "10"}, + {"0x1.8fffffde7210bp+6", 8, "99.999999"}, + {"0x1.8fffffde7210cp+6", 8, "100"}, + {"0x1.f3ffffd60e94ep+9", 8, "999.99999"}, + {"0x1.f3ffffd60e94fp+9", 8, "1000"}, + {"0x1.387fffe5c91d1p+13", 8, "9999.9999"}, + {"0x1.387fffe5c91d2p+13", 8, "10000"}, + {"0x1.869fffdf3b645p+16", 8, "99999.999"}, + {"0x1.869fffdf3b646p+16", 8, "100000"}, + {"0x1.e847ffd70a3d7p+19", 8, "999999.99"}, + {"0x1.e847ffd70a3d8p+19", 8, "1000000"}, + {"0x1.312cffe666666p+23", 8, "9999999.9"}, + {"0x1.312cffe666667p+23", 8, "10000000"}, + {"0x1.7d783fdffffffp+26", 8, "99999999"}, + {"0x1.7d783fe000000p+26", 8, "1e+8"}, + {"0x1.a36e2eae3f7a7p-14", 9, "9.99999999e-5"}, + {"0x1.a36e2eae3f7a8p-14", 9, "0.0001"}, + {"0x1.0624dd2ce7ac8p-10", 9, "0.000999999999"}, + {"0x1.0624dd2ce7ac9p-10", 9, "0.001"}, + {"0x1.47ae14782197bp-7", 9, "0.00999999999"}, + {"0x1.47ae14782197cp-7", 9, "0.01"}, + {"0x1.9999999629fd9p-4", 9, "0.0999999999"}, + {"0x1.9999999629fdap-4", 9, "0.1"}, + {"0x1.fffffffbb47d0p-1", 9, "0.999999999"}, + {"0x1.fffffffbb47d1p-1", 9, "1"}, + {"0x1.3ffffffd50ce2p+3", 9, "9.99999999"}, + {"0x1.3ffffffd50ce3p+3", 9, "10"}, + {"0x1.8ffffffca501ap+6", 9, "99.9999999"}, + {"0x1.8ffffffca501bp+6", 9, "100"}, + {"0x1.f3fffffbce421p+9", 9, "999.999999"}, + {"0x1.f3fffffbce422p+9", 9, "1000"}, + {"0x1.387ffffd60e94p+13", 9, "9999.99999"}, + {"0x1.387ffffd60e95p+13", 9, "10000"}, + {"0x1.869ffffcb923ap+16", 9, "99999.9999"}, + {"0x1.869ffffcb923bp+16", 9, "100000"}, + {"0x1.e847fffbe76c8p+19", 9, "999999.999"}, + {"0x1.e847fffbe76c9p+19", 9, "1000000"}, + {"0x1.312cfffd70a3dp+23", 9, "9999999.99"}, + {"0x1.312cfffd70a3ep+23", 9, "10000000"}, + {"0x1.7d783ffccccccp+26", 9, "99999999.9"}, + {"0x1.7d783ffcccccdp+26", 9, "100000000"}, + {"0x1.dcd64ffbfffffp+29", 9, "999999999"}, + {"0x1.dcd64ffc00000p+29", 9, "1e+9"}, + {"0x1.a36e2eb16a205p-14", 10, "9.999999999e-5"}, + {"0x1.a36e2eb16a206p-14", 10, "0.0001"}, + {"0x1.0624dd2ee2543p-10", 10, "0.0009999999999"}, + {"0x1.0624dd2ee2544p-10", 10, "0.001"}, + {"0x1.47ae147a9ae94p-7", 10, "0.009999999999"}, + {"0x1.47ae147a9ae95p-7", 10, "0.01"}, + {"0x1.9999999941a39p-4", 10, "0.09999999999"}, + {"0x1.9999999941a3ap-4", 10, "0.1"}, + {"0x1.ffffffff920c8p-1", 10, "0.9999999999"}, + {"0x1.ffffffff920c9p-1", 10, "1"}, + {"0x1.3fffffffbb47dp+3", 10, "9.999999999"}, + {"0x1.3fffffffbb47ep+3", 10, "10"}, + {"0x1.8fffffffaa19cp+6", 10, "99.99999999"}, + {"0x1.8fffffffaa19dp+6", 10, "100"}, + {"0x1.f3ffffff94a03p+9", 10, "999.9999999"}, + {"0x1.f3ffffff94a04p+9", 10, "1000"}, + {"0x1.387fffffbce42p+13", 10, "9999.999999"}, + {"0x1.387fffffbce43p+13", 10, "10000"}, + {"0x1.869fffffac1d2p+16", 10, "99999.99999"}, + {"0x1.869fffffac1d3p+16", 10, "100000"}, + {"0x1.e847ffff97247p+19", 10, "999999.9999"}, + {"0x1.e847ffff97248p+19", 10, "1000000"}, + {"0x1.312cffffbe76cp+23", 10, "9999999.999"}, + {"0x1.312cffffbe76dp+23", 10, "10000000"}, + {"0x1.7d783fffae147p+26", 10, "99999999.99"}, + {"0x1.7d783fffae148p+26", 10, "100000000"}, + {"0x1.dcd64fff99999p+29", 10, "999999999.9"}, + {"0x1.dcd64fff9999ap+29", 10, "1000000000"}, + {"0x1.2a05f1ffbffffp+33", 10, "9999999999"}, + {"0x1.2a05f1ffc0000p+33", 10, "1e+10"}, + {"0x1.a36e2eb1bb30fp-14", 11, "9.9999999999e-5"}, + {"0x1.a36e2eb1bb310p-14", 11, "0.0001"}, + {"0x1.0624dd2f14fe9p-10", 11, "0.00099999999999"}, + {"0x1.0624dd2f14feap-10", 11, "0.001"}, + {"0x1.47ae147ada3e3p-7", 11, "0.0099999999999"}, + {"0x1.47ae147ada3e4p-7", 11, "0.01"}, + {"0x1.9999999990cdcp-4", 11, "0.099999999999"}, + {"0x1.9999999990cddp-4", 11, "0.1"}, + {"0x1.fffffffff5014p-1", 11, "0.99999999999"}, + {"0x1.fffffffff5015p-1", 11, "1"}, + {"0x1.3ffffffff920cp+3", 11, "9.9999999999"}, + {"0x1.3ffffffff920dp+3", 11, "10"}, + {"0x1.8ffffffff768fp+6", 11, "99.999999999"}, + {"0x1.8ffffffff7690p+6", 11, "100"}, + {"0x1.f3fffffff5433p+9", 11, "999.99999999"}, + {"0x1.f3fffffff5434p+9", 11, "1000"}, + {"0x1.387ffffff94a0p+13", 11, "9999.9999999"}, + {"0x1.387ffffff94a1p+13", 11, "10000"}, + {"0x1.869ffffff79c8p+16", 11, "99999.999999"}, + {"0x1.869ffffff79c9p+16", 11, "100000"}, + {"0x1.e847fffff583ap+19", 11, "999999.99999"}, + {"0x1.e847fffff583bp+19", 11, "1000000"}, + {"0x1.312cfffff9724p+23", 11, "9999999.9999"}, + {"0x1.312cfffff9725p+23", 11, "10000000"}, + {"0x1.7d783ffff7cedp+26", 11, "99999999.999"}, + {"0x1.7d783ffff7ceep+26", 11, "100000000"}, + {"0x1.dcd64ffff5c28p+29", 11, "999999999.99"}, + {"0x1.dcd64ffff5c29p+29", 11, "1000000000"}, + {"0x1.2a05f1fff9999p+33", 11, "9999999999.9"}, + {"0x1.2a05f1fff999ap+33", 11, "10000000000"}, + {"0x1.74876e7ff7fffp+36", 11, "99999999999"}, + {"0x1.74876e7ff8000p+36", 11, "1e+11"}, + {"0x1.a36e2eb1c34c3p-14", 12, "9.99999999999e-5"}, + {"0x1.a36e2eb1c34c4p-14", 12, "0.0001"}, + {"0x1.0624dd2f1a0fap-10", 12, "0.000999999999999"}, + {"0x1.0624dd2f1a0fbp-10", 12, "0.001"}, + {"0x1.47ae147ae0938p-7", 12, "0.00999999999999"}, + {"0x1.47ae147ae0939p-7", 12, "0.01"}, + {"0x1.9999999998b86p-4", 12, "0.0999999999999"}, + {"0x1.9999999998b87p-4", 12, "0.1"}, + {"0x1.fffffffffee68p-1", 12, "0.999999999999"}, + {"0x1.fffffffffee69p-1", 12, "1"}, + {"0x1.3fffffffff501p+3", 12, "9.99999999999"}, + {"0x1.3fffffffff502p+3", 12, "10"}, + {"0x1.8fffffffff241p+6", 12, "99.9999999999"}, + {"0x1.8fffffffff242p+6", 12, "100"}, + {"0x1.f3fffffffeed1p+9", 12, "999.999999999"}, + {"0x1.f3fffffffeed2p+9", 12, "1000"}, + {"0x1.387fffffff543p+13", 12, "9999.99999999"}, + {"0x1.387fffffff544p+13", 12, "10000"}, + {"0x1.869fffffff294p+16", 12, "99999.9999999"}, + {"0x1.869fffffff295p+16", 12, "100000"}, + {"0x1.e847fffffef39p+19", 12, "999999.999999"}, + {"0x1.e847fffffef3ap+19", 12, "1000000"}, + {"0x1.312cffffff583p+23", 12, "9999999.99999"}, + {"0x1.312cffffff584p+23", 12, "10000000"}, + {"0x1.7d783fffff2e4p+26", 12, "99999999.9999"}, + {"0x1.7d783fffff2e5p+26", 12, "100000000"}, + {"0x1.dcd64ffffef9dp+29", 12, "999999999.999"}, + {"0x1.dcd64ffffef9ep+29", 12, "1000000000"}, + {"0x1.2a05f1ffff5c2p+33", 12, "9999999999.99"}, + {"0x1.2a05f1ffff5c3p+33", 12, "10000000000"}, + {"0x1.74876e7fff333p+36", 12, "99999999999.9"}, + {"0x1.74876e7fff334p+36", 12, "100000000000"}, + {"0x1.d1a94a1ffefffp+39", 12, "999999999999"}, + {"0x1.d1a94a1fff000p+39", 12, "1e+12"}, + {"0x1.a36e2eb1c41bbp-14", 13, "9.999999999999e-5"}, + {"0x1.a36e2eb1c41bcp-14", 13, "0.0001"}, + {"0x1.0624dd2f1a915p-10", 13, "0.0009999999999999"}, + {"0x1.0624dd2f1a916p-10", 13, "0.001"}, + {"0x1.47ae147ae135ap-7", 13, "0.009999999999999"}, + {"0x1.47ae147ae135bp-7", 13, "0.01"}, + {"0x1.9999999999831p-4", 13, "0.09999999999999"}, + {"0x1.9999999999832p-4", 13, "0.1"}, + {"0x1.ffffffffffe3dp-1", 13, "0.9999999999999"}, + {"0x1.ffffffffffe3ep-1", 13, "1"}, + {"0x1.3fffffffffee6p+3", 13, "9.999999999999"}, + {"0x1.3fffffffffee7p+3", 13, "10"}, + {"0x1.8fffffffffea0p+6", 13, "99.99999999999"}, + {"0x1.8fffffffffea1p+6", 13, "100"}, + {"0x1.f3ffffffffe48p+9", 13, "999.9999999999"}, + {"0x1.f3ffffffffe49p+9", 13, "1000"}, + {"0x1.387fffffffeedp+13", 13, "9999.999999999"}, + {"0x1.387fffffffeeep+13", 13, "10000"}, + {"0x1.869fffffffea8p+16", 13, "99999.99999999"}, + {"0x1.869fffffffea9p+16", 13, "100000"}, + {"0x1.e847ffffffe52p+19", 13, "999999.9999999"}, + {"0x1.e847ffffffe53p+19", 13, "1000000"}, + {"0x1.312cffffffef3p+23", 13, "9999999.999999"}, + {"0x1.312cffffffef4p+23", 13, "10000000"}, + {"0x1.7d783fffffeb0p+26", 13, "99999999.99999"}, + {"0x1.7d783fffffeb1p+26", 13, "100000000"}, + {"0x1.dcd64fffffe5cp+29", 13, "999999999.9999"}, + {"0x1.dcd64fffffe5dp+29", 13, "1000000000"}, + {"0x1.2a05f1ffffef9p+33", 13, "9999999999.999"}, + {"0x1.2a05f1ffffefap+33", 13, "10000000000"}, + {"0x1.74876e7fffeb8p+36", 13, "99999999999.99"}, + {"0x1.74876e7fffeb9p+36", 13, "100000000000"}, + {"0x1.d1a94a1fffe66p+39", 13, "999999999999.9"}, + {"0x1.d1a94a1fffe67p+39", 13, "1000000000000"}, + {"0x1.2309ce53ffeffp+43", 13, "9999999999999"}, + {"0x1.2309ce53fff00p+43", 13, "1e+13"}, + {"0x1.a36e2eb1c4307p-14", 14, "9.9999999999999e-5"}, + {"0x1.a36e2eb1c4308p-14", 14, "0.0001"}, + {"0x1.0624dd2f1a9e4p-10", 14, "0.00099999999999999"}, + {"0x1.0624dd2f1a9e5p-10", 14, "0.001"}, + {"0x1.47ae147ae145ep-7", 14, "0.0099999999999999"}, + {"0x1.47ae147ae145fp-7", 14, "0.01"}, + {"0x1.9999999999975p-4", 14, "0.099999999999999"}, + {"0x1.9999999999976p-4", 14, "0.1"}, + {"0x1.fffffffffffd2p-1", 14, "0.99999999999999"}, + {"0x1.fffffffffffd3p-1", 14, "1"}, + {"0x1.3ffffffffffe3p+3", 14, "9.9999999999999"}, + {"0x1.3ffffffffffe4p+3", 14, "10"}, + {"0x1.8ffffffffffdcp+6", 14, "99.999999999999"}, + {"0x1.8ffffffffffddp+6", 14, "100"}, + {"0x1.f3fffffffffd4p+9", 14, "999.99999999999"}, + {"0x1.f3fffffffffd5p+9", 14, "1000"}, + {"0x1.387ffffffffe4p+13", 14, "9999.9999999999"}, + {"0x1.387ffffffffe5p+13", 14, "10000"}, + {"0x1.869ffffffffddp+16", 14, "99999.999999999"}, + {"0x1.869ffffffffdep+16", 14, "100000"}, + {"0x1.e847fffffffd5p+19", 14, "999999.99999999"}, + {"0x1.e847fffffffd6p+19", 14, "1000000"}, + {"0x1.312cfffffffe5p+23", 14, "9999999.9999999"}, + {"0x1.312cfffffffe6p+23", 14, "10000000"}, + {"0x1.7d783ffffffdep+26", 14, "99999999.999999"}, + {"0x1.7d783ffffffdfp+26", 14, "100000000"}, + {"0x1.dcd64ffffffd6p+29", 14, "999999999.99999"}, + {"0x1.dcd64ffffffd7p+29", 14, "1000000000"}, + {"0x1.2a05f1fffffe5p+33", 14, "9999999999.9999"}, + {"0x1.2a05f1fffffe6p+33", 14, "10000000000"}, + {"0x1.74876e7ffffdfp+36", 14, "99999999999.999"}, + {"0x1.74876e7ffffe0p+36", 14, "100000000000"}, + {"0x1.d1a94a1ffffd7p+39", 14, "999999999999.99"}, + {"0x1.d1a94a1ffffd8p+39", 14, "1000000000000"}, + {"0x1.2309ce53fffe6p+43", 14, "9999999999999.9"}, + {"0x1.2309ce53fffe7p+43", 14, "10000000000000"}, + {"0x1.6bcc41e8fffdfp+46", 14, "99999999999999"}, + {"0x1.6bcc41e8fffe0p+46", 14, "1e+14"}, + {"0x1.a36e2eb1c4328p-14", 15, "9.99999999999999e-5"}, + {"0x1.a36e2eb1c4329p-14", 15, "0.0001"}, + {"0x1.0624dd2f1a9f9p-10", 15, "0.000999999999999999"}, + {"0x1.0624dd2f1a9fap-10", 15, "0.001"}, + {"0x1.47ae147ae1477p-7", 15, "0.00999999999999999"}, + {"0x1.47ae147ae1478p-7", 15, "0.01"}, + {"0x1.9999999999995p-4", 15, "0.0999999999999999"}, + {"0x1.9999999999996p-4", 15, "0.1"}, + {"0x1.ffffffffffffbp-1", 15, "0.999999999999999"}, + {"0x1.ffffffffffffcp-1", 15, "1"}, + {"0x1.3fffffffffffdp+3", 15, "9.99999999999999"}, + {"0x1.3fffffffffffep+3", 15, "10"}, + {"0x1.8fffffffffffcp+6", 15, "99.9999999999999"}, + {"0x1.8fffffffffffdp+6", 15, "100"}, + {"0x1.f3ffffffffffbp+9", 15, "999.999999999999"}, + {"0x1.f3ffffffffffcp+9", 15, "1000"}, + {"0x1.387fffffffffdp+13", 15, "9999.99999999999"}, + {"0x1.387fffffffffep+13", 15, "10000"}, + {"0x1.869fffffffffcp+16", 15, "99999.9999999999"}, + {"0x1.869fffffffffdp+16", 15, "100000"}, + {"0x1.e847ffffffffbp+19", 15, "999999.999999999"}, + {"0x1.e847ffffffffcp+19", 15, "1000000"}, + {"0x1.312cffffffffdp+23", 15, "9999999.99999999"}, + {"0x1.312cffffffffep+23", 15, "10000000"}, + {"0x1.7d783fffffffcp+26", 15, "99999999.9999999"}, + {"0x1.7d783fffffffdp+26", 15, "100000000"}, + {"0x1.dcd64fffffffbp+29", 15, "999999999.999999"}, + {"0x1.dcd64fffffffcp+29", 15, "1000000000"}, + {"0x1.2a05f1ffffffdp+33", 15, "9999999999.99999"}, + {"0x1.2a05f1ffffffep+33", 15, "10000000000"}, + {"0x1.74876e7fffffcp+36", 15, "99999999999.9999"}, + {"0x1.74876e7fffffdp+36", 15, "100000000000"}, + {"0x1.d1a94a1fffffbp+39", 15, "999999999999.999"}, + {"0x1.d1a94a1fffffcp+39", 15, "1000000000000"}, + {"0x1.2309ce53ffffdp+43", 15, "9999999999999.99"}, + {"0x1.2309ce53ffffep+43", 15, "10000000000000"}, + {"0x1.6bcc41e8ffffcp+46", 15, "99999999999999.9"}, + {"0x1.6bcc41e8ffffdp+46", 15, "100000000000000"}, + {"0x1.c6bf52633fffbp+49", 15, "999999999999999"}, + {"0x1.c6bf52633fffcp+49", 15, "1e+15"}, + {"0x1.1c37937e07fffp+53", 16, "9999999999999998"}, + {"0x1.1c37937e08000p+53", 16, "1e+16"}, + {"0x1.6345785d89fffp+56", 17, "99999999999999984"}, + {"0x1.6345785d8a000p+56", 17, "1e+17"}, + {"0x1.bc16d674ec7ffp+59", 18, "999999999999999872"}, + {"0x1.bc16d674ec800p+59", 18, "1e+18"}, + {"0x1.158e460913cffp+63", 19, "9999999999999997952"}, + {"0x1.158e460913d00p+63", 19, "1e+19"}, + {"0x1.5af1d78b58c3fp+66", 20, "99999999999999983616"}, + {"0x1.5af1d78b58c40p+66", 20, "1e+20"}, + {"0x1.b1ae4d6e2ef4fp+69", 21, "999999999999999868928"}, + {"0x1.b1ae4d6e2ef50p+69", 21, "1e+21"}, + {"0x1.0f0cf064dd591p+73", 22, "9999999999999997902848"}, + {"0x1.0f0cf064dd592p+73", 22, "1e+22"}, + {"0x1.52d02c7e14af6p+76", 23, "99999999999999991611392"}, + {"0x1.52d02c7e14af7p+76", 23, "1.0000000000000000838861e+23"}, + {"0x1.a784379d99db4p+79", 24, "999999999999999983222784"}, + {"0x1.a784379d99db5p+79", 24, "1.00000000000000011744051e+24"}, + {"0x1.a36e2eb1c432cp-14", 25, "9.999999999999999123964645e-5"}, + {"0x1.a36e2eb1c432dp-14", 25, "0.0001000000000000000047921736"}, + {"0x1.0624dd2f1a9fbp-10", 25, "0.0009999999999999998039762472"}, + {"0x1.0624dd2f1a9fcp-10", 25, "0.001000000000000000020816682"}, + {"0x1.47ae147ae147ap-7", 25, "0.009999999999999998473443341"}, + {"0x1.47ae147ae147bp-7", 25, "0.01000000000000000020816682"}, + {"0x1.9999999999999p-4", 25, "0.09999999999999999167332732"}, + {"0x1.999999999999ap-4", 25, "0.1000000000000000055511151"}, + {"0x1.fffffffffffffp-1", 25, "0.9999999999999998889776975"}, + {"0x1.0000000000000p+0", 25, "1"}, + {"0x1.3ffffffffffffp+3", 25, "9.999999999999998223643161"}, + {"0x1.4000000000000p+3", 25, "10"}, + {"0x1.8ffffffffffffp+6", 25, "99.99999999999998578914528"}, + {"0x1.9000000000000p+6", 25, "100"}, + {"0x1.f3fffffffffffp+9", 25, "999.9999999999998863131623"}, + {"0x1.f400000000000p+9", 25, "1000"}, + {"0x1.387ffffffffffp+13", 25, "9999.999999999998181010596"}, + {"0x1.3880000000000p+13", 25, "10000"}, + {"0x1.869ffffffffffp+16", 25, "99999.99999999998544808477"}, + {"0x1.86a0000000000p+16", 25, "100000"}, + {"0x1.e847fffffffffp+19", 25, "999999.9999999998835846782"}, + {"0x1.e848000000000p+19", 25, "1000000"}, + {"0x1.312cfffffffffp+23", 25, "9999999.999999998137354851"}, + {"0x1.312d000000000p+23", 25, "10000000"}, + {"0x1.7d783ffffffffp+26", 25, "99999999.99999998509883881"}, + {"0x1.7d78400000000p+26", 25, "100000000"}, + {"0x1.dcd64ffffffffp+29", 25, "999999999.9999998807907104"}, + {"0x1.dcd6500000000p+29", 25, "1000000000"}, + {"0x1.2a05f1fffffffp+33", 25, "9999999999.999998092651367"}, + {"0x1.2a05f20000000p+33", 25, "10000000000"}, + {"0x1.74876e7ffffffp+36", 25, "99999999999.99998474121094"}, + {"0x1.74876e8000000p+36", 25, "100000000000"}, + {"0x1.d1a94a1ffffffp+39", 25, "999999999999.9998779296875"}, + {"0x1.d1a94a2000000p+39", 25, "1000000000000"}, + {"0x1.2309ce53fffffp+43", 25, "9999999999999.998046875"}, + {"0x1.2309ce5400000p+43", 25, "10000000000000"}, + {"0x1.6bcc41e8fffffp+46", 25, "99999999999999.984375"}, + {"0x1.6bcc41e900000p+46", 25, "100000000000000"}, + {"0x1.c6bf52633ffffp+49", 25, "999999999999999.875"}, + {"0x1.c6bf526340000p+49", 25, "1000000000000000"}, + {"0x1.1c37937e07fffp+53", 25, "9999999999999998"}, + {"0x1.1c37937e08000p+53", 25, "10000000000000000"}, + {"0x1.6345785d89fffp+56", 25, "99999999999999984"}, + {"0x1.6345785d8a000p+56", 25, "100000000000000000"}, + {"0x1.bc16d674ec7ffp+59", 25, "999999999999999872"}, + {"0x1.bc16d674ec800p+59", 25, "1000000000000000000"}, + {"0x1.158e460913cffp+63", 25, "9999999999999997952"}, + {"0x1.158e460913d00p+63", 25, "10000000000000000000"}, + {"0x1.5af1d78b58c3fp+66", 25, "99999999999999983616"}, + {"0x1.5af1d78b58c40p+66", 25, "100000000000000000000"}, + {"0x1.b1ae4d6e2ef4fp+69", 25, "999999999999999868928"}, + {"0x1.b1ae4d6e2ef50p+69", 25, "1000000000000000000000"}, + {"0x1.0f0cf064dd591p+73", 25, "9999999999999997902848"}, + {"0x1.0f0cf064dd592p+73", 25, "10000000000000000000000"}, + {"0x1.52d02c7e14af6p+76", 25, "99999999999999991611392"}, + {"0x1.52d02c7e14af7p+76", 25, "100000000000000008388608"}, + {"0x1.a784379d99db4p+79", 25, "999999999999999983222784"}, + {"0x1.a784379d99db5p+79", 25, "1000000000000000117440512"}, + {"0x1.08b2a2c280290p+83", 25, "9999999999999998758486016"}, + {"0x1.08b2a2c280291p+83", 25, "1.000000000000000090596966e+25"}, + {"0x1.4adf4b7320334p+86", 26, "99999999999999987584860160"}, + {"0x1.4adf4b7320335p+86", 26, "1.0000000000000000476472934e+26"}, + {"0x1.9d971e4fe8401p+89", 27, "999999999999999875848601600"}, + {"0x1.9d971e4fe8402p+89", 27, "1.00000000000000001328755507e+27"}, + {"0x1.027e72f1f1281p+93", 28, "9999999999999999583119736832"}, + {"0x1.027e72f1f1282p+93", 28, "1.000000000000000178214299238e+28"}, + {"0x1.431e0fae6d721p+96", 29, "99999999999999991433150857216"}, + {"0x1.431e0fae6d722p+96", 29, "1.0000000000000000902533690163e+29"}, + {"0x1.93e5939a08ce9p+99", 30, "999999999999999879147136483328"}, + {"0x1.93e5939a08ceap+99", 30, "1.00000000000000001988462483866e+30"}, + {"0x1.f8def8808b024p+102", 31, "9999999999999999635896294965248"}, + {"0x1.f8def8808b025p+102", 31, "1.000000000000000076179620180787e+31"}, + {"0x1.3b8b5b5056e16p+106", 32, "99999999999999987351763694911488"}, + {"0x1.3b8b5b5056e17p+106", 32, "1.0000000000000000536616220439347e+32"}, + {"0x1.8a6e32246c99cp+109", 33, "999999999999999945575230987042816"}, + {"0x1.8a6e32246c99dp+109", 33, "1.00000000000000008969041906289869e+33"}, + {"0x1.ed09bead87c03p+112", 34, "9999999999999999455752309870428160"}, + {"0x1.ed09bead87c04p+112", 34, "1.000000000000000060867381447727514e+34"}, + {"0x1.3426172c74d82p+116", 35, "99999999999999996863366107917975552"}, + {"0x1.3426172c74d83p+116", 35, "1.0000000000000001531011018162752717e+35"}, + {"0x1.812f9cf7920e2p+119", 36, "999999999999999894846684784341549056"}, + {"0x1.812f9cf7920e3p+119", 36, "1.00000000000000004242063737401796198e+36"}, + {"0x1.e17b84357691bp+122", 37, "9999999999999999538762658202121142272"}, + {"0x1.e17b84357691cp+122", 37, "1.00000000000000007193542789195324457e+37"}, + {"0x1.2ced32a16a1b1p+126", 38, "99999999999999997748809823456034029568"}, + {"0x1.2ced32a16a1b2p+126", 38, "1.0000000000000001663827575493461488435e+38"}, + {"0x1.78287f49c4a1dp+129", 39, "999999999999999939709166371603178586112"}, + {"0x1.78287f49c4a1ep+129", 39, "1.00000000000000009082489382343182542438e+39"}, + {"0x1.d6329f1c35ca4p+132", 40, "9999999999999999094860208812374492184576"}, + {"0x1.d6329f1c35ca5p+132", 40, "1.000000000000000030378602842700366689075e+40"}, + {"0x1.25dfa371a19e6p+136", 41, "99999999999999981277195531206711524196352"}, + {"0x1.25dfa371a19e7p+136", 41, "1.0000000000000000062000864504077831949517e+41"}, + {"0x1.6f578c4e0a060p+139", 42, "999999999999999890143207767403382423158784"}, + {"0x1.6f578c4e0a061p+139", 42, "1.00000000000000004488571267807591678554931e+42"}, + {"0x1.cb2d6f618c878p+142", 43, "9999999999999998901432077674033824231587840"}, + {"0x1.cb2d6f618c879p+142", 43, "1.000000000000000013937211695941409913071206e+43"}, + {"0x1.1efc659cf7d4bp+146", 44, "99999999999999989014320776740338242315878400"}, + {"0x1.1efc659cf7d4cp+146", 44, "1.0000000000000000882136140530642264070186598e+44"}, + {"0x1.66bb7f0435c9ep+149", 45, "999999999999999929757289024535551219930759168"}, + {"0x1.66bb7f0435c9fp+149", 45, "1.00000000000000008821361405306422640701865984e+45"}, + {"0x1.c06a5ec5433c6p+152", 46, "9999999999999999931398190359470212947659194368"}, + {"0x1.c06a5ec5433c7p+152", 46, "1.000000000000000119904879058769961444436239974e+46"}, + {"0x1.18427b3b4a05bp+156", 47, "99999999999999984102174700855949311516153479168"}, + {"0x1.18427b3b4a05cp+156", 47, "1.0000000000000000438458430450761973546340476518e+47"}, + {"0x1.5e531a0a1c872p+159", 48, "999999999999999881586566215862833963056037363712"}, + {"0x1.5e531a0a1c873p+159", 48, "1.00000000000000004384584304507619735463404765184e+48"}, + {"0x1.b5e7e08ca3a8fp+162", 49, "9999999999999999464902769475481793196872414789632"}, + {"0x1.b5e7e08ca3a90p+162", 49, "1.000000000000000076297698410918870032949649709466e+49"}, + {"0x1.11b0ec57e6499p+166", 50, "99999999999999986860582406952576489172979654066176"}, + {"0x1.11b0ec57e649ap+166", 50, "1.0000000000000000762976984109188700329496497094656e+50"}, + {"0x1.561d276ddfdc0p+169", 51, "999999999999999993220948674361627976461708441944064"}, + {"0x1.561d276ddfdc1p+169", 51, "1.00000000000000015937444814747611208943759097698714e+51"}, + {"0x1.aba4714957d30p+172", 52, "9999999999999999932209486743616279764617084419440640"}, + {"0x1.aba4714957d31p+172", 52, "1.000000000000000126143748252853215266842414469978522e+52"}, + {"0x1.0b46c6cdd6e3ep+176", 53, "99999999999999999322094867436162797646170844194406400"}, + {"0x1.0b46c6cdd6e3fp+176", 53, "1.0000000000000002058974279999481676410708380867991962e+53"}, + {"0x1.4e1878814c9cdp+179", 54, "999999999999999908150356944127012110618056584002011136"}, + {"0x1.4e1878814c9cep+179", 54, "1.00000000000000007829154040459624384230536029988611686e+54"}, + {"0x1.a19e96a19fc40p+182", 55, "9999999999999998741221202520331657642805958408251899904"}, + {"0x1.a19e96a19fc41p+182", 55, "1.000000000000000010235067020408551149630438813532474573e+55"}, + {"0x1.05031e2503da8p+186", 56, "99999999999999987412212025203316576428059584082518999040"}, + {"0x1.05031e2503da9p+186", 56, "1.0000000000000000919028350814337823808403445971568453222e+56"}, + {"0x1.4643e5ae44d12p+189", 57, "999999999999999874122120252033165764280595840825189990400"}, + {"0x1.4643e5ae44d13p+189", 57, "1.00000000000000004834669211555365905752839484589051425587e+57"}, + {"0x1.97d4df19d6057p+192", 58, "9999999999999999438119489974413630815797154428513196965888"}, + {"0x1.97d4df19d6058p+192", 58, "1.000000000000000083191606488257757716177954646903579108966e+58"}, + {"0x1.fdca16e04b86dp+195", 59, "99999999999999997168788049560464200849936328366177157906432"}, + {"0x1.fdca16e04b86ep+195", 59, "1.0000000000000000831916064882577577161779546469035791089664e+59"}, + {"0x1.3e9e4e4c2f344p+199", 60, "999999999999999949387135297074018866963645011013410073083904"}, + {"0x1.3e9e4e4c2f345p+199", 60, "1.00000000000000012779309688531900399924939119220030212092723e+60"}, + {"0x1.8e45e1df3b015p+202", 61, "9999999999999999493871352970740188669636450110134100730839040"}, + {"0x1.8e45e1df3b016p+202", 61, "1.000000000000000092111904567670006972792241955962923711358566e+61"}, + {"0x1.f1d75a5709c1ap+205", 62, "99999999999999992084218144295482124579792562202350734542897152"}, + {"0x1.f1d75a5709c1bp+205", 62, "1.0000000000000000350219968594316117304608031779831182560487014e+62"}, + {"0x1.3726987666190p+209", 63, "999999999999999875170255276364105051932774599639662981181079552"}, + {"0x1.3726987666191p+209", 63, "1.00000000000000005785795994272696982739337868917504043817264742e+63"}, + {"0x1.84f03e93ff9f4p+212", 64, "9999999999999998751702552763641050519327745996396629811810795520"}, + {"0x1.84f03e93ff9f5p+212", 64, "1.00000000000000002132041900945439687230125787126796494677433385e+64"}, + {"0x1.e62c4e38ff872p+215", 65, "99999999999999999209038626283633850822756121694230455365568299008"}, + {"0x1.e62c4e38ff873p+215", 65, "1.0000000000000001090105172493085719645223478342449461261302864282e+65"}, + {"0x1.2fdbb0e39fb47p+219", 66, "999999999999999945322333868247445125709646570021247924665841614848"}, + {"0x1.2fdbb0e39fb48p+219", 66, "1.00000000000000013239454344660301865578130515770547444062520711578e+66"}, + {"0x1.7bd29d1c87a19p+222", 67, "9999999999999999827367757839185598317239782875580932278577147150336"}, + {"0x1.7bd29d1c87a1ap+222", 67, "1.000000000000000132394543446603018655781305157705474440625207115776e+67"}, + {"0x1.dac74463a989fp+225", 68, "99999999999999995280522225138166806691251291352861698530421623488512"}, + {"0x1.dac74463a98a0p+225", 68, "1.000000000000000072531436381529235126158374409646521955518210155479e+68"}, + {"0x1.28bc8abe49f63p+229", 69, "999999999999999880969493773293127831364996015857874003175819882528768"}, + {"0x1.28bc8abe49f64p+229", 69, "1.00000000000000007253143638152923512615837440964652195551821015547904e+69"}, + {"0x1.72ebad6ddc73cp+232", 70, "9999999999999999192818822949403492903236716946156035936442979371188224"}, + {"0x1.72ebad6ddc73dp+232", 70, "1.00000000000000007253143638152923512615837440964652195551821015547904e+70"}, + {"0x1.cfa698c95390bp+235", 71, "99999999999999991928188229494034929032367169461560359364429793711882240"}, + {"0x1.cfa698c95390cp+235", 71, "1.0000000000000000418815255642114579589914338666403382831434277118069965e+71"}, + {"0x1.21c81f7dd43a7p+239", 72, "999999999999999943801810948794571024057224129020550531544123892056457216"}, + {"0x1.21c81f7dd43a8p+239", 72, "1.00000000000000013996124017962834489392564360426012603474273153155753574e+72"}, + {"0x1.6a3a275d49491p+242", 73, "9999999999999999830336967949613257980309080240684656321838454199566729216"}, + {"0x1.6a3a275d49492p+242", 73, "1.000000000000000139961240179628344893925643604260126034742731531557535744e+73"}, + {"0x1.c4c8b1349b9b5p+245", 74, "99999999999999995164818811802792197885196090803013355167206819763650035712"}, + {"0x1.c4c8b1349b9b6p+245", 74, "1.000000000000000077190222825761537255567749372183461873719177086917190615e+74"}, + {"0x1.1afd6ec0e1411p+249", 75, "999999999999999926539781176481198923508803215199467887262646419780362305536"}, + {"0x1.1afd6ec0e1412p+249", 75, "1.00000000000000012740703670885498336625406475784479320253802064262946671821e+75"}, + {"0x1.61bcca7119915p+252", 76, "9999999999999998863663300700064420349597509066704028242075715752105414230016"}, + {"0x1.61bcca7119916p+252", 76, "1.000000000000000047060134495905469589155960140786663076427870953489824953139e+76"}, + {"0x1.ba2bfd0d5ff5bp+255", 77, "99999999999999998278261272554585856747747644714015897553975120217811154108416"}, + {"0x1.ba2bfd0d5ff5cp+255", 77, "1.0000000000000001113376562662650806108344438344331671773159907048015383651942e+77"}, + {"0x1.145b7e285bf98p+259", 78, "999999999999999802805551768538947706777722104929947493053015898505313987330048"}, + {"0x1.145b7e285bf99p+259", 78, "1.00000000000000000849362143368970297614886992459876061589499910270279690590618e+78"}, + {"0x1.59725db272f7fp+262", 79, "9999999999999999673560075006595519222746403606649979913266024618633003221909504"}, + {"0x1.59725db272f80p+262", 79, "1.000000000000000131906463232780156137771558616400048489600189025221286657051853e+79"}, + {"0x1.afcef51f0fb5ep+265", 80, "99999999999999986862573406138718939297648940722396769236245052384850852127440896"}, + {"0x1.afcef51f0fb5fp+265", 80, "1.0000000000000000002660986470836727653740240118120080909813197745348975891631309e+80"}, + {"0x1.0de1593369d1bp+269", 81, "999999999999999921281879895665782741935503249059183851809998224123064148429897728"}, + {"0x1.0de1593369d1cp+269", 81, "1.0000000000000001319064632327801561377715586164000484896001890252212866570518528e+81"}, + {"0x1.5159af8044462p+272", 82, "9999999999999999634067965630886574211027143225273567793680363843427086501542887424"}, + {"0x1.5159af8044463p+272", 82, "1.0000000000000001319064632327801561377715586164000484896001890252212866570518528e+82"}, + {"0x1.a5b01b605557ap+275", 83, "99999999999999989600692989521205793443517660497828009527517532799127744739526311936"}, + {"0x1.a5b01b605557bp+275", 83, "1.0000000000000000308066632309652569077702520400764334634608974406941398529133143654e+83"}, + {"0x1.078e111c3556cp+279", 84, "999999999999999842087036560910778345101146430939018748000886482910132485188042620928"}, + {"0x1.078e111c3556dp+279", 84, "1.00000000000000005776660989811589670243726712709606413709804186323471233401692461466e+84"}, + {"0x1.4971956342ac7p+282", 85, "9999999999999998420870365609107783451011464309390187480008864829101324851880426209280"}, + {"0x1.4971956342ac8p+282", 85, "1.00000000000000001463069523067487303097004298786465505927861078716979636425114821591e+85"}, + {"0x1.9bcdfabc13579p+285", 86, "99999999999999987659576829486359728227492574232414601025643134376206526100066373992448"}, + {"0x1.9bcdfabc1357ap+285", 86, "1.0000000000000000146306952306748730309700429878646550592786107871697963642511482159104e+86"}, + {"0x1.0160bcb58c16cp+289", 87, "999999999999999959416724456350362731491996089648451439669739009806703922950954425516032"}, + {"0x1.0160bcb58c16dp+289", 87, "1.0000000000000001802726075536484039294041836825132659181052261192590736881517295870935e+87"}, + {"0x1.41b8ebe2ef1c7p+292", 88, "9999999999999999594167244563503627314919960896484514396697390098067039229509544255160320"}, + {"0x1.41b8ebe2ef1c8p+292", 88, "1.00000000000000013610143093418879568982174616394030302241812869736859973511157455477801e+88"}, + {"0x1.922726dbaae39p+295", 89, "99999999999999999475366575191804932315794610450682175621941694731908308538307845136842752"}, + {"0x1.922726dbaae3ap+295", 89, "1.0000000000000001361014309341887956898217461639403030224181286973685997351115745547780096e+89"}, + {"0x1.f6b0f092959c7p+298", 90, "999999999999999966484112715463900049825186092620125502979674597309179755437379230686511104"}, + {"0x1.f6b0f092959c8p+298", 90, "1.00000000000000007956232486128049714315622614016691051593864399734879307522017611341417677e+90"}, + {"0x1.3a2e965b9d81cp+302", 91, "9999999999999998986371854279739417938265620640920544952042929572854117635677011010499117056"}, + {"0x1.3a2e965b9d81dp+302", 91, "1.000000000000000079562324861280497143156226140166910515938643997348793075220176113414176768e+91"}, + {"0x1.88ba3bf284e23p+305", 92, "99999999999999989863718542797394179382656206409205449520429295728541176356770110104991170560"}, + {"0x1.88ba3bf284e24p+305", 92, "1.0000000000000000433772969746191860732902933249519393117917737893361168128896811109413237555e+92"}, + {"0x1.eae8caef261acp+308", 93, "999999999999999927585207737302990649719308316264031458521789123695552773432097103028194115584"}, + {"0x1.eae8caef261adp+308", 93, "1.00000000000000004337729697461918607329029332495193931179177378933611681288968111094132375552e+93"}, + {"0x1.32d17ed577d0bp+312", 94, "9999999999999998349515363474500343108625203093137051759058013911831015418660298966976904036352"}, + {"0x1.32d17ed577d0cp+312", 94, "1.000000000000000020218879127155946988576096323214357741137776856208004004998164309358697827533e+94"}, + {"0x1.7f85de8ad5c4ep+315", 95, "99999999999999987200500490339121684640523551209383568895219648418808203449245677922989188841472"}, + {"0x1.7f85de8ad5c4fp+315", 95, "1.0000000000000000202188791271559469885760963232143577411377768562080040049981643093586978275328e+95"}, + {"0x1.df67562d8b362p+318", 96, "999999999999999931290554592897108903273579836542044509826428632996050822694739791281414264061952"}, + {"0x1.df67562d8b363p+318", 96, "1.00000000000000004986165397190889301701026848543846215157489293061198839909930581538445901535642e+96"}, + {"0x1.2ba095dc7701dp+322", 97, "9999999999999998838621148412923952577789043769834774531270429139496757921329133816401963635441664"}, + {"0x1.2ba095dc7701ep+322", 97, "1.000000000000000073575873847711249839757606215217745679924585790135175914380219020205067965615309e+97"}, + {"0x1.7688bb5394c25p+325", 98, "99999999999999999769037024514370800696612547992403838920556863966097586548129676477911932478685184"}, + {"0x1.7688bb5394c26p+325", 98, "1.0000000000000001494613774502787916725490869505114529706436029406093759632791412756310166064437658e+98"}, + {"0x1.d42aea2879f2ep+328", 99, "999999999999999967336168804116691273849533185806555472917961779471295845921727862608739868455469056"}, + {"0x1.d42aea2879f2fp+328", 99, "1.00000000000000008875297456822475820631590236227648713806838922023001592416000347129025769378100019e+99"}, + {"0x1.249ad2594c37cp+332", 100, "9999999999999998216360018871870109548898901740426374747374488505608317520357971321909184780648316928"}, + {"0x1.249ad2594c37dp+332", 100, "1.00000000000000001590289110975991804683608085639452813897813275577478387721703810608134699858568151e+100"}, + {"0x1.6dc186ef9f45cp+335", 101, "99999999999999997704951326524533662844684271992415000612999597473199345218078991130326129448151154688"}, + {"0x1.6dc186ef9f45dp+335", 101, "1.000000000000000132463024643303662302003795265805662537522543098903155152325782690415604110898191401e+101"}, + {"0x1.c931e8ab87173p+338", 102, "999999999999999977049513265245336628446842719924150006129995974731993452180789911303261294481511546880"}, + {"0x1.c931e8ab87174p+338", 102, "1.00000000000000010138032236769199716729240475662936003124403367406892281229678413459313554761485543014e+102"}, + {"0x1.1dbf316b346e7p+342", 103, "9999999999999998029863805218200118740630558685368559709703431956602923480183979986974373400948301103104"}, + {"0x1.1dbf316b346e8p+342", 103, "1.000000000000000001915675085734668736215955127265192011152803514599379324203988755961236145108180323533e+103"}, + {"0x1.652efdc6018a1p+345", 104, "99999999999999984277223943460294324649363572028252317900683525944810974325551615015019710109750015295488"}, + {"0x1.652efdc6018a2p+345", 104, "1.0000000000000000019156750857346687362159551272651920111528035145993793242039887559612361451081803235328e+104"}, + {"0x1.be7abd3781ecap+348", 105, "999999999999999938258300825281978540327027364472124478294416212538871491824599713636820527503908255301632"}, + {"0x1.be7abd3781ecbp+348", 105, "1.00000000000000006557304934618735893210488289005825954401119081665988715658337779828565176271245239176397e+105"}, + {"0x1.170cb642b133ep+352", 106, "9999999999999998873324014169198263836158851542376704520077063708904652259210884797772880334204906007166976"}, + {"0x1.170cb642b133fp+352", 106, "1.000000000000000091035999050368435010460453995175486557154545737484090289535133415215418009754161219056435e+106"}, + {"0x1.5ccfe3d35d80ep+355", 107, "99999999999999996881384047029926983435371269061279689406644211752791525136670645395254002395395884805259264"}, + {"0x1.5ccfe3d35d80fp+355", 107, "1.0000000000000001317767185770581567358293677633630497781839136108028153022579424023030440050208953427243827e+107"}, + {"0x1.b403dcc834e11p+358", 108, "999999999999999903628689227595715073763450661512695740419453520217955231010212074612338431527184250183876608"}, + {"0x1.b403dcc834e12p+358", 108, "1.00000000000000003399899171300282459494397471971289804771343071483787527172320083329274161638073344592130867e+108"}, + {"0x1.108269fd210cbp+362", 109, "9999999999999999818508707188399807864717650964328171247958398369899072554380053298205803424393137676263358464"}, + {"0x1.108269fd210ccp+362", 109, "1.000000000000000190443354695491356020360603589553140816466203348381779320578787343709225438204992480806227149e+109"}, + {"0x1.54a3047c694fdp+365", 110, "99999999999999985669538033284915564613846200056062290979362173015478401635353612148739328497990653971840106496"}, + {"0x1.54a3047c694fep+365", 110, "1.0000000000000000235693675141702558332495327950568818631299125392682816684661617325983093615924495102623141069e+110"}, + {"0x1.a9cbc59b83a3dp+368", 111, "999999999999999956819772641641815758405104477258378281795396215622882607621111488153942930947432322044748890112"}, + {"0x1.a9cbc59b83a3ep+368", 111, "1.00000000000000009031896238669869590809396111285538544446442886291368072931121197704267579223746669847987932365e+111"}, + {"0x1.0a1f5b8132466p+372", 112, "9999999999999999301199346926304397284673331501389768492615896861647229832830913903761963586894254467577228034048"}, + {"0x1.0a1f5b8132467p+372", 112, "1.000000000000000143718638284721447967969503767094188309532041921829999977987252172598168936753480449053931497062e+112"}, + {"0x1.4ca732617ed7fp+375", 113, "99999999999999984468045325579403643266646490335689226515340879189861218540142707748740732746380344583923932594176"}, + {"0x1.4ca732617ed80p+375", 113, "1.0000000000000000155594161294668430242682013969210614333697705804308337811647557032649853899150474476762062808678e+113"}, + {"0x1.9fd0fef9de8dfp+378", 114, "999999999999999878856245830528597750986812202069726098796681149605056504554092802642922939954052246206632716926976"}, + {"0x1.9fd0fef9de8e0p+378", 114, "1.00000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784e+114"}, + {"0x1.03e29f5c2b18bp+382", 115, "9999999999999997968343436511656505870179786851589248980528274911095901385876950622696854699774551253248885785624576"}, + {"0x1.03e29f5c2b18cp+382", 115, "1.00000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784e+115"}, + {"0x1.44db473335deep+385", 116, "99999999999999984057935814682588907446802322751135220511621610897383886710310719046874545396497358979515211902353408"}, + {"0x1.44db473335defp+385", 116, "1.00000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784e+116"}, + {"0x1.961219000356ap+388", 117, "999999999999999910571381339882270654388094495275235896417637897556636832727766595587241428345003132947573783761256448"}, + {"0x1.961219000356bp+388", 117, "1.00000000000000005055542772599503381422823703080300327902048147472223276397708540582423337710506221925241711323670118e+117"}, + {"0x1.fb969f40042c5p+391", 118, "9999999999999999665649998943273759183241515094863428494587753284228752052274941196820382078490267674695111155514343424"}, + {"0x1.fb969f40042c6p+391", 118, "1.000000000000000078552237003217586446196265537908556755541050190155351950226949167871631766857074036513385779131790131e+118"}, + {"0x1.3d3e2388029bbp+395", 119, "99999999999999994416755247254933381274972870380190006824232035607637985622760311004411949604741731366073618283536318464"}, + {"0x1.3d3e2388029bcp+395", 119, "1.0000000000000001233471318467736706573451111492774423179739601348483426482267311871474691904602929441309356445639324467e+119"}, + {"0x1.8c8dac6a0342ap+398", 120, "999999999999999980003468347394201181668805192897008518188648311830772414627428725464789434929992439754776075181077037056"}, + {"0x1.8c8dac6a0342bp+398", 120, "1.00000000000000012334713184677367065734511114927744231797396013484834264822673118714746919046029294413093564456393244672e+120"}, + {"0x1.efb1178484134p+401", 121, "9999999999999999226660029476424133913982828103448349982745235826237443211877077407917175327178722380043122474279348731904"}, + {"0x1.efb1178484135p+401", 121, "1.000000000000000037340933747145988971939327575449182038102773041037800508067149710137861337142112641505239902934219200922e+121"}, + {"0x1.35ceaeb2d28c0p+405", 122, "99999999999999983092605830803955292696544699826135736641192401589249937168415416531480248917847991520357012302290741100544"}, + {"0x1.35ceaeb2d28c1p+405", 122, "1.0000000000000000144059475872452738558311186224283126301371231493549892706912613162686325762572645608050543718329623353754e+122"}, + {"0x1.83425a5f872f1p+408", 123, "999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376"}, + {"0x1.83425a5f872f2p+408", 123, "1.00000000000000012449388115476870641315052159692848578837224262943248321009552560684093062850453534816594492111899528999731e+123"}, + {"0x1.e412f0f768fadp+411", 124, "9999999999999999483531874467312143214394768377282087351960514613084929070487027419252537449089020883885200422613425626021888"}, + {"0x1.e412f0f768faep+411", 124, "1.000000000000000065780316585422875715913506677195060103980178906724486442413251318535705000639324261573469961499777714198938e+124"}, + {"0x1.2e8bd69aa19ccp+415", 125, "99999999999999992486776161899288204254467086983483846143922597222529419997579302660316349376281765375153005841365553228283904"}, + {"0x1.2e8bd69aa19cdp+415", 125, "1.0000000000000001127511682408995402737031186129818006514938298848908838565590707491798855029314931308474499291951517748376371e+125"}, + {"0x1.7a2ecc414a03fp+418", 126, "999999999999999924867761618992882042544670869834838461439225972225294199975793026603163493762817653751530058413655532282839040"}, + {"0x1.7a2ecc414a040p+418", 126, "1.0000000000000000751744869165182086274714290643524082134829091023577659252424152046645411010977580354282659550388525263266775e+126"}, + {"0x1.d8ba7f519c84fp+421", 127, "9999999999999999549291066784979473595300225087383524118479625982517885450291174622154390152298057300868772377386949310916067328"}, + {"0x1.d8ba7f519c850p+421", 127, "1.000000000000000075174486916518208627471429064352408213482909102357765925242415204664541101097758035428265955038852526326677504e+127"}, + {"0x1.27748f9301d31p+425", 128, "99999999999999988278187853568579059876517857536991893086699469578820211690113881674597776370903434688204400735860037395056427008"}, + {"0x1.27748f9301d32p+425", 128, "1.000000000000000075174486916518208627471429064352408213482909102357765925242415204664541101097758035428265955038852526326677504e+128"}, + {"0x1.7151b377c247ep+428", 129, "999999999999999998217443564185241415988928868759412500436543339729940401905904649497115766142268560009777175966751665376232210432"}, + {"0x1.7151b377c247fp+428", 129, "1.00000000000000015213153026885117583895392925994540392652927486498559144857892575983196643605324751084675473411095338727712279757e+129"}, + {"0x1.cda62055b2d9dp+431", 130, "9999999999999999366518088823188676468029287122850159299994507296276799832366962053631754981778769796749861527090709766158759755776"}, + {"0x1.cda62055b2d9ep+431", 130, "1.000000000000000059783078246051615185174929025233809070873635949832200820575113093631056034106660140344568199224432354136588445286e+130"}, + {"0x1.2087d4358fc82p+435", 131, "99999999999999991202555500957231813912852864969525730182461368558677581576901282770959939099212034754106974340599870111173348163584"}, + {"0x1.2087d4358fc83p+435", 131, "1.0000000000000001090355859915447142005237291504133263272233100379140091555104798489382082484781734046124010178305769051448734331699e+131"}, + {"0x1.68a9c942f3ba3p+438", 132, "999999999999999990829567402361276563686608849982484911984092226517669151665599636201042933986541570369602253175829982724989462249472"}, + {"0x1.68a9c942f3ba4p+438", 132, "1.00000000000000014843759218793919341280276925055694013230304930837945582345877325318393001997538401602666727271549254595150142347674e+132"}, + {"0x1.c2d43b93b0a8bp+441", 133, "9999999999999998962647525310145264542169126096378117797927179774005971485896954660113106823932361029753632414520324447890822855131136"}, + {"0x1.c2d43b93b0a8cp+441", 133, "1.000000000000000022351172359476859933509840930097375956047883642890026486024234359597620351184310059501015257083762495370291854494925e+133"}, + {"0x1.19c4a53c4e697p+445", 134, "99999999999999992148203649670699315007549827372972461504375111049848301607660324472857261615145089428049364457837845490532419930947584"}, + {"0x1.19c4a53c4e698p+445", 134, "1.0000000000000001232203082222467267169441835864650272970520161752815699559718654744666680862171692247215368695891465358352595096803738e+134"}, + {"0x1.6035ce8b6203dp+448", 135, "999999999999999961829690841814939863449235336276785151445404123455100404055655690676191710164594560368702289580532071091311261383655424"}, + {"0x1.6035ce8b6203ep+448", 135, "1.00000000000000012322030822224672671694418358646502729705201617528156995597186547446666808621716922472153686958914653583525950968037376e+135"}, + {"0x1.b843422e3a84cp+451", 136, "9999999999999999295515673657285824927502456862391367223240817130898064936724137339180964349540796274981353735788091781425216117243117568"}, + {"0x1.b843422e3a84dp+451", 136, "1.000000000000000058664061270074011975546204286389730438809371354550982135205381560950477535796139358980403037585700749937680210361686426e+136"}, + {"0x1.132a095ce492fp+455", 137, "99999999999999982626157224225223890651347880611866174913584999992086598044603947229219155428043184231232124237329592070639473281441202176"}, + {"0x1.132a095ce4930p+455", 137, "1.0000000000000000328415624892049260789870125663596116955123134262587470068987879955440013156277274126839495047843224355786484906342114918e+137"}, + {"0x1.57f48bb41db7bp+458", 138, "999999999999999867577570291642776341008185558166851738411142685188442185736589176942553506549890956386646894855501223680845484378371915776"}, + {"0x1.57f48bb41db7cp+458", 138, "1.00000000000000003284156248920492607898701256635961169551231342625874700689878799554400131562772741268394950478432243557864849063421149184e+138"}, + {"0x1.adf1aea12525ap+461", 139, "9999999999999999006303687311552062886039509598054037298313768334025031499690289406628430683654582476461074168412654660604060856295398309888"}, + {"0x1.adf1aea12525bp+461", 139, "1.00000000000000003284156248920492607898701256635961169551231342625874700689878799554400131562772741268394950478432243557864849063421149184e+139"}, + {"0x1.0cb70d24b7378p+465", 140, "99999999999999984774589122793531837245072631718372054355900219626000560719712531871037976946055058163097058166404267825310912362767116664832"}, + {"0x1.0cb70d24b7379p+465", 140, "1.0000000000000000592838012408148700370636248876704532886485007448299957782847398065202329650801812456915179223729338294822969716351458240102e+140"}, + {"0x1.4fe4d06de5056p+468", 141, "999999999999999847745891227935318372450726317183720543559002196260005607197125318710379769460550581630970581664042678253109123627671166648320"}, + {"0x1.4fe4d06de5057p+468", 141, "1.00000000000000001697621923823895970414104517357310673963060103511599774406721690895826232595625511287940845423115559923645940203365089253786e+141"}, + {"0x1.a3de04895e46cp+471", 142, "9999999999999999154380224320567749051268538597394750219876417318024024619451619548095327920588323941303457306908878466464492349900630570041344"}, + {"0x1.a3de04895e46dp+471", 142, "1.000000000000000050822284840299687970479108944850983978844920802887196171441235227007838837255396019129096028744578183433129457714846837715763e+142"}, + {"0x1.066ac2d5daec3p+475", 143, "99999999999999980713061250546244445284504979165026785650181847493456749434830333705088795590158149413134549224793557721710505681023603243483136"}, + {"0x1.066ac2d5daec4p+475", 143, "1.0000000000000000237454323586511053574086579278286821874734649886702374295420205725681776282160832941293459691338401160757934131698900815734374e+143"}, + {"0x1.4805738b51a74p+478", 144, "999999999999999850453576476100176633757771418885950722696147777681701481387046784154345890364481854130945587625116484988842728082166842262552576"}, + {"0x1.4805738b51a75p+478", 144, "1.00000000000000002374543235865110535740865792782868218747346498867023742954202057256817762821608329412934596913384011607579341316989008157343744e+144"}, + {"0x1.9a06d06e26112p+481", 145, "9999999999999999890870611821409196126784806260401358945180015464725302399110258148854112806457630061296658928320953898584032761523454337112604672"}, + {"0x1.9a06d06e26113p+481", 145, "1.000000000000000127720545888181662591599189833194321066339855315263358998435004845616476670927044158128386198039074294727963824222524025159968358e+145"}, + {"0x1.00444244d7cabp+485", 146, "99999999999999993363366729972462242111019694317846182578926003895619873650143420259298512453325054533017777074930382791057905692427399713177731072"}, + {"0x1.00444244d7cacp+485", 146, "1.0000000000000001554472428293898111873833316746251581007042260690215247501398006517626897489833003885281302590804700757018759338365597434497099366e+146"}, + {"0x1.405552d60dbd6p+488", 147, "999999999999999977996382405657660174364823889467801080772253244969263939229107492426926049423260513969768268415537077468838432306731146395363835904"}, + {"0x1.405552d60dbd7p+488", 147, "1.00000000000000015544724282938981118738333167462515810070422606902152475013980065176268974898330038852813025908047007570187593383655974344970993664e+147"}, + {"0x1.906aa78b912cbp+491", 148, "9999999999999999070160382361647997691574207754048582727994641153483596148648302286926205695992445641464234721495638781756234316947997075736253956096"}, + {"0x1.906aa78b912ccp+491", 148, "1.000000000000000048976726575150520579572227003530743888745042374590168263593384756161231529247276463793113064681510276762053432918662585217102276198e+148"}, + {"0x1.f485516e7577ep+494", 149, "99999999999999993540817590396194393124038202103003539598857976719672134461054113418634276152885094407576139065595315789290943193957228310232077172736"}, + {"0x1.f485516e7577fp+494", 149, "1.0000000000000000489767265751505205795722270035307438887450423745901682635933847561612315292472764637931130646815102767620534329186625852171022761984e+149"}, + {"0x1.38d352e5096afp+498", 150, "999999999999999980835596172437374590573120014030318793091164810154100112203678582976298268616221151962702060266176005440567032331208403948233373515776"}, + {"0x1.38d352e5096b0p+498", 150, "1.00000000000000016254527724633909722790407198603145238150150498198361518257622837813612029696570198351046473870706739563119743389775288733188378066944e+150"}, + {"0x1.8708279e4bc5ap+501", 151, "9999999999999998718097875280963410081745488308296386400449607070563910699801487058804050516065326530340444532016411713261887913912817139180431292235776"}, + {"0x1.8708279e4bc5bp+501", 151, "1.000000000000000017177532387217719118039310408430545510773232844520003126278188542008262674286117318272254595954354283478693112644517300624963454946509e+151"}, + {"0x1.e8ca3185deb71p+504", 152, "99999999999999992995688547174489225212045346187000138833626956204183589249936464033154810067836651912932851030272641618719051989257594860081125951275008"}, + {"0x1.e8ca3185deb72p+504", 152, "1.000000000000000046251081359041994740012262723950726884918887272012725537537796509233834198822034251319896624504896905909193976895164417966347520091095e+152"}, + {"0x1.317e5ef3ab327p+508", 153, "999999999999999999733403004123153744855539019118436686285840188024369679522423761672919759564567158443669378824028710020392594094129030220133015859757056"}, + {"0x1.317e5ef3ab328p+508", 153, "1.00000000000000018580411642379851772548243383844759748081802852397779311158391475191657751659443552994857836154750149357559812529827058120499103278510899e+153"}, + {"0x1.7dddf6b095ff0p+511", 154, "9999999999999998880909749523179353564794021275209402095665271864523156202855291675267251053466461355407239891899450398872692753716440996292182057045458944"}, + {"0x1.7dddf6b095ff1p+511", 154, "1.000000000000000036947545688058226540980917982984268845192277855215054365934721959721651310970540832744651175368723266731433700334957340417104619244827443e+154"}, + {"0x1.dd55745cbb7ecp+514", 155, "99999999999999988809097495231793535647940212752094020956652718645231562028552916752672510534664613554072398918994503988726927537164409962921820570454589440"}, + {"0x1.dd55745cbb7edp+514", 155, "1.0000000000000000071762315409101683040806148118916031180671277214625066168048834012826660698457618933038657381329676213626008153422946922595273365367711334e+155"}, + {"0x1.2a5568b9f52f4p+518", 156, "999999999999999983359180223191721714560372275017470536367007614460468417501012554531477876945938741751237388344363105067534507348164573733465510370326085632"}, + {"0x1.2a5568b9f52f5p+518", 156, "1.0000000000000001738955907649392944307223125700105311899679684704767740119319793285409834201445239541722641866531992354280649713012055219419601197018864681e+156"}, + {"0x1.74eac2e8727b1p+521", 157, "9999999999999999833591802231917217145603722750174705363670076144604684175010125545314778769459387417512373883443631050675345073481645737334655103703260856320"}, + {"0x1.74eac2e8727b2p+521", 157, "1.000000000000000135788308656589779887489924511011919059247776299273512893045785973739082311504806911688058826991432009355958878510597332300261197835574391603e+157"}, + {"0x1.d22573a28f19dp+524", 158, "99999999999999995287335453651211007997446182781858083179085387749785952239205787068995699003416510776387310061494932420984963311567802202010637287727642443776"}, + {"0x1.d22573a28f19ep+524", 158, "1.0000000000000000748166572832305566183181036166141396500954688253482951028278766060560405376812596437133302515326044476405891300456242288735429228494750692147e+158"}, + {"0x1.2357684599702p+528", 159, "999999999999999928484693987168420772305733470059469068129930887927772406304894123616740280504746200573981670431418299523701733729688780649419062882836695482368"}, + {"0x1.2357684599703p+528", 159, "1.0000000000000001235939783819179352336555603321323631774173148044884693350022041002024739567400974580931131118996664970128849288176027116149175428383545271255e+159"}, + {"0x1.6c2d4256ffcc2p+531", 160, "9999999999999998504409802292686149877658027252303114244149773213034936348259701329824468100106056975663290938441190205280284556945232082632196709006295628251136"}, + {"0x1.6c2d4256ffcc3p+531", 160, "1.000000000000000006528407745068226556845664214888626711844884454552051177783818114251033750998886703581634247018717578519375011764854353035618454865043828139622e+160"}, + {"0x1.c73892ecbfbf3p+534", 161, "99999999999999991287595123558845961539774732109363753938694017460291665200910932548988158640591809997245115511395844372456707812265566617217918448639526895091712"}, + {"0x1.c73892ecbfbf4p+534", 161, "1.0000000000000000377458932482281488706616365128202897693308658812017626863753877105047511391965429047846952776536372901176443229789205819900982116579266812025242e+161"}, + {"0x1.1c835bd3f7d78p+538", 162, "999999999999999937849939638116397466450525159438967985375725315922685858882365002492855496964043060934899979621894213003182527093908649335762989920701551401238528"}, + {"0x1.1c835bd3f7d79p+538", 162, "1.00000000000000013764184685833990027487274786620161155328600644648083951386841041851664678142904274863449057568538036723210611886393251464443343339515181100380979e+162"}, + {"0x1.63a432c8f5cd6p+541", 163, "9999999999999999378499396381163974664505251594389679853757253159226858588823650024928554969640430609348999796218942130031825270939086493357629899207015514012385280"}, + {"0x1.63a432c8f5cd7p+541", 163, "1.000000000000000097683465414295199713188303324849082839703950220369208782871201335311888524536042811094572456472683136386321400509927741582699344700261759083295539e+163"}, + {"0x1.bc8d3f7b3340bp+544", 164, "99999999999999987391652932764487656775541389327492204364443535414407668928683046936524228593524316087103098888157864364992697772750101243698844800887746832841572352"}, + {"0x1.bc8d3f7b3340cp+544", 164, "1.0000000000000000017833499485879183651456364256030139271070152777012950284778995356204687079928429609987689703622097823564380764603162862345375318325256344740613325e+164"}, + {"0x1.15d847ad00087p+548", 165, "999999999999999899489893451833484927233458399740540420336951338855520357125044282616287570346763120896578585177704871391229197474064067196498264773607101557544845312"}, + {"0x1.15d847ad00088p+548", 165, "1.00000000000000010407680644534235180305781445146548743387707921654706969983075478862464984563892280110095935554671469332164695544656850527257679889144416739057781965e+165"}, + {"0x1.5b4e5998400a9p+551", 166, "9999999999999999404072760505352583023983296100855298230449769143938302256661863838179600254051950569374547392515068357773127490685649548117139715971745147241514401792"}, + {"0x1.5b4e5998400aap+551", 166, "1.000000000000000104076806445342351803057814451465487433877079216547069699830754788624649845638922801100959355546714693321646955446568505272576798891444167390577819648e+166"}, + {"0x1.b221effe500d3p+554", 167, "99999999999999990767336997157383960226643264180953830087855645396318233083327270285662206135844950810475381599246526426844590779296424471954140613832058419086616428544"}, + {"0x1.b221effe500d4p+554", 167, "1.0000000000000000386089942874195144027940205149135043895442382956857739101649274267019739175454317034355575090286315503039132728953670850882316679737363063240072678605e+167"}, + {"0x1.0f5535fef2084p+558", 168, "999999999999999933860494834742974562371950216430331518611692822307700646699603647625692432595845947170914554599698521475539380813444812793279458505403728617494385000448"}, + {"0x1.0f5535fef2085p+558", 168, "1.00000000000000014335749374009605424321609081339667726047678376906384717363025120577825540249501745970020046345756457913228716497728935738318387744206888403052015072051e+168"}, + {"0x1.532a837eae8a5p+561", 169, "9999999999999999338604948347429745623719502164303315186116928223077006466996036476256924325958459471709145545996985214755393808134448127932794585054037286174943850004480"}, + {"0x1.532a837eae8a6p+561", 169, "1.000000000000000101458093959025438307047262694003408112103765579712617868244121694147742808515183157194343281685991367600937608144520448465202993654735852947914997576499e+169"}, + {"0x1.a7f5245e5a2cep+564", 170, "99999999999999990034097500988648181343688772091571619991327827082671720239070003832128235741197850516622880918243995225045973534722968565889475147553730375141026248523776"}, + {"0x1.a7f5245e5a2cfp+564", 170, "1.0000000000000000344190543093124528091771377029741774747069364767506509796263144755389226581474482731849717908514742291507783172120901941964335795950030032157467525460787e+170"}, + {"0x1.08f936baf85c1p+568", 171, "999999999999999953972206729656870211732987713739100709830741553196290713284945813208338477706166412373726001850053663010587168093173889073910282723323583537144858509574144"}, + {"0x1.08f936baf85c2p+568", 171, "1.00000000000000016849713360873842380491738768503263874950059468267458475686192891275656295888291804120371477252050850605109689907695070273397240771446870268008324260691968e+171"}, + {"0x1.4b378469b6731p+571", 172, "9999999999999999110672213538405594930961077194803931018967709273006319045695491932986935814708160866077282477159626944024852218964185263418978577250945597085571816901050368"}, + {"0x1.4b378469b6732p+571", 172, "1.000000000000000082687162857105802367643627696515223533632653430883267139431135672937273166412217389671719264252326568834893006683439977269947557718010655022907888967981466e+172"}, + {"0x1.9e056584240fdp+574", 173, "99999999999999987674323305318751091818660372407342701554959442658410485759723189737097766448253582599493004440868991951600366493901423615628791772651134064568704023452975104"}, + {"0x1.9e056584240fep+574", 173, "1.0000000000000000140391862557997052178246197057012913609383004294502130454865010810818413324356568684461228576377810190619298927686313968987276777208442168971676060568308941e+173"}, + {"0x1.02c35f729689ep+578", 174, "999999999999999849284042412665072058259000527747854146471853226010883220019378060628804930891911617504691481762871699606818419373090804007799965727644765395390927070069522432"}, + {"0x1.02c35f729689fp+578", 174, "1.0000000000000000689575675368445829376798260983524370990937828305966563206422087545661867996169052854265999829294174588803003839004782611957035817185773673977598323857513513e+174"}, + {"0x1.4374374f3c2c6p+581", 175, "9999999999999999371534524623368764100273307559896873275206250678451924602685103382037576783819090846734548822294900033162112051840457868829614121240178061963384891963422539776"}, + {"0x1.4374374f3c2c7p+581", 175, "1.000000000000000112892272561680485113563991212473353689618168751513810940766774893353663173361904019010981683162726610734996776805955752633284304916763887798233613448887717069e+175"}, + {"0x1.945145230b377p+584", 176, "99999999999999986685792442259943292861266657339622078268160759437774506806920451614379548038991111093844416185619536034869697653528180058283225500691937355558043949532406874112"}, + {"0x1.945145230b378p+584", 176, "1.0000000000000000074489805020743198914419949385831538723596425413126398524678161602637198763739070584084656026027846462837254338328097731830905692411162388370965388973604392141e+176"}, + {"0x1.f965966bce055p+587", 177, "999999999999999894976135638494410321178532246433607400617214583764724024948926844967780359586710300432448450005513217535702667994787395102883917853758746611883659375731342835712"}, + {"0x1.f965966bce056p+587", 177, "1.00000000000000000744898050207431989144199493858315387235964254131263985246781616026371987637390705840846560260278464628372543383280977318309056924111623883709653889736043921408e+177"}, + {"0x1.3bdf7e0360c35p+591", 178, "9999999999999998724815666657784284071258397080036981062687289922551408594451489819085924562292709488372450194860589317860981148271829194868425875762872481668410834714055235600384"}, + {"0x1.3bdf7e0360c36p+591", 178, "1.000000000000000052438118447506283719547380015442972461056613724331806183475371886382095683088785761598872463641693217782934540168018724415173229796059235727181690706012077765427e+178"}, + {"0x1.8ad75d8438f43p+594", 179, "99999999999999998045549773481514159457876389246726271914145983150114005386328272459269439234497983649422148597943950338419997003168440244384097290815044070304544781216945608327168"}, + {"0x1.8ad75d8438f44p+594", 179, "1.0000000000000001244207391601974258445159961384186822029717676171624723130874610481714969738325916867035234413039469321816691103043530463865054866839680307513179335998546994475827e+179"}, + {"0x1.ed8d34e547313p+597", 180, "999999999999999894076352879585771044616424544896411028843275160104340698328775730445412843452412726368640312784735046105718485868083216078242264642659886674081956339558310064685056"}, + {"0x1.ed8d34e547314p+597", 180, "1.00000000000000000924854601989159844456621034165754661590752138863340650570811838930845490864250220653608187704434098914369379808621813123237387566331395871269994496970650475613389e+180"}, + {"0x1.3478410f4c7ecp+601", 181, "9999999999999999171107915076469365246063817042486381462561244058101538598046442622180212564904306224021286256366562347133135483117101991090685868467907010818055540655879490029748224"}, + {"0x1.3478410f4c7edp+601", 181, "1.000000000000000101386300532136260364526038979066455085558918371456659151611592516398888560794573790670035128452025743574074047860726063355679164479837216343594335873825060509292954e+181"}, + {"0x1.819651531f9e7p+604", 182, "99999999999999991711079150764693652460638170424863814625612440581015385980464426221802125649043062240212862563665623471331354831171019910906858684679070108180555406558794900297482240"}, + {"0x1.819651531f9e8p+604", 182, "1.0000000000000000645311987272383955965421075241028916976983595783273580932502028655627150999337451570164538278889518418019219479509228905063570489532279132912365795121776382080293274e+182"}, + {"0x1.e1fbe5a7e7861p+607", 183, "999999999999999946594872951565228338993526868219488856544571440313594706493755982886960025179093529324993666087115356131035228239552737388526279268078143523691759154905886843985723392"}, + {"0x1.e1fbe5a7e7862p+607", 183, "1.00000000000000006453119872723839559654210752410289169769835957832735809325020286556271509993374515701645382788895184180192194795092289050635704895322791329123657951217763820802932736e+183"}, + {"0x1.2d3d6f88f0b3cp+611", 184, "9999999999999998286585471758920610814449462123360860153907833022998313197373091002112049504244419016335335042852788704601485085281825842706955095829283737561469387976341354799421194240"}, + {"0x1.2d3d6f88f0b3dp+611", 184, "1.000000000000000017356668416969128693522675261749530561236844323121852738547624112492413070031884505939869763168217247533567260066374829259224741079168005384218651369268937662411885773e+184"}, + {"0x1.788ccb6b2ce0cp+614", 185, "99999999999999997961704416875371517110712945186684165206763211895744845478556111003617144611039598507860251139162957211888350975873638026151889477992007905860430885494197722591793250304"}, + {"0x1.788ccb6b2ce0dp+614", 185, "1.0000000000000001305755411616153692607693126913975972887444809356150655898338131198611379417963500685236715184979802737776185109892901762523422799769117843610616789122498189718937455821e+185"}, + {"0x1.d6affe45f818fp+617", 186, "999999999999999979617044168753715171107129451866841652067632118957448454785561110036171446110395985078602511391629572118883509758736380261518894779920079058604308854941977225917932503040"}, + {"0x1.d6affe45f8190p+617", 186, "1.00000000000000010038384176304303844283687604349144616140911117228354216282416271789614464265915925183465771707671013344587151074317941705417760293751344330057020490078825062269858296627e+186"}, + {"0x1.262dfeebbb0f9p+621", 187, "9999999999999999071569656121801212080692814968920789464627446869617922299624001453201875281811380250249693879805812353226907091680705581859236698853640605134247712274342131878495422251008"}, + {"0x1.262dfeebbb0fap+621", 187, "1.000000000000000100383841763043038442836876043491446161409111172283542162824162717896144642659159251834657717076710133445871510743179417054177602937513443300570204900788250622698582966272e+187"}, + {"0x1.6fb97ea6a9d37p+624", 188, "99999999999999986851159038200753776111576258757220550347347138989744224339004763080499610528553377966303172216135545569805454885304878641227288327493418395599568449276340570087973407686656"}, + {"0x1.6fb97ea6a9d38p+624", 188, "1.0000000000000000230930913026978715489298382248516992754305645781548421896794576888657617968679507611107823854382585741965991901131358735068760297166536901857120314314466356487589666698035e+188"}, + {"0x1.cba7de5054485p+627", 189, "999999999999999899427890566145604518678577715028104257864890027548922232647929642417149243602017175952581854816736079397763477105066203831193512563278085201938953880500051690455580595453952"}, + {"0x1.cba7de5054486p+627", 189, "1.00000000000000002309309130269787154892983822485169927543056457815484218967945768886576179686795076111078238543825857419659919011313587350687602971665369018571203143144663564875896666980352e+189"}, + {"0x1.1f48eaf234ad3p+631", 190, "9999999999999998746948504188351511126283256130633852543517551174277382412416240331274267329488304589209417486924315804379963345034522698960570091326029642051843383703107348987949033805840384"}, + {"0x1.1f48eaf234ad4p+631", 190, "1.000000000000000072559171597318778361030342428781137282456834398397210172492068907445206818174324195174062597686867572116133475316363741377149036578003932179221262451825269232080321099543347e+190"}, + {"0x1.671b25aec1d88p+634", 191, "99999999999999991426771465453187656230872897620693565997277097362163262749171300799098274999392920617156591849131877877362376266603456419227541462168315779999172318661364176545198692437590016"}, + {"0x1.671b25aec1d89p+634", 191, "1.0000000000000000725591715973187783610303424287811372824568343983972101724920689074452068181743241951740625976868675721161334753163637413771490365780039321792212624518252692320803210995433472e+191"}, + {"0x1.c0e1ef1a724eap+637", 192, "999999999999999914267714654531876562308728976206935659972770973621632627491713007990982749993929206171565918491318778773623762666034564192275414621683157799991723186613641765451986924375900160"}, + {"0x1.c0e1ef1a724ebp+637", 192, "1.00000000000000004090088020876139800128601973826629695796002171344209466349199772755436200453824519737356326184775781344763153278629790594017431218673977730337535459878294373875465426450985779e+192"}, + {"0x1.188d357087712p+641", 193, "9999999999999998636144484328400679867178126713831911407778706776934478130915991201656310481762028096907669811487431649040206546179292274931158555956605099986382706217459209761309199883223171072"}, + {"0x1.188d357087713p+641", 193, "1.000000000000000066227513319607302289081477890678169217557471861406187070692054671467037855447108395613962730519045620382433086810350574289754091699751101204052080881216804133415187732536649318e+193"}, + {"0x1.5eb082cca94d7p+644", 194, "99999999999999994465967438754696170766327875910118237148971115117854351613178134068619377108456504406004528089686414709538562749489776621177115003729674648080379472553427423904462708600804999168"}, + {"0x1.5eb082cca94d8p+644", 194, "1.0000000000000001067501262969607491495542109345371648329133920981487349222121457817273192169012895127986018803931061114781155732488348436490817389205692194451348429331109807648720412813795157606e+194"}, + {"0x1.b65ca37fd3a0dp+647", 195, "999999999999999977077764769429719196041465194188378863774447340572581797347854228894418860247909937807756600796112539971931616645685181699233267813951241073670004367049615544210109925082343145472"}, + {"0x1.b65ca37fd3a0ep+647", 195, "1.00000000000000010675012629696074914955421093453716483291339209814873492221214578172731921690128951279860188039310611147811557324883484364908173892056921944513484293311098076487204128137951576064e+195"}, + {"0x1.11f9e62fe4448p+651", 196, "9999999999999999511432924639235132053389160461186216699466583890573511723749959183278387889172340228095875448767138256706948253250552493092635735926276453993770366538373425000777236538229086224384"}, + {"0x1.11f9e62fe4449p+651", 196, "1.000000000000000158619070907973161130959309230676679220568970001179196172157862402860479359562641342794939992231903540080589155890094708429021127363216410793720778359535526853136813823898384806707e+196"}, + {"0x1.56785fbbdd55ap+654", 197, "99999999999999995114329246392351320533891604611862166994665838905735117237499591832783878891723402280958754487671382567069482532505524930926357359262764539937703665383734250007772365382290862243840"}, + {"0x1.56785fbbdd55bp+654", 197, "1.0000000000000001171239152191632315458352305937650677104445076787548271722012891059539512454335598787978695027608655971986102897770868166050696166090986577148520300183958899825249957898832895698534e+197"}, + {"0x1.ac1677aad4ab0p+657", 198, "999999999999999884751043361827625869140390227060043253747518673178360772444478643277393806310703680414274761723053117059528639544242622390941156386039240473187039308013923507098814799398756243472384"}, + {"0x1.ac1677aad4ab1p+657", 198, "1.00000000000000001753554156601940054153744186517720008614579810493634157230551319337828377152376436520490032803037453428186101110586787622758599079921605032556703399966076149305663250824706100140442e+198"}, + {"0x1.0b8e0acac4eaep+661", 199, "9999999999999998847510433618276258691403902270600432537475186731783607724444786432773938063107036804142747617230531170595286395442426223909411563860392404731870393080139235070988147993987562434723840"}, + {"0x1.0b8e0acac4eafp+661", 199, "1.000000000000000097206240488534465344975672848047494185584765763991130052222133923438817750651600776079275667814767384615260434042843028529572891447122136236995030814648864284631323133556043856163635e+199"}, + {"0x1.4e718d7d7625ap+664", 200, "99999999999999996973312221251036165947450327545502362648241750950346848435554075534196338404706251868027512415973882408182135734368278484639385041047239877871023591066789981811181813306167128854888448"}, + {"0x1.4e718d7d7625bp+664", 200, "1.0000000000000001396972799138758332401427293722449843719522151821536839081776649794711025395197801952122758490331102381264067929425631097572992384593387153897566291159758524401378248003875013787018854e+200"}, + {"0x1.a20df0dcd3af0p+667", 201, "999999999999999901747459131964173027207212836739039328294498440443382314826691065690307721857975448067474834210390258463987183104130654882031695190925872134291678628544718769301415466131339252487684096"}, + {"0x1.a20df0dcd3af1p+667", 201, "1.00000000000000003771878529305655029174179371417100792467033657856355465388439044499361904623614958929307541410908738969965553158323491481075600563001892542312879319279108086692222079999200332461008486e+201"}, + {"0x1.0548b68a044d6p+671", 202, "9999999999999999017474591319641730272072128367390393282944984404433823148266910656903077218579754480674748342103902584639871831041306548820316951909258721342916786285447187693014154661313392524876840960"}, + {"0x1.0548b68a044d7p+671", 202, "1.000000000000000119301580989711976650462542240630189082495839461435658057319010072575605840863054074028435762048305668441056540670697470767990591893474757396431061931338898125494704000308401767883525325e+202"}, + {"0x1.469ae42c8560cp+674", 203, "99999999999999998876910787506329447650934459829549922997503484884029261182361866844442696946000689845185920534555642245481492613075738123641525387194542623914743194966239051177873087980216425864602058752"}, + {"0x1.469ae42c8560dp+674", 203, "1.0000000000000001628124053612615373751136081214084190333361076656341132058174738739526654646640697992206279476158887504364704121840108339451823712339845344488589385918977339967333617071438142709626935706e+203"}, + {"0x1.98419d37a6b8fp+677", 204, "999999999999999988769107875063294476509344598295499229975034848840292611823618668444426969460006898451859205345556422454814926130757381236415253871945426239147431949662390511778730879802164258646020587520"}, + {"0x1.98419d37a6b90p+677", 204, "1.00000000000000012800374586402188879539275541678583507266389310227534908701870283285101776562325721906687419916182228484013931497336014340342894776157671280691663726345066529974243554167548426849935897395e+204"}, + {"0x1.fe52048590672p+680", 205, "9999999999999999052283250816881378851792981072012977243617198967792587267065681698004724917620567060828502090557969050236202928251957239362070375381666542984859087613894256390005080826781722527340175556608"}, + {"0x1.fe52048590673p+680", 205, "1.000000000000000016616035472855013340286026761993566398512806499527303906862635501325745128692656962574862204108809594931879803899277933669817992649871683552701273012420045469371471812176828260616688264806e+205"}, + {"0x1.3ef342d37a407p+684", 206, "99999999999999986067324092522138770313660664528439025470128525568004065464414123719036343698981660348604541103459182906031648839556284004276265549348464259679976306097717770685212259087870984958094927200256"}, + {"0x1.3ef342d37a408p+684", 206, "1.0000000000000000388935775510883884313073724929520201333430238200769129428938489676307996560787770138732646031194121329135317061140943756165401836722126894035443458626261694354456645580765594621932224066355e+206"}, + {"0x1.8eb0138858d09p+687", 207, "999999999999999896317308250394787848770759814817916230429632968559415112294082783278450680807608685563489249451555889830959531939269147157518161129230251958148679621306976052570830984318279772103403898929152"}, + {"0x1.8eb0138858d0ap+687", 207, "1.00000000000000003889357755108838843130737249295202013334302382007691294289384896763079965607877701387326460311941213291353170611409437561654018367221268940354434586262616943544566455807655946219322240663552e+207"}, + {"0x1.f25c186a6f04cp+690", 208, "9999999999999999818630698308109481982927274216983785721776674794699138106539424938898600659703096825493544616522696356805028364441642842329313746550197144253860793660984920822957311285732475861572950035529728"}, + {"0x1.f25c186a6f04dp+690", 208, "1.000000000000000095924085271365828664322017564205661694508380160683912075133755441371739246187244345197174744586554630146560575784024467000148992689405664381702612359153846788595597987579871338229149809718067e+208"}, + {"0x1.37798f428562fp+694", 209, "99999999999999989061425747836704382546929530769255207431309733449871519907009213590435672179676195243109823530484164010765664497227613801915728022751095446033285297165420831725583764136794858449981115862089728"}, + {"0x1.37798f4285630p+694", 209, "1.0000000000000000731118821832548525711161595357042050700422376244411124222377928518753634101438574126676106879996976312533490279160524304467054690825284743904393057605427758473356246157785465878147788484850483e+209"}, + {"0x1.8557f31326bbbp+697", 210, "999999999999999927113782419344605574598668153294882673458925392487194643703632279098558059466181044478400725843812838336795121561031396504666917998514458446354143529431921823271795036250068185162804696593727488"}, + {"0x1.8557f31326bbcp+697", 210, "1.00000000000000007311188218325485257111615953570420507004223762444111242223779285187536341014385741266761068799969763125334902791605243044670546908252847439043930576054277584733562461577854658781477884848504832e+210"}, + {"0x1.e6adefd7f06aap+700", 211, "9999999999999999563134023721266549739021664297767471527755878388779781994104643936539191296017163181162427182749897969201059028320356032930746282153172616351711759756540926280845609521557638656931995269719916544"}, + {"0x1.e6adefd7f06abp+700", 211, "1.00000000000000007311188218325485257111615953570420507004223762444111242223779285187536341014385741266761068799969763125334902791605243044670546908252847439043930576054277584733562461577854658781477884848504832e+211"}, + {"0x1.302cb5e6f642ap+704", 212, "99999999999999990959401044767537593501656918740576398586892792465272451027953301036534141738485988029569553038510666318680865279842887243162229186843277653306392406169861934038413548670665077684456779836676898816"}, + {"0x1.302cb5e6f642bp+704", 212, "1.0000000000000000964715781454804920905589581568896966534955675815537392668032585435196522662522856315778842819446391981199976529328557958774316372559707169414929317175205124911858373485031031322390947127876596531e+212"}, + {"0x1.7c37e360b3d35p+707", 213, "999999999999999984345037526797422397233524775199337052919583787413130412889023223627065756931830180808571031008919677160084252852199641809946030023447952696435527124027376600704816231425231719002378564135125254144"}, + {"0x1.7c37e360b3d36p+707", 213, "1.00000000000000013384709168504151532166743595078648318702089551293394221810800365015051443602577078183432203225654570510663545295974118056659350633347830502317873324868489112134617772086239360331800009567183778611e+213"}, + {"0x1.db45dc38e0c82p+710", 214, "9999999999999999544446266951486038123467425400819078260993214423089680518452271383223760211130420606034208307593944715707740128306913340586165347614418822310868858990958736965765439335377993421392542578277827477504"}, + {"0x1.db45dc38e0c83p+710", 214, "1.000000000000000074046270021743878151893871480551624733380370822725617496020411479541134964388194541424021631757495293928014972916724565063934515809466164092481450798821885313089633125087528849591751483057152773325e+214"}, + {"0x1.290ba9a38c7d1p+714", 215, "99999999999999990660396936451049407652789096389402106318690169014230827417515340183487244380298106827518051036015414262787762879627804165648934234223216948652905993920546904997130825691790753915825536773603473752064"}, + {"0x1.290ba9a38c7d2p+714", 215, "1.0000000000000000979665986870629330198032972686455681148365806988089473848554483477848867530432250375881417919571154583994631649339312112649981120190710204647603637787670876363922509633974747510822509281030267784397e+215"}, + {"0x1.734e940c6f9c5p+717", 216, "999999999999999868331443500000006287872809702943711652856965888408980452039094412644869581954932274412588254040761879473560521568747407734787588406864399290882799171293145332687119715621994096773456255662636329336832"}, + {"0x1.734e940c6f9c6p+717", 216, "1.00000000000000002142154695804195744249313474674494929417670909534229174058333036940488102934712744986295727931833093209082895047886994342159460414833548007346784224294244020182387388080564786631265270395622996207206e+216"}, + {"0x1.d022390f8b837p+720", 217, "9999999999999999601855055748251769806450047292244542376488118125689672251656359867008764503902493796828096692073033110439215789148209291468717978517470477604338250142827222541691722147321863584969741246387925089779712"}, + {"0x1.d022390f8b838p+720", 217, "1.000000000000000082657588341258737904341264764265444350704606378115616256001024752108885608304005520043104889429358553137736322042918957696317410444923912386501859471602158149478575546879109374128331283273667415166157e+217"}, + {"0x1.221563a9b7322p+724", 218, "99999999999999988670225591496504042642724870819986016981533507324097780666440272745607095564199569546663253707407016578763273303796211201720443029584092898479300433989106071698353021544403254911815982945786756526505984"}, + {"0x1.221563a9b7323p+724", 218, "1.0000000000000000826575883412587379043412647642654443507046063781156162560010247521088856083040055200431048894293585531377363220429189576963174104449239123865018594716021581494785755468791093741283312832736674151661568e+218"}, + {"0x1.6a9abc9424febp+727", 219, "999999999999999965084388885482519417592855130626093842171043595190833186399051537317196816706799625297221478016185520727674168639944850288849622355474122345476546392575499689981548348018063279122228410984187505225498624"}, + {"0x1.6a9abc9424fecp+727", 219, "1.00000000000000012184865482651747739992406797547856118688246063909054394586834915703944853883640748495839935990041623060775703984391032683214000647474050906684363049794437763597758461316612473913036557403682738514637619e+219"}, + {"0x1.c5416bb92e3e6p+730", 220, "9999999999999999964372420736895110140590976995965873111133270039707753382929110612616471611327211972294570543930316627036907428807379455975076991793273996897499632136492752791807556010476755711238558435947154812096741376"}, + {"0x1.c5416bb92e3e7p+730", 220, "1.000000000000000121848654826517477399924067975478561186882460639090543945868349157039448538836407484958399359900416230607757039843910326832140006474740509066843630497944377635977584613166124739130365574036827385146376192e+220"}, + {"0x1.1b48e353bce6fp+734", 221, "99999999999999984594354677029595135102113336853821866019036664182705300920238534632828550788829765195472628778417018121881118652493108811594893042483166843723756247249515245102456078650553656951604416706418119648563167232"}, + {"0x1.1b48e353bce70p+734", 221, "1.0000000000000000466018071748206975684050858099493768614209804580186827813230862995727677122141957123210339765959854898653172616660068980913606220974926434405874301273673162218994872058950552383264597357715602427843549594e+221"}, + {"0x1.621b1c28ac20bp+737", 222, "999999999999999886075198851200900594497923856820450300436489405065378963626525536977181948753477264027987825546533242948112401553146250111031268759363863437907536003469585205199546070383440303278127280805657005745376329728"}, + {"0x1.621b1c28ac20cp+737", 222, "1.00000000000000004660180717482069756840508580994937686142098045801868278132308629957276771221419571232103397659598548986531726166600689809136062209749264344058743012736731622189948720589505523832645973577156024278435495936e+222"}, + {"0x1.baa1e332d728ep+740", 223, "9999999999999999181805205159248599892793562474462356126333876156560397271658376894962991014456209536865970557564236923315533735757183797070971394269896194384435148282491314085395342974857632902877937717988376531531720556544"}, + {"0x1.baa1e332d728fp+740", 223, "1.00000000000000004660180717482069756840508580994937686142098045801868278132308629957276771221419571232103397659598548986531726166600689809136062209749264344058743012736731622189948720589505523832645973577156024278435495936e+223"}, + {"0x1.14a52dffc6799p+744", 224, "99999999999999996954903517948319502092964807244749211214842475260109694882873713352688654575305085714037182409224841134505892881183378706080253249519082903930108094789640533388351546084948006950326015738792668900564521713664"}, + {"0x1.14a52dffc679ap+744", 224, "1.0000000000000001750230938337165351475308153724525181102085733003813258354803349096492363229827704709554708974355472873990811497562954164756241047679956674427313454264855010352594401143043471863651256997442828324155378630656e+224"}, + {"0x1.59ce797fb817fp+747", 225, "999999999999999928454223448636526995609414612446486912536395043045051171498417578302416590307106934377352009423588636134254484622941461177838218040629861358615028052178586193608330530158506646130887048916655460323666687950848"}, + {"0x1.59ce797fb8180p+747", 225, "1.00000000000000009283347037202319909689034845245050771098451388126923428081969579920029641209088262542943126809822773697747226137851076470969547585887373208135923963504986275470907025292240033962037948280174037505158080469402e+225"}, + {"0x1.b04217dfa61dfp+750", 226, "9999999999999999613300728333138614158656013804472910722260188106898877933626732224819925546638620725877678611585164563028980399740553218842096696042786355031638703687528415058284784747112853848287855356936724432692495112994816"}, + {"0x1.b04217dfa61e0p+750", 226, "1.000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016e+226"}, + {"0x1.0e294eebc7d2bp+754", 227, "99999999999999988242803431008825880725075313724536108897092176834227990088845967645101024020764974088276981699468968789815350713138205618891818585152157755624664880897462875650012340778461641195382916742883168419985073526276096"}, + {"0x1.0e294eebc7d2cp+754", 227, "1.000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016e+227"}, + {"0x1.51b3a2a6b9c76p+757", 228, "999999999999999924509121522475246865178672200286390413373640190927670776874706901000867474584296317792102107215397297714017257980807797893073643852992008461269166974189675556141912776812173197487139230503413422370196749149011968"}, + {"0x1.51b3a2a6b9c77p+757", 228, "1.000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016e+228"}, + {"0x1.a6208b5068394p+760", 229, "9999999999999999918388610622944277578633427011520373324179896670642961784527024602806390495869308408470337715685294734193992593398889846197223766553446979093051960385337504355687757672562640543404353314227442034427503713670135808"}, + {"0x1.a6208b5068395p+760", 229, "1.000000000000000126498340141932789543232683702883331170506688619337546981608693578840182199592199886956897100274793824830163262058051358073019842260050076805377254167221900194422501748144445768047027533261405765587857615803016806e+229"}, + {"0x1.07d457124123cp+764", 230, "99999999999999988411127779858373832956786989976700226194703050524569553592790956543300452958271560395914310860351799229078805716535908585708440417158039479244754953558323062848579498254571868337516156995181495372666457581821100032"}, + {"0x1.07d457124123dp+764", 230, "1.0000000000000000995664443260051171861588155025370724028889488288828968209774953551282735695911460777349244345335409545480104615144188833823603491391090010261628425414842702426517565519668094253057090928936734531588361669158161613e+230"}, + {"0x1.49c96cd6d16cbp+767", 231, "999999999999999884111277798583738329567869899767002261947030505245695535927909565433004529582715603959143108603517992290788057165359085857084404171580394792447549535583230628485794982545718683375161569951814953726664575818211000320"}, + {"0x1.49c96cd6d16ccp+767", 231, "1.00000000000000005647541102052084141484062638198305837470056516415545656396757819718921976158945998297976816934753636209656598064460692387730516014560327977941978394030406231981856423808259127691959958830530175327240184869629512909e+231"}, + {"0x1.9c3bc80c85c7ep+770", 232, "9999999999999999185841044429711589466224211962102134844977374370276477415358432917842475759840644797632681207523216662519436418612086534611285553663849717898419964165273969667523488336530932020840491736225123136358120303938278260736"}, + {"0x1.9c3bc80c85c7fp+770", 232, "1.000000000000000056475411020520841414840626381983058374700565164155456563967578197189219761589459982979768169347536362096565980644606923877305160145603279779419783940304062319818564238082591276919599588305301753272401848696295129088e+232"}, + {"0x1.01a55d07d39cfp+774", 233, "99999999999999997374062707399103193390970327051935144057886852787877127050853725394623645022622268104986814019040754458979257737456796162759919727807229498567311142603806310797883499542489243201826933949562808949044795771481474727936"}, + {"0x1.01a55d07d39d0p+774", 233, "1.0000000000000001943667175980705238830588315677559032649033928912832653863993131025941919471948554861962682179427510579411883194280051942934817649248215877689975714640807276728847796425120893517551500029880911929089916669987624321024e+233"}, + {"0x1.420eb449c8842p+777", 234, "999999999999999841364972759543336764420226292177420345984153909836074800974071744757463152045042997962028093539001436578955132142505622028069656690022719315678435403212464369035268207172574280176140941400150227439321732144446136385536"}, + {"0x1.420eb449c8843p+777", 234, "1.00000000000000001786584517880693032373952892996666180544377340055967009368669242367582754961994924207914815574087624726007172578525540816077571080742215354233800343364659602096002392484233181596564547219412071017415669957160428424397e+234"}, + {"0x1.9292615c3aa53p+780", 235, "9999999999999999119653217272487741881479473472931169297680017061255129180591200163248089110750054956088761184197513608514017695996055364811520783369824930063422626153861170298051704942404772944919427537177384205332557191153093955289088"}, + {"0x1.9292615c3aa54p+780", 235, "1.000000000000000053166019662659649035603389457524510097335697298704389152229216559459500429134930490902572168181251209396295044513805365387316921630902040387669917039733422351344975068376283323123546378352914806721123693057035913815654e+235"}, + {"0x1.f736f9b3494e8p+783", 236, "99999999999999994020546131433094915763903576933939556328154082464128816489313932495174721468699049466761532837205133056038042458244550226238504699576640248260779350025557809411313140906763850021826347864477369777082931390365469918625792"}, + {"0x1.f736f9b3494e9p+783", 236, "1.0000000000000000531660196626596490356033894575245100973356972987043891522292165594595004291349304909025721681812512093962950445138053653873169216309020403876699170397334223513449750683762833231235463783529148067211236930570359138156544e+236"}, + {"0x1.3a825c100dd11p+787", 237, "999999999999999940205461314330949157639035769339395563281540824641288164893139324951747214686990494667615328372051330560380424582445502262385046995766402482607793500255578094113131409067638500218263478644773697770829313903654699186257920"}, + {"0x1.3a825c100dd12p+787", 237, "1.00000000000000012094235467165686896238200167043557881776819118314224974463086290016415235780369448864354627206677113669784381647262128326227604641198342313070719116342012890568408126396147021686671611817779947209130032054906464259329229e+237"}, + {"0x1.8922f31411455p+790", 238, "9999999999999999040580826428657651966904425891201589123842107529410958489455946099092661860636496958724291396331073693328877462044103460624068471125229983529879139676226679317989414380888721568885729507381685429067351125745727105048510464"}, + {"0x1.8922f31411456p+790", 238, "1.000000000000000048647597328726501040484815309997105515973531039741865112735773470079190300557012891053173894588883214242858459716550970862319646645496614871467432098154308581055701322003937530207335062364589162363111917890900665230478541e+238"}, + {"0x1.eb6bafd91596bp+793", 239, "99999999999999999081179145438220670296706622164632687453780292502155740721970192601122065475966761298087599260657287627887017431169472094235452683230716826407562484594165232135299736843791138087983021771402091458056119576436948334022754304"}, + {"0x1.eb6bafd91596cp+793", 239, "1.0000000000000001064834032030707953780025643983478841574092591544621728182518450141471599463543581691254717965711935522068467451214072207822847664586860614788592393503669648407584052755699636795348399070151574101456626400174318471207295386e+239"}, + {"0x1.33234de7ad7e2p+797", 240, "999999999999999828871535006218182557917368774264146678517764203804695831774701602620905646527100834378441867056103929979702975178097221166452191355376717763378564539746214794185426298453038162762816652692429820789419173810082174047524749312"}, + {"0x1.33234de7ad7e3p+797", 240, "1.00000000000000001394611380411992443797416585698663833111209417090968048942613054363840851307860572420979515339949701146446548847363722091034057475758294690703234774682671482523407894986432184061083215557424821369358148461498195609632794214e+240"}, + {"0x1.7fec216198ddbp+800", 241, "9999999999999999029013665253788793099400876073531433395554961906466896948352731790279067931477027903109831815934611625736079804963132210640075447162592094208400778225784148066048873590175516339020228538451571779510840981320420868670460264448"}, + {"0x1.7fec216198ddcp+800", 241, "1.00000000000000005096102956370027281398552527353113666163096016433067742095641633184190908638890670217606581066817562776141799113274522085911825143802419273576310438824281483144380948014657857618043525615061189227441394677596191250608858071e+241"}, + {"0x1.dfe729b9ff152p+803", 242, "99999999999999993251329913304315801074917514058874200397058898538348724005950180959070725179594357268399970740840405561116998262359962102302968606061220608382468313571129481157267178324335702235770533430624812081575006786082605199485453729792"}, + {"0x1.dfe729b9ff153p+803", 242, "1.0000000000000000509610295637002728139855252735311366616309601643306774209564163318419090863889067021760658106681756277614179911327452208591182514380241927357631043882428148314438094801465785761804352561506118922744139467759619125060885807104e+242"}, + {"0x1.2bf07a143f6d3p+807", 243, "999999999999999885134206960780312089454635087411784140906440513804611167700736000690226517958758320887173266104495426751070779219941381088594259909647411423049314634698686803624216704482068400828613365568502612232284516294771707790360919932928"}, + {"0x1.2bf07a143f6d4p+807", 243, "1.0000000000000000746505756498316957746327953001196155931630344001201154571357992362921494533074993280744790313201299421914675928345743408263359645135065900661507886387491188354180370195272228869449812405194846465661467225589890846083353893929e+243"}, + {"0x1.76ec98994f488p+810", 244, "9999999999999999230374806985905888264902671299533504313577592910677120255877486478106111050285065223246344191476223298391501419428679730361426008304192471516696094355087732099829807674910992980518869405586990190990569575476151831539558138249216"}, + {"0x1.76ec98994f489p+810", 244, "1.000000000000000074650575649831695774632795300119615593163034400120115457135799236292149453307499328074479031320129942191467592834574340826335964513506590066150788638749118835418037019527222886944981240519484646566146722558989084608335389392896e+244"}, + {"0x1.d4a7bebfa31aap+813", 245, "99999999999999992303748069859058882649026712995335043135775929106771202558774864781061110502850652232463441914762232983915014194286797303614260083041924715166960943550877320998298076749109929805188694055869901909905695754761518315395581382492160"}, + {"0x1.d4a7bebfa31abp+813", 245, "1.0000000000000000443279566595834743850042896660863625608019793783096347708261891185958417836517007669245101088856284197210041026562330672682972917768891214832545527981010497103310257691199981691663623805273275210727287695567143043174594742793011e+245"}, + {"0x1.24e8d737c5f0ap+817", 246, "999999999999999874521290314193434603084658115500145579580071256170942927492372459496518833579228824484684143252419893886408557657521935343280724451831297419035632090471862609843762766839539749606096764571247618309588232743975534688554349643169792"}, + {"0x1.24e8d737c5f0bp+817", 246, "1.00000000000000006858605185178205149670709417331296498669082339575801931987387721275288791937633961584448524683322963769737489479890608611472822996618309634957154147061950501040063476944577794338925746852105322146746313195853412855016020637017702e+246"}, + {"0x1.6e230d05b76cdp+820", 247, "9999999999999999521471949292288813605336325386252733424243721120057734844449743607990664678980731410286045846847437914107950925140755956518597266575720169912499958425309195700665115678820350271193610461511698595727381924297989722331966923339726848"}, + {"0x1.6e230d05b76cep+820", 247, "1.00000000000000010739900415929977487543158138487552886811297382367543459835017816340416173653576177411644546754939158645956816222718291626901773106905345613567872334664903349051200916996702558214588960931101434209903811180144584732248137771557847e+247"}, + {"0x1.c9abd04725480p+823", 248, "99999999999999992109683308321470265755404276937522223728665176967184126166393360027804741417053541441103640811181423240104047857145413152842812577527572916236425034170729678597741204746503691611405533351920096306747820855546959721533975525765152768"}, + {"0x1.c9abd04725481p+823", 248, "1.0000000000000000452982804672714174694724018463754266578375331390075701527880966423621236290806863208813091144035324684400589343419399880221545293044608804779072323450017879223338101291330293601352781840470765490885181440527870972867675035629361562e+248"}, + {"0x1.1e0b622c774d0p+827", 249, "999999999999999921096833083214702657554042769375222237286651769671841261663933600278047414170535414411036408111814232401040478571454131528428125775275729162364250341707296785977412047465036916114055333519200963067478208555469597215339755257651527680"}, + {"0x1.1e0b622c774d1p+827", 249, "1.00000000000000011981914889770544635662341729257554931016806196060900748746259446761256935802677686476347273817856341006347000780423150191839037142197197126723302154697848260414764897813382482654801189436380190070114210535117759732962415254610693325e+249"}, + {"0x1.658e3ab795204p+830", 250, "9999999999999999210968330832147026575540427693752222372866517696718412616639336002780474141705354144110364081118142324010404785714541315284281257752757291623642503417072967859774120474650369161140553335192009630674782085554695972153397552576515276800"}, + {"0x1.658e3ab795205p+830", 250, "1.000000000000000080074685734807297616809542387935483895591779922421574242302862294145664969255528574692985472165213574530984101957676027840397922292632722846259267305924245440513601592000067244461220582194881713174409325992035997306767273088415852134e+250"}, + {"0x1.bef1c9657a685p+833", 251, "99999999999999992109683308321470265755404276937522223728665176967184126166393360027804741417053541441103640811181423240104047857145413152842812577527572916236425034170729678597741204746503691611405533351920096306747820855546959721533975525765152768000"}, + {"0x1.bef1c9657a686p+833", 251, "1.0000000000000000482791152044887786249584424642234315639307542918716276461750765553721414582385299426365956593545337061049953772804316485780039629891613241094802639130808557096063636830930611787917875324597455631530231025047227172884817695222629872435e+251"}, + {"0x1.17571ddf6c813p+837", 252, "999999999999999895660376658959887464073162830405580371957831265231883984761705009259228605356936508765924557863270337660249498829658628118512958332498610172941047627432585001251621720339432063578508893731092043050369229765618973200711352404729235767296"}, + {"0x1.17571ddf6c814p+837", 252, "1.00000000000000009915202805299840901192020234216271529458839530075154219997953373740977907586572775392681935985162149558657733676402265539783429787471556208832666934163027927905794433734427088386288041203596340318724106008442396531773857522810757106893e+252"}, + {"0x1.5d2ce55747a18p+840", 253, "9999999999999999363587069377675917736425707327570073564839440723358156278052707548893386994586947577981035182609405692455150664165314335743772262409420005560181719702721238568128862437403998276353831973920663150777435958293799716241167969694049028276224"}, + {"0x1.5d2ce55747a19p+840", 253, "1.000000000000000099152028052998409011920202342162715294588395300751542199979533737409779075865727753926819359851621495586577336764022655397834297874715562088326669341630279279057944337344270883862880412035963403187241060084423965317738575228107571068928e+253"}, + {"0x1.b4781ead1989ep+843", 254, "99999999999999993635870693776759177364257073275700735648394407233581562780527075488933869945869475779810351826094056924551506641653143357437722624094200055601817197027212385681288624374039982763538319739206631507774359582937997162411679696940490282762240"}, + {"0x1.b4781ead1989fp+843", 254, "1.0000000000000000665933638299522455642646760202815737069675050550683968855446811409056910005843211547010761915334853103183648826945244110331428835479608497818649698673586481946089327186234966726173809691071839855653415672334151665790142195763670374206669e+254"}, + {"0x1.10cb132c2ff63p+847", 255, "999999999999999988452569694641453289891412847766833896677368465428848130901034909295879619908945316559292587569958465674654992927728624557883489163749540246356891129106733591931304833693638565628182306078113383272782784390994049606075766012189756664840192"}, + {"0x1.10cb132c2ff64p+847", 255, "1.00000000000000019682802072213689935488678130780614005745106603780097814328409152692204330170994755160404886480603005139121469897251738849190854085497969900771176776444517253240497919350659351759937874082230165605293953863745036153391164218332917201371136e+255"}, + {"0x1.54fdd7f73bf3bp+850", 256, "9999999999999998634272990781441856508941917717432502002131499220055701234712009387201814108283439755324388212283155142447191693008553661974684581490114449895439651479036702276471002178058655944454644452316004196046887318431202624493742403095061074555174912"}, + {"0x1.54fdd7f73bf3cp+850", 256, "1.000000000000000030127659900140542502890486539774695128832107979903274133377646232821112356269145763568243843017172782817966934136686377344688499501995571998627866456174421380026039705656229556022421593026951037828814135240285311991642941246417639734614426e+256"}, + {"0x1.aa3d4df50af0ap+853", 257, "99999999999999989676737124254345702129345072534953918593694153358511092545248999754036759991650433313959982558608696795936872226802156842691246641960827039136074540955782045812288811537593838676085587479067054324951381252255327235782798049688841391133687808"}, + {"0x1.aa3d4df50af0bp+853", 257, "1.0000000000000000301276599001405425028904865397746951288321079799032741333776462328211123562691457635682438430171727828179669341366863773446884995019955719986278664561744213800260397056562295560224215930269510378288141352402853119916429412464176397346144256e+257"}, + {"0x1.0a6650b926d66p+857", 258, "999999999999999843423255779504622828654636399579476808778874955057845642282427503428069697375447760968142218613652642015929437520555644859802053186653349748453896990911180089361627479263821919056229587496158345417793683435460456504301996197076723582025859072"}, + {"0x1.0a6650b926d67p+857", 258, "1.0000000000000000567997176316599595992098937026597263174111412691669067749626774798772613075396740496539726465033899457896865765104193391282437061184730323200812906654977415644066700237122877898747347366742071367446741997838317199184059333963234848992699351e+258"}, + {"0x1.4cffe4e7708c0p+860", 259, "9999999999999999287738405203667575368767393208115766122317814807014700953545274940077463414411382764424743897695475635254322931165011225671787143593812227771048544607458046793796444970432082673836316471673778619485458899748089618699435710767754281089234894848"}, + {"0x1.4cffe4e7708c1p+860", 259, "1.00000000000000009947501000209102695332094516327577621913759453198871900149872747516709962957251930739113873208133740654443800430839207798193203670483696883440676940041505385941567853260198096403843576650981689501005030305350597260122672083617283716271875031e+259"}, + {"0x1.a03fde214caf0p+863", 260, "99999999999999992877384052036675753687673932081157661223178148070147009535452749400774634144113827644247438976954756352543229311650112256717871435938122277710485446074580467937964449704320826738363164716737786194854588997480896186994357107677542810892348948480"}, + {"0x1.a03fde214caf1p+863", 260, "1.0000000000000000653347761057461730700321039947829362977564319217312692202698874789352289719462431012014058636189794379406368620700138868989813722357458196229463864124812040234084717254902264247074749426413290883977494204377665704549700908842933553519596981453e+260"}, + {"0x1.0427ead4cfed6p+867", 261, "999999999999999928773840520366757536876739320811576612231781480701470095354527494007746341441138276442474389769547563525432293116501122567178714359381222777104854460745804679379644497043208267383631647167377861948545889974808961869943571076775428108923489484800"}, + {"0x1.0427ead4cfed7p+867", 261, "1.00000000000000014727133745697382238992532279916575210907122218634914869521910346989171855024930599605676474792863856258975960344212154549806296696156457773045130558352244362982576806255843731910178091992569982426727153871554113560598600276880411169778142334157e+261"}, + {"0x1.4531e58a03e8bp+870", 262, "9999999999999998413748417457239315956573059294699064134960051984423986554086971036541574579178711885967582465059111638997013689862529533948250133185078807957662740116351490992011950708371166466963719380640490770210556304785160923755265983999639546733803159420928"}, + {"0x1.4531e58a03e8cp+870", 262, "1.000000000000000016172839295009583478096172712153246810967557762960541535300357884361335224964405364288190533033183963151163217246749291739532415400254564758443434909856460259558093923249299888070891356270706646876036149471101831364360543753586901544466663027507e+262"}, + {"0x1.967e5eec84e2ep+873", 263, "99999999999999987633444125558106197214507928600657449299031571134602723138702925979559301132717802373504470381136572374999373863835222106376649373485721758830170619127941133127257484131955329497127582170538059099205173427703324017329338747068854404759758535917568"}, + {"0x1.967e5eec84e2fp+873", 263, "1.0000000000000000161728392950095834780961727121532468109675577629605415353003578843613352249644053642881905330331839631511632172467492917395324154002545647584434349098564602595580939232492998880708913562707066468760361494711018313643605437535869015444666630275072e+263"}, + {"0x1.fc1df6a7a61bap+876", 264, "999999999999999932269800471352470574525516656465243420181212531991832952952360709621889896782068959956303035500093019510461530081711049334072862401016156456358397678710230902586782474091451932211122035531511013345645500354660676649720249983847887046345216426508288"}, + {"0x1.fc1df6a7a61bbp+876", 264, "1.0000000000000000441405189028952877792863913973825812745630061732834443960830236092744836676918508323988196988775476110313971129684287058746855997333340341924717806535718700452151977396352492066908144631837718580528330325099155496025739750101665730438404785611735e+264"}, + {"0x1.3d92ba28c7d14p+880", 265, "9999999999999998875215130987353436926211667600983082784284950754751883757000955497608523884181562109792963701491111829020872969270239867178277674680890053619130444887655752455354163678739330224192450644706066754627704874925587274685787599733204126473471115726422016"}, + {"0x1.3d92ba28c7d15p+880", 265, "1.000000000000000066514662589203851220238566345566048845439364901541766684709156189205002421873807206887323031553038529335584229545772237182808147199797609739694457248544197873740880792744008661586752948714224026994270538940966524193144720015430310243339530988106547e+265"}, + {"0x1.8cf768b2f9c59p+883", 266, "99999999999999988752151309873534369262116676009830827842849507547518837570009554976085238841815621097929637014911118290208729692702398671782776746808900536191304448876557524553541636787393302241924506447060667546277048749255872746857875997332041264734711157264220160"}, + {"0x1.8cf768b2f9c5ap+883", 266, "1.0000000000000000307160326911101497147150864284725007320371909363284510229073440613161724151826770077057176992722530600488848430220225870898120712534558888641381746965884733480997879077699935337532513718655005566879705286512849648482315280070083307241410471050136781e+266"}, + {"0x1.f03542dfb8370p+886", 267, "999999999999999973438224854160227305877518561122823750593712591987145964024444656694044404476868689015149167622996309190165824584023146941018349739309135463248122613459314107074039291811569329219648848907543004197890512187794469896370420793533163493423472892065087488"}, + {"0x1.f03542dfb8371p+886", 267, "1.00000000000000008799384052806007212355265429582217771348066928066975608179024346593830042588848532639628623092150981090760386146002202723860579276760264226502822677971763258912553652372841773828685389482345810917805054511477545980009263522048349795485862131796226867e+267"}, + {"0x1.362149cbd3226p+890", 268, "9999999999999999734382248541602273058775185611228237505937125919871459640244446566940444044768686890151491676229963091901658245840231469410183497393091354632481226134593141070740392918115693292196488489075430041978905121877944698963704207935331634934234728920650874880"}, + {"0x1.362149cbd3227p+890", 268, "1.000000000000000156727209932399979014157735736641790091212843293879322152449722751484854038735455308824968468900617911938066683585621355417158258584578746346096289279472623678356434862878526783727176922373007172166146564870964053742325963876653698631719710373500577382e+268"}, + {"0x1.83a99c3ec7eafp+893", 269, "99999999999999990012263082286432662256543169091523721434606031123027548865433341877772055077343404109122144711194766809100548098338386355056238620120129111010885594705399027856108106338478634741663761952135733701058809111452663635798820356028494943810497789949089153024"}, + {"0x1.83a99c3ec7eb0p+893", 269, "1.0000000000000000467538188854561279891896054313304102868413648727440164393945558946103682581803033369390768881340449502893261681846624303314743132774169798163873892798646379355869975202383523110226600782937286713851929332610623034347526380267813775487419678846392834458e+269"}, + {"0x1.e494034e79e5bp+896", 270, "999999999999999929448868435382686895890266438998271828845121223533023678802377913944250092254807900260792535316367124530669618423639576906744771616444428851364562613616119809966264354755499540137842111275831603885509059543833769773341090453584235060232375896520569913344"}, + {"0x1.e494034e79e5cp+896", 270, "1.00000000000000004675381888545612798918960543133041028684136487274401643939455589461036825818030333693907688813404495028932616818466243033147431327741697981638738927986463793558699752023835231102266007829372867138519293326106230343475263802678137754874196788463928344576e+270"}, + {"0x1.2edc82110c2f9p+900", 271, "9999999999999999529098585253973751145501342374646995204443699533752222309208135100774737254399069875964494058799026896824009283758441475916906799486389390443691279468658234350904109878520700943148057046794110173854458342872794765056233999682236635579342942941443126198272"}, + {"0x1.2edc82110c2fap+900", 271, "1.000000000000000140597779245514880863829076625196121053238359792112810647868298279143262790920699686281704370388187210896251407993480713071257946606195020588405650612863452436083584052624634527730514451908046325384940032234845130363881876085339091539549641475134254271693e+271"}, + {"0x1.7a93a2954f3b7p+903", 272, "99999999999999991537227438137387396469434575991841521388557198562770454753131655626431591234374844785939841297824578543963083245231683449577722661712772273556182341366629763489177637489755720763166395523368395578554699469776634573397170474480057796161122485794632428945408"}, + {"0x1.7a93a2954f3b8p+903", 272, "1.0000000000000000655226109574678785641174996701035524401207638566177752810893043715169471647283826068076023845848734024107112161464260868794310399431725879707910415464644008356863148267156087543642309530165922021851423530558188688205784856384929203469035026027382776109466e+272"}, + {"0x1.d9388b3aa30a5p+906", 273, "999999999999999945402341696592674884578976541955442659132610359825718694242914119314842162820675279649039207299571308833846909191138684972507989282336695782607667040225918275050684065261167516978177354790265605065466066369376850351293060923539046438669680406904714953752576"}, + {"0x1.d9388b3aa30a6p+906", 273, "1.00000000000000006552261095746787856411749967010355244012076385661777528108930437151694716472838260680760238458487340241071121614642608687943103994317258797079104154646440083568631482671560875436423095301659220218514235305581886882057848563849292034690350260273827761094656e+273"}, + {"0x1.27c35704a5e67p+910", 274, "9999999999999999213782878444176341486712719163258207029349796604673073768736360688744211624391338142173265718425108901184740478000812045911233791501695173449709921389782217629235579129702792695009666351450002856415308090320884466574359759805482716570229159677380024223137792"}, + {"0x1.27c35704a5e68p+910", 274, "1.000000000000000113570718661817960035932908921362796352516025255334597915827860472397789165491465537671027655498994239841456938928541047642200260207506944846064391348959793859940567131297385249318652392307122841033012867730395676208292655524474469910197031481071702673824154e+274"}, + {"0x1.71b42cc5cf601p+913", 275, "99999999999999995981677400789769932612359931733321583285118877944076548466448094957909476304960015890806678857380756006307062602577317320133875536163700284518967198097453618232695975663570046546450378657742479671982722077174989256760731188933351130765773907040474247261585408"}, + {"0x1.71b42cc5cf602p+913", 275, "1.0000000000000001135707186618179600359329089213627963525160252553345979158278604723977891654914655376710276554989942398414569389285410476422002602075069448460643913489597938599405671312973852493186523923071228410330128677303956762082926555244744699101970314810717026738241536e+275"}, + {"0x1.ce2137f743381p+916", 276, "999999999999999929065985077113647184161737396527299728918221484261998998431805045015355882561227083155474615188770224107393363445219598313166454392463014445014728107377484646804238281703363508693674065431485187857190091380020735839470243162305319587149880588271350432374194176"}, + {"0x1.ce2137f743382p+916", 276, "1.00000000000000005206914080024985575200918507975096414465009066497706494336250866327031140451471938616584330872891956793010241376743389786585565826915896804571450360176569078889512418143271133577699295001524362330773860894693736275201851807041808646918131451680491859334083379e+276"}, + {"0x1.20d4c2fa8a030p+920", 277, "9999999999999998060628293539774386163142897133036353131863523035469330535011014267604003606077347801451059216486208802846843131230052987604772505157670608443149526129892785047133523819740156816103551808477267524066415738131041089269219682541925527051184466597377822714075545600"}, + {"0x1.20d4c2fa8a031p+920", 277, "1.000000000000000002867878510995372324870206006461498378357342992691038565390227215968329195733322464961695831312859830401018793638548178044779976718480586605434593404010408332058769821540972204943665396181740249127519201920170711986999208107172979716368740945391491328954177946e+277"}, + {"0x1.6909f3b92c83dp+923", 278, "99999999999999996350686867959178558315902274782992576532314485486221746301240205812674342870820492799837784938001204037775189753543960218791943147793788145321066524580618236658968633362758090027700335311493754978334367629875739137498376013657689431411868208826074951744485326848"}, + {"0x1.6909f3b92c83ep+923", 278, "1.000000000000000120950908005206132550003755782356216217459937406177501872523702689493086496808675075851649777111403200470819481947873905615361612440108702062106377878623086228466020285281146118943651525382148347160045778784410673823045552018961235923118917516783716763482151977e+278"}, + {"0x1.c34c70a777a4cp+926", 279, "999999999999999932018060814468916189790076140924667674895786344599160581110141931853474815088110898427723463833733808359138380652952741502430995285503717331431522719242801594214419543296867856543673718661495390308003255801626734885371401760100025992318635002556156068237393526784"}, + {"0x1.c34c70a777a4dp+926", 279, "1.00000000000000005797329227496039376326586256854570003660522038565138810871918243694654926956848701671034100601884673643359244818290018424438474005524037381854809282549632468371548670461972003147699225647526402820936493779014936084382083526600749927951882334537452986506723249357e+279"}, + {"0x1.1a0fc668aac6fp+930", 280, "9999999999999998312538756460757341310094469988278417855282391117573785590229095277790152515038100038016294300856434658995751266289947873088679994697143921417382666342399831226135658142385861165970188884104804799869139102108086341186118549553740473625584843283014570307735223533568"}, + {"0x1.1a0fc668aac70p+930", 280, "1.000000000000000032782245982862098248570705283021493564263333577440942603197374335927934378672411793053817497581824150818701634676910695695993991101293042521124778804245620065815273272355149596490328548912510300629092601392444835652130948564826004622078785676810855105701264700211e+280"}, + {"0x1.6093b802d578bp+933", 281, "99999999999999987155954971343300695452169865566657214127525800489409136785780248940879907693753036165206704358487960288340042823857796898629319779603012221761556906824111051125390730586189881257568082051088644411534964844713587442531567367726443881446254459800333664575907082272768"}, + {"0x1.6093b802d578cp+933", 281, "1.0000000000000000327822459828620982485707052830214935642633335774409426031973743359279343786724117930538174975818241508187016346769106956959939911012930425211247788042456200658152732723551495964903285489125103006290926013924448356521309485648260046220787856768108551057012647002112e+281"}, + {"0x1.b8b8a6038ad6ep+936", 282, "999999999999999903804088967318825213331499981137556425872873119403461614925716858712626137284506647932417134384268512470460669526244514328233356457082706278317411015442012422166180499160548969358610366191211215418098239036197666670678728654776751975985792813764840337747509598224384"}, + {"0x1.b8b8a6038ad6fp+936", 282, "1.0000000000000000327822459828620982485707052830214935642633335774409426031973743359279343786724117930538174975818241508187016346769106956959939911012930425211247788042456200658152732723551495964903285489125103006290926013924448356521309485648260046220787856768108551057012647002112e+282"}, + {"0x1.137367c236c65p+940", 283, "9999999999999999553953517735361344274271821018911312812290573026184540102343798495987494338396687059809772796632907678097570555865109868753376103147668407754403581309634554796258176084383892202112976392797308495024959839786965342632596166187964530344229899589832462449290116390191104"}, + {"0x1.137367c236c66p+940", 283, "1.000000000000000161760402998405371283809910584905430702653794035478423591469031813143242620060316938175217860779379789166942599827576877063754625745503378763932146593049227709464366045549750223622046731633809385840086963748692004633583168474875257268171778539856869873655019802198016e+283"}, + {"0x1.585041b2c477ep+943", 284, "99999999999999991412234152856228705615063640528827139694410995604646009398744945688985079659553905954212916344007296353831994673829780883765420722861953317774200043854630103365810792101611701952914782080891514223497778802469744018919490624758069218767323224280852151918381000638332928"}, + {"0x1.585041b2c477fp+943", 284, "1.0000000000000000792143825084576765412568191916997109340838993423344357589751710277254453455720576452975216283329441806240683821311505209883878195732087635685354312082149188175289466707052058222577470946921779713050505718406938164854537477324437355746722631075074204221646165369264538e+284"}, + {"0x1.ae64521f7595ep+946", 285, "999999999999999980159157920520442850193109519852847211800025710561650359982538085224088616186146493844286149397221450372619320895438893697947652166455225334059372746413748147206443420891752540620587530362220273863006901551095990707698442841525909542472844588688081080376132618600579072"}, + {"0x1.ae64521f7595fp+946", 285, "1.00000000000000011223279070443675443827805574898199884151185721959203089197271534189256425536736136244860012131151842404121806920972106341853454204212660964669411736214864237430311442064302358280346694946883053711906512860389309174470551602941634425207206928044720020276077784303507866e+285"}, + {"0x1.0cfeb353a97dap+950", 286, "9999999999999998216707985798208689444911740448978652561458278997251937215943253772219178491686886515191093831000650819703008229183002900332433843156495641588976792075318750746904382211902272900011322274342879579557370290877394694632899550160573878909537749585771381335145583492791795712"}, + {"0x1.0cfeb353a97dbp+950", 286, "1.000000000000000032988611034086967485427088011504507863684758314173802572778608987891478871858632441286011738162940239840058820221151761586182408116723779059113270592707705838045111820792260957493739298004864379165430192372214831122501272116682083426312534465391728729329990708374378906e+286"}, + {"0x1.503e602893dd1p+953", 287, "99999999999999990619792356152730836086553963154052229916140006550463726206803882148974225824466616742587032512521514511820402183944087865441899383607925011898391576160220738003230766103104075699817505566251852643961429440152961412697448185630726610509727876130297437184073129291725930496"}, + {"0x1.503e602893dd2p+953", 287, "1.0000000000000000752521735249401871936142708048258363851925443970635243430154657100253910763966211992393922091755152714140104196817220558967702128769386220391563888697428719907160465407126676909922607121189796634073688250291099034543435355368070225333842863667546468484930771801934187725e+287"}, + {"0x1.a44df832b8d45p+956", 288, "999999999999999872387073568844732594315793396883459481955171199192859845878553443782612494614275161063165948315155119859042742270984643205948750027907375734949421139974074457895559885094715370199357924371226299046063388276013556261500671120207314819439877240212639876510262115462027411456"}, + {"0x1.a44df832b8d46p+956", 288, "1.00000000000000000763047353957503566051477833551171075078008666443996951063649495461113154913583918651398345555539522089568786054480958499982972526059487327108739962648660614644255098884001691739462644953639520862026701277807778772339591406460711996206948332457397785783213882528295498547e+288"}, + {"0x1.06b0bb1fb384bp+960", 289, "9999999999999998453383935746986719810759964091578092281901881061434379129269651416169086837099623559730024468671070996517137186162196548471725549813698762277218254426715681201861616643456550607603042193381925171312226633756007099691216225313273537909139560233403722802458867734978418966528"}, + {"0x1.06b0bb1fb384cp+960", 289, "1.000000000000000061727833527867156886994372310963011258310052850538813376539671558942539170944464796694310458451491261310345907854339561717382115353669872285542591021091618821861347430338137536272733859602462772449948462578903480308154011242367042019121325758318513050360889509211326015078e+289"}, + {"0x1.485ce9e7a065ep+963", 290, "99999999999999988861628156533236896225967158951884963421416105502251300564950642508203478115686284411726404918398393198344015646384363622121446705582987543928597855835557826052119881754415155586279014739104656819496782321626126403692810027353529143655542997033600043426888732064053872033792"}, + {"0x1.485ce9e7a065fp+963", 290, "1.0000000000000000617278335278671568869943723109630112583100528505388133765396715589425391709444647966943104584514912613103459078543395617173821153536698722855425910210916188218613474303381375362727338596024627724499484625789034803081540112423670420191213257583185130503608895092113260150784e+290"}, + {"0x1.9a742461887f6p+966", 291, "999999999999999957860902350346284132153551878096514283852517773229033154005572478626236537071903625148082612890986863714202457020042006419681526374965874177788623543449994485057258262661745948026767632275613049896960078961318150545418464661067991669581788285529005480705688196068853638234112"}, + {"0x1.9a742461887f7p+966", 291, "1.0000000000000000963501439203741144719413124552518435831292312096420734507177045857146400489019851872097197403049927271757270581324387468166156450132378716547939135136388269341293771528969347323547226020447460133009445904514319235623991934361333921356345049159150155735792899469254834740265e+291"}, + {"0x1.008896bcf54f9p+970", 292, "9999999999999997916738124663128877244082391855101191247204616495333847979510139501201523228758057506741180599941798275603729356851659179433605840090394772053822755792233955461707155943795194068332216685526534938121786651731816229250415901309895111103185283290657933692573660950408978352832512"}, + {"0x1.008896bcf54fap+970", 292, "1.000000000000000013256598978357416268068656108958646003563203147794249272690425321461597941803936249972737463856589209098812297465000702578455173830274673168590739531525527464686105818755821461757949620183266235258553883557363659752210756171094151856002874937683409517855128896411505572551066e+292"}, + {"0x1.40aabc6c32a38p+973", 293, "99999999999999992462348437353960485060448933957923525202610654848990348279466077292501969423268405025328970231162545648343655275306678872441733790178059478330735395060467469727994972900530063978805843953102113868000379620369084502134308975505229555772913629423636305841602377586326247764393984"}, + {"0x1.40aabc6c32a39p+973", 293, "1.0000000000000001018897135831752276855328228783380567551002997470985950625861898699981761893751884496921852254015529617141880421769346164324930097587687515538741251124463802320922619085063422837278408008355113318371039709110364744830784225871360081542766135811304559772942340169597486674581914e+293"}, + {"0x1.90d56b873f4c6p+976", 294, "999999999999999924623484373539604850604489339579235252026106548489903482794660772925019694232684050253289702311625456483436552753066788724417337901780594783307353950604674697279949729005300639788058439531021138680003796203690845021343089755052295557729136294236363058416023775863262477643939840"}, + {"0x1.90d56b873f4c7p+976", 294, "1.00000000000000006643646774124810311854715617058629245448546110737685674662788405058354489034668756980440612078356746066803774429216105089087787538737112019976077088007803912512979947260613395493988432857461329320568393596956734859073135602071926563496711812375163739351859196874045142949534106e+294"}, + {"0x1.f50ac6690f1f8p+979", 295, "9999999999999999813486777206230041577815560719820581330098483720446847883279500839884297726782854580737362697004022581572770293687044935910015528960168049498887207223940204684198896264456339658487887951484580004902758521100414464490983962613190835886243290260424727924570510530141380583845003264"}, + {"0x1.f50ac6690f1f9p+979", 295, "1.000000000000000094799064414789802772135689536787703894977332019154247399394528706115249929569488273714629404477955861504957982599979903324169982884489225283051454265972712010699769421326300617970249506383331724110819963922742649304609009273852659650414714489654692260539105607315889219865621299e+295"}, + {"0x1.3926bc01a973bp+983", 296, "99999999999999998134867772062300415778155607198205813300984837204468478832795008398842977267828545807373626970040225815727702936870449359100155289601680494988872072239402046841988962644563396584878879514845800049027585211004144644909839626131908358862432902604247279245705105301413805838450032640"}, + {"0x1.3926bc01a973cp+983", 296, "1.0000000000000001628692964312898819407481696156710913521578222074199849660344758793913420237042099630991652853444880235135665545387451491640710408775726774829490943921199269360676972982547006092431259331242559582831464310103633710179153770813728052874889457678220239413883383398969399167542938829e+296"}, + {"0x1.87706b0213d09p+986", 297, "999999999999999872436306494222877488001587945768638201521064070819504681704034606746682422062730755058478860313950798943503314266680100247159860107083281430052496520558476587831205023360193979812186512362979225814553504769848291707808207769286850569305558980974742103098278680884456943362624192512"}, + {"0x1.87706b0213d0ap+986", 297, "1.0000000000000000176528014627563797143748787807198647768394431391197448238692552430690122228834703590788220728292194112285349344027126247056154504923279794565007954563392017619494511608074472945276562227436175920488499678901058313628617924253298279283972523743983830222433085103906984300584590377e+297"}, + {"0x1.e94c85c298c4cp+989", 298, "9999999999999999595662034753429788238255624467393741467120915117996487670031669885400803025551745174706847878231119663145222863482996149222332143382301002459214758820269116923021527058285459686414683385913622455551313826420028155008403585629126369847605750170289266545852965785882018353801250996224"}, + {"0x1.e94c85c298c4dp+989", 298, "1.00000000000000007573939945016978060492419511470035540696679476643984088073534349759794414321176620068695935783532685614254758245712563448899768664642585866708011503065149183159674961578634862041384410689587293854256855313820884722488322628774701887203392973176783938990132044219319502473679297577e+298"}, + {"0x1.31cfd3999f7afp+993", 299, "99999999999999986662764669548153739894665631237058913850832890808749507601742578129378923002990117089766513181334005445210204946123879926882163649167349350899456456312724758086647517786230384722356772394775369116518164624503799012160606438304513147494189124523779646633247748770420728389479079870464"}, + {"0x1.31cfd3999f7b0p+993", 299, "1.0000000000000000525047602552044202487044685811081591549158541155118024579889081957863713750804478640437044438328838781769425232353604305756447921847867069828483872009265758037378302337947880900593689532349707999450811190389676408800746527427801424945792587888200568428381156694721963868654594005402e+299"}, + {"0x1.7e43c8800759bp+996", 300, "999999999999999903803069407426113968898218766118103141789833949572356552411722264192305659040010509526872994217248819197070144216063125530186267630296136203765329090687113225440746189048800695790727969805197112921161540803823920273299782054992133678869364753954248541633605124057805104488924519071744"}, + {"0x1.7e43c8800759cp+996", 300, "1.00000000000000005250476025520442024870446858110815915491585411551180245798890819578637137508044786404370444383288387817694252323536043057564479218478670698284838720092657580373783023379478809005936895323497079994508111903896764088007465274278014249457925878882005684283811566947219638686545940054016e+300"}, + {"0x1.ddd4baa009302p+999", 301, "9999999999999999335434075769817752248594687291161143444150379827602457335271594505111188022480979804302392841403758309930446200199225865392779725411942503595819407127350057411001629979979981746444561664911518503259454564508526643946547561925497354420113435609274102018745072331406833609642314953654272"}, + {"0x1.ddd4baa009303p+999", 301, "1.00000000000000005250476025520442024870446858110815915491585411551180245798890819578637137508044786404370444383288387817694252323536043057564479218478670698284838720092657580373783023379478809005936895323497079994508111903896764088007465274278014249457925878882005684283811566947219638686545940054016e+301"}, + {"0x1.2aa4f4a405be1p+1003", 302, "99999999999999988595886650569271721532146878831929642021471152965962304374245995240101777311515802698485322026337261211948545873374744892473124468375726771027536211745837771604509610367928220847849105179362427047829119141560667380048679757245757262098417746977035154548906385860807815060374033329553408"}, + {"0x1.2aa4f4a405be2p+1003", 302, "1.0000000000000000762970307908489492534734685515065681170160173420621138028812579448414218896469178407663974757713854876137221038784479993829181561135051983075016764985648898162653636809541460731423515105837345898689082515565906361771586320528262239050928418343985861710308373567384989920457049815751066e+302"}, + {"0x1.754e31cd072d9p+1006", 303, "999999999999999847891233648661470807691068835681842080854450367179124891914700353912936949808806064228544369161770037020638129704807338833093862397807681590830099241237075296001042588224309435545718960035602206600167779387409881325152430676383842364162444596844704620380709158981993982315347403639619584"}, + {"0x1.754e31cd072dap+1006", 303, "1.00000000000000000016176507678645643821266864623165943829549501710111749922573874786526024303421391525377977356818033741602744582056777919964339154160602606861115074612228497617725665004420052727680732706769046211266142750019705122648989826067876339144937608854729232081412795748633065546891912226327757e+303"}, + {"0x1.d2a1be4048f90p+1009", 304, "9999999999999999392535525055364621860040287220117324953190771571323204563013233902843309257440507748436856118056162172578717193742636030530235798840866882774987301441682011041067710253162440905843719802548551599076639682550821832659549112269607949805346034918662572406407604380845959862074904348138143744"}, + {"0x1.d2a1be4048f91p+1009", 304, "1.000000000000000061069977648036450690421308570451586381271912877069914542150154105446189560324377055663873935330744457574183172266871955346263203199125363859723571348076368848247742274772156963969242673880525764317658886745311919187024885294396731802364148685228327400987495476888065324730347809712740762e+304"}, + {"0x1.23a516e82d9bap+1013", 305, "99999999999999993925355250553646218600402872201173249531907715713232045630132339028433092574405077484368561180561621725787171937426360305302357988408668827749873014416820110410677102531624409058437198025485515990766396825508218326595491122696079498053460349186625724064076043808459598620749043481381437440"}, + {"0x1.23a516e82d9bbp+1013", 305, "1.0000000000000001341598327335364437930716764795154987128436143090324709936594525345433047410725728241559869294458214017639700440024369667222069771881485692090584760704212694947323250244457046880001650900559281269636558378394497607396668697348582938954618758012455694971955365001701469278440622346520965939e+305"}, + {"0x1.6c8e5ca239028p+1016", 306, "999999999999999861291040414336469543176969619010226008309262296372260241358071732580741399612641955118765084749534143455432389522994257585350220962461935904874831773666973747856549425664459851618054736334425973085267220421335152276470127823801795414563694568114532338018850013250375609552861714878501486592"}, + {"0x1.6c8e5ca239029p+1016", 306, "1.00000000000000001721606459673645482883108782501323898232889201789238067124457504798792045187545959456860613886169829106031104922553294852069693880571144065012262851466942846035699262496802832955068922417528434673006071608882921425543969463011979454650551241561798214326267086291881636286211915474912726221e+306"}, + {"0x1.c7b1f3cac7433p+1019", 307, "9999999999999999860310597602564577717002641838126363875249660735883565852672743849064846414228960666786379280392654615393353172850252103336275952370615397010730691664689375178569039851073146339641623266071126720011020169553304018596457812688561947201171488461172921822139066929851282122002676667750021070848"}, + {"0x1.c7b1f3cac7434p+1019", 307, "1.000000000000000110771079106176446000223558748615046766740669850804452929176477037232227883233150178238510771328996779623238245047056163081904969511661143497271306559270901287857258544550169416310269916879799370916936813489325651442821434713910594025670603124120052026408963372719880814847673618671502727578e+307"}, + {"0x1.1ccf385ebc89fp+1023", 308, "99999999999999981139503267596847425176765179308926185662298078548582170379439067165044410288854031049481594743364161622187121841818187648603927125262209438639553681654618823985640760188731793867961170022535129351893330180773705244319986644578003569234231285691342840034082734135647456849389933411990123839488"}, + {"0x1.1ccf385ebc8a0p+1023", 308, "1.0000000000000000109790636294404554174049230967731184633681068290315758540491149153716332897849468889906124966972117251561159028374314008832830700919814604603127166450293302718569748969958855904333838446616500117842689762621294517762809119578670745812278397017178441510529180289320787327297488571543022311834e+308"}, + {"0x1.a36e2eb1c432cp-14", 309, "9.99999999999999912396464463171241732197813689708709716796875e-5"}, + {"0x1.a36e2eb1c432dp-14", 309, "0.000100000000000000004792173602385929598312941379845142364501953125"}, + {"0x1.0624dd2f1a9fbp-10", 309, "0.00099999999999999980397624721462079833145253360271453857421875"}, + {"0x1.0624dd2f1a9fcp-10", 309, "0.001000000000000000020816681711721685132943093776702880859375"}, + {"0x1.47ae147ae147ap-7", 309, "0.0099999999999999984734433411404097569175064563751220703125"}, + {"0x1.47ae147ae147bp-7", 309, "0.01000000000000000020816681711721685132943093776702880859375"}, + {"0x1.9999999999999p-4", 309, "0.09999999999999999167332731531132594682276248931884765625"}, + {"0x1.999999999999ap-4", 309, "0.1000000000000000055511151231257827021181583404541015625"}, + {"0x1.fffffffffffffp-1", 309, "0.99999999999999988897769753748434595763683319091796875"}, + {"0x1.0000000000000p+0", 309, "1"}, + {"0x1.3ffffffffffffp+3", 309, "9.9999999999999982236431605997495353221893310546875"}, + {"0x1.4000000000000p+3", 309, "10"}, + {"0x1.8ffffffffffffp+6", 309, "99.9999999999999857891452847979962825775146484375"}, + {"0x1.9000000000000p+6", 309, "100"}, + {"0x1.f3fffffffffffp+9", 309, "999.9999999999998863131622783839702606201171875"}, + {"0x1.f400000000000p+9", 309, "1000"}, + {"0x1.387ffffffffffp+13", 309, "9999.999999999998181010596454143524169921875"}, + {"0x1.3880000000000p+13", 309, "10000"}, + {"0x1.869ffffffffffp+16", 309, "99999.999999999985448084771633148193359375"}, + {"0x1.86a0000000000p+16", 309, "100000"}, + {"0x1.e847fffffffffp+19", 309, "999999.999999999883584678173065185546875"}, + {"0x1.e848000000000p+19", 309, "1000000"}, + {"0x1.312cfffffffffp+23", 309, "9999999.99999999813735485076904296875"}, + {"0x1.312d000000000p+23", 309, "10000000"}, + {"0x1.7d783ffffffffp+26", 309, "99999999.99999998509883880615234375"}, + {"0x1.7d78400000000p+26", 309, "100000000"}, + {"0x1.dcd64ffffffffp+29", 309, "999999999.99999988079071044921875"}, + {"0x1.dcd6500000000p+29", 309, "1000000000"}, + {"0x1.2a05f1fffffffp+33", 309, "9999999999.9999980926513671875"}, + {"0x1.2a05f20000000p+33", 309, "10000000000"}, + {"0x1.74876e7ffffffp+36", 309, "99999999999.9999847412109375"}, + {"0x1.74876e8000000p+36", 309, "100000000000"}, + {"0x1.d1a94a1ffffffp+39", 309, "999999999999.9998779296875"}, + {"0x1.d1a94a2000000p+39", 309, "1000000000000"}, + {"0x1.2309ce53fffffp+43", 309, "9999999999999.998046875"}, + {"0x1.2309ce5400000p+43", 309, "10000000000000"}, + {"0x1.6bcc41e8fffffp+46", 309, "99999999999999.984375"}, + {"0x1.6bcc41e900000p+46", 309, "100000000000000"}, + {"0x1.c6bf52633ffffp+49", 309, "999999999999999.875"}, + {"0x1.c6bf526340000p+49", 309, "1000000000000000"}, + {"0x1.1c37937e07fffp+53", 309, "9999999999999998"}, + {"0x1.1c37937e08000p+53", 309, "10000000000000000"}, + {"0x1.6345785d89fffp+56", 309, "99999999999999984"}, + {"0x1.6345785d8a000p+56", 309, "100000000000000000"}, + {"0x1.bc16d674ec7ffp+59", 309, "999999999999999872"}, + {"0x1.bc16d674ec800p+59", 309, "1000000000000000000"}, + {"0x1.158e460913cffp+63", 309, "9999999999999997952"}, + {"0x1.158e460913d00p+63", 309, "10000000000000000000"}, + {"0x1.5af1d78b58c3fp+66", 309, "99999999999999983616"}, + {"0x1.5af1d78b58c40p+66", 309, "100000000000000000000"}, + {"0x1.b1ae4d6e2ef4fp+69", 309, "999999999999999868928"}, + {"0x1.b1ae4d6e2ef50p+69", 309, "1000000000000000000000"}, + {"0x1.0f0cf064dd591p+73", 309, "9999999999999997902848"}, + {"0x1.0f0cf064dd592p+73", 309, "10000000000000000000000"}, + {"0x1.52d02c7e14af6p+76", 309, "99999999999999991611392"}, + {"0x1.52d02c7e14af7p+76", 309, "100000000000000008388608"}, + {"0x1.a784379d99db4p+79", 309, "999999999999999983222784"}, + {"0x1.a784379d99db5p+79", 309, "1000000000000000117440512"}, + {"0x1.08b2a2c280290p+83", 309, "9999999999999998758486016"}, + {"0x1.08b2a2c280291p+83", 309, "10000000000000000905969664"}, + {"0x1.4adf4b7320334p+86", 309, "99999999999999987584860160"}, + {"0x1.4adf4b7320335p+86", 309, "100000000000000004764729344"}, + {"0x1.9d971e4fe8401p+89", 309, "999999999999999875848601600"}, + {"0x1.9d971e4fe8402p+89", 309, "1000000000000000013287555072"}, + {"0x1.027e72f1f1281p+93", 309, "9999999999999999583119736832"}, + {"0x1.027e72f1f1282p+93", 309, "10000000000000001782142992384"}, + {"0x1.431e0fae6d721p+96", 309, "99999999999999991433150857216"}, + {"0x1.431e0fae6d722p+96", 309, "100000000000000009025336901632"}, + {"0x1.93e5939a08ce9p+99", 309, "999999999999999879147136483328"}, + {"0x1.93e5939a08ceap+99", 309, "1000000000000000019884624838656"}, + {"0x1.f8def8808b024p+102", 309, "9999999999999999635896294965248"}, + {"0x1.f8def8808b025p+102", 309, "10000000000000000761796201807872"}, + {"0x1.3b8b5b5056e16p+106", 309, "99999999999999987351763694911488"}, + {"0x1.3b8b5b5056e17p+106", 309, "100000000000000005366162204393472"}, + {"0x1.8a6e32246c99cp+109", 309, "999999999999999945575230987042816"}, + {"0x1.8a6e32246c99dp+109", 309, "1000000000000000089690419062898688"}, + {"0x1.ed09bead87c03p+112", 309, "9999999999999999455752309870428160"}, + {"0x1.ed09bead87c04p+112", 309, "10000000000000000608673814477275136"}, + {"0x1.3426172c74d82p+116", 309, "99999999999999996863366107917975552"}, + {"0x1.3426172c74d83p+116", 309, "100000000000000015310110181627527168"}, + {"0x1.812f9cf7920e2p+119", 309, "999999999999999894846684784341549056"}, + {"0x1.812f9cf7920e3p+119", 309, "1000000000000000042420637374017961984"}, + {"0x1.e17b84357691bp+122", 309, "9999999999999999538762658202121142272"}, + {"0x1.e17b84357691cp+122", 309, "10000000000000000719354278919532445696"}, + {"0x1.2ced32a16a1b1p+126", 309, "99999999999999997748809823456034029568"}, + {"0x1.2ced32a16a1b2p+126", 309, "100000000000000016638275754934614884352"}, + {"0x1.78287f49c4a1dp+129", 309, "999999999999999939709166371603178586112"}, + {"0x1.78287f49c4a1ep+129", 309, "1000000000000000090824893823431825424384"}, + {"0x1.d6329f1c35ca4p+132", 309, "9999999999999999094860208812374492184576"}, + {"0x1.d6329f1c35ca5p+132", 309, "10000000000000000303786028427003666890752"}, + {"0x1.25dfa371a19e6p+136", 309, "99999999999999981277195531206711524196352"}, + {"0x1.25dfa371a19e7p+136", 309, "100000000000000000620008645040778319495168"}, + {"0x1.6f578c4e0a060p+139", 309, "999999999999999890143207767403382423158784"}, + {"0x1.6f578c4e0a061p+139", 309, "1000000000000000044885712678075916785549312"}, + {"0x1.cb2d6f618c878p+142", 309, "9999999999999998901432077674033824231587840"}, + {"0x1.cb2d6f618c879p+142", 309, "10000000000000000139372116959414099130712064"}, + {"0x1.1efc659cf7d4bp+146", 309, "99999999999999989014320776740338242315878400"}, + {"0x1.1efc659cf7d4cp+146", 309, "100000000000000008821361405306422640701865984"}, + {"0x1.66bb7f0435c9ep+149", 309, "999999999999999929757289024535551219930759168"}, + {"0x1.66bb7f0435c9fp+149", 309, "1000000000000000088213614053064226407018659840"}, + {"0x1.c06a5ec5433c6p+152", 309, "9999999999999999931398190359470212947659194368"}, + {"0x1.c06a5ec5433c7p+152", 309, "10000000000000001199048790587699614444362399744"}, + {"0x1.18427b3b4a05bp+156", 309, "99999999999999984102174700855949311516153479168"}, + {"0x1.18427b3b4a05cp+156", 309, "100000000000000004384584304507619735463404765184"}, + {"0x1.5e531a0a1c872p+159", 309, "999999999999999881586566215862833963056037363712"}, + {"0x1.5e531a0a1c873p+159", 309, "1000000000000000043845843045076197354634047651840"}, + {"0x1.b5e7e08ca3a8fp+162", 309, "9999999999999999464902769475481793196872414789632"}, + {"0x1.b5e7e08ca3a90p+162", 309, "10000000000000000762976984109188700329496497094656"}, + {"0x1.11b0ec57e6499p+166", 309, "99999999999999986860582406952576489172979654066176"}, + {"0x1.11b0ec57e649ap+166", 309, "100000000000000007629769841091887003294964970946560"}, + {"0x1.561d276ddfdc0p+169", 309, "999999999999999993220948674361627976461708441944064"}, + {"0x1.561d276ddfdc1p+169", 309, "1000000000000000159374448147476112089437590976987136"}, + {"0x1.aba4714957d30p+172", 309, "9999999999999999932209486743616279764617084419440640"}, + {"0x1.aba4714957d31p+172", 309, "10000000000000001261437482528532152668424144699785216"}, + {"0x1.0b46c6cdd6e3ep+176", 309, "99999999999999999322094867436162797646170844194406400"}, + {"0x1.0b46c6cdd6e3fp+176", 309, "100000000000000020589742799994816764107083808679919616"}, + {"0x1.4e1878814c9cdp+179", 309, "999999999999999908150356944127012110618056584002011136"}, + {"0x1.4e1878814c9cep+179", 309, "1000000000000000078291540404596243842305360299886116864"}, + {"0x1.a19e96a19fc40p+182", 309, "9999999999999998741221202520331657642805958408251899904"}, + {"0x1.a19e96a19fc41p+182", 309, "10000000000000000102350670204085511496304388135324745728"}, + {"0x1.05031e2503da8p+186", 309, "99999999999999987412212025203316576428059584082518999040"}, + {"0x1.05031e2503da9p+186", 309, "100000000000000009190283508143378238084034459715684532224"}, + {"0x1.4643e5ae44d12p+189", 309, "999999999999999874122120252033165764280595840825189990400"}, + {"0x1.4643e5ae44d13p+189", 309, "1000000000000000048346692115553659057528394845890514255872"}, + {"0x1.97d4df19d6057p+192", 309, "9999999999999999438119489974413630815797154428513196965888"}, + {"0x1.97d4df19d6058p+192", 309, "10000000000000000831916064882577577161779546469035791089664"}, + {"0x1.fdca16e04b86dp+195", 309, "99999999999999997168788049560464200849936328366177157906432"}, + {"0x1.fdca16e04b86ep+195", 309, "100000000000000008319160648825775771617795464690357910896640"}, + {"0x1.3e9e4e4c2f344p+199", 309, "999999999999999949387135297074018866963645011013410073083904"}, + {"0x1.3e9e4e4c2f345p+199", 309, "1000000000000000127793096885319003999249391192200302120927232"}, + {"0x1.8e45e1df3b015p+202", 309, "9999999999999999493871352970740188669636450110134100730839040"}, + {"0x1.8e45e1df3b016p+202", 309, "10000000000000000921119045676700069727922419559629237113585664"}, + {"0x1.f1d75a5709c1ap+205", 309, "99999999999999992084218144295482124579792562202350734542897152"}, + {"0x1.f1d75a5709c1bp+205", 309, "100000000000000003502199685943161173046080317798311825604870144"}, + {"0x1.3726987666190p+209", 309, "999999999999999875170255276364105051932774599639662981181079552"}, + {"0x1.3726987666191p+209", 309, "1000000000000000057857959942726969827393378689175040438172647424"}, + {"0x1.84f03e93ff9f4p+212", 309, "9999999999999998751702552763641050519327745996396629811810795520"}, + {"0x1.84f03e93ff9f5p+212", 309, "10000000000000000213204190094543968723012578712679649467743338496"}, + {"0x1.e62c4e38ff872p+215", 309, "99999999999999999209038626283633850822756121694230455365568299008"}, + {"0x1.e62c4e38ff873p+215", 309, "100000000000000010901051724930857196452234783424494612613028642816"}, + {"0x1.2fdbb0e39fb47p+219", 309, "999999999999999945322333868247445125709646570021247924665841614848"}, + {"0x1.2fdbb0e39fb48p+219", 309, "1000000000000000132394543446603018655781305157705474440625207115776"}, + {"0x1.7bd29d1c87a19p+222", 309, "9999999999999999827367757839185598317239782875580932278577147150336"}, + {"0x1.7bd29d1c87a1ap+222", 309, "10000000000000001323945434466030186557813051577054744406252071157760"}, + {"0x1.dac74463a989fp+225", 309, "99999999999999995280522225138166806691251291352861698530421623488512"}, + {"0x1.dac74463a98a0p+225", 309, "100000000000000007253143638152923512615837440964652195551821015547904"}, + {"0x1.28bc8abe49f63p+229", 309, "999999999999999880969493773293127831364996015857874003175819882528768"}, + {"0x1.28bc8abe49f64p+229", 309, "1000000000000000072531436381529235126158374409646521955518210155479040"}, + {"0x1.72ebad6ddc73cp+232", 309, "9999999999999999192818822949403492903236716946156035936442979371188224"}, + {"0x1.72ebad6ddc73dp+232", 309, "10000000000000000725314363815292351261583744096465219555182101554790400"}, + {"0x1.cfa698c95390bp+235", 309, "99999999999999991928188229494034929032367169461560359364429793711882240"}, + {"0x1.cfa698c95390cp+235", 309, "100000000000000004188152556421145795899143386664033828314342771180699648"}, + {"0x1.21c81f7dd43a7p+239", 309, "999999999999999943801810948794571024057224129020550531544123892056457216"}, + {"0x1.21c81f7dd43a8p+239", 309, "1000000000000000139961240179628344893925643604260126034742731531557535744"}, + {"0x1.6a3a275d49491p+242", 309, "9999999999999999830336967949613257980309080240684656321838454199566729216"}, + {"0x1.6a3a275d49492p+242", 309, "10000000000000001399612401796283448939256436042601260347427315315575357440"}, + {"0x1.c4c8b1349b9b5p+245", 309, "99999999999999995164818811802792197885196090803013355167206819763650035712"}, + {"0x1.c4c8b1349b9b6p+245", 309, "100000000000000007719022282576153725556774937218346187371917708691719061504"}, + {"0x1.1afd6ec0e1411p+249", 309, "999999999999999926539781176481198923508803215199467887262646419780362305536"}, + {"0x1.1afd6ec0e1412p+249", 309, "1000000000000000127407036708854983366254064757844793202538020642629466718208"}, + {"0x1.61bcca7119915p+252", 309, "9999999999999998863663300700064420349597509066704028242075715752105414230016"}, + {"0x1.61bcca7119916p+252", 309, "10000000000000000470601344959054695891559601407866630764278709534898249531392"}, + {"0x1.ba2bfd0d5ff5bp+255", 309, "99999999999999998278261272554585856747747644714015897553975120217811154108416"}, + {"0x1.ba2bfd0d5ff5cp+255", 309, "100000000000000011133765626626508061083444383443316717731599070480153836519424"}, + {"0x1.145b7e285bf98p+259", 309, "999999999999999802805551768538947706777722104929947493053015898505313987330048"}, + {"0x1.145b7e285bf99p+259", 309, "1000000000000000008493621433689702976148869924598760615894999102702796905906176"}, + {"0x1.59725db272f7fp+262", 309, "9999999999999999673560075006595519222746403606649979913266024618633003221909504"}, + {"0x1.59725db272f80p+262", 309, "10000000000000001319064632327801561377715586164000484896001890252212866570518528"}, + {"0x1.afcef51f0fb5ep+265", 309, "99999999999999986862573406138718939297648940722396769236245052384850852127440896"}, + {"0x1.afcef51f0fb5fp+265", 309, "100000000000000000026609864708367276537402401181200809098131977453489758916313088"}, + {"0x1.0de1593369d1bp+269", 309, "999999999999999921281879895665782741935503249059183851809998224123064148429897728"}, + {"0x1.0de1593369d1cp+269", 309, "1000000000000000131906463232780156137771558616400048489600189025221286657051852800"}, + {"0x1.5159af8044462p+272", 309, "9999999999999999634067965630886574211027143225273567793680363843427086501542887424"}, + {"0x1.5159af8044463p+272", 309, "10000000000000001319064632327801561377715586164000484896001890252212866570518528000"}, + {"0x1.a5b01b605557ap+275", 309, "99999999999999989600692989521205793443517660497828009527517532799127744739526311936"}, + {"0x1.a5b01b605557bp+275", 309, "100000000000000003080666323096525690777025204007643346346089744069413985291331436544"}, + {"0x1.078e111c3556cp+279", 309, "999999999999999842087036560910778345101146430939018748000886482910132485188042620928"}, + {"0x1.078e111c3556dp+279", 309, "1000000000000000057766609898115896702437267127096064137098041863234712334016924614656"}, + {"0x1.4971956342ac7p+282", 309, "9999999999999998420870365609107783451011464309390187480008864829101324851880426209280"}, + {"0x1.4971956342ac8p+282", 309, "10000000000000000146306952306748730309700429878646550592786107871697963642511482159104"}, + {"0x1.9bcdfabc13579p+285", 309, "99999999999999987659576829486359728227492574232414601025643134376206526100066373992448"}, + {"0x1.9bcdfabc1357ap+285", 309, "100000000000000001463069523067487303097004298786465505927861078716979636425114821591040"}, + {"0x1.0160bcb58c16cp+289", 309, "999999999999999959416724456350362731491996089648451439669739009806703922950954425516032"}, + {"0x1.0160bcb58c16dp+289", 309, "1000000000000000180272607553648403929404183682513265918105226119259073688151729587093504"}, + {"0x1.41b8ebe2ef1c7p+292", 309, "9999999999999999594167244563503627314919960896484514396697390098067039229509544255160320"}, + {"0x1.41b8ebe2ef1c8p+292", 309, "10000000000000001361014309341887956898217461639403030224181286973685997351115745547780096"}, + {"0x1.922726dbaae39p+295", 309, "99999999999999999475366575191804932315794610450682175621941694731908308538307845136842752"}, + {"0x1.922726dbaae3ap+295", 309, "100000000000000013610143093418879568982174616394030302241812869736859973511157455477800960"}, + {"0x1.f6b0f092959c7p+298", 309, "999999999999999966484112715463900049825186092620125502979674597309179755437379230686511104"}, + {"0x1.f6b0f092959c8p+298", 309, "1000000000000000079562324861280497143156226140166910515938643997348793075220176113414176768"}, + {"0x1.3a2e965b9d81cp+302", 309, "9999999999999998986371854279739417938265620640920544952042929572854117635677011010499117056"}, + {"0x1.3a2e965b9d81dp+302", 309, "10000000000000000795623248612804971431562261401669105159386439973487930752201761134141767680"}, + {"0x1.88ba3bf284e23p+305", 309, "99999999999999989863718542797394179382656206409205449520429295728541176356770110104991170560"}, + {"0x1.88ba3bf284e24p+305", 309, "100000000000000004337729697461918607329029332495193931179177378933611681288968111094132375552"}, + {"0x1.eae8caef261acp+308", 309, "999999999999999927585207737302990649719308316264031458521789123695552773432097103028194115584"}, + {"0x1.eae8caef261adp+308", 309, "1000000000000000043377296974619186073290293324951939311791773789336116812889681110941323755520"}, + {"0x1.32d17ed577d0bp+312", 309, "9999999999999998349515363474500343108625203093137051759058013911831015418660298966976904036352"}, + {"0x1.32d17ed577d0cp+312", 309, "10000000000000000202188791271559469885760963232143577411377768562080040049981643093586978275328"}, + {"0x1.7f85de8ad5c4ep+315", 309, "99999999999999987200500490339121684640523551209383568895219648418808203449245677922989188841472"}, + {"0x1.7f85de8ad5c4fp+315", 309, "100000000000000002021887912715594698857609632321435774113777685620800400499816430935869782753280"}, + {"0x1.df67562d8b362p+318", 309, "999999999999999931290554592897108903273579836542044509826428632996050822694739791281414264061952"}, + {"0x1.df67562d8b363p+318", 309, "1000000000000000049861653971908893017010268485438462151574892930611988399099305815384459015356416"}, + {"0x1.2ba095dc7701dp+322", 309, "9999999999999998838621148412923952577789043769834774531270429139496757921329133816401963635441664"}, + {"0x1.2ba095dc7701ep+322", 309, "10000000000000000735758738477112498397576062152177456799245857901351759143802190202050679656153088"}, + {"0x1.7688bb5394c25p+325", 309, "99999999999999999769037024514370800696612547992403838920556863966097586548129676477911932478685184"}, + {"0x1.7688bb5394c26p+325", 309, "100000000000000014946137745027879167254908695051145297064360294060937596327914127563101660644376576"}, + {"0x1.d42aea2879f2ep+328", 309, "999999999999999967336168804116691273849533185806555472917961779471295845921727862608739868455469056"}, + {"0x1.d42aea2879f2fp+328", 309, "1000000000000000088752974568224758206315902362276487138068389220230015924160003471290257693781000192"}, + {"0x1.249ad2594c37cp+332", 309, "9999999999999998216360018871870109548898901740426374747374488505608317520357971321909184780648316928"}, + {"0x1.249ad2594c37dp+332", 309, "10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104"}, + {"0x1.6dc186ef9f45cp+335", 309, "99999999999999997704951326524533662844684271992415000612999597473199345218078991130326129448151154688"}, + {"0x1.6dc186ef9f45dp+335", 309, "100000000000000013246302464330366230200379526580566253752254309890315515232578269041560411089819140096"}, + {"0x1.c931e8ab87173p+338", 309, "999999999999999977049513265245336628446842719924150006129995974731993452180789911303261294481511546880"}, + {"0x1.c931e8ab87174p+338", 309, "1000000000000000101380322367691997167292404756629360031244033674068922812296784134593135547614855430144"}, + {"0x1.1dbf316b346e7p+342", 309, "9999999999999998029863805218200118740630558685368559709703431956602923480183979986974373400948301103104"}, + {"0x1.1dbf316b346e8p+342", 309, "10000000000000000019156750857346687362159551272651920111528035145993793242039887559612361451081803235328"}, + {"0x1.652efdc6018a1p+345", 309, "99999999999999984277223943460294324649363572028252317900683525944810974325551615015019710109750015295488"}, + {"0x1.652efdc6018a2p+345", 309, "100000000000000000191567508573466873621595512726519201115280351459937932420398875596123614510818032353280"}, + {"0x1.be7abd3781ecap+348", 309, "999999999999999938258300825281978540327027364472124478294416212538871491824599713636820527503908255301632"}, + {"0x1.be7abd3781ecbp+348", 309, "1000000000000000065573049346187358932104882890058259544011190816659887156583377798285651762712452391763968"}, + {"0x1.170cb642b133ep+352", 309, "9999999999999998873324014169198263836158851542376704520077063708904652259210884797772880334204906007166976"}, + {"0x1.170cb642b133fp+352", 309, "10000000000000000910359990503684350104604539951754865571545457374840902895351334152154180097541612190564352"}, + {"0x1.5ccfe3d35d80ep+355", 309, "99999999999999996881384047029926983435371269061279689406644211752791525136670645395254002395395884805259264"}, + {"0x1.5ccfe3d35d80fp+355", 309, "100000000000000013177671857705815673582936776336304977818391361080281530225794240230304400502089534272438272"}, + {"0x1.b403dcc834e11p+358", 309, "999999999999999903628689227595715073763450661512695740419453520217955231010212074612338431527184250183876608"}, + {"0x1.b403dcc834e12p+358", 309, "1000000000000000033998991713002824594943974719712898047713430714837875271723200833292741616380733445921308672"}, + {"0x1.108269fd210cbp+362", 309, "9999999999999999818508707188399807864717650964328171247958398369899072554380053298205803424393137676263358464"}, + {"0x1.108269fd210ccp+362", 309, "10000000000000001904433546954913560203606035895531408164662033483817793205787873437092254382049924808062271488"}, + {"0x1.54a3047c694fdp+365", 309, "99999999999999985669538033284915564613846200056062290979362173015478401635353612148739328497990653971840106496"}, + {"0x1.54a3047c694fep+365", 309, "100000000000000002356936751417025583324953279505688186312991253926828166846616173259830936159244951026231410688"}, + {"0x1.a9cbc59b83a3dp+368", 309, "999999999999999956819772641641815758405104477258378281795396215622882607621111488153942930947432322044748890112"}, + {"0x1.a9cbc59b83a3ep+368", 309, "1000000000000000090318962386698695908093961112855385444464428862913680729311211977042675792237466698479879323648"}, + {"0x1.0a1f5b8132466p+372", 309, "9999999999999999301199346926304397284673331501389768492615896861647229832830913903761963586894254467577228034048"}, + {"0x1.0a1f5b8132467p+372", 309, "10000000000000001437186382847214479679695037670941883095320419218299999779872521725981689367534804490539314970624"}, + {"0x1.4ca732617ed7fp+375", 309, "99999999999999984468045325579403643266646490335689226515340879189861218540142707748740732746380344583923932594176"}, + {"0x1.4ca732617ed80p+375", 309, "100000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784"}, + {"0x1.9fd0fef9de8dfp+378", 309, "999999999999999878856245830528597750986812202069726098796681149605056504554092802642922939954052246206632716926976"}, + {"0x1.9fd0fef9de8e0p+378", 309, "1000000000000000015559416129466843024268201396921061433369770580430833781164755703264985389915047447676206280867840"}, + {"0x1.03e29f5c2b18bp+382", 309, "9999999999999997968343436511656505870179786851589248980528274911095901385876950622696854699774551253248885785624576"}, + {"0x1.03e29f5c2b18cp+382", 309, "10000000000000000155594161294668430242682013969210614333697705804308337811647557032649853899150474476762062808678400"}, + {"0x1.44db473335deep+385", 309, "99999999999999984057935814682588907446802322751135220511621610897383886710310719046874545396497358979515211902353408"}, + {"0x1.44db473335defp+385", 309, "100000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784000"}, + {"0x1.961219000356ap+388", 309, "999999999999999910571381339882270654388094495275235896417637897556636832727766595587241428345003132947573783761256448"}, + {"0x1.961219000356bp+388", 309, "1000000000000000050555427725995033814228237030803003279020481474722232763977085405824233377105062219252417113236701184"}, + {"0x1.fb969f40042c5p+391", 309, "9999999999999999665649998943273759183241515094863428494587753284228752052274941196820382078490267674695111155514343424"}, + {"0x1.fb969f40042c6p+391", 309, "10000000000000000785522370032175864461962655379085567555410501901553519502269491678716317668570740365133857791317901312"}, + {"0x1.3d3e2388029bbp+395", 309, "99999999999999994416755247254933381274972870380190006824232035607637985622760311004411949604741731366073618283536318464"}, + {"0x1.3d3e2388029bcp+395", 309, "100000000000000012334713184677367065734511114927744231797396013484834264822673118714746919046029294413093564456393244672"}, + {"0x1.8c8dac6a0342ap+398", 309, "999999999999999980003468347394201181668805192897008518188648311830772414627428725464789434929992439754776075181077037056"}, + {"0x1.8c8dac6a0342bp+398", 309, "1000000000000000123347131846773670657345111149277442317973960134848342648226731187147469190460292944130935644563932446720"}, + {"0x1.efb1178484134p+401", 309, "9999999999999999226660029476424133913982828103448349982745235826237443211877077407917175327178722380043122474279348731904"}, + {"0x1.efb1178484135p+401", 309, "10000000000000000373409337471459889719393275754491820381027730410378005080671497101378613371421126415052399029342192009216"}, + {"0x1.35ceaeb2d28c0p+405", 309, "99999999999999983092605830803955292696544699826135736641192401589249937168415416531480248917847991520357012302290741100544"}, + {"0x1.35ceaeb2d28c1p+405", 309, "100000000000000001440594758724527385583111862242831263013712314935498927069126131626863257625726456080505437183296233537536"}, + {"0x1.83425a5f872f1p+408", 309, "999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376"}, + {"0x1.83425a5f872f2p+408", 309, "1000000000000000124493881154768706413150521596928485788372242629432483210095525606840930628504535348165944921118995289997312"}, + {"0x1.e412f0f768fadp+411", 309, "9999999999999999483531874467312143214394768377282087351960514613084929070487027419252537449089020883885200422613425626021888"}, + {"0x1.e412f0f768faep+411", 309, "10000000000000000657803165854228757159135066771950601039801789067244864424132513185357050006393242615734699614997777141989376"}, + {"0x1.2e8bd69aa19ccp+415", 309, "99999999999999992486776161899288204254467086983483846143922597222529419997579302660316349376281765375153005841365553228283904"}, + {"0x1.2e8bd69aa19cdp+415", 309, "100000000000000011275116824089954027370311861298180065149382988489088385655907074917988550293149313084744992919515177483763712"}, + {"0x1.7a2ecc414a03fp+418", 309, "999999999999999924867761618992882042544670869834838461439225972225294199975793026603163493762817653751530058413655532282839040"}, + {"0x1.7a2ecc414a040p+418", 309, "1000000000000000075174486916518208627471429064352408213482909102357765925242415204664541101097758035428265955038852526326677504"}, + {"0x1.d8ba7f519c84fp+421", 309, "9999999999999999549291066784979473595300225087383524118479625982517885450291174622154390152298057300868772377386949310916067328"}, + {"0x1.d8ba7f519c850p+421", 309, "10000000000000000751744869165182086274714290643524082134829091023577659252424152046645411010977580354282659550388525263266775040"}, + {"0x1.27748f9301d31p+425", 309, "99999999999999988278187853568579059876517857536991893086699469578820211690113881674597776370903434688204400735860037395056427008"}, + {"0x1.27748f9301d32p+425", 309, "100000000000000007517448691651820862747142906435240821348290910235776592524241520466454110109775803542826595503885252632667750400"}, + {"0x1.7151b377c247ep+428", 309, "999999999999999998217443564185241415988928868759412500436543339729940401905904649497115766142268560009777175966751665376232210432"}, + {"0x1.7151b377c247fp+428", 309, "1000000000000000152131530268851175838953929259945403926529274864985591448578925759831966436053247510846754734110953387277122797568"}, + {"0x1.cda62055b2d9dp+431", 309, "9999999999999999366518088823188676468029287122850159299994507296276799832366962053631754981778769796749861527090709766158759755776"}, + {"0x1.cda62055b2d9ep+431", 309, "10000000000000000597830782460516151851749290252338090708736359498322008205751130936310560341066601403445681992244323541365884452864"}, + {"0x1.2087d4358fc82p+435", 309, "99999999999999991202555500957231813912852864969525730182461368558677581576901282770959939099212034754106974340599870111173348163584"}, + {"0x1.2087d4358fc83p+435", 309, "100000000000000010903558599154471420052372915041332632722331003791400915551047984893820824847817340461240101783057690514487343316992"}, + {"0x1.68a9c942f3ba3p+438", 309, "999999999999999990829567402361276563686608849982484911984092226517669151665599636201042933986541570369602253175829982724989462249472"}, + {"0x1.68a9c942f3ba4p+438", 309, "1000000000000000148437592187939193412802769250556940132303049308379455823458773253183930019975384016026667272715492545951501423476736"}, + {"0x1.c2d43b93b0a8bp+441", 309, "9999999999999998962647525310145264542169126096378117797927179774005971485896954660113106823932361029753632414520324447890822855131136"}, + {"0x1.c2d43b93b0a8cp+441", 309, "10000000000000000223511723594768599335098409300973759560478836428900264860242343595976203511843100595010152570837624953702918544949248"}, + {"0x1.19c4a53c4e697p+445", 309, "99999999999999992148203649670699315007549827372972461504375111049848301607660324472857261615145089428049364457837845490532419930947584"}, + {"0x1.19c4a53c4e698p+445", 309, "100000000000000012322030822224672671694418358646502729705201617528156995597186547446666808621716922472153686958914653583525950968037376"}, + {"0x1.6035ce8b6203dp+448", 309, "999999999999999961829690841814939863449235336276785151445404123455100404055655690676191710164594560368702289580532071091311261383655424"}, + {"0x1.6035ce8b6203ep+448", 309, "1000000000000000123220308222246726716944183586465027297052016175281569955971865474466668086217169224721536869589146535835259509680373760"}, + {"0x1.b843422e3a84cp+451", 309, "9999999999999999295515673657285824927502456862391367223240817130898064936724137339180964349540796274981353735788091781425216117243117568"}, + {"0x1.b843422e3a84dp+451", 309, "10000000000000000586640612700740119755462042863897304388093713545509821352053815609504775357961393589804030375857007499376802103616864256"}, + {"0x1.132a095ce492fp+455", 309, "99999999999999982626157224225223890651347880611866174913584999992086598044603947229219155428043184231232124237329592070639473281441202176"}, + {"0x1.132a095ce4930p+455", 309, "100000000000000003284156248920492607898701256635961169551231342625874700689878799554400131562772741268394950478432243557864849063421149184"}, + {"0x1.57f48bb41db7bp+458", 309, "999999999999999867577570291642776341008185558166851738411142685188442185736589176942553506549890956386646894855501223680845484378371915776"}, + {"0x1.57f48bb41db7cp+458", 309, "1000000000000000032841562489204926078987012566359611695512313426258747006898787995544001315627727412683949504784322435578648490634211491840"}, + {"0x1.adf1aea12525ap+461", 309, "9999999999999999006303687311552062886039509598054037298313768334025031499690289406628430683654582476461074168412654660604060856295398309888"}, + {"0x1.adf1aea12525bp+461", 309, "10000000000000000328415624892049260789870125663596116955123134262587470068987879955440013156277274126839495047843224355786484906342114918400"}, + {"0x1.0cb70d24b7378p+465", 309, "99999999999999984774589122793531837245072631718372054355900219626000560719712531871037976946055058163097058166404267825310912362767116664832"}, + {"0x1.0cb70d24b7379p+465", 309, "100000000000000005928380124081487003706362488767045328864850074482999577828473980652023296508018124569151792237293382948229697163514582401024"}, + {"0x1.4fe4d06de5056p+468", 309, "999999999999999847745891227935318372450726317183720543559002196260005607197125318710379769460550581630970581664042678253109123627671166648320"}, + {"0x1.4fe4d06de5057p+468", 309, "1000000000000000016976219238238959704141045173573106739630601035115997744067216908958262325956255112879408454231155599236459402033650892537856"}, + {"0x1.a3de04895e46cp+471", 309, "9999999999999999154380224320567749051268538597394750219876417318024024619451619548095327920588323941303457306908878466464492349900630570041344"}, + {"0x1.a3de04895e46dp+471", 309, "10000000000000000508222848402996879704791089448509839788449208028871961714412352270078388372553960191290960287445781834331294577148468377157632"}, + {"0x1.066ac2d5daec3p+475", 309, "99999999999999980713061250546244445284504979165026785650181847493456749434830333705088795590158149413134549224793557721710505681023603243483136"}, + {"0x1.066ac2d5daec4p+475", 309, "100000000000000002374543235865110535740865792782868218747346498867023742954202057256817762821608329412934596913384011607579341316989008157343744"}, + {"0x1.4805738b51a74p+478", 309, "999999999999999850453576476100176633757771418885950722696147777681701481387046784154345890364481854130945587625116484988842728082166842262552576"}, + {"0x1.4805738b51a75p+478", 309, "1000000000000000023745432358651105357408657927828682187473464988670237429542020572568177628216083294129345969133840116075793413169890081573437440"}, + {"0x1.9a06d06e26112p+481", 309, "9999999999999999890870611821409196126784806260401358945180015464725302399110258148854112806457630061296658928320953898584032761523454337112604672"}, + {"0x1.9a06d06e26113p+481", 309, "10000000000000001277205458881816625915991898331943210663398553152633589984350048456164766709270441581283861980390742947279638242225240251599683584"}, + {"0x1.00444244d7cabp+485", 309, "99999999999999993363366729972462242111019694317846182578926003895619873650143420259298512453325054533017777074930382791057905692427399713177731072"}, + {"0x1.00444244d7cacp+485", 309, "100000000000000015544724282938981118738333167462515810070422606902152475013980065176268974898330038852813025908047007570187593383655974344970993664"}, + {"0x1.405552d60dbd6p+488", 309, "999999999999999977996382405657660174364823889467801080772253244969263939229107492426926049423260513969768268415537077468838432306731146395363835904"}, + {"0x1.405552d60dbd7p+488", 309, "1000000000000000155447242829389811187383331674625158100704226069021524750139800651762689748983300388528130259080470075701875933836559743449709936640"}, + {"0x1.906aa78b912cbp+491", 309, "9999999999999999070160382361647997691574207754048582727994641153483596148648302286926205695992445641464234721495638781756234316947997075736253956096"}, + {"0x1.906aa78b912ccp+491", 309, "10000000000000000489767265751505205795722270035307438887450423745901682635933847561612315292472764637931130646815102767620534329186625852171022761984"}, + {"0x1.f485516e7577ep+494", 309, "99999999999999993540817590396194393124038202103003539598857976719672134461054113418634276152885094407576139065595315789290943193957228310232077172736"}, + {"0x1.f485516e7577fp+494", 309, "100000000000000004897672657515052057957222700353074388874504237459016826359338475616123152924727646379311306468151027676205343291866258521710227619840"}, + {"0x1.38d352e5096afp+498", 309, "999999999999999980835596172437374590573120014030318793091164810154100112203678582976298268616221151962702060266176005440567032331208403948233373515776"}, + {"0x1.38d352e5096b0p+498", 309, "1000000000000000162545277246339097227904071986031452381501504981983615182576228378136120296965701983510464738707067395631197433897752887331883780669440"}, + {"0x1.8708279e4bc5ap+501", 309, "9999999999999998718097875280963410081745488308296386400449607070563910699801487058804050516065326530340444532016411713261887913912817139180431292235776"}, + {"0x1.8708279e4bc5bp+501", 309, "10000000000000000171775323872177191180393104084305455107732328445200031262781885420082626742861173182722545959543542834786931126445173006249634549465088"}, + {"0x1.e8ca3185deb71p+504", 309, "99999999999999992995688547174489225212045346187000138833626956204183589249936464033154810067836651912932851030272641618719051989257594860081125951275008"}, + {"0x1.e8ca3185deb72p+504", 309, "100000000000000004625108135904199474001226272395072688491888727201272553753779650923383419882203425131989662450489690590919397689516441796634752009109504"}, + {"0x1.317e5ef3ab327p+508", 309, "999999999999999999733403004123153744855539019118436686285840188024369679522423761672919759564567158443669378824028710020392594094129030220133015859757056"}, + {"0x1.317e5ef3ab328p+508", 309, "1000000000000000185804116423798517725482433838447597480818028523977793111583914751916577516594435529948578361547501493575598125298270581204991032785108992"}, + {"0x1.7dddf6b095ff0p+511", 309, "9999999999999998880909749523179353564794021275209402095665271864523156202855291675267251053466461355407239891899450398872692753716440996292182057045458944"}, + {"0x1.7dddf6b095ff1p+511", 309, "10000000000000000369475456880582265409809179829842688451922778552150543659347219597216513109705408327446511753687232667314337003349573404171046192448274432"}, + {"0x1.dd55745cbb7ecp+514", 309, "99999999999999988809097495231793535647940212752094020956652718645231562028552916752672510534664613554072398918994503988726927537164409962921820570454589440"}, + {"0x1.dd55745cbb7edp+514", 309, "100000000000000000717623154091016830408061481189160311806712772146250661680488340128266606984576189330386573813296762136260081534229469225952733653677113344"}, + {"0x1.2a5568b9f52f4p+518", 309, "999999999999999983359180223191721714560372275017470536367007614460468417501012554531477876945938741751237388344363105067534507348164573733465510370326085632"}, + {"0x1.2a5568b9f52f5p+518", 309, "1000000000000000173895590764939294430722312570010531189967968470476774011931979328540983420144523954172264186653199235428064971301205521941960119701886468096"}, + {"0x1.74eac2e8727b1p+521", 309, "9999999999999999833591802231917217145603722750174705363670076144604684175010125545314778769459387417512373883443631050675345073481645737334655103703260856320"}, + {"0x1.74eac2e8727b2p+521", 309, "10000000000000001357883086565897798874899245110119190592477762992735128930457859737390823115048069116880588269914320093559588785105973323002611978355743916032"}, + {"0x1.d22573a28f19dp+524", 309, "99999999999999995287335453651211007997446182781858083179085387749785952239205787068995699003416510776387310061494932420984963311567802202010637287727642443776"}, + {"0x1.d22573a28f19ep+524", 309, "100000000000000007481665728323055661831810361661413965009546882534829510282787660605604053768125964371333025153260444764058913004562422887354292284947506921472"}, + {"0x1.2357684599702p+528", 309, "999999999999999928484693987168420772305733470059469068129930887927772406304894123616740280504746200573981670431418299523701733729688780649419062882836695482368"}, + {"0x1.2357684599703p+528", 309, "1000000000000000123593978381917935233655560332132363177417314804488469335002204100202473956740097458093113111899666497012884928817602711614917542838354527125504"}, + {"0x1.6c2d4256ffcc2p+531", 309, "9999999999999998504409802292686149877658027252303114244149773213034936348259701329824468100106056975663290938441190205280284556945232082632196709006295628251136"}, + {"0x1.6c2d4256ffcc3p+531", 309, "10000000000000000065284077450682265568456642148886267118448844545520511777838181142510337509988867035816342470187175785193750117648543530356184548650438281396224"}, + {"0x1.c73892ecbfbf3p+534", 309, "99999999999999991287595123558845961539774732109363753938694017460291665200910932548988158640591809997245115511395844372456707812265566617217918448639526895091712"}, + {"0x1.c73892ecbfbf4p+534", 309, "100000000000000003774589324822814887066163651282028976933086588120176268637538771050475113919654290478469527765363729011764432297892058199009821165792668120252416"}, + {"0x1.1c835bd3f7d78p+538", 309, "999999999999999937849939638116397466450525159438967985375725315922685858882365002492855496964043060934899979621894213003182527093908649335762989920701551401238528"}, + {"0x1.1c835bd3f7d79p+538", 309, "1000000000000000137641846858339900274872747866201611553286006446480839513868410418516646781429042748634490575685380367232106118863932514644433433395151811003809792"}, + {"0x1.63a432c8f5cd6p+541", 309, "9999999999999999378499396381163974664505251594389679853757253159226858588823650024928554969640430609348999796218942130031825270939086493357629899207015514012385280"}, + {"0x1.63a432c8f5cd7p+541", 309, "10000000000000000976834654142951997131883033248490828397039502203692087828712013353118885245360428110945724564726831363863214005099277415826993447002617590832955392"}, + {"0x1.bc8d3f7b3340bp+544", 309, "99999999999999987391652932764487656775541389327492204364443535414407668928683046936524228593524316087103098888157864364992697772750101243698844800887746832841572352"}, + {"0x1.bc8d3f7b3340cp+544", 309, "100000000000000000178334994858791836514563642560301392710701527770129502847789953562046870799284296099876897036220978235643807646031628623453753183252563447406133248"}, + {"0x1.15d847ad00087p+548", 309, "999999999999999899489893451833484927233458399740540420336951338855520357125044282616287570346763120896578585177704871391229197474064067196498264773607101557544845312"}, + {"0x1.15d847ad00088p+548", 309, "1000000000000000104076806445342351803057814451465487433877079216547069699830754788624649845638922801100959355546714693321646955446568505272576798891444167390577819648"}, + {"0x1.5b4e5998400a9p+551", 309, "9999999999999999404072760505352583023983296100855298230449769143938302256661863838179600254051950569374547392515068357773127490685649548117139715971745147241514401792"}, + {"0x1.5b4e5998400aap+551", 309, "10000000000000001040768064453423518030578144514654874338770792165470696998307547886246498456389228011009593555467146933216469554465685052725767988914441673905778196480"}, + {"0x1.b221effe500d3p+554", 309, "99999999999999990767336997157383960226643264180953830087855645396318233083327270285662206135844950810475381599246526426844590779296424471954140613832058419086616428544"}, + {"0x1.b221effe500d4p+554", 309, "100000000000000003860899428741951440279402051491350438954423829568577391016492742670197391754543170343555750902863155030391327289536708508823166797373630632400726786048"}, + {"0x1.0f5535fef2084p+558", 309, "999999999999999933860494834742974562371950216430331518611692822307700646699603647625692432595845947170914554599698521475539380813444812793279458505403728617494385000448"}, + {"0x1.0f5535fef2085p+558", 309, "1000000000000000143357493740096054243216090813396677260476783769063847173630251205778255402495017459700200463457564579132287164977289357383183877442068884030520150720512"}, + {"0x1.532a837eae8a5p+561", 309, "9999999999999999338604948347429745623719502164303315186116928223077006466996036476256924325958459471709145545996985214755393808134448127932794585054037286174943850004480"}, + {"0x1.532a837eae8a6p+561", 309, "10000000000000001014580939590254383070472626940034081121037655797126178682441216941477428085151831571943432816859913676009376081445204484652029936547358529479149975764992"}, + {"0x1.a7f5245e5a2cep+564", 309, "99999999999999990034097500988648181343688772091571619991327827082671720239070003832128235741197850516622880918243995225045973534722968565889475147553730375141026248523776"}, + {"0x1.a7f5245e5a2cfp+564", 309, "100000000000000003441905430931245280917713770297417747470693647675065097962631447553892265814744827318497179085147422915077831721209019419643357959500300321574675254607872"}, + {"0x1.08f936baf85c1p+568", 309, "999999999999999953972206729656870211732987713739100709830741553196290713284945813208338477706166412373726001850053663010587168093173889073910282723323583537144858509574144"}, + {"0x1.08f936baf85c2p+568", 309, "1000000000000000168497133608738423804917387685032638749500594682674584756861928912756562958882918041203714772520508506051096899076950702733972407714468702680083242606919680"}, + {"0x1.4b378469b6731p+571", 309, "9999999999999999110672213538405594930961077194803931018967709273006319045695491932986935814708160866077282477159626944024852218964185263418978577250945597085571816901050368"}, + {"0x1.4b378469b6732p+571", 309, "10000000000000000826871628571058023676436276965152235336326534308832671394311356729372731664122173896717192642523265688348930066834399772699475577180106550229078889679814656"}, + {"0x1.9e056584240fdp+574", 309, "99999999999999987674323305318751091818660372407342701554959442658410485759723189737097766448253582599493004440868991951600366493901423615628791772651134064568704023452975104"}, + {"0x1.9e056584240fep+574", 309, "100000000000000001403918625579970521782461970570129136093830042945021304548650108108184133243565686844612285763778101906192989276863139689872767772084421689716760605683089408"}, + {"0x1.02c35f729689ep+578", 309, "999999999999999849284042412665072058259000527747854146471853226010883220019378060628804930891911617504691481762871699606818419373090804007799965727644765395390927070069522432"}, + {"0x1.02c35f729689fp+578", 309, "1000000000000000068957567536844582937679826098352437099093782830596656320642208754566186799616905285426599982929417458880300383900478261195703581718577367397759832385751351296"}, + {"0x1.4374374f3c2c6p+581", 309, "9999999999999999371534524623368764100273307559896873275206250678451924602685103382037576783819090846734548822294900033162112051840457868829614121240178061963384891963422539776"}, + {"0x1.4374374f3c2c7p+581", 309, "10000000000000001128922725616804851135639912124733536896181687515138109407667748933536631733619040190109816831627266107349967768059557526332843049167638877982336134488877170688"}, + {"0x1.945145230b377p+584", 309, "99999999999999986685792442259943292861266657339622078268160759437774506806920451614379548038991111093844416185619536034869697653528180058283225500691937355558043949532406874112"}, + {"0x1.945145230b378p+584", 309, "100000000000000000744898050207431989144199493858315387235964254131263985246781616026371987637390705840846560260278464628372543383280977318309056924111623883709653889736043921408"}, + {"0x1.f965966bce055p+587", 309, "999999999999999894976135638494410321178532246433607400617214583764724024948926844967780359586710300432448450005513217535702667994787395102883917853758746611883659375731342835712"}, + {"0x1.f965966bce056p+587", 309, "1000000000000000007448980502074319891441994938583153872359642541312639852467816160263719876373907058408465602602784646283725433832809773183090569241116238837096538897360439214080"}, + {"0x1.3bdf7e0360c35p+591", 309, "9999999999999998724815666657784284071258397080036981062687289922551408594451489819085924562292709488372450194860589317860981148271829194868425875762872481668410834714055235600384"}, + {"0x1.3bdf7e0360c36p+591", 309, "10000000000000000524381184475062837195473800154429724610566137243318061834753718863820956830887857615988724636416932177829345401680187244151732297960592357271816907060120777654272"}, + {"0x1.8ad75d8438f43p+594", 309, "99999999999999998045549773481514159457876389246726271914145983150114005386328272459269439234497983649422148597943950338419997003168440244384097290815044070304544781216945608327168"}, + {"0x1.8ad75d8438f44p+594", 309, "100000000000000012442073916019742584451599613841868220297176761716247231308746104817149697383259168670352344130394693218166911030435304638650548668396803075131793359985469944758272"}, + {"0x1.ed8d34e547313p+597", 309, "999999999999999894076352879585771044616424544896411028843275160104340698328775730445412843452412726368640312784735046105718485868083216078242264642659886674081956339558310064685056"}, + {"0x1.ed8d34e547314p+597", 309, "1000000000000000009248546019891598444566210341657546615907521388633406505708118389308454908642502206536081877044340989143693798086218131232373875663313958712699944969706504756133888"}, + {"0x1.3478410f4c7ecp+601", 309, "9999999999999999171107915076469365246063817042486381462561244058101538598046442622180212564904306224021286256366562347133135483117101991090685868467907010818055540655879490029748224"}, + {"0x1.3478410f4c7edp+601", 309, "10000000000000001013863005321362603645260389790664550855589183714566591516115925163988885607945737906700351284520257435740740478607260633556791644798372163435943358738250605092929536"}, + {"0x1.819651531f9e7p+604", 309, "99999999999999991711079150764693652460638170424863814625612440581015385980464426221802125649043062240212862563665623471331354831171019910906858684679070108180555406558794900297482240"}, + {"0x1.819651531f9e8p+604", 309, "100000000000000006453119872723839559654210752410289169769835957832735809325020286556271509993374515701645382788895184180192194795092289050635704895322791329123657951217763820802932736"}, + {"0x1.e1fbe5a7e7861p+607", 309, "999999999999999946594872951565228338993526868219488856544571440313594706493755982886960025179093529324993666087115356131035228239552737388526279268078143523691759154905886843985723392"}, + {"0x1.e1fbe5a7e7862p+607", 309, "1000000000000000064531198727238395596542107524102891697698359578327358093250202865562715099933745157016453827888951841801921947950922890506357048953227913291236579512177638208029327360"}, + {"0x1.2d3d6f88f0b3cp+611", 309, "9999999999999998286585471758920610814449462123360860153907833022998313197373091002112049504244419016335335042852788704601485085281825842706955095829283737561469387976341354799421194240"}, + {"0x1.2d3d6f88f0b3dp+611", 309, "10000000000000000173566684169691286935226752617495305612368443231218527385476241124924130700318845059398697631682172475335672600663748292592247410791680053842186513692689376624118857728"}, + {"0x1.788ccb6b2ce0cp+614", 309, "99999999999999997961704416875371517110712945186684165206763211895744845478556111003617144611039598507860251139162957211888350975873638026151889477992007905860430885494197722591793250304"}, + {"0x1.788ccb6b2ce0dp+614", 309, "100000000000000013057554116161536926076931269139759728874448093561506558983381311986113794179635006852367151849798027377761851098929017625234227997691178436106167891224981897189374558208"}, + {"0x1.d6affe45f818fp+617", 309, "999999999999999979617044168753715171107129451866841652067632118957448454785561110036171446110395985078602511391629572118883509758736380261518894779920079058604308854941977225917932503040"}, + {"0x1.d6affe45f8190p+617", 309, "1000000000000000100383841763043038442836876043491446161409111172283542162824162717896144642659159251834657717076710133445871510743179417054177602937513443300570204900788250622698582966272"}, + {"0x1.262dfeebbb0f9p+621", 309, "9999999999999999071569656121801212080692814968920789464627446869617922299624001453201875281811380250249693879805812353226907091680705581859236698853640605134247712274342131878495422251008"}, + {"0x1.262dfeebbb0fap+621", 309, "10000000000000001003838417630430384428368760434914461614091111722835421628241627178961446426591592518346577170767101334458715107431794170541776029375134433005702049007882506226985829662720"}, + {"0x1.6fb97ea6a9d37p+624", 309, "99999999999999986851159038200753776111576258757220550347347138989744224339004763080499610528553377966303172216135545569805454885304878641227288327493418395599568449276340570087973407686656"}, + {"0x1.6fb97ea6a9d38p+624", 309, "100000000000000002309309130269787154892983822485169927543056457815484218967945768886576179686795076111078238543825857419659919011313587350687602971665369018571203143144663564875896666980352"}, + {"0x1.cba7de5054485p+627", 309, "999999999999999899427890566145604518678577715028104257864890027548922232647929642417149243602017175952581854816736079397763477105066203831193512563278085201938953880500051690455580595453952"}, + {"0x1.cba7de5054486p+627", 309, "1000000000000000023093091302697871548929838224851699275430564578154842189679457688865761796867950761110782385438258574196599190113135873506876029716653690185712031431446635648758966669803520"}, + {"0x1.1f48eaf234ad3p+631", 309, "9999999999999998746948504188351511126283256130633852543517551174277382412416240331274267329488304589209417486924315804379963345034522698960570091326029642051843383703107348987949033805840384"}, + {"0x1.1f48eaf234ad4p+631", 309, "10000000000000000725591715973187783610303424287811372824568343983972101724920689074452068181743241951740625976868675721161334753163637413771490365780039321792212624518252692320803210995433472"}, + {"0x1.671b25aec1d88p+634", 309, "99999999999999991426771465453187656230872897620693565997277097362163262749171300799098274999392920617156591849131877877362376266603456419227541462168315779999172318661364176545198692437590016"}, + {"0x1.671b25aec1d89p+634", 309, "100000000000000007255917159731877836103034242878113728245683439839721017249206890744520681817432419517406259768686757211613347531636374137714903657800393217922126245182526923208032109954334720"}, + {"0x1.c0e1ef1a724eap+637", 309, "999999999999999914267714654531876562308728976206935659972770973621632627491713007990982749993929206171565918491318778773623762666034564192275414621683157799991723186613641765451986924375900160"}, + {"0x1.c0e1ef1a724ebp+637", 309, "1000000000000000040900880208761398001286019738266296957960021713442094663491997727554362004538245197373563261847757813447631532786297905940174312186739777303375354598782943738754654264509857792"}, + {"0x1.188d357087712p+641", 309, "9999999999999998636144484328400679867178126713831911407778706776934478130915991201656310481762028096907669811487431649040206546179292274931158555956605099986382706217459209761309199883223171072"}, + {"0x1.188d357087713p+641", 309, "10000000000000000662275133196073022890814778906781692175574718614061870706920546714670378554471083956139627305190456203824330868103505742897540916997511012040520808812168041334151877325366493184"}, + {"0x1.5eb082cca94d7p+644", 309, "99999999999999994465967438754696170766327875910118237148971115117854351613178134068619377108456504406004528089686414709538562749489776621177115003729674648080379472553427423904462708600804999168"}, + {"0x1.5eb082cca94d8p+644", 309, "100000000000000010675012629696074914955421093453716483291339209814873492221214578172731921690128951279860188039310611147811557324883484364908173892056921944513484293311098076487204128137951576064"}, + {"0x1.b65ca37fd3a0dp+647", 309, "999999999999999977077764769429719196041465194188378863774447340572581797347854228894418860247909937807756600796112539971931616645685181699233267813951241073670004367049615544210109925082343145472"}, + {"0x1.b65ca37fd3a0ep+647", 309, "1000000000000000106750126296960749149554210934537164832913392098148734922212145781727319216901289512798601880393106111478115573248834843649081738920569219445134842933110980764872041281379515760640"}, + {"0x1.11f9e62fe4448p+651", 309, "9999999999999999511432924639235132053389160461186216699466583890573511723749959183278387889172340228095875448767138256706948253250552493092635735926276453993770366538373425000777236538229086224384"}, + {"0x1.11f9e62fe4449p+651", 309, "10000000000000001586190709079731611309593092306766792205689700011791961721578624028604793595626413427949399922319035400805891558900947084290211273632164107937207783595355268531368138238983848067072"}, + {"0x1.56785fbbdd55ap+654", 309, "99999999999999995114329246392351320533891604611862166994665838905735117237499591832783878891723402280958754487671382567069482532505524930926357359262764539937703665383734250007772365382290862243840"}, + {"0x1.56785fbbdd55bp+654", 309, "100000000000000011712391521916323154583523059376506771044450767875482717220128910595395124543355987879786950276086559719861028977708681660506961660909865771485203001839588998252499578988328956985344"}, + {"0x1.ac1677aad4ab0p+657", 309, "999999999999999884751043361827625869140390227060043253747518673178360772444478643277393806310703680414274761723053117059528639544242622390941156386039240473187039308013923507098814799398756243472384"}, + {"0x1.ac1677aad4ab1p+657", 309, "1000000000000000017535541566019400541537441865177200086145798104936341572305513193378283771523764365204900328030374534281861011105867876227585990799216050325567033999660761493056632508247061001404416"}, + {"0x1.0b8e0acac4eaep+661", 309, "9999999999999998847510433618276258691403902270600432537475186731783607724444786432773938063107036804142747617230531170595286395442426223909411563860392404731870393080139235070988147993987562434723840"}, + {"0x1.0b8e0acac4eafp+661", 309, "10000000000000000972062404885344653449756728480474941855847657639911300522221339234388177506516007760792756678147673846152604340428430285295728914471221362369950308146488642846313231335560438561636352"}, + {"0x1.4e718d7d7625ap+664", 309, "99999999999999996973312221251036165947450327545502362648241750950346848435554075534196338404706251868027512415973882408182135734368278484639385041047239877871023591066789981811181813306167128854888448"}, + {"0x1.4e718d7d7625bp+664", 309, "100000000000000013969727991387583324014272937224498437195221518215368390817766497947110253951978019521227584903311023812640679294256310975729923845933871538975662911597585244013782480038750137870188544"}, + {"0x1.a20df0dcd3af0p+667", 309, "999999999999999901747459131964173027207212836739039328294498440443382314826691065690307721857975448067474834210390258463987183104130654882031695190925872134291678628544718769301415466131339252487684096"}, + {"0x1.a20df0dcd3af1p+667", 309, "1000000000000000037718785293056550291741793714171007924670336578563554653884390444993619046236149589293075414109087389699655531583234914810756005630018925423128793192791080866922220799992003324610084864"}, + {"0x1.0548b68a044d6p+671", 309, "9999999999999999017474591319641730272072128367390393282944984404433823148266910656903077218579754480674748342103902584639871831041306548820316951909258721342916786285447187693014154661313392524876840960"}, + {"0x1.0548b68a044d7p+671", 309, "10000000000000001193015809897119766504625422406301890824958394614356580573190100725756058408630540740284357620483056684410565406706974707679905918934747573964310619313388981254947040003084017678835253248"}, + {"0x1.469ae42c8560cp+674", 309, "99999999999999998876910787506329447650934459829549922997503484884029261182361866844442696946000689845185920534555642245481492613075738123641525387194542623914743194966239051177873087980216425864602058752"}, + {"0x1.469ae42c8560dp+674", 309, "100000000000000016281240536126153737511360812140841903333610766563411320581747387395266546466406979922062794761588875043647041218401083394518237123398453444885893859189773399673336170714381427096269357056"}, + {"0x1.98419d37a6b8fp+677", 309, "999999999999999988769107875063294476509344598295499229975034848840292611823618668444426969460006898451859205345556422454814926130757381236415253871945426239147431949662390511778730879802164258646020587520"}, + {"0x1.98419d37a6b90p+677", 309, "1000000000000000128003745864021888795392755416785835072663893102275349087018702832851017765623257219066874199161822284840139314973360143403428947761576712806916637263450665299742435541675484268499358973952"}, + {"0x1.fe52048590672p+680", 309, "9999999999999999052283250816881378851792981072012977243617198967792587267065681698004724917620567060828502090557969050236202928251957239362070375381666542984859087613894256390005080826781722527340175556608"}, + {"0x1.fe52048590673p+680", 309, "10000000000000000166160354728550133402860267619935663985128064995273039068626355013257451286926569625748622041088095949318798038992779336698179926498716835527012730124200454693714718121768282606166882648064"}, + {"0x1.3ef342d37a407p+684", 309, "99999999999999986067324092522138770313660664528439025470128525568004065464414123719036343698981660348604541103459182906031648839556284004276265549348464259679976306097717770685212259087870984958094927200256"}, + {"0x1.3ef342d37a408p+684", 309, "100000000000000003889357755108838843130737249295202013334302382007691294289384896763079965607877701387326460311941213291353170611409437561654018367221268940354434586262616943544566455807655946219322240663552"}, + {"0x1.8eb0138858d09p+687", 309, "999999999999999896317308250394787848770759814817916230429632968559415112294082783278450680807608685563489249451555889830959531939269147157518161129230251958148679621306976052570830984318279772103403898929152"}, + {"0x1.8eb0138858d0ap+687", 309, "1000000000000000038893577551088388431307372492952020133343023820076912942893848967630799656078777013873264603119412132913531706114094375616540183672212689403544345862626169435445664558076559462193222406635520"}, + {"0x1.f25c186a6f04cp+690", 309, "9999999999999999818630698308109481982927274216983785721776674794699138106539424938898600659703096825493544616522696356805028364441642842329313746550197144253860793660984920822957311285732475861572950035529728"}, + {"0x1.f25c186a6f04dp+690", 309, "10000000000000000959240852713658286643220175642056616945083801606839120751337554413717392461872443451971747445865546301465605757840244670001489926894056643817026123591538467885955979875798713382291498097180672"}, + {"0x1.37798f428562fp+694", 309, "99999999999999989061425747836704382546929530769255207431309733449871519907009213590435672179676195243109823530484164010765664497227613801915728022751095446033285297165420831725583764136794858449981115862089728"}, + {"0x1.37798f4285630p+694", 309, "100000000000000007311188218325485257111615953570420507004223762444111242223779285187536341014385741266761068799969763125334902791605243044670546908252847439043930576054277584733562461577854658781477884848504832"}, + {"0x1.8557f31326bbbp+697", 309, "999999999999999927113782419344605574598668153294882673458925392487194643703632279098558059466181044478400725843812838336795121561031396504666917998514458446354143529431921823271795036250068185162804696593727488"}, + {"0x1.8557f31326bbcp+697", 309, "1000000000000000073111882183254852571116159535704205070042237624441112422237792851875363410143857412667610687999697631253349027916052430446705469082528474390439305760542775847335624615778546587814778848485048320"}, + {"0x1.e6adefd7f06aap+700", 309, "9999999999999999563134023721266549739021664297767471527755878388779781994104643936539191296017163181162427182749897969201059028320356032930746282153172616351711759756540926280845609521557638656931995269719916544"}, + {"0x1.e6adefd7f06abp+700", 309, "10000000000000000731118821832548525711161595357042050700422376244411124222377928518753634101438574126676106879996976312533490279160524304467054690825284743904393057605427758473356246157785465878147788484850483200"}, + {"0x1.302cb5e6f642ap+704", 309, "99999999999999990959401044767537593501656918740576398586892792465272451027953301036534141738485988029569553038510666318680865279842887243162229186843277653306392406169861934038413548670665077684456779836676898816"}, + {"0x1.302cb5e6f642bp+704", 309, "100000000000000009647157814548049209055895815688969665349556758155373926680325854351965226625228563157788428194463919811999765293285579587743163725597071694149293171752051249118583734850310313223909471278765965312"}, + {"0x1.7c37e360b3d35p+707", 309, "999999999999999984345037526797422397233524775199337052919583787413130412889023223627065756931830180808571031008919677160084252852199641809946030023447952696435527124027376600704816231425231719002378564135125254144"}, + {"0x1.7c37e360b3d36p+707", 309, "1000000000000000133847091685041515321667435950786483187020895512933942218108003650150514436025770781834322032256545705106635452959741180566593506333478305023178733248684891121346177720862393603318000095671837786112"}, + {"0x1.db45dc38e0c82p+710", 309, "9999999999999999544446266951486038123467425400819078260993214423089680518452271383223760211130420606034208307593944715707740128306913340586165347614418822310868858990958736965765439335377993421392542578277827477504"}, + {"0x1.db45dc38e0c83p+710", 309, "10000000000000000740462700217438781518938714805516247333803708227256174960204114795411349643881945414240216317574952939280149729167245650639345158094661640924814507988218853130896331250875288495917514830571527733248"}, + {"0x1.290ba9a38c7d1p+714", 309, "99999999999999990660396936451049407652789096389402106318690169014230827417515340183487244380298106827518051036015414262787762879627804165648934234223216948652905993920546904997130825691790753915825536773603473752064"}, + {"0x1.290ba9a38c7d2p+714", 309, "100000000000000009796659868706293301980329726864556811483658069880894738485544834778488675304322503758814179195711545839946316493393121126499811201907102046476036377876708763639225096339747475108225092810302677843968"}, + {"0x1.734e940c6f9c5p+717", 309, "999999999999999868331443500000006287872809702943711652856965888408980452039094412644869581954932274412588254040761879473560521568747407734787588406864399290882799171293145332687119715621994096773456255662636329336832"}, + {"0x1.734e940c6f9c6p+717", 309, "1000000000000000021421546958041957442493134746744949294176709095342291740583330369404881029347127449862957279318330932090828950478869943421594604148335480073467842242942440201823873880805647866312652703956229962072064"}, + {"0x1.d022390f8b837p+720", 309, "9999999999999999601855055748251769806450047292244542376488118125689672251656359867008764503902493796828096692073033110439215789148209291468717978517470477604338250142827222541691722147321863584969741246387925089779712"}, + {"0x1.d022390f8b838p+720", 309, "10000000000000000826575883412587379043412647642654443507046063781156162560010247521088856083040055200431048894293585531377363220429189576963174104449239123865018594716021581494785755468791093741283312832736674151661568"}, + {"0x1.221563a9b7322p+724", 309, "99999999999999988670225591496504042642724870819986016981533507324097780666440272745607095564199569546663253707407016578763273303796211201720443029584092898479300433989106071698353021544403254911815982945786756526505984"}, + {"0x1.221563a9b7323p+724", 309, "100000000000000008265758834125873790434126476426544435070460637811561625600102475210888560830400552004310488942935855313773632204291895769631741044492391238650185947160215814947857554687910937412833128327366741516615680"}, + {"0x1.6a9abc9424febp+727", 309, "999999999999999965084388885482519417592855130626093842171043595190833186399051537317196816706799625297221478016185520727674168639944850288849622355474122345476546392575499689981548348018063279122228410984187505225498624"}, + {"0x1.6a9abc9424fecp+727", 309, "1000000000000000121848654826517477399924067975478561186882460639090543945868349157039448538836407484958399359900416230607757039843910326832140006474740509066843630497944377635977584613166124739130365574036827385146376192"}, + {"0x1.c5416bb92e3e6p+730", 309, "9999999999999999964372420736895110140590976995965873111133270039707753382929110612616471611327211972294570543930316627036907428807379455975076991793273996897499632136492752791807556010476755711238558435947154812096741376"}, + {"0x1.c5416bb92e3e7p+730", 309, "10000000000000001218486548265174773999240679754785611868824606390905439458683491570394485388364074849583993599004162306077570398439103268321400064747405090668436304979443776359775846131661247391303655740368273851463761920"}, + {"0x1.1b48e353bce6fp+734", 309, "99999999999999984594354677029595135102113336853821866019036664182705300920238534632828550788829765195472628778417018121881118652493108811594893042483166843723756247249515245102456078650553656951604416706418119648563167232"}, + {"0x1.1b48e353bce70p+734", 309, "100000000000000004660180717482069756840508580994937686142098045801868278132308629957276771221419571232103397659598548986531726166600689809136062209749264344058743012736731622189948720589505523832645973577156024278435495936"}, + {"0x1.621b1c28ac20bp+737", 309, "999999999999999886075198851200900594497923856820450300436489405065378963626525536977181948753477264027987825546533242948112401553146250111031268759363863437907536003469585205199546070383440303278127280805657005745376329728"}, + {"0x1.621b1c28ac20cp+737", 309, "1000000000000000046601807174820697568405085809949376861420980458018682781323086299572767712214195712321033976595985489865317261666006898091360622097492643440587430127367316221899487205895055238326459735771560242784354959360"}, + {"0x1.baa1e332d728ep+740", 309, "9999999999999999181805205159248599892793562474462356126333876156560397271658376894962991014456209536865970557564236923315533735757183797070971394269896194384435148282491314085395342974857632902877937717988376531531720556544"}, + {"0x1.baa1e332d728fp+740", 309, "10000000000000000466018071748206975684050858099493768614209804580186827813230862995727677122141957123210339765959854898653172616660068980913606220974926434405874301273673162218994872058950552383264597357715602427843549593600"}, + {"0x1.14a52dffc6799p+744", 309, "99999999999999996954903517948319502092964807244749211214842475260109694882873713352688654575305085714037182409224841134505892881183378706080253249519082903930108094789640533388351546084948006950326015738792668900564521713664"}, + {"0x1.14a52dffc679ap+744", 309, "100000000000000017502309383371653514753081537245251811020857330038132583548033490964923632298277047095547089743554728739908114975629541647562410476799566744273134542648550103525944011430434718636512569974428283241553786306560"}, + {"0x1.59ce797fb817fp+747", 309, "999999999999999928454223448636526995609414612446486912536395043045051171498417578302416590307106934377352009423588636134254484622941461177838218040629861358615028052178586193608330530158506646130887048916655460323666687950848"}, + {"0x1.59ce797fb8180p+747", 309, "1000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016"}, + {"0x1.b04217dfa61dfp+750", 309, "9999999999999999613300728333138614158656013804472910722260188106898877933626732224819925546638620725877678611585164563028980399740553218842096696042786355031638703687528415058284784747112853848287855356936724432692495112994816"}, + {"0x1.b04217dfa61e0p+750", 309, "10000000000000000928334703720231990968903484524505077109845138812692342808196957992002964120908826254294312680982277369774722613785107647096954758588737320813592396350498627547090702529224003396203794828017403750515808046940160"}, + {"0x1.0e294eebc7d2bp+754", 309, "99999999999999988242803431008825880725075313724536108897092176834227990088845967645101024020764974088276981699468968789815350713138205618891818585152157755624664880897462875650012340778461641195382916742883168419985073526276096"}, + {"0x1.0e294eebc7d2cp+754", 309, "100000000000000009283347037202319909689034845245050771098451388126923428081969579920029641209088262542943126809822773697747226137851076470969547585887373208135923963504986275470907025292240033962037948280174037505158080469401600"}, + {"0x1.51b3a2a6b9c76p+757", 309, "999999999999999924509121522475246865178672200286390413373640190927670776874706901000867474584296317792102107215397297714017257980807797893073643852992008461269166974189675556141912776812173197487139230503413422370196749149011968"}, + {"0x1.51b3a2a6b9c77p+757", 309, "1000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016000"}, + {"0x1.a6208b5068394p+760", 309, "9999999999999999918388610622944277578633427011520373324179896670642961784527024602806390495869308408470337715685294734193992593398889846197223766553446979093051960385337504355687757672562640543404353314227442034427503713670135808"}, + {"0x1.a6208b5068395p+760", 309, "10000000000000001264983401419327895432326837028833311705066886193375469816086935788401821995921998869568971002747938248301632620580513580730198422600500768053772541672219001944225017481444457680470275332614057655878576158030168064"}, + {"0x1.07d457124123cp+764", 309, "99999999999999988411127779858373832956786989976700226194703050524569553592790956543300452958271560395914310860351799229078805716535908585708440417158039479244754953558323062848579498254571868337516156995181495372666457581821100032"}, + {"0x1.07d457124123dp+764", 309, "100000000000000009956644432600511718615881550253707240288894882888289682097749535512827356959114607773492443453354095454801046151441888338236034913910900102616284254148427024265175655196680942530570909289367345315883616691581616128"}, + {"0x1.49c96cd6d16cbp+767", 309, "999999999999999884111277798583738329567869899767002261947030505245695535927909565433004529582715603959143108603517992290788057165359085857084404171580394792447549535583230628485794982545718683375161569951814953726664575818211000320"}, + {"0x1.49c96cd6d16ccp+767", 309, "1000000000000000056475411020520841414840626381983058374700565164155456563967578197189219761589459982979768169347536362096565980644606923877305160145603279779419783940304062319818564238082591276919599588305301753272401848696295129088"}, + {"0x1.9c3bc80c85c7ep+770", 309, "9999999999999999185841044429711589466224211962102134844977374370276477415358432917842475759840644797632681207523216662519436418612086534611285553663849717898419964165273969667523488336530932020840491736225123136358120303938278260736"}, + {"0x1.9c3bc80c85c7fp+770", 309, "10000000000000000564754110205208414148406263819830583747005651641554565639675781971892197615894599829797681693475363620965659806446069238773051601456032797794197839403040623198185642380825912769195995883053017532724018486962951290880"}, + {"0x1.01a55d07d39cfp+774", 309, "99999999999999997374062707399103193390970327051935144057886852787877127050853725394623645022622268104986814019040754458979257737456796162759919727807229498567311142603806310797883499542489243201826933949562808949044795771481474727936"}, + {"0x1.01a55d07d39d0p+774", 309, "100000000000000019436671759807052388305883156775590326490339289128326538639931310259419194719485548619626821794275105794118831942800519429348176492482158776899757146408072767288477964251208935175515000298809119290899166699876243210240"}, + {"0x1.420eb449c8842p+777", 309, "999999999999999841364972759543336764420226292177420345984153909836074800974071744757463152045042997962028093539001436578955132142505622028069656690022719315678435403212464369035268207172574280176140941400150227439321732144446136385536"}, + {"0x1.420eb449c8843p+777", 309, "1000000000000000017865845178806930323739528929966661805443773400559670093686692423675827549619949242079148155740876247260071725785255408160775710807422153542338003433646596020960023924842331815965645472194120710174156699571604284243968"}, + {"0x1.9292615c3aa53p+780", 309, "9999999999999999119653217272487741881479473472931169297680017061255129180591200163248089110750054956088761184197513608514017695996055364811520783369824930063422626153861170298051704942404772944919427537177384205332557191153093955289088"}, + {"0x1.9292615c3aa54p+780", 309, "10000000000000000531660196626596490356033894575245100973356972987043891522292165594595004291349304909025721681812512093962950445138053653873169216309020403876699170397334223513449750683762833231235463783529148067211236930570359138156544"}, + {"0x1.f736f9b3494e8p+783", 309, "99999999999999994020546131433094915763903576933939556328154082464128816489313932495174721468699049466761532837205133056038042458244550226238504699576640248260779350025557809411313140906763850021826347864477369777082931390365469918625792"}, + {"0x1.f736f9b3494e9p+783", 309, "100000000000000005316601966265964903560338945752451009733569729870438915222921655945950042913493049090257216818125120939629504451380536538731692163090204038766991703973342235134497506837628332312354637835291480672112369305703591381565440"}, + {"0x1.3a825c100dd11p+787", 309, "999999999999999940205461314330949157639035769339395563281540824641288164893139324951747214686990494667615328372051330560380424582445502262385046995766402482607793500255578094113131409067638500218263478644773697770829313903654699186257920"}, + {"0x1.3a825c100dd12p+787", 309, "1000000000000000120942354671656868962382001670435578817768191183142249744630862900164152357803694488643546272066771136697843816472621283262276046411983423130707191163420128905684081263961470216866716118177799472091300320549064642593292288"}, + {"0x1.8922f31411455p+790", 309, "9999999999999999040580826428657651966904425891201589123842107529410958489455946099092661860636496958724291396331073693328877462044103460624068471125229983529879139676226679317989414380888721568885729507381685429067351125745727105048510464"}, + {"0x1.8922f31411456p+790", 309, "10000000000000000486475973287265010404848153099971055159735310397418651127357734700791903005570128910531738945888832142428584597165509708623196466454966148714674320981543085810557013220039375302073350623645891623631119178909006652304785408"}, + {"0x1.eb6bafd91596bp+793", 309, "99999999999999999081179145438220670296706622164632687453780292502155740721970192601122065475966761298087599260657287627887017431169472094235452683230716826407562484594165232135299736843791138087983021771402091458056119576436948334022754304"}, + {"0x1.eb6bafd91596cp+793", 309, "100000000000000010648340320307079537800256439834788415740925915446217281825184501414715994635435816912547179657119355220684674512140722078228476645868606147885923935036696484075840527556996367953483990701515741014566264001743184712072953856"}, + {"0x1.33234de7ad7e2p+797", 309, "999999999999999828871535006218182557917368774264146678517764203804695831774701602620905646527100834378441867056103929979702975178097221166452191355376717763378564539746214794185426298453038162762816652692429820789419173810082174047524749312"}, + {"0x1.33234de7ad7e3p+797", 309, "1000000000000000013946113804119924437974165856986638331112094170909680489426130543638408513078605724209795153399497011464465488473637220910340574757582946907032347746826714825234078949864321840610832155574248213693581484614981956096327942144"}, + {"0x1.7fec216198ddbp+800", 309, "9999999999999999029013665253788793099400876073531433395554961906466896948352731790279067931477027903109831815934611625736079804963132210640075447162592094208400778225784148066048873590175516339020228538451571779510840981320420868670460264448"}, + {"0x1.7fec216198ddcp+800", 309, "10000000000000000509610295637002728139855252735311366616309601643306774209564163318419090863889067021760658106681756277614179911327452208591182514380241927357631043882428148314438094801465785761804352561506118922744139467759619125060885807104"}, + {"0x1.dfe729b9ff152p+803", 309, "99999999999999993251329913304315801074917514058874200397058898538348724005950180959070725179594357268399970740840405561116998262359962102302968606061220608382468313571129481157267178324335702235770533430624812081575006786082605199485453729792"}, + {"0x1.dfe729b9ff153p+803", 309, "100000000000000005096102956370027281398552527353113666163096016433067742095641633184190908638890670217606581066817562776141799113274522085911825143802419273576310438824281483144380948014657857618043525615061189227441394677596191250608858071040"}, + {"0x1.2bf07a143f6d3p+807", 309, "999999999999999885134206960780312089454635087411784140906440513804611167700736000690226517958758320887173266104495426751070779219941381088594259909647411423049314634698686803624216704482068400828613365568502612232284516294771707790360919932928"}, + {"0x1.2bf07a143f6d4p+807", 309, "1000000000000000074650575649831695774632795300119615593163034400120115457135799236292149453307499328074479031320129942191467592834574340826335964513506590066150788638749118835418037019527222886944981240519484646566146722558989084608335389392896"}, + {"0x1.76ec98994f488p+810", 309, "9999999999999999230374806985905888264902671299533504313577592910677120255877486478106111050285065223246344191476223298391501419428679730361426008304192471516696094355087732099829807674910992980518869405586990190990569575476151831539558138249216"}, + {"0x1.76ec98994f489p+810", 309, "10000000000000000746505756498316957746327953001196155931630344001201154571357992362921494533074993280744790313201299421914675928345743408263359645135065900661507886387491188354180370195272228869449812405194846465661467225589890846083353893928960"}, + {"0x1.d4a7bebfa31aap+813", 309, "99999999999999992303748069859058882649026712995335043135775929106771202558774864781061110502850652232463441914762232983915014194286797303614260083041924715166960943550877320998298076749109929805188694055869901909905695754761518315395581382492160"}, + {"0x1.d4a7bebfa31abp+813", 309, "100000000000000004432795665958347438500428966608636256080197937830963477082618911859584178365170076692451010888562841972100410265623306726829729177688912148325455279810104971033102576911999816916636238052732752107272876955671430431745947427930112"}, + {"0x1.24e8d737c5f0ap+817", 309, "999999999999999874521290314193434603084658115500145579580071256170942927492372459496518833579228824484684143252419893886408557657521935343280724451831297419035632090471862609843762766839539749606096764571247618309588232743975534688554349643169792"}, + {"0x1.24e8d737c5f0bp+817", 309, "1000000000000000068586051851782051496707094173312964986690823395758019319873877212752887919376339615844485246833229637697374894798906086114728229966183096349571541470619505010400634769445777943389257468521053221467463131958534128550160206370177024"}, + {"0x1.6e230d05b76cdp+820", 309, "9999999999999999521471949292288813605336325386252733424243721120057734844449743607990664678980731410286045846847437914107950925140755956518597266575720169912499958425309195700665115678820350271193610461511698595727381924297989722331966923339726848"}, + {"0x1.6e230d05b76cep+820", 309, "10000000000000001073990041592997748754315813848755288681129738236754345983501781634041617365357617741164454675493915864595681622271829162690177310690534561356787233466490334905120091699670255821458896093110143420990381118014458473224813777155784704"}, + {"0x1.c9abd04725480p+823", 309, "99999999999999992109683308321470265755404276937522223728665176967184126166393360027804741417053541441103640811181423240104047857145413152842812577527572916236425034170729678597741204746503691611405533351920096306747820855546959721533975525765152768"}, + {"0x1.c9abd04725481p+823", 309, "100000000000000004529828046727141746947240184637542665783753313900757015278809664236212362908068632088130911440353246844005893434193998802215452930446088047790723234500178792233381012913302936013527818404707654908851814405278709728676750356293615616"}, + {"0x1.1e0b622c774d0p+827", 309, "999999999999999921096833083214702657554042769375222237286651769671841261663933600278047414170535414411036408111814232401040478571454131528428125775275729162364250341707296785977412047465036916114055333519200963067478208555469597215339755257651527680"}, + {"0x1.1e0b622c774d1p+827", 309, "1000000000000000119819148897705446356623417292575549310168061960609007487462594467612569358026776864763472738178563410063470007804231501918390371421971971267233021546978482604147648978133824826548011894363801900701142105351177597329624152546106933248"}, + {"0x1.658e3ab795204p+830", 309, "9999999999999999210968330832147026575540427693752222372866517696718412616639336002780474141705354144110364081118142324010404785714541315284281257752757291623642503417072967859774120474650369161140553335192009630674782085554695972153397552576515276800"}, + {"0x1.658e3ab795205p+830", 309, "10000000000000000800746857348072976168095423879354838955917799224215742423028622941456649692555285746929854721652135745309841019576760278403979222926327228462592673059242454405136015920000672444612205821948817131744093259920359973067672730884158521344"}, + {"0x1.bef1c9657a685p+833", 309, "99999999999999992109683308321470265755404276937522223728665176967184126166393360027804741417053541441103640811181423240104047857145413152842812577527572916236425034170729678597741204746503691611405533351920096306747820855546959721533975525765152768000"}, + {"0x1.bef1c9657a686p+833", 309, "100000000000000004827911520448877862495844246422343156393075429187162764617507655537214145823852994263659565935453370610499537728043164857800396298916132410948026391308085570960636368309306117879178753245974556315302310250472271728848176952226298724352"}, + {"0x1.17571ddf6c813p+837", 309, "999999999999999895660376658959887464073162830405580371957831265231883984761705009259228605356936508765924557863270337660249498829658628118512958332498610172941047627432585001251621720339432063578508893731092043050369229765618973200711352404729235767296"}, + {"0x1.17571ddf6c814p+837", 309, "1000000000000000099152028052998409011920202342162715294588395300751542199979533737409779075865727753926819359851621495586577336764022655397834297874715562088326669341630279279057944337344270883862880412035963403187241060084423965317738575228107571068928"}, + {"0x1.5d2ce55747a18p+840", 309, "9999999999999999363587069377675917736425707327570073564839440723358156278052707548893386994586947577981035182609405692455150664165314335743772262409420005560181719702721238568128862437403998276353831973920663150777435958293799716241167969694049028276224"}, + {"0x1.5d2ce55747a19p+840", 309, "10000000000000000991520280529984090119202023421627152945883953007515421999795337374097790758657277539268193598516214955865773367640226553978342978747155620883266693416302792790579443373442708838628804120359634031872410600844239653177385752281075710689280"}, + {"0x1.b4781ead1989ep+843", 309, "99999999999999993635870693776759177364257073275700735648394407233581562780527075488933869945869475779810351826094056924551506641653143357437722624094200055601817197027212385681288624374039982763538319739206631507774359582937997162411679696940490282762240"}, + {"0x1.b4781ead1989fp+843", 309, "100000000000000006659336382995224556426467602028157370696750505506839688554468114090569100058432115470107619153348531031836488269452441103314288354796084978186496986735864819460893271862349667261738096910718398556534156723341516657901421957636703742066688"}, + {"0x1.10cb132c2ff63p+847", 309, "999999999999999988452569694641453289891412847766833896677368465428848130901034909295879619908945316559292587569958465674654992927728624557883489163749540246356891129106733591931304833693638565628182306078113383272782784390994049606075766012189756664840192"}, + {"0x1.10cb132c2ff64p+847", 309, "1000000000000000196828020722136899354886781307806140057451066037800978143284091526922043301709947551604048864806030051391214698972517388491908540854979699007711767764445172532404979193506593517599378740822301656052939538637450361533911642183329172013711360"}, + {"0x1.54fdd7f73bf3bp+850", 309, "9999999999999998634272990781441856508941917717432502002131499220055701234712009387201814108283439755324388212283155142447191693008553661974684581490114449895439651479036702276471002178058655944454644452316004196046887318431202624493742403095061074555174912"}, + {"0x1.54fdd7f73bf3cp+850", 309, "10000000000000000301276599001405425028904865397746951288321079799032741333776462328211123562691457635682438430171727828179669341366863773446884995019955719986278664561744213800260397056562295560224215930269510378288141352402853119916429412464176397346144256"}, + {"0x1.aa3d4df50af0ap+853", 309, "99999999999999989676737124254345702129345072534953918593694153358511092545248999754036759991650433313959982558608696795936872226802156842691246641960827039136074540955782045812288811537593838676085587479067054324951381252255327235782798049688841391133687808"}, + {"0x1.aa3d4df50af0bp+853", 309, "100000000000000003012765990014054250289048653977469512883210797990327413337764623282111235626914576356824384301717278281796693413668637734468849950199557199862786645617442138002603970565622955602242159302695103782881413524028531199164294124641763973461442560"}, + {"0x1.0a6650b926d66p+857", 309, "999999999999999843423255779504622828654636399579476808778874955057845642282427503428069697375447760968142218613652642015929437520555644859802053186653349748453896990911180089361627479263821919056229587496158345417793683435460456504301996197076723582025859072"}, + {"0x1.0a6650b926d67p+857", 309, "1000000000000000056799717631659959599209893702659726317411141269166906774962677479877261307539674049653972646503389945789686576510419339128243706118473032320081290665497741564406670023712287789874734736674207136744674199783831719918405933396323484899269935104"}, + {"0x1.4cffe4e7708c0p+860", 309, "9999999999999999287738405203667575368767393208115766122317814807014700953545274940077463414411382764424743897695475635254322931165011225671787143593812227771048544607458046793796444970432082673836316471673778619485458899748089618699435710767754281089234894848"}, + {"0x1.4cffe4e7708c1p+860", 309, "10000000000000000994750100020910269533209451632757762191375945319887190014987274751670996295725193073911387320813374065444380043083920779819320367048369688344067694004150538594156785326019809640384357665098168950100503030535059726012267208361728371627187503104"}, + {"0x1.a03fde214caf0p+863", 309, "99999999999999992877384052036675753687673932081157661223178148070147009535452749400774634144113827644247438976954756352543229311650112256717871435938122277710485446074580467937964449704320826738363164716737786194854588997480896186994357107677542810892348948480"}, + {"0x1.a03fde214caf1p+863", 309, "100000000000000006533477610574617307003210399478293629775643192173126922026988747893522897194624310120140586361897943794063686207001388689898137223574581962294638641248120402340847172549022642470747494264132908839774942043776657045497009088429335535195969814528"}, + {"0x1.0427ead4cfed6p+867", 309, "999999999999999928773840520366757536876739320811576612231781480701470095354527494007746341441138276442474389769547563525432293116501122567178714359381222777104854460745804679379644497043208267383631647167377861948545889974808961869943571076775428108923489484800"}, + {"0x1.0427ead4cfed7p+867", 309, "1000000000000000147271337456973822389925322799165752109071222186349148695219103469891718550249305996056764747928638562589759603442121545498062966961564577730451305583522443629825768062558437319101780919925699824267271538715541135605986002768804111697781423341568"}, + {"0x1.4531e58a03e8bp+870", 309, "9999999999999998413748417457239315956573059294699064134960051984423986554086971036541574579178711885967582465059111638997013689862529533948250133185078807957662740116351490992011950708371166466963719380640490770210556304785160923755265983999639546733803159420928"}, + {"0x1.4531e58a03e8cp+870", 309, "10000000000000000161728392950095834780961727121532468109675577629605415353003578843613352249644053642881905330331839631511632172467492917395324154002545647584434349098564602595580939232492998880708913562707066468760361494711018313643605437535869015444666630275072"}, + {"0x1.967e5eec84e2ep+873", 309, "99999999999999987633444125558106197214507928600657449299031571134602723138702925979559301132717802373504470381136572374999373863835222106376649373485721758830170619127941133127257484131955329497127582170538059099205173427703324017329338747068854404759758535917568"}, + {"0x1.967e5eec84e2fp+873", 309, "100000000000000001617283929500958347809617271215324681096755776296054153530035788436133522496440536428819053303318396315116321724674929173953241540025456475844343490985646025955809392324929988807089135627070664687603614947110183136436054375358690154446666302750720"}, + {"0x1.fc1df6a7a61bap+876", 309, "999999999999999932269800471352470574525516656465243420181212531991832952952360709621889896782068959956303035500093019510461530081711049334072862401016156456358397678710230902586782474091451932211122035531511013345645500354660676649720249983847887046345216426508288"}, + {"0x1.fc1df6a7a61bbp+876", 309, "1000000000000000044140518902895287779286391397382581274563006173283444396083023609274483667691850832398819698877547611031397112968428705874685599733334034192471780653571870045215197739635249206690814463183771858052833032509915549602573975010166573043840478561173504"}, + {"0x1.3d92ba28c7d14p+880", 309, "9999999999999998875215130987353436926211667600983082784284950754751883757000955497608523884181562109792963701491111829020872969270239867178277674680890053619130444887655752455354163678739330224192450644706066754627704874925587274685787599733204126473471115726422016"}, + {"0x1.3d92ba28c7d15p+880", 309, "10000000000000000665146625892038512202385663455660488454393649015417666847091561892050024218738072068873230315530385293355842295457722371828081471997976097396944572485441978737408807927440086615867529487142240269942705389409665241931447200154303102433395309881065472"}, + {"0x1.8cf768b2f9c59p+883", 309, "99999999999999988752151309873534369262116676009830827842849507547518837570009554976085238841815621097929637014911118290208729692702398671782776746808900536191304448876557524553541636787393302241924506447060667546277048749255872746857875997332041264734711157264220160"}, + {"0x1.8cf768b2f9c5ap+883", 309, "100000000000000003071603269111014971471508642847250073203719093632845102290734406131617241518267700770571769927225306004888484302202258708981207125345588886413817469658847334809978790776999353375325137186550055668797052865128496484823152800700833072414104710501367808"}, + {"0x1.f03542dfb8370p+886", 309, "999999999999999973438224854160227305877518561122823750593712591987145964024444656694044404476868689015149167622996309190165824584023146941018349739309135463248122613459314107074039291811569329219648848907543004197890512187794469896370420793533163493423472892065087488"}, + {"0x1.f03542dfb8371p+886", 309, "1000000000000000087993840528060072123552654295822177713480669280669756081790243465938300425888485326396286230921509810907603861460022027238605792767602642265028226779717632589125536523728417738286853894823458109178050545114775459800092635220483497954858621317962268672"}, + {"0x1.362149cbd3226p+890", 309, "9999999999999999734382248541602273058775185611228237505937125919871459640244446566940444044768686890151491676229963091901658245840231469410183497393091354632481226134593141070740392918115693292196488489075430041978905121877944698963704207935331634934234728920650874880"}, + {"0x1.362149cbd3227p+890", 309, "10000000000000001567272099323999790141577357366417900912128432938793221524497227514848540387354553088249684689006179119380666835856213554171582585845787463460962892794726236783564348628785267837271769223730071721661465648709640537423259638766536986317197103735005773824"}, + {"0x1.83a99c3ec7eafp+893", 309, "99999999999999990012263082286432662256543169091523721434606031123027548865433341877772055077343404109122144711194766809100548098338386355056238620120129111010885594705399027856108106338478634741663761952135733701058809111452663635798820356028494943810497789949089153024"}, + {"0x1.83a99c3ec7eb0p+893", 309, "100000000000000004675381888545612798918960543133041028684136487274401643939455589461036825818030333693907688813404495028932616818466243033147431327741697981638738927986463793558699752023835231102266007829372867138519293326106230343475263802678137754874196788463928344576"}, + {"0x1.e494034e79e5bp+896", 309, "999999999999999929448868435382686895890266438998271828845121223533023678802377913944250092254807900260792535316367124530669618423639576906744771616444428851364562613616119809966264354755499540137842111275831603885509059543833769773341090453584235060232375896520569913344"}, + {"0x1.e494034e79e5cp+896", 309, "1000000000000000046753818885456127989189605431330410286841364872744016439394555894610368258180303336939076888134044950289326168184662430331474313277416979816387389279864637935586997520238352311022660078293728671385192933261062303434752638026781377548741967884639283445760"}, + {"0x1.2edc82110c2f9p+900", 309, "9999999999999999529098585253973751145501342374646995204443699533752222309208135100774737254399069875964494058799026896824009283758441475916906799486389390443691279468658234350904109878520700943148057046794110173854458342872794765056233999682236635579342942941443126198272"}, + {"0x1.2edc82110c2fap+900", 309, "10000000000000001405977792455148808638290766251961210532383597921128106478682982791432627909206996862817043703881872108962514079934807130712579466061950205884056506128634524360835840526246345277305144519080463253849400322348451303638818760853390915395496414751342542716928"}, + {"0x1.7a93a2954f3b7p+903", 309, "99999999999999991537227438137387396469434575991841521388557198562770454753131655626431591234374844785939841297824578543963083245231683449577722661712772273556182341366629763489177637489755720763166395523368395578554699469776634573397170474480057796161122485794632428945408"}, + {"0x1.7a93a2954f3b8p+903", 309, "100000000000000006552261095746787856411749967010355244012076385661777528108930437151694716472838260680760238458487340241071121614642608687943103994317258797079104154646440083568631482671560875436423095301659220218514235305581886882057848563849292034690350260273827761094656"}, + {"0x1.d9388b3aa30a5p+906", 309, "999999999999999945402341696592674884578976541955442659132610359825718694242914119314842162820675279649039207299571308833846909191138684972507989282336695782607667040225918275050684065261167516978177354790265605065466066369376850351293060923539046438669680406904714953752576"}, + {"0x1.d9388b3aa30a6p+906", 309, "1000000000000000065522610957467878564117499670103552440120763856617775281089304371516947164728382606807602384584873402410711216146426086879431039943172587970791041546464400835686314826715608754364230953016592202185142353055818868820578485638492920346903502602738277610946560"}, + {"0x1.27c35704a5e67p+910", 309, "9999999999999999213782878444176341486712719163258207029349796604673073768736360688744211624391338142173265718425108901184740478000812045911233791501695173449709921389782217629235579129702792695009666351450002856415308090320884466574359759805482716570229159677380024223137792"}, + {"0x1.27c35704a5e68p+910", 309, "10000000000000001135707186618179600359329089213627963525160252553345979158278604723977891654914655376710276554989942398414569389285410476422002602075069448460643913489597938599405671312973852493186523923071228410330128677303956762082926555244744699101970314810717026738241536"}, + {"0x1.71b42cc5cf601p+913", 309, "99999999999999995981677400789769932612359931733321583285118877944076548466448094957909476304960015890806678857380756006307062602577317320133875536163700284518967198097453618232695975663570046546450378657742479671982722077174989256760731188933351130765773907040474247261585408"}, + {"0x1.71b42cc5cf602p+913", 309, "100000000000000011357071866181796003593290892136279635251602525533459791582786047239778916549146553767102765549899423984145693892854104764220026020750694484606439134895979385994056713129738524931865239230712284103301286773039567620829265552447446991019703148107170267382415360"}, + {"0x1.ce2137f743381p+916", 309, "999999999999999929065985077113647184161737396527299728918221484261998998431805045015355882561227083155474615188770224107393363445219598313166454392463014445014728107377484646804238281703363508693674065431485187857190091380020735839470243162305319587149880588271350432374194176"}, + {"0x1.ce2137f743382p+916", 309, "1000000000000000052069140800249855752009185079750964144650090664977064943362508663270311404514719386165843308728919567930102413767433897865855658269158968045714503601765690788895124181432711335776992950015243623307738608946937362752018518070418086469181314516804918593340833792"}, + {"0x1.20d4c2fa8a030p+920", 309, "9999999999999998060628293539774386163142897133036353131863523035469330535011014267604003606077347801451059216486208802846843131230052987604772505157670608443149526129892785047133523819740156816103551808477267524066415738131041089269219682541925527051184466597377822714075545600"}, + {"0x1.20d4c2fa8a031p+920", 309, "10000000000000000028678785109953723248702060064614983783573429926910385653902272159683291957333224649616958313128598304010187936385481780447799767184805866054345934040104083320587698215409722049436653961817402491275192019201707119869992081071729797163687409453914913289541779456"}, + {"0x1.6909f3b92c83dp+923", 309, "99999999999999996350686867959178558315902274782992576532314485486221746301240205812674342870820492799837784938001204037775189753543960218791943147793788145321066524580618236658968633362758090027700335311493754978334367629875739137498376013657689431411868208826074951744485326848"}, + {"0x1.6909f3b92c83ep+923", 309, "100000000000000012095090800520613255000375578235621621745993740617750187252370268949308649680867507585164977711140320047081948194787390561536161244010870206210637787862308622846602028528114611894365152538214834716004577878441067382304555201896123592311891751678371676348215197696"}, + {"0x1.c34c70a777a4cp+926", 309, "999999999999999932018060814468916189790076140924667674895786344599160581110141931853474815088110898427723463833733808359138380652952741502430995285503717331431522719242801594214419543296867856543673718661495390308003255801626734885371401760100025992318635002556156068237393526784"}, + {"0x1.c34c70a777a4dp+926", 309, "1000000000000000057973292274960393763265862568545700036605220385651388108719182436946549269568487016710341006018846736433592448182900184244384740055240373818548092825496324683715486704619720031476992256475264028209364937790149360843820835266007499279518823345374529865067232493568"}, + {"0x1.1a0fc668aac6fp+930", 309, "9999999999999998312538756460757341310094469988278417855282391117573785590229095277790152515038100038016294300856434658995751266289947873088679994697143921417382666342399831226135658142385861165970188884104804799869139102108086341186118549553740473625584843283014570307735223533568"}, + {"0x1.1a0fc668aac70p+930", 309, "10000000000000000327822459828620982485707052830214935642633335774409426031973743359279343786724117930538174975818241508187016346769106956959939911012930425211247788042456200658152732723551495964903285489125103006290926013924448356521309485648260046220787856768108551057012647002112"}, + {"0x1.6093b802d578bp+933", 309, "99999999999999987155954971343300695452169865566657214127525800489409136785780248940879907693753036165206704358487960288340042823857796898629319779603012221761556906824111051125390730586189881257568082051088644411534964844713587442531567367726443881446254459800333664575907082272768"}, + {"0x1.6093b802d578cp+933", 309, "100000000000000003278224598286209824857070528302149356426333357744094260319737433592793437867241179305381749758182415081870163467691069569599399110129304252112477880424562006581527327235514959649032854891251030062909260139244483565213094856482600462207878567681085510570126470021120"}, + {"0x1.b8b8a6038ad6ep+936", 309, "999999999999999903804088967318825213331499981137556425872873119403461614925716858712626137284506647932417134384268512470460669526244514328233356457082706278317411015442012422166180499160548969358610366191211215418098239036197666670678728654776751975985792813764840337747509598224384"}, + {"0x1.b8b8a6038ad6fp+936", 309, "1000000000000000032782245982862098248570705283021493564263333577440942603197374335927934378672411793053817497581824150818701634676910695695993991101293042521124778804245620065815273272355149596490328548912510300629092601392444835652130948564826004622078785676810855105701264700211200"}, + {"0x1.137367c236c65p+940", 309, "9999999999999999553953517735361344274271821018911312812290573026184540102343798495987494338396687059809772796632907678097570555865109868753376103147668407754403581309634554796258176084383892202112976392797308495024959839786965342632596166187964530344229899589832462449290116390191104"}, + {"0x1.137367c236c66p+940", 309, "10000000000000001617604029984053712838099105849054307026537940354784235914690318131432426200603169381752178607793797891669425998275768770637546257455033787639321465930492277094643660455497502236220467316338093858400869637486920046335831684748752572681717785398568698736550198021980160"}, + {"0x1.585041b2c477ep+943", 309, "99999999999999991412234152856228705615063640528827139694410995604646009398744945688985079659553905954212916344007296353831994673829780883765420722861953317774200043854630103365810792101611701952914782080891514223497778802469744018919490624758069218767323224280852151918381000638332928"}, + {"0x1.585041b2c477fp+943", 309, "100000000000000007921438250845767654125681919169971093408389934233443575897517102772544534557205764529752162833294418062406838213115052098838781957320876356853543120821491881752894667070520582225774709469217797130505057184069381648545374773244373557467226310750742042216461653692645376"}, + {"0x1.ae64521f7595ep+946", 309, "999999999999999980159157920520442850193109519852847211800025710561650359982538085224088616186146493844286149397221450372619320895438893697947652166455225334059372746413748147206443420891752540620587530362220273863006901551095990707698442841525909542472844588688081080376132618600579072"}, + {"0x1.ae64521f7595fp+946", 309, "1000000000000000112232790704436754438278055748981998841511857219592030891972715341892564255367361362448600121311518424041218069209721063418534542042126609646694117362148642374303114420643023582803466949468830537119065128603893091744705516029416344252072069280447200202760777843035078656"}, + {"0x1.0cfeb353a97dap+950", 309, "9999999999999998216707985798208689444911740448978652561458278997251937215943253772219178491686886515191093831000650819703008229183002900332433843156495641588976792075318750746904382211902272900011322274342879579557370290877394694632899550160573878909537749585771381335145583492791795712"}, + {"0x1.0cfeb353a97dbp+950", 309, "10000000000000000329886110340869674854270880115045078636847583141738025727786089878914788718586324412860117381629402398400588202211517615861824081167237790591132705927077058380451118207922609574937392980048643791654301923722148311225012721166820834263125344653917287293299907083743789056"}, + {"0x1.503e602893dd1p+953", 309, "99999999999999990619792356152730836086553963154052229916140006550463726206803882148974225824466616742587032512521514511820402183944087865441899383607925011898391576160220738003230766103104075699817505566251852643961429440152961412697448185630726610509727876130297437184073129291725930496"}, + {"0x1.503e602893dd2p+953", 309, "100000000000000007525217352494018719361427080482583638519254439706352434301546571002539107639662119923939220917551527141401041968172205589677021287693862203915638886974287199071604654071266769099226071211897966340736882502910990345434353553680702253338428636675464684849307718019341877248"}, + {"0x1.a44df832b8d45p+956", 309, "999999999999999872387073568844732594315793396883459481955171199192859845878553443782612494614275161063165948315155119859042742270984643205948750027907375734949421139974074457895559885094715370199357924371226299046063388276013556261500671120207314819439877240212639876510262115462027411456"}, + {"0x1.a44df832b8d46p+956", 309, "1000000000000000007630473539575035660514778335511710750780086664439969510636494954611131549135839186513983455555395220895687860544809584999829725260594873271087399626486606146442550988840016917394626449536395208620267012778077787723395914064607119962069483324573977857832138825282954985472"}, + {"0x1.06b0bb1fb384bp+960", 309, "9999999999999998453383935746986719810759964091578092281901881061434379129269651416169086837099623559730024468671070996517137186162196548471725549813698762277218254426715681201861616643456550607603042193381925171312226633756007099691216225313273537909139560233403722802458867734978418966528"}, + {"0x1.06b0bb1fb384cp+960", 309, "10000000000000000617278335278671568869943723109630112583100528505388133765396715589425391709444647966943104584514912613103459078543395617173821153536698722855425910210916188218613474303381375362727338596024627724499484625789034803081540112423670420191213257583185130503608895092113260150784"}, + {"0x1.485ce9e7a065ep+963", 309, "99999999999999988861628156533236896225967158951884963421416105502251300564950642508203478115686284411726404918398393198344015646384363622121446705582987543928597855835557826052119881754415155586279014739104656819496782321626126403692810027353529143655542997033600043426888732064053872033792"}, + {"0x1.485ce9e7a065fp+963", 309, "100000000000000006172783352786715688699437231096301125831005285053881337653967155894253917094446479669431045845149126131034590785433956171738211535366987228554259102109161882186134743033813753627273385960246277244994846257890348030815401124236704201912132575831851305036088950921132601507840"}, + {"0x1.9a742461887f6p+966", 309, "999999999999999957860902350346284132153551878096514283852517773229033154005572478626236537071903625148082612890986863714202457020042006419681526374965874177788623543449994485057258262661745948026767632275613049896960078961318150545418464661067991669581788285529005480705688196068853638234112"}, + {"0x1.9a742461887f7p+966", 309, "1000000000000000096350143920374114471941312455251843583129231209642073450717704585714640048901985187209719740304992727175727058132438746816615645013237871654793913513638826934129377152896934732354722602044746013300944590451431923562399193436133392135634504915915015573579289946925483474026496"}, + {"0x1.008896bcf54f9p+970", 309, "9999999999999997916738124663128877244082391855101191247204616495333847979510139501201523228758057506741180599941798275603729356851659179433605840090394772053822755792233955461707155943795194068332216685526534938121786651731816229250415901309895111103185283290657933692573660950408978352832512"}, + {"0x1.008896bcf54fap+970", 309, "10000000000000000132565989783574162680686561089586460035632031477942492726904253214615979418039362499727374638565892090988122974650007025784551738302746731685907395315255274646861058187558214617579496201832662352585538835573636597522107561710941518560028749376834095178551288964115055725510656"}, + {"0x1.40aabc6c32a38p+973", 309, "99999999999999992462348437353960485060448933957923525202610654848990348279466077292501969423268405025328970231162545648343655275306678872441733790178059478330735395060467469727994972900530063978805843953102113868000379620369084502134308975505229555772913629423636305841602377586326247764393984"}, + {"0x1.40aabc6c32a39p+973", 309, "100000000000000010188971358317522768553282287833805675510029974709859506258618986999817618937518844969218522540155296171418804217693461643249300975876875155387412511244638023209226190850634228372784080083551133183710397091103647448307842258713600815427661358113045597729423401695974866745819136"}, + {"0x1.90d56b873f4c6p+976", 309, "999999999999999924623484373539604850604489339579235252026106548489903482794660772925019694232684050253289702311625456483436552753066788724417337901780594783307353950604674697279949729005300639788058439531021138680003796203690845021343089755052295557729136294236363058416023775863262477643939840"}, + {"0x1.90d56b873f4c7p+976", 309, "1000000000000000066436467741248103118547156170586292454485461107376856746627884050583544890346687569804406120783567460668037744292161050890877875387371120199760770880078039125129799472606133954939884328574613293205683935969567348590731356020719265634967118123751637393518591968740451429495341056"}, + {"0x1.f50ac6690f1f8p+979", 309, "9999999999999999813486777206230041577815560719820581330098483720446847883279500839884297726782854580737362697004022581572770293687044935910015528960168049498887207223940204684198896264456339658487887951484580004902758521100414464490983962613190835886243290260424727924570510530141380583845003264"}, + {"0x1.f50ac6690f1f9p+979", 309, "10000000000000000947990644147898027721356895367877038949773320191542473993945287061152499295694882737146294044779558615049579825999799033241699828844892252830514542659727120106997694213263006179702495063833317241108199639227426493046090092738526596504147144896546922605391056073158892198656212992"}, + {"0x1.3926bc01a973bp+983", 309, "99999999999999998134867772062300415778155607198205813300984837204468478832795008398842977267828545807373626970040225815727702936870449359100155289601680494988872072239402046841988962644563396584878879514845800049027585211004144644909839626131908358862432902604247279245705105301413805838450032640"}, + {"0x1.3926bc01a973cp+983", 309, "100000000000000016286929643128988194074816961567109135215782220741998496603447587939134202370420996309916528534448802351356655453874514916407104087757267748294909439211992693606769729825470060924312593312425595828314643101036337101791537708137280528748894576782202394138833833989693991675429388288"}, + {"0x1.87706b0213d09p+986", 309, "999999999999999872436306494222877488001587945768638201521064070819504681704034606746682422062730755058478860313950798943503314266680100247159860107083281430052496520558476587831205023360193979812186512362979225814553504769848291707808207769286850569305558980974742103098278680884456943362624192512"}, + {"0x1.87706b0213d0ap+986", 309, "1000000000000000017652801462756379714374878780719864776839443139119744823869255243069012222883470359078822072829219411228534934402712624705615450492327979456500795456339201761949451160807447294527656222743617592048849967890105831362861792425329827928397252374398383022243308510390698430058459037696"}, + {"0x1.e94c85c298c4cp+989", 309, "9999999999999999595662034753429788238255624467393741467120915117996487670031669885400803025551745174706847878231119663145222863482996149222332143382301002459214758820269116923021527058285459686414683385913622455551313826420028155008403585629126369847605750170289266545852965785882018353801250996224"}, + {"0x1.e94c85c298c4dp+989", 309, "10000000000000000757393994501697806049241951147003554069667947664398408807353434975979441432117662006869593578353268561425475824571256344889976866464258586670801150306514918315967496157863486204138441068958729385425685531382088472248832262877470188720339297317678393899013204421931950247367929757696"}, + {"0x1.31cfd3999f7afp+993", 309, "99999999999999986662764669548153739894665631237058913850832890808749507601742578129378923002990117089766513181334005445210204946123879926882163649167349350899456456312724758086647517786230384722356772394775369116518164624503799012160606438304513147494189124523779646633247748770420728389479079870464"}, + {"0x1.31cfd3999f7b0p+993", 309, "100000000000000005250476025520442024870446858110815915491585411551180245798890819578637137508044786404370444383288387817694252323536043057564479218478670698284838720092657580373783023379478809005936895323497079994508111903896764088007465274278014249457925878882005684283811566947219638686545940054016"}, + {"0x1.7e43c8800759bp+996", 309, "999999999999999903803069407426113968898218766118103141789833949572356552411722264192305659040010509526872994217248819197070144216063125530186267630296136203765329090687113225440746189048800695790727969805197112921161540803823920273299782054992133678869364753954248541633605124057805104488924519071744"}, + {"0x1.7e43c8800759cp+996", 309, "1000000000000000052504760255204420248704468581108159154915854115511802457988908195786371375080447864043704443832883878176942523235360430575644792184786706982848387200926575803737830233794788090059368953234970799945081119038967640880074652742780142494579258788820056842838115669472196386865459400540160"}, + {"0x1.ddd4baa009302p+999", 309, "9999999999999999335434075769817752248594687291161143444150379827602457335271594505111188022480979804302392841403758309930446200199225865392779725411942503595819407127350057411001629979979981746444561664911518503259454564508526643946547561925497354420113435609274102018745072331406833609642314953654272"}, + {"0x1.ddd4baa009303p+999", 309, "10000000000000000525047602552044202487044685811081591549158541155118024579889081957863713750804478640437044438328838781769425232353604305756447921847867069828483872009265758037378302337947880900593689532349707999450811190389676408800746527427801424945792587888200568428381156694721963868654594005401600"}, + {"0x1.2aa4f4a405be1p+1003", 309, "99999999999999988595886650569271721532146878831929642021471152965962304374245995240101777311515802698485322026337261211948545873374744892473124468375726771027536211745837771604509610367928220847849105179362427047829119141560667380048679757245757262098417746977035154548906385860807815060374033329553408"}, + {"0x1.2aa4f4a405be2p+1003", 309, "100000000000000007629703079084894925347346855150656811701601734206211380288125794484142188964691784076639747577138548761372210387844799938291815611350519830750167649856488981626536368095414607314235151058373458986890825155659063617715863205282622390509284183439858617103083735673849899204570498157510656"}, + {"0x1.754e31cd072d9p+1006", 309, "999999999999999847891233648661470807691068835681842080854450367179124891914700353912936949808806064228544369161770037020638129704807338833093862397807681590830099241237075296001042588224309435545718960035602206600167779387409881325152430676383842364162444596844704620380709158981993982315347403639619584"}, + {"0x1.754e31cd072dap+1006", 309, "1000000000000000000161765076786456438212668646231659438295495017101117499225738747865260243034213915253779773568180337416027445820567779199643391541606026068611150746122284976177256650044200527276807327067690462112661427500197051226489898260678763391449376088547292320814127957486330655468919122263277568"}, + {"0x1.d2a1be4048f90p+1009", 309, "9999999999999999392535525055364621860040287220117324953190771571323204563013233902843309257440507748436856118056162172578717193742636030530235798840866882774987301441682011041067710253162440905843719802548551599076639682550821832659549112269607949805346034918662572406407604380845959862074904348138143744"}, + {"0x1.d2a1be4048f91p+1009", 309, "10000000000000000610699776480364506904213085704515863812719128770699145421501541054461895603243770556638739353307444575741831722668719553462632031991253638597235713480763688482477422747721569639692426738805257643176588867453119191870248852943967318023641486852283274009874954768880653247303478097127407616"}, + {"0x1.23a516e82d9bap+1013", 309, "99999999999999993925355250553646218600402872201173249531907715713232045630132339028433092574405077484368561180561621725787171937426360305302357988408668827749873014416820110410677102531624409058437198025485515990766396825508218326595491122696079498053460349186625724064076043808459598620749043481381437440"}, + {"0x1.23a516e82d9bbp+1013", 309, "100000000000000013415983273353644379307167647951549871284361430903247099365945253454330474107257282415598692944582140176397004400243696672220697718814856920905847607042126949473232502444570468800016509005592812696365583783944976073966686973485829389546187580124556949719553650017014692784406223465209659392"}, + {"0x1.6c8e5ca239028p+1016", 309, "999999999999999861291040414336469543176969619010226008309262296372260241358071732580741399612641955118765084749534143455432389522994257585350220962461935904874831773666973747856549425664459851618054736334425973085267220421335152276470127823801795414563694568114532338018850013250375609552861714878501486592"}, + {"0x1.6c8e5ca239029p+1016", 309, "1000000000000000017216064596736454828831087825013238982328892017892380671244575047987920451875459594568606138861698291060311049225532948520696938805711440650122628514669428460356992624968028329550689224175284346730060716088829214255439694630119794546505512415617982143262670862918816362862119154749127262208"}, + {"0x1.c7b1f3cac7433p+1019", 309, "9999999999999999860310597602564577717002641838126363875249660735883565852672743849064846414228960666786379280392654615393353172850252103336275952370615397010730691664689375178569039851073146339641623266071126720011020169553304018596457812688561947201171488461172921822139066929851282122002676667750021070848"}, + {"0x1.c7b1f3cac7434p+1019", 309, "10000000000000001107710791061764460002235587486150467667406698508044529291764770372322278832331501782385107713289967796232382450470561630819049695116611434972713065592709012878572585445501694163102699168797993709169368134893256514428214347139105940256706031241200520264089633727198808148476736186715027275776"}, + {"0x1.1ccf385ebc89fp+1023", 309, "99999999999999981139503267596847425176765179308926185662298078548582170379439067165044410288854031049481594743364161622187121841818187648603927125262209438639553681654618823985640760188731793867961170022535129351893330180773705244319986644578003569234231285691342840034082734135647456849389933411990123839488"}, + {"0x1.1ccf385ebc8a0p+1023", 309, "100000000000000001097906362944045541740492309677311846336810682903157585404911491537163328978494688899061249669721172515611590283743140088328307009198146046031271664502933027185697489699588559043338384466165001178426897626212945177628091195786707458122783970171784415105291802893207873272974885715430223118336"}, + {"0x1.fffffffffffffp+1023", 309, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368"}, +] of _ diff --git a/spec/std/http/server/server_spec.cr b/spec/std/http/server/server_spec.cr index e5aa0ec261a7..f5a82a514e0b 100644 --- a/spec/std/http/server/server_spec.cr +++ b/spec/std/http/server/server_spec.cr @@ -45,12 +45,9 @@ describe HTTP::Server do server = HTTP::Server.new { } server.bind_unused_port - spawn do + run_server(server) do server.close - sleep 0.001 end - - server.listen end it "closes the server" do diff --git a/spec/std/http/spec_helper.cr b/spec/std/http/spec_helper.cr index 410e211e4dbe..18ec9e0bab46 100644 --- a/spec/std/http/spec_helper.cr +++ b/spec/std/http/spec_helper.cr @@ -46,6 +46,11 @@ def run_server(server, &) wait_for { server.listening? } wait_until_blocked f + {% if flag?(:preview_mt) %} + # avoids fiber synchronization issues in specs, like closing the server + # before we properly listen, ... + sleep 0.001 + {% end %} yield server_done ensure server.close unless server.closed? diff --git a/spec/std/humanize_spec.cr b/spec/std/humanize_spec.cr index 841fde6cb2ba..c909417aca36 100644 --- a/spec/std/humanize_spec.cr +++ b/spec/std/humanize_spec.cr @@ -99,6 +99,14 @@ describe Number do assert_prints 1.9999998.format, "1.9999998" assert_prints 1111111.999999998.format, "1,111,111.999999998" end + + it "does not perform double rounding when decimal places are given" do + assert_prints 1.2345.format(decimal_places: 24), "1.234499999999999930722083" + assert_prints 1.2345.format(decimal_places: 65), "1.23449999999999993072208326339023187756538391113281250000000000000" + assert_prints 1.2345.format(decimal_places: 71), "1.23449999999999993072208326339023187756538391113281250000000000000000000" + assert_prints 1.2345.format(decimal_places: 83), "1.23449999999999993072208326339023187756538391113281250000000000000000000000000000000" + assert_prints 1.2345.format(decimal_places: 99), "1.234499999999999930722083263390231877565383911132812500000000000000000000000000000000000000000000000" + end end describe "#humanize" do diff --git a/spec/std/io/io_spec.cr b/spec/std/io/io_spec.cr index e2c065ecebf0..2c53df75205e 100644 --- a/spec/std/io/io_spec.cr +++ b/spec/std/io/io_spec.cr @@ -1013,4 +1013,14 @@ describe IO do typeof(STDIN.cooked!) typeof(STDIN.raw { }) typeof(STDIN.raw!) + + describe IO::Error do + describe ".new" do + it "accepts `cause` argument (#14241)" do + cause = Exception.new("cause") + error = IO::Error.new("foo", cause: cause) + error.cause.should be cause + end + end + end end diff --git a/spec/std/io/memory_spec.cr b/spec/std/io/memory_spec.cr index 37ff01e3421d..7d51c09483ed 100644 --- a/spec/std/io/memory_spec.cr +++ b/spec/std/io/memory_spec.cr @@ -18,6 +18,17 @@ describe IO::Memory do io.gets_to_end.should eq(s) end + it "write raises EOFError" do + io = IO::Memory.new + initial_capacity = io.@capacity + expect_raises(IO::EOFError) do + io.write Slice.new(Pointer(UInt8).null, Int32::MAX) + end + # nothing get's written + io.bytesize.should eq 0 + io.@capacity.should eq initial_capacity + end + it "reads byte" do io = IO::Memory.new("abc") io.read_byte.should eq('a'.ord) @@ -494,4 +505,26 @@ describe IO::Memory do end end {% end %} + + it "allocates for > 1 GB", tags: %w[slow] do + io = IO::Memory.new + mbstring = "a" * 1024 * 1024 + 1024.times { io << mbstring } + + io.bytesize.should eq(1 << 30) + io.@capacity.should eq 1 << 30 + + io << mbstring + + io.bytesize.should eq (1 << 30) + (1 << 20) + io.@capacity.should eq Int32::MAX + + 1022.times { io << mbstring } + + io.write mbstring.to_slice[0..-4] + io << "a" + expect_raises(IO::EOFError) do + io << "a" + end + end end diff --git a/spec/std/log/env_config_spec.cr b/spec/std/log/env_config_spec.cr index 7bfdfb0f239a..5ddc2941b82a 100644 --- a/spec/std/log/env_config_spec.cr +++ b/spec/std/log/env_config_spec.cr @@ -10,7 +10,7 @@ end describe "Log.setup_from_env" do after_all do # Setup logging in specs (again) since these specs perform Log.setup - Spec.log_setup + Spec.cli.log_setup end describe "backend" do diff --git a/spec/std/object_spec.cr b/spec/std/object_spec.cr index 3df134513ae2..43d1c009a19e 100644 --- a/spec/std/object_spec.cr +++ b/spec/std/object_spec.cr @@ -11,6 +11,8 @@ private class StringWrapper end end +private EQ_OPERATORS = %w(<= >= == != []= ===) + private class TestObject getter getter1 getter getter2 : Int32 @@ -113,6 +115,19 @@ private class TestObject {key, value} end + # NOTE: these methods are a syntax error in older versions + {% if compare_versions(Crystal::VERSION, "1.12.0-dev") >= 0 %} + {% for op in EQ_OPERATORS %} + def {{ op.id }}(*args, **opts) + [args, opts] + end + + def {{ op.id }}(*args, **opts, &) + [args, opts, yield] + end + {% end %} + {% end %} + annotation TestAnnotation end @@ -130,7 +145,10 @@ end private class DelegatedTestObject delegate :property1=, to: @test_object - delegate :[]=, to: @test_object + + {% for op in EQ_OPERATORS %} + delegate {{ op.id.symbolize }}, to: @test_object + {% end %} def initialize(@test_object : TestObject) end @@ -206,6 +224,22 @@ describe Object do delegated = DelegatedTestObject.new(test_object) (delegated["foo"] = "bar").should eq({"foo", "bar"}) end + + {% if compare_versions(Crystal::VERSION, "1.12.0-dev") >= 0 %} + {% for op in EQ_OPERATORS %} + it "forwards \#{{ op.id }} with multiple parameters" do + test_object = TestObject.new + delegated = DelegatedTestObject.new(test_object) + delegated.{{ op.id }}(1, 2, a: 3, b: 4).should eq [{1, 2}, {a: 3, b: 4}] + end + + it "forwards \#{{ op.id }} with multiple parameters and block parameter" do + test_object = TestObject.new + delegated = DelegatedTestObject.new(test_object) + delegated.{{ op.id }}(1, 2, a: 3, b: 4) { 5 }.should eq [{1, 2}, {a: 3, b: 4}, 5] + end + {% end %} + {% end %} end describe "getter" do diff --git a/spec/std/openssl/ssl/socket_spec.cr b/spec/std/openssl/ssl/socket_spec.cr index ccf1046b6949..bbc5b11e4b9b 100644 --- a/spec/std/openssl/ssl/socket_spec.cr +++ b/spec/std/openssl/ssl/socket_spec.cr @@ -160,20 +160,26 @@ describe OpenSSL::SSL::Socket do server_context, client_context = ssl_context_pair server_context.disable_session_resume_tickets # avoid Broken pipe - server_finished_reading = Channel(String).new + server_finished_reading = Channel(String | Exception).new spawn do OpenSSL::SSL::Server.open(tcp_server, server_context, sync_close: true) do |server| server_socket = server.accept received = server_socket.gets_to_end # interprets underlying socket close as a graceful EOF server_finished_reading.send(received) end + rescue exc + server_finished_reading.send exc end + socket = TCPSocket.new(tcp_server.local_address.address, tcp_server.local_address.port) socket_ssl = OpenSSL::SSL::Socket::Client.new(socket, client_context, hostname: "example.com", sync_close: true) socket_ssl.print "hello" socket_ssl.flush # needed today see #5375 socket.close # close underlying socket without gracefully shutting down SSL at all server_received = server_finished_reading.receive + if server_received.is_a?(Exception) + raise server_received + end server_received.should eq("hello") end end diff --git a/spec/std/process_spec.cr b/spec/std/process_spec.cr index 94b8ec18a915..9734ec5ea99c 100644 --- a/spec/std/process_spec.cr +++ b/spec/std/process_spec.cr @@ -3,6 +3,7 @@ require "spec" require "process" require "./spec_helper" +require "../support/env" private def exit_code_command(code) {% if flag?(:win32) %} @@ -267,68 +268,62 @@ describe Process do end it "deletes existing environment variable" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"FOO" => nil}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"FOO" => nil}) do |proc| + proc.output.gets_to_end + end + value.should_not match /(*ANYCRLF)^FOO=/m end - value.should_not match /(*ANYCRLF)^FOO=/m - ensure - ENV.delete("FOO") end {% if flag?(:win32) %} it "deletes existing environment variable case-insensitive" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"foo" => nil}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"foo" => nil}) do |proc| + proc.output.gets_to_end + end + value.should_not match /(*ANYCRLF)^FOO=/mi end - value.should_not match /(*ANYCRLF)^FOO=/mi - ensure - ENV.delete("FOO") end {% end %} it "preserves existing environment variable" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command) do |proc| + proc.output.gets_to_end + end + value.should match /(*ANYCRLF)^FOO=bar$/m end - value.should match /(*ANYCRLF)^FOO=bar$/m - ensure - ENV.delete("FOO") end it "preserves and sets an environment variable" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"FOO2" => "bar2"}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"FOO2" => "bar2"}) do |proc| + proc.output.gets_to_end + end + value.should match /(*ANYCRLF)^FOO=bar$/m + value.should match /(*ANYCRLF)^FOO2=bar2$/m end - value.should match /(*ANYCRLF)^FOO=bar$/m - value.should match /(*ANYCRLF)^FOO2=bar2$/m - ensure - ENV.delete("FOO") end it "overrides existing environment variable" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"FOO" => "different"}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"FOO" => "different"}) do |proc| + proc.output.gets_to_end + end + value.should match /(*ANYCRLF)^FOO=different$/m end - value.should match /(*ANYCRLF)^FOO=different$/m - ensure - ENV.delete("FOO") end {% if flag?(:win32) %} it "overrides existing environment variable case-insensitive" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"fOo" => "different"}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"fOo" => "different"}) do |proc| + proc.output.gets_to_end + end + value.should_not match /(*ANYCRLF)^FOO=/m + value.should match /(*ANYCRLF)^fOo=different$/m end - value.should_not match /(*ANYCRLF)^FOO=/m - value.should match /(*ANYCRLF)^fOo=different$/m - ensure - ENV.delete("FOO") end {% end %} end diff --git a/spec/std/signal_spec.cr b/spec/std/signal_spec.cr index e92b74a6370c..d1d3aa3f1643 100644 --- a/spec/std/signal_spec.cr +++ b/spec/std/signal_spec.cr @@ -29,6 +29,8 @@ describe "Signal" do sleep 0.1 end ran.should be_true + ensure + Signal::USR1.reset end it "ignores a signal" do @@ -36,6 +38,26 @@ describe "Signal" do Process.signal Signal::USR2, Process.pid end + it "allows chaining of signals" do + ran_first = false + ran_second = false + + Signal::USR1.trap { ran_first = true } + existing = Signal::USR1.trap_handler? + + Signal::USR1.trap do |signal| + existing.try &.call(signal) + ran_second = true + end + + Process.signal Signal::USR1, Process.pid + sleep 0.1 + ran_first.should be_true + ran_second.should be_true + ensure + Signal::USR1.reset + end + it "CHLD.reset sets default Crystal child handler" do Signal::CHLD.reset child = Process.new("true", shell: true) diff --git a/spec/std/sprintf_spec.cr b/spec/std/sprintf_spec.cr index f37384d3a70c..67cc1ac1604c 100644 --- a/spec/std/sprintf_spec.cr +++ b/spec/std/sprintf_spec.cr @@ -378,597 +378,802 @@ describe "::sprintf" do assert_sprintf "1\u{0}%i\u{0}3", 2, "1\u00002\u00003" end - describe "floats" do - context "fixed format" do - it "works" do - assert_sprintf "%f", 123, "123.000000" - - assert_sprintf "%12f", 123.45, " 123.450000" - assert_sprintf "%-12f", 123.45, "123.450000 " - assert_sprintf "% f", 123.45, " 123.450000" - assert_sprintf "%+f", 123, "+123.000000" - assert_sprintf "%012f", 123, "00123.000000" - assert_sprintf "%.f", 1234.56, "1235" - assert_sprintf "%.2f", 1234.5678, "1234.57" - assert_sprintf "%10.2f", 1234.5678, " 1234.57" - assert_sprintf "%*.2f", [10, 1234.5678], " 1234.57" - assert_sprintf "%*.*f", [10, 2, 1234.5678], " 1234.57" - assert_sprintf "%.2f", 2.536_f32, "2.54" - assert_sprintf "%+0*.*f", [10, 2, 2.536_f32], "+000002.54" - assert_sprintf "%#.0f", 1234.56, "1235." - assert_sprintf "%#.1f", 1234.56, "1234.6" - - expect_raises(ArgumentError, "Expected dynamic value '*' to be an Int - \"not a number\" (String)") do - sprintf("%*f", ["not a number", 2.536_f32]) + if String::Formatter::HAS_RYU_PRINTF + describe "floats" do + context "fixed format" do + it "works" do + assert_sprintf "%f", 123, "123.000000" + + assert_sprintf "%12f", 123.45, " 123.450000" + assert_sprintf "%-12f", 123.45, "123.450000 " + assert_sprintf "% f", 123.45, " 123.450000" + assert_sprintf "%+f", 123, "+123.000000" + assert_sprintf "%012f", 123, "00123.000000" + assert_sprintf "%.f", 1234.56, "1235" + assert_sprintf "%.2f", 1234.5678, "1234.57" + assert_sprintf "%10.2f", 1234.5678, " 1234.57" + assert_sprintf "%*.2f", [10, 1234.5678], " 1234.57" + assert_sprintf "%*.*f", [10, 2, 1234.5678], " 1234.57" + assert_sprintf "%.2f", 2.536_f32, "2.54" + assert_sprintf "%+0*.*f", [10, 2, 2.536_f32], "+000002.54" + assert_sprintf "%#.0f", 1234.56, "1235." + assert_sprintf "%#.1f", 1234.56, "1234.6" + + expect_raises(ArgumentError, "Expected dynamic value '*' to be an Int - \"not a number\" (String)") do + sprintf("%*f", ["not a number", 2.536_f32]) + end + + assert_sprintf "%12.2f %12.2f %6.2f %.2f", [2.0, 3.0, 4.0, 5.0], " 2.00 3.00 4.00 5.00" + + assert_sprintf "%f", 1e15, "1000000000000000.000000" end - - assert_sprintf "%12.2f %12.2f %6.2f %.2f", [2.0, 3.0, 4.0, 5.0], " 2.00 3.00 4.00 5.00" - - assert_sprintf "%f", 1e15, "1000000000000000.000000" end - end - context "scientific format" do - it "works" do - assert_sprintf "%e", 123.45, "1.234500e+2" - assert_sprintf "%E", 123.45, "1.234500E+2" - - assert_sprintf "%e", Float64::MAX, "1.797693e+308" - assert_sprintf "%e", Float64::MIN_POSITIVE, "2.225074e-308" - assert_sprintf "%e", Float64::MIN_SUBNORMAL, "4.940656e-324" - assert_sprintf "%e", 0.0, "0.000000e+0" - assert_sprintf "%e", -0.0, "-0.000000e+0" - assert_sprintf "%e", -Float64::MIN_SUBNORMAL, "-4.940656e-324" - assert_sprintf "%e", -Float64::MIN_POSITIVE, "-2.225074e-308" - assert_sprintf "%e", Float64::MIN, "-1.797693e+308" - end + context "scientific format" do + it "works" do + assert_sprintf "%e", 123.45, "1.234500e+2" + assert_sprintf "%E", 123.45, "1.234500E+2" + + assert_sprintf "%e", Float64::MAX, "1.797693e+308" + assert_sprintf "%e", Float64::MIN_POSITIVE, "2.225074e-308" + assert_sprintf "%e", Float64::MIN_SUBNORMAL, "4.940656e-324" + assert_sprintf "%e", 0.0, "0.000000e+0" + assert_sprintf "%e", -0.0, "-0.000000e+0" + assert_sprintf "%e", -Float64::MIN_SUBNORMAL, "-4.940656e-324" + assert_sprintf "%e", -Float64::MIN_POSITIVE, "-2.225074e-308" + assert_sprintf "%e", Float64::MIN, "-1.797693e+308" + end - context "width specifier" do - it "sets the minimum length of the string" do - assert_sprintf "%20e", 123.45, " 1.234500e+2" - assert_sprintf "%20e", -123.45, " -1.234500e+2" - assert_sprintf "%+20e", 123.45, " +1.234500e+2" + context "width specifier" do + it "sets the minimum length of the string" do + assert_sprintf "%20e", 123.45, " 1.234500e+2" + assert_sprintf "%20e", -123.45, " -1.234500e+2" + assert_sprintf "%+20e", 123.45, " +1.234500e+2" - assert_sprintf "%12e", 123.45, " 1.234500e+2" - assert_sprintf "%12e", -123.45, "-1.234500e+2" - assert_sprintf "%+12e", 123.45, "+1.234500e+2" + assert_sprintf "%12e", 123.45, " 1.234500e+2" + assert_sprintf "%12e", -123.45, "-1.234500e+2" + assert_sprintf "%+12e", 123.45, "+1.234500e+2" - assert_sprintf "%11e", 123.45, "1.234500e+2" - assert_sprintf "%11e", -123.45, "-1.234500e+2" - assert_sprintf "%+11e", 123.45, "+1.234500e+2" + assert_sprintf "%11e", 123.45, "1.234500e+2" + assert_sprintf "%11e", -123.45, "-1.234500e+2" + assert_sprintf "%+11e", 123.45, "+1.234500e+2" - assert_sprintf "%2e", 123.45, "1.234500e+2" - assert_sprintf "%2e", -123.45, "-1.234500e+2" - assert_sprintf "%+2e", 123.45, "+1.234500e+2" - end + assert_sprintf "%2e", 123.45, "1.234500e+2" + assert_sprintf "%2e", -123.45, "-1.234500e+2" + assert_sprintf "%+2e", 123.45, "+1.234500e+2" + end - it "left-justifies on negative width" do - assert_sprintf "%*e", [-20, 123.45], "1.234500e+2 " + it "left-justifies on negative width" do + assert_sprintf "%*e", [-20, 123.45], "1.234500e+2 " + end end - end - context "precision specifier" do - it "sets the minimum length of the fractional part" do - assert_sprintf "%.0e", 2.0, "2e+0" - assert_sprintf "%.0e", 2.5.prev_float, "2e+0" - assert_sprintf "%.0e", 2.5, "2e+0" - assert_sprintf "%.0e", 2.5.next_float, "3e+0" - assert_sprintf "%.0e", 3.0, "3e+0" - assert_sprintf "%.0e", 3.5.prev_float, "3e+0" - assert_sprintf "%.0e", 3.5, "4e+0" - assert_sprintf "%.0e", 3.5.next_float, "4e+0" - assert_sprintf "%.0e", 4.0, "4e+0" - - assert_sprintf "%.0e", 9.5, "1e+1" - - assert_sprintf "%.100e", 1.1, "1.1000000000000000888178419700125232338905334472656250000000000000000000000000000000000000000000000000e+0" - - assert_sprintf "%.10000e", 1.0, "1.#{"0" * 10000}e+0" - - assert_sprintf "%.1000e", Float64::MIN_POSITIVE.prev_float, - "2.2250738585072008890245868760858598876504231122409594654935248025624400092282356951" \ - "787758888037591552642309780950434312085877387158357291821993020294379224223559819827" \ - "501242041788969571311791082261043971979604000454897391938079198936081525613113376149" \ - "842043271751033627391549782731594143828136275113838604094249464942286316695429105080" \ - "201815926642134996606517803095075913058719846423906068637102005108723282784678843631" \ - "944515866135041223479014792369585208321597621066375401613736583044193603714778355306" \ - "682834535634005074073040135602968046375918583163124224521599262546494300836851861719" \ - "422417646455137135420132217031370496583210154654068035397417906022589503023501937519" \ - "773030945763173210852507299305089761582519159720757232455434770912461317493580281734" \ - "466552734375000000000000000000000000000000000000000000000000000000000000000000000000" \ - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000" \ - "000000000000000000000000000000000000000000000000000000000000000000000000000000e-308" + context "precision specifier" do + it "sets the minimum length of the fractional part" do + assert_sprintf "%.0e", 2.0, "2e+0" + assert_sprintf "%.0e", 2.5.prev_float, "2e+0" + assert_sprintf "%.0e", 2.5, "2e+0" + assert_sprintf "%.0e", 2.5.next_float, "3e+0" + assert_sprintf "%.0e", 3.0, "3e+0" + assert_sprintf "%.0e", 3.5.prev_float, "3e+0" + assert_sprintf "%.0e", 3.5, "4e+0" + assert_sprintf "%.0e", 3.5.next_float, "4e+0" + assert_sprintf "%.0e", 4.0, "4e+0" + + assert_sprintf "%.0e", 9.5, "1e+1" + + assert_sprintf "%.100e", 1.1, "1.1000000000000000888178419700125232338905334472656250000000000000000000000000000000000000000000000000e+0" + + assert_sprintf "%.10000e", 1.0, "1.#{"0" * 10000}e+0" + + assert_sprintf "%.1000e", Float64::MIN_POSITIVE.prev_float, + "2.2250738585072008890245868760858598876504231122409594654935248025624400092282356951" \ + "787758888037591552642309780950434312085877387158357291821993020294379224223559819827" \ + "501242041788969571311791082261043971979604000454897391938079198936081525613113376149" \ + "842043271751033627391549782731594143828136275113838604094249464942286316695429105080" \ + "201815926642134996606517803095075913058719846423906068637102005108723282784678843631" \ + "944515866135041223479014792369585208321597621066375401613736583044193603714778355306" \ + "682834535634005074073040135602968046375918583163124224521599262546494300836851861719" \ + "422417646455137135420132217031370496583210154654068035397417906022589503023501937519" \ + "773030945763173210852507299305089761582519159720757232455434770912461317493580281734" \ + "466552734375000000000000000000000000000000000000000000000000000000000000000000000000" \ + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000" \ + "000000000000000000000000000000000000000000000000000000000000000000000000000000e-308" + end + + it "can be used with width" do + assert_sprintf "%20.12e", 123.45, " 1.234500000000e+2" + assert_sprintf "%20.12e", -123.45, " -1.234500000000e+2" + assert_sprintf "%20.12e", 0.0, " 0.000000000000e+0" + + assert_sprintf "%-20.12e", 123.45, "1.234500000000e+2 " + assert_sprintf "%-20.12e", -123.45, "-1.234500000000e+2 " + assert_sprintf "%-20.12e", 0.0, "0.000000000000e+0 " + + assert_sprintf "%8.12e", 123.45, "1.234500000000e+2" + assert_sprintf "%8.12e", -123.45, "-1.234500000000e+2" + assert_sprintf "%8.12e", 0.0, "0.000000000000e+0" + end + + it "is ignored if precision argument is negative" do + assert_sprintf "%.*e", [-2, 123.45], "1.234500e+2" + end end - it "can be used with width" do - assert_sprintf "%20.12e", 123.45, " 1.234500000000e+2" - assert_sprintf "%20.12e", -123.45, " -1.234500000000e+2" - assert_sprintf "%20.12e", 0.0, " 0.000000000000e+0" - - assert_sprintf "%-20.12e", 123.45, "1.234500000000e+2 " - assert_sprintf "%-20.12e", -123.45, "-1.234500000000e+2 " - assert_sprintf "%-20.12e", 0.0, "0.000000000000e+0 " - - assert_sprintf "%8.12e", 123.45, "1.234500000000e+2" - assert_sprintf "%8.12e", -123.45, "-1.234500000000e+2" - assert_sprintf "%8.12e", 0.0, "0.000000000000e+0" + context "sharp flag" do + it "prints a decimal point even if no digits follow" do + assert_sprintf "%#.0e", 1.0, "1.e+0" + assert_sprintf "%#.0e", 10000.0, "1.e+4" + assert_sprintf "%#.0e", 1.0e+23, "1.e+23" + assert_sprintf "%#.0e", 1.0e-100, "1.e-100" + assert_sprintf "%#.0e", 0.0, "0.e+0" + assert_sprintf "%#.0e", -0.0, "-0.e+0" + end end - it "is ignored if precision argument is negative" do - assert_sprintf "%.*e", [-2, 123.45], "1.234500e+2" + context "plus flag" do + it "writes a plus sign for positive values" do + assert_sprintf "%+e", 123.45, "+1.234500e+2" + assert_sprintf "%+e", -123.45, "-1.234500e+2" + assert_sprintf "%+e", 0.0, "+0.000000e+0" + end + + it "writes plus sign after left space-padding" do + assert_sprintf "%+20e", 123.45, " +1.234500e+2" + assert_sprintf "%+20e", -123.45, " -1.234500e+2" + assert_sprintf "%+20e", 0.0, " +0.000000e+0" + end + + it "writes plus sign before left zero-padding" do + assert_sprintf "%+020e", 123.45, "+000000001.234500e+2" + assert_sprintf "%+020e", -123.45, "-000000001.234500e+2" + assert_sprintf "%+020e", 0.0, "+000000000.000000e+0" + end end - end - context "sharp flag" do - it "prints a decimal point even if no digits follow" do - assert_sprintf "%#.0e", 1.0, "1.e+0" - assert_sprintf "%#.0e", 10000.0, "1.e+4" - assert_sprintf "%#.0e", 1.0e+23, "1.e+23" - assert_sprintf "%#.0e", 1.0e-100, "1.e-100" - assert_sprintf "%#.0e", 0.0, "0.e+0" - assert_sprintf "%#.0e", -0.0, "-0.e+0" + context "space flag" do + it "writes a space for positive values" do + assert_sprintf "% e", 123.45, " 1.234500e+2" + assert_sprintf "% e", -123.45, "-1.234500e+2" + assert_sprintf "% e", 0.0, " 0.000000e+0" + end + + it "writes space before left space-padding" do + assert_sprintf "% 20e", 123.45, " 1.234500e+2" + assert_sprintf "% 20e", -123.45, " -1.234500e+2" + assert_sprintf "% 20e", 0.0, " 0.000000e+0" + + assert_sprintf "% 020e", 123.45, " 000000001.234500e+2" + assert_sprintf "% 020e", -123.45, "-000000001.234500e+2" + assert_sprintf "% 020e", 0.0, " 000000000.000000e+0" + end + + it "is ignored if plus flag is also specified" do + assert_sprintf "% +e", 123.45, "+1.234500e+2" + assert_sprintf "%+ e", -123.45, "-1.234500e+2" + end end - end - context "plus flag" do - it "writes a plus sign for positive values" do - assert_sprintf "%+e", 123.45, "+1.234500e+2" - assert_sprintf "%+e", -123.45, "-1.234500e+2" - assert_sprintf "%+e", 0.0, "+0.000000e+0" + context "zero flag" do + it "left-pads the result with zeros" do + assert_sprintf "%020e", 123.45, "0000000001.234500e+2" + assert_sprintf "%020e", -123.45, "-000000001.234500e+2" + assert_sprintf "%020e", 0.0, "0000000000.000000e+0" + end + + it "is ignored if string is left-justified" do + assert_sprintf "%-020e", 123.45, "1.234500e+2 " + assert_sprintf "%-020e", -123.45, "-1.234500e+2 " + assert_sprintf "%-020e", 0.0, "0.000000e+0 " + end + + it "can be used with precision" do + assert_sprintf "%020.12e", 123.45, "0001.234500000000e+2" + assert_sprintf "%020.12e", -123.45, "-001.234500000000e+2" + assert_sprintf "%020.12e", 0.0, "0000.000000000000e+0" + end end - it "writes plus sign after left space-padding" do - assert_sprintf "%+20e", 123.45, " +1.234500e+2" - assert_sprintf "%+20e", -123.45, " -1.234500e+2" - assert_sprintf "%+20e", 0.0, " +0.000000e+0" - end - - it "writes plus sign before left zero-padding" do - assert_sprintf "%+020e", 123.45, "+000000001.234500e+2" - assert_sprintf "%+020e", -123.45, "-000000001.234500e+2" - assert_sprintf "%+020e", 0.0, "+000000000.000000e+0" + context "minus flag" do + it "left-justifies the string" do + assert_sprintf "%-20e", 123.45, "1.234500e+2 " + assert_sprintf "%-20e", -123.45, "-1.234500e+2 " + assert_sprintf "%-20e", 0.0, "0.000000e+0 " + end end end - context "space flag" do - it "writes a space for positive values" do - assert_sprintf "% e", 123.45, " 1.234500e+2" - assert_sprintf "% e", -123.45, "-1.234500e+2" - assert_sprintf "% e", 0.0, " 0.000000e+0" + context "general format" do + it "works" do + assert_sprintf "%g", 123.45, "123.45" + assert_sprintf "%G", 123.45, "123.45" + + assert_sprintf "%g", 1.2345e-5, "1.2345e-5" + assert_sprintf "%G", 1.2345e-5, "1.2345E-5" + + assert_sprintf "%g", 1.2345e+25, "1.2345e+25" + assert_sprintf "%G", 1.2345e+25, "1.2345E+25" + + assert_sprintf "%g", Float64::MAX, "1.79769e+308" + assert_sprintf "%g", Float64::MIN_POSITIVE, "2.22507e-308" + assert_sprintf "%g", Float64::MIN_SUBNORMAL, "4.94066e-324" + assert_sprintf "%g", 0.0, "0" + assert_sprintf "%g", -0.0, "-0" + assert_sprintf "%g", -Float64::MIN_SUBNORMAL, "-4.94066e-324" + assert_sprintf "%g", -Float64::MIN_POSITIVE, "-2.22507e-308" + assert_sprintf "%g", Float64::MIN, "-1.79769e+308" end - it "writes space before left space-padding" do - assert_sprintf "% 20e", 123.45, " 1.234500e+2" - assert_sprintf "% 20e", -123.45, " -1.234500e+2" - assert_sprintf "% 20e", 0.0, " 0.000000e+0" + context "width specifier" do + it "sets the minimum length of the string" do + assert_sprintf "%10g", 123.45, " 123.45" + assert_sprintf "%10g", -123.45, " -123.45" + assert_sprintf "%+10g", 123.45, " +123.45" - assert_sprintf "% 020e", 123.45, " 000000001.234500e+2" - assert_sprintf "% 020e", -123.45, "-000000001.234500e+2" - assert_sprintf "% 020e", 0.0, " 000000000.000000e+0" - end - - it "is ignored if plus flag is also specified" do - assert_sprintf "% +e", 123.45, "+1.234500e+2" - assert_sprintf "%+ e", -123.45, "-1.234500e+2" - end - end + assert_sprintf "%7g", 123.45, " 123.45" + assert_sprintf "%7g", -123.45, "-123.45" + assert_sprintf "%+7g", 123.45, "+123.45" - context "zero flag" do - it "left-pads the result with zeros" do - assert_sprintf "%020e", 123.45, "0000000001.234500e+2" - assert_sprintf "%020e", -123.45, "-000000001.234500e+2" - assert_sprintf "%020e", 0.0, "0000000000.000000e+0" - end + assert_sprintf "%6g", 123.45, "123.45" + assert_sprintf "%6g", -123.45, "-123.45" + assert_sprintf "%+6g", 123.45, "+123.45" - it "is ignored if string is left-justified" do - assert_sprintf "%-020e", 123.45, "1.234500e+2 " - assert_sprintf "%-020e", -123.45, "-1.234500e+2 " - assert_sprintf "%-020e", 0.0, "0.000000e+0 " - end + assert_sprintf "%2g", 123.45, "123.45" + assert_sprintf "%2g", -123.45, "-123.45" + assert_sprintf "%+2g", 123.45, "+123.45" + end - it "can be used with precision" do - assert_sprintf "%020.12e", 123.45, "0001.234500000000e+2" - assert_sprintf "%020.12e", -123.45, "-001.234500000000e+2" - assert_sprintf "%020.12e", 0.0, "0000.000000000000e+0" + it "left-justifies on negative width" do + assert_sprintf "%*g", [-10, 123.45], "123.45 " + end end - end - context "minus flag" do - it "left-justifies the string" do - assert_sprintf "%-20e", 123.45, "1.234500e+2 " - assert_sprintf "%-20e", -123.45, "-1.234500e+2 " - assert_sprintf "%-20e", 0.0, "0.000000e+0 " + context "precision specifier" do + it "sets the precision of the value" do + assert_sprintf "%.0g", 123.45, "1e+2" + assert_sprintf "%.1g", 123.45, "1e+2" + assert_sprintf "%.2g", 123.45, "1.2e+2" + assert_sprintf "%.3g", 123.45, "123" + assert_sprintf "%.4g", 123.45, "123.5" + assert_sprintf "%.5g", 123.45, "123.45" + assert_sprintf "%.6g", 123.45, "123.45" + assert_sprintf "%.7g", 123.45, "123.45" + assert_sprintf "%.8g", 123.45, "123.45" + + assert_sprintf "%.1000g", 123.45, "123.4500000000000028421709430404007434844970703125" + + assert_sprintf "%.0g", 1.23e-45, "1e-45" + assert_sprintf "%.1g", 1.23e-45, "1e-45" + assert_sprintf "%.2g", 1.23e-45, "1.2e-45" + assert_sprintf "%.3g", 1.23e-45, "1.23e-45" + assert_sprintf "%.4g", 1.23e-45, "1.23e-45" + assert_sprintf "%.5g", 1.23e-45, "1.23e-45" + assert_sprintf "%.6g", 1.23e-45, "1.23e-45" + + assert_sprintf "%.1000g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125e-5" + end + + it "can be used with width" do + assert_sprintf "%10.1g", 123.45, " 1e+2" + assert_sprintf "%10.2g", 123.45, " 1.2e+2" + assert_sprintf "%10.3g", 123.45, " 123" + assert_sprintf "%10.4g", 123.45, " 123.5" + assert_sprintf "%10.5g", 123.45, " 123.45" + assert_sprintf "%10.1g", -123.45, " -1e+2" + assert_sprintf "%10.2g", -123.45, " -1.2e+2" + assert_sprintf "%10.3g", -123.45, " -123" + assert_sprintf "%10.4g", -123.45, " -123.5" + assert_sprintf "%10.5g", -123.45, " -123.45" + assert_sprintf "%10.5g", 0, " 0" + + assert_sprintf "%-10.1g", 123.45, "1e+2 " + assert_sprintf "%-10.2g", 123.45, "1.2e+2 " + assert_sprintf "%-10.3g", 123.45, "123 " + assert_sprintf "%-10.4g", 123.45, "123.5 " + assert_sprintf "%-10.5g", 123.45, "123.45 " + assert_sprintf "%-10.1g", -123.45, "-1e+2 " + assert_sprintf "%-10.2g", -123.45, "-1.2e+2 " + assert_sprintf "%-10.3g", -123.45, "-123 " + assert_sprintf "%-10.4g", -123.45, "-123.5 " + assert_sprintf "%-10.5g", -123.45, "-123.45 " + assert_sprintf "%-10.5g", 0, "0 " + + assert_sprintf "%3.1g", 123.45, "1e+2" + assert_sprintf "%3.2g", 123.45, "1.2e+2" + assert_sprintf "%3.3g", 123.45, "123" + assert_sprintf "%3.4g", 123.45, "123.5" + assert_sprintf "%3.5g", 123.45, "123.45" + assert_sprintf "%3.1g", -123.45, "-1e+2" + assert_sprintf "%3.2g", -123.45, "-1.2e+2" + assert_sprintf "%3.3g", -123.45, "-123" + assert_sprintf "%3.4g", -123.45, "-123.5" + assert_sprintf "%3.5g", -123.45, "-123.45" + + assert_sprintf "%1000.800g", 123.45, "#{" " * 950}123.4500000000000028421709430404007434844970703125" + end + + it "is ignored if precision argument is negative" do + assert_sprintf "%.*g", [-2, 123.45], "123.45" + end end - end - end - - context "general format" do - pending_win32 "works" do - assert_sprintf "%g", 123, "123" - assert_sprintf "%G", 12345678.45, "1.23457E+07" - assert_sprintf "%100.50g", 123.45, " 123.4500000000000028421709430404007434844970703125" - assert_sprintf "%#.12g", 12345.0, "12345.0000000" - end - end - - context "hex format" do - it "works" do - assert_sprintf "%a", 1194684.0, "0x1.23abcp+20" - assert_sprintf "%A", 1194684.0, "0X1.23ABCP+20" - assert_sprintf "%a", 12345678.45, "0x1.78c29ce666666p+23" - assert_sprintf "%A", 12345678.45, "0X1.78C29CE666666P+23" - - assert_sprintf "%a", Float64::MAX, "0x1.fffffffffffffp+1023" - assert_sprintf "%a", Float64::MIN_POSITIVE, "0x1p-1022" - assert_sprintf "%a", Float64::MIN_SUBNORMAL, "0x0.0000000000001p-1022" - assert_sprintf "%a", 0.0, "0x0p+0" - assert_sprintf "%a", -0.0, "-0x0p+0" - assert_sprintf "%a", -Float64::MIN_SUBNORMAL, "-0x0.0000000000001p-1022" - assert_sprintf "%a", -Float64::MIN_POSITIVE, "-0x1p-1022" - assert_sprintf "%a", Float64::MIN, "-0x1.fffffffffffffp+1023" - end - context "width specifier" do - it "sets the minimum length of the string" do - assert_sprintf "%20a", hexfloat("0x1p+0"), " 0x1p+0" - assert_sprintf "%20a", hexfloat("0x1.2p+0"), " 0x1.2p+0" - assert_sprintf "%20a", hexfloat("0x1.23p+0"), " 0x1.23p+0" - assert_sprintf "%20a", hexfloat("0x1.234p+0"), " 0x1.234p+0" - assert_sprintf "%20a", hexfloat("0x1.2345p+0"), " 0x1.2345p+0" - assert_sprintf "%20a", hexfloat("0x1.23456p+0"), " 0x1.23456p+0" - assert_sprintf "%20a", hexfloat("0x1.234567p+0"), " 0x1.234567p+0" - assert_sprintf "%20a", hexfloat("0x1.2345678p+0"), " 0x1.2345678p+0" - assert_sprintf "%20a", hexfloat("0x1.23456789p+0"), " 0x1.23456789p+0" - assert_sprintf "%20a", hexfloat("0x1.23456789ap+0"), " 0x1.23456789ap+0" - assert_sprintf "%20a", hexfloat("0x1.23456789abp+0"), " 0x1.23456789abp+0" - assert_sprintf "%20a", hexfloat("0x1.23456789abcp+0"), " 0x1.23456789abcp+0" - - assert_sprintf "%20a", hexfloat("-0x1p+0"), " -0x1p+0" - assert_sprintf "%20a", hexfloat("-0x1.2p+0"), " -0x1.2p+0" - assert_sprintf "%20a", hexfloat("-0x1.23p+0"), " -0x1.23p+0" - assert_sprintf "%20a", hexfloat("-0x1.234p+0"), " -0x1.234p+0" - assert_sprintf "%20a", hexfloat("-0x1.2345p+0"), " -0x1.2345p+0" - assert_sprintf "%20a", hexfloat("-0x1.23456p+0"), " -0x1.23456p+0" - assert_sprintf "%20a", hexfloat("-0x1.234567p+0"), " -0x1.234567p+0" - assert_sprintf "%20a", hexfloat("-0x1.2345678p+0"), " -0x1.2345678p+0" - assert_sprintf "%20a", hexfloat("-0x1.23456789p+0"), " -0x1.23456789p+0" - assert_sprintf "%20a", hexfloat("-0x1.23456789ap+0"), " -0x1.23456789ap+0" - assert_sprintf "%20a", hexfloat("-0x1.23456789abp+0"), " -0x1.23456789abp+0" - assert_sprintf "%20a", hexfloat("-0x1.23456789abcp+0"), " -0x1.23456789abcp+0" - - assert_sprintf "%+20a", 1194684.0, " +0x1.23abcp+20" - - assert_sprintf "%14a", 1194684.0, " 0x1.23abcp+20" - assert_sprintf "%14a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "%+14a", 1194684.0, "+0x1.23abcp+20" - - assert_sprintf "%13a", 1194684.0, "0x1.23abcp+20" - assert_sprintf "%13a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "%+13a", 1194684.0, "+0x1.23abcp+20" - - assert_sprintf "%2a", 1194684.0, "0x1.23abcp+20" - assert_sprintf "%2a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "%+2a", 1194684.0, "+0x1.23abcp+20" + context "sharp flag" do + it "prints decimal point and trailing zeros" do + assert_sprintf "%#.0g", 12345, "1.e+4" + assert_sprintf "%#.6g", 12345, "12345.0" + assert_sprintf "%#.10g", 12345, "12345.00000" + assert_sprintf "%#.100g", 12345, "12345.#{"0" * 95}" + assert_sprintf "%#.1000g", 12345, "12345.#{"0" * 995}" + + assert_sprintf "%#.0g", 1e-5, "1.e-5" + assert_sprintf "%#.6g", 1e-5, "1.00000e-5" + assert_sprintf "%#.10g", 1e-5, "1.000000000e-5" + assert_sprintf "%#.100g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125#{"0" * 35}e-5" + assert_sprintf "%#.1000g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125#{"0" * 935}e-5" + + assert_sprintf "%#15.0g", 12345, " 1.e+4" + assert_sprintf "%#15.6g", 12345, " 12345.0" + assert_sprintf "%#15.10g", 12345, " 12345.00000" + end end - it "left-justifies on negative width" do - assert_sprintf "%*a", [-20, 1194684.0], "0x1.23abcp+20 " + context "plus flag" do + it "writes a plus sign for positive values" do + assert_sprintf "%+g", 123.45, "+123.45" + assert_sprintf "%+g", -123.45, "-123.45" + assert_sprintf "%+g", 0.0, "+0" + end + + it "writes plus sign after left space-padding" do + assert_sprintf "%+10g", 123.45, " +123.45" + assert_sprintf "%+10g", -123.45, " -123.45" + assert_sprintf "%+10g", 0.0, " +0" + end + + it "writes plus sign before left zero-padding" do + assert_sprintf "%+010g", 123.45, "+000123.45" + assert_sprintf "%+010g", -123.45, "-000123.45" + assert_sprintf "%+010g", 0.0, "+000000000" + end end - end - context "precision specifier" do - it "sets the minimum length of the fractional part" do - assert_sprintf "%.0a", 0.0, "0x0p+0" - - assert_sprintf "%.0a", (Float64::MIN_POSITIVE / 2).prev_float, "0x0p-1022" - assert_sprintf "%.0a", Float64::MIN_POSITIVE / 2, "0x0p-1022" - assert_sprintf "%.0a", (Float64::MIN_POSITIVE / 2).next_float, "0x1p-1022" - assert_sprintf "%.0a", Float64::MIN_POSITIVE.prev_float, "0x1p-1022" - assert_sprintf "%.0a", Float64::MIN_POSITIVE, "0x1p-1022" - - assert_sprintf "%.0a", 0.0625, "0x1p-4" - assert_sprintf "%.0a", 0.0625.next_float, "0x1p-4" - assert_sprintf "%.0a", 0.09375.prev_float, "0x1p-4" - assert_sprintf "%.0a", 0.09375, "0x2p-4" - assert_sprintf "%.0a", 0.09375.next_float, "0x2p-4" - assert_sprintf "%.0a", 0.125.prev_float, "0x2p-4" - assert_sprintf "%.0a", 0.125, "0x1p-3" - - assert_sprintf "%.1a", 2.0, "0x1.0p+1" - assert_sprintf "%.1a", 2.0.next_float, "0x1.0p+1" - assert_sprintf "%.1a", 2.0625.prev_float, "0x1.0p+1" - assert_sprintf "%.1a", 2.0625, "0x1.0p+1" - assert_sprintf "%.1a", 2.0625.next_float, "0x1.1p+1" - assert_sprintf "%.1a", 2.125.prev_float, "0x1.1p+1" - assert_sprintf "%.1a", 2.125, "0x1.1p+1" - assert_sprintf "%.1a", 2.125.next_float, "0x1.1p+1" - assert_sprintf "%.1a", 2.1875.prev_float, "0x1.1p+1" - assert_sprintf "%.1a", 2.1875, "0x1.2p+1" - assert_sprintf "%.1a", 2.1875.next_float, "0x1.2p+1" - assert_sprintf "%.1a", 2.25.prev_float, "0x1.2p+1" - assert_sprintf "%.1a", 2.25, "0x1.2p+1" - - assert_sprintf "%.1a", 60.0, "0x1.ep+5" - assert_sprintf "%.1a", 60.0.next_float, "0x1.ep+5" - assert_sprintf "%.1a", 61.0.prev_float, "0x1.ep+5" - assert_sprintf "%.1a", 61.0, "0x1.ep+5" - assert_sprintf "%.1a", 61.0.next_float, "0x1.fp+5" - assert_sprintf "%.1a", 62.0.prev_float, "0x1.fp+5" - assert_sprintf "%.1a", 62.0, "0x1.fp+5" - assert_sprintf "%.1a", 62.0.next_float, "0x1.fp+5" - assert_sprintf "%.1a", 63.0.prev_float, "0x1.fp+5" - assert_sprintf "%.1a", 63.0, "0x2.0p+5" - assert_sprintf "%.1a", 63.0.next_float, "0x2.0p+5" - assert_sprintf "%.1a", 64.0.prev_float, "0x2.0p+5" - assert_sprintf "%.1a", 64.0, "0x1.0p+6" - - assert_sprintf "%.4a", 65536.0, "0x1.0000p+16" - assert_sprintf "%.4a", 65536.0.next_float, "0x1.0000p+16" - assert_sprintf "%.4a", 65536.5.prev_float, "0x1.0000p+16" - assert_sprintf "%.4a", 65536.5, "0x1.0000p+16" - assert_sprintf "%.4a", 65536.5.next_float, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.0.prev_float, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.0, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.0.next_float, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.5.prev_float, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.5, "0x1.0002p+16" - assert_sprintf "%.4a", 65537.5.next_float, "0x1.0002p+16" - assert_sprintf "%.4a", 65538.0.prev_float, "0x1.0002p+16" - assert_sprintf "%.4a", 65538.0, "0x1.0002p+16" - - assert_sprintf "%.4a", 131070.0, "0x1.fffep+16" - assert_sprintf "%.4a", 131070.0.next_float, "0x1.fffep+16" - assert_sprintf "%.4a", 131070.5.prev_float, "0x1.fffep+16" - assert_sprintf "%.4a", 131070.5, "0x1.fffep+16" - assert_sprintf "%.4a", 131070.5.next_float, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.0.prev_float, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.0, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.0.next_float, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.5.prev_float, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.5, "0x2.0000p+16" - assert_sprintf "%.4a", 131071.5.next_float, "0x2.0000p+16" - assert_sprintf "%.4a", 131072.0.prev_float, "0x2.0000p+16" - assert_sprintf "%.4a", 131072.0, "0x1.0000p+17" - - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x01, "0x0.000000000000p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x07, "0x0.000000000000p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x08, "0x0.000000000000p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x09, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x0f, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x10, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x11, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x17, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x18, "0x0.000000000002p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x19, "0x0.000000000002p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x1f, "0x0.000000000002p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x20, "0x0.000000000002p-1022" - - assert_sprintf "%.17a", Float64::MAX, "0x1.fffffffffffff0000p+1023" - assert_sprintf "%.16a", Float64::MAX, "0x1.fffffffffffff000p+1023" - assert_sprintf "%.15a", Float64::MAX, "0x1.fffffffffffff00p+1023" - assert_sprintf "%.14a", Float64::MAX, "0x1.fffffffffffff0p+1023" - assert_sprintf "%.13a", Float64::MAX, "0x1.fffffffffffffp+1023" - assert_sprintf "%.12a", Float64::MAX, "0x2.000000000000p+1023" - assert_sprintf "%.11a", Float64::MAX, "0x2.00000000000p+1023" - assert_sprintf "%.10a", Float64::MAX, "0x2.0000000000p+1023" - assert_sprintf "%.9a", Float64::MAX, "0x2.000000000p+1023" - assert_sprintf "%.8a", Float64::MAX, "0x2.00000000p+1023" - assert_sprintf "%.7a", Float64::MAX, "0x2.0000000p+1023" - assert_sprintf "%.6a", Float64::MAX, "0x2.000000p+1023" - assert_sprintf "%.5a", Float64::MAX, "0x2.00000p+1023" - assert_sprintf "%.4a", Float64::MAX, "0x2.0000p+1023" - assert_sprintf "%.3a", Float64::MAX, "0x2.000p+1023" - assert_sprintf "%.2a", Float64::MAX, "0x2.00p+1023" - assert_sprintf "%.1a", Float64::MAX, "0x2.0p+1023" - assert_sprintf "%.0a", Float64::MAX, "0x2p+1023" - - assert_sprintf "%.1000a", 1194684.0, "0x1.23abc#{"0" * 995}p+20" + context "space flag" do + it "writes a space for positive values" do + assert_sprintf "% g", 123.45, " 123.45" + assert_sprintf "% g", -123.45, "-123.45" + assert_sprintf "% g", 0.0, " 0" + end + + it "writes space before left space-padding" do + assert_sprintf "% 10g", 123.45, " 123.45" + assert_sprintf "% 10g", -123.45, " -123.45" + assert_sprintf "% 10g", 0.0, " 0" + + assert_sprintf "% 010g", 123.45, " 000123.45" + assert_sprintf "% 010g", -123.45, "-000123.45" + assert_sprintf "% 010g", 0.0, " 000000000" + end + + it "is ignored if plus flag is also specified" do + assert_sprintf "% +g", 123.45, "+123.45" + assert_sprintf "%+ g", -123.45, "-123.45" + end end - it "can be used with width" do - assert_sprintf "%20.8a", 1194684.0, " 0x1.23abc000p+20" - assert_sprintf "%20.8a", -1194684.0, " -0x1.23abc000p+20" - assert_sprintf "%20.8a", 0.0, " 0x0.00000000p+0" - - assert_sprintf "%-20.8a", 1194684.0, "0x1.23abc000p+20 " - assert_sprintf "%-20.8a", -1194684.0, "-0x1.23abc000p+20 " - assert_sprintf "%-20.8a", 0.0, "0x0.00000000p+0 " - - assert_sprintf "%4.8a", 1194684.0, "0x1.23abc000p+20" - assert_sprintf "%4.8a", -1194684.0, "-0x1.23abc000p+20" - assert_sprintf "%4.8a", 0.0, "0x0.00000000p+0" + context "zero flag" do + it "left-pads the result with zeros" do + assert_sprintf "%010g", 123.45, "0000123.45" + assert_sprintf "%010g", -123.45, "-000123.45" + assert_sprintf "%010g", 0.0, "0000000000" + end + + it "is ignored if string is left-justified" do + assert_sprintf "%-010g", 123.45, "123.45 " + assert_sprintf "%-010g", -123.45, "-123.45 " + assert_sprintf "%-010g", 0.0, "0 " + end + + it "can be used with precision" do + assert_sprintf "%010.2g", 123.45, "00001.2e+2" + assert_sprintf "%010.2g", -123.45, "-0001.2e+2" + assert_sprintf "%010.2g", 0.0, "0000000000" + end end - it "is ignored if precision argument is negative" do - assert_sprintf "%.*a", [-2, 1194684.0], "0x1.23abcp+20" - end - end + context "minus flag" do + it "left-justifies the string" do + assert_sprintf "%-10g", 123.45, "123.45 " + assert_sprintf "%-10g", -123.45, "-123.45 " + assert_sprintf "%-10g", 0.0, "0 " - context "sharp flag" do - it "prints a decimal point even if no digits follow" do - assert_sprintf "%#a", 1.0, "0x1.p+0" - assert_sprintf "%#a", Float64::MIN_POSITIVE, "0x1.p-1022" - assert_sprintf "%#a", 2.0 ** -234, "0x1.p-234" - assert_sprintf "%#a", 2.0 ** 1021, "0x1.p+1021" - assert_sprintf "%#a", 0.0, "0x0.p+0" - assert_sprintf "%#a", -0.0, "-0x0.p+0" - - assert_sprintf "%#.0a", 1.0, "0x1.p+0" - assert_sprintf "%#.0a", Float64::MIN_POSITIVE, "0x1.p-1022" - assert_sprintf "%#.0a", 2.0 ** -234, "0x1.p-234" - assert_sprintf "%#.0a", 2.0 ** 1021, "0x1.p+1021" - assert_sprintf "%#.0a", 1194684.0, "0x1.p+20" - assert_sprintf "%#.0a", 0.0, "0x0.p+0" - assert_sprintf "%#.0a", -0.0, "-0x0.p+0" + assert_sprintf "%- 10g", 123.45, " 123.45 " + assert_sprintf "%- 10g", -123.45, "-123.45 " + assert_sprintf "%- 10g", 0.0, " 0 " + end end end - context "plus flag" do - it "writes a plus sign for positive values" do - assert_sprintf "%+a", 1194684.0, "+0x1.23abcp+20" - assert_sprintf "%+a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "%+a", 0.0, "+0x0p+0" + context "hex format" do + it "works" do + assert_sprintf "%a", 1194684.0, "0x1.23abcp+20" + assert_sprintf "%A", 1194684.0, "0X1.23ABCP+20" + assert_sprintf "%a", 12345678.45, "0x1.78c29ce666666p+23" + assert_sprintf "%A", 12345678.45, "0X1.78C29CE666666P+23" + + assert_sprintf "%a", Float64::MAX, "0x1.fffffffffffffp+1023" + assert_sprintf "%a", Float64::MIN_POSITIVE, "0x1p-1022" + assert_sprintf "%a", Float64::MIN_SUBNORMAL, "0x0.0000000000001p-1022" + assert_sprintf "%a", 0.0, "0x0p+0" + assert_sprintf "%a", -0.0, "-0x0p+0" + assert_sprintf "%a", -Float64::MIN_SUBNORMAL, "-0x0.0000000000001p-1022" + assert_sprintf "%a", -Float64::MIN_POSITIVE, "-0x1p-1022" + assert_sprintf "%a", Float64::MIN, "-0x1.fffffffffffffp+1023" end - it "writes plus sign after left space-padding" do - assert_sprintf "%+20a", 1194684.0, " +0x1.23abcp+20" - assert_sprintf "%+20a", -1194684.0, " -0x1.23abcp+20" - assert_sprintf "%+20a", 0.0, " +0x0p+0" + context "width specifier" do + it "sets the minimum length of the string" do + assert_sprintf "%20a", hexfloat("0x1p+0"), " 0x1p+0" + assert_sprintf "%20a", hexfloat("0x1.2p+0"), " 0x1.2p+0" + assert_sprintf "%20a", hexfloat("0x1.23p+0"), " 0x1.23p+0" + assert_sprintf "%20a", hexfloat("0x1.234p+0"), " 0x1.234p+0" + assert_sprintf "%20a", hexfloat("0x1.2345p+0"), " 0x1.2345p+0" + assert_sprintf "%20a", hexfloat("0x1.23456p+0"), " 0x1.23456p+0" + assert_sprintf "%20a", hexfloat("0x1.234567p+0"), " 0x1.234567p+0" + assert_sprintf "%20a", hexfloat("0x1.2345678p+0"), " 0x1.2345678p+0" + assert_sprintf "%20a", hexfloat("0x1.23456789p+0"), " 0x1.23456789p+0" + assert_sprintf "%20a", hexfloat("0x1.23456789ap+0"), " 0x1.23456789ap+0" + assert_sprintf "%20a", hexfloat("0x1.23456789abp+0"), " 0x1.23456789abp+0" + assert_sprintf "%20a", hexfloat("0x1.23456789abcp+0"), " 0x1.23456789abcp+0" + + assert_sprintf "%20a", hexfloat("-0x1p+0"), " -0x1p+0" + assert_sprintf "%20a", hexfloat("-0x1.2p+0"), " -0x1.2p+0" + assert_sprintf "%20a", hexfloat("-0x1.23p+0"), " -0x1.23p+0" + assert_sprintf "%20a", hexfloat("-0x1.234p+0"), " -0x1.234p+0" + assert_sprintf "%20a", hexfloat("-0x1.2345p+0"), " -0x1.2345p+0" + assert_sprintf "%20a", hexfloat("-0x1.23456p+0"), " -0x1.23456p+0" + assert_sprintf "%20a", hexfloat("-0x1.234567p+0"), " -0x1.234567p+0" + assert_sprintf "%20a", hexfloat("-0x1.2345678p+0"), " -0x1.2345678p+0" + assert_sprintf "%20a", hexfloat("-0x1.23456789p+0"), " -0x1.23456789p+0" + assert_sprintf "%20a", hexfloat("-0x1.23456789ap+0"), " -0x1.23456789ap+0" + assert_sprintf "%20a", hexfloat("-0x1.23456789abp+0"), " -0x1.23456789abp+0" + assert_sprintf "%20a", hexfloat("-0x1.23456789abcp+0"), " -0x1.23456789abcp+0" + + assert_sprintf "%+20a", 1194684.0, " +0x1.23abcp+20" + + assert_sprintf "%14a", 1194684.0, " 0x1.23abcp+20" + assert_sprintf "%14a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "%+14a", 1194684.0, "+0x1.23abcp+20" + + assert_sprintf "%13a", 1194684.0, "0x1.23abcp+20" + assert_sprintf "%13a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "%+13a", 1194684.0, "+0x1.23abcp+20" + + assert_sprintf "%2a", 1194684.0, "0x1.23abcp+20" + assert_sprintf "%2a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "%+2a", 1194684.0, "+0x1.23abcp+20" + end + + it "left-justifies on negative width" do + assert_sprintf "%*a", [-20, 1194684.0], "0x1.23abcp+20 " + end end - it "writes plus sign before left zero-padding" do - assert_sprintf "%+020a", 1194684.0, "+0x0000001.23abcp+20" - assert_sprintf "%+020a", -1194684.0, "-0x0000001.23abcp+20" - assert_sprintf "%+020a", 0.0, "+0x00000000000000p+0" + context "precision specifier" do + it "sets the minimum length of the fractional part" do + assert_sprintf "%.0a", 0.0, "0x0p+0" + + assert_sprintf "%.0a", (Float64::MIN_POSITIVE / 2).prev_float, "0x0p-1022" + assert_sprintf "%.0a", Float64::MIN_POSITIVE / 2, "0x0p-1022" + assert_sprintf "%.0a", (Float64::MIN_POSITIVE / 2).next_float, "0x1p-1022" + assert_sprintf "%.0a", Float64::MIN_POSITIVE.prev_float, "0x1p-1022" + assert_sprintf "%.0a", Float64::MIN_POSITIVE, "0x1p-1022" + + assert_sprintf "%.0a", 0.0625, "0x1p-4" + assert_sprintf "%.0a", 0.0625.next_float, "0x1p-4" + assert_sprintf "%.0a", 0.09375.prev_float, "0x1p-4" + assert_sprintf "%.0a", 0.09375, "0x2p-4" + assert_sprintf "%.0a", 0.09375.next_float, "0x2p-4" + assert_sprintf "%.0a", 0.125.prev_float, "0x2p-4" + assert_sprintf "%.0a", 0.125, "0x1p-3" + + assert_sprintf "%.1a", 2.0, "0x1.0p+1" + assert_sprintf "%.1a", 2.0.next_float, "0x1.0p+1" + assert_sprintf "%.1a", 2.0625.prev_float, "0x1.0p+1" + assert_sprintf "%.1a", 2.0625, "0x1.0p+1" + assert_sprintf "%.1a", 2.0625.next_float, "0x1.1p+1" + assert_sprintf "%.1a", 2.125.prev_float, "0x1.1p+1" + assert_sprintf "%.1a", 2.125, "0x1.1p+1" + assert_sprintf "%.1a", 2.125.next_float, "0x1.1p+1" + assert_sprintf "%.1a", 2.1875.prev_float, "0x1.1p+1" + assert_sprintf "%.1a", 2.1875, "0x1.2p+1" + assert_sprintf "%.1a", 2.1875.next_float, "0x1.2p+1" + assert_sprintf "%.1a", 2.25.prev_float, "0x1.2p+1" + assert_sprintf "%.1a", 2.25, "0x1.2p+1" + + assert_sprintf "%.1a", 60.0, "0x1.ep+5" + assert_sprintf "%.1a", 60.0.next_float, "0x1.ep+5" + assert_sprintf "%.1a", 61.0.prev_float, "0x1.ep+5" + assert_sprintf "%.1a", 61.0, "0x1.ep+5" + assert_sprintf "%.1a", 61.0.next_float, "0x1.fp+5" + assert_sprintf "%.1a", 62.0.prev_float, "0x1.fp+5" + assert_sprintf "%.1a", 62.0, "0x1.fp+5" + assert_sprintf "%.1a", 62.0.next_float, "0x1.fp+5" + assert_sprintf "%.1a", 63.0.prev_float, "0x1.fp+5" + assert_sprintf "%.1a", 63.0, "0x2.0p+5" + assert_sprintf "%.1a", 63.0.next_float, "0x2.0p+5" + assert_sprintf "%.1a", 64.0.prev_float, "0x2.0p+5" + assert_sprintf "%.1a", 64.0, "0x1.0p+6" + + assert_sprintf "%.4a", 65536.0, "0x1.0000p+16" + assert_sprintf "%.4a", 65536.0.next_float, "0x1.0000p+16" + assert_sprintf "%.4a", 65536.5.prev_float, "0x1.0000p+16" + assert_sprintf "%.4a", 65536.5, "0x1.0000p+16" + assert_sprintf "%.4a", 65536.5.next_float, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.0.prev_float, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.0, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.0.next_float, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.5.prev_float, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.5, "0x1.0002p+16" + assert_sprintf "%.4a", 65537.5.next_float, "0x1.0002p+16" + assert_sprintf "%.4a", 65538.0.prev_float, "0x1.0002p+16" + assert_sprintf "%.4a", 65538.0, "0x1.0002p+16" + + assert_sprintf "%.4a", 131070.0, "0x1.fffep+16" + assert_sprintf "%.4a", 131070.0.next_float, "0x1.fffep+16" + assert_sprintf "%.4a", 131070.5.prev_float, "0x1.fffep+16" + assert_sprintf "%.4a", 131070.5, "0x1.fffep+16" + assert_sprintf "%.4a", 131070.5.next_float, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.0.prev_float, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.0, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.0.next_float, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.5.prev_float, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.5, "0x2.0000p+16" + assert_sprintf "%.4a", 131071.5.next_float, "0x2.0000p+16" + assert_sprintf "%.4a", 131072.0.prev_float, "0x2.0000p+16" + assert_sprintf "%.4a", 131072.0, "0x1.0000p+17" + + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x01, "0x0.000000000000p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x07, "0x0.000000000000p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x08, "0x0.000000000000p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x09, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x0f, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x10, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x11, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x17, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x18, "0x0.000000000002p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x19, "0x0.000000000002p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x1f, "0x0.000000000002p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x20, "0x0.000000000002p-1022" + + assert_sprintf "%.17a", Float64::MAX, "0x1.fffffffffffff0000p+1023" + assert_sprintf "%.16a", Float64::MAX, "0x1.fffffffffffff000p+1023" + assert_sprintf "%.15a", Float64::MAX, "0x1.fffffffffffff00p+1023" + assert_sprintf "%.14a", Float64::MAX, "0x1.fffffffffffff0p+1023" + assert_sprintf "%.13a", Float64::MAX, "0x1.fffffffffffffp+1023" + assert_sprintf "%.12a", Float64::MAX, "0x2.000000000000p+1023" + assert_sprintf "%.11a", Float64::MAX, "0x2.00000000000p+1023" + assert_sprintf "%.10a", Float64::MAX, "0x2.0000000000p+1023" + assert_sprintf "%.9a", Float64::MAX, "0x2.000000000p+1023" + assert_sprintf "%.8a", Float64::MAX, "0x2.00000000p+1023" + assert_sprintf "%.7a", Float64::MAX, "0x2.0000000p+1023" + assert_sprintf "%.6a", Float64::MAX, "0x2.000000p+1023" + assert_sprintf "%.5a", Float64::MAX, "0x2.00000p+1023" + assert_sprintf "%.4a", Float64::MAX, "0x2.0000p+1023" + assert_sprintf "%.3a", Float64::MAX, "0x2.000p+1023" + assert_sprintf "%.2a", Float64::MAX, "0x2.00p+1023" + assert_sprintf "%.1a", Float64::MAX, "0x2.0p+1023" + assert_sprintf "%.0a", Float64::MAX, "0x2p+1023" + + assert_sprintf "%.1000a", 1194684.0, "0x1.23abc#{"0" * 995}p+20" + end + + it "can be used with width" do + assert_sprintf "%20.8a", 1194684.0, " 0x1.23abc000p+20" + assert_sprintf "%20.8a", -1194684.0, " -0x1.23abc000p+20" + assert_sprintf "%20.8a", 0.0, " 0x0.00000000p+0" + + assert_sprintf "%-20.8a", 1194684.0, "0x1.23abc000p+20 " + assert_sprintf "%-20.8a", -1194684.0, "-0x1.23abc000p+20 " + assert_sprintf "%-20.8a", 0.0, "0x0.00000000p+0 " + + assert_sprintf "%4.8a", 1194684.0, "0x1.23abc000p+20" + assert_sprintf "%4.8a", -1194684.0, "-0x1.23abc000p+20" + assert_sprintf "%4.8a", 0.0, "0x0.00000000p+0" + end + + it "is ignored if precision argument is negative" do + assert_sprintf "%.*a", [-2, 1194684.0], "0x1.23abcp+20" + end end - end - context "space flag" do - it "writes a space for positive values" do - assert_sprintf "% a", 1194684.0, " 0x1.23abcp+20" - assert_sprintf "% a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "% a", 0.0, " 0x0p+0" + context "sharp flag" do + it "prints a decimal point even if no digits follow" do + assert_sprintf "%#a", 1.0, "0x1.p+0" + assert_sprintf "%#a", Float64::MIN_POSITIVE, "0x1.p-1022" + assert_sprintf "%#a", 2.0 ** -234, "0x1.p-234" + assert_sprintf "%#a", 2.0 ** 1021, "0x1.p+1021" + assert_sprintf "%#a", 0.0, "0x0.p+0" + assert_sprintf "%#a", -0.0, "-0x0.p+0" + + assert_sprintf "%#.0a", 1.0, "0x1.p+0" + assert_sprintf "%#.0a", Float64::MIN_POSITIVE, "0x1.p-1022" + assert_sprintf "%#.0a", 2.0 ** -234, "0x1.p-234" + assert_sprintf "%#.0a", 2.0 ** 1021, "0x1.p+1021" + assert_sprintf "%#.0a", 1194684.0, "0x1.p+20" + assert_sprintf "%#.0a", 0.0, "0x0.p+0" + assert_sprintf "%#.0a", -0.0, "-0x0.p+0" + end end - it "writes space before left space-padding" do - assert_sprintf "% 20a", 1194684.0, " 0x1.23abcp+20" - assert_sprintf "% 20a", -1194684.0, " -0x1.23abcp+20" - assert_sprintf "% 20a", 0.0, " 0x0p+0" - - assert_sprintf "% 020a", 1194684.0, " 0x0000001.23abcp+20" - assert_sprintf "% 020a", -1194684.0, "-0x0000001.23abcp+20" - assert_sprintf "% 020a", 0.0, " 0x00000000000000p+0" + context "plus flag" do + it "writes a plus sign for positive values" do + assert_sprintf "%+a", 1194684.0, "+0x1.23abcp+20" + assert_sprintf "%+a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "%+a", 0.0, "+0x0p+0" + end + + it "writes plus sign after left space-padding" do + assert_sprintf "%+20a", 1194684.0, " +0x1.23abcp+20" + assert_sprintf "%+20a", -1194684.0, " -0x1.23abcp+20" + assert_sprintf "%+20a", 0.0, " +0x0p+0" + end + + it "writes plus sign before left zero-padding" do + assert_sprintf "%+020a", 1194684.0, "+0x0000001.23abcp+20" + assert_sprintf "%+020a", -1194684.0, "-0x0000001.23abcp+20" + assert_sprintf "%+020a", 0.0, "+0x00000000000000p+0" + end end - it "is ignored if plus flag is also specified" do - assert_sprintf "% +a", 1194684.0, "+0x1.23abcp+20" - assert_sprintf "%+ a", -1194684.0, "-0x1.23abcp+20" - end - end - - context "zero flag" do - it "left-pads the result with zeros" do - assert_sprintf "%020a", 1194684.0, "0x00000001.23abcp+20" - assert_sprintf "%020a", -1194684.0, "-0x0000001.23abcp+20" - assert_sprintf "%020a", 0.0, "0x000000000000000p+0" + context "space flag" do + it "writes a space for positive values" do + assert_sprintf "% a", 1194684.0, " 0x1.23abcp+20" + assert_sprintf "% a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "% a", 0.0, " 0x0p+0" + end + + it "writes space before left space-padding" do + assert_sprintf "% 20a", 1194684.0, " 0x1.23abcp+20" + assert_sprintf "% 20a", -1194684.0, " -0x1.23abcp+20" + assert_sprintf "% 20a", 0.0, " 0x0p+0" + + assert_sprintf "% 020a", 1194684.0, " 0x0000001.23abcp+20" + assert_sprintf "% 020a", -1194684.0, "-0x0000001.23abcp+20" + assert_sprintf "% 020a", 0.0, " 0x00000000000000p+0" + end + + it "is ignored if plus flag is also specified" do + assert_sprintf "% +a", 1194684.0, "+0x1.23abcp+20" + assert_sprintf "%+ a", -1194684.0, "-0x1.23abcp+20" + end end - it "is ignored if string is left-justified" do - assert_sprintf "%-020a", 1194684.0, "0x1.23abcp+20 " - assert_sprintf "%-020a", -1194684.0, "-0x1.23abcp+20 " - assert_sprintf "%-020a", 0.0, "0x0p+0 " + context "zero flag" do + it "left-pads the result with zeros" do + assert_sprintf "%020a", 1194684.0, "0x00000001.23abcp+20" + assert_sprintf "%020a", -1194684.0, "-0x0000001.23abcp+20" + assert_sprintf "%020a", 0.0, "0x000000000000000p+0" + end + + it "is ignored if string is left-justified" do + assert_sprintf "%-020a", 1194684.0, "0x1.23abcp+20 " + assert_sprintf "%-020a", -1194684.0, "-0x1.23abcp+20 " + assert_sprintf "%-020a", 0.0, "0x0p+0 " + end + + it "can be used with precision" do + assert_sprintf "%020.8a", 1194684.0, "0x00001.23abc000p+20" + assert_sprintf "%020.8a", -1194684.0, "-0x0001.23abc000p+20" + assert_sprintf "%020.8a", 0.0, "0x000000.00000000p+0" + end end - it "can be used with precision" do - assert_sprintf "%020.8a", 1194684.0, "0x00001.23abc000p+20" - assert_sprintf "%020.8a", -1194684.0, "-0x0001.23abc000p+20" - assert_sprintf "%020.8a", 0.0, "0x000000.00000000p+0" + context "minus flag" do + it "left-justifies the string" do + assert_sprintf "%-20a", 1194684.0, "0x1.23abcp+20 " + assert_sprintf "%-20a", -1194684.0, "-0x1.23abcp+20 " + assert_sprintf "%-20a", 0.0, "0x0p+0 " + end end end - context "minus flag" do - it "left-justifies the string" do - assert_sprintf "%-20a", 1194684.0, "0x1.23abcp+20 " - assert_sprintf "%-20a", -1194684.0, "-0x1.23abcp+20 " - assert_sprintf "%-20a", 0.0, "0x0p+0 " + [Float32, Float64].each do |float| + it "infinities" do + pos_inf = float.new(1) / float.new(0) + neg_inf = float.new(-1) / float.new(0) + + assert_sprintf "%f", pos_inf, "inf" + assert_sprintf "%a", pos_inf, "inf" + assert_sprintf "%e", pos_inf, "inf" + assert_sprintf "%g", pos_inf, "inf" + assert_sprintf "%A", pos_inf, "INF" + assert_sprintf "%E", pos_inf, "INF" + assert_sprintf "%G", pos_inf, "INF" + + assert_sprintf "%f", neg_inf, "-inf" + assert_sprintf "%G", neg_inf, "-INF" + + assert_sprintf "%2f", pos_inf, "inf" + assert_sprintf "%4f", pos_inf, " inf" + assert_sprintf "%6f", pos_inf, " inf" + assert_sprintf "%2f", neg_inf, "-inf" + assert_sprintf "%4f", neg_inf, "-inf" + assert_sprintf "%6f", neg_inf, " -inf" + + assert_sprintf "% f", pos_inf, " inf" + assert_sprintf "% 2f", pos_inf, " inf" + assert_sprintf "% 4f", pos_inf, " inf" + assert_sprintf "% 6f", pos_inf, " inf" + assert_sprintf "% f", neg_inf, "-inf" + assert_sprintf "% 2f", neg_inf, "-inf" + assert_sprintf "% 4f", neg_inf, "-inf" + assert_sprintf "% 6f", neg_inf, " -inf" + + assert_sprintf "%+f", pos_inf, "+inf" + assert_sprintf "%+2f", pos_inf, "+inf" + assert_sprintf "%+4f", pos_inf, "+inf" + assert_sprintf "%+6f", pos_inf, " +inf" + assert_sprintf "%+f", neg_inf, "-inf" + assert_sprintf "%+2f", neg_inf, "-inf" + assert_sprintf "%+4f", neg_inf, "-inf" + assert_sprintf "%+6f", neg_inf, " -inf" + + assert_sprintf "%+ f", pos_inf, "+inf" + + assert_sprintf "%-4f", pos_inf, "inf " + assert_sprintf "%-6f", pos_inf, "inf " + assert_sprintf "%-4f", neg_inf, "-inf" + assert_sprintf "%-6f", neg_inf, "-inf " + + assert_sprintf "% -4f", pos_inf, " inf" + assert_sprintf "% -6f", pos_inf, " inf " + assert_sprintf "% -4f", neg_inf, "-inf" + assert_sprintf "% -6f", neg_inf, "-inf " + + assert_sprintf "%-+4f", pos_inf, "+inf" + assert_sprintf "%-+6f", pos_inf, "+inf " + assert_sprintf "%-+4f", neg_inf, "-inf" + assert_sprintf "%-+6f", neg_inf, "-inf " + + assert_sprintf "%-+ 6f", pos_inf, "+inf " + + assert_sprintf "%06f", pos_inf, " inf" + assert_sprintf "%-06f", pos_inf, "inf " + assert_sprintf "%06f", neg_inf, " -inf" + assert_sprintf "%-06f", neg_inf, "-inf " + + assert_sprintf "%.1f", pos_inf, "inf" + + assert_sprintf "%#f", pos_inf, "inf" end - end - end - [Float32, Float64].each do |float| - it "infinities" do - pos_inf = float.new(1) / float.new(0) - neg_inf = float.new(-1) / float.new(0) - - assert_sprintf "%f", pos_inf, "inf" - assert_sprintf "%a", pos_inf, "inf" - assert_sprintf "%e", pos_inf, "inf" - assert_sprintf "%g", pos_inf, "inf" - assert_sprintf "%A", pos_inf, "INF" - assert_sprintf "%E", pos_inf, "INF" - assert_sprintf "%G", pos_inf, "INF" - - assert_sprintf "%f", neg_inf, "-inf" - assert_sprintf "%G", neg_inf, "-INF" - - assert_sprintf "%2f", pos_inf, "inf" - assert_sprintf "%4f", pos_inf, " inf" - assert_sprintf "%6f", pos_inf, " inf" - assert_sprintf "%2f", neg_inf, "-inf" - assert_sprintf "%4f", neg_inf, "-inf" - assert_sprintf "%6f", neg_inf, " -inf" - - assert_sprintf "% f", pos_inf, " inf" - assert_sprintf "% 2f", pos_inf, " inf" - assert_sprintf "% 4f", pos_inf, " inf" - assert_sprintf "% 6f", pos_inf, " inf" - assert_sprintf "% f", neg_inf, "-inf" - assert_sprintf "% 2f", neg_inf, "-inf" - assert_sprintf "% 4f", neg_inf, "-inf" - assert_sprintf "% 6f", neg_inf, " -inf" - - assert_sprintf "%+f", pos_inf, "+inf" - assert_sprintf "%+2f", pos_inf, "+inf" - assert_sprintf "%+4f", pos_inf, "+inf" - assert_sprintf "%+6f", pos_inf, " +inf" - assert_sprintf "%+f", neg_inf, "-inf" - assert_sprintf "%+2f", neg_inf, "-inf" - assert_sprintf "%+4f", neg_inf, "-inf" - assert_sprintf "%+6f", neg_inf, " -inf" - - assert_sprintf "%+ f", pos_inf, "+inf" - - assert_sprintf "%-4f", pos_inf, "inf " - assert_sprintf "%-6f", pos_inf, "inf " - assert_sprintf "%-4f", neg_inf, "-inf" - assert_sprintf "%-6f", neg_inf, "-inf " - - assert_sprintf "% -4f", pos_inf, " inf" - assert_sprintf "% -6f", pos_inf, " inf " - assert_sprintf "% -4f", neg_inf, "-inf" - assert_sprintf "% -6f", neg_inf, "-inf " - - assert_sprintf "%-+4f", pos_inf, "+inf" - assert_sprintf "%-+6f", pos_inf, "+inf " - assert_sprintf "%-+4f", neg_inf, "-inf" - assert_sprintf "%-+6f", neg_inf, "-inf " - - assert_sprintf "%-+ 6f", pos_inf, "+inf " - - assert_sprintf "%06f", pos_inf, " inf" - assert_sprintf "%-06f", pos_inf, "inf " - assert_sprintf "%06f", neg_inf, " -inf" - assert_sprintf "%-06f", neg_inf, "-inf " - - assert_sprintf "%.1f", pos_inf, "inf" - - assert_sprintf "%#f", pos_inf, "inf" - end - - it "not-a-numbers" do - pos_nan = Math.copysign(float.new(0) / float.new(0), 1) - neg_nan = Math.copysign(float.new(0) / float.new(0), -1) - - assert_sprintf "%f", pos_nan, "nan" - assert_sprintf "%a", pos_nan, "nan" - assert_sprintf "%e", pos_nan, "nan" - assert_sprintf "%g", pos_nan, "nan" - assert_sprintf "%A", pos_nan, "NAN" - assert_sprintf "%E", pos_nan, "NAN" - assert_sprintf "%G", pos_nan, "NAN" - - assert_sprintf "%f", neg_nan, "nan" - assert_sprintf "%a", neg_nan, "nan" - assert_sprintf "%e", neg_nan, "nan" - assert_sprintf "%g", neg_nan, "nan" - assert_sprintf "%A", neg_nan, "NAN" - assert_sprintf "%E", neg_nan, "NAN" - assert_sprintf "%G", neg_nan, "NAN" - - assert_sprintf "%+f", pos_nan, "+nan" - assert_sprintf "%+f", neg_nan, "+nan" + it "not-a-numbers" do + pos_nan = Math.copysign(float.new(0) / float.new(0), 1) + neg_nan = Math.copysign(float.new(0) / float.new(0), -1) + + assert_sprintf "%f", pos_nan, "nan" + assert_sprintf "%a", pos_nan, "nan" + assert_sprintf "%e", pos_nan, "nan" + assert_sprintf "%g", pos_nan, "nan" + assert_sprintf "%A", pos_nan, "NAN" + assert_sprintf "%E", pos_nan, "NAN" + assert_sprintf "%G", pos_nan, "NAN" + + assert_sprintf "%f", neg_nan, "nan" + assert_sprintf "%a", neg_nan, "nan" + assert_sprintf "%e", neg_nan, "nan" + assert_sprintf "%g", neg_nan, "nan" + assert_sprintf "%A", neg_nan, "NAN" + assert_sprintf "%E", neg_nan, "NAN" + assert_sprintf "%G", neg_nan, "NAN" + + assert_sprintf "%+f", pos_nan, "+nan" + assert_sprintf "%+f", neg_nan, "+nan" + end end end + else + pending "floats" end context "strings" do diff --git a/spec/std/string_builder_spec.cr b/spec/std/string_builder_spec.cr index 2b5f62c6c03c..250a4b0239f2 100644 --- a/spec/std/string_builder_spec.cr +++ b/spec/std/string_builder_spec.cr @@ -40,4 +40,43 @@ describe String::Builder do str.chomp!(44).to_s.should eq("a,b,c") end end + + it "raises EOFError" do + builder = String::Builder.new + initial_capacity = builder.capacity + expect_raises(IO::EOFError) do + builder.write Slice.new(Pointer(UInt8).null, Int32::MAX) + end + # nothing get's written + builder.bytesize.should eq 0 + builder.capacity.should eq initial_capacity + end + + # FIXME(wasm32): https://github.com/crystal-lang/crystal/issues/14057 + {% if flag?(:wasm32) %} + pending "allocation for > 1 GB" + {% else %} + it "allocates for > 1 GB", tags: %w[slow] do + String::Builder.build do |str| + mbstring = "a" * 1024 * 1024 + 1023.times { str << mbstring } + + str.bytesize.should eq (1 << 30) - (1 << 20) + str.capacity.should eq 1 << 30 + + str << mbstring + + str.bytesize.should eq 1 << 30 + str.capacity.should eq Int32::MAX + + 1023.times { str << mbstring } + + str.write mbstring.to_slice[0..(-4 - String::HEADER_SIZE)] + str << "a" + expect_raises(IO::EOFError) do + str << "a" + end + end + end + {% end %} end diff --git a/spec/std/string_spec.cr b/spec/std/string_spec.cr index 0d60b3ac2466..ebebcd2c6561 100644 --- a/spec/std/string_spec.cr +++ b/spec/std/string_spec.cr @@ -1416,6 +1416,7 @@ describe "String" do it { "=".split(/\=/, 2).should eq(["", ""]) } it { "=".split(/\=/, 2, remove_empty: true).should eq([] of String) } it { ",".split(/(?:(x)|(,))/).should eq(["", ",", ""]) } + it { "ba".split(/a/, options: :anchored).should eq ["ba"] } it "keeps groups" do s = "split on the word on okay?" @@ -2322,6 +2323,10 @@ describe "String" do it "does with number and string" do "1ab4".scan(/\d+/).map(&.[0]).should eq(["1", "4"]) end + + it "options parameter" do + "ba".scan(/a/, options: :anchored).map(&.[0]).should eq [] of String + end end it "has match" do diff --git a/spec/std/thread_spec.cr b/spec/std/thread_spec.cr index 599a1968f52f..136026667137 100644 --- a/spec/std/thread_spec.cr +++ b/spec/std/thread_spec.cr @@ -49,4 +49,17 @@ describe Thread do thread.join end + + it "names the thread" do + Thread.current.name.should be_nil + name = nil + + thread = Thread.new(name: "some-name") do + name = Thread.current.name + end + thread.name.should eq("some-name") + + thread.join + name.should eq("some-name") + end end diff --git a/spec/std/time/location_spec.cr b/spec/std/time/location_spec.cr index bcf7595cffd8..78e27a230fde 100644 --- a/spec/std/time/location_spec.cr +++ b/spec/std/time/location_spec.cr @@ -67,9 +67,7 @@ class Time::Location with_zoneinfo do Location.load("UTC").should eq Location::UTC Location.load("").should eq Location::UTC - - # Etc/UTC could be pointing to anything - Location.load("Etc/UTC").should_not eq Location::UTC + Location.load("Etc/UTC").should eq Location::UTC end end diff --git a/spec/std/xml/reader_spec.cr b/spec/std/xml/reader_spec.cr index 54183dd8742d..d89593620970 100644 --- a/spec/std/xml/reader_spec.cr +++ b/spec/std/xml/reader_spec.cr @@ -359,6 +359,11 @@ module XML reader.value.should eq("2") reader.read.should be_false end + + it "raises if attribute contains null byte" do + reader = Reader.new("") + expect_raises(Exception) { reader.move_to_attribute("\0") } + end end describe "#[]" do @@ -378,6 +383,11 @@ module XML reader.read # reader["id"].should eq("1") end + + it "raises if attribute contains null byte" do + reader = Reader.new("") + expect_raises(Exception) { reader["\0"] } + end end describe "#[]?" do @@ -397,6 +407,11 @@ module XML reader.read # reader["id"]?.should eq("1") end + + it "raises if attribute contains null byte" do + reader = Reader.new("") + expect_raises(Exception) { reader["\0"]? } + end end describe "#move_to_element" do diff --git a/src/VERSION b/src/VERSION index 1f724bf455d7..381cf02417c4 100644 --- a/src/VERSION +++ b/src/VERSION @@ -1 +1 @@ -1.11.0-dev +1.12.0-dev diff --git a/src/annotations.cr b/src/annotations.cr index c906f61b9b79..929ed73533f9 100644 --- a/src/annotations.cr +++ b/src/annotations.cr @@ -27,7 +27,7 @@ end annotation Flags end -# A `lib` can be marked with `@[Link(lib : String, *, ldflags : String, framework : String, pkg_config : String)]` +# A `lib` can be marked with `@[Link(lib : String, *, ldflags : String, static : Bool, framework : String, pkg_config : String, wasm_import_module : String, dll : String)]` # to declare the library that should be linked when compiling the program. # # At least one of the *lib*, *ldflags*, *framework* arguments needs to be specified. @@ -45,6 +45,13 @@ end # # `@[Link(framework: "Cocoa")]` will pass `-framework Cocoa` to the linker. # +# `@[Link(dll: "gc.dll")]` will copy `gc.dll` to any built program. The DLL name +# must use `.dll` as its file extension and cannot contain any directory +# separators. The actual DLL is searched among `CRYSTAL_LIBRARY_PATH`, the +# compiler's own directory, and `PATH` in that order; a warning is printed if +# the DLL isn't found, although it might still run correctly if the DLLs are +# available in other DLL search paths on the system. +# # When an `-l` option is passed to the linker, it will lookup the libraries in # paths passed with the `-L` option. Any paths in `CRYSTAL_LIBRARY_PATH` are # added by default. Custom paths can be passed using `ldflags`: diff --git a/src/colorize.cr b/src/colorize.cr index 48975c8a451f..83fd82c3935e 100644 --- a/src/colorize.cr +++ b/src/colorize.cr @@ -129,8 +129,7 @@ module Colorize # "hello".colorize.red.to_s # => "hello" # ``` # - # NOTE: This is by default disabled on non-TTY devices because they likely don't support ANSI escape codes. - # This will also be disabled if the environment variable `TERM` is "dumb" or `NO_COLOR` contains any value. + # NOTE: This is by default disabled if the environment variable `NO_COLOR` contains any value. class_property? enabled : Bool { !ENV.has_key?("NO_COLOR") } # Makes `Colorize.enabled` `true` if and only if both of `STDOUT.tty?` diff --git a/src/compiler/crystal/codegen/asm.cr b/src/compiler/crystal/codegen/asm.cr index f0b3e2f088ab..107d63f19ecf 100644 --- a/src/compiler/crystal/codegen/asm.cr +++ b/src/compiler/crystal/codegen/asm.cr @@ -53,7 +53,7 @@ class Crystal::CodeGenVisitor fun_type = LLVM::Type.function(input_types, output_type) constraints = constraints.to_s - value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.can_throw?) + value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.can_throw?, node.dialect) value = LLVM::Function.from_value(value) asm_value = call LLVMTypedFunction.new(fun_type, value), input_values diff --git a/src/compiler/crystal/codegen/ast.cr b/src/compiler/crystal/codegen/ast.cr index 816958844dd9..ab4fa76d4e16 100644 --- a/src/compiler/crystal/codegen/ast.cr +++ b/src/compiler/crystal/codegen/ast.cr @@ -138,4 +138,10 @@ module Crystal found_extern end end + + class Asm + def dialect : LLVM::InlineAsmDialect + intel? ? LLVM::InlineAsmDialect::Intel : LLVM::InlineAsmDialect::ATT + end + end end diff --git a/src/compiler/crystal/codegen/codegen.cr b/src/compiler/crystal/codegen/codegen.cr index f5c35db9d65a..441f3cfa09ae 100644 --- a/src/compiler/crystal/codegen/codegen.cr +++ b/src/compiler/crystal/codegen/codegen.cr @@ -69,8 +69,10 @@ module Crystal end end - def codegen(node, single_module = false, debug = Debug::Default) - visitor = CodeGenVisitor.new self, node, single_module: single_module, debug: debug + def codegen(node, single_module = false, debug = Debug::Default, + frame_pointers = FramePointers::Auto) + visitor = CodeGenVisitor.new self, node, single_module: single_module, + debug: debug, frame_pointers: frame_pointers visitor.accept node visitor.process_finished_hooks visitor.finish @@ -190,7 +192,10 @@ module Crystal @c_malloc_fun : LLVMTypedFunction? @c_realloc_fun : LLVMTypedFunction? - def initialize(@program : Program, @node : ASTNode, @single_module : Bool = false, @debug = Debug::Default) + def initialize(@program : Program, @node : ASTNode, + @single_module : Bool = false, + @debug = Debug::Default, + @frame_pointers : FramePointers = :auto) @abi = @program.target_machine.abi @llvm_context = LLVM::Context.new # LLVM::Context.register(@llvm_context, "main") @@ -496,18 +501,22 @@ module Crystal def visit(node : Nop) @last = llvm_nil + false end def visit(node : NilLiteral) @last = llvm_nil + false end def visit(node : BoolLiteral) @last = int1(node.value ? 1 : 0) + false end def visit(node : CharLiteral) @last = int32(node.value.ord) + false end def visit(node : NumberLiteral) @@ -537,14 +546,17 @@ module Crystal in .f64? @last = float64(node.value) end + false end def visit(node : StringLiteral) @last = build_string_constant(node.value, node.value) + false end def visit(node : SymbolLiteral) @last = int(@symbols[node.value]) + false end def visit(node : TupleLiteral) @@ -1087,7 +1099,7 @@ module Crystal request_value(value) - return if value.no_returns? + return false if value.no_returns? last = @last @@ -1101,7 +1113,7 @@ module Crystal read_class_var_ptr(target) when Var # Can't assign void - return if target.type.void? + return false if target.type.void? # If assigning to a special variable in a method that yields, # assign to that variable too. @@ -1279,6 +1291,7 @@ module Crystal else node.raise "BUG: missing context var: #{node.name}" end + false end def visit(node : Global) @@ -1287,6 +1300,7 @@ module Crystal def visit(node : ClassVar) @last = read_class_var(node) + false end def visit(node : InstanceVar) @@ -1398,7 +1412,7 @@ module Crystal unless filtered_type @last = upcast llvm_nil, resulting_type, @program.nil - return + return false end non_nilable_type = node.non_nilable_type @@ -1471,12 +1485,15 @@ module Crystal def codegen_type_filter(node, &) accept node.obj - obj_type = node.obj.type - type_id = type_id @last, obj_type - filtered_type = yield(obj_type).not_nil! + if @needs_value + obj_type = node.obj.type - @last = match_type_id obj_type, filtered_type, type_id + type_id = type_id @last, obj_type + filtered_type = yield(obj_type).not_nil! + + @last = match_type_id obj_type, filtered_type, type_id + end false end @@ -1656,6 +1673,7 @@ module Crystal def visit(node : Unreachable) builder.unreachable + false end def check_proc_is_not_closure(value, type) @@ -2041,6 +2059,7 @@ module Crystal def unreachable(file = __FILE__, line = __LINE__) debug_codegen_log(file, line) { "Reached the unreachable!" } builder.unreachable + false end def allocate_aggregate(type) @@ -2234,11 +2253,11 @@ module Crystal res end - def memcpy(dest, src, len, align, volatile) + def memcpy(dest, src, len, align, volatile, *, src_align = align) res = call c_memcpy_fun, [dest, src, len, volatile] LibLLVM.set_instr_param_alignment(res, 1, align) - LibLLVM.set_instr_param_alignment(res, 2, align) + LibLLVM.set_instr_param_alignment(res, 2, src_align) res end diff --git a/src/compiler/crystal/codegen/debug.cr b/src/compiler/crystal/codegen/debug.cr index 58d139ef2b3c..72555d074bb0 100644 --- a/src/compiler/crystal/codegen/debug.cr +++ b/src/compiler/crystal/codegen/debug.cr @@ -47,14 +47,6 @@ module Crystal "CodeView", mod.context.int32.const_int(1) ) - elsif @program.has_flag?("osx") || @program.has_flag?("android") - # DebugInfo generation in LLVM by default uses a higher version of dwarf - # than OS X currently understands. Android has the same problem. - mod.add_flag( - LibLLVM::ModuleFlagBehavior::Warning, - "Dwarf Version", - mod.context.int32.const_int(2) - ) end mod.add_flag( diff --git a/src/compiler/crystal/codegen/fun.cr b/src/compiler/crystal/codegen/fun.cr index 9a8e51df3175..784eba83b9b9 100644 --- a/src/compiler/crystal/codegen/fun.cr +++ b/src/compiler/crystal/codegen/fun.cr @@ -101,9 +101,13 @@ class Crystal::CodeGenVisitor context.fun.add_attribute LLVM::Attribute::UWTable, value: @program.has_flag?("aarch64") ? LLVM::UWTableKind::Sync : LLVM::UWTableKind::Async {% end %} - if @program.has_flag?("darwin") + if @frame_pointers.always? + context.fun.add_attribute "frame-pointer", value: "all" + elsif @program.has_flag?("darwin") # Disable frame pointer elimination in Darwin, as it causes issues during stack unwind context.fun.add_target_dependent_attribute "frame-pointer", "all" + elsif @frame_pointers.non_leaf? + context.fun.add_attribute "frame-pointer", value: "non-leaf" end new_entry_block diff --git a/src/compiler/crystal/codegen/link.cr b/src/compiler/crystal/codegen/link.cr index 7ef2ab85f92c..d9910d64c7a8 100644 --- a/src/compiler/crystal/codegen/link.cr +++ b/src/compiler/crystal/codegen/link.cr @@ -5,8 +5,9 @@ module Crystal getter ldflags : String? getter framework : String? getter wasm_import_module : String? + getter dll : String? - def initialize(@lib = nil, @pkg_config = @lib, @ldflags = nil, @static = false, @framework = nil, @wasm_import_module = nil) + def initialize(@lib = nil, @pkg_config = @lib, @ldflags = nil, @static = false, @framework = nil, @wasm_import_module = nil, @dll = nil) end def static? @@ -27,6 +28,7 @@ module Crystal lib_pkg_config = nil lib_framework = nil lib_wasm_import_module = nil + lib_dll = nil count = 0 args.each do |arg| @@ -76,12 +78,21 @@ module Crystal when "wasm_import_module" named_arg.raise "'wasm_import_module' link argument must be a String" unless value.is_a?(StringLiteral) lib_wasm_import_module = value.value + when "dll" + named_arg.raise "'dll' link argument must be a String" unless value.is_a?(StringLiteral) + lib_dll = value.value + unless lib_dll.size >= 4 && lib_dll[-4..].compare(".dll", case_insensitive: true) == 0 + named_arg.raise "'dll' link argument must use a '.dll' file extension" + end + if ::Path.separators(::Path::Kind::WINDOWS).any? { |separator| lib_dll.includes?(separator) } + named_arg.raise "'dll' link argument must not include directory separators" + end else - named_arg.raise "unknown link argument: '#{named_arg.name}' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config', 'framework', and 'wasm_import_module')" + named_arg.raise "unknown link argument: '#{named_arg.name}' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config', 'framework', 'wasm_import_module', and 'dll')" end end - new(lib_name, lib_pkg_config, lib_ldflags, lib_static, lib_framework, lib_wasm_import_module) + new(lib_name, lib_pkg_config, lib_ldflags, lib_static, lib_framework, lib_wasm_import_module, lib_dll) end end @@ -221,6 +232,46 @@ module Crystal flags.join(" ") end + # Searches among CRYSTAL_LIBRARY_PATH, the compiler's directory, and PATH + # for every DLL specified in the used `@[Link]` annotations. Yields the + # absolute path and `true` if found, the base name and `false` if not found. + # The directories should match `Crystal::Repl::Context#dll_search_paths` + def each_dll_path(& : String, Bool ->) + executable_path = nil + compiler_origin = nil + paths = nil + + link_annotations.each do |ann| + next unless dll = ann.dll + + dll_path = CrystalLibraryPath.paths.each do |path| + full_path = File.join(path, dll) + break full_path if File.file?(full_path) + end + + unless dll_path + executable_path ||= Process.executable_path + compiler_origin ||= File.dirname(executable_path) if executable_path + + if compiler_origin + full_path = File.join(compiler_origin, dll) + dll_path = full_path if File.file?(full_path) + end + end + + unless dll_path + paths ||= ENV["PATH"]?.try &.split(Process::PATH_DELIMITER, remove_empty: true) + + dll_path = paths.try &.each do |path| + full_path = File.join(path, dll) + break full_path if File.file?(full_path) + end + end + + yield dll_path || dll, !dll_path.nil? + end + end + PKG_CONFIG_PATH = Process.find_executable("pkg-config") # Returns the result of running `pkg-config mod` but returns nil if diff --git a/src/compiler/crystal/codegen/llvm_typer.cr b/src/compiler/crystal/codegen/llvm_typer.cr index d20fbd59fa9a..d72a25ecd3cb 100644 --- a/src/compiler/crystal/codegen/llvm_typer.cr +++ b/src/compiler/crystal/codegen/llvm_typer.cr @@ -245,6 +245,10 @@ module Crystal llvm_type(type.remove_alias, wants_size) end + private def create_llvm_type(type : ReferenceStorageType, wants_size) + llvm_struct_type(type.reference_type, wants_size) + end + private def create_llvm_type(type : NonGenericModuleType | GenericClassType, wants_size) # This can only be reached if the module or generic class don't have implementors @llvm_context.int1 diff --git a/src/compiler/crystal/codegen/primitives.cr b/src/compiler/crystal/codegen/primitives.cr index 9ed05c0009f2..80ba7d832a41 100644 --- a/src/compiler/crystal/codegen/primitives.cr +++ b/src/compiler/crystal/codegen/primitives.cr @@ -11,6 +11,8 @@ class Crystal::CodeGenVisitor else raise "BUG: unhandled primitive in codegen visit: #{node.name}" end + + false end def codegen_primitive(call, node, target_def, call_args) diff --git a/src/compiler/crystal/codegen/unions.cr b/src/compiler/crystal/codegen/unions.cr index 1f29763d504a..bcef273a8010 100644 --- a/src/compiler/crystal/codegen/unions.cr +++ b/src/compiler/crystal/codegen/unions.cr @@ -28,20 +28,19 @@ module Crystal @structs[llvm_name] = a_struct end - max_size = 0 + max_size = 0_u64 + max_alignment = pointer_size.to_u32! + type.expand_union_types.each do |subtype| unless subtype.void? - size = size_of(llvm_type(subtype, wants_size: true)) - max_size = size if size > max_size + llvm_type = llvm_type(subtype, wants_size: true) + max_size = {size_of(llvm_type), max_size}.max + max_alignment = {align_of(llvm_type), max_alignment}.max end end - max_size /= pointer_size.to_f - max_size = max_size.ceil.to_i - - max_size = 1 if max_size == 0 - - llvm_value_type = size_t.array(max_size) + value_size = {(max_size + (max_alignment - 1)) // max_alignment, 1_u64}.max + llvm_value_type = @llvm_context.int(max_alignment * 8).array(value_size) [@llvm_context.int32, llvm_value_type] end @@ -109,23 +108,64 @@ module Crystal store type_id(@program.void), union_type_id(struct_type, union_pointer) end - def assign_distinct_union_types(target_pointer, target_type, value_type, value) + # this is needed if `union_type` and `value_type` have different alignments, + # i.e. their `#union_value`s do not have the same offsets + def store_union_in_union(union_type, union_pointer, value_type, value) + to_llvm_type = llvm_type(union_type) + from_llvm_type = llvm_type(value_type) + to_value_type = to_llvm_type.struct_element_types[1] + from_value_type = from_llvm_type.struct_element_types[1] + + store type_id(value, value_type), union_type_id(to_llvm_type, union_pointer) + + size = { + @llvm_typer.size_of(from_value_type), + @llvm_typer.size_of(to_value_type), + }.min + size = @program.bits64? ? int64(size) : int32(size) + memcpy( + cast_to_void_pointer(union_value(to_llvm_type, union_pointer)), + cast_to_void_pointer(union_value(from_llvm_type, value)), + size, + align: @llvm_typer.align_of(to_value_type), + src_align: @llvm_typer.align_of(from_value_type), + volatile: int1(0), + ) + end + + def assign_distinct_union_types(to_pointer, to_type, from_type, from_pointer) # If we have: - # - target_pointer: Pointer(A | B | C) - # - target_type: A | B | C - # - value_type: A | B - # - value: Pointer(A | B) + # - to_pointer: Pointer(A | B | C) + # - to_type: A | B | C + # - from_type: A | B + # - from_pointer: Pointer(A | B) # - # Then we: - # - load the value, we get A | B - # - cast the target pointer to Pointer(A | B) - # - store the A | B from the first pointer into the casted target pointer - casted_target_pointer = cast_to_pointer target_pointer, value_type - store load(llvm_type(value_type), value), casted_target_pointer + # Then it might happen that from_type and to_type have the same alignment. + # In this case, the two pointers are interchangeable, so we can simply: + if align_of(to_type) == align_of(from_type) + # - load the value, we get A | B + # - cast the target pointer to Pointer(A | B) + # - store the A | B from the value pointer into the casted target pointer + casted_target_pointer = cast_to_pointer to_pointer, from_type + store load(llvm_type(from_type), from_pointer), casted_target_pointer + else + # Otherwise, the type ID and the value must be stored separately + store_union_in_union to_type, to_pointer, from_type, from_pointer + end end def downcast_distinct_union_types(value, to_type : MixedUnionType, from_type : MixedUnionType) - cast_to_pointer value, to_type + # If from_type and to_type have the same alignment, we don't need a + # separate value; just cast the larger value pointer to the smaller one + if align_of(to_type) == align_of(from_type) + cast_to_pointer value, to_type + else + # This is the same as upcasting and we need that separate, newly aligned + # union value + target_pointer = alloca llvm_type(to_type) + store_union_in_union to_type, target_pointer, from_type, value + target_pointer + end end def upcast_distinct_union_types(value, to_type : MixedUnionType, from_type : MixedUnionType) diff --git a/src/compiler/crystal/command.cr b/src/compiler/crystal/command.cr index 2c5492445e0b..b51f9405c4e6 100644 --- a/src/compiler/crystal/command.cr +++ b/src/compiler/crystal/command.cr @@ -41,6 +41,7 @@ class Crystal::Command Tool: context show context for given location expand show macro expansion for given location + flags print all macro `flag?` values format format project, directories and/or files hierarchy show type hierarchy dependencies show file dependency tree @@ -58,7 +59,7 @@ class Crystal::Command @compiler : Compiler? def initialize(@options : Array(String)) - @color = ENV["TERM"]? != "dumb" + @color = ENV["TERM"]? != "dumb" && !ENV.has_key?("NO_COLOR") @error_trace = false @progress_tracker = ProgressTracker.new end @@ -177,6 +178,9 @@ class Crystal::Command when "format".starts_with?(tool) options.shift format + when "flags" == tool + options.shift + flags when "expand".starts_with?(tool) options.shift expand @@ -349,7 +353,8 @@ class Crystal::Command includes : Array(String), excludes : Array(String), verbose : Bool, - check : Bool do + check : Bool, + tallies : Bool do def compile(output_filename = self.output_filename) compiler.emit_base_filename = emit_base_filename || output_filename.rchop(File.extname(output_filename)) compiler.compile sources, output_filename, combine_rpath: combine_rpath @@ -367,6 +372,7 @@ class Crystal::Command allowed_formats = ["text", "json"]) compiler = new_compiler compiler.progress_tracker = @progress_tracker + compiler.no_codegen = no_codegen link_flags = [] of String filenames = [] of String has_stdin_filename = false @@ -381,6 +387,7 @@ class Crystal::Command includes = [] of String verbose = false check = false + tallies = false option_parser = parse_with_crystal_opts do |opts| opts.banner = "Usage: crystal #{command} [options] [programfile] [--] [arguments]\n\nOptions:" @@ -397,6 +404,14 @@ class Crystal::Command opts.on("--no-debug", "Skip any symbolic debug info") do compiler.debug = Crystal::Debug::None end + + opts.on("--frame-pointers auto|always|non-leaf", "Control the preservation of frame pointers") do |value| + if frame_pointers = FramePointers.parse?(value) + compiler.frame_pointers = frame_pointers + else + error "Invalid value `#{value}` for frame-pointers" + end + end end opts.on("-D FLAG", "--define FLAG", "Define a compile-time flag") do |flag| @@ -443,6 +458,10 @@ class Crystal::Command end if unreachable_command + opts.on("--tallies", "Print reachable methods and their call counts as well") do + tallies = true + end + opts.on("--check", "Exits with error if there is any unreachable code") do |f| check = true end @@ -590,7 +609,7 @@ class Crystal::Command output_filename = "#{::Path[first_filename].stem}#{output_extension}" # Check if we'll overwrite the main source file - if !no_codegen && !run && first_filename == File.expand_path(output_filename) + if !compiler.no_codegen? && !run && first_filename == File.expand_path(output_filename) error "compilation will overwrite source file '#{Crystal.relative_filename(first_filename)}', either change its extension to '.cr' or specify an output file with '-o'" end end @@ -602,7 +621,7 @@ class Crystal::Command error "maximum number of threads cannot be lower than 1" if compiler.n_threads < 1 - if !no_codegen && !run && Dir.exists?(output_filename) + if !compiler.no_codegen? && !run && Dir.exists?(output_filename) error "can't use `#{output_filename}` as output filename because it's a directory" end @@ -610,10 +629,10 @@ class Crystal::Command emit_base_filename = ::Path[sources.first.filename].stem end - combine_rpath = run && !no_codegen + combine_rpath = run && !compiler.no_codegen? @config = CompilerConfig.new compiler, sources, output_filename, emit_base_filename, arguments, specified_output, hierarchy_exp, cursor_location, output_format.not_nil!, - combine_rpath, includes, excludes, verbose, check + combine_rpath, includes, excludes, verbose, check, tallies end private def gather_sources(filenames) @@ -621,6 +640,8 @@ class Crystal::Command filename = File.expand_path(filename) Compiler::Source.new(filename, File.read(filename)) end + rescue exc : IO::Error + error exc end private def setup_simple_compiler_options(compiler, opts) @@ -727,7 +748,7 @@ class Crystal::Command private def error(msg, exit_code = 1) # This is for the case where the main command is wrong - @color = false if ARGV.includes?("--no-color") || ENV["TERM"]? == "dumb" + @color = false if ARGV.includes?("--no-color") || ENV["TERM"]? == "dumb" || ENV.has_key?("NO_COLOR") Crystal.error msg, @color, exit_code: exit_code end diff --git a/src/compiler/crystal/command/spec.cr b/src/compiler/crystal/command/spec.cr index ff8f47b11859..ce34b2ac4155 100644 --- a/src/compiler/crystal/command/spec.cr +++ b/src/compiler/crystal/command/spec.cr @@ -24,7 +24,7 @@ class Crystal::Command puts opts puts - runtime_options = Spec.option_parser + runtime_options = Spec::CLI.new.option_parser runtime_options.banner = "Runtime options (passed to spec runner):" puts runtime_options exit diff --git a/src/compiler/crystal/compiler.cr b/src/compiler/crystal/compiler.cr index 237783c2ed8c..899ef242f318 100644 --- a/src/compiler/crystal/compiler.cr +++ b/src/compiler/crystal/compiler.cr @@ -16,6 +16,12 @@ module Crystal Default = LineNumbers end + enum FramePointers + Auto + Always + NonLeaf + end + # Main interface to the compiler. # # A Compiler parses source code, type checks it and @@ -45,6 +51,9 @@ module Crystal # code by the `flag?(...)` macro method. property flags = [] of String + # Controls generation of frame pointers. + property frame_pointers = FramePointers::Auto + # If `true`, the executable will be generated with debug code # that can be understood by `gdb` and `lldb`. property debug = Debug::Default @@ -297,7 +306,8 @@ module Crystal private def codegen(program, node : ASTNode, sources, output_filename) llvm_modules = @progress_tracker.stage("Codegen (crystal)") do - program.codegen node, debug: debug, single_module: @single_module || @cross_compile || !@emit_targets.none? + program.codegen node, debug: debug, frame_pointers: frame_pointers, + single_module: @single_module || @cross_compile || !@emit_targets.none? end output_dir = CacheDir.instance.directory_for(sources) @@ -321,6 +331,10 @@ module Crystal {% if flag?(:darwin) %} run_dsymutil(output_filename) unless debug.none? {% end %} + + {% if flag?(:windows) %} + copy_dlls(program, output_filename) if program.has_flag?("preview_dll") + {% end %} end CacheDir.instance.cleanup if @cleanup @@ -345,6 +359,25 @@ module Crystal end end + private def copy_dlls(program, output_filename) + not_found = nil + output_directory = File.dirname(output_filename) + + program.each_dll_path do |path, found| + if found + FileUtils.cp(path, output_directory) + else + not_found ||= [] of String + not_found << path + end + end + + if not_found + stderr << "Warning: The following DLLs are required at run time, but Crystal is unable to locate them in CRYSTAL_LIBRARY_PATH, the compiler's directory, or PATH: " + not_found.sort!.join(stderr, ", ") + end + end + private def cross_compile(program, units, output_filename) unit = units.first llvm_mod = unit.llvm_mod diff --git a/src/compiler/crystal/ffi/lib_ffi.cr b/src/compiler/crystal/ffi/lib_ffi.cr index 699a0c125468..97163c989ee5 100644 --- a/src/compiler/crystal/ffi/lib_ffi.cr +++ b/src/compiler/crystal/ffi/lib_ffi.cr @@ -1,5 +1,8 @@ module Crystal @[Link("ffi")] + {% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "libffi.dll")] + {% end %} lib LibFFI {% begin %} enum ABI diff --git a/src/compiler/crystal/interpreter/compiler.cr b/src/compiler/crystal/interpreter/compiler.cr index bfd1514b419f..04fc885fce7e 100644 --- a/src/compiler/crystal/interpreter/compiler.cr +++ b/src/compiler/crystal/interpreter/compiler.cr @@ -762,7 +762,7 @@ class Crystal::Repl::Compiler < Crystal::Visitor # particularly when outside of a method. if is_self && !scope.is_a?(Program) && !scope.passed_as_self? put_type scope, node: node - return + return false end local_var = lookup_local_var_or_closured_var(node.name) @@ -1687,7 +1687,7 @@ class Crystal::Repl::Compiler < Crystal::Visitor if node.upcast? upcast node.obj, obj_type, node.non_nilable_type upcast node.obj, node.non_nilable_type, node.type - return + return false end # Check if obj is a `to_type` @@ -3158,6 +3158,7 @@ class Crystal::Repl::Compiler < Crystal::Visitor {% end %} call compiled_def, node: node + false end def visit(node : ASTNode) diff --git a/src/compiler/crystal/interpreter/context.cr b/src/compiler/crystal/interpreter/context.cr index f4a4444e105c..2d5da06dcf15 100644 --- a/src/compiler/crystal/interpreter/context.cr +++ b/src/compiler/crystal/interpreter/context.cr @@ -46,6 +46,9 @@ class Crystal::Repl::Context def initialize(@program : Program) @program.flags << "interpreted" + {% if flag?(:win32) %} + @program.flags << "preview_dll" + {% end %} @gc_references = [] of Void* @@ -392,6 +395,8 @@ class Crystal::Repl::Context @id_to_type[id] end + getter? loader : Loader? + getter(loader : Loader) { lib_flags = program.lib_flags # Execute and expand `subcommands`. @@ -404,14 +409,7 @@ class Crystal::Repl::Context # (MSVC doesn't seem to have this issue) args.delete("-lgc") - Crystal::Loader.parse(args).tap do |loader| - if ENV["CRYSTAL_INTERPRETER_LOADER_INFO"]?.presence - STDERR.puts "Crystal::Loader loaded libraries:" - loader.loaded_libraries.each do |path| - STDERR.puts " #{path}" - end - end - + Crystal::Loader.parse(args, dll_search_paths: dll_search_paths).tap do |loader| # FIXME: Part 2: This is a workaround for initial integration of the interpreter: # We append a handle to the current executable (i.e. the compiler program) # to the loader's handle list. This gives the loader access to all the symbols in the compiler program, @@ -421,11 +419,35 @@ class Crystal::Repl::Context loader.load_current_program_handle if ENV["CRYSTAL_INTERPRETER_LOADER_INFO"]?.presence - STDERR.puts " current program handle" + STDERR.puts "Crystal::Loader loaded libraries:" + loader.loaded_libraries.each do |path| + STDERR.puts " #{path}" + end end end } + # Extra DLL search paths to mimic compiled code's DLL-copying behavior + # regarding `@[Link]` annotations. These directories should match the ones + # used in `Crystal::Program#each_dll_path` + private def dll_search_paths + {% if flag?(:msvc) %} + paths = CrystalLibraryPath.paths + + if executable_path = Process.executable_path + paths << File.dirname(executable_path) + end + + ENV["PATH"]?.try &.split(Process::PATH_DELIMITER, remove_empty: true) do |path| + paths << path + end + + paths + {% else %} + nil + {% end %} + end + def c_function(name : String) loader.find_symbol(name) end diff --git a/src/compiler/crystal/interpreter/instructions.cr b/src/compiler/crystal/interpreter/instructions.cr index 67966277bf15..f2b8abcb9a51 100644 --- a/src/compiler/crystal/interpreter/instructions.cr +++ b/src/compiler/crystal/interpreter/instructions.cr @@ -1649,6 +1649,11 @@ require "./repl" pop_values: [current_context : Void*, new_context : Void*], code: swapcontext(current_context, new_context), }, + interpreter_fiber_resumable: { + pop_values: [context : Void*], + push: true, + code: fiber_resumable(context), + }, {% if flag?(:bits64) %} interpreter_intrinsics_memcpy: { diff --git a/src/compiler/crystal/interpreter/interpreter.cr b/src/compiler/crystal/interpreter/interpreter.cr index 608fb6d85d1a..eca73ecae6bc 100644 --- a/src/compiler/crystal/interpreter/interpreter.cr +++ b/src/compiler/crystal/interpreter/interpreter.cr @@ -1154,6 +1154,7 @@ class Crystal::Repl::Interpreter nil end end + spawned_fiber.@context.resumable = 1 spawned_fiber.as(Void*) end @@ -1161,11 +1162,17 @@ class Crystal::Repl::Interpreter # current_fiber = current_context.as(Fiber*).value new_fiber = new_context.as(Fiber*).value - # We directly resume the next fiber. - # TODO: is this okay? We totally ignore the scheduler here! + # delegates the context switch to the interpreter's scheduler, so we update + # the current fiber reference, set the GC stack bottom, and so on (aka + # there's more to switching context than `Fiber.swapcontext`): new_fiber.resume end + private def fiber_resumable(context : Void*) : LibC::Long + fiber = context.as(Fiber*).value + fiber.@context.resumable + end + private def pry(ip, instructions, stack_bottom, stack) offset = (ip - instructions.instructions.to_unsafe).to_i32 node = instructions.nodes[offset]? diff --git a/src/compiler/crystal/interpreter/primitives.cr b/src/compiler/crystal/interpreter/primitives.cr index 1d50568c5d62..968361fb6c1d 100644 --- a/src/compiler/crystal/interpreter/primitives.cr +++ b/src/compiler/crystal/interpreter/primitives.cr @@ -402,6 +402,9 @@ class Crystal::Repl::Compiler when "interpreter_fiber_swapcontext" accept_call_args(node) interpreter_fiber_swapcontext(node: node) + when "interpreter_fiber_resumable" + accept_call_args(node) + interpreter_fiber_resumable(node: node) when "interpreter_intrinsics_memcpy" accept_call_args(node) interpreter_intrinsics_memcpy(node: node) diff --git a/src/compiler/crystal/interpreter/repl.cr b/src/compiler/crystal/interpreter/repl.cr index 93b3a6cef65c..2c009a89e87d 100644 --- a/src/compiler/crystal/interpreter/repl.cr +++ b/src/compiler/crystal/interpreter/repl.cr @@ -22,15 +22,13 @@ class Crystal::Repl when "exit" break when .presence - parser = new_parser(expression) - parser.warnings.report(STDOUT) + result = parse_and_interpret(expression) + result.warnings.report(STDOUT) - node = parser.parse - next unless node + next unless result.value - value = interpret(node) print " => " - puts SyntaxHighlighter::Colorize.highlight!(value.to_s) + puts SyntaxHighlighter::Colorize.highlight!(result.value.to_s) end rescue ex : EscapingException print "Unhandled exception: " @@ -44,6 +42,18 @@ class Crystal::Repl end end + record EvalResult, value : Value?, warnings : WarningCollection + + def parse_and_interpret(expression : String) : EvalResult + parser = new_parser(expression) + + node = parser.parse + return EvalResult.new(value: nil, warnings: parser.warnings) unless node + + value = interpret(node) + return EvalResult.new(value: value, warnings: parser.warnings) + end + def run_file(filename, argv) @interpreter.argv = argv @@ -68,7 +78,7 @@ class Crystal::Repl interpret(exps) end - private def load_prelude + def load_prelude node = parse_prelude interpret_and_exit_on_error(node) diff --git a/src/compiler/crystal/loader.cr b/src/compiler/crystal/loader.cr index d7d0133cc993..5a147dad590f 100644 --- a/src/compiler/crystal/loader.cr +++ b/src/compiler/crystal/loader.cr @@ -14,6 +14,7 @@ class Crystal::Loader class LoadError < Exception property args : Array(String)? property search_paths : Array(String)? + property dll_search_paths : Array(String)? def message String.build do |io| @@ -26,28 +27,26 @@ class Crystal::Loader io << "\nSearch path: " search_paths.join(io, Process::PATH_DELIMITER) end + if dll_search_paths = @dll_search_paths + io << "\nDLL search path: " + dll_search_paths.join(io, Process::PATH_DELIMITER) + end end end end - def self.new(search_paths : Array(String), libnames : Array(String), file_paths : Array(String)) : self - loader = new(search_paths) - + def load_all(libnames : Array(String), file_paths : Array(String)) file_paths.each do |path| - loader.load_file(::Path[path].expand) + load_file(::Path[path].expand) end libnames.each do |libname| - loader.load_library(libname) + load_library(libname) end - loader end getter search_paths : Array(String) getter loaded_libraries = [] of String - - def initialize(@search_paths : Array(String)) - @handles = [] of Handle - end + @handles = [] of Handle # def self.library_filename(libname : String) : String # raise NotImplementedError.new("library_filename") diff --git a/src/compiler/crystal/loader/msvc.cr b/src/compiler/crystal/loader/msvc.cr index bf0b5c74a36f..60aca1aae333 100644 --- a/src/compiler/crystal/loader/msvc.cr +++ b/src/compiler/crystal/loader/msvc.cr @@ -5,9 +5,9 @@ require "crystal/system/win32/library_archive" # `link.exe`, using the Win32 DLL API. # # * Only dynamic libraries can be loaded. Static libraries and object files -# are unsupported. in particular, `LibC.printf` and `LibC.snprintf`are inline -# functions in `legacy-stdio_definitions.lib` since VS2015, so they are never -# found by the loader. +# are unsupported. For example, `LibC.printf` and `LibC.snprintf` are inline +# functions in `legacy_stdio_definitions.lib` since VS2015, so they are never +# found by the loader (this is why stdlib no longer uses those functions). # * Unlike the Unix counterpart, symbols in the current module do not clash with # the ones in DLLs or their corresponding import libraries. @@ -18,16 +18,28 @@ class Crystal::Loader include SystemError end + getter dll_search_paths : Array(String)? + + def initialize(@search_paths : Array(String), @dll_search_paths : Array(String)? = nil) + end + # Parses linker arguments in the style of `link.exe`. - def self.parse(args : Array(String), *, search_paths : Array(String) = default_search_paths) : self + # + # The directories in *dll_search_paths* are tried before Windows' search order + # when looking for DLLs corresponding to an import library. The compiler uses + # this to mimic `@[Link]`'s DLL-copying behavior for compiled code. + def self.parse(args : Array(String), *, search_paths : Array(String) = default_search_paths, dll_search_paths : Array(String)? = nil) : self search_paths, libnames = parse_args(args, search_paths) file_paths = [] of String begin - self.new(search_paths, libnames, file_paths) + loader = new(search_paths, dll_search_paths) + loader.load_all(libnames, file_paths) + loader rescue exc : LoadError exc.args = args exc.search_paths = search_paths + exc.dll_search_paths = dll_search_paths raise exc end end @@ -60,7 +72,7 @@ class Crystal::Loader result end - private def self.search_library(libname, search_paths, extra_suffix) + protected def self.search_library(libname, search_paths, extra_suffix) if ::Path::SEPARATORS.any? { |separator| libname.includes?(separator) } libname = File.expand_path(libname) library_path = library_filename(libname) @@ -106,7 +118,7 @@ class Crystal::Loader end def self.library_filename(libname : String) : String - "#{libname}.lib" + "#{libname.rchop(".lib")}.lib" end def find_symbol?(name : String) : Handle? @@ -127,19 +139,24 @@ class Crystal::Loader # files, whose base names may not match the library's. Thus it is necessary # to extract this information from the library archive itself. System::LibraryArchive.imported_dlls(path).each do |dll| - # always consider the `.dll` in the same directory as the `.lib` first, - # regardless of the search order - first_path = File.join(File.dirname(path), dll) - dll = first_path if File.file?(first_path) + dll_full_path = @dll_search_paths.try &.each do |search_path| + full_path = File.join(search_path, dll) + break full_path if File.file?(full_path) + end + dll = dll_full_path || dll # TODO: `dll` is an unqualified name, e.g. `SHELL32.dll`, so the default - # DLL search order is used; consider getting rid of the cwd + # DLL search order is used if *dll_full_path* is nil; consider getting rid + # of the current working directory altogether # (https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order) + # + # Note that the compiler's directory and PATH are effectively searched + # twice when coming from the interpreter handle = open_library(dll) return false unless handle @handles << handle - @loaded_libraries << dll + @loaded_libraries << (module_filename(handle) || dll) end true @@ -149,14 +166,20 @@ class Crystal::Loader load_library?(libname) || raise LoadError.from_winerror "cannot find #{Loader.library_filename(libname)}" end + def load_library?(libname : String) : Bool + library_path = Loader.search_library(libname, @search_paths, "-dynamic") + !library_path.nil? && load_file?(library_path) + end + private def open_library(path : String) - # TODO: respect Crystal::LIBRARY_RPATH (#13490) + # TODO: respect Crystal::LIBRARY_RPATH (#13490), or `@[Link(dll:)]`'s search order LibC.LoadLibraryExW(System.to_wstr(path), nil, 0) end def load_current_program_handle if LibC.GetModuleHandleExW(0, nil, out hmodule) != 0 @handles << hmodule + @loaded_libraries << (Process.executable_path || "current program handle") end end @@ -167,6 +190,19 @@ class Crystal::Loader @handles.clear end + private def module_filename(handle) + Crystal::System.retry_wstr_buffer do |buffer, small_buf| + len = LibC.GetModuleFileNameW(handle, buffer, buffer.size) + if 0 < len < buffer.size + break String.from_utf16(buffer[0, len]) + elsif small_buf && len == buffer.size + next 32767 # big enough. 32767 is the maximum total path length of UNC path. + else + break nil + end + end + end + # Returns a list of directories used as the default search paths. # # For MSVC this is simply the contents of the `LIB` environment variable, diff --git a/src/compiler/crystal/loader/unix.cr b/src/compiler/crystal/loader/unix.cr index 4c202231d7e6..46bca67341cc 100644 --- a/src/compiler/crystal/loader/unix.cr +++ b/src/compiler/crystal/loader/unix.cr @@ -35,8 +35,16 @@ class Crystal::Loader end end + def initialize(@search_paths : Array(String)) + end + # Parses linker arguments in the style of `ld`. - def self.parse(args : Array(String), *, search_paths : Array(String) = default_search_paths) : self + # + # *dll_search_paths* has no effect. (Technically speaking, `LD_LIBRARY_PATH` + # goes here and `LIBRARY_PATH` goes into *search_paths*, but there is little + # point in doing so since the same library files are used at both compile and + # run time.) + def self.parse(args : Array(String), *, search_paths : Array(String) = default_search_paths, dll_search_paths : Array(String)? = nil) : self libnames = [] of String file_paths = [] of String @@ -73,7 +81,9 @@ class Crystal::Loader search_paths = extra_search_paths + search_paths begin - self.new(search_paths, libnames, file_paths) + loader = new(search_paths) + loader.load_all(libnames, file_paths) + loader rescue exc : LoadError exc.args = args exc.search_paths = search_paths @@ -120,6 +130,7 @@ class Crystal::Loader def load_current_program_handle if program_handle = LibC.dlopen(nil, LibC::RTLD_LAZY | LibC::RTLD_GLOBAL) @handles << program_handle + @loaded_libraries << (Process.executable_path || "current program handle") end end diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr index 983af69ae4b7..3ec6243ffd62 100644 --- a/src/compiler/crystal/macros.cr +++ b/src/compiler/crystal/macros.cr @@ -442,6 +442,8 @@ module Crystal::Macros # Returns a `MacroId` that contains the documentation comments attached to this node, or an empty `MacroId` if there are none. # Each line is prefixed with a `#` character to allow the output to be used directly within another node's documentation comment. # + # A common use case is combining this method with the `@caller` macro instance variable in order to allow [merging macro expansion and call comments](https://crystal-lang.org/reference/syntax_and_semantics/macros/index.html#merging-expansion-and-call-comments). + # # WARNING: The return value will be empty when executed outside of the `crystal docs` command. def doc_comment : MacroId end @@ -1405,6 +1407,27 @@ module Crystal::Macros end end + # A fictitious node representing the body of a `Def` marked with + # `@[Primitive]`. + class Primitive < ASTNode + # Returns the name of the primitive. + # + # This is identical to the argument to the associated `@[Primitive]` + # annotation. + # + # ``` + # module Foo + # @[Primitive(:abc)] + # def foo + # end + # end + # + # {{ Foo.methods.first.body.name }} # => :abc + # ``` + def name : SymbolLiteral + end + end + # A macro definition. class Macro < ASTNode # Returns the name of this macro. @@ -1804,6 +1827,185 @@ module Crystal::Macros end end + # A lib definition. + # + # Every lib definition `node` is equivalent to: + # + # ``` + # {% begin %} + # {{ node.kind }} {{ node.name }} + # {{ node.body }} + # end + # {% end %} + # ``` + class LibDef < ASTNode + # Returns the keyword used to define this type. + # + # For `LibDef` this is always `lib`. + def kind : MacroId + end + + # Returns the name of this type definition. + # + # *generic_args* has no effect. It exists solely to match the interface of + # other related AST nodes. + def name(*, generic_args : BoolLiteral = true) : Path + end + + # Returns the body of this type definition. + def body : ASTNode + end + end + + # A struct or union definition inside a lib. + # + # Every type definition `node` is equivalent to: + # + # ``` + # {% begin %} + # {{ node.kind }} {{ node.name }} + # {{ node.body }} + # end + # {% end %} + # ``` + class CStructOrUnionDef < ASTNode + # Returns whether this node defines a C union. + def union? : BoolLiteral + end + + # Returns the keyword used to define this type. + # + # For `CStructOrUnionDef` this is either `struct` or `union`. + def kind : MacroId + end + + # Returns the name of this type definition. + # + # *generic_args* has no effect. It exists solely to match the interface of + # other related AST nodes. + def name(*, generic_args : BoolLiteral = true) : Path + end + + # Returns the body of this type definition. + def body : ASTNode + end + end + + # A function declaration inside a lib, or a top-level C function definition. + # + # Every function `node` is equivalent to: + # + # ``` + # fun {{ node.name }} {% if real_name = node.real_name %}= {{ real_name }}{% end %}( + # {% for arg in node.args %} {{ arg }}, {% end %} + # {% if node.variadic? %} ... {% end %} + # ) {% if return_type = node.return_type %}: {{ return_type }}{% end %} + # {% if node.has_body? %} + # {{ body }} + # end + # {% end %} + # ``` + class FunDef < ASTNode + # Returns the name of the function in Crystal. + def name : MacroId + end + + # Returns the real C name of the function, if any. + def real_name : StringLiteral | Nop + end + + # Returns the parameters of the function. + # + # This does not include the variadic parameter. + def args : ArrayLiteral(Arg) + end + + # Returns whether the function is variadic. + def variadic? : BoolLiteral + end + + # Returns the return type of the function, if specified. + def return_type : ASTNode | Nop + end + + # Returns the body of the function, if any. + # + # Both top-level funs and lib funs may return a `Nop`. Instead, `#has_body?` + # can be used to distinguish between the two. + # + # ``` + # macro body_class(x) + # {{ (x.is_a?(LibDef) ? x.body : x).body.class_name }} + # end + # + # body_class(lib MyLib + # fun foo + # end) # => "Nop" + # + # body_class(fun foo + # end) # => "Nop" + # ``` + def body : ASTNode | Nop + end + + # Returns whether this function has a body. + # + # Top-level funs have a body, whereas lib funs do not. + # + # ``` + # macro has_body(x) + # {{ (x.is_a?(LibDef) ? x.body : x).has_body? }} + # end + # + # has_body(lib MyLib + # fun foo + # end) # => false + # + # has_body(fun foo + # end) # => true + # ``` + def has_body? : BoolLiteral + end + end + + # A typedef inside a lib. + # + # Every typedef `node` is equivalent to: + # + # ``` + # type {{ node.name }} = {{ node.type }} + # ``` + class TypeDef < ASTNode + # Returns the name of the typedef. + def name : Path + end + + # Returns the name of the type this typedef is equivalent to. + def type : ASTNode + end + end + + # An external variable declaration inside a lib. + # + # Every variable `node` is equivalent to: + # + # ``` + # ${{ node.name }} {% if real_name = node.real_name %}= {{ real_name }}{% end %} : {{ node.type }} + # ``` + class ExternalVar < ASTNode + # Returns the name of the variable in Crystal, without the preceding `$`. + def name : MacroId + end + + # Returns the real C name of the variable, if any. + def real_name : StringLiteral | Nop + end + + # Returns the name of the variable's type. + def type : ASTNode + end + end + # A `while` expression class While < ASTNode # Returns this while's condition. @@ -2032,29 +2234,22 @@ module Crystal::Macros end end - # class LibDef < ASTNode - # end - - # class FunDef < ASTNode - # end - - # class TypeDef < ASTNode - # end - - # abstract class CStructOrUnionDef < ASTNode - # end - - # class StructDef < CStructOrUnionDef - # end - - # class UnionDef < CStructOrUnionDef - # end - - # class ExternalVar < ASTNode - # end + # An `alias` statement. + # + # Every statement `node` is equivalent to: + # + # ``` + # alias {{ node.name }} = {{ node.type }} + # ``` + class Alias < ASTNode + # Returns the name of the alias. + def name : Path + end - # class Alias < ASTNode - # end + # Returns the name of the type this alias is equivalent to. + def type : ASTNode + end + end # A metaclass in a type expression: `T.class` class Metaclass < ASTNode @@ -2095,8 +2290,18 @@ module Crystal::Macros end end - # class TypeOf < ASTNode - # end + # A `typeof` expression. + # + # Every expression *node* is equivalent to: + # + # ``` + # typeof({{ node.args.splat }}) + # ``` + class TypeOf < ASTNode + # Returns the arguments to this `typeof`. + def args : ArrayLiteral(ASTNode) + end + end # A macro expression, # surrounded by {{ ... }} (output = true) @@ -2172,6 +2377,75 @@ module Crystal::Macros class MagicConstant < ASTNode end + # An inline assembly expression. + # + # Every assembly `node` is equivalent to: + # + # ``` + # asm( + # {{ node.text }} : + # {{ node.outputs.splat }} : + # {{ node.inputs.splat }} : + # {{ node.clobbers.splat }} : + # {% if node.volatile? %} "volatile", {% end %} + # {% if node.alignstack? %} "alignstack", {% end %} + # {% if node.intel? %} "intel", {% end %} + # {% if node.can_throw? %} "unwind", {% end %} + # ) + # ``` + class Asm < ASTNode + # Returns the template string for this assembly expression. + def text : StringLiteral + end + + # Returns an array of output operands for this assembly expression. + def outputs : ArrayLiteral(AsmOperand) + end + + # Returns an array of input operands for this assembly expression. + def inputs : ArrayLiteral(AsmOperand) + end + + # Returns an array of clobbered register names for this assembly expression. + def clobbers : ArrayLiteral(StringLiteral) + end + + # Returns whether the assembly expression contains side effects that are + # not listed in `#outputs`, `#inputs`, and `#clobbers`. + def volatile? : BoolLiteral + end + + # Returns whether the assembly expression requires stack alignment code. + def alignstack? : BoolLiteral + end + + # Returns `true` if the template string uses the Intel syntax, `false` if it + # uses the AT&T syntax. + def intel? : BoolLiteral + end + + # Returns whether the assembly expression might unwind the stack. + def can_throw? : BoolLiteral + end + end + + # An output or input operand for an `Asm` node. + # + # Every operand `node` is equivalent to: + # + # ``` + # {{ node.constraint }}({{ node.exp }}) + # ``` + class AsmOperand < ASTNode + # Returns the constraint string of this operand. + def constraint : StringLiteral + end + + # Returns the associated output or input argument of this operand. + def exp : ASTNode + end + end + # A fictitious node representing an identifier like, `foo`, `Bar` or `something_else`. # # The parser doesn't create these nodes. Instead, you create them by invoking `id` diff --git a/src/compiler/crystal/macros/interpreter.cr b/src/compiler/crystal/macros/interpreter.cr index 5bc7cd0117ca..1e18e92b7545 100644 --- a/src/compiler/crystal/macros/interpreter.cr +++ b/src/compiler/crystal/macros/interpreter.cr @@ -118,6 +118,7 @@ module Crystal def visit(node : MacroLiteral) @str << node.value + false end def visit(node : MacroVerbatim) @@ -135,7 +136,8 @@ module Crystal def visit(node : Var) var = @vars[node.name]? if var - return @last = var + @last = var + return false end # Try to consider the var as a top-level macro call. @@ -150,7 +152,8 @@ module Crystal # and in this case the parser has no idea about this, so the only # solution is to do it now. if value = interpret_top_level_call?(Call.new(nil, node.name)) - return @last = value + @last = value + return false end node.raise "undefined macro variable '#{node.name}'" @@ -549,6 +552,7 @@ module Crystal else node.raise "unknown macro instance var: '#{node.name}'" end + false end def visit(node : TupleLiteral) diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index 24d3d8bbd14d..9891c4cc2b2a 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -300,7 +300,7 @@ module Crystal def interpret_run(node) if node.args.size == 0 - node.wrong_number_of_arguments "top-level macro 'run'", 0, "1+" + node.wrong_number_of_arguments "macro '::run'", 0, "1+" end node.args.first.accept self @@ -1459,6 +1459,17 @@ module Crystal end end + class Primitive + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { SymbolLiteral.new(@name) } + else + super + end + end + end + class Macro def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method @@ -1549,6 +1560,19 @@ module Crystal end end + class Alias + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { @name } + when "type" + interpret_check_args { @value } + else + super + end + end + end + class OffsetOf def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method @@ -1629,6 +1653,62 @@ module Crystal end end + class Asm + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "text" + interpret_check_args { StringLiteral.new(@text) } + when "outputs" + interpret_check_args do + if outputs = @outputs + ArrayLiteral.map(outputs, &.itself) + else + empty_no_return_array + end + end + when "inputs" + interpret_check_args do + if inputs = @inputs + ArrayLiteral.map(inputs, &.itself) + else + empty_no_return_array + end + end + when "clobbers" + interpret_check_args do + if clobbers = @clobbers + ArrayLiteral.map(clobbers) { |clobber| StringLiteral.new(clobber) } + else + empty_no_return_array + end + end + when "volatile?" + interpret_check_args { BoolLiteral.new(@volatile) } + when "alignstack?" + interpret_check_args { BoolLiteral.new(@alignstack) } + when "intel?" + interpret_check_args { BoolLiteral.new(@intel) } + when "can_throw?" + interpret_check_args { BoolLiteral.new(@can_throw) } + else + super + end + end + end + + class AsmOperand + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "constraint" + interpret_check_args { StringLiteral.new(@constraint) } + when "exp" + interpret_check_args { @exp } + else + super + end + end + end + class MacroId def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method @@ -2351,6 +2431,17 @@ module Crystal end end + class TypeOf + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "args" + interpret_check_args { ArrayLiteral.map(@expressions, &.itself) } + else + super + end + end + end + class Generic def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method @@ -2522,6 +2613,97 @@ module Crystal end end end + + class LibDef + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "kind" + interpret_check_args { MacroId.new("lib") } + when "name" + interpret_check_args(named_params: ["generic_args"]) do + # parse the argument, but ignore it otherwise + parse_generic_args_argument(self, method, named_args, default: true) + @name + end + when "body" + interpret_check_args { @body } + else + super + end + end + end + + class CStructOrUnionDef + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "kind" + interpret_check_args { MacroId.new(@union ? "union" : "struct") } + when "name" + interpret_check_args(named_params: ["generic_args"]) do + # parse the argument, but ignore it otherwise + parse_generic_args_argument(self, method, named_args, default: true) + Path.new(@name) + end + when "body" + interpret_check_args { @body } + when "union?" + interpret_check_args { BoolLiteral.new(@union) } + else + super + end + end + end + + class FunDef + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { MacroId.new(@name) } + when "real_name" + interpret_check_args { @real_name != @name ? StringLiteral.new(@real_name) : Nop.new } + when "args" + interpret_check_args { ArrayLiteral.map(@args, &.itself) } + when "variadic?" + interpret_check_args { BoolLiteral.new(@varargs) } + when "return_type" + interpret_check_args { @return_type || Nop.new } + when "body" + interpret_check_args { @body || Nop.new } + when "has_body?" + interpret_check_args { BoolLiteral.new(!@body.nil?) } + else + super + end + end + end + + class TypeDef + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { Path.new(@name).at(@name_location) } + when "type" + interpret_check_args { @type_spec } + else + super + end + end + end + + class ExternalVar + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { MacroId.new(@name) } + when "real_name" + interpret_check_args { (real_name = @real_name) ? StringLiteral.new(real_name) : Nop.new } + when "type" + interpret_check_args { @type_spec } + else + super + end + end + end end private def get_named_annotation_args(object) @@ -2841,7 +3023,7 @@ end private def full_macro_name(node, method, top_level) if top_level - "top-level macro '#{method}'" + "macro '::#{method}'" else "macro '#{node.class_desc}##{method}'" end diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr index 936fc6a0a270..675202ee0144 100644 --- a/src/compiler/crystal/program.cr +++ b/src/compiler/crystal/program.cr @@ -275,36 +275,77 @@ module Crystal # Defines a predefined constant in the Crystal module, such as BUILD_DATE and VERSION. private def define_crystal_constants if build_commit = Crystal::Config.build_commit - define_crystal_string_constant "BUILD_COMMIT", build_commit + build_commit_const = define_crystal_string_constant "BUILD_COMMIT", build_commit else - define_crystal_nil_constant "BUILD_COMMIT" + build_commit_const = define_crystal_nil_constant "BUILD_COMMIT" end - - define_crystal_string_constant "BUILD_DATE", Crystal::Config.date - define_crystal_string_constant "CACHE_DIR", CacheDir.instance.dir - define_crystal_string_constant "DEFAULT_PATH", Crystal::Config.path - define_crystal_string_constant "DESCRIPTION", Crystal::Config.description - define_crystal_string_constant "PATH", Crystal::CrystalPath.default_path - define_crystal_string_constant "LIBRARY_PATH", Crystal::CrystalLibraryPath.default_path - define_crystal_string_constant "LIBRARY_RPATH", Crystal::CrystalLibraryPath.default_rpath - define_crystal_string_constant "VERSION", Crystal::Config.version - define_crystal_string_constant "LLVM_VERSION", Crystal::Config.llvm_version - define_crystal_string_constant "HOST_TRIPLE", Crystal::Config.host_target.to_s - define_crystal_string_constant "TARGET_TRIPLE", Crystal::Config.host_target.to_s - end - - private def define_crystal_string_constant(name, value) - define_crystal_constant name, StringLiteral.new(value).tap(&.set_type(string)) - end - - private def define_crystal_nil_constant(name) - define_crystal_constant name, NilLiteral.new.tap(&.set_type(self.nil)) - end - - private def define_crystal_constant(name, value) + build_commit_const.doc = <<-MD if wants_doc? + The build commit identifier of the Crystal compiler. + MD + + define_crystal_string_constant "BUILD_DATE", Crystal::Config.date, <<-MD + The build date of the Crystal compiler. + MD + define_crystal_string_constant "CACHE_DIR", CacheDir.instance.dir, <<-MD + The cache directory configured for the Crystal compiler. + + The value is defined by the environment variable `CRYSTAL_CACHE_DIR` and + defaults to the user's configured cache directory. + MD + define_crystal_string_constant "DEFAULT_PATH", Crystal::Config.path, <<-MD + The default Crystal path configured in the compiler. This value is baked + into the compiler and usually points to the accompanying version of the + standard library. + MD + define_crystal_string_constant "DESCRIPTION", Crystal::Config.description, <<-MD + Full version information of the Crystal compiler. Equivalent to `crystal --version`. + MD + define_crystal_string_constant "PATH", Crystal::CrystalPath.default_path, <<-MD + Colon-separated paths where the compiler searches for required source files. + + The value is defined by the environment variable `CRYSTAL_PATH` + and defaults to `DEFAULT_PATH`. + MD + define_crystal_string_constant "LIBRARY_PATH", Crystal::CrystalLibraryPath.default_path, <<-MD + Colon-separated paths where the compiler searches for (binary) libraries. + + The value is defined by the environment variables `CRYSTAL_LIBRARY_PATH`. + MD + define_crystal_string_constant "LIBRARY_RPATH", Crystal::CrystalLibraryPath.default_rpath, <<-MD + Colon-separated paths where the loader searches for dynamic libraries at runtime. + + The value is defined by the environment variables `CRYSTAL_LIBRARY_RPATH`. + MD + define_crystal_string_constant "VERSION", Crystal::Config.version, <<-MD + The version of the Crystal compiler. + MD + define_crystal_string_constant "LLVM_VERSION", Crystal::Config.llvm_version, <<-MD + The version of LLVM used by the Crystal compiler. + MD + define_crystal_string_constant "HOST_TRIPLE", Crystal::Config.host_target.to_s, <<-MD + The LLVM target triple of the host system (the machine that the compiler runs on). + MD + define_crystal_string_constant "TARGET_TRIPLE", Crystal::Config.host_target.to_s, <<-MD + The LLVM target triple of the target system (the machine that the compiler builds for). + MD + end + + private def define_crystal_string_constant(name, value, doc = nil) + define_crystal_constant name, StringLiteral.new(value).tap(&.set_type(string)), doc + end + + private def define_crystal_nil_constant(name, doc = nil) + define_crystal_constant name, NilLiteral.new.tap(&.set_type(self.nil)), doc + end + + private def define_crystal_constant(name, value, doc = nil) : Const crystal.types[name] = const = Const.new self, crystal, name, value const.no_init_flag = true + if doc && wants_doc? + const.doc = doc + end predefined_constants << const + const end property(target_machine : LLVM::TargetMachine) { codegen_target.to_target_machine } diff --git a/src/compiler/crystal/semantic/cleanup_transformer.cr b/src/compiler/crystal/semantic/cleanup_transformer.cr index ad1b570f0cbd..541e0f51d662 100644 --- a/src/compiler/crystal/semantic/cleanup_transformer.cr +++ b/src/compiler/crystal/semantic/cleanup_transformer.cr @@ -256,28 +256,35 @@ module Crystal end def transform(node : StringInterpolation) - string = node.expressions.join do |exp| - if !(transformed_piece = solve_string_interpolation_expression(exp)).nil? - # Valid piece, continue joining - next transformed_piece - elsif expanded = node.expanded - # Invalid piece, transform expansion and exit early - return expanded.transform(self) - else - # No expansion, return self - return node - end + # See if we can solve all the pieces to string literals. + # If that's the case, we can replace the entire interpolation + # with a single string literal. + pieces = node.expressions.dup + solve_string_interpolation_expressions(pieces) + + if pieces.all?(StringLiteral) + string = pieces.join(&.as(StringLiteral).value) + string_literal = StringLiteral.new(string).at(node) + string_literal.type = @program.string + return string_literal end - string_literal = StringLiteral.new(string).at(node) - string_literal.type = @program.string - string_literal + + if expanded = node.expanded + return expanded.transform(self) + end + node end - # Returns the solved piece for string interpolation, if it can find one. - # For example, this returns a String when given a StringLiteral. - private def solve_string_interpolation_expression(piece : ASTNode) : String | Char | Number::Primitive | Bool | Nil - # Check for ExpandableNode happens first in case any nodes below are - # updated to be ExpandableNodes themselves. + private def solve_string_interpolation_expressions(pieces : Array(ASTNode)) + pieces.each_with_index do |piece, i| + replacement = solve_string_interpolation_expression(piece) + next unless replacement + + pieces[i] = replacement + end + end + + private def solve_string_interpolation_expression(piece : ASTNode) : StringLiteral? if piece.is_a?(ExpandableNode) if expanded = piece.expanded return solve_string_interpolation_expression(expanded) @@ -287,13 +294,13 @@ module Crystal case piece when Path if target_const = piece.target_const - solve_string_interpolation_expression(target_const.value) + return solve_string_interpolation_expression(target_const.value) end - when StringLiteral then piece.value - when CharLiteral then piece.value - when NumberLiteral then piece.to_number - when BoolLiteral then piece.value + when StringLiteral + return piece end + + nil end def transform(node : ExpandableNode) @@ -628,10 +635,12 @@ module Crystal if @a_def.vars.try &.[node.name]?.try &.closured? @vars << node end + false end def visit(node : InstanceVar) @vars << node + false end def visit(node : ASTNode) diff --git a/src/compiler/crystal/semantic/main_visitor.cr b/src/compiler/crystal/semantic/main_visitor.cr index 37218e7a34dc..61d1aa508a46 100644 --- a/src/compiler/crystal/semantic/main_visitor.cr +++ b/src/compiler/crystal/semantic/main_visitor.cr @@ -226,6 +226,8 @@ module Crystal node.syntax_replacement = type node.bind_to type end + + false end def visit(node : Generic) @@ -353,6 +355,7 @@ module Crystal def visit(node : Self) node.type = the_self(node).instance_type + false end def visit(node : Var) @@ -394,6 +397,7 @@ module Crystal else node.raise "read before assignment to local variable '#{node.name}'" end + false end def visit(node : TypeDeclaration) @@ -628,6 +632,8 @@ module Crystal ivar.nil_reason ||= NilReason.new(node.name, :used_before_initialized, [node] of ASTNode) ivar.bind_to program.nil_var end + + false end def visit(node : ReadInstanceVar) @@ -1007,7 +1013,7 @@ module Crystal end def visit(node : Block) - return if node.visited? + return false if node.visited? node.visited = true node.context = current_non_block_context @@ -1630,6 +1636,7 @@ module Crystal ivars[node.name] = node_in_callstack(node) end end + false end def visit(node : Var) @@ -1761,7 +1768,7 @@ module Crystal comp.accept self node.syntax_replacement = comp node.bind_to comp - return + return false end if needs_type_filters? && (var = get_expression_var(node.obj)) @@ -2060,7 +2067,7 @@ module Crystal unless node.has_breaks? if endless_while node.type = program.no_return - return + return false end filter_vars TypeFilters.not(cond_type_filters) @@ -2325,6 +2332,8 @@ module Crystal else node.raise "BUG: unhandled primitive in MainVisitor: #{node.name}" end + + false end def visit_va_arg(node) @@ -3042,31 +3051,38 @@ module Crystal def visit(node : Nop) node.type = @program.nil + false end def visit(node : NilLiteral) node.type = @program.nil + false end def visit(node : BoolLiteral) node.type = program.bool + false end def visit(node : NumberLiteral) node.type = program.type_from_literal_kind node.kind + false end def visit(node : CharLiteral) node.type = program.char + false end def visit(node : SymbolLiteral) node.type = program.symbol program.symbols.add node.value + false end def visit(node : StringLiteral) node.type = program.string + false end def visit(node : RegexLiteral) diff --git a/src/compiler/crystal/semantic/restrictions_augmenter.cr b/src/compiler/crystal/semantic/restrictions_augmenter.cr index a627f27f5fe0..5b3e31056110 100644 --- a/src/compiler/crystal/semantic/restrictions_augmenter.cr +++ b/src/compiler/crystal/semantic/restrictions_augmenter.cr @@ -59,7 +59,8 @@ module Crystal def visit(node : Call) if expanded = node.expanded - return expanded.accept self + expanded.accept self + return false end node.obj.try &.accept self diff --git a/src/compiler/crystal/semantic/to_s.cr b/src/compiler/crystal/semantic/to_s.cr index 8c91426bc379..13e8203efe1d 100644 --- a/src/compiler/crystal/semantic/to_s.cr +++ b/src/compiler/crystal/semantic/to_s.cr @@ -44,14 +44,17 @@ module Crystal def visit(node : Primitive) @str << "# primitive: " @str << node.name + false end def visit(node : MetaVar) @str << node.name + false end def visit(node : MetaMacroVar) @str << node.name + false end def visit(node : TypeFilteredNode) diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr index 5d0cbc477260..98ceb23df6b3 100644 --- a/src/compiler/crystal/semantic/top_level_visitor.cr +++ b/src/compiler/crystal/semantic/top_level_visitor.cr @@ -41,6 +41,11 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor @last_doc : String? + # special types recognized for `@[Primitive]` + private enum PrimitiveType + ReferenceStorageType + end + def visit(node : ClassDef) check_outside_exp node, "declare class" @@ -48,6 +53,27 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor annotations = read_annotations + special_type = nil + process_annotations(annotations) do |annotation_type, ann| + case annotation_type + when @program.primitive_annotation + if ann.args.size != 1 + ann.raise "expected Primitive annotation to have one argument" + end + + arg = ann.args.first + unless arg.is_a?(SymbolLiteral) + arg.raise "expected Primitive argument to be a symbol literal" + end + + value = arg.value + special_type = PrimitiveType.parse?(value) + unless special_type + arg.raise "BUG: Unknown primitive type #{value.inspect}" + end + end + end + created_new_type = false if type @@ -70,14 +96,34 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor end else created_new_type = true - if type_vars = node.type_vars - type = GenericClassType.new @program, scope, name, nil, type_vars, false - type.splat_index = node.splat_index - else - type = NonGenericClassType.new @program, scope, name, nil, false + case special_type + in Nil + if type_vars = node.type_vars + type = GenericClassType.new @program, scope, name, nil, type_vars, false + type.splat_index = node.splat_index + else + type = NonGenericClassType.new @program, scope, name, nil, false + end + type.abstract = node.abstract? + type.struct = node.struct? + in .reference_storage_type? + type_vars = node.type_vars + case + when !node.struct? + node.raise "BUG: Expected ReferenceStorageType to be a struct type" + when node.abstract? + node.raise "BUG: Expected ReferenceStorageType to be a non-abstract type" + when !type_vars + node.raise "BUG: Expected ReferenceStorageType to be a generic type" + when type_vars.size != 1 + node.raise "BUG: Expected ReferenceStorageType to have a single generic type parameter" + when node.splat_index + node.raise "BUG: Expected ReferenceStorageType to have no splat parameter" + end + type = GenericReferenceStorageType.new @program, scope, name, @program.value, type_vars + type.declare_instance_var("@type_id", @program.int32) + type.can_be_stored = false end - type.abstract = node.abstract? - type.struct = node.struct? end type.private = true if node.visibility.private? @@ -133,6 +179,10 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor if superclass.struct? && !superclass.abstract? node.raise "can't extend non-abstract struct #{superclass}" end + + if type.is_a?(GenericReferenceStorageType) && superclass != @program.value + node.raise "BUG: Expected reference_storage_type to inherit from Value" + end end if created_new_type @@ -375,7 +425,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor process_def_annotations(node, annotations) do |annotation_type, ann| if annotation_type == @program.primitive_annotation - process_primitive_annotation(node, ann) + process_def_primitive_annotation(node, ann) end node.add_annotation(annotation_type, ann) @@ -460,7 +510,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor false end - private def process_primitive_annotation(node, ann) + private def process_def_primitive_annotation(node, ann) if ann.args.size != 1 ann.raise "expected Primitive annotation to have one argument" end @@ -598,6 +648,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor typed_def_type = lookup_type(node.type_spec) typed_def_type = check_allowed_in_lib node.type_spec, typed_def_type current_type.types[node.name] = TypeDefType.new @program, current_type, node.name, typed_def_type + false end end @@ -655,16 +706,27 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor if enum_type.flags? unless enum_type.types.has_key?("None") - enum_type.add_constant("None", 0) + none_member = enum_type.add_constant("None", 0) + + if node_location = node.location + none_member.add_location node_location + end + define_enum_none_question_method(enum_type, node) end unless enum_type.types.has_key?("All") all_value = enum_type.base_type.kind.cast(0).as(Int::Primitive) + enum_type.types.each_value do |member| all_value |= interpret_enum_value(member.as(Const).value, enum_type.base_type) end - enum_type.add_constant("All", all_value) + + all_member = enum_type.add_constant("All", all_value) + + if node_location = node.location + all_member.add_location node_location + end end end @@ -907,13 +969,14 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor end external = External.new(node.name, external_args, node.body, node.real_name).at(node) + external.name_location = node.name_location call_convention = nil process_def_annotations(external, annotations) do |annotation_type, ann| if annotation_type == @program.call_convention_annotation call_convention = parse_call_convention(ann, call_convention) elsif annotation_type == @program.primitive_annotation - process_primitive_annotation(external, ann) + process_def_primitive_annotation(external, ann) else ann.raise "funs can only be annotated with: NoInline, AlwaysInline, Naked, ReturnsTwice, Raises, CallConvention" end diff --git a/src/compiler/crystal/semantic/type_guess_visitor.cr b/src/compiler/crystal/semantic/type_guess_visitor.cr index 693cade2906b..612390db8e21 100644 --- a/src/compiler/crystal/semantic/type_guess_visitor.cr +++ b/src/compiler/crystal/semantic/type_guess_visitor.cr @@ -86,6 +86,7 @@ module Crystal end check_var_is_self(node) + false end def visit(node : UninitializedVar) @@ -114,6 +115,7 @@ module Crystal # TODO: can this be reached? end end + false end def visit(node : Assign) @@ -1353,6 +1355,7 @@ module Crystal if node.name == "self" @has_self = true end + false end def visit(node : ASTNode) diff --git a/src/compiler/crystal/syntax/ast.cr b/src/compiler/crystal/syntax/ast.cr index d0be18606714..9c0ffcf0d7e5 100644 --- a/src/compiler/crystal/syntax/ast.cr +++ b/src/compiler/crystal/syntax/ast.cr @@ -1954,6 +1954,7 @@ module Crystal property real_name : String property doc : String? property? varargs : Bool + property name_location : Location? def initialize(@name, @args = [] of Arg, @return_type = nil, @varargs = false, @body = nil, @real_name = name) end @@ -1965,7 +1966,13 @@ module Crystal end def clone_without_location - FunDef.new(@name, @args.clone, @return_type.clone, @varargs, @body.clone, @real_name) + clone = FunDef.new(@name, @args.clone, @return_type.clone, @varargs, @body.clone, @real_name) + clone.name_location = name_location + clone + end + + def name_size + @name.size end def_equals_and_hash @name, @args, @return_type, @varargs, @body, @real_name diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index 751608468cd5..5d80b28ed20b 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -788,12 +788,6 @@ module Crystal end block = parse_block(block, stop_on_do: @stop_on_do) - if block || block_arg - if name == "[]=" - raise "setter method '[]=' cannot be called with a block" - end - end - atomic = Call.new atomic, name, (args || [] of ASTNode), block, block_arg, named_args atomic.has_parentheses = has_parentheses atomic.name_location = name_location @@ -3658,8 +3652,8 @@ module Crystal end_location = token_end_location - if name.ends_with?('=') - if name != "[]=" && (params.size > 1 || found_splat || found_double_splat) + if Lexer.setter?(name) + if params.size > 1 || found_splat || found_double_splat raise "setter method '#{name}' cannot have more than one parameter" elsif found_block raise "setter method '#{name}' cannot have a block" @@ -5732,6 +5726,7 @@ module Crystal with_isolated_var_scope(require_body) do next_token_skip_space_or_newline + name_location = @token.location name = if top_level check_ident else @@ -5835,6 +5830,7 @@ module Crystal end fun_def = FunDef.new name, params, return_type, varargs, body, real_name + fun_def.name_location = name_location fun_def.doc = doc fun_def.at(location).at_end(end_location) end @@ -5852,9 +5848,10 @@ module Crystal next_token_skip_space_or_newline value = parse_bare_proc_type + end_location = value.end_location skip_space - alias_node = Alias.new(name, value) + alias_node = Alias.new(name, value).at_end(end_location) alias_node.doc = doc alias_node end diff --git a/src/compiler/crystal/syntax/to_s.cr b/src/compiler/crystal/syntax/to_s.cr index 8ea364d3f991..3ea146d15c3e 100644 --- a/src/compiler/crystal/syntax/to_s.cr +++ b/src/compiler/crystal/syntax/to_s.cr @@ -28,7 +28,6 @@ module Crystal def initialize(@str = IO::Memory.new, @macro_expansion_pragmas = nil, @emit_doc = false) @indent = 0 @inside_macro = 0 - @inside_lib = false end def visit_any(node) @@ -50,10 +49,12 @@ module Crystal end def visit(node : Nop) + false end def visit(node : BoolLiteral) @str << (node.value ? "true" : "false") + false end def visit(node : NumberLiteral) @@ -63,6 +64,8 @@ module Crystal @str << '_' @str << node.kind.to_s end + + false end def needs_suffix?(node : NumberLiteral) @@ -84,10 +87,12 @@ module Crystal def visit(node : CharLiteral) node.value.inspect(@str) + false end def visit(node : SymbolLiteral) visit_symbol_literal_value node.value + false end def visit_symbol_literal_value(value : String) @@ -101,6 +106,7 @@ module Crystal def visit(node : StringLiteral) node.value.inspect(@str) + false end def visit(node : StringInterpolation) @@ -190,6 +196,7 @@ module Crystal def visit(node : NilLiteral) @str << "nil" + false end def visit(node : Expressions) @@ -574,6 +581,7 @@ module Crystal def visit(node : Var) @str << node.name + false end def visit(node : ProcLiteral) @@ -837,35 +845,18 @@ module Crystal def visit(node : Self) @str << "self" + false end def visit(node : Path) @str << "::" if node.global? node.names.join(@str, "::") + false end def visit(node : Generic) name = node.name - if @inside_lib && (name.is_a?(Path) && name.names.size == 1) - case name.names.first - when "Pointer" - node.type_vars.first.accept self - @str << '*' - return false - when "StaticArray" - if node.type_vars.size == 2 - node.type_vars[0].accept self - @str << '[' - node.type_vars[1].accept self - @str << ']' - return false - end - else - # Not a special type - end - end - node.name.accept self printed_arg = false @@ -927,6 +918,7 @@ module Crystal def visit(node : InstanceVar) @str << node.name + false end def visit(node : ReadInstanceVar) @@ -938,6 +930,7 @@ module Crystal def visit(node : ClassVar) @str << node.name + false end def visit(node : Yield) @@ -1125,15 +1118,14 @@ module Crystal def visit(node : Global) @str << node.name + false end def visit(node : LibDef) @str << "lib " node.name.accept self newline - @inside_lib = true accept_with_indent(node.body) - @inside_lib = false append_indent @str << "end" false @@ -1170,7 +1162,6 @@ module Crystal if body = node.body newline accept_with_indent body - newline append_indent @str << "end" end @@ -1472,6 +1463,7 @@ module Crystal def visit(node : MagicConstant) @str << node.name + false end def visit(node : Asm) diff --git a/src/compiler/crystal/tools/expand.cr b/src/compiler/crystal/tools/expand.cr index 365fc2b3f865..792d60869bd3 100644 --- a/src/compiler/crystal/tools/expand.cr +++ b/src/compiler/crystal/tools/expand.cr @@ -144,6 +144,8 @@ module Crystal else contains_target(node) end + else + false end end @@ -156,6 +158,8 @@ module Crystal else contains_target(node) end + else + false end end diff --git a/src/compiler/crystal/tools/flags.cr b/src/compiler/crystal/tools/flags.cr new file mode 100644 index 000000000000..17bb15007021 --- /dev/null +++ b/src/compiler/crystal/tools/flags.cr @@ -0,0 +1,104 @@ +require "colorize" +require "../syntax/ast" + +class Crystal::Command + private def flags + OptionParser.parse(@options) do |opts| + opts.banner = "Usage: crystal tool flags [path...]\n\nOptions:" + + opts.on("-h", "--help", "Show this message") do + puts opts + exit + end + + opts.on("--no-color", "Disable colored output") do + @color = false + end + end + + visitor = FlagsVisitor.new + find_sources(options) do |source| + Parser.parse(source.code).accept(visitor) + end + visitor.flag_names.each do |flag| + puts flag + end + end + + def find_sources( + paths : Array(String), + stdin : IO = STDIN, + & : Compiler::Source -> + ) : Nil + stdin_content = nil + paths.each do |path| + if path == "-" + stdin_content ||= stdin.gets_to_end + yield Compiler::Source.new(path, stdin_content) + elsif File.file?(path) + yield Compiler::Source.new(path, File.read(path)) + elsif Dir.exists?(path) + Dir.glob(::Path[path].to_posix.join("**/*.cr")) do |dir_path| + if File.file?(dir_path) + yield Compiler::Source.new(path, File.read(dir_path)) + end + end + else + Crystal.error "file or directory does not exist: #{path}", @color, leading_error: false + end + end + end + + class FlagsVisitor < Visitor + @in_macro_expression = false + + getter all_flags = [] of ASTNode + + def initialize(@flag_name : String = "flag?") + end + + def flag_names + all_flags.map { |flag| string_flag(flag) }.uniq!.sort! + end + + private def string_flag(node) + case node + when StringLiteral, SymbolLiteral + node.value + else + node.to_s + end + end + + def visit(node) + true + end + + def visit(node : Crystal::MacroExpression | Crystal::MacroIf | Crystal::MacroFor) + @in_macro_expression = true + + true + end + + def end_visit(node : Crystal::MacroExpression | Crystal::MacroIf | Crystal::MacroFor) + @in_macro_expression = false + end + + def visit(node : Crystal::Call) + check_call(node) + true + end + + private def check_call(node) + return unless @in_macro_expression + return unless node.name == @flag_name + return unless node.obj.nil? && node.block.nil? && node.named_args.nil? + + args = node.args + return unless args.size == 1 + arg = args[0] + + all_flags << arg + end + end +end diff --git a/src/compiler/crystal/tools/formatter.cr b/src/compiler/crystal/tools/formatter.cr index fc3be7a4cf66..f7ebf63be7d2 100644 --- a/src/compiler/crystal/tools/formatter.cr +++ b/src/compiler/crystal/tools/formatter.cr @@ -4256,7 +4256,7 @@ module Crystal skip_space_or_newline end - write " " unless a_def.args.empty? && !return_type + write " " if a_def.args.present? || return_type || flag?("proc_literal_whitespace") is_do = false if @token.keyword?(:do) @@ -4264,6 +4264,7 @@ module Crystal is_do = true else write_token :OP_LCURLY + write " " if a_def.body.is_a?(Nop) && flag?("proc_literal_whitespace") end skip_space @@ -4369,6 +4370,7 @@ module Crystal skip_space if @token.type.newline? + @indent += 2 consume_newlines has_newlines = true end @@ -4377,7 +4379,7 @@ module Crystal string = StringLiteral.new(node.text) if has_newlines - write_indent(@indent + 2, string) + write_indent(@indent, string) else indent(@column, string) end @@ -4385,8 +4387,8 @@ module Crystal skip_space if @token.type.newline? + consume_newlines if node.outputs || node.inputs - consume_newlines column += 4 write_indent(column) end @@ -4418,7 +4420,8 @@ module Crystal write_token :OP_COLON part_index += 1 end - skip_space_or_newline + skip_space + consume_newlines case part_index when 1 @@ -4456,7 +4459,9 @@ module Crystal skip_space_or_newline if has_newlines - write_line + @indent -= 2 + + write_line unless @wrote_newline write_indent end @@ -4479,7 +4484,12 @@ module Crystal end def visit_asm_parts(parts, colon_column, &) : Nil - write " " + if @wrote_newline + write_indent + else + write " " + end + column = @column parts.each_with_index do |part, i| diff --git a/src/compiler/crystal/tools/implementations.cr b/src/compiler/crystal/tools/implementations.cr index f4f3a390f0eb..e2dbee001346 100644 --- a/src/compiler/crystal/tools/implementations.cr +++ b/src/compiler/crystal/tools/implementations.cr @@ -114,6 +114,7 @@ module Crystal @locations << target_def.location.not_nil! end end + false end def visit(node : Path) @@ -123,6 +124,7 @@ module Crystal target.try &.locations.try &.each do |loc| @locations << loc end + false end def visit(node) diff --git a/src/compiler/crystal/tools/print_types_visitor.cr b/src/compiler/crystal/tools/print_types_visitor.cr index 6ffc533a4b0f..0744dc17febd 100644 --- a/src/compiler/crystal/tools/print_types_visitor.cr +++ b/src/compiler/crystal/tools/print_types_visitor.cr @@ -39,10 +39,12 @@ module Crystal def visit(node : Var) output_name node + false end def visit(node : Global) output_name node + false end def visit(node : TypeDeclaration) @@ -50,6 +52,7 @@ module Crystal if var.is_a?(Var) output_name var end + false end def visit(node : UninitializedVar) @@ -57,6 +60,7 @@ module Crystal if var.is_a?(Var) output_name var end + false end def output_name(node) diff --git a/src/compiler/crystal/tools/unreachable.cr b/src/compiler/crystal/tools/unreachable.cr index f89f90e4c37d..a8886fecf596 100644 --- a/src/compiler/crystal/tools/unreachable.cr +++ b/src/compiler/crystal/tools/unreachable.cr @@ -15,8 +15,8 @@ module Crystal unreachable.excludes.concat CrystalPath.default_paths.map { |path| ::Path[path].expand.to_posix.to_s } unreachable.excludes.concat config.excludes.map { |path| ::Path[path].expand.to_posix.to_s } - defs = unreachable.process(result) - defs.sort_by! do |a_def| + tallies = unreachable.process(result) + tallies.sort_by! do |a_def, _| location = a_def.location.not_nil! { location.filename.as(String), @@ -25,15 +25,15 @@ module Crystal } end - UnreachablePresenter.new(defs, format: config.output_format).to_s(STDOUT) + UnreachablePresenter.new(tallies, format: config.output_format, print_tallies: config.tallies).to_s(STDOUT) if config.check - exit 1 unless defs.empty? + exit 1 if tallies.any?(&.[1].zero?) end end end - record UnreachablePresenter, defs : Array(Def), format : String? do + record UnreachablePresenter, tallies : Array({Def, Int32}), format : String?, print_tallies : Bool do include JSON::Serializable def to_s(io) @@ -49,16 +49,19 @@ module Crystal def each(&) current_dir = Dir.current - defs.each do |a_def| + tallies.each do |a_def, count| + next unless print_tallies || count.zero? + location = a_def.location.not_nil! filename = ::Path[location.filename.as(String)].relative_to(current_dir).to_s location = Location.new(filename, location.line_number, location.column_number) - yield a_def, location + yield a_def, location, count end end def to_text(io) - each do |a_def, location| + each do |a_def, location, count| + io << count << "\t" if print_tallies io << location << "\t" io << a_def.short_reference << "\t" io << a_def.length << " lines" @@ -72,13 +75,14 @@ module Crystal def to_json(builder : JSON::Builder) builder.array do - each do |a_def, location| + each do |a_def, location, count| builder.object do builder.field "name", a_def.short_reference builder.field "location", location.to_s if lines = a_def.length builder.field "lines", lines end + builder.field "count", count if print_tallies if annotations = a_def.all_annotations builder.field "annotations", annotations.map(&.to_s) end @@ -89,9 +93,14 @@ module Crystal def to_csv(io) CSV.build(io) do |builder| - builder.row %w[name file line column length annotations] - each do |a_def, location| + builder.row do |row| + row << "count" if print_tallies + row.concat %w[name file line column length annotations] + end + + each do |a_def, location, count| builder.row do |row| + row << count if print_tallies row << a_def.short_reference row << location.filename row << location.line_number @@ -111,8 +120,8 @@ module Crystal # Then it traverses all types and their defs and reports those that are not # in `@used_def_locations` (and match the filter). class UnreachableVisitor < Visitor - @used_def_locations = Set(Location).new - @defs : Set(Def) = Set(Def).new.compare_by_identity + @used_def_locations = Hash(Location, Int32).new(0) + @tallies : Hash(Def, Int32) = Hash(Def, Int32).new.compare_by_identity @visited : Set(ASTNode) = Set(ASTNode).new.compare_by_identity property includes = [] of String @@ -130,14 +139,14 @@ module Crystal process_type(type.metaclass) if type.metaclass != type end - def process(result : Compiler::Result) : Array(Def) - @defs.clear + def process(result : Compiler::Result) : Array({Def, Int32}) + @tallies.clear result.node.accept(self) process_type(result.program) - @defs.to_a + @tallies.to_a end def visit(node) @@ -163,7 +172,7 @@ module Crystal node.target_defs.try &.each do |a_def| if (location = a_def.location) - @used_def_locations << location if interested_in(location) + @used_def_locations.update(location, &.+(1)) if interested_in(location) end if @visited.add?(a_def) @@ -199,11 +208,10 @@ module Crystal check_def(previous) if previous && !a_def.calls_previous_def? - return if @used_def_locations.includes?(a_def.location) - - check_def(previous) if previous && a_def.calls_previous_def? + tally = @used_def_locations[a_def.location] + @tallies[a_def] = tally - @defs << a_def + check_def(previous) if previous && a_def.calls_previous_def? && tally == 0 end private def interested_in(location) diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr index ad9f3d391fa6..5d903b763050 100644 --- a/src/compiler/crystal/types.cr +++ b/src/compiler/crystal/types.cr @@ -555,7 +555,7 @@ module Crystal program.tuple, program.named_tuple, program.pointer, program.static_array, program.union, program.enum, program.proc, - PrimitiveType + PrimitiveType, GenericReferenceStorageType false else true @@ -2642,6 +2642,33 @@ module Crystal end end + # The non-instantiated ReferenceStorage(T) type. + class GenericReferenceStorageType < GenericClassType + @struct = true + + def new_generic_instance(program, generic_type, type_vars) + type_param = self.type_vars.first + t = type_vars[type_param].type + + unless t.is_a?(TypeParameter) || (t.class? && !t.struct?) + raise TypeException.new "Can't instantiate ReferenceStorage(#{type_param}) with #{type_param} = #{t} (#{type_param} must be a reference type)" + end + + ReferenceStorageType.new program, t, self, type_param + end + end + + class ReferenceStorageType < GenericClassInstanceType + getter reference_type : Type + + def initialize(program, @reference_type, generic_type, type_param) + t_var = Var.new("T", @reference_type) + t_var.bind_to t_var + + super(program, generic_type, program.value, {type_param => t_var} of String => ASTNode) + end + end + # A lib type, like `lib LibC`. class LibType < ModuleType getter link_annotations : Array(LinkAnnotation)? diff --git a/src/crystal/interpreter.cr b/src/crystal/interpreter.cr index 2a9a6b23c5f8..d3b3589d50cb 100644 --- a/src/crystal/interpreter.cr +++ b/src/crystal/interpreter.cr @@ -19,5 +19,10 @@ module Crystal @[Primitive(:interpreter_spawn)] def self.spawn(fiber : Fiber, fiber_main : Void*) : Void* end + + # Returns the resumable value from the interpreter's fiber. + @[Primitive(:interpreter_fiber_resumable)] + def self.fiber_resumable(context) : LibC::Long + end end end diff --git a/src/crystal/lib_iconv.cr b/src/crystal/lib_iconv.cr index a180a770a67a..5f1506758454 100644 --- a/src/crystal/lib_iconv.cr +++ b/src/crystal/lib_iconv.cr @@ -5,6 +5,9 @@ require "c/stddef" {% end %} @[Link("iconv")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "libiconv.dll")] +{% end %} lib LibIconv type IconvT = Void* diff --git a/src/crystal/scheduler.cr b/src/crystal/scheduler.cr index ce06e3c60275..1728a9b7f335 100644 --- a/src/crystal/scheduler.cr +++ b/src/crystal/scheduler.cr @@ -2,6 +2,7 @@ require "crystal/system/event_loop" require "crystal/system/print_error" require "./fiber_channel" require "fiber" +require "fiber/stack_pool" require "crystal/system/thread" # :nodoc: @@ -13,6 +14,11 @@ require "crystal/system/thread" # protected and must never be called directly. class Crystal::Scheduler @event_loop = Crystal::EventLoop.create + @stack_pool = Fiber::StackPool.new + + def self.stack_pool : Fiber::StackPool + Thread.current.scheduler.@stack_pool + end def self.event_loop Thread.current.scheduler.@event_loop @@ -83,15 +89,8 @@ class Crystal::Scheduler {% end %} end - {% if flag?(:preview_mt) %} - def self.enqueue_free_stack(stack : Void*) : Nil - Thread.current.scheduler.enqueue_free_stack(stack) - end - {% end %} - {% if flag?(:preview_mt) %} private getter(fiber_channel : Crystal::FiberChannel) { Crystal::FiberChannel.new } - @free_stacks = Deque(Void*).new {% end %} @main : Fiber @@ -126,14 +125,6 @@ class Crystal::Scheduler {% end %} current, @current = @current, fiber - - {% if flag?(:interpreted) %} - # TODO: ideally we could set this in the interpreter if the - # @context had a pointer back to the fiber. - # I also wonder why this isn't done always like that instead of in asm. - current.@context.resumable = 1 - {% end %} - Fiber.swapcontext(pointerof(current.@context), pointerof(fiber.@context)) {% if flag?(:preview_mt) %} @@ -157,18 +148,6 @@ class Crystal::Scheduler exit 1 end - {% if flag?(:preview_mt) %} - protected def enqueue_free_stack(stack) - @free_stacks.push stack - end - - private def release_free_stacks - while stack = @free_stacks.shift? - Fiber.stack_pool.release stack - end - end - {% end %} - protected def reschedule : Nil loop do if runnable = @lock.sync { @runnables.shift? } @@ -178,10 +157,6 @@ class Crystal::Scheduler @event_loop.run_once end end - - {% if flag?(:preview_mt) %} - release_free_stacks - {% end %} end protected def sleep(time : Time::Span) : Nil @@ -207,6 +182,8 @@ class Crystal::Scheduler end def run_loop + spawn_stack_pool_collector + fiber_channel = self.fiber_channel loop do @lock.lock @@ -239,7 +216,7 @@ class Crystal::Scheduler @lock.unlock end - def self.init_workers + def self.init : Nil count = worker_count pending = Atomic(Int32).new(count - 1) @@workers = Array(Thread).new(count) do |i| @@ -249,7 +226,7 @@ class Crystal::Scheduler Thread.current.scheduler.enqueue worker_loop Thread.current else - Thread.new do + Thread.new(name: "CRYSTAL-MT-#{i}") do scheduler = Thread.current.scheduler pending.sub(1) scheduler.run_loop @@ -281,5 +258,18 @@ class Crystal::Scheduler 4 end end + {% else %} + def self.init : Nil + {% unless flag?(:interpreted) %} + Thread.current.scheduler.spawn_stack_pool_collector + {% end %} + end {% end %} + + # Background loop to cleanup unused fiber stacks. + def spawn_stack_pool_collector + fiber = Fiber.new(name: "Stack pool collector", &->@stack_pool.collect_loop) + {% if flag?(:preview_mt) %} fiber.set_current_thread {% end %} + enqueue(fiber) + end end diff --git a/src/crystal/system/print_error.cr b/src/crystal/system/print_error.cr index 18f68d923507..3832eed5d9f4 100644 --- a/src/crystal/system/print_error.cr +++ b/src/crystal/system/print_error.cr @@ -1,15 +1,152 @@ module Crystal::System - # Prints directly to stderr without going through an IO. + # Prints directly to stderr without going through an `IO::FileDescriptor`. # This is useful for error messages from components that are required for # IO to work (fibers, scheduler, event_loop). def self.print_error(message, *args) - {% if flag?(:unix) %} - LibC.dprintf 2, message, *args - {% elsif flag?(:win32) %} - buffer = StaticArray(UInt8, 512).new(0_u8) - len = LibC.snprintf(buffer, buffer.size, message, *args) - LibC._write 2, buffer, len - {% end %} + print_error(message, *args) do |bytes| + {% if flag?(:unix) || flag?(:wasm32) %} + LibC.write 2, bytes, bytes.size + {% elsif flag?(:win32) %} + LibC._write 2, bytes, bytes.size + {% end %} + end + end + + # Minimal drop-in replacement for a C `printf` function. Yields successive + # non-empty `Bytes` to the block, which should do the actual printing. + # + # *format* only supports the `%(l|ll)?[dpsux]` format specifiers; more should + # be added only when we need them or an external library passes its own format + # string to here. *format* must also be null-terminated. + # + # Since this method may be called under low memory conditions or even with a + # corrupted heap, its implementation should be as low-level as possible, + # avoiding memory allocations. + # + # NOTE: C's `printf` is incompatible with Crystal's `sprintf`, because the + # latter does not support argument width specifiers nor `%p`. + def self.print_error(format, *args, &) + format = to_string_slice(format) + format_len = format.size + ptr = format.to_unsafe + finish = ptr + format_len + arg_index = 0 + + while ptr < finish + next_percent = ptr + while next_percent < finish && !(next_percent.value === '%') + next_percent += 1 + end + unless next_percent == ptr + yield Slice.new(ptr, next_percent - ptr) + end + + fmt_ptr = next_percent + 1 + width = 0 + if fmt_ptr.value === 'l' + width = 1 + fmt_ptr += 1 + if fmt_ptr.value === 'l' + width = 2 + fmt_ptr += 1 + end + end + + break unless fmt_ptr < finish + + case fmt_ptr.value + when 's' + read_arg(String | Pointer(UInt8)) do |arg| + yield to_string_slice(arg) + end + when 'd' + read_arg(Int::Primitive) do |arg| + to_int_slice(arg, 10, true, width) { |bytes| yield bytes } + end + when 'u' + read_arg(Int::Primitive) do |arg| + to_int_slice(arg, 10, false, width) { |bytes| yield bytes } + end + when 'x' + read_arg(Int::Primitive) do |arg| + to_int_slice(arg, 16, false, width) { |bytes| yield bytes } + end + when 'p' + read_arg(Pointer(Void)) do |arg| + # NOTE: MSVC uses `%X` rather than `0x%x`, we follow the latter on all platforms + yield "0x".to_slice + to_int_slice(arg.address, 16, false, 2) { |bytes| yield bytes } + end + else + yield Slice.new(next_percent, fmt_ptr + 1 - next_percent) + end + + ptr = fmt_ptr + 1 + end + end + + private macro read_arg(type, &block) + {{ block.args[0] }} = args[arg_index].as?({{ type }}) + if !{{ block.args[0] }}.nil? + {{ block.body }} + else + yield "(???)".to_slice + end + arg_index += 1 + end + + private def self.to_string_slice(str) + if str.is_a?(UInt8*) + if str.null? + "(null)".to_slice + else + Slice.new(str, LibC.strlen(str)) + end + else + str.to_s.to_slice + end + end + + # simplified version of `Int#internal_to_s` + private def self.to_int_slice(num, base, signed, width, &) + if num == 0 + yield "0".to_slice + return + end + + # Given sizeof(num) <= 64 bits, we need at most 20 bytes for `%d` or `%u` + # note that `chars` does not have to be null-terminated, since we are + # only yielding a `Bytes` + chars = uninitialized UInt8[20] + ptr_end = chars.to_unsafe + 20 + ptr = ptr_end + + num = case {signed, width} + when {true, 2} then LibC::LongLong.new!(num) + when {true, 1} then LibC::Long.new!(num) + when {true, 0} then LibC::Int.new!(num) + when {false, 2} then LibC::ULongLong.new!(num) + when {false, 1} then LibC::ULong.new!(num) + else LibC::UInt.new!(num) + end + + neg = num < 0 + + # do not assume Crystal constant initialization succeeds, hence not `DIGITS` + digits = "0123456789abcdef".to_unsafe + + while num != 0 + ptr -= 1 + ptr.value = digits[num.remainder(base).abs] + num = num.tdiv(base) + end + + if neg + ptr -= 1 + ptr.value = '-'.ord.to_u8 + end + + yield Slice.new(ptr, ptr_end - ptr) end def self.print_exception(message, ex) diff --git a/src/crystal/system/signal.cr b/src/crystal/system/signal.cr index b5ba591b2ec5..a5e3eca885da 100644 --- a/src/crystal/system/signal.cr +++ b/src/crystal/system/signal.cr @@ -2,6 +2,9 @@ module Crystal::System::Signal # Sets the handler for this signal to the passed function. # def self.trap(signal, handler) : Nil + # Returns any existing handler set on the signal + # def self.trap_handler?(signal) + # Resets the handler for this signal to the OS default. # def self.reset(signal) : Nil diff --git a/src/crystal/system/thread.cr b/src/crystal/system/thread.cr index 88784ed68330..b40a7dceb32b 100644 --- a/src/crystal/system/thread.cr +++ b/src/crystal/system/thread.cr @@ -17,6 +17,8 @@ module Crystal::System::Thread # private def system_close # private def stack_address : Void* + + # private def system_name=(String) : String end {% if flag?(:wasi) %} @@ -49,12 +51,14 @@ class Thread # :nodoc: property previous : Thread? + getter name : String? + def self.unsafe_each(&) threads.unsafe_each { |thread| yield thread } end # Creates and starts a new system thread. - def initialize(&@func : ->) + def initialize(@name : String? = nil, &@func : ->) @system_handle = uninitialized Crystal::System::Thread::Handle init_handle end @@ -104,6 +108,12 @@ class Thread Crystal::System::Thread.yield_current end + # Changes the name of the current thread. + def self.name=(name : String) : String + thread = Thread.current + thread.name = name + end + # :nodoc: getter scheduler : Crystal::Scheduler { Crystal::Scheduler.new(self) } @@ -112,6 +122,10 @@ class Thread Thread.current = self @main_fiber = fiber = Fiber.new(stack_address, self) + if name = @name + self.system_name = name + end + begin @func.call rescue ex @@ -123,6 +137,10 @@ class Thread end end + protected def name=(@name : String) + self.system_name = name + end + # Holds the GC thread handler property gc_thread_handler : Void* = Pointer(Void).null end diff --git a/src/crystal/system/unix/fiber.cr b/src/crystal/system/unix/fiber.cr index 17cbe5c07fdb..2a06b3d3d1a1 100644 --- a/src/crystal/system/unix/fiber.cr +++ b/src/crystal/system/unix/fiber.cr @@ -3,7 +3,7 @@ require "c/sys/mman" module Crystal::System::Fiber def self.allocate_stack(stack_size) : Void* flags = LibC::MAP_PRIVATE | LibC::MAP_ANON - {% if flag?(:openbsd) && !flag?(:"openbsd6.2") %} + {% if flag?(:openbsd) %} flags |= LibC::MAP_STACK {% end %} diff --git a/src/crystal/system/unix/pthread.cr b/src/crystal/system/unix/pthread.cr index ca16080621e3..5d6e2a332adc 100644 --- a/src/crystal/system/unix/pthread.cr +++ b/src/crystal/system/unix/pthread.cr @@ -112,6 +112,23 @@ module Crystal::System::Thread address end + + # Warning: must be called from the current thread itself, because Darwin + # doesn't allow to set the name of any thread but the current one! + private def system_name=(name : String) : String + {% if flag?(:darwin) %} + LibC.pthread_setname_np(name) + {% elsif flag?(:netbsd) %} + LibC.pthread_setname_np(@system_handle, name, nil) + {% elsif LibC.has_method?(:pthread_setname_np) %} + LibC.pthread_setname_np(@system_handle, name) + {% elsif LibC.has_method?(:pthread_set_name_np) %} + LibC.pthread_set_name_np(@system_handle, name) + {% else %} + {% raise "No `Crystal::System::Thread#system_name` implementation available" %} + {% end %} + name + end end # In musl (alpine) the calls to unwind API segfaults diff --git a/src/crystal/system/unix/signal.cr b/src/crystal/system/unix/signal.cr index 06422e36f7b6..dfb1c1af8cb8 100644 --- a/src/crystal/system/unix/signal.cr +++ b/src/crystal/system/unix/signal.cr @@ -15,7 +15,7 @@ module Crystal::System::Signal @@pipe = IO.pipe(read_blocking: false, write_blocking: true) @@handlers = {} of ::Signal => Handler @@sigset = Sigset.new - class_setter child_handler : Handler? + class_property child_handler : Handler? @@mutex = Mutex.new(:unchecked) def self.trap(signal, handler) : Nil @@ -30,6 +30,10 @@ module Crystal::System::Signal end end + def self.trap_handler?(signal) + @@mutex.synchronize { @@handlers[signal]? } + end + def self.reset(signal) : Nil set(signal, LibC::SIG_DFL) end @@ -149,7 +153,7 @@ module Crystal::System::Signal if is_stack_overflow Crystal::System.print_error "Stack overflow (e.g., infinite or very deep recursion)\n" else - Crystal::System.print_error "Invalid memory access (signal %d) at address 0x%lx\n", sig, addr + Crystal::System.print_error "Invalid memory access (signal %d) at address %p\n", sig, addr end Exception::CallStack.print_backtrace diff --git a/src/crystal/system/wasi/signal.cr b/src/crystal/system/wasi/signal.cr index d66b9c22c5cd..35675ce14f34 100644 --- a/src/crystal/system/wasi/signal.cr +++ b/src/crystal/system/wasi/signal.cr @@ -3,6 +3,10 @@ module Crystal::System::Signal raise NotImplementedError.new("Crystal::System::Signal.trap") end + def self.trap_handler?(signal) + raise NotImplementedError.new("Crystal::System::Signal.trap_handler?") + end + def self.reset(signal) : Nil raise NotImplementedError.new("Crystal::System::Signal.reset") end diff --git a/src/crystal/system/win32/file_descriptor.cr b/src/crystal/system/win32/file_descriptor.cr index 6e4f42d46b17..109c353c0325 100644 --- a/src/crystal/system/win32/file_descriptor.cr +++ b/src/crystal/system/win32/file_descriptor.cr @@ -11,7 +11,10 @@ module Crystal::System::FileDescriptor @system_blocking = true private def unbuffered_read(slice : Bytes) - if system_blocking? + handle = windows_handle + if ConsoleUtils.console?(handle) + ConsoleUtils.read(handle, slice) + elsif system_blocking? bytes_read = LibC._read(fd, slice, slice.size) if bytes_read == -1 if Errno.value == Errno::EBADF @@ -22,7 +25,6 @@ module Crystal::System::FileDescriptor end bytes_read else - handle = windows_handle overlapped_operation(handle, "ReadFile", read_timeout) do |overlapped| ret = LibC.ReadFile(handle, slice, slice.size, out byte_count, overlapped) {ret, byte_count} @@ -276,6 +278,71 @@ module Crystal::System::FileDescriptor end end +private module ConsoleUtils + # N UTF-16 code units correspond to no more than 3*N UTF-8 code units. + # NOTE: For very large buffers, `ReadConsoleW` may fail. + private BUFFER_SIZE = 10000 + @@utf8_buffer = Slice(UInt8).new(3 * BUFFER_SIZE) + + # `@@buffer` points to part of `@@utf8_buffer`. + # It represents data that has not been read yet. + @@buffer : Bytes = @@utf8_buffer[0, 0] + + # Remaining UTF-16 code unit. + @@remaining_unit : UInt16? + + # Determines if *handle* is a console. + def self.console?(handle : LibC::HANDLE) : Bool + LibC.GetConsoleMode(handle, out _) != 0 + end + + # Reads to *slice* from the console specified by *handle*, + # and return the actual number of bytes read. + def self.read(handle : LibC::HANDLE, slice : Bytes) : Int32 + return 0 if slice.empty? + fill_buffer(handle) if @@buffer.empty? + + bytes_read = {slice.size, @@buffer.size}.min + @@buffer[0, bytes_read].copy_to(slice) + @@buffer += bytes_read + bytes_read + end + + private def self.fill_buffer(handle : LibC::HANDLE) : Nil + utf16_buffer = uninitialized UInt16[BUFFER_SIZE] + remaining_unit = @@remaining_unit + if remaining_unit + utf16_buffer[0] = remaining_unit + index = read_console(handle, utf16_buffer.to_slice + 1) + else + index = read_console(handle, utf16_buffer.to_slice) - 1 + end + + if index >= 0 && utf16_buffer[index] & 0xFC00 == 0xD800 + @@remaining_unit = utf16_buffer[index] + index -= 1 + else + @@remaining_unit = nil + end + return if index < 0 + + appender = @@utf8_buffer.to_unsafe.appender + String.each_utf16_char(utf16_buffer.to_slice[..index]) do |char| + char.each_byte do |byte| + appender << byte + end + end + @@buffer = @@utf8_buffer[0, appender.size] + end + + private def self.read_console(handle : LibC::HANDLE, slice : Slice(UInt16)) : Int32 + if 0 == LibC.ReadConsoleW(handle, slice, slice.size, out units_read, nil) + raise IO::Error.from_winerror("ReadConsoleW") + end + units_read.to_i32 + end +end + # Enable UTF-8 console I/O for the duration of program execution if LibC.IsValidCodePage(LibC::CP_UTF8) != 0 old_input_cp = LibC.GetConsoleCP diff --git a/src/crystal/system/win32/path.cr b/src/crystal/system/win32/path.cr index a5e60db82576..06f9346a2bae 100644 --- a/src/crystal/system/win32/path.cr +++ b/src/crystal/system/win32/path.cr @@ -6,12 +6,16 @@ module Crystal::System::Path def self.home : String if home_path = ENV["USERPROFILE"]?.presence home_path - elsif LibC.SHGetKnownFolderPath(pointerof(LibC::FOLDERID_Profile), 0, nil, out path_ptr) == 0 - home_path, _ = String.from_utf16(path_ptr) - LibC.CoTaskMemFree(path_ptr) - home_path else - raise RuntimeError.from_winerror("SHGetKnownFolderPath") + # TODO: interpreter doesn't implement pointerof(Path)` yet + folderid = LibC::FOLDERID_Profile + if LibC.SHGetKnownFolderPath(pointerof(folderid), 0, nil, out path_ptr) == 0 + home_path, _ = String.from_utf16(path_ptr) + LibC.CoTaskMemFree(path_ptr) + home_path + else + raise RuntimeError.from_winerror("SHGetKnownFolderPath") + end end end end diff --git a/src/crystal/system/win32/signal.cr b/src/crystal/system/win32/signal.cr index 8f5541c7599b..d805ea4fd1ab 100644 --- a/src/crystal/system/win32/signal.cr +++ b/src/crystal/system/win32/signal.cr @@ -5,6 +5,10 @@ module Crystal::System::Signal raise NotImplementedError.new("Crystal::System::Signal.trap") end + def self.trap_handler?(signal) + raise NotImplementedError.new("Crystal::System::Signal.trap_handler?") + end + def self.reset(signal) : Nil raise NotImplementedError.new("Crystal::System::Signal.reset") end diff --git a/src/crystal/system/win32/thread.cr b/src/crystal/system/win32/thread.cr index 9a13bfb4dc03..2b44f66c28ce 100644 --- a/src/crystal/system/win32/thread.cr +++ b/src/crystal/system/win32/thread.cr @@ -12,13 +12,24 @@ module Crystal::System::Thread @system_handle = GC.beginthreadex( security: Pointer(Void).null, stack_size: LibC::UInt.zero, - start_address: ->(data : Void*) { data.as(::Thread).start; LibC::UInt.zero }, + start_address: ->Thread.thread_proc(Void*), arglist: self.as(Void*), initflag: LibC::UInt.zero, thrdaddr: Pointer(LibC::UInt).null, ) end + def self.thread_proc(data : Void*) : LibC::UInt + # ensure that even in the case of stack overflow there is enough reserved + # stack space for recovery (for the main thread this is done in + # `Exception::CallStack.setup_crash_handler`) + stack_size = Crystal::System::Fiber::RESERVED_STACK_SIZE + LibC.SetThreadStackGuarantee(pointerof(stack_size)) + + data.as(::Thread).start + LibC::UInt.zero + end + def self.current_handle : Handle # `GetCurrentThread` returns a _constant_ and is only meaningful as an # argument to Win32 APIs; to uniquely identify it we must duplicate the handle @@ -61,4 +72,11 @@ module Crystal::System::Thread low_limit {% end %} end + + private def system_name=(name : String) : String + {% if LibC.has_method?(:SetThreadDescription) %} + LibC.SetThreadDescription(@system_handle, System.to_wstr(name)) + {% end %} + name + end end diff --git a/src/enumerable.cr b/src/enumerable.cr index c7b566e647e4..9a1aad3debd0 100644 --- a/src/enumerable.cr +++ b/src/enumerable.cr @@ -636,11 +636,7 @@ module Enumerable(T) h = Hash(U, Array(T)).new each do |e| v = yield e - if h.has_key?(v) - h[v].push(e) - else - h[v] = [e] - end + h.put_if_absent(v) { Array(T).new } << e end h end @@ -1997,9 +1993,18 @@ module Enumerable(T) # ``` # (1..5).to_a # => [1, 2, 3, 4, 5] # ``` - def to_a - ary = [] of T - each { |e| ary << e } + def to_a : Array(T) + to_a(&.itself) + end + + # Returns an `Array` with the results of running *block* against each element of the collection. + # + # ``` + # (1..5).to_a { |i| i * 2 } # => [2, 4, 6, 8, 10] + # ``` + def to_a(& : T -> U) : Array(U) forall U + ary = [] of U + each { |e| ary << yield e } ary end diff --git a/src/exception/call_stack/libunwind.cr b/src/exception/call_stack/libunwind.cr index 220db21b71f0..9f17512491fe 100644 --- a/src/exception/call_stack/libunwind.cr +++ b/src/exception/call_stack/libunwind.cr @@ -102,7 +102,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 + Crystal::System.print_error "[%p] ", repeated_frame.ip print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" diff --git a/src/exception/call_stack/stackwalk.cr b/src/exception/call_stack/stackwalk.cr index f49c87fae623..47b78e0ee0df 100644 --- a/src/exception/call_stack/stackwalk.cr +++ b/src/exception/call_stack/stackwalk.cr @@ -37,7 +37,7 @@ struct Exception::CallStack case exception_info.value.exceptionRecord.value.exceptionCode when LibC::EXCEPTION_ACCESS_VIOLATION addr = exception_info.value.exceptionRecord.value.exceptionInformation[1] - Crystal::System.print_error "Invalid memory access (C0000005) at address 0x%llx\n", addr + Crystal::System.print_error "Invalid memory access (C0000005) at address %p\n", Pointer(Void).new(addr) print_backtrace(exception_info) LibC._exit(1) when LibC::EXCEPTION_STACK_OVERFLOW @@ -51,7 +51,8 @@ struct Exception::CallStack end) # ensure that even in the case of stack overflow there is enough reserved - # stack space for recovery + # stack space for recovery (for other threads this is done in + # `Crystal::System::Thread.thread_proc`) stack_size = Crystal::System::Fiber::RESERVED_STACK_SIZE LibC.SetThreadStackGuarantee(pointerof(stack_size)) end @@ -150,7 +151,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 + Crystal::System.print_error "[%p] ", repeated_frame.ip print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" diff --git a/src/fiber.cr b/src/fiber.cr index aa2af7bf2229..049b7e9bb0c0 100644 --- a/src/fiber.cr +++ b/src/fiber.cr @@ -1,6 +1,5 @@ require "crystal/system/thread_linked_list" require "./fiber/context" -require "./fiber/stack_pool" # :nodoc: @[NoInline] @@ -47,9 +46,6 @@ class Fiber # :nodoc: protected class_getter(fibers) { Thread::LinkedList(Fiber).new } - # :nodoc: - class_getter stack_pool = StackPool.new - @context : Context @stack : Void* @resume_event : Crystal::EventLoop::Event? @@ -89,10 +85,9 @@ class Fiber @context = Context.new @stack, @stack_bottom = {% if flag?(:interpreted) %} - # For interpreted mode we don't need a new stack, the stack is held by the interpreter {Pointer(Void).null, Pointer(Void).null} {% else %} - Fiber.stack_pool.checkout + Crystal::Scheduler.stack_pool.checkout {% end %} fiber_main = ->(f : Fiber) { f.run } @@ -145,22 +140,22 @@ class Fiber GC.unlock_read @proc.call rescue ex + io = {% if flag?(:preview_mt) %} + IO::Memory.new(4096) # PIPE_BUF + {% else %} + STDERR + {% end %} if name = @name - STDERR.print "Unhandled exception in spawn(name: #{name}): " + io << "Unhandled exception in spawn(name: " << name << "): " else - STDERR.print "Unhandled exception in spawn: " + io << "Unhandled exception in spawn: " end - ex.inspect_with_backtrace(STDERR) - STDERR.flush - ensure + ex.inspect_with_backtrace(io) {% if flag?(:preview_mt) %} - Crystal::Scheduler.enqueue_free_stack @stack - {% elsif flag?(:interpreted) %} - # For interpreted mode we don't need a new stack, the stack is held by the interpreter - {% else %} - Fiber.stack_pool.release(@stack) + STDERR.write(io.to_slice) {% end %} - + STDERR.flush + ensure # Remove the current fiber from the linked list Fiber.inactive(self) @@ -170,6 +165,9 @@ class Fiber @timeout_select_action = nil @alive = false + {% unless flag?(:interpreted) %} + Crystal::Scheduler.stack_pool.release(@stack) + {% end %} Crystal::Scheduler.reschedule end diff --git a/src/fiber/context.cr b/src/fiber/context.cr index 28b54458fe66..eab06d886de6 100644 --- a/src/fiber/context.cr +++ b/src/fiber/context.cr @@ -7,10 +7,26 @@ class Fiber @[Extern] struct Context property stack_top : Void* - property resumable : LibC::Long + + {% if flag?(:interpreted) %} + # In interpreted mode, the interpreted fibers will be backed by a real + # fiber run by the interpreter. The fiber context is thus fake. + # + # The `stack_top` property is actually a pointer to the real Fiber + # running in the interpreter. + # + # The `resumable` property is also delegated to the real fiber. Only the + # getter is defined (so we know the real state of the fiber); we don't + # declare a setter because only the interpreter can manipulate it (in the + # `makecontext` and `swapcontext` primitives). + def resumable : LibC::Long + Crystal::Interpreter.fiber_resumable(pointerof(@stack_top)) + end + {% else %} + property resumable : LibC::Long = 0 + {% end %} def initialize(@stack_top = Pointer(Void).null) - @resumable = 0 end end diff --git a/src/fiber/context/interpreted.cr b/src/fiber/context/interpreted.cr index 55b9354a1a57..900ad6f3111c 100644 --- a/src/fiber/context/interpreted.cr +++ b/src/fiber/context/interpreted.cr @@ -5,9 +5,9 @@ require "crystal/interpreter" class Fiber # :nodoc: def makecontext(stack_ptr, fiber_main) : Nil - # In interpreted mode the stack_top variable actually points to a fiber + # In interpreted mode the stack_top variable actually points to the actual + # fiber running on the interpreter @context.stack_top = Crystal::Interpreter.spawn(self, fiber_main.pointer) - @context.resumable = 1 end # :nodoc: diff --git a/src/fiber/stack_pool.cr b/src/fiber/stack_pool.cr index 54d03e4ffa5f..aebd82a0870f 100644 --- a/src/fiber/stack_pool.cr +++ b/src/fiber/stack_pool.cr @@ -7,14 +7,13 @@ class Fiber def initialize @deque = Deque(Void*).new - @mutex = Thread::Mutex.new end # Removes and frees at most *count* stacks from the top of the pool, # returning memory to the operating system. def collect(count = lazy_size // 2) : Nil count.times do - if stack = @mutex.synchronize { @deque.shift? } + if stack = @deque.shift? Crystal::System::Fiber.free_stack(stack, STACK_SIZE) else return @@ -22,21 +21,28 @@ class Fiber end end + def collect_loop(every = 5.seconds) : Nil + loop do + sleep every + collect + end + end + # Removes a stack from the bottom of the pool, or allocates a new one. def checkout : {Void*, Void*} - stack = @mutex.synchronize { @deque.pop? } || Crystal::System::Fiber.allocate_stack(STACK_SIZE) + stack = @deque.pop? || Crystal::System::Fiber.allocate_stack(STACK_SIZE) {stack, stack + STACK_SIZE} end # Appends a stack to the bottom of the pool. def release(stack) : Nil - @mutex.synchronize { @deque.push(stack) } + @deque.push(stack) end # Returns the approximated size of the pool. It may be equal or slightly # bigger or smaller than the actual size. def lazy_size : Int32 - @mutex.synchronize { @deque.size } + @deque.size end end end diff --git a/src/float/printer/ryu_printf.cr b/src/float/printer/ryu_printf.cr index d44a2fa8739b..feffb98fdb0e 100644 --- a/src/float/printer/ryu_printf.cr +++ b/src/float/printer/ryu_printf.cr @@ -1,5 +1,4 @@ -# FIXME: this leads to an OOB on wasm32 (#13918) -{% skip_file if flag?(:wasm32) %} +{% skip_file unless String::Formatter::HAS_RYU_PRINTF %} require "./ryu_printf_table" @@ -613,6 +612,76 @@ module Float::Printer::RyuPrintf index end + private MAX_FIXED_PRECISION = 66_u32 + private MAX_SCI_PRECISION = 766_u32 + + # Source port of Microsoft STL's `std::to_chars` based on: + # + # * https://github.com/ulfjack/ryu/pull/185/files + # * https://github.com/microsoft/STL/blob/a8888806c6960f1687590ffd4244794c753aa819/stl/inc/charconv#L2324 + # * https://github.com/llvm/llvm-project/blob/701f64790520790f75b1f948a752472d421ddaa3/libcxx/src/include/to_chars_floating_point.h#L836 + def self.d2gen_buffered_n(d : Float64, precision : UInt32, result : UInt8*, alternative : Bool = false) + if d == 0 + result[0] = '0'.ord.to_u8! + return {1, 0} + end + + precision = precision.clamp(1_u32, 1000000_u32) + if precision <= MAX_SPECIAL_P + table_begin = SPECIAL_X.to_unsafe + (precision &- 1) * (precision &+ 10) // 2 + table_length = precision.to_i32! &+ 5 + else + table_begin = ORDINARY_X.to_unsafe + table_length = {precision, MAX_ORDINARY_P}.min.to_i32! &+ 5 + end + + bits = d.unsafe_as(UInt64) + index = 0 + while index < table_length + break if bits <= table_begin[index] + index &+= 1 + end + + sci_exp_x = index &- 5 + use_fixed_notation = precision > sci_exp_x && sci_exp_x >= -4 + + significand_last = exponent_first = exponent_last = Pointer(UInt8).null + + # Write into the local buffer. + if use_fixed_notation + effective_precision = precision &- 1 &- sci_exp_x + max_precision = MAX_FIXED_PRECISION + len = d2fixed_buffered_n(d, {effective_precision, max_precision}.min, result) + significand_last = result + len + else + effective_precision = precision &- 1 + max_precision = MAX_SCI_PRECISION + len = d2exp_buffered_n(d, {effective_precision, max_precision}.min, result) + exponent_first = result + Slice.new(result, len).fast_index('e'.ord.to_u8!, 0).not_nil! + significand_last = exponent_first + exponent_last = result + len + end + + # If we printed a decimal point followed by digits, perform zero-trimming. + if effective_precision > 0 && !alternative + while significand_last[-1] === '0' # will stop at '.' or a nonzero digit + significand_last -= 1 + end + + if significand_last[-1] === '.' + significand_last -= 1 + end + end + + # Copy the exponent to the output range. + unless use_fixed_notation + exponent_first.move_to(significand_last, exponent_last - exponent_first) + end + + extra_zeros = effective_precision > max_precision ? effective_precision &- max_precision : 0_u32 + {(significand_last - result + (exponent_last - exponent_first)).to_i32!, extra_zeros.to_i32!} + end + def self.d2fixed(d : Float64, precision : Int) String.new(2000) do |buffer| len = d2fixed_buffered_n(d, precision.to_u32, buffer) @@ -626,4 +695,11 @@ module Float::Printer::RyuPrintf {len, len} end end + + def self.d2gen(d : Float64, precision : Int) + String.new(773) do |buffer| + len, _ = d2gen_buffered_n(d, precision.to_u32, buffer) + {len, len} + end + end end diff --git a/src/float/printer/ryu_printf_table.cr b/src/float/printer/ryu_printf_table.cr index dc733c492991..b9db3363f072 100644 --- a/src/float/printer/ryu_printf_table.cr +++ b/src/float/printer/ryu_printf_table.cr @@ -1,5 +1,4 @@ -# FIXME: this leads to an OOB on wasm32 (#13918) -{% skip_file if flag?(:wasm32) %} +{% skip_file unless String::Formatter::HAS_RYU_PRINTF %} module Float::Printer::RyuPrintf {% begin %} @@ -16,6 +15,533 @@ module Float::Printer::RyuPrintf array << values end + # Special constants for `%g` formatting; for details refer to + # https://github.com/ulfjack/ryu/pull/185/files or + # https://github.com/microsoft/STL/blob/a8888806c6960f1687590ffd4244794c753aa819/stl/inc/xcharconv_tables.h + + private MAX_SPECIAL_P = 15_u32 + + private SPECIAL_X = begin + data = Array(UInt64).new(195) + put(data, 0x3F18E757928E0C9Du64) + put(data, 0x3F4F212D77318FC5u64) + put(data, 0x3F8374BC6A7EF9DBu64) + put(data, 0x3FB851EB851EB851u64) + put(data, 0x3FEE666666666666u64) + put(data, 0x4022FFFFFFFFFFFFu64) + put(data, 0x3F1A1554FBDAD751u64) + put(data, 0x3F504D551D68C692u64) + put(data, 0x3F8460AA64C2F837u64) + put(data, 0x3FB978D4FDF3B645u64) + put(data, 0x3FEFD70A3D70A3D7u64) + put(data, 0x4023E66666666666u64) + put(data, 0x4058DFFFFFFFFFFFu64) + put(data, 0x3F1A3387ECC8EB96u64) + put(data, 0x3F506034F3FD933Eu64) + put(data, 0x3F84784230FCF80Du64) + put(data, 0x3FB99652BD3C3611u64) + put(data, 0x3FEFFBE76C8B4395u64) + put(data, 0x4023FD70A3D70A3Du64) + put(data, 0x4058FCCCCCCCCCCCu64) + put(data, 0x408F3BFFFFFFFFFFu64) + put(data, 0x3F1A368D04E0BA6Au64) + put(data, 0x3F506218230C7482u64) + put(data, 0x3F847A9E2BCF91A3u64) + put(data, 0x3FB99945B6C3760Bu64) + put(data, 0x3FEFFF972474538Eu64) + put(data, 0x4023FFBE76C8B439u64) + put(data, 0x4058FFAE147AE147u64) + put(data, 0x408F3F9999999999u64) + put(data, 0x40C387BFFFFFFFFFu64) + put(data, 0x3F1A36DA54164F19u64) + put(data, 0x3F506248748DF16Fu64) + put(data, 0x3F847ADA91B16DCBu64) + put(data, 0x3FB99991361DC93Eu64) + put(data, 0x3FEFFFF583A53B8Eu64) + put(data, 0x4023FFF972474538u64) + put(data, 0x4058FFF7CED91687u64) + put(data, 0x408F3FF5C28F5C28u64) + put(data, 0x40C387F999999999u64) + put(data, 0x40F869F7FFFFFFFFu64) + put(data, 0x3F1A36E20F35445Du64) + put(data, 0x3F50624D49814ABAu64) + put(data, 0x3F847AE09BE19D69u64) + put(data, 0x3FB99998C2DA04C3u64) + put(data, 0x3FEFFFFEF39085F4u64) + put(data, 0x4023FFFF583A53B8u64) + put(data, 0x4058FFFF2E48E8A7u64) + put(data, 0x408F3FFEF9DB22D0u64) + put(data, 0x40C387FF5C28F5C2u64) + put(data, 0x40F869FF33333333u64) + put(data, 0x412E847EFFFFFFFFu64) + put(data, 0x3F1A36E2D51EC34Bu64) + put(data, 0x3F50624DC5333A0Eu64) + put(data, 0x3F847AE136800892u64) + put(data, 0x3FB9999984200AB7u64) + put(data, 0x3FEFFFFFE5280D65u64) + put(data, 0x4023FFFFEF39085Fu64) + put(data, 0x4058FFFFEB074A77u64) + put(data, 0x408F3FFFE5C91D14u64) + put(data, 0x40C387FFEF9DB22Du64) + put(data, 0x40F869FFEB851EB8u64) + put(data, 0x412E847FE6666666u64) + put(data, 0x416312CFEFFFFFFFu64) + put(data, 0x3F1A36E2E8E94FFCu64) + put(data, 0x3F50624DD191D1FDu64) + put(data, 0x3F847AE145F6467Du64) + put(data, 0x3FB999999773D81Cu64) + put(data, 0x3FEFFFFFFD50CE23u64) + put(data, 0x4023FFFFFE5280D6u64) + put(data, 0x4058FFFFFDE7210Bu64) + put(data, 0x408F3FFFFD60E94Eu64) + put(data, 0x40C387FFFE5C91D1u64) + put(data, 0x40F869FFFDF3B645u64) + put(data, 0x412E847FFD70A3D7u64) + put(data, 0x416312CFFE666666u64) + put(data, 0x4197D783FDFFFFFFu64) + put(data, 0x3F1A36E2EAE3F7A7u64) + put(data, 0x3F50624DD2CE7AC8u64) + put(data, 0x3F847AE14782197Bu64) + put(data, 0x3FB9999999629FD9u64) + put(data, 0x3FEFFFFFFFBB47D0u64) + put(data, 0x4023FFFFFFD50CE2u64) + put(data, 0x4058FFFFFFCA501Au64) + put(data, 0x408F3FFFFFBCE421u64) + put(data, 0x40C387FFFFD60E94u64) + put(data, 0x40F869FFFFCB923Au64) + put(data, 0x412E847FFFBE76C8u64) + put(data, 0x416312CFFFD70A3Du64) + put(data, 0x4197D783FFCCCCCCu64) + put(data, 0x41CDCD64FFBFFFFFu64) + put(data, 0x3F1A36E2EB16A205u64) + put(data, 0x3F50624DD2EE2543u64) + put(data, 0x3F847AE147A9AE94u64) + put(data, 0x3FB9999999941A39u64) + put(data, 0x3FEFFFFFFFF920C8u64) + put(data, 0x4023FFFFFFFBB47Du64) + put(data, 0x4058FFFFFFFAA19Cu64) + put(data, 0x408F3FFFFFF94A03u64) + put(data, 0x40C387FFFFFBCE42u64) + put(data, 0x40F869FFFFFAC1D2u64) + put(data, 0x412E847FFFF97247u64) + put(data, 0x416312CFFFFBE76Cu64) + put(data, 0x4197D783FFFAE147u64) + put(data, 0x41CDCD64FFF99999u64) + put(data, 0x4202A05F1FFBFFFFu64) + put(data, 0x3F1A36E2EB1BB30Fu64) + put(data, 0x3F50624DD2F14FE9u64) + put(data, 0x3F847AE147ADA3E3u64) + put(data, 0x3FB9999999990CDCu64) + put(data, 0x3FEFFFFFFFFF5014u64) + put(data, 0x4023FFFFFFFF920Cu64) + put(data, 0x4058FFFFFFFF768Fu64) + put(data, 0x408F3FFFFFFF5433u64) + put(data, 0x40C387FFFFFF94A0u64) + put(data, 0x40F869FFFFFF79C8u64) + put(data, 0x412E847FFFFF583Au64) + put(data, 0x416312CFFFFF9724u64) + put(data, 0x4197D783FFFF7CEDu64) + put(data, 0x41CDCD64FFFF5C28u64) + put(data, 0x4202A05F1FFF9999u64) + put(data, 0x42374876E7FF7FFFu64) + put(data, 0x3F1A36E2EB1C34C3u64) + put(data, 0x3F50624DD2F1A0FAu64) + put(data, 0x3F847AE147AE0938u64) + put(data, 0x3FB9999999998B86u64) + put(data, 0x3FEFFFFFFFFFEE68u64) + put(data, 0x4023FFFFFFFFF501u64) + put(data, 0x4058FFFFFFFFF241u64) + put(data, 0x408F3FFFFFFFEED1u64) + put(data, 0x40C387FFFFFFF543u64) + put(data, 0x40F869FFFFFFF294u64) + put(data, 0x412E847FFFFFEF39u64) + put(data, 0x416312CFFFFFF583u64) + put(data, 0x4197D783FFFFF2E4u64) + put(data, 0x41CDCD64FFFFEF9Du64) + put(data, 0x4202A05F1FFFF5C2u64) + put(data, 0x42374876E7FFF333u64) + put(data, 0x426D1A94A1FFEFFFu64) + put(data, 0x3F1A36E2EB1C41BBu64) + put(data, 0x3F50624DD2F1A915u64) + put(data, 0x3F847AE147AE135Au64) + put(data, 0x3FB9999999999831u64) + put(data, 0x3FEFFFFFFFFFFE3Du64) + put(data, 0x4023FFFFFFFFFEE6u64) + put(data, 0x4058FFFFFFFFFEA0u64) + put(data, 0x408F3FFFFFFFFE48u64) + put(data, 0x40C387FFFFFFFEEDu64) + put(data, 0x40F869FFFFFFFEA8u64) + put(data, 0x412E847FFFFFFE52u64) + put(data, 0x416312CFFFFFFEF3u64) + put(data, 0x4197D783FFFFFEB0u64) + put(data, 0x41CDCD64FFFFFE5Cu64) + put(data, 0x4202A05F1FFFFEF9u64) + put(data, 0x42374876E7FFFEB8u64) + put(data, 0x426D1A94A1FFFE66u64) + put(data, 0x42A2309CE53FFEFFu64) + put(data, 0x3F1A36E2EB1C4307u64) + put(data, 0x3F50624DD2F1A9E4u64) + put(data, 0x3F847AE147AE145Eu64) + put(data, 0x3FB9999999999975u64) + put(data, 0x3FEFFFFFFFFFFFD2u64) + put(data, 0x4023FFFFFFFFFFE3u64) + put(data, 0x4058FFFFFFFFFFDCu64) + put(data, 0x408F3FFFFFFFFFD4u64) + put(data, 0x40C387FFFFFFFFE4u64) + put(data, 0x40F869FFFFFFFFDDu64) + put(data, 0x412E847FFFFFFFD5u64) + put(data, 0x416312CFFFFFFFE5u64) + put(data, 0x4197D783FFFFFFDEu64) + put(data, 0x41CDCD64FFFFFFD6u64) + put(data, 0x4202A05F1FFFFFE5u64) + put(data, 0x42374876E7FFFFDFu64) + put(data, 0x426D1A94A1FFFFD7u64) + put(data, 0x42A2309CE53FFFE6u64) + put(data, 0x42D6BCC41E8FFFDFu64) + put(data, 0x3F1A36E2EB1C4328u64) + put(data, 0x3F50624DD2F1A9F9u64) + put(data, 0x3F847AE147AE1477u64) + put(data, 0x3FB9999999999995u64) + put(data, 0x3FEFFFFFFFFFFFFBu64) + put(data, 0x4023FFFFFFFFFFFDu64) + put(data, 0x4058FFFFFFFFFFFCu64) + put(data, 0x408F3FFFFFFFFFFBu64) + put(data, 0x40C387FFFFFFFFFDu64) + put(data, 0x40F869FFFFFFFFFCu64) + put(data, 0x412E847FFFFFFFFBu64) + put(data, 0x416312CFFFFFFFFDu64) + put(data, 0x4197D783FFFFFFFCu64) + put(data, 0x41CDCD64FFFFFFFBu64) + put(data, 0x4202A05F1FFFFFFDu64) + put(data, 0x42374876E7FFFFFCu64) + put(data, 0x426D1A94A1FFFFFBu64) + put(data, 0x42A2309CE53FFFFDu64) + put(data, 0x42D6BCC41E8FFFFCu64) + put(data, 0x430C6BF52633FFFBu64) + data + end + + private MAX_ORDINARY_P = 309_u32 + + private ORDINARY_X = begin + data = Array(UInt64).new(314) + put(data, 0x3F1A36E2EB1C432Cu64) + put(data, 0x3F50624DD2F1A9FBu64) + put(data, 0x3F847AE147AE147Au64) + put(data, 0x3FB9999999999999u64) + put(data, 0x3FEFFFFFFFFFFFFFu64) + put(data, 0x4023FFFFFFFFFFFFu64) + put(data, 0x4058FFFFFFFFFFFFu64) + put(data, 0x408F3FFFFFFFFFFFu64) + put(data, 0x40C387FFFFFFFFFFu64) + put(data, 0x40F869FFFFFFFFFFu64) + put(data, 0x412E847FFFFFFFFFu64) + put(data, 0x416312CFFFFFFFFFu64) + put(data, 0x4197D783FFFFFFFFu64) + put(data, 0x41CDCD64FFFFFFFFu64) + put(data, 0x4202A05F1FFFFFFFu64) + put(data, 0x42374876E7FFFFFFu64) + put(data, 0x426D1A94A1FFFFFFu64) + put(data, 0x42A2309CE53FFFFFu64) + put(data, 0x42D6BCC41E8FFFFFu64) + put(data, 0x430C6BF52633FFFFu64) + put(data, 0x4341C37937E07FFFu64) + put(data, 0x4376345785D89FFFu64) + put(data, 0x43ABC16D674EC7FFu64) + put(data, 0x43E158E460913CFFu64) + put(data, 0x4415AF1D78B58C3Fu64) + put(data, 0x444B1AE4D6E2EF4Fu64) + put(data, 0x4480F0CF064DD591u64) + put(data, 0x44B52D02C7E14AF6u64) + put(data, 0x44EA784379D99DB4u64) + put(data, 0x45208B2A2C280290u64) + put(data, 0x4554ADF4B7320334u64) + put(data, 0x4589D971E4FE8401u64) + put(data, 0x45C027E72F1F1281u64) + put(data, 0x45F431E0FAE6D721u64) + put(data, 0x46293E5939A08CE9u64) + put(data, 0x465F8DEF8808B024u64) + put(data, 0x4693B8B5B5056E16u64) + put(data, 0x46C8A6E32246C99Cu64) + put(data, 0x46FED09BEAD87C03u64) + put(data, 0x4733426172C74D82u64) + put(data, 0x476812F9CF7920E2u64) + put(data, 0x479E17B84357691Bu64) + put(data, 0x47D2CED32A16A1B1u64) + put(data, 0x48078287F49C4A1Du64) + put(data, 0x483D6329F1C35CA4u64) + put(data, 0x48725DFA371A19E6u64) + put(data, 0x48A6F578C4E0A060u64) + put(data, 0x48DCB2D6F618C878u64) + put(data, 0x4911EFC659CF7D4Bu64) + put(data, 0x49466BB7F0435C9Eu64) + put(data, 0x497C06A5EC5433C6u64) + put(data, 0x49B18427B3B4A05Bu64) + put(data, 0x49E5E531A0A1C872u64) + put(data, 0x4A1B5E7E08CA3A8Fu64) + put(data, 0x4A511B0EC57E6499u64) + put(data, 0x4A8561D276DDFDC0u64) + put(data, 0x4ABABA4714957D30u64) + put(data, 0x4AF0B46C6CDD6E3Eu64) + put(data, 0x4B24E1878814C9CDu64) + put(data, 0x4B5A19E96A19FC40u64) + put(data, 0x4B905031E2503DA8u64) + put(data, 0x4BC4643E5AE44D12u64) + put(data, 0x4BF97D4DF19D6057u64) + put(data, 0x4C2FDCA16E04B86Du64) + put(data, 0x4C63E9E4E4C2F344u64) + put(data, 0x4C98E45E1DF3B015u64) + put(data, 0x4CCF1D75A5709C1Au64) + put(data, 0x4D03726987666190u64) + put(data, 0x4D384F03E93FF9F4u64) + put(data, 0x4D6E62C4E38FF872u64) + put(data, 0x4DA2FDBB0E39FB47u64) + put(data, 0x4DD7BD29D1C87A19u64) + put(data, 0x4E0DAC74463A989Fu64) + put(data, 0x4E428BC8ABE49F63u64) + put(data, 0x4E772EBAD6DDC73Cu64) + put(data, 0x4EACFA698C95390Bu64) + put(data, 0x4EE21C81F7DD43A7u64) + put(data, 0x4F16A3A275D49491u64) + put(data, 0x4F4C4C8B1349B9B5u64) + put(data, 0x4F81AFD6EC0E1411u64) + put(data, 0x4FB61BCCA7119915u64) + put(data, 0x4FEBA2BFD0D5FF5Bu64) + put(data, 0x502145B7E285BF98u64) + put(data, 0x50559725DB272F7Fu64) + put(data, 0x508AFCEF51F0FB5Eu64) + put(data, 0x50C0DE1593369D1Bu64) + put(data, 0x50F5159AF8044462u64) + put(data, 0x512A5B01B605557Au64) + put(data, 0x516078E111C3556Cu64) + put(data, 0x5194971956342AC7u64) + put(data, 0x51C9BCDFABC13579u64) + put(data, 0x5200160BCB58C16Cu64) + put(data, 0x52341B8EBE2EF1C7u64) + put(data, 0x526922726DBAAE39u64) + put(data, 0x529F6B0F092959C7u64) + put(data, 0x52D3A2E965B9D81Cu64) + put(data, 0x53088BA3BF284E23u64) + put(data, 0x533EAE8CAEF261ACu64) + put(data, 0x53732D17ED577D0Bu64) + put(data, 0x53A7F85DE8AD5C4Eu64) + put(data, 0x53DDF67562D8B362u64) + put(data, 0x5412BA095DC7701Du64) + put(data, 0x5447688BB5394C25u64) + put(data, 0x547D42AEA2879F2Eu64) + put(data, 0x54B249AD2594C37Cu64) + put(data, 0x54E6DC186EF9F45Cu64) + put(data, 0x551C931E8AB87173u64) + put(data, 0x5551DBF316B346E7u64) + put(data, 0x558652EFDC6018A1u64) + put(data, 0x55BBE7ABD3781ECAu64) + put(data, 0x55F170CB642B133Eu64) + put(data, 0x5625CCFE3D35D80Eu64) + put(data, 0x565B403DCC834E11u64) + put(data, 0x569108269FD210CBu64) + put(data, 0x56C54A3047C694FDu64) + put(data, 0x56FA9CBC59B83A3Du64) + put(data, 0x5730A1F5B8132466u64) + put(data, 0x5764CA732617ED7Fu64) + put(data, 0x5799FD0FEF9DE8DFu64) + put(data, 0x57D03E29F5C2B18Bu64) + put(data, 0x58044DB473335DEEu64) + put(data, 0x583961219000356Au64) + put(data, 0x586FB969F40042C5u64) + put(data, 0x58A3D3E2388029BBu64) + put(data, 0x58D8C8DAC6A0342Au64) + put(data, 0x590EFB1178484134u64) + put(data, 0x59435CEAEB2D28C0u64) + put(data, 0x59783425A5F872F1u64) + put(data, 0x59AE412F0F768FADu64) + put(data, 0x59E2E8BD69AA19CCu64) + put(data, 0x5A17A2ECC414A03Fu64) + put(data, 0x5A4D8BA7F519C84Fu64) + put(data, 0x5A827748F9301D31u64) + put(data, 0x5AB7151B377C247Eu64) + put(data, 0x5AECDA62055B2D9Du64) + put(data, 0x5B22087D4358FC82u64) + put(data, 0x5B568A9C942F3BA3u64) + put(data, 0x5B8C2D43B93B0A8Bu64) + put(data, 0x5BC19C4A53C4E697u64) + put(data, 0x5BF6035CE8B6203Du64) + put(data, 0x5C2B843422E3A84Cu64) + put(data, 0x5C6132A095CE492Fu64) + put(data, 0x5C957F48BB41DB7Bu64) + put(data, 0x5CCADF1AEA12525Au64) + put(data, 0x5D00CB70D24B7378u64) + put(data, 0x5D34FE4D06DE5056u64) + put(data, 0x5D6A3DE04895E46Cu64) + put(data, 0x5DA066AC2D5DAEC3u64) + put(data, 0x5DD4805738B51A74u64) + put(data, 0x5E09A06D06E26112u64) + put(data, 0x5E400444244D7CABu64) + put(data, 0x5E7405552D60DBD6u64) + put(data, 0x5EA906AA78B912CBu64) + put(data, 0x5EDF485516E7577Eu64) + put(data, 0x5F138D352E5096AFu64) + put(data, 0x5F48708279E4BC5Au64) + put(data, 0x5F7E8CA3185DEB71u64) + put(data, 0x5FB317E5EF3AB327u64) + put(data, 0x5FE7DDDF6B095FF0u64) + put(data, 0x601DD55745CBB7ECu64) + put(data, 0x6052A5568B9F52F4u64) + put(data, 0x60874EAC2E8727B1u64) + put(data, 0x60BD22573A28F19Du64) + put(data, 0x60F2357684599702u64) + put(data, 0x6126C2D4256FFCC2u64) + put(data, 0x615C73892ECBFBF3u64) + put(data, 0x6191C835BD3F7D78u64) + put(data, 0x61C63A432C8F5CD6u64) + put(data, 0x61FBC8D3F7B3340Bu64) + put(data, 0x62315D847AD00087u64) + put(data, 0x6265B4E5998400A9u64) + put(data, 0x629B221EFFE500D3u64) + put(data, 0x62D0F5535FEF2084u64) + put(data, 0x630532A837EAE8A5u64) + put(data, 0x633A7F5245E5A2CEu64) + put(data, 0x63708F936BAF85C1u64) + put(data, 0x63A4B378469B6731u64) + put(data, 0x63D9E056584240FDu64) + put(data, 0x64102C35F729689Eu64) + put(data, 0x6444374374F3C2C6u64) + put(data, 0x647945145230B377u64) + put(data, 0x64AF965966BCE055u64) + put(data, 0x64E3BDF7E0360C35u64) + put(data, 0x6518AD75D8438F43u64) + put(data, 0x654ED8D34E547313u64) + put(data, 0x6583478410F4C7ECu64) + put(data, 0x65B819651531F9E7u64) + put(data, 0x65EE1FBE5A7E7861u64) + put(data, 0x6622D3D6F88F0B3Cu64) + put(data, 0x665788CCB6B2CE0Cu64) + put(data, 0x668D6AFFE45F818Fu64) + put(data, 0x66C262DFEEBBB0F9u64) + put(data, 0x66F6FB97EA6A9D37u64) + put(data, 0x672CBA7DE5054485u64) + put(data, 0x6761F48EAF234AD3u64) + put(data, 0x679671B25AEC1D88u64) + put(data, 0x67CC0E1EF1A724EAu64) + put(data, 0x680188D357087712u64) + put(data, 0x6835EB082CCA94D7u64) + put(data, 0x686B65CA37FD3A0Du64) + put(data, 0x68A11F9E62FE4448u64) + put(data, 0x68D56785FBBDD55Au64) + put(data, 0x690AC1677AAD4AB0u64) + put(data, 0x6940B8E0ACAC4EAEu64) + put(data, 0x6974E718D7D7625Au64) + put(data, 0x69AA20DF0DCD3AF0u64) + put(data, 0x69E0548B68A044D6u64) + put(data, 0x6A1469AE42C8560Cu64) + put(data, 0x6A498419D37A6B8Fu64) + put(data, 0x6A7FE52048590672u64) + put(data, 0x6AB3EF342D37A407u64) + put(data, 0x6AE8EB0138858D09u64) + put(data, 0x6B1F25C186A6F04Cu64) + put(data, 0x6B537798F428562Fu64) + put(data, 0x6B88557F31326BBBu64) + put(data, 0x6BBE6ADEFD7F06AAu64) + put(data, 0x6BF302CB5E6F642Au64) + put(data, 0x6C27C37E360B3D35u64) + put(data, 0x6C5DB45DC38E0C82u64) + put(data, 0x6C9290BA9A38C7D1u64) + put(data, 0x6CC734E940C6F9C5u64) + put(data, 0x6CFD022390F8B837u64) + put(data, 0x6D3221563A9B7322u64) + put(data, 0x6D66A9ABC9424FEBu64) + put(data, 0x6D9C5416BB92E3E6u64) + put(data, 0x6DD1B48E353BCE6Fu64) + put(data, 0x6E0621B1C28AC20Bu64) + put(data, 0x6E3BAA1E332D728Eu64) + put(data, 0x6E714A52DFFC6799u64) + put(data, 0x6EA59CE797FB817Fu64) + put(data, 0x6EDB04217DFA61DFu64) + put(data, 0x6F10E294EEBC7D2Bu64) + put(data, 0x6F451B3A2A6B9C76u64) + put(data, 0x6F7A6208B5068394u64) + put(data, 0x6FB07D457124123Cu64) + put(data, 0x6FE49C96CD6D16CBu64) + put(data, 0x7019C3BC80C85C7Eu64) + put(data, 0x70501A55D07D39CFu64) + put(data, 0x708420EB449C8842u64) + put(data, 0x70B9292615C3AA53u64) + put(data, 0x70EF736F9B3494E8u64) + put(data, 0x7123A825C100DD11u64) + put(data, 0x7158922F31411455u64) + put(data, 0x718EB6BAFD91596Bu64) + put(data, 0x71C33234DE7AD7E2u64) + put(data, 0x71F7FEC216198DDBu64) + put(data, 0x722DFE729B9FF152u64) + put(data, 0x7262BF07A143F6D3u64) + put(data, 0x72976EC98994F488u64) + put(data, 0x72CD4A7BEBFA31AAu64) + put(data, 0x73024E8D737C5F0Au64) + put(data, 0x7336E230D05B76CDu64) + put(data, 0x736C9ABD04725480u64) + put(data, 0x73A1E0B622C774D0u64) + put(data, 0x73D658E3AB795204u64) + put(data, 0x740BEF1C9657A685u64) + put(data, 0x74417571DDF6C813u64) + put(data, 0x7475D2CE55747A18u64) + put(data, 0x74AB4781EAD1989Eu64) + put(data, 0x74E10CB132C2FF63u64) + put(data, 0x75154FDD7F73BF3Bu64) + put(data, 0x754AA3D4DF50AF0Au64) + put(data, 0x7580A6650B926D66u64) + put(data, 0x75B4CFFE4E7708C0u64) + put(data, 0x75EA03FDE214CAF0u64) + put(data, 0x7620427EAD4CFED6u64) + put(data, 0x7654531E58A03E8Bu64) + put(data, 0x768967E5EEC84E2Eu64) + put(data, 0x76BFC1DF6A7A61BAu64) + put(data, 0x76F3D92BA28C7D14u64) + put(data, 0x7728CF768B2F9C59u64) + put(data, 0x775F03542DFB8370u64) + put(data, 0x779362149CBD3226u64) + put(data, 0x77C83A99C3EC7EAFu64) + put(data, 0x77FE494034E79E5Bu64) + put(data, 0x7832EDC82110C2F9u64) + put(data, 0x7867A93A2954F3B7u64) + put(data, 0x789D9388B3AA30A5u64) + put(data, 0x78D27C35704A5E67u64) + put(data, 0x79071B42CC5CF601u64) + put(data, 0x793CE2137F743381u64) + put(data, 0x79720D4C2FA8A030u64) + put(data, 0x79A6909F3B92C83Du64) + put(data, 0x79DC34C70A777A4Cu64) + put(data, 0x7A11A0FC668AAC6Fu64) + put(data, 0x7A46093B802D578Bu64) + put(data, 0x7A7B8B8A6038AD6Eu64) + put(data, 0x7AB137367C236C65u64) + put(data, 0x7AE585041B2C477Eu64) + put(data, 0x7B1AE64521F7595Eu64) + put(data, 0x7B50CFEB353A97DAu64) + put(data, 0x7B8503E602893DD1u64) + put(data, 0x7BBA44DF832B8D45u64) + put(data, 0x7BF06B0BB1FB384Bu64) + put(data, 0x7C2485CE9E7A065Eu64) + put(data, 0x7C59A742461887F6u64) + put(data, 0x7C9008896BCF54F9u64) + put(data, 0x7CC40AABC6C32A38u64) + put(data, 0x7CF90D56B873F4C6u64) + put(data, 0x7D2F50AC6690F1F8u64) + put(data, 0x7D63926BC01A973Bu64) + put(data, 0x7D987706B0213D09u64) + put(data, 0x7DCE94C85C298C4Cu64) + put(data, 0x7E031CFD3999F7AFu64) + put(data, 0x7E37E43C8800759Bu64) + put(data, 0x7E6DDD4BAA009302u64) + put(data, 0x7EA2AA4F4A405BE1u64) + put(data, 0x7ED754E31CD072D9u64) + put(data, 0x7F0D2A1BE4048F90u64) + put(data, 0x7F423A516E82D9BAu64) + put(data, 0x7F76C8E5CA239028u64) + put(data, 0x7FAC7B1F3CAC7433u64) + put(data, 0x7FE1CCF385EBC89Fu64) + put(data, 0x7FEFFFFFFFFFFFFFu64) + data + end + private POW10_OFFSET = [ 0, 2, 5, 8, 12, 16, 21, 26, 32, 39, 46, 54, 62, 71, 80, 90, 100, 111, 122, 134, diff --git a/src/gc/boehm.cr b/src/gc/boehm.cr index b4dfb0061900..609f71189795 100644 --- a/src/gc/boehm.cr +++ b/src/gc/boehm.cr @@ -21,11 +21,24 @@ {% if flag?(:freebsd) || flag?(:dragonfly) %} @[Link("gc-threaded")] -{% else %} +{% elsif flag?(:interpreted) %} + # FIXME: We're not using the pkg-config name here because that would resolve the + # lib flags for libgc including `-lpthread` which the interpreter is not able + # to load on systems with modern libc where libpthread is only available as an + # (empty) static library. @[Link("gc")] +{% else %} + @[Link("gc", pkg_config: "bdw-gc")] {% end %} +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "gc.dll")] +{% end %} lib LibGC + {% unless flag?(:win32) %} + VERSION = {{ `pkg-config bdw-gc --silence-errors --modversion || printf "0.0.0"`.chomp.stringify }} + {% end %} + alias Int = LibC::Int alias SizeT = LibC::SizeT {% if flag?(:win32) && flag?(:bits64) %} @@ -93,7 +106,7 @@ lib LibGC fun push_all_eager = GC_push_all_eager(bottom : Void*, top : Void*) - {% if flag?(:preview_mt) || flag?(:win32) %} + {% if flag?(:preview_mt) || flag?(:win32) || compare_versions(VERSION, "8.2.0") >= 0 %} fun get_my_stackbottom = GC_get_my_stackbottom(sb : StackBase*) : ThreadHandle fun set_stackbottom = GC_set_stackbottom(th : ThreadHandle, sb : StackBase*) : ThreadHandle {% else %} @@ -274,10 +287,11 @@ module GC # :nodoc: def self.current_thread_stack_bottom - {% if flag?(:preview_mt) || flag?(:win32) %} + {% if LibGC.has_method?(:get_my_stackbottom) %} th = LibGC.get_my_stackbottom(out sb) {th, sb.mem_base} {% else %} + # support for legacy gc releases {Pointer(Void).null, LibGC.stackbottom} {% end %} end @@ -289,10 +303,11 @@ module GC sb.mem_base = stack_bottom LibGC.set_stackbottom(thread_handle, pointerof(sb)) end - {% elsif flag?(:win32) %} + {% elsif LibGC.has_method?(:set_stackbottom) %} # this is necessary because Boehm GC does _not_ use `GC_stackbottom` on - # Windows when pushing all threads' stacks; instead `GC_set_stackbottom` - # must be used to associate the new bottom with the running thread + # Windows when pushing all threads' stacks; it also started crashing on + # Linux with libgc after v8.2.4; instead `GC_set_stackbottom` must be used + # to associate the new bottom with the running thread def self.set_stackbottom(stack_bottom : Void*) sb = LibGC::StackBase.new sb.mem_base = stack_bottom @@ -300,6 +315,7 @@ module GC LibGC.set_stackbottom(nil, pointerof(sb)) end {% else %} + # support for legacy gc releases def self.set_stackbottom(stack_bottom : Void*) LibGC.stackbottom = stack_bottom end diff --git a/src/hash.cr b/src/hash.cr index 8d8ccea22a0b..082f2a0a80e0 100644 --- a/src/hash.cr +++ b/src/hash.cr @@ -2055,16 +2055,30 @@ class Hash(K, V) pp.text "{...}" unless executed end - # Returns an array of tuples with key and values belonging to this Hash. + # Returns an `Array` of `Tuple(K, V)` with key and values belonging to this Hash. # # ``` # h = {1 => 'a', 2 => 'b', 3 => 'c'} # h.to_a # => [{1, 'a'}, {2, 'b'}, {3, 'c'}] # ``` + # # The order of the array follows the order the keys were inserted in the Hash. def to_a : Array({K, V}) + to_a(&.itself) + end + + # Returns an `Array` with the results of running *block* against tuples with key and values + # belonging to this Hash. + # + # ``` + # h = {"first_name" => "foo", "last_name" => "bar"} + # h.to_a { |_k, v| v.capitalize } # => ["Foo", "Bar"] + # ``` + # + # The order of the array follows the order the keys were inserted in the Hash. + def to_a(&block : {K, V} -> U) : Array(U) forall U to_a_impl do |entry| - {entry.key, entry.value} + yield ({entry.key, entry.value}) end end diff --git a/src/humanize.cr b/src/humanize.cr index e0c69a37b3ad..bb285fe3a07d 100644 --- a/src/humanize.cr +++ b/src/humanize.cr @@ -20,7 +20,7 @@ struct Number def format(io : IO, separator = '.', delimiter = ',', decimal_places : Int? = nil, *, group : Int = 3, only_significant : Bool = false) : Nil number = self # TODO: Optimize implementation for Int - if decimal_places + if decimal_places && (decimal_places < 0 || !number.is_a?(Float)) number = number.round(decimal_places) end diff --git a/src/indexable.cr b/src/indexable.cr index 3725c1552e38..7496a95e0df0 100644 --- a/src/indexable.cr +++ b/src/indexable.cr @@ -693,14 +693,14 @@ module Indexable(T) end end - # Returns an `Array` with all the elements in the collection. + # Returns an `Array` with the results of running *block* against each element of the collection. # # ``` - # {1, 2, 3}.to_a # => [1, 2, 3] + # {1, 2, 3}.to_a { |i| i * 2 } # => [2, 4, 6] # ``` - def to_a : Array(T) - ary = Array(T).new(size) - each { |e| ary << e } + def to_a(& : T -> U) : Array(U) forall U + ary = Array(U).new(size) + each { |e| ary << yield e } ary end diff --git a/src/int.cr b/src/int.cr index 005d2c625c7b..b36ddba14e9e 100644 --- a/src/int.cr +++ b/src/int.cr @@ -567,6 +567,20 @@ struct Int end # Calls the given block with each integer value from self down to `to`. + # + # ``` + # 3.downto(1) do |i| + # puts i + # end + # ``` + # + # Prints: + # + # ```text + # 3 + # 2 + # 1 + # ``` def downto(to, &block : self ->) : Nil return unless self >= to x = self diff --git a/src/io/error.cr b/src/io/error.cr index 4c6d30952f13..ec0374040699 100644 --- a/src/io/error.cr +++ b/src/io/error.cr @@ -16,10 +16,10 @@ class IO "#{message} (#{target})" end - def initialize(message : String? = nil, *, target = nil) + def initialize(message : String? = nil, cause : Exception? = nil, *, target = nil) @target = target.try(&.to_s) - super message + super message, cause end end diff --git a/src/io/memory.cr b/src/io/memory.cr index d0b925df1d70..bd486f0cbdc2 100644 --- a/src/io/memory.cr +++ b/src/io/memory.cr @@ -90,11 +90,7 @@ class IO::Memory < IO return if count == 0 - new_bytesize = @pos + count - if new_bytesize > @capacity - check_resizeable - resize_to_capacity(Math.pw2ceil(new_bytesize)) - end + increase_capacity_by(count) slice.copy_to(@buffer + @pos, count) @@ -112,11 +108,7 @@ class IO::Memory < IO check_writeable check_open - new_bytesize = @pos + 1 - if new_bytesize > @capacity - check_resizeable - resize_to_capacity(Math.pw2ceil(new_bytesize)) - end + increase_capacity_by(1) (@buffer + @pos).value = byte @@ -458,6 +450,28 @@ class IO::Memory < IO end end + private def increase_capacity_by(count) + raise IO::EOFError.new if count >= Int32::MAX - bytesize + + new_bytesize = @pos + count + return if new_bytesize <= @capacity + + check_resizeable + + new_capacity = calculate_new_capacity(new_bytesize) + resize_to_capacity(new_capacity) + end + + private def calculate_new_capacity(new_bytesize : Int32) + # If the new bytesize is bigger than 1 << 30, the next power of two would + # be 1 << 31, which is out of range for Int32. + # So we limit the capacity to Int32::MAX in order to be able to use the + # range (1 << 30) < new_bytesize < Int32::MAX + return Int32::MAX if new_bytesize > 1 << 30 + + Math.pw2ceil(new_bytesize) + end + private def resize_to_capacity(capacity) @capacity = capacity @buffer = GC.realloc(@buffer, @capacity) diff --git a/src/json/builder.cr b/src/json/builder.cr index 9bc074f7c6ef..c1dc2c39c8e8 100644 --- a/src/json/builder.cr +++ b/src/json/builder.cr @@ -430,7 +430,10 @@ module JSON # end # string # => %<{"name":"foo","values":[1,2,3]}> # ``` - def self.build(indent = nil, &) + # + # Accepts an indent parameter which can either be an `Int` (number of spaces to indent) + # or a `String`, which will prefix each level with the string a corresponding amount of times. + def self.build(indent : String | Int | Nil = nil, &) String.build do |str| build(str, indent) do |json| yield json @@ -439,7 +442,7 @@ module JSON end # Writes JSON into the given `IO`. A `JSON::Builder` is yielded to the block. - def self.build(io : IO, indent = nil, &) : Nil + def self.build(io : IO, indent : String | Int | Nil = nil, &) : Nil builder = JSON::Builder.new(io) builder.indent = indent if indent builder.document do diff --git a/src/kernel.cr b/src/kernel.cr index c3b3106ccae3..d3817ee11661 100644 --- a/src/kernel.cr +++ b/src/kernel.cr @@ -563,14 +563,6 @@ end {% end %} {% unless flag?(:interpreted) || flag?(:wasm32) %} - # Background loop to cleanup unused fiber stacks. - spawn(name: "Fiber Clean Loop") do - loop do - sleep 5 - Fiber.stack_pool.collect - end - end - {% if flag?(:win32) %} Crystal::System::Process.start_interrupt_loop {% else %} @@ -586,7 +578,5 @@ end Exception::CallStack.load_debug_info if ENV["CRYSTAL_LOAD_DEBUG_INFO"]? == "1" Exception::CallStack.setup_crash_handler - {% if flag?(:preview_mt) %} - Crystal::Scheduler.init_workers - {% end %} + Crystal::Scheduler.init {% end %} diff --git a/src/lib_c/aarch64-android/c/pthread.cr b/src/lib_c/aarch64-android/c/pthread.cr index d761bcb3ceb2..fbab59bd07d7 100644 --- a/src/lib_c/aarch64-android/c/pthread.cr +++ b/src/lib_c/aarch64-android/c/pthread.cr @@ -38,6 +38,7 @@ lib LibC fun pthread_mutex_unlock(__mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(__key : PthreadT, __name : Char*) : Int fun pthread_setspecific(__key : PthreadKeyT, __value : Void*) : Int end diff --git a/src/lib_c/aarch64-darwin/c/pthread.cr b/src/lib_c/aarch64-darwin/c/pthread.cr index dd262f7d9c12..d146e227197f 100644 --- a/src/lib_c/aarch64-darwin/c/pthread.cr +++ b/src/lib_c/aarch64-darwin/c/pthread.cr @@ -25,4 +25,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(Char*) : Int end diff --git a/src/lib_c/aarch64-linux-gnu/c/pthread.cr b/src/lib_c/aarch64-linux-gnu/c/pthread.cr index 643fca7c015a..5d9f7b94e225 100644 --- a/src/lib_c/aarch64-linux-gnu/c/pthread.cr +++ b/src/lib_c/aarch64-linux-gnu/c/pthread.cr @@ -36,4 +36,5 @@ lib LibC fun pthread_mutex_trylock(mutex : PthreadMutexT*) : Int fun pthread_mutex_unlock(mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/aarch64-linux-musl/c/pthread.cr b/src/lib_c/aarch64-linux-musl/c/pthread.cr index c318bb5f4357..6ee1a20d90a6 100644 --- a/src/lib_c/aarch64-linux-musl/c/pthread.cr +++ b/src/lib_c/aarch64-linux-musl/c/pthread.cr @@ -27,4 +27,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/arm-linux-gnueabihf/c/pthread.cr b/src/lib_c/arm-linux-gnueabihf/c/pthread.cr index 643fca7c015a..5d9f7b94e225 100644 --- a/src/lib_c/arm-linux-gnueabihf/c/pthread.cr +++ b/src/lib_c/arm-linux-gnueabihf/c/pthread.cr @@ -36,4 +36,5 @@ lib LibC fun pthread_mutex_trylock(mutex : PthreadMutexT*) : Int fun pthread_mutex_unlock(mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/i386-linux-gnu/c/pthread.cr b/src/lib_c/i386-linux-gnu/c/pthread.cr index ab943b23587d..33274a6cf51d 100644 --- a/src/lib_c/i386-linux-gnu/c/pthread.cr +++ b/src/lib_c/i386-linux-gnu/c/pthread.cr @@ -35,4 +35,5 @@ lib LibC fun pthread_mutex_trylock(mutex : PthreadMutexT*) : Int fun pthread_mutex_unlock(mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/i386-linux-musl/c/pthread.cr b/src/lib_c/i386-linux-musl/c/pthread.cr index c318bb5f4357..6ee1a20d90a6 100644 --- a/src/lib_c/i386-linux-musl/c/pthread.cr +++ b/src/lib_c/i386-linux-musl/c/pthread.cr @@ -27,4 +27,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/x86_64-darwin/c/pthread.cr b/src/lib_c/x86_64-darwin/c/pthread.cr index dd262f7d9c12..d146e227197f 100644 --- a/src/lib_c/x86_64-darwin/c/pthread.cr +++ b/src/lib_c/x86_64-darwin/c/pthread.cr @@ -25,4 +25,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(Char*) : Int end diff --git a/src/lib_c/x86_64-dragonfly/c/pthread.cr b/src/lib_c/x86_64-dragonfly/c/pthread.cr index 87ae8c05c358..90bf0c6285a0 100644 --- a/src/lib_c/x86_64-dragonfly/c/pthread.cr +++ b/src/lib_c/x86_64-dragonfly/c/pthread.cr @@ -29,4 +29,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/x86_64-freebsd/c/pthread.cr b/src/lib_c/x86_64-freebsd/c/pthread.cr index 87ae8c05c358..9cc78c2f2850 100644 --- a/src/lib_c/x86_64-freebsd/c/pthread.cr +++ b/src/lib_c/x86_64-freebsd/c/pthread.cr @@ -29,4 +29,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_set_name_np(PthreadT, Char*) end diff --git a/src/lib_c/x86_64-linux-gnu/c/pthread.cr b/src/lib_c/x86_64-linux-gnu/c/pthread.cr index ab943b23587d..33274a6cf51d 100644 --- a/src/lib_c/x86_64-linux-gnu/c/pthread.cr +++ b/src/lib_c/x86_64-linux-gnu/c/pthread.cr @@ -35,4 +35,5 @@ lib LibC fun pthread_mutex_trylock(mutex : PthreadMutexT*) : Int fun pthread_mutex_unlock(mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/x86_64-linux-musl/c/pthread.cr b/src/lib_c/x86_64-linux-musl/c/pthread.cr index c318bb5f4357..6ee1a20d90a6 100644 --- a/src/lib_c/x86_64-linux-musl/c/pthread.cr +++ b/src/lib_c/x86_64-linux-musl/c/pthread.cr @@ -27,4 +27,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/x86_64-netbsd/c/pthread.cr b/src/lib_c/x86_64-netbsd/c/pthread.cr index 133d4922c57f..e0f477018777 100644 --- a/src/lib_c/x86_64-netbsd/c/pthread.cr +++ b/src/lib_c/x86_64-netbsd/c/pthread.cr @@ -35,5 +35,6 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*, Void*) : Int fun pthread_setspecific(PthreadKeyT, Void*) : Int end diff --git a/src/lib_c/x86_64-openbsd/c/pthread.cr b/src/lib_c/x86_64-openbsd/c/pthread.cr index 788823c40a31..15773336f239 100644 --- a/src/lib_c/x86_64-openbsd/c/pthread.cr +++ b/src/lib_c/x86_64-openbsd/c/pthread.cr @@ -30,6 +30,7 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_set_name_np(PthreadT, Char*) fun pthread_setspecific(PthreadKeyT, Void*) : Int fun pthread_stackseg_np(PthreadT, StackT*) : Int end diff --git a/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr b/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr index 680e199be2ab..796369c65a85 100644 --- a/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr +++ b/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr @@ -14,6 +14,14 @@ lib LibC fun GetConsoleCP : DWORD fun GetConsoleOutputCP : DWORD + fun ReadConsoleW( + hConsoleInput : HANDLE, + lpBuffer : Void*, + nNumberOfCharsToRead : DWORD, + lpNumberOfCharsRead : DWORD*, + pInputControl : Void* + ) : BOOL + CTRL_C_EVENT = 0 CTRL_BREAK_EVENT = 1 diff --git a/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr b/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr index 9c22d4530c81..efa684075162 100644 --- a/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr +++ b/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr @@ -50,6 +50,9 @@ lib LibC bInheritHandles : BOOL, dwCreationFlags : DWORD, lpEnvironment : Void*, lpCurrentDirectory : LPWSTR, lpStartupInfo : STARTUPINFOW*, lpProcessInformation : PROCESS_INFORMATION*) : BOOL + {% if LibC::WIN32_WINNT >= LibC::WIN32_WINNT_WIN10 %} + fun SetThreadDescription(hThread : HANDLE, lpThreadDescription : LPWSTR) : LONG + {% end %} fun SetThreadStackGuarantee(stackSizeInBytes : DWORD*) : BOOL fun GetProcessTimes(hProcess : HANDLE, lpCreationTime : FILETIME*, lpExitTime : FILETIME*, lpKernelTime : FILETIME*, lpUserTime : FILETIME*) : BOOL diff --git a/src/lib_z/lib_z.cr b/src/lib_z/lib_z.cr index e261cde29683..1c88cb67bba8 100644 --- a/src/lib_z/lib_z.cr +++ b/src/lib_z/lib_z.cr @@ -1,4 +1,7 @@ @[Link("z")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "zlib1.dll")] +{% end %} lib LibZ alias Char = LibC::Char alias Int = LibC::Int diff --git a/src/llvm/enums.cr b/src/llvm/enums.cr index b8e06fb46f89..ac23fa711560 100644 --- a/src/llvm/enums.cr +++ b/src/llvm/enums.cr @@ -440,6 +440,11 @@ module LLVM LittleEndian = 1 << 28 end + enum InlineAsmDialect + ATT + Intel + end + struct Value enum Kind Argument diff --git a/src/llvm/ext/llvm-versions.txt b/src/llvm/ext/llvm-versions.txt index 7c8773c02212..92ae5ecbaa5a 100644 --- a/src/llvm/ext/llvm-versions.txt +++ b/src/llvm/ext/llvm-versions.txt @@ -1 +1 @@ -17.0 16.0 15.0 14.0 13.0 12.0 11.1 11.0 10.0 9.0 8.0 +18.1 17.0 16.0 15.0 14.0 13.0 12.0 11.1 11.0 10.0 9.0 8.0 diff --git a/src/llvm/function.cr b/src/llvm/function.cr index a586cd6fdde5..d643e74d758b 100644 --- a/src/llvm/function.cr +++ b/src/llvm/function.cr @@ -28,6 +28,13 @@ struct LLVM::Function end end + def add_attribute(attribute : String, index = AttributeIndex::FunctionIndex, *, value : String) + context = LibLLVM.get_module_context(LibLLVM.get_global_parent(self)) + attribute_ref = LibLLVM.create_string_attribute(context, attribute, attribute.bytesize, + value, value.bytesize) + LibLLVM.add_attribute_at_index(self, index, attribute_ref) + end + def add_attribute(attribute : Attribute, index = AttributeIndex::FunctionIndex, *, value) return if attribute.value == 0 diff --git a/src/llvm/lib_llvm.cr b/src/llvm/lib_llvm.cr index ee18eddfbce3..b68e212d2052 100644 --- a/src/llvm/lib_llvm.cr +++ b/src/llvm/lib_llvm.cr @@ -15,6 +15,9 @@ {% llvm_ldflags = lines[2] %} @[Link("llvm")] + {% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "LLVM-C.dll")] + {% end %} lib LibLLVM end {% else %} @@ -32,7 +35,7 @@ @[Link(ldflags: {{ llvm_ldflags }})] lib LibLLVM - VERSION = {{ llvm_version.strip.gsub(/git/, "") }} + VERSION = {{ llvm_version.strip.gsub(/git/, "").gsub(/rc.*/, "") }} BUILT_TARGETS = {{ llvm_targets.strip.downcase.split(' ').map(&.id.symbolize) }} end {% end %} diff --git a/src/llvm/lib_llvm/core.cr b/src/llvm/lib_llvm/core.cr index 0645441f8a70..c865baaa55a5 100644 --- a/src/llvm/lib_llvm/core.cr +++ b/src/llvm/lib_llvm/core.cr @@ -4,11 +4,6 @@ lib LibLLVM # NOTE: the following C enums usually have different values from their C++ # counterparts (e.g. `LLVMModuleFlagBehavior` v.s. `LLVM::Module::ModFlagBehavior`) - enum InlineAsmDialect - ATT - Intel - end - enum ModuleFlagBehavior Warning = 1 end @@ -25,6 +20,7 @@ lib LibLLVM fun get_enum_attribute_kind_for_name = LLVMGetEnumAttributeKindForName(name : Char*, s_len : SizeT) : UInt fun get_last_enum_attribute_kind = LLVMGetLastEnumAttributeKind : UInt fun create_enum_attribute = LLVMCreateEnumAttribute(c : ContextRef, kind_id : UInt, val : UInt64) : AttributeRef + fun create_string_attribute = LLVMCreateStringAttribute(c : ContextRef, k : Char*, k_length : UInt, v : Char*, v_length : UInt) : AttributeRef {% unless LibLLVM::IS_LT_120 %} fun create_type_attribute = LLVMCreateTypeAttribute(c : ContextRef, kind_id : UInt, type_ref : TypeRef) : AttributeRef {% end %} @@ -38,9 +34,9 @@ lib LibLLVM fun print_module_to_file = LLVMPrintModuleToFile(m : ModuleRef, filename : Char*, error_message : Char**) : Bool fun print_module_to_string = LLVMPrintModuleToString(m : ModuleRef) : Char* {% if !LibLLVM::IS_LT_130 %} - fun get_inline_asm = LLVMGetInlineAsm(ty : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : InlineAsmDialect, can_throw : Bool) : ValueRef + fun get_inline_asm = LLVMGetInlineAsm(ty : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : LLVM::InlineAsmDialect, can_throw : Bool) : ValueRef {% else %} - fun get_inline_asm = LLVMGetInlineAsm(t : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : InlineAsmDialect) : ValueRef + fun get_inline_asm = LLVMGetInlineAsm(t : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : LLVM::InlineAsmDialect) : ValueRef {% end %} fun get_module_context = LLVMGetModuleContext(m : ModuleRef) : ContextRef diff --git a/src/llvm/parameter_collection.cr b/src/llvm/parameter_collection.cr index 937d9ec2edcc..dd9a7eae91d7 100644 --- a/src/llvm/parameter_collection.cr +++ b/src/llvm/parameter_collection.cr @@ -8,7 +8,7 @@ struct LLVM::ParameterCollection LibLLVM.get_count_params(@function).to_i end - def to_a + def to_a : Array(LLVM::Value) param_size = size() Array(LLVM::Value).build(param_size) do |buffer| LibLLVM.get_params(@function, buffer.as(LibLLVM::ValueRef*)) diff --git a/src/llvm/type.cr b/src/llvm/type.cr index 06c36ff5796d..42d1a314c118 100644 --- a/src/llvm/type.cr +++ b/src/llvm/type.cr @@ -173,29 +173,29 @@ struct LLVM::Type Value.new LibLLVM.const_array(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size) end - def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, can_throw = false) + def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, can_throw = false, dialect : InlineAsmDialect = InlineAsmDialect::ATT) value = {% if LibLLVM::IS_LT_130 %} LibLLVM.get_inline_asm( self, asm_string, - asm_string.size, + asm_string.bytesize, constraints, - constraints.size, + constraints.bytesize, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), - LibLLVM::InlineAsmDialect::ATT + dialect, ) {% else %} LibLLVM.get_inline_asm( self, asm_string, - asm_string.size, + asm_string.bytesize, constraints, - constraints.size, + constraints.bytesize, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), - LibLLVM::InlineAsmDialect::ATT, + dialect, (can_throw ? 1 : 0) ) {% end %} diff --git a/src/mutex.cr b/src/mutex.cr index 6bdd9a98fd25..83dd4bb53429 100644 --- a/src/mutex.cr +++ b/src/mutex.cr @@ -107,6 +107,9 @@ class Mutex @mutex_fiber = nil end + {% if flag?(:aarch64) %} + Atomic::Ops.fence :sequentially_consistent, false + {% end %} @state.lazy_set(0) if @queue_count.get == 0 diff --git a/src/named_tuple.cr b/src/named_tuple.cr index 7cceb568a260..4ea9df02fd20 100644 --- a/src/named_tuple.cr +++ b/src/named_tuple.cr @@ -588,12 +588,25 @@ struct NamedTuple # # NOTE: `to_a` on an empty named tuple produces an `Array(Tuple(Symbol, NoReturn))` def to_a + to_a(&.itself) + end + + # Returns an `Array` with the results of running *block* against tuples with key and values belonging + # to this `NamedTuple`. + # + # ``` + # tuple = {first_name: "foo", last_name: "bar"} + # tuple.to_a(&.last.capitalize) # => ["Foo", "Bar"] + # ``` + # + # NOTE: `to_a` on an empty named tuple produces an `Array(Tuple(Symbol, NoReturn))` + def to_a(&) {% if T.size == 0 %} [] of {Symbol, NoReturn} {% else %} [ {% for key in T %} - { {{key.symbolize}}, self[{{key.symbolize}}] }, + yield({ {{key.symbolize}}, self[{{key.symbolize}}] }), {% end %} ] {% end %} diff --git a/src/object.cr b/src/object.cr index 6687e19f424a..ba818ac2979e 100644 --- a/src/object.cr +++ b/src/object.cr @@ -1293,17 +1293,18 @@ class Object # wrapper.capitalize # => "Hello" # ``` macro delegate(*methods, to object) - {% for method in methods %} - {% if method.id.ends_with?('=') && method.id != "[]=" %} - def {{method.id}}(arg) - {{object.id}}.{{method.id}} arg - end - {% else %} - def {{method.id}}(*args, **options) - {{object.id}}.{{method.id}}(*args, **options) - end + {% if compare_versions(Crystal::VERSION, "1.12.0-dev") >= 0 %} + {% eq_operators = %w(<= >= == != []= ===) %} + {% for method in methods %} + {% if method.id.ends_with?('=') && !eq_operators.includes?(method.id.stringify) %} + def {{method.id}}(arg) + {{object.id}}.{{method.id}} arg + end + {% else %} + def {{method.id}}(*args, **options) + {{object.id}}.{{method.id}}(*args, **options) + end - {% if method.id != "[]=" %} def {{method.id}}(*args, **options) {{object.id}}.{{method.id}}(*args, **options) do |*yield_args| yield *yield_args @@ -1311,6 +1312,26 @@ class Object end {% end %} {% end %} + {% else %} + {% for method in methods %} + {% if method.id.ends_with?('=') && method.id != "[]=" %} + def {{method.id}}(arg) + {{object.id}}.{{method.id}} arg + end + {% else %} + def {{method.id}}(*args, **options) + {{object.id}}.{{method.id}}(*args, **options) + end + + {% if method.id != "[]=" %} + def {{method.id}}(*args, **options) + {{object.id}}.{{method.id}}(*args, **options) do |*yield_args| + yield *yield_args + end + end + {% end %} + {% end %} + {% end %} {% end %} end diff --git a/src/openssl/lib_crypto.cr b/src/openssl/lib_crypto.cr index c783aa7903a9..caca9c11c520 100644 --- a/src/openssl/lib_crypto.cr +++ b/src/openssl/lib_crypto.cr @@ -36,6 +36,10 @@ {% else %} @[Link(ldflags: "`command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libcrypto || printf %s '-lcrypto'`")] {% end %} +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + # TODO: if someone brings their own OpenSSL 1.x.y on Windows, will this have a different name? + @[Link(dll: "libcrypto-3-x64.dll")] +{% end %} lib LibCrypto alias Char = LibC::Char alias Int = LibC::Int diff --git a/src/openssl/lib_ssl.cr b/src/openssl/lib_ssl.cr index 37a4cea3a161..27faf9bbe185 100644 --- a/src/openssl/lib_ssl.cr +++ b/src/openssl/lib_ssl.cr @@ -43,6 +43,11 @@ require "./lib_crypto" {% else %} @[Link(ldflags: "`command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libssl || printf %s '-lssl -lcrypto'`")] {% end %} +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + # TODO: if someone brings their own OpenSSL 1.x.y on Windows, will this have a different name? + @[Link(dll: "libssl-3-x64.dll")] + @[Link(dll: "libcrypto-3-x64.dll")] +{% end %} lib LibSSL alias Int = LibC::Int alias Char = LibC::Char diff --git a/src/prelude.cr b/src/prelude.cr index f06f5bc87015..f84bb86cb3c1 100644 --- a/src/prelude.cr +++ b/src/prelude.cr @@ -65,6 +65,7 @@ require "raise" require "random" require "range" require "reference" +require "reference_storage" require "regex" require "set" {% unless flag?(:wasm32) %} diff --git a/src/reference_storage.cr b/src/reference_storage.cr new file mode 100644 index 000000000000..2ca3edc171aa --- /dev/null +++ b/src/reference_storage.cr @@ -0,0 +1,55 @@ +# `ReferenceStorage(T)` provides the minimum storage for the instance data of +# an object of type `T`. The compiler guarantees that +# `sizeof(ReferenceStorage(T)) == instance_sizeof(T)` and +# `alignof(ReferenceStorage(T)) == instance_alignof(T)` always hold, which means +# `Pointer(ReferenceStorage(T))` and `T` are binary-compatible. +# +# `T` must be a non-union reference type. +# +# WARNING: `ReferenceStorage` is only necessary for manual memory management, +# such as creating instances of `T` with a non-default allocator. Therefore, +# this type is unsafe and no public constructors are defined. +# +# WARNING: `ReferenceStorage` is unsuitable when instances of `T` require more +# than `instance_sizeof(T)` bytes, such as `String` and `Log::Metadata`. +@[Experimental("This type's API is still under development. Join the discussion about custom reference allocation at [#13481](https://github.com/crystal-lang/crystal/issues/13481).")] +@[Primitive(:ReferenceStorageType)] +struct ReferenceStorage(T) < Value + private def initialize + end + + # Returns whether `self` and *other* are bytewise equal. + # + # NOTE: This does not call `T#==`, so it works even if `self` or *other* does + # not represent a valid instance of `T`. If validity is guaranteed, call + # `to_reference == other.to_reference` instead to use `T#==`. + def ==(other : ReferenceStorage(T)) : Bool + to_bytes == other.to_bytes + end + + def ==(other) : Bool + false + end + + def hash(hasher) + to_bytes.hash(hasher) + end + + def to_s(io : IO) : Nil + io << "ReferenceStorage(#<" << T << ":0x" + pointerof(@type_id).address.to_s(io, 16) + io << ">)" + end + + # Returns a `T` whose instance data refers to `self`. + # + # WARNING: The caller is responsible for ensuring that the instance data is + # correctly initialized and outlives the returned `T`. + def to_reference : T + pointerof(@type_id).as(T) + end + + protected def to_bytes + Slice.new(pointerof(@type_id).as(UInt8*), instance_sizeof(T)) + end +end diff --git a/src/regex/lib_pcre.cr b/src/regex/lib_pcre.cr index 5f110eba0ce7..647a172a9d43 100644 --- a/src/regex/lib_pcre.cr +++ b/src/regex/lib_pcre.cr @@ -1,4 +1,7 @@ @[Link("pcre")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "pcre.dll")] +{% end %} lib LibPCRE alias Int = LibC::Int diff --git a/src/regex/lib_pcre2.cr b/src/regex/lib_pcre2.cr index a04761cbe07e..71a0fd4b6639 100644 --- a/src/regex/lib_pcre2.cr +++ b/src/regex/lib_pcre2.cr @@ -1,4 +1,7 @@ @[Link("pcre2-8")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "pcre2-8.dll")] +{% end %} lib LibPCRE2 alias Int = LibC::Int diff --git a/src/set.cr b/src/set.cr index 091352302c7d..40425e9aa032 100644 --- a/src/set.cr +++ b/src/set.cr @@ -382,6 +382,19 @@ struct Set(T) @hash.keys end + # Returns an `Array` with the results of running *block* against each element of the collection. + # + # ``` + # Set{1, 2, 3, 4, 5}.to_a { |i| i // 2 } # => [0, 1, 2] + # ``` + def to_a(& : T -> U) : Array(U) forall U + array = Array(U).new(size) + @hash.each_key do |key| + array << key + end + array + end + # Alias of `#to_s`. def inspect(io : IO) : Nil to_s(io) diff --git a/src/signal.cr b/src/signal.cr index 60eba5b8e7f3..2e085b92311e 100644 --- a/src/signal.cr +++ b/src/signal.cr @@ -117,6 +117,24 @@ enum Signal : Int32 Crystal::System::Signal.trap(self, handler) end + # Returns any existing handler for this signal + # + # ``` + # Signal::USR1.trap { } + # prev_handler = Signal::USR1.trap_handler? + # + # Signal::USR1.trap do |signal| + # prev_handler.try &.call(signal) + # # ... + # end + # ``` + def trap_handler? + {% if @type.has_constant?("CHLD") %} + return Crystal::System::Signal.child_handler if self == CHLD + {% end %} + Crystal::System::Signal.trap_handler?(self) + end + # Resets the handler for this signal to the OS default. # # Note that trying to reset `CHLD` will actually set the default crystal diff --git a/src/spec.cr b/src/spec.cr index e9cf5d448efd..c51ee8831de4 100644 --- a/src/spec.cr +++ b/src/spec.cr @@ -91,45 +91,51 @@ require "./spec/cli" # value can be used to rerun the specs in that same order by passing the seed # value to `--order`. module Spec -end + # :nodoc: + class CLI + # :nodoc: + # + # Implement formatter configuration. + def configure_formatter(formatter, output_path = nil) + case formatter + when "junit" + junit_formatter = Spec::JUnitFormatter.file(Path.new(output_path.not_nil!)) + add_formatter(junit_formatter) + when "verbose" + override_default_formatter(Spec::VerboseFormatter.new) + when "tap" + override_default_formatter(Spec::TAPFormatter.new) + end + end -Colorize.on_tty_only! + def main(args) + Colorize.on_tty_only! -# :nodoc: -# -# Implement formatter configuration. -def Spec.configure_formatter(formatter, output_path = nil) - case formatter - when "junit" - junit_formatter = Spec::JUnitFormatter.file(Path.new(output_path.not_nil!)) - Spec.add_formatter(junit_formatter) - when "verbose" - Spec.override_default_formatter(Spec::VerboseFormatter.new) - when "tap" - Spec.override_default_formatter(Spec::TAPFormatter.new) - end -end + begin + option_parser.parse(args) + rescue e : OptionParser::InvalidOption + abort("Error: #{e.message}") + end -begin - Spec.option_parser.parse(ARGV) -rescue e : OptionParser::InvalidOption - abort("Error: #{e.message}") -end + unless args.empty? + STDERR.puts "Error: unknown argument '#{args.first}'" + exit 1 + end -unless ARGV.empty? - STDERR.puts "Error: unknown argument '#{ARGV.first}'" - exit 1 -end + if ENV["SPEC_VERBOSE"]? == "1" + override_default_formatter(Spec::VerboseFormatter.new) + end -if ENV["SPEC_VERBOSE"]? == "1" - Spec.override_default_formatter(Spec::VerboseFormatter.new) -end + add_split_filter ENV["SPEC_SPLIT"]? -Spec.add_split_filter ENV["SPEC_SPLIT"]? + {% unless flag?(:wasm32) %} + # TODO(wasm): Enable this once `Process.on_interrupt` is implemented + Process.on_interrupt { abort! } + {% end %} -{% unless flag?(:wasm32) %} - # TODO(wasm): Enable this once `Process.on_interrupt` is implemented - Process.on_interrupt { Spec.abort! } -{% end %} + run + end + end +end -Spec.run +Spec.cli.main(ARGV) diff --git a/src/spec/cli.cr b/src/spec/cli.cr index e17f59206123..4f57c3d4adbb 100644 --- a/src/spec/cli.cr +++ b/src/spec/cli.cr @@ -1,139 +1,130 @@ require "option_parser" +require "colorize" # This file is included in the compiler to add usage instructions for the # spec runner on `crystal spec --help`. module Spec # :nodoc: - class_property pattern : Regex? - - # :nodoc: - class_property line : Int32? - - # :nodoc: - class_property slowest : Int32? - - # :nodoc: - class_property? fail_fast = false - - # :nodoc: - class_property? focus = false - - # :nodoc: - class_property? dry_run = false - - # :nodoc: - class_property? list_tags = false - - # :nodoc: - def self.add_location(file, line) - locations = @@locations ||= {} of String => Array(Int32) - locations.put_if_absent(File.expand_path(file)) { [] of Int32 } << line - end + # + # Configuration for a spec runner. More global state is defined in `./dsl.cr`. + class CLI + getter pattern : Regex? + getter line : Int32? + getter slowest : Int32? + getter? fail_fast = false + property? focus = false + getter? dry_run = false + getter? list_tags = false - # :nodoc: - def self.add_tag(tag) - if anti_tag = tag.lchop?('~') - (@@anti_tags ||= Set(String).new) << anti_tag - else - (@@tags ||= Set(String).new) << tag + def add_location(file, line) + locations = @locations ||= {} of String => Array(Int32) + locations.put_if_absent(File.expand_path(file)) { [] of Int32 } << line end - end - - # :nodoc: - class_getter randomizer_seed : UInt64? - class_getter randomizer : Random::PCG32? - # :nodoc: - def self.order=(mode) - seed = - case mode - when "default" - nil - when "random" - Random::Secure.rand(1..99999).to_u64 # 5 digits or less for simplicity - when UInt64 - mode + def add_tag(tag) + if anti_tag = tag.lchop?('~') + (@anti_tags ||= Set(String).new) << anti_tag else - raise ArgumentError.new("Order must be either 'default', 'random', or a numeric seed value") + (@tags ||= Set(String).new) << tag end + end - @@randomizer_seed = seed - @@randomizer = seed ? Random::PCG32.new(seed) : nil - end + getter randomizer_seed : UInt64? + getter randomizer : Random::PCG32? - # :nodoc: - class_property option_parser : OptionParser = begin - OptionParser.new do |opts| - opts.banner = "crystal spec runner" - opts.on("-e", "--example STRING", "run examples whose full nested names include STRING") do |pattern| - Spec.pattern = Regex.new(Regex.escape(pattern)) - end - opts.on("-l", "--line LINE", "run examples whose line matches LINE") do |line| - Spec.line = line.to_i - end - opts.on("-p", "--profile", "Print the 10 slowest specs") do - Spec.slowest = 10 - end - opts.on("--fail-fast", "abort the run on first failure") do - Spec.fail_fast = true - end - opts.on("--location file:line", "run example at line 'line' in file 'file', multiple allowed") do |location| - if location =~ /\A(.+?)\:(\d+)\Z/ - Spec.add_location $1, $2.to_i + def order=(mode) + seed = + case mode + when "default" + nil + when "random" + Random::Secure.rand(1..99999).to_u64 # 5 digits or less for simplicity + when UInt64 + mode else - STDERR.puts "location #{location} must be file:line" - exit 1 + raise ArgumentError.new("Order must be either 'default', 'random', or a numeric seed value") end - end - opts.on("--tag TAG", "run examples with the specified TAG, or exclude examples by adding ~ before the TAG.") do |tag| - Spec.add_tag tag - end - opts.on("--list-tags", "lists all the tags used.") do - Spec.list_tags = true - end - opts.on("--order MODE", "run examples in random order by passing MODE as 'random' or to a specific seed by passing MODE as the seed value") do |mode| - if mode.in?("default", "random") - Spec.order = mode - elsif seed = mode.to_u64? - Spec.order = seed - else - abort("order must be either 'default', 'random', or a numeric seed value") + + @randomizer_seed = seed + @randomizer = seed ? Random::PCG32.new(seed) : nil + end + + def option_parser : OptionParser + @option_parser ||= OptionParser.new do |opts| + opts.banner = "crystal spec runner" + opts.on("-e", "--example STRING", "run examples whose full nested names include STRING") do |pattern| + @pattern = Regex.new(Regex.escape(pattern)) + end + opts.on("-l", "--line LINE", "run examples whose line matches LINE") do |line| + @line = line.to_i + end + opts.on("-p", "--profile", "Print the 10 slowest specs") do + @slowest = 10 + end + opts.on("--fail-fast", "abort the run on first failure") do + @fail_fast = true + end + opts.on("--location file:line", "run example at line 'line' in file 'file', multiple allowed") do |location| + if location =~ /\A(.+?)\:(\d+)\Z/ + add_location $1, $2.to_i + else + STDERR.puts "location #{location} must be file:line" + exit 1 + end + end + opts.on("--tag TAG", "run examples with the specified TAG, or exclude examples by adding ~ before the TAG.") do |tag| + add_tag tag + end + opts.on("--list-tags", "lists all the tags used.") do + @list_tags = true + end + opts.on("--order MODE", "run examples in random order by passing MODE as 'random' or to a specific seed by passing MODE as the seed value") do |mode| + if mode.in?("default", "random") + self.order = mode + elsif seed = mode.to_u64? + self.order = seed + else + abort("order must be either 'default', 'random', or a numeric seed value") + end + end + opts.on("--junit_output OUTPUT_PATH", "generate JUnit XML output within the given OUTPUT_PATH") do |output_path| + configure_formatter("junit", output_path) + end + opts.on("-h", "--help", "show this help") do |pattern| + puts opts + exit + end + opts.on("-v", "--verbose", "verbose output") do + configure_formatter("verbose") + end + opts.on("--tap", "Generate TAP output (Test Anything Protocol)") do + configure_formatter("tap") + end + opts.on("--color", "Enabled ANSI colored output") do + Colorize.enabled = true + end + opts.on("--no-color", "Disable ANSI colored output") do + Colorize.enabled = false + end + opts.on("--dry-run", "Pass all tests without execution") do + @dry_run = true + end + opts.unknown_args do |args| end - end - opts.on("--junit_output OUTPUT_PATH", "generate JUnit XML output within the given OUTPUT_PATH") do |output_path| - configure_formatter("junit", output_path) - end - opts.on("-h", "--help", "show this help") do |pattern| - puts opts - exit - end - opts.on("-v", "--verbose", "verbose output") do - configure_formatter("verbose") - end - opts.on("--tap", "Generate TAP output (Test Anything Protocol)") do - configure_formatter("tap") - end - opts.on("--color", "Enabled ANSI colored output") do - Colorize.enabled = true - end - opts.on("--no-color", "Disable ANSI colored output") do - Colorize.enabled = false - end - opts.on("--dry-run", "Pass all tests without execution") do - Spec.dry_run = true - end - opts.unknown_args do |args| end end + + # Blank implementation to reduce the interface of spec's option parser for + # inclusion in the compiler. This avoids depending on more of `Spec` + # module. + # The real implementation in `../spec.cr` overrides this for actual use. + def configure_formatter(formatter, output_path = nil) + end end - # :nodoc: - # - # Blank implementation to reduce the interface of spec's option parser for - # inclusion in the compiler. This avoids depending on more of `Spec` - # module. - # The real implementation in `../spec.cr` overrides this for actual use. - def self.configure_formatter(formatter, output_path = nil) + @[Deprecated("This is an internal API.")] + def self.randomizer : Random::PCG32? + @@cli.randomizer end end diff --git a/src/spec/context.cr b/src/spec/context.cr index 0a1109c12b92..c18836fe0455 100644 --- a/src/spec/context.cr +++ b/src/spec/context.cr @@ -126,13 +126,15 @@ module Spec exception : Exception? # :nodoc: - def self.root_context - RootContext.instance - end + class CLI + def root_context + RootContext.instance + end - # :nodoc: - def self.current_context : Context - RootContext.current_context + # :nodoc: + def current_context : Context + RootContext.current_context + end end # :nodoc: @@ -167,7 +169,7 @@ module Spec end def report_formatters(result) - Spec.formatters.each(&.report(result)) + Spec.cli.formatters.each(&.report(result)) end def succeeded @@ -175,8 +177,8 @@ module Spec end def finish(elapsed_time, aborted = false) - Spec.formatters.each(&.finish(elapsed_time, aborted)) - Spec.formatters.each(&.print_results(elapsed_time, aborted)) + Spec.cli.formatters.each(&.finish(elapsed_time, aborted)) + Spec.cli.formatters.each(&.print_results(elapsed_time, aborted)) end def print_results(elapsed_time, aborted = false) @@ -223,13 +225,13 @@ module Spec end end - if Spec.slowest + if Spec.cli.slowest puts results = results_for(:success) + results_for(:fail) - top_n = results.sort_by { |res| -res.elapsed.not_nil!.to_f }[0..Spec.slowest.not_nil!] + top_n = results.sort_by { |res| -res.elapsed.not_nil!.to_f }[0..Spec.cli.slowest.not_nil!] top_n_time = top_n.sum &.elapsed.not_nil!.total_seconds percent = (top_n_time * 100) / elapsed_time.total_seconds - puts "Top #{Spec.slowest} slowest examples (#{top_n_time.humanize} seconds, #{percent.round(2)}% of total time):" + puts "Top #{Spec.cli.slowest} slowest examples (#{top_n_time.humanize} seconds, #{percent.round(2)}% of total time):" top_n.each do |res| puts " #{res.description}" res_elapsed = res.elapsed.not_nil!.total_seconds.humanize @@ -252,7 +254,7 @@ module Spec puts "Aborted!".colorize.red if aborted puts "Finished in #{Spec.to_human(elapsed_time)}" puts Spec.color("#{total} examples, #{failures.size} failures, #{errors.size} errors, #{pendings.size} pending", final_status) - puts Spec.color("Only running `focus: true`", :focus) if Spec.focus? + puts Spec.color("Only running `focus: true`", :focus) if Spec.cli.focus? unless failures_and_errors.empty? puts @@ -268,13 +270,13 @@ module Spec end def print_order_message - if randomizer_seed = Spec.randomizer_seed + if randomizer_seed = Spec.cli.randomizer_seed puts Spec.color("Randomized with seed: #{randomizer_seed}", :order) end end def describe(description, file, line, end_line, focus, tags, &block) - Spec.focus = true if focus + Spec.cli.focus = true if focus context = Spec::ExampleGroup.new(@@current_context, description, file, line, end_line, focus, tags) @@current_context.children << context @@ -298,7 +300,7 @@ module Spec private def add_example(description, file, line, end_line, focus, tags, block) check_nesting_spec(file, line) do - Spec.focus = true if focus + Spec.cli.focus = true if focus @@current_context.children << Example.new(@@current_context, description, file, line, end_line, focus, tags, block) end @@ -334,12 +336,12 @@ module Spec # :nodoc: def run - Spec.formatters.each(&.push(self)) + Spec.cli.formatters.each(&.push(self)) ran = run_around_all_hooks(ExampleGroup::Procsy.new(self) { internal_run }) ran || internal_run - Spec.formatters.each(&.pop) + Spec.cli.formatters.each(&.pop) end protected def report(status : Status, description, file, line, elapsed = nil, ex = nil) diff --git a/src/spec/dsl.cr b/src/spec/dsl.cr index 065b31e7aff4..578076b86d69 100644 --- a/src/spec/dsl.cr +++ b/src/spec/dsl.cr @@ -2,6 +2,10 @@ require "colorize" require "option_parser" module Spec + # :nodoc: + # The default spec runner. + class_getter cli = CLI.new + # :nodoc: enum InfoKind Comment @@ -61,14 +65,6 @@ module Spec class NestingSpecError < SpecError end - @@aborted = false - - # :nodoc: - def self.abort! - @@aborted = true - finish_run - end - # :nodoc: def self.to_human(span : Time::Span) total_milliseconds = span.total_milliseconds @@ -92,17 +88,6 @@ module Spec record SplitFilter, remainder : Int32, quotient : Int32 - @@split_filter : SplitFilter? = nil - - def self.add_split_filter(filter) - if filter - r, _, m = filter.partition('%') - @@split_filter = SplitFilter.new(remainder: r.to_i, quotient: m.to_i) - else - @@split_filter = nil - end - end - # Instructs the spec runner to execute the given block # before each spec in the spec suite. # @@ -118,7 +103,7 @@ module Spec # # will print, just before each spec, 1 and then 2. def self.before_each(&block) - root_context.before_each(&block) + @@cli.root_context.before_each(&block) end # Instructs the spec runner to execute the given block @@ -136,7 +121,7 @@ module Spec # # will print, just after each spec, 2 and then 1. def self.after_each(&block) - root_context.after_each(&block) + @@cli.root_context.after_each(&block) end # Instructs the spec runner to execute the given block @@ -154,7 +139,7 @@ module Spec # # will print, just before the spec suite starts, 1 and then 2. def self.before_suite(&block) - root_context.before_all(&block) + @@cli.root_context.before_all(&block) end # Instructs the spec runner to execute the given block @@ -172,7 +157,7 @@ module Spec # # will print, just after the spec suite ends, 2 and then 1. def self.after_suite(&block) - root_context.after_all(&block) + @@cli.root_context.after_all(&block) end # Instructs the spec runner to execute the given block when each spec in the @@ -196,129 +181,157 @@ module Spec # it { } # ``` def self.around_each(&block : Example::Procsy ->) - root_context.around_each(&block) + @@cli.root_context.around_each(&block) end - @@start_time : Time::Span? = nil - # :nodoc: - def self.run - @@start_time = Time.monotonic - - at_exit do |status| - # Do not run specs if the process is exiting on an error - next unless status == 0 - - begin - if Spec.list_tags? - execute_list_tags - else - execute_examples + class CLI + @aborted = false + + def abort! + @aborted = true + finish_run + end + + @split_filter : SplitFilter? = nil + + def add_split_filter(filter) + if filter + r, _, m = filter.partition('%') + @split_filter = SplitFilter.new(remainder: r.to_i, quotient: m.to_i) + else + @split_filter = nil + end + end + + @start_time : Time::Span? = nil + + def run + @start_time = Time.monotonic + + at_exit do |status| + # Do not run specs if the process is exiting on an error + next unless status == 0 + + begin + if list_tags? + execute_list_tags + else + execute_examples + end + rescue ex + STDERR.print "Unhandled exception: " + ex.inspect_with_backtrace(STDERR) + STDERR.flush + @aborted = true + ensure + finish_run unless list_tags? end - rescue ex - STDERR.print "Unhandled exception: " - ex.inspect_with_backtrace(STDERR) - STDERR.flush - @@aborted = true - ensure - finish_run unless Spec.list_tags? end end - end - # :nodoc: - def self.execute_examples - log_setup - maybe_randomize - run_filters - root_context.run - end + def execute_examples + log_setup + maybe_randomize + run_filters + root_context.run + end - # :nodoc: - def self.execute_list_tags - run_filters - tag_counts = collect_tags(root_context) - print_list_tags(tag_counts) - end + def execute_list_tags + run_filters + tag_counts = collect_tags(root_context) + print_list_tags(tag_counts) + end - private def self.collect_tags(context) : Hash(String, Int32) - tag_counts = Hash(String, Int32).new(0) - collect_tags(tag_counts, context, Set(String).new) - tag_counts - end + private def collect_tags(context) : Hash(String, Int32) + tag_counts = Hash(String, Int32).new(0) + collect_tags(tag_counts, context, Set(String).new) + tag_counts + end - private def self.collect_tags(tag_counts, context : Context, tags) - if context.responds_to?(:tags) && (context_tags = context.tags) - tags += context_tags + private def collect_tags(tag_counts, context : Context, tags) + if context.responds_to?(:tags) && (context_tags = context.tags) + tags += context_tags + end + context.children.each do |child| + collect_tags(tag_counts, child, tags) + end end - context.children.each do |child| - collect_tags(tag_counts, child, tags) + + private def collect_tags(tag_counts, example : Example, tags) + if example_tags = example.tags + tags += example_tags + end + if tags.empty? + tag_counts.update("untagged") { |count| count + 1 } + else + tags.tally(tag_counts) + end end - end - private def self.collect_tags(tag_counts, example : Example, tags) - if example_tags = example.tags - tags += example_tags + private def print_list_tags(tag_counts : Hash(String, Int32)) : Nil + return if tag_counts.empty? + longest_name_size = tag_counts.keys.max_of(&.size) + tag_counts.to_a.sort_by! { |k, v| {-v, k} }.each do |tag_name, count| + puts "#{tag_name.rjust(longest_name_size)}: #{count}" + end end - if tags.empty? - tag_counts.update("untagged") { |count| count + 1 } - else - tags.tally(tag_counts) + + # :nodoc: + # + # Workaround for #8914 + private macro defined?(t) + {% if t.resolve? %} + {{ yield }} + {% end %} end - end - private def self.print_list_tags(tag_counts : Hash(String, Int32)) : Nil - return if tag_counts.empty? - longest_name_size = tag_counts.keys.max_of(&.size) - tag_counts.to_a.sort_by! { |k, v| {-v, k} }.each do |tag_name, count| - puts "#{tag_name.rjust(longest_name_size)}: #{count}" + # :nodoc: + def log_setup end - end - # :nodoc: - # - # Workaround for #8914 - private macro defined?(t) - {% if t.resolve? %} - {{ yield }} - {% end %} - end + # :nodoc: + macro finished + # :nodoc: + # + # Initialized the log module for the specs. + # If the "log" module is required it is configured to emit no entries by default. + def log_setup + defined?(::Log) do + if Log.responds_to?(:setup) + Log.setup_from_env(default_level: :none) + end + end + end + end - # :nodoc: - def self.log_setup - end + def finish_run + elapsed_time = Time.monotonic - @start_time.not_nil! + root_context.finish(elapsed_time, @aborted) + exit 1 if !root_context.succeeded || @aborted || (focus? && ENV["SPEC_FOCUS_NO_FAIL"]? != "1") + end - # :nodoc: - macro finished # :nodoc: - # - # Initialized the log module for the specs. - # If the "log" module is required it is configured to emit no entries by default. - def self.log_setup - defined?(::Log) do - if Log.responds_to?(:setup) - Log.setup_from_env(default_level: :none) - end + def maybe_randomize + if randomizer = @randomizer + root_context.randomize(randomizer) end end - end - def self.finish_run - elapsed_time = Time.monotonic - @@start_time.not_nil! - root_context.finish(elapsed_time, @@aborted) - exit 1 if !root_context.succeeded || @@aborted || (focus? && ENV["SPEC_FOCUS_NO_FAIL"]? != "1") + # :nodoc: + def run_filters + root_context.run_filters(@pattern, @line, @locations, @split_filter, @focus, @tags, @anti_tags) + end end - # :nodoc: - def self.maybe_randomize - if randomizer = @@randomizer - root_context.randomize(randomizer) - end + @[Deprecated("This is an internal API.")] + def self.finish_run + @@cli.finish_run end - # :nodoc: - def self.run_filters - root_context.run_filters(@@pattern, @@line, @@locations, @@split_filter, @@focus, @@tags, @@anti_tags) + @[Deprecated("This is an internal API.")] + def self.add_split_filter(filter) + @@cli.add_split_filter(filter) end end diff --git a/src/spec/example.cr b/src/spec/example.cr index e6ae51942a38..72bffd6c0e07 100644 --- a/src/spec/example.cr +++ b/src/spec/example.cr @@ -18,10 +18,10 @@ module Spec # :nodoc: def run - Spec.root_context.check_nesting_spec(file, line) do - Spec.formatters.each(&.before_example(description)) + Spec.cli.root_context.check_nesting_spec(file, line) do + Spec.cli.formatters.each(&.before_example(description)) - if Spec.dry_run? + if Spec.cli.dry_run? @parent.report(:success, description, file, line) return end @@ -51,12 +51,12 @@ module Spec @parent.report(:success, description, file, line, Time.monotonic - start) rescue ex : Spec::AssertionFailed @parent.report(:fail, description, file, line, Time.monotonic - start, ex) - Spec.abort! if Spec.fail_fast? + Spec.cli.abort! if Spec.cli.fail_fast? rescue ex : Spec::ExamplePending @parent.report(:pending, description, file, line, Time.monotonic - start) rescue ex @parent.report(:error, description, file, line, Time.monotonic - start, ex) - Spec.abort! if Spec.fail_fast? + Spec.cli.abort! if Spec.cli.fail_fast? ensure @parent.run_after_each_hooks end diff --git a/src/spec/formatter.cr b/src/spec/formatter.cr index 51b355ec075f..cfd88f2b5a6a 100644 --- a/src/spec/formatter.cr +++ b/src/spec/formatter.cr @@ -55,7 +55,7 @@ module Spec end def print_results(elapsed_time : Time::Span, aborted : Bool) - Spec.root_context.print_results(elapsed_time, aborted) + Spec.cli.root_context.print_results(elapsed_time, aborted) end end @@ -111,22 +111,34 @@ module Spec end def print_results(elapsed_time : Time::Span, aborted : Bool) - Spec.root_context.print_results(elapsed_time, aborted) + Spec.cli.root_context.print_results(elapsed_time, aborted) end end - @@formatters = [Spec::DotFormatter.new] of Spec::Formatter - # :nodoc: - def self.formatters - @@formatters + class CLI + @formatters = [Spec::DotFormatter.new] of Spec::Formatter + + def formatters + @formatters + end + + def override_default_formatter(formatter) + @formatters[0] = formatter + end + + def add_formatter(formatter) + @formatters << formatter + end end + @[Deprecated("This is an internal API.")] def self.override_default_formatter(formatter) - @@formatters[0] = formatter + @@cli.override_default_formatter(formatter) end + @[Deprecated("This is an internal API.")] def self.add_formatter(formatter) - @@formatters << formatter + @@cli.add_formatter(formatter) end end diff --git a/src/spec/methods.cr b/src/spec/methods.cr index f98326be0ed3..54b8de34b9bb 100644 --- a/src/spec/methods.cr +++ b/src/spec/methods.cr @@ -17,7 +17,7 @@ module Spec::Methods # # If `focus` is `true`, only this `describe`, and others marked with `focus: true`, will run. def describe(description = nil, file = __FILE__, line = __LINE__, end_line = __END_LINE__, focus : Bool = false, tags : String | Enumerable(String) | Nil = nil, &block) - Spec.root_context.describe(description.to_s, file, line, end_line, focus, tags, &block) + Spec.cli.root_context.describe(description.to_s, file, line, end_line, focus, tags, &block) end # Defines an example group that establishes a specific context, @@ -46,7 +46,7 @@ module Spec::Methods # # If `focus` is `true`, only this test, and others marked with `focus: true`, will run. def it(description = "assert", file = __FILE__, line = __LINE__, end_line = __END_LINE__, focus : Bool = false, tags : String | Enumerable(String) | Nil = nil, &block) - Spec.root_context.it(description.to_s, file, line, end_line, focus, tags, &block) + Spec.cli.root_context.it(description.to_s, file, line, end_line, focus, tags, &block) end # Defines a pending test case. @@ -72,7 +72,7 @@ module Spec::Methods # # If `focus` is `true`, only this test, and others marked with `focus: true`, will run. def pending(description = "assert", file = __FILE__, line = __LINE__, end_line = __END_LINE__, focus : Bool = false, tags : String | Enumerable(String) | Nil = nil) - Spec.root_context.pending(description.to_s, file, line, end_line, focus, tags) + Spec.cli.root_context.pending(description.to_s, file, line, end_line, focus, tags) end # Fails an example. @@ -124,10 +124,10 @@ module Spec::Methods # end # ``` def before_each(&block) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `before_each` outside of a describe/context" end - Spec.current_context.before_each(&block) + Spec.cli.current_context.before_each(&block) end # Executes the given block after each spec in the current context runs. @@ -154,10 +154,10 @@ module Spec::Methods # end # ``` def after_each(&block) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `after_each` outside of a describe/context" end - Spec.current_context.after_each(&block) + Spec.cli.current_context.after_each(&block) end # Executes the given block before the first spec in the current context runs. @@ -184,10 +184,10 @@ module Spec::Methods # end # ``` def before_all(&block) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `before_all` outside of a describe/context" end - Spec.current_context.before_all(&block) + Spec.cli.current_context.before_all(&block) end # Executes the given block after the last spec in the current context runs. @@ -214,10 +214,10 @@ module Spec::Methods # end # ``` def after_all(&block) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `after_all` outside of a describe/context" end - Spec.current_context.after_all(&block) + Spec.cli.current_context.after_all(&block) end # Executes the given block when each spec in the current context runs. @@ -252,10 +252,10 @@ module Spec::Methods # end # ``` def around_each(&block : Example::Procsy ->) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `around_each` outside of a describe/context" end - Spec.current_context.around_each(&block) + Spec.cli.current_context.around_each(&block) end # Executes the given block when the current context runs. @@ -297,10 +297,10 @@ module Spec::Methods # end # ``` def around_all(&block : ExampleGroup::Procsy ->) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `around_all` outside of a describe/context" end - Spec.current_context.around_all(&block) + Spec.cli.current_context.around_all(&block) end end diff --git a/src/string.cr b/src/string.cr index 98b7ec3884fd..4004f0d34929 100644 --- a/src/string.cr +++ b/src/string.cr @@ -4198,7 +4198,6 @@ class String count = 0 match_offset = slice_offset = 0 - options = Regex::MatchOptions::None while match = separator.match_at_byte_index(self, match_offset, options: options) index = match.byte_begin(0) match_bytesize = match.byte_end(0) - index @@ -4744,7 +4743,6 @@ class String def scan(pattern : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None, &) : self byte_offset = 0 - options = Regex::MatchOptions::None while match = pattern.match_at_byte_index(self, byte_offset, options: options) index = match.byte_begin(0) $~ = match diff --git a/src/string/builder.cr b/src/string/builder.cr index 0fb77f4ca41b..a06644b831d1 100644 --- a/src/string/builder.cr +++ b/src/string/builder.cr @@ -41,21 +41,14 @@ class String::Builder < IO return if slice.empty? count = slice.size - new_bytesize = real_bytesize + count - if new_bytesize > @capacity - resize_to_capacity(Math.pw2ceil(new_bytesize)) - end + increase_capacity_by count slice.copy_to(@buffer + real_bytesize, count) @bytesize += count end def write_byte(byte : UInt8) : Nil - new_bytesize = real_bytesize + 1 - if new_bytesize > @capacity - resize_to_capacity(Math.pw2ceil(new_bytesize)) - end - + increase_capacity_by 1 @buffer[real_bytesize] = byte @bytesize += 1 @@ -108,17 +101,18 @@ class String::Builder < IO raise "Can only invoke 'to_s' once on String::Builder" if @finished @finished = true - write_byte 0_u8 + real_bytesize = real_bytesize() + @buffer[real_bytesize] = 0_u8 + real_bytesize += 1 # Try to reclaim some memory if capacity is bigger than what we need - real_bytesize = real_bytesize() if @capacity > real_bytesize resize_to_capacity(real_bytesize) end String.set_crystal_type_id(@buffer) str = @buffer.as(String) - str.initialize_header((bytesize - 1).to_i) + str.initialize_header(bytesize) str end @@ -126,6 +120,26 @@ class String::Builder < IO @bytesize + String::HEADER_SIZE end + private def increase_capacity_by(count) + raise IO::EOFError.new if count >= Int32::MAX - real_bytesize + + new_bytesize = real_bytesize + count + return if new_bytesize <= @capacity + + new_capacity = calculate_new_capacity(new_bytesize) + resize_to_capacity(new_capacity) + end + + private def calculate_new_capacity(new_bytesize) + # If the new bytesize is bigger than 1 << 30, the next power of two would + # be 1 << 31, which is out of range for Int32. + # So we limit the capacity to Int32::MAX in order to be able to use the + # range (1 << 30) < new_bytesize < Int32::MAX + return Int32::MAX if new_bytesize > 1 << 30 + + Math.pw2ceil(new_bytesize) + end + private def resize_to_capacity(capacity) @capacity = capacity @buffer = GC.realloc(@buffer, @capacity) diff --git a/src/string/formatter.cr b/src/string/formatter.cr index e85322f39d2e..b5f80d2aee87 100644 --- a/src/string/formatter.cr +++ b/src/string/formatter.cr @@ -2,6 +2,13 @@ require "c/stdio" # :nodoc: struct String::Formatter(A) + # FIXME: wasm32 appears to run out of memory if we use Ryu Printf, which + # initializes very large lookup tables, so we fall back to `LibC.snprintf` for + # the floating-point format specifiers (#13918) + {% begin %} + HAS_RYU_PRINTF = {{ !flag?(:wasm32) }} + {% end %} + private enum Mode None @@ -15,15 +22,19 @@ struct String::Formatter(A) Named end - @format_buf = Pointer(UInt8).null - @temp_buf = Pointer(UInt8).null + {% unless HAS_RYU_PRINTF %} + @format_buf = Pointer(UInt8).null + @format_buf_len = 0 + + @temp_buf = Pointer(UInt8).null + @temp_buf_len = 0 + {% end %} + @arg_mode : Mode = :none def initialize(string, @args : A, @io : IO) @reader = Char::Reader.new(string) @arg_index = 0 - @temp_buf_len = 0 - @format_buf_len = 0 end def format : Nil @@ -118,13 +129,17 @@ struct String::Formatter(A) next else flags.width = val - flags.width_size = size + {% unless HAS_RYU_PRINTF %} + flags.width_size = size + {% end %} break end when '*' val = consume_dynamic_value flags.width = val - flags.width_size = val.to_s.size + {% unless HAS_RYU_PRINTF %} + flags.width_size = val.to_s.size + {% end %} break else break @@ -141,16 +156,22 @@ struct String::Formatter(A) when '0'..'9' num, size = consume_number flags.precision = num - flags.precision_size = size + {% unless HAS_RYU_PRINTF %} + flags.precision_size = size + {% end %} when '*' val = consume_dynamic_value if val >= 0 flags.precision = val - flags.precision_size = val.to_s.size + {% unless HAS_RYU_PRINTF %} + flags.precision_size = val.to_s.size + {% end %} end else flags.precision = 0 - flags.precision_size = 1 + {% unless HAS_RYU_PRINTF %} + flags.precision_size = 1 + {% end %} end end flags @@ -307,12 +328,7 @@ struct String::Formatter(A) elsif float.nan? float_special("nan", 1, flags) else - # FIXME: wasm32 appears to run out of memory if we use Ryu Printf, which - # initializes very large lookup tables, so we always fall back to - # `LibC.snprintf` (#13918) - {% if flag?(:wasm32) %} - float_fallback(float, flags) - {% else %} + {% if HAS_RYU_PRINTF %} case flags.type when 'f' float_fixed(float, flags) @@ -325,6 +341,8 @@ struct String::Formatter(A) else raise "BUG: Unknown format type '#{flags.type}'" end + {% else %} + float_fallback(float, flags) {% end %} end else @@ -346,7 +364,7 @@ struct String::Formatter(A) pad(str_size, flags) if flags.right_padding? end - {% unless flag?(:wasm32) %} + {% if HAS_RYU_PRINTF %} # Formats floats with `%f` private def float_fixed(float, flags) # the longest string possible is due to `Float64::MIN_SUBNORMAL`, which @@ -430,8 +448,37 @@ struct String::Formatter(A) # Formats floats with `%g` or `%G` private def float_general(float, flags) - # TODO: implement using `Float::Printer::RyuPrintf` - float_fallback(float, flags) + # `d2gen_buffered_n` will always take care of trailing zeros and return + # the number of stripped digits + precision = flags.precision.try(&.to_u32) || 6_u32 + + printf_buf = uninitialized UInt8[773] + printf_size, trailing_zeros = + Float::Printer::RyuPrintf.d2gen_buffered_n(float.abs, precision, printf_buf.to_unsafe, flags.sharp) + printf_slice = printf_buf.to_slice[0, printf_size] + dot_index = printf_slice.index('.'.ord) + e_index = printf_slice.rindex('e'.ord) + sign = Math.copysign(1.0, float) + + printf_slice[e_index] = 'E'.ord.to_u8! if e_index && flags.uppercase? + + str_size = printf_size + str_size += 1 if sign < 0 || flags.plus || flags.space + str_size += (dot_index.nil? ? 1 : 0) + trailing_zeros if flags.sharp + + pad(str_size, flags) if flags.left_padding? && flags.padding_char != '0' + + # this preserves -0.0's sign correctly + write_plus_or_space(sign, flags) + @io << '-' if sign < 0 + + pad(str_size, flags) if flags.left_padding? && flags.padding_char == '0' + @io.write_string(printf_slice[0...e_index]) + trailing_zeros.times { @io << '0' } if flags.sharp + @io << '.' if flags.sharp && dot_index.nil? + @io.write_string(printf_slice[e_index..]) if e_index + + pad(str_size, flags) if flags.right_padding? end # Formats floats with `%a` or `%A` @@ -456,50 +503,78 @@ struct String::Formatter(A) pad(str_size, flags) if flags.right_padding? end - {% end %} + {% else %} + # Delegate to `LibC.snprintf` for float formats if Ryu Printf is unavailable + private def float_fallback(float, flags) + format_buf = recreate_float_format_string(flags) - # Delegate to `LibC.snprintf` for float formats not yet ported to Crystal - private def float_fallback(float, flags) - format_buf = recreate_float_format_string(flags) + len = LibC.snprintf(nil, 0, format_buf, float) + 1 + temp_buf = temp_buf(len) + LibC.snprintf(temp_buf, len, format_buf, float) - len = LibC.snprintf(nil, 0, format_buf, float) + 1 - temp_buf = temp_buf(len) - LibC.snprintf(temp_buf, len, format_buf, float) + @io.write_string Slice.new(temp_buf, len - 1) + end - @io.write_string Slice.new(temp_buf, len - 1) - end + # Here we rebuild the original format string, like %f or %.2g and use snprintf + private def recreate_float_format_string(flags) + capacity = 3 # percent + type + \0 + capacity += flags.width_size + capacity += flags.precision_size + 1 # size + . + capacity += 1 if flags.sharp + capacity += 1 if flags.plus + capacity += 1 if flags.minus + capacity += 1 if flags.zero + capacity += 1 if flags.space + + format_buf = format_buf(capacity) + original_format_buf = format_buf + + io = IO::Memory.new(Bytes.new(format_buf, capacity)) + io << '%' + io << '#' if flags.sharp + io << '+' if flags.plus + io << '-' if flags.minus + io << '0' if flags.zero + io << ' ' if flags.space + io << flags.width if flags.width > 0 + if precision = flags.precision + io << '.' + io << precision if precision != 0 + end + io << flags.type + io.write_byte 0_u8 - # Here we rebuild the original format string, like %f or %.2g and use snprintf - def recreate_float_format_string(flags) - capacity = 3 # percent + type + \0 - capacity += flags.width_size - capacity += flags.precision_size + 1 # size + . - capacity += 1 if flags.sharp - capacity += 1 if flags.plus - capacity += 1 if flags.minus - capacity += 1 if flags.zero - capacity += 1 if flags.space - - format_buf = format_buf(capacity) - original_format_buf = format_buf - - io = IO::Memory.new(Bytes.new(format_buf, capacity)) - io << '%' - io << '#' if flags.sharp - io << '+' if flags.plus - io << '-' if flags.minus - io << '0' if flags.zero - io << ' ' if flags.space - io << flags.width if flags.width > 0 - if precision = flags.precision - io << '.' - io << precision if precision != 0 + original_format_buf end - io << flags.type - io.write_byte 0_u8 - original_format_buf - end + # We reuse a temporary buffer for snprintf + private def temp_buf(len) + temp_buf = @temp_buf + if temp_buf + if len > @temp_buf_len + @temp_buf_len = len + @temp_buf = temp_buf = temp_buf.realloc(len) + end + temp_buf + else + @temp_buf = Pointer(UInt8).malloc(len) + end + end + + # We reuse a temporary buffer for the float format string + private def format_buf(len) + format_buf = @format_buf + if format_buf + if len > @format_buf_len + @format_buf_len = len + @format_buf = format_buf = format_buf.realloc(len) + end + format_buf + else + @format_buf = Pointer(UInt8).malloc(len) + end + end + {% end %} # HAS_RYU_PRINTF def pad(consumed, flags) : Nil padding_char = flags.padding_char @@ -557,48 +632,23 @@ struct String::Formatter(A) @reader.next_char end - # We reuse a temporary buffer for snprintf - private def temp_buf(len) - temp_buf = @temp_buf - if temp_buf - if len > @temp_buf_len - @temp_buf_len = len - @temp_buf = temp_buf = temp_buf.realloc(len) - end - temp_buf - else - @temp_buf = Pointer(UInt8).malloc(len) - end - end - - # We reuse a temporary buffer for the float format string - private def format_buf(len) - format_buf = @format_buf - if format_buf - if len > @format_buf_len - @format_buf_len = len - @format_buf = format_buf = format_buf.realloc(len) - end - format_buf - else - @format_buf = Pointer(UInt8).malloc(len) - end - end - struct Flags property space : Bool, sharp : Bool, plus : Bool, minus : Bool, zero : Bool, float : Bool, base : Int32 - property width : Int32, width_size : Int32 - property type : Char, precision : Int32?, precision_size : Int32 + property width : Int32 + property type : Char, precision : Int32? property index : Int32? + {% unless HAS_RYU_PRINTF %} + property width_size : Int32 = 0 + property precision_size : Int32 = 0 + {% end %} + def initialize @space = @sharp = @plus = @minus = @zero = @float = false @width = 0 - @width_size = 0 @base = 10 @type = ' ' @precision = nil - @precision_size = 0 end def left_padding? : Bool diff --git a/src/string/utf16.cr b/src/string/utf16.cr index b3fdc09301af..042391cca15d 100644 --- a/src/string/utf16.cr +++ b/src/string/utf16.cr @@ -128,8 +128,10 @@ class String {string, pointer + 1} end + # :nodoc: + # # Yields each decoded char in the given slice. - private def self.each_utf16_char(slice : Slice(UInt16), &) + def self.each_utf16_char(slice : Slice(UInt16), &) i = 0 while i < slice.size byte = slice[i].to_i diff --git a/src/time/location.cr b/src/time/location.cr index d84c1ab14218..7e0e8f160cb9 100644 --- a/src/time/location.cr +++ b/src/time/location.cr @@ -236,7 +236,7 @@ class Time::Location # # *name* is understood to be a location name in the IANA Time # Zone database, such as `"America/New_York"`. As special cases, - # `"UTC"` and empty string (`""`) return `Location::UTC`, and + # `"UTC"`, `"Etc/UTC"` and empty string (`""`) return `Location::UTC`, and # `"Local"` returns `Location.local`. # # The implementation uses a list of system-specific paths to look for a time @@ -277,7 +277,11 @@ class Time::Location # `Location`, unless the time zone database has been updated in between. def self.load(name : String) : Location case name - when "", "UTC" + when "", "UTC", "Etc/UTC" + # `UTC` is a special identifier, empty string represents a fallback mechanism. + # `Etc/UTC` is technically a tzdb identifier which could potentially point to anything. + # But we map it to `Location::UTC` directly for convenience which allows it to work + # without a copy of the database. UTC when "Local" local @@ -339,7 +343,7 @@ class Time::Location # The environment variable `ENV["TZ"]` is consulted for finding the time zone # to use. # - # * `"UTC"` and empty string (`""`) return `Location::UTC` + # * `"UTC"`, `"Etc/UTC"` and empty string (`""`) return `Location::UTC` # * Any other value (such as `"Europe/Berlin"`) is tried to be resolved using # `Location.load`. # * If `ENV["TZ"]` is not set, the system's local time zone data will be used @@ -348,7 +352,7 @@ class Time::Location # `Location::UTC` is returned. def self.load_local : Location case tz = ENV["TZ"]? - when "", "UTC" + when "", "UTC", "Etc/UTC" return UTC when Nil if localtime = Crystal::System::Time.load_localtime diff --git a/src/tuple.cr b/src/tuple.cr index d67578271363..2f9cde352e4f 100644 --- a/src/tuple.cr +++ b/src/tuple.cr @@ -539,10 +539,28 @@ struct Tuple to_s end - def to_a + # Returns an `Array` with all the elements in the tuple. + # + # ``` + # {1, 2, 3, 4, 5}.to_a # => [1, 2, 3, 4, 5] + # ``` + def to_a : Array(Union(*T)) + {% if compare_versions(Crystal::VERSION, "1.1.0") < 0 %} + to_a(&.itself.as(Union(*T))) + {% else %} + to_a(&.itself) + {% end %} + end + + # Returns an `Array` with the results of running *block* against each element of the tuple. + # + # ``` + # {1, 2, 3, 4, 5}).to_a { |i| i * 2 } # => [2, 4, 6, 8, 10] + # ``` + def to_a(& : Union(*T) -> _) Array(Union(*T)).build(size) do |buffer| {% for i in 0...T.size %} - buffer[{{i}}] = self[{{i}}] + buffer[{{i}}] = yield self[{{i}}] {% end %} size end diff --git a/src/xml/libxml2.cr b/src/xml/libxml2.cr index 68c9943425d2..feea8a1ba6d7 100644 --- a/src/xml/libxml2.cr +++ b/src/xml/libxml2.cr @@ -5,12 +5,16 @@ require "./html_parser_options" require "./save_options" @[Link("xml2", pkg_config: "libxml-2.0")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "libxml2.dll")] +{% end %} lib LibXML alias Int = LibC::Int + fun xmlInitParser + # TODO: check if other platforms also support per-thread globals {% if flag?(:win32) %} - fun xmlInitParser fun __xmlIndentTreeOutput : Int* fun __xmlTreeIndentString : UInt8** {% else %} @@ -321,9 +325,7 @@ lib LibXML fun xmlValidateNameValue(value : UInt8*) : Int end -{% if flag?(:win32) %} - LibXML.xmlInitParser -{% end %} +LibXML.xmlInitParser LibXML.xmlGcMemSetup( ->GC.free, diff --git a/src/xml/reader.cr b/src/xml/reader.cr index 9d1de3ed4c9e..decdd8468185 100644 --- a/src/xml/reader.cr +++ b/src/xml/reader.cr @@ -119,6 +119,7 @@ class XML::Reader # Moves to the `XML::Reader::Type::ATTRIBUTE` with the specified name. def move_to_attribute(name : String) : Bool + check_no_null_byte(name) LibXML.xmlTextReaderMoveToAttribute(@reader, name) == 1 end @@ -131,6 +132,7 @@ class XML::Reader # Gets the attribute content for the *attribute* given by name. # Returns `nil` if attribute is not found. def []?(attribute : String) : String? + check_no_null_byte(attribute) value = LibXML.xmlTextReaderGetAttribute(@reader, attribute) String.new(value) if value end @@ -200,4 +202,10 @@ class XML::Reader Error.add_errors(@errors) end end + + private def check_no_null_byte(attribute) + if attribute.byte_index(0) + raise XML::Error.new("Invalid attribute name: #{attribute.inspect} (contains null character)", 0) + end + end end diff --git a/src/yaml/lib_yaml.cr b/src/yaml/lib_yaml.cr index 4c0d329f8f36..0b4248afc793 100644 --- a/src/yaml/lib_yaml.cr +++ b/src/yaml/lib_yaml.cr @@ -1,6 +1,9 @@ require "./enums" @[Link("yaml", pkg_config: "yaml-0.1")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "yaml.dll")] +{% end %} lib LibYAML alias Int = LibC::Int