diff --git a/.github/workflows/ci-typ.yml b/.github/workflows/ci-typ.yml new file mode 100644 index 00000000..0b4e1a6f --- /dev/null +++ b/.github/workflows/ci-typ.yml @@ -0,0 +1,65 @@ +name: Typst CI + +on: + push: # Run CI for all branches except GitHub merge queue tmp branches + branches-ignore: + - "gh-readonly-queue/**" + pull_request: # Run CI for PRs on any branch + merge_group: # Run CI for the GitHub merge queue + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + + - name: Install PDF fonts + run: sudo apt install -y fonts-noto-cjk + + - name: Install Python dependencies + run: | + pip3 install --user python-dateutil linkchecker + - name: Put pip binary directory into path + run: echo "~/.local/bin" >> $GITHUB_PATH + + - name: Cache Cargo installed binaries + uses: actions/cache@v4 + id: cache-cargo-typst + with: + path: ~/cargo-bin + key: cache-cargo-typst-0.15.1 + - name: Install Typst + if: steps.cache-cargo-typst.outputs.cache-hit != 'true' + uses: actions-rs/install@v0.1 + with: + crate: typst-cli + version: latest + - name: Install Just + if: steps.cache-cargo-typst.outputs.cache-hit != 'true' + uses: actions-rs/install@v0.1 + with: + crate: just + version: latest + - name: Copy typst to cache directory + if: steps.cache-cargo-typst.outputs.cache-hit != 'true' + run: | + mkdir -p ~/cargo-bin + cp ~/.cargo/bin/just ~/cargo-bin + cp ~/.cargo/bin/typst ~/cargo-bin + - name: Put new cargo binary directory into path + run: echo "~/cargo-bin" >> $GITHUB_PATH + + - name: Build book + run: just build + + - name: Check links + run: just check-links + + - name: Deploy book + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: book + force_orphan: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8356fe1c..e8e929a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: - name: Copy mdbook to cache directory if: steps.cache-cargo.outputs.cache-hit != 'true' run: | - mkdir ~/cargo-bin + mkdir -p ~/cargo-bin cp ~/.cargo/bin/mdbook ~/cargo-bin - name: Put new cargo binary directory into path run: echo "~/cargo-bin" >> $GITHUB_PATH @@ -47,10 +47,10 @@ jobs: - name: Check links run: linkchecker book - - name: Deploy book - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: book - force_orphan: true + #- name: Deploy book + # if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + # uses: peaceiris/actions-gh-pages@v3 + # with: + # github_token: ${{ secrets.GITHUB_TOKEN }} + # publish_dir: book + # force_orphan: true diff --git a/.gitignore b/.gitignore index 7585238e..122c0943 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ book +.vscode diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..5fffd65e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "tinymist.exportTarget": "paged", + "tinymist.typstExtraArgs": [ + "--features=html,bundle", + "--input=lang=en", + "--input=target=pdf", + "--input=goal=translation" + ] +} diff --git a/Justfile b/Justfile new file mode 100644 index 00000000..7f51cf2b --- /dev/null +++ b/Justfile @@ -0,0 +1,37 @@ +clean: + rm -r book + +build-en: + typst compile typ/book.typ --input lang=en --input target=html book --features bundle,html -f bundle + typst compile typ/book.typ --input lang=en --input target=pdf book/book_en.pdf + +build-de: + typst compile typ/book.typ --input lang=de --input target=html book --features bundle,html -f bundle + typst compile typ/book.typ --input lang=de --input target=pdf book/book_de.pdf + typst compile typ/book.typ --input lang=de --input target=pdf book/book_de_tr.pdf --input goal=translation + +build-ja: + typst compile typ/book.typ --input lang=ja --input target=html book --features bundle,html -f bundle + typst compile typ/book.typ --input lang=ja --input target=pdf book/book_ja.pdf + typst compile typ/book.typ --input lang=ja --input target=pdf book/book_ja_tr.pdf --input goal=translation + +build-uk: + typst compile typ/book.typ --input lang=uk --input target=html book --features bundle,html -f bundle + typst compile typ/book.typ --input lang=uk --input target=pdf book/book_uk.pdf + typst compile typ/book.typ --input lang=uk --input target=pdf book/book_uk_tr.pdf --input goal=translation + +build-zh: + typst compile typ/book.typ --input lang=zh --input target=html book --features bundle,html -f bundle + typst compile typ/book.typ --input lang=zh --input target=pdf book/book_zh.pdf + typst compile typ/book.typ --input lang=zh --input target=pdf book/book_zh_tr.pdf --input goal=translation + +build: build-en build-de build-ja build-uk build-zh + +check-links: + linkchecker book + +format-html: + for file in `find book -name "*.html"`; do \ + echo $file; \ + tidy -qim --alt-text "inlined image" --tidy-mark no --warn-proprietary-attributes no -w 120 --custom-tags blocklevel $file; \ + done diff --git a/typ/appendix/glossary.typ b/typ/appendix/glossary.typ new file mode 100644 index 00000000..dea06b1e --- /dev/null +++ b/typ/appendix/glossary.typ @@ -0,0 +1,216 @@ +#import "../config.typ": * + +#h1((en: [Appendix A: Glossary], + de: [Anhang A: Glossar], + zh: [附录A: 词汇表], +)) + +#tr(( +en: [ + The embedded ecosystem is full of different protocols, hardware + components and vendor-specific things that use their own terms and + abbreviations. This Glossary attempts to list them with pointers for + understanding them better. +], +de: [ + Das Embedded-Ökosystem ist geprägt von einer Vielzahl unterschiedlicher + Protokolle, Hardwarekomponenten und herstellerspezifischer Elemente, für + die jeweils eigene Begriffe und Abkürzungen verwendet werden. Dieses + Glossar soll diese auflisten und Hinweise zum besseren Verständnis geben. +], +zh: [ + 嵌入式生态系统中充满了不同的协议,硬件组件,还有许多与生产商相关的东西,它们都使用自己的缩写和项目名。这个词汇表尝试列出它们以便更好理解它们。 +])) + +*BSP* + +#let url_bspvideo = "https://youtu.be/vLYit_HHPaY" +#tr(( +en: [ + A Board Support Crate provides a high level interface configured for a + specific board. It usually depends on a #link()[HAL] crate. There + is a more detailed description on the + #link()[memory-mapped registers page] or for a + broader overview see #link(url_bspvideo)[this video]. +], +de: [ + Ein „Board Support Crate" stellt eine auf eine bestimmte Platine + zugeschnittene Schnittstelle auf hoher Ebene bereit. Es hängt in der + Regel von einem #link()[HAL]-Crate ab. Eine ausführlichere + Beschreibung finden Sie auf der + #link()[Seite zu den im Speicher abgebildeten Registern] + oder für einen umfassenderen Überblick sehen Sie sich + #link(url_bspvideo)[dieses Video] an. +], +zh: [ + 板级支持的Crate(Board Support + Crate)提供为某个特定板子配置的高级接口。它通常依赖一个#link()[HAL] + crate 。在#link()[存储映射的寄存器那页]有更多细节的描述或者看#link(url_bspvideo)[这个视频]来获取一个更广泛的概述。 +])) + +*FPU* + +#tr(( +en: [ + Floating-point Unit. A 'math processor' running only operations on + floating-point numbers. +], +de: [ + Gleitkommaeinheit. Ein „Mathematikprozessor", der ausschließlich + Operationen mit Gleitkommazahlen ausführt. +], +zh: [ + 浮点单元(Floating-Point Unit)。一个只运行在浮点数上的'数学处理器'。 +])) + +*HAL* + +#let ln_hal = link("https://crates.io/crates/embedded-hal")[`embedded-hal`] +#let url_hal_video = "https://youtu.be/vLYit_HHPaY" +#tr(( +en: [ + A Hardware Abstraction Layer crate provides a developer friendly + interface to a microcontroller's features and peripherals. It is usually + implemented on top of a #link()[Peripheral Access Crate (PAC)]. It + may also implement traits from the #ln_hal crate. + There is a more detailed description on the + #link()[memory-mapped registers page] or for a + broader overview see #link(url_hal_video)[this video]. +], +de: [ + Ein „Hardware Abstraction Layer"-Crate bietet eine entwicklerfreundliche + Schnittstelle zu den Funktionen und Peripheriegeräten eines + Mikrocontrollers. Es wird in der Regel auf Basis eines + #link()[Peripheral Access Crate (PAC)] implementiert. + Möglicherweise implementiert es auch Traits aus dem #ln_hal;-Crate. + Eine ausführlichere Beschreibung finden Sie auf der + #link()[Seite zu den im Speicher abgebildeten Registern] + oder für einen umfassenderen Überblick in #link(url_hal_video)[diesem Video]. +], +zh: [ + 硬件抽象层(Hardware Abstraction Layer) + crate为微控制器的功能和外设提供一个开发者友好的接口。它通常在#link()[Peripheral Access Crate (PAC)]之上被实现。它可能也会实现来自#ln_hal + crate的traits + 。在#link()[存储映射的寄存器那页]上有更多的细节或者看#link(url_hal_video)[这个视频]获取一个更广泛的概述。 +])) + +*I2C* + +#let wiki_i2c = "https://en.wikipedia.org/wiki/I2c" +#tr(( +en: [ + Sometimes referred to as `I²C` or Inter-IC. It is a protocol meant for + hardware communication within a single integrated circuit. + See #link(wiki_i2c)[here] for more details +], +de: [ + Wird manchmal auch als „I²C" oder „Inter-IC" bezeichnet. Es handelt sich + um ein Protokoll für die Hardware-Kommunikation innerhalb eines + einzelnen integrierten Schaltkreises. Weitere Informationen finden Sie + #link(wiki_i2c)[hier]. +], +zh: [ + 有时又被称为 `I²C` 或者 Intere-IC + 。它是一种用于在单个集成电路中进行硬件通信的协议。看#link(wiki_i2c)[这里]来获取更多细节。 +])) + +*PAC* + +#let ln_svd2rust = link("https://github.com/rust-embedded/svd2rust/")[svd2rust] +#let url_pacvideo = "https://youtu.be/vLYit_HHPaY" +#tr(( +en: [ + A Peripheral Access Crate provides access to a microcontroller's + peripherals. It is one of the lower level crates and is usually + generated directly from the provided #link()[SVD], + often using #ln_svd2rust. + The #link()[Hardware Abstraction Layer] would usually + depend on this crate. There is a more detailed description on the + #link()[memory-mapped registers page] or for a + broader overview see #link(url_pacvideo)[this video]. +], +de: [ + Ein „Peripheral Access Crate" ermöglicht den Zugriff auf die + Peripheriegeräte eines Mikrocontrollers. Es handelt sich um eines der + Crates auf niedrigerer Ebene, das in der Regel direkt aus der + bereitgestellten #link()[SVD] generiert wird, häufig unter + Verwendung von + #ln_svd2rust. Die + #link()[Hardware-Abstraktionsschicht] hängt in der Regel von diesem + Crate ab. Eine ausführlichere Beschreibung finden Sie auf der + #link()[Seite zu den im Speicher abgebildeten Registern] + oder für einen umfassenderen Überblick in + #link(url_pacvideo)[diesem Video]. +], +zh: [ + 一个外设访问 Crate (Peripheral Access + Crate)提供了对一个微控制器的外设的访问。它是一个底层的crates且通常从提供的#link()[SVD]被直接生成,经常使用#ln_svd2rust。#link()[硬件抽象层]应该依赖这个crate。在#link()[存储映射的寄存器那页]有更细节的描述或者看#link(url_pacvideo)[这个视频]获取一个更广泛的概述。 +])) + +*SPI* + +#let wiki_spi = "https://en.wikipedia.org/wiki/Serial_peripheral_interface" +#tr(( +en: [ + Serial Peripheral Interface. + See #link(wiki_spi)[here] for more information. +], +de: [ + Serial Peripheral Interface. + Weitere Informationen finden Sie #link(wiki_spi)[hier]. +], +zh: [ + 串行外设接口。看#link(wiki_spi)[这里]获取更多信息。 +])) + +*SVD* + +#let url_svd = "https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html" +#tr(( +en: [ + System View Description is an XML file format used to describe the + programmers view of a microcontroller device. You can read more about it + on #link(url_svd)[the ARM CMSIS documentation site]. +], +de: [ + „System View Description" ist ein XML-Dateiformat, das dazu dient, die + Programmierersicht eines Mikrocontrollers zu beschreiben. Weitere + Informationen hierzu finden Sie auf + #link(url_svd)[der ARM CMSIS-Dokumentationsseite]. +], +zh: [ + 系统视图描述文件(System View + Description)是一个XML文件格式,以程序员视角来描述一个微控制器设备。你能在#link(url_svd)[the ARM CMSIS documentation site]上获取更多信息。 +])) + +*UART* + +#let wiki_uart = "https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter" +#tr(( +en: [ + Universal asynchronous receiver-transmitter. + See #link(wiki_uart)[here] for more information. +], +de: [ + Universeller asynchroner Empfänger-Sender. + Weitere Informationen finden Sie #link(wiki_uart)[hier]. +], +zh: [ + 通用异步收发器。看#link(wiki_uart)[这里]获取更多信息。 +])) + +*USART* + +#let wiki_usart = "https://en.wikipedia.org/wiki/Universal_synchronous_and_asynchronous_receiver-transmitter" +#tr(( +en: [ + Universal synchronous and asynchronous receiver-transmitter. + See #link(wiki_usart)[here] for more information. +], +de: [ + Universeller synchroner und asynchroner Empfänger-Sender. + Weitere Informationen finden Sie #link(wiki_usart)[hier]. +], +zh: [ + 通用同步异步收发器。看#link(wiki_usart)[这里]获取更多信息。 +])) diff --git a/typ/assets/crates.png b/typ/assets/crates.png new file mode 100644 index 00000000..d5898301 Binary files /dev/null and b/typ/assets/crates.png differ diff --git a/typ/assets/embedded-hal.svg b/typ/assets/embedded-hal.svg new file mode 100644 index 00000000..40c9475b --- /dev/null +++ b/typ/assets/embedded-hal.svg @@ -0,0 +1,2 @@ + +
HAL Implementation Crate
nrf52-hal
[Not supported by viewer]
Device Crate
nrf52
[Not supported by viewer]
Device Hardware
<font style="font-size: 16px">Device Hardware</font>
Embedded HAL Traits
embedded-hal
[Not supported by viewer]
Accelerometer Driver
LSM303DLHC
[Not supported by viewer]
Gas Sensor Driver
SGP30
[Not supported by viewer]
Light Intensity Driver
TSL256X
[Not supported by viewer]
\ No newline at end of file diff --git a/typ/assets/f3.jpg b/typ/assets/f3.jpg new file mode 100644 index 00000000..7a122aa0 Binary files /dev/null and b/typ/assets/f3.jpg differ diff --git a/typ/assets/nrf52-memory-map.png b/typ/assets/nrf52-memory-map.png new file mode 100644 index 00000000..8252f02d Binary files /dev/null and b/typ/assets/nrf52-memory-map.png differ diff --git a/typ/assets/nrf52-spi-frequency-register.png b/typ/assets/nrf52-spi-frequency-register.png new file mode 100644 index 00000000..e8eaef8c Binary files /dev/null and b/typ/assets/nrf52-spi-frequency-register.png differ diff --git a/typ/assets/rust_layers.svg b/typ/assets/rust_layers.svg new file mode 100644 index 00000000..c9e55fff --- /dev/null +++ b/typ/assets/rust_layers.svg @@ -0,0 +1 @@ +Peripheral Access CrateHardware Abstraction Layer ImplDriverDriverApplicationBoard Support CrateUsesImplementsHardware Abstraction Layer TraitsMicrocontroller \ No newline at end of file diff --git a/typ/assets/verify.jpeg b/typ/assets/verify.jpeg new file mode 100644 index 00000000..ed466457 Binary files /dev/null and b/typ/assets/verify.jpeg differ diff --git a/typ/book.typ b/typ/book.typ new file mode 100644 index 00000000..947761eb --- /dev/null +++ b/typ/book.typ @@ -0,0 +1,425 @@ +#import "config.typ": * +#import "mdbook/lib.typ": book + +#let sources = ( + "intro/index": ( + content: include "intro/index.typ", + title: tr(( + en: [Introduction], + de: [Einleitung], + ja: [導入], + uk: [Вступ], + zh: [引言], + )), + sub: ( + "intro/hardware": ( + content: include "intro/hardware.typ", + title: tr(( + en: [Hardware], + de: [Hardware], + ja: [ハードウェア], + uk: [Залізо], + zh: [硬件], + )), + ), + "intro/no-std": ( + content: include "intro/no-std.typ", + title: `no_std` + ), + "intro/tooling": ( + content: include "intro/tooling.typ", + title: tr(( + en: [Tooling], + de: [Werkzeuge], + ja: [ツール], + uk: [Інструменти], + zh: [工具], + )), + ), + "intro/install": ( + content: include "intro/install.typ", + title: tr(( + en: [Installation], + de: [Installation], + ja: [インストール], + uk: [Встановлення], + zh: [安装], + )), + sub: ( + "intro/install/linux": ( + content: include "intro/install/linux.typ", + title: [Linux] + ), + "intro/install/macos": ( + content: include "intro/install/macos.typ", + title: [MacOS] + ), + "intro/install/windows": ( + content: include "intro/install/windows.typ", + title: [Windows] + ), + "intro/install/verify": ( + content: include "intro/install/verify.typ", + title: tr(( + en: [Verify Installation], + de: [Die Installation überprüfen], + ja: [インストールの確認], + uk: [Перевірка встановлення], + zh: [验证工具链的安装], + )), + ) + ) + ), + ), + ), + "start/index": ( + content: include "start/index.typ", + title: tr(( + en: [Getting started], + de: [Erste Schritte], + ja: [入門], + uk: [Початок роботи], + zh: [开始], + )), + sub: ( + "start/qemu": ( + content: include "start/qemu.typ", + title: [QEMU] + ), + "start/hardware": ( + content: include "start/hardware.typ", + title: tr(( + en: [Hardware], + de: [Hardware], + ja: [ハードウェア], + uk: [Залізо], + zh: [硬件], + )), + ), + "start/registers": ( + content: include "start/registers.typ", + title: tr(( + en: [Memory-mapped Registers], + de: [Im Speicher abgebildete Register], + ja: [メモリマップドレジスタ], + uk: [Відображені в пам'яті регістри], + zh: [存储映射的寄存器], + )), + ), + "start/semihosting": ( + content: include "start/semihosting.typ", + title: tr(( + ja: [セミホスティング], + zh: [半主机模式], + ), default: [Semihosting]), + ), + "start/panicking": ( + content: include "start/panicking.typ", + title: tr(( + en: [Panicking], + de: [In Panik geraten], + ja: [パニック], + uk: [Паніка], + zh: [运行时恐慌(Panicking)], + )), + ), + "start/exceptions": ( + content: include "start/exceptions.typ", + title: tr(( + en: [Exceptions], + de: [Exceptions], + ja: [例外], + uk: [Виключення], + zh: [异常], + )), + ), + "start/interrupts": ( + content: include "start/interrupts.typ", + title: tr(( + en: [Interrupts], + de: [Interrupts], + ja: [割り込み], + uk: [Переривання], + zh: [中断], + )), + ), + ) + ), + "peripherals/index": ( + content: include "peripherals/index.typ", + title: tr(( + en: [Peripherals], + de: [Peripheriegeräte], + ja: [ペリフェラル], + uk: [Периферійні пристрої], + zh: [外设], + )), + sub: ( + "peripherals/a-first-attempt": ( + content: include "peripherals/a-first-attempt.typ", + title: tr(( + en: [A first attempt in Rust], + de: [Ein erster Versuch in Rust], + ja: [Rustでの最初の試み], + uk: [Перша спроба на Rust], + zh: [Rust尝鲜], + )), + ), + "peripherals/borrowck": ( + content: include "peripherals/borrowck.typ", + title: tr(( + en: [The Borrow Checker], + de: [Der Borrow-Prüfer], + ja: [借用チェッカ], + uk: [Перевірка запозичень], + zh: [借用检查器], + )), + ), + "peripherals/singletons": ( + content: include "peripherals/singletons.typ", + title: tr(( + en: [Singletons], + de: [Singletons], + ja: [シングルトン], + uk: [Одинаки], + zh: [单例], + )), + ) + ) + ), + "static-guarantees/index": ( + content: include "static-guarantees/index.typ", + title: tr(( + en: [Static Guarantees], + de: [Statische Garantien], + ja: [静的な保証], + uk: [Статичні гарантії], + zh: [静态保障(static guarantees)], + )), + sub: ( + "static-guarantees/typestate-programming": ( + content: include "static-guarantees/typestate-programming.typ", + title: tr(( + en: [Typestate Programming], + de: [Typgestützte Programmierung], + ja: [型状態プログラミング], + uk: [Програмування типів-станів], + zh: [类型状态编程], + )), + ), + "static-guarantees/state-machines": ( + content: include "static-guarantees/state-machines.typ", + title: tr(( + en: [Peripherals as State Machines], + de: [Peripheriegeräte als Zustandsmaschinen], + ja: [ステートマシンとしてのペリフェラル], + uk: [Периферія як кінцеві автомати], + zh: [把外设当作状态机], + )), + ), + "static-guarantees/design-contracts": ( + content: include "static-guarantees/design-contracts.typ", + title: tr(( + en: [Design Contracts], + de: [Designverträge], + ja: [設計契約], + uk: [Угоди щодо дизайну], + zh: [设计约定], + )), + ), + "static-guarantees/zero-cost-abstractions": ( + content: include "static-guarantees/zero-cost-abstractions.typ", + title: tr(( + en: [Zero Cost Abstractions], + de: [Abstraktionen ohne Kosten], + ja: [ゼロコスト抽象化], + uk: [Безкоштовні абстракції], + zh: [零成本抽象], + )), + ), + ) + ), + "portability/index": ( + content: include "portability/index.typ", + title: tr(( + en: [Portability], + de: [Portabilität], + ja: [移植性], + uk: [Переносимість], + zh: [可移植性], + )), + ), + "concurrency/index": ( + content: include "concurrency/index.typ", + title: tr(( + en: [Concurrency], + de: [Nebenläufigkeit], + ja: [並行性], + uk: [Паралелізм], + zh: [并发], + )), + ), + "collections/index": ( + content: include "collections/index.typ", + title: tr(( + en: [Collections], + de: [Sammlungen], + ja: [コレクション], + uk: [Колекції], + zh: [容器], + )), + ), + "design-patterns/index": ( + content: include "design-patterns/index.typ", + title: tr(( + en: [Design Patterns], + de: [Desginmuster], + uk: [Шаблони проектування], + zh: [设计模式], + )), + sub: ( + "design-patterns/hal/index": ( + content: include "design-patterns/hal/index.typ", + title: tr(( + en: [HALs], + de: [HALs], + zh: [HALs], + uk: [HALи] + )), + sub: ( + "design-patterns/hal/checklist": ( + content: include "design-patterns/hal/checklist.typ", + title: tr(( + en: [Checklist], + de: [Checkliste], + uk: [Контрольний список], + zh: [列表], + )), + ), + "design-patterns/hal/naming": ( + content: include "design-patterns/hal/naming.typ", + title: tr(( + en: [Naming], + de: [Benennung], + uk: [Найменування], + zh: [命名], + )), + ), + "design-patterns/hal/interoperability": ( + content: include "design-patterns/hal/interoperability.typ", + title: tr(( + en: [Interoperability], + de: [Interoperabilität], + uk: [Сумісність], + zh: [互操性], + )), + ), + "design-patterns/hal/predictability": ( + content: include "design-patterns/hal/predictability.typ", + title: tr(( + en: [Predictability], + de: [Vorhersehbarkeit], + uk: [Передбачуваність], + zh: [可预见性], + )), + ), + "design-patterns/hal/gpio": ( + content: include "design-patterns/hal/gpio.typ", + title: [GPIO] + ), + ) + ) + ) + ), + "c-tips/index": ( + content: include "c-tips/index.typ", + title: tr(( + en: [Tips for embedded C developers], + de: [Tipps für Entwickler im Bereich Embedded-C], + ja: [組込みC開発者へのヒント], + uk: [Поради для розробників мовою C], + zh: [给嵌入式C开发者的贴士], + )), + ), + "interoperability/index": ( + content: include "interoperability/index.typ", + title: tr(( + en: [Interoperability], + de: [Interoperabilität], + ja: [相互運用性], + uk: [Сумісність], + zh: [互操性], + )), + sub: ( + "interoperability/c-with-rust": ( + content: include "interoperability/c-with-rust.typ", + title: tr(( + en: [A little C with your Rust], + de: [Ein bisschen C zu Ihrem Rust], + ja: [Rustと少しのC], + uk: [Трошки C в вашому Rust], + zh: [使用C的Rust], + )), + ), + "interoperability/rust-with-c": ( + content: include "interoperability/rust-with-c.typ", + title: tr(( + en: [A little Rust with your C], + de: [Ein bisschen Rust zu Ihrem C], + ja: [Cと少しのRust], + uk: [Трошки Rust в вашому C], + zh: [使用Rust的C], + )), + ) + ) + ), + "unsorted/index": ( + content: include "unsorted/index.typ", + title: tr(( + en: [Unsorted topics], + de: [Unsortierte Themen], + ja: [未分類のトピック], + uk: [Невідсортовані теми], + zh: [没有排序的主题], + )), + sub: ( + "unsorted/speed-vs-size": ( + content: include "unsorted/speed-vs-size.typ", + title: tr(( + en: [Optimizations: The speed size tradeoff], + de: [Optimierungen: Der Kompromiss zwischen Geschwindigkeit und Größe], + ja: [最適化: 速度とサイズのトレードオフ], + uk: [Оптимізація: компроміс між швидкістю та розміром], + zh: [优化: 速度与大小间的博弈], + )), + ), + "unsorted/math": ( + content: include "unsorted/math.typ", + title: tr(( + en: [Performing Math Functionality], + de: [Ausführung mathematischer Funktionen], + uk: [Виконання математики], + zh: [执行数学运算], + )), + ) + ) + ), + "appendix/glossary": ( + content: include "appendix/glossary.typ", + title: tr(( + en: [Appendix A: Glossary], + de: [Anhang A: Glossar], + uk: [Додаток А: Глосарій], + zh: [附录A: 词汇表], + )), + ) +) + +#book( + tgt, + sources, + lang, + languages, + book_title: "The Embedded Rust Book", + git: "https://github.com/rust-embedded/book", +) diff --git a/typ/c-tips/index.typ b/typ/c-tips/index.typ new file mode 100644 index 00000000..f5c8b3d6 --- /dev/null +++ b/typ/c-tips/index.typ @@ -0,0 +1,1399 @@ +#import "../config.typ": * + +#h1((en: [Tips for embedded C developers], + de: [Tipps für Embedded-C-Entwickler], + ja: [組込みC開発者へのヒント], + zh: [给嵌入式C开发者的贴士], +)) + +#tr(( +en: [ + This chapter collects a variety of tips that might be useful to + experienced embedded C developers looking to start writing Rust. It will + especially highlight how things you might already be used to in C are + different in Rust. +], +de: [ + Dieses Kapitel versammelt eine Reihe von Tipps, die für erfahrene + Embedded-C-Entwickler nützlich sein können, die mit der Programmierung + in Rust beginnen möchten. Dabei wird insbesondere hervorgehoben, wie + sich Dinge, die man aus C bereits kennt, in Rust unterscheiden. +], +ja: [ + この章では、組込みC開発の経験者が、Rustを書き始める時に役に立つ様々なヒントをまとめます。 + 特に、既にC言語で慣れ親しんでいることが、Rustではどう違うのかを強調します。 +], +zh: [ + 这个章节收集了可能对于刚开始编写Rust的,有经验的嵌入式C开发者来说,有用的各种各样的贴士。它将解释你在C中可能已经用到的那些东西与Rust中的有何不同。 +])) + +== #tr(( + en: [Preprocessor], + de: [Präprozessor], + ja: [プリプロセッサ], + zh: [预处理器], +)) + +#tr(( +en: [ + In embedded C it is very common to use the preprocessor for a variety of + purposes, such as: + - Compile-time selection of code blocks with `#ifdef` + - Compile-time array sizes and computations + - Macros to simplify common patterns (to avoid function call overhead) +], +de: [ + In der Embedded-C-Programmierung ist es sehr üblich, den Präprozessor + für eine Vielzahl von Zwecken zu nutzen, wie zum Beispiel: + - Auswahl von Codeblöcken zur Kompilierzeit mittels `#ifdef` + - Zur Kompilierzeit festgelegte Array-Größen und Berechnungen + - Makros zur Vereinfachung häufiger Muster (um den Overhead von + Funktionsaufrufen zu vermeiden) +], +ja: [ + 組込みCでは、次のような様々な目的でプリプロセッサを使うことが一般的です。 + - `#ifdef`を使ったコンパイル時のコードブロック選択 + - コンパイル時の配列サイズやコンパイル時計算 + - (関数呼び出しのオーバーヘッドを避けるための)共通パターンを簡単化するマクロ +], +zh: [ + 在嵌入式C中,为了各种各样的目的使用预处理器是很常见的,比如: + - 使用`#ifdef`编译时选择代码块 + - 编译时的数组大小和计算 + - 用来简化常见的模式的宏(避免调用函数的开销) +])) + +#tr(( +en: [ + In Rust there is no preprocessor, and so many of these use cases are + addressed differently. In the rest of this section we cover various + alternatives to using the preprocessor. +], +de: [ + In Rust gibt es keinen Präprozessor, weshalb viele dieser + Anwendungsfälle anders gelöst werden. Im weiteren Verlauf dieses + Abschnitts behandeln wir verschiedene Alternativen zur Verwendung des + Präprozessors. +], +ja: [ + Rustにはプリプロセッサはありません。上記のユースケースは異なる方法で解決されます。 + セクションの残りの部分では、プリプロセッサの様々な代替手段について説明します。 +], +zh: [ + 在Rust中没有预处理器,所以许多案例有不同的处理方法。本章节剩下的部分,我们将介绍各种替代预处理器的方法。 +])) + +=== #tr(( + en: [Compile-Time Code Selection], + de: [Code-Auswahl zur Kompilierzeit], + ja: [コンパイル時コード選択], + zh: [编译时的代码选择], +)) + +#let url_features = "https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section" +#tr(( +en: [ + The closest match to `#ifdef ... #endif` in Rust are + #link(url_features)[Cargo features]. + These are a little more formal than the C preprocessor: all possible + features are explicitly listed per crate, and can only be either on or + off. Features are turned on when you list a crate as a dependency, and + are additive: if any crate in your dependency tree enables a feature for + another crate, that feature will be enabled for all users of that crate. +], +de: [ + Das Äquivalent zu `#ifdef ... #endif` in Rust sind + #link(url_features)[Cargo-Features]. + Diese sind etwas formaler als der C-Präprozessor: Alle möglichen + Features werden pro Crate explizit aufgelistet und können entweder + aktiviert oder deaktiviert sein. Features werden eingeschaltet, sobald + man ein Crate als Abhängigkeit angibt; sie sind zudem additiv: Wenn + irgendein Crate im Abhängigkeitsbaum ein Feature für ein anderes Crate + aktiviert, ist dieses Feature für alle Nutzer jenes Crates aktiviert. +], +ja: [ + `#ifdef ... #endif`に最も近いRustの機能は、#link(url_features)[Cargoフィーチャ]です。 + Cargoフィーチャは、Cプリプロセッサよりももう少し秩序だったものです。 + フィーチャの候補は、クレートごとに明示的にリスト化されており、オンまたはオフのいずれかになります。 + 依存関係としてクレートを記載すると、フィーチャが有効になります。またこのフィーチャは追加式です。 + 依存ツリー内の何らかのクレートが、別クレートのフィーチャを有効化した場合、そのフィーチャは、そのクレートを使う全てのユーザに対して有効化されます。 +], +zh: [ + Rust中最接近`#ifdef ... #endif`的是#link(url_features)[Cargo features]。这些比C预处理器更正式一点: + 每个crate显式列举的,所有可能的features只能是关了的或者打开了的。当你把一个crate列为依赖项时,Features被打开,且是可添加的:如果你依赖树中的任何crate为另一个crate打开了一个feature,那么这个feature将为所有使用那个crate的用户而打开。 +])) + +#tr(( +en: [ + For example, you might have a crate which provides a library of signal + processing primitives. Each one might take some extra time to compile or + declare some large table of constants which you'd like to avoid. You + could declare a Cargo feature for each component in your `Cargo.toml`: +], +de: [ + Angenommen, du hast ein Crate, das eine Bibliothek von Grundbausteinen + für die Signalverarbeitung bereitstellt. Jeder dieser Bausteine ​​könnte + zusätzliche Kompilierzeit beanspruchen oder eine umfangreiche Tabelle + von Konstanten definieren, die du gerne vermeiden möchtest. Du könntest + für jede Komponente in deiner `Cargo.toml` ein Cargo-Feature definieren: +], +ja: [ + 例えば、信号処理プリミティブを提供するライブラリがあるとします。 + それぞれが、大きな定数テーブルをコンパイルまたは宣言するのに余分な時間がかかるとすると、その時間を回避したいと思うでしょう。 + `Cargo.toml`内で各コンポーネントのフィーチャを宣言することができます。 +], +zh: [ + 比如,你可能有一个crate,其提供一个信号处理的基本类型库(library of + signal processing + primitives)。每个基本类型可能带来一些额外的时间去编译大量的常量,你想要避开这些常量。你可以为你的`Cargo.toml`中每个组件声明一个Cargo + feature。 +])) + +```toml +[features] +FIR = [] +IIR = [] +``` + +#tr(( +en: [ + Then, in your code, use `#[cfg(feature="FIR")]` to control what is + included. +], +de: [ + Verwenden Sie dann in Ihrem Code `#[cfg(feature="FIR")]`, um zu steuern, + was einbezogen wird. +], +ja: [ + それから、コード内で、何をインクルードするか制御するために`#[cfg(feature="FIR")]`を使います。 +], +zh: [ + 然后,在你的代码中,使用`#[cfg(feature="FIR")]`去控制要包含什么东西。 +])) + +#raw(block: true, lang: "rust", +"/// " + ts(( + en: "In your top-level lib.rs", + de: "In deiner lib.rs auf oberster Ebene", + ja: "トップレベルのlib.rs内", + zh: "在你的顶层的lib.rs中" + )) + " + +#[cfg(feature=\"FIR\")] +pub mod fir; + +#[cfg(feature=\"IIR\")] +pub mod iir; +") + +#tr(( +en: [ + You can similarly include code blocks only if a feature is _not_ + enabled, or if any combination of features are or are not enabled. +], +de: [ + Sie können Codeblöcke analog dazu nur dann einfügen, wenn eine Funktion + _nicht_ aktiviert ist oder wenn eine beliebige Kombination von + Funktionen aktiviert oder deaktiviert ist. +], +ja: [ + 同様に、フィーチャが有効になって _いない_ + 場合にだけコードブロックをインクルードすることができます。 + また、フィーチャの組み合わせや、フィーチャが有効か無効かに関わらず、コードブロックをインクルードすることもできます。 +], +zh: [ + 同样地,你可以控制,只有当某个feature _没有_ + 被打开时,包含代码块,或者某些features的组合被打开或者被关闭时。 +])) + +#let url_conditional = "https://doc.rust-lang.org/reference/conditional-compilation.html" +#tr(( +en: [ + Additionally, Rust provides a number of automatically-set conditions you + can use, such as `target_arch` to select different code based on + architecture. For full details of the conditional compilation support, + refer to the #link(url_conditional)[conditional compilation] + chapter of the Rust reference. +], +de: [ + Darüber hinaus bietet Rust eine Reihe automatisch gesetzter Bedingungen, + die Sie verwenden können, beispielsweise `target_arch`, um je nach + Architektur unterschiedlichen Code auszuwählen. Ausführliche + Informationen zur bedingten Kompilierung finden Sie im Kapitel + #link(url_conditional)[Bedingte Kompilierung] + der Rust-Referenz. +], +ja: [ + さらに、Rustは、自動的に設定される数々の条件を提供します。例えば、アーキテクチャに基づいて異なるコードを選択する`target_arch`です。 + 条件コンパイルがサポートしている全ての詳細については、Rustリファレンスの#link(url_conditional)[条件コンパイル]の章を参照して下さい。 +], +zh: [ + 另外,Rust提供了许多可以使用的自动配置了的条件,比如`target_arch`用来选择不同的代码所基于的架构。对于条件编译的全部细节,可以参看the + Rust + reference的#link(url_conditional)[conditional compilation]章节。 +])) + +#tr(( +en: [ + The conditional compilation will only apply to the next statement or + block. If a block can not be used in the current scope then the `cfg` + attribute will need to be used multiple times. It's worth noting that + most of the time it is better to simply include all the code and allow + the compiler to remove dead code when optimising: it's simpler for you + and your users, and in general the compiler will do a good job of + removing unused code. +], +de: [ + Die bedingte Kompilierung bezieht sich nur auf die unmittelbar folgende + Anweisung oder den folgenden Block. Kann im aktuellen Gültigkeitsbereich + kein Block verwendet werden, muss das `cfg`-Attribut mehrfach eingesetzt + werden. Es sei darauf hingewiesen, dass es meist besser ist, den + gesamten Code einzubeziehen und den Compiler bei der Optimierung nicht + mehr benötigten Code („Dead Code") entfernen zu lassen: Dies ist für Sie + und Ihre Nutzer einfacher, und der Compiler leistet im Allgemeinen gute + Arbeit beim Entfernen von ungenutztem Code. +], +ja: [ + 条件コンパイルは、次のステートメントまたはブロックにのみ適用されます。 + 現在のスコープ内でブロックが使えない場合、`cfg`アトリビュートは複数回必要になります。 + ほとんどの場合、単純に全てのコードをインクルードして、コンパイラが最適化時にデッドコードを削除できるようにするほうが良いことに、注意すべきです。 + これは、あなたにも、あなたのユーザにとってもより簡単です。そして、通常、コンパイラは使用されていないコードをうまく削除します。 +], +zh: [ + 条件编译将只应用于下一条语句或者块。如果一个块不能在现在的作用域中被使用,那么`cfg`属性将需要被多次使用。值得注意的是大多数时间,仅是包含所有的代码而让编译器在优化时去删除死代码(dead + code)更好,通常,在移除不使用的代码方面的工作,编译器做得很好。 +])) + +=== #tr(( + en: [Compile-Time Sizes and Computation], + de: [Größen und Berechnungen zur Kompilierzeit], + ja: [コンパイル時サイズとコンパイル時計算], + zh: [编译时大小和计算], +)) + +#tr(( +en: [ + Rust supports `const fn`, functions which are guaranteed to be evaluable + at compile-time and can therefore be used where constants are required, + such as in the size of arrays. This can be used alongside features + mentioned above, for example: +], +de: [ + Rust unterstützt `const fn` -- Funktionen, die garantiert zur + Kompilierzeit ausgewertet werden können und sich daher überall dort + einsetzen lassen, wo Konstanten erforderlich sind, etwa bei der Größe + von Arrays. Dies lässt sich mit den zuvor genannten Funktionen + kombinieren, zum Beispiel: +], +ja: [ + Rustは`const fn`を提供しています。この関数はコンパイル時に評価されることが保証されているため、配列のサイズなど、定数が求められる場所で使用できます。 + const fnは、上述したフィーチャと同時に使う事ができます。例を示します。 +], +zh: [ + Rust支持`const fn`,`const fn`是在编译时可以被计算的函数,因此可以被用在需要常量的地方,比如在数组的大小中。这个能与上述的features一起使用,比如: +])) + +```rust +const fn array_size() -> usize { + #[cfg(feature="use_more_ram")] + { 1024 } + #[cfg(not(feature="use_more_ram"))] + { 128 } +} + +static BUF: [u32; array_size()] = [0u32; array_size()]; +``` + +#tr(( +en: [ + These are new to stable Rust as of 1.31, so documentation is still + sparse. The functionality available to `const fn` is also very limited + at the time of writing; in future Rust releases it is expected to expand + on what is permitted in a `const fn`. +], +de: [ + Diese Funktionen sind seit Version 1.31 in Stable Rust verfügbar, + weshalb die Dokumentation noch spärlich ist. Auch der für `const fn` + verfügbare Funktionsumfang ist zum Zeitpunkt der Erstellung dieses + Textes stark eingeschränkt; es ist jedoch zu erwarten, dass die in einer + `const fn` zulässigen Operationen in künftigen Rust-Versionen erweitert werden. +], +ja: [ + これらは、Rust + 1.31以降の新しい機能であるため、ドキュメントはまだわずかしかありません。 + 執筆時点では、`const fn`で利用可能な機能は、非常に限られています。 + 将来のRustでは、`const fn`内で許可されることが拡張されていくでしょう。 +], +zh: [ + 这些对于stable版本的Rust来说是新的特性,从1.31开始引入,因此文档依然很少。在写这篇文章的时候`const fn`可用的功能也非常有限; + 在未来的Rust release版本中,我们可以期望`const fn`将带来更多的功能。 +])) + +=== #tr(( + en: [Macros], + de: [Makros], + ja: [マクロ], + zh: [宏], +)) + +#let url_macros = "https://doc.rust-lang.org/book/ch19-06-macros.html" +#tr(( +en: [ + Rust provides an extremely powerful #link(url_macros)[macro system]. + While the C preprocessor operates almost directly on the text of your + source code, the Rust macro system operates at a higher level. There are + two varieties of Rust macro: _macros by example_ and + _procedural macros_. The former are simpler and most common; they + look like function calls and can expand to a complete expression, + statement, item, or pattern. Procedural macros are more complex but + permit extremely powerful additions to the Rust language: they can + transform arbitrary Rust syntax into new Rust syntax. +], +de: [ + Rust bietet ein äußerst leistungsfähiges #link(url_macros)[Makrosystem]. + Während der C-Präprozessor fast direkt auf dem Text des Quellcodes + arbeitet, operiert das Rust-Makrosystem auf einer höheren Ebene. Es gibt + zwei Arten von Rust-Makros: _Macros by Example_ (Makros nach + Muster) und _prozedurale Makros_. Erstere sind einfacher und weiter + verbreitet; sie sehen wie Funktionsaufrufe aus und können zu einem + vollständigen Ausdruck, einer Anweisung, einem Element oder einem Muster + expandiert werden. Prozedurale Makros sind komplexer, ermöglichen jedoch + äußerst leistungsfähige Erweiterungen der Sprache Rust: Sie können + beliebige Rust-Syntax in neue Rust-Syntax umwandeln. +], +ja: [ + Rustは、極めて強力な#link(url_macros)[マクロシステム]を提供しています。 + Cプリプロセッサがソースコードのテキストにほぼ直接作用するのに対して、Rustのマクロシステムはより上位レベルで作用します。 + Rustのマクロは2種類あります。_例によるマクロ_ と + _手続きマクロ_ です。 + 前者はより単純で最も一般的なものです。関数呼び出しのように見えて、完全な式やステートメント、アイテム、パターンに展開できます。 + 手続きマクロは、より複雑ですが、Rust言語に非常に強力な拡張を許可します。任意のRust構文を、新しいRust構文に変換することができます。 +], +zh: [ + Rust提供一个极度强大的#link(url_macros)[宏系统]。虽然C预处理器几乎直接在你的源代码之上进行操作,但是Rust宏系统可以在一个更高的级别上操作。存在两种Rust宏: + _声明宏_ 和 _过程宏_ 。前者更简单也最常见; + 它们看起来像是函数调用,且能扩展成一个完整的表达式,语句,项,或者模式。过程宏更复杂但是却能让Rust更强大: + 它们可以把任一条Rust语法变成一个新的Rust语法。 +])) + +#tr(( +en: [ + In general, where you might have used a C preprocessor macro, you + probably want to see if a macro-by-example can do the job instead. They + can be defined in your crate and easily used by your own crate or + exported for other users. Be aware that since they must expand to + complete expressions, statements, items, or patterns, some use cases of + C preprocessor macros will not work, for example a macro that expands to + part of a variable name or an incomplete set of items in a list. +], +de: [ + Wenn Sie normalerweise ein C-Präprozessor-Makro verwenden würden, + sollten Sie im Allgemeinen prüfen, ob stattdessen ein „Macro-by-Example" + (Makro-durch-Beispiel) die Aufgabe erfüllen kann. Solche Makros lassen + sich in Ihrem Crate definieren und sowohl intern verwenden als auch für + andere Nutzer exportieren. Beachten Sie jedoch, dass sie zu + vollständigen Ausdrücken, Anweisungen, Elementen (Items) oder Mustern + expandieren müssen; bestimmte Anwendungsfälle von C-Präprozessor-Makros + funktionieren daher nicht -- etwa Makros, die nur einen Teil eines + Variablennamens oder unvollständige Listenelemente erzeugen. +], +ja: [ + 通常、Cプリプロセッサマクロを使っていた場所に、例によるマクロで同じことができるかどうか、確認したいと思います。 + マクロは、クレート内に定義でき、自身のクレート内で簡単に使ったり、他のユーザにエクスポートしたりできます。 + マクロは、完全な式や、ステートメント、アイテム、パターンに展開されなければならないため、Cプリプロセッサマクロのいくつかのユースケースではうまく機能しません。 + 例えば、変数名や、リスト内の不完全なアイテムの一部に展開するようなマクロです。 +], +zh: [ + 通常,你可能想知道在那些使用一个C预处理器宏的地方,能否使用一个声明宏做同样的工作。你可以在crate中定义它们,且在你的crate中轻松使用它们或者导出给其他人用。但是请注意,因为它们必须扩展成完整的表达式,语句,项或者模式,因此C预处理器宏的某些用例没法用,比如可以扩展成一个变量名的一部分的宏或者可以把列表中的项扩展成不完整的集合的宏。 +])) + +#let url_inline = "https://doc.rust-lang.org/reference/attributes.html#inline-attribute" +#tr(( +en: [ + As with Cargo features, it is worth considering if you even need the + macro. In many cases a regular function is easier to understand and will + be inlined to the same code as a macro. The `#[inline]` and + `#[inline(always)]` #link(url_inline)[attributes] + give you further control over this process, although care should be + taken here as well --- the compiler will automatically inline functions + from the same crate where appropriate, so forcing it to do so + inappropriately might actually lead to decreased performance. +], +de: [ + Wie bei Cargo-Features lohnt es sich auch hier zu überlegen, ob das + Makro überhaupt erforderlich ist. Oftmals ist eine gewöhnliche Funktion + leichter verständlich und wird vom Compiler zu demselben Maschinencode + expandiert (geinlined) wie ein Makro. Die Attribute `#[inline]` und + `#[inline(always)]`-#link(url_inline)[Attribute] + bieten Ihnen zusätzliche Kontrolle über diesen Vorgang, wobei jedoch + Vorsicht geboten ist: Der Compiler inlined Funktionen aus demselben + Crate ohnehin automatisch, wenn dies sinnvoll ist; ein erzwungenes + Inlining in ungeeigneten Fällen kann die Leistung sogar verschlechtern. +], +ja: [ + Cargoフィーチャと同様、本当にマクロが必要かどうか、は検討する価値があります。 + 多くの場合、通常の関数は理解しやすく、マクロと同様にインライン化されます。 + `#[inline]`および`#[inline(always)]`の#link(url_inline)[アトリビュート]を使用すると、このプロセスをさらに細かく制御できます。 + ここでも注意が必要です。コンパイラは、適切な場合、関数を自動的にインライン化します。 + そのため、不適切なインライン化を強制すると、パフォーマンスが低下する可能性があります。 +], +zh: [ + 和Cargo + features一样,值得考虑下你是否真的需要宏。在一些例子中一个常规的函数更容易被理解,它也能被内联成和一个和宏一样的代码。`#[inline]`和`#[inline(always)]` + #link(url_inline)[attributes] + 能让你更深入控制这个过程,这里也要小心 - + 编译器会从同一个crate的恰当的地方自动地内联函数,因此不恰当地强迫它内联函数实际可能会导致性能下降。 +])) + +#tr(( +en: [ + Explaining the entire Rust macro system is out of scope for this tips + page, so you are encouraged to consult the Rust documentation for full + details. +], +de: [ + Eine Erläuterung des gesamten Rust-Makrosystems würde den Rahmen dieser + Tipps-Seite sprengen; für alle Einzelheiten sei daher auf die + Rust-Dokumentation verwiesen. +], +ja: [ + Rustのマクロシステムの全体を説明することは、このヒントページのスコープ範囲外です。 + 詳細については、Rustのドキュメントの参照をお勧めします。 +], +zh: [ + 研究完整的Rust宏系统超出了本节内容,因此我们鼓励你去查阅Rust文档了解完整的细节。 +])) + +== #tr(( + en: [Build System], + de: [Build System], + ja: [ビルドシステム], + zh: [编译系统], +)) + +#let url_build_scripts = "https://doc.rust-lang.org/cargo/reference/build-scripts.html" +#tr(( +en: [ + Most Rust crates are built using Cargo (although it is not required). + This takes care of many difficult problems with traditional build + systems. However, you may wish to customise the build process. Cargo + provides + #link(url_build_scripts)[`build.rs` scripts] + for this purpose. They are Rust scripts which can interact with the + Cargo build system as required. +], +de: [ + Die meisten Rust-Crates werden mit Cargo erstellt (auch wenn dies nicht + zwingend erforderlich ist). Cargo löst dabei viele der schwierigen + Probleme, die mit herkömmlichen Build-Systemen verbunden sind. Dennoch + kann es sinnvoll sein, den Build-Prozess individuell anzupassen. Hierfür + stellt Cargo #link(url_build_scripts)[`build.rs`-Skripte] + bereit. Dabei handelt es sich um Rust-Skripte, die bei Bedarf mit dem + Cargo-Build-System interagieren können. +], +ja: [ + (必須ではありませんが)ほとんどのRustのクレートは、Cargoを使ってビルドされます。 + Cargoは、従来のビルドシステムに関する多くの難しい問題の面倒を見ています。 + しかし、ビルドプロセスをカスタマイズしたいと思うかもしれません。このため、Cargoは#link(url_build_scripts)[`build.rs`スクリプト]を提供しています。 + build.rsスクリプトはRustで書かれたスクリプトで、必要に応じてCargoのビルドシステムとやり取りします。 +], +zh: [ + 大多数Rust crates使用Cargo编译 + (即使这不是必须的)。这解决了传统编译系统带来的许多难题。然而,你可能希望自定义编译过程。为了实现这个目的,Cargo提供了#link(url_build_scripts)[`build.rs`脚本]。它们是可以根据需要与Cargo编译系统进行交互的Rust脚本。 +])) + +#tr(( +en: [ + Common use cases for build scripts include: + - provide build-time information, for example statically embedding the + build date or Git commit hash into your executable + - generate linker scripts at build time depending on selected features + or other logic + - change the Cargo build configuration + - add extra static libraries to link against +], +de: [ + Zu den häufigen Anwendungsfällen für Build-Skripte gehören: + - Informationen zum Build-Zeitpunkt bereitstellen, zum Beispiel durch + das statische Einbetten des Build-Datums oder des Git-Commit-Hashs in + die ausführbare Datei. + - Linker-Skripte zur Build-Zeit generieren, abhängig von ausgewählten + Funktionen oder anderer Logik. + - die Cargo-Build-Konfiguration ändern + - Zusätzliche statische Bibliotheken für den Linkvorgang hinzufügen +], +ja: [ + ビルドスクリプトの一般的なユースケースを示します。 + - ビルド時の情報を提供します。例えば、実行ファイルにビルド日時やGitのコミットハッシュを静的に埋め込みます。 + - 選択されたフィーチャやその他のロジックに応じて、リンカスクリプトをビルド時に生成します。 + - Cargoのビルド設定を変更します。 + - リンクする静的ライブラリを追加します。 +], +zh: [ + 与编译脚本有关的常见用例包括: + - 提供编译时信息,比如静态嵌入编译日期或者Git commit + hash进你的可执行文件中 + - 根据被选择的features或者其它逻辑在编译时生成链接脚本 + - 改变Cargo的编译配置 + - 添加额外的静态链接库以进行链接 +])) + +#tr(( +en: [ + At present there is no support for post-build scripts, which you might + traditionally have used for tasks like automatic generation of binaries + from the build objects or printing build information. +], +de: [ + Derzeit gibt es keine Unterstützung für Post-Build-Skripte, wie man sie + üblicherweise für Aufgaben wie die automatische Erstellung von + Binärdateien aus den Build-Objekten oder die Ausgabe von + Build-Informationen verwendet hat. +], +ja: [ + 現状、ビルド後に実行するスクリプトは提供されていません。 + そのようなスクリプトは、従来では、ビルドしたオブジェクトからバイナリを自動的に生成したり、ビルド情報を表示したりするタスクに使われています。 +], +zh: [ + 现在还不支持post-build脚本,通常将它用于像是从编译的对象自动生生成二进制文件或者打印编译信息这类任务中。 +])) + +=== #tr(( + en: [Cross-Compiling], + de: [Cross-Kompilierung], + ja: [クロスコンパイル], + zh: [交叉编译], +)) + +#tr(( +en: [ + Using Cargo for your build system also simplifies cross-compiling. In + most cases it suffices to tell Cargo `--target thumbv6m-none-eabi` and + find a suitable executable in `target/thumbv6m-none-eabi/debug/myapp`. +], +de: [ + Die Verwendung von Cargo als Build-System vereinfacht auch die + Cross-Kompilierung. In den meisten Fällen genügt es, Cargo die Option + `--target thumbv6m-none-eabi` mitzugeben und die entsprechende + ausführbare Datei unter `target/thumbv6m-none-eabi/debug/myapp` zu finden. +], +ja: [ + Cargoをビルドシステムに使用するとクロスコンパイルも簡単になります。 + 多くの場合、Cargoに`--target thumbv6m-none-eabi`を伝えるだけで十分です。 + そうすると、適切な実行ファイルが`target/thumbv6m-none-eabi/debug/myapp`に見つかります。 +], +zh: [ + 为你的编译系统使用Cargo也能简化交叉编译。在大多数例子里,告诉Cargo + `--target thumbv6m-none-eabi`就行了,可以在`target/thumbv6m-none-eabi/debug/myapp`中找到一个合适的可执行文件。 +])) + +#let ln_xargo = link("https://github.com/japaric/xargo")[Xargo] +#tr(( +en: [ + For platforms not natively supported by Rust, you will need to build + `libcore` for that target yourself. On such platforms, + #ln_xargo can be used as a + stand-in for Cargo which automatically builds `libcore` for you. +], +de: [ + Für Plattformen, die nicht nativ von Rust unterstützt werden, müssen Sie + `libcore` für das jeweilige Zielsystem selbst kompilieren. Auf solchen + Plattformen lässt sich #ln_xargo + als Ersatz für Cargo verwenden, da es `libcore` automatisch für Sie + erstellt. +], +ja: [ + Rustが本来サポートしていないプラットフォームの場合、ターゲットの`libcore`を自分自身でビルドする必要があります。 + そのようなプラットフォームでは、#ln_xargo;をCargoの代わりに使うことができ、自動的に`libcore`をビルドしてくれます。 +], +zh: [ + 对于那些并不是Rust原生支持的平台,将需要自己为那个目标平台编译`libcore`。遇到这样的平台,#ln_xargo;可以作为Cargo的替代来使用,它可以自动地为你编译`libcore`。 +])) + +== #tr(( + en: [Iterators vs Array Access], + de: [Iteratoren vs.~Array-Zugriff], + ja: [イテレータ vs 配列アクセス], + zh: [迭代器与数组访问], +)) + +#tr(( +en: [ + In C you are probably used to accessing arrays directly by their index: +], +de: [ + In C sind Sie es wahrscheinlich gewohnt, direkt über den Index auf + Arrays zuzugreifen: +], +ja: [ + Cでは、おそらくインデックスによって直接配列にアクセスしているでしょう。 +], +zh: [ + 在C中,你可能习惯于通过索引直接访问数组: +])) + +```c +int16_t arr[16]; +int i; +for(i=0; i)[Concurrency chapter]). +], +de: [ + Es ist selten erforderlich, diese Funktionen direkt im eigenen Code zu + verwenden, da sie üblicherweise von höherwertigen Bibliotheken für Sie + übernommen werden. Bei speicherabgebildeten Peripheriekomponenten + implementieren die entsprechenden „Peripheral Access Crates" den + volatilen Zugriff automatisch, während für Nebenläufigkeits-Primitive + bessere Abstraktionen zur Verfügung stehen (siehe das Kapitel + #link()[Nebenläufigkeit]). +], +ja: [ + これらの関数をコードに直接書くことは稀です。通常、より上位レベルのライブラリで面倒を見てくれます。 + メモリマップドペリフェラルについては、ペリフェラルアクセスクレートがvolatileアクセスを自動的に実装します。 + 並行性プリミティブの場合、より優れた抽象化が利用できます(#link()[並行性の章]を参照して下さい)。 +], +zh: [ + 在你的代码中直接使用这些函数是很少见的,因为它们通常由更高级的库封装起来为你提供服务。对于存储映射的外设,提供外设访问的crates将自动实现volatile访问,而对于并发的基本类型,存在更好的抽象可用。(看#link()[并发章节]) +])) + +== #tr(( + en: [Packed and Aligned Types], + de: [Gepackte und ausgerichtete Datentypen], + ja: [パック型と整列型], + zh: [填充和对齐类型], +)) + +#tr(( +en: [ + In embedded C it is common to tell the compiler a variable must have a + certain alignment or a struct must be packed rather than aligned, + usually to meet specific hardware or protocol requirements. +], +de: [ + In der Embedded-Programmierung mit C ist es üblich, dem Compiler + vorzugeben, dass eine Variable eine bestimmte Ausrichtung (Alignment) + aufweisen oder eine Struktur „gepackt" (packed) statt ausgerichtet sein + muss -- meist, um spezifische Hardware- oder Protokollanforderungen zu erfüllen. +], +ja: [ + 組込みCでは、通常、特定のハードウェアやプロトコルの要件を満たすために、変数に特定のアライメントが必要なことや、 + 構造体が整列されているだけでなくパックされている必要があることを、コンパイラに指示することが一般的です。 +], +zh: [ + 在嵌入式C中,告诉编译器一个变量必须遵守某个对齐或者一个结构体必须被填充而不是对齐,是很常见的行为,通常是为了满足特定的硬件或者协议要求。 +])) + +#tr(( +en: [ + In Rust this is controlled by the `repr` attribute on a struct or union. + The default representation provides no guarantees of layout, so should + not be used for code that interoperates with hardware or C. The compiler + may re-order struct members or insert padding and the behaviour may + change with future versions of Rust. +], +de: [ + In Rust wird dies über das `repr`-Attribut an einer `struct` oder + `union` gesteuert. Die Standarddarstellung macht keine Zusagen über das + Speicherlayout und sollte daher nicht für Code verwendet werden, der mit + Hardware oder C interagiert. Der Compiler kann die Reihenfolge der + Strukturmitglieder ändern oder Füllbytes (Padding) einfügen, und das + Verhalten kann sich in zukünftigen Rust-Versionen ändern. +], +ja: [ + Rustでは、これは構造体または共用体の`repr`アトリビュートによって制御されます。 + デフォルトでは、レイアウトは保証されないため、ハードウェアやCとやり取りするコードでは使うべきではありません。 + コンパイラは、構造体のメンバを並べ替えたり、パディングを挿入したりする可能性があります。この動作は将来のバージョンのRustで変更になる可能性があります。 +], +zh: [ + 在Rust中,这由一个结构体或者联合体上的`repr`属性来控制。默认的表示(representation)不保障布局,因此不应该被用于与硬件或者C互用的代码。编译器可能会对结构体成员重新排序或者插入填充,且这种行为可能在未来的Rust版本中改变。 +])) + +#raw(block: true, lang: "rust", +"struct Foo { + x: u16, + y: u8, + z: u16, +} + +fn main() { + let v = Foo { x: 0, y: 0, z: 0 }; + println!(\"{:p} {:p} {:p}\", &v.x, &v.y, &v.z); +} + +// 0x7ffecb3511d0 0x7ffecb3511d4 0x7ffecb3511d2 +// " + ts(( + en: "Note ordering has been changed to x, z, y to improve packing.", + de: "Die Reihenfolge der Noten wurde auf x, z, y geaendert, um die Packdichte zu +// verbessern.", + ja: "データの詰め方を改善するために、x, y, zの順序が入れ替わっていることに注目して下さい。", + zh: "0x7ffecb3511d0 0x7ffecb3511d4 0x7ffecb3511d2 +// 注意为了改进填充,顺序已经被变成了x, z, y" + )) + " +") + +#tr(( +en: [ + To ensure layouts that are interoperable with C, use `repr(C)`: +], +de: [ + Um Layouts zu gewährleisten, die mit C interoperabel sind, verwenden Sie `repr(C)`: +], +ja: [ + Cと相互にやり取りできるレイアウトを保証するためには、`repr(C)`を使います。 +], +zh: [ + 使用`repr(C)`可以确保布局可以与C互用。 +])) + +#raw(block: true, lang: "rust", +"#[repr(C)] +struct Foo { + x: u16, + y: u8, + z: u16, +} + +fn main() { + let v = Foo { x: 0, y: 0, z: 0 }; + println!(\"{:p} {:p} {:p}\", &v.x, &v.y, &v.z); +} + +// 0x7fffd0d84c60 0x7fffd0d84c62 0x7fffd0d84c64 +// " + ts(( + en: "Ordering is preserved and the layout will not change over time. +// `z` is two-byte aligned so a byte of padding exists between `y` and `z`.", + de: "Die Reihenfolge bleibt erhalten und das Layout veraendert sich im Laufe der +// Zeit nicht. +// `z` ist auf Zwei-Byte-Grenzen ausgerichtet, sodass sich zwischen `y` und `z` +// ein Padding-Byte befindet.", + ja: "順序は維持され、レイアウトは時間が経っても変化しません。 +// `z`は2バイトで整列されており、`y`と`z`の間には、1バイトのパディングが存在します。", + zh: "0x7fffd0d84c60 0x7fffd0d84c62 0x7fffd0d84c64 +// 顺序被保留了,布局将不会随着时间而改变 +// `z`是两个字节对齐,因此在`y`和`z`之间填充了一个字节。" + )) + " +") + +#tr(( +en: [ + To ensure a packed representation, use `repr(packed)`: +], +de: [ + Um eine kompakte Darstellung zu gewährleisten, verwenden Sie `repr(packed)`: +], +ja: [ + パックされた表現を保証する場合、`repr(packed)`を使います。 +], +zh: [ + 使用`repr(packed)`去确保表示(representation)被填充了: +])) + +#raw(block: true, lang: "rust", +"#[repr(packed)] +struct Foo { + x: u16, + y: u8, + z: u16, +} + +fn main() { + let v = Foo { x: 0, y: 0, z: 0 }; + // " + ts(( + en: "References must always be aligned, so to check the addresses of the + // struct's fields, we use `std::ptr::addr_of!()` to get a raw pointer + // instead of just printing `&v.x`.", + de: "Referenzen muessen stets korrekt ausgerichtet sein; um also die + // Adressen der Struct-Felder zu ueberpruefen, verwenden wir + // `std::ptr::addr_of!()`, um einen Rohzeiger (Raw Pointer) zu erhalten, + // anstatt einfach `&v.x` auszugeben.", + ja: "パックされた構造体のフィールドを借用するには、アンセーフが必要です。", + zh: "引用必须总是对齐的,因此为了检查结构体字段的地址,我们使用 + // `std::ptr::addr_of!()`去获取一个裸指针而不仅是打印`&v.x`" + )) + " + let px = std::ptr::addr_of!(v.x); + let py = std::ptr::addr_of!(v.y); + let pz = std::ptr::addr_of!(v.z); + println!(\"{:p} {:p} {:p}\", px, py, pz); +} + +// 0x7ffd33598490 0x7ffd33598492 0x7ffd33598493 +// " + ts(( + en: "No padding has been inserted between `y` and `z`, so now `z` is unaligned.", + de: "Zwischen `y` und `z` wurde kein Padding eingefuegt, daher ist `z` nun +// nicht ausgerichtet.", + ja: "`y`と`z`の間にパディングは挿入されていません。そのため、`z`は整列されていません。", + zh: "0x7ffd33598490 0x7ffd33598492 0x7ffd33598493 +// 在`y`和`z`没有填充被插入,因此现在`z`没有被对齐。" + )) + " +") + +#tr(( +en: [ + Note that using `repr(packed)` also sets the alignment of the type to `1`. +], +de: [ + Beachten Sie, dass die Verwendung von `repr(packed)` die Ausrichtung des + Typs ebenfalls auf `1` setzt. +], +ja: [ + `repr(packed)`を使うと、型のアライメントも`1`に設定されることに注意して下さい。 +], +zh: [ + 注意使用`repr(packed)`也会将类型的对齐设置成`1` 。 +])) + +#tr(( +en: [ + Finally, to specify a specific alignment, use `repr(align(n))`, where + `n` is the number of bytes to align to (and must be a power of two): +], +de: [ + Um eine bestimmte Ausrichtung festzulegen, verwenden Sie schließlich + `repr(align(n))`, wobei `n` die Anzahl der auszurichtenden Bytes ist + (und eine Zweierpotenz sein muss). +], +ja: [ + 最後に、特定のアライメントを指定するために、`repr(align(n))`を使います。 + ここで`n`は、整列するバイト数です(2の累乗である必要があります)。 +], +zh: [ + 最后,为了指定一个特定的对齐,可以使用`repr(align(n))`,`n`是要对齐的字节数(必须是2的幂): +])) + +#raw(block: true, lang: "rust", +"#[repr(C)] +#[repr(align(4096))] +struct Foo { + x: u16, + y: u8, + z: u16, +} + +fn main() { + let v = Foo { x: 0, y: 0, z: 0 }; + let u = Foo { x: 0, y: 0, z: 0 }; + println!(\"{:p} {:p} {:p}\", &v.x, &v.y, &v.z); + println!(\"{:p} {:p} {:p}\", &u.x, &u.y, &u.z); +} + +// 0x7ffec909a000 0x7ffec909a002 0x7ffec909a004 +// 0x7ffec909b000 0x7ffec909b002 0x7ffec909b004 +// " + ts(( + en: "The two instances `u` and `v` have been placed on 4096-byte alignments, +// evidenced by the `000` at the end of their addresses.", + de: "Die beiden Instanzen `u` und `v` wurden an 4096-Byte-Grenzen ausgerichtet, +// was an den `000` am Ende ihrer Adressen erkennbar ist.", + ja: "2つのインスタンス`u`と`v`は4096バイトのアライメントで配置されます。 +// インスタンスのアドレスの最後は`000`になっています。", + zh: "`u`和`v`两个实例已经被放置在4096字节的对齐上。 +// 它们地址结尾处的`000`证明了这件事。" + )) + " +") + +#tr(( +en: [ + Note we can combine `repr(C)` with `repr(align(n))` to obtain an aligned + and C-compatible layout. It is not permissible to combine + `repr(align(n))` with `repr(packed)`, since `repr(packed)` sets the + alignment to `1`. It is also not permissible for a `repr(packed)` type + to contain a `repr(align(n))` type. +], +de: [ + Beachten Sie, dass wir `repr(C)` mit `repr(align(n))` kombinieren + können, um ein ausgerichtetes und C-kompatibles Layout zu erhalten. Die + Kombination von `repr(align(n))` mit `repr(packed)` ist nicht zulässig, + da `repr(packed)` die Ausrichtung auf `1` setzt. Ebenso ist es nicht + zulässig, dass ein `repr(packed)`-Typ einen `repr(align(n))`-Typ + enthält. +], +ja: [ + 整列されていてCと互換性のあるレイアウトを取得するため、`repr(C)`と`repr(align(n))`とを組み合わせることができます。 + `repr(align(n))`と`repr(packed)`とを組み合わせることはできません。`repr(packed)`はアライメントを`1`に設定するからです。 + `repr(packed)`の型を`repr(align(n))`の型に含めることもできません。 +], +zh: [ + 注意我们可以结合`repr(C)`和`repr(align(n))`来获取一个对齐的c兼容的布局。不允许将`repr(align(n))`和`repr(packed)`一起使用,因为`repr(packed)`将对齐设置为`1`。也不允许一个`repr(packed)`类型包含一个`repr(align(n))`类型。 +])) + +#let url_layout = "https://doc.rust-lang.org/reference/type-layout.html" +#tr(( +en: [ + For further details on type layouts, refer to the #link(url_layout)[type layout] + chapter of the Rust Reference. +], +de: [ + Weitere Details zu Typ-Layouts finden Sie im Kapitel + #link(url_layout)[Typ-Layout] der Rust-Referenz. +], +ja: [ + 型レイアウトに関するさらなる詳細は、Rustリファレンスの#link(url_layout)[型レイアウト]の章を参照して下さい。 +], +zh: [ + 关于类型布局更多的细节,参考the Rust Reference的#link(url_layout)[type layout]章节。 +])) + +== #tr(( + en: [Other Resources], + de: [Weitere Ressourcen], + ja: [その他のリソース], + zh: [其它资源], +)) + +#let url_faq = "https://docs.rust-embedded.org/faq.html" +#let url_for_c = "http://blahg.josefsipek.net/?p=580" +#let url_pointers = "https://github.com/diwic/reffers-rs/blob/master/docs/Pointers.html" +#tr(( +en: [ + - In this book: + - #link()[A little C with your Rust] + - #link()[A little Rust with your C] + - #link(url_faq)[The Rust Embedded FAQs] + - #link(url_for_c)[Rust Pointers for C Programmers] + - #link(url_pointers)[I used to use pointers - now what?] +], +de: [ + - In diesem Buch: + - #link()[Ein bisschen C zu Ihrem Rust] + - #link()[Ein bisschen Rust zu Ihrem C] + - #link(url_faq)[Die Rust-Embedded-FAQs] + - #link(url_for_c)[Rust-Pointer für C-Programmierer] + - #link(url_pointers)[Früher habe ich Pointer verwendet -- und jetzt?] +], +ja: [ + - 本書内 + - #link()[Rustと少しのC] + - #link()[Cと少しのRust] + - #link(url_faq)[組込みRustよくある質問] + - #link(url_for_c)[CプログラマのためのRustのポインタ] + - #link(url_pointers)[昔はポインタを使っていました。今は?] +], +zh: [ + - 这本书中: + - #link()[使用C的Rust] + - #link()[使用Rust的C] + - #link(url_faq)[The Rust Embedded FAQs] + - #link(url_for_c)[Rust Pointers for C Programmers] + - #link(url_pointers)[I used to use pointers - now what?] +])) diff --git a/typ/collections/index.typ b/typ/collections/index.typ new file mode 100644 index 00000000..e01d20b0 --- /dev/null +++ b/typ/collections/index.typ @@ -0,0 +1,845 @@ +#import "../config.typ": * + +#h1((en: [Collections], + de: [Sammlungen (Collections)], + ja: [コレクション], + zh: [集合], +)) + +#let ln_vec = link("https://doc.rust-lang.org/std/vec/struct.Vec.html")[`Vec`] +#let ln_string = link("https://doc.rust-lang.org/std/string/struct.String.html")[`String`] +#let ln_map = link("https://doc.rust-lang.org/std/collections/struct.HashMap.html")[`HashMap`] +#tr(( +en: [ + Eventually you'll want to use dynamic data structures (AKA collections) + in your program. `std` provides a set of common collections: + #ln_vec, #ln_string, #ln_map, etc. + All the collections implemented in `std` use a global dynamic + memory allocator (AKA the heap). +], +de: [ + Irgendwann wirst du in deinem Programm dynamische Datenstrukturen (auch + bekannt als Collections) verwenden wollen. Die Standardbibliothek + (`std`) stellt eine Reihe gängiger Collections bereit: + #ln_vec, #ln_string, #ln_map usw. + Alle in `std` implementierten Collections nutzen einen globalen + dynamischen Speicherverwalter (den sogenannten Heap). +], +ja: [ + いずれは、プログラム内で動的なデータ構造(別名コレクション)を使いたいでしょう。 + `std`は、#ln_vec;や#ln_string;、#ln_map;といった、一般的なコレクションを提供しています。 + `std`で実装されている全てのコレクションは、グローバルな動的アロケータ(別名ヒープ)を使用します。 +], +zh: [ + 最后,还希望在程序里使用动态数据结构(也称为集合)。`std` + 提供了一组常见的集合: + #ln_vec,#ln_string,#ln_map,等等。所有这些在`std`中被实现的集合都使用一个全局动态分配器(也称为堆)。 +])) + +#tr(( +en: [ + As `core` is, by definition, free of memory allocations these + implementations are not available there, but they can be found in the + `alloc` crate that's shipped with the compiler. +], +de: [ + Da `core` definitionsgemäß frei von Speicherzuweisungen ist, stehen + diese Implementierungen dort nicht zur Verfügung; sie sind jedoch im + `alloc`-Crate zu finden, das mit dem Compiler ausgeliefert wird. +], +ja: [ + `core`は、定義上、メモリアロケーションがないためコレクションの実装を使うことができません。 + しかし、コンパイラと共に配布されている_安定化していない_`alloc`クレートの中にコレクションの実装があります。 +], +zh: [ + 因为`core`的定义中是没有内存分配的,所以这些实现在`core`中是没有的,但是我们可以在编译器附带的`alloc` + crate中找到。 +])) + +#let ln_heapless = link("https://crates.io/crates/heapless")[`heapless`] +#tr(( +en: [ + If you need collections, a heap allocated implementation is not your + only option. You can also use _fixed capacity_ collections; one + such implementation can be found in the #ln_heapless crate. +], +de: [ + Wenn Sie Sammlungen benötigen, ist eine auf dem Heap alloziierte + Implementierung nicht Ihre einzige Option. Sie können auch Sammlungen + mit _fester Kapazität_ verwenden; eine solche Implementierung + findet sich im #ln_heapless;-Crate. +], +ja: [ + もしコレクションが必要であれば、ヒープに割り当てる実装だけが選択肢ではありません。 + _サイズが固定された_コレクションを使うことができます。そのような実装は#ln_heapless;クレートの中にあります。 +], +zh: [ + 如果需要集合,一个基于堆分配的实现不是唯一的选择。也可以使用 _fixed capacity_ 集合; 其实现可以在 + #ln_heapless crate中被找到。 +])) + +#tr(( +en: [ + In this section, we'll explore and compare these two implementations. +], +de: [ + In diesem Abschnitt werden wir diese beiden Implementierungen + untersuchen und vergleichen. +], +ja: [ + `alloc`クレートは、標準のRust配布物に同梱されています。このクレートをインポートするには、 + `Cargo.toml`ファイルに依存関係を宣言_することなしに_直接`use`します。 +], +zh: [ + 在这部分,我们将研究和比较这两个实现。 +])) + +== #tr(( + en: [Using `alloc`], + de: [Verwendung von `alloc`], + ja: [`alloc`を使用], + zh: [使用 `alloc`], +)) + +#tr(( +en: [ + The `alloc` crate is shipped with the standard Rust distribution. To + import the crate you can directly `use` it _without_ declaring it + as a dependency in your `Cargo.toml` file. +], +de: [ + Die `alloc`-Crate ist in der Standard-Rust-Distribution enthalten. Um + das Crate zu importieren, können Sie es direkt per `use` einbinden, + _ohne_ es als Abhängigkeit in Ihrer `Cargo.toml`-Datei zu deklarieren. +], +ja: [ + `alloc`クレートは、標準のRust配布物に同梱されています。このクレートをインポートするには、 + `Cargo.toml`ファイルに依存関係を宣言_することなしに_直接`use`します。 +], +zh: [ + `alloc` crate与标准的Rust发行版在一起。你可以直接 `use` + 导入这个crate,而不需要在`Cargo.toml`文件中把它声明为一个依赖。 +])) + +```rust +#![feature(alloc)] + +extern crate alloc; + +use alloc::vec::Vec; +``` + +#let ln_alloc = link("https://doc.rust-lang.org/core/alloc/trait.GlobalAlloc.html")[`GlobalAlloc`] +#tr(( +en: [ + To be able to use any collection you'll first need use the + `global_allocator` attribute to declare the global allocator your + program will use. It's required that the allocator you select implements + the #ln_alloc trait. +], +de: [ + Um eine beliebige Collection nutzen zu können, müssen Sie zunächst das + Attribut `global_allocator` verwenden, um den globalen Allocator zu + deklarieren, den Ihr Programm einsetzen soll. Der gewählte Allocator + muss zwingend das Trait #ln_alloc implementieren. +], +ja: [ + コレクションを使うには、まず最初に、プログラム中のグローバルアロケータを宣言する`global_allocator`アトリビュートを使う必要があります。 + 選択したアロケータが#ln_alloc;トレイトを実装することが求められます。 +], +zh: [ + 为了能使用集合,首先需要使用`global_allocator`属性去声明程序将使用的全局分配器。它要求选择的分配器实现了#link("https://doc.rust-lang.org/core/alloc/trait.GlobalAlloc.html")[`GlobalAlloc`] + trait 。 +])) + +#tr(( +en: [ + For completeness and to keep this section as self-contained as possible + we'll implement a simple bump pointer allocator and use that as the + global allocator. However, we _strongly_ suggest you use a battle + tested allocator from crates.io in your program instead of this allocator. +], +de: [ + Der Vollständigkeit halber und um diesen Abschnitt so in sich + abgeschlossen wie möglich zu halten, implementieren wir einen einfachen + Bump-Pointer-Allokator und verwenden diesen als globalen Allokator. Wir + empfehlen Ihnen jedoch _dringend_, in Ihrem Programm stattdessen + einen praxiserprobten Allokator von crates.io zu verwenden. +], +ja: [ + このセクションを可能な限り自己完結させるため、グローバルアロケータとして、単純にポインタを増加するだけのアロケータを実装します。 + しかしながら、あなたのプログラムではこのアロケータでなく、crates.ioから歴戦のアロケータを使用することを_強く_お勧めします。 +], +zh: [ + 为了完整性和尽可能保持本节的自包含性,我们将实现一个简单线性指针分配器且用它作为全局分配器。然而,我们 + _强烈地_ + 建议你在你的程序中使用一个来自crates.io的久经战斗测试的分配器而不是这个分配器。 +])) + +#raw(block: true, lang: "rust", +"// " + ts(( + en: "Bump pointer allocator implementation", + de: "Implementierung eines Bump-Pointer-Allocators", + ja: "ポインタを増加するだけのアロケータ実装", + zh: "线性指针分配器实现", + )) + " + +use core::alloc::{GlobalAlloc, Layout}; +use core::cell::UnsafeCell; +use core::ptr; + +use cortex_m::interrupt; + +// " + ts(( + en: "Bump pointer allocator for *single* core systems", + de: "Bump-Pointer-Allocator fuer Systeme mit *einem* Rechenkern", + ja: "*シングル*コアシステム用のポインタを増加するだけのアロケータ", + zh: "用于单核系统的线性指针分配器", + )) + " +struct BumpPointerAlloc { + head: UnsafeCell, + end: usize, +} + +unsafe impl Sync for BumpPointerAlloc {} + +unsafe impl GlobalAlloc for BumpPointerAlloc { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + // " + ts(( + en: "`interrupt::free` is a critical section that makes our allocator safe + // to use from within interrupts", + de: "`interrupt::free` ist ein kritischer Abschnitt, der die sichere + // Verwendung unseres Allocators aus Interrupts heraus ermoeglicht.", + ja: "`interrupt::free`は、割り込み内でアロケータを安全に使用するための + // クリティカルセクションです。", + zh: "`interrupt::free`是一个临界区,临界区让我们的分配器在中断中用起来安全", + )) + " + interrupt::free(|_| { + let head = self.head.get(); + let size = layout.size(); + let align = layout.align(); + let align_mask = !(align - 1); + + // " + ts(( + en: "move start up to the next alignment boundary", + de: "Verschiebe den Startpunkt zur naechsten Ausrichtungsgrenze.", + ja: "ヌルポインタはメモリ不足の状態を知らせます", + zh: "将start移至下一个对齐边界。", + )) + " + let start = (*head + align - 1) & align_mask; + + if start + size > self.end { + // " + ts(( + en: "a null pointer signal an Out Of Memory condition", + de: "ein Nullzeiger signalisiert einen „Out of Memory“-Zustand", + ja: "このアロケータはメモリを解放しません", + zh: "一个空指针通知内存不足", + )) + " + ptr::null_mut() + } else { + *head = start + size; + start as *mut u8 + } + }) + } + + unsafe fn dealloc(&self, _: *mut u8, _: Layout) { + // " + ts(( + en: "this allocator never deallocates memory", + de: "Dieser Allokator gibt niemals Speicher frei.", + ja: "このアロケータはメモリを解放しません", + zh: "这个分配器从不释放内存", + )) + " + } +} + +// " + ts(( + en: "Declaration of the global memory allocator +// NOTE the user must ensure that the memory region `[0x2000_0100, 0x2000_0200]` +// is not used by other parts of the program", + de: "Deklaration des globalen Speicher-Allocators +// HINWEIS: Der Benutzer muss sicherstellen, dass der Speicherbereich +// `[0x2000_0100, 0x2000_0200]` nicht von anderen Teilen des Programms +// verwendet wird.", + ja: "グローバルメモリアロケータの宣言 +// ユーザはメモリ領域の`[0x2000_0100, 0x2000_0200]`がプログラムの他の部分で使用されないことを +// 保証しなければなりません", + zh: "全局内存分配器的声明 +// 注意 用户必须确保`[0x2000_0100, 0x2000_0200]`内存区域 +// 没有被程序的其它部分使用" + )) + " +#[global_allocator] +static HEAP: BumpPointerAlloc = BumpPointerAlloc { + head: UnsafeCell::new(0x2000_0100), + end: 0x2000_0200, +}; +") + +#tr(( +en: [ + Apart from selecting a global allocator the user will also have to + define how Out Of Memory (OOM) errors are handled using the + _unstable_ `alloc_error_handler` attribute. +], +de: [ + Neben der Auswahl eines globalen Allocators muss der Benutzer auch + festlegen, wie mit „Out of Memory" (OOM)-Fehlern umgegangen wird; + hierfür wird das _instabile_ Attribut `alloc_error_handler` + verwendet. +], +ja: [ + グローバルアロケータの選択とは別に、ユーザはメモリ不足(OOM)エラーの処理方法を、 + _安定化していない_`alloc_error_handler`アトリビュートを使って定義する必要があります。 +], +zh: [ + 除了选择一个全局分配器,用户也必须要定义如何使用_不稳定的_`alloc_error_handler`属性来处理内存溢出错误。 +])) + +```rust +#![feature(alloc_error_handler)] + +use cortex_m::asm; + +#[alloc_error_handler] +fn on_oom(_layout: Layout) -> ! { + asm::bkpt(); + + loop {} +} +``` + +#tr(( +en: [ + Once all that is in place, the user can finally use the collections in `alloc`. +], +de: [ + Sobald alles vorhanden ist, kann der Benutzer endlich die Sammlungen in + „alloc" verwenden. +], +ja: [ + 全ての準備が整うと、ユーザはついに`alloc`のコレクションを使うことができます。 +], +zh: [ + 一旦一切都完成了,用户最后就可以在`alloc`中使用集合。 +])) + +```rust +#[entry] +fn main() -> ! { + let mut xs = Vec::new(); + + xs.push(42); + assert!(xs.pop(), Some(42)); + + loop { + // .. + } +} +``` + +#tr(( +en: [ + If you have used the collections in the `std` crate then these will be + familiar as they are exact same implementation. +], +de: [ + Wenn Sie die Sammlungen aus dem `std`-Crate bereits verwendet haben, + werden Ihnen diese vertraut vorkommen, da es sich um exakt dieselbe + Implementierung handelt. +], +ja: [ + `std`クレートのコレクションを使ったことがあれば、実装が全く同じものであるため、これらのコレクションはお馴染みでしょう。 +], +zh: [ + 如果你已经使用了`std` + crate中的集合,那么这些对你来说将非常熟悉,因为他们的实现一样。 +])) + +== #tr(( + en: [Using `heapless`], + de: [Verwendung von `heapless`], + ja: [`heapless`の使用], + zh: [使用 `heapless`], +)) + +#tr(( +en: [ + `heapless` requires no setup as its collections don't depend on a global + memory allocator. Just `use` its collections and proceed to instantiate them: +], +de: [ + `heapless` erfordert keine Einrichtung, da seine Datenstrukturen nicht + von einem globalen Speicher-Allocator abhängen. Binde die + Datenstrukturen einfach per `use` ein und instanziiere sie: +], +ja: [ + `heapless`のコレクションはグローバルメモリアロケータに依存しないため、準備は不要です。 + 単にコレクションを`use`して、インスタンスを作成するだけです。 +], +zh: [ + `heapless`无需设置,因为它的集合不依赖一个全局内存分配器。只是`use`它的集合然后实例化它们: +])) + +```rust +// heapless version: v0.4.x +use heapless::Vec; +use heapless::consts::*; + +#[entry] +fn main() -> ! { + let mut xs: Vec<_, U8> = Vec::new(); + + xs.push(42).unwrap(); + assert_eq!(xs.pop(), Some(42)); + loop {} +} +``` + +#tr(( +en: [ + You'll note two differences between these collections and the ones in `alloc`. +], +de: [ + Sie werden zwei Unterschiede zwischen diesen Sammlungen und denen in + `alloc` feststellen. +], +ja: [ + `alloc`のコレクションとは違う点が2つあることに留意して下さい。 +], +zh: [ + 你会注意到这些集合与`alloc`中的集合有两个不一样的地方。 +])) + +#let ln_typenum = link("https://crates.io/crates/typenum")[`typenum`] +#tr(( +en: [ + First, you have to declare upfront the capacity of the collection. + `heapless` collections never reallocate and have fixed capacities; this + capacity is part of the type signature of the collection. In this case + we have declared that `xs` has a capacity of 8 elements that is the + vector can, at most, hold 8 elements. This is indicated by the `U8` + (see #ln_typenum) in the type signature. +], +de: [ + Erstens muss die Kapazität der Sammlung im Voraus deklariert werden. + `heapless`-Sammlungen werden nie neu allokiert und haben eine feste + Kapazität; diese Kapazität ist Teil der Typsignatur der Sammlung. In + diesem Fall haben wir deklariert, dass `xs` eine Kapazität von 8 + Elementen hat, d.~h. der Vektor kann maximal 8 Elemente aufnehmen. Dies + wird durch das `u8` (siehe #ln_typenum) in der Typsignatur + angezeigt. +], +ja: [ + 1つ目は、コレクションの容量を最初に宣言しなければならないことです。 + `heapless`コレクションは、再割り当てが発生せず、固定の容量になります。この容量はコレクションの型シグネチャの一部になります。 + 上記の例では、`xs`は8要素の容量を持つように宣言しています。このベクタは最大で8つの要素を保持することができます。 + 型シグネチャの`U8`(#ln_typenum;を参照)がこのことを表しています。 +], +zh: [ + 第一,你必须预先声明集合的容量。`heapless`集合从来不会发生重分配且具有固定的容量;这个容量是集合的类型签名的一部分。在这个例子里,我们已经声明了`xs`的容量为8个元素,也就是说,这个vector最多只能有八个元素。这是通过类型签名中的`U8` + (看#ln_typenum)来指定的。 +])) + +#tr(( +en: [ + Second, the `push` method, and many other methods, return a `Result`. + Since the `heapless` collections have fixed capacity all operations that + insert elements into the collection can potentially fail. The API + reflects this problem by returning a `Result` indicating whether the + operation succeeded or not. In contrast, `alloc` collections will + reallocate themselves on the heap to increase their capacity. +], +de: [ + Zweitens geben die Methode `push` sowie viele weitere Methoden ein + `Result` zurück. Da `heapless`-Datenstrukturen über eine feste Kapazität + verfügen, können alle Operationen, die Elemente in die Struktur + einfügen, potenziell fehlschlagen. Die API trägt diesem Umstand + Rechnung, indem sie ein `Result` liefert, das anzeigt, ob die Operation + erfolgreich war oder nicht. Im Gegensatz dazu passen + `alloc`-Datenstrukturen ihre Kapazität durch eine erneute + Speicherzuweisung auf dem Heap an. +], +ja: [ + 2つ目は、`push`メソッドおよび他の多くのメソッドが`Result`を返すことです。 + `heapless`コレクションは固定の容量を持つため、コレクションに要素を挿入する全ての操作は、失敗する可能性があります。 + APIは、操作が成功したかどうかを示すための`Result`を返すことで、この問題に対処しています。 + 一方、`alloc`コレクションは、ヒープ上で再割り当てするため、容量を増やすことができます。 +], +zh: [ + 第二,`push`方法和另外一些方法返回的是一个`Result`。因为`heapless`集合有一个固定的容量,所以所有插入的操作都可能会失败。通过返回一个`Result`,API反应了这个问题,指出操作是否成功还是失败。相反,`alloc`集合自己将会在堆上重新分配去增加它的容量。 +])) + +#tr(( +en: [ + As of version v0.4.x all `heapless` collections store all their elements + inline. This means that an operation like + `let x = heapless::Vec::new();` will allocate the collection on the + stack, but it's also possible to allocate the collection on a `static` + variable, or even on the heap (`Box>`). +], +de: [ + Seit Version v0.4.x speichern alle `heapless`-Datenstrukturen ihre + Elemente direkt „inline". Das bedeutet, dass eine Operation wie + `let x = heapless::Vec::new();` die Datenstruktur auf dem Stack anlegt; + es ist jedoch auch möglich, sie in einer `static`-Variablen oder sogar + auf dem Heap (`Box>`) zu speichern. +], +ja: [ + v0.4.x以降、全ての`heapless`コレクションは、全ての要素をインラインで格納しています。 + つまり、 + `let x = heapless::Vec::new();`のような操作は、スタック上にコレクションを割り当てます。 + また、コレクションを`static`変数や、ヒープ上(`Box>`)にさえ、に割り当てることが可能です。 +], +zh: [ + 自v0.4.x版本起,所有的`heapless`集合将所有的元素内联地存储起来了。这意味着像是`let x = heapless::Vec::new()`这样的一个操作将会在栈上分配集合,但是它也能够在一个`static`变量上分配集合,或者甚至在堆上(`Box>`)。 +])) + +== #tr(( + en: [Trade-offs], + de: [Abwägungen], + ja: [トレードオフ], + zh: [取舍], +)) + +#tr(( +en: [ + Keep these in mind when choosing between heap allocated, relocatable + collections and fixed capacity collections. +], +de: [ + Berücksichtigen Sie diese Punkte, wenn Sie zwischen auf dem Heap + alloziierten, verschiebbaren Sammlungen und Sammlungen mit fester + Kapazität wählen. +], +ja: [ + ヒープに割り当てられる再配置可能なコレクションと固定容量のコレクションとを選定する時は、次のことに留意して下さい。 +], +zh: [ + 当在堆分配的可重定位的集合和固定容量的集合间进行选择的时候,记住这些内容。 +])) + +=== #tr(( + en: [Out Of Memory and error handling], + de: [„Out of Memory" und Fehlerbehandlung], + ja: [メモリ不足とエラー処理], + zh: [内存溢出和错误处理], +)) + +#tr(( +en: [ + With heap allocations Out Of Memory is always a possibility and can + occur in any place where a collection may need to grow: for example, all + `alloc::Vec.push` invocations can potentially generate an OOM condition. + Thus some operations can _implicitly_ fail. Some `alloc` + collections expose `try_reserve` methods that let you check for + potential OOM conditions when growing the collection but you need be + proactive about using them. +], +de: [ + Bei Heap-Allokationen ist ein „Out of Memory" (OOM) -- also ein + Speichermangel -- immer möglich; er kann überall dort auftreten, wo eine + Collection wachsen muss: So können beispielsweise alle Aufrufe von + `alloc::Vec.push` potenziell zu einer OOM-Situation führen. Folglich + können manche Operationen _implizit_ fehlschlagen. Einige + `alloc`-Collections bieten `try_reserve`-Methoden an, mit denen sich + potenzielle OOM-Situationen beim Vergrößern der Collection überprüfen + lassen; man muss diese Methoden jedoch aktiv einsetzen. +], +ja: [ + ヒープアロケーションでは、メモリ不足は常に発生する可能性があり、コレクションが拡大する場所であれば、どこでも発生する可能性があります。 + 例えば、全ての`alloc::Vec.push`呼び出しは、OOM状態を引き起こす可能性があります。 + そのため、一部の操作は_暗黙的に_失敗する可能性があります。 + 一部の`alloc`コレクションは`try_reserve`メソッドを提供しています。 + このメソッドにより、コレクションを拡大する時にOOM状態が発生するかどうかを確認できますが、先を見越して使用する必要があります。 +], +zh: [ + 使用堆分配,内存溢出总是有可能出现的且会发生在任何一个集合需要增长的地方: + 比如,所有的 `alloc::Vec.push` 调用会潜在地产生一个OOM(Out of + Memory)条件。因此一些操作可能会_隐式地_失败。一些`alloc`集合暴露了`try_reserve`方法,可以当增加集合时让你检查潜在的OOM条件,但是你需要主动地使用它们。 +])) + +#tr(( +en: [ + If you exclusively use `heapless` collections and you don't use a memory + allocator for anything else then an OOM condition is impossible. + Instead, you'll have to deal with collections running out of capacity on + a case by case basis. That is you'll have deal with _all_ the + `Result`s returned by methods like `Vec.push`. +], +de: [ + Wenn man ausschließlich `heapless`-Collections verwendet und keinen + Speicher-Allocator für andere Zwecke nutzt, ist eine OOM-Situation + ausgeschlossen. Stattdessen muss man im Einzelfall damit umgehen, wenn + die Kapazität einer Collection erschöpft ist. Das bedeutet, man muss + _alle_ `Result`-Werte behandeln, die von Methoden wie `Vec.push` + zurückgegeben werden. +], +ja: [ + `heapless`コレクションだけを使っていて、メモリアロケータを使用しないのであれば、OOM状態は発生しません。 + その代わりに、コレクションの容量オーバーを個別に処理しなければなりません。 + つまり、`Vec.push`のようなメソッドが返す全ての`Result`を処理することになります。 +], +zh: [ + 如果你只使用`heapless`集合,而不使用内存分配器,那么一个OOM条件不可能出现。反而,你必须逐个处理容量不足的集合。也就是必须处理_所有_的`Result`,`Result`由像是`Vec.push`这样的方法返回的。 +])) + +#tr(( +en: [ + OOM failures can be harder to debug than say `unwrap`-ing on all + `Result`s returned by `heapless::Vec.push` because the observed location + of failure may _not_ match with the location of the cause of the + problem. For example, even `vec.reserve(1)` can trigger an OOM if the + allocator is nearly exhausted because some other collection was leaking + memory (memory leaks are possible in safe Rust). +], +de: [ + Fehler durch Speichermangel (OOM) können schwieriger zu debuggen sein + als etwa das Aufrufen von `unwrap` auf allen `Result`-Werten von + `heapless::Vec.push`, da die Stelle, an der der Fehler sichtbar wird, + nicht unbedingt mit der Ursache des Problems übereinstimmen muss. So + kann beispielsweise selbst `vec.reserve(1)` ein OOM auslösen, wenn der + Allocator nahezu erschöpft ist, weil eine andere Collection Speicher + verloren hat (Speicherlecks sind auch in „Safe Rust" möglich). +], +ja: [ + OOM障害は、`heapless::Vec.push`が返す全ての`Result`を`unwrap`するより、デバッグが難しいでしょう。 + なぜなら、障害が発生した場所は、問題の原因となる場所と一致_しない_可能性があるからです。 + 例えば、他のコレクションがメモリリークを起こしているせいでアロケータが枯渇しそうな場合、`vec.reserve(1)`がOOMを発生させる可能性があります + (メモリリークは安全なRustでも発生します)。 +], +zh: [ + 与在所有由`heapless::Vec.push`返回的`Result`上调用`unwrap`相比,OOM错误更难调试,因为错误被发现的位置可能与导致问题的位置_不_一致。比如,甚至如果分配器接近消耗完`vec.reserve(1)`都能触发一个OOM,因为一些其它的集合正在泄露内存(内存泄露在安全的Rust是会发生的)。 +])) + +=== #tr(( + en: [Memory usage], + de: [Speichernutzung], + ja: [メモリ使用量], + zh: [内存使用], +)) + +#tr(( +en: [ + Reasoning about memory usage of heap allocated collections is hard + because the capacity of long lived collections can change at runtime. + Some operations may implicitly reallocate the collection increasing its + memory usage, and some collections expose methods like `shrink_to_fit` + that can potentially reduce the memory used by the collection -- + ultimately, it's up to the allocator to decide whether to actually + shrink the memory allocation or not. Additionally, the allocator may + have to deal with memory fragmentation which can increase the + _apparent_ memory usage. +], +de: [ + Die Einschätzung des Speicherverbrauchs von auf dem Heap allozierten + Collections ist schwierig, da sich die Kapazität langlebiger Collections + zur Laufzeit ändern kann. Manche Operationen führen möglicherweise zu + einer impliziten Neuzuweisung des Speichers, wodurch der Speicherbedarf + steigt; andere Collections bieten Methoden wie `shrink_to_fit` an, die + den genutzten Speicher potenziell verringern können -- wobei letztlich + der Allocator entscheidet, ob die Speicherzuweisung tatsächlich + reduziert wird. Zudem muss der Allocator unter Umständen mit + Speicherfragmentierung umgehen, was den _scheinbaren_ + Speicherverbrauch erhöhen kann. +], +ja: [ + 長期間使われるコレクションの容量は、実行時に変わる可能性があるため、ヒープ割り当てされたコレクションのメモリ使用量を推測することは難しいです。 + 一部の操作は、暗黙的にコレクションを再割り当てし、メモリ使用量が増加します。 + 一部のコレクションは、`shrink_to_fit`のようなメソッドを持っており、コレクションが使用しているメモリを減らすこともあります。 + 最終的に、実際にメモリアロケーションを縮小するかどうかは、アロケータ次第です。 + さらに、アロケータは、メモリフラグメンテーションを扱う必要があります。このことは_見かけ上の_メモリ使用量を増やす可能性があります。 +], +zh: [ + 推理堆分配集合的内存使用是很难的因为长期使用的集合的大小会在运行时改变。一些操作可能隐式地重分配集合,增加了它的内存使用,一些集合暴露的方法,像是`shrink_to_fit`,会潜在地减少集合使用的内存 -- + 最终,它由分配器去决定是否确定减小内存的分配或者不。另外,分配器可能不得不处理内存碎片,它会_明显_增加内存的使用。 +])) + +#tr(( +en: [ + On the other hand if you exclusively use fixed capacity collections, + store most of them in `static` variables and set a maximum size for the + call stack then the linker will detect if you try to use more memory + than what's physically available. +], +de: [ + Verwendet man hingegen ausschließlich Collections mit fester Kapazität, + legt die meisten davon in `static`-Variablen ab und legt eine maximale + Größe für den Aufruf-Stack (Call Stack) fest, so erkennt der Linker, + wenn mehr Speicher beansprucht wird, als physisch verfügbar ist. +], +ja: [ + 一方で、固定容量のコレクションだけを使用して、そのほとんどを`static`変数に格納し、コールスタックの最大サイズを設定すると、 + リンカは、物理的に利用可能なメモリより大きな容量を使おうとしたかどうか検出します。 +], +zh: [ + 另一方面,如果你只使用固定容量的集合,请把大多数的数据保存在`static`变量中,并为调用栈设置一个最大尺寸,随后如果你尝试使用大于可用的物理内存的内存大小时,链接器会发现它。 +])) + +#let ln_z_emit = link("https://doc.rust-lang.org/beta/unstable-book/compiler-flags/emit-stack-sizes.html")[`-Z emit-stack-sizes`] +#let ln_stack_sizes = link("https://crates.io/crates/stack-sizes")[`stack-sizes`] +#tr(( +en: [ + Furthermore, fixed capacity collections allocated on the stack will be + reported by #ln_z_emit + flag which means that tools that analyze stack usage + (like #ln_stack_sizes) will include them in their analysis. +], +de: [ + Darüber hinaus werden auf dem Stack alloziierte Collections mit fester + Kapazität durch das Flag #ln_z_emit + erfasst; das bedeutet, dass Werkzeuge zur Analyse der Stack-Nutzung + (wie #ln_stack_sizes) diese in ihre Auswertung einbeziehen. +], +ja: [ + その上、スタックに割り当てられた固定容量のコレクションは、#ln_z_emit;フラグによって報告されます。 + このフラグは、(#ln_stack_sizes;のような)スタック使用量を解析するツールがスタック使用量を解析することを意味します。 +], +zh: [ + 另外,在栈上分配的固定容量的集合可以通过#ln_z_emit;标识来报告,其意味着用来分析栈使用的工具(像是#ln_stack_sizes)将会把在栈上分配的集合包含进它们的分析中。 +])) + +#tr(( +en: [ + However, fixed capacity collections can _not_ be shrunk which can + result in lower load factors (the ratio between the size of the + collection and its capacity) than what relocatable collections can achieve. +], +de: [ + Sammlungen mit fester Kapazität können jedoch _nicht_ verkleinert + werden, was zu niedrigeren Auslastungsgraden (dem Verhältnis zwischen + der Größe der Sammlung und ihrer Kapazität) führen kann, als sie bei + Sammlungen mit veränderbarer Kapazität möglich sind. +], +ja: [ + しかし、固定容量のコレクションは、縮小することが_できません_。 + 再配置可能なコレクションよりも負荷率(コレクションのサイズとその容量の比率)が低くなる可能性があります。 +], +zh: [ + 然而,固定容量的集合_不_能被减少,与可重定位集合所能达到的负载系数(集合的大小和它的容量之间的比值)相比,它能产生更低的负载系数。 +])) + +=== #tr(( + en: [Worst Case Execution Time (WCET)], + de: [Maximale Ausführungszeit (WCET)], + ja: [最悪実行時間(WCET; Worst Case Execution Time)], + zh: [最坏执行时间 (WCET)], +)) + +#tr(( +en: [ + If you are building time sensitive applications or hard real time + applications then you care, maybe a lot, about the worst case execution + time of the different parts of your program. +], +de: [ + Wenn Sie zeitkritische oder Echtzeitanwendungen entwickeln, ist Ihnen + die Worst-Case-Ausführungszeit (WCET) der verschiedenen Programmteile + wahrscheinlich sehr wichtig. +], +ja: [ + 時間制約のあるアプリケーションやハードリアルタイムアプリケーションを作成している場合、 + プログラムの様々な部分で最悪実行時間が気になるでしょう。 +], +zh: [ + 如果你正在搭建时间敏感型应用或者硬实时应用,那么你可能更关心你程序的不同部分的最坏执行时间。 +])) + +#tr(( +en: [ + The `alloc` collections can reallocate so the WCET of operations that + may grow the collection will also include the time it takes to + reallocate the collection, which itself depends on the _runtime_ + capacity of the collection. This makes it hard to determine the WCET of, + for example, the `alloc::Vec.push` operation as it depends on both the + allocator being used and its runtime capacity. +], +de: [ + Da `alloc`-Collections Speicher neu allokieren können, umfasst die WCET + von Operationen, die die Collection vergrößern, auch die Zeit für die + Neuallokation. Diese hängt wiederum von der _Laufzeitkapazität_ der + Collection ab. Daher ist es schwierig, die WCET beispielsweise der + Operation `alloc::Vec.push` zu bestimmen, da sie sowohl vom verwendeten + Allokator als auch von dessen Laufzeitkapazität abhängt. +], +ja: [ + `alloc`コレクションは再割り当てする可能性があるため、コレクションが拡大する操作の最悪実行時間は、 + コレクションが再割り当てされるのにかかる時間も含みます。 + コレクションが再割り当てされるかどうかは、_実行時_のコレクションの容量に依存します。 + このことは、`alloc::Vec.push`といった操作の最悪実行時間の決定を難しくします。 + この操作の最悪実行時間は、使用するアロケータとコレクションの実行時容量との両方に依存するためです。 +], +zh: [ + `alloc`集合能重分配,所以操作的WCET可能会增加,集合也将包括它用来重分配集合所需的时间,它取决于集合的_运行时_容量。这使得它更难去决定操作,比如`alloc::Vec.push`,的WCET,因为它依赖被使用的分配器和它的运行时容量。 +])) + +#tr(( +en: [ + On the other hand fixed capacity collections never reallocate so all + operations have a predictable execution time. For example, + `heapless::Vec.push` executes in constant time. +], +de: [ + Collections mit fester Kapazität hingegen allokieren nie Speicher neu, + sodass alle Operationen eine vorhersehbare Ausführungszeit haben. + Beispielsweise wird `heapless::Vec.push` in konstanter Zeit ausgeführt. +], +ja: [ + 一方、固定容量のコレクションは再割り当てが発生しないため、全ての操作の実行時間が予測可能です。 + 例えば、`heapless::Vec.push`は定数時間で実行します。 + +], +zh: [ + 另一方面固定容量的集合不会重分配,因此所有的操作有个可预期的执行时间。比如,`heapless::Vec.push`以固定时间执行。 +])) + +=== #tr(( + en: [Ease of use], + de: [Benutzerfreundlichkeit], + ja: [使いやすさ], + zh: [易用性], +)) + +#tr(( +en: [ + `alloc` requires setting up a global allocator whereas `heapless` does + not. However, `heapless` requires you to pick the capacity of each + collection that you instantiate. +], +de: [ + Für `alloc` muss ein globaler Allocator eingerichtet werden, für + `heapless` hingegen nicht. Allerdings erfordert `heapless`, dass man bei + der Instanziierung jeder Collection deren Kapazität festlegt. +], +ja: [ + `alloc`はグローバルアロケータの準備が必要ですが、`heapless`はそうではありません。 + しかし、`heapless`は、インスタンスを作成する各コレクションの容量を指定する必要があります。 +], +zh: [ + `alloc`要求配置一个全局分配器而`heapless`不需要。然而,`heapless`要求你去选择你要实例化的每一个集合的容量。 +])) + +#tr(( +en: [ + The `alloc` API will be familiar to virtually every Rust developer. The + `heapless` API tries to closely mimic the `alloc` API but it will never + be exactly the same due to its explicit error handling -- some developers + may feel the explicit error handling is excessive or too cumbersome. +], +de: [ + Die `alloc`-API dürfte so gut wie jedem Rust-Entwickler vertraut sein. + Die `heapless`-API orientiert sich zwar eng an der `alloc`-API, + unterscheidet sich jedoch aufgrund der expliziten Fehlerbehandlung -- + manche Entwickler empfinden diese explizite Fehlerbehandlung womöglich + als übertrieben oder zu umständlich. +], +ja: [ + `alloc` APIは、事実上、全てのRust開発者がなじみのあるものです。 + `heapless` APIは、`alloc` + APIに似せてはいますが、明示的なエラー処理のため、全く同じにはなりません。 + 一部の開発者はこの明示的なエラー処理を、度が過ぎていたり、面倒すぎる、と感じるかもしれません。 +], +zh: [ + `alloc` API几乎为每一个Rust开发者所熟知。`heapless` API尝试模仿`alloc` + API,但是因为`heapless`的显式错误处理,它们不可能会一模一样 -- + 一些开发者可能会觉得显式的错误处理过多或太麻烦。 +])) diff --git a/typ/concurrency/index.typ b/typ/concurrency/index.typ new file mode 100644 index 00000000..0fa7f17c --- /dev/null +++ b/typ/concurrency/index.typ @@ -0,0 +1,1945 @@ +#import "../config.typ": * + +#h1((en: [Concurrency], + de: [Nebenläufigkeit], + ja: [並行性], + zh: [并发], +)) + + +#tr(( +en: [ + Concurrency happens whenever different parts of your program might + execute at different times or out of order. In an embedded context, this + includes: + - interrupt handlers, which run whenever the associated interrupt + happens, + - various forms of multithreading, where your microprocessor regularly + swaps between parts of your program, + - and in some systems, multiple-core microprocessors, where each core + can be independently running a different part of your program at the + same time. +], +de: [ + Nebenläufigkeit tritt immer dann auf, wenn verschiedene Teile Ihres + Programms zu unterschiedlichen Zeiten oder in einer anderen als der + vorgesehenen Reihenfolge ausgeführt werden können. Im Kontext + eingebetteter Systeme umfasst dies: + - Interrupt-Handler, die immer dann ausgeführt werden, wenn der + zugehörige Interrupt auftritt, + - verschiedene Formen des Multithreadings, bei denen Ihr Mikroprozessor + regelmäßig zwischen Teilen Ihres Programms wechselt, + - und in einigen Systemen Mehrkern-Mikroprozessoren, bei denen jeder + Kern gleichzeitig und unabhängig voneinander einen anderen Teil Ihres + Programms ausführen kann. +], +ja: [ + プログラムの異なる部分が様々なタイミングで実行されたり、アウトオブオーダに実行されると、並行性が発生します。 + 組込みでは、次のものが該当します。 + - 割り込みが発生するたびに実行される割り込みハンドラ + - マイクロプロセッサがプログラムの一部を定期的にスワップする様々な形式のマルチスレッド + - システムによっては、各コアがプログラムの異なる部分を同時に独立して実行できるマルチコアマイクロプロセッサ +], +zh: [ + 当程序的不同部分有可能会在不同的时刻被执行或者不按顺序地被执行时,那并发就出现了。在一个嵌入式环境中,这包括: + - 中断处理函数,一旦相关的中断发生时,中断处理函数就会运行, + - 不同的多线程形式,在这块,微处理器通常会在程序的不同部分间进行切换, + - 在一些多核微处理器系统中,每个核可以同时独立地运行程序的不同部分。 +])) + +#tr(( +en: [ + Since many embedded programs need to deal with interrupts, concurrency + will usually come up sooner or later, and it's also where many subtle + and difficult bugs can occur. Luckily, Rust provides a number of + abstractions and safety guarantees to help us write correct code. +], +de: [ + Da viele eingebettete Programme mit Interrupts umgehen müssen, spielt + Nebenläufigkeit früher oder später meist eine Rolle -- und genau hier + können auch viele schwer zu findende und komplexe Fehler auftreten. + Glücklicherweise bietet Rust eine Reihe von Abstraktionen und + Sicherheitsgarantien, die uns dabei helfen, korrekten Code zu schreiben. +], +ja: [ + 多くの組込みプログラムは割り込みを処理する必要があるため、早かれ遅かれ、並行性は発生します。 + 割り込みは、捉えにくく、難しいバグが数多く発生し得る場所でもあります。 + 幸運なことに、Rustは正しいコードを書く助けになる抽象化と安全性保証とを、いくつか提供しています。 +], +zh: [ + 因为许多嵌入式程序需要处理中断,因此并发迟早会出现,这也是许多微妙和困难的bugs会出现的地方。幸运地是,Rust提供了许多抽象和安全保障去帮助我们写正确的代码。 +])) + +== #tr(( + en: [No Concurrency], + de: [Keine Nebenläufigkeit], + ja: [並行性なし], + zh: [没有并发], +)) + +#tr(( +en: [ + The simplest concurrency for an embedded program is no concurrency: your + software consists of a single main loop which just keeps running, and + there are no interrupts at all. Sometimes this is perfectly suited to + the problem at hand! Typically your loop will read some inputs, perform + some processing, and write some outputs. +], +de: [ + Die einfachste Form der Nebenläufigkeit für ein Embedded-Programm ist + der Verzicht darauf: Die Software besteht aus einer einzigen + Hauptschleife, die kontinuierlich durchlaufen wird, und es kommen + keinerlei Interrupts zum Einsatz. Manchmal ist genau dieser Ansatz für + die vorliegende Aufgabenstellung ideal! Typischerweise liest die + Schleife Eingabewerte ein, führt Berechnungen oder Verarbeitungen durch + und gibt Ergebnisse aus. +], +ja: [ + 組込みプログラムの最も簡単な並行性は、並行性がないことです。ソフトウェアは1つの動作し続けるメインループからなり、割り込みも発生しません。 + 時には、これが手元の問題の最適解かもしれません。 + 通常、ループは何か入力を受け付け、何らかの処理を行い、何かを出力します。 +], +zh: [ + 对于一个嵌入式程序来说最简单的并发是没有并发: + 软件由一个保持运行的main循环组成,一点中断也没有。有时候这非常适合手边的问题! + 通常你的循环将会读取一些输入,执行一些处理,且写入一些输出。 +])) + +```rust +#[entry] +fn main() { + let peripherals = setup_peripherals(); + loop { + let inputs = read_inputs(&peripherals); + let outputs = process(inputs); + write_outputs(&peripherals, outputs); + } +} +``` + +#tr(( +en: [ + Since there's no concurrency, there's no need to worry about sharing + data between parts of your program or synchronising access to + peripherals. If you can get away with such a simple approach this can be + a great solution. +], +de: [ + Da keine Nebenläufigkeit vorliegt, müssen Sie sich keine Gedanken über + die gemeinsame Datennutzung zwischen verschiedenen Programmteilen oder + die Synchronisierung des Zugriffs auf Peripheriegeräte machen. Wenn ein + solch einfacher Ansatz ausreicht, kann dies eine hervorragende Lösung sein. +], +ja: [ + 並行性がないため、プログラム間でのデータ共有や、ペリフェラルへのアクセス同期に悩む必要はありません。 + このような単純なアプローチに逃れることができるのであれば、素晴らしい解決策かもしれません。 +], +zh: [ + 因为这里没有并发,因此不需要担心程序不同部分间的共享数据或者同步对外设的访问。如果可以使用一个简单的方法来解决问题,这种方法是个不错的选择。 +])) + +== #tr(( + en: [Global Mutable Data], + de: [Globale veränderliche Daten], + ja: [グローバルでミュータブルなデータ], + zh: [全局可变数据], +)) + +#tr(( +en: [ + Unlike non-embedded Rust, we will not usually have the luxury of + creating heap allocations and passing references to that data into a + newly-created thread. Instead, our interrupt handlers might be called at + any time and must know how to access whatever shared memory we are + using. At the lowest level, this means we must have _statically allocated_ + mutable memory, which both the interrupt handler and the main + code can refer to. +], +de: [ + Im Gegensatz zu Rust-Anwendungen außerhalb des Embedded-Bereichs haben + wir meist nicht den Luxus, Speicher auf dem Heap zu reservieren und + Referenzen auf diese Daten an einen neu erstellten Thread zu übergeben. + Stattdessen können unsere Interrupt-Handler jederzeit aufgerufen werden + und müssen wissen, wie sie auf den jeweils genutzten gemeinsamen + Speicher zugreifen können. Auf unterster Ebene bedeutet dies, dass wir + über _statisch reservierten_, veränderbaren Speicher verfügen + müssen, auf den sowohl der Interrupt-Handler als auch der + Hauptprogrammcode zugreifen können. +], +ja: [ + 組込みでないRustと異なり、通常、ヒープ領域を作成し、そのデータへの参照を新しく作成したスレッドに渡す、というような贅沢はできません。 + 代わりに、割り込みハンドラはいつでも呼び出される可能性があり、使用する共有メモリにアクセスする方法を知っていなければなりません。 + 最も低いレベルでは、 _静的に割り当てられた_ + ミュータブルなメモリを持つ必要があることを意味します。 + このメモリは、割り込みハンドラとメインコードの両方が参照できます。 +], +zh: [ + 不像非嵌入式Rust,我们通常不会奢侈地在堆上分配数据,并将对该数据的引用传递到新创建的线程中。相反,我们的中断处理函数随时可能被调用,且必须知道如何访问我们正在使用的共享内存。从最底层看来,这意味着我们必须有 + _静态分配的_ 可变的内存,中断处理函数和main代码都可以引用这块内存。 +])) + +#let ln_staticmut = link("https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable")[`static mut`] +#tr(( +en: [ + In Rust, such #ln_staticmut + variables are always unsafe to read or write, because without taking + special care, you might trigger a race condition, where your access to + the variable is interrupted halfway through by an interrupt which also + accesses that variable. +], +de: [ + In Rust ist der Lese- oder Schreibzugriff auf solche + #ln_staticmut;-Variablen + stets als `unsafe` (unsicher) eingestuft. Ohne besondere + Vorsichtsmaßnahmen könnte es nämlich zu einer sogenannten Race Condition + (Wettlaufsituation) kommen: Der Zugriff auf die Variable wird mitten im + Vorgang durch einen Interrupt unterbrochen, der seinerseits ebenfalls + auf diese Variable zugreift. +], +ja: [ + Rustでは、このような#ln_staticmut;変数への読み書きは、常にアンセーフです。 + 特別な注意を払わないと、レースコンディションを引き起こす可能性があります。 + つまり、その変数へのアクセスが、さらにその変数にアクセスする割り込みによって、中断されるということです。 +], +zh: [ + 在Rust中,#ln_staticmut;这样的变量读取或者写入总是unsafe的,因为不特别关注它们的话,可能会触发一个竞态条件,对变量的访问在中途就被一个也访问那个变量的中断打断了。 +])) + +#tr(( +en: [ + For an example of how this behaviour can cause subtle errors in your + code, consider an embedded program which counts rising edges of some + input signal in each one-second period (a frequency counter): +], +de: [ + Um zu veranschaulichen, wie dieses Verhalten subtile Fehler in Ihrem + Code verursachen kann, betrachten Sie ein eingebettetes Programm, das + die steigenden Flanken eines Eingangssignals innerhalb jedes + Ein-Sekunden-Intervalls zählt (einen Frequenzzähler): +], +ja: [ + この動作によって、コード内に分かりにくいエラーが発生する可能性があります。 + 例えば、1秒毎に入力信号の立ち上がりエッジをカウントする組込みプログラム(周波数カウンタ)を考えてみましょう。 +], +zh: [ + 为了举例这种行为如何在代码中导致了微妙的错误,思考一个嵌入式程序,这个程序在每一秒的周期内计数一些输入信号的上升沿(一个频率计数器): +])) + +#raw(block: true, lang: "rust", +"static mut COUNTER: u32 = 0; + +#[entry] +fn main() -> ! { + set_timer_1hz(); + let mut last_state = false; + loop { + let state = read_signal_level(); + if state && !last_state { + // " + ts(( + en: "DANGER - Not actually safe! Could cause data races.", + de: "GEFAHR – Nicht wirklich sicher! Koennte zu Datenwettlaeufen + // fuehren.", + ja: "危険。実際に安全ではありません。データ競合を引き起こす可能性があります。", + zh: "危险 - 实际不安全! 可能导致数据竞争。", + )) + " + unsafe { COUNTER += 1 }; + } + last_state = state; + } +} + +#[interrupt] +fn timer() { + unsafe { COUNTER = 0; } +} +") + +#tr(( +en: [ + Each second, the timer interrupt sets the counter back to 0. Meanwhile, + the main loop continually measures the signal, and incremements the + counter when it sees a change from low to high. We've had to use + `unsafe` to access `COUNTER`, as it's `static mut`, and that means we're + promising the compiler we won't cause any undefined behaviour. Can you + spot the race condition? The increment on `COUNTER` is _not_ + guaranteed to be atomic --- in fact, on most embedded platforms, it will + be split into a load, then the increment, then a store. If the interrupt + fired after the load but before the store, the reset back to 0 would be + ignored after the interrupt returns --- and we would count twice as many + transitions for that period. +], +de: [ + Sekündlich setzt der Timer-Interrupt den Zähler auf 0 zurück. + Währenddessen misst die Hauptschleife kontinuierlich das Signal und + erhöht den Zähler, sobald ein Wechsel von „Low" auf „High" erkannt wird. + Wir mussten das Schlüsselwort `unsafe` verwenden, um auf `COUNTER` + zuzugreifen, da es als `static mut` deklariert ist; damit versichern wir + dem Compiler, dass wir kein undefiniertes Verhalten verursachen. + Erkennst du die Race Condition? Die Inkrementierung von `COUNTER` ist + _nicht_ garantiert atomar -- tatsächlich wird sie auf den meisten + Embedded-Plattformen in die Schritte Laden, Inkrementieren und Speichern + aufgeteilt. Würde der Interrupt nach dem Laden, aber vor dem Speichern + ausgelöst, ginge das Zurücksetzen auf 0 nach der Rückkehr aus dem + Interrupt verloren -- und wir würden für diesen Zeitraum doppelt so + viele Signalwechsel zählen. +], +ja: [ + 毎秒、タイマ割り込みはカウンタを0に戻します。同時に、メインループは信号を継続的に測定し、信号がローからハイに変わった時にカウンタをインクリメントします。 + `static mut`な`COUNTER`にアクセスするためには、`unsafe`を使う必要があります。 + これは、未定義動作を引き起こさないことを、コンパイラに約束するということです。 + レースコンディションがどこにあるかわかりますか? + `COUNTER`のインクリメントは、アトミックであることが保証されて + _いません_ 。 + 実際、ほとんどの組込みプラットフォームにおいて、この操作は、ロードし、インクリメントし、ストアする、という動作に分割されます。 + 割り込みがロードの後からストアの前に発生した場合、0に戻すリセットは、割り込みから復帰した後に無視されます。 + そして、その期間では、2倍の遷移をカウントすることになります。 +], +zh: [ + 每秒计时器中断会把计数器设置回0。这期间,main循环连续地测量信号,且当看到从低电平到高电平的变化时,增加计数器的值。因为它是`static mut`的,我们不得不使用`unsafe`去访问`COUNTER`,意思是我们向编译器保证我们的操作不会导致任何未定义的行为。你能发现竞态条件吗?`COUNTER`上的增加并不一定是原子的 - + 事实上,在大多数嵌入式平台上,它将被分开成一个读取操作,然后是增加,然后是写回。如果中断在计数器被读取之后但是在被写回之前被激活,在中断返回后,重置回0的操作会被忽略掉 - 那期间,我们会算出两倍的转换次数。 +])) + +== #tr(( + en: [Critical Sections], + de: [Kritische Abschnitte], + ja: [クリティカルセクション], + zh: [临界区(Critical Sections)], +)) + +#tr(( +en: [ + So, what can we do about data races? A simple approach is to use + _critical sections_, a context where interrupts are disabled. By + wrapping the access to `COUNTER` in `main` in a critical section, we can + be sure the timer interrupt will not fire until we're finished + incrementing `COUNTER`: +], +de: [ + Was können wir also gegen Data Races unternehmen? Ein einfacher Ansatz + ist die Verwendung von _kritischen Abschnitten_ -- also Bereichen, + in denen Interrupts deaktiviert sind. Indem wir den Zugriff auf + `COUNTER` in der Funktion `main` in einen kritischen Abschnitt + einbetten, stellen wir sicher, dass der Timer-Interrupt erst ausgelöst + wird, nachdem wir das Inkrementieren von `COUNTER` abgeschlossen haben: +], +ja: [ + それでは、データ競合についてどうすれば良いのでしょうか。 + 単純な方法は、割り込みが無効なコンテキストである + _クリティカルセクション_ を使うことです。 + `main`中の`COUNTER`へのアクセスを、クリティカルセクションでラッピングします。 + そうすることで、`COUNTER`のインクリメントが完了するまで、タイマ割り込みが発生しないようにできます。 +], +zh: [ + 因此,关于数据竞争可以做些什么?一个简单的方法是使用 + _临界区(critical sections)_ + ,在临界区的上下文中中断被关闭了。通过把对`main`中的`COUNTER`访问封装进一个临界区,我们能确保计时器中断将不会激活,直到我们完成了增加`COUNTER`的操作: +])) + +#raw(block: true, lang: "rust", +"static mut COUNTER: u32 = 0; + +#[entry] +fn main() -> ! { + set_timer_1hz(); + let mut last_state = false; + loop { + let state = read_signal_level(); + if state && !last_state { + // " + ts(( + en: "New critical section ensures synchronised access to COUNTER", + de: "Ein neuer kritischer Abschnitt gewaehrleistet den + // synchronisierten Zugriff auf COUNTER.", + ja: "新しいクリティカルセクションは、COUNTERへの同期アクセスを保証します", + zh: "新的临界区确保对COUNTER的同步访问", + )) + " + cortex_m::interrupt::free(|_| { + unsafe { COUNTER += 1 }; + }); + } + last_state = state; + } +} + +#[interrupt] +fn timer() { + unsafe { COUNTER = 0; } +} +") + +#tr(( +en: [ + In this example, we use `cortex_m::interrupt::free`, but other platforms + will have similar mechanisms for executing code in a critical section. + This is also the same as disabling interrupts, running some code, and + then re-enabling interrupts. +], +de: [ + In diesem Beispiel verwenden wir `cortex_m::interrupt::free`, doch auch + andere Plattformen verfügen über ähnliche Mechanismen, um Code in einem + kritischen Abschnitt auszuführen. Dies entspricht im Grunde dem + Deaktivieren von Interrupts, der Ausführung von Code und dem + anschließenden erneuten Aktivieren der Interrupts. +], +ja: [ + この例では`cortex_m::interrupt::free`を使いました。他のプラットフォームでもクリティカルセクションのコードを実行するための、類似の方法があります。 + これは、割り込みを無効にして、コードを実行し、再び割り込みを有効にすることと同じです。 +], +zh: [ + 在这个例子里,我们使用 + `cortex_m::interrupt::free`,但是其它平台将会有更简单的机制在一个临界区中执行代码。它们都有一样的逻辑,关闭中断,运行一些代码,然后重新使能中断。 +])) + +#tr(( +en: [ + Note we didn't need to put a critical section inside the timer + interrupt, for two reasons: + - Writing 0 to `COUNTER` can't be affected by a race since we don't read it + - It will never be interrupted by the `main` thread anyway +], +de: [ + Beachten Sie, dass wir innerhalb des Timer-Interrupts keinen kritischen + Abschnitt benötigten; dies hat zwei Gründe: + - Das Schreiben von 0 in `COUNTER` kann nicht von einer Race-Condition + betroffen sein, da wir den Wert nicht lesen. + - Es wird ohnehin niemals vom `main`-Thread unterbrochen werden. +], +ja: [ + タイマ割り込み内クリティカルセクションを置く必要がないことに注意して下さい。これは次の2つの理由からです。 + - 読み込みをしないため、`COUNTER`に0を書くことは、競合の影響を受けません + - いずれにせよ、`main`スレッドによって割り込まれることはありえません +], +zh: [ + 注意,有两个理由,不需要把一个临界区放进计时器中断中: + - 向`COUNTER`写入0不会被一个竞争影响,因为我们不需要读取它 + - 无论如何,它永远不会被`main`线程中断 +])) + +#tr(( +en: [ + If `COUNTER` was being shared by multiple interrupt handlers that might + _preempt_ each other, then each one might require a critical + section as well. +], +de: [ + Wenn `COUNTER` von mehreren Interrupt-Handlern gemeinsam genutzt würde, + die sich gegenseitig _unterbrechen_ könnten, müsste jeder von ihnen + ebenfalls einen kritischen Abschnitt verwenden. +], +ja: [ + `COUNTER`がお互いに _プリエンプション_ + する複数の割り込みハンドラから共有される場合、 + それぞれにクリティカルセクションが必要になるでしょう。 +], +zh: [ + 如果`COUNTER`被多个可能相互 _抢占_ + 的中断处理函数共享,那么每一个也需要一个临界区。 +])) + +#tr(( +en: [ + This solves our immediate problem, but we're still left writing a lot of + unsafe code which we need to carefully reason about, and we might be + using critical sections needlessly. Since each critical section + temporarily pauses interrupt processing, there is an associated cost of + some extra code size and higher interrupt latency and jitter (interrupts + may take longer to be processed, and the time until they are processed + will be more variable). Whether this is a problem depends on your + system, but in general, we'd like to avoid it. +], +de: [ + Dies löst zwar unser unmittelbares Problem, doch wir müssen weiterhin + viel unsicheren Code schreiben, dessen Verhalten wir sorgfältig + analysieren müssen; zudem setzen wir möglicherweise unnötigerweise + kritische Abschnitte ein. Da jeder kritische Abschnitt die + Interrupt-Verarbeitung vorübergehend aussetzt, entstehen Kosten in Form + von zusätzlichem Codeumfang sowie höherer Interrupt-Latenz und stärkerem + Jitter (die Verarbeitung von Interrupts kann länger dauern, und die Zeit + bis zur Verarbeitung schwankt stärker). Ob dies ein Problem darstellt, + hängt vom jeweiligen System ab, doch im Allgemeinen sollten wir dies + vermeiden. +], +ja: [ + クリティカルセクションは、当面の問題を解決しますが、慎重に検討しなければならない`unsafe`なコードをまだたくさん書いています。 + その結果、必要以上にクリティカルセクションを使用することになり、オーバーヘッドと割り込みレイテンシおよびジッタをもたらします。 +], +zh: [ + 这解决了我们眼前的问题,但是我们仍然要编写许多unsafe的代码,我们需要仔细推敲这些代码,有些我们可能不需要使用临界区。因为每个临界区暂时暂停了中断处理,就会带来一些相关的成本,一些额外的代码大小,更高的中断延迟和抖动(中断可能花费很长时间去处理,等待被处理的时间变化非常大)。这是否是个问题取决于你的系统,但是通常,我们想要避免它。 +])) + +#tr(( +en: [ + It's worth noting that while a critical section guarantees no interrupts + will fire, it does not provide an exclusivity guarantee on multi-core + systems! The other core could be happily accessing the same memory as + your core, even without interrupts. You will need stronger + synchronisation primitives if you are using multiple cores. +], +de: [ + Es ist wichtig zu beachten: Auch wenn ein kritischer Abschnitt + garantiert, dass keine Interrupts ausgelöst werden, bietet er auf + Mehrkernsystemen keine Exklusivitätsgarantie! Der andere Rechenkern + könnte -- selbst ohne Interrupts -- problemlos auf denselben Speicher + zugreifen wie Ihr eigener Kern. Wenn Sie mehrere Rechenkerne nutzen, + benötigen Sie daher leistungsfähigere Synchronisationsmechanismen. +], +ja: [ + 注目すべき点は、クリティカルセクションでは、割り込みが発生しないことが保証されますが、 + マルチコアシステムでは、排他性の保証は提供されないことです。 + 他のコアは、割り込みでなくても、とあるコアと同じメモリにアクセスできてしまいます。 + マルチコアを使う場合、より強力な同期プリミティブが必要になります。 +], +zh: [ + 值得注意的是,虽然一个临界区保障了不会发生中断,但是它在多核系统上不提供一个排他性保证(exclusivity + guarantee)!其它核可能很开心地访问与你的核一样的内存区域,即使没有中断。如果你正在使用多核,你将需要更强的同步原语(synchronisation primitives)。 +])) + +== #tr(( + en: [Atomic Access], + de: [Atomarer Zugriff], + ja: [アトミックアクセス], + zh: [原子访问], +)) + +#tr(( +en: [ + On some platforms, special atomic instructions are available, which + provide guarantees about read-modify-write operations. Specifically for + Cortex-M: `thumbv6` (Cortex-M0, Cortex-M0+) only provide atomic load and + store instructions, while `thumbv7` (Cortex-M3 and above) provide full + Compare and Swap (CAS) instructions. These CAS instructions give an + alternative to the heavy-handed disabling of all interrupts: we can + attempt the increment, it will succeed most of the time, but if it was + interrupted it will automatically retry the entire increment operation. + These atomic operations are safe even across multiple cores. +], +de: [ + Auf einigen Plattformen stehen spezielle atomare Befehle zur Verfügung, + die Garantien für Lese-Modifizier-Schreib-Operationen + (Read-Modify-Write) bieten. Speziell für Cortex-M gilt: `thumbv6` + (Cortex-M0, Cortex-M0+) bietet lediglich atomare Lade- und + Speicherbefehle, während `thumbv7` (Cortex-M3 und höher) vollständige + „Compare-and-Swap"-Befehle (CAS) bereitstellt. Diese CAS-Befehle bieten + eine Alternative zur drastischen Maßnahme, sämtliche Interrupts zu + deaktivieren: Man kann versuchen, den Inkrementierungsvorgang + durchzuführen -- was meistens gelingt --, doch sollte eine Unterbrechung + auftreten, wird der gesamte Vorgang automatisch erneut versucht. Diese + atomaren Operationen sind auch in Mehrkernsystemen sicher. +], +ja: [ + プラットフォームによっては、アトミック命令が利用できます。アトミック命令は、リードモディファイライト操作の保証を提供します。 + 特にCortex-Mの場合、`thumbv6`(Cortex-M0)はアトミック命令を提供しませんが、`thumbv7`(Cortex-M3以上)は提供します。 + これらの命令は、全ての割り込みを無効化する手荒な方法の代替手段を提供します。 + インクリメントを試みる時、ほとんどの場合は成功しますが、割り込まれた場合はインクリメント操作全体を自動的にやり直します。 + このようなアトミック操作は、複数のコアにまたがっても安全です。 +], +zh: [ + 在一些平台上,可以使用特定的原子指令,它保障了读取-修改-写回操作。针对Cortex-M: + `thumbv6`\(Cortex-M0,Cortex-M0+)只提供原子读取和存取指令,而`thumv7`\(Cortex-M3及以上)提供完整的比较和交换(CAS)指令。这些CAS指令可以替代过重的禁用所有中断的方法: + 我们可以尝试执行加法操作,它在大多数情况下都会成功,但是如果它被中断了它将会自动重试完整的加法操作。这些原子操作甚至在多核间也是安全的。 +])) + +#raw(block: true, lang: "rust", +"use core::sync::atomic::{AtomicUsize, Ordering}; + +static COUNTER: AtomicUsize = AtomicUsize::new(0); + +#[entry] +fn main() -> ! { + set_timer_1hz(); + let mut last_state = false; + loop { + let state = read_signal_level(); + if state && !last_state { + // " + ts(( + en: "Use `fetch_add` to atomically add 1 to COUNTER", + de: "Verwenden Sie `fetch_add`, um 1 atomar zu COUNTER zu addieren.", + ja: "自動的にCOUNTERに1を加えるために`fetch_add`を使います", + zh: "使用 `fetch_add` 原子性地给 COUNTER 加一", + )) + " + COUNTER.fetch_add(1, Ordering::Relaxed); + } + last_state = state; + } +} + +#[interrupt] +fn timer() { + // " + ts(( + en: "Use `store` to write 0 directly to COUNTER", + de: "Verwenden Sie `store`, um 0 direkt in COUNTER zu schreiben.", + ja: "COUNTERに直接0を書くために`store`を使います", + zh: "使用 `store` 将 0 直接写入 COUNTER", + )) + " + COUNTER.store(0, Ordering::Relaxed) +} +") + +#tr(( +en: [ + This time `COUNTER` is a safe `static` variable. Thanks to the + `AtomicUsize` type `COUNTER` can be safely modified from both the + interrupt handler and the main thread without disabling interrupts. When + possible, this is a better solution --- but it may not be supported on + your platform. +], +de: [ + Diesmal ist `COUNTER` eine sichere `static`-Variable. Dank des Typs + `AtomicUsize` kann `COUNTER` sowohl vom Interrupt-Handler als auch vom + Hauptthread aus sicher geändert werden, ohne Interrupts zu deaktivieren. + Wenn möglich, ist dies die bessere Lösung -- wird aber möglicherweise + von Ihrer Plattform nicht unterstützt. +], +ja: [ + ここで、`COUNTER`は安全な`static`変数です。`AtomicUsize`のおかげで`COUNTER`の型は、割り込みを無効化することなく、 + 割り込みハンドラとメインスレッドの両方から安全に修正できます。 + 可能であれば、これはより良い解決方法です。しかし、あなたのプラットフォームではサポートされていないかもしれません。 +], +zh: [ + 这时,`COUNTER`是一个safe的`static`变量。多亏了`AtomicUsize`类型,不需要禁用中断,`COUNTER`能从中断处理函数和main线程被安全地修改。当可以这么做时,这是一个更好的解决方案 - 然而平台上可能不支持这么做。 +])) + +#let ln_ordering = link("https://doc.rust-lang.org/core/sync/atomic/enum.Ordering.html")[`Ordering`] +#tr(( +en: [ + A note on #ln_ordering: + this affects how the compiler and hardware may reorder instructions, and + also has consequences on cache visibility. Assuming that the target is a + single core platform `Relaxed` is sufficient and the most efficient + choice in this particular case. Stricter ordering will cause the + compiler to emit memory barriers around the atomic operations; depending + on what you're using atomics for you may or may not need this! The + precise details of the atomic model are complicated and best described + elsewhere. +], +de: [ + Hinweis zur #ln_ordering: + Diese beeinflusst, wie Compiler und Hardware Anweisungen neu anordnen, + und hat auch Auswirkungen auf die Cache-Sichtbarkeit. Bei einer + Einkernplattform ist die Option `Relaxed` ausreichend und in diesem Fall + die effizienteste Wahl. Eine strengere Befehlsreihenfolge führt dazu, + dass der Compiler Speicherbarrieren um die atomaren Operationen erzeugt. + Je nachdem, wofür Sie atomare Operationen verwenden, benötigen Sie dies + möglicherweise nicht. Die genauen Details des atomaren Modells sind + komplex und werden am besten an anderer Stelle beschrieben. +], +ja: [ + #link("https://doc.rust-lang.org/core/sync/atomic/enum.Ordering.html")[`Ordering`]の注釈:これは、コンパイラとハードウェアがどのように命令の順番を入れ替えるか、に影響を与えます。 + また、キャッシュの可視性にも影響します。ターゲットがシングルコアプラットフォームだと仮定すると、`Relaxed`で十分であり、このケースでは最も効率の良い選択です。 + より厳密なオーダリングでは、コンパイラはアトミック操作の前後にメモリバリアを発行します。 + 使用するアトミック操作によって、必要かもしれませんし、必要でないかもしれません! + アトミックモデルの正確な詳細は複雑であり、他の文書内でしっかりと説明されています。 +], +zh: [ + 关于#ln_ordering;的提醒: + 它可能影响编译器和硬件如何重新排序指令,也会影响缓存可见性。假设目标是个单核平台,在这个案例里`Relaxed`是充足的和最有效的选择。更严格的排序将导致编译器在原子操作周围产生内存屏障(Memory + Barriers);取决于你做什么原子操作,你可能需要或者不需要这个排序!原子模型的精确细节是复杂的,最好写在其它地方。 +])) + +#let url_atomics = "https://doc.rust-lang.org/nomicon/atomics.html" +#tr(( +en: [ + For more details on atomics and ordering, see the + #link(url_atomics)[nomicon]. +], +de: [ + Weitere Informationen zu atomaren Operationen und deren Reihenfolge + finden Sie im #link(url_atomics)[nomicon]. +], +ja: [ + 詳細は、#link(url_atomics)[ノミコン]のアトミックとオーダリングを参照して下さい。 +], +zh: [ + 关于原子操作和排序的更多细节,可以看这里#link(url_atomics)[nomicon]。 +])) + +== #tr(( + en: [Abstractions, Send, and Sync], + de: [Abstraktionen, Send und Sync], + ja: [抽象化、SendとSync], + zh: [抽象,Send和Sync], +)) + +#tr(( +en: [ + None of the above solutions are especially satisfactory. They require + `unsafe` blocks which must be very carefully checked and are not + ergonomic. Surely we can do better in Rust! +], +de: [ + Keine der oben genannten Lösungen ist wirklich zufriedenstellend. Sie + erfordern unsichere Blöcke, die sehr sorgfältig geprüft werden müssen + und nicht ergonomisch sind. In Rust geht das doch bestimmt besser! +], +ja: [ + 上記の解決方法のいずれも、これと言って満足いくものではありません。 + どの解決方法も`unsafe`ブロックを必要とし、非常に注意深くチェックしなければならず、人間工学的ではありません。 + Rustではもっとうまくやれるはずです! +], +zh: [ + 上面的解决方案都不是特别令人满意。它们需要`unsafe`块,`unsafe`块必须要被十分小心地检查且不符合人体工程学。确实,我们在Rust中可以做得更好! +])) + +#tr(( +en: [ + We can abstract our counter into a safe interface which can be safely + used anywhere else in our code. For this example, we'll use the + critical-section counter, but you could do something very similar with + atomics. +], +de: [ + Wir können unseren Zähler in eine sichere Schnittstelle abstrahieren, + die überall im Code sicher verwendet werden kann. In diesem Beispiel + verwenden wir den Zähler für kritische Abschnitte, aber mit atomaren + Operationen ließe sich etwas sehr Ähnliches realisieren. +], +ja: [ + カウンタを、コード内のどこからでも安全に使えるインタフェースに抽象化することができます。 + 次の例では、クリティカルセクションカウンタを使いますが、アトミックと非常に良く似たことが実現できます。 +], +zh: [ + 我们可以把我们的计数器抽象进一个安全的接口中,它可以在代码的其它地方被安全地使用。在这个例子里,我们将使用临界区的(cirtical-section)计数器,但是你可以用原子操作做一些非常类似的事情。 +])) + +#raw(block: true, lang: "rust", +"use core::cell::UnsafeCell; +use cortex_m::interrupt; + +// " + ts(( + en: "Our counter is just a wrapper around UnsafeCell, which is the heart +// of interior mutability in Rust. By using interior mutability, we can have +// COUNTER be `static` instead of `static mut`, but still able to mutate +// its counter value.", + de: "Unser Zaehler ist lediglich ein Wrapper um `UnsafeCell`, das Herzstueck +// der „Interior Mutability“ in Rust. Dank dieses Konzepts können wir `COUNTER` +// als `static` statt als `static mut` definieren und dennoch den Zaehlerwert +// veraendern.", + ja: "カウンタはUnsafeCellの単なるラッパです。UnsafeCellはRustの内部可変性の重要要素です。 +// 内部可変性を使用することで、COUNTERを`static mut`の代わりに`static`として持つことができます。 +// しかし、依然として、カウンタの値は変更することができます。", + zh: "我们的计数器只是包围UnsafeCell的一个封装,它是Rust中内部可变性 +// (interior mutability)的关键。通过使用内部可变性,我们能让COUNTER +// 变成`static`而不是`static mut`,但是仍能改变它的计数器值。" + )) + " +struct CSCounter(UnsafeCell); + +const CS_COUNTER_INIT: CSCounter = CSCounter(UnsafeCell::new(0)); + +impl CSCounter { + pub fn reset(&self, _cs: &interrupt::CriticalSection) { + // " + ts(( + en: "By requiring a CriticalSection be passed in, we know we must + // be operating inside a CriticalSection, and so can confidently + // use this unsafe block (required to call UnsafeCell::get).", + de: "Indem wir die Uebergabe einer `CriticalSection` voraussetzen, wissen + // wir, dass wir uns innerhalb einer `CriticalSection` befinden; daher + // koennen wir bedenkenlos diesen `unsafe`-Block verwenden (der für den + // Aufruf von `UnsafeCell::get` erforderlich ist).", + ja: "クリティカルセクションを引数として要求することで、クリティカルセクション内で + // 実行されなければならないことがわかります。そのため、このアンセーフブロックを + // 自信を持って使用できます(UnsafeCell::getの呼び出しに必要です)。", + zh: "通过要求一个CriticalSection被传递进来,我们知道我们肯定正在一个 + // CriticalSection中操作,且因此可以自信地使用这个unsafe块(调用UnsafeCell::get的前提)。", + )) + " + unsafe { *self.0.get() = 0 }; + } + + pub fn increment(&self, _cs: &interrupt::CriticalSection) { + unsafe { *self.0.get() += 1 }; + } +} + +// " + ts(( + en: "Required to allow static CSCounter. See explanation below.", + de: "Erforderlich, um ein statisches CSCounter zu ermoeglichen. Siehe Erlaeuterung +// unten.", + ja: "静的なCSCounterを許可するために必要です。以下の説明を参照して下さい。", + zh: "允许静态CSCounter的前提。看下面的解释。" + )) + " +unsafe impl Sync for CSCounter {} + +// " + ts(( + en: "COUNTER is no longer `mut` as it uses interior mutability; +// therefore it also no longer requires unsafe blocks to access.", + de: "COUNTER ist nicht mehr `mut`, da es „Interior Mutability“ verwendet; daher +// sind fuer den Zugriff auch keine `unsafe`-Bloecke mehr erforderlich.", + ja: "内部可変性を使用するため、COUNTERは、もはや`mut`ではありません。 +// 従って、アクセスの際に、アンセーフなブロックも必要なくなりました。", + zh: "COUNTER不再是`mut`的因为它使用内部可变性; +// 因此访问它也不再需要unsafe块。" + )) + " +static COUNTER: CSCounter = CS_COUNTER_INIT; + +#[entry] +fn main() -> ! { + set_timer_1hz(); + let mut last_state = false; + loop { + let state = read_signal_level(); + if state && !last_state { + // " + ts(( + en: "No unsafe here!", + ja: "アンセーフはここでは必要ありません!", + zh: "这里不用unsafe!", + )) + " + interrupt::free(|cs| COUNTER.increment(cs)); + } + last_state = state; + } +} + +#[interrupt] +fn timer() { + // " + ts(( + en: "We do need to enter a critical section here just to obtain a valid + // cs token, even though we know no other interrupt could pre-empt + // this one.", + de: "Wir muessen hier tatsaechlich einen kritischen Abschnitt betreten, nur um + // ein gueltiges CS-Token zu erhalten, auch wenn wir wissen, dass kein + // anderer Interrupt diesen unterbrechen koennte.", + ja: "有効なcsトークンを得るため、ここでクリティカルセクションに入る必要があります。 + // 他の割り込みがプリエンプションを起こさないと分かっていても必要です。", + zh: "这里我们需要进入一个临界区,只是为了传递进一个有效的cs token,尽管我们知道 + // 没有其它中断可以抢占这个中断。" + )) + " + interrupt::free(|cs| COUNTER.reset(cs)); + + // " + ts(( + en: "We could use unsafe code to generate a fake CriticalSection if we + // really wanted to, avoiding the overhead:", + de: "Wir koennten „unsicheren“ Code (unsafe code) verwenden, um eine + // gefaelschte CriticalSection zu erzeugen, falls wir das wirklich wollten, + // und so den Overhead vermeiden:", + ja: "オーバーヘッドを避けるために、本当に必要であれば、偽のクリティカルセクションを生成する + // アンセーフなコードを使うことができます。", + zh: "如果我们真的需要,我们可以使用unsafe代码去生成一个假CriticalSection, + // 避免开销:" + )) + " + // let cs = unsafe { interrupt::CriticalSection::new() }; +} +") + +#tr(( +en: [ + We've moved our `unsafe` code to inside our carefully-planned + abstraction, and now our application code does not contain any `unsafe` + blocks. +], +de: [ + Wir haben unseren `unsafe`-Code in unsere sorgfältig entworfene + Abstraktion verlagert; nun enthält unser Anwendungscode keine + `unsafe`-Blöcke mehr. +], +ja: [ + `unsafe`コードを慎重に検討された抽象の内側に移動しました。 + そして、アプリケーションコードは、`unsafe`ブロックを含んでいません。 +], +zh: [ + 我们已经把我们的`unsafe`代码移进了精心安排的抽象中,现在我们的应用代码不包含任何`unsafe`块。 +])) + +#tr(( +en: [ + This design requires that the application pass a `CriticalSection` token + in: these tokens are only safely generated by `interrupt::free`, so by + requiring one be passed in, we ensure we are operating inside a critical + section, without having to actually do the lock ourselves. This + guarantee is provided statically by the compiler: there won't be any + runtime overhead associated with `cs`. If we had multiple counters, they + could all be given the same `cs`, without requiring multiple nested + critical sections. +], +de: [ + Dieser Entwurf setzt voraus, dass die Anwendung ein + `CriticalSection`-Token übergibt: Da diese Tokens nur sicher durch + `interrupt::free` erzeugt werden können, stellen wir durch die + Anforderung eines solchen Tokens sicher, dass wir uns innerhalb eines + kritischen Abschnitts befinden, ohne die Sperre selbst implementieren zu + müssen. Diese Garantie wird statisch vom Compiler gewährleistet; es + entsteht also kein Laufzeit-Overhead durch `cs`. Hätten wir mehrere + Zähler, könnten diese alle dasselbe `cs` verwenden, ohne dass mehrere + verschachtelte kritische Abschnitte erforderlich wären. +], +ja: [ + この設計は、アプリケーションが`CriticalSection`トークンを渡すことを要求します。 + トークンは、`interrupt::free`によってのみ、安全に生成することができます。 + そのため、このトークンが渡されることを要求することで、自分自身でロックを実際にかけることなしに、クリティカルセクション内で動作していることを保証します。 + この保証は、静的にコンパイラによって提供されます。`cs`による実行時のオーバーヘッドはありません。 + カウンタが複数ある場合、複数の入れ子になったクリティカルセクションなしに、同じ`cs`を与えることができます。 +], +zh: [ + 这个设计要求应用传递一个`CriticalSection` token进来: + 这些tokens仅由`interrupt::free`安全地产生,因此通过要求传递进一个`CriticalSection` + token,我们确保我们正在一个临界区中操作,不用自己动手锁起来。这个保障由编译器静态地提供: + 这将不会带来任何与`cs`有关的运行时消耗。如果我们有多个计数器,它们都可以被指定同一个`cs`,而不用要求多个嵌套的临界区。 +])) + +#let url_sendsync = "https://doc.rust-lang.org/nomicon/send-and-sync.html" +#tr(( +en: [ + This also brings up an important topic for concurrency in Rust: the + #link(url_sendsync)[`Send` and `Sync`] + traits. To summarise the Rust book, a type is Send when it can safely be + moved to another thread, while it is Sync when it can be safely shared + between multiple threads. In an embedded context, we consider interrupts + to be executing in a separate thread to the application code, so + variables accessed by both an interrupt and the main code must be Sync. +], +de: [ + Dies führt zu einem wichtigen Thema der Nebenläufigkeit in Rust: den + Traits + #link(url_sendsync)[`Send` und `Sync`]. + Um das „Rust Book" zusammenzufassen: Ein Typ ist `Send`, wenn er sicher + in einen anderen Thread verschoben werden kann, während er `Sync` ist, + wenn er sicher zwischen mehreren Threads geteilt werden kann. Im + Embedded-Kontext betrachten wir Interrupts als Prozesse, die in einem + vom Anwendungscode getrennten Thread ausgeführt werden; daher müssen + Variablen, auf die sowohl ein Interrupt als auch der Hauptcode zugreift, + `Sync` implementieren. +], +ja: [ + これは、Rustの並行性についても重要なトピックを提起します。#link(url_sendsync)[`Send`と`Sync`]トレイトです。 + the Rust + bookを要約すると、安全に別のスレッドに移動できるとき、型はSendです。 + 一方、複数のスレッド間で安全に共有できるとき、型はSyncです。 + 組込みでは、割り込みがアプリケーションコードとは異なるスレッドで動作すると考えます。 + そのため、割り込みとメインコードとの両方からアクセスされる変数は、Syncでなければなりません。 +], +zh: [ + 这也带来了Rust中关于并发的一个重要主题: + #link(url_sendsync)[`Send` and `Sync`] + traits。总结一下Rust + book,当一个类型能够安全地被移动到另一个线程,它是Send,当一个类型能被安全地在多个线程间共享的时候,它是Sync。在一个嵌入式上下文中,我们认为中断是在应用代码的一个独立线程中执行的,因此在一个中断和main代码中都能被访问的变量必须是Sync。 +])) + +#let ln_unsafecell = link("https://doc.rust-lang.org/core/cell/struct.UnsafeCell.html")[`UnsafeCell`] +#tr(( +en: [ + For most types in Rust, both of these traits are automatically derived + for you by the compiler. However, because `CSCounter` contains an #ln_unsafecell, + it is not Sync, and therefore we could not make a `static CSCounter`: + `static` variables _must_ be Sync, since they can be accessed by + multiple threads. +], +de: [ + Für die meisten Typen in Rust werden diese beiden Traits automatisch vom + Compiler für dich abgeleitet. Da `CSCounter` jedoch eine #ln_unsafecell + enthält, ist der Typ nicht `Sync`\; folglich konnten wir keinen + `static CSCounter` definieren, denn `static`-Variablen _müssen_ + `Sync` sein, da von mehreren Threads aus auf sie zugegriffen werden kann. +], +ja: [ + Rustのほとんどの型では、コンパイラによってSendとSyncの両方のトレイトが自動的に継承されます。 + しかし、`CSCounter`は#ln_unsafecell;を含んでいるため、Syncではありません。 + 従って、`static CSCounter`を作ることはできません。`static`変数は、複数のスレッドからアクセスされるため、Syncでなければなりません。 +], +zh: [ + 在Rust中的大多数类型,这两个traits都会由你的编译器为你自动地产生。然而,因为`CSCounter`包含了一个#ln_unsafecell,它不是Sync,因此我们不能使用一个`static CSCounter`: + `static` 变量 _必须_ 是Sync,因此它们能被多个线程访问。 +])) + +#tr(( +en: [ + To tell the compiler we have taken care that the `CSCounter` is in fact + safe to share between threads, we implement the Sync trait explicitly. + As with the previous use of critical sections, this is only safe on + single-core platforms: with multiple cores, you would need to go to + greater lengths to ensure safety. +], +de: [ + Um dem Compiler mitzuteilen, dass wir sichergestellt haben, dass der + `CSCounter` tatsächlich gefahrlos zwischen Threads geteilt werden kann, + implementieren wir das `Sync`-Trait explizit. Wie schon bei der früheren + Verwendung kritischer Abschnitte ist dies nur auf + Single-Core-Plattformen sicher; bei mehreren Kernen wäre ein deutlich + höherer Aufwand erforderlich, um die Sicherheit zu gewährleisten. +], +ja: [ + `CSCounter`が実はスレッド間で共有しても安全なように処理していることを、コンパイラに伝えるため、Syncトレイトを明示的に実装します。 + これまでのクリティカルセクションの使用と同様に、シングルコアのプラットフォームでのみ安全です。 + マルチコアのプラットフォームでは、安全性を確保するためにさらなる取り組みが必要です。 +], +zh: [ + 为了告诉编译器我们已经注意到`CSCounter`事实上在线程间共享是安全的,我们显式地实现了Sync + trait。与之前使用的临界区一样,这只在单核平台上是安全的: + 对于多核,你需要做更多的事来确保安全。 +])) + +== #tr(( + en: [Mutexes], + de: [Mutexe], + ja: [ミューテックス], + zh: [互斥量(Mutexs)], +)) + +#tr(( +en: [ + We've created a useful abstraction specific to our counter problem, but + there are many common abstractions used for concurrency. +], +de: [ + Wir haben eine nützliche, speziell auf unser Zählerproblem + zugeschnittene Abstraktion entwickelt; es gibt jedoch viele gängige + Abstraktionen für Nebenläufigkeit. +], +ja: [ + カウンタの問題に特有の便利な抽象化を行いましたが、並行性のために利用されるいくつかの抽象化が存在します。 +], +zh: [ + 我们已经为我们的计数器问题创造了一个有用的抽象,但是关于并发这里还存在许多通用的抽象。 +])) + +#let ln_drop = link("https://doc.rust-lang.org/core/ops/trait.Drop.html")[`Drop`] +#tr(( +en: [ + One such _synchronisation primitive_ is a mutex, short for mutual + exclusion. These constructs ensure exclusive access to a variable, such + as our counter. A thread can attempt to _lock_ (or _acquire_) + the mutex, and either succeeds immediately, or blocks waiting for the + lock to be acquired, or returns an error that the mutex could not be + locked. While that thread holds the lock, it is granted access to the + protected data. When the thread is done, it _unlocks_ (or + _releases_) the mutex, allowing another thread to lock it. In Rust, + we would usually implement the unlock using the #ln_drop + trait to ensure it is always released when the mutex goes out of scope. +], +de: [ + Ein solches _Synchronisationsprimitiv_ ist der Mutex (kurz für + „mutual exclusion", also gegenseitiger Ausschluss). Diese Konstrukte + gewährleisten den exklusiven Zugriff auf eine Variable, wie etwa unseren + Zähler. Ein Thread kann versuchen, den Mutex zu _sperren_ (oder zu + _erwerben_); dabei ist er entweder sofort erfolgreich, blockiert, + bis die Sperre verfügbar ist, oder erhält eine Fehlermeldung, dass der + Mutex nicht gesperrt werden konnte. Solange der Thread die Sperre hält, + hat er Zugriff auf die geschützten Daten. Ist der Thread fertig, + _entsperrt_ (oder _gibt_) er den Mutex _frei_, sodass ein + anderer Thread ihn sperren kann. In Rust würden wir die Freigabe + üblicherweise mithilfe des + #ln_drop;-Traits + implementieren; so ist sichergestellt, dass der Mutex immer freigegeben + wird, sobald er den Gültigkeitsbereich (Scope) verlässt. +], +ja: [ + そのような _同期プリミティブ_ + の1つはミューテックス(mutex)です。mutexはmutual exclusionの略です。 + ミューテックスは、私達のカウンタのような変数への排他アクセスを保証します。 + あるスレッドは、ミューテックスの _ロック_(または + _獲得_)を試みます。 + すると、すぐに成功するか、ロックが獲得されるのを待ってブロックするか、ミューテックスをロックできなかったエラーを返します。 + そのスレッドがロックを保持している間、保護されたデータへのアクセスが許可されます。 + そのスレッドが実行を完了すると、ミューテックスを + _アンロック_(または + _解放_)することで、他のスレッドがミューテックスをロックできるようにします。 + Rustでは、通常、アンロックを実装するために#ln_drop;トレイトを使用します。 + これは、ミューテックスがスコープの外に到達すると、常に解放されることを保証するためです。 +], +zh: [ + 一个互斥量(mutex),互斥(mutual exclusion)的缩写,就是这样的一个 + _同步原语_ + 。这些构造确保了对一个变量的排他访问,比如我们的计数器。一个线程会尝试 + _lock_ (或者 _acquire_) + 互斥量,或者当互斥量不能被锁住时返回一个错误。当线程持有锁时,它有权访问被保护的数据,当线程工作完成了,它 + _unlocks_ (或者 _releases_) + 互斥量,允许其它线程锁住它。在Rust中,我们通常使用#ln_drop + trait实现unlock去确保当互斥量超出作用域时它总是被释放。 +])) + +#tr(( +en: [ + Using a mutex with interrupt handlers can be tricky: it is not normally + acceptable for the interrupt handler to block, and it would be + especially disastrous for it to block waiting for the main thread to + release a lock, since we would then _deadlock_ (the main thread + will never release the lock because execution stays in the interrupt + handler). Deadlocking is not considered unsafe: it is possible even in + safe Rust. +], +de: [ + Die Verwendung eines Mutex in Interrupt-Handlern kann tückisch sein: + Normalerweise darf ein Interrupt-Handler nicht blockieren. Besonders + fatal wäre es, wenn er blockieren würde, während er darauf wartet, dass + der Haupt-Thread eine Sperre (Lock) freigibt, da dies zu einem + _Deadlock_ führen würde (der Haupt-Thread würde die Sperre niemals + freigeben, da die Ausführung im Interrupt-Handler verbleibt). Ein + Deadlock gilt nicht als „unsicher" (unsafe): Er ist selbst in sicherem + Rust möglich. +], +ja: [ + 割り込みハンドラでミューテックスを使用するのはトリッキーです。割り込みハンドラ内でブロックすることは、通常、好ましくありません。 + 割り込みハンドラ内で、メインスレッドがロックを解放するのを待ってブロックすると、特に悲惨です。 + なぜならば。_デッドロック_ + になるからです。(割り込みハンドラ内に実行がとどまるため、メインスレッドがロックを解放することは決してありません) + デッドロックはアンセーフとは考えられていません。安全なRustでも発生する可能性があります。 +], +zh: [ + 将中断处理函数与一个互斥量一起使用可能有点棘手: + 阻塞中断处理函数通常是不可接受的,如果它阻塞等待main线程去释放一个锁,那将是一场灾难。因为我们会 + _死锁_ + (因为执行停留在中断处理函数中,主线程将永远不会释放锁)。死锁被认为是不安全的: + 即使在安全的Rust中这也是可能发生的。 +])) + +#tr(( +en: [ + To avoid this behaviour entirely, we could implement a mutex which + requires a critical section to lock, just like our counter example. So + long as the critical section must last as long as the lock, we can be + sure we have exclusive access to the wrapped variable without even + needing to track the lock/unlock state of the mutex. +], +de: [ + Um dieses Verhalten vollständig zu vermeiden, könnten wir einen Mutex + implementieren, der für das Sperren eine kritische Sektion erfordert -- + genau wie in unserem Zähler-Beispiel. Solange die Dauer der kritischen + Sektion der Dauer der Sperre entspricht, ist sichergestellt, dass wir + exklusiven Zugriff auf die gekapselte Variable haben, ohne den + Sperrstatus des Mutex explizit nachverfolgen zu müssen. +], +ja: [ + この動作を完全に避けるため、カウンタの例で示すように、ロックのためにクリティカルセクションを必要とするミューテックスを実装できます。 + クリティカルセクションがロックしている間続く限り、ミューテックスのロック/アンロックの状態を追跡することなしに、 + ラップされた変数に排他的にアクセスできます。 +], +zh: [ + 为了完全避免这个行为,我们可以实现一个要求临界区的互斥量去锁住,就像我们的计数器例子一样。临界区的存在时间必须和锁存在的时间一样长,我们能确保我们对被封装的变量有排他式访问,甚至不需要跟踪互斥量的 + lock/unlock 状态。 +])) + +#tr(( +en: [ + This is in fact done for us in the `cortex_m` crate! We could have + written our counter using it: +], +de: [ + Genau dies wird uns bereits durch die `cortex_m`-Crate abgenommen! Wir + hätten unseren Zähler auch unter Verwendung dieser Crate implementieren können: +], +ja: [ + これは実際に`cortex_m`クレートで行われています! それを使ってカウンタを書くことができます。 +], +zh: [ + 实际上我们在 `cortex_m` crate中就是这么做的!我们可以用它来写入我们的计数器: +])) + +#raw(block: true, lang: "rust", +"use core::cell::Cell; +use cortex_m::interrupt::Mutex; + +static COUNTER: Mutex> = Mutex::new(Cell::new(0)); + +#[entry] +fn main() -> ! { + set_timer_1hz(); + let mut last_state = false; + loop { + let state = read_signal_level(); + if state && !last_state { + interrupt::free(|cs| + COUNTER.borrow(cs).set(COUNTER.borrow(cs).get() + 1)); + } + last_state = state; + } +} + +#[interrupt] +fn timer() { + // " + ts(( + en: "We still need to enter a critical section here to satisfy the Mutex.", + de: "Wir muessen hier noch einen kritischen Abschnitt betreten, um die + // Mutex-Bedingung zu erfuellen.", + ja: "ミューテックスを満たすために、ここでもクリティカルセクションに入る必要があります。", + zh: "这里我们仍然需要进入一个临界区去满足互斥量。", + )) + " + interrupt::free(|cs| COUNTER.borrow(cs).set(0)); +} +") + +#let ln_cell = link("https://doc.rust-lang.org/core/cell/struct.Cell.html")[`Cell`] +#tr(( +en: [ + We're now using #ln_cell, + which along with its sibling `RefCell` is used to provide safe interior + mutability. We've already seen `UnsafeCell` which is the bottom layer of + interior mutability in Rust: it allows you to obtain multiple mutable + references to its value, but only with unsafe code. A `Cell` is like an + `UnsafeCell` but it provides a safe interface: it only permits taking a + copy of the current value or replacing it, not taking a reference, and + since it is not Sync, it cannot be shared between threads. These + constraints mean it's safe to use, but we couldn't use it directly in a + `static` variable as a `static` must be Sync. +], +de: [ + Wir verwenden nun #ln_cell;; + dieses bietet -- ebenso wie sein Pendant `RefCell` -- eine sichere Form + der „Interior Mutability" (internen Veränderbarkeit). Wir haben bereits + `UnsafeCell` kennengelernt, die unterste Ebene der internen + Veränderbarkeit in Rust: Sie ermöglicht es, mehrere veränderbare + Referenzen auf den enthaltenen Wert zu erhalten, allerdings nur mittels + `unsafe`-Code. Eine `Cell` ähnelt einer `UnsafeCell`, stellt jedoch eine + sichere Schnittstelle bereit: Sie erlaubt lediglich das Kopieren des + aktuellen Werts oder dessen Austausch, nicht jedoch den Zugriff über + eine Referenz; zudem ist sie nicht `Sync` und kann daher nicht zwischen + Threads geteilt werden. Aufgrund dieser Einschränkungen ist ihre + Verwendung sicher, allerdings lässt sie sich nicht direkt in einer + `static`-Variablen einsetzen, da `static`-Elemente die Eigenschaft + `Sync` erfüllen müssen. +], +ja: [ + 今回は#ln_cell;を使っています。これは、`RefCell`の同類で安全な内部可変性を提供するために使用されます。 + 既に、`UnsafeCell`が、Rustの内部可変性の最下層であることを見てきました。 + UnsafeCellは、値への複数のミュータブル参照の取得を可能としますが、アンセーフなコードでのみ使用できます。 + `Cell`は`UnsafeCell`と似ていますが、安全なインタフェースを提供します。 + Cellは参照を取得せず、現在値のコピーを取得するか、置き換えることだけを許可します。 + CellはSyncでないため、スレッド間で共有できません。 + これらの制約は安全に使えることを意味しますが、`static`変数として直接使用できません。`static`はSyncである必要があるからです。 +], +zh: [ + 我们现在使用了#ln_cell,它与它的兄弟`RefCell`一起被用于提供safe的内部可变性。我们已经见过`UnsafeCell`了,在Rust中它是内部可变性的底层: + 它允许你去获得对某个值的多个可变引用,但是只能与不安全的代码一起工作。一个`Cell`像一个`UnsafeCell`一样但是它提供了一个安全的接口: + 它只允许拷贝现在的值或者替换它,不允许获取一个引用,因此它不是Sync,它不能被在线程间共享。这些限制意味着它用起来是safe的,但是我们不能直接将它用于`static`变量因为一个`static`必须是Sync。 +])) + +#tr(( +en: [ + So why does the example above work? The `Mutex` implements Sync for + any `T` which is Send --- such as a `Cell`. It can do this safely + because it only gives access to its contents during a critical section. + We're therefore able to get a safe counter with no unsafe code at all! +], +de: [ + Warum funktioniert das obige Beispiel? Der `Mutex` implementiert + `Sync` für jedes `T`, das `Send` ist -- wie beispielsweise eine `Cell`. + Dies ist sicher möglich, da der Zugriff auf den Inhalt nur während eines + kritischen Abschnitts gewährt wird. Dadurch erhalten wir einen sicheren + Zähler ohne jeglichen unsicheren Code! +], +ja: [ + では、なぜ上記の例はうまく動くのでしょうか?`Mutex`は、`Cell`のようなSendな`T`に対してSyncを実装します。 + このことが、Cellをstaticで使うことを安全にします。なぜなら、クリティカルセクションの間だけ、その中身へのアクセスを提供するからです。 + 従って、全くアンセーフなコードなしに、安全なカウンタを手に入れることができます。 +], +zh: [ + 因此为什么上面的例子可以工作?`Mutex`对于任何是Send的`T`实现了Sync - + 比如一个`Cell`。因为它只能在临界区对它的内容进行访问,所以它这么做是safe的。因此我们可以即使没有一点unsafe的代码我们也能获取一个safe的计数器! +])) + +#tr(( +en: [ + This is great for simple types like the `u32` of our counter, but what + about more complex types which are not Copy? An extremely common example + in an embedded context is a peripheral struct, which generally is not + Copy. For that, we can turn to `RefCell`. +], +de: [ + Das ist ideal für einfache Typen wie den `u32` unseres Zählers. Was aber + ist mit komplexeren Typen, die nicht `Copy` sind? Ein sehr häufiges + Beispiel in eingebetteten Systemen ist eine Peripheriestruktur, die in + der Regel nicht `Copy` ist. Für diesen Fall können wir `RefCell` verwenden. +], +ja: [ + この方法は、カウンタの`u32`のような単純な型に適しています。しかし、もっと複雑なCopyでない型についてはどうでしょうか? + 組込みにおいて非常に一般的な例は、ペリフェラル構造体です。これは、通常Copyではありません。 + そのためには、`RefCell`に頼ることができます。 +], +zh: [ + 对于我们的简单类型,像是我们的计数器的`u32`来说是很棒的,但是对于更复杂的不能拷贝的类型呢?在一个嵌入式上下文中一个极度常见的例子是一个外设结构体,通常它们不是Copy。针对那种情况,我们可以使用`RefCell`。 +])) + +== #tr(( + en: [Sharing Peripherals], + de: [Gemeinsame Nutzung von Peripheriegeräten], + ja: [ペリフェラルの共有], + zh: [共享外设], +)) + +#tr(( +en: [ + Device crates generated using `svd2rust` and similar abstractions + provide safe access to peripherals by enforcing that only one instance + of the peripheral struct can exist at a time. This ensures safety, but + makes it difficult to access a peripheral from both the main thread and + an interrupt handler. +], +de: [ + Mit `svd2rust` und ähnlichen Abstraktionen erzeugte Device-Crates + ermöglichen einen sicheren Zugriff auf Peripheriekomponenten, indem sie + sicherstellen, dass zu jedem Zeitpunkt nur eine einzige Instanz der + entsprechenden Peripherie-Struktur existiert. Dies gewährleistet zwar + die Sicherheit, erschwert jedoch den gleichzeitigen Zugriff auf eine + Peripheriekomponente sowohl aus dem Haupt-Thread als auch aus einem + Interrupt-Handler heraus. +], +ja: [ + `svd2rust`および同様の抽象化を使って生成されるデバイスクレートは、ペリフェラルへの安全なアクセスを提供します。 + これは、同時に1つのペリフェラル構造体インスタンスしか存在できないように強制することによって、もたらされます。 + このことは、安全性を保証しますが、メインスレッドと割り込みハンドとの両方からペリフェラルにアクセスすることを難しくします。 +], +zh: [ + 使用`svd2rust`生成的设备crates和相似的抽象,通过强制要求同时只能存在一个外设结构体的实例,提供了对外设的安全的访问。这个确保了安全性,但是使得它很难从main线程和一个中断处理函数一起访问一个外设。 +])) + +#let ln_refcell = link("https://doc.rust-lang.org/core/cell/struct.RefCell.html")[`RefCell`] +#tr(( +en: [ + To safely share peripheral access, we can use the `Mutex` we saw before. + We'll also need to use #ln_refcell, + which uses a runtime check to ensure only one reference to a peripheral + is given out at a time. This has more overhead than the plain `Cell`, + but since we are giving out references rather than copies, we must be + sure only one exists at a time. +], +de: [ + Um den Zugriff auf Peripheriekomponenten sicher zu teilen, können wir + den bereits bekannten `Mutex` verwenden. Zudem benötigen wir + #ln_refcell;; + dieses stellt mittels einer Laufzeitprüfung sicher, dass jeweils nur + eine einzige Referenz auf eine Peripheriekomponente ausgegeben wird. + Dies ist zwar mit einem höheren Overhead verbunden als bei einem + einfachen `Cell`, doch da wir Referenzen anstatt Kopien weitergeben, + müssen wir sicherstellen, dass zu jedem Zeitpunkt nur eine einzige + Referenz existiert. +], +ja: [ + ペリフェラルアクセスを安全に共有するため、上で見たように`Mutex`を使うことができます。 + また、#ln_refcell;も必要です。RefCellは、実行時チェックを使って、同時に1つのペリフェラルへの参照だけが渡されるようにします。 + 実行時チェックは、普通の`Cell`よりもオーバーヘッドが大きくなりますが、 + コピーではなく参照を受け渡しするため、同時に存在するのが1つだけであることを確認する必要があります。 +], +zh: [ + 为了安全地共享对外设的访问,我们能使用我们之前看到的`Mutex`。我们也将需要使用#ln_refcell,它使用一个运行时检查去确保对一个外设每次只有一个引用被给出。这个比纯`Cell`消耗更多,但是因为我们正给出引用而不是拷贝,我们必须确保每次只有一个引用存在。 +])) + +#tr(( +en: [ + Finally, we'll also have to account for somehow moving the peripheral + into the shared variable after it has been initialised in the main code. + To do this we can use the `Option` type, initialised to `None` and later + set to the instance of the peripheral. +], +de: [ + Schließlich müssen wir auch berücksichtigen, wie die + Peripheriekomponente in die gemeinsam genutzte Variable übertragen + werden kann, nachdem sie im Hauptcode initialisiert wurde. Hierfür + können wir den Typ `Option` verwenden, der zunächst mit `None` + initialisiert und später auf die Instanz der Peripheriekomponente gesetzt wird. +], +ja: [ + 最後に、メインコード内でペリフェラルを初期化した後、なんとかしてペリフェラルを共有変数に移動する方法が必要です。 + これを実現するために、`Option`型を使います。`None`で初期化し、後でペリフェラルのインスタンスを設定します。 +], +zh: [ + 最终,我们也必须考虑在main代码中初始化外设后,如何将外设移到共享变量中。为了做这个,我们使用`Option`类型,初始成`None`,之后设置成外设的实例。 +])) + +#raw(block: true, lang: "rust", +"use core::cell::RefCell; +use cortex_m::interrupt::{self, Mutex}; +use stm32f4::stm32f405; + +static MY_GPIO: Mutex>> = + Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + // " + ts(( + en: "Obtain the peripheral singletons and configure it. + // This example is from an svd2rust-generated crate, but + // most embedded device crates will be similar.", + de: "Die Peripherie-Singletons abrufen und konfigurieren. + // Dieses Beispiel stammt aus einer mit svd2rust erstellten Crate, die + // meisten Crates für eingebettete Geräte sind jedoch ähnlich.", + ja: "ペリフェラルのシングルトンを取得し、設定します。 + // この例は、svd2rustで生成されたクレートから持ってきたものですが、 + // ほとんどの組込みデバイスクレートは同様になります。", + zh: "获得外设的单例并配置它。这个例子来自一个svd2rust生成的crate, + // 但是大多数的嵌入式设备crates都相似。", + )) + " + let dp = stm32f405::Peripherals::take().unwrap(); + let gpioa = &dp.GPIOA; + + // " + ts(( + en: "Some sort of configuration function. + // Assume it sets PA0 to an input and PA1 to an output.", + de: "Eine Art Konfigurationsfunktion. + // Gehen wir davon aus, dass es PA0 als Eingang und PA1 als Ausgang + // konfiguriert.", + ja: "一連の設定をする関数です。 + // PA0を入力、PA1を出力に設定すると仮定して下さい。", + zh: "某个配置函数。假设它把PA0设置成一个输入和把PA1设置成一个输出。", + )) + " + configure_gpio(gpioa); + + // " + ts(( + en: "Store the GPIOA in the mutex, moving it.", + de: "Speichere GPIOA im Mutex und verschiebe es dabei.", + ja: "GPIOAをミューテックスに格納し、ムーブします。", + zh: "把GPIOA存进互斥量中,移动它。", + )) + " + interrupt::free(|cs| MY_GPIO.borrow(cs).replace(Some(dp.GPIOA))); + // " + ts(( + en: "We can no longer use `gpioa` or `dp.GPIOA`, and instead have to + // access it via the mutex. + + // Be careful to enable the interrupt only after setting MY_GPIO: + // otherwise the interrupt might fire while it still contains None, + // and as-written (with `unwrap()`), it would panic.", + de: "Wir koennen `gpioa` oder `dp.GPIOA` nicht mehr verwenden, sondern + // muessen stattdessen ueber den Mutex darauf zugreifen. + + // Achten Sie darauf, den Interrupt erst nach dem Setzen von MY_GPIO zu + // aktivieren: + // Andernfalls koennte der Interrupt ausgeloest werden, solange MY_GPIO + // noch None enthaelt, was – wie implementiert (mit `unwrap()`) – zu einer + // Panic fuehren wuerde.", + ja: "もはや`gpioa`や`dp.GPIOA`は使いません。 + // 代わりに、ミューテックス経由でアクセスする必要があります。 + + // MY_GPIOを設定した後にのみ、割り込みを有効にするように注意して下さい。 + // そうしなければ、まだNoneが含まれている間に、割り込みが発生する可能性があります。 + // (`unwrap()`を使用して)書き込まれると、パニックになるでしょう。", + zh: "我可以不再用`gpioa`或者`dp.GPIOA`,反而必须通过互斥量访问它。 + + // 请注意,只有在设置MY_GPIO后才能使能中断: 要不然当MY_GPIO还是包含None的时候, + // 中断可能会发生,然后像上面写的那样操作(使用`unwrap()`),它将发生运行时恐慌。" + )) + " + set_timer_1hz(); + let mut last_state = false; + loop { + // " + ts(( + en: "We'll now read state as a digital input, via the mutex", + de: "Wir lesen den Status nun als digitalen Eingang ueber den Mutex aus.", + ja: "ミューテックス経由で、デジタル入力としての状態を読み込みます。", + zh: "我们现在将通过互斥量,读取其作为数字输入时的状态。", + )) + " + let state = interrupt::free(|cs| { + let gpioa = MY_GPIO.borrow(cs).borrow(); + gpioa.as_ref().unwrap().idr.read().idr0().bit_is_set() + }); + + if state && !last_state { + // " + ts(( + en: "Set PA1 high if we've seen a rising edge on PA0.", + de: "Setze PA1 auf High, wenn an PA0 eine steigende Flanke erkannt + // wurde.", + ja: "PA0の立ち上がりエッジを検出した場合、PA1をハイに設定します。", + zh: "如果我们在PA0上已经看到了一个上升沿,拉高PA1。" + )) + " + interrupt::free(|cs| { + let gpioa = MY_GPIO.borrow(cs).borrow(); + gpioa.as_ref().unwrap().odr.modify(|_, w| w.odr1().set_bit()); + }); + } + last_state = state; + } +} + +#[interrupt] +fn timer() { + // " + ts(( + en: "This time in the interrupt we'll just clear PA0.", + de: "Diesmal setzen wir im Interrupt lediglich PA0 zurueck.", + ja: "今回は、割り込み内では単純にPA0をクリアするだけです。", + zh: "这次在中断中,我们将清除PA0。", + )) + " + interrupt::free(|cs| { + // " + ts(( + en: "We can use `unwrap()` because we know the interrupt wasn't enabled + // until after MY_GPIO was set; otherwise we should handle the potential + // for a None value.", + de: "Wir koennen `unwrap()` verwenden, da wir wissen, dass der Interrupt + // erst aktiviert wurde, nachdem `MY_GPIO` gesetzt war; andernfalls + // muessten wir den moeglichen Fall eines `None`-Werts behandeln.", + ja: "`unwrap()`を使うことができます。割り込みはMY_GPIOが設定されるまで有効化されないことを + // 知っているためです。そうでなければ、Noneを処理しなければならないでしょう。", + zh: "我们可以使用`unwrap()` 因为我们知道直到MY_GPIO被设置后,中断都是禁用的; + // 否则我应该处理会出现一个None值的潜在可能" + )) + " + let gpioa = MY_GPIO.borrow(cs).borrow(); + gpioa.as_ref().unwrap().odr.modify(|_, w| w.odr1().clear_bit()); + }); +} +") + +#tr(( +en: [ + That's quite a lot to take in, so let's break down the important lines. +], +de: [ + Das ist eine ganze Menge, die man erst einmal verarbeiten muss -- + schauen wir uns also die wichtigen Zeilen genauer an. +], +ja: [ + 非常に多くのことを取り入れています。重要な部分を詳細に見ていきましょう。 +], +zh: [ + 这需要理解的内容很多,所以让我们把重要的内容分解一下。 +])) + +```rust +static MY_GPIO: Mutex>> = + Mutex::new(RefCell::new(None)); +``` + +#tr(( +en: [ + Our shared variable is now a `Mutex` around a `RefCell` which contains + an `Option`. The `Mutex` ensures we only have access during a critical + section, and therefore makes the variable Sync, even though a plain + `RefCell` would not be Sync. The `RefCell` gives us interior mutability + with references, which we'll need to use our `GPIOA`. The `Option` lets + us initialise this variable to something empty, and only later actually + move the variable in. We cannot access the peripheral singleton + statically, only at runtime, so this is required. +], +de: [ + Unsere gemeinsam genutzte Variable ist nun ein `Mutex`, der einen + `RefCell` umschließt, welcher wiederum ein `Option` enthält. Der `Mutex` + stellt sicher, dass der Zugriff nur innerhalb eines kritischen + Abschnitts erfolgt, und macht die Variable dadurch `Sync` -- auch wenn + ein einfacher `RefCell` dies nicht wäre. Der `RefCell` ermöglicht uns + „Interior Mutability" (interne Veränderbarkeit) bei Verwendung von + Referenzen, was wir für unseren `GPIOA` benötigen. Das `Option` erlaubt + es uns, die Variable zunächst leer zu initialisieren und den + eigentlichen Wert erst später hineinzubewegen. Da wir nicht statisch, + sondern nur zur Laufzeit auf das Peripherie-Singleton zugreifen können, + ist dieses Vorgehen erforderlich. +], +ja: [ + ここでは、共有変数は`RefCell`を内部に含む`Mutex`です。さらに、RefCellは`Option`を含んでいます。 + `Mutex`はクリティカルセクションの間だけ、アクセスできるようにします。 + その結果、普通の`RefCell`はSyncでないにも関わらず、変数はSyncになります。 + `RefCell`は、`GPIOA`を使うのに必要となる参照によって内部可変性を提供します。 + `Option`を使用すると、この変数を空の値に初期化できます。後で実際に変数を移動します。 + ペリフェラルのシングルトンには静的にアクセスすることはできません。実行時のみアクセスできるため、Optionが必要とされます。 +], +zh: [ + 我们的共享变量现在是一个包围了一个`RefCell`的`Mutex`,`RefCell`包含一个`Option`。`Mutex`确保只在一个临界区中的时候可以访问,因此使变量变成了Sync,甚至即使一个纯`RefCell`不是Sync。`RefCell`赋予了我们引用的内部可变性,我们将需要使用我们的`GPIOA`。`Option`让我们可以初始化这个变量成空的东西,只在随后实际移动变量进来。只有在运行时,我们才能静态地访问外设单例,因此这是必须的。 + +])) + +```rust +interrupt::free(|cs| MY_GPIO.borrow(cs).replace(Some(dp.GPIOA))); +``` + +#tr(( +en: [ + Inside a critical section we can call `borrow()` on the mutex, which + gives us a reference to the `RefCell`. We then call `replace()` to move + our new value into the `RefCell`. +], +de: [ + Innerhalb eines kritischen Abschnitts können wir `borrow()` auf dem + Mutex aufrufen, was uns eine Referenz auf die `RefCell` liefert. + Anschließend rufen wir `replace()` auf, um unseren neuen Wert in die + `RefCell` zu verschieben. +], +ja: [ + クリティカルセクションの内部で、ミューテックスの`borrow()`を呼んでいます。borrow()は`RefCell`の参照を提供します。 + その後、`replace()`を呼び出して、`RefCell`に新しい値をムーブします。 +], +zh: [ + 在一个临界区中,我们可以在互斥量上调用`borrow()`,其给了我们一个指向`RefCell`的引用。然后我们调用`replace()`去移动我们的新值进来`RefCell`。 +])) + +```rust +interrupt::free(|cs| { + let gpioa = MY_GPIO.borrow(cs).borrow(); + gpioa.as_ref().unwrap().odr.modify(|_, w| w.odr1().set_bit()); +}); +``` + +#tr(( +en: [ + Finally, we use `MY_GPIO` in a safe and concurrent fashion. The critical + section prevents the interrupt firing as usual, and lets us borrow the + mutex. The `RefCell` then gives us an `&Option`, and tracks how + long it remains borrowed - once that reference goes out of scope, the + `RefCell` will be updated to indicate it is no longer borrowed. +], +de: [ + Schließlich verwenden wir `MY_GPIO` auf sichere und nebenläufige Weise. + Der kritische Abschnitt verhindert wie üblich das Auslösen von + Interrupts und ermöglicht es uns, den Mutex auszuleihen. Die `RefCell` + liefert uns dann ein `&Option` und überwacht die Dauer der + Ausleihe; sobald die Referenz ihren Gültigkeitsbereich verlässt, wird + der Status der `RefCell` aktualisiert, um anzuzeigen, dass sie nicht + mehr ausgeliehen ist. +], +ja: [ + 最後に、`MY_GPIO`を安全で並行なやり方で使います。 + クリティカルセクションは、通常通り割り込みの発生を防ぎ、ミューテックスを借用できます。 + `RefCell`は`&Option`を提供し、その借用がいつまで続くかを追跡します。 + その参照がスコープ外になると、`RefCell`が借用されなくなったことを示すため、更新されます。 +], +zh: [ + 最终,我们用一种安全和并发的方式使用`MY_GPIO`。临界区禁止了中断像往常一样发生,让我们借用互斥量。`RefCell`然后给了我们一个`&Option`并追踪它还要借用多久 - 一旦引用超出作用域,`RefCell`将会被更新去指出引用不再被借用。 +])) + +#tr(( +en: [ + Since we can't move the `GPIOA` out of the `&Option`, we need to convert + it to an `&Option<&GPIOA>` with `as_ref()`, which we can finally + `unwrap()` to obtain the `&GPIOA` which lets us modify the peripheral. +], +de: [ + Da wir das `GPIOA`-Objekt nicht aus dem `&Option` herausverschieben + können, müssen wir es mittels `as_ref()` in ein `&Option<&GPIOA>` + umwandeln. Dieses können wir schließlich mit `unwrap()` auflösen, um das + `&GPIOA` zu erhalten, das uns den Zugriff zur Modifikation der + Peripherieeinheit ermöglicht. +], +ja: [ + `&Option`の外に`GPIOA`をムーブすることはできないので、`as_ref()`を使って`&Option<&GPIOA>`に変換します。 + そうすると、最終的に、`unwrap()`で`&GPIOA`を取得できます。 + &GPIOAにより、ペリフェラルを修正することができます。 +], +zh: [ + 因为我不能把`GPIOA`移出`&Option`,我们需要用`as_ref()`将它转换成一个`&Option<&GPIOA>`,最终我们能使用`unwrap()`获得`&GPIOA`,其让我们可以修改外设。 +])) + +#tr(( +en: [ + If we need a mutable reference to a shared resource, then `borrow_mut` + and `deref_mut` should be used instead. The following code shows an + example using the TIM2 timer. +], +de: [ + Wenn wir eine veränderbare Referenz auf eine gemeinsam genutzte + Ressource benötigen, sollten stattdessen `borrow_mut` und `deref_mut` + verwendet werden. Der folgende Code zeigt ein Beispiel unter Verwendung + des TIM2-Timers. +], +zh: [ + 如果我们需要一个共享的资源的可变引用,那么`borrow_mut`和`deref_mut`应该被使用。下面的代码展示了一个使用TIM2计时器的例子。 +])) + +#raw(block: true, lang: "rust", +"use core::cell::RefCell; +use core::ops::DerefMut; +use cortex_m::interrupt::{self, Mutex}; +use cortex_m::asm::wfi; +use stm32f4::stm32f405; + +static G_TIM: Mutex>>> = + Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let mut cp = cm::Peripherals::take().unwrap(); + let dp = stm32f405::Peripherals::take().unwrap(); + + // " + ts(( + en: "Some sort of timer configuration function. + // Assume it configures the TIM2 timer, its NVIC interrupt, + // and finally starts the timer.", + de: "Eine Art Timer-Konfigurationsfunktion. + // Angenommen, sie konfiguriert den TIM2-Timer sowie dessen NVIC-Interrupt + // und startet schließlich den Timer.", + zh: "某个计时器配置函数。假设它配置了TIM2计时器和它的NVIC中断, + // 最终启动计时器。" + )) + " + let tim = configure_timer_interrupt(&mut cp, dp); + + interrupt::free(|cs| { + G_TIM.borrow(cs).replace(Some(tim)); + }); + + loop { + wfi(); + } +} + +#[interrupt] +fn timer() { + interrupt::free(|cs| { + if let Some(ref mut tim)) = G_TIM.borrow(cs).borrow_mut().deref_mut() { + tim.start(1.hz()); + } + }); +} +") + +#tr(( +en: [ + Whew! This is safe, but it is also a little unwieldy. Is there anything + else we can do? +], +de: [ + Puh! Das ist zwar sicher, aber auch etwas unhandlich. Können wir sonst + noch etwas tun? +], +ja: [ + ヒューッ!これは安全ですが、少し大げさすぎて扱いにくいです。他に方法はないのでしょうか? +], +zh: [ + 呼!这是安全的,但也有点笨拙。我们还能做些什么吗? +])) + +== RTIC + +#let url_rtic = "https://github.com/rtic-rs/cortex-m-rtic" +#tr(( +en: [ + One alternative is the #link(url_rtic)[RTIC framework], short for Real Time + Interrupt-driven Concurrency. It enforces static priorities and tracks + accesses to `static mut` variables ("resources") to statically ensure + that shared resources are always accessed safely, without requiring the + overhead of always entering critical sections and using reference + counting (as in `RefCell`). This has a number of advantages such as + guaranteeing no deadlocks and giving extremely low time and memory + overhead. +], +de: [ + Eine Alternative ist das + #link(url_rtic)[RTIC-Framework] (kurz für _Real + Time Interrupt-driven Concurrency_). Es erzwingt statische Prioritäten + und überwacht Zugriffe auf `static mut`-Variablen („Ressourcen"), um + statisch sicherzustellen, dass auf gemeinsam genutzte Ressourcen stets + sicher zugegriffen wird -- ohne den Overhead, der durch das ständige + Betreten kritischer Abschnitte oder die Verwendung von Referenzzählung + (wie bei `RefCell`) entstünde. Dies bietet eine Reihe von Vorteilen, wie + etwa die Garantie von Deadlock-Freiheit sowie einen extrem geringen + Zeit- und Speicheraufwand. +], +ja: [ + 代替手段の1つは、#link(url_rtic)[RTFMフレームワーク]です。RTFMは、Real + Time For the Massesの略です。 + RTFMは、共有リソースが常に安全にアクセスされることを保証するために、静的な優先度を適用し、 + `static mut`変数(「リソース」)へのアクセスを追跡します。 + この方法は、(`RefCell`のように)常にクリティカルセクションに入り、参照カウントを使うというオーバーヘッドを必要としません。 + デッドロックがないことを保証したり、時間とメモリのオーバーヘッドを極めて小さくするといった、多くの利点があります。 +], +zh: [ + 另一个方法是使用#link(url_rtic)[RTIC框架],Real + Time Interrupt-driven + Concurrency的缩写。它强制执行静态优先级并追踪对`static mut`变量("资源")的访问去确保共享资源总是能被安全地访问,而不需要总是进入临界区和使用引用计数带来的消耗(如`RefCell`中所示)。这有许多好处,比如保证没有死锁且时间和内存的消耗极度低。 +])) + +#tr(( +en: [ + RTIC comes with as asynchronous executor, so your software tasks are + `async` functions where you can use `async` APIs in addition to regular + synchronous APIs. +], +de: [ + RTIC bietet einen asynchronen Executor, sodass Ihre Software-Tasks als + `async`-Funktionen implementiert sind; darin können Sie neben + herkömmlichen synchronen APIs auch `async`-APIs nutzen. +])) + +#let url_rtic_doc = "https://rtic.rs" +#tr(( +en: [ + The framework also includes other features like message passing, which + reduces the need for explicit shared state, and the ability to schedule + tasks to run at a given time, which can be used to implement periodic + tasks. Check out #link(url_rtic_doc)[the documentation] for more + information! +], +de: [ + Das Framework umfasst zudem Funktionen wie Message Passing -- was den + Bedarf an explizit gemeinsam genutztem Zustand (Shared State) verringert + -- sowie die Möglichkeit, Tasks für einen bestimmten Zeitpunkt zu + planen, womit sich beispielsweise periodische Aufgaben realisieren + lassen. Weitere Informationen finden Sie in + #link(url_rtic_doc)[der Dokumentation]! +], +ja: [ + このフレームワークは他の機能も含んでいます。例えば、メッセージパッシングは明示的な共有状態の必要性を減らします。 + また、タスクを指定した時間に実行するスケジュールする機能もあります。これは、周期タスクの実装に使えます。 + 詳しくは#link(url_rtic_doc)[ドキュメント]を参照して下さい。 +], +zh: [ + 这个框架也包括了其它的特性,像是消息传递(message + passing),消息传递减少了对显式共享状态的需要,还提供了在一个给定时间调度任务去运行的功能,这功能能被用来实现周期性的任务。看下#link(url_rtic_doc)[文档]可以知道更多的信息! +])) + +== Embassy + +#let url_executor = "https://docs.rs/embassy-executor/latest/embassy_executor/" +#tr(( +en: [ + Embassy is an ecosystem of libraries which focus on using the `async` / + `await` syntax included in Rust for concurrency. The core of embassy is + its #link(url_executor)[asynchronous executor] + which supports most common MCU architectures. +], +de: [ + Embassy ist ein Ökosystem von Bibliotheken, die sich auf die Nutzung der + in Rust enthaltenen `async`/`await`-Syntax für Nebenläufigkeit + konzentrieren. Das Herzstück von Embassy ist sein + #link(url_executor)[asynchroner Executor], + der die gängigsten MCU-Architekturen unterstützt. +])) + +#let url_em_time = "https://docs.rs/embassy-time/latest/embassy_time/" +#let ln_en_sync = link("https://docs.embassy.dev/embassy-sync/git/default/index.html")[embassy-sync] +#tr(( +en: [ + embassy also takes a battery-included approach and offers many other + components, for example: + - #link(url_em_time)[Time library] + - Various HAL libraries which also provide the time library support. + - #ln_en_sync for synchronization primitives +], +de: [ + Embassy verfolgt zudem einen „Batteries-included"-Ansatz und bietet + viele weitere Komponenten an, zum Beispiel: + - #link(url_em_time)[Zeit-Bibliothek] + - Verschiedene HAL-Bibliotheken, die auch Unterstützung für die + Zeitbibliothek bieten. + - #ln_en_sync für Synchronisationsprimitive +])) + +#let url_em_site = "https://embassy.dev/" +#let url_em_book = "https://embassy.dev/book/" +#tr(( +en: [ + You can check the #link(url_em_site)[website] and the + #link(url_em_book)[book] for more information. +], +de: [ + Weitere Informationen finden Sie auf der + #link(url_em_site)[Website] und im #link(url_em_book)[Buch]. +])) + +== #tr(( + en: [Real Time Operating Systems], + de: [Echtzeitbetriebssysteme], + ja: [リアルタイムオペレーティングシステム], + zh: [实时操作系统], +)) + +#let ln_freertos = link("https://freertos.org/")[FreeRTOS] +#let ln_chibi = link("http://chibios.org/")[ChibiOS] +#tr(( +en: [ + Another common model for embedded concurrency is the real-time operating + system (RTOS). While currently less well explored in Rust, they are + widely used in traditional embedded development. Open source examples + include #ln_freertos and #ln_chibi. These RTOSs provide support for + running multiple application threads which the CPU swaps between, either + when the threads yield control (called cooperative multitasking) or + based on a regular timer or interrupts (preemptive multitasking). The + RTOS typically provide mutexes and other synchronisation primitives, and + often interoperate with hardware features such as DMA engines. +], +de: [ + Ein weiteres verbreitetes Modell für Nebenläufigkeit in eingebetteten + Systemen ist das Echtzeitbetriebssystem (RTOS). Während diese in Rust + bislang weniger stark erforscht sind, kommen sie in der klassischen + Entwicklung eingebetteter Systeme häufig zum Einsatz. Zu den + Open-Source-Beispielen zählen #ln_freertos und #ln_chibi. + Solche Echtzeitbetriebssysteme unterstützen die Ausführung mehrerer + Anwendungsthreads, zwischen denen die CPU wechselt -- entweder wenn die + Threads die Kontrolle freiwillig abgeben (kooperatives Multitasking) + oder gesteuert durch Timer bzw. Interrupts (präemptives Multitasking). + Typischerweise stellen RTOS Mechanismen wie Mutexe und andere + Synchronisationsprimitive bereit und interagieren häufig mit + Hardwarefunktionen wie DMA-Controllern. +], +ja: [ + #todoupd("ja") + 組込み向け並行性の異なる一般的なモデルとして、リアルタイムオペレーティングシステム(RTOS)があります。 + 現在、Rustではあまり検証されていませんが、従来の組込み開発では広く使用されています。 + オープンソースの例として、#ln_freertos;と#ln_chibi;があります。 + これらのRTOSは、複数のアプリケーションスレッドを動作させる機能を提供しています。 + スレッドが制御を明け渡す時(コオペレーティブマルチタスク)か、 + 周期タイマまたは割り込みに基づく時(プリエンプティブマルチタスク)に、CPUで実行するスレッドを切り替えます。 + RTOSは、通常ミューテックスや他の同期プリミティブを提供します。また、DMAエンジンようなハードウェア機能を同時に使えることも多いです。 +], +zh: [ + #todoupd("zh") + 与嵌入式并发有关的另一个模型是实时操作系统(RTOS)。虽然现在在Rust中的研究较少,但是它们被广泛用于传统的嵌入式开发。开源的例子包括#ln_freertos;和#ln_chibi。这些RTOSs提供对运行多个应用线程的支持,CPU在这些线程间进行切换,切换要么发生在当线程让出控制权的时候(被称为非抢占式多任务),要么是基于一个常规计时器或者中断(抢占式多任务)。RTOS通常提供互斥量或者其它的同步原语,经常与硬件功能相互使用,比如DMA引擎。 +])) + +#tr(( +en: [ + At the time of writing, there are not many Rust RTOS examples to point + to, but it's an interesting area so watch this space! +], +de: [ + Zum jetzigen Zeitpunkt gibt es noch nicht viele Beispiele für Rust-RTOS, + auf die man verweisen könnte; es handelt sich jedoch um ein + interessantes Gebiet -- bleiben Sie also dran! +], +ja: [ + この本を書いている時点では、Rustで書かれたRTOSの例はそれほど多くありません。 + しかし、興味深い分野ですので、この分野にご注目下さい! +], +zh: [ + 在撰写本文时,没有太多的Rust RTOS示例可供参考,但这是一个有趣的领域,所以请关注这块! +])) + +== #tr(( + en: [Multiple Cores], + de: [Mehrere Kerne], + ja: [マルチコア], + zh: [多个核心], +)) + +#tr(( +en: [ + It is becoming more common to have two or more cores in embedded + processors, which adds an extra layer of complexity to concurrency. All + the examples using a critical section (including the + `cortex_m::interrupt::Mutex`) assume the only other execution thread is + the interrupt thread, but on a multi-core system that's no longer true. + Instead, we'll need synchronisation primitives designed for multiple + cores (also called SMP, for symmetric multi-processing). +], +de: [ + Es wird immer üblicher, eingebettete Prozessoren mit zwei oder mehr + Kernen auszustatten, was die Parallelverarbeitung zusätzlich + verkompliziert. Alle Beispiele mit kritischen Abschnitten + (einschließlich `cortex_m::interrupt::Mutex`) gehen davon aus, dass der + einzige weitere Ausführungsthread der Interrupt-Thread ist. Auf einem + Mehrkernsystem trifft dies jedoch nicht mehr zu. Stattdessen benötigen + wir Synchronisierungsprimitive, die speziell für Mehrkernsysteme (auch + SMP, für symmetrisches Multiprocessing, genannt) entwickelt wurden. +], +ja: [ + 組込みプロセッサにおいても、2個以上のコアを持つことがより一般的になってきています。 + このことは、並行性をさらに複雑にします。(`cortex_m::interrupt::Mutex`を含む)クリティカルセクションで使っている全ての例は、 + 他の実行スレッドは、割り込みスレッドだけであることを前提にしています。 + しかし、マルチコアシステムにおいては、これは当てはまりません。 + 代わりに、マルチコア(SMP; symmetric + multi-proccesingとも呼ばれます)向けに設計した同期プリミティブが必要になります。 +], +zh: [ + 在嵌入式处理器中有两个或者多个核心很正常,其为并发添加了额外一层复杂性。所有使用临界区的例子(包括`cortex_m::interrupt::Mutex`)都假设了另一个执行的线程仅是中断线程,但是在一个多核系统中,这不再是正确的假设。反而,我们将需要为多核设计的同步原语(也被叫做SMP,symmetric + multi-processing的缩写)。 +])) + +#tr(( +en: [ + These typically use the atomic instructions we saw earlier, since the + processing system will ensure that atomicity is maintained over all cores. +], +de: [ + Diese verwenden typischerweise die bereits erwähnten atomaren Befehle, + da das Verarbeitungssystem die Atomarität über alle Kerne hinweg gewährleistet. +], +ja: [ + 通常、これまでに見たアトミック命令を使用します。 + アトミック命令は、処理システムが全てのコア間でのアトミック性を維持してくれるためです。 +], +zh: [ + 我们之前看到的,这些通常使用原子指令,因为处理系统将确保原子性在所有的核中都保持着。 +])) + +#tr(( +en: [ + Covering these topics in detail is currently beyond the scope of this + book, but the general patterns are the same as for the single-core case. +], +de: [ + Eine detaillierte Behandlung dieser Themen würde den Rahmen dieses + Buches sprengen, die allgemeinen Muster sind jedoch dieselben wie im Einzelkernfall. +], +ja: [ + これらのトピックを詳細に説明することは、この本のスコープ範囲外ですが、 + 一般的なパターンはシングルコアの場合と同じです。 +], +zh: [ + 覆盖这些主题的细节已经超出了本书的范围,但是常规的模式与单核的相似。 +])) diff --git a/typ/config.typ b/typ/config.typ new file mode 100644 index 00000000..026a6bf5 --- /dev/null +++ b/typ/config.typ @@ -0,0 +1,75 @@ +#let default_lang = sys.inputs.at("default-lang", default: "en") +#let lang = sys.inputs.at("lang", default: default_lang) +#let goal = sys.inputs.at("goal", default: "publish") +#let languages = ( + "en": [English], + "de": [German], + "ja": [Japanese], + "uk": [Ukrainian], + "zh": [Chinese] +) +#let tgt = sys.inputs.at("target", default: "html") +#let whole = int(tgt == "pdf") + +// str: use in code blocks +#let todos = { + ( + en: "untranslated", + de: "unübersetzt", + ja: "未翻訳", + uk: "не перекладено", + zh: "未翻译", + ).at(lang) +} +// content: use in other places +#let todo = text( + fill: red, + todos +) +// str: use in code blocks +#let todoupds(l) = { + ( + en: "translation is outdated", + de: "die Übersetzung ist veraltet", + ja: "翻訳が古くなっています", + uk: "переклад застарів", + zh: "翻译已过时", + ).at(lang) +} // content: use in other places +#let todoupd(l) = text( + fill: orange, + todoupds(l) +) + +// content: use in other places +#let tr(dict, default: todo) = { + if true { + for l in dict.keys() { + assert(l in languages, message: "Language `"+l+"` is not supported yet") + } + } + dict.at( + lang, + default: if default != todo and default != todos { default } + else if goal == "publish" { dict.at(default_lang) } + else { default } + ) +} + +// str: use in code blocks +#let ts = tr.with(default: todos) + +#let h1(it, offset: 0) = { + if type(it) == dictionary { + it = tr(it) + } + if tgt == "pdf" { + heading(it, depth: 1, offset: offset) + } else { + title(it) + } + /*show title: it => { + heading(it.body, depth: 1, offset: offset) + } + title(it)*/ +} diff --git a/typ/design-patterns/hal/checklist.typ b/typ/design-patterns/hal/checklist.typ new file mode 100644 index 00000000..e86929fc --- /dev/null +++ b/typ/design-patterns/hal/checklist.typ @@ -0,0 +1,51 @@ +#import "../../config.typ": * + +#h1((en: [HAL Design Patterns Checklist], + de: [Checkliste HAL-Design-Muster], + zh: [HAL设计检查清单], +), offset: whole*2) + + +#tr(( +en: [ + *Naming* (_crate aligns with Rust naming conventions_) + - ☐ The crate is named appropriately (#link()[C-CRATE-NAME]) + - *Interoperability* (_crate interacts nicely with other library functionality_) + - ☐ Wrapper types provide a destructor method (#link()[C-FREE]) + - ☐ HALs reexport their register access crate (#link()[C-REEXPORT-PAC]) + - ☐ Types implement the `embedded-hal` traits (#link()[C-HAL-TRAITS]) + - *Predictability* (_crate enables legible code that acts how it looks_) + - ☐ Constructors are used instead of extension traits (#link()[C-CTOR]) + - *GPIO Interfaces* (_GPIO Interfaces follow a common pattern_) + - ☐ Pin types are zero-sized by default (#link()[C-ZST-PIN]) + - ☐ Pin types provide methods to erase pin and port (#link()[C-ERASED-PIN]) + - ☐ Pin state should be encoded as type parameters (#link()[C-PIN-STATE]) +], +de: [ + - *Benennung* (_Crate richtet sich nach den Namenskonventionen von Rust_) + - ☐ Das Crate trägt einen passenden Namen. (#link()[C-CRATE-NAME]) + - *Interoperabilität* (_das Crate harmoniert gut mit der Funktionalität anderer Bibliotheken_) + - ☐ Wrapper-Typen stellen eine Destruktor-Methode bereit. (#link()[C-FREE]) + - ☐ HALs exportieren ihr Registerzugriffs-Crate erneut. (#link()[C-REEXPORT-PAC]) + - ☐ Typen implementieren die `embedded-hal`-Traits. (#link()[C-HAL-TRAITS]) + - *Vorhersehbarkeit* (_Das Crate ermöglicht gut lesbaren Code, der sich so verhält, wie er aussieht_) + - ☐ Anstelle von Extension Traits werden Konstruktoren verwendet. (#link()[C-CTOR]) + - *GPIO-Schnittstellen* (_GPIO-Schnittstellen folgen einem einheitlichen Muster_) + - ☐ Pin-Typen haben standardmäßig die Größe Null. (#link()[C-ZST-PIN]) + - ☐ Pin-Typen stellen Methoden zum Löschen von Pins und Ports bereit. (#link()[C-ERASED-PIN]) + - ☐ Der Pin-Zustand sollte als Typparameter kodiert werden. (#link()[C-PIN-STATE]) +], +zh: [ +- *命名* (_crate要符合Rust命名规则_) + - ☐ crate被恰当地命名 (#link()[C-CRATE-NAME]) +- *互用性* (_crate要很好地与其它的库功能交互_) + - ☐ 封装类型提供一种析构方法 (#link()[C-FREE]) + - ☐ HALs重新导出了它们的寄存器访问crate (#link()[C-REEXPORT-PAC]) + - ☐ 类型实现了 `embedded-hal` traits (#link()[C-HAL-TRAITS]) +- *可预见性* (_crate的代码清晰可读,行为和看起来的一样_) + - ☐ 使用构造函数而不是扩展traits (#link()[C-CTOR]) +- *GPIO接口* (_GPIO接口要遵循一个公共的模式_) + - ☐ Pin类型默认是零大小类型 (#link()[C-ZST-PIN]) + - ☐ Pin类型提供擦除管脚和端口的方法 (#link()[C-ERASED-PIN]) + - ☐ Pin状态应该被编码为类型参数 (#link()[C-PIN-STATE]) +])) diff --git a/typ/design-patterns/hal/gpio.typ b/typ/design-patterns/hal/gpio.typ new file mode 100644 index 00000000..3d8668d8 --- /dev/null +++ b/typ/design-patterns/hal/gpio.typ @@ -0,0 +1,367 @@ +#import "../../config.typ": * + +#h1((en: [Recommendations for GPIO Interfaces], + de: [Empfehlungen für GPIO-Schnittstellen], + zh: [关于GPIO接口的建议], +), offset: whole*2) + + += #tr(( + en: [Pin types are zero-sized by default], + de: [Pin-Typen haben standardmäßig die Größe Null], + zh: [Pin类型默认是零大小的], +)) (C-ZST-PIN) + + +#tr(( +en: [ + GPIO Interfaces exposed by the HAL should provide dedicated zero-sized + types for each pin on every interface or port, resulting in a zero-cost + GPIO abstraction when all pin assignments are statically known. +], +de: [ + Die von der HAL bereitgestellten GPIO-Schnittstellen sollten für jeden + Pin jeder Schnittstelle oder jedes Ports einen dedizierten Datentyp der + Größe Null bereitstellen. Dies führt zu einer kostenlosen + GPIO-Abstraktion, wenn alle Pinbelegungen statisch bekannt sind. +], +zh: [ + 由HAL暴露的GPIO接口应该为所有接口或者端口上的每一个管脚提供一个专用的零大小类型,从而当所有的管脚分配静态已知时,提供一个零开销抽象。 +])) + +#tr(( +en: [ + Each GPIO Interface or Port should implement a `split` method returning + a struct with every pin. +], +de: [ + Jede GPIO-Schnittstelle oder jeder Port sollte eine `split`-Methode + implementieren, die eine Struktur mit allen Pins zurückgibt. +], +zh: [ + 每个GPIO接口或者端口应该实现一个`split`方法,它返回一个拥有所有管脚的结构体。 +])) + +#tr(( +en: [ + Example: +], +de: [ + Beispiel: +])) + +```rust +pub struct PA0; +pub struct PA1; +// ... + +pub struct PortA; + +impl PortA { + pub fn split(self) -> PortAPins { + PortAPins { + pa0: PA0, + pa1: PA1, + // ... + } + } +} + +pub struct PortAPins { + pub pa0: PA0, + pub pa1: PA1, + // ... +} +``` + += #tr(( + en: [Pin types provide methods to erase pin and port], + de: [Pin-Typen stellen Methoden zum Löschen von Pins und Ports bereit], + zh: [管脚类型提供方法去擦除管脚和端口], +)) (C-ERASED-PIN) + + +#tr(( +en: [ + Pins should provide type erasure methods that move their properties from + compile time to runtime, and allow more flexibility in applications. +], +de: [ + Pins sollten Methoden zur Typeliminierung (Type Erasure) bereitstellen, + die ihre Eigenschaften von der Kompilierzeit in die Laufzeit verlagern + und so mehr Flexibilität in Anwendungen ermöglichen. +], +zh: [ + 从编译时到运行时,管脚都应该提供可以改变属性的类型擦出方法,允许在应用中有更多的灵活性。 +])) + +#tr(( +en: [ + Example: +], +de: [ + Beispiel: +], +zh: [ + 案例: +])) + +#raw(block: true, lang: "rust", +"/// " + ts(( + en: "Port A, pin 0.", + de: "Port A, pin 0.", + zh: "端口 A, 管脚 0。", + )) + " +pub struct PA0; + +impl PA0 { + pub fn erase_pin(self) -> PA { + PA { pin: 0 } + } +} + +/// " + ts(( + en: "A pin on port A.", + de: "A pin on port A.", + zh: "端口A上的A管脚。", + )) + " +pub struct PA { + /// " + ts(( + en: "The pin number.", + zh: "管脚号。", + )) + " + pin: u8, +} + +impl PA { + pub fn erase_port(self) -> Pin { + Pin { + port: Port::A, + pin: self.pin, + } + } +} + +pub struct Pin { + port: Port, + pin: u8, + // " + ts(( + en: "(these fields can be packed to reduce the memory footprint)", + de: "(Diese Felder koennen gepackt werden, um den Speicherbedarf zu + // verringern.)", + zh: "(这些字段) + // (这些字段可以打包以减少内存占用)", + )) + " +} + +enum Port { + A, + B, + C, + D, +} +") + += #tr(( + en: [Pin state should be encoded as type parameters], + de: [Der Pin-Zustand sollte als Typparameter kodiert werden], + zh: [管脚状态应该被编码成类型参数], +)) (C-PIN-STATE) + + +#tr(( +en: [ + Pins may be configured as input or output with different characteristics + depending on the chip or family. This state should be encoded in the + type system to prevent use of pins in incorrect states. +], +de: [ + Je nach Chip oder Chipfamilie können Pins als Eingang oder Ausgang mit + unterschiedlichen Eigenschaften konfiguriert werden. Dieser Zustand + sollte im Typsystem abgebildet werden, um eine Verwendung der Pins in + einem falschen Zustand zu verhindern. +], +zh: [ + 取决于芯片或者芯片系列,管脚可能被配置为具有不同特性的输出或者输入。这个状态应该编码进类型系统中以避免在错误的状态中使用管脚。 +])) + +#tr(( +en: [ + Additional, chip-specific state (eg. drive strength) may also be encoded + in this way, using additional type parameters. +], +de: [ + Auch zusätzliche, chip-spezifische Zustände (z. B. die Treiberstärke) + lassen sich auf diese Weise mittels zusätzlicher Typparameter kodieren. +], +zh: [ + 另外,也可以用这个方法使用额外的类型参数编码芯片特定的状态(eg. + 驱动强度)。 +])) + +#tr(( +en: [ + Methods for changing the pin state should be provided as `into_input` + and `into_output` methods. +], +de: [ + Methoden zur Änderung des Pin-Zustands sollten als `into_input` und + `into_output` bereitgestellt werden. +], +zh: [ + 用来改变管脚状态的方法应该被实现成`into_input`和`into_output`方法。 +])) + +#tr(( +en: [ + Additionally, `with_{input,output}_state` methods should be provided + that temporarily reconfigure a pin in a different state without moving it. +], +de: [ + Zusätzlich sollten Methoden wie `with_{input,output}_state` angeboten + werden, die einen Pin vorübergehend in einen anderen Zustand versetzen, + ohne ihn zu verschieben (d.~h. ohne Eigentumsübergang). +], +zh: [ + 另外,应该提供`with_{input,output}_state`方法,在一个不同的状态中临时配置一个管脚而不是移动它。 +])) + +#tr(( +en: [ + The following methods should be provided for every pin type (that is, + both erased and non-erased pin types should provide the same API): +], +de: [ + Für jeden Pin-Typ sollten die folgenden Methoden bereitgestellt werden + (das heißt, sowohl „erased" als auch „non-erased" Pin-Typen müssen + dieselbe API bieten): +], +zh: [ + 应该为每个的管脚类型提供下列的方法(也就是说,已擦除和未擦除的管脚类型应该提供一样的API): +])) +- `pub fn into_input(self, input: N) -> Pin` +- `pub fn into_output(self, output: N) -> Pin` +- ```rust + pub fn with_input_state( + &mut self, + input: N, + f: impl FnOnce(&mut PA1) -> R, + ) -> R + ``` +- ```rust + pub fn with_output_state( + &mut self, + output: N, + f: impl FnOnce(&mut PA1) -> R, + ) -> R + ``` + +#tr(( +en: [ + Pin state should be bounded by sealed traits. Users of the HAL should + have no need to add their own state. The traits can provide HAL-specific + methods required to implement the pin state API. +], +de: [ + Der Pin-Zustand sollte durch „Sealed Traits" eingeschränkt sein. Nutzer + des HAL sollten keinen eigenen Zustand hinzufügen müssen. Die Traits + können HAL-spezifische Methoden bereitstellen, die für die + Implementierung der Pin-Zustands-API erforderlich sind. +], +zh: [ + 管脚状态应该用sealed + traits来绑定。HAL的用户不必添加他们自己的状态。这个traits能提供HAL特定的方法,实现管脚状态API需要这些方法。 +])) + +#tr(( +en: [ + Example: +], +de: [ + Beispiel: +], +zh: [ + 案例: +])) + +#raw(block: true, lang: "rust", +"# use std::marker::PhantomData; +mod sealed { + pub trait Sealed {} +} + +pub trait PinState: sealed::Sealed {} +pub trait OutputState: sealed::Sealed {} +pub trait InputState: sealed::Sealed { + // ... +} + +pub struct Output { + _p: PhantomData, +} + +impl PinState for Output {} +impl sealed::Sealed for Output {} + +pub struct PushPull; +pub struct OpenDrain; + +impl OutputState for PushPull {} +impl OutputState for OpenDrain {} +impl sealed::Sealed for PushPull {} +impl sealed::Sealed for OpenDrain {} + +pub struct Input { + _p: PhantomData, +} + +impl PinState for Input {} +impl sealed::Sealed for Input {} + +pub struct Floating; +pub struct PullUp; +pub struct PullDown; + +impl InputState for Floating {} +impl InputState for PullUp {} +impl InputState for PullDown {} +impl sealed::Sealed for Floating {} +impl sealed::Sealed for PullUp {} +impl sealed::Sealed for PullDown {} + +pub struct PA1 { + _p: PhantomData, +} + +impl PA1 { + pub fn into_input(self, input: N) -> PA1> { + todo!() + } + + pub fn into_output(self, output: N) -> PA1> { + todo!() + } + + pub fn with_input_state( + &mut self, + input: N, + f: impl FnOnce(&mut PA1) -> R, + ) -> R { + todo!() + } + + pub fn with_output_state( + &mut self, + output: N, + f: impl FnOnce(&mut PA1) -> R, + ) -> R { + todo!() + } +} + +// " + ts(( + en: "Same for `PA` and `Pin`, and other pin types.", + de: "Dasselbe gilt fuer `PA` und `Pin` sowie andere Pin-Typen.", + zh: "对于`PA`和`Pin`一样的,对于其它管脚类型来说也是。", + )) + " +") diff --git a/typ/design-patterns/hal/index.typ b/typ/design-patterns/hal/index.typ new file mode 100644 index 00000000..86f1e643 --- /dev/null +++ b/typ/design-patterns/hal/index.typ @@ -0,0 +1,43 @@ +#import "../../config.typ": * + +#h1((en: [HAL Design Patterns], + de: [HAL-Design-Muster], + zh: [HAL设计模式], +), offset: whole) + +#let url_quide = "https://rust-lang.github.io/api-guidelines/" +#tr(( +en: [ + This is a set of common and recommended patterns for writing hardware + abstraction layers (HALs) for microcontrollers in Rust. These patterns + are intended to be used in addition to the existing + #link(url_quide)[Rust API Guidelines] + when writing HALs for microcontrollers. + - #link()[Checklist] + - #link()[Naming] + - #link()[Interoperability] + - #link()[Predictability] + - #link()[GPIO] +], +de: [ + Hierbei handelt es sich um eine Sammlung bewährter und empfohlener + Muster für die Implementierung von Hardware-Abstraktionsschichten (HALs) + für Mikrocontroller in Rust. Diese Muster sind als Ergänzung zu den + bestehenden #link(url_quide)[Rust-API-Richtlinien] + für die Entwicklung von HALs für Mikrocontroller gedacht. + #link()[Checkliste] + - #link()[Benennung] + - #link()[Interoperabilität] + - #link()[Vorhersehbarkeit] + - #link()[GPIO] +], +zh: [ + 这是一组关于使用Rust为微控制器写硬件抽象层的常见的和推荐的模式。当为微控制器编写HALs时,除了现有的 + #link(url_quide)[Rust API 指南] + 外,也可以使用这些模式。 + #link()[检查清单] + - #link()[命名] + - #link()[互用性] + - #link()[可预见性] + - #link()[GPIO] +])) diff --git a/typ/design-patterns/hal/interoperability.typ b/typ/design-patterns/hal/interoperability.typ new file mode 100644 index 00000000..19981169 --- /dev/null +++ b/typ/design-patterns/hal/interoperability.typ @@ -0,0 +1,164 @@ +#import "../../config.typ": * + +#h1((en: [Interoperability], + de: [Interoperabilität], + zh: [互用性], +), offset: whole*2) + + += #tr(( + en: [Wrapper types provide a destructor method], + de: [Wrapper-Typen stellen eine Destruktor-Methode bereit], + zh: [封装类型提供一个析构方法], +)) (C-FREE) + + +#tr(( +en: [ + Any non-`Copy` wrapper type provided by the HAL should provide a `free` + method that consumes the wrapper and returns back the raw peripheral + (and possibly other objects) it was created from. +], +de: [ + Jeder vom HAL bereitgestellte Wrapper-Typ, der nicht `Copy` + implementiert, sollte eine `free`-Methode anbieten; diese verbraucht den + Wrapper und gibt das rohe Peripheriegerät (sowie gegebenenfalls weitere + Objekte), aus dem er erstellt wurde, wieder frei. +], +zh: [ + 任何由HAL提供的非`Copy`封装类型应该提供一个`free`方法,这个方法消费封装类且返回最初生成它的外设(可能是其它对象)。 +])) + +#tr(( +en: [ + The method should shut down and reset the peripheral if necessary. + Calling `new` with the raw peripheral returned by `free` should not fail + due to an unexpected state of the peripheral. +], +de: [ + Die Methode sollte das Peripheriegerät bei Bedarf deaktivieren und + zurücksetzen. Ein Aufruf von `new` mit dem durch `free` zurückgegebenen + rohen Peripheriegerät darf nicht aufgrund eines unerwarteten Zustands + des Geräts fehlschlagen. +], +zh: [ + 如果有必要,方法应该关闭和重置外设。使用由`free`返回的原始外设去调用`new`不应该由于设备的意外状态而失败, +])) + +#tr(( +en: [ + If the HAL type requires other non-`Copy` objects to be constructed (for + example I/O pins), any such object should be released and returned by + `free` as well. `free` should return a tuple in that case. +], +de: [ + Falls für die Konstruktion des HAL-Typs weitere Objekte erforderlich + sind, die nicht `Copy` implementieren (zum Beispiel I/O-Pins), sollten + auch diese Objekte durch `free` freigegeben und zurückgegeben werden. In + diesem Fall sollte `free` ein Tupel zurückgeben. +], +zh: [ + 如果HAL类型要求构造其它的非`Copy`对象(比如 I/O + 管脚),任何这样的对象应该也由`free`返回和释放。在这种情况下`free`应该返回一个元组。 +])) + +#tr(( +en: [ + For example: +], +de: [ + Zum Beispiel: +], +zh: [ + 比如: +])) + +```rust +# pub struct TIMER0; +pub struct Timer(TIMER0); + +impl Timer { + pub fn new(periph: TIMER0) -> Self { + Self(periph) + } + + pub fn free(self) -> TIMER0 { + self.0 + } +} +``` + += #tr(( + en: [HALs reexport their register access crate], + de: [HALs exportieren ihr Registerzugriffs-Crate erneut], + zh: [HALs重新导出它们的寄存器访问crate], +)) (C-REEXPORT-PAC) + + +#let ln_svd2rust = link("https://github.com/rust-embedded/svd2rust")[svd2rust] +#tr(( +en: [ + HALs can be written on top of #ln_svd2rust;-generated + PACs, or on top of other crates that provide raw register access. HALs + should always reexport the register access crate they are based on in + their crate root. +], +de: [ + HALs können auf der Basis von mit + #ln_svd2rust generierten + PACs oder anderen Crates implementiert werden, die einen direkten + Registerzugriff ermöglichen. HALs sollten das Crate für den + Registerzugriff, auf dem sie aufbauen, stets an der Wurzel ihres eigenen + Crates erneut exportieren (re-exportieren). +], +zh: [ + 可以在#ln_svd2rust;生成的PACs之上,或在其它纯寄存器访问的crates之上编写HALs。HALs需要在crate + root中重新导出它们所基于的寄存器访问crate +])) + +#tr(( +en: [ + A PAC should be reexported under the name `pac`, regardless of the + actual name of the crate, as the name of the HAL should already make it + clear what PAC is being accessed. +], +de: [ + Ein PAC sollte unter dem Namen `pac` re-exportiert werden -- unabhängig + vom eigentlichen Namen des Crates --, da bereits der Name der HAL + verdeutlichen sollte, auf welches PAC zugegriffen wird. +], +zh: [ + 一个PAC应该被重新导出在`pac`名下,无论这个crate实际的名字是什么,因为HAL的名字应该已经明确了正被访问的是什么PAC +])) + += #tr(( + en: [Types implement the `embedded-hal` traits], + de: [Typen implementieren die `embedded-hal`-Traits], + zh: [类型实现`embedded-hal` traits], +)) (C-HAL-TRAITS) + + +#let ln_hal = link("https://github.com/rust-embedded/embedded-hal")[`embedded-hal`] +#tr(( +en: [ + Types provided by the HAL should implement all applicable traits + provided by the #ln_hal crate. +], +de: [ + Vom HAL bereitgestellte Typen sollten alle anwendbaren Traits + implementieren, die vom #ln_hal;-Crate bereitgestellt werden. +], +zh: [ + HAL提供的类型应该实现所有的由#ln_hal crate提供的能用的traits。 +])) + +#tr(( +en: [ + Multiple traits may be implemented for the same type. +], +de: [ + Für denselben Typ können mehrere Traits implementiert werden. +], +zh: [ + 同个类型可能实现多个traits。 +])) diff --git a/typ/design-patterns/hal/naming.typ b/typ/design-patterns/hal/naming.typ new file mode 100644 index 00000000..43af582d --- /dev/null +++ b/typ/design-patterns/hal/naming.typ @@ -0,0 +1,31 @@ +#import "../../config.typ": * + +#h1((en: [Naming], + de: [Benennung], + zh: [命名], +), offset: whole*2) + + += #tr(( + en: [The crate is named appropriately], + de: [Das Crate trägt einen passenden Namen], + zh: [crate要被恰当地命名], +)) (C-CRATE-NAME) + + +#tr(( +en: [ + HAL crates should be named after the chip or family of chips they aim to + support. Their name should end with `-hal` to distinguish them from + register access crates. The name should not contain underscores (use + dashes instead). +], +de: [ + HAL-Crates sollten nach dem Chip oder der Chip-Familie benannt werden, + die sie unterstützen sollen. Ihr Name sollte auf `-hal` enden, um sie + von Registerzugriffs-Crates zu unterscheiden. Der Name sollte keine + Unterstriche enthalten (stattdessen sind Bindestriche zu verwenden). +], +zh: [ + HAL crates应该在目标支持的芯片或者芯片系列之后被命名。它们的名字应该以`-hal`结尾,为了将它们与PAC区分开来。名字不应该包含下划线(请改用破折号)。 +])) diff --git a/typ/design-patterns/hal/predictability.typ b/typ/design-patterns/hal/predictability.typ new file mode 100644 index 00000000..a436f2fc --- /dev/null +++ b/typ/design-patterns/hal/predictability.typ @@ -0,0 +1,86 @@ +#import "../../config.typ": * + +#h1((en: [Predictability], + de: [Vorhersehbarkeit], + zh: [可预见性], +), offset: whole*2) + + += #tr(( + en: [Constructors are used instead of extension traits], + de: [Anstelle von Extension Traits werden Konstruktoren verwendet], + zh: [使用构造函数而不是扩展traits], +)) (C-CTOR) + + +#tr(( +en: [ + All peripherals to which the HAL adds functionality should be wrapped in + a new type, even if no additional fields are required for that + functionality. +], +de: [ + Alle Peripheriegeräte, denen die HAL Funktionalität hinzufügt, sollten + in einen neuen Typ gekapselt werden -- selbst dann, wenn für diese + Funktionalität keine zusätzlichen Felder erforderlich sind. +], +zh: [ + 所有由HAL添加功能的外设应该被封装进一个新类型,即使该功能不需要额外的字段。 +])) + +#tr(( +en: [ + Extension traits implemented for the raw peripheral should be avoided. +], +de: [ + Die Implementierung von Extension Traits für das rohe Peripheriegerät + (Raw Peripheral) sollte vermieden werden. +], +zh: [ + 应该避免为基本外设扩展traits。 +])) + += #tr(( + en: [Methods are decorated with `#[inline]` where appropriate], + de: [Methoden werden dort, wo es angebracht ist, mit `#[inline]` + versehen], + zh: [方法在适当的地方用`#[inline]`修饰], +)) (C-INLINE) + + +#tr(( +en: [ + The Rust compiler does not by default perform full inlining across crate + boundaries. As embedded applications are sensitive to unexpected code + size increases, `#[inline]` should be used to guide the compiler as + follows: + - All "small" functions should be marked `#[inline]`. What qualifies as + "small" is subjective, but generally all functions that are expected + to compile down to single-digit instruction sequences qualify as + small. + - Functions that are very likely to take constant values as parameters + should be marked as `#[inline]`. This enables the compiler to compute + even complicated initialization logic at compile time, provided the + function inputs are known. +], +de: [ + Der Rust-Compiler führt standardmäßig kein vollständiges Inlining über + Crate-Grenzen hinweg durch. Da eingebettete Anwendungen empfindlich auf + unerwartete Vergrößerungen des Codes reagieren, sollte `#[inline]` + verwendet werden, um den Compiler wie folgt zu steuern: + - Alle „kleinen" Funktionen sollten mit `#[inline]` gekennzeichnet + werden. Was als „klein" gilt, ist subjektiv; im Allgemeinen zählen + jedoch alle Funktionen dazu, die voraussichtlich zu einer Sequenz von + nur wenigen Maschinenbefehlen kompiliert werden. + - Funktionen, die sehr wahrscheinlich konstante Werte als Parameter + erhalten, sollten mit `#[inline]` gekennzeichnet werden. Dies + ermöglicht es dem Compiler, selbst komplexe Initialisierungslogik zur + Kompilierzeit zu berechnen, sofern die Eingabewerte der Funktion + bekannt sind. +], +zh: [ + Rust编译器默认不会越过crate边界执行完全内联。因为嵌入式应用对于不可预期的代码大小的增加很敏感,`#[inline]`应该如下所示用来指导编译器: + - 所有的"小"函数应该被标记`#[inline]`。什么是"小"是主观的,但是通常所有有可能被编译成一位数的指令序列(single-digit + instruction sequences)都可以被视为"小"。 + - 非常有可能把一个常量数值作为参数的函数应该被标记为`#[inline]`。这让编译器在编译时就可以进行计算甚至是复杂的初始化逻辑,前提是函数输入是已知的。 +])) diff --git a/typ/design-patterns/index.typ b/typ/design-patterns/index.typ new file mode 100644 index 00000000..1dd0f266 --- /dev/null +++ b/typ/design-patterns/index.typ @@ -0,0 +1,18 @@ +#import "../config.typ": * + +#h1((en: [Design Patterns], + de: [Design-Muster], + zh: [设计模式], +)) + +#tr(( +en: [ + This chapter aims to collect various useful design patterns for embedded Rust. +], +de: [ + Dieses Kapitel zielt darauf ab, verschiedene nützliche Entwurfsmuster + für Embedded-Rust zusammenzustellen. +], +zh: [ + 这个章节的目标是为嵌入式Rust收集不同的有用的设计模式。 +])) diff --git a/typ/interoperability/c-with-rust.typ b/typ/interoperability/c-with-rust.typ new file mode 100644 index 00000000..064e88f6 --- /dev/null +++ b/typ/interoperability/c-with-rust.typ @@ -0,0 +1,687 @@ +#import "../config.typ": * + +#h1((en: [A little C with your Rust], + de: [Ein bisschen C zu Ihrem Rust], + ja: [Rustと少しのC], + zh: [使用C的Rust], +), offset: whole) + + +#tr(( +en: [ + Using C or C++ inside of a Rust project consists of two major parts: + - Wrapping the exposed C API for use with Rust + - Building your C or C++ code to be integrated with the Rust code +], +de: [ + Die Verwendung von C oder C++ innerhalb eines Rust-Projekts umfasst zwei + wesentliche Aspekte: + - Einkapselung der bereitgestellten C-API für die Verwendung mit Rust + - Erstellen Ihres C- oder C++-Codes zur Integration mit dem Rust-Code +], +ja: [ + CまたはC++をRustプロジェクトの内部で使うには、主に2つの対応をします。 + - 公開されているCのAPIを、Rustで使えるようにラッピングする + - CまたはC++のコードを、Rustのコードと一緒にビルドする +], +zh: [ + 要在一个Rust项目中使用C或者C++,主要有两个步骤: + - 用Rust封装要暴露出来使用的C API + - 编译要和Rust代码集成在一起的C或者C++代码 +])) + +#tr(( +en: [ + As C++ does not have a stable ABI for the Rust compiler to target, it is + recommended to use the `C` ABI when combining Rust with C or C++. +], +de: [ + Da C++ über keine stabile ABI verfügt, auf die der Rust-Compiler + abzielen könnte, wird empfohlen, bei der Kombination von Rust mit C oder + C++ die `C`-ABI zu verwenden. +], +ja: [ + C++は、Rustコンパイラがターゲットにできる安定したABIを持っていないため、CまたはC++とRustとを組み合わせるときは、`C`のABIを使うのがお勧めです。 +], +zh: [ + 因为对于Rust编译器来说,C++没有一个稳定的ABI,当要将Rust和C或者C++结合时,建议优先选择`C`。 +])) + += #tr(( + en: [Defining the interface], + de: [Definition der Schnittstelle], + ja: [インタフェースの定義], + zh: [定义接口], +)) + +#tr(( +en: [ + Before consuming C or C++ code from Rust, it is necessary to define (in + Rust) what data types and function signatures exist in the linked code. + In C or C++, you would include a header (`.h` or `.hpp`) file which + defines this data. In Rust, it is necessary to either manually translate + these definitions to Rust, or use a tool to generate these definitions. +], +de: [ + Bevor C- oder C++-Code aus Rust heraus verwendet werden kann, muss (in + Rust) definiert werden, welche Datentypen und Funktionssignaturen im + verlinkten Code vorhanden sind. In C oder C++ würde man eine + Header-Datei (`.h` oder `.hpp`) einbinden, die diese Daten definiert. In + Rust ist es erforderlich, diese Definitionen entweder manuell nach Rust + zu übertragen oder ein Werkzeug zu ihrer Generierung zu verwenden. +], +ja: [ + RustからCまたはC++のコードを使う前に、リンクされるコードにどのようなデータ型や関数シグネチャが存在するかを、(Rustに)定義する必要があります。 + CまたはC++では、このデータを定義したヘッダファイル(`.h`または`.hpp`)をインクルードします。 + Rustでは、これらの定義を手動で変換するか、定義を自動生成するツールを使うか、のいずれかが必要です。 +], +zh: [ + 在Rust消费C或者C++代码之前,必须定义(在Rust中定义),在要被链接的代码中存在什么数据类型和函数签名。在C或者C++中,你要包含一个头文件(`.h`或者`.hpp`),其定义了这个数据。而在Rust中,必须手动地将这些定义翻译成Rust,或者使用一个工具去生成这些定义。 +])) + +#tr(( +en: [ + First, we will cover manually translating these definitions from C/C++ + to Rust. +], +de: [ + Zunächst behandeln wir die manuelle Übertragung dieser Definitionen von + C/C++ nach Rust. +], +ja: [ + まずは、C/C++からRustに、定義を手動で変換する方法を説明します。 +], +zh: [ + 首先,我们将介绍如何将这些定义从C/C++手动地转换为Rust。 +])) + +== #tr(( + en: [Wrapping C functions and Datatypes], + de: [Einbinden von C-Funktionen und -Datentypen], + ja: [Cの関数とデータ型のラッピング], + zh: [封装C函数和数据类型], +)) + +#tr(( +en: [ + Typically, libraries written in C or C++ will provide a header file + defining all types and functions used in public interfaces. An example + file may look like this: +], +de: [ + Typischerweise stellen in C oder C++ geschriebene Bibliotheken eine + Header-Datei bereit, die alle in öffentlichen Schnittstellen verwendeten + Typen und Funktionen definiert. Eine Beispieldatei könnte wie folgt aussehen: +], +ja: [ + 通常、CまたはC++で書かれたライブラリは、公開インタフェースで使用する全ての型と関数を定義するヘッダファイルを提供します。 + ヘッダファイルの例は次の通りです。 +], +zh: [ + 通常,用C或者C++写的库会提供一个头文件,头文件定义了所有的类型和用于公共接口的函数。如下是一个示例文件: +])) + +```c +/* File: cool.h */ +typedef struct CoolStruct { + int x; + int y; +} CoolStruct; + +void cool_function(int i, char c, CoolStruct* cs); +``` + +#tr(( +en: [ + When translated to Rust, this interface would look as such: +], +de: [ + Nach Rust übertragen, sähe diese Schnittstelle folgendermaßen aus: +], +ja: [ + Rustに変換すると、このインタフェースは次のようになります。 +], +zh: [ + 当翻译成Rust时,这个接口将看起来像是: +])) + +```rust +/* File: cool_bindings.rs */ +#[repr(C)] +pub struct CoolStruct { + pub x: cty::c_int, + pub y: cty::c_int, +} + +extern "C" { + pub fn cool_function( + i: cty::c_int, + c: cty::c_char, + cs: *mut CoolStruct + ); +} +``` + +#tr(( +en: [ + Let's take a look at this definition one piece at a time, to explain + each of the parts. +], +de: [ + Schauen wir uns diese Definition Schritt für Schritt an, um die + einzelnen Bestandteile zu erläutern. +], +ja: [ + 各部分の説明をするため、この定義を1つずつ見ていきましょう。 +], +zh: [ + 让我们一次看一个语句,来解释每个部分。 +])) + +```rust +#[repr(C)] +pub struct CoolStruct { ... } +``` + +#tr(( +en: [ + By default, Rust does not guarantee order, padding, or the size of data + included in a `struct`. In order to guarantee compatibility with C code, + we include the `#[repr(C)]` attribute, which instructs the Rust compiler + to always use the same rules C does for organizing data within a struct. +], +de: [ + Standardmäßig garantiert Rust weder die Reihenfolge noch das Padding + oder die Größe der in einer `struct` enthaltenen Daten. Um die + Kompatibilität mit C-Code zu gewährleisten, verwenden wir das Attribut + `#[repr(C)]`; dieses weist den Rust-Compiler an, für die Anordnung der + Daten innerhalb der Struktur stets dieselben Regeln wie C anzuwenden. +], +ja: [ + デフォルトでは、Rustは`struct`に含まれるデータの順序やパディング、サイズを保証しません。 + Cのコードとの互換性を保証するために、`#[repr(C)]`アトリビュートを使います。 + このアトリビュートにより、Rustコンパイラは、構造体のデータをCと同じルールで構成します。 +], +zh: [ + 默认,Rust不会保证包含在`struct`中的数据的大小,填充,或者顺序。为了保证与C代码兼容,我们使用`#[repr(C)]`属性,它指示Rust编译器总是使用和C一样的规则去组织一个结构体中的数据。 +])) + + +```rust +pub x: cty::c_int, +pub y: cty::c_int, +``` + +#tr(( +en: [ + Due to the flexibility of how C or C++ defines an `int` or `char`, it is + recommended to use primitive data types defined in `cty`, which will map + types from C to types in Rust. +], +de: [ + Aufgrund der Flexibilität, wie C oder C++ ein „int" oder „char" + definiert, wird empfohlen, in „cty" definierte primitive Datentypen zu + verwenden, die Typen von C auf Typen in Rust abbilden. +], +ja: [ + CまたはC++が`int`や`char`を定義する方法は柔軟であるため、`cty`で定義されているプリミティブデータ型の使用をお勧めします。 + ctyは、Cの型をRustの型にマップします。 +], +zh: [ + 由于C或者C++定义一个`int`或者`char`的方式很灵活,所以建议使用在`cty`中定义的基础类型,它将类型从C映射到Rust中的类型。 +])) + +```rust +extern "C" { pub fn cool_function( ... ); } +``` + +#tr(( +en: [ + This statement defines the signature of a function that uses the C ABI, + called `cool_function`. By defining the signature without defining the + body of the function, the definition of this function will need to be + provided elsewhere, or linked into the final library or binary from a + static library. +], +de: [ + Diese Anweisung definiert die Signatur einer Funktion namens + `cool_function`, die die C-ABI verwendet. Da die Signatur ohne den + Funktionsrumpf definiert wird, muss die eigentliche Funktionsdefinition + an anderer Stelle bereitgestellt oder aus einer statischen Bibliothek in + die endgültige Bibliothek bzw. das fertige Binärprogramm eingebunden werden. +], +ja: [ + このステートメントは、`cool_function`という名前の、CのABIを使った関数シグネチャを定義します。 + 関数本体の定義なしにシグネチャを定義することで、この関数の定義は別の場所で与えられるか、静的ライブラリから最終的なライブラリまたはバイナリにリンクされる必要があります。 +], +zh: [ + 这个语句定义了一个使用C + ABI的函数的签名,叫做`cool_function`。因为只定义了签名而没有定义函数的主体,所以这个函数的定义将需要在其它地方定义,或者从一个静态库链接进最终的库或者一个二进制文件中。 +])) + +```rust + i: cty::c_int, + c: cty::c_char, + cs: *mut CoolStruct +``` + +#tr(( +en: [ + Similar to our datatype above, we define the datatypes of the function + arguments using C-compatible definitions. We also retain the same + argument names, for clarity. +], +de: [ + Ähnlich wie bei unserem obigen Datentyp definieren wir die Datentypen + der Funktionsargumente mithilfe von C-kompatiblen Definitionen. Der + Übersichtlichkeit halber behalten wir zudem die ursprünglichen Argumentnamen bei. +], +ja: [ + 上記のデータ型と同様に、Cと互換の定義を使って、関数の引数のデータ型を定義します。 + わかりやすくするために、引数の名前は同じままにしてあります。 +], +zh: [ + 与我们上面的数据类型一样,我们使用C兼容的定义去定义函数参数的数据类型。为了清晰可见,我们还保留了相同的参数名。 +])) + +#tr(( +en: [ + We have one new type here, `*mut CoolStruct`. As C does not have a + concept of Rust's references, which would look like this: + `&mut CoolStruct`, we instead have a raw pointer. As dereferencing this + pointer is `unsafe`, and the pointer may in fact be a `null` pointer, + care must be taken to ensure the guarantees typical of Rust when + interacting with C or C++ code. +], +de: [ + Hier begegnet uns ein neuer Typ: `*mut CoolStruct`. Da C das Konzept der + Rust-Referenzen (die etwa so aussehen: `&mut CoolStruct`) nicht kennt, + verwenden wir stattdessen einen sogenannten „Raw Pointer" (Rohzeiger). + Da das Dereferenzieren dieses Zeigers als `unsafe` gilt und es sich + tatsächlich um einen `null`-Zeiger handeln kann, ist bei der Interaktion + mit C- oder C++-Code besondere Sorgfalt geboten, um die für Rust + typischen Garantien zu wahren. +], +ja: [ + `*mut CoolStruct`という新しい型があります。Cは、`&mut CoolStruct`のようなRustの参照という概念を持っていません。 + 代わりに、生ポインタを使います。 + このポインタの参照外しは、`unsafe`です。また、このポインタは実際に`null`ポインタになる可能性があります。 + CまたはC++のコードとやり取りする時には、Rustが通常行う保証を確実にするように気をつける必要があります。 +], +zh: [ + 这里我们有了一个新类型,`*mut CoolStruct` 。因为C没有Rust中像 + `&mut CoolStruct` + 这样的引用,替代的是一个裸指针。所以解引用这个指针是`unsafe`的,因为这个指针实际上可能是一个`null`指针,因此当与C或者C++代码交互时必须要小心对待那些Rust做出的安全保证。 +])) + +== #tr(( + en: [Automatically generating the interface], + de: [Automatische Generierung der Schnittstelle], + ja: [インタフェースの自動生成], + zh: [自动产生接口], +)) + +#let url_bindgen = "https://github.com/rust-lang/rust-bindgen" +#let url_bindgen_manual = "https://rust-lang.github.io/rust-bindgen/" +#let ln_cty = link("https://crates.io/crates/cty")[`cty`] +#tr(( +en: [ + Rather than manually generating these interfaces, which may be tedious + and error prone, there is a tool called + #link(url_bindgen)[bindgen] which will + perform these conversions automatically. For instructions of the usage + of #link(url_bindgen)[bindgen], please + refer to the #link(url_bindgen_manual)[bindgen user's manual], + however the typical process consists of the following: + + Gather all C or C++ headers defining interfaces or datatypes you would + like to use with Rust. + + Write a `bindings.h` file, which `#include "..."`'s each of the files + you gathered in step one. + + Feed this `bindings.h` file, along with any compilation flags used to + compile your code into `bindgen`. Tip: use + `Builder.ctypes_prefix("cty")` / `--ctypes-prefix=cty` and + `Builder.use_core()` / `--use-core` to make the generated code + `#![no_std]` compatible. + + `bindgen` will produce the generated Rust code to the output of the + terminal window. This output may be piped to a file in your project, + such as `bindings.rs`. You may use this file in your Rust project to + interact with C/C++ code compiled and linked as an external library. + Tip: don't forget to use the #ln_cty crate if your types in + the generated bindings are prefixed with `cty`. +], +de: [ + Anstatt diese Schnittstellen manuell zu erstellen -- was mühsam und + fehleranfällig sein kann --, gibt es ein Werkzeug namens + #link(url_bindgen)[bindgen], das diese + Konvertierungen automatisch durchführt. Hinweise zur Verwendung von + #link(url_bindgen)[bindgen] finden Sie im + #link(url_bindgen_manual)[bindgen-Benutzerhandbuch]\; + der typische Ablauf sieht jedoch folgendermaßen aus: + + Sammeln Sie alle C- oder C++-Header, die Schnittstellen oder + Datentypen definieren, die Sie mit Rust verwenden möchten. + + Erstelle eine Datei namens `bindings.h`, die mittels `#include "..."` + jede der Dateien einbindet, die du in Schritt eins zusammengetragen + hast. + + Übergeben Sie diese `bindings.h`-Datei zusammen mit den für die + Kompilierung Ihres Codes verwendeten Flags an `bindgen`. Tipp: + Verwenden Sie `Builder.ctypes_prefix("cty")` / `--ctypes-prefix=cty` + und `Builder.use_core()` / `--use-core`, um den generierten Code + `#![no_std]`-kompatibel zu machen. + + `bindgen` gibt den generierten Rust-Code direkt im Terminal aus. Diese + Ausgabe lässt sich in eine Datei Ihres Projekts umleiten, + beispielsweise `bindings.rs`. Sie können diese Datei in Ihrem + Rust-Projekt verwenden, um mit C/C++-Code zu interagieren, der als + externe Bibliothek kompiliert und gelinkt wurde. Tipp: Vergessen Sie + nicht, das #ln_cty;-Crate zu + verwenden, falls die Typen in den generierten Bindings das Präfix + `cty` aufweisen. +], +ja: [ + 面倒であり間違いの元である手動のインタフェース生成ではなく、#link(url_bindgen)[bindgen]と呼ばれるインタフェース変換を自動で行ってくれるツールがあります。 + #link(url_bindgen)[bindgen]の使用手順は、#link(url_bindgen_manual)[bindgenユーザマニュアル]を参照して下さい。 + #link(url_bindgen)[bindgen]を使用するための一般的なプロセスは、次の通りです。 + + Rustで使いたいインタフェースやデータ型を定義している全てのCまたはC++ヘッダを集めます。 + + ステップ1で集めたヘッダファイルを`#include "..."`する`bindings.h`ファイルを書きます。 + + `bindgen`にコンパイルフラグとコードと共に、`bindings.h`を与えます。 + ヒント:`#![no_std]`互換なコードを生成するために、`Builder.ctypes_prefix("cty")`と`--ctypes-prefix=cty`を使って下さい。 + + `bindgen`は、端末のウィンドウに生成したRustコードを出力します。これは、`bindings.rs`のようなプロジェクトのファイルにパイプすることができます。 + 外部ライブラリとしてコンパイル、リンクされたC/C++コードとやり取りするために、このファイルをRustプロジェクトで使用できます。 + #todoupd("ja") +], +zh: [ + 有一个叫做#link(url_bindgen)[bindgen]的工具,它可以自动执行这些转换,而不用手动生成这些接口,手动进行这样的操作非常繁琐且容易出错。关于#link(url_bindgen)[bindgen]的使用指令,可以参考#link(url_bindgen_manual)[bindgen user's manual],常用的步骤大致如下: + + 收集所有定义了你可能在Rust中会用到的数据类型或者接口的C或者C++头文件。 + + 写一个`bindings.h`文件,其`#include "..."`每一个你在步骤一中收集的文件。 + + 将这个`bindings.h`文件和任何用来编译你代码的编译标识发给`bindgen`。贴士: + 使用`Builder.ctypes_prefix("cty")` / `--ctypes-prefix=cty` 和 + `Builder.use_core()` / `--use-core` 去使生成的代码兼容`#![no_std]` + + `bindgen`将会在终端窗口输出生成的Rust代码。这个文件可能会被通过管道发送给你项目中的一个文件,比如`bindings.rs` + 。你可能要在你的Rust项目中使用这个文件来与被编译和链接成一个外部库的C/C++代码交互。贴士: + 如果你的类型在生成的绑定中被前缀了`cty`,不要忘记使用#ln_cty crate 。 +])) + += #tr(( + en: [Building your C/C++ code], + de: [Erstellen Ihres C/C++-Codes], + ja: [C/C++コードのビルド], + zh: [编译你的 C/C++ 代码], +)) + +#tr(( +en: [ + As the Rust compiler does not directly know how to compile C or C++ code + (or code from any other language, which presents a C interface), it is + necessary to compile your non-Rust code ahead of time. +], +de: [ + Da der Rust-Compiler nicht direkt weiß, wie man C- oder C++-Code (oder + Code einer anderen Sprache mit C-Schnittstelle) kompiliert, muss der + Nicht-Rust-Code vorab kompiliert werden. +], +ja: [ + Rustコンパイラは、CまたはC++のコード(または、Cのインタフェースを提供する他の言語のコード)をコンパイルする方法を直接は知らないため、Rustでないコードは事前にコンパイルする必要があります。 +], +zh: [ + 因为Rust编译器并不直接知道如何编译C或者C++代码(或者从其它语言来的代码,其提供了一个C接口),所以必须要静态编译你的非Rust代码。 +])) + +#tr(( +en: [ + For embedded projects, this most commonly means compiling the C/C++ code + to a static archive (such as `cool-library.a`), which can then be + combined with your Rust code at the final linking step. +], +de: [ + Bei Embedded-Projekten bedeutet dies meist, dass der C/C++-Code zu einem + statischen Archiv (z. B. `cool-library.a`) kompiliert wird, welches dann + im abschließenden Link-Schritt mit dem Rust-Code zusammengeführt werden kann. +], +ja: [ + 組込みプロジェクトでは、C/C++のコードを(`cool-library.a`のような)静的なアーカイブにコンパイルすることを意味します。 + このアーカイブは、最終リンク時に、Rustのコードに組み込むことができます。 +], +zh: [ + 对于嵌入式项目,这通常意味着把C/C++代码编译成一个静态库文档(比如 + `cool-library.a`),然后其能在最后链接阶段与你的Rust代码组合起来。 +])) + +#tr(( +en: [ + If the library you would like to use is already distributed as a static + archive, it is not necessary to rebuild your code. Just convert the + provided interface header file as described above, and include the + static archive at compile/link time. +], +de: [ + Wenn die gewünschte Bibliothek bereits als statisches Archiv vorliegt, + ist eine erneute Kompilierung des Codes nicht erforderlich. Es genügt, + die bereitgestellte Header-Datei für die Schnittstelle wie oben + beschrieben umzuwandeln und das statische Archiv beim Kompilieren bzw. + Linken einzubinden. +], +ja: [ + 使おうとしているライブラリが、既に静的なアーカイブとして配布されている場合、そのコードを再度ビルドする必要はありません。 + 提供されているインタフェースのヘッダファイルを、上述の方法で、単に変換するだけです。 + そして、その静的なアーカイブをコンパイル/リンク時に組み込みます。 +], +zh: [ + 如果你要使用的库已经作为一个静态库文档被发布,那就没必要重新编译你的代码。只需按照上面所述转换提供的接口头文件,且在编译/链接时包含静态库文档。 +])) + +#tr(( +en: [ + If your code exists as a source project, it will be necessary to compile + your C/C++ code to a static library, either by triggering your existing + build system (such as `make`, `CMake`, etc.), or by porting the + necessary compilation steps to use a tool called the `cc` crate. For + both of these steps, it is necessary to use a `build.rs` script. +], +de: [ + Liegt der Code als Quellcode-Projekt vor, muss der C/C++-Code in eine + statische Bibliothek kompiliert werden. Dies kann entweder durch Aufruf + des vorhandenen Build-Systems (z. B. `make`, `CMake` usw.) oder durch + Portierung der erforderlichen Kompilierungsschritte auf das sogenannte + `cc`-Crate erfolgen. Für beide Vorgehensweisen ist die Verwendung eines + `build.rs`-Skripts erforderlich. +], +ja: [ + もしコードがソースファイルとして存在するのであれば、C/C++のコードを静的ライブラリとしてコンパイルする必要があります。 + (`make`や`CMake`のような)ビルドシステムを使うか、必要なコンパイルステップを`cc`クレートを使って移植するか、いずれかの方法を取れます。 + どちらの方法でも、`build.rs`スクリプトを使う必要があります。 +], +zh: [ + 如果你的代码作为一个源项目(source + project)存在,将你的C/C++代码编译成一个静态库将是必须的,要么通过使用你现存的编译系统(比如 + `make`,`CMake`,等等),要么通过使用一个被叫做`cc` + crate的工具移植必要的编译步骤。关于这两个,都必须使用一个`build.rs`脚本。 +])) + +== #tr(( + en: [Rust `build.rs` build scripts], + de: [Rust-`build.rs`-Build-Skripte], + ja: [Rustの`build.rs`ビルドスクリプト], + zh: [Rust的 `build.rs` 编译脚本], +)) + +#tr(( +en: [ + A `build.rs` script is a file written in Rust syntax, that is executed + on your compilation machine, AFTER dependencies of your project have + been built, but BEFORE your project is built. +], +de: [ + Ein `build.rs`-Skript ist eine in Rust-Syntax verfasste Datei, die auf + dem Kompilierrechner ausgeführt wird -- und zwar _nachdem_ die + Abhängigkeiten Ihres Projekts erstellt wurden, aber _bevor_ Ihr + Projekt selbst kompiliert wird. +], +ja: [ + `build.rs`スクリプトは、Rustの構文で書かれたファイルです。 + このスクリプトは、プロジェクトの依存をビルドした後、プロジェクトをビルドする前に、コンパイルを行っているコンピュータ上で実行されます。 +], +zh: [ + 一个 `build.rs` + 脚本是一个用Rust语法编写的文件,它被运行在你的编译机器上,发生在你项目的依赖项被编译*之后*,但是在你的项目被编译*之前* 。 +])) + +#let url_build_scripts = "https://doc.rust-lang.org/cargo/reference/build-scripts.html" +#tr(( +en: [ + The full reference may be found #link(url_build_scripts)[here]. + `build.rs` scripts are useful for generating code + (such as via #link(url_bindgen)[bindgen]), calling + out to external build systems such as `Make`, or directly compiling + C/C++ through use of the `cc` crate. +], +de: [ + Die vollständige Referenz finden Sie #link(url_build_scripts)[hier]. + `build.rs`-Skripte eignen sich beispielsweise zur Code-Generierung (etwa + mittels #link(url_bindgen)[bindgen]), + zum Aufruf externer Build-Systeme wie `Make` oder zur direkten + Kompilierung von C/C++-Code unter Verwendung des `cc`-Crates. +], +ja: [ + 完全なリファレンスは#link(url_build_scripts)[ここ]にあります。 + `build.rs`スクリプトは、(#link(url_bindgen)[bindgen]のようなツールを用いて)コードを生成したり、 + `Make`のような外部ビルドシステムを呼び出したり、`cc`クレートを使ってC/C++を直接ビルドしたりするのに便利です。 +], +zh: [ + 可能能在#link(url_build_scripts)[这里]发现完整的参考。`build.rs` + 脚本能用来生成代码(比如通过#link(url_bindgen)[bindgen]),调用外部编译系统,比如`Make`,或者直接通过使用`cc` + crate来直接编译C/C++ 。 +])) + +== #tr(( + en: [Triggering external build systems], + de: [Auslösen externer Build-Systeme], + ja: [外部ビルドシステムの使用], + zh: [使用外部编译系统], +)) + +#let ln_command = link("https://doc.rust-lang.org/std/process/struct.Command.html")[`std::process::Command`] +#tr(( +en: [ + For projects with complex external projects or build systems, + it may be easiest to use #ln_command + to "shell out" to your other build systems by traversing relative paths, + calling a fixed command (such as `make library`), and then copying the + resulting static library to the proper location in the `target` build + directory. +], +de: [ + Bei Projekten, die komplexe externe Projekte oder Build-Systeme + einbinden, ist es oft am einfachsten, #ln_command + zu verwenden, um andere Build-Systeme aufzurufen (sogenanntes + „Shelling-out"). Dabei navigieren Sie über relative Pfade, führen einen + festen Befehl aus (wie etwa `make library`) und kopieren anschließend + die erzeugte statische Bibliothek an den entsprechenden Ort im + `target`-Build-Verzeichnis. +], +ja: [ + 複雑な外部プロジェクトや外部ビルドシステムを使うプロジェクトに関しては、#ln_command;を使って、他のビルドシステムに対して「シェルを呼び出す」のが最も簡単でしょう。 + これにより、相対パスを渡り歩いたり、(`make library`のような)固定のコマンドを呼び出したり、その後、`target`ビルドディレクトリにある静的ライブラリをコピーしたりすることができます。 +], +zh: [ + 对于有复杂的外部项或者编译系统的项目,使用#ln_command;通过遍历相对路径来向其它编译系统"输出",调用一个固定的命令(比如 + `make library`),然后拷贝最终的静态库到`target`编译文件夹中恰当的位置,可能是最简单的方法。 +])) + +#tr(( +en: [ + While your crate may be targeting a `no_std` embedded platform, your + `build.rs` executes only on machines compiling your crate. This means + you may use any Rust crates which will run on your compilation host. +], +de: [ + Auch wenn Ihre Crate für eine eingebettete Plattform ohne + Standardbibliothek (`no_std`) gedacht ist, wird die `build.rs` + ausschließlich auf dem Rechner ausgeführt, der die Crate kompiliert. Das + bedeutet, dass Sie beliebige Rust-Crates verwenden können, die auf Ihrem + Kompilier-Host lauffähig sind. +], +ja: [ + 作っているクレートが`no_std`な組込みプラットフォームをターゲットにしていたとしても、`build.rs`はクレートをコンパイルしているコンピュータ上でのみ動作します。 + そのため、コンパイルしているホスト上で動作する、あらゆるRustのクレートを使うことができます。 +], +zh: [ + 虽然你的crate目标可能是一个`no_std`嵌入式平台,但你的`build.rs`只运行在负责编译你的crate的机器上。这意味着你能使用任何Rust + crates,其将运行在你的编译主机上。 +])) + +== #tr(( + en: [Building C/C++ code with the `cc` crate], + de: [Kompilieren von C/C++-Code mit dem `cc`-Crate], + ja: [C/C++コードを`cc`クレートでビルド], + zh: [使用`cc` crate构建C/C++代码], +)) + +#let url_cc = "https://github.com/alexcrichton/cc-rs" +#tr(( +en: [ + For projects with limited dependencies or complexity, or for projects + where it is difficult to modify the build system to produce a static + library (rather than a final binary or executable), it may be easier to + instead utilize the #link(url_cc)[`cc` crate], which + provides an idiomatic Rust interface to the compiler provided by the + host. +], +de: [ + Bei Projekten mit geringen Abhängigkeiten oder überschaubarer + Komplexität -- oder wenn es schwierig ist, das Build-System so + anzupassen, dass eine statische Bibliothek (statt einer fertigen + Binärdatei oder eines ausführbaren Programms) erzeugt wird -- kann es + einfacher sein, stattdessen das + #link(url_cc)[`cc`-Crate] zu verwenden; + dieses bietet eine idiomatische Rust-Schnittstelle zu dem vom Host + bereitgestellten Compiler. +], +ja: [ + 依存や複雑さが少ないプロジェクトや、(最終バイナリや実行ファイルではなく)静的ライブラリを作成するためにビルドシステムを修正するのが難しいプロジェクトであれば、 + 代わりに#link(url_cc)[`cc`クレート]を使う方が簡単でしょう。 + ccクレートは、ホスト上のコンパイラへの、扱いやすいRustインタフェースを提供します。 +], +zh: [ + 对于具有有限的依赖项或者复杂度的项目,或者对于那些难以修改编译系统去生成一个静态库(而不是一个二进制文件或者可执行文件)的项目,使用#url_cc;可能更容易,它提供了一个符合Rust语法的接口,这个接口是关于主机提供的编译器的。 +])) + +#tr(( +en: [ + In the simplest case of compiling a single C file as a dependency to a + static library, an example `build.rs` script using the + #link(url_cc)[`cc` crate] would look like this: +], +de: [ + Im einfachsten Fall, bei dem eine einzelne C-Datei als Abhängigkeit für + eine statische Bibliothek kompiliert wird, sähe ein Beispiel für ein + `build.rs`-Skript, das das #link(url_cc)[`cc`-Crate] verwendet, folgendermaßen aus: +], +ja: [ + 単一のCファイルを静的ライブラリにコンパイルする最も単純な例では、#link(url_cc)[`cc`クレート]を使った`build.rs`スクリプトは次のようになります。 +], +zh: [ + 在把一个C文件编译成一个静态库的依赖项的最简单的场景下,可以使用#link(url_cc)[`cc` crate],示例`build.rs`脚本看起来像这样: +])) + +```rust +fn main() { + cc::Build::new() + .file("src/foo.c") + .compile("foo"); +} +``` + +#tr(( +en: [ + The `build.rs` is placed at the root of the package. Then `cargo build` + will compile and execute it before the build of the package. A static + archive named `libfoo.a` is generated and placed in the `target` directory. +], +de: [ + Die Datei `build.rs` befindet sich im Wurzelverzeichnis des Pakets. + `cargo build` kompiliert und führt sie dann vor dem eigentlichen + Build-Vorgang des Pakets aus. Dabei wird ein statisches Archiv namens + `libfoo.a` erstellt und im Verzeichnis `target` abgelegt. +], +zh: [ + 要把`build.rs`放在包的根目录下.然后`cargo build`会在构建包之前编译和执行它.一个静态的名为`libfoo.a`的归档文件会生成并被放在`target`文件夹中. +])) diff --git a/typ/interoperability/index.typ b/typ/interoperability/index.typ new file mode 100644 index 00000000..2842394f --- /dev/null +++ b/typ/interoperability/index.typ @@ -0,0 +1,241 @@ +#import "../config.typ": * + +#h1((en: [Interoperability], + de: [Interoperabilität], + ja: [相互運用性], + zh: [互操性], +)) + +#let ln_ffi = link("https://doc.rust-lang.org/std/ffi/index.html")[`std::ffi`] +#tr(( +en: [ + Interoperability between Rust and C code is always dependent on + transforming data between the two languages. For this purpose, there is + a dedicated module in the `stdlib` called #ln_ffi. +], +de: [ + Die Interoperabilität zwischen Rust- und C-Code hängt stets von der + Umwandlung von Daten zwischen den beiden Sprachen ab. Hierfür gibt es in + der Standardbibliothek (`stdlib`) ein spezielles Modul namens #ln_ffi. +], +ja: [ + #todoupd("ja") + RustとCとの相互運用性は、常に2つの言語間のデータ変換に依存しています。 + そこで、2つの専用モジュールが`stdlib`内にあります。 + #ln_ffi;と呼ばれるものです。 +], +zh: [ + Rust和C代码之间的互操性始终依赖于数据在两个语言间的转换.为了互操性,在`stdlib`中有一个专用的模块,叫作 #ln_ffi. +])) + +#tr(( +en: [ + `std::ffi` provides type definitions for C primitive types, such as + `char`, `int`, and `long`. It also provides some utility for converting + more complex types such as strings, mapping both `&str` and `String` to + C types that are easier and safer to handle. +], +de: [ + `std::ffi` stellt Typdefinitionen für primitive C-Datentypen bereit, wie + etwa `char`, `int` und `long`. Zudem bietet es Hilfsmittel zur + Konvertierung komplexerer Typen wie Strings, indem es sowohl `&str` als + auch `String` auf C-Typen abbildet, die sich einfacher und sicherer + handhaben lassen. +], +zh: [ + `std::ffi`提供了与C基础类型对应的类型定义,比如`char`, + `int`,和`long`. + 它也提供了一些工具用于更复杂的类型之间的转换,比如字符串,可以把`&str`和`String`映射成更容易和安全处理的C类型. +])) + +#let ln_cty = link("https://crates.io/crates/cty")[`cty`] +#let ln_cstr = link("https://crates.io/crates/cstr_core")[`cstr_core`] +#tr(( +en: [ + As of Rust 1.30, functionalities of `std::ffi` are available in either + `core::ffi` or `alloc::ffi` depending on whether or not memory + allocation is involved. The #ln_cty crate and the #ln_cstr + crate also offer similar functionalities. +], +de: [ + Seit Rust 1.30 stehen die Funktionalitäten von `std::ffi` wahlweise in + `core::ffi` oder `alloc::ffi` zur Verfügung, je nachdem, ob + Speicherreservierungen erforderlich sind oder nicht. + Auch die Crates #ln_cty und #ln_cstr bieten vergleichbare Funktionalitäten an. +], +zh: [ + 从Rust + 1.30以来,`std::ffi`的功能也出现在`core::ffi`或者`alloc::ffi`中,取决于是否涉及到内存分配. + #ln_cty;库和#ln_cstr;库也提供了相同的功能. +])) + +#figure( + kind: table, + table( + columns: 3, + align: (auto,auto,auto,), + table.header( + tr(( + en: [Rust type], + de: [Rusttyp], + ja: [Rustの型], + zh: [Rust类型], + )), + tr(( + en: [Intermediate], + de: [Dazwischenliegend], + ja: [中間表現], + zh: [间接], + )), + tr(( + en: [C type], + de: [C-Typ], + ja: [Cの型], + zh: [C类型], + )), + ), + `String`, `CString`, `char *`, + `&str`, `CStr`, `const char *`, + `()`, `c_void`, `void`, + tr(( + en: [`u32` or `u64`], + de: [`u32` or `u64`], + ja: [`u32` or `u64`], + )), + )), + `c_uint`, `unsigned int`, + tr(( + en: [etc], + de: [usw.], + ja: [他], + )), + […], […], + ) +) + +#tr(( +en: [ + A value of a C primitive type can be used as one of the corresponding + Rust type and vice versa, since the former is simply a type alias of the + latter. For example, the following code compiles on platforms where + `unsigned int` is 32-bit long. +], +de: [ + Ein Wert eines primitiven C-Datentyps kann als Wert des entsprechenden + Rust-Datentyps verwendet werden und umgekehrt, da der erstere lediglich + ein Typalias des letzteren ist. Beispielsweise lässt sich der folgende + Code auf Plattformen kompilieren, auf denen `unsigned int` 32 Bit lang + ist. +], +zh: [ + 一个C基本类型的值可以被用来作为相关的Rust类型的值,反之亦然,因此前者仅仅是后者的一个类型伪名. + 比如,下列的代码可以在`unsigned int`是32位宽的平台上编译. +])) + +```rust +fn foo(num: u32) { + let c_num: c_uint = num; + let r_num: u32 = c_num; +} +``` + +== #tr(( + en: [Interoperability with other build systems], + de: [Interoperabilität mit anderen Build-Systemen], + ja: [他のビルドシステムとの相互運用性], + zh: [与其它编译系统的互用性], +)) + +#tr(( +en: [ + A common requirement for including Rust in your embedded project is + combining Cargo with your existing build system, such as make or cmake. +], +de: [ + Eine häufige Voraussetzung für die Einbindung von Rust in + Embedded-Projekte ist die Kombination von Cargo mit Ihrem bestehenden + Build-System, beispielsweise Make oder CMake. +], +ja: [ + 組込みプロジェクトにRustを組み込むための共通の要件は、Cargoとmakeやcmakeのような既存のビルドシステムとを組み合わせることです。 +], +zh: [ + 在嵌入式项目中引入Rust的一个常见需求是,把Cargo结合进你现存的编译系统中,比如make或者cmake。 +])) + +#let url_issue61 = "https://github.com/rust-embedded/book/issues/61" +#tr(( +en: [ + We are collecting examples and use cases for this on our issue tracker + in #link(url_issue61)[issue \#61]. +], +de: [ + Wir sammeln Beispiele und Anwendungsfälle hierzu in unserem + Problem-Verfolgungswerkzeug unter #link(url_issue61)[Issue \#61]. +], +ja: [ + #link(url_issue61)[issue \#61]でこれに関する事例とユースケースを集めています。 +], +zh: [ + 在#link(url_issue61)[issue \#61]的issue + tracker上,我们正在为这个需求收集例子和用例。 +])) + +== #tr(( + en: [Interoperability with RTOSs], + de: [Interoperabilität mit RTOS], + ja: [RTOSとの相互運用性], + zh: [与RTOSs的互操性], +)) + +#tr(( +en: [ + Integrating Rust with an RTOS such as FreeRTOS or ChibiOS is still a + work in progress; especially calling RTOS functions from Rust can be + tricky. +], +de: [ + Die Integration von Rust in ein RTOS wie FreeRTOS oder ChibiOS befindet + sich noch in der Entwicklung; insbesondere der Aufruf von + RTOS-Funktionen aus Rust heraus kann sich als schwierig erweisen. +], +ja: [ + RustをFreeRTOSやChibiOSといったRTOSに統合することは、まだ作業を進めている状態です。 + 特に、RTOSの関数をRustから呼び出すことはトリッキーです。 +], +zh: [ + 将Rust和一个RTOS集成在一起,比如FreeRTOS或者ChibiOS仍然在进行中; + 尤其是从Rust调用RTOS函数可能很棘手。 +])) + +#let url_zephyr = "https://docs.zephyrproject.org/latest/develop/languages/rust/index.html" +#tr(( +en: [ + Currently, the following projects publicly support Rust\<-\>RTOS + interoperability: + - #link(url_zephyr)[Zephyr Project] +], +de: [ + Derzeit unterstützen die folgenden Projekte öffentlich die + Interoperabilität zwischen Rust und RTOS: + - #link(url_zephyr)[Zephyr-Projekt] +])) + +#let url_issue62 = "https://github.com/rust-embedded/book/issues/62" +#tr(( +en: [ + We are collecting examples and use cases for this on our issue tracker + in #link(url_issue62)[issue \#62]. +], +de: [ + Wir sammeln hierfür Beispiele und Anwendungsfälle in unserem + Problem-Verfolgungswerkzeug unter + #link(url_issue62)[Issue \#62]. +], +ja: [ + #link(url_issue62)[issue \#62]でこれに関する事例とユースケースを集めています。 +], +zh: [ + 在#link(url_issue62)[issue \#62]的issue + tracker上,我们正为这件事收集例子和用例。 +])) diff --git a/typ/interoperability/rust-with-c.typ b/typ/interoperability/rust-with-c.typ new file mode 100644 index 00000000..c997d597 --- /dev/null +++ b/typ/interoperability/rust-with-c.typ @@ -0,0 +1,406 @@ +#import "../config.typ": * + +#h1((en: [A little Rust with your C], + de: [Ein bisschen Rust zu Ihrem C], + ja: [Cと少しのRust], + zh: [使用Rust的C], +), offset: whole) + + +#tr(( +en: [ + Using Rust code inside a C or C++ project mostly consists of two parts. + - Creating a C-friendly API in Rust + - Embedding your Rust project into an external build system +], +de: [ + Die Verwendung von Rust-Code in einem C- oder C++-Projekt besteht + größtenteils aus zwei Teilen. + - Erstellung einer C-kompatiblen API in Rust + - Einbindung Ihres Rust-Projekts in ein externes Build-System +], +ja: [ + CまたはC++のプロジェクト内でRustのコードを使うためには、主に次の2つの対応をします。 + - Cが扱いやすいAPIをRustに作ります + - 外部ビルドシステムにRustプロジェクトを組み込みます +], +zh: [ + 在C或者C++中使用Rust代码通常由两部分组成。 + - 用Rust生成一个C友好的API + - 将你的Rust项目嵌入一个外部的编译系统 +])) + +#tr(( +en: [ + Apart from `cargo` and `meson`, most build systems don't have native + Rust support. So you're most likely best off just using `cargo` for + compiling your crate and any dependencies. +], +de: [ + Abgesehen von `cargo` und `meson` bieten die meisten Build-Systeme keine + native Rust-Unterstützung. Daher fährst du höchstwahrscheinlich am + besten damit, einfach `cargo` für die Kompilierung deines Crates und + aller Abhängigkeiten zu verwenden. +], +ja: [ + `cargo`と`meson`は別として、ほとんどのビルドシステムはRustをサポートしていません。 + そのため、自分のクレートとその依存関係をコンパイルするには、`cargo`を使うのが一番です。 +], +zh: [ + 除了`cargo`和`meson`,大多数编译系统没有原生Rust支持。因此你最好只用`cargo`编译你的crate和依赖。 +])) + += #tr(( + en: [Setting up a project], + de: [Ein Projekt einrichten], + ja: [プロジェクトの準備], + zh: [设置一个项目], +)) + +#tr(( +en: [ + Create a new `cargo` project as usual. +], +de: [ + Erstellen Sie wie gewohnt ein neues `cargo`-Projekt. +], +ja: [ + いつもどおり、新しい`cargo`プロジェクトを作成します。 +])) + +#tr(( +en: [ + There are flags to tell `cargo` to emit a systems library, instead of + its regular rust target. This also allows you to set a different output + name for your library, if you want it to differ from the rest of your crate. +], +de: [ + Es gibt Flags, mit denen man `cargo` anweisen kann, eine + Systembibliothek anstelle des üblichen Rust-Ziels zu erstellen. Auf + diese Weise können Sie auch einen abweichenden Namen für die Bibliothek + festlegen, falls dieser sich von dem des restlichen Crates unterscheiden soll. +], +ja: [ + 通常のRustのターゲットではなく、システムライブラリを出力するように、`cargo`に指示するフラグがあります。 + クレートの残り部分と異なる名前を付けたい場合、ライブラリに対して、別の名前を設定することもできます。 +], +zh: [ + 像往常一样创建一个新的`cargo`项目。有一些标志可以告诉`cargo`去生成一个系统库,而不是常规的rust目标文件。如果你想要它与crate的其它部分不一样,你也可以为你的库设置一个不同的输出名。 +])) + +#raw(block: true, lang: "toml", +"[lib] +name = \"your_crate\" +crate-type = [\"cdylib\"] # " + ts(( + en: "Creates dynamic lib", + de: "Erstellt eine dynamische Bibliothek", + ja: "動的ライブラリを作ります", + zh: "生成动态链接库", + )) + " +# crate-type = [\"staticlib\"] # " + ts(( + en: "Creates static lib", + de: "Erstellt eine statische Bibliothek", + ja: "静的ライブラリを作ります", + zh: "生成静态链接库", + )) + " +") + += #tr(( + en: [Building a `C` API], + de: [Erstellung einer C-API], + ja: [`C` APIの作成], + zh: [构建一个`C` API], +)) + +#tr(( +en: [ + Because C++ has no stable ABI for the Rust compiler to target, we use + `C` for any interoperability between different languages. This is no + exception when using Rust inside of C and C++ code. +], +de: [ + Da C++ über keine stabile ABI verfügt, auf die der Rust-Compiler + abzielen könnte, nutzen wir C für die Interoperabilität zwischen + verschiedenen Sprachen. Dies gilt auch für die Verwendung von Rust + innerhalb von C- und C++-Code. +], +ja: [ + C++は、Rustコンパイラがターゲットにできる安定したABIを持っていないため、別言語との相互運用には、CのABIを使用します。 + CとC++のコード内でRustを使うとき、このことに例外はありません。 +], +zh: [ + 因为对于Rust编译器来说,C++没有稳定的ABI,因此对于不同语言间的互操性我们使用`C`。在C和C++代码的内部使用Rust时也不例外。 +])) + +== `#[no_mangle]` + +#tr(( +en: [ + The Rust compiler mangles symbol names differently than native code + linkers expect. As such, any function that Rust exports to be used + outside of Rust needs to be told not to be mangled by the compiler. +], +de: [ + Der Rust-Compiler verarbeitet Symbolnamen anders als Linker für nativen + Code erwarten. Daher muss jeder Funktion, die Rust zur Verwendung + außerhalb von Rust exportiert, mitgeteilt werden, dass der Compiler sie + nicht verändern soll. +], +ja: [ + Rustコンパイラは、シンボル名をネイティブコードリンカが期待するものとは異なるものにマングルします。 + そのため、Rustの外にエクスポートするRustの関数は、マングルしないようにコンパイラに指示する必要があります。 +], +zh: [ + Rust对符号名的修饰与主机的代码链接器所期望的不同。因此,需要告知任何被Rust导出到Rust外部去使用的函数不要被编译器修饰。 +])) + +== `extern "C"` + +#tr(( +en: [ + By default, any function you write in Rust will use the Rust ABI (which + is also not stabilized). Instead, when building outwards facing FFI APIs + we need to tell the compiler to use the system ABI. +], +de: [ + Standardmäßig verwendet jede in Rust geschriebene Funktion die Rust-ABI + (die ebenfalls nicht stabilisiert ist). Beim Erstellen von nach außen + gerichteten FFI-APIs muss der Compiler daher angewiesen werden, die + System-ABI zu verwenden. +], +ja: [ + デフォルトでは、Rustに書いたいずれの関数もRustのABI(これも安定化されていません)を使います。 + 代わりに、外に公開するFFI + APIはシステムABIを使うように、コンパイラに指示する必要があります。 +], +zh: [ + 默认,任何用Rust写的函数将使用Rust ABI(这也不稳定)。当编译面向外部的FFI + APIs时,我们需要告诉编译器去使用系统ABI 。 +])) + +#let url_external = "https://doc.rust-lang.org/reference/items/external-blocks.html" +#tr(( +en: [ + Depending on your platform, you might want to target a specific ABI + version, which are documented #link(url_external)[here]. +], +de: [ + Je nach Plattform möchten Sie möglicherweise eine bestimmte ABI-Version + anvisieren; diese sind #link(url_external)[hier] dokumentiert. +], +ja: [ + プラットフォームによっては、特定のABIバージョンをターゲットにしたい場合があります。 + ABIについては、#link(url_external)[ここ]にドキュメントがあります。 +], +zh: [ + 取决于你的平台,你可能想要针对一个特定的ABI版本,其记录在#link(url_external)[这里]。 +])) + +#divider() + +#tr(( +en: [ + Putting these parts together, you get a function that looks roughly like this. +], +de: [ + Wenn man diese Teile zusammensetzt, erhält man eine Funktion, die + ungefähr so ​​aussieht. +], +ja: [ + これらの部品をまとめると、おおよそ次のような関数になります。 +], +zh: [ + 把这些部分放在一起,你得到一个函数,其粗略看起来像是这个。 +])) + +```rust +#[no_mangle] +pub extern "C" fn rust_function() { + +} +``` + +#tr(( +en: [ + Just as when using `C` code in your Rust project you now need to + transform data from and to a form that the rest of the application will + understand. +], +de: [ + Genau wie bei der Verwendung von C-Code in Ihrem Rust-Projekt müssen Sie + nun Daten in eine Form umwandeln -- und aus dieser zurück --, die der + Rest der Anwendung versteht. +], +ja: [ + Rustプロジェクトで`C`コードを使った時と同様に、異なる言語間で理解できるデータ型に変換する必要があります。 +], +zh: [ + 就像在Rust项目中使用`C`代码时那样,现在需要把数据转换为应用中其它部分可以理解的形式。 +])) + += #tr(( + en: [Linking and greater project context], + de: [Verknüpfung und übergeordneter Projektkontext], + ja: [リンクとより大きなプロジェクトの状況], + zh: [链接和更大的项目上下文], +)) + +#tr(( +en: [ + So then, that's one half of the problem solved. How do you use this now? +], +de: [ + Damit ist die eine Hälfte des Problems gelöst. Wie verwendet man das nun? +], +ja: [ + ここまでで、問題の半分は解決しました。 これをどうやって使うのでしょうか? +], +zh: [ + 问题只解决了一半。 + + 你现在要如何使用它? +])) + +#tr(( +en: [ + *This very much depends on your project and/or build system* +], +de: [ + *Das hängt stark von Ihrem Projekt bzw. Ihrem Build-System ab.* +], +ja: [ + *それは、プロジェクトやビルドシステムに強く依存します。* +], +zh: [ + *这很大程度上取决于你的项目或者编译系统* +])) + +#tr(( +en: [ + `cargo` will create a `my_lib.so`/`my_lib.dll` or `my_lib.a` file, + depending on your platform and settings. This library can simply be + linked by your build system. +], +de: [ + `cargo` erstellt -- je nach Plattform und Einstellungen -- eine Datei + namens `my_lib.so`, `my_lib.dll` oder `my_lib.a`. Diese Bibliothek kann + einfach von Ihrem Build-System eingebunden (gelinkt) werden. +], +ja: [ + `cargo`は、プラットフォームと設定に依存して、`my_lib.so`、`my_lib.dll`または`my_lib.a`ファイルを作成します。 + このライブラリは、そのプラットフォームのビルドシステムによって簡単にリンクすることができます。 +], +zh: [ + `cargo`将生成一个`my_lib.so`/`my_lib.dll`或者`my_lib.a`文件,取决于你的平台和配置。可以通过编译系统简单地链接这个库。 +])) + +#tr(( +en: [ + However, calling a Rust function from C requires a header file to + declare the function signatures. +], +de: [ + Um jedoch eine Rust-Funktion aus C heraus aufzurufen, ist eine + Header-Datei erforderlich, in der die Funktionssignaturen deklariert werden. +], +ja: [ + しかし、CからRustを呼ぶためには、関数シグネチャを宣言するためのヘッダファイルが必要です。 +], +zh: [ + 然而,从C调用一个Rust函数要求一个头文件去声明函数的签名。 +])) + +#tr(( +en: [ + Every function in your Rust-ffi API needs to have a corresponding header function. +], +de: [ + Für jede Funktion in Ihrer Rust-FFI-API muss eine entsprechende + Deklaration im Header vorhanden sein. +], +ja: [ + Rust-ffi APIの関数全てが、対応する関数ヘッダを持つ必要があります。 +], +zh: [ + 在Rust-ffi API中的每个函数需要有一个相关的头文件函数。 +])) + +```rust +#[no_mangle] +pub extern "C" fn rust_function() {} +``` + +#tr(( +en: [ + would then become +], +de: [ + würde dann werden +], +ja: [ + 上記は、次のようになるでしょう。 +], +zh: [ + 将会变成 +])) + +```c +void rust_function(); +``` + +#tr(( +en: [ + etc. +], +de: [ + usw. +], +ja: [ + などなど。 +], +zh: [ + 等等。 +])) + +#let ln_cbindgen = link("https://github.com/eqrion/cbindgen")[cbindgen] +#tr(( +en: [ + There is a tool to automate this process, called + #ln_cbindgen which analyses + your Rust code and then generates headers for your C and C++ projects + from it. +], +de: [ + Es gibt ein Werkzeug zur Automatisierung dieses Prozesses namens + #ln_cbindgen, das Ihren + Rust-Code analysiert und daraus Header-Dateien für Ihre C- und + C++-Projekte generiert. +], +ja: [ + このプロセスを自動化する#ln_cbindgen;というツールがあります。 + このツールは、Rustのコードを解析して、CとC++プロジェクトのためのヘッダを生成します。 +], +zh: [ + 这里有个工具可以自动化这个过程,叫做#ln_cbindgen,其会分析你的Rust代码然后为C和C++项目生成头文件。 +])) + +#tr(( +en: [ + At this point, using the Rust functions from C is as simple as including + the header and calling them! +], +de: [ + An diesem Punkt ist die Verwendung der Rust-Funktionen aus C heraus so + einfach, wie den Header einzubinden und die Funktionen aufzurufen! +], +ja: [ + この時点で、CからRustの関数を使うには、単にヘッダをインクルードして、それを呼び出すだけです! +], +zh: [ + 此时从C中使用Rust函数非常简单,只需包含头文件和调用它们! +])) + +```c +#include "my-rust-project.h" +rust_function(); +``` diff --git a/typ/intro/hardware.typ b/typ/intro/hardware.typ new file mode 100644 index 00000000..dd2f7d6b --- /dev/null +++ b/typ/intro/hardware.typ @@ -0,0 +1,209 @@ +#import "../config.typ": * + +#h1((en: [Meet Your Hardware], + de: [Lernen Sie Ihre Hardware kennen], + ja: [ハードウェアとの出会い], + uk: [Зустрічайте залізо], + zh: [熟悉你的硬件], +), offset: whole) + +#tr(( +en: [ + Let's get familiar with the hardware we'll be working with. +], +de: [ + Machen wir uns mit der Hardware vertraut, mit der wir arbeiten werden. +], +ja: [ + これから作業するハードウェアに詳しくなりましょう。 +], +uk: [ + Давайте ознайомимося з обладнанням, з яким ми будемо працювати. +], +zh: [ + 先来熟悉下我们要用的硬件。 +])) + +#figure( + image("../assets/f3.jpg") +) + += #tr(( + en: [STM32F3DISCOVERY (the "F3")], + de: [STM32F3DISCOVERY (die "F3")], + ja: [STM32F3DISCOVERY ("F3")], + uk: [STM32F3DISCOVERY (скорочено "F3")], + zh: [STM32F3DISCOVERY (the "F3")], +)) + +#tr(( +en: [ + What does this board contain? +], +de: [ + Was beinhaltet diese Platine? +], +ja: [ + 私たちは、本書内でこのボードを"F3"と呼びます。 +], +uk: [ + Що міститься на цій платі? +], +zh: [ + 这个板子有什么? +])) + +#let url_f303 = "https://www.st.com/en/microcontrollers/stm32f303vc.html" +#let wiki_accelerometer = "https://en.wikipedia.org/wiki/Accelerometer" +#let url_lsm303 = "https://www.st.com/en/mems-and-sensors/lsm303dlhc.html" +#let wiki_magnetometer = "https://en.wikipedia.org/wiki/Magnetometer" +#let wiki_gyroscope = "https://en.wikipedia.org/wiki/Gyroscope" +#let url_l3gd20 = "https://www.pololu.com/file/0J563/L3GD20.pdf" +#let url_f103 = "https://www.st.com/en/microcontrollers/stm32f103cb.html" +#tr(( +en: [ + - A #link(url_f303)[STM32F303VCT6] microcontroller. This microcontroller has + - A single-core ARM Cortex-M4F processor with hardware support for + single-precision floating point operations and a maximum clock + frequency of 72 MHz. + - 256 KiB of "Flash" memory. (1 KiB = 10#[*24*] bytes) + - 48 KiB of RAM. + - A variety of integrated peripherals such as timers, I2C, SPI and + USART. + - General purpose Input Output (GPIO) and other types of pins + accessible through the two rows of headers along side the board. + - A Mini-USB interface accessible through the USB port labeled "USB + USER". + - An #link(wiki_accelerometer)[accelerometer] as part of the #link(url_lsm303)[LSM303DLHC] chip. + - A #link(wiki_magnetometer)[magnetometer] as part of the #link(url_lsm303)[LSM303DLHC] chip. + - A #link(wiki_gyroscope)[gyroscope] as part of the #link(url_l3gd20)[L3GD20] chip. + - 8 user LEDs arranged in the shape of a compass. + - A second microcontroller: a #link(url_f103)[STM32F103]. + This microcontroller is actually part of an on-board programmer / + debugger and is connected to the Mini-USB port named "USB ST-LINK". +], +de: [ + - Ein #link(url_f303)[STM32F303VCT6]-Mikrocontroller. + Dieser Mikrocontroller hat + - Ein Single-Core-ARM-Cortex-M4F-Prozessor mit Hardware-Unterstützung + für Gleitkommaoperationen einfacher Genauigkeit und einer maximalen + Taktfrequenz von 72 MHz. + - 256 KiB "Flash"-Speicher. (1 KiB = 10#[*24*] bytes) + - 48 KiB RAM. + - Eine Vielzahl integrierter Peripherieeinheiten wie Timer, I2C, SPI + und USART. + - GPIO-Pins (General Purpose Input/Output) und andere Pin-Typen, die + über die beiden Stiftleistenreihen an den Seiten der Platine + zugänglich sind. + - Einen #link(wiki_accelerometer)[Beschleunigungsmesser] als Teil des #link(url_lsm303)[LSM303DLHC]-Chips. + - Ein #link(wiki_magnetometer)[Magnetfeldstärkenmessgerät] als Teil des #link(url_lsm303)[LSM303DLHC]-Chips. + gekennzeichneten USB-Anschluss zugänglich ist. + - Ein #link(wiki_accelerometer)[Beschleunigungssensor] als Teil des #link(url_lsm303)[LSM303DLHC]-Chips. #todoupd("de") + - Ein #link(wiki_gyroscope)[Gyroskop] als Teil des + #link(url_l3gd20)[L3GD20]-Chips. + - 8 Benutzer-LEDs, angeordnet in Form eines Kompasses. + - Ein zweiter Mikrocontroller: ein + #link(url_f103)[STM32F103]. + Dieser Mikrocontroller ist eigentlich Teil eines + On-Board-Programmers/Debuggers und mit dem Mini-USB-Anschluss namens + „USB ST-LINK" verbunden. +], +ja: [ + このボードには何が搭載されているか見てみましょう。 + - STM32F303VCT6マイクロコントローラが1つ。このマイクロコントローラは、次のものを搭載しています。 + - 単精度浮動小数点演算をハードウェアサポートし、最大72MHzのクロック周波数で動作するシングルコアのARM + Cortex-M4Fプロセッサ + - 256 KiBの"フラッシュ"メモリ (1 KiB = 10#[*24*] bytes) + - 48 KiBのRAM + - 多くの"ペリフェラル": タイマ、GPIO、I2C、SPI、USART、他 + - 両側面の"ヘッダ"に配置された多数の"ピン" + - *重要* このマイクロコントローラは、約3.3ボルトで動作します。 + - #link(wiki_accelerometer)[加速度センサ]と#link(wiki_magnetometer)[磁気センサ]が1つずつ + (1つのパッケージにまとめられています) + - #link(wiki_gyroscope)[ジャイロセンサ]が1つ + - 円形に配置された8個のユーザLED + - 第2のマイクロコントローラ: + STM32F103CBT。このマイクロコントローラは、実際には、ST-LINKというオンボードプログラマおよびデバッガの一部であり、"USB + ST-LINK"という名前のUSBポートに接続されています。 + - "USB + USER"というラベルが付いている第2のUSBポート。このUSBポートは、メインマイクロコントローラ + (STM32F303VCT6)に接続されており、アプリケーションで利用できます。 +], +uk: [ + - Мікроконтролер #link(url_f303)[STM32F303VCT6]. Цей мікроконтролер має: + - Одноядерний процесор ARM Cortex-M4F з апаратною підтримкою операцій + з плаваючою комою одинарної точності і максимальною тактовою частотою 72 МГц. + - 256 KiB флеш-пам'яті. (1 KiB = 10#[*24*] байт) + - 48 KiB оперативної пам'яті. + - Різноманітні інтегровані периферійні пристрої, такі як таймери, I2C, SPI та USART. + - Піни вводу-виводу загального призначення (GPIO) та інші типи пінів, + доступні через дворядні гребінки уздовж бокових стінок плати. + - Інтерфейс USB, доступний через порт USB з позначкою "USB USER". + - #link(wiki_accelerometer)[Акселерометр] у складі мікросхеми #link(url_lsm303)[LSM303DLHC]. + - #link(wiki_magnetometer)[Магнітометр] у складі мікросхеми #link(url_lsm303)[LSM303DLHC]. + - #link(wiki_gyroscope)[Гіроскоп] у складі мікросхеми #link(url_l3gd20)[L3GD20]. + - 8 користувацьких світлодіодів, розташованих у формі компаса. + - Другий мікроконтролер: #link(url_f103)[STM32F103]. + Цей мікроконтролер фактично є частиною програматора/відладчика, розміщеного на платі, і підключений до USB-порту з назвою "USB ST-LINK". +], +zh: [ + - 一个#link(url_f303)[STM32F303VCT6]微控制器。这个微控制器包含 + - 一个单核的ARM Cortex-M4F + 处理器,支持单精度浮点运算,72MHz的最大时钟频率。 + - 256 KiB的"Flash"存储。 + - 48 KiB的RAM + - 多种多样的外设,比如计时器,I2C,SPI和USART + - 通用GPIO和在板子两侧的其它类型的引脚 + - 一个写着"USB USER"的USB接口 + - 一个位于#link(url_lsm303)[LSM303DLHC]芯片上的#link(wiki_accelerometer)[加速度计]。 + - 一个位于#link(url_lsm303)[LSM303DLHC]芯片上的#link(wiki_magnetometer)[磁力计]。 + - 一个位于#link(url_l3gd20)[L3GD20]芯片上的#link(wiki_gyroscope)[陀螺仪]. + - 8个摆得像一个指南针形状的user LEDs。 + - 一个二级微控制器: + #link(url_f103)[STM32F103]。这个微控制器实际上是一个板载编程器/调试器的一部分,与名为"USB + ST-LINK"的USB端口相连。 +])) + +#let url_f3disco = "https://www.st.com/en/evaluation-tools/stm32f3discovery.html" +#tr(( +en: [ + For a more detailed list of features and further specifications of the + board take a look at the #link(url_f3disco)[STMicroelectronics] website. +], +de: [ + Eine detailliertere Liste der Funktionen und weitere technische Daten + des Boards finden Sie auf der Website von #link(url_f3disco)[STMicroelectronics]. +], +uk: [ + Більш детальний перелік функцій та специфікацій плати можна знайти + на сайті #link(url_f3disco)[STMicroelectronics]. +], +zh: [ + 关于所列举的功能的更多细节和开发板的更多规格请查阅#link(url_f3disco)[STMicroelectronics]网站。 +])) + + +#let url_f303_ds = "https://www.st.com/resource/en/datasheet/stm32f303vc.pdf" +#tr(( +en: [ + A word of caution: be careful if you want to apply external signals to + the board. The microcontroller STM32F303VCT6 pins take a nominal voltage + of 3.3 volts. For further information consult the + #link(url_f303_ds)[6.2 Absolute maximum ratings section in the manual] +], +de: [ + Ein wichtiger Hinweis: Seien Sie vorsichtig, wenn Sie externe Signale an + das Board anlegen möchten. Die Pins des Mikrocontrollers STM32F303VCT6 + sind für eine Nennspannung von 3,3 Volt ausgelegt. Weitere Informationen + finden Sie im Abschnitt „6.2 Absolute maximum ratings" (Absolute + Grenzwerte) im #link(url_f303_ds)[Datenblatt]. +], +uk: [ + Застереження: будьте обережні, подаючи на плату зовнішні сигнали. + Виводи мікроконтролера STM32F303VCT6 мають номінальну напругу 3,3 вольта. + Для отримання додаткової інформації зверніться до розділу #link(url_f303_ds)[6.2 Absolute maximum ratings section у Reference Manual] +], +zh: [ + 提醒一句: + 如果想要为板子提供外部信号,请小心。微控制器STM32F303VCT6管脚的标称电压是3.3伏。更多信息请查看#link(url_f303_ds)[6.2 Absolute maximum ratings section in the manual]。 +])) \ No newline at end of file diff --git a/typ/intro/index.typ b/typ/intro/index.typ new file mode 100644 index 00000000..306080d6 --- /dev/null +++ b/typ/intro/index.typ @@ -0,0 +1,733 @@ +#import "../config.typ": * + +#h1((en: [Introduction], + de: [Einleitung], + ja: [導入], + uk: [Вступ], + zh: [引言], +)) +#set heading(offset: whole*2) + +#tr(( +en: [ + Welcome to The Embedded Rust Book: An introductory book about using + the Rust Programming Language on "Bare Metal" embedded systems, such as Microcontrollers. +], +de: [ + Willkommen bei „Das Embedded-Rust Buch“ – einem Einführungswerk zur Verwendung + der Programmiersprache Rust auf „Bare-Metal“-Embedded-Systemen, wie etwa Mikrocontrollern. +], +ja: [ + _The Embedded Rust + Book_へようこそ。Rustをマイクロコントローラのような、「ベアメタル」の組込みシステムで使うための入門書です。 +], +uk: [ + Ласкаво просимо до The Embedded Rust Book: ознайомчої книги про використання + мови програмування Rust у вбудованих "Bare Metal" системах, таких як мікроконтролери. +], +zh: [ + 欢迎阅读嵌入式Rust:一本关于如何在裸机(比如,微处理器)上使用Rust编程语言的入门书籍。 +])) + += #tr(( + en: [Who Embedded Rust is For], + de: [Für wen Embedded-Rust geeignet ist], + ja: [組込みRustは誰のためのもの], + uk: [Для кого Вбудований Rust], + zh: [嵌入式Rust是为谁准备的], +)) + +#let url_rustbook = "https://doc.rust-lang.org/book/ch00-00-introduction.html" +#tr(( +en: [ + Embedded Rust is for everyone who wants to do embedded programming while + taking advantage of the higher-level concepts and safety guarantees the + Rust language provides. (See also + #link(url_rustbook)[Who Rust Is For]) +], +de: [ + Embedded-Rust ist für alle, die eingebettete Systeme programmieren und + dabei die Vorteile der fortgeschrittenen Konzepte und + Sicherheitsgarantien der Rust-Sprache nutzen möchten. + + (Siehe auch + #link(url_rustbook)[Für wen ist Rust geeignet?]) +], +ja: [ + 組込みRustは、Rustの高い抽象度と安全性のもと、組込みプログラミングをしたい人のためのものです。 + (#url_rustbook)[Rustは誰のためのもの]も合わせて見て下さい) +], +uk: [ + Вбудований Rust для кожного, хто бажає програмувати вбудовані системи використовуючи + переваги концепцій вищого рівня та гарантій безпеки, які надає мова Rust. + (Дивіться також #link(url_rustbook)[Для кого Rust]) +], +zh: [ + 嵌入式Rust是为了那些既想要进行嵌入式编程,又想要使用Rust语言所提供的高级概念和安全保障的人们而准备的(参见#link(url_rustbook)[Who Rust Is For]) +])) + += #tr(( + en: [Scope], + de: [Umfang], + ja: [スコープ], + uk: [Область застосування], + zh: [本书范围], +)) + +#tr(( +en: [ + The goals of this book are: + - Get developers up to speed with embedded Rust development. + i.e.~How to et up a development environment. + - Share _current_ best practices about using Rust for embedded + development. i.e. How to best use Rust language features to write more + correct embedded software. + - Serve as a cookbook in some cases. e.g.~How do I mix C and Rust in a + single project? +], +de: [ + Die Ziele dieses Buches sind: + - Machen Sie Entwickler mit der Embedded-Rust-Entwicklung vertraut -- + zum Beispiel damit, wie man eine Entwicklungsumgebung einrichtet. + - Teilen Sie _aktuelle_ Best Practices für den Einsatz von Rust in + der Embedded-Entwicklung -- zum Beispiel: Wie man Sprachfunktionen von + Rust optimal nutzt, um korrektere Embedded-Software zu schreiben. + - Dient in einigen Fällen als Kochbuch -- zum Beispiel: Wie kombiniere + ich C und Rust in einem einzigen Projekt? +], +ja: [ + この本の目的は、以下の通りです。 + - 組込みRustをできる限り速く開始できるようにします。すなわち、開発環境のセットアップ方法です。 + - 組込み開発におけるRustの_現在_のベストプラクティスを共有します。つまり、より正しい組込みソフトウェアを書くための、Rustの最善な利用方法です。 + - いくつかのケースに対するマニュアルを提供します。例えば、1つのプロジェクト内で、C言語とRustとを混在する方法です。 +], +uk: [ + Цілі цієї книги: + - Надати розробникам швидкий доступ до розробки вбудованих систем на Rust. + Тобто як налаштувати середовище розробки. + - Поділіться найкращими _сучасними_ практиками використання Rust + для розробки вбудованих систем. Тобто як найкраще використовувати можливості мови Rust + для написання більш коректних вбудованих програм. + - Cлугувати кулінарною книгою у деяких випадках. Наприклад як поєднати C та Rust в одному проекті? +], +zh: [ + 这本书的目的是: + - 让开发者快速上手Rust嵌入式开发,比如,如何设置一个开发环境。 + - 分享那些关于使用Rust进行嵌入式开发的,现存的,最好的实践经验,比如,如何最大程度上地利用好Rust语言的特性去写更正确的嵌入式软件 + - 某种程度下作为工具书,比如,如何在一个项目里将C和Rust混合在一起使用 +])) + +#tr(( +en: [ + This book tries to be as general as possible but to make things easier + for both the readers and the writers it uses the ARM Cortex-M + architecture in all its examples. However, the book doesn't assume that + the reader is familiar with this particular architecture and explains + details particular to this architecture where required. +], +de: [ + Dieses Buch ist bestrebt, so allgemein wie möglich zu bleiben; um jedoch + sowohl den Lesern als auch den Autoren die Arbeit zu erleichtern, + verwendet es in allen Beispielen die ARM-Cortex-M-Architektur. Dennoch + setzt das Buch keine Vorkenntnisse zu dieser speziellen Architektur + voraus und erläutert die entsprechenden Besonderheiten, wo immer dies + erforderlich ist. +], +ja: [ + 本書は出来る限り一般的な事項を取り扱います。ただし、説明を簡単にするために、全ての例で、ARM + Cortex-Mアーキテクチャを利用します。 + 読者は、このアーキテクチャに詳しい必要はありません。本書では、アーキテクチャ固有の詳細について、必要に応じて説明をします。 +], +uk: [ + Ця книга намагається бути якомога більш загальною, але щоб полегшити роботу + як читачам, так і авторам, у ній використовується архітектура ARM Cortex-M у всіх її прикладах. + Однак книга не передбачає, що читач знайомий із цією конкретною архітектурою, + і пояснює деталі, пов’язані з цією архітектурою, де потрібно. +], +zh: [ + 虽然尽可能地尝试让这本书可以用于大多数场景,但是为了使读者和作者更容易理解,在所有的示例中,这本书都使用了ARM + Cortex-M架构。然而,这本书并不需要读者熟悉这个架构,书中会在需要时对这个架构的特定细节进行解释。 +])) + += #tr(( + en: [Who This Book is For], + de: [Für wen dieses Buch gedacht ist], + ja: [この本は誰のためのもの], + uk: [Для кого Ця Книга], + zh: [这本书是为谁准备的], +)) + +#tr(( +en: [ + This book caters towards people with either some embedded background or + some Rust background, however we believe everybody curious about + embedded Rust programming can get something out of this book. For those + without any prior knowledge we suggest you read the "Assumptions and + Prerequisites" section and catch up on missing knowledge to get more out + of the book and improve your reading experience. You can check out the + "Other Resources" section to find resources on topics you might want to + catch up on. +], +de: [ + Dieses Buch richtet sich an Personen mit Vorkenntnissen im Bereich + Embedded-Systeme oder Rust; wir sind jedoch der Meinung, dass jeder, der + sich für die Embedded-Programmierung mit Rust interessiert, von diesem + Buch profitieren kann. Wer keine Vorkenntnisse mitbringt, dem empfehlen + wir, den Abschnitt „Annahmen und Voraussetzungen" zu lesen und sich + entsprechendes Wissen anzueignen, um den größtmöglichen Nutzen aus dem + Buch zu ziehen und das Leseerlebnis zu verbessern. Im Abschnitt „Weitere + Ressourcen" finden Sie Hinweise zu Themen, in die Sie sich bei Bedarf + einarbeiten können. +], +ja: [ + 本書は、組込み開発か、Rustかのバックグラウンドを持つ人々に向けたものです。しかし、組込みRustに興味がある人なら、誰でも、この本から何かを得られると思います。本書による学習効果を高めるために、事前知識が不足している読者は、「仮定と前提条件」のセクションを読み、不足している知識を補うことをお勧めします。不足知識を補うリソースを見つけるために、「その他のリソース」セクションをチェックすることができます。 +], +uk: [ + Ця книга розрахована на людей, які мають досвід роботи з вбудованими програмами або з Rust, + але ми віримо, що всі, хто цікавиться програмуванням у вбудованому Rust, можуть щось отримати з цієї книги. + Для тих, хто не має попередніх знань, ми пропонуємо прочитати розділ «Припущення та передумови» + та надолужити пропущені знання, щоб отримати більше від книги та покращити свій досвід читання. + Ви можете переглянути розділ «Інші ресурси», щоб знайти ресурси на теми, які, можливо, захочете надолужити. +], +zh: [ + 这本书适合那些有一些嵌入式背景或者有Rust背景的人,然而我相信每一个对Rust嵌入式编程好奇的人都能从这本书中获得某些收获。对于那些先前没有任何经验的人,我们建议你读一下"要求和预备知识"部分。从其它资料中获取、补充缺失的知识,这样能提高你的阅读体验。你可以看看"其它资源"部分,以找到你感兴趣的那些主题的资源。 +])) + +== #tr(( + en: [Assumptions and Prerequisites], + de: [Annahmen und Voraussetzungen], + ja: [仮定と前提条件], + uk: [Припущення та передумови], + zh: [要求和预备知识], +)) + +#let url_ediion = "https://doc.rust-lang.org/edition-guide/" +#tr(( +en: [ + - You are comfortable using the Rust Programming Language, and have + written, run, and debugged Rust applications on a desktop environment. + You should also be familiar with the idioms of the + #link(url_ediion)[2018 edition] as + this book targets Rust 2018. + + - You are comfortable developing and debugging embedded systems in + another language such as C, C++, or Ada, and are familiar with + concepts such as: + - Cross Compilation + - Memory Mapped Peripherals + - Interrupts + - Common interfaces such as I2C, SPI, Serial, etc. +], +de: [ + - Sie sind sicher im Umgang mit der Programmiersprache Rust und haben + bereits Rust-Anwendungen in einer Desktop-Umgebung geschrieben, + ausgeführt und deren Fehler behoben. Zudem sollten Sie mit den Idiomen + der #link(url_ediion)[2018 Edition] + vertraut sein, da sich dieses Buch auf Rust 2018 konzentriert. + + - Sie sind sicher in der Entwicklung und Fehlersuche bei + Embedded-Systemen in einer anderen Sprache wie C, C++ oder Ada und mit + Konzepten vertraut wie: + - Cross-Kompilierung + - Im Speicher abgebildete Peripheriegeräte + - Interrupts + - Gängige Schnittstellen wie I2C, SPI, seriell usw. +], +ja: [ + - Rustでのプログラミングを楽しんでおり、デスクトップ環境でRustアプリケーションを書いたり、実行したり、デバッグしたりしたことがあることを前提とします。また、本書ではRust + 2018を対象とするため、2018 + editionのイディオムに慣れ親しんでいる必要があります。 + - C, C++, + Adaといった言語で組込みシステムを開発、デバッグすることに慣れており、次の概念になじみがあることを想定します。 + - クロスコンパイル + - メモリマップ方式のペリフェラル + - 割り込み + - I2C、SPI、シリアルといった一般的なインタフェース +], +uk: [ + - Вам зручно користуватися мовою програмування Rust і ви вже писали, + запускали та налагоджували програми Rust у середовищі робочого столу. + Ви також повинні бути знайомі з ідіомами #link(url_ediion)[2018 Edition], оскільки ця книга спрямована на Rust 2018. + - Вам зручно розробляти та налагоджувати вбудовані системи іншою + мовою, наприклад C, C++ або Ada, і ви знайомі з такими поняттями, як: + - Крос-компіляція + - Периферійні пристрої з відображенням у пам'яті + - Переривання + - Загальні інтерфейси, такі як I2C, SPI, Serial тощо. +], +zh: [ + - 你可以轻松地使用Rust编程语言,且在一个桌面环境上写过,运行过,调试过Rust应用。你应该也要熟悉#link(url_ediion)[2018 edition]的术语,因为这本书是面向Rust + 2018的。 + + - 你可以轻松地使用其它语言,比如C,C++或者Ada,开发和调试嵌入式系统,且熟悉如下的概念: + - 交叉编译 + - 存储映射的外设(Memory Mapped Peripherals) + - 中断 + - I2C,SPI,串口等等常见的接口 +])) + +== #tr(( + en: [Other Resources], + de: [Weitere Ressourcen], + ja: [その他のリソース], + uk: [Інші ресурси], + zh: [其它资源], +)) + +#tr(( +en: [ + If you are unfamiliar with anything mentioned above or if you want more + information about a specific topic mentioned in this book you might find + some of these resources helpful. +], +de: [ + Falls Ihnen einer der oben genannten Punkte nicht vertraut ist oder Sie + mehr über ein bestimmtes, in diesem Buch erwähntes Thema erfahren + möchten, könnten einige dieser Ressourcen hilfreich für Sie sein. +], +ja: [ + もしあなたが上述した何らかの事項をよく知らない場合、もしくは、本書内の特定トピックに関して、より詳細な情報を知りたい場合、これらのリソースが役に立つでしょう。 +], +uk: [ + Якщо ви не знайомі з чимось із згаданого вище або вам потрібна додаткова інформація про конкретну тему, згадану в цій книзі, деякі з цих ресурсів можуть стати в нагоді. +], +zh: [ + 如果你还不熟悉上面提到的东西或者你对这本书中提到的某个特定主题感兴趣,你也许能从这些资源中找到有用的信息。 +])) + +#figure( + kind: table, + table( + columns: (37.84%, 27.03%, 35.14%), + align: (center,left,left,), + table.header( + tr(( + en: [Topic], + de: [Thema], + ja: [トピック], + zh: [主题], + )), + tr(( + en: [Resource], + de: [Ressource], + ja: [リソース], + zh: [资源], + )), + tr(( + en: [Description], + de: [Beschreibung], + ja: [説明], + zh: [描述], + )), + ), + [Rust], + link("https://doc.rust-lang.org/book/")[Rust Book], + tr(( + en: [ + If you are not yet comfortable with Rust, we highly suggest reading this book. + ], + de: [ + Wenn Sie sich mit Rust noch nicht sicher fühlen, + empfehlen wir Ihnen dringend, dieses Buch zu lesen. + ], + ja: [ + もしRustに親しんでいない場合、この本を読むことを強くお勧めします。 + ], + zh: [ + 如果你还不熟悉Rust,我们强烈建议你读这本书. + ], + )), + + [Rust, Embedded], + link("https://docs.rust-embedded.org/discovery/")[Discovery Book], + tr(( + en: [ + If you have never done any embedded programming, this book might be a better start + ], + de: [ + Wenn Sie sich noch nie mit eingebetteter Programmierung beschäftigt haben, + ist dieses Buch möglicherweise der bessere Einstieg + ], + zh: [ + 如果你从没做过嵌入式编程,这本书可能是个更好的开端. + ], + )), + + [Rust, Embedded], link("https://docs.rust-embedded.org")[Embedded Rust Bookshelf], + tr(( + en: [ + Here you can find several other resources provided by Rust's Embedded Working Group. + ], + de: [ + Hier finden Sie weitere Ressourcen, die von der Embedded Working Group + von Rust bereitgestellt werden. + ], + ja: [ + Rust組込みワーキンググループによるいくらかのリソースがあります。 + ], + zh: [ + 在这里,你可以找到由Rust的嵌入式工作组提供的许多其它资源. + ], + )), + + [Rust, Embedded], + link("https://docs.rust-embedded.org/embedonomicon/")[Embedonomicon], + tr(( + en: [ + The nitty gritty details when doing embedded programming in Rust. + ], + de: [ + Die Feinheiten der Embedded-Programmierung mit Rust. + ], + ja: [ + Rustで組込みプログラミングを行うときのより深い詳細が記載されています。 + ], + zh: [ + 用Rust进行嵌入式编程的细节. + ], + )), + + [Rust, Embedded], + link("https://docs.rust-embedded.org/faq.html")[embedded FAQ], + tr(( + en: [ + Frequently asked questions about Rust in an embedded context. + ], + de: [ + Häufig gestellte Fragen zu Rust im Embedded-Umfeld. + ], + ja: [ + 組込みでRustを使う際のよくある質問と回答です。 + ], + zh: [ + Rust在嵌入式上下文中遇到的常见问题. + ], + )), + + [Rust, Embedded], + link("https://google.github.io/comprehensive-rust/bare-metal.html")[Comprehensive Rust 🦀: Bare Metal], + tr(( + en: [ + Teaching material for a 4-day class on bare-metal Rust development + ], + de: [ + Unterrichtsmaterial für einen viertägigen Kurs zu Bare-Metal Rust development + ], + zh: [ + 用于四天课时的裸机Rust开发课程的教学资料. + ], + )), + + [Interrupts], + link("https://en.wikipedia.org/wiki/Interrupt")[Interrupt], + [-], + + [Memory-mapped IO/Peripherals], + link("https://en.wikipedia.org/wiki/Memory-mapped_I/O")[Memory-mapped I/O], + [-], + + [SPI, UART, RS232, USB, I2C, TTL], + link("https://electronics.stackexchange.com/questions/37814/usart-uart-rs232-usb-spi-i2c-ttl-etc-what-are-all-of-these-and-how-do-th")[Stack Exchange about SPI, UART, and other interfaces], + [-], + ) +) + +== #tr(( + en: [Translations], + de: [Übersetzungen], + uk: [Переклади], + zh: [翻译], +)) + +#let url_ja = "https://tomoyuki-nakabayashi.github.io/book/" +#let url_ja_rep = "https://github.com/tomoyuki-nakabayashi/book" +#let url_zh = "https://xxchang.github.io/book/" +#let url_zh_rep = "https://github.com/XxChang/book" +#tr(( +en: [ + This book has been translated by generous volunteers. If you would like + your translation listed here, please open a PR to add it. + - #link(url_ja)[Japanese] (#link(url_ja_rep)[repository]) + - #link(url_zh)[Chinese] (#link(url_zh_rep)[repository]) +], +de: [ + Dieses Buch wurde von großzügigen Freiwilligen übersetzt. Wenn Ihre + Übersetzung hier aufgeführt werden soll, erstellen Sie bitte einen Pull + Request, um sie hinzuzufügen. + - #link(url_ja)[Japanisch] (#link(url_ja_rep)[repository]) + - #link(url_zh)[Chinesisch] (#link(url_zh_rep)[repository]) +], +uk: [ + Цю книгу перекладено волонтерами. + Якщо ви хочете, щоб ваш переклад був тут, будь ласка, + відкрийте запит на злиття, щоб додати його. + - #link(url_ja)[Японською] (#link(url_ja_rep)[репозиторій]) + - #link(url_zh)[Китайською] (#link(url_zh_rep)[репозиторій]) +], +zh: [ + 这本书是已经被一些慷慨的志愿者们翻译了。如果你想要将你的翻译列在这里,请打开一个PR去添加它。 + - #link(url_ja)[日文] (#link(url_ja_rep)[repository]) + - #link(url_zh)[中文] (#link(url_zh_rep)[repository]) +])) + +== #tr(( + en: [How to Use This Book], + de: [Wie Sie dieses Buch nutzen], + ja: [この本はどう使う], + uk: [Як читати цю книгу], + zh: [如何使用这本书], +)) + +#tr(( +en: [ + This book generally assumes that you're reading it front-to-back. Later + chapters build on concepts in earlier chapters, and earlier chapters may + not dig into details on a topic, revisiting the topic in a later + chapter. +], +de: [ + Dieses Buch ist im Allgemeinen so konzipiert, dass es von Anfang bis + Ende gelesen wird. Spätere Kapitel bauen auf den Konzepten früherer + Kapitel auf; dabei werden bestimmte Themen in den früheren Kapiteln + möglicherweise noch nicht bis ins Detail behandelt, sondern erst in + einem späteren Kapitel erneut aufgegriffen. +], +ja: [ + この本は、前から順番に読んでいくことを想定しています。後半の章は、前半の章で説明する概念に基づいて成り立っています。前半の章では、トピックの詳細に深入りせず、後半の章で再訪問します。 +], +uk: [ + Ця книга зазвичай передбачає, що ви читаєте її послідовно. Подальші + розділи ґрунтуються на концепціях попередніх розділів, і попередні розділи можуть + не заглиблюватися в деталі теми, повертаючись до неї в наступному розділі. +], +zh: [ + 这本书通常假设你是按顺序阅读的。之后的章节是建立在先前的章节中提到的概念之上的,先前章节可能不会深入一个主题的细节,因为在随后的章节将会再次重温这个主题。 +])) + +#let url_f3disco = "http://www.st.com/en/evaluation-tools/stm32f3discovery.html" +#tr(( +en: [ + This book will be using the #link(url_f3disco)[STM32F3DISCOVERY] + development board from STMicroelectronics for the majority of the + examples contained within. This board is based on the ARM Cortex-M + architecture, and while basic functionality is the same across most CPUs + based on this architecture, peripherals and other implementation details + of Microcontrollers are different between different vendors, and often + even different between Microcontroller families from the same vendor. +], +de: [ + Für den Großteil der in diesem Buch enthaltenen Beispiele wird das + Entwicklungsboard #link(url_f3disco)[STM32F3DISCOVERY] + von STMicroelectronics verwendet. Dieses Board basiert auf der + ARM-Cortex-M-Architektur. Zwar ist die grundlegende Funktionalität bei + den meisten auf dieser Architektur basierenden CPUs identisch, doch + unterscheiden sich Peripheriekomponenten und andere + Implementierungsdetails der Mikrocontroller je nach Hersteller -- und + oft sogar zwischen verschiedenen Mikrocontroller-Familien desselben + Herstellers. +], +ja: [ + この本は、ほとんどの例で、STマイクロエレクトロニクスの#link(url_f3disco)[STM32F3DISCOVERY]開発ボードを使用します。このボードは、ARM + Cortex-Mアーキテクチャをベースとしています。基本機能はこのアーキテクチャベースのCPUでは共通です。一方、ペリフェラルとマイクロコントローラ実装の詳細は、他のベンダーと異なります。同じSTマイクロエレクトロニクスのマイクロコントローラファミリでも、違いがあります。 +], +uk: [ + Для більшості наведених у цій книзі прикладів використовуватиметься + розробна плата #link(url_f3disco)[STM32F3DISCOVERY] від STMicroelectronics. Ця плата + заснована на архітектурі ARM Cortex-M, і хоча основні функції однакові + для більшості процесорів на основі цієї архітектури, периферійні пристрої та інші + деталі реалізації відрізняються у мікроконтролерах різних постачальників, + і часто навіть різняться між сімействами мікроконтролерів одного й того ж + постачальника. +], +zh: [ + 在大多数示例中这本书将使用#link(url_f3disco)[STM32F3DISCOVERY]开发板。这个板子是基于ARM + Cortex-M架构的,且基本功能与大多数基于这个架构的CPUs功能相似。微处理器的外设和其它实现细节在不同的厂家之间是不同的,甚至来自同一个厂家,不同处理器系列之间也是不同的。 +])) + +#tr(( +en: [ + For this reason, we suggest purchasing the + #link(url_f3disco)[STM32F3DISCOVERY] + development board for the purpose of following the examples in this + book. +], +de: [ + Aus diesem Grund empfehlen wir die Anschaffung des Entwicklungsboards + #link(url_f3disco)[STM32F3DISCOVERY], + um die Beispiele in diesem Buch praktisch nachvollziehen zu können. +], +ja: [ + 上記の理由から、本書内の例を理解するために、#link(url_f3disco)[STM32F3DISCOVERY]開発ボードを購入することをお勧めします。 +], +uk: [ + З цієї причини ми пропонуємо придбати плату розробки + #link(url_f3disco)[STM32F3DISCOVERY] щоб повторювати приклади з цієї книги. +], +zh: [ + 因此我们建议购买#link(url_f3disco)[STM32F3DISCOVERY]开发板来尝试这本书中的例子。 +])) + +== #tr(( + en: [Contributing to This Book], + de: [Beiträge zu diesem Buch], + uk: [Внесок у цю книгу], + zh: [贡献], +)) + +#let url_repo = "https://github.com/rust-embedded/book" +#let url_team = "https://github.com/rust-embedded/wg#the-resources-team" +#tr(( +en: [ + The work on this book is coordinated in #link(url_repo)[this repository] + and is mainly developed by the #link(url_team)[resources team]. +], +de: [ + Die Arbeit an diesem Buch wird in #link(url_repo)[diesem Repository] koordiniert + und hauptsächlich vom #link(url_team)[Ressourcen-Team] vorangetrieben. +], +uk: [ + Робота над цією книгою координується в #link(url_repo)[цьому сховищі] + і в основному розробляється #link(url_team)[командою ресурсів]. +], +zh: [ + 这本书的工作主要在#link(url_repo)[这个仓库]里管理,且主要由#link(url_team)[resouces team]开发。 +])) + +#let url_issues = "https://github.com/rust-embedded/book/issues/" +#tr(( +en: [ + If you have trouble following the instructions in this book or find that + some section of the book is not clear enough or hard to follow then + that's a bug and it should be reported in #link(url_issues)[the issue tracker] + of this book. +], +de: [ + Wenn Sie Schwierigkeiten haben, den Anweisungen in diesem Buch zu + folgen, oder wenn ein Abschnitt des Buches nicht klar genug oder schwer + verständlich ist, handelt es sich um einen Fehler; dieser sollte im + #link(url_issues)[Problem-Verfolgungswerkzeug] + des Buches gemeldet werden. +], +uk: [ + Якщо у вас виникли проблеми з дотриманням інструкцій з цієї книги + або ви вважаєте, що якийсь розділ книги недостатньо зрозумілий + або складний для виконання, то це помилка, і про неї слід повідомити + в #link(url_issues)[трекері випуску] цієї книги. +], +zh: [ + 如果你按着这本书的操作遇到了什么麻烦,或者这本书的一些部分不够清楚,或者很难进行下去,那这本书就是有个bug,这个bug应该被报道给这本书的#link("https://github.com/rust-embedded/book/issues/")[the issue tracker] + 。 +])) + +#tr(( +en: [ + Pull requests fixing typos and adding new content are very welcome! +], +de: [ + Pull Requests, die Tippfehler korrigieren oder neue Inhalte hinzufügen, + sind herzlich willkommen! +], +uk: [ + Запити на виправлення помилок і додавання нового матеріалу дуже вітаються! +], +zh: [ + 修改拼写错误和添加新内容的Pull requests非常欢迎! +])) + += #tr(( + en: [Re-using this material], + de: [Wiederverwendung dieses Materials], + uk: [Повторне використання цього матеріалу], + zh: [二次使用这个材料], +)) + +#{ +let mit = "https://opensource.org/licenses/MIT" +let apache = "http://www.apache.org/licenses/LICENSE-2.0" +let legalcode = "https://creativecommons.org/licenses/by-sa/4.0/legalcode" +tr(( + en: [ + This book is distributed under the following licenses: + - The code samples and free-standing Cargo projects contained within + this book are licensed under the terms of both the + #link(mit)[MIT License] and the + #link(apache)[Apache License v2.0]. + - The written prose, pictures and diagrams contained within this book + are licensed under the terms of the Creative Commons + #link(legalcode)[CC-BY-SA v4.0] + license. +], +de: [ + Dieses Buch wird unter den folgenden Lizenzen vertrieben: + - Die in diesem Buch enthaltenen Codebeispiele und eigenständigen + Cargo-Projekte stehen unter den Bedingungen sowohl der + #link(apache)[MIT-Lizenz] als auch der + #link(apache)[Apache-Lizenz v2.0]. + - Die in diesem Buch enthaltenen Texte, Bilder und Diagramme stehen + unter der Lizenz Creative Commons + #link(legalcode)[CC-BY-SA v4.0]. +], +uk: [ + Ця книга розповсюджується за наступними ліцензіями: + - Зразки коду та окремі проекти Cargo, що містяться в цій книзі, ліцензовано + відповідно до умов #link(mit)[MIT License] та #link(apache)[Apache License v2.0]. + - Текст, малюнки та діаграми, що містяться в цій книзі, ліцензовані відповідно до + умов ліцензії Creative Commons #link(legalcode)[CC-BY-SA v4.0]. +], +zh: [ + 这本书根据以下许可证发布: + - 本书中包含的代码示例和独立的Cargo项目均根据#link(mit)[MIT License]和#link(apache)[Apache License v2.0]发放许可的。 + - 本书中包含的文档,图片和表格均根据#link(legalcode)[CC-BY-SA v4.0]发放许可的。 +])) + +tr(( + en: [ + TL;DR: If you want to use our text or images in your work, you need to: + - Give the appropriate credit (i.e.~mention this book on your slide, and + provide a link to the relevant page) + - Provide a link to the + #link(legalcode)[CC-BY-SA v4.0] + licence + - Indicate if you have changed the material in any way, and make any + changes to our material available under the same licence +], +de: [ + Kurz gesagt: Wenn Sie unsere Texte oder Bilder für Ihre Arbeit verwenden + möchten, müssen Sie: + - Geben Sie die entsprechende Quellenangabe an (d.~h. erwähnen Sie + dieses Buch auf Ihrer Folie und geben Sie einen Link zur entsprechenden Seite an). + - Geben Sie einen Link zur + #link(legalcode)[CC-BY-SA v4.0]-Lizenz an. + - Geben Sie an, ob Sie das Material in irgendeiner Weise verändert + haben, und stellen Sie Änderungen an unserem Material unter derselben + Lizenz zur Verfügung. +], +uk: [ + TL;DR: Якщо ви маєте намір використовувати наш текст або зображення у своїй роботі, вам потрібно: + - Надати відповідне посилання (тобто згадати цю книгу + на своєму слайді та надати посилання на відповідну сторінку) + - Надати посилання на ліцензію #link(legalcode)[CC-BY-SA v4.0] + - Вказати, чи змінювали ви матеріал будь-яким чином, + і зробити зміни в наші матеріали доступними за тією ж ліцензією +], +zh: [ + 总之:如果你想在你的工作中使用我们的文档或者图片,你需要: + - 提供合适的授信 (i.e.~在你的幻灯片中提到本书,提供相关页面的连接) + - 提供#link(legalcode)[CC-BY-SA v4.0]的许可证的链接 + - 指出你是否改变了材料的内容,在同一个许可证下,可以对材料进行任何改变 +])) +} + +#tr(( +en: [ + Also, please do let us know if you find this book useful! +], +de: [ + Teilen Sie uns bitte auch mit, ob Sie dieses Buch nützlich finden! +], +uk: [ + Також, будь ласка, повідомте нам, якщо ви знайдете цю книгу корисною! +], +zh: [ + 也请告诉我这本书对你是否有帮助! +])) diff --git a/typ/intro/install.typ b/typ/intro/install.typ new file mode 100644 index 00000000..006991a1 --- /dev/null +++ b/typ/intro/install.typ @@ -0,0 +1,278 @@ +#import "../config.typ": * + +#h1((en: [Installing the tools], + de: [Werkzeuge installieren], + ja: [ツールのインストール], + zh: [安装工具], +), offset: whole) + +#tr(( +en: [ + This page contains OS-agnostic installation instructions for a few of + the tools: +], +de: [ + Diese Seite enthält betriebssystemunabhängige Installationsanleitungen für + einige der Werkzeuge: +], +ja: [ + このページには、いくつかのツールのOSに依存しないインストール手順を掲載します。 +], +zh: [ + 这一页包含的工具安装指令与操作系统无关: +])) + +== #tr(( + en: [Rust Toolchain], + de: [Rust-Werkzeuge], + ja: [Rustツールチェイン], + zh: [Rust 工具链], +)) + +#let ln_rustup = link("https://rustup.rs") +#tr(( +en: [ + Install rustup by following the instructions at #ln_rustup. +], +de: [ + Installieren Sie rustup, indem Sie die Anweisungen unter #ln_rustup. +], +ja: [ + #ln_rustup;の手順に従って、rustupをインストールします。 +])) + +#tr(( +en: [ + *NOTE* Make sure you have a compiler version equal to or newer than `1.31`. + `rustc -V` should return a date newer than the one shown below. +], +de: [ + *HINWEIS* Stellen Sie sicher, dass Sie eine Compiler-Version verwenden, die mindestens `1.31` entspricht. Der Befehl `rustc -V` + sollte ein Datum ausgeben, das neuer ist als das unten angegebene. +], +ja: [ + *注意* + コンパイラのバージョンが`1.31`以上であることを確認して下さい。`rustc -v`は下記に示す日付より新しい日付を返すべきです。 +], +zh: [ + *注意* + 确保你的编译器版本等于或者大于`1.31`版本。`rustc -V`应该返回一个比下列日期更新的日期。 +])) + +```text +$ rustc -V +rustc 1.31.1 (b6c32da9b 2018-12-18) +``` + +#let url_find = "https://developer.arm.com/ip-products/processors/cortex-m#c-7d3b69ce-5b17-4c9e-8f06-59b605713133" +#tr(( +en: [ + For bandwidth and disk usage concerns the default installation only + supports native compilation. To add cross compilation support for the + ARM Cortex-M architectures choose one of the following compilation + targets. For the STM32F3DISCOVERY board used for the examples in this + book, use the `thumbv7em-none-eabihf` target. + #link(url_find)[Find the best Cortex-M for you.] +], +de: [ + Aus Gründen der Bandbreite und der Festplattenauslastung + unterstützt die Standardinstallation nur die native Kompilierung. Um die + Unterstützung für die Cross-Kompilierung für die ARM-Cortex-M-Architekturen + hinzuzufügen, wählen Sie eines der folgenden Kompilierungsziele aus. Für das + STM32F3DISCOVERY-Board, das für die Beispiele in diesem Buch verwendet wird, + verwenden Sie das Ziel `thumbv7em-none-eabihf`. + #link(url_find)[Finden Sie den für Sie am besten geeigneten Cortex-M.] +], +ja: [ + #todoupd("ja") + バンド幅とディスク使用量に関する懸念から、デフォルトインストールではネイティブコンパイルのみをサポートします。 + ARM + Cortex-Mアーキテクチャのクロスコンパイラを追加するために、下記のコンパイルターゲットをインストールします。 +], +zh: [ + #todoupd("zh") + 考虑到带宽和磁盘的使用量,默认的安装只支持主机环境的编译。为了添加对ARM + Cortex-M架构交叉编译的支持,从下列编译目标中选择一个。对于这本书里使用的STM32F3DISCOVERY板子,使用`thumbv7em-none-eabihf`作为目标。 +])) + +#tr(( +en: [ + Cortex-M0, M0+, and M1 (ARMv6-M architecture): +], +de: [ + Cortex-M0, M0+, and M1 (ARMv6-M-Architektur): +], +zh: [ + Cortex-M0, M0+, 和 M1 (ARMv6-M 架构): +])) + +```console +rustup target add thumbv6m-none-eabi +``` + +#tr(( +en: [ + Cortex-M3 (ARMv7-M architecture): +], +de: [ + Cortex-M3 (ARMv7-M-Architektur): +], +zh: [ + Cortex-M3 (ARMv7-M 架构): +])) + +```console +rustup target add thumbv7m-none-eabi +``` + +#tr(( +en: [ + Cortex-M4 and M7 without hardware floating point (ARMv7E-M architecture): +], +de: [ + Cortex-M4 und M7 ohne Hardware-Gleitkommafunktion + (ARMv7E-M-Architektur): +], +zh: [ + 没有硬件浮点单元的Cortex-M4和M7 (ARMv7E-M架构) +])) + +```console +rustup target add thumbv7em-none-eabi +``` + +#tr(( +en: [ + Cortex-M4F and M7F with hardware floating point (ARMv7E-M architecture): +], +de: [ + Cortex-M4F und M7F mit Hardware-Gleitkomma (ARMv7E-M-Architektur): +], +zh: [ + 具有硬件浮点单元的Cortex-M4F和M7F (ARMv7E-M架构) +])) + +```console +rustup target add thumbv7em-none-eabihf +``` + +#tr(( +en: [ + Cortex-M23 (ARMv8-M architecture): +], +de: [ + Cortex-M23 (ARMv8-M-Architektur): +], +zh: [ + Cortex-M23 (ARMv8-M架构): +])) + +```console +rustup target add thumbv8m.base-none-eabi +``` + +#tr(( +en: [ + Cortex-M33 and M35P (ARMv8-M architecture): +], +de: [ + Cortex-M33 und M35P (ARMv8-M-Architektur): +], +zh: [ + Cortex-M33和M35P (ARMv8-M架构): +])) + +```console +rustup target add thumbv8m.main-none-eabi +``` + +#tr(( +en: [ + Cortex-M33F and M35PF with hardware floating point (ARMv8-M architecture): +], +de: [ + Cortex-M33F und M35PF mit Hardware-Gleitkomma (ARMv8-M-Architektur): +], +zh: [ + 具有硬件浮点单元的Cortex-M33F和M35PF (ARMv8-M架构): +])) + +```console +rustup target add thumbv8m.main-none-eabihf +``` + +== `cargo-binutils` + +```text +cargo install cargo-binutils + +rustup component add llvm-tools +``` + +#let ln_vs = link("https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=16") +#tr(( +en: [ + WINDOWS: prerequisite C++ Build Tools for Visual Studio 2019 is installed. #ln_vs +], +de: [ + WINDOWS: Voraussetzung ist, dass die C++-Build-Tools für Visual Studio 2019 + installiert sind. #ln_vs +], +zh: [ + WINDOWS: 需要预先安装 C++ Build Tools for Visual Studio 2019。#ln_vs +])) + +== `cargo-generate` + +#tr(( +en: [ + We'll use this later to generate a project from a template. +], +de: [ + Wir werden dies später verwenden, um ein Projekt aus einer Vorlage zu generieren. +], +zh: [ + 我们随后将使用这个来从模板生成一个项目。 +])) + +```console +cargo install cargo-generate +``` + +#tr(( +en: [ + Note: on some Linux distros (e.g.~Ubuntu) you may need to install the + packages `libssl-dev` and `pkg-config` prior to installing cargo-generate. +], +de: [ + Hinweis: Bei einigen Linux-Distributionen (z. B. Ubuntu) müssen Sie + möglicherweise vor der Installation von `cargo-generate` die Pakete `libssl-dev` + und `pkg-config` installieren. +], +zh: [ + 注意:在某些Linux发行版上(e.g.~Ubuntu) + 在安装cargo-generate之前,你可能需要安装`libssl-dev`和`pkg-config` +])) + +== #tr(( + en: [OS-Specific Instructions], + de: [Betriebssystemspezifische Anweisungen], + zh: [特定于操作系统的指令], +)) + +#tr(( +en: [ + Now follow the instructions specific to the OS you are using: +], +de: [ + Befolgen Sie nun die Anweisungen für das von Ihnen verwendete Betriebssystem: +], +ja: [ + 使用しているOSに特有の手順に従って下さい。 +], +zh: [ + 现在根据你使用的操作系统,来执行对应的指令: +])) +- #link()[Linux] +- #link()[Windows] +- #link()[macOS] diff --git a/typ/intro/install/linux.typ b/typ/intro/install/linux.typ new file mode 100644 index 00000000..0eff6de1 --- /dev/null +++ b/typ/intro/install/linux.typ @@ -0,0 +1,321 @@ +#import "../../config.typ": * + +#h1([Linux], + offset: whole*2) + + +#tr(( +en: [ + Here are the installation commands for a few Linux distributions. +], +de: [ + Hier sind die Installationsbefehle für einige Linux-Distributionen. +], +ja: [ + いくつかのLinuxディストリビューションのインストールコマンドを示します。 +], +zh: [ + 这部分是在某些Linux发行版下的安装指令。 +])) + += #tr(( + en: [Packages], + de: [Pakete], + ja: [Packages], + zh: [依赖包], +)) + +#tr(( +en: [ + - Ubuntu 18.04 or newer / Debian stretch or newer +], +de: [ + - Ubuntu 18.04 oder neuer / Debian Stretch oder neuer +], +ja: [ + - Ubuntu 18.04以上 / Debian stretch以降 +], +zh: [ + - Ubuntu 18.04 或者更新的版本 / Debian stretch 或者更新的版本 +])) + +#quote(block: true)[ +#tr(( +en: [ + *NOTE* `gdb-multiarch` is the GDB command you'll use to debug + your ARM Cortex-M programs +], +de: [ + *HINWEIS* `gdb-multiarch` ist der GDB-Befehl, den Sie zum + Debuggen Ihrer ARM-Cortex-M-Programme verwenden werden. +], +ja: [ + *注記* `gdb-multiarch`は、ARM + Cortex-Mプログラムをデバッグするために使用するGDBのコマンドです。 +], +zh: [ + * 注意* `gdb-multiarch` 是你将用来调试你的ARM +])) +] + +```console +sudo apt install gdb-multiarch openocd qemu-system-arm +``` + +#let _and_ = tr(( + en: [ and ], + de: [ und ], + ja: [と], +), default: [ and ]) + +- Ubuntu 14.04#_and_;16.04 + +#quote(block: true)[ +#tr(( +en: [ + *NOTE* `arm-none-eabi-gdb` is the GDB command you'll use to debug + your ARM Cortex-M programs +], +de: [ + *HINWEIS* `arm-none-eabi-gdb` ist der GDB-Befehl, den Sie zum + Debuggen Ihrer ARM-Cortex-M-Programme verwenden werden. +], +ja: [ + *注記* `arm-none-eabi-gdb`は、ARM + Cortex-Mプログラムをデバッグするために使用するGDBのコマンドです。 +], +zh: [ + *注意* `arm-none-eabi-gdb` 是你将用来调试你的ARM + Cortex-M程序的GDB命令 +])) +] + +```console +sudo apt install gdb-arm-none-eabi openocd qemu-system-arm +``` + +#tr(( +en: [ + - Fedora 27 or newer +], +de: [ + - Fedora 27 oder neuer +], +ja: [ + - Fedora 27以上 +], +zh: [ + - Fedora 27 或者更新的版本 +])) + +```console +sudo dnf install gdb openocd qemu-system-arm +``` + +- Arch Linux + +#quote(block: true)[ +#tr(( +en: [ + *NOTE* `arm-none-eabi-gdb` is the GDB command you'll use to debug + ARM Cortex-M programs +], +de: [ + *HINWEIS* `arm-none-eabi-gdb` ist der GDB-Befehl, den Sie zum + Debuggen von ARM-Cortex-M-Programmen verwenden. +], +ja: [ + *注記* `arm-none-eabi-gdb`は、ARM + Cortex-Mプログラムをデバッグするために使用するGDBのコマンドです。 +], +zh: [ + *注意* `arm-none-eabi-gdb` 是你将用来调试你的ARM Cortex-M程序的GDB命令 +])) +] + +```console +sudo pacman -S arm-none-eabi-gdb qemu-system-arm openocd +``` + += #tr(( + en: [udev rules], + de: [udev-Regeln], + ja: [udevルール], + zh: [udev 规则], +)) + + +#tr(( +en: [ + This rule lets you use OpenOCD with the Discovery board without root privilege. +], +de: [ + Diese Regel ermöglicht die Nutzung von OpenOCD mit dem Discovery Board ohne Root-Rechte. +], +ja: [ + このルールにより、ルート権限なしで、OpenOCDをDiscoveryボードに対して使えるようにします。 +], +zh: [ + 这个规则可以让你在不使用超级用户权限的情况下,使用OpenOCD和Discovery开发板。 +])) + +#let file_stlink = `/etc/udev/rules.d/70-st-link.rules` +#tr(( +en: [ + Create the file #file_stlink with the contents shown below. +], +de: [ + Erstellen Sie die Datei #file_stlink mit dem unten stehenden Inhalt. +], +ja: [ + #todoupd("ja") + 下記の内容で、`/etc/udev/rules.d`ディレクトリにファイルを作成します。 +], +zh: [ + 生成包含下列内容的 #file_stlink 文件 +])) + +```text +# STM32F3DISCOVERY rev A/B - ST-LINK/V2 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", TAG+="uaccess" + +# STM32F3DISCOVERY rev C+ - ST-LINK/V2-1 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", TAG+="uaccess" +``` + +#tr(( +en: [ + Then reload all the udev rules with: +], +de: [ + Laden Sie anschließend alle udev-Regeln neu mit: +], +ja: [ + その後、全てのudevルールをリロードします。 +], +zh: [ + 然后重新加载所有的udev规则 +])) + +```console +sudo udevadm control --reload-rules +``` + +#tr(( +en: [ + If you had the board plugged to your laptop, unplug it and then plug it again. +], +de: [ + Wenn Sie die Platine an Ihren Laptop angeschlossen hatten, ziehen Sie + den Stecker heraus und schließen Sie ihn dann erneut an. +], +ja: [ + 既にボードをノートPCに接続している場合、一度抜いてから、もう一度接続します。 +], +zh: [ + 如果你已经把开发板插入到笔记本中了,请拔下它然后再插上它。 +])) + +#tr(( +en: [ + You can check the permissions by running this command: +], +de: [ + Sie können die Berechtigungen überprüfen, indem Sie diesen Befehl ausführen: +], +ja: [ + これらのコマンド実行することで、パーミッションを確認できます。 +], +zh: [ + 你可以通过运行这个命令检查权限: +])) + +```console +lsusb +``` + +#tr(( +en: [ + Which should show something like +], +de: [ + Was so etwas wie +], +zh: [ + 终端可能有如下显示 +])) + +```text +(..) +Bus 001 Device 018: ID 0483:374b STMicroelectronics ST-LINK/V2.1 +(..) +``` +#if lang == "de" [ + anzeigen sollte. +] + +#tr(( +en: [ + Take note of the bus and device numbers. Use those numbers to create a + path like `/dev/bus/usb//`. Then use this path like so: +], +de: [ + Notieren Sie sich die Bus- und Gerätenummern. Verwenden Sie diese + Nummern, um einen Pfad wie `/dev/bus/usb//` zu bilden. + Verwenden Sie diesen Pfad anschließend wie folgt: +], +zh: [ + 记住bus和device号,使用这些数字组合成一个像是 + `/dev/bus/usb//` 这样的路径。然后像这样使用这个路径: +])) + +```console +ls -l /dev/bus/usb/001/018 +``` + +```text +crw-------+ 1 root root 189, 17 Sep 13 12:34 /dev/bus/usb/001/018 +``` + +```console +getfacl /dev/bus/usb/001/018 | grep user +``` + +```text +user::rw- +user:you:rw- +``` + +#tr(( +en: [ + The `+` appended to permissions indicates the existence of an extended + permission. The `getfacl` command tells the user `you` can make use of + this device. +], +de: [ + Das angehängte „+" bei den Berechtigungen weist auf eine erweiterte + Berechtigung hin. Der Befehl „getfacl" teilt dem Benutzer mit, dass er + dieses Gerät verwenden darf. +], +ja: [ + #todoupd("ja") + パーミッションに追加された`+`は、パーミッションが拡張されたことを意味しています。 +], +zh: [ + 权限后的 `+` 指出存在一个扩展权限。`getfacl` + 命令显示,`user`也就是`你`,可以使用这个设备。 +])) + +#tr(( +en: [ + Now, go to the #link()[next section]. +], +de: [ + Fahren Sie nun mit dem #link()[nächsten Abschnitt] fort. +], +ja: [ + それでは、#link()[次のセクション]に進んで下さい。 +], +zh: [ + 现在,去往#link()[下个章节]. +])) diff --git a/typ/intro/install/macos.typ b/typ/intro/install/macos.typ new file mode 100644 index 00000000..2f873458 --- /dev/null +++ b/typ/intro/install/macos.typ @@ -0,0 +1,90 @@ +#import "../../config.typ": * + +#h1([macOS], + offset: whole*2) + + +#let brew_ln = link("http://brew.sh/")[Homebrew] +#let ports_ln = link("https://www.macports.org/")[MacPorts] + +#tr(( +en: [ + All the tools can be installed using #brew_ln or #ports_ln: +], +de: [ + Alle Werkzeuge können mit #brew_ln oder #ports_ln installiert werden: +], +ja: [ + #todoupd("ja") + 全てのツールは、#brew_ln;を使ってインストールできます。 +], +zh: [ + 所有的工具都可以使用#brew_ln;或者#ports_ln;来安装: +])) + += #tr(( + en: [Install tools with #brew_ln], + de: [Werkzeuge mit #brew_ln installieren], + zh: [使用#brew_ln;安装工具], +)) + +```text +$ # GDB +$ brew install arm-none-eabi-gdb + +$ # OpenOCD +$ brew install openocd + +$ # QEMU +$ brew install qemu +``` + +#quote(block: true)[ +#tr(( +en: [ + *NOTE* If OpenOCD crashes you may need to install the latest + version using: +], +de: [ + *HINWEIS* Falls OpenOCD abstürzt, müssen Sie möglicherweise die + neueste Version installieren; verwenden Sie dazu: +], +zh: [ + *注意* 如果OpenOCD崩溃了,你可能需要用以下方法安装最新版本: +])) +] + +```text +$ brew install --HEAD openocd +``` + += #tr(( + en: [Install tools with #ports_ln], + de: [Werkzeuge mit #ports_ln installieren], + zh: [使用#ports_ln;安装工具], +)) + +```text +$ # GDB +$ sudo port install arm-none-eabi-gcc + +$ # OpenOCD +$ sudo port install openocd + +$ # QEMU +$ sudo port install qemu +``` + +#tr(( +en: [ + That's all! Go to the #link()[next section]. +], +de: [ + Das war's! Gehen Sie zum #link()[nächsten Abschnitt]. +], +ja: [ + 以上です!#link()[次のセクション]に進んで下さい。 +], +zh: [ + 这是全部内容,请转入#link()[下个章节]. +])) diff --git a/typ/intro/install/verify.typ b/typ/intro/install/verify.typ new file mode 100644 index 00000000..ad12df6a --- /dev/null +++ b/typ/intro/install/verify.typ @@ -0,0 +1,245 @@ +#import "../../config.typ": * + +#h1((en: [Verify Installation], + de: [Die Installation überprüfen], + ja: [インストールの確認], + zh: [安装验证], +), offset: whole*2) + + +#tr(( +en: [ + In this section we check that some of the required tools / drivers have + been correctly installed and configured. +], +de: [ + In diesem Abschnitt überprüfen wir, ob einige der erforderlichen + Werkzeuge bzw. Treiber korrekt installiert und konfiguriert wurden. +], +ja: [ + このセクションでは、必要となるツールとドライバが正しくインストールされ、設定されていることを確認します。 +], +zh: [ + 在这个章节中我们将检查工具和驱动是否已经被正确地安装和配置了。 +])) + +#tr(( +en: [ + Connect your laptop / PC to the discovery board using a Mini-USB USB + cable. The discovery board has two USB connectors; use the one labeled + "USB ST-LINK" that sits on the center of the edge of the board. +], +de: [ + Verbinden Sie Ihren Laptop oder PC über ein Mini-USB-Kabel mit dem + Discovery-Board. Das Discovery-Board verfügt über zwei USB-Anschlüsse; + verwenden Sie den mit „USB ST-LINK" beschrifteten Anschluss, der sich + mittig an der Platinenkante befindet. +], +ja: [ + マイクロUSBケーブルを使って、ノートPC / + PCをdiscoveryボードに接続して下さい。 + discoveryボードは2つのUSBコネクタを搭載しています。 + ボード端の中央にある"USB ST-LINK"とラベルが付いたものを使用して下さい。 +], +zh: [ + 使用一个micro USB线缆将你的笔记本/个人电脑连接到discovery开发板上。discovery开发板有两个USB连接器;使用标记着"USB ST-LINK"的那个,它位于开发板边缘的中间位置。 +])) + +#tr(( +en: [ + Also check that the ST-LINK header is populated. See the picture below; + the ST-LINK header is highlighted. +], +de: [ + Überprüfen Sie außerdem, ob die ST-LINK-Stiftleiste bestückt ist. Siehe + dazu die Abbildung unten; die ST-LINK-Stiftleiste ist dort hervorgehoben. +], +ja: [ + ST-LINKヘッダが装着されていることも確認します。下の写真の赤丸で囲った部分がST-LINKヘッダです。 +], +zh: [ + 也要检查下ST-LINK的短路帽是否被安装了。看下面的图;ST-LINK短路帽用红色圈起来了。 +])) + +#tr(( +en: [ + Now run the following command: +], +de: [ + Führen Sie nun den folgenden Befehl aus: +], +ja: [ + それでは、次のコマンドを実行して下さい。 +], +zh: [ + 现在运行下面的命令: +])) + +```console +openocd -f interface/stlink.cfg -f target/stm32f3x.cfg +``` + +#quote(block: true)[ +#tr(( +en: [ + *NOTE*: Old versions of openocd, including the 0.10.0 release + from 2017, do not contain the new (and preferable) + `interface/stlink.cfg` file; instead you may need to use + `interface/stlink-v2.cfg` or `interface/stlink-v2-1.cfg`. +], +de: [ + *HINWEIS*: Ältere Versionen von OpenOCD, einschließlich der + Version 0.10.0 aus dem Jahr 2017, enthalten nicht die neue (und zu + bevorzugende) Datei `interface/stlink.cfg`; stattdessen müssen Sie + möglicherweise `interface/stlink-v2.cfg` oder + `interface/stlink-v2-1.cfg` verwenden. +], +zh: [ + *注意*: 旧版的openocd, 包括从2017发布的0.10.0, + 不包含新的(且更适合的)`interface/stlink.cfg`文件; + 你需要使用`interface/stlink-v2.cfg` 或者 `interface/stlink-v2-1.cfg`。 +])) +] + +#tr(( +en: [ + You should get the following output and the program should block the + console: +], +de: [ + Sie sollten die folgende Ausgabe erhalten und das Programm sollte die + Konsole blockieren: +], +ja: [ + 次の出力が得られ、プログラムはコンソールをブロックするはずです。 +], +zh: [ + 你应该看到了下面的输出,且程序应该阻塞住了控制台: +])) + +```text +Open On-Chip Debugger 0.10.0 +Licensed under GNU GPL v2 +For bug reports, read + http://openocd.org/doc/doxygen/bugs.html +Info : auto-selecting first available session transport "hla_swd". To override use 'transport select '. +adapter speed: 1000 kHz +adapter_nsrst_delay: 100 +Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD +none separate +Info : Unable to match requested speed 1000 kHz, using 950 kHz +Info : Unable to match requested speed 1000 kHz, using 950 kHz +Info : clock speed 950 kHz +Info : STLINK v2 JTAG v27 API v2 SWIM v15 VID 0x0483 PID 0x374B +Info : using stlink api v2 +Info : Target voltage: 2.919881 +Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints +``` + +#tr(( +en: [ + The contents may not match exactly but you should get the last line + about breakpoints and watchpoints. If you got it then terminate the + OpenOCD process and move to the #link()[next section]. +], +de: [ + Der Inhalt stimmt möglicherweise nicht exakt überein, aber die letzte + Zeile bezüglich Breakpoints und Watchpoints sollten Sie sehen. Wenn dies + der Fall ist, beenden Sie den OpenOCD-Prozess und fahren Sie mit dem + #link()[nächsten Abschnitt] fort. +], +ja: [ + 確認作業とは直接関係しませんが、ブレイクポイントとウォッチポイントに関する最後の行を取得したはずです。 + 取得できた場合、OpenOCDプロセスを停止し、#link()[次のセクション]へ進んで下さい。 +], +zh: [ + 内容可能并不是一模一样,但是在最后一行,你应该看到了breakpoints和watchpoints,如果你看到了,那就终止OpenOCD进程然后进入#link()[下个章节] +])) + +#tr(( +en: [ + If you didn't get the "breakpoints" line then try one of the following + commands. +], +de: [ + Falls du die Zeile „breakpoints" nicht erhalten hast, versuche einen der + folgenden Befehle. +], +ja: [ + "breakpoints"の行が取得できなかった場合、次のコマンドを試してく下さい。 +], +zh: [ + 如果你没看到"breakpoints"这行,尝试下下列命令中的某一个命令。 +])) + +```console +openocd -f interface/stlink-v2.cfg -f target/stm32f3x.cfg +``` + +```console +openocd -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg +``` + +#tr(( +en: [ + If one of those commands works it means you got an old hardware revision + of the discovery board. That won't be a problem but commit that fact to + memory as you'll need to configure things a bit differently later on. + You can move to the #link()[next section]. +], +de: [ + Wenn einer dieser Befehle funktioniert, bedeutet das, dass Sie eine + ältere Hardware-Revision des Discovery-Boards besitzen. Das stellt kein + Problem dar, aber merken Sie sich diesen Umstand, da Sie die + Konfiguration später etwas anders vornehmen müssen. Sie können zum + #link()[nächsten Abschnitt] übergehen. +], +ja: [ + このコマンドが機能した場合、古いハードウェアリビジョンのdiscoveryボードを入手したことを意味します。 + これは問題になりませんが、後で少し設定を変える必要があるので、そのことを覚えておいて下さい。 + #link()[次のセクション]に進むことができます。 +], +zh: [ + 如果这些命令的某条起作用了,那意味着你使用的discovery开发板是一个旧的版本。那也不成问题,但是你要记住这件事,因为随后你的配置可能有点不同。你可以移到#link()[下个章节]了。 +])) + +#tr(( +en: [ + If none of the commands work as a normal user then try to run them with + root permission (e.g.~`sudo openocd ..`). If the commands do work with + root permission then check that the + #link()[udev rules] have been correctly set. +], +de: [ + Wenn keiner der Befehle als normaler Benutzer funktioniert, versuchen + Sie, sie mit Root-Rechten auszuführen (z. B. `sudo openocd ..`). Sollten + die Befehle mit Root-Rechten funktionieren, überprüfen Sie, ob die + #link()[udev-Regeln] korrekt eingerichtet wurden. +], +ja: [ + どちらのコマンドも通常ユーザとしてうまく動かなかった場合、rootパーミッションで実行してみて下さい(例えば、`sudo openocd ..`)。 + コマンドがrootパーミッションで機能した場合、#link()[udevルール]が正しく設定されているか確認して下さい。 +], +zh: [ + 如果这些命令在普通用户模式下都没用,尝试下使用root模式运行它们(e.g.~`sudo openocd ..`)。如果命令在root模式下起作用,需要检查下#link()[udev rules]是否被正确地设置了。 +])) + +#let url_issues = "https://github.com/rust-embedded/book/issues" +#tr(( +en: [ + If you have reached this point and OpenOCD is not working please open + #link(url_issues)[an issue] and + we'll help you out! +], +de: [ + Wenn Sie an diesem Punkt angelangt sind und OpenOCD nicht funktioniert, + eröffnen Sie bitte + #link(url_issues)[eine Problemmeldung], + und wir helfen Ihnen weiter! +], +ja: [ + ここまで到着していまい、OpenOCDが動いていないならば、#link(url_issues)[issue]を作って下さい。私たちがあなたを支援します。 +], +zh: [ + 如果这些都试了,OpenOCD还不工作,请打开一个#link(url_issues)[issue],我们将帮助你! +])) diff --git a/typ/intro/install/windows.typ b/typ/intro/install/windows.typ new file mode 100644 index 00000000..d5b293c0 --- /dev/null +++ b/typ/intro/install/windows.typ @@ -0,0 +1,146 @@ +#import "../../config.typ": * + +#h1([Windows], + offset: whole*2) + + += `arm-none-eabi-gdb` + +#let url_arm_gnu = "https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads" +#tr(( +en: [ + ARM provides `.exe` installers for Windows. Grab one from #link(url_arm_gnu)[here], + and follow the instructions. Just before the installation process + finishes tick/select the "Add path to environment variable" option. Then + verify that the tools are in your `%PATH%`: +], +de: [ + ARM stellt `.exe`-Installationsprogramme für Windows bereit. + Laden Sie eines von #link(url_arm_gnu)[hier] + herunter und befolgen Sie die Anweisungen. Aktivieren Sie kurz vor + Abschluss des Installationsvorgangs die Option „Add path to environment + variable". Überprüfen Sie anschließend, ob die Werkzeuge in Ihrem + `%PATH%` enthalten sind: +], +ja: [ + ARMはWindows向けに`.exe`インストーラを提供しています。#link(url_arm_gnu)[here]から1つを入手して、手順に従って下さい。 + インストールプロセスが終了する直前に"環境変数にパスを追加"オプションを選択します。 + その後、ツールが`%PATH%`にあることを確認します。 +], +zh: [ + ARM提供了用于Windows的`.exe`安装程序。从#link(url_arm_gnu)[这里]获取, + 然后按照说明操作。 在完成安装之前,勾选/选择"Add path to environment + variable"选项。 然后验证环境变量是否添加到 `%PATH%`中: +])) + +```text +$ arm-none-eabi-gdb -v +GNU gdb (GNU Tools for Arm Embedded Processors 7-2018-q2-update) 8.1.0.20180315-git +(..) +``` + += OpenOCD + +#let url_openocd = "https://xpack.github.io/openocd/" +#let bin_path = `C:\Users\USERNAME\AppData\Roaming\xPacks\@xpack-dev-tools\openocd\0.10.0-13.1\.content\bin\` +#tr(( +en: [ + There's no official binary release of OpenOCD for Windows but if you're + not in the mood to compile it yourself, the xPack project provides a + binary distribution, #link(url_openocd)[here]. + Follow the provided installation instructions. Then update your `%PATH%` + environment variable to include the path where the binaries were + installed. (#bin_path, if you've been using the easy install) +], +de: [ + Es gibt kein offizielles Binär-Release von OpenOCD für Windows, aber + wenn Sie es nicht selbst kompilieren möchten, stellt das xPack-Projekt + eine Binärdistribution bereit -- zu finden + #link(url_openocd)[hier]. Befolgen Sie die dort + aufgeführten Installationsanweisungen. Aktualisieren Sie anschließend + Ihre Umgebungsvariable `%PATH%`, indem Sie den Pfad hinzufügen, unter + dem die Binärdateien installiert wurden (z. B. #bin_path, + falls Sie die einfache Installation verwendet haben). +], +zh: [ + OpenOCD 官方没有提供Windows的二进制版本, + 若你没有心情去折腾编译,#link(url_openocd)[这里]有xPack提供的一个二进制发布.。按照说明进行安装。然后更新你的`%PATH%` 环境变量,将安装目录包括进去。 (#bin_path, 如果使用简易安装) +])) + +#tr(( +en: [ + Verify that OpenOCD is in your `%PATH%` with: +], +de: [ + Überprüfen Sie mit folgendem Befehl, ob OpenOCD in Ihrem `%PATH%` enthalten ist: +], +zh: [ + 使用以下命令验证OpenOCD是否在你的`%PATH%`环境变量中 : +])) + +```text +$ openocd -v +Open On-Chip Debugger 0.10.0 +(..) +``` + += QEMU + +#let url_qemu = "https://www.qemu.org/download/#windows" +#tr(( +en: [ + Grab QEMU from #link(url_qemu)[the official website]. +], +de: [ + Lade QEMU von #link(url_qemu)[der offiziellen Website] herunter. +], +ja: [ + #link(url_qemu)[QEMU公式サイト]からQEMUを入手します。 +], +zh: [ + 从#link(url_qemu)[官网]获取QEMU。 +])) + += #tr(( + en: [ST-LINK USB driver], + de: [ST-LINK USB driver], + ja: [ST-LINK USBドライバ], + zh: [ST-LINK USB driver], +)) + +#let url_stlink = "http://www.st.com/en/embedded-software/stsw-link009.html" +#tr(( +en: [ + You'll also need to install #link(url_stlink)[this USB driver] + or OpenOCD won't work. Follow the installer instructions and make sure + you install the right version (32-bit or 64-bit) of the driver. +], +de: [ + Sie müssen außerdem #link(url_stlink)[diesen USB-Treiber] + installieren, da OpenOCD sonst nicht funktioniert. Befolgen Sie die + Anweisungen des Installationsprogramms und stellen Sie sicher, dass Sie + die richtige Version des Treibers (32-Bit oder 64-Bit) installieren. +], +ja: [ + #link(url_stlink)[USBドライバ]もインストールする必要があります。そうでなければOpenOCDは動きません。インストーラの手順に従って下さい。 + そして、正しいドライバのバージョン(32ビットか64ビット)をインストールすることを確認して下さい。 +], +zh: [ + 你还需要安装这个 + #link(url_stlink)[USB驱动] + 否则OpenOCD将无法工作。按照安装程序的说明,确保你安装了正确版本(32位或64位)的驱动程序。 +])) + +#tr(( +en: [ + That's all! Go to the #link()[next section]. +], +de: [ + Das war's! Gehen Sie zum #link()[nächsten Abschnitt]. +], +ja: [ + 以上です!#link()[次のセクション]に進んで下さい。 +], +zh: [ + 以上是全部内容!转到 #link()[下个章节]。 +])) diff --git a/typ/intro/no-std.typ b/typ/intro/no-std.typ new file mode 100644 index 00000000..cb0cecdd --- /dev/null +++ b/typ/intro/no-std.typ @@ -0,0 +1,368 @@ +#import "../config.typ": * + +#h1((en: [A `no_std` Rust Environment], + de: [Eine `no_std`-Rust-Umgebung], + ja: [Rustの`no_std`環境], + zh: [一个 `no_std` Rust环境], +), offset: whole) + +#let ln_st72325 = link("https://www.st.com/resource/en/datasheet/st72325j6.pdf")[ST72325xx] +#let ln_rpi = link("https://en.wikipedia.org/wiki/Raspberry_Pi#Specifications")[Modell B 3+] +#tr(( +en: [ + The term Embedded Programming is used for a wide range of different + classes of programming. Ranging from programming 8-Bit MCUs (like the + #ln_st72325 with just a few KB of RAM and ROM, + up to systems like the Raspberry Pi (#ln_rpi) + which has a 32/64-bit 4-core Cortex-A53 \@ 1.4 GHz and 1GB of RAM. + Different restrictions/limitations will apply when writing code + depending on what kind of target and use case you have. +], +de: [ + Der Begriff „Embedded Programming" (Programmierung eingebetteter + Systeme) umfasst ein breites Spektrum unterschiedlichster + Programmierbereiche. Das Spektrum reicht von der Programmierung von + 8-Bit-Mikrocontrollern (wie dem + #ln_st72325 mit nur wenigen Kilobyte RAM und ROM + bis hin zu Systemen wie dem Raspberry Pi (#ln_rpi), + der über einen 32/64-Bit-Quad-Core-Prozessor (Cortex-A53 mit 1,4 GHz) + und 1 GB RAM verfügt. Je nach Zielsystem und Anwendungsfall gelten bei + der Programmierung unterschiedliche Einschränkungen und + Rahmenbedingungen. +], +ja: [ + 組込みプログラミングという用語は、様々な分野のプログラミングに使用されます。 + たった数キロバイトのRAMかROMが付随する8ビットMCU + (例えば、#ln_st72325)から、32/64ビットの4コア + Cortex-A53 \@ 1.4GHzと1GBのRAMが搭載されたRaspberry + Pi(#ln_rpi)のようなシステムまで、幅広いです。 + どのような種類の目的とユースケースがあるか、によって、コードを書くときに異なる制限/限界が課されます。 +], +zh: [ + 嵌入式编程这个词被广泛用于许多不同的编程场景中。小到RAM和ROM只有KB的8位机(像是#ln_st72325),大到一个具有32/64位4核Cortex-A53和1GB + RAM的系统,比如树莓派(#ln_rpi)。当编写代码时,取决于你的目标环境和用例,将会有不同的限制和局限。 +])) + +#tr(( +en: [ + There are two general Embedded Programming classifications: +], +de: [ + Es gibt zwei grundlegende Kategorien der Programmierung eingebetteter Systeme: +], +ja: [ + 2つの一般的な組込みプログラミングの分類があります。 +], +zh: [ + 通常嵌入式编程有两类: +])) + += #tr(( + en: [Hosted Environments], + de: [Hosted Environments], + ja: [ホストされた環境], + zh: [主机环境下], +)) + +#let ln_posix = "https://en.wikipedia.org/wiki/POSIX" +#tr(( +en: [ + These kinds of environments are close to a normal PC environment. What + this means is that you are provided with a System Interface + #link(ln_posix)[E.G. POSIX] that provides + you with primitives to interact with various systems, such as file + systems, networking, memory management, threads, etc. Standard libraries + in turn usually depend on these primitives to implement their + functionality. You may also have some sort of sysroot and restrictions + on RAM/ROM-usage, and perhaps some special HW or I/Os. Overall it feels + like coding on a special-purpose PC environment. +], +de: [ + Derartige Umgebungen ähneln einer herkömmlichen PC-Umgebung. Das + bedeutet, dass Ihnen eine Systemschnittstelle (z. B. + #link(ln_posix)[POSIX]) zur Verfügung + steht, die Grundfunktionen (Primitive) für die Interaktion mit + verschiedenen Systemkomponenten bietet -- etwa Dateisystemen, + Netzwerkfunktionen, Speicherverwaltung, Threads usw. + Standardbibliotheken wiederum basieren in der Regel auf diesen + Grundfunktionen, um ihre Funktionalität zu implementieren. Zudem können + eine spezifische System-Root-Umgebung (sysroot) sowie Einschränkungen + bei der RAM- oder ROM-Nutzung vorliegen; auch spezielle Hardware oder + Ein-/Ausgabeschnittstellen (I/Os) können vorhanden sein. Insgesamt + vermittelt die Programmierung den Eindruck, in einer auf einen + speziellen Einsatzzweck ausgerichteten PC-Umgebung zu arbeiten. +], +ja: [ + この分類の環境は、普通のPCの環境に近いです。 + これの意味するところは、#link("https://en.wikipedia.org/wiki/POSIX")[POSIX]のようなシステムインタフェースが提供されている、ということです。システムインタフェースは、ファイルシステムやネットワーク、メモリ管理、スレッドといった多様なシステムとやりとりするための基本要素を提供します。 + 通常、標準ライブラリは、その機能を実装するために、これらの基本要素に依存します。 + また、sysrootや、RAM/ROM利用の制限、そしておそらく特別なハードウェアやIOがあるかもしれません。 + 全体としては、特殊な用途のPC環境でコーディングをするようなものです。 +], +zh: [ + 这类环境与一个常见的PC环境类似。意味着向你提供了一个系统接口#link(ln_posix)[比如 POSIX],使你能和不同的系统进行交互,比如文件系统,网络,内存管理,进程,等等。标准库相应地依赖这些接口去实现了它们的功能。可能有某种sysroot并限制了对RAM/ROM的使用,可能还有一些特别的硬件或者I/O。总之感觉像是在专用的PC环境上编程一样。 +])) + += #tr(( + en: [Bare Metal Environments], + de: [Rein physische Umgebung], + ja: [ベアメタル環境], + zh: [裸机环境下], +)) + +#let ln_core = link("https://doc.rust-lang.org/core/")[libcore] +#tr(( +en: [ + In a bare metal environment no code has been loaded before your program. + Without the software provided by an OS we can not load the standard + library. Instead the program, along with the crates it uses, can only + use the hardware (bare metal) to run. To prevent rust from loading the + standard library use `no_std`. The platform-agnostic parts of the + standard library are available through #ln_core. libcore also excludes + things which are not always desirable in an embedded environment. One of + these things is a memory allocator for dynamic memory allocation. If you + require this or any other functionalities there are often crates which + provide these. +], +de: [ + In einer rein physischen Umgebung wird vor Ihrem Programm kein Code + geladen. Ohne die vom Betriebssystem bereitgestellte Software kann die + Standardbibliothek nicht geladen werden. Stattdessen kann das Programm + zusammen mit den verwendeten Crates ausschließlich die Hardware (Bare + Metal) nutzen. Um zu verhindern, dass Rust die Standardbibliothek lädt, + verwenden Sie `no_std`. Die plattformunabhängigen Teile der + Standardbibliothek sind über #ln_core verfügbar. libcore + schließt außerdem Funktionen aus, die in eingebetteten Umgebungen nicht + immer erwünscht sind. Eine dieser Funktionen ist ein Speicherallokator + für die dynamische Speicherverwaltung. Falls Sie diese oder andere + Funktionalitäten benötigen, stehen Ihnen häufig entsprechende Crates zur Verfügung. +], +ja: [ + #todoupd("ja") + ベアメタル環境では、高機能なOSが動作していて、私たちのコードをホスティングしてくれる、ということはありません。 + これは、基本要素がないことを意味しており、それ故に、デフォルトでは標準ライブラリもありません。 + コードに`no_std`のマーキングをすることで、そのコードが、ベアメタル環境で実行できることを示します。 + no_stdなコードからは、Rustの#link("https://doc.rust-lang.org/std/")[libstd]とメモリの動的確保が使えません。 + しかしながら、no_stdなコードでも#ln_core;を使うことができます。libcoreは、ほんの数種類のシンボルを提供することで、いかなる環境でも容易に利用することができます + (詳細は、#ln_core;を参照して下さい)。 +], +zh: [ + 在一个裸机环境中,程序被加载前,环境中不存在代码。没有系统提供的软件,我们不能加载标准库。相反地,程序和它使用的crates只能使用硬件(裸机)去运行。使用`no-std`可以防止rust读取标准库。标准库中与平台无关的部分在#link("https://doc.rust-lang.org/core/")[libcore]中。libcore剔除了那些在一个嵌入式环境中非必要的东西。比如用于动态分配的内存分配器。如果你需要这些或者其它的某些功能,通常会有提供这些功能的crates。 +])) + +== #tr(( + en: [The libstd Runtime], + de: [Die libstd-Laufzeitumgebung], + ja: [libstdランタイム], + zh: [libstd运行时], +)) + +#let ln_std = link("https://doc.rust-lang.org/std/")[libstd] +#tr(( +en: [ + As mentioned before using + #ln_std requires some sort of + system integration, but this is not only because + #ln_std is just providing a + common way of accessing OS abstractions, it also provides a runtime. + This runtime, among other things, takes care of setting up stack + overflow protection, processing command line arguments, and spawning the + main thread before a program's main function is invoked. This runtime + also won't be available in a `no_std` environment. +], +de: [ + Wie bereits erwähnt, erfordert die Verwendung von + #ln_std eine gewisse + Systemintegration; dies liegt jedoch nicht nur daran, dass + #ln_std eine einheitliche + Schnittstelle zu Betriebssystem-Abstraktionen bereitstellt, sondern auch + daran, dass es eine Laufzeitumgebung (Runtime) mitliefert. Diese + Laufzeitumgebung kümmert sich unter anderem um die Einrichtung eines + Stack-Overflow-Schutzes, die Verarbeitung von Kommandozeilenargumenten + sowie das Starten des Haupt-Threads, bevor die `main`-Funktion des + Programms aufgerufen wird. In einer `no_std`-Umgebung steht diese + Laufzeitumgebung nicht zur Verfügung. +], +ja: [ + 上述の通り、#ln_std;の利用には、いくらかのシステムインテグレーションが必要です。しかし、これは#ln_std;がOSの抽象にアクセスするための共通の方法を提供しているだけでなく、ランタイムも提供しているためです。 + ランタイムは、とりわけ、スタックオーバーフロープロテクションの準備、コマンドライン引数の処理、メインスレッドの生成、をプログラムのメイン関数が呼び出される前に処理します。 + このランタイムも、`no_std`環境では利用できません。 +], +zh: [ + 就像之前提到的,使用#ln_std;需要一些系统集成,这不仅仅是因为#ln_std;使用了一个公共的方法访问操作系统,它也提供了一个运行时环境。这个运行时环境,负责设置堆栈溢出保护,处理命令行参数,并在一个程序的主函数被激活前启动一个主线程。在一个`no_std`环境中,这个运行时环境也是不可用的。 +])) + += #tr(( + en: [Summary], + de: [Zusammenfassung], + ja: [まとめ], + zh: [总结], +)) + +#let ln_core = link("https://doc.rust-lang.org/core/")[libcore] +#tr(( +en: [ + `#![no_std]` is a crate-level attribute that indicates that the crate + will link to the core-crate instead of the std-crate. The + #ln_core crate in turn is a + platform-agnostic subset of the std crate which makes no assumptions + about the system the program will run on. As such, it provides APIs for + language primitives like floats, strings and slices, as well as APIs + that expose processor features like atomic operations and SIMD + instructions. However it lacks APIs for anything that involves platform + integration. Because of these properties no_std and + #ln_core code can be used for + any kind of bootstrapping (stage 0) code like bootloaders, firmware or kernels. +], +de: [ + `#![no_std]` ist ein Attribut auf Crate-Ebene, das angibt, dass das + Crate gegen das `core`-Crate anstatt gegen das `std`-Crate gelinkt wird. + Das #ln_core;-Crate wiederum ist + eine plattformunabhängige Teilmenge des `std`-Crates, die keinerlei + Annahmen über das System trifft, auf dem das Programm ausgeführt wird. + Dementsprechend stellt es APIs für Sprachprimitive wie Gleitkommazahlen, + Strings und Slices bereit sowie APIs, die Prozessorfunktionen wie + atomare Operationen und SIMD-Befehle zugänglich machen. Es fehlen jedoch + APIs für Funktionen, die eine Plattformintegration erfordern. Aufgrund + dieser Eigenschaften eignen sich `no_std`- und + #ln_core;-Code für jegliche Art + von Bootstrapping-Code (Stufe 0), wie etwa Bootloader, Firmware oder Kernel. +], +ja: [ + `#![no_std]`は、クレートレベルの属性で、そのクレートがstdクレートの代わりにcoreクレートとリンクすることを意味します。 + #ln_core;クレートは、プラットフォームに依存しないstdクレートのサブセットです。libcoreクレートは、プログラムが動作するシステムについて前提を置きません。 + libcoreクレートは、浮動小数点、文字列やスライスといった言語の基本要素となるAPIと、アトミック操作やSIMD命令といったプロセッサの機能を公開するAPIとを、提供します。一方、プラットフォームインテグレーションを伴うようなAPIは欠如しています。 + これらの特性のため、no\_stdと#ln_core;のコードは、ブートローダー、ファームウェア、カーネルといったあらゆるブートストラップ + (ステージ0)のコードにも利用できます。 +], +zh: [ + `#![no_std]`是一个crate层级的属性,它说明crate将连接至core-crate而不是std-crate。#ln_core crate是std + crate的一个的子集,其与平台无关,它对程序将要运行的系统没有做要求。比如,它提供了像是floats,strings和切片的APIs,暴露了像是与原子操作和SIMD指令相关的处理器功能的APIs。然而,它缺少涉及到平台集成的那些APIs。由于这些特性,no_std和#ln_core;代码可以用于任何引导程序(stage + 0)像是bootloaders,固件或者内核。 +])) + +== #tr(( + en: [Overview], + de: [Überblick], + ja: [概略], + zh: [概述], +)) + +#figure( + kind: table, + table( + columns: (1fr, 11.11%, 6.94%), + align: center, + table.header( + tr(( + en: [feature], + de: [Eigenschaft], + ja: [機能], + zh: [特性], + )), + [no_std], + [std], + ), + tr(( + en: [heap (dynamic memory)], + de: [heap (dynamischer Speicher)], + ja: [ヒープ (動的メモリ)], + zh: [堆 (dynamic memory)], + )), + [\*], [✓], + tr(( + en: [collections (Vec, BTreeMap, etc)], + de: [collections (Vec, BTreeMap, usw.)], + ja: [コレクション (Vec, HashMap, など)], + zh: [容器 (Vec, BTreeMap, etc)], + )), + [\*\*], [✓], + tr(( + en: [stack overflow protection], + de: [Schutz vor Stack-Überlauf], + ja: [スタックオーバーフロープロテクション], + zh: [栈溢出保护], + )), + [✘], [✓], + tr(( + en: [runs init code before main], + de: [führt Initialisierungscode vor der main-Funktion aus], + ja: [main関数前の初期化コード実行], + zh: [在进入main之前运行的初始化代码], + )), + [✘], [✓], + tr(( + en: [libstd available], + de: [libstd verfügbar], + ja: [libstdの利用], + zh: [libstd available], + )), + [✘], [✓], + tr(( + en: [libcore available], + de: [libcore verfügbar], + ja: [libcoreの利用], + zh: [libcore available], + )), + [✓], [✓], + tr(( + en: [writing firmware, kernel, or bootloader code], + de: [schreibt firmware, kernel, oder bootloader code], + ja: [ファームウェア、カーネル、ブートローダーのコードを書く], + zh: [编写固件,内核,或者引导程序], + )), + [✓], [✘], + ) +) + +#let ln_cortex = link("https://github.com/rust-embedded/alloc-cortex-m")[alloc-cortex-m] +#tr(( +en: [ + \* Only if you use the `alloc` crate and use a suitable allocator like #ln_cortex. +], +de: [ + \* Nur wenn Sie das `alloc`-Crate und einen geeigneten Allocator wie #ln_cortex verwenden. +], +ja: [ + \* `alloc`クレートを使い、\[alloc-cortex-m\]のような適切なアロケータを使った場合のみ +], +zh: [ + \* 只有在你使用了 `alloc` crate + 并设置了一个适合的分配器后,比如#ln_cortex;后可用. +])) + +#tr(( +en: [ + \*\* Only if you use the `collections` crate and configure a global default allocator. +], +de: [ + \*\* Nur wenn Sie das `collections`-Crate verwenden und einen globalen Standard-Allocator konfigurieren. +], +ja: [ + \*\* `collections`クレートを使い、グローバルなデフォルトアロケータを設定した場合のみ +], +zh: [ + \*\* 只有在你使用了 `collections` crate + 并配置了一个全局默认的分配器后可用. +])) + +#tr(( +en: [ + \*\* HashMap and HashSet are not available due to a lack of a secure random number generator. +], +de: [ + \*\* HashMap und HashSet stehen aufgrund des Fehlens eines sicheren + Zufallszahlengenerators nicht zur Verfügung. +], +zh: [ + \*\* 由于缺少安全的随机数产生器,所以无法使用HashMap和HashSet. +])) + += #tr(( + en: [See Also], + de: [Siehe auch], + ja: [参照], + zh: [参见], +)) + +- #link("https://github.com/rust-lang/rfcs/blob/master/text/1184-stabilize-no_std.html")[RFC-1184] diff --git a/typ/intro/tooling.typ b/typ/intro/tooling.typ new file mode 100644 index 00000000..14205523 --- /dev/null +++ b/typ/intro/tooling.typ @@ -0,0 +1,609 @@ +#import "../config.typ": * + +#h1((en: [Tooling], + de: [Werkzeuge], + ja: [ツール], + zh: [工具], +), offset: whole) + +#tr(( +en: [ + Dealing with microcontrollers involves using several different tools as + we'll be dealing with an architecture different than your laptop's and + we'll have to run and debug programs on a _remote_ device. +], +de: [ + Der Umgang mit Mikrocontrollern erfordert den Einsatz verschiedener + Werkzeuge, da wir es mit einer Architektur zu tun haben, die sich von + der Ihres Laptops unterscheidet, und Programme auf einem + _entfernten_ Gerät ausführen sowie debuggen müssen. +], +ja: [ + マイクロコントローラを扱う際は、いくつかの異なるツールを利用することになります。あなたのノートPCとは異なるアーキテクチャを扱うことになるでしょうし、_リモート_デバイス上でプログラムを実行しデバッグする必要があります。 +], +zh: [ + 与微控制器打交道需要使用几种不同的工具,因为我们要处理的架构与笔记本电脑不同,我们必须在 _远程_ +])) + +#let ln_binutils = link("https://github.com/rust-embedded/cargo-binutils")[`cargo-binutils`] +#let ln_qemu = link("https://www.qemu.org/")[`qemu-system-arm`] +#let ln_generate = link("https://github.com/ashleygwilliams/cargo-generate")[`cargo-generate`] +#tr(( +en: [ + We'll use all the tools listed below. Any recent version should work + when a minimum version is not specified, but we have listed the versions + we have tested. + - Rust 1.31, 1.31-beta, or a newer toolchain PLUS ARM Cortex-M + compilation support. + - #ln_binutils \~0.1.4 + - #ln_qemu. Tested versions: 3.0.0 + - OpenOCD \>=0.8. Tested versions: v0.9.0 and v0.10.0 + - GDB with ARM support. Version 7.12 or newer highly recommended. + Tested versions: 7.10, 7.11, 7.12 and 8.1 + - #ln_generate or `git`. + These tools are optional but will make it easier to follow along with the book. +], +de: [ + Wir werden alle unten aufgeführten Werkzeuge verwenden. Sofern keine + Mindestversion angegeben ist, sollte jede aktuelle Version + funktionieren; wir haben jedoch die Versionen aufgelistet, die wir + getestet haben. + - Rust 1.31, 1.31-beta oder neuer, SOWIE Unterstützung für die + Kompilierung für ARM Cortex-M. + - #ln_binutils \~0.1.4 + - #ln_qemu. Getestete Version: 3.0.0 + - OpenOCD \>=0.8. Getestete Versionen: v0.9.0 und v0.10.0 + - GDB mit ARM-Unterstützung. Version 7.12 oder neuer wird dringend + empfohlen. Getestete Versionen: 7.10, 7.11, 7.12 und 8.1. + - #ln_generate oder `git`. + Diese Werkzeuge sind optional, erleichtern es jedoch, dem Buch zu folgen. +], +ja: [ + 下記リストのツールを利用します。最小バージョンが指定されていない場合、新しいバージョンであれば機能するはずです。私たちがテストしたバージョンをリストに示しています。 + - ARM Cortex-Mコンパイルサポートを追加したRust 1.31、1.31-beta以上のツールチェイン。 + - #ln_binutils\~0.1.4 + - #ln_qemu。テストしたバージョン: 3.0.0 + - OpenOCD \>=0.8.テストしたバージョン: v0.9.0とv0.10.0 + - ARMサポートのGDB。バージョン7.12以上を強く推奨。テストしたバージョン: + 7.10、7.11、7.12、8.1 + - \[任意\] + `git`または#ln_generate。どちらもインストールしていないのであれば、どちらをインストールしてもかまいません。 +], +zh: [ + 设备上运行和调试程序。我们将使用下面列举出来的工具。当没有指定一个最小版本时,最新的版本应该也可以用,但是我们还是列出了我们已经测过的那些版本。 + - Rust 1.31, 1.31-beta, 或者一个更新的,支持ARM Cortex-M编译的工具链。 + - #ln_binutils \~0.1.4 + - #ln_qemu. 测试的版本: 3.0.0 + - OpenOCD \>=0.8. 测试的版本: v0.9.0 and v0.10.0 + - 有ARM支持的GDB。强烈建议7.12或者更新的版本。测试版本: 7.10, 7.11 和 8.1 + - #ln_generate 或者 `git`。 + 这些工具都是可选的,但是跟着这本书来使用它们,会更容易。 +])) + +#tr(( +en: [ + The text below explains why we are using these tools. Installation + instructions can be found on the next page. +], +de: [ + Der folgende Text erläutert, warum wir diese Werkzeuge verwenden. + Installationsanweisungen finden Sie auf der nächsten Seite. +], +ja: [ + 下記に、なぜこれらのツールを利用するのか、を説明します。インストール方法は、次のページにあります。 +], +zh: [ + 下面的文档将解释我们为什么使用这些工具。安装指令可以在下一页找到。 +])) + += #tr(( + en: [`cargo-generate` OR `git`], + de: [`cargo-generate` ODER `git`], + ja: [`cargo-generate`か`git`], + zh: [`cargo-generate` 或者 `git`], +)) + +#tr(( +en: [ + Bare metal programs are non-standard (`no_std`) Rust programs that + require some adjustments to the linking process in order to get the + memory layout of the program right. This requires some additional files + (like linker scripts) and settings (like linker flags). We have packaged + those for you in a template such that you only need to fill in the + missing information (such as the project name and the characteristics of + your target hardware). +], +de: [ + „Bare-Metal"-Programme sind Rust-Programme ohne Standardbibliothek + (`no_std`), die Anpassungen am Linker-Vorgang erfordern, um das korrekte + Speicherlayout des Programms zu gewährleisten. Dies macht zusätzliche + Dateien (wie Linker-Skripte) und Einstellungen (wie Linker-Flags) + erforderlich. Wir haben diese Elemente in einer Vorlage zusammengefasst, + sodass Sie lediglich die noch fehlenden Angaben ergänzen müssen (etwa + den Projektnamen und die Spezifikationen Ihrer Zielhardware). +], +ja: [ + ベアメタルプログラムは、非標準 + (`no_std`)なRustプログラムであり、プログラムのメモリレイアウトを正しくするために、リンクプロセスをいじる必要があります。 + これには、独特なファイル(リンカスクリプトなど)と設定(リンカフラグ)が必要です。 + プロジェクト名やターゲットハードウェアの特徴などを、空白に入力するだけで済むように、テンプレートを用意しています。 +], +zh: [ + 裸机编程是非标准Rust编程,为了得到正确的程序的内存布局,需要对链接过程进行一些调整,这要求添加一些额外的文件(比如linker + scripts)和配置(比如linker + flags)。我们已经为你把这些打包进了一个模板里了,你只需要补充缺失的信息(比如项目名和目标硬件的特性)。 +])) + +#tr(( +en: [ + Our template is compatible with `cargo-generate`: a Cargo subcommand for + creating new Cargo projects from templates. You can also download the + template using `git`, `curl`, `wget`, or your web browser. +], +de: [ + Unsere Vorlage ist mit `cargo-generate` kompatibel -- einem + Cargo-Unterbefehl zum Erstellen neuer Cargo-Projekte auf Basis von + Vorlagen. Alternativ können Sie die Vorlage auch mithilfe von `git`, + `curl`, `wget` oder Ihrem Webbrowser herunterladen. +], +ja: [ + このテンプレートは、`cargo-generate`との互換性があります。`cargo-generate`は、テンプレートからCargoプロジェクトを作成するためのCargoのサブコマンドです。 + このテンプレートは、`git`や`curl`、`wget`、ウェブブラウザを使ってダウンロードできます。 +], +zh: [ + 我们的模板兼容`cargo-generate`:一个用来从模板生成新的Cargo项目的Cargo子命令。你也能使用`git`,`curl`,`wget`,或者你的网页浏览器下载模板。 +])) + += `cargo-binutils` + +#tr(( +en: [ + `cargo-binutils` is a collection of Cargo subcommands that make it easy + to use the LLVM tools that are shipped with the Rust toolchain. These + tools include the LLVM versions of `objdump`, `nm` and `size` and are + used for inspecting binaries. +], +de: [ + `cargo-binutils` ist eine Sammlung von Cargo-Unterbefehlen, die die + Verwendung der mit der Rust-Toolchain ausgelieferten LLVM-Werkzeuge + vereinfachen. Zu diesen Werkzeugen gehören die LLVM-Varianten von + `objdump`, `nm` und `size`, die zur Untersuchung von Binärdateien dienen. +], +ja: [ + `cargo-binutils`は、Rustツールチェインとともに配布されているLLVMツールを簡単に使うためのCargoサブコマンド一式です。 + これらのツールは、LLVMの`objdump`や`nm`、`size`を含んでおり、バイナリを調査するために使われます。 +], +zh: [ + `cargo-binutils`是一个Cargo命令的子集,它让我们能轻松使用Rust工具链带来的LLVM工具。这些工具包括LLVM版本的`objdump`,`nm`和`size`,用来查看二进制文件。 + 在GNU +])) + +#{ +let cmd = `rustup component add llvm-tools` +tr(( + en: [ + The advantage of using these tools over GNU binutils is that (a) + installing the LLVM tools is the same one-command installation + (#cmd) regardless of your OS and (b) tools + like `objdump` support all the architectures that `rustc` supports -- + from ARM to x86_64 -- because they both share the same LLVM backend. +], +de: [ + Der Vorteil dieser Werkzeuge gegenüber den GNU-Binutils liegt darin, + dass (a) die Installation der LLVM-Werkzeuge unabhängig vom + Betriebssystem stets mit demselben einzelnen Befehl + (#cmd) erfolgt und (b) Werkzeuge wie + `objdump` alle von `rustc` unterstützten Architekturen abdecken -- von + ARM bis x86_64 --, da sie auf demselben LLVM-Backend basieren. +], +ja: [ + GNU binutilsではなく、これらのツールを利用する利点は次の通りです。 (a) + LLVMツールのインストールは、OSに関わらず、共通のコマンド1つ(cmd)で済みます。 + (b) + `objdump`などのツールは、`rustc`がサポートする全てのアーキテクチャ(ARMからx86\_64まで)をサポートします。これは、同じLLVMバックエンドを共有しているためです。 +], +zh: [ + binutils之上使用这些工具的好处是,(a)无论你的操作系统是什么,安装这些LLVM工具都可以用同一条命令(#cmd)。(b)像是`objdump`这样的工具,支持所有`rustc`支持的架构--从ARM到x86\_64--因为它们都有一样的LLVM后端。 +])) +} + += `qemu-system-arm` + +#tr(( +en: [ + QEMU is an emulator. In this case we use the variant that can fully + emulate ARM systems. We use QEMU to run embedded programs on the host. + Thanks to this you can follow some parts of this book even if you don't + have any hardware with you! +], +de: [ + QEMU ist ein Emulator. In diesem Fall verwenden wir die Variante, die + ARM-Systeme vollständig emulieren kann. Wir nutzen QEMU, um + Embedded-Programme auf dem Host-System auszuführen. Auf diese Weise + können Sie einige Teile dieses Buches auch dann nachvollziehen, wenn Sie + keine Hardware zur Hand haben! +], +ja: [ + QEMUはエミュレータです。今回は、ARMシステムを完全にエミュレートできるものを使います。 + 私たちは、ホスト上で組込みプログラムを実行するためにQEMUを利用します。 + このおかげで、ハードウェアを持っていなくても、この本のいくつかの部分を試すことができます。 +], +zh: [ + QEMU是一个仿真器。在这个例子里,我们使用能完全仿真ARM系统的改良版QEMU。我们使用QEMU在主机上运行嵌入式程序。多亏了它,你可以在没有任何硬件的情况下,尝试这本书的部分示例。 +])) + +#h1((en: [Tooling for Embedded Rust Debugging], + de: [Werkzeuge für das Debugging von Embedded Rust], + zh: [用于调试嵌入式Rust的工具], +), offset: whole) + += #tr(( + en: [Overview], + de: [Überblick], + zh: [概述], +)) + +#tr(( +en: [ + Debugging embedded systems in Rust requires specialized tools including + software to manage the debugging process, debuggers to inspect and + control program execution, and hardware probes to facilitate interaction + between the host and the embedded device. This document outlines + essential software tools like Probe-rs and OpenOCD, which simplify and + support the debugging process, alongside prominent debuggers such as GDB + and the Probe-rs Visual Studio Code extension. Additionally, it covers + key hardware probes such as Rusty-probe, ST-Link, J-Link, and MCU-Link, + which are integral for effective debugging and programming of embedded devices. +], +de: [ + Das Debugging eingebetteter Systeme in Rust erfordert spezialisierte + Werkzeuge, darunter Software zur Steuerung des Debugging-Prozesses, + Debugger zur Überwachung und Kontrolle der Programmausführung sowie + Hardware-Probes, die die Interaktion zwischen dem Host-System und dem + eingebetteten Gerät ermöglichen. Dieses Dokument stellt wesentliche + Software-Werkzeuge wie Probe-rs und OpenOCD vor, die den + Debugging-Prozess vereinfachen und unterstützen, sowie bekannte Debugger + wie GDB und die Probe-rs-Erweiterung für Visual Studio Code. Zudem + werden wichtige Hardware-Probes wie Rusty-probe, ST-Link, J-Link und + MCU-Link behandelt, die für das effiziente Debugging und Programmieren + eingebetteter Geräte unerlässlich sind. +], +zh: [ + 在Rust中调试嵌入式系统需要用到专业的工具,这包括用于管理调试进程的软件,用于观察和控制程序执行的调试器,和用于便捷主机和嵌入式设备之间进行交互的硬件探测器.这个文档会介绍像是Probe-rs和OpenOCD这样的基础软件,以及像是GDB和Probe-rs + Visual Studio + Code扩展这样常见的调试器.另外,该文档会覆盖像是Rusty-probe,ST-Link,J-Link,和MCU-Link这样的硬件探测器,它们整合在一起可以高效地对嵌入式设备进行调试和编程. +])) + += #tr(( + en: [Software that drives debugging tools], + de: [Software, die Debugging-Werkzeuge steuert], + zh: [驱动调试工具的软件], +)) + +== Probe-rs + +#tr(( +en: [ + Probe-rs is a modern, Rust-focused software designed to work with + debuggers in embedded systems. Unlike OpenOCD, Probe-rs is built with + simplicity in mind and aims to reduce the configuration burden often + found in other debugging solutions. It supports various probes and + targets, providing a high-level interface for interacting with embedded + hardware. Probe-rs integrates directly with Rust tooling, and integrates + with Visual Studio Code through its extension, allowing developers to + streamline their debugging workflow. +], +de: [ + Probe-rs ist eine moderne, auf Rust ausgerichtete Software für das + Debugging in Embedded-Systemen. Im Gegensatz zu OpenOCD wurde Probe-rs + mit dem Fokus auf Einfachheit entwickelt und zielt darauf ab, den bei + anderen Debugging-Lösungen oft hohen Konfigurationsaufwand zu + reduzieren. Es unterstützt diverse Debug-Probes sowie Zielsysteme und + bietet eine komfortable Schnittstelle für die Interaktion mit + Embedded-Hardware. Probe-rs lässt sich direkt in die Rust-Toolchain + sowie -- dank einer entsprechenden Erweiterung -- in Visual Studio Code + integrieren, wodurch Entwickler ihren Debugging-Workflow optimieren können. +], +zh: [ + Probe-rs是一个现代化的,以Rust开发的软件,被设计用来配合嵌入式系统中的调试器一起工作.不像OpenOCD,Probe-rs设计的时候就考虑到了简单性,目标是减少在其它调试解决方案中常见的配置重担. + 它支持不同的探测器和目标架构,提供一个用于与嵌入式硬件交互的高层接口.Probe-rs直接集成了Rust工具链,并且通过扩展集成进了Visual + Studio Code中,允许开发者精简它们的调试工作流程. +])) + +== OpenOCD (Open On-Chip Debugger) + +#tr(( +en: [ + OpenOCD is an open-source software tool used for debugging, testing, and + programming embedded systems. It provides an interface between the host + system and embedded hardware, supporting various transport layers like + JTAG and SWD (Serial Wire Debug). OpenOCD integrates with GDB, which is + a debugger. OpenOCD is widely supported, with extensive documentation + and a large community, but may require complex configuration, especially + for custom embedded setups. +], +de: [ + OpenOCD ist ein Open-Source-Softwaretool für das Debugging, Testen und + Programmieren eingebetteter Systeme. Es stellt eine Schnittstelle + zwischen dem Host-System und der eingebetteten Hardware bereit und + unterstützt verschiedene Übertragungsprotokolle wie JTAG und SWD (Serial + Wire Debug). OpenOCD lässt sich in GDB, einen Debugger, integrieren. Das + Werkzeug ist weit verbreitet, verfügt über eine umfangreiche + Dokumentation sowie eine große Community, kann jedoch -- insbesondere + bei kundenspezifischen Embedded-Konfigurationen -- eine komplexe + Einrichtung erfordern. +], +zh: [ + OpenOCD是一个用于调试,测试,和编程嵌入式系统的开源软件工具.它提供了一个主机系统和嵌入式硬件之间的接口,支持不同的传输层,比如JTAG和SWD(Serial + Wire + Debug).OpenOCD集成了GDB,其是一个调试器.OpenOCD受到了广泛的支持,拥有大量的文档和一个庞大的社区,但是配置可能会很复杂,特别是对于自定义的嵌入式设置. +])) + += #tr(( + en: [Debuggers], + de: [Debugger], + zh: [Debuggers], +)) + +#tr(( +en: [ + A debugger allows developers to inspect and control the execution of a + program in order to identify and correct errors or bugs. It provides + functionalities such as setting breakpoints, stepping through code line + by line, and examining the values of variables and memory states. + Debuggers are essential for thorough software development and + maintenance, enabling developers to ensure that their code behaves as + intended under various conditions. +], +de: [ + Ein Debugger ermöglicht es Entwicklern, die Ausführung eines Programms + zu untersuchen und zu steuern, um Fehler oder Bugs zu identifizieren und + zu beheben. Er bietet Funktionen wie das Setzen von Haltepunkten + (Breakpoints), das schrittweise Durchlaufen des Codes sowie die + Überprüfung von Variablenwerten und Speicherzuständen. Debugger sind für + eine gründliche Softwareentwicklung und -wartung unerlässlich, da sie + Entwicklern helfen sicherzustellen, dass sich ihr Code unter + verschiedenen Bedingungen wie vorgesehen verhält. +], +zh: [ + 调试器允许开发者观察和控制一个程序的执行,以辨别和纠正错误或者bugs.它提供像是设置断点,一行一行地步进代码,和研究变量的值以及内存的状态等功能.调试器本质上是为了通过软件开发和维护,使得开发者可以确保他们的代码的行为在不同环境下就像他们预期的那样运行. +])) + +#tr(( +en: [ + Debuggers know how to: + - Interact with the memory mapped registers. + - Set Breakpoints/Watchpoints. + - Read and write to the memory mapped registers. + - Detect when the MCU has been halted for a debug event. + - Continue MCU execution after a debug event has been encountered. + - Erase and write to the microcontroller's FLASH. +], +de: [ + Debugger bieten folgende Möglichkeiten: + - Auf die im Speicher abgebildeten Register zugreifen. + - Haltepunkte/Überwachungspunkte setzen. + - In/aus im Speicher abgebildeten Registern lesen und schreiben. + - Erkennen, wenn die MCU aufgrund eines Debug-Ereignisses angehalten wurde. + - Die MCU-Ausführung nach dem Auftreten eines Debug-Ereignisses fortsetzen. + - Den Flash-Speicher des Mikrocontrollers löschen und beschreiben. +], +zh: [ + 调试器可以知道如何: + - 与映射到存储上的寄存器交互. + - 设置断点. + - 读取和写入映射到存储上的寄存器. + - 检测什么时候MCU因为一个调试时间被挂了起来. + - 在遇到一个调试事件后继续MCU的执行. + - 擦出和写入微控制器的FLASH. +])) + +== Probe-rs Visual Studio Code Extension + +#tr(( +en: [ + Probe-rs has a Visual Studio Code extension, providing a seamless + debugging experience without extensive setup. Through this connection, + developers can use Rust-specific features like pretty printing and + detailed error messages, ensuring that their debugging process aligns + with the Rust ecosystem. +], +de: [ + Probe-rs bietet eine Visual Studio Code-Erweiterung, die ein nahtloses + Debugging-Erlebnis ohne aufwendige Einrichtung ermöglicht. Dank dieser + Integration können Entwickler Rust-spezifische Funktionen wie + Pretty-Printing und detaillierte Fehlermeldungen nutzen und so + sicherstellen, dass ihr Debugging-Prozess optimal auf das Rust-Ökosystem + abgestimmt ist. +], +zh: [ + Probe-rs有一个Visual Studio + Code的扩展,提供了不需要额外设置的无缝的调试体验.通过它的帮助,开发者可以使用Rust特定的特性,像是漂亮的打印和详细的错误信息,确保它们的调试过程可以与Rust的生态对齐. +])) + +== TRACE32 + +#tr(( +en: [ + TRACE32 is a professional debugging and tracing solution developed by + Lauterbach for embedded systems. It supports a wide range of processor + architectures, including ARM and RISC-V, and connects to target hardware + via JTAG, SWD, and various trace interfaces. TRACE32 provides advanced + debugging capabilities such as multicore debugging, complex breakpoints, + and real-time trace analysis. It works with standard ELF/DWARF debug + information, making it compatible with Rust binaries built using + conventional toolchains. +], +de: [ + TRACE32 ist eine von Lauterbach für Embedded-Systeme entwickelte + professionelle Debugging- und Tracing-Lösung. Sie unterstützt eine + Vielzahl von Prozessorarchitekturen, darunter ARM und RISC-V, und stellt + die Verbindung zur Zielhardware über JTAG, SWD sowie diverse + Trace-Schnittstellen her. TRACE32 bietet leistungsstarke + Debugging-Funktionen wie Multicore-Debugging, komplexe Breakpoints und + Echtzeit-Trace-Analyse. Da das System auf + Standard-ELF/DWARF-Debuginformationen basiert, ist es mit + Rust-Binärdateien kompatibel, die mit herkömmlichen Werkzeugen erstellt wurden. +])) + +== GDB (GNU Debugger) + +#tr(( +en: [ + GDB is a versatile debugging tool that allows developers to examine the + state of programs while they run or after they crash. For embedded Rust, + GDB connects to the target system via OpenOCD or other debugging servers + to interact with the embedded code. GDB is highly configurable and + supports features like remote debugging, variable inspection, and + conditional breakpoints. It can be used on a variety of platforms, and + has extensive support for Rust-specific debugging needs, such as pretty + printing and integration with IDEs. +], +de: [ + GDB ist ein vielseitiges Debugging-Werkzeug, das es Entwicklern + ermöglicht, den Zustand von Programmen während der Laufzeit oder nach + einem Absturz zu untersuchen. Im Bereich Embedded Rust verbindet sich + GDB über OpenOCD oder andere Debugging-Server mit dem Zielsystem, um mit + dem Embedded-Code zu interagieren. GDB ist hochgradig konfigurierbar und + unterstützt Funktionen wie Remote-Debugging, Variableninspektion und + bedingte Haltepunkte. Es ist auf einer Vielzahl von Plattformen + einsetzbar und bietet umfassende Unterstützung für Rust-spezifische + Debugging-Anforderungen, wie etwa Pretty-Printing und die Integration in IDEs. +], +zh: [ + GDB是一个多用途的调试工具,其允许开发者研究程序的状态,无论其正在运行中还是程序崩溃后.对于嵌入式Rust,GDB通过OpenOCD或者其它的调试服务器链接到目标系统上去和嵌入式代码交互.GDB是高度可配置的,并且支持像是远程调试,变量检测,和条件断点.它可以被用于多个平台,并对Rust特定的调试需求有广泛的支持,比如好看的打印和与IDEs集成. +])) + += #tr(( + en: [Probes], + de: [Probes], + zh: [探测器], +)) + +#tr(( +en: [ + A hardware probe is a device used in the development and debugging of + embedded systems to facilitate communication between a host computer and + the target embedded device. It typically supports protocols like JTAG or + SWD, enabling it to program, debug, and analyze the microcontroller or + microprocessor on the embedded system. Hardware probes are crucial for + developers to set breakpoints, step through code, and inspect memory and + processor registers, effectively allowing them to diagnose and fix + issues in real-time. +], +de: [ + Eine Hardware-Sonde ist ein Gerät, das bei der Entwicklung und dem + Debugging eingebetteter Systeme eingesetzt wird, um die Kommunikation + zwischen einem Host-Computer und dem eingebetteten Zielsystem zu + ermöglichen. Sie unterstützt typischerweise Protokolle wie JTAG oder SWD + und ermöglicht so das Programmieren, Debuggen und Analysieren des + Mikrocontrollers oder Mikroprozessors auf dem eingebetteten System. + Hardware-Sonden sind für Entwickler unverzichtbar, um Haltepunkte + (Breakpoints) zu setzen, den Code schrittweise auszuführen sowie + Speicher und Prozessorregister zu untersuchen; dies erlaubt es ihnen, + Probleme effizient in Echtzeit zu diagnostizieren und zu beheben. +], +zh: [ + 硬件探头是一个被用于嵌入式系统的开发和调试的设备,其可以使得主机和目标嵌入式设备间的通信变得简单.它通常支持像是JTAG或者SWD这样的协议,可以编程,调试和分析嵌入式系统上的微控制器或者微处理器.硬件探头对于要设置断点,步进代码,和观察内存与处理器的寄存器的开发者来说很重要,可以让开发者们高效地实时地分析和修复问题. +])) + +== Rusty-probe + +#tr(( +en: [ + Rusty-probe is an open-sourced USB-based hardware debugging probe + designed to work with probe-rs. The combination of Rusty-Probe and + probe-rs provides an easy-to-use, cost-effective solution for developers + working with embedded Rust applications. +], +de: [ + Rusty-probe ist ein Open-Source-Hardware-Debugging-Interface auf + USB-Basis, das für den Einsatz mit probe-rs entwickelt wurde. Die + Kombination aus Rusty-Probe und probe-rs bietet Entwicklern, die mit + Embedded-Rust-Anwendungen arbeiten, eine benutzerfreundliche und + kostengünstige Lösung. +], +zh: [ + Rusty-probe是一个开源的基于USB的硬件调试探测器,被设计用来辅助probe-rs一起工作.Rusy-Probe和probe-rs的结合为嵌入式Rust应用的开发者提供了一个易用的,成本高效的解决方案. +])) + +== ST-Link + +#tr(( +en: [ + The ST-Link is a popular debugging and programming probe developed by + STMicroelectronics primarily for their STM32 and STM8 microcontroller + series. It supports both debugging and programming via JTAG or SWD + (Serial Wire Debug) interfaces. ST-Link is widely used due to its direct + support from STMicroelectronics' extensive range of development boards + and its integration into major IDEs, making it a convenient choice for + developers working with STM microcontrollers. +], +de: [ + Der ST-Link ist ein weit verbreiteter Debugging- und Programmieradapter, + der von STMicroelectronics primär für die Mikrocontroller-Serien STM32 + und STM8 entwickelt wurde. Er unterstützt sowohl das Debugging als auch + die Programmierung über JTAG- oder SWD-Schnittstellen (Serial Wire + Debug). Dank der direkten Unterstützung durch das umfangreiche Angebot + an Entwicklungsboards von STMicroelectronics sowie der Integration in + gängige Entwicklungsumgebungen (IDEs) ist der ST-Link weit verbreitet + und stellt eine komfortable Wahl für Entwickler dar, die mit + STM-Mikrocontrollern arbeiten. +], +zh: [ + ST-Link是一个由STMicroelectronics开发的常见的调试和编程探测器,其主要用于它们的STM32和STM8微控制器系列.它支持通过JTAG或者SWD接口进行调试和编程.因为STMicroelectronics的大量的开发板对其直接支持并且它集成进了主流的IDEs中,所以使得它成为使用STM微控制器的开发者的首选. +])) + +== J-Link + +#tr(( +en: [ + J-Link, developed by SEGGER Microcontroller, is a robust and versatile + debugger supporting a wide range of CPU cores and devices beyond just + ARM, such as RISC-V. Known for its high performance and reliability, + J-Link supports various communication interfaces, including JTAG, SWD, + and fine-pitch JTAG interfaces. It is favored for its advanced features + like unlimited breakpoints in flash memory and its compatibility with a + multitude of development environments. +], +de: [ + J-Link, entwickelt von SEGGER Microcontroller, ist ein robuster und + vielseitiger Debugger, der neben ARM auch eine breite Palette weiterer + CPU-Kerne und Bausteine -- wie etwa RISC-V -- unterstützt. J-Link ist + für seine hohe Leistungsfähigkeit und Zuverlässigkeit bekannt und + unterstützt diverse Kommunikationsschnittstellen, darunter JTAG, SWD + sowie Fine-Pitch-JTAG-Schnittstellen. Geschätzt wird das System zudem + für seine erweiterten Funktionen, wie etwa unbegrenzte Breakpoints im + Flash-Speicher, sowie für seine Kompatibilität mit einer Vielzahl von + Entwicklungsumgebungen. +], +zh: [ + J-Link是由SEGGER微控制器开发的,它是一个鲁棒和功能丰富的调试器,其支持大量的CPU内核和设备,不仅仅是ARM,比如RISC-V.因其高性能和可读性而闻名,J-Link支持不同的通信接口,包括JTAG,SWD,和fine-pitch + JTAG接口.它因其高级的特性而受到欢迎,比如在flash存储中的无限的断点和它与多种开发环境的兼容性. +])) + +== MCU-Link + +#tr(( +en: [ + MCU-Link is a debugging probe that also functions as a programmer, + provided by NXP Semiconductors. It supports a variety of ARM Cortex + microcontrollers and interfaces seamlessly with development tools like + MCUXpresso IDE. MCU-Link is particularly notable for its versatility and + affordability, making it an accessible option for hobbyists, educators, + and professional developers alike. +], +de: [ + MCU-Link ist ein von NXP Semiconductors bereitgestellter + Debugging-Adapter, der auch als Programmiergerät fungiert. Er + unterstützt eine Vielzahl von ARM-Cortex-Mikrocontrollern und lässt sich + nahtlos in Entwicklungsumgebungen wie die MCUXpresso IDE integrieren. + MCU-Link zeichnet sich besonders durch seine Vielseitigkeit und + Kosteneffizienz aus und ist damit eine attraktive Lösung für + Hobbyanwender, Lehrkräfte und professionelle Entwickler gleichermaßen. +], +zh: [ + MCU-Link是一个调试探测器,也可以作为编程器使用,由NXP + Semiconductors提供.它支持不同的ARM Cortex微控制器且可以与像是MCUXpresso + IDE这样的开发工具进行无缝地交互.MCU-Link因其丰富的功能和易使用而闻名,使它成为像是爱好者,教育者,和专业的开发者们的可行的选项. +])) diff --git a/typ/mdbook/assets/ayu-highlight-3fdfc3ac.css b/typ/mdbook/assets/ayu-highlight-3fdfc3ac.css new file mode 100644 index 00000000..dba94b09 --- /dev/null +++ b/typ/mdbook/assets/ayu-highlight-3fdfc3ac.css @@ -0,0 +1,77 @@ +/* +Based off of the Ayu theme +Original by Dempfi (https://github.com/dempfi/ayu) +*/ + +.hljs { + display: block; + overflow-x: auto; + background: #191f26; + color: #e6e1cf; +} + +.hljs-comment, +.hljs-quote { + color: #5c6773; +} + +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-attr, +.hljs-regexp, +.hljs-link, +.hljs-selector-id, +.hljs-selector-class { + color: #ff7733; +} + +.hljs-number, +.hljs-meta, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #ffee99; +} + +.hljs-string, +.hljs-bullet { + color: #b8cc52; +} + +.hljs-title, +.hljs-built_in, +.hljs-section { + color: #ffb454; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-symbol { + color: #ff7733; +} + +.hljs-name { + color: #36a3d9; +} + +.hljs-tag { + color: #00568d; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-addition { + color: #91b362; +} + +.hljs-deletion { + color: #d96c75; +} diff --git a/typ/mdbook/assets/book-609e4cb8.js b/typ/mdbook/assets/book-609e4cb8.js new file mode 100644 index 00000000..c62124cb --- /dev/null +++ b/typ/mdbook/assets/book-609e4cb8.js @@ -0,0 +1,870 @@ +'use strict'; + +/* global default_theme, default_dark_theme, default_light_theme, hljs, ClipboardJS */ + +// Fix back button cache problem +window.onunload = function() { }; + +// Global variable, shared between modules +function playground_text(playground, hidden = true) { + const code_block = playground.querySelector('code'); + + if (window.ace && code_block.classList.contains('editable')) { + const editor = window.ace.edit(code_block); + return editor.getValue(); + } else if (hidden) { + return code_block.textContent; + } else { + return code_block.innerText; + } +} + +/** + * Helper for global keypress handlers so they don't trigger when certain elements are active. + * @returns {boolean} True if the keypress handler should be skipped. + */ +function mdbook_something_else_has_focus(e) { + // Check composedPath in case the event happened from something generated + // from the shadowDOM. + const target = e.composedPath()[0] || e.target; + // If this is the `checkbox-img` input which has the focus, we want to handle it here. + if (target.classList.contains('checkbox-img')) { + return false; + } + return /^(?:input|select|textarea)$/i.test(target.nodeName); +} + +(function codeSnippets() { + function fetch_with_timeout(url, options, timeout = 6000) { + return Promise.race([ + fetch(url, options), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout)), + ]); + } + + const playgrounds = Array.from(document.querySelectorAll('.playground')); + if (playgrounds.length > 0) { + fetch_with_timeout('https://play.rust-lang.org/meta/crates', { + headers: { + 'Content-Type': 'application/json', + }, + method: 'POST', + mode: 'cors', + }) + .then(response => response.json()) + .then(response => { + // get list of crates available in the rust playground + const playground_crates = response.crates.map(item => item['id']); + playgrounds.forEach(block => handle_crate_list_update(block, playground_crates)); + }); + } + + function handle_crate_list_update(playground_block, playground_crates) { + // update the play buttons after receiving the response + update_play_button(playground_block, playground_crates); + + // and install on change listener to dynamically update ACE editors + if (window.ace) { + const code_block = playground_block.querySelector('code'); + if (code_block.classList.contains('editable')) { + const editor = window.ace.edit(code_block); + editor.addEventListener('change', () => { + update_play_button(playground_block, playground_crates); + }); + // add Ctrl-Enter command to execute rust code + editor.commands.addCommand({ + name: 'run', + bindKey: { + win: 'Ctrl-Enter', + mac: 'Ctrl-Enter', + }, + exec: _editor => run_rust_code(playground_block), + }); + } + } + } + + // updates the visibility of play button based on `no_run` class and + // used crates vs ones available on https://play.rust-lang.org + function update_play_button(pre_block, playground_crates) { + const play_button = pre_block.querySelector('.play-button'); + + // skip if code is `no_run` + if (pre_block.querySelector('code').classList.contains('no_run')) { + play_button.classList.add('hidden'); + return; + } + + // get list of `extern crate`'s from snippet + const txt = playground_text(pre_block); + const re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g; + const snippet_crates = []; + let item; + while (item = re.exec(txt)) { + snippet_crates.push(item[1]); + } + + // check if all used crates are available on play.rust-lang.org + const all_available = snippet_crates.every(function(elem) { + return playground_crates.indexOf(elem) > -1; + }); + + if (all_available) { + play_button.classList.remove('hidden'); + play_button.hidden = false; + } else { + play_button.classList.add('hidden'); + } + } + + function run_rust_code(code_block) { + let result_block = code_block.querySelector('.result'); + if (!result_block) { + result_block = document.createElement('code'); + result_block.className = 'result hljs language-bash'; + + code_block.append(result_block); + } + + const text = playground_text(code_block); + const classes = code_block.querySelector('code').classList; + let edition = '2015'; + classes.forEach(className => { + if (className.startsWith('edition')) { + edition = className.slice(7); + } + }); + const params = { + version: 'stable', + optimize: '0', + code: text, + edition: edition, + }; + + if (text.indexOf('#![feature') !== -1) { + params.version = 'nightly'; + } + + result_block.innerText = 'Running...'; + + fetch_with_timeout('https://play.rust-lang.org/evaluate.json', { + headers: { + 'Content-Type': 'application/json', + }, + method: 'POST', + mode: 'cors', + body: JSON.stringify(params), + }) + .then(response => response.json()) + .then(response => { + if (response.result.trim() === '') { + result_block.innerText = 'No output'; + result_block.classList.add('result-no-output'); + } else { + result_block.innerText = response.result; + result_block.classList.remove('result-no-output'); + } + }) + .catch(error => result_block.innerText = 'Playground Communication: ' + error.message); + } + + // Syntax highlighting Configuration + hljs.configure({ + tabReplace: ' ', // 4 spaces + languages: [], // Languages used for auto-detection + }); + + const code_nodes = Array + .from(document.querySelectorAll('code')) + // Don't highlight `inline code` blocks in headers. + .filter(function(node) { + return !node.parentElement.classList.contains('header'); + }); + + if (window.ace) { + // language-rust class needs to be removed for editable + // blocks or highlightjs will capture events + code_nodes + .filter(function(node) { + return node.classList.contains('editable'); + }) + .forEach(function(block) { + block.classList.remove('language-rust'); + }); + + code_nodes + .filter(function(node) { + return !node.classList.contains('editable'); + }) + .forEach(function(block) { + hljs.highlightBlock(block); + }); + } else { + code_nodes.forEach(function(block) { + hljs.highlightBlock(block); + }); + } + + // Adding the hljs class gives code blocks the color css + // even if highlighting doesn't apply + code_nodes.forEach(function(block) { + block.classList.add('hljs'); + }); + + Array.from(document.querySelectorAll('code.hljs')).forEach(function(block) { + + const lines = Array.from(block.querySelectorAll('.boring')); + // If no lines were hidden, return + if (!lines.length) { + return; + } + block.classList.add('hide-boring'); + + const buttons = document.createElement('div'); + buttons.className = 'buttons'; + buttons.innerHTML = ''; + buttons.firstChild.innerHTML = document.getElementById('fa-eye').innerHTML; + + // add expand button + const pre_block = block.parentNode; + pre_block.insertBefore(buttons, pre_block.firstChild); + + buttons.firstChild.addEventListener('click', function(e) { + if (this.title === 'Show hidden lines') { + this.innerHTML = document.getElementById('fa-eye-slash').innerHTML; + this.title = 'Hide lines'; + this.setAttribute('aria-label', e.target.title); + + block.classList.remove('hide-boring'); + } else if (this.title === 'Hide lines') { + this.innerHTML = document.getElementById('fa-eye').innerHTML; + this.title = 'Show hidden lines'; + this.setAttribute('aria-label', e.target.title); + + block.classList.add('hide-boring'); + } + }); + }); + + if (window.playground_copyable) { + Array.from(document.querySelectorAll('pre code')).forEach(function(block) { + const pre_block = block.parentNode; + if (!pre_block.classList.contains('playground')) { + let buttons = pre_block.querySelector('.buttons'); + if (!buttons) { + buttons = document.createElement('div'); + buttons.className = 'buttons'; + pre_block.insertBefore(buttons, pre_block.firstChild); + } + + const clipButton = document.createElement('button'); + clipButton.className = 'clip-button'; + clipButton.title = 'Copy to clipboard'; + clipButton.setAttribute('aria-label', clipButton.title); + clipButton.innerHTML = ''; + + buttons.insertBefore(clipButton, buttons.firstChild); + } + }); + } + + // Process playground code blocks + Array.from(document.querySelectorAll('.playground')).forEach(function(pre_block) { + // Add play button + let buttons = pre_block.querySelector('.buttons'); + if (!buttons) { + buttons = document.createElement('div'); + buttons.className = 'buttons'; + pre_block.insertBefore(buttons, pre_block.firstChild); + } + + const runCodeButton = document.createElement('button'); + runCodeButton.className = 'play-button'; + runCodeButton.hidden = true; + runCodeButton.title = 'Run this code'; + runCodeButton.setAttribute('aria-label', runCodeButton.title); + runCodeButton.innerHTML = document.getElementById('fa-play').innerHTML; + + buttons.insertBefore(runCodeButton, buttons.firstChild); + runCodeButton.addEventListener('click', () => { + run_rust_code(pre_block); + }); + + if (window.playground_copyable) { + const copyCodeClipboardButton = document.createElement('button'); + copyCodeClipboardButton.className = 'clip-button'; + copyCodeClipboardButton.innerHTML = ''; + copyCodeClipboardButton.title = 'Copy to clipboard'; + copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title); + + buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild); + } + + const code_block = pre_block.querySelector('code'); + if (window.ace && code_block.classList.contains('editable')) { + const undoChangesButton = document.createElement('button'); + undoChangesButton.className = 'reset-button'; + undoChangesButton.title = 'Undo changes'; + undoChangesButton.setAttribute('aria-label', undoChangesButton.title); + undoChangesButton.innerHTML += + document.getElementById('fa-clock-rotate-left').innerHTML; + + buttons.insertBefore(undoChangesButton, buttons.firstChild); + + undoChangesButton.addEventListener('click', function() { + const editor = window.ace.edit(code_block); + editor.setValue(editor.originalCode); + editor.clearSelection(); + }); + } + }); +})(); + +(function themes() { + const html = document.querySelector('html'); + const themeToggleButton = document.getElementById('mdbook-theme-toggle'); + const themePopup = document.getElementById('mdbook-theme-list'); + const themeColorMetaTag = document.querySelector('meta[name="theme-color"]'); + const themeIds = []; + themePopup.querySelectorAll('button.theme').forEach(function(el) { + themeIds.push(el.id); + }); + const stylesheets = { + ayuHighlight: document.querySelector('#mdbook-ayu-highlight-css'), + tomorrowNight: document.querySelector('#mdbook-tomorrow-night-css'), + highlight: document.querySelector('#mdbook-highlight-css'), + }; + + function showThemes() { + themePopup.style.display = 'block'; + themeToggleButton.setAttribute('aria-expanded', true); + themePopup.querySelector('button#mdbook-theme-' + get_theme()).focus(); + } + + function updateThemeSelected() { + themePopup.querySelectorAll('.theme-selected').forEach(function(el) { + el.classList.remove('theme-selected'); + }); + const selected = get_saved_theme() ?? 'default_theme'; + let element = themePopup.querySelector('button#mdbook-theme-' + selected); + if (element === null) { + // Fall back in case there is no "Default" item. + element = themePopup.querySelector('button#mdbook-theme-' + get_theme()); + } + element.classList.add('theme-selected'); + } + + function hideThemes() { + themePopup.style.display = 'none'; + themeToggleButton.setAttribute('aria-expanded', false); + themeToggleButton.focus(); + } + + function get_saved_theme() { + let theme = null; + try { + theme = localStorage.getItem('mdbook-theme'); + } catch { + // ignore error. + } + return theme; + } + + function delete_saved_theme() { + localStorage.removeItem('mdbook-theme'); + } + + function get_theme() { + const theme = get_saved_theme(); + if (theme === null || theme === undefined || !themeIds.includes('mdbook-theme-' + theme)) { + if (typeof default_dark_theme === 'undefined') { + // A customized index.hbs might not define this, so fall back to + // old behavior of determining the default on page load. + return default_theme; + } + return window.matchMedia('(prefers-color-scheme: dark)').matches + ? default_dark_theme + : default_light_theme; + } else { + return theme; + } + } + + let previousTheme = default_theme; + function set_theme(theme, store = true) { + let ace_theme; + + if (theme === 'coal' || theme === 'navy') { + stylesheets.ayuHighlight.disabled = true; + stylesheets.tomorrowNight.disabled = false; + stylesheets.highlight.disabled = true; + + ace_theme = 'ace/theme/tomorrow_night'; + } else if (theme === 'ayu') { + stylesheets.ayuHighlight.disabled = false; + stylesheets.tomorrowNight.disabled = true; + stylesheets.highlight.disabled = true; + ace_theme = 'ace/theme/tomorrow_night'; + } else { + stylesheets.ayuHighlight.disabled = true; + stylesheets.tomorrowNight.disabled = true; + stylesheets.highlight.disabled = false; + ace_theme = 'ace/theme/dawn'; + } + + setTimeout(function() { + themeColorMetaTag.content = getComputedStyle(document.documentElement).backgroundColor; + }, 1); + + if (window.ace && window.editors) { + window.editors.forEach(function(editor) { + editor.setTheme(ace_theme); + }); + } + + if (store) { + try { + localStorage.setItem('mdbook-theme', theme); + } catch { + // ignore error. + } + } + + html.classList.remove(previousTheme); + html.classList.add(theme); + previousTheme = theme; + updateThemeSelected(); + } + + const query = window.matchMedia('(prefers-color-scheme: dark)'); + query.onchange = function() { + set_theme(get_theme(), false); + }; + + // Set theme. + set_theme(get_theme(), false); + + themeToggleButton.addEventListener('click', function() { + if (themePopup.style.display === 'block') { + hideThemes(); + } else { + showThemes(); + } + }); + + themePopup.addEventListener('click', function(e) { + let theme; + if (e.target.className === 'theme') { + theme = e.target.id; + } else if (e.target.parentElement.className === 'theme') { + theme = e.target.parentElement.id; + } else { + return; + } + theme = theme.replace(/^mdbook-theme-/, ''); + + if (theme === 'default_theme' || theme === null) { + delete_saved_theme(); + set_theme(get_theme(), false); + } else { + set_theme(theme); + } + }); + + themePopup.addEventListener('focusout', function(e) { + // e.relatedTarget is null in Safari and Firefox on macOS (see workaround below) + if (!!e.relatedTarget && + !themeToggleButton.contains(e.relatedTarget) && + !themePopup.contains(e.relatedTarget) + ) { + hideThemes(); + } + }); + + // Should not be needed, but it works around an issue on macOS & iOS: + // https://github.com/rust-lang/mdBook/issues/628 + document.addEventListener('click', function(e) { + if (themePopup.style.display === 'block' && + !themeToggleButton.contains(e.target) && + !themePopup.contains(e.target) + ) { + hideThemes(); + } + }); + + document.addEventListener('keydown', function(e) { + if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { + return; + } + if (!themePopup.contains(e.target)) { + return; + } + + let li; + switch (e.key) { + case 'Escape': + e.preventDefault(); + hideThemes(); + break; + case 'ArrowUp': + e.preventDefault(); + li = document.activeElement.parentElement; + if (li && li.previousElementSibling) { + li.previousElementSibling.querySelector('button').focus(); + } + break; + case 'ArrowDown': + e.preventDefault(); + li = document.activeElement.parentElement; + if (li && li.nextElementSibling) { + li.nextElementSibling.querySelector('button').focus(); + } + break; + case 'Home': + e.preventDefault(); + themePopup.querySelector('li:first-child button').focus(); + break; + case 'End': + e.preventDefault(); + themePopup.querySelector('li:last-child button').focus(); + break; + } + }); +})(); + +(function sidebar() { + const sidebar = document.getElementById('mdbook-sidebar'); + const sidebarLinks = document.querySelectorAll('#mdbook-sidebar a'); + const sidebarToggleButton = document.getElementById('mdbook-sidebar-toggle'); + const sidebarResizeHandle = document.getElementById('mdbook-sidebar-resize-handle'); + const sidebarCheckbox = document.getElementById('mdbook-sidebar-toggle-anchor'); + let firstContact = null; + + + /* Because we cannot change the `display` using only CSS after/before the transition, we + need JS to do it. We change the display to prevent the browsers search to find text inside + the collapsed sidebar. */ + if (!document.documentElement.classList.contains('sidebar-visible')) { + sidebar.style.display = 'none'; + } + sidebar.addEventListener('transitionend', () => { + /* We only change the display to "none" if we're collapsing the sidebar. */ + if (!sidebarCheckbox.checked) { + sidebar.style.display = 'none'; + } + }); + sidebarToggleButton.addEventListener('click', () => { + /* To allow the sidebar expansion animation, we first need to put back the display. */ + if (!sidebarCheckbox.checked) { + sidebar.style.display = ''; + // Workaround for Safari skipping the animation when changing + // `display` and a transform in the same event loop. This forces a + // reflow after updating the display. + sidebar.offsetHeight; + } + }); + + function showSidebar() { + document.documentElement.classList.add('sidebar-visible'); + Array.from(sidebarLinks).forEach(function(link) { + link.setAttribute('tabIndex', 0); + }); + sidebarToggleButton.setAttribute('aria-expanded', true); + sidebar.setAttribute('aria-hidden', false); + try { + localStorage.setItem('mdbook-sidebar', 'visible'); + } catch { + // Ignore error. + } + } + + function hideSidebar() { + document.documentElement.classList.remove('sidebar-visible'); + Array.from(sidebarLinks).forEach(function(link) { + link.setAttribute('tabIndex', -1); + }); + sidebarToggleButton.setAttribute('aria-expanded', false); + sidebar.setAttribute('aria-hidden', true); + try { + localStorage.setItem('mdbook-sidebar', 'hidden'); + } catch { + // Ignore error. + } + } + + // Toggle sidebar + sidebarCheckbox.addEventListener('change', function sidebarToggle() { + if (sidebarCheckbox.checked) { + const current_width = parseInt( + document.documentElement.style.getPropertyValue('--sidebar-target-width'), 10); + if (current_width < 150) { + document.documentElement.style.setProperty('--sidebar-target-width', '150px'); + } + showSidebar(); + } else { + hideSidebar(); + } + }); + + sidebarResizeHandle.addEventListener('mousedown', initResize, false); + + function initResize() { + window.addEventListener('mousemove', resize, false); + window.addEventListener('mouseup', stopResize, false); + document.documentElement.classList.add('sidebar-resizing'); + } + function resize(e) { + let pos = e.clientX - sidebar.offsetLeft; + if (pos < 20) { + hideSidebar(); + } else { + if (!document.documentElement.classList.contains('sidebar-visible')) { + showSidebar(); + } + pos = Math.min(pos, window.innerWidth - 100); + document.documentElement.style.setProperty('--sidebar-target-width', pos + 'px'); + } + } + //on mouseup remove windows functions mousemove & mouseup + function stopResize() { + document.documentElement.classList.remove('sidebar-resizing'); + window.removeEventListener('mousemove', resize, false); + window.removeEventListener('mouseup', stopResize, false); + } + + document.addEventListener('touchstart', function(e) { + firstContact = { + x: e.touches[0].clientX, + time: Date.now(), + }; + }, { passive: true }); + + document.addEventListener('touchmove', function(e) { + if (!firstContact) { + return; + } + + const curX = e.touches[0].clientX; + const xDiff = curX - firstContact.x, + tDiff = Date.now() - firstContact.time; + + if (tDiff < 250 && Math.abs(xDiff) >= 150) { + if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300)) { + showSidebar(); + } else if (xDiff < 0 && curX < 300) { + hideSidebar(); + } + + firstContact = null; + } + }, { passive: true }); +})(); + +(function chapterNavigation() { + function zoomOutImages() { + for (const elem of Array.from(document.querySelectorAll('input.checkbox-img'))) { + elem.checked = false; + } + } + + document.addEventListener('keydown', function(e) { + if (e.altKey || + e.ctrlKey || + e.metaKey || + window.search && window.search.hasFocus() || + mdbook_something_else_has_focus(e) + ) { + return; + } + + const html = document.querySelector('html'); + + function next() { + const nextButton = document.querySelector('.nav-chapters.next'); + if (nextButton) { + window.location.href = nextButton.href; + } + } + function prev() { + const previousButton = document.querySelector('.nav-chapters.previous'); + if (previousButton) { + window.location.href = previousButton.href; + } + } + function showHelp() { + const container = document.getElementById('mdbook-help-container'); + const overlay = document.getElementById('mdbook-help-popup'); + container.style.display = 'flex'; + + // Clicking outside the popup will dismiss it. + const mouseHandler = event => { + if (overlay.contains(event.target)) { + return; + } + if (event.button !== 0) { + return; + } + event.preventDefault(); + event.stopPropagation(); + document.removeEventListener('mousedown', mouseHandler); + hideHelp(); + }; + + // Pressing esc will dismiss the popup. + const escapeKeyHandler = event => { + if (event.key === 'Escape') { + event.preventDefault(); + event.stopPropagation(); + document.removeEventListener('keydown', escapeKeyHandler, true); + hideHelp(); + } + }; + document.addEventListener('keydown', escapeKeyHandler, true); + document.getElementById('mdbook-help-container') + .addEventListener('mousedown', mouseHandler); + } + function hideHelp() { + document.getElementById('mdbook-help-container').style.display = 'none'; + } + + // Usually needs the Shift key to be pressed + switch (e.key) { + case '?': + e.preventDefault(); + showHelp(); + break; + case 'Escape': + zoomOutImages(); + break; + } + + // Rest of the keys are only active when the Shift key is not pressed + if (e.shiftKey) { + return; + } + + switch (e.key) { + case 'ArrowRight': + e.preventDefault(); + if (html.dir === 'rtl') { + prev(); + } else { + next(); + } + break; + case 'ArrowLeft': + e.preventDefault(); + if (html.dir === 'rtl') { + next(); + } else { + prev(); + } + break; + } + }); +})(); + +(function clipboard() { + const clipButtons = document.querySelectorAll('.clip-button'); + + function hideTooltip(elem) { + elem.firstChild.innerText = ''; + elem.className = 'clip-button'; + } + + function showTooltip(elem, msg) { + elem.firstChild.innerText = msg; + elem.className = 'clip-button tooltipped'; + } + + const clipboardSnippets = new ClipboardJS('.clip-button', { + text: function(trigger) { + hideTooltip(trigger); + const playground = trigger.closest('pre'); + return playground_text(playground, false); + }, + }); + + Array.from(clipButtons).forEach(function(clipButton) { + clipButton.addEventListener('mouseout', function(e) { + hideTooltip(e.currentTarget); + }); + }); + + clipboardSnippets.on('success', function(e) { + e.clearSelection(); + showTooltip(e.trigger, 'Copied!'); + }); + + clipboardSnippets.on('error', function(e) { + showTooltip(e.trigger, 'Clipboard error!'); + }); +})(); + +(function scrollToTop() { + const menuTitle = document.querySelector('.menu-title'); + + menuTitle.addEventListener('click', function() { + document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' }); + }); +})(); + +(function controllMenu() { + const menu = document.getElementById('mdbook-menu-bar'); + + (function controllPosition() { + let scrollTop = document.scrollingElement.scrollTop; + let prevScrollTop = scrollTop; + const minMenuY = -menu.clientHeight - 50; + // When the script loads, the page can be at any scroll (e.g. if you refresh it). + menu.style.top = scrollTop + 'px'; + // Same as parseInt(menu.style.top.slice(0, -2), but faster + let topCache = menu.style.top.slice(0, -2); + menu.classList.remove('sticky'); + let stickyCache = false; // Same as menu.classList.contains('sticky'), but faster + document.addEventListener('scroll', function() { + scrollTop = Math.max(document.scrollingElement.scrollTop, 0); + // `null` means that it doesn't need to be updated + let nextSticky = null; + let nextTop = null; + const scrollDown = scrollTop > prevScrollTop; + const menuPosAbsoluteY = topCache - scrollTop; + if (scrollDown) { + nextSticky = false; + if (menuPosAbsoluteY > 0) { + nextTop = prevScrollTop; + } + } else { + if (menuPosAbsoluteY > 0) { + nextSticky = true; + } else if (menuPosAbsoluteY < minMenuY) { + nextTop = prevScrollTop + minMenuY; + } + } + if (nextSticky === true && stickyCache === false) { + menu.classList.add('sticky'); + stickyCache = true; + } else if (nextSticky === false && stickyCache === true) { + menu.classList.remove('sticky'); + stickyCache = false; + } + if (nextTop !== null) { + menu.style.top = nextTop + 'px'; + topCache = nextTop; + } + prevScrollTop = scrollTop; + }, { passive: true }); + })(); + (function controllBorder() { + function updateBorder() { + if (menu.offsetTop === 0) { + menu.classList.remove('bordered'); + } else { + menu.classList.add('bordered'); + } + } + updateBorder(); + document.addEventListener('scroll', updateBorder, { passive: true }); + })(); +})(); diff --git a/typ/mdbook/assets/clipboard-1626706a.min.js b/typ/mdbook/assets/clipboard-1626706a.min.js new file mode 100644 index 00000000..02c549e3 --- /dev/null +++ b/typ/mdbook/assets/clipboard-1626706a.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.4 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n .hljs { + color: var(--links); +} + +/* + mdbook-body-container is necessary because mobile browsers don't seem to like + overflow-x on the body tag when there is a tag. +*/ +#mdbook-body-container { + /* + This is used when the sidebar pushes the body content off the side of + the screen on small screens. Without it, dragging on mobile Safari + will want to reposition the viewport in a weird way. + */ + overflow-x: clip; +} + +/* Menu Bar */ + +#mdbook-menu-bar, +#mdbook-menu-bar-hover-placeholder { + z-index: 101; + margin: auto calc(0px - var(--page-padding)); +} +#mdbook-menu-bar { + position: relative; + display: flex; + flex-wrap: wrap; + background-color: var(--bg); + border-block-end-color: var(--bg); + border-block-end-width: 1px; + border-block-end-style: solid; +} +#mdbook-menu-bar.sticky, +#mdbook-menu-bar-hover-placeholder:hover + #mdbook-menu-bar, +#mdbook-menu-bar:hover, +html.sidebar-visible #mdbook-menu-bar { + position: -webkit-sticky; + position: sticky; + top: 0 !important; +} +#mdbook-menu-bar-hover-placeholder { + position: sticky; + position: -webkit-sticky; + top: 0; + height: var(--menu-bar-height); +} +#mdbook-menu-bar.bordered { + border-block-end-color: var(--table-border-color); +} +#mdbook-menu-bar .fa-svg, #mdbook-menu-bar .icon-button { + position: relative; + padding: 0 8px; + z-index: 10; + line-height: var(--menu-bar-height); + cursor: pointer; + transition: color 0.5s; +} +@media only screen and (max-width: 420px) { + #mdbook-menu-bar .fa-svg, #mdbook-menu-bar .icon-button { + padding: 0 5px; + } +} + +.icon-button { + border: none; + background: none; + padding: 0; + color: inherit; +} +.icon-button .fa-svg { + margin: 0; +} + +.right-buttons { + margin: 0 15px; +} +.right-buttons a { + text-decoration: none; +} + +.left-buttons { + display: flex; + margin: 0 5px; +} +html:not(.js) .left-buttons button { + display: none; +} + +.menu-title { + display: inline-block; + font-weight: 200; + font-size: 2.4rem; + line-height: var(--menu-bar-height); + text-align: center; + margin: 0; + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.menu-title { + cursor: pointer; +} + +.menu-bar, +.menu-bar:visited, +.nav-chapters, +.nav-chapters:visited, +.mobile-nav-chapters, +.mobile-nav-chapters:visited, +.menu-bar .icon-button, +.menu-bar a .fa-svg { + color: var(--icons); +} + +.menu-bar .fa-svg:hover, +.menu-bar .icon-button:hover, +.nav-chapters:hover, +.mobile-nav-chapters .fa-svg:hover { + color: var(--icons-hover); +} + +/* Nav Icons */ + +.nav-chapters { + font-size: 2.5em; + text-align: center; + text-decoration: none; + + position: fixed; + top: 0; + bottom: 0; + margin: 0; + max-width: 150px; + min-width: 90px; + + display: flex; + justify-content: center; + align-content: center; + flex-direction: column; + + transition: color 0.5s, background-color 0.5s; +} + +.nav-chapters:hover { + text-decoration: none; + background-color: var(--theme-hover); + transition: background-color 0.15s, color 0.15s; +} + +.nav-chapters.previous { + /* Ensure that the previous arrow does not overlap the resize indicator. */ + margin-inline-start: var(--sidebar-resize-indicator-width); +} + +.nav-wrapper { + margin-block-start: 50px; + display: none; +} + +.mobile-nav-chapters { + font-size: 2.5em; + text-align: center; + text-decoration: none; + width: 90px; + border-radius: 5px; + background-color: var(--sidebar-bg); +} + +/* Only Firefox supports flow-relative values */ +.previous { float: left; } +[dir=rtl] .previous { float: right; } + +/* Only Firefox supports flow-relative values */ +.next { + float: right; + right: var(--page-padding); +} +[dir=rtl] .next { + float: left; + right: unset; + left: var(--page-padding); +} + +@media only screen and (max-width: 1080px) { + .nav-wide-wrapper { display: none; } + .nav-wrapper { display: block; } +} + +/* sidebar-visible */ +@media only screen and (max-width: 1380px) { + #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper .nav-wide-wrapper { display: none; } + #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper .nav-wrapper { display: block; } +} + +/* Inline code */ + +:not(pre) > .hljs { + display: inline; + padding: 0.1em 0.3em; + border-radius: 3px; +} + +:not(pre):not(a) > .hljs { + color: var(--inline-code-color); + overflow-x: initial; +} + +a:hover > .hljs { + text-decoration: underline; +} + +pre { + position: relative; +} +pre > .buttons { + position: absolute; + z-index: 100; + right: 0px; + top: 2px; + margin: 0px; + padding: 2px 0px; + + color: var(--sidebar-fg); + cursor: pointer; + visibility: hidden; + opacity: 0; + transition: visibility 0.1s linear, opacity 0.1s linear; +} +pre:hover > .buttons { + visibility: visible; + opacity: 1 +} +pre > .buttons :hover { + color: var(--sidebar-active); + border-color: var(--icons-hover); + background-color: var(--theme-hover); +} +pre > .buttons button { + cursor: inherit; + margin: 0px 5px; + padding: 2px 3px 0px 4px; + font-size: 23px; + + border-style: solid; + border-width: 1px; + border-radius: 4px; + border-color: var(--icons); + background-color: var(--theme-popup-bg); + transition: 100ms; + transition-property: color,border-color,background-color; + color: var(--icons); +} + +pre > .buttons button.clip-button { + padding: 2px 4px 0px 6px; +} +pre > .buttons button.clip-button::before { + /* clipboard image from octicons (https://github.com/primer/octicons/tree/v2.0.0) MIT license + */ + content: url('data:image/svg+xml,\ +\ +\ +'); + filter: var(--copy-button-filter); +} +pre > .buttons button.clip-button:hover::before { + filter: var(--copy-button-filter-hover); +} + +@media (pointer: coarse) { + pre > .buttons button { + /* On mobile, make it easier to tap buttons. */ + padding: 0.3rem 1rem; + } + + .sidebar-resize-indicator { + /* Hide resize indicator on devices with limited accuracy */ + display: none; + } +} +pre > code { + display: block; + padding: 1rem; +} + +/* FIXME: ACE editors overlap their buttons because ACE does absolute + positioning within the code block which breaks padding. The only solution I + can think of is to move the padding to the outer pre tag (or insert a div + wrapper), but that would require fixing a whole bunch of CSS rules. +*/ +.hljs.ace_editor { + padding: 0rem 0rem; +} + +pre > .result { + margin-block-start: 10px; +} + +/* Search */ + +#mdbook-searchresults a { + text-decoration: none; +} + +mark { + border-radius: 2px; + padding-block-start: 0; + padding-block-end: 1px; + padding-inline-start: 3px; + padding-inline-end: 3px; + margin-block-start: 0; + margin-block-end: -1px; + margin-inline-start: -3px; + margin-inline-end: -3px; + background-color: var(--search-mark-bg); + transition: background-color 300ms linear; + cursor: pointer; +} + +mark.fade-out { + background-color: rgba(0,0,0,0) !important; + cursor: auto; +} + +.searchbar-outer { + margin-inline-start: auto; + margin-inline-end: auto; + max-width: var(--content-max-width); +} + +#mdbook-searchbar-outer.searching #mdbook-searchbar { + padding-right: 30px; +} +#mdbook-searchbar-outer .spinner-wrapper { + display: none; +} +#mdbook-searchbar-outer.searching .spinner-wrapper { + display: block; +} + +.search-wrapper { + position: relative; +} + +.spinner-wrapper { + --spinner-margin: 2px; + position: absolute; + margin-block-start: calc(var(--searchbar-margin-block-start) + var(--spinner-margin)); + right: var(--spinner-margin); + top: 0; + bottom: var(--spinner-margin); + padding: 6px; + background-color: var(--bg); +} + +#fa-spin { + animation: rotating 2s linear infinite; + display: inline-block; +} + +@keyframes rotating { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +#mdbook-searchbar { + width: 100%; + margin-block-start: var(--searchbar-margin-block-start); + margin-block-end: 0; + margin-inline-start: auto; + margin-inline-end: auto; + padding: 10px 16px; + transition: box-shadow 300ms ease-in-out; + border: 1px solid var(--searchbar-border-color); + border-radius: 3px; + background-color: var(--searchbar-bg); + color: var(--searchbar-fg); +} +#mdbook-searchbar:focus, +#mdbook-searchbar.active { + box-shadow: 0 0 3px var(--searchbar-shadow-color); +} + +.searchresults-header { + font-weight: bold; + font-size: 1em; + padding-block-start: 18px; + padding-block-end: 0; + padding-inline-start: 5px; + padding-inline-end: 0; + color: var(--searchresults-header-fg); +} + +.searchresults-outer { + margin-inline-start: auto; + margin-inline-end: auto; + max-width: var(--content-max-width); + border-block-end: 1px dashed var(--searchresults-border-color); +} + +ul#mdbook-searchresults { + list-style: none; + padding-inline-start: 20px; +} +ul#mdbook-searchresults li { + margin: 10px 0px; + padding: 2px; + border-radius: 2px; +} +ul#mdbook-searchresults li.focus { + background-color: var(--searchresults-li-bg); +} +ul#mdbook-searchresults span.teaser { + display: block; + clear: both; + margin-block-start: 5px; + margin-block-end: 0; + margin-inline-start: 20px; + margin-inline-end: 0; + font-size: 0.8em; +} +ul#mdbook-searchresults span.teaser em { + font-weight: bold; + font-style: normal; +} + +/* Sidebar */ + +.sidebar { + position: fixed; + left: 0; + top: 0; + bottom: 0; + width: var(--sidebar-width); + font-size: 0.875em; + box-sizing: border-box; + -webkit-overflow-scrolling: touch; + overscroll-behavior-y: contain; + background-color: var(--sidebar-bg); + color: var(--sidebar-fg); +} +.sidebar-iframe-inner { + --padding: 10px; + + background-color: var(--sidebar-bg); + padding: var(--padding); + margin: 0; + font-size: 1.4rem; + color: var(--sidebar-fg); + min-height: calc(100vh - var(--padding) * 2); +} +.sidebar-iframe-outer { + border: none; + height: 100%; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; +} +[dir=rtl] .sidebar { left: unset; right: 0; } +.sidebar-resizing { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} +html:not(.sidebar-resizing) .sidebar { + transition: transform 0.3s; /* Animation: slide away */ +} +.sidebar code { + line-height: 2em; +} +.sidebar .sidebar-scrollbox { + overflow-y: auto; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + padding: 10px 10px; +} +.sidebar .sidebar-resize-handle { + position: absolute; + cursor: col-resize; + width: 0; + right: calc(var(--sidebar-resize-indicator-width) * -1); + top: 0; + bottom: 0; + display: flex; + align-items: center; +} + +.sidebar-resize-handle .sidebar-resize-indicator { + width: 100%; + height: 16px; + color: var(--icons); + margin-inline-start: var(--sidebar-resize-indicator-space); + display: flex; + align-items: center; + justify-content: flex-start; +} +.sidebar-resize-handle .sidebar-resize-indicator::before { + content: ""; + width: 2px; + height: 12px; + border-left: dotted 2px currentColor; +} +.sidebar-resize-handle .sidebar-resize-indicator::after { + content: ""; + width: 2px; + height: 16px; + border-left: dotted 2px currentColor; +} + +[dir=rtl] .sidebar .sidebar-resize-handle { + left: calc(var(--sidebar-resize-indicator-width) * -1); + right: unset; +} +.js .sidebar .sidebar-resize-handle { + cursor: col-resize; + width: calc(var(--sidebar-resize-indicator-width) - var(--sidebar-resize-indicator-space)); +} + +html:not(.js) .sidebar-resize-handle { + display: none; +} + +/* sidebar-hidden */ +#mdbook-sidebar-toggle-anchor:not(:checked) ~ .sidebar { + transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width))); +} +[dir=rtl] #mdbook-sidebar-toggle-anchor:not(:checked) ~ .sidebar { + transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width))); +} +.sidebar::-webkit-scrollbar { + background: var(--sidebar-bg); +} +.sidebar::-webkit-scrollbar-thumb { + background: var(--scrollbar); +} + +/* sidebar-visible */ +#mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width))); +} +[dir=rtl] #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width))); +} +@media only screen and (min-width: 620px) { + #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: none; + margin-inline-start: calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width)); + } + [dir=rtl] #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: none; + } +} + +.chapter { + list-style: none outside none; + padding-inline-start: 0; + line-height: 2.2em; +} + +.chapter li { + color: var(--sidebar-non-existant); +} + +/* This is a span wrapping the chapter link and the fold chevron. */ +.chapter-link-wrapper { + /* Used to position the chevron to the right, allowing the text to wrap before it. */ + display: flex; +} + +.chapter li a { + /* Remove underlines. */ + text-decoration: none; + color: var(--sidebar-fg); +} + +.chapter li a:hover { + color: var(--sidebar-active); +} + +.chapter li a.active { + color: var(--sidebar-active); +} + +/* This is the toggle chevron. */ +.chapter-fold-toggle { + cursor: pointer; + /* Positions the chevron to the side. */ + margin-inline-start: auto; + padding: 0 10px; + user-select: none; + opacity: 0.68; +} + +.chapter-fold-toggle div { + transition: transform 0.5s; +} + +/* collapse the section */ +.chapter li:not(.expanded) > ol { + display: none; +} + +.chapter li.chapter-item { + line-height: 1.5em; + margin-block-start: 0.6em; +} + +.chapter li.header-item { + /* Make sure there is plenty of spacing between sections so they don't blend in + with each other. */ + margin-block-end: 0.5em; + /* Avoid too much spacing between lines when section heading word wraps so that + it can be distinguished between successive headings. */ + line-height: 1.5em; +} + +/* When expanded, rotate the chevron to point down. */ +.chapter li.expanded > span > .chapter-fold-toggle div { + transform: rotate(90deg); +} + +.chapter a.current-header { + color: var(--sidebar-active); +} + +.on-this-page { + margin-left: 22px; + border-inline-start: 4px solid var(--sidebar-header-border-color); + padding-left: 8px; +} + +.on-this-page > ol { + padding-left: 0; +} + +/* Horizontal line in chapter list. */ +.spacer { + width: 100%; + height: 3px; + margin: 5px 0px; +} +.chapter .spacer { + background-color: var(--sidebar-spacer); +} + +/* On touch devices, add more vertical spacing to make it easier to tap links. */ +@media (-moz-touch-enabled: 1), (pointer: coarse) { + .chapter li a { padding: 5px 0; } + .spacer { margin: 10px 0; } +} + +.section { + list-style: none outside none; + padding-inline-start: 20px; + line-height: 1.9em; +} + +/* Theme Menu Popup */ + +.theme-popup { + position: absolute; + left: 10px; + top: var(--menu-bar-height); + z-index: 1000; + border-radius: 4px; + font-size: 0.7em; + color: var(--fg); + background: var(--theme-popup-bg); + border: 1px solid var(--theme-popup-border); + margin: 0; + padding: 0; + list-style: none; + display: none; + /* Don't let the children's background extend past the rounded corners. */ + overflow: hidden; +} +[dir=rtl] .theme-popup { left: unset; right: 10px; } +.theme-popup .default { + color: var(--icons); +} +.theme-popup .theme { + width: 100%; + border: 0; + margin: 0; + padding: 2px 20px; + line-height: 25px; + white-space: nowrap; + text-align: start; + cursor: pointer; + color: inherit; + background: inherit; + font-size: inherit; +} +.theme-popup .theme:hover { + background-color: var(--theme-hover); +} + +.theme-selected::before { + display: inline-block; + content: "✓"; + margin-inline-start: -14px; + width: 14px; +} + +/* The container for the help popup that covers the whole window. */ +#mdbook-help-container { + /* Position and size for the whole window. */ + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + /* This uses flex layout (which is set in book.js), and centers the popup + in the window.*/ + display: none; + align-items: center; + justify-content: center; + z-index: 1000; + /* Dim out the book while the popup is visible. */ + background: var(--overlay-bg); +} + +/* The popup help box. */ +#mdbook-help-popup { + box-shadow: 0 4px 24px rgba(0,0,0,0.15); + min-width: 300px; + max-width: 500px; + width: 100%; + box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; + background-color: var(--bg); + color: var(--fg); + border-width: 1px; + border-color: var(--theme-popup-border); + border-style: solid; + border-radius: 8px; + padding: 10px; +} + +.mdbook-help-title { + text-align: center; + /* mdbook's margin for h2 is way too large. */ + margin: 10px; +} diff --git a/typ/mdbook/assets/css/general-e96d0476.css b/typ/mdbook/assets/css/general-e96d0476.css new file mode 100644 index 00000000..06a7f427 --- /dev/null +++ b/typ/mdbook/assets/css/general-e96d0476.css @@ -0,0 +1,464 @@ +/* Base styles and content styles */ + +:root { + /* Browser default font-size is 16px, this way 1 rem = 10px */ + font-size: 62.5%; + color-scheme: var(--color-scheme); +} + +html { + font-family: "Open Sans", sans-serif; + color: var(--fg); + background-color: var(--bg); + text-size-adjust: none; + -webkit-text-size-adjust: none; +} + +body { + margin: 0; + font-size: 1.6rem; + overflow-x: hidden; +} + +code { + font-family: var(--mono-font) !important; + font-size: var(--code-font-size); + direction: ltr !important; +} + +/* make long words/inline code not x overflow */ +main { + overflow-wrap: break-word; +} + +/* make wide tables scroll if they overflow */ +.table-wrapper { + overflow-x: auto; +} + +/* Don't change font size in headers. */ +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + font-size: unset; +} + +.left { float: left; } +.right { float: right; } +.boring { opacity: 0.6; } +.hide-boring .boring { display: none; } +.hidden { display: none !important; } + +h2, h3 { margin-block-start: 2.5em; } +h4, h5 { margin-block-start: 2em; } + +.header + .header h3, +.header + .header h4, +.header + .header h5 { + margin-block-start: 1em; +} + +h1:target::before, +h2:target::before, +h3:target::before, +h4:target::before, +h5:target::before, +h6:target::before, +dt:target::before { + display: inline-block; + content: "»"; + margin-inline-start: -30px; + width: 30px; +} + +/* This is broken on Safari as of version 14, but is fixed + in Safari Technology Preview 117 which I think will be Safari 14.2. + https://bugs.webkit.org/show_bug.cgi?id=218076 +*/ +:target { + /* Safari does not support logical properties */ + scroll-margin-top: calc(var(--menu-bar-height) + 0.5em); +} + +.page { + outline: 0; + padding: 0 var(--page-padding); + margin-block-start: calc(0px - var(--menu-bar-height)); /* Compensate for the #mdbook-menu-bar-hover-placeholder */ +} +.page-wrapper { + box-sizing: border-box; + background-color: var(--bg); +} +html:not(.js) .page-wrapper, +.js:not(.sidebar-resizing) .page-wrapper { + transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */ +} +[dir=rtl]:not(.js) .page-wrapper, +[dir=rtl].js:not(.sidebar-resizing) .page-wrapper { + transition: margin-right 0.3s ease, transform 0.3s ease; /* Animation: slide away */ +} + +.content { + overflow-y: auto; + padding: 0 5px 50px 5px; +} +.content main { + margin-inline-start: auto; + margin-inline-end: auto; + max-width: var(--content-max-width); +} +.content p { line-height: 1.45em; } +.content ol { line-height: 1.45em; } +.content ul { line-height: 1.45em; } +.content a { text-decoration: none; } +.content a:hover { text-decoration: underline; } +.content img, .content video { max-width: 100%; } +/* When an image is inside an anchor, ensure the focus ring covers the entire + image instead of the anchor's line box. */ +.content a:has(img) { display: inline-block; } +.content .header:link, +.content .header:visited { + color: var(--fg); +} +.content .header:link, +.content .header:visited:hover { + text-decoration: none; +} + +table { + margin: 0 auto; + border-collapse: collapse; +} +table td { + padding: 3px 20px; + border: 1px var(--table-border-color) solid; +} +table thead { + background: var(--table-header-bg); +} +table thead td { + font-weight: 700; + border: none; +} +table thead th { + padding: 3px 20px; +} +table thead tr { + border: 1px var(--table-header-bg) solid; +} +/* Alternate background colors for rows */ +table tbody tr:nth-child(2n) { + background: var(--table-alternate-bg); +} + + +blockquote { + margin: 20px 0; + padding: 0 20px; + color: var(--fg); + background-color: var(--quote-bg); + border-block-start: .1em solid var(--quote-border); + border-block-end: .1em solid var(--quote-border); +} + +/* TODO: Remove .warning in a future version of mdbook, it is replaced by +blockquote tags. */ +.warning { + margin: 20px; + padding: 0 20px; + border-inline-start: 2px solid var(--warning-border); +} + +.warning:before { + position: absolute; + width: 3rem; + height: 3rem; + margin-inline-start: calc(-1.5rem - 21px); + content: "ⓘ"; + text-align: center; + background-color: var(--bg); + color: var(--warning-border); + font-weight: bold; + font-size: 2rem; +} + +blockquote .warning:before { + background-color: var(--quote-bg); +} + +kbd { + background-color: var(--table-border-color); + border-radius: 4px; + border: solid 1px var(--theme-popup-border); + box-shadow: inset 0 -1px 0 var(--theme-hover); + display: inline-block; + font-size: var(--code-font-size); + font-family: var(--mono-font); + line-height: 10px; + padding: 4px 5px; + vertical-align: middle; +} + +sup { + /* Set the line-height for superscript and footnote references so that there + isn't an awkward space appearing above lines that contain the footnote. + + See https://github.com/rust-lang/mdBook/pull/2443#discussion_r1813773583 + for an explanation. + */ + line-height: 0; +} + +.footnote-definition { + font-size: 0.9em; +} +/* The default spacing for a list is a little too large. */ +.footnote-definition ul, +.footnote-definition ol { + padding-left: 20px; +} +.footnote-definition > li { + /* Required to position the ::before target */ + position: relative; +} +.footnote-definition > li:target { + scroll-margin-top: 50vh; +} +.footnote-reference:target { + scroll-margin-top: 50vh; +} +/* Draws a border around the footnote (including the marker) when it is selected. + TODO: If there are multiple linkbacks, highlight which one you just came + from so you know which one to click. +*/ +.footnote-definition > li:target::before { + border: 2px solid var(--footnote-highlight); + border-radius: 6px; + position: absolute; + top: -8px; + right: -8px; + bottom: -8px; + left: -32px; + pointer-events: none; + content: ""; +} +/* Pulses the footnote reference so you can quickly see where you left off reading. + This could use some improvement. +*/ +@media not (prefers-reduced-motion) { + .footnote-reference:target { + animation: fn-highlight 0.8s; + border-radius: 2px; + } + + @keyframes fn-highlight { + from { + background-color: var(--footnote-highlight); + } + } +} + +.tooltiptext { + position: absolute; + visibility: hidden; + color: #fff; + background-color: #333; + transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */ + left: -8px; /* Half of the width of the icon */ + top: -35px; + font-size: 0.8em; + text-align: center; + border-radius: 6px; + padding: 5px 8px; + margin: 5px; + z-index: 1000; +} +.tooltipped .tooltiptext { + visibility: visible; +} + +.chapter li.part-title { + color: var(--sidebar-fg); + margin: 5px 0px; + font-weight: bold; +} + +.result-no-output { + font-style: italic; +} + +.fa-svg svg { + width: 1em; + height: 1em; + fill: currentColor; + margin-bottom: -0.1em; +} + +dt { + font-weight: bold; + margin-top: 0.5em; + margin-bottom: 0.1em; +} + +/* This uses a CSS counter to add numbers to definitions, but only if there is + more than one definition. */ +dl, dt { + counter-reset: dd-counter; +} + +/* When there is more than one definition, increment the counter. The first +selector selects the first definition, and the second one selects definitions +2 and beyond.*/ +dd:has(+ dd), dd + dd { + counter-increment: dd-counter; + /* Use flex display to help with positioning the numbers when there is a p + tag inside the definition. */ + display: flex; + align-items: flex-start; +} + +/* Shows the counter for definitions. The first selector selects the first +definition, and the second one selections definitions 2 and beyond.*/ +dd:has(+ dd)::before, dd + dd::before { + content: counter(dd-counter) ". "; + font-weight: 600; + display: inline-block; + margin-right: 0.5em; +} + +dd > p { + /* For loose definitions that have a p tag inside, don't add a bunch of + space before the definition. */ + margin-top: 0; +} + +/* Remove some excess space from the bottom. */ +.blockquote-tag p:last-child { + margin-bottom: 2px; +} + +.blockquote-tag { + /* Add some padding to make the vertical bar a little taller than the text.*/ + padding: 2px 0px 2px 20px; + /* Add a solid color bar on the left side. */ + border-inline-start-style: solid; + border-inline-start-width: 4px; + /* Disable the background color from normal blockquotes . */ + background-color: inherit; + /* Disable border blocks from blockquotes. */ + border-block-start: none; + border-block-end: none; +} + +.blockquote-tag-title svg { + fill: currentColor; + /* Add space between the icon and the title. */ + margin-right: 8px; +} + +.blockquote-tag-note { + border-inline-start-color: var(--blockquote-note-color); +} + +.blockquote-tag-tip { + border-inline-start-color: var(--blockquote-tip-color); +} + +.blockquote-tag-important { + border-inline-start-color: var(--blockquote-important-color); +} + +.blockquote-tag-warning { + border-inline-start-color: var(--blockquote-warning-color); +} + +.blockquote-tag-caution { + border-inline-start-color: var(--blockquote-caution-color); +} + +.blockquote-tag-note > .blockquote-tag-title { + color: var(--blockquote-note-color); +} + +.blockquote-tag-tip > .blockquote-tag-title { + color: var(--blockquote-tip-color); +} + +.blockquote-tag-important > .blockquote-tag-title { + color: var(--blockquote-important-color); +} + +.blockquote-tag-warning > .blockquote-tag-title { + color: var(--blockquote-warning-color); +} + +.blockquote-tag-caution > .blockquote-tag-title { + color: var(--blockquote-caution-color); +} + +.blockquote-tag-title { + /* Slightly increase the weight for more emphasis. */ + font-weight: 600; + /* Vertically center the icon with the text. */ + display: flex; + align-items: center; + /* Remove default large margins for a more compact display. */ + margin: 2px 0 8px 0; +} + +.blockquote-tag-title .fa-svg { + fill: currentColor; + /* Add some space between the icon and the text. */ + margin-right: 8px; +} + +/* All this code is to handle the "zoomable" images feature. */ + +/* This one makes the checkbox invisible while keeping it selectable with the keyboard (with the + "tab" key). */ +.content .checkbox-img { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} +/* When the input is focused, we make it appear to the user by adding an outline to the img + instead */ +.content .checkbox-img:focus + img { + outline: auto; +} +/* The "zoomed-in" image is not displayed until the checkbox is "ticked". */ +.content .checkbox-img:not(:checked) ~ .img-wrapper { + display: none; +} +.content .checkbox-label { + display: block; + max-width: 100%; +} +.content .checkbox-label img { + cursor: zoom-in; +} +.content .checkbox-img:checked ~ .img-wrapper { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: rgba(0, 0, 0, 0.4); + z-index: 1001; + display: flex; + align-items: center; + justify-content: center; + cursor: zoom-out; +} +.content .checkbox-img:checked ~ .img-wrapper > img { + --img-padding: 5px; + padding: var(--img-padding); + background: #999; + cursor: zoom-out; + max-width: calc(100% - (var(--img-padding) * 2)); + max-height: calc(100% - (var(--img-padding) * 2)); +} diff --git a/typ/mdbook/assets/css/print-9e4910d8.css b/typ/mdbook/assets/css/print-9e4910d8.css new file mode 100644 index 00000000..2004384d --- /dev/null +++ b/typ/mdbook/assets/css/print-9e4910d8.css @@ -0,0 +1,50 @@ + +#mdbook-sidebar, +#mdbook-menu-bar, +.nav-chapters, +.mobile-nav-chapters { + display: none; +} + +#mdbook-page-wrapper.page-wrapper { + transform: none !important; + margin-inline-start: 0px; + overflow-y: initial; +} + +#mdbook-content { + max-width: none; + margin: 0; + padding: 0; +} + +.page { + overflow-y: initial; +} + +code { + direction: ltr !important; +} + +pre > .buttons { + z-index: 2; +} + +a, a:visited, a:active, a:hover { + color: #4183c4; + text-decoration: none; +} + +h1, h2, h3, h4, h5, h6 { + page-break-inside: avoid; + page-break-after: avoid; +} + +pre, code { + page-break-inside: avoid; + white-space: pre-wrap; +} + +.fa { + display: none !important; +} diff --git a/typ/mdbook/assets/css/variables-8adf115d.css b/typ/mdbook/assets/css/variables-8adf115d.css new file mode 100644 index 00000000..af5023bc --- /dev/null +++ b/typ/mdbook/assets/css/variables-8adf115d.css @@ -0,0 +1,383 @@ + +/* Globals */ + +:root { + --sidebar-target-width: 300px; + --sidebar-width: min(var(--sidebar-target-width), 80vw); + --sidebar-resize-indicator-width: 8px; + --sidebar-resize-indicator-space: 2px; + --page-padding: 15px; + --content-max-width: 750px; + --menu-bar-height: 50px; + --mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace; + --code-font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */ + --searchbar-margin-block-start: 5px; +} + +/* Themes */ + +.ayu { + --bg: hsl(210, 25%, 8%); + --fg: #c5c5c5; + + --sidebar-bg: #14191f; + --sidebar-fg: #c8c9db; + --sidebar-non-existant: #5c6773; + --sidebar-active: #ffb454; + --sidebar-spacer: #2d334f; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #b7b9cc; + + --links: #0096cf; + + --inline-code-color: #ffb454; + + --theme-popup-bg: #14191f; + --theme-popup-border: #5c6773; + --theme-hover: #191f26; + + --quote-bg: hsl(226, 15%, 17%); + --quote-border: hsl(226, 15%, 22%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(210, 25%, 13%); + --table-header-bg: hsl(210, 25%, 28%); + --table-alternate-bg: hsl(210, 25%, 11%); + + --searchbar-border-color: #848484; + --searchbar-bg: #424242; + --searchbar-fg: #fff; + --searchbar-shadow-color: #d4c89f; + --searchresults-header-fg: #666; + --searchresults-border-color: #888; + --searchresults-li-bg: #252932; + --search-mark-bg: #e3b171; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(45%) sepia(6%) saturate(621%) hue-rotate(198deg) brightness(99%) contrast(85%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(68%) sepia(55%) saturate(531%) hue-rotate(341deg) brightness(104%) contrast(101%); + + --footnote-highlight: #2668a6; + + --overlay-bg: rgba(33, 40, 48, 0.4); + + --blockquote-note-color: #74b9ff; + --blockquote-tip-color: #09ca09; + --blockquote-important-color: #d3abff; + --blockquote-warning-color: #f0b72f; + --blockquote-caution-color: #f21424; + + --sidebar-header-border-color: #c18639; +} + +.coal { + --bg: hsl(200, 7%, 8%); + --fg: #98a3ad; + + --sidebar-bg: #292c2f; + --sidebar-fg: #a1adb8; + --sidebar-non-existant: #505254; + --sidebar-active: #3473ad; + --sidebar-spacer: #393939; + + --scrollbar: var(--sidebar-fg); + + --icons: #43484d; + --icons-hover: #b3c0cc; + + --links: #2b79a2; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #141617; + --theme-popup-border: #43484d; + --theme-hover: #1f2124; + + --quote-bg: hsl(234, 21%, 18%); + --quote-border: hsl(234, 21%, 23%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(200, 7%, 13%); + --table-header-bg: hsl(200, 7%, 28%); + --table-alternate-bg: hsl(200, 7%, 11%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #b7b7b7; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #98a3ad; + --searchresults-li-bg: #2b2b2f; + --search-mark-bg: #355c7d; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(26%) sepia(8%) saturate(575%) hue-rotate(169deg) brightness(87%) contrast(82%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%); + + --footnote-highlight: #4079ae; + + --overlay-bg: rgba(33, 40, 48, 0.4); + + --blockquote-note-color: #4493f8; + --blockquote-tip-color: #08ae08; + --blockquote-important-color: #ab7df8; + --blockquote-warning-color: #d29922; + --blockquote-caution-color: #d91b29; + + --sidebar-header-border-color: #3473ad; +} + +.light, html:not(.js) { + --bg: hsl(0, 0%, 100%); + --fg: hsl(0, 0%, 0%); + + --sidebar-bg: #fafafa; + --sidebar-fg: hsl(0, 0%, 0%); + --sidebar-non-existant: #aaaaaa; + --sidebar-active: #1f1fff; + --sidebar-spacer: #f4f4f4; + + --scrollbar: #8F8F8F; + + --icons: #747474; + --icons-hover: #000000; + + --links: #20609f; + + --inline-code-color: #301900; + + --theme-popup-bg: #fafafa; + --theme-popup-border: #cccccc; + --theme-hover: #e6e6e6; + + --quote-bg: hsl(197, 37%, 96%); + --quote-border: hsl(197, 37%, 91%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(0, 0%, 95%); + --table-header-bg: hsl(0, 0%, 80%); + --table-alternate-bg: hsl(0, 0%, 97%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #fafafa; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #888; + --searchresults-li-bg: #e4f2fe; + --search-mark-bg: #a2cff5; + + --color-scheme: light; + + /* Same as `--icons` */ + --copy-button-filter: invert(45.49%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(14%) sepia(93%) saturate(4250%) hue-rotate(243deg) brightness(99%) contrast(130%); + + --footnote-highlight: #7e7eff; + + --overlay-bg: rgba(200, 200, 205, 0.4); + + --blockquote-note-color: #0969da; + --blockquote-tip-color: #008000; + --blockquote-important-color: #8250df; + --blockquote-warning-color: #9a6700; + --blockquote-caution-color: #b52731; + + --sidebar-header-border-color: #6e6edb; +} + +.navy { + --bg: hsl(226, 23%, 11%); + --fg: #bcbdd0; + + --sidebar-bg: #282d3f; + --sidebar-fg: #c8c9db; + --sidebar-non-existant: #505274; + --sidebar-active: #2b79a2; + --sidebar-spacer: #2d334f; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #b7b9cc; + + --links: #2b79a2; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #161923; + --theme-popup-border: #737480; + --theme-hover: #282e40; + + --quote-bg: hsl(226, 15%, 17%); + --quote-border: hsl(226, 15%, 22%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(226, 23%, 16%); + --table-header-bg: hsl(226, 23%, 31%); + --table-alternate-bg: hsl(226, 23%, 14%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #aeaec6; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #5f5f71; + --searchresults-border-color: #5c5c68; + --searchresults-li-bg: #242430; + --search-mark-bg: #a2cff5; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(46%) sepia(20%) saturate(1537%) hue-rotate(156deg) brightness(85%) contrast(90%); + + --footnote-highlight: #4079ae; + + --overlay-bg: rgba(33, 40, 48, 0.4); + + --blockquote-note-color: #4493f8; + --blockquote-tip-color: #09ca09; + --blockquote-important-color: #ab7df8; + --blockquote-warning-color: #d29922; + --blockquote-caution-color: #f21424; + + --sidebar-header-border-color: #2f6ab5; +} + +.rust { + --bg: hsl(60, 9%, 87%); + --fg: #262625; + + --sidebar-bg: #3b2e2a; + --sidebar-fg: #c8c9db; + --sidebar-non-existant: #505254; + --sidebar-active: #e69f67; + --sidebar-spacer: #45373a; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #262625; + + --links: #2b79a2; + + --inline-code-color: #6e6b5e; + + --theme-popup-bg: #e1e1db; + --theme-popup-border: #b38f6b; + --theme-hover: #99908a; + + --quote-bg: hsl(60, 5%, 75%); + --quote-border: hsl(60, 5%, 70%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(60, 9%, 82%); + --table-header-bg: #b3a497; + --table-alternate-bg: hsl(60, 9%, 84%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #fafafa; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #888; + --searchresults-li-bg: #dec2a2; + --search-mark-bg: #e69f67; + + /* Same as `--icons` */ + --copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(77%) sepia(16%) saturate(1798%) hue-rotate(328deg) brightness(98%) contrast(83%); + + --footnote-highlight: #d3a17a; + + --overlay-bg: rgba(150, 150, 150, 0.25); + + --blockquote-note-color: #023b95; + --blockquote-tip-color: #007700; + --blockquote-important-color: #8250df; + --blockquote-warning-color: #603700; + --blockquote-caution-color: #aa1721; + + --sidebar-header-border-color: #8c391f; +} + +@media (prefers-color-scheme: dark) { + html:not(.js) { + --bg: hsl(200, 7%, 8%); + --fg: #98a3ad; + + --sidebar-bg: #292c2f; + --sidebar-fg: #a1adb8; + --sidebar-non-existant: #505254; + --sidebar-active: #3473ad; + --sidebar-spacer: #393939; + + --scrollbar: var(--sidebar-fg); + + --icons: #43484d; + --icons-hover: #b3c0cc; + + --links: #2b79a2; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #141617; + --theme-popup-border: #43484d; + --theme-hover: #1f2124; + + --quote-bg: hsl(234, 21%, 18%); + --quote-border: hsl(234, 21%, 23%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(200, 7%, 13%); + --table-header-bg: hsl(200, 7%, 28%); + --table-alternate-bg: hsl(200, 7%, 11%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #b7b7b7; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #98a3ad; + --searchresults-li-bg: #2b2b2f; + --search-mark-bg: #355c7d; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(26%) sepia(8%) saturate(575%) hue-rotate(169deg) brightness(87%) contrast(82%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%); + + --footnote-highlight: #4079ae; + + --overlay-bg: rgba(33, 40, 48, 0.4); + + --blockquote-note-color: #4493f8; + --blockquote-tip-color: #08ae08; + --blockquote-important-color: #ab7df8; + --blockquote-warning-color: #d29922; + --blockquote-caution-color: #d91b29; + + --sidebar-header-border-color: #3473ad; + } +} diff --git a/typ/mdbook/assets/elasticlunr-ef4e11c1.min.js b/typ/mdbook/assets/elasticlunr-ef4e11c1.min.js new file mode 100644 index 00000000..94b20dd2 --- /dev/null +++ b/typ/mdbook/assets/elasticlunr-ef4e11c1.min.js @@ -0,0 +1,10 @@ +/** + * elasticlunr - http://weixsong.github.io + * Lightweight full-text search engine in Javascript for browser search and offline search. - 0.9.5 + * + * Copyright (C) 2017 Oliver Nightingale + * Copyright (C) 2017 Wei Song + * MIT Licensed + * @license + */ +!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o + + + + diff --git a/typ/mdbook/assets/fonts/OPEN-SANS-LICENSE.txt b/typ/mdbook/assets/fonts/OPEN-SANS-LICENSE.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/typ/mdbook/assets/fonts/OPEN-SANS-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/typ/mdbook/assets/fonts/SOURCE-CODE-PRO-LICENSE.txt b/typ/mdbook/assets/fonts/SOURCE-CODE-PRO-LICENSE.txt new file mode 100644 index 00000000..366206f5 --- /dev/null +++ b/typ/mdbook/assets/fonts/SOURCE-CODE-PRO-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/typ/mdbook/assets/fonts/fonts-9644e21d.css b/typ/mdbook/assets/fonts/fonts-9644e21d.css new file mode 100644 index 00000000..ce32fdc8 --- /dev/null +++ b/typ/mdbook/assets/fonts/fonts-9644e21d.css @@ -0,0 +1,100 @@ +/* Open Sans is licensed under the Apache License, Version 2.0. See http://www.apache.org/licenses/LICENSE-2.0 */ +/* Source Code Pro is under the Open Font License. See https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL */ + +/* open-sans-300 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + src: local('Open Sans Light'), local('OpenSans-Light'), + url('../fonts/open-sans-v17-all-charsets-300-7736aa35.woff2') format('woff2'); +} + +/* open-sans-300italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + src: local('Open Sans Light Italic'), local('OpenSans-LightItalic'), + url('../fonts/open-sans-v17-all-charsets-300italic-2c7b95c0.woff2') format('woff2'); +} + +/* open-sans-regular - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans Regular'), local('OpenSans-Regular'), + url('../fonts/open-sans-v17-all-charsets-regular-2e3b1d34.woff2') format('woff2'); +} + +/* open-sans-italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), + url('../fonts/open-sans-v17-all-charsets-italic-6c9463f7.woff2') format('woff2'); +} + +/* open-sans-600 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), + url('../fonts/open-sans-v17-all-charsets-600-486c6759.woff2') format('woff2'); +} + +/* open-sans-600italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), + url('../fonts/open-sans-v17-all-charsets-600italic-1a3e8659.woff2') format('woff2'); +} + +/* open-sans-700 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + src: local('Open Sans Bold'), local('OpenSans-Bold'), + url('../fonts/open-sans-v17-all-charsets-700-c22fe8c7.woff2') format('woff2'); +} + +/* open-sans-700italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'), + url('../fonts/open-sans-v17-all-charsets-700italic-238ae959.woff2') format('woff2'); +} + +/* open-sans-800 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + src: local('Open Sans ExtraBold'), local('OpenSans-ExtraBold'), + url('../fonts/open-sans-v17-all-charsets-800-3d2c812a.woff2') format('woff2'); +} + +/* open-sans-800italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + src: local('Open Sans ExtraBold Italic'), local('OpenSans-ExtraBoldItalic'), + url('../fonts/open-sans-v17-all-charsets-800italic-ba1521ec.woff2') format('woff2'); +} + +/* source-code-pro-500 - latin_vietnamese_latin-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 500; + src: url('../fonts/source-code-pro-v11-all-charsets-500-2bdd9410.woff2') format('woff2'); +} diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-300-7736aa35.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-300-7736aa35.woff2 new file mode 100644 index 00000000..9f51be37 Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-300-7736aa35.woff2 differ diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-300italic-2c7b95c0.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-300italic-2c7b95c0.woff2 new file mode 100644 index 00000000..2f545448 Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-300italic-2c7b95c0.woff2 differ diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-600-486c6759.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-600-486c6759.woff2 new file mode 100644 index 00000000..f503d558 Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-600-486c6759.woff2 differ diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-600italic-1a3e8659.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-600italic-1a3e8659.woff2 new file mode 100644 index 00000000..c99aabe8 Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-600italic-1a3e8659.woff2 differ diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-700-c22fe8c7.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-700-c22fe8c7.woff2 new file mode 100644 index 00000000..421a1ab2 Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-700-c22fe8c7.woff2 differ diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-700italic-238ae959.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-700italic-238ae959.woff2 new file mode 100644 index 00000000..12ce3d20 Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-700italic-238ae959.woff2 differ diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-800-3d2c812a.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-800-3d2c812a.woff2 new file mode 100644 index 00000000..c94a223b Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-800-3d2c812a.woff2 differ diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-800italic-ba1521ec.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-800italic-ba1521ec.woff2 new file mode 100644 index 00000000..eed7d3c6 Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-800italic-ba1521ec.woff2 differ diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-italic-6c9463f7.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-italic-6c9463f7.woff2 new file mode 100644 index 00000000..398b68a0 Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-italic-6c9463f7.woff2 differ diff --git a/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-regular-2e3b1d34.woff2 b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-regular-2e3b1d34.woff2 new file mode 100644 index 00000000..8383e94c Binary files /dev/null and b/typ/mdbook/assets/fonts/open-sans-v17-all-charsets-regular-2e3b1d34.woff2 differ diff --git a/typ/mdbook/assets/fonts/source-code-pro-v11-all-charsets-500-2bdd9410.woff2 b/typ/mdbook/assets/fonts/source-code-pro-v11-all-charsets-500-2bdd9410.woff2 new file mode 100644 index 00000000..72224568 Binary files /dev/null and b/typ/mdbook/assets/fonts/source-code-pro-v11-all-charsets-500-2bdd9410.woff2 differ diff --git a/typ/mdbook/assets/highlight-493f70e1.css b/typ/mdbook/assets/highlight-493f70e1.css new file mode 100644 index 00000000..352c79b9 --- /dev/null +++ b/typ/mdbook/assets/highlight-493f70e1.css @@ -0,0 +1,83 @@ +/* + * An increased contrast highlighting scheme loosely based on the + * "Base16 Atelier Dune Light" theme by Bram de Haan + * (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) + * Original Base16 color scheme by Chris Kempson + * (https://github.com/chriskempson/base16) + */ + +/* Comment */ +.hljs-comment, +.hljs-quote { + color: #575757; +} + +/* Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-attr, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #d70025; +} + +/* Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #b21e00; +} + +/* Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #008200; +} + +/* Blue */ +.hljs-title, +.hljs-section { + color: #0030f2; +} + +/* Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #9d00ec; +} + +.hljs { + display: block; + overflow-x: auto; + background: #f6f7f6; + color: #000; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-addition { + color: #22863a; + background-color: #f0fff4; +} + +.hljs-deletion { + color: #b31d28; + background-color: #ffeef0; +} diff --git a/typ/mdbook/assets/highlight-abc7f01d.js b/typ/mdbook/assets/highlight-abc7f01d.js new file mode 100644 index 00000000..18d24345 --- /dev/null +++ b/typ/mdbook/assets/highlight-abc7f01d.js @@ -0,0 +1,54 @@ +/* + Highlight.js 10.1.1 (93fd0d73) + License: BSD-3-Clause + Copyright (c) 2006-2020, Ivan Sagalaev +*/ +var hljs=function(){"use strict";function e(n){Object.freeze(n);var t="function"==typeof n;return Object.getOwnPropertyNames(n).forEach((function(r){!Object.hasOwnProperty.call(n,r)||null===n[r]||"object"!=typeof n[r]&&"function"!=typeof n[r]||t&&("caller"===r||"callee"===r||"arguments"===r)||Object.isFrozen(n[r])||e(n[r])})),n}class n{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data}ignoreMatch(){this.ignore=!0}}function t(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function r(e,...n){var t={};for(const n in e)t[n]=e[n];return n.forEach((function(e){for(const n in e)t[n]=e[n]})),t}function a(e){return e.nodeName.toLowerCase()}var i=Object.freeze({__proto__:null,escapeHTML:t,inherit:r,nodeStream:function(e){var n=[];return function e(t,r){for(var i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?r+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:r,node:i}),r=e(i,r),a(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:r,node:i}));return r}(e,0),n},mergeStreams:function(e,n,r){var i=0,s="",o=[];function l(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){s+=""}function d(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var g=l();if(s+=t(r.substring(i,g[0].offset)),i=g[0].offset,g===e){o.reverse().forEach(u);do{d(g.splice(0,1)[0]),g=l()}while(g===e&&g.length&&g[0].offset===i);o.reverse().forEach(c)}else"start"===g[0].event?o.push(g[0].node):o.pop(),d(g.splice(0,1)[0])}return s+t(r.substr(i))}});const s="",o=e=>!!e.kind;class l{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=t(e)}openNode(e){if(!o(e))return;let n=e.kind;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){o(e)&&(this.buffer+=s)}value(){return this.buffer}span(e){this.buffer+=``}}class c{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{c._collapse(e)}))}}class u extends c{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new l(this,this.options).value()}finalize(){return!0}}function d(e){return e?"string"==typeof e?e:e.source:null}const g="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",h={begin:"\\\\[\\s\\S]",relevance:0},f={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[h]},p={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[h]},b={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},m=function(e,n,t={}){var a=r({className:"comment",begin:e,end:n,contains:[]},t);return a.contains.push(b),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a},v=m("//","$"),x=m("/\\*","\\*/"),E=m("#","$");var _=Object.freeze({__proto__:null,IDENT_RE:"[a-zA-Z]\\w*",UNDERSCORE_IDENT_RE:"[a-zA-Z_]\\w*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:g,BINARY_NUMBER_RE:"\\b(0b[01]+)",RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){return e.map(e=>d(e)).join("")}(n,/.*\b/,e.binary,/\b.*/)),r({className:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:h,APOS_STRING_MODE:f,QUOTE_STRING_MODE:p,PHRASAL_WORDS_MODE:b,COMMENT:m,C_LINE_COMMENT_MODE:v,C_BLOCK_COMMENT_MODE:x,HASH_COMMENT_MODE:E,NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?",relevance:0},C_NUMBER_MODE:{className:"number",begin:g,relevance:0},BINARY_NUMBER_MODE:{className:"number",begin:"\\b(0b[01]+)",relevance:0},CSS_NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[h,{begin:/\[/,end:/\]/,relevance:0,contains:[h]}]}]},TITLE_MODE:{className:"title",begin:"[a-zA-Z]\\w*",relevance:0},UNDERSCORE_TITLE_MODE:{className:"title",begin:"[a-zA-Z_]\\w*",relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})}}),N="of and for in not or if then".split(" ");function w(e,n){return n?+n:function(e){return N.includes(e.toLowerCase())}(e)?0:1}const R=t,y=r,{nodeStream:k,mergeStreams:O}=i,M=Symbol("nomatch");return function(t){var a=[],i={},s={},o=[],l=!0,c=/(^(<[^>]+>|\t|)+|\n)/gm,g="Could not find the language '{}', did you forget to load/include a language module?";const h={disableAutodetect:!0,name:"Plain text",contains:[]};var f={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:u};function p(e){return f.noHighlightRe.test(e)}function b(e,n,t,r){var a={code:n,language:e};S("before:highlight",a);var i=a.result?a.result:m(a.language,a.code,t,r);return i.code=a.code,S("after:highlight",i),i}function m(e,t,a,s){var o=t;function c(e,n){var t=E.case_insensitive?n[0].toLowerCase():n[0];return Object.prototype.hasOwnProperty.call(e.keywords,t)&&e.keywords[t]}function u(){null!=y.subLanguage?function(){if(""!==A){var e=null;if("string"==typeof y.subLanguage){if(!i[y.subLanguage])return void O.addText(A);e=m(y.subLanguage,A,!0,k[y.subLanguage]),k[y.subLanguage]=e.top}else e=v(A,y.subLanguage.length?y.subLanguage:null);y.relevance>0&&(I+=e.relevance),O.addSublanguage(e.emitter,e.language)}}():function(){if(!y.keywords)return void O.addText(A);let e=0;y.keywordPatternRe.lastIndex=0;let n=y.keywordPatternRe.exec(A),t="";for(;n;){t+=A.substring(e,n.index);const r=c(y,n);if(r){const[e,a]=r;O.addText(t),t="",I+=a,O.addKeyword(n[0],e)}else t+=n[0];e=y.keywordPatternRe.lastIndex,n=y.keywordPatternRe.exec(A)}t+=A.substr(e),O.addText(t)}(),A=""}function h(e){return e.className&&O.openNode(e.className),y=Object.create(e,{parent:{value:y}})}function p(e){return 0===y.matcher.regexIndex?(A+=e[0],1):(L=!0,0)}var b={};function x(t,r){var i=r&&r[0];if(A+=t,null==i)return u(),0;if("begin"===b.type&&"end"===r.type&&b.index===r.index&&""===i){if(A+=o.slice(r.index,r.index+1),!l){const n=Error("0 width match regex");throw n.languageName=e,n.badRule=b.rule,n}return 1}if(b=r,"begin"===r.type)return function(e){var t=e[0],r=e.rule;const a=new n(r),i=[r.__beforeBegin,r["on:begin"]];for(const n of i)if(n&&(n(e,a),a.ignore))return p(t);return r&&r.endSameAsBegin&&(r.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),r.skip?A+=t:(r.excludeBegin&&(A+=t),u(),r.returnBegin||r.excludeBegin||(A=t)),h(r),r.returnBegin?0:t.length}(r);if("illegal"===r.type&&!a){const e=Error('Illegal lexeme "'+i+'" for mode "'+(y.className||"")+'"');throw e.mode=y,e}if("end"===r.type){var s=function(e){var t=e[0],r=o.substr(e.index),a=function e(t,r,a){let i=function(e,n){var t=e&&e.exec(n);return t&&0===t.index}(t.endRe,a);if(i){if(t["on:end"]){const e=new n(t);t["on:end"](r,e),e.ignore&&(i=!1)}if(i){for(;t.endsParent&&t.parent;)t=t.parent;return t}}if(t.endsWithParent)return e(t.parent,r,a)}(y,e,r);if(!a)return M;var i=y;i.skip?A+=t:(i.returnEnd||i.excludeEnd||(A+=t),u(),i.excludeEnd&&(A=t));do{y.className&&O.closeNode(),y.skip||y.subLanguage||(I+=y.relevance),y=y.parent}while(y!==a.parent);return a.starts&&(a.endSameAsBegin&&(a.starts.endRe=a.endRe),h(a.starts)),i.returnEnd?0:t.length}(r);if(s!==M)return s}if("illegal"===r.type&&""===i)return 1;if(B>1e5&&B>3*r.index)throw Error("potential infinite loop, way more iterations than matches");return A+=i,i.length}var E=T(e);if(!E)throw console.error(g.replace("{}",e)),Error('Unknown language: "'+e+'"');var _=function(e){function n(n,t){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class t{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=function(e){return RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map(e=>e[1]);this.matcherRe=n(function(e,n="|"){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i0&&(a+=n),a+="(";o.length>0;){var l=t.exec(o);if(null==l){a+=o;break}a+=o.substring(0,l.index),o=o.substring(l.index+l[0].length),"\\"===l[0][0]&&l[1]?a+="\\"+(+l[1]+s):(a+=l[0],"("===l[0]&&r++)}a+=")"}return a}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex((e,n)=>n>0&&void 0!==e),r=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,r)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;const t=n.exec(e);return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&(this.regexIndex=0)),t}}function i(e,n){const t=e.input[e.index-1],r=e.input[e.index+e[0].length];"."!==t&&"."!==r||n.ignoreMatch()}if(e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return function t(s,o){const l=s;if(s.compiled)return l;s.compiled=!0,s.__beforeBegin=null,s.keywords=s.keywords||s.beginKeywords;let c=null;if("object"==typeof s.keywords&&(c=s.keywords.$pattern,delete s.keywords.$pattern),s.keywords&&(s.keywords=function(e,n){var t={};return"string"==typeof e?r("keyword",e):Object.keys(e).forEach((function(n){r(n,e[n])})),t;function r(e,r){n&&(r=r.toLowerCase()),r.split(" ").forEach((function(n){var r=n.split("|");t[r[0]]=[e,w(r[0],r[1])]}))}}(s.keywords,e.case_insensitive)),s.lexemes&&c)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return l.keywordPatternRe=n(s.lexemes||c||/\w+/,!0),o&&(s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?=\\b|\\s)",s.__beforeBegin=i),s.begin||(s.begin=/\B|\b/),l.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),s.end&&(l.endRe=n(s.end)),l.terminator_end=d(s.end)||"",s.endsWithParent&&o.terminator_end&&(l.terminator_end+=(s.end?"|":"")+o.terminator_end)),s.illegal&&(l.illegalRe=n(s.illegal)),void 0===s.relevance&&(s.relevance=1),s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((function(e){return function(e){return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(n){return r(e,{variants:null},n)}))),e.cached_variants?e.cached_variants:function e(n){return!!n&&(n.endsWithParent||e(n.starts))}(e)?r(e,{starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e}("self"===e?s:e)}))),s.contains.forEach((function(e){t(e,l)})),s.starts&&t(s.starts,o),l.matcher=function(e){const n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminator_end&&n.addRule(e.terminator_end,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(l),l}(e)}(E),N="",y=s||_,k={},O=new f.__emitter(f);!function(){for(var e=[],n=y;n!==E;n=n.parent)n.className&&e.unshift(n.className);e.forEach(e=>O.openNode(e))}();var A="",I=0,S=0,B=0,L=!1;try{for(y.matcher.considerAll();;){B++,L?L=!1:(y.matcher.lastIndex=S,y.matcher.considerAll());const e=y.matcher.exec(o);if(!e)break;const n=x(o.substring(S,e.index),e);S=e.index+n}return x(o.substr(S)),O.closeAllNodes(),O.finalize(),N=O.toHTML(),{relevance:I,value:N,language:e,illegal:!1,emitter:O,top:y}}catch(n){if(n.message&&n.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:n.message,context:o.slice(S-100,S+100),mode:n.mode},sofar:N,relevance:0,value:R(o),emitter:O};if(l)return{illegal:!1,relevance:0,value:R(o),emitter:O,language:e,top:y,errorRaised:n};throw n}}function v(e,n){n=n||f.languages||Object.keys(i);var t=function(e){const n={relevance:0,emitter:new f.__emitter(f),value:R(e),illegal:!1,top:h};return n.emitter.addText(e),n}(e),r=t;return n.filter(T).filter(I).forEach((function(n){var a=m(n,e,!1);a.language=n,a.relevance>r.relevance&&(r=a),a.relevance>t.relevance&&(r=t,t=a)})),r.language&&(t.second_best=r),t}function x(e){return f.tabReplace||f.useBR?e.replace(c,e=>"\n"===e?f.useBR?"
":e:f.tabReplace?e.replace(/\t/g,f.tabReplace):e):e}function E(e){let n=null;const t=function(e){var n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=f.languageDetectRe.exec(n);if(t){var r=T(t[1]);return r||(console.warn(g.replace("{}",t[1])),console.warn("Falling back to no-highlight mode for this block.",e)),r?t[1]:"no-highlight"}return n.split(/\s+/).find(e=>p(e)||T(e))}(e);if(p(t))return;S("before:highlightBlock",{block:e,language:t}),f.useBR?(n=document.createElement("div")).innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n"):n=e;const r=n.textContent,a=t?b(t,r,!0):v(r),i=k(n);if(i.length){const e=document.createElement("div");e.innerHTML=a.value,a.value=O(i,k(e),r)}a.value=x(a.value),S("after:highlightBlock",{block:e,result:a}),e.innerHTML=a.value,e.className=function(e,n,t){var r=n?s[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),e.includes(r)||a.push(r),a.join(" ").trim()}(e.className,t,a.language),e.result={language:a.language,re:a.relevance,relavance:a.relevance},a.second_best&&(e.second_best={language:a.second_best.language,re:a.second_best.relevance,relavance:a.second_best.relevance})}const N=()=>{if(!N.called){N.called=!0;var e=document.querySelectorAll("pre code");a.forEach.call(e,E)}};function T(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]}function A(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach(e=>{s[e]=n})}function I(e){var n=T(e);return n&&!n.disableAutodetect}function S(e,n){var t=e;o.forEach((function(e){e[t]&&e[t](n)}))}Object.assign(t,{highlight:b,highlightAuto:v,fixMarkup:x,highlightBlock:E,configure:function(e){f=y(f,e)},initHighlighting:N,initHighlightingOnLoad:function(){window.addEventListener("DOMContentLoaded",N,!1)},registerLanguage:function(e,n){var r=null;try{r=n(t)}catch(n){if(console.error("Language definition for '{}' could not be registered.".replace("{}",e)),!l)throw n;console.error(n),r=h}r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&A(r.aliases,{languageName:e})},listLanguages:function(){return Object.keys(i)},getLanguage:T,registerAliases:A,requireLanguage:function(e){var n=T(e);if(n)return n;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:I,inherit:y,addPlugin:function(e){o.push(e)}}),t.debugMode=function(){l=!1},t.safeMode=function(){l=!0},t.versionString="10.1.1";for(const n in _)"object"==typeof _[n]&&e(_[n]);return Object.assign(t,_),t}({})}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs); +hljs.registerLanguage("apache",function(){"use strict";return function(e){var n={className:"number",begin:"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?"};return{name:"Apache config",aliases:["apacheconf"],case_insensitive:!0,contains:[e.HASH_COMMENT_MODE,{className:"section",begin:"",contains:[n,{className:"number",begin:":\\d{1,5}"},e.inherit(e.QUOTE_STRING_MODE,{relevance:0})]},{className:"attribute",begin:/\w+/,relevance:0,keywords:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{end:/$/,relevance:0,keywords:{literal:"on off all deny allow"},contains:[{className:"meta",begin:"\\s\\[",end:"\\]$"},{className:"variable",begin:"[\\$%]\\{",end:"\\}",contains:["self",{className:"number",begin:"[\\$%]\\d+"}]},n,{className:"number",begin:"\\d+"},e.QUOTE_STRING_MODE]}}],illegal:/\S/}}}()); +hljs.registerLanguage("bash",function(){"use strict";return function(e){const s={};Object.assign(s,{className:"variable",variants:[{begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{/,end:/\}/,contains:[{begin:/:-/,contains:[s]}]}]});const t={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},n={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,t]};t.contains.push(n);const a={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,s]},i=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10}),c={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b-?[a-z\._]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},contains:[i,e.SHEBANG(),c,a,e.HASH_COMMENT_MODE,n,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},s]}}}()); +hljs.registerLanguage("c-like",function(){"use strict";return function(e){function t(e){return"(?:"+e+")?"}var n="(decltype\\(auto\\)|"+t("[a-zA-Z_]\\w*::")+"[a-zA-Z_]\\w*"+t("<.*?>")+")",r={className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},a={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},i={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},s={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{"meta-keyword":"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(a,{className:"meta-string"}),{className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},o={className:"title",begin:t("[a-zA-Z_]\\w*::")+e.IDENT_RE,relevance:0},c=t("[a-zA-Z_]\\w*::")+e.IDENT_RE+"\\s*\\(",l={keyword:"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_t short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq",built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary",literal:"true false nullptr NULL"},d=[r,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,i,a],_={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:l,contains:d.concat([{begin:/\(/,end:/\)/,keywords:l,contains:d.concat(["self"]),relevance:0}]),relevance:0},u={className:"function",begin:"("+n+"[\\*&\\s]+)+"+c,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:l,illegal:/[^\w\s\*&:<>]/,contains:[{begin:"decltype\\(auto\\)",keywords:l,relevance:0},{begin:c,returnBegin:!0,contains:[o],relevance:0},{className:"params",begin:/\(/,end:/\)/,keywords:l,relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,i,r,{begin:/\(/,end:/\)/,keywords:l,relevance:0,contains:["self",e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,i,r]}]},r,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s]};return{aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],keywords:l,disableAutodetect:!0,illegal:"",keywords:l,contains:["self",r]},{begin:e.IDENT_RE+"::",keywords:l},{className:"class",beginKeywords:"class struct",end:/[{;:]/,contains:[{begin://,contains:["self"]},e.TITLE_MODE]}]),exports:{preprocessor:s,strings:a,keywords:l}}}}()); +hljs.registerLanguage("c",function(){"use strict";return function(e){var n=e.getLanguage("c-like").rawDefinition();return n.name="C",n.aliases=["c","h"],n}}()); +hljs.registerLanguage("coffeescript",function(){"use strict";const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);return function(r){var t={keyword:e.concat(["then","unless","until","loop","by","when","and","or","is","isnt","not"]).filter((e=>n=>!e.includes(n))(["var","const","let","function","static"])).join(" "),literal:n.concat(["yes","no","on","off"]).join(" "),built_in:a.concat(["npm","print"]).join(" ")},i="[A-Za-z$_][0-9A-Za-z$_]*",s={className:"subst",begin:/#\{/,end:/}/,keywords:t},o=[r.BINARY_NUMBER_MODE,r.inherit(r.C_NUMBER_MODE,{starts:{end:"(\\s*/)?",relevance:0}}),{className:"string",variants:[{begin:/'''/,end:/'''/,contains:[r.BACKSLASH_ESCAPE]},{begin:/'/,end:/'/,contains:[r.BACKSLASH_ESCAPE]},{begin:/"""/,end:/"""/,contains:[r.BACKSLASH_ESCAPE,s]},{begin:/"/,end:/"/,contains:[r.BACKSLASH_ESCAPE,s]}]},{className:"regexp",variants:[{begin:"///",end:"///",contains:[s,r.HASH_COMMENT_MODE]},{begin:"//[gim]{0,3}(?=\\W)",relevance:0},{begin:/\/(?![ *]).*?(?![\\]).\/[gim]{0,3}(?=\W)/}]},{begin:"@"+i},{subLanguage:"javascript",excludeBegin:!0,excludeEnd:!0,variants:[{begin:"```",end:"```"},{begin:"`",end:"`"}]}];s.contains=o;var c=r.inherit(r.TITLE_MODE,{begin:i}),l={className:"params",begin:"\\([^\\(]",returnBegin:!0,contains:[{begin:/\(/,end:/\)/,keywords:t,contains:["self"].concat(o)}]};return{name:"CoffeeScript",aliases:["coffee","cson","iced"],keywords:t,illegal:/\/\*/,contains:o.concat([r.COMMENT("###","###"),r.HASH_COMMENT_MODE,{className:"function",begin:"^\\s*"+i+"\\s*=\\s*(\\(.*\\))?\\s*\\B[-=]>",end:"[-=]>",returnBegin:!0,contains:[c,l]},{begin:/[:\(,=]\s*/,relevance:0,contains:[{className:"function",begin:"(\\(.*\\))?\\s*\\B[-=]>",end:"[-=]>",returnBegin:!0,contains:[l]}]},{className:"class",beginKeywords:"class",end:"$",illegal:/[:="\[\]]/,contains:[{beginKeywords:"extends",endsWithParent:!0,illegal:/[:="\[\]]/,contains:[c]},c]},{begin:i+":",end:":",returnBegin:!0,returnEnd:!0,relevance:0}])}}}()); +hljs.registerLanguage("cpp",function(){"use strict";return function(e){var t=e.getLanguage("c-like").rawDefinition();return t.disableAutodetect=!1,t.name="C++",t.aliases=["cc","c++","h++","hpp","hh","hxx","cxx"],t}}()); +hljs.registerLanguage("csharp",function(){"use strict";return function(e){var n={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let nameof on orderby partial remove select set value var when where yield",literal:"null false true"},i=e.inherit(e.TITLE_MODE,{begin:"[a-zA-Z](\\.?\\w)*"}),a={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},s={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},t=e.inherit(s,{illegal:/\n/}),l={className:"subst",begin:"{",end:"}",keywords:n},r=e.inherit(l,{illegal:/\n/}),c={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},e.BACKSLASH_ESCAPE,r]},o={className:"string",begin:/\$@"/,end:'"',contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},l]},g=e.inherit(o,{illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},r]});l.contains=[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.C_BLOCK_COMMENT_MODE],r.contains=[g,c,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.inherit(e.C_BLOCK_COMMENT_MODE,{illegal:/\n/})];var d={variants:[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},E={begin:"<",end:">",contains:[{beginKeywords:"in out"},i]},_=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",b={begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"],keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{begin:"\x3c!--|--\x3e"},{begin:""}]}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},d,a,{beginKeywords:"class interface",end:/[{;=]/,illegal:/[^\s:,]/,contains:[{beginKeywords:"where class"},i,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",end:/[{;=]/,illegal:/[^\s:]/,contains:[i,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta",begin:"^\\s*\\[",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{className:"meta-string",begin:/"/,end:/"/}]},{beginKeywords:"new return throw await else",relevance:0},{className:"function",begin:"("+_+"\\s+)+"+e.IDENT_RE+"\\s*(\\<.+\\>)?\\s*\\(",returnBegin:!0,end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{begin:e.IDENT_RE+"\\s*(\\<.+\\>)?\\s*\\(",returnBegin:!0,contains:[e.TITLE_MODE,E],relevance:0},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0,contains:[d,a,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},b]}}}()); +hljs.registerLanguage("css",function(){"use strict";return function(e){var n={begin:/(?:[A-Z\_\.\-]+|--[a-zA-Z0-9_-]+)\s*:/,returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute",begin:/\S/,end:":",excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0,contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in",begin:/[\w-]+/},{begin:/\(/,end:/\)/,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]},e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}]}}]};return{name:"CSS",case_insensitive:!0,illegal:/[=\/|'\$]/,contains:[e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:/\.[A-Za-z0-9_-]+/},{className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"@(page|font-face)",lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]",illegal:/:/,returnBegin:!0,contains:[{className:"keyword",begin:/@\-?\w[\w]*(\-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:"and or not only",contains:[{begin:/[a-z-]+:/,className:"attribute"},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},{begin:"{",end:"}",illegal:/\S/,contains:[e.C_BLOCK_COMMENT_MODE,n]}]}}}()); +hljs.registerLanguage("diff",function(){"use strict";return function(e){return{name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,variants:[{begin:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{begin:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{begin:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{className:"comment",variants:[{begin:/Index: /,end:/$/},{begin:/={3,}/,end:/$/},{begin:/^\-{3}/,end:/$/},{begin:/^\*{3} /,end:/$/},{begin:/^\+{3}/,end:/$/},{begin:/^\*{15}$/}]},{className:"addition",begin:"^\\+",end:"$"},{className:"deletion",begin:"^\\-",end:"$"},{className:"addition",begin:"^\\!",end:"$"}]}}}()); +hljs.registerLanguage("go",function(){"use strict";return function(e){var n={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",literal:"true false iota nil",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{name:"Go",aliases:["golang"],keywords:n,illegal:"e(n)).join("")}return function(a){var s={className:"number",relevance:0,variants:[{begin:/([\+\-]+)?[\d]+_[\d_]+/},{begin:a.NUMBER_RE}]},i=a.COMMENT();i.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];var t={className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)}/}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},l={className:"string",contains:[a.BACKSLASH_ESCAPE],variants:[{begin:"'''",end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'},{begin:"'",end:"'"}]},c={begin:/\[/,end:/\]/,contains:[i,r,t,l,s,"self"],relevance:0},g="("+[/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/].map(n=>e(n)).join("|")+")";return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/,contains:[i,{className:"section",begin:/\[+/,end:/\]+/},{begin:n(g,"(\\s*\\.\\s*",g,")*",n("(?=",/\s*=\s*[^#\s]/,")")),className:"attr",starts:{end:/$/,contains:[i,c,r,t,l,s]}}]}}}()); +hljs.registerLanguage("java",function(){"use strict";function e(e){return e?"string"==typeof e?e:e.source:null}function n(e){return a("(",e,")?")}function a(...n){return n.map(n=>e(n)).join("")}function s(...n){return"("+n.map(n=>e(n)).join("|")+")"}return function(e){var t="false synchronized int abstract float private char boolean var static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",i={className:"meta",begin:"@[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*",contains:[{begin:/\(/,end:/\)/,contains:["self"]}]},r=e=>a("[",e,"]+([",e,"_]*[",e,"]+)?"),c={className:"number",variants:[{begin:`\\b(0[bB]${r("01")})[lL]?`},{begin:`\\b(0${r("0-7")})[dDfFlL]?`},{begin:a(/\b0[xX]/,s(a(r("a-fA-F0-9"),/\./,r("a-fA-F0-9")),a(r("a-fA-F0-9"),/\.?/),a(/\./,r("a-fA-F0-9"))),/([pP][+-]?(\d+))?/,/[fFdDlL]?/)},{begin:a(/\b/,s(a(/\d*\./,r("\\d")),r("\\d")),/[eE][+-]?[\d]+[dDfF]?/)},{begin:a(/\b/,r(/\d/),n(/\.?/),n(r(/\d/)),/[dDfFlL]?/)}],relevance:0};return{name:"Java",aliases:["jsp"],keywords:t,illegal:/<\/|#/,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"class",beginKeywords:"class interface",end:/[{;=]/,excludeEnd:!0,keywords:"class interface",illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"new throw return else",relevance:0},{className:"function",begin:"([À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(<[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(\\s*,\\s*[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*)*>)?\\s+)+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:t,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/,keywords:t,relevance:0,contains:[i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},c,i]}}}()); +hljs.registerLanguage("javascript",function(){"use strict";const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);function s(e){return r("(?=",e,")")}function r(...e){return e.map(e=>(function(e){return e?"string"==typeof e?e:e.source:null})(e)).join("")}return function(t){var i="[A-Za-z$_][0-9A-Za-z$_]*",c={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/},o={$pattern:"[A-Za-z$_][0-9A-Za-z$_]*",keyword:e.join(" "),literal:n.join(" "),built_in:a.join(" ")},l={className:"number",variants:[{begin:"\\b(0[bB][01]+)n?"},{begin:"\\b(0[oO][0-7]+)n?"},{begin:t.C_NUMBER_RE+"n?"}],relevance:0},E={className:"subst",begin:"\\$\\{",end:"\\}",keywords:o,contains:[]},d={begin:"html`",end:"",starts:{end:"`",returnEnd:!1,contains:[t.BACKSLASH_ESCAPE,E],subLanguage:"xml"}},g={begin:"css`",end:"",starts:{end:"`",returnEnd:!1,contains:[t.BACKSLASH_ESCAPE,E],subLanguage:"css"}},u={className:"string",begin:"`",end:"`",contains:[t.BACKSLASH_ESCAPE,E]};E.contains=[t.APOS_STRING_MODE,t.QUOTE_STRING_MODE,d,g,u,l,t.REGEXP_MODE];var b=E.contains.concat([{begin:/\(/,end:/\)/,contains:["self"].concat(E.contains,[t.C_BLOCK_COMMENT_MODE,t.C_LINE_COMMENT_MODE])},t.C_BLOCK_COMMENT_MODE,t.C_LINE_COMMENT_MODE]),_={className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:b};return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:o,contains:[t.SHEBANG({binary:"node",relevance:5}),{className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},t.APOS_STRING_MODE,t.QUOTE_STRING_MODE,d,g,u,t.C_LINE_COMMENT_MODE,t.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+",contains:[{className:"type",begin:"\\{",end:"\\}",relevance:0},{className:"variable",begin:i+"(?=\\s*(-)|$)",endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]}),t.C_BLOCK_COMMENT_MODE,l,{begin:r(/[{,\n]\s*/,s(r(/(((\/\/.*)|(\/\*(.|\n)*\*\/))\s*)*/,i+"\\s*:"))),relevance:0,contains:[{className:"attr",begin:i+s("\\s*:"),relevance:0}]},{begin:"("+t.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[t.C_LINE_COMMENT_MODE,t.C_BLOCK_COMMENT_MODE,t.REGEXP_MODE,{className:"function",begin:"(\\([^(]*(\\([^(]*(\\([^(]*\\))?\\))?\\)|"+t.UNDERSCORE_IDENT_RE+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:t.UNDERSCORE_IDENT_RE},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:o,contains:b}]}]},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{begin:"<>",end:""},{begin:c.begin,end:c.end}],subLanguage:"xml",contains:[{begin:c.begin,end:c.end,skip:!0,contains:["self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/\{/,excludeEnd:!0,contains:[t.inherit(t.TITLE_MODE,{begin:i}),_],illegal:/\[|%/},{begin:/\$[(.]/},t.METHOD_GUARD,{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends"},t.UNDERSCORE_TITLE_MODE]},{beginKeywords:"constructor",end:/\{/,excludeEnd:!0},{begin:"(get|set)\\s+(?="+i+"\\()",end:/{/,keywords:"get set",contains:[t.inherit(t.TITLE_MODE,{begin:i}),{begin:/\(\)/},_]}],illegal:/#(?!!)/}}}()); +hljs.registerLanguage("json",function(){"use strict";return function(n){var e={literal:"true false null"},i=[n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE],t=[n.QUOTE_STRING_MODE,n.C_NUMBER_MODE],a={end:",",endsWithParent:!0,excludeEnd:!0,contains:t,keywords:e},l={begin:"{",end:"}",contains:[{className:"attr",begin:/"/,end:/"/,contains:[n.BACKSLASH_ESCAPE],illegal:"\\n"},n.inherit(a,{begin:/:/})].concat(i),illegal:"\\S"},s={begin:"\\[",end:"\\]",contains:[n.inherit(a)],illegal:"\\S"};return t.push(l,s),i.forEach((function(n){t.push(n)})),{name:"JSON",contains:t,keywords:e,illegal:"\\S"}}}()); +hljs.registerLanguage("kotlin",function(){"use strict";return function(e){var n={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual trait volatile transient native default",built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},a={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@"},i={className:"subst",begin:"\\${",end:"}",contains:[e.C_NUMBER_MODE]},s={className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},t={className:"string",variants:[{begin:'"""',end:'"""(?=[^"])',contains:[s,i]},{begin:"'",end:"'",illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,s,i]}]};i.contains.push(t);var r={className:"meta",begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?"},l={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/,end:/\)/,contains:[e.inherit(t,{className:"meta-string"})]}]},c=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),o={variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/,contains:[]}]},d=o;return d.variants[1].contains=[o],o.variants[1].contains=[d],{name:"Kotlin",aliases:["kt"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,c,{className:"keyword",begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol",begin:/@\w+/}]}},a,r,l,{className:"function",beginKeywords:"fun",end:"[(]|$",returnBegin:!0,excludeEnd:!0,keywords:n,illegal:/fun\s+(<.*>)?[^\s\(]+(\s+[^\s\(]+)\s*=/,relevance:5,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://,keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/,endsWithParent:!0,contains:[o,e.C_LINE_COMMENT_MODE,c],relevance:0},e.C_LINE_COMMENT_MODE,c,r,l,t,e.C_NUMBER_MODE]},c]},{className:"class",beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0,illegal:"extends implements",contains:[{beginKeywords:"public protected internal private constructor"},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/,excludeBegin:!0,returnEnd:!0},r,l]},t,{className:"meta",begin:"^#!/usr/bin/env",end:"$",illegal:"\n"},{className:"number",begin:"\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",relevance:0}]}}}()); +hljs.registerLanguage("less",function(){"use strict";return function(e){var n="([\\w-]+|@{[\\w-]+})",a=[],s=[],t=function(e){return{className:"string",begin:"~?"+e+".*?"+e}},r=function(e,n,a){return{className:e,begin:n,relevance:a}},i={begin:"\\(",end:"\\)",contains:s,relevance:0};s.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t("'"),t('"'),e.CSS_NUMBER_MODE,{begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]",excludeEnd:!0}},r("number","#[0-9A-Fa-f]+\\b"),i,r("variable","@@?[\\w-]+",10),r("variable","@{[\\w-]+}"),r("built_in","~?`[^`]*?`"),{className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0},{className:"meta",begin:"!important"});var c=s.concat({begin:"{",end:"}",contains:a}),l={beginKeywords:"when",endsWithParent:!0,contains:[{beginKeywords:"and not"}].concat(s)},o={begin:n+"\\s*:",returnBegin:!0,end:"[;}]",relevance:0,contains:[{className:"attribute",begin:n,end:":",excludeEnd:!0,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:s}}]},g={className:"keyword",begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{end:"[;{}]",returnEnd:!0,contains:s,relevance:0}},d={className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:c}},b={variants:[{begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:n,end:"{"}],returnBegin:!0,returnEnd:!0,illegal:"[<='$\"]",relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,l,r("keyword","all\\b"),r("variable","@{[\\w-]+}"),r("selector-tag",n+"%?",0),r("selector-id","#"+n),r("selector-class","\\."+n,0),r("selector-tag","&",0),{className:"selector-attr",begin:"\\[",end:"\\]"},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"\\(",end:"\\)",contains:c},{begin:"!important"}]};return a.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,g,d,o,b),{name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:a}}}()); +hljs.registerLanguage("lua",function(){"use strict";return function(e){var t={begin:"\\[=*\\[",end:"\\]=*\\]",contains:["self"]},a=[e.COMMENT("--(?!\\[=*\\[)","$"),e.COMMENT("--\\[=*\\[","\\]=*\\]",{contains:[t],relevance:10})];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE,literal:"true false nil",keyword:"and break do else elseif end for goto if in local not or repeat return then until while",built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove"},contains:a.concat([{className:"function",beginKeywords:"function",end:"\\)",contains:[e.inherit(e.TITLE_MODE,{begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",begin:"\\(",endsWithParent:!0,contains:a}].concat(a)},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string",begin:"\\[=*\\[",end:"\\]=*\\]",contains:[t],relevance:5}])}}}()); +hljs.registerLanguage("makefile",function(){"use strict";return function(e){var i={className:"variable",variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)",contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin:"",relevance:10,contains:[a,i,t,s,{begin:"\\[",end:"\\]",contains:[{className:"meta",begin:"",contains:[a,s,i,t]}]}]},e.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},n,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:")",end:">",keywords:{name:"style"},contains:[c],starts:{end:"",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:")",end:">",keywords:{name:"script"},contains:[c],starts:{end:"<\/script>",returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:"",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},c]}]}}}()); +hljs.registerLanguage("markdown",function(){"use strict";return function(n){const e={begin:"<",end:">",subLanguage:"xml",relevance:0},a={begin:"\\[.+?\\][\\(\\[].*?[\\)\\]]",returnBegin:!0,contains:[{className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0,relevance:0},{className:"link",begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}],relevance:10},i={className:"strong",contains:[],variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},s={className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,relevance:0}]};i.contains.push(s),s.contains.push(i);var c=[e,a];return i.contains=i.contains.concat(c),s.contains=s.contains.concat(c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:c=c.concat(i,s)},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:c}]}]},e,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:c,end:"$"},{className:"code",variants:[{begin:"(`{3,})(.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})(.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}}()); +hljs.registerLanguage("nginx",function(){"use strict";return function(e){var n={className:"variable",variants:[{begin:/\$\d+/},{begin:/\$\{/,end:/}/},{begin:"[\\$\\@]"+e.UNDERSCORE_IDENT_RE}]},a={endsWithParent:!0,keywords:{$pattern:"[a-z/_]+",literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/}]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[n]},{className:"regexp",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:"\\s\\^",end:"\\s|{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|{|;",returnEnd:!0},{begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number",begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{className:"number",begin:"\\b\\d+[kKmMgGdshdwy]*\\b",relevance:0},n]};return{name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{begin:e.UNDERSCORE_IDENT_RE+"\\s+{",returnBegin:!0,end:"{",contains:[{className:"section",begin:e.UNDERSCORE_IDENT_RE}],relevance:0},{begin:e.UNDERSCORE_IDENT_RE+"\\s",end:";|{",returnBegin:!0,contains:[{className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:a}],relevance:0}],illegal:"[^\\s\\}]"}}}()); +hljs.registerLanguage("objectivec",function(){"use strict";return function(e){var n=/[a-zA-Z@][a-zA-Z0-9_]*/,_={$pattern:n,keyword:"@interface @class @protocol @implementation"};return{name:"Objective-C",aliases:["mm","objc","obj-c"],keywords:{$pattern:n,keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},illegal:"/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class",begin:"("+_.keyword.split(" ").join("|")+")\\b",end:"({|$)",excludeEnd:!0,keywords:_,contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE,relevance:0}]}}}()); +hljs.registerLanguage("perl",function(){"use strict";return function(e){var n={$pattern:/[\w.]+/,keyword:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmget sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when"},t={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:n},s={begin:"->{",end:"}"},r={variants:[{begin:/\$\d/},{begin:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{begin:/[\$%@][^\s\w{]/,relevance:0}]},i=[e.BACKSLASH_ESCAPE,t,r],a=[r,e.HASH_COMMENT_MODE,e.COMMENT("^\\=\\w","\\=cut",{endsWithParent:!0}),s,{className:"string",contains:i,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*\\<",end:"\\>",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE]},{begin:"{\\w+}",contains:[],relevance:0},{begin:"-?\\w+\\s*\\=\\>",contains:[],relevance:0}]},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",keywords:"split return print reverse grep",relevance:0,contains:[e.HASH_COMMENT_MODE,{className:"regexp",begin:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",relevance:10},{className:"regexp",begin:"(m|qr)?/",end:"/[a-z]*",contains:[e.BACKSLASH_ESCAPE],relevance:0}]},{className:"function",beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]}];return t.contains=a,s.contains=a,{name:"Perl",aliases:["pl","pm"],keywords:n,contains:a}}}()); +hljs.registerLanguage("php",function(){"use strict";return function(e){var r={begin:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},t={className:"meta",variants:[{begin:/<\?php/,relevance:10},{begin:/<\?[=]?/},{begin:/\?>/}]},a={className:"string",contains:[e.BACKSLASH_ESCAPE,t],variants:[{begin:'b"',end:'"'},{begin:"b'",end:"'"},e.inherit(e.APOS_STRING_MODE,{illegal:null}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null})]},n={variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]},i={keyword:"__CLASS__ __DIR__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __NAMESPACE__ __TRAIT__ die echo exit include include_once print require require_once array abstract and as binary bool boolean break callable case catch class clone const continue declare default do double else elseif empty enddeclare endfor endforeach endif endswitch endwhile eval extends final finally float for foreach from global goto if implements instanceof insteadof int integer interface isset iterable list new object or private protected public real return string switch throw trait try unset use var void while xor yield",literal:"false null true",built_in:"Error|0 AppendIterator ArgumentCountError ArithmeticError ArrayIterator ArrayObject AssertionError BadFunctionCallException BadMethodCallException CachingIterator CallbackFilterIterator CompileError Countable DirectoryIterator DivisionByZeroError DomainException EmptyIterator ErrorException Exception FilesystemIterator FilterIterator GlobIterator InfiniteIterator InvalidArgumentException IteratorIterator LengthException LimitIterator LogicException MultipleIterator NoRewindIterator OutOfBoundsException OutOfRangeException OuterIterator OverflowException ParentIterator ParseError RangeException RecursiveArrayIterator RecursiveCachingIterator RecursiveCallbackFilterIterator RecursiveDirectoryIterator RecursiveFilterIterator RecursiveIterator RecursiveIteratorIterator RecursiveRegexIterator RecursiveTreeIterator RegexIterator RuntimeException SeekableIterator SplDoublyLinkedList SplFileInfo SplFileObject SplFixedArray SplHeap SplMaxHeap SplMinHeap SplObjectStorage SplObserver SplObserver SplPriorityQueue SplQueue SplStack SplSubject SplSubject SplTempFileObject TypeError UnderflowException UnexpectedValueException ArrayAccess Closure Generator Iterator IteratorAggregate Serializable Throwable Traversable WeakReference Directory __PHP_Incomplete_Class parent php_user_filter self static stdClass"};return{aliases:["php","php3","php4","php5","php6","php7"],case_insensitive:!0,keywords:i,contains:[e.HASH_COMMENT_MODE,e.COMMENT("//","$",{contains:[t]}),e.COMMENT("/\\*","\\*/",{contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.COMMENT("__halt_compiler.+?;",!1,{endsWithParent:!0,keywords:"__halt_compiler"}),{className:"string",begin:/<<<['"]?\w+['"]?$/,end:/^\w+;?$/,contains:[e.BACKSLASH_ESCAPE,{className:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/,end:/\}/}]}]},t,{className:"keyword",begin:/\$this\b/},r,{begin:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{className:"function",beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0,illegal:"[$%\\[]",contains:[e.UNDERSCORE_TITLE_MODE,{className:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:i,contains:["self",r,e.C_BLOCK_COMMENT_MODE,a,n]}]},{className:"class",beginKeywords:"class interface",end:"{",excludeEnd:!0,illegal:/[:\(\$"]/,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",end:";",illegal:/[\.']/,contains:[e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"use",end:";",contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"=>"},a,n]}}}()); +hljs.registerLanguage("php-template",function(){"use strict";return function(n){return{name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},n.inherit(n.APOS_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0}),n.inherit(n.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0})]}]}}}()); +hljs.registerLanguage("plaintext",function(){"use strict";return function(t){return{name:"Plain text",aliases:["text","txt"],disableAutodetect:!0}}}()); +hljs.registerLanguage("properties",function(){"use strict";return function(e){var n="[ \\t\\f]*",t="("+n+"[:=]"+n+"|[ \\t\\f]+)",a="([^\\\\:= \\t\\f\\n]|\\\\.)+",s={end:t,relevance:0,starts:{className:"string",end:/$/,relevance:0,contains:[{begin:"\\\\\\n"}]}};return{name:".properties",case_insensitive:!0,illegal:/\S/,contains:[e.COMMENT("^\\s*[!#]","$"),{begin:"([^\\\\\\W:= \\t\\f\\n]|\\\\.)+"+t,returnBegin:!0,contains:[{className:"attr",begin:"([^\\\\\\W:= \\t\\f\\n]|\\\\.)+",endsParent:!0,relevance:0}],starts:s},{begin:a+t,returnBegin:!0,relevance:0,contains:[{className:"meta",begin:a,endsParent:!0,relevance:0}],starts:s},{className:"attr",relevance:0,begin:a+n+"$"}]}}}()); +hljs.registerLanguage("python",function(){"use strict";return function(e){var n={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10",built_in:"Ellipsis NotImplemented",literal:"False None True"},a={className:"meta",begin:/^(>>>|\.\.\.) /},i={className:"subst",begin:/\{/,end:/\}/,keywords:n,illegal:/#/},s={begin:/\{\{/,relevance:0},r={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/(u|b)?r?'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(u|b)?r?"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(fr|rf|f)'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(fr|rf|f)"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(u|r|ur)'/,end:/'/,relevance:10},{begin:/(u|r|ur)"/,end:/"/,relevance:10},{begin:/(b|br)'/,end:/'/},{begin:/(b|br)"/,end:/"/},{begin:/(fr|rf|f)'/,end:/'/,contains:[e.BACKSLASH_ESCAPE,s,i]},{begin:/(fr|rf|f)"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,i]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},l={className:"number",relevance:0,variants:[{begin:e.BINARY_NUMBER_RE+"[lLjJ]?"},{begin:"\\b(0o[0-7]+)[lLjJ]?"},{begin:e.C_NUMBER_RE+"[lLjJ]?"}]},t={className:"params",variants:[{begin:/\(\s*\)/,skip:!0,className:null},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:["self",a,l,r,e.HASH_COMMENT_MODE]}]};return i.contains=[r,l,a],{name:"Python",aliases:["py","gyp","ipython"],keywords:n,illegal:/(<\/|->|\?)|=>/,contains:[a,l,{beginKeywords:"if",relevance:0},r,e.HASH_COMMENT_MODE,{variants:[{className:"function",beginKeywords:"def"},{className:"class",beginKeywords:"class"}],end:/:/,illegal:/[${=;\n,]/,contains:[e.UNDERSCORE_TITLE_MODE,t,{begin:/->/,endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/,end:/$/},{begin:/\b(print|exec)\(/}]}}}()); +hljs.registerLanguage("python-repl",function(){"use strict";return function(n){return{aliases:["pycon"],contains:[{className:"meta",starts:{end:/ |$/,starts:{end:"$",subLanguage:"python"}},variants:[{begin:/^>>>(?=[ ]|$)/},{begin:/^\.\.\.(?=[ ]|$)/}]}]}}}()); +hljs.registerLanguage("ruby",function(){"use strict";return function(e){var n="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",a={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},s={className:"doctag",begin:"@[A-Za-z]+"},i={begin:"#<",end:">"},r=[e.COMMENT("#","$",{contains:[s]}),e.COMMENT("^\\=begin","^\\=end",{contains:[s],relevance:10}),e.COMMENT("^__END__","\\n$")],c={className:"subst",begin:"#\\{",end:"}",keywords:a},t={className:"string",contains:[e.BACKSLASH_ESCAPE,c],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{begin:/<<[-~]?'?(\w+)(?:.|\n)*?\n\s*\1\b/,returnBegin:!0,contains:[{begin:/<<[-~]?'?/},e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,c]})]}]},b={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:a},d=[t,i,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE}]}].concat(r)},{className:"function",beginKeywords:"def",end:"$|;",contains:[e.inherit(e.TITLE_MODE,{begin:n}),b].concat(r)},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[t,{begin:n}],relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:a},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[i,{className:"regexp",contains:[e.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(r),relevance:0}].concat(r);c.contains=d,b.contains=d;var g=[{begin:/^\s*=>/,starts:{end:"$",contains:d}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{end:"$",contains:d}}];return{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:a,illegal:/\/\*/,contains:r.concat(g).concat(d)}}}()); +hljs.registerLanguage("rust",function(){"use strict";return function(e){var n="([ui](8|16|32|64|128|size)|f(32|64))?",t="drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!";return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",keyword:"abstract as async await become box break const continue crate do dyn else enum extern false final fn for if impl in let loop macro match mod move mut override priv pub ref return self Self static struct super trait true try type typeof unsafe unsized use virtual where while yield",literal:"true false Some None Ok Err",built_in:t},illegal:""}]}}}()); +hljs.registerLanguage("scss",function(){"use strict";return function(e){var t={className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"},i={className:"number",begin:"#[0-9A-Fa-f]+"};return e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{name:"SCSS",case_insensitive:!0,illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:"\\#[A-Za-z0-9_-]+",relevance:0},{className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},{className:"selector-attr",begin:"\\[",end:"\\]",illegal:"$"},{className:"selector-tag",begin:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",relevance:0},{className:"selector-pseudo",begin:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"},{className:"selector-pseudo",begin:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"},t,{className:"attribute",begin:"\\b(src|z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",illegal:"[^\\s]"},{begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{begin:":",end:";",contains:[t,i,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{className:"meta",begin:"!important"}]},{begin:"@(page|font-face)",lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]",returnBegin:!0,keywords:"and or not only",contains:[{begin:"@[a-z-]+",className:"keyword"},t,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,i,e.CSS_NUMBER_MODE]}]}}}()); +hljs.registerLanguage("shell",function(){"use strict";return function(s){return{name:"Shell Session",aliases:["console"],contains:[{className:"meta",begin:"^\\s{0,3}[/\\w\\d\\[\\]()@-]*[>%$#]",starts:{end:"$",subLanguage:"bash"}}]}}}()); +hljs.registerLanguage("sql",function(){"use strict";return function(e){var t=e.COMMENT("--","$");return{name:"SQL",case_insensitive:!0,illegal:/[<>{}*]/,contains:[{beginKeywords:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment values with",end:/;/,endsWithParent:!0,keywords:{$pattern:/[\w\.]+/,keyword:"as abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias all allocate allow alter always analyze ancillary and anti any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound bucket buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain explode export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force foreign form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour hours http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lateral lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minutes minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notnull notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second seconds section securefile security seed segment select self semi sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tablesample tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unnest unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace window with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null unknown",built_in:"array bigint binary bit blob bool boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text time timestamp tinyint varchar varchar2 varying void"},contains:[{className:"string",begin:"'",end:"'",contains:[{begin:"''"}]},{className:"string",begin:'"',end:'"',contains:[{begin:'""'}]},{className:"string",begin:"`",end:"`"},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,e.HASH_COMMENT_MODE]},e.C_BLOCK_COMMENT_MODE,t,e.HASH_COMMENT_MODE]}}}()); +hljs.registerLanguage("swift",function(){"use strict";return function(e){var i={keyword:"#available #colorLiteral #column #else #elseif #endif #file #fileLiteral #function #if #imageLiteral #line #selector #sourceLocation _ __COLUMN__ __FILE__ __FUNCTION__ __LINE__ Any as as! as? associatedtype associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false fileprivate final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating open operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet",literal:"true false nil",built_in:"abs advance alignof alignofValue anyGenerator assert assertionFailure bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c compactMap contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal fatalError filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare map max maxElement min minElement numericCast overlaps partition posix precondition preconditionFailure print println quickSort readLine reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith stride strideof strideofValue swap toString transcode underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers withUnsafePointer withUnsafePointers withVaList zip"},n=e.COMMENT("/\\*","\\*/",{contains:["self"]}),t={className:"subst",begin:/\\\(/,end:"\\)",keywords:i,contains:[]},a={className:"string",contains:[e.BACKSLASH_ESCAPE,t],variants:[{begin:/"""/,end:/"""/},{begin:/"/,end:/"/}]},r={className:"number",begin:"\\b([\\d_]+(\\.[\\deE_]+)?|0x[a-fA-F0-9_]+(\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b",relevance:0};return t.contains=[r],{name:"Swift",keywords:i,contains:[a,e.C_LINE_COMMENT_MODE,n,{className:"type",begin:"\\b[A-Z][\\wÀ-ʸ']*[!?]"},{className:"type",begin:"\\b[A-Z][\\wÀ-ʸ']*",relevance:0},r,{className:"function",beginKeywords:"func",end:"{",excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{begin://},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:i,contains:["self",r,a,e.C_BLOCK_COMMENT_MODE,{begin:":"}],illegal:/["']/}],illegal:/\[|%/},{className:"class",beginKeywords:"struct protocol class extension enum",keywords:i,end:"\\{",excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/})]},{className:"meta",begin:"(@discardableResult|@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@objcMembers|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain|@dynamicMemberLookup|@propertyWrapper)\\b"},{beginKeywords:"import",end:/$/,contains:[e.C_LINE_COMMENT_MODE,n]}]}}}()); +hljs.registerLanguage("typescript",function(){"use strict";const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);return function(r){var t={$pattern:"[A-Za-z$_][0-9A-Za-z$_]*",keyword:e.concat(["type","namespace","typedef","interface","public","private","protected","implements","declare","abstract","readonly"]).join(" "),literal:n.join(" "),built_in:a.concat(["any","void","number","boolean","string","object","never","enum"]).join(" ")},s={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*"},i={className:"number",variants:[{begin:"\\b(0[bB][01]+)n?"},{begin:"\\b(0[oO][0-7]+)n?"},{begin:r.C_NUMBER_RE+"n?"}],relevance:0},o={className:"subst",begin:"\\$\\{",end:"\\}",keywords:t,contains:[]},c={begin:"html`",end:"",starts:{end:"`",returnEnd:!1,contains:[r.BACKSLASH_ESCAPE,o],subLanguage:"xml"}},l={begin:"css`",end:"",starts:{end:"`",returnEnd:!1,contains:[r.BACKSLASH_ESCAPE,o],subLanguage:"css"}},E={className:"string",begin:"`",end:"`",contains:[r.BACKSLASH_ESCAPE,o]};o.contains=[r.APOS_STRING_MODE,r.QUOTE_STRING_MODE,c,l,E,i,r.REGEXP_MODE];var d={begin:"\\(",end:/\)/,keywords:t,contains:["self",r.QUOTE_STRING_MODE,r.APOS_STRING_MODE,r.NUMBER_MODE]},u={className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:[r.C_LINE_COMMENT_MODE,r.C_BLOCK_COMMENT_MODE,s,d]};return{name:"TypeScript",aliases:["ts"],keywords:t,contains:[r.SHEBANG(),{className:"meta",begin:/^\s*['"]use strict['"]/},r.APOS_STRING_MODE,r.QUOTE_STRING_MODE,c,l,E,r.C_LINE_COMMENT_MODE,r.C_BLOCK_COMMENT_MODE,i,{begin:"("+r.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[r.C_LINE_COMMENT_MODE,r.C_BLOCK_COMMENT_MODE,r.REGEXP_MODE,{className:"function",begin:"(\\([^(]*(\\([^(]*(\\([^(]*\\))?\\))?\\)|"+r.UNDERSCORE_IDENT_RE+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:r.UNDERSCORE_IDENT_RE},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:d.contains}]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/[\{;]/,excludeEnd:!0,keywords:t,contains:["self",r.inherit(r.TITLE_MODE,{begin:"[A-Za-z$_][0-9A-Za-z$_]*"}),u],illegal:/%/,relevance:0},{beginKeywords:"constructor",end:/[\{;]/,excludeEnd:!0,contains:["self",u]},{begin:/module\./,keywords:{built_in:"module"},relevance:0},{beginKeywords:"module",end:/\{/,excludeEnd:!0},{beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:"interface extends"},{begin:/\$[(.]/},{begin:"\\."+r.IDENT_RE,relevance:0},s,d]}}}()); +hljs.registerLanguage("yaml",function(){"use strict";return function(e){var n="true false yes no null",a="[\\w#;/?:@&=+$,.~*\\'()[\\]]+",s={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:"{{",end:"}}"},{begin:"%{",end:"}"}]}]},i=e.inherit(s,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={end:",",endsWithParent:!0,excludeEnd:!0,contains:[],keywords:n,relevance:0},t={begin:"{",end:"}",contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]",contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---s*$",relevance:10},{className:"string",begin:"[\\|>]([0-9]?[+-])?[ ]*\\n( *)[\\S ]+\\n(\\2[\\S ]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type",begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"\\-(?=[ ]|$)",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},{className:"number",begin:e.C_NUMBER_RE+"\\b"},t,g,s],c=[...b];return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0,aliases:["yml","YAML"],contains:b}}}()); +hljs.registerLanguage("armasm",function(){"use strict";return function(s){const e={variants:[s.COMMENT("^[ \\t]*(?=#)","$",{relevance:0,excludeBegin:!0}),s.COMMENT("[;@]","$",{relevance:0}),s.C_LINE_COMMENT_MODE,s.C_BLOCK_COMMENT_MODE]};return{name:"ARM Assembly",case_insensitive:!0,aliases:["arm"],keywords:{$pattern:"\\.?"+s.IDENT_RE,meta:".2byte .4byte .align .ascii .asciz .balign .byte .code .data .else .end .endif .endm .endr .equ .err .exitm .extern .global .hword .if .ifdef .ifndef .include .irp .long .macro .rept .req .section .set .skip .space .text .word .arm .thumb .code16 .code32 .force_thumb .thumb_func .ltorg ALIAS ALIGN ARM AREA ASSERT ATTR CN CODE CODE16 CODE32 COMMON CP DATA DCB DCD DCDU DCDO DCFD DCFDU DCI DCQ DCQU DCW DCWU DN ELIF ELSE END ENDFUNC ENDIF ENDP ENTRY EQU EXPORT EXPORTAS EXTERN FIELD FILL FUNCTION GBLA GBLL GBLS GET GLOBAL IF IMPORT INCBIN INCLUDE INFO KEEP LCLA LCLL LCLS LTORG MACRO MAP MEND MEXIT NOFP OPT PRESERVE8 PROC QN READONLY RELOC REQUIRE REQUIRE8 RLIST FN ROUT SETA SETL SETS SN SPACE SUBT THUMB THUMBX TTL WHILE WEND ",built_in:"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 pc lr sp ip sl sb fp a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 v7 v8 f0 f1 f2 f3 f4 f5 f6 f7 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 cpsr_c cpsr_x cpsr_s cpsr_f cpsr_cx cpsr_cxs cpsr_xs cpsr_xsf cpsr_sf cpsr_cxsf spsr_c spsr_x spsr_s spsr_f spsr_cx spsr_cxs spsr_xs spsr_xsf spsr_sf spsr_cxsf s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 {PC} {VAR} {TRUE} {FALSE} {OPT} {CONFIG} {ENDIAN} {CODESIZE} {CPU} {FPU} {ARCHITECTURE} {PCSTOREOFFSET} {ARMASM_VERSION} {INTER} {ROPI} {RWPI} {SWST} {NOSWST} . @"},contains:[{className:"keyword",begin:"\\b(adc|(qd?|sh?|u[qh]?)?add(8|16)?|usada?8|(q|sh?|u[qh]?)?(as|sa)x|and|adrl?|sbc|rs[bc]|asr|b[lx]?|blx|bxj|cbn?z|tb[bh]|bic|bfc|bfi|[su]bfx|bkpt|cdp2?|clz|clrex|cmp|cmn|cpsi[ed]|cps|setend|dbg|dmb|dsb|eor|isb|it[te]{0,3}|lsl|lsr|ror|rrx|ldm(([id][ab])|f[ds])?|ldr((s|ex)?[bhd])?|movt?|mvn|mra|mar|mul|[us]mull|smul[bwt][bt]|smu[as]d|smmul|smmla|mla|umlaal|smlal?([wbt][bt]|d)|mls|smlsl?[ds]|smc|svc|sev|mia([bt]{2}|ph)?|mrr?c2?|mcrr2?|mrs|msr|orr|orn|pkh(tb|bt)|rbit|rev(16|sh)?|sel|[su]sat(16)?|nop|pop|push|rfe([id][ab])?|stm([id][ab])?|str(ex)?[bhd]?|(qd?)?sub|(sh?|q|u[qh]?)?sub(8|16)|[su]xt(a?h|a?b(16)?)|srs([id][ab])?|swpb?|swi|smi|tst|teq|wfe|wfi|yield)(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo)?[sptrx]?(?=\\s)"},e,s.QUOTE_STRING_MODE,{className:"string",begin:"'",end:"[^\\\\]'",relevance:0},{className:"title",begin:"\\|",end:"\\|",illegal:"\\n",relevance:0},{className:"number",variants:[{begin:"[#$=]?0x[0-9a-f]+"},{begin:"[#$=]?0b[01]+"},{begin:"[#$=]\\d+"},{begin:"\\b\\d+"}],relevance:0},{className:"symbol",variants:[{begin:"^[ \\t]*[a-z_\\.\\$][a-z0-9_\\.\\$]+:"},{begin:"^[a-z_\\.\\$][a-z0-9_\\.\\$]+"},{begin:"[=#]\\w+"}],relevance:0}]}}}()); +hljs.registerLanguage("d",function(){"use strict";return function(e){var a={$pattern:e.UNDERSCORE_IDENT_RE,keyword:"abstract alias align asm assert auto body break byte case cast catch class const continue debug default delete deprecated do else enum export extern final finally for foreach foreach_reverse|10 goto if immutable import in inout int interface invariant is lazy macro mixin module new nothrow out override package pragma private protected public pure ref return scope shared static struct super switch synchronized template this throw try typedef typeid typeof union unittest version void volatile while with __FILE__ __LINE__ __gshared|10 __thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__",built_in:"bool cdouble cent cfloat char creal dchar delegate double dstring float function idouble ifloat ireal long real short string ubyte ucent uint ulong ushort wchar wstring",literal:"false null true"},d="((0|[1-9][\\d_]*)|0[bB][01_]+|0[xX]([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*))",n="\\\\(['\"\\?\\\\abfnrtv]|u[\\dA-Fa-f]{4}|[0-7]{1,3}|x[\\dA-Fa-f]{2}|U[\\dA-Fa-f]{8})|&[a-zA-Z\\d]{2,};",t={className:"number",begin:"\\b"+d+"(L|u|U|Lu|LU|uL|UL)?",relevance:0},_={className:"number",begin:"\\b(((0[xX](([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)\\.([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)|\\.?([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*))[pP][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d))|((0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)(\\.\\d*|([eE][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)))|\\d+\\.(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)|\\.(0|[1-9][\\d_]*)([eE][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d))?))([fF]|L|i|[fF]i|Li)?|"+d+"(i|[fF]i|Li))",relevance:0},r={className:"string",begin:"'("+n+"|.)",end:"'",illegal:"."},i={className:"string",begin:'"',contains:[{begin:n,relevance:0}],end:'"[cwd]?'},s=e.COMMENT("\\/\\+","\\+\\/",{contains:["self"],relevance:10});return{name:"D",keywords:a,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s,{className:"string",begin:'x"[\\da-fA-F\\s\\n\\r]*"[cwd]?',relevance:10},i,{className:"string",begin:'[rq]"',end:'"[cwd]?',relevance:5},{className:"string",begin:"`",end:"`[cwd]?"},{className:"string",begin:'q"\\{',end:'\\}"'},_,t,r,{className:"meta",begin:"^#!",end:"$",relevance:5},{className:"meta",begin:"#(line)",end:"$",relevance:5},{className:"keyword",begin:"@[a-zA-Z_][a-zA-Z_\\d]*"}]}}}()); +hljs.registerLanguage("handlebars",function(){"use strict";function e(...e){return e.map(e=>(function(e){return e?"string"==typeof e?e:e.source:null})(e)).join("")}return function(n){const a={"builtin-name":"action bindattr collection component concat debugger each each-in get hash if in input link-to loc log lookup mut outlet partial query-params render template textarea unbound unless view with yield"},t=/\[.*?\]/,s=/[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+/,i=e("(",/'.*?'/,"|",/".*?"/,"|",t,"|",s,"|",/\.|\//,")+"),r=e("(",t,"|",s,")(?==)"),l={begin:i,lexemes:/[\w.\/]+/},c=n.inherit(l,{keywords:{literal:"true false undefined null"}}),o={begin:/\(/,end:/\)/},m={className:"attr",begin:r,relevance:0,starts:{begin:/=/,end:/=/,starts:{contains:[n.NUMBER_MODE,n.QUOTE_STRING_MODE,n.APOS_STRING_MODE,c,o]}}},d={contains:[n.NUMBER_MODE,n.QUOTE_STRING_MODE,n.APOS_STRING_MODE,{begin:/as\s+\|/,keywords:{keyword:"as"},end:/\|/,contains:[{begin:/\w+/}]},m,c,o],returnEnd:!0},g=n.inherit(l,{className:"name",keywords:a,starts:n.inherit(d,{end:/\)/})});o.contains=[g];const u=n.inherit(l,{keywords:a,className:"name",starts:n.inherit(d,{end:/}}/})}),b=n.inherit(l,{keywords:a,className:"name"}),h=n.inherit(l,{className:"name",keywords:a,starts:n.inherit(d,{end:/}}/})});return{name:"Handlebars",aliases:["hbs","html.hbs","html.handlebars","htmlbars"],case_insensitive:!0,subLanguage:"xml",contains:[{begin:/\\\{\{/,skip:!0},{begin:/\\\\(?=\{\{)/,skip:!0},n.COMMENT(/\{\{!--/,/--\}\}/),n.COMMENT(/\{\{!/,/\}\}/),{className:"template-tag",begin:/\{\{\{\{(?!\/)/,end:/\}\}\}\}/,contains:[u],starts:{end:/\{\{\{\{\//,returnEnd:!0,subLanguage:"xml"}},{className:"template-tag",begin:/\{\{\{\{\//,end:/\}\}\}\}/,contains:[b]},{className:"template-tag",begin:/\{\{#/,end:/\}\}/,contains:[u]},{className:"template-tag",begin:/\{\{(?=else\}\})/,end:/\}\}/,keywords:"else"},{className:"template-tag",begin:/\{\{\//,end:/\}\}/,contains:[b]},{className:"template-variable",begin:/\{\{\{/,end:/\}\}\}/,contains:[h]},{className:"template-variable",begin:/\{\{/,end:/\}\}/,contains:[h]}]}}}()); +hljs.registerLanguage("haskell",function(){"use strict";return function(e){var n={variants:[e.COMMENT("--","$"),e.COMMENT("{-","-}",{contains:["self"]})]},i={className:"meta",begin:"{-#",end:"#-}"},a={className:"meta",begin:"^#",end:"$"},s={className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},l={begin:"\\(",end:"\\)",illegal:'"',contains:[i,a,{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},e.inherit(e.TITLE_MODE,{begin:"[_a-z][\\w']*"}),n]};return{name:"Haskell",aliases:["hs"],keywords:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",contains:[{beginKeywords:"module",end:"where",keywords:"module where",contains:[l,n],illegal:"\\W\\.|;"},{begin:"\\bimport\\b",end:"$",keywords:"import qualified as hiding",contains:[l,n],illegal:"\\W\\.|;"},{className:"class",begin:"^(\\s*)?(class|instance)\\b",end:"where",keywords:"class family instance where",contains:[s,l,n]},{className:"class",begin:"\\b(data|(new)?type)\\b",end:"$",keywords:"data family type newtype deriving",contains:[i,s,l,{begin:"{",end:"}",contains:l.contains},n]},{beginKeywords:"default",end:"$",contains:[s,l,n]},{beginKeywords:"infix infixl infixr",end:"$",contains:[e.C_NUMBER_MODE,n]},{begin:"\\bforeign\\b",end:"$",keywords:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",contains:[s,e.QUOTE_STRING_MODE,n]},{className:"meta",begin:"#!\\/usr\\/bin\\/env runhaskell",end:"$"},i,a,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,s,e.inherit(e.TITLE_MODE,{begin:"^[_a-z][\\w']*"}),n,{begin:"->|<-"}]}}}()); +hljs.registerLanguage("julia",function(){"use strict";return function(e){var r="[A-Za-z_\\u00A1-\\uFFFF][A-Za-z_0-9\\u00A1-\\uFFFF]*",t={$pattern:r,keyword:"in isa where baremodule begin break catch ccall const continue do else elseif end export false finally for function global if import importall let local macro module quote return true try using while type immutable abstract bitstype typealias ",literal:"true false ARGS C_NULL DevNull ENDIAN_BOM ENV I Inf Inf16 Inf32 Inf64 InsertionSort JULIA_HOME LOAD_PATH MergeSort NaN NaN16 NaN32 NaN64 PROGRAM_FILE QuickSort RoundDown RoundFromZero RoundNearest RoundNearestTiesAway RoundNearestTiesUp RoundToZero RoundUp STDERR STDIN STDOUT VERSION catalan e|0 eu|0 eulergamma golden im nothing pi γ π φ ",built_in:"ANY AbstractArray AbstractChannel AbstractFloat AbstractMatrix AbstractRNG AbstractSerializer AbstractSet AbstractSparseArray AbstractSparseMatrix AbstractSparseVector AbstractString AbstractUnitRange AbstractVecOrMat AbstractVector Any ArgumentError Array AssertionError Associative Base64DecodePipe Base64EncodePipe Bidiagonal BigFloat BigInt BitArray BitMatrix BitVector Bool BoundsError BufferStream CachingPool CapturedException CartesianIndex CartesianRange Cchar Cdouble Cfloat Channel Char Cint Cintmax_t Clong Clonglong ClusterManager Cmd CodeInfo Colon Complex Complex128 Complex32 Complex64 CompositeException Condition ConjArray ConjMatrix ConjVector Cptrdiff_t Cshort Csize_t Cssize_t Cstring Cuchar Cuint Cuintmax_t Culong Culonglong Cushort Cwchar_t Cwstring DataType Date DateFormat DateTime DenseArray DenseMatrix DenseVecOrMat DenseVector Diagonal Dict DimensionMismatch Dims DirectIndexString Display DivideError DomainError EOFError EachLine Enum Enumerate ErrorException Exception ExponentialBackOff Expr Factorization FileMonitor Float16 Float32 Float64 Function Future GlobalRef GotoNode HTML Hermitian IO IOBuffer IOContext IOStream IPAddr IPv4 IPv6 IndexCartesian IndexLinear IndexStyle InexactError InitError Int Int128 Int16 Int32 Int64 Int8 IntSet Integer InterruptException InvalidStateException Irrational KeyError LabelNode LinSpace LineNumberNode LoadError LowerTriangular MIME Matrix MersenneTwister Method MethodError MethodTable Module NTuple NewvarNode NullException Nullable Number ObjectIdDict OrdinalRange OutOfMemoryError OverflowError Pair ParseError PartialQuickSort PermutedDimsArray Pipe PollingFileWatcher ProcessExitedException Ptr QuoteNode RandomDevice Range RangeIndex Rational RawFD ReadOnlyMemoryError Real ReentrantLock Ref Regex RegexMatch RemoteChannel RemoteException RevString RoundingMode RowVector SSAValue SegmentationFault SerializationState Set SharedArray SharedMatrix SharedVector Signed SimpleVector Slot SlotNumber SparseMatrixCSC SparseVector StackFrame StackOverflowError StackTrace StepRange StepRangeLen StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubString SymTridiagonal Symbol Symmetric SystemError TCPSocket Task Text TextDisplay Timer Tridiagonal Tuple Type TypeError TypeMapEntry TypeMapLevel TypeName TypeVar TypedSlot UDPSocket UInt UInt128 UInt16 UInt32 UInt64 UInt8 UndefRefError UndefVarError UnicodeError UniformScaling Union UnionAll UnitRange Unsigned UpperTriangular Val Vararg VecElement VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef WorkerConfig WorkerPool "},a={keywords:t,illegal:/<\//},n={className:"subst",begin:/\$\(/,end:/\)/,keywords:t},o={className:"variable",begin:"\\$"+r},i={className:"string",contains:[e.BACKSLASH_ESCAPE,n,o],variants:[{begin:/\w*"""/,end:/"""\w*/,relevance:10},{begin:/\w*"/,end:/"\w*/}]},l={className:"string",contains:[e.BACKSLASH_ESCAPE,n,o],begin:"`",end:"`"},s={className:"meta",begin:"@"+r};return a.name="Julia",a.contains=[{className:"number",begin:/(\b0x[\d_]*(\.[\d_]*)?|0x\.\d[\d_]*)p[-+]?\d+|\b0[box][a-fA-F0-9][a-fA-F0-9_]*|(\b\d[\d_]*(\.[\d_]*)?|\.\d[\d_]*)([eEfF][-+]?\d+)?/,relevance:0},{className:"string",begin:/'(.|\\[xXuU][a-zA-Z0-9]+)'/},i,l,s,{className:"comment",variants:[{begin:"#=",end:"=#",relevance:10},{begin:"#",end:"$"}]},e.HASH_COMMENT_MODE,{className:"keyword",begin:"\\b(((abstract|primitive)\\s+)type|(mutable\\s+)?struct)\\b"},{begin:/<:/}],n.contains=a.contains,a}}()); +hljs.registerLanguage("nim",function(){"use strict";return function(e){return{name:"Nim",aliases:["nim"],keywords:{keyword:"addr and as asm bind block break case cast const continue converter discard distinct div do elif else end enum except export finally for from func generic if import in include interface is isnot iterator let macro method mixin mod nil not notin object of or out proc ptr raise ref return shl shr static template try tuple type using var when while with without xor yield",literal:"shared guarded stdin stdout stderr result true false",built_in:"int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float float32 float64 bool char string cstring pointer expr stmt void auto any range array openarray varargs seq set clong culong cchar cschar cshort cint csize clonglong cfloat cdouble clongdouble cuchar cushort cuint culonglong cstringarray semistatic"},contains:[{className:"meta",begin:/{\./,end:/\.}/,relevance:10},{className:"string",begin:/[a-zA-Z]\w*"/,end:/"/,contains:[{begin:/""/}]},{className:"string",begin:/([a-zA-Z]\w*)?"""/,end:/"""/},e.QUOTE_STRING_MODE,{className:"type",begin:/\b[A-Z]\w+\b/,relevance:0},{className:"number",relevance:0,variants:[{begin:/\b(0[xX][0-9a-fA-F][_0-9a-fA-F]*)('?[iIuU](8|16|32|64))?/},{begin:/\b(0o[0-7][_0-7]*)('?[iIuUfF](8|16|32|64))?/},{begin:/\b(0(b|B)[01][_01]*)('?[iIuUfF](8|16|32|64))?/},{begin:/\b(\d[_\d]*)('?[iIuUfF](8|16|32|64))?/}]},e.HASH_COMMENT_MODE]}}}()); +hljs.registerLanguage("nix",function(){"use strict";return function(e){var n={keyword:"rec with let in inherit assert if else then",literal:"true false or and null",built_in:"import abort baseNameOf dirOf isNull builtins map removeAttrs throw toString derivation"},i={className:"subst",begin:/\$\{/,end:/}/,keywords:n},t={className:"string",contains:[i],variants:[{begin:"''",end:"''"},{begin:'"',end:'"'}]},s=[e.NUMBER_MODE,e.HASH_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t,{begin:/[a-zA-Z0-9-_]+(\s*=)/,returnBegin:!0,relevance:0,contains:[{className:"attr",begin:/\S+/}]}];return i.contains=s,{name:"Nix",aliases:["nixos"],keywords:n,contains:s}}}()); +hljs.registerLanguage("r",function(){"use strict";return function(e){var n="([a-zA-Z]|\\.[a-zA-Z.])[a-zA-Z0-9._]*";return{name:"R",contains:[e.HASH_COMMENT_MODE,{begin:n,keywords:{$pattern:n,keyword:"function if in break next repeat else for return switch while try tryCatch stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...",literal:"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10"},relevance:0},{className:"number",begin:"0[xX][0-9a-fA-F]+[Li]?\\b",relevance:0},{className:"number",begin:"\\d+(?:[eE][+\\-]?\\d*)?L\\b",relevance:0},{className:"number",begin:"\\d+\\.(?!\\d)(?:i\\b)?",relevance:0},{className:"number",begin:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b",relevance:0},{className:"number",begin:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b",relevance:0},{begin:"`",end:"`",relevance:0},{className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:'"',end:'"'},{begin:"'",end:"'"}]}]}}}()); +hljs.registerLanguage("scala",function(){"use strict";return function(e){var n={className:"subst",variants:[{begin:"\\$[A-Za-z0-9_]+"},{begin:"\\${",end:"}"}]},a={className:"string",variants:[{begin:'"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:'"""',end:'"""',relevance:10},{begin:'[a-z]+"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE,n]},{className:"string",begin:'[a-z]+"""',end:'"""',contains:[n],relevance:10}]},s={className:"type",begin:"\\b[A-Z][A-Za-z0-9_]*",relevance:0},t={className:"title",begin:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,relevance:0},i={className:"class",beginKeywords:"class object trait type",end:/[:={\[\n;]/,excludeEnd:!0,contains:[{beginKeywords:"extends with",relevance:10},{begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[s]},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[s]},t]},l={className:"function",beginKeywords:"def",end:/[:={\[(\n;]/,excludeEnd:!0,contains:[t]};return{name:"Scala",keywords:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,{className:"symbol",begin:"'\\w[\\w\\d_]*(?!')"},s,l,i,e.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"}]}}}()); +hljs.registerLanguage("x86asm",function(){"use strict";return function(s){return{name:"Intel x86 Assembly",case_insensitive:!0,keywords:{$pattern:"[.%]?"+s.IDENT_RE,keyword:"lock rep repe repz repne repnz xaquire xrelease bnd nobnd aaa aad aam aas adc add and arpl bb0_reset bb1_reset bound bsf bsr bswap bt btc btr bts call cbw cdq cdqe clc cld cli clts cmc cmp cmpsb cmpsd cmpsq cmpsw cmpxchg cmpxchg486 cmpxchg8b cmpxchg16b cpuid cpu_read cpu_write cqo cwd cwde daa das dec div dmint emms enter equ f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcmovb fcmovbe fcmove fcmovnb fcmovnbe fcmovne fcmovnu fcmovu fcom fcomi fcomip fcomp fcompp fcos fdecstp fdisi fdiv fdivp fdivr fdivrp femms feni ffree ffreep fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit fist fistp fisttp fisub fisubr fld fld1 fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex fndisi fneni fninit fnop fnsave fnstcw fnstenv fnstsw fpatan fprem fprem1 fptan frndint frstor fsave fscale fsetpm fsin fsincos fsqrt fst fstcw fstenv fstp fstsw fsub fsubp fsubr fsubrp ftst fucom fucomi fucomip fucomp fucompp fxam fxch fxtract fyl2x fyl2xp1 hlt ibts icebp idiv imul in inc incbin insb insd insw int int01 int1 int03 int3 into invd invpcid invlpg invlpga iret iretd iretq iretw jcxz jecxz jrcxz jmp jmpe lahf lar lds lea leave les lfence lfs lgdt lgs lidt lldt lmsw loadall loadall286 lodsb lodsd lodsq lodsw loop loope loopne loopnz loopz lsl lss ltr mfence monitor mov movd movq movsb movsd movsq movsw movsx movsxd movzx mul mwait neg nop not or out outsb outsd outsw packssdw packsswb packuswb paddb paddd paddsb paddsiw paddsw paddusb paddusw paddw pand pandn pause paveb pavgusb pcmpeqb pcmpeqd pcmpeqw pcmpgtb pcmpgtd pcmpgtw pdistib pf2id pfacc pfadd pfcmpeq pfcmpge pfcmpgt pfmax pfmin pfmul pfrcp pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd pmachriw pmaddwd pmagw pmulhriw pmulhrwa pmulhrwc pmulhw pmullw pmvgezb pmvlzb pmvnzb pmvzb pop popa popad popaw popf popfd popfq popfw por prefetch prefetchw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb psubd psubsb psubsiw psubsw psubusb psubusw psubw punpckhbw punpckhdq punpckhwd punpcklbw punpckldq punpcklwd push pusha pushad pushaw pushf pushfd pushfq pushfw pxor rcl rcr rdshr rdmsr rdpmc rdtsc rdtscp ret retf retn rol ror rdm rsdc rsldt rsm rsts sahf sal salc sar sbb scasb scasd scasq scasw sfence sgdt shl shld shr shrd sidt sldt skinit smi smint smintold smsw stc std sti stosb stosd stosq stosw str sub svdc svldt svts swapgs syscall sysenter sysexit sysret test ud0 ud1 ud2b ud2 ud2a umov verr verw fwait wbinvd wrshr wrmsr xadd xbts xchg xlatb xlat xor cmove cmovz cmovne cmovnz cmova cmovnbe cmovae cmovnb cmovb cmovnae cmovbe cmovna cmovg cmovnle cmovge cmovnl cmovl cmovnge cmovle cmovng cmovc cmovnc cmovo cmovno cmovs cmovns cmovp cmovpe cmovnp cmovpo je jz jne jnz ja jnbe jae jnb jb jnae jbe jna jg jnle jge jnl jl jnge jle jng jc jnc jo jno js jns jpo jnp jpe jp sete setz setne setnz seta setnbe setae setnb setnc setb setnae setcset setbe setna setg setnle setge setnl setl setnge setle setng sets setns seto setno setpe setp setpo setnp addps addss andnps andps cmpeqps cmpeqss cmpleps cmpless cmpltps cmpltss cmpneqps cmpneqss cmpnleps cmpnless cmpnltps cmpnltss cmpordps cmpordss cmpunordps cmpunordss cmpps cmpss comiss cvtpi2ps cvtps2pi cvtsi2ss cvtss2si cvttps2pi cvttss2si divps divss ldmxcsr maxps maxss minps minss movaps movhps movlhps movlps movhlps movmskps movntps movss movups mulps mulss orps rcpps rcpss rsqrtps rsqrtss shufps sqrtps sqrtss stmxcsr subps subss ucomiss unpckhps unpcklps xorps fxrstor fxrstor64 fxsave fxsave64 xgetbv xsetbv xsave xsave64 xsaveopt xsaveopt64 xrstor xrstor64 prefetchnta prefetcht0 prefetcht1 prefetcht2 maskmovq movntq pavgb pavgw pextrw pinsrw pmaxsw pmaxub pminsw pminub pmovmskb pmulhuw psadbw pshufw pf2iw pfnacc pfpnacc pi2fw pswapd maskmovdqu clflush movntdq movnti movntpd movdqa movdqu movdq2q movq2dq paddq pmuludq pshufd pshufhw pshuflw pslldq psrldq psubq punpckhqdq punpcklqdq addpd addsd andnpd andpd cmpeqpd cmpeqsd cmplepd cmplesd cmpltpd cmpltsd cmpneqpd cmpneqsd cmpnlepd cmpnlesd cmpnltpd cmpnltsd cmpordpd cmpordsd cmpunordpd cmpunordsd cmppd comisd cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi cvtpd2ps cvtpi2pd cvtps2dq cvtps2pd cvtsd2si cvtsd2ss cvtsi2sd cvtss2sd cvttpd2pi cvttpd2dq cvttps2dq cvttsd2si divpd divsd maxpd maxsd minpd minsd movapd movhpd movlpd movmskpd movupd mulpd mulsd orpd shufpd sqrtpd sqrtsd subpd subsd ucomisd unpckhpd unpcklpd xorpd addsubpd addsubps haddpd haddps hsubpd hsubps lddqu movddup movshdup movsldup clgi stgi vmcall vmclear vmfunc vmlaunch vmload vmmcall vmptrld vmptrst vmread vmresume vmrun vmsave vmwrite vmxoff vmxon invept invvpid pabsb pabsw pabsd palignr phaddw phaddd phaddsw phsubw phsubd phsubsw pmaddubsw pmulhrsw pshufb psignb psignw psignd extrq insertq movntsd movntss lzcnt blendpd blendps blendvpd blendvps dppd dpps extractps insertps movntdqa mpsadbw packusdw pblendvb pblendw pcmpeqq pextrb pextrd pextrq phminposuw pinsrb pinsrd pinsrq pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq pmuldq pmulld ptest roundpd roundps roundsd roundss crc32 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq popcnt getsec pfrcpv pfrsqrtv movbe aesenc aesenclast aesdec aesdeclast aesimc aeskeygenassist vaesenc vaesenclast vaesdec vaesdeclast vaesimc vaeskeygenassist vaddpd vaddps vaddsd vaddss vaddsubpd vaddsubps vandpd vandps vandnpd vandnps vblendpd vblendps vblendvpd vblendvps vbroadcastss vbroadcastsd vbroadcastf128 vcmpeq_ospd vcmpeqpd vcmplt_ospd vcmpltpd vcmple_ospd vcmplepd vcmpunord_qpd vcmpunordpd vcmpneq_uqpd vcmpneqpd vcmpnlt_uspd vcmpnltpd vcmpnle_uspd vcmpnlepd vcmpord_qpd vcmpordpd vcmpeq_uqpd vcmpnge_uspd vcmpngepd vcmpngt_uspd vcmpngtpd vcmpfalse_oqpd vcmpfalsepd vcmpneq_oqpd vcmpge_ospd vcmpgepd vcmpgt_ospd vcmpgtpd vcmptrue_uqpd vcmptruepd vcmplt_oqpd vcmple_oqpd vcmpunord_spd vcmpneq_uspd vcmpnlt_uqpd vcmpnle_uqpd vcmpord_spd vcmpeq_uspd vcmpnge_uqpd vcmpngt_uqpd vcmpfalse_ospd vcmpneq_ospd vcmpge_oqpd vcmpgt_oqpd vcmptrue_uspd vcmppd vcmpeq_osps vcmpeqps vcmplt_osps vcmpltps vcmple_osps vcmpleps vcmpunord_qps vcmpunordps vcmpneq_uqps vcmpneqps vcmpnlt_usps vcmpnltps vcmpnle_usps vcmpnleps vcmpord_qps vcmpordps vcmpeq_uqps vcmpnge_usps vcmpngeps vcmpngt_usps vcmpngtps vcmpfalse_oqps vcmpfalseps vcmpneq_oqps vcmpge_osps vcmpgeps vcmpgt_osps vcmpgtps vcmptrue_uqps vcmptrueps vcmplt_oqps vcmple_oqps vcmpunord_sps vcmpneq_usps vcmpnlt_uqps vcmpnle_uqps vcmpord_sps vcmpeq_usps vcmpnge_uqps vcmpngt_uqps vcmpfalse_osps vcmpneq_osps vcmpge_oqps vcmpgt_oqps vcmptrue_usps vcmpps vcmpeq_ossd vcmpeqsd vcmplt_ossd vcmpltsd vcmple_ossd vcmplesd vcmpunord_qsd vcmpunordsd vcmpneq_uqsd vcmpneqsd vcmpnlt_ussd vcmpnltsd vcmpnle_ussd vcmpnlesd vcmpord_qsd vcmpordsd vcmpeq_uqsd vcmpnge_ussd vcmpngesd vcmpngt_ussd vcmpngtsd vcmpfalse_oqsd vcmpfalsesd vcmpneq_oqsd vcmpge_ossd vcmpgesd vcmpgt_ossd vcmpgtsd vcmptrue_uqsd vcmptruesd vcmplt_oqsd vcmple_oqsd vcmpunord_ssd vcmpneq_ussd vcmpnlt_uqsd vcmpnle_uqsd vcmpord_ssd vcmpeq_ussd vcmpnge_uqsd vcmpngt_uqsd vcmpfalse_ossd vcmpneq_ossd vcmpge_oqsd vcmpgt_oqsd vcmptrue_ussd vcmpsd vcmpeq_osss vcmpeqss vcmplt_osss vcmpltss vcmple_osss vcmpless vcmpunord_qss vcmpunordss vcmpneq_uqss vcmpneqss vcmpnlt_usss vcmpnltss vcmpnle_usss vcmpnless vcmpord_qss vcmpordss vcmpeq_uqss vcmpnge_usss vcmpngess vcmpngt_usss vcmpngtss vcmpfalse_oqss vcmpfalsess vcmpneq_oqss vcmpge_osss vcmpgess vcmpgt_osss vcmpgtss vcmptrue_uqss vcmptruess vcmplt_oqss vcmple_oqss vcmpunord_sss vcmpneq_usss vcmpnlt_uqss vcmpnle_uqss vcmpord_sss vcmpeq_usss vcmpnge_uqss vcmpngt_uqss vcmpfalse_osss vcmpneq_osss vcmpge_oqss vcmpgt_oqss vcmptrue_usss vcmpss vcomisd vcomiss vcvtdq2pd vcvtdq2ps vcvtpd2dq vcvtpd2ps vcvtps2dq vcvtps2pd vcvtsd2si vcvtsd2ss vcvtsi2sd vcvtsi2ss vcvtss2sd vcvtss2si vcvttpd2dq vcvttps2dq vcvttsd2si vcvttss2si vdivpd vdivps vdivsd vdivss vdppd vdpps vextractf128 vextractps vhaddpd vhaddps vhsubpd vhsubps vinsertf128 vinsertps vlddqu vldqqu vldmxcsr vmaskmovdqu vmaskmovps vmaskmovpd vmaxpd vmaxps vmaxsd vmaxss vminpd vminps vminsd vminss vmovapd vmovaps vmovd vmovq vmovddup vmovdqa vmovqqa vmovdqu vmovqqu vmovhlps vmovhpd vmovhps vmovlhps vmovlpd vmovlps vmovmskpd vmovmskps vmovntdq vmovntqq vmovntdqa vmovntpd vmovntps vmovsd vmovshdup vmovsldup vmovss vmovupd vmovups vmpsadbw vmulpd vmulps vmulsd vmulss vorpd vorps vpabsb vpabsw vpabsd vpacksswb vpackssdw vpackuswb vpackusdw vpaddb vpaddw vpaddd vpaddq vpaddsb vpaddsw vpaddusb vpaddusw vpalignr vpand vpandn vpavgb vpavgw vpblendvb vpblendw vpcmpestri vpcmpestrm vpcmpistri vpcmpistrm vpcmpeqb vpcmpeqw vpcmpeqd vpcmpeqq vpcmpgtb vpcmpgtw vpcmpgtd vpcmpgtq vpermilpd vpermilps vperm2f128 vpextrb vpextrw vpextrd vpextrq vphaddw vphaddd vphaddsw vphminposuw vphsubw vphsubd vphsubsw vpinsrb vpinsrw vpinsrd vpinsrq vpmaddwd vpmaddubsw vpmaxsb vpmaxsw vpmaxsd vpmaxub vpmaxuw vpmaxud vpminsb vpminsw vpminsd vpminub vpminuw vpminud vpmovmskb vpmovsxbw vpmovsxbd vpmovsxbq vpmovsxwd vpmovsxwq vpmovsxdq vpmovzxbw vpmovzxbd vpmovzxbq vpmovzxwd vpmovzxwq vpmovzxdq vpmulhuw vpmulhrsw vpmulhw vpmullw vpmulld vpmuludq vpmuldq vpor vpsadbw vpshufb vpshufd vpshufhw vpshuflw vpsignb vpsignw vpsignd vpslldq vpsrldq vpsllw vpslld vpsllq vpsraw vpsrad vpsrlw vpsrld vpsrlq vptest vpsubb vpsubw vpsubd vpsubq vpsubsb vpsubsw vpsubusb vpsubusw vpunpckhbw vpunpckhwd vpunpckhdq vpunpckhqdq vpunpcklbw vpunpcklwd vpunpckldq vpunpcklqdq vpxor vrcpps vrcpss vrsqrtps vrsqrtss vroundpd vroundps vroundsd vroundss vshufpd vshufps vsqrtpd vsqrtps vsqrtsd vsqrtss vstmxcsr vsubpd vsubps vsubsd vsubss vtestps vtestpd vucomisd vucomiss vunpckhpd vunpckhps vunpcklpd vunpcklps vxorpd vxorps vzeroall vzeroupper pclmullqlqdq pclmulhqlqdq pclmullqhqdq pclmulhqhqdq pclmulqdq vpclmullqlqdq vpclmulhqlqdq vpclmullqhqdq vpclmulhqhqdq vpclmulqdq vfmadd132ps vfmadd132pd vfmadd312ps vfmadd312pd vfmadd213ps vfmadd213pd vfmadd123ps vfmadd123pd vfmadd231ps vfmadd231pd vfmadd321ps vfmadd321pd vfmaddsub132ps vfmaddsub132pd vfmaddsub312ps vfmaddsub312pd vfmaddsub213ps vfmaddsub213pd vfmaddsub123ps vfmaddsub123pd vfmaddsub231ps vfmaddsub231pd vfmaddsub321ps vfmaddsub321pd vfmsub132ps vfmsub132pd vfmsub312ps vfmsub312pd vfmsub213ps vfmsub213pd vfmsub123ps vfmsub123pd vfmsub231ps vfmsub231pd vfmsub321ps vfmsub321pd vfmsubadd132ps vfmsubadd132pd vfmsubadd312ps vfmsubadd312pd vfmsubadd213ps vfmsubadd213pd vfmsubadd123ps vfmsubadd123pd vfmsubadd231ps vfmsubadd231pd vfmsubadd321ps vfmsubadd321pd vfnmadd132ps vfnmadd132pd vfnmadd312ps vfnmadd312pd vfnmadd213ps vfnmadd213pd vfnmadd123ps vfnmadd123pd vfnmadd231ps vfnmadd231pd vfnmadd321ps vfnmadd321pd vfnmsub132ps vfnmsub132pd vfnmsub312ps vfnmsub312pd vfnmsub213ps vfnmsub213pd vfnmsub123ps vfnmsub123pd vfnmsub231ps vfnmsub231pd vfnmsub321ps vfnmsub321pd vfmadd132ss vfmadd132sd vfmadd312ss vfmadd312sd vfmadd213ss vfmadd213sd vfmadd123ss vfmadd123sd vfmadd231ss vfmadd231sd vfmadd321ss vfmadd321sd vfmsub132ss vfmsub132sd vfmsub312ss vfmsub312sd vfmsub213ss vfmsub213sd vfmsub123ss vfmsub123sd vfmsub231ss vfmsub231sd vfmsub321ss vfmsub321sd vfnmadd132ss vfnmadd132sd vfnmadd312ss vfnmadd312sd vfnmadd213ss vfnmadd213sd vfnmadd123ss vfnmadd123sd vfnmadd231ss vfnmadd231sd vfnmadd321ss vfnmadd321sd vfnmsub132ss vfnmsub132sd vfnmsub312ss vfnmsub312sd vfnmsub213ss vfnmsub213sd vfnmsub123ss vfnmsub123sd vfnmsub231ss vfnmsub231sd vfnmsub321ss vfnmsub321sd rdfsbase rdgsbase rdrand wrfsbase wrgsbase vcvtph2ps vcvtps2ph adcx adox rdseed clac stac xstore xcryptecb xcryptcbc xcryptctr xcryptcfb xcryptofb montmul xsha1 xsha256 llwpcb slwpcb lwpval lwpins vfmaddpd vfmaddps vfmaddsd vfmaddss vfmaddsubpd vfmaddsubps vfmsubaddpd vfmsubaddps vfmsubpd vfmsubps vfmsubsd vfmsubss vfnmaddpd vfnmaddps vfnmaddsd vfnmaddss vfnmsubpd vfnmsubps vfnmsubsd vfnmsubss vfrczpd vfrczps vfrczsd vfrczss vpcmov vpcomb vpcomd vpcomq vpcomub vpcomud vpcomuq vpcomuw vpcomw vphaddbd vphaddbq vphaddbw vphadddq vphaddubd vphaddubq vphaddubw vphaddudq vphadduwd vphadduwq vphaddwd vphaddwq vphsubbw vphsubdq vphsubwd vpmacsdd vpmacsdqh vpmacsdql vpmacssdd vpmacssdqh vpmacssdql vpmacsswd vpmacssww vpmacswd vpmacsww vpmadcsswd vpmadcswd vpperm vprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vbroadcasti128 vpblendd vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vpermd vpermpd vpermps vpermq vperm2i128 vextracti128 vinserti128 vpmaskmovd vpmaskmovq vpsllvd vpsllvq vpsravd vpsrlvd vpsrlvq vgatherdpd vgatherqpd vgatherdps vgatherqps vpgatherdd vpgatherqd vpgatherdq vpgatherqq xabort xbegin xend xtest andn bextr blci blcic blsi blsic blcfill blsfill blcmsk blsmsk blsr blcs bzhi mulx pdep pext rorx sarx shlx shrx tzcnt tzmsk t1mskc valignd valignq vblendmpd vblendmps vbroadcastf32x4 vbroadcastf64x4 vbroadcasti32x4 vbroadcasti64x4 vcompresspd vcompressps vcvtpd2udq vcvtps2udq vcvtsd2usi vcvtss2usi vcvttpd2udq vcvttps2udq vcvttsd2usi vcvttss2usi vcvtudq2pd vcvtudq2ps vcvtusi2sd vcvtusi2ss vexpandpd vexpandps vextractf32x4 vextractf64x4 vextracti32x4 vextracti64x4 vfixupimmpd vfixupimmps vfixupimmsd vfixupimmss vgetexppd vgetexpps vgetexpsd vgetexpss vgetmantpd vgetmantps vgetmantsd vgetmantss vinsertf32x4 vinsertf64x4 vinserti32x4 vinserti64x4 vmovdqa32 vmovdqa64 vmovdqu32 vmovdqu64 vpabsq vpandd vpandnd vpandnq vpandq vpblendmd vpblendmq vpcmpltd vpcmpled vpcmpneqd vpcmpnltd vpcmpnled vpcmpd vpcmpltq vpcmpleq vpcmpneqq vpcmpnltq vpcmpnleq vpcmpq vpcmpequd vpcmpltud vpcmpleud vpcmpnequd vpcmpnltud vpcmpnleud vpcmpud vpcmpequq vpcmpltuq vpcmpleuq vpcmpnequq vpcmpnltuq vpcmpnleuq vpcmpuq vpcompressd vpcompressq vpermi2d vpermi2pd vpermi2ps vpermi2q vpermt2d vpermt2pd vpermt2ps vpermt2q vpexpandd vpexpandq vpmaxsq vpmaxuq vpminsq vpminuq vpmovdb vpmovdw vpmovqb vpmovqd vpmovqw vpmovsdb vpmovsdw vpmovsqb vpmovsqd vpmovsqw vpmovusdb vpmovusdw vpmovusqb vpmovusqd vpmovusqw vpord vporq vprold vprolq vprolvd vprolvq vprord vprorq vprorvd vprorvq vpscatterdd vpscatterdq vpscatterqd vpscatterqq vpsraq vpsravq vpternlogd vpternlogq vptestmd vptestmq vptestnmd vptestnmq vpxord vpxorq vrcp14pd vrcp14ps vrcp14sd vrcp14ss vrndscalepd vrndscaleps vrndscalesd vrndscaless vrsqrt14pd vrsqrt14ps vrsqrt14sd vrsqrt14ss vscalefpd vscalefps vscalefsd vscalefss vscatterdpd vscatterdps vscatterqpd vscatterqps vshuff32x4 vshuff64x2 vshufi32x4 vshufi64x2 kandnw kandw kmovw knotw kortestw korw kshiftlw kshiftrw kunpckbw kxnorw kxorw vpbroadcastmb2q vpbroadcastmw2d vpconflictd vpconflictq vplzcntd vplzcntq vexp2pd vexp2ps vrcp28pd vrcp28ps vrcp28sd vrcp28ss vrsqrt28pd vrsqrt28ps vrsqrt28sd vrsqrt28ss vgatherpf0dpd vgatherpf0dps vgatherpf0qpd vgatherpf0qps vgatherpf1dpd vgatherpf1dps vgatherpf1qpd vgatherpf1qps vscatterpf0dpd vscatterpf0dps vscatterpf0qpd vscatterpf0qps vscatterpf1dpd vscatterpf1dps vscatterpf1qpd vscatterpf1qps prefetchwt1 bndmk bndcl bndcu bndcn bndmov bndldx bndstx sha1rnds4 sha1nexte sha1msg1 sha1msg2 sha256rnds2 sha256msg1 sha256msg2 hint_nop0 hint_nop1 hint_nop2 hint_nop3 hint_nop4 hint_nop5 hint_nop6 hint_nop7 hint_nop8 hint_nop9 hint_nop10 hint_nop11 hint_nop12 hint_nop13 hint_nop14 hint_nop15 hint_nop16 hint_nop17 hint_nop18 hint_nop19 hint_nop20 hint_nop21 hint_nop22 hint_nop23 hint_nop24 hint_nop25 hint_nop26 hint_nop27 hint_nop28 hint_nop29 hint_nop30 hint_nop31 hint_nop32 hint_nop33 hint_nop34 hint_nop35 hint_nop36 hint_nop37 hint_nop38 hint_nop39 hint_nop40 hint_nop41 hint_nop42 hint_nop43 hint_nop44 hint_nop45 hint_nop46 hint_nop47 hint_nop48 hint_nop49 hint_nop50 hint_nop51 hint_nop52 hint_nop53 hint_nop54 hint_nop55 hint_nop56 hint_nop57 hint_nop58 hint_nop59 hint_nop60 hint_nop61 hint_nop62 hint_nop63",built_in:"ip eip rip al ah bl bh cl ch dl dh sil dil bpl spl r8b r9b r10b r11b r12b r13b r14b r15b ax bx cx dx si di bp sp r8w r9w r10w r11w r12w r13w r14w r15w eax ebx ecx edx esi edi ebp esp eip r8d r9d r10d r11d r12d r13d r14d r15d rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 cs ds es fs gs ss st st0 st1 st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7 xmm8 xmm9 xmm10 xmm11 xmm12 xmm13 xmm14 xmm15 xmm16 xmm17 xmm18 xmm19 xmm20 xmm21 xmm22 xmm23 xmm24 xmm25 xmm26 xmm27 xmm28 xmm29 xmm30 xmm31 ymm0 ymm1 ymm2 ymm3 ymm4 ymm5 ymm6 ymm7 ymm8 ymm9 ymm10 ymm11 ymm12 ymm13 ymm14 ymm15 ymm16 ymm17 ymm18 ymm19 ymm20 ymm21 ymm22 ymm23 ymm24 ymm25 ymm26 ymm27 ymm28 ymm29 ymm30 ymm31 zmm0 zmm1 zmm2 zmm3 zmm4 zmm5 zmm6 zmm7 zmm8 zmm9 zmm10 zmm11 zmm12 zmm13 zmm14 zmm15 zmm16 zmm17 zmm18 zmm19 zmm20 zmm21 zmm22 zmm23 zmm24 zmm25 zmm26 zmm27 zmm28 zmm29 zmm30 zmm31 k0 k1 k2 k3 k4 k5 k6 k7 bnd0 bnd1 bnd2 bnd3 cr0 cr1 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr8 tr3 tr4 tr5 tr6 tr7 r0 r1 r2 r3 r4 r5 r6 r7 r0b r1b r2b r3b r4b r5b r6b r7b r0w r1w r2w r3w r4w r5w r6w r7w r0d r1d r2d r3d r4d r5d r6d r7d r0h r1h r2h r3h r0l r1l r2l r3l r4l r5l r6l r7l r8l r9l r10l r11l r12l r13l r14l r15l db dw dd dq dt ddq do dy dz resb resw resd resq rest resdq reso resy resz incbin equ times byte word dword qword nosplit rel abs seg wrt strict near far a32 ptr",meta:"%define %xdefine %+ %undef %defstr %deftok %assign %strcat %strlen %substr %rotate %elif %else %endif %if %ifmacro %ifctx %ifidn %ifidni %ifid %ifnum %ifstr %iftoken %ifempty %ifenv %error %warning %fatal %rep %endrep %include %push %pop %repl %pathsearch %depend %use %arg %stacksize %local %line %comment %endcomment .nolist __FILE__ __LINE__ __SECT__ __BITS__ __OUTPUT_FORMAT__ __DATE__ __TIME__ __DATE_NUM__ __TIME_NUM__ __UTC_DATE__ __UTC_TIME__ __UTC_DATE_NUM__ __UTC_TIME_NUM__ __PASS__ struc endstruc istruc at iend align alignb sectalign daz nodaz up down zero default option assume public bits use16 use32 use64 default section segment absolute extern global common cpu float __utf16__ __utf16le__ __utf16be__ __utf32__ __utf32le__ __utf32be__ __float8__ __float16__ __float32__ __float64__ __float80m__ __float80e__ __float128l__ __float128h__ __Infinity__ __QNaN__ __SNaN__ Inf NaN QNaN SNaN float8 float16 float32 float64 float80m float80e float128l float128h __FLOAT_DAZ__ __FLOAT_ROUND__ __FLOAT__"},contains:[s.COMMENT(";","$",{relevance:0}),{className:"number",variants:[{begin:"\\b(?:([0-9][0-9_]*)?\\.[0-9_]*(?:[eE][+-]?[0-9_]+)?|(0[Xx])?[0-9][0-9_]*\\.?[0-9_]*(?:[pP](?:[+-]?[0-9_]+)?)?)\\b",relevance:0},{begin:"\\$[0-9][0-9A-Fa-f]*",relevance:0},{begin:"\\b(?:[0-9A-Fa-f][0-9A-Fa-f_]*[Hh]|[0-9][0-9_]*[DdTt]?|[0-7][0-7_]*[QqOo]|[0-1][0-1_]*[BbYy])\\b"},{begin:"\\b(?:0[Xx][0-9A-Fa-f_]+|0[DdTt][0-9_]+|0[QqOo][0-7_]+|0[BbYy][0-1_]+)\\b"}]},s.QUOTE_STRING_MODE,{className:"string",variants:[{begin:"'",end:"[^\\\\]'"},{begin:"`",end:"[^\\\\]`"}],relevance:0},{className:"symbol",variants:[{begin:"^\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\s+label)"},{begin:"^\\s*%%[A-Za-z0-9_$#@~.?]*:"}],relevance:0},{className:"subst",begin:"%[0-9]+",relevance:0},{className:"subst",begin:"%!S+",relevance:0},{className:"meta",begin:/^\s*\.[\w_-]+/}]}}}()); \ No newline at end of file diff --git a/typ/mdbook/assets/mark-09e88c2c.min.js b/typ/mdbook/assets/mark-09e88c2c.min.js new file mode 100644 index 00000000..16362318 --- /dev/null +++ b/typ/mdbook/assets/mark-09e88c2c.min.js @@ -0,0 +1,7 @@ +/*!*************************************************** +* mark.js v8.11.1 +* https://markjs.io/ +* Copyright (c) 2014–2018, Julian Kühnel +* Released under the MIT license https://git.io/vwTVl +*****************************************************/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Mark=t()}(this,function(){"use strict";var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},n=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5e3;t(this,e),this.ctx=n,this.iframes=r,this.exclude=i,this.iframesTimeout=o}return n(e,[{key:"getContexts",value:function(){var e=[];return(void 0!==this.ctx&&this.ctx?NodeList.prototype.isPrototypeOf(this.ctx)?Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?this.ctx:"string"==typeof this.ctx?Array.prototype.slice.call(document.querySelectorAll(this.ctx)):[this.ctx]:[]).forEach(function(t){var n=e.filter(function(e){return e.contains(t)}).length>0;-1!==e.indexOf(t)||n||e.push(t)}),e}},{key:"getIframeContents",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},r=void 0;try{var i=e.contentWindow;if(r=i.document,!i||!r)throw new Error("iframe inaccessible")}catch(e){n()}r&&t(r)}},{key:"isIframeBlank",value:function(e){var t="about:blank",n=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&n!==t&&n}},{key:"observeIframeLoad",value:function(e,t,n){var r=this,i=!1,o=null,a=function a(){if(!i){i=!0,clearTimeout(o);try{r.isIframeBlank(e)||(e.removeEventListener("load",a),r.getIframeContents(e,t,n))}catch(e){n()}}};e.addEventListener("load",a),o=setTimeout(a,this.iframesTimeout)}},{key:"onIframeReady",value:function(e,t,n){try{"complete"===e.contentWindow.document.readyState?this.isIframeBlank(e)?this.observeIframeLoad(e,t,n):this.getIframeContents(e,t,n):this.observeIframeLoad(e,t,n)}catch(e){n()}}},{key:"waitForIframes",value:function(e,t){var n=this,r=0;this.forEachIframe(e,function(){return!0},function(e){r++,n.waitForIframes(e.querySelector("html"),function(){--r||t()})},function(e){e||t()})}},{key:"forEachIframe",value:function(t,n,r){var i=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},a=t.querySelectorAll("iframe"),s=a.length,c=0;a=Array.prototype.slice.call(a);var u=function(){--s<=0&&o(c)};s||u(),a.forEach(function(t){e.matches(t,i.exclude)?u():i.onIframeReady(t,function(e){n(t)&&(c++,r(e)),u()},u)})}},{key:"createIterator",value:function(e,t,n){return document.createNodeIterator(e,t,n,!1)}},{key:"createInstanceOnIframe",value:function(t){return new e(t.querySelector("html"),this.iframes)}},{key:"compareNodeIframe",value:function(e,t,n){if(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_PRECEDING){if(null===t)return!0;if(t.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)return!0}return!1}},{key:"getIteratorNode",value:function(e){var t=e.previousNode();return{prevNode:t,node:null===t?e.nextNode():e.nextNode()&&e.nextNode()}}},{key:"checkIframeFilter",value:function(e,t,n,r){var i=!1,o=!1;return r.forEach(function(e,t){e.val===n&&(i=t,o=e.handled)}),this.compareNodeIframe(e,t,n)?(!1!==i||o?!1===i||o||(r[i].handled=!0):r.push({val:n,handled:!0}),!0):(!1===i&&r.push({val:n,handled:!1}),!1)}},{key:"handleOpenIframes",value:function(e,t,n,r){var i=this;e.forEach(function(e){e.handled||i.getIframeContents(e.val,function(e){i.createInstanceOnIframe(e).forEachNode(t,n,r)})})}},{key:"iterateThroughNodes",value:function(e,t,n,r,i){for(var o,a=this,s=this.createIterator(t,e,r),c=[],u=[],l=void 0,h=void 0;void 0,o=a.getIteratorNode(s),h=o.prevNode,l=o.node;)this.iframes&&this.forEachIframe(t,function(e){return a.checkIframeFilter(l,h,e,c)},function(t){a.createInstanceOnIframe(t).forEachNode(e,function(e){return u.push(e)},r)}),u.push(l);u.forEach(function(e){n(e)}),this.iframes&&this.handleOpenIframes(c,e,n,r),i()}},{key:"forEachNode",value:function(e,t,n){var r=this,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},o=this.getContexts(),a=o.length;a||i(),o.forEach(function(o){var s=function(){r.iterateThroughNodes(e,o,t,n,function(){--a<=0&&i()})};r.iframes?r.waitForIframes(o,s):s()})}}],[{key:"matches",value:function(e,t){var n="string"==typeof t?[t]:t,r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(r){var i=!1;return n.every(function(t){return!r.call(e,t)||(i=!0,!1)}),i}return!1}}]),e}(),o=function(){function e(n){t(this,e),this.opt=r({},{diacritics:!0,synonyms:{},accuracy:"partially",caseSensitive:!1,ignoreJoiners:!1,ignorePunctuation:[],wildcards:"disabled"},n)}return n(e,[{key:"create",value:function(e){return"disabled"!==this.opt.wildcards&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),"disabled"!==this.opt.wildcards&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e),new RegExp(e,"gm"+(this.opt.caseSensitive?"":"i"))}},{key:"escapeStr",value:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}},{key:"createSynonymsRegExp",value:function(e){var t=this.opt.synonyms,n=this.opt.caseSensitive?"":"i",r=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(var i in t)if(t.hasOwnProperty(i)){var o=t[i],a="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(i):this.escapeStr(i),s="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(o):this.escapeStr(o);""!==a&&""!==s&&(e=e.replace(new RegExp("("+this.escapeStr(a)+"|"+this.escapeStr(s)+")","gm"+n),r+"("+this.processSynonyms(a)+"|"+this.processSynonyms(s)+")"+r))}return e}},{key:"processSynonyms",value:function(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}},{key:"setupWildcardsRegExp",value:function(e){return(e=e.replace(/(?:\\)*\?/g,function(e){return"\\"===e.charAt(0)?"?":""})).replace(/(?:\\)*\*/g,function(e){return"\\"===e.charAt(0)?"*":""})}},{key:"createWildcardsRegExp",value:function(e){var t="withSpaces"===this.opt.wildcards;return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}},{key:"setupIgnoreJoinersRegExp",value:function(e){return e.replace(/[^(|)\\]/g,function(e,t,n){var r=n.charAt(t+1);return/[(|)\\]/.test(r)||""===r?e:e+"\0"})}},{key:"createJoinersRegExp",value:function(e){var t=[],n=this.opt.ignorePunctuation;return Array.isArray(n)&&n.length&&t.push(this.escapeStr(n.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join("["+t.join("")+"]*"):e}},{key:"createDiacriticsRegExp",value:function(e){var t=this.opt.caseSensitive?"":"i",n=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"],r=[];return e.split("").forEach(function(i){n.every(function(n){if(-1!==n.indexOf(i)){if(r.indexOf(n)>-1)return!1;e=e.replace(new RegExp("["+n+"]","gm"+t),"["+n+"]"),r.push(n)}return!0})}),e}},{key:"createMergedBlanksRegExp",value:function(e){return e.replace(/[\s]+/gim,"[\\s]+")}},{key:"createAccuracyRegExp",value:function(e){var t=this,n=this.opt.accuracy,r="string"==typeof n?n:n.value,i="";switch(("string"==typeof n?[]:n.limiters).forEach(function(e){i+="|"+t.escapeStr(e)}),r){case"partially":default:return"()("+e+")";case"complementary":return"()([^"+(i="\\s"+(i||this.escapeStr("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿")))+"]*"+e+"[^"+i+"]*)";case"exactly":return"(^|\\s"+i+")("+e+")(?=$|\\s"+i+")"}}}]),e}(),a=function(){function a(e){t(this,a),this.ctx=e,this.ie=!1;var n=window.navigator.userAgent;(n.indexOf("MSIE")>-1||n.indexOf("Trident")>-1)&&(this.ie=!0)}return n(a,[{key:"log",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"debug",r=this.opt.log;this.opt.debug&&"object"===(void 0===r?"undefined":e(r))&&"function"==typeof r[n]&&r[n]("mark.js: "+t)}},{key:"getSeparatedKeywords",value:function(e){var t=this,n=[];return e.forEach(function(e){t.opt.separateWordSearch?e.split(" ").forEach(function(e){e.trim()&&-1===n.indexOf(e)&&n.push(e)}):e.trim()&&-1===n.indexOf(e)&&n.push(e)}),{keywords:n.sort(function(e,t){return t.length-e.length}),length:n.length}}},{key:"isNumeric",value:function(e){return Number(parseFloat(e))==e}},{key:"checkRanges",value:function(e){var t=this;if(!Array.isArray(e)||"[object Object]"!==Object.prototype.toString.call(e[0]))return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];var n=[],r=0;return e.sort(function(e,t){return e.start-t.start}).forEach(function(e){var i=t.callNoMatchOnInvalidRanges(e,r),o=i.start,a=i.end;i.valid&&(e.start=o,e.length=a-o,n.push(e),r=a)}),n}},{key:"callNoMatchOnInvalidRanges",value:function(e,t){var n=void 0,r=void 0,i=!1;return e&&void 0!==e.start?(r=(n=parseInt(e.start,10))+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&r-t>0&&r-n>0?i=!0:(this.log("Ignoring invalid or overlapping range: "+JSON.stringify(e)),this.opt.noMatch(e))):(this.log("Ignoring invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:n,end:r,valid:i}}},{key:"checkWhitespaceRanges",value:function(e,t,n){var r=void 0,i=!0,o=n.length,a=t-o,s=parseInt(e.start,10)-a;return(r=(s=s>o?o:s)+parseInt(e.length,10))>o&&(r=o,this.log("End range automatically set to the max value of "+o)),s<0||r-s<0||s>o||r>o?(i=!1,this.log("Invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)):""===n.substring(s,r).replace(/\s+/g,"")&&(i=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:s,end:r,valid:i}}},{key:"getTextNodes",value:function(e){var t=this,n="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,function(e){r.push({start:n.length,end:(n+=e.textContent).length,node:e})},function(e){return t.matchesExclude(e.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},function(){e({value:n,nodes:r})})}},{key:"matchesExclude",value:function(e){return i.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}},{key:"wrapRangeInTextNode",value:function(e,t,n){var r=this.opt.element?this.opt.element:"mark",i=e.splitText(t),o=i.splitText(n-t),a=document.createElement(r);return a.setAttribute("data-markjs","true"),this.opt.className&&a.setAttribute("class",this.opt.className),a.textContent=i.textContent,i.parentNode.replaceChild(a,i),o}},{key:"wrapRangeInMappedTextNode",value:function(e,t,n,r,i){var o=this;e.nodes.every(function(a,s){var c=e.nodes[s+1];if(void 0===c||c.start>t){if(!r(a.node))return!1;var u=t-a.start,l=(n>a.end?a.end:n)-a.start,h=e.value.substr(0,a.start),f=e.value.substr(l+a.start);if(a.node=o.wrapRangeInTextNode(a.node,u,l),e.value=h+f,e.nodes.forEach(function(t,n){n>=s&&(e.nodes[n].start>0&&n!==s&&(e.nodes[n].start-=l),e.nodes[n].end-=l)}),n-=l,i(a.node.previousSibling,a.start),!(n>a.end))return!1;t=a.end}return!0})}},{key:"wrapGroups",value:function(e,t,n,r){return r((e=this.wrapRangeInTextNode(e,t,t+n)).previousSibling),e}},{key:"separateGroups",value:function(e,t,n,r,i){for(var o=t.length,a=1;a-1&&r(t[a],e)&&(e=this.wrapGroups(e,s,t[a].length,i))}return e}},{key:"wrapMatches",value:function(e,t,n,r,i){var o=this,a=0===t?0:t+1;this.getTextNodes(function(t){t.nodes.forEach(function(t){t=t.node;for(var i=void 0;null!==(i=e.exec(t.textContent))&&""!==i[a];){if(o.opt.separateGroups)t=o.separateGroups(t,i,a,n,r);else{if(!n(i[a],t))continue;var s=i.index;if(0!==a)for(var c=1;c tag. + mark_exclude = ['text'], + marker = new Mark(content), + URL_SEARCH_PARAM = 'search', + URL_MARK_PARAM = 'highlight'; + + let current_searchterm = '', + doc_urls = [], + search_options = { + bool: 'AND', + expand: true, + fields: { + title: {boost: 1}, + body: {boost: 1}, + breadcrumbs: {boost: 0}, + }, + }, + searchindex = null, + results_options = { + teaser_word_count: 30, + limit_results: 30, + }, + teaser_count = 0; + + function hasFocus() { + return searchbar === document.activeElement; + } + + function removeChildren(elem) { + while (elem.firstChild) { + elem.removeChild(elem.firstChild); + } + } + + // Helper to parse a url into its building blocks. + function parseURL(url) { + const a = document.createElement('a'); + a.href = url; + return { + source: url, + protocol: a.protocol.replace(':', ''), + host: a.hostname, + port: a.port, + params: (function() { + const ret = {}; + const seg = a.search.replace(/^\?/, '').split('&'); + for (const part of seg) { + if (!part) { + continue; + } + const s = part.split('='); + ret[s[0]] = s[1]; + } + return ret; + })(), + file: (a.pathname.match(/\/([^/?#]+)$/i) || ['', ''])[1], + hash: a.hash.replace('#', ''), + path: a.pathname.replace(/^([^/])/, '/$1'), + }; + } + + // Helper to recreate a url string from its building blocks. + function renderURL(urlobject) { + let url = urlobject.protocol + '://' + urlobject.host; + if (urlobject.port !== '') { + url += ':' + urlobject.port; + } + url += urlobject.path; + let joiner = '?'; + for (const prop in urlobject.params) { + if (Object.prototype.hasOwnProperty.call(urlobject.params, prop)) { + url += joiner + prop + '=' + urlobject.params[prop]; + joiner = '&'; + } + } + if (urlobject.hash !== '') { + url += '#' + urlobject.hash; + } + return url; + } + + // Helper to escape html special chars for displaying the teasers + const escapeHTML = (function() { + const MAP = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''', + }; + const repl = function(c) { + return MAP[c]; + }; + return function(s) { + return s.replace(/[&<>'"]/g, repl); + }; + })(); + + function formatSearchMetric(count, searchterm) { + if (count === 1) { + return count + ' search result for \'' + searchterm + '\':'; + } else if (count === 0) { + return 'No search results for \'' + searchterm + '\'.'; + } else { + return count + ' search results for \'' + searchterm + '\':'; + } + } + + function formatSearchResult(result, searchterms) { + const teaser = makeTeaser(escapeHTML(result.doc.body), searchterms); + teaser_count++; + + // The ?URL_MARK_PARAM= parameter belongs in between the page and the #heading-anchor + const url = doc_urls[result.ref].split('#'); + if (url.length === 1) { // no anchor found + url.push(''); + } + + // encodeURIComponent escapes all chars that could allow an XSS except + // for '. Due to that we also manually replace ' with its url-encoded + // representation (%27). + const encoded_search = encodeURIComponent(searchterms.join(' ')).replace(/'/g, '%27'); + + return '' + + result.doc.breadcrumbs + '' + + '' + teaser + ''; + } + + function makeTeaser(body, searchterms) { + // The strategy is as follows: + // First, assign a value to each word in the document: + // Words that correspond to search terms (stemmer aware): 40 + // Normal words: 2 + // First word in a sentence: 8 + // Then use a sliding window with a constant number of words and count the + // sum of the values of the words within the window. Then use the window that got the + // maximum sum. If there are multiple maximas, then get the last one. + // Enclose the terms in . + const stemmed_searchterms = searchterms.map(function(w) { + return elasticlunr.stemmer(w.toLowerCase()); + }); + const searchterm_weight = 40; + const weighted = []; // contains elements of ["word", weight, index_in_document] + // split in sentences, then words + const sentences = body.toLowerCase().split('. '); + let index = 0; + let value = 0; + let searchterm_found = false; + for (const sentenceindex in sentences) { + const words = sentences[sentenceindex].split(' '); + value = 8; + for (const wordindex in words) { + const word = words[wordindex]; + if (word.length > 0) { + for (const searchtermindex in stemmed_searchterms) { + if (elasticlunr.stemmer(word).startsWith( + stemmed_searchterms[searchtermindex]) + ) { + value = searchterm_weight; + searchterm_found = true; + } + } + weighted.push([word, value, index]); + value = 2; + } + index += word.length; + index += 1; // ' ' or '.' if last word in sentence + } + index += 1; // because we split at a two-char boundary '. ' + } + + if (weighted.length === 0) { + return body; + } + + const window_weight = []; + const window_size = Math.min(weighted.length, results_options.teaser_word_count); + + let cur_sum = 0; + for (let wordindex = 0; wordindex < window_size; wordindex++) { + cur_sum += weighted[wordindex][1]; + } + window_weight.push(cur_sum); + for (let wordindex = 0; wordindex < weighted.length - window_size; wordindex++) { + cur_sum -= weighted[wordindex][1]; + cur_sum += weighted[wordindex + window_size][1]; + window_weight.push(cur_sum); + } + + let max_sum_window_index = 0; + if (searchterm_found) { + let max_sum = 0; + // backwards + for (let i = window_weight.length - 1; i >= 0; i--) { + if (window_weight[i] > max_sum) { + max_sum = window_weight[i]; + max_sum_window_index = i; + } + } + } else { + max_sum_window_index = 0; + } + + // add around searchterms + const teaser_split = []; + index = weighted[max_sum_window_index][2]; + for (let i = max_sum_window_index; i < max_sum_window_index + window_size; i++) { + const word = weighted[i]; + if (index < word[2]) { + // missing text from index to start of `word` + teaser_split.push(body.substring(index, word[2])); + index = word[2]; + } + if (word[1] === searchterm_weight) { + teaser_split.push(''); + } + index = word[2] + word[0].length; + teaser_split.push(body.substring(word[2], index)); + if (word[1] === searchterm_weight) { + teaser_split.push(''); + } + } + + return teaser_split.join(''); + } + + function init(config) { + results_options = config.results_options; + search_options = config.search_options; + doc_urls = config.doc_urls; + searchindex = elasticlunr.Index.load(config.index); + + searchbar_outer.classList.remove('searching'); + + searchbar.focus(); + + const searchterm = searchbar.value.trim(); + if (searchterm !== '') { + searchbar.classList.add('active'); + doSearch(searchterm); + } + } + + function initSearchInteractions(config) { + // Set up events + searchicon.addEventListener('click', () => { + searchIconClickHandler(); + }, false); + searchbar.addEventListener('keyup', () => { + searchbarKeyUpHandler(); + }, false); + document.addEventListener('keydown', e => { + globalKeyHandler(e); + }, false); + // If the user uses the browser buttons, do the same as if a reload happened + window.onpopstate = () => { + doSearchOrMarkFromUrl(); + }; + // Suppress "submit" events so the page doesn't reload when the user presses Enter + document.addEventListener('submit', e => { + e.preventDefault(); + }, false); + + // If reloaded, do the search or mark again, depending on the current url parameters + doSearchOrMarkFromUrl(); + + // Exported functions + config.hasFocus = hasFocus; + } + + initSearchInteractions(window.search); + + function unfocusSearchbar() { + // hacky, but just focusing a div only works once + const tmp = document.createElement('input'); + tmp.setAttribute('style', 'position: absolute; opacity: 0;'); + searchicon.appendChild(tmp); + tmp.focus(); + tmp.remove(); + } + + // On reload or browser history backwards/forwards events, parse the url and do search or mark + function doSearchOrMarkFromUrl() { + // Check current URL for search request + const url = parseURL(window.location.href); + if (Object.prototype.hasOwnProperty.call(url.params, URL_SEARCH_PARAM) + && url.params[URL_SEARCH_PARAM] !== '') { + showSearch(true); + searchbar.value = decodeURIComponent( + (url.params[URL_SEARCH_PARAM] + '').replace(/\+/g, '%20')); + searchbarKeyUpHandler(); // -> doSearch() + } else { + showSearch(false); + } + + if (Object.prototype.hasOwnProperty.call(url.params, URL_MARK_PARAM)) { + const words = decodeURIComponent(url.params[URL_MARK_PARAM]).split(' '); + marker.mark(words, { + exclude: mark_exclude, + }); + + const markers = document.querySelectorAll('mark'); + const hide = () => { + for (let i = 0; i < markers.length; i++) { + markers[i].classList.add('fade-out'); + window.setTimeout(() => { + marker.unmark(); + }, 300); + } + // also removes the `?URL_MARK_PARAM=` search param so that + // in-page navigation doesn't make highlights unexpectedly appear again + setSearchUrlParameters('', 'replace'); + }; + + for (let i = 0; i < markers.length; i++) { + markers[i].addEventListener('click', hide); + } + } + } + + // Eventhandler for keyevents on `document` + function globalKeyHandler(e) { + if (e.altKey || + e.ctrlKey || + e.metaKey || + e.shiftKey || + e.target.type === 'textarea' || + e.target.type === 'text' || + !hasFocus() && mdbook_something_else_has_focus(e) + ) { + return; + } + + if (e.key === 'Escape') { + e.preventDefault(); + searchbar.classList.remove('active'); + setSearchUrlParameters('', + searchbar.value.trim() !== '' ? 'push' : 'replace'); + if (hasFocus()) { + unfocusSearchbar(); + } + showSearch(false); + marker.unmark(); + } else if (!hasFocus() && (e.key === 's' || e.key === '/')) { + e.preventDefault(); + showSearch(true); + window.scrollTo(0, 0); + searchbar.select(); + } else if (hasFocus() && (e.key === 'ArrowDown' + || e.key === 'Enter')) { + e.preventDefault(); + const first = searchresults.firstElementChild; + if (first !== null) { + unfocusSearchbar(); + first.classList.add('focus'); + if (e.key === 'Enter') { + window.location.assign(first.querySelector('a')); + } + } + } else if (!hasFocus() && (e.key === 'ArrowDown' + || e.key === 'ArrowUp' + || e.key === 'Enter')) { + // not `:focus` because browser does annoying scrolling + const focused = searchresults.querySelector('li.focus'); + if (!focused) { + return; + } + e.preventDefault(); + if (e.key === 'ArrowDown') { + const next = focused.nextElementSibling; + if (next) { + focused.classList.remove('focus'); + next.classList.add('focus'); + } + } else if (e.key === 'ArrowUp') { + focused.classList.remove('focus'); + const prev = focused.previousElementSibling; + if (prev) { + prev.classList.add('focus'); + } else { + searchbar.select(); + } + } else { // Enter + window.location.assign(focused.querySelector('a')); + } + } + } + + function loadSearchScript(url, id) { + if (document.getElementById(id)) { + return; + } + searchbar_outer.classList.add('searching'); + + const script = document.createElement('script'); + script.src = url; + script.id = id; + script.onload = () => init(window.search); + script.onerror = error => { + console.error(`Failed to load \`${url}\`: ${error}`); + }; + document.head.append(script); + } + + function showSearch(yes) { + if (yes) { + loadSearchScript( + window.path_to_searchindex_js || + path_to_root + 'searchindex-8ec871e3.js', + 'mdbook-search-index'); + search_wrap.classList.remove('hidden'); + searchicon.setAttribute('aria-expanded', 'true'); + } else { + search_wrap.classList.add('hidden'); + searchicon.setAttribute('aria-expanded', 'false'); + const results = searchresults.children; + for (let i = 0; i < results.length; i++) { + results[i].classList.remove('focus'); + } + } + } + + function showResults(yes) { + if (yes) { + searchresults_outer.classList.remove('hidden'); + } else { + searchresults_outer.classList.add('hidden'); + } + } + + // Eventhandler for search icon + function searchIconClickHandler() { + if (search_wrap.classList.contains('hidden')) { + showSearch(true); + window.scrollTo(0, 0); + searchbar.select(); + } else { + showSearch(false); + } + } + + // Eventhandler for keyevents while the searchbar is focused + function searchbarKeyUpHandler() { + const searchterm = searchbar.value.trim(); + if (searchterm !== '') { + searchbar.classList.add('active'); + doSearch(searchterm); + } else { + searchbar.classList.remove('active'); + showResults(false); + removeChildren(searchresults); + } + + setSearchUrlParameters(searchterm, 'push_if_new_search_else_replace'); + + // Remove marks + marker.unmark(); + } + + // Update current url with ?URL_SEARCH_PARAM= parameter, remove ?URL_MARK_PARAM and + // `#heading-anchor`. `action` can be one of "push", "replace", + // "push_if_new_search_else_replace" and replaces or pushes a new browser history item. + // "push_if_new_search_else_replace" pushes if there is no `?URL_SEARCH_PARAM=abc` yet. + function setSearchUrlParameters(searchterm, action) { + const url = parseURL(window.location.href); + const first_search = !Object.prototype.hasOwnProperty.call(url.params, URL_SEARCH_PARAM); + + if (searchterm !== '' || action === 'push_if_new_search_else_replace') { + url.params[URL_SEARCH_PARAM] = searchterm; + delete url.params[URL_MARK_PARAM]; + url.hash = ''; + } else { + delete url.params[URL_MARK_PARAM]; + delete url.params[URL_SEARCH_PARAM]; + } + // A new search will also add a new history item, so the user can go back + // to the page prior to searching. A updated search term will only replace + // the url. + if (action === 'push' || action === 'push_if_new_search_else_replace' && first_search ) { + history.pushState({}, document.title, renderURL(url)); + } else if (action === 'replace' || + action === 'push_if_new_search_else_replace' && + !first_search + ) { + history.replaceState({}, document.title, renderURL(url)); + } + } + + function doSearch(searchterm) { + // Don't search the same twice + if (current_searchterm === searchterm) { + return; + } + searchbar_outer.classList.add('searching'); + if (searchindex === null) { + return; + } + + current_searchterm = searchterm; + + // Do the actual search + const results = searchindex.search(searchterm, search_options); + const resultcount = Math.min(results.length, results_options.limit_results); + + // Display search metrics + searchresults_header.innerText = formatSearchMetric(resultcount, searchterm); + + // Clear and insert results + const searchterms = searchterm.split(' '); + removeChildren(searchresults); + for (let i = 0; i < resultcount ; i++) { + const resultElem = document.createElement('li'); + resultElem.innerHTML = formatSearchResult(results[i], searchterms); + searchresults.appendChild(resultElem); + } + + // Display results + showResults(true); + searchbar_outer.classList.remove('searching'); + } + + // Exported functions + search.hasFocus = hasFocus; +})(window.search); diff --git a/typ/mdbook/assets/searchindex-8ec871e3.js b/typ/mdbook/assets/searchindex-8ec871e3.js new file mode 100644 index 00000000..f494646a --- /dev/null +++ b/typ/mdbook/assets/searchindex-8ec871e3.js @@ -0,0 +1 @@ +window.search = Object.assign(window.search, JSON.parse('{"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}},"doc_urls":["intro/index.html#introduction","intro/index.html#who-embedded-rust-is-for","intro/index.html#scope","intro/index.html#who-this-book-is-for","intro/index.html#assumptions-and-prerequisites","intro/index.html#other-resources","intro/index.html#translations","intro/index.html#how-to-use-this-book","intro/index.html#contributing-to-this-book","intro/index.html#re-using-this-material","intro/hardware.html#meet-your-hardware","intro/hardware.html#stm32f3discovery-the-f3","intro/no-std.html#a-no_std-rust-environment","intro/no-std.html#hosted-environments","intro/no-std.html#bare-metal-environments","intro/no-std.html#the-libstd-runtime","intro/no-std.html#summary","intro/no-std.html#overview","intro/no-std.html#see-also","intro/tooling.html#tooling","intro/tooling.html#cargo-generate-or-git","intro/tooling.html#cargo-binutils","intro/tooling.html#qemu-system-arm","intro/tooling.html#tooling-for-embedded-rust-debugging","intro/tooling.html#overview","intro/tooling.html#software-that-drives-debugging-tools","intro/tooling.html#probe-rs","intro/tooling.html#openocd-open-on-chip-debugger","intro/tooling.html#debuggers","intro/tooling.html#probe-rs-visual-studio-code-extension","intro/tooling.html#trace32","intro/tooling.html#gdb-gnu-debugger","intro/tooling.html#probes","intro/tooling.html#rusty-probe","intro/tooling.html#st-link","intro/tooling.html#j-link","intro/tooling.html#mcu-link","intro/install.html#installing-the-tools","intro/install.html#rust-toolchain","intro/install.html#cargo-binutils","intro/install.html#cargo-generate","intro/install.html#os-specific-instructions","intro/install/linux.html#linux","intro/install/linux.html#packages","intro/install/linux.html#udev-rules","intro/install/macos.html#macos","intro/install/macos.html#install-tools-with-homebrew","intro/install/macos.html#install-tools-with-macports","intro/install/windows.html#windows","intro/install/windows.html#arm-none-eabi-gdb","intro/install/windows.html#openocd","intro/install/windows.html#qemu","intro/install/windows.html#st-link-usb-driver","intro/install/verify.html#verify-installation","start/index.html#getting-started","start/qemu.html#qemu","start/qemu.html#creating-a-non-standard-rust-program","start/qemu.html#using-cargo-generate","start/qemu.html#using-git","start/qemu.html#using-neither","start/qemu.html#program-overview","start/qemu.html#cross-compiling","start/qemu.html#inspecting","start/qemu.html#running","start/qemu.html#debugging","start/hardware.html#hardware","start/hardware.html#know-your-hardware","start/hardware.html#configuring","start/hardware.html#debugging","start/registers.html#memory-mapped-registers","start/registers.html#board-crate","start/registers.html#micro-architecture-crate","start/registers.html#using-a-peripheral-access-crate-pac","start/registers.html#reading","start/registers.html#writing","start/registers.html#modifying","start/registers.html#using-a-hal-crate","start/semihosting.html#semihosting","start/panicking.html#panicking","start/panicking.html#an-example","start/exceptions.html#exceptions","start/exceptions.html#a-complete-example","start/exceptions.html#the-default-exception-handler","start/exceptions.html#the-hard-fault-handler","start/interrupts.html#interrupts","peripherals/index.html#peripherals","peripherals/index.html#what-are-peripherals","peripherals/index.html#linear-and-real-memory-space","peripherals/index.html#memory-mapped-peripherals","peripherals/a-first-attempt.html#a-first-attempt","peripherals/a-first-attempt.html#the-registers","peripherals/a-first-attempt.html#the-c-approach","peripherals/a-first-attempt.html#volatile-accesses","peripherals/a-first-attempt.html#the-rusty-wrapper","peripherals/borrowck.html#mutable-global-state","peripherals/borrowck.html#what-should-our-rules-be","peripherals/borrowck.html#the-borrow-checker","peripherals/singletons.html#singletons","peripherals/singletons.html#but-why-cant-we-just-use-global-variables","peripherals/singletons.html#how-do-we-do-this-in-rust","peripherals/singletons.html#existing-library-support","peripherals/singletons.html#but-why","peripherals/singletons.html#treat-your-hardware-like-data","static-guarantees/index.html#static-guarantees","static-guarantees/typestate-programming.html#typestate-programming","static-guarantees/typestate-programming.html#strong-types","static-guarantees/state-machines.html#peripherals-as-state-machines","static-guarantees/state-machines.html#hardware-representation","static-guarantees/design-contracts.html#design-contracts","static-guarantees/design-contracts.html#type-states","static-guarantees/design-contracts.html#compile-time-functional-safety","static-guarantees/zero-cost-abstractions.html#zero-cost-abstractions","static-guarantees/zero-cost-abstractions.html#zero-sized-types","static-guarantees/zero-cost-abstractions.html#nesting","portability/index.html#portability","portability/index.html#what-is-embedded-hal","portability/index.html#users-of-the-embedded-hal","portability/index.html#hal-implementation","portability/index.html#driver","portability/index.html#application","concurrency/index.html#concurrency","concurrency/index.html#no-concurrency","concurrency/index.html#global-mutable-data","concurrency/index.html#critical-sections","concurrency/index.html#atomic-access","concurrency/index.html#abstractions-send-and-sync","concurrency/index.html#mutexes","concurrency/index.html#sharing-peripherals","concurrency/index.html#rtic","concurrency/index.html#embassy","concurrency/index.html#real-time-operating-systems","concurrency/index.html#multiple-cores","collections/index.html#collections","collections/index.html#using-alloc","collections/index.html#using-heapless","collections/index.html#trade-offs","collections/index.html#out-of-memory-and-error-handling","collections/index.html#memory-usage","collections/index.html#worst-case-execution-time-wcet","collections/index.html#ease-of-use","design-patterns/index.html#design-patterns","design-patterns/hal/index.html#hal-design-patterns","design-patterns/hal/checklist.html#hal-design-patterns-checklist","design-patterns/hal/naming.html#naming","design-patterns/hal/naming.html#the-crate-is-named-appropriately-c-crate-name","design-patterns/hal/interoperability.html#interoperability","design-patterns/hal/interoperability.html#wrapper-types-provide-a-destructor-method-c-free","design-patterns/hal/interoperability.html#hals-reexport-their-register-access-crate-c-reexport-pac","design-patterns/hal/interoperability.html#types-implement-the-embedded-hal-traits-c-hal-traits","design-patterns/hal/predictability.html#predictability","design-patterns/hal/predictability.html#constructors-are-used-instead-of-extension-traits-c-ctor","design-patterns/hal/predictability.html#methods-are-decorated-with-inline-where-appropriate-c-inline","design-patterns/hal/gpio.html#recommendations-for-gpio-interfaces","design-patterns/hal/gpio.html#pin-types-are-zero-sized-by-default-c-zst-pin","design-patterns/hal/gpio.html#pin-types-provide-methods-to-erase-pin-and-port-c-erased-pin","design-patterns/hal/gpio.html#pin-state-should-be-encoded-as-type-parameters-c-pin-state","c-tips/index.html#tips-for-embedded-c-developers","c-tips/index.html#preprocessor","c-tips/index.html#compile-time-code-selection","c-tips/index.html#compile-time-sizes-and-computation","c-tips/index.html#macros","c-tips/index.html#build-system","c-tips/index.html#cross-compiling","c-tips/index.html#iterators-vs-array-access","c-tips/index.html#references-vs-pointers","c-tips/index.html#volatile-access","c-tips/index.html#packed-and-aligned-types","c-tips/index.html#other-resources","interoperability/index.html#interoperability","interoperability/index.html#interoperability-with-other-build-systems","interoperability/index.html#interoperability-with-rtoss","interoperability/c-with-rust.html#a-little-c-with-your-rust","interoperability/c-with-rust.html#defining-the-interface","interoperability/c-with-rust.html#wrapping-c-functions-and-datatypes","interoperability/c-with-rust.html#automatically-generating-the-interface","interoperability/c-with-rust.html#building-your-cc-code","interoperability/c-with-rust.html#rust-buildrs-build-scripts","interoperability/c-with-rust.html#triggering-external-build-systems","interoperability/c-with-rust.html#building-cc-code-with-the-cc-crate","interoperability/rust-with-c.html#a-little-rust-with-your-c","interoperability/rust-with-c.html#setting-up-a-project","interoperability/rust-with-c.html#building-a-c-api","interoperability/rust-with-c.html#no_mangle","interoperability/rust-with-c.html#extern-c","interoperability/rust-with-c.html#linking-and-greater-project-context","unsorted/index.html#unsorted-topics","unsorted/speed-vs-size.html#optimizations-the-speed-size-tradeoff","unsorted/speed-vs-size.html#no-optimizations","unsorted/speed-vs-size.html#optimizing-dependencies","unsorted/speed-vs-size.html#optimize-for-speed","unsorted/speed-vs-size.html#optimize-for-size","unsorted/math.html#performing-math-functionality-with-no_std","appendix/glossary.html#appendix-a-glossary","appendix/glossary.html#bsp","appendix/glossary.html#fpu","appendix/glossary.html#hal","appendix/glossary.html#i2c","appendix/glossary.html#pac","appendix/glossary.html#spi","appendix/glossary.html#svd","appendix/glossary.html#uart","appendix/glossary.html#usart"],"index":{"fields":["title","body","breadcrumbs"],"pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5","index":{"body":{"root":{"docs":{},"df":0,"0":{"docs":{"100":{"tf":1.0},"107":{"tf":2.23606797749979},"108":{"tf":2.23606797749979},"111":{"tf":2.0},"122":{"tf":2.0},"123":{"tf":1.7320508075688772},"124":{"tf":1.0},"125":{"tf":1.0},"154":{"tf":1.4142135623730951},"16":{"tf":1.0},"166":{"tf":3.872983346207417},"187":{"tf":1.4142135623730951},"188":{"tf":1.7320508075688772},"62":{"tf":1.7320508075688772},"63":{"tf":1.4142135623730951},"79":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0}},"df":20,".":{"docs":{},"df":0,"1":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"58":{"tf":1.0}},"df":1},"4":{"docs":{"19":{"tf":1.0}},"df":1}},"0":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"50":{"tf":1.0},"53":{"tf":1.4142135623730951},"68":{"tf":1.0}},"df":3}}}},"2":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"81":{"tf":1.0}},"df":1}},"6":{"docs":{"63":{"tf":1.0}},"df":1}},"3":{"docs":{},"df":0,".":{"docs":{},"df":0,"1":{"docs":{"81":{"tf":1.0}},"df":1}}},"5":{"docs":{},"df":0,".":{"docs":{},"df":0,"7":{"docs":{"81":{"tf":1.0}},"df":1}}},"6":{"docs":{},"df":0,".":{"docs":{},"df":0,"1":{"docs":{},"df":0,"/":{"docs":{},"df":0,"s":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"/":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,"4":{"docs":{},"df":0,"7":{"docs":{},"df":0,"3":{"docs":{"64":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}},"3":{"docs":{"81":{"tf":1.0}},"df":1}}},"8":{"docs":{"19":{"tf":1.0}},"df":1}},"0":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"62":{"tf":3.0}},"df":3,"0":{"docs":{"166":{"tf":1.0}},"df":1},"1":{"docs":{"44":{"tf":1.0}},"df":1}},"1":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"62":{"tf":1.7320508075688772}},"df":3,"8":{"docs":{"44":{"tf":1.0}},"df":1}},"4":{"docs":{},"df":0,"8":{"docs":{},"df":0,"3":{"docs":{},"df":0,":":{"docs":{},"df":0,"3":{"docs":{},"df":0,"7":{"docs":{},"df":0,"4":{"docs":{},"df":0,"b":{"docs":{"44":{"tf":1.0}},"df":1}}}}}}}},"9":{"docs":{"189":{"tf":1.0},"190":{"tf":1.0}},"df":2},"u":{"docs":{},"df":0,"1":{"docs":{},"df":0,"6":{"docs":{"163":{"tf":1.0}},"df":1}},"3":{"docs":{},"df":0,"2":{"docs":{"159":{"tf":1.0}},"df":1}}},"x":{"docs":{},"df":0,"0":{"docs":{"62":{"tf":3.7416573867739413}},"df":1,"0":{"docs":{"90":{"tf":1.0}},"df":1,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"61":{"tf":1.0},"68":{"tf":1.0},"83":{"tf":1.4142135623730951}},"df":3},"3":{"docs":{"83":{"tf":1.0}},"df":1}}}},"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"87":{"tf":1.7320508075688772}},"df":1}}}}}},"7":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{"87":{"tf":1.0}},"df":1}}}}}}}},"2":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"88":{"tf":1.0}},"df":1}}}}}}}},"4":{"docs":{"90":{"tf":1.0}},"df":1,"8":{"docs":{},"df":0,"3":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}}},"8":{"docs":{"90":{"tf":1.0}},"df":1,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"67":{"tf":1.0}},"df":1}}},"4":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"68":{"tf":1.0}},"df":1}},"9":{"docs":{},"df":0,"6":{"docs":{"68":{"tf":1.0}},"df":1}},"a":{"docs":{},"df":0,"c":{"docs":{"68":{"tf":1.0}},"df":1},"e":{"docs":{"68":{"tf":1.0}},"df":1}},"b":{"docs":{},"df":0,"0":{"docs":{"68":{"tf":1.0}},"df":1},"4":{"docs":{"68":{"tf":1.0}},"df":1},"8":{"docs":{"68":{"tf":1.0}},"df":1},"c":{"docs":{"68":{"tf":1.0}},"df":1}}},"5":{"docs":{},"df":0,"0":{"docs":{},"df":0,"2":{"docs":{"68":{"tf":1.0}},"df":1}}},"9":{"docs":{},"df":0,"4":{"docs":{},"df":0,"a":{"docs":{"83":{"tf":1.0}},"df":1}}}},"1":{"docs":{},"df":0,"6":{"docs":{},"df":0,"d":{"docs":{},"df":0,"f":{"docs":{"83":{"tf":1.0}},"df":1}},"e":{"docs":{},"df":0,"2":{"docs":{"83":{"tf":1.0}},"df":1}}}},"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"e":{"docs":{},"df":0,"8":{"docs":{"83":{"tf":1.0}},"df":1}}}},"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"66":{"tf":1.0}},"df":1}}}}}}}},"c":{"docs":{"90":{"tf":1.0}},"df":1}},"1":{"docs":{"62":{"tf":1.4142135623730951}},"df":1,"2":{"docs":{},"df":0,"3":{"docs":{},"df":0,"4":{"docs":{"87":{"tf":1.0}},"df":1}}},"5":{"docs":{},"df":0,"1":{"docs":{},"df":0,"8":{"docs":{"68":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"7":{"docs":{},"df":0,"0":{"docs":{"68":{"tf":1.0}},"df":1}}}},"2":{"docs":{"62":{"tf":1.0}},"df":1,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"87":{"tf":1.0}},"df":1,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"188":{"tf":2.0},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"67":{"tf":1.0}},"df":4}}}},"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"66":{"tf":1.4142135623730951},"87":{"tf":1.4142135623730951}},"df":2}}},"1":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"133":{"tf":1.0}},"df":1}}},"2":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"133":{"tf":1.4142135623730951}},"df":1}}}},"1":{"docs":{},"df":0,"2":{"docs":{},"df":0,"3":{"docs":{},"df":0,"4":{"docs":{"87":{"tf":1.0}},"df":1}}}},"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{"87":{"tf":1.0}},"df":1}}}}}}}},"4":{"docs":{},"df":0,"e":{"docs":{"62":{"tf":1.0}},"df":1}},"5":{"docs":{},"df":0,"6":{"docs":{"62":{"tf":1.0}},"df":1}}},"3":{"docs":{"62":{"tf":1.0}},"df":1,"7":{"docs":{},"df":0,"4":{"docs":{},"df":0,"b":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}}},"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{"83":{"tf":1.0}},"df":1,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"83":{"tf":1.0}},"df":1}}}},"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{"83":{"tf":1.0}},"df":1}}}}}}}}},"4":{"docs":{"62":{"tf":1.7320508075688772},"83":{"tf":1.0}},"df":2,"0":{"docs":{},"df":0,"0":{"docs":{"61":{"tf":1.0},"62":{"tf":1.0},"68":{"tf":1.4142135623730951}},"df":3,"0":{"docs":{},"df":0,"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"87":{"tf":1.0}},"df":1}}}},"1":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"101":{"tf":1.0}},"df":1}}}}}}},"5":{"docs":{"62":{"tf":1.0}},"df":1}},"1":{"docs":{},"df":0,"4":{"docs":{"68":{"tf":1.0}},"df":1}},"5":{"docs":{},"df":0,"c":{"docs":{"62":{"tf":1.0}},"df":1}}},"5":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"2":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"62":{"tf":1.0}},"df":1}}}}}}},"6":{"docs":{},"df":0,"1":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"83":{"tf":1.0}},"df":1}}}}}},"c":{"docs":{"68":{"tf":1.0}},"df":1}}},"7":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"d":{"docs":{},"df":0,"3":{"docs":{},"df":0,"3":{"docs":{},"df":0,"5":{"docs":{},"df":0,"9":{"docs":{},"df":0,"8":{"docs":{},"df":0,"4":{"docs":{},"df":0,"9":{"docs":{},"df":0,"0":{"docs":{"166":{"tf":1.0}},"df":1},"2":{"docs":{"166":{"tf":1.0}},"df":1},"3":{"docs":{"166":{"tf":1.0}},"df":1}}}}}}}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"9":{"docs":{},"df":0,"0":{"docs":{},"df":0,"9":{"docs":{},"df":0,"a":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"166":{"tf":1.0}},"df":1},"2":{"docs":{"166":{"tf":1.0}},"df":1},"4":{"docs":{"166":{"tf":1.0}},"df":1}}}},"b":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"166":{"tf":1.0}},"df":1},"2":{"docs":{"166":{"tf":1.0}},"df":1},"4":{"docs":{"166":{"tf":1.0}},"df":1}}}}}}},"b":{"docs":{},"df":0,"3":{"docs":{},"df":0,"5":{"docs":{},"df":0,"1":{"docs":{},"df":0,"1":{"docs":{},"df":0,"d":{"docs":{},"df":0,"0":{"docs":{"166":{"tf":1.0}},"df":1},"2":{"docs":{"166":{"tf":1.0}},"df":1},"4":{"docs":{"166":{"tf":1.0}},"df":1}}}}}}}}},"f":{"docs":{},"df":0,"d":{"docs":{},"df":0,"0":{"docs":{},"df":0,"d":{"docs":{},"df":0,"8":{"docs":{},"df":0,"4":{"docs":{},"df":0,"c":{"docs":{},"df":0,"6":{"docs":{},"df":0,"0":{"docs":{"166":{"tf":1.0}},"df":1},"2":{"docs":{"166":{"tf":1.0}},"df":1},"4":{"docs":{"166":{"tf":1.0}},"df":1}}}}}}}}}}}},"8":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"188":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951}},"df":2}}},"4":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"188":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951}},"df":2}},"9":{"docs":{},"df":0,"0":{"docs":{"68":{"tf":1.0}},"df":1}}},"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"88":{"tf":1.0}},"df":1}}}}}},"1":{"docs":{},"df":0,"1":{"docs":{},"df":0,"c":{"docs":{},"df":0,"0":{"docs":{"188":{"tf":1.0}},"df":1}}},"4":{"docs":{},"df":0,"4":{"docs":{},"df":0,"e":{"docs":{"68":{"tf":1.0}},"df":1}}},"9":{"docs":{},"df":0,"1":{"docs":{},"df":0,"8":{"docs":{"68":{"tf":1.0}},"df":1}}}},"2":{"docs":{},"df":0,"2":{"docs":{},"df":0,"7":{"docs":{},"df":0,"0":{"docs":{"68":{"tf":1.0}},"df":1}}},"7":{"docs":{},"df":0,"8":{"docs":{},"df":0,"0":{"docs":{"188":{"tf":1.0}},"df":1}}}}}}},"e":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"_":{"docs":{},"df":0,"e":{"docs":{},"df":0,"0":{"docs":{},"df":0,"1":{"docs":{},"df":0,"0":{"docs":{"91":{"tf":1.0},"92":{"tf":1.4142135623730951},"93":{"tf":1.0}},"df":3}}}}}}}}},"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{"83":{"tf":1.0}},"df":1},"f":{"docs":{"87":{"tf":1.0}},"df":1,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{"87":{"tf":1.0}},"df":1}}}}}}}}},"{":{"docs":{},"df":0,":":{"docs":{},"df":0,"0":{"docs":{},"df":0,"8":{"docs":{},"df":0,"x":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}},"1":{"docs":{"107":{"tf":2.23606797749979},"108":{"tf":2.23606797749979},"109":{"tf":1.0},"11":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"133":{"tf":1.4142135623730951},"166":{"tf":1.4142135623730951},"188":{"tf":1.0},"189":{"tf":1.0},"44":{"tf":1.4142135623730951},"61":{"tf":1.4142135623730951},"62":{"tf":1.4142135623730951},"64":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":1.7320508075688772},"72":{"tf":1.0},"77":{"tf":1.4142135623730951},"79":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":1.0},"84":{"tf":1.0}},"df":25,".":{"docs":{},"df":0,"2":{"docs":{},"df":0,"9":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"190":{"tf":1.0}},"df":1}}}},"3":{"docs":{},"df":0,"0":{"docs":{"168":{"tf":1.0}},"df":1},"1":{"docs":{"159":{"tf":1.0},"19":{"tf":1.4142135623730951},"38":{"tf":1.0}},"df":3,".":{"docs":{},"df":0,"1":{"docs":{"38":{"tf":1.0}},"df":1}}}},"4":{"docs":{"12":{"tf":1.0}},"df":1},"5":{"docs":{},"df":0,"v":{"docs":{"107":{"tf":1.4142135623730951},"108":{"tf":1.4142135623730951}},"df":2}},"c":{"docs":{},"df":0,"f":{"docs":{},"df":0,"g":{"docs":{"53":{"tf":1.4142135623730951}},"df":1}}}},"0":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"11":{"tf":1.0},"64":{"tf":1.0}},"df":4,"0":{"docs":{"53":{"tf":1.0},"62":{"tf":1.0},"68":{"tf":1.0}},"df":3,"0":{"docs":{"53":{"tf":1.7320508075688772},"68":{"tf":1.7320508075688772}},"df":2}},"2":{"docs":{},"df":0,"4":{"docs":{"159":{"tf":1.0},"188":{"tf":1.4142135623730951},"61":{"tf":1.0},"62":{"tf":1.0},"67":{"tf":1.0}},"df":5}},"3":{"docs":{},"df":0,"8":{"docs":{},"df":0,"0":{"docs":{"68":{"tf":1.0}},"df":1}}}},"1":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.4142135623730951}},"df":4,"0":{"docs":{},"df":0,"0":{"docs":{"188":{"tf":1.0}},"df":1}},"5":{"docs":{},"df":0,"2":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"_":{"docs":{},"df":0,"u":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"p":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}},"8":{"docs":{},"df":0,"4":{"docs":{"18":{"tf":1.0}},"df":1}}},"2":{"docs":{"38":{"tf":1.0},"64":{"tf":1.0},"81":{"tf":1.0}},"df":3,"3":{"docs":{},"df":0,"4":{"docs":{},"df":0,"5":{"docs":{},"df":0,"6":{"docs":{},"df":0,"7":{"docs":{},"df":0,"8":{"docs":{},"df":0,"9":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}},"5":{"docs":{"88":{"tf":1.0}},"df":1},"8":{"docs":{"159":{"tf":1.0}},"df":1},":":{"docs":{},"df":0,"3":{"docs":{},"df":0,"4":{"docs":{"44":{"tf":1.0}},"df":1}}}},"3":{"docs":{"44":{"tf":1.0},"64":{"tf":2.0},"68":{"tf":1.4142135623730951}},"df":3,".":{"docs":{},"df":0,"1":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"50":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"4":{"docs":{"64":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"0":{"docs":{},"df":0,"4":{"docs":{"43":{"tf":1.0}},"df":1}}},"5":{"docs":{},"df":0,"7":{"docs":{},"df":0,"0":{"docs":{"62":{"tf":1.0}},"df":1}}}},"5":{"docs":{"64":{"tf":1.0}},"df":1,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"0":{"docs":{},"df":0,"4":{"docs":{"62":{"tf":1.0}},"df":1}}}}},"6":{"docs":{"163":{"tf":1.0},"64":{"tf":1.0}},"df":2,".":{"docs":{},"df":0,"0":{"docs":{},"df":0,"4":{"docs":{"43":{"tf":1.0}},"df":1}}}},"7":{"docs":{"44":{"tf":1.0},"68":{"tf":1.0}},"df":2,"0":{"docs":{},"df":0,"8":{"docs":{"188":{"tf":1.0}},"df":1}}},"8":{"docs":{"189":{"tf":1.0},"190":{"tf":1.0},"38":{"tf":1.0},"62":{"tf":1.0}},"df":4,".":{"docs":{},"df":0,"0":{"docs":{},"df":0,"4":{"docs":{"43":{"tf":1.0}},"df":1}}},"9":{"docs":{"44":{"tf":1.0}},"df":1,"2":{"docs":{"62":{"tf":1.0}},"df":1}}},"9":{"docs":{"62":{"tf":1.4142135623730951},"68":{"tf":1.0}},"df":2,"4":{"docs":{"189":{"tf":1.0}},"df":1},"7":{"docs":{},"df":0,"0":{"docs":{"86":{"tf":1.0}},"df":1}},"8":{"docs":{},"df":0,"0":{"docs":{"86":{"tf":1.0}},"df":1}}},"g":{"docs":{},"df":0,"b":{"docs":{"12":{"tf":1.0}},"df":1}}},"2":{"docs":{"104":{"tf":1.0},"109":{"tf":1.0},"189":{"tf":2.23606797749979},"190":{"tf":1.0},"62":{"tf":1.0},"79":{"tf":1.0}},"df":6,"\'":{"docs":{"62":{"tf":1.0}},"df":1},".":{"docs":{},"df":0,".":{"docs":{},"df":0,"3":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}},"9":{"docs":{},"df":0,"1":{"docs":{},"df":0,"3":{"docs":{},"df":0,"8":{"docs":{},"df":0,"7":{"docs":{},"df":0,"9":{"docs":{"68":{"tf":1.0}},"df":1}}}},"9":{"docs":{},"df":0,"8":{"docs":{},"df":0,"8":{"docs":{},"df":0,"1":{"docs":{"53":{"tf":1.0}},"df":1}}}}}}},"0":{"docs":{},"df":0,"1":{"docs":{},"df":0,"7":{"docs":{"53":{"tf":1.0}},"df":1},"8":{"docs":{"189":{"tf":1.0},"190":{"tf":1.0},"38":{"tf":1.0},"4":{"tf":1.4142135623730951},"49":{"tf":1.0},"58":{"tf":1.0},"78":{"tf":1.0}},"df":7},"9":{"docs":{"39":{"tf":1.0}},"df":1}},"3":{"docs":{},"df":0,"5":{"docs":{"62":{"tf":1.0}},"df":1}}},"1":{"docs":{},"df":0,"1":{"docs":{},"df":0,"2":{"docs":{"72":{"tf":1.0}},"df":1}}},"2":{"docs":{},"df":0,"5":{"docs":{"190":{"tf":1.4142135623730951}},"df":1}},"4":{"docs":{"11":{"tf":1.0}},"df":1,"8":{"docs":{},"df":0,"9":{"docs":{"68":{"tf":1.0}},"df":1}}},"5":{"docs":{"190":{"tf":1.0}},"df":1,"6":{"docs":{"11":{"tf":1.0},"66":{"tf":1.4142135623730951},"72":{"tf":1.0}},"df":3,"k":{"docs":{"61":{"tf":1.0},"67":{"tf":1.0}},"df":2}}},"6":{"docs":{"189":{"tf":1.0}},"df":1,"4":{"docs":{"72":{"tf":1.0}},"df":1}},"7":{"docs":{"43":{"tf":1.0}},"df":1,"5":{"docs":{"190":{"tf":1.4142135623730951}},"df":1}},"9":{"docs":{},"df":0,"5":{"docs":{},"df":0,"8":{"docs":{"62":{"tf":1.0}},"df":1}}}},"3":{"docs":{"109":{"tf":1.0},"12":{"tf":1.0},"189":{"tf":2.23606797749979},"190":{"tf":1.0},"79":{"tf":1.0}},"df":5,".":{"docs":{},"df":0,"0":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"19":{"tf":1.0}},"df":1}}},"3":{"docs":{"11":{"tf":1.0}},"df":1}},"2":{"docs":{"168":{"tf":1.0},"52":{"tf":1.0},"62":{"tf":1.0},"66":{"tf":1.0},"72":{"tf":1.4142135623730951},"87":{"tf":1.0},"88":{"tf":1.4142135623730951},"90":{"tf":2.0},"91":{"tf":1.0}},"df":9,"/":{"docs":{},"df":0,"6":{"docs":{},"df":0,"4":{"docs":{"12":{"tf":1.0}},"df":1}}}},"3":{"docs":{},"df":0,"3":{"docs":{},"df":0,"3":{"docs":{"64":{"tf":2.0},"68":{"tf":2.0}},"df":2}}},"4":{"docs":{},"df":0,"6":{"docs":{},"df":0,"0":{"docs":{"68":{"tf":1.0}},"df":1}},"9":{"docs":{},"df":0,"0":{"docs":{"188":{"tf":1.0}},"df":1}}}},"4":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"12":{"tf":1.0},"188":{"tf":1.4142135623730951},"5":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"72":{"tf":1.0},"79":{"tf":1.0}},"df":9,".":{"docs":{},"df":0,"8":{"docs":{},"df":0,"2":{"docs":{},"df":0,"8":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"191":{"tf":1.4142135623730951}},"df":1}}}}}},"0":{"docs":{"62":{"tf":1.4142135623730951},"66":{"tf":1.0}},"df":2,"0":{"docs":{"62":{"tf":1.0}},"df":1},"4":{"docs":{"62":{"tf":1.0}},"df":1},"6":{"docs":{"62":{"tf":1.0}},"df":1},"9":{"docs":{},"df":0,"6":{"docs":{"166":{"tf":1.0}},"df":1}},"a":{"docs":{"62":{"tf":1.0}},"df":1},"k":{"docs":{"67":{"tf":1.0}},"df":1}},"5":{"docs":{"62":{"tf":1.0}},"df":1},"6":{"docs":{"62":{"tf":1.4142135623730951}},"df":1},"7":{"docs":{},"df":0,"3":{"docs":{"64":{"tf":1.0}},"df":1}},"8":{"docs":{"11":{"tf":1.0}},"df":1},"9":{"docs":{},"df":0,"2":{"docs":{},"df":0,"9":{"docs":{"62":{"tf":1.0}},"df":1}}},"c":{"docs":{"62":{"tf":1.0}},"df":1}},"5":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2,"1":{"docs":{},"df":0,"2":{"docs":{"87":{"tf":1.0}},"df":1}},"2":{"docs":{"62":{"tf":1.4142135623730951}},"df":1,"8":{"docs":{"72":{"tf":1.0}},"df":1}},"6":{"docs":{},"df":0,"7":{"docs":{"62":{"tf":1.0}},"df":1}}},"6":{"docs":{"188":{"tf":1.0},"53":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0}},"df":4,".":{"docs":{},"df":0,"2":{"docs":{"11":{"tf":1.0}},"df":1}},"1":{"docs":{"169":{"tf":1.0}},"df":1},"2":{"docs":{"170":{"tf":1.0}},"df":1},"4":{"docs":{"52":{"tf":1.0},"87":{"tf":1.0}},"df":2,"k":{"docs":{"61":{"tf":1.0}},"df":1}},"5":{"docs":{},"df":0,"6":{"docs":{"62":{"tf":1.0}},"df":1},"7":{"docs":{"62":{"tf":1.0}},"df":1},"8":{"docs":{"62":{"tf":1.0}},"df":1},"9":{"docs":{"62":{"tf":1.0}},"df":1},"a":{"docs":{"62":{"tf":1.0}},"df":1},"c":{"docs":{"62":{"tf":1.0}},"df":1}},"6":{"docs":{},"df":0,"0":{"docs":{"62":{"tf":1.0}},"df":1},"2":{"docs":{"62":{"tf":1.0}},"df":1},"3":{"docs":{"62":{"tf":1.0}},"df":1}}},"7":{"docs":{"49":{"tf":1.0},"64":{"tf":1.0}},"df":2,".":{"docs":{},"df":0,"1":{"docs":{},"df":0,"0":{"docs":{"19":{"tf":1.0}},"df":1},"1":{"docs":{"19":{"tf":1.0}},"df":1},"2":{"docs":{"19":{"tf":1.4142135623730951}},"df":1}}},"2":{"docs":{"11":{"tf":1.0}},"df":1},"4":{"docs":{},"df":0,"6":{"docs":{},"df":0,"8":{"docs":{"68":{"tf":1.0}},"df":1}}},"5":{"docs":{"190":{"tf":1.0}},"df":1},"f":{"docs":{"62":{"tf":1.0}},"df":1}},"8":{"docs":{"11":{"tf":1.0},"12":{"tf":1.0},"134":{"tf":1.4142135623730951},"64":{"tf":1.0},"88":{"tf":1.0}},"df":5,".":{"docs":{},"df":0,"1":{"docs":{"19":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"0":{"docs":{},"df":0,".":{"docs":{},"df":0,"2":{"docs":{},"df":0,"0":{"docs":{},"df":0,"1":{"docs":{},"df":0,"8":{"docs":{},"df":0,"0":{"docs":{},"df":0,"3":{"docs":{},"df":0,"1":{"docs":{},"df":0,"5":{"docs":{"49":{"tf":1.0}},"df":1}}}}}}}}}}}}},"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"9":{"docs":{},"df":0,"4":{"docs":{},"df":0,"2":{"docs":{"83":{"tf":1.0}},"df":1},"6":{"docs":{"83":{"tf":1.0}},"df":1},"a":{"docs":{"83":{"tf":1.0}},"df":1},"c":{"docs":{"83":{"tf":1.0}},"df":1}}}}},"m":{"docs":{},"df":0,"h":{"docs":{},"df":0,"z":{"docs":{"72":{"tf":1.0}},"df":1}}}},"6":{"docs":{},"df":0,"7":{"docs":{"62":{"tf":1.0}},"df":1}}},"9":{"docs":{"64":{"tf":1.0},"81":{"tf":1.4142135623730951}},"df":2,"0":{"docs":{},"df":0,"6":{"docs":{},"df":0,"0":{"docs":{"188":{"tf":1.0}},"df":1}}},"2":{"docs":{"62":{"tf":1.0}},"df":1},"5":{"docs":{},"df":0,"0":{"docs":{"53":{"tf":1.7320508075688772},"68":{"tf":1.7320508075688772}},"df":2}}},"_":{"docs":{"101":{"tf":1.4142135623730951},"109":{"tf":1.4142135623730951},"111":{"tf":2.0},"133":{"tf":1.4142135623730951},"134":{"tf":1.0},"191":{"tf":1.0},"60":{"tf":1.4142135623730951},"63":{"tf":1.4142135623730951},"64":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.7320508075688772},"78":{"tf":2.0},"79":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0},"98":{"tf":1.0}},"df":18,"_":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{"62":{"tf":1.0}},"df":1}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"62":{"tf":1.0}},"df":1}}}}}}}}},"c":{"docs":{"125":{"tf":1.4142135623730951}},"df":1},"p":{"docs":{"155":{"tf":1.7320508075688772}},"df":1},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"61":{"tf":1.0}},"df":1}}}}}}}}},"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"t":{"docs":{"61":{"tf":1.0}},"df":1}}}}},"y":{"docs":{"79":{"tf":1.0}},"df":1}},"a":{"docs":{},"df":0,"/":{"docs":{},"df":0,"b":{"docs":{"44":{"tf":1.0}},"df":1}},"5":{"docs":{},"df":0,"3":{"docs":{"12":{"tf":1.0}},"df":1}},"b":{"docs":{},"df":0,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{},"df":0,"i":{"docs":{"192":{"tf":1.0}},"df":1}}}}},"i":{"docs":{"171":{"tf":1.4142135623730951},"173":{"tf":1.0},"181":{"tf":1.0},"183":{"tf":1.7320508075688772},"62":{"tf":1.0}},"df":5,"l":{"docs":{"111":{"tf":1.0},"128":{"tf":1.0}},"df":2}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"78":{"tf":2.0}},"df":1}},"v":{"docs":{"100":{"tf":1.0},"107":{"tf":1.4142135623730951},"116":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"159":{"tf":1.0},"165":{"tf":1.0},"173":{"tf":1.0},"175":{"tf":1.0},"5":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0},"72":{"tf":1.0},"77":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.0}},"df":19}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"80":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"11":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"100":{"tf":1.0},"111":{"tf":1.0},"112":{"tf":1.0},"113":{"tf":1.0},"114":{"tf":1.7320508075688772},"120":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.4142135623730951},"127":{"tf":1.0},"141":{"tf":1.0},"15":{"tf":1.0},"153":{"tf":1.0},"165":{"tf":1.0},"190":{"tf":1.4142135623730951},"195":{"tf":1.0},"197":{"tf":1.0},"70":{"tf":1.0}},"df":17}}}}}}},"c":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"11":{"tf":1.0},"118":{"tf":1.0}},"df":2}}}}}}},"p":{"docs":{},"df":0,"t":{"docs":{"126":{"tf":1.0},"93":{"tf":1.0}},"df":2}},"s":{"docs":{},"df":0,"s":{"docs":{"101":{"tf":1.4142135623730951},"103":{"tf":1.0},"11":{"tf":1.4142135623730951},"112":{"tf":1.0},"114":{"tf":1.0},"117":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":2.0},"123":{"tf":1.7320508075688772},"125":{"tf":1.7320508075688772},"126":{"tf":2.0},"127":{"tf":2.449489742783178},"128":{"tf":1.4142135623730951},"142":{"tf":1.0},"144":{"tf":1.0},"147":{"tf":1.7320508075688772},"15":{"tf":1.0},"163":{"tf":1.7320508075688772},"164":{"tf":1.7320508075688772},"165":{"tf":2.23606797749979},"195":{"tf":1.0},"197":{"tf":1.4142135623730951},"36":{"tf":1.0},"69":{"tf":1.7320508075688772},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.7320508075688772},"73":{"tf":1.0},"74":{"tf":1.0},"79":{"tf":1.0},"80":{"tf":1.4142135623730951},"87":{"tf":1.4142135623730951},"92":{"tf":2.0},"95":{"tf":1.4142135623730951}},"df":34,"o":{"docs":{},"df":0,"r":{"docs":{"72":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"78":{"tf":1.0}},"df":1}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0},"84":{"tf":1.0}},"df":2}}}},"u":{"docs":{},"df":0,"r":{"docs":{"62":{"tf":1.0}},"df":1}}},"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{"119":{"tf":1.0},"137":{"tf":1.0}},"df":2}}}},"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{"126":{"tf":1.4142135623730951}},"df":1}}}},"t":{"docs":{"112":{"tf":1.0},"142":{"tf":1.0},"87":{"tf":1.0}},"df":3,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.0},"105":{"tf":1.0},"87":{"tf":1.0}},"df":3}},"v":{"docs":{"68":{"tf":1.0},"76":{"tf":1.0},"87":{"tf":1.0}},"df":3}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"11":{"tf":1.0},"111":{"tf":1.4142135623730951},"112":{"tf":1.0},"122":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.0},"137":{"tf":1.0},"147":{"tf":1.0},"160":{"tf":1.0},"187":{"tf":1.0},"63":{"tf":1.0},"82":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":1.4142135623730951},"87":{"tf":1.0},"92":{"tf":1.4142135623730951}},"df":16},"t":{"docs":{"118":{"tf":1.0}},"df":1}}}}},"d":{"docs":{"61":{"tf":1.0},"8":{"tf":1.0}},"df":2,"a":{"docs":{"4":{"tf":1.0}},"df":1,"p":{"docs":{},"df":0,"t":{"docs":{"117":{"tf":1.4142135623730951},"119":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0}},"df":4,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}}},"d":{"docs":{"124":{"tf":1.0},"131":{"tf":1.0},"150":{"tf":1.0},"155":{"tf":1.0},"161":{"tf":1.0},"21":{"tf":1.0},"38":{"tf":2.8284271247461903},"39":{"tf":1.0},"49":{"tf":1.0},"6":{"tf":1.0},"61":{"tf":1.4142135623730951},"63":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.0}},"df":14,"i":{"docs":{},"df":0,"t":{"docs":{"115":{"tf":1.4142135623730951},"128":{"tf":1.0},"141":{"tf":1.0},"150":{"tf":1.0},"155":{"tf":1.4142135623730951},"158":{"tf":1.0},"160":{"tf":1.0},"20":{"tf":1.0},"56":{"tf":1.0}},"df":9,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.0},"102":{"tf":1.0},"105":{"tf":1.0},"137":{"tf":1.0},"155":{"tf":1.0},"158":{"tf":1.0},"24":{"tf":1.0}},"df":7}}}}},"r":{"docs":{"188":{"tf":1.4142135623730951},"62":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"157":{"tf":1.0},"166":{"tf":1.4142135623730951},"62":{"tf":1.0},"66":{"tf":2.0},"68":{"tf":1.7320508075688772},"80":{"tf":1.0},"86":{"tf":1.0},"87":{"tf":3.4641016151377544},"88":{"tf":1.7320508075688772}},"df":9}}}}},"j":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"20":{"tf":1.0},"61":{"tf":1.0}},"df":2}}}},"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"191":{"tf":1.0},"30":{"tf":1.0},"35":{"tf":1.0},"68":{"tf":1.0},"84":{"tf":1.0}},"df":5},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"1":{"tf":1.0},"128":{"tf":1.0},"21":{"tf":1.0}},"df":3}}}}}}},"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"123":{"tf":1.0},"124":{"tf":1.0},"186":{"tf":1.0}},"df":3}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"189":{"tf":1.0},"36":{"tf":1.0}},"df":2}}}}},"g":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"188":{"tf":1.0},"44":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.0},"74":{"tf":1.0},"80":{"tf":1.0}},"df":6,"s":{"docs":{},"df":0,"t":{"docs":{"161":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"14":{"tf":1.0},"16":{"tf":1.0},"37":{"tf":1.0},"70":{"tf":1.0}},"df":4}}}}},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"175":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"m":{"docs":{"140":{"tf":1.0},"144":{"tf":1.0},"26":{"tf":1.0},"70":{"tf":1.0}},"df":4}},"k":{"docs":{},"df":0,"a":{"docs":{"132":{"tf":1.4142135623730951},"187":{"tf":1.0},"82":{"tf":1.0}},"df":3}},"l":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{"191":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"a":{"docs":{"168":{"tf":1.0}},"df":1},"g":{"docs":{},"df":0,"n":{"docs":{"133":{"tf":2.0},"142":{"tf":1.0},"166":{"tf":3.1622776601683795},"29":{"tf":1.0}},"df":4,"(":{"docs":{},"df":0,"4":{"docs":{"61":{"tf":1.4142135623730951}},"df":1}},"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"k":{"docs":{"133":{"tf":1.4142135623730951}},"df":1}}}}}}},"k":{"docs":{"36":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{"122":{"tf":1.4142135623730951},"132":{"tf":2.0},"133":{"tf":3.872983346207417},"134":{"tf":2.23606797749979},"135":{"tf":1.0},"136":{"tf":2.0},"137":{"tf":2.23606797749979},"138":{"tf":1.4142135623730951},"139":{"tf":2.0},"14":{"tf":1.4142135623730951},"168":{"tf":1.0},"17":{"tf":2.0},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"78":{"tf":1.0}},"df":15,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"133":{"tf":1.0}},"df":1}}}}}},":":{"docs":{},"df":0,":":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"168":{"tf":1.0}},"df":1}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,".":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{"136":{"tf":1.0},"138":{"tf":1.0}},"df":2}}}}},":":{"docs":{},"df":0,":":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}}}},"_":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{"133":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}},"w":{"docs":{"102":{"tf":1.4142135623730951},"105":{"tf":1.0},"107":{"tf":1.4142135623730951},"114":{"tf":1.0},"118":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.4142135623730951},"154":{"tf":1.0},"158":{"tf":1.0},"164":{"tf":1.0},"180":{"tf":1.0},"26":{"tf":1.0},"28":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":1.4142135623730951},"91":{"tf":1.0},"99":{"tf":1.4142135623730951}},"df":19,"(":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{"146":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0}},"df":6}}}}}}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"11":{"tf":1.0},"126":{"tf":1.0},"14":{"tf":1.0},"174":{"tf":1.0},"19":{"tf":1.0}},"df":5,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"159":{"tf":1.0},"188":{"tf":1.0},"24":{"tf":1.0}},"df":3}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{"104":{"tf":1.0},"126":{"tf":1.0},"147":{"tf":1.0},"156":{"tf":1.0},"175":{"tf":1.0},"64":{"tf":1.0},"69":{"tf":1.0},"77":{"tf":1.0},"96":{"tf":1.0}},"df":9}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"n":{"docs":{"103":{"tf":1.0},"124":{"tf":1.0},"128":{"tf":1.0},"157":{"tf":1.0},"68":{"tf":1.0},"76":{"tf":1.0}},"df":6}}},"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"100":{"tf":1.0},"104":{"tf":1.0},"107":{"tf":1.0},"112":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"87":{"tf":1.0},"99":{"tf":1.0}},"df":8}}}}}},"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"122":{"tf":1.0},"126":{"tf":1.0},"128":{"tf":1.4142135623730951},"136":{"tf":1.0},"14":{"tf":1.0},"147":{"tf":1.0},"164":{"tf":1.0},"166":{"tf":1.0},"168":{"tf":1.0},"173":{"tf":1.0},"62":{"tf":1.0},"84":{"tf":1.4142135623730951},"95":{"tf":1.0},"98":{"tf":1.0}},"df":14}}}},"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"87":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"g":{"docs":{"115":{"tf":1.0}},"df":1}},"y":{"docs":{},"df":0,"s":{"docs":{"184":{"tf":1.0}},"df":1,"i":{"docs":{"111":{"tf":1.0},"137":{"tf":1.0},"30":{"tf":1.0}},"df":3}},"z":{"docs":{"137":{"tf":1.0},"32":{"tf":1.0}},"df":2}}}},"d":{"docs":{},"df":0,"/":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"184":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{"105":{"tf":1.0},"108":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"130":{"tf":1.0},"158":{"tf":1.0},"4":{"tf":1.0},"60":{"tf":1.0},"64":{"tf":1.4142135623730951},"66":{"tf":1.0},"68":{"tf":1.4142135623730951},"84":{"tf":1.0},"87":{"tf":1.0}},"df":13}}},"s":{"docs":{},"df":0,"w":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"61":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"i":{"docs":{"163":{"tf":1.0}},"df":1}},"y":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{"127":{"tf":1.0},"136":{"tf":1.0},"16":{"tf":1.0},"5":{"tf":1.0},"64":{"tf":1.0},"78":{"tf":1.0}},"df":6}},"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"123":{"tf":1.0},"68":{"tf":1.0}},"df":2}},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"125":{"tf":1.0},"92":{"tf":1.0}},"df":2}}}}}},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"9":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.0},"179":{"tf":1.0}},"df":2}}},"i":{"docs":{"103":{"tf":1.0},"115":{"tf":1.4142135623730951},"128":{"tf":1.4142135623730951},"134":{"tf":1.0},"139":{"tf":1.7320508075688772},"141":{"tf":1.0},"155":{"tf":1.4142135623730951},"16":{"tf":1.7320508075688772},"171":{"tf":1.0},"179":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.0},"53":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951},"69":{"tf":1.0},"71":{"tf":1.4142135623730951},"76":{"tf":2.0},"77":{"tf":1.0},"86":{"tf":1.0},"88":{"tf":1.0},"93":{"tf":1.4142135623730951}},"df":21},"p":{"docs":{"100":{"tf":1.0},"188":{"tf":2.23606797749979},"55":{"tf":1.7320508075688772},"57":{"tf":1.7320508075688772},"58":{"tf":2.0},"59":{"tf":1.4142135623730951},"62":{"tf":2.6457513110645907},"63":{"tf":1.0},"67":{"tf":1.7320508075688772},"83":{"tf":1.0}},"df":10,"a":{"docs":{},"df":0,"r":{"docs":{"137":{"tf":1.0}},"df":1}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"78":{"tf":1.0}},"df":1}},"n":{"docs":{},"df":0,"d":{"docs":{"190":{"tf":1.0},"44":{"tf":1.0}},"df":2}}},"l":{"docs":{},"df":0,"i":{"docs":{"103":{"tf":1.4142135623730951},"11":{"tf":1.0},"12":{"tf":1.0},"158":{"tf":1.0},"63":{"tf":1.0},"86":{"tf":1.0}},"df":6,"c":{"docs":{"102":{"tf":1.4142135623730951},"114":{"tf":1.0},"115":{"tf":2.0},"119":{"tf":1.4142135623730951},"125":{"tf":1.7320508075688772},"130":{"tf":1.0},"138":{"tf":1.4142135623730951},"148":{"tf":1.0},"151":{"tf":1.0},"154":{"tf":1.0},"183":{"tf":1.0},"188":{"tf":1.0},"33":{"tf":1.0},"4":{"tf":1.0},"56":{"tf":1.7320508075688772},"78":{"tf":1.4142135623730951}},"df":16}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"114":{"tf":1.4142135623730951},"115":{"tf":1.0},"121":{"tf":1.0},"123":{"tf":1.0},"129":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0}},"df":7}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"101":{"tf":1.0},"142":{"tf":1.0},"160":{"tf":1.0},"69":{"tf":1.0},"76":{"tf":1.0},"80":{"tf":1.0},"9":{"tf":1.0}},"df":7}}}}}},"t":{"docs":{"43":{"tf":1.4142135623730951}},"df":1}},"r":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"160":{"tf":1.0},"87":{"tf":1.0}},"df":2}}}}}}},"c":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"104":{"tf":1.0}},"df":1}},"h":{"docs":{"43":{"tf":1.0}},"df":1,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"129":{"tf":1.0},"158":{"tf":1.0},"19":{"tf":1.0},"2":{"tf":1.7320508075688772},"21":{"tf":1.0},"30":{"tf":1.0},"38":{"tf":2.8284271247461903},"61":{"tf":1.4142135623730951},"69":{"tf":1.0},"7":{"tf":1.4142135623730951},"70":{"tf":1.0},"84":{"tf":1.0}},"df":12}}}}}},"v":{"docs":{"175":{"tf":1.7320508075688772},"178":{"tf":1.0}},"df":2}}}},"e":{"docs":{},"df":0,"a":{"docs":{"130":{"tf":1.0}},"df":1}},"g":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"15":{"tf":1.0},"173":{"tf":1.4142135623730951},"187":{"tf":1.0},"62":{"tf":1.0},"72":{"tf":1.4142135623730951},"74":{"tf":1.4142135623730951},"75":{"tf":1.7320508075688772},"82":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0},"93":{"tf":1.0}},"df":11}}}}}},"m":{"docs":{"11":{"tf":1.0},"19":{"tf":1.7320508075688772},"190":{"tf":1.0},"199":{"tf":1.0},"2":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"30":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"38":{"tf":1.0},"43":{"tf":3.3166247903554},"46":{"tf":1.0},"47":{"tf":1.0},"49":{"tf":1.7320508075688772},"62":{"tf":1.7320508075688772},"63":{"tf":2.23606797749979},"64":{"tf":2.0},"66":{"tf":1.4142135623730951},"68":{"tf":2.449489742783178},"7":{"tf":1.0},"71":{"tf":1.0},"77":{"tf":2.23606797749979},"78":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0},"90":{"tf":1.4142135623730951}},"df":28,".":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"62":{"tf":1.4142135623730951}},"df":1}}}}}}}}},"v":{"docs":{},"df":0,"6":{"docs":{"38":{"tf":1.0}},"df":1},"7":{"docs":{"38":{"tf":1.7320508075688772}},"df":1},"8":{"docs":{"38":{"tf":1.7320508075688772}},"df":1}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"124":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.0},"69":{"tf":1.0},"96":{"tf":1.0}},"df":5}}}},"r":{"docs":{"163":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"163":{"tf":1.0}},"df":1}}},"[":{"docs":{},"df":0,"1":{"docs":{},"df":0,"6":{"docs":{"163":{"tf":1.0}},"df":1}}},"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"11":{"tf":1.0},"91":{"tf":1.0}},"df":2}},"y":{"docs":{"118":{"tf":1.0},"157":{"tf":1.0},"159":{"tf":1.0},"163":{"tf":2.0},"189":{"tf":1.0},"79":{"tf":1.0}},"df":6,"_":{"docs":{},"df":0,"s":{"docs":{"159":{"tf":1.7320508075688772}},"df":1}}}}}},"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{"127":{"tf":1.0},"190":{"tf":1.0}},"df":2}}}},"k":{"docs":{"5":{"tf":1.0}},"df":1},"m":{"docs":{"68":{"tf":1.0}},"df":1,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"b":{"docs":{},"df":0,"k":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"112":{"tf":1.0},"62":{"tf":1.0},"72":{"tf":1.0},"88":{"tf":1.0}},"df":4}}},"r":{"docs":{},"df":0,"t":{"docs":{"77":{"tf":1.0}},"df":1,"!":{"docs":{},"df":0,"(":{"docs":{},"df":0,"x":{"docs":{},"df":0,"s":{"docs":{},"df":0,".":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}},"_":{"docs":{},"df":0,"e":{"docs":{},"df":0,"q":{"docs":{},"df":0,"!":{"docs":{},"df":0,"(":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{"77":{"tf":1.0}},"df":1}}},"x":{"docs":{},"df":0,"s":{"docs":{},"df":0,".":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{"134":{"tf":1.0}},"df":1}}}}}}}}}}}}}},"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{"153":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{"120":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.0}},"df":3}}},"u":{"docs":{},"df":0,"m":{"docs":{"124":{"tf":1.0},"127":{"tf":1.4142135623730951},"131":{"tf":1.0},"190":{"tf":1.0},"2":{"tf":1.0},"61":{"tf":1.0},"7":{"tf":1.0},"72":{"tf":1.0},"80":{"tf":1.0}},"df":9,"p":{"docs":{},"df":0,"t":{"docs":{"16":{"tf":1.0},"3":{"tf":1.0}},"df":2}}}}},"y":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"128":{"tf":1.4142135623730951},"129":{"tf":1.0}},"df":2,"h":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"128":{"tf":1.0},"129":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":1.0},"80":{"tf":1.0}},"df":5}}}}}}}},"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"122":{"tf":1.0},"124":{"tf":2.8284271247461903},"125":{"tf":1.0},"131":{"tf":1.4142135623730951},"16":{"tf":1.0},"165":{"tf":1.0},"80":{"tf":1.0}},"df":7,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{"124":{"tf":1.4142135623730951}},"df":1,"i":{"docs":{},"df":0,"z":{"docs":{},"df":0,"e":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"0":{"docs":{"124":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"124":{"tf":1.0},"126":{"tf":1.0},"192":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.0},"84":{"tf":1.0}},"df":6}}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.4142135623730951},"158":{"tf":1.0},"16":{"tf":1.0},"160":{"tf":1.0},"166":{"tf":1.0},"173":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"80":{"tf":1.7320508075688772},"82":{"tf":1.4142135623730951},"84":{"tf":2.23606797749979}},"df":11}}}},"s":{"docs":{},"df":0,"{":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{},"df":0,"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"}":{"docs":{},"df":0,"=":{"docs":{},"df":0,"=":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"3":{"docs":{},"df":0,"7":{"docs":{},"df":0,"4":{"docs":{},"df":0,"8":{"docs":{"44":{"tf":1.0}},"df":1},"b":{"docs":{"44":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"}":{"docs":{},"df":0,"=":{"docs":{},"df":0,"=":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"0":{"docs":{},"df":0,"4":{"docs":{},"df":0,"8":{"docs":{},"df":0,"3":{"docs":{"44":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}}}}}}},"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"58":{"tf":1.7320508075688772},"93":{"tf":1.4142135623730951}},"df":2}}},"o":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0},"72":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":4,"m":{"docs":{"184":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"t":{"docs":{"124":{"tf":1.0},"125":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"162":{"tf":1.0},"165":{"tf":1.4142135623730951},"174":{"tf":1.0},"61":{"tf":1.0},"68":{"tf":1.0},"76":{"tf":1.0},"88":{"tf":1.0},"92":{"tf":1.0}},"df":13}}}}}},"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"115":{"tf":1.0},"119":{"tf":1.0},"124":{"tf":1.0},"132":{"tf":1.0},"137":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"159":{"tf":1.0},"165":{"tf":1.0},"168":{"tf":1.0},"17":{"tf":1.7320508075688772},"191":{"tf":1.7320508075688772},"53":{"tf":1.0},"68":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"84":{"tf":1.4142135623730951},"9":{"tf":1.0}},"df":18}}},"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"123":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"150":{"tf":1.0},"157":{"tf":1.0},"158":{"tf":1.0},"55":{"tf":1.0},"86":{"tf":1.0}},"df":8}}}},"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"129":{"tf":1.0}},"df":1}},"r":{"docs":{"160":{"tf":1.0}},"df":1},"y":{"docs":{"112":{"tf":1.0},"121":{"tf":1.0}},"df":2}}}},"b":{"docs":{"104":{"tf":1.7320508075688772},"12":{"tf":1.0},"154":{"tf":1.0},"21":{"tf":1.0},"62":{"tf":2.0},"68":{"tf":1.0},"83":{"tf":1.0}},"df":7,"6":{"docs":{},"df":0,"c":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"9":{"docs":{},"df":0,"b":{"docs":{"38":{"tf":1.0}},"df":1}}}}}}}},"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"122":{"tf":1.4142135623730951},"146":{"tf":1.0},"7":{"tf":1.0},"75":{"tf":1.0}},"df":4,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"21":{"tf":1.0}},"df":1}}},"g":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"3":{"tf":1.4142135623730951}},"df":1}}}}}}}},"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"w":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{"38":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{"0":{"tf":1.0},"102":{"tf":1.0},"14":{"tf":1.4142135623730951},"187":{"tf":1.0},"20":{"tf":1.0},"5":{"tf":1.4142135623730951}},"df":6,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"56":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"124":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"e":{"docs":{"130":{"tf":1.0},"147":{"tf":1.0},"158":{"tf":1.0},"191":{"tf":1.4142135623730951},"33":{"tf":1.0},"69":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951},"71":{"tf":1.0}},"df":8},"i":{"docs":{"136":{"tf":1.0}},"df":1,"c":{"docs":{"105":{"tf":1.0},"54":{"tf":1.0},"7":{"tf":1.0},"72":{"tf":1.0},"94":{"tf":1.0}},"df":5}}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"129":{"tf":1.0}},"df":1}}},"l":{"docs":{"133":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"d":{"docs":{"69":{"tf":1.0},"76":{"tf":1.7320508075688772}},"df":2}}},"e":{"docs":{"123":{"tf":1.0},"138":{"tf":1.0},"147":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.0},"82":{"tf":1.7320508075688772},"87":{"tf":1.0}},"df":7,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"102":{"tf":1.0},"131":{"tf":1.0},"184":{"tf":1.0},"80":{"tf":1.0}},"df":4}}},"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"104":{"tf":1.0},"108":{"tf":1.0},"110":{"tf":1.0},"122":{"tf":1.0},"127":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.4142135623730951},"17":{"tf":1.0},"172":{"tf":1.0},"176":{"tf":1.0},"178":{"tf":1.0},"49":{"tf":1.0},"64":{"tf":1.4142135623730951},"66":{"tf":1.0},"67":{"tf":1.4142135623730951},"68":{"tf":2.0},"76":{"tf":1.0},"78":{"tf":1.0},"83":{"tf":1.0}},"df":19}}},"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"66":{"tf":1.0}},"df":1}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"v":{"docs":{"164":{"tf":1.0},"28":{"tf":1.0}},"df":2,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"107":{"tf":1.0},"111":{"tf":1.0},"60":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":3.0},"79":{"tf":1.4142135623730951},"80":{"tf":1.7320508075688772},"83":{"tf":1.0}},"df":8},"u":{"docs":{},"df":0,"r":{"docs":{"122":{"tf":1.4142135623730951},"126":{"tf":1.0},"166":{"tf":1.0}},"df":3}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"164":{"tf":1.0}},"df":1}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{"3":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"w":{"docs":{"125":{"tf":1.0},"188":{"tf":1.0},"19":{"tf":1.4142135623730951},"190":{"tf":1.0},"38":{"tf":1.0},"44":{"tf":1.0},"53":{"tf":1.0},"61":{"tf":1.4142135623730951},"77":{"tf":1.0}},"df":9}}},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"58":{"tf":1.0}},"df":1}},"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"115":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"t":{"docs":{"124":{"tf":1.0},"179":{"tf":1.0},"2":{"tf":1.4142135623730951},"38":{"tf":1.0}},"df":4}},"t":{"docs":{},"df":0,"a":{"docs":{"19":{"tf":1.0}},"df":1},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"109":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"158":{"tf":1.0},"165":{"tf":1.0},"188":{"tf":1.0},"192":{"tf":1.0},"5":{"tf":1.0}},"df":8}}},"w":{"docs":{},"df":0,"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"115":{"tf":1.0},"117":{"tf":1.0},"119":{"tf":1.0},"120":{"tf":1.0},"121":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.0},"130":{"tf":1.0},"134":{"tf":1.0},"135":{"tf":1.0},"137":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.4142135623730951},"168":{"tf":1.4142135623730951},"181":{"tf":1.0},"24":{"tf":1.0},"27":{"tf":1.0},"32":{"tf":1.0},"7":{"tf":1.4142135623730951},"70":{"tf":1.0},"87":{"tf":1.0}},"df":21}}}}},"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"188":{"tf":1.0}},"df":1}}},"y":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"131":{"tf":1.0},"35":{"tf":1.0},"79":{"tf":1.0}},"df":3}}}}},"i":{"docs":{},"df":0,"g":{"docs":{"119":{"tf":1.0},"189":{"tf":1.0},"62":{"tf":1.0}},"df":3,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"187":{"tf":1.0}},"df":1}}}}},"n":{"docs":{"188":{"tf":1.4142135623730951},"58":{"tf":1.0},"62":{"tf":2.23606797749979},"63":{"tf":1.0},"83":{"tf":1.0}},"df":5,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"161":{"tf":1.0},"173":{"tf":1.0},"178":{"tf":1.0},"186":{"tf":1.0},"187":{"tf":2.0},"189":{"tf":1.0},"190":{"tf":1.7320508075688772},"21":{"tf":1.0},"30":{"tf":1.0},"50":{"tf":1.7320508075688772},"62":{"tf":2.8284271247461903},"63":{"tf":2.0},"67":{"tf":1.0},"78":{"tf":1.0}},"df":14}}},"d":{"docs":{"119":{"tf":1.0},"174":{"tf":1.0},"191":{"tf":1.0}},"df":3,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"174":{"tf":2.23606797749979},"176":{"tf":1.0}},"df":2}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"s":{"docs":{},"df":0,".":{"docs":{},"df":0,"h":{"docs":{"174":{"tf":1.4142135623730951}},"df":1},"r":{"docs":{"174":{"tf":1.0}},"df":1}}}}}}},"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"19":{"tf":1.0},"21":{"tf":1.4142135623730951},"39":{"tf":1.0},"62":{"tf":1.0},"67":{"tf":1.0}},"df":5}}}}},"t":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"114":{"tf":1.0},"12":{"tf":1.4142135623730951},"168":{"tf":1.0},"52":{"tf":1.4142135623730951},"53":{"tf":1.0},"60":{"tf":1.4142135623730951},"68":{"tf":1.0},"72":{"tf":1.7320508075688772},"75":{"tf":1.0},"83":{"tf":1.4142135623730951},"87":{"tf":1.0},"88":{"tf":1.7320508075688772},"90":{"tf":2.0},"91":{"tf":1.0}},"df":16,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"l":{"docs":{"62":{"tf":1.4142135623730951}},"df":1,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"k":{"docs":{"69":{"tf":1.0},"70":{"tf":1.0}},"df":2}}},"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"125":{"tf":2.0},"126":{"tf":1.7320508075688772},"157":{"tf":1.0},"158":{"tf":1.7320508075688772},"165":{"tf":1.0},"53":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":1.0},"80":{"tf":1.4142135623730951},"81":{"tf":1.0}},"df":11}}},"u":{"docs":{},"df":0,"e":{"docs":{"77":{"tf":1.7320508075688772}},"df":1,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{"70":{"tf":1.0}},"df":1}}}}}}}},"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"11":{"tf":2.23606797749979},"193":{"tf":1.4142135623730951},"34":{"tf":1.0},"38":{"tf":1.0},"44":{"tf":1.4142135623730951},"53":{"tf":2.0},"63":{"tf":1.0},"66":{"tf":1.0},"68":{"tf":2.0},"69":{"tf":1.7320508075688772},"7":{"tf":1.7320508075688772},"70":{"tf":2.8284271247461903},"81":{"tf":1.0},"86":{"tf":1.0}},"df":14}}},"d":{"docs":{},"df":0,"i":{"docs":{"173":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"l":{"docs":{"112":{"tf":1.0}},"df":1}},"o":{"docs":{},"df":0,"k":{"docs":{"0":{"tf":1.4142135623730951},"125":{"tf":1.0},"129":{"tf":1.0},"131":{"tf":1.0},"163":{"tf":1.0},"167":{"tf":1.0},"19":{"tf":1.0},"2":{"tf":1.7320508075688772},"22":{"tf":1.0},"3":{"tf":1.7320508075688772},"38":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":2.23606797749979},"6":{"tf":1.0},"60":{"tf":1.0},"7":{"tf":1.7320508075688772},"70":{"tf":1.7320508075688772},"77":{"tf":1.0},"8":{"tf":2.0},"84":{"tf":1.0},"9":{"tf":2.23606797749979}},"df":21,"s":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"5":{"tf":1.0}},"df":1}}}}}},"l":{"docs":{"100":{"tf":1.4142135623730951},"102":{"tf":1.0},"107":{"tf":2.0},"108":{"tf":1.7320508075688772},"109":{"tf":1.4142135623730951},"165":{"tf":1.4142135623730951}},"df":6},"t":{"docs":{"64":{"tf":1.0},"67":{"tf":1.0}},"df":2,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"16":{"tf":1.0},"17":{"tf":1.0}},"df":2}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"16":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"101":{"tf":1.0},"127":{"tf":2.0},"190":{"tf":1.0},"76":{"tf":1.4142135623730951},"96":{"tf":1.4142135623730951},"98":{"tf":1.0},"99":{"tf":1.0}},"df":7,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}},"t":{"docs":{},"df":0,"h":{"docs":{"115":{"tf":1.0},"122":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.4142135623730951},"127":{"tf":1.0},"138":{"tf":1.0},"155":{"tf":1.0},"168":{"tf":1.0},"175":{"tf":1.0},"186":{"tf":1.0},"189":{"tf":1.0},"2":{"tf":1.0},"21":{"tf":1.0},"34":{"tf":1.0},"68":{"tf":1.0},"84":{"tf":1.0},"9":{"tf":1.0}},"df":17},"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"126":{"tf":1.0},"70":{"tf":1.0}},"df":2}}}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"118":{"tf":1.0},"155":{"tf":1.0},"163":{"tf":1.4142135623730951},"78":{"tf":1.0},"79":{"tf":1.4142135623730951}},"df":5,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"133":{"tf":1.0},"151":{"tf":1.0}},"df":2}}}}}},"x":{"docs":{},"df":0,"<":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"<":{"docs":{},"df":0,"_":{"docs":{"134":{"tf":1.0}},"df":1}}}}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"190":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{"127":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.7320508075688772},"68":{"tf":2.0}},"df":4,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"187":{"tf":1.0},"28":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"35":{"tf":1.0},"53":{"tf":1.7320508075688772},"64":{"tf":2.0},"68":{"tf":2.449489742783178},"78":{"tf":1.0},"82":{"tf":1.0}},"df":11,"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"28":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}},"w":{"docs":{"46":{"tf":2.0}},"df":1}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"125":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.0}},"df":3}}}},"w":{"docs":{},"df":0,"s":{"docs":{"59":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{"20":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"s":{"docs":{"188":{"tf":1.4142135623730951},"61":{"tf":1.0},"62":{"tf":1.4142135623730951}},"df":3}},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"17":{"tf":1.0}},"df":1}}}}}}},"u":{"docs":{"44":{"tf":1.4142135623730951},"69":{"tf":1.0},"86":{"tf":2.0}},"df":3,"f":{"docs":{"159":{"tf":1.0}},"df":1,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"164":{"tf":1.0}},"df":1}}}},"g":{"docs":{"120":{"tf":1.0},"28":{"tf":1.0},"53":{"tf":1.0},"62":{"tf":1.0},"68":{"tf":1.0},"8":{"tf":1.0}},"df":6},"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{"138":{"tf":1.0},"161":{"tf":3.3166247903554},"162":{"tf":1.7320508075688772},"169":{"tf":1.0},"171":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.7320508075688772},"178":{"tf":1.7320508075688772},"179":{"tf":1.4142135623730951},"183":{"tf":1.0},"184":{"tf":1.4142135623730951},"187":{"tf":1.4142135623730951},"189":{"tf":1.0},"39":{"tf":1.0},"54":{"tf":1.0},"61":{"tf":2.23606797749979},"63":{"tf":1.4142135623730951},"67":{"tf":2.449489742783178},"68":{"tf":1.0},"7":{"tf":1.0},"78":{"tf":1.4142135623730951}},"df":22,".":{"docs":{},"df":0,"r":{"docs":{"161":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.4142135623730951},"177":{"tf":1.0},"178":{"tf":1.4142135623730951}},"df":5}},"e":{"docs":{},"df":0,"r":{"docs":{"104":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"y":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"x":{"docs":{},"df":0,"(":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"174":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"174":{"tf":1.0}},"df":1}}}}}}}}}}},"t":{"docs":{"161":{"tf":1.0},"176":{"tf":1.4142135623730951},"26":{"tf":1.0},"30":{"tf":1.0},"78":{"tf":1.7320508075688772}},"df":5}}},"m":{"docs":{},"df":0,"p":{"docs":{"133":{"tf":1.7320508075688772}},"df":1,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{"133":{"tf":2.23606797749979}},"df":1}}}}}}}}}}}}}},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"72":{"tf":1.0},"92":{"tf":1.0}},"df":2}}},"r":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"26":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"e":{"docs":{"119":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"59":{"tf":1.0},"69":{"tf":1.0}},"df":2}}}}},"x":{"docs":{"62":{"tf":1.4142135623730951}},"df":1},"y":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{"11":{"tf":1.0},"166":{"tf":2.0},"189":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":2.23606797749979},"67":{"tf":1.0}},"df":6,"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"68":{"tf":1.4142135623730951}},"df":1}}}}}}}}}},"c":{"docs":{"142":{"tf":2.8284271247461903},"154":{"tf":1.0},"156":{"tf":1.4142135623730951},"157":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.7320508075688772},"163":{"tf":1.7320508075688772},"164":{"tf":1.0},"165":{"tf":1.4142135623730951},"166":{"tf":2.0},"167":{"tf":1.7320508075688772},"168":{"tf":2.23606797749979},"171":{"tf":3.0},"172":{"tf":2.0},"173":{"tf":4.123105625617661},"174":{"tf":1.4142135623730951},"175":{"tf":1.7320508075688772},"178":{"tf":1.0},"179":{"tf":1.7320508075688772},"181":{"tf":2.0},"183":{"tf":1.4142135623730951},"184":{"tf":2.23606797749979},"187":{"tf":1.0},"190":{"tf":1.4142135623730951},"2":{"tf":1.0},"39":{"tf":1.0},"4":{"tf":1.4142135623730951},"44":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"75":{"tf":1.0},"88":{"tf":1.0},"91":{"tf":1.7320508075688772},"92":{"tf":1.0}},"df":35,"/":{"docs":{},"df":0,"c":{"docs":{"172":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.4142135623730951},"176":{"tf":1.0}},"df":4}},":":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{},"df":0,"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"x":{"docs":{},"df":0,"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"s":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"@":{"docs":{},"df":0,"x":{"docs":{},"df":0,"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"50":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"_":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{"168":{"tf":1.4142135623730951}},"df":1}}},"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"168":{"tf":1.4142135623730951}},"df":1}}}},"v":{"docs":{},"df":0,"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"168":{"tf":1.0}},"df":1}}}}},"a":{"docs":{"124":{"tf":1.4142135623730951}},"df":1,"b":{"docs":{},"df":0,"l":{"docs":{"53":{"tf":1.0}},"df":1}},"c":{"docs":{},"df":0,"h":{"docs":{"124":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{"191":{"tf":1.0},"76":{"tf":1.0}},"df":2}}},"i":{"docs":{},"df":0,"b":{"docs":{"91":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0}},"df":3,"r":{"docs":{"90":{"tf":1.0}},"df":1}}},"l":{"docs":{"100":{"tf":1.0},"101":{"tf":1.0},"105":{"tf":1.4142135623730951},"112":{"tf":1.4142135623730951},"114":{"tf":1.4142135623730951},"122":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.4142135623730951},"130":{"tf":1.0},"131":{"tf":1.0},"137":{"tf":1.0},"146":{"tf":1.0},"157":{"tf":1.0},"160":{"tf":1.0},"164":{"tf":1.0},"168":{"tf":1.0},"170":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"184":{"tf":1.7320508075688772},"187":{"tf":1.0},"190":{"tf":1.0},"57":{"tf":1.0},"61":{"tf":1.4142135623730951},"64":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.0},"76":{"tf":1.4142135623730951},"80":{"tf":2.0},"81":{"tf":1.0},"84":{"tf":1.4142135623730951},"88":{"tf":1.0},"93":{"tf":1.0},"99":{"tf":1.7320508075688772}},"df":41}},"n":{"docs":{},"df":0,"\'":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.7320508075688772}},"df":1}},"’":{"docs":{},"df":0,"t":{"docs":{"123":{"tf":1.0},"127":{"tf":1.0},"189":{"tf":1.0},"71":{"tf":1.0}},"df":4}}},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"114":{"tf":1.0},"115":{"tf":1.4142135623730951},"119":{"tf":1.0},"30":{"tf":1.0}},"df":4}},"c":{"docs":{"132":{"tf":1.0},"134":{"tf":2.449489742783178},"135":{"tf":1.0},"136":{"tf":1.0},"137":{"tf":2.23606797749979},"138":{"tf":1.7320508075688772},"139":{"tf":1.0}},"df":7}}},"r":{"docs":{},"df":0,"d":{"docs":{"86":{"tf":1.4142135623730951}},"df":1},"e":{"docs":{"11":{"tf":1.0},"122":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.0},"138":{"tf":1.0},"15":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"173":{"tf":1.0}},"df":11,"f":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"123":{"tf":1.0},"125":{"tf":1.4142135623730951}},"df":2}}}}}},"g":{"docs":{},"df":0,"o":{"docs":{"158":{"tf":1.4142135623730951},"160":{"tf":1.0},"161":{"tf":2.0},"162":{"tf":1.7320508075688772},"169":{"tf":1.0},"178":{"tf":1.0},"179":{"tf":1.4142135623730951},"180":{"tf":1.4142135623730951},"184":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.7320508075688772},"189":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":1.7320508075688772},"21":{"tf":1.4142135623730951},"39":{"tf":1.4142135623730951},"40":{"tf":1.7320508075688772},"57":{"tf":2.0},"61":{"tf":1.7320508075688772},"62":{"tf":2.8284271247461903},"63":{"tf":2.6457513110645907},"67":{"tf":2.8284271247461903},"68":{"tf":2.23606797749979},"77":{"tf":2.0},"78":{"tf":1.4142135623730951},"79":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0},"9":{"tf":1.0}},"df":29,".":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"l":{"docs":{"133":{"tf":1.0},"158":{"tf":1.0},"188":{"tf":1.0},"190":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"77":{"tf":1.0},"81":{"tf":1.0}},"df":8}}}}},"/":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,".":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"l":{"docs":{"190":{"tf":1.4142135623730951},"61":{"tf":1.7320508075688772},"63":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951},"77":{"tf":1.0}},"df":6}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"i":{"docs":{"86":{"tf":1.4142135623730951}},"df":1}}},"s":{"docs":{},"df":0,"e":{"docs":{"103":{"tf":1.0},"113":{"tf":1.0},"12":{"tf":1.0},"124":{"tf":1.0},"131":{"tf":1.0},"134":{"tf":1.0},"136":{"tf":1.4142135623730951},"138":{"tf":1.0},"146":{"tf":1.0},"157":{"tf":1.0},"160":{"tf":1.4142135623730951},"161":{"tf":1.0},"162":{"tf":1.0},"164":{"tf":1.0},"169":{"tf":1.0},"170":{"tf":1.0},"178":{"tf":1.0},"188":{"tf":1.0},"2":{"tf":1.0},"22":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":1.0},"79":{"tf":1.0},"87":{"tf":1.0},"99":{"tf":1.0}},"df":26}},"t":{"docs":{"67":{"tf":1.0},"68":{"tf":1.4142135623730951}},"df":2,"c":{"docs":{},"df":0,"h":{"docs":{"3":{"tf":1.4142135623730951},"63":{"tf":1.0},"82":{"tf":1.0}},"df":3}},"e":{"docs":{},"df":0,"r":{"docs":{"3":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"s":{"docs":{"107":{"tf":1.0},"122":{"tf":1.7320508075688772},"124":{"tf":1.0},"136":{"tf":1.0},"78":{"tf":1.4142135623730951},"83":{"tf":1.0},"84":{"tf":1.0}},"df":7},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"11":{"tf":1.0}},"df":1}}}}}},"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"184":{"tf":1.0}},"df":1}}}}}}},"c":{"docs":{"175":{"tf":1.0},"176":{"tf":1.0},"178":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}},"df":4,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"178":{"tf":1.0}},"df":1}}}}}}}}}}}}},"d":{"docs":{"57":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"63":{"tf":1.0},"67":{"tf":1.0}},"df":5,"y":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{"180":{"tf":1.0}},"df":1}}}}},"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{"126":{"tf":1.7320508075688772},"127":{"tf":1.0}},"df":2}},"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"53":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"103":{"tf":1.0},"107":{"tf":1.0},"111":{"tf":1.0},"115":{"tf":1.4142135623730951},"118":{"tf":1.0},"166":{"tf":1.0},"87":{"tf":1.0},"88":{"tf":1.0}},"df":8}}}}}},"f":{"docs":{},"df":0,"g":{"docs":{"158":{"tf":1.0}},"df":1,"(":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"_":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"78":{"tf":1.0}},"df":1}}}}}}}}}}}},"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"=":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{"158":{"tf":1.4142135623730951}},"df":1}}},"i":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{"158":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"159":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}},"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"_":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"78":{"tf":1.0}},"df":1}}}}}}}}}}}},"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"=":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"159":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"163":{"tf":1.4142135623730951}},"df":1}},"n":{"docs":{},"df":0,"c":{"docs":{"64":{"tf":1.0}},"df":1},"g":{"docs":{"102":{"tf":1.4142135623730951},"103":{"tf":1.0},"122":{"tf":1.0},"137":{"tf":1.0},"155":{"tf":1.0},"161":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.7320508075688772},"190":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"75":{"tf":1.0},"78":{"tf":1.0},"79":{"tf":1.0},"9":{"tf":1.4142135623730951},"95":{"tf":1.0}},"df":15}},"p":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"103":{"tf":1.0},"108":{"tf":1.0},"140":{"tf":1.0},"156":{"tf":1.0},"158":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"60":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"7":{"tf":2.0},"87":{"tf":1.0}},"df":14}}}},"r":{"docs":{"168":{"tf":1.7320508075688772},"173":{"tf":1.4142135623730951}},"df":2,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":1.0},"186":{"tf":1.0},"20":{"tf":1.0},"66":{"tf":1.0}},"df":4}}}}}}}}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"103":{"tf":2.0},"108":{"tf":1.4142135623730951},"110":{"tf":1.0},"115":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.0},"128":{"tf":1.0},"129":{"tf":1.0},"136":{"tf":1.0},"163":{"tf":1.4142135623730951},"166":{"tf":1.0},"3":{"tf":1.0},"44":{"tf":1.0},"53":{"tf":1.7320508075688772},"62":{"tf":1.0},"63":{"tf":1.0},"68":{"tf":1.7320508075688772},"72":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.0},"83":{"tf":1.0},"93":{"tf":1.0}},"df":22,"e":{"docs":{},"df":0,"r":{"docs":{"101":{"tf":1.0},"96":{"tf":1.4142135623730951},"98":{"tf":1.0},"99":{"tf":1.0}},"df":4}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"141":{"tf":1.0}},"df":1}}}}}}},"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"130":{"tf":1.0},"170":{"tf":1.0}},"df":2}}},"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{"6":{"tf":1.0}},"df":1}}},"p":{"docs":{"11":{"tf":1.7320508075688772},"144":{"tf":1.4142135623730951},"155":{"tf":1.4142135623730951},"50":{"tf":1.0},"53":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"72":{"tf":1.0},"73":{"tf":1.4142135623730951},"74":{"tf":1.4142135623730951},"76":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":2.0},"90":{"tf":1.0}},"df":15}},"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"119":{"tf":1.0},"124":{"tf":1.0},"34":{"tf":1.0}},"df":3}},"o":{"docs":{},"df":0,"s":{"docs":{"135":{"tf":1.0},"38":{"tf":1.0}},"df":2}},"s":{"docs":{},"df":0,"e":{"docs":{"79":{"tf":1.0}},"df":1,"n":{"docs":{"55":{"tf":1.0},"78":{"tf":1.0}},"df":2}}}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"k":{"docs":{"86":{"tf":1.0},"88":{"tf":1.0}},"df":2}}}},"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"196":{"tf":1.0},"86":{"tf":1.0}},"df":2}},"m":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"164":{"tf":1.0}},"df":1}}}}}}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"190":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"173":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"s":{"docs":{"12":{"tf":1.0},"5":{"tf":1.0},"62":{"tf":1.0},"97":{"tf":1.0}},"df":4,"i":{"docs":{},"df":0,"f":{"docs":{"12":{"tf":1.0}},"df":1}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"67":{"tf":1.0}},"df":1},"r":{"docs":{"127":{"tf":1.0},"147":{"tf":1.0},"78":{"tf":1.0},"8":{"tf":1.0},"84":{"tf":1.4142135623730951}},"df":5}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"92":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"59":{"tf":1.4142135623730951}},"df":1}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"64":{"tf":1.4142135623730951},"68":{"tf":1.0}},"df":2}}}},"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"11":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"76":{"tf":2.6457513110645907},"81":{"tf":1.0}},"df":5}},"n":{"docs":{},"df":0,"e":{"docs":{"58":{"tf":1.4142135623730951},"59":{"tf":1.0},"63":{"tf":1.0}},"df":3}},"s":{"docs":{},"df":0,"e":{"docs":{"13":{"tf":1.0},"139":{"tf":1.0},"64":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0}},"df":5,"r":{"docs":{"60":{"tf":1.0}},"df":1},"s":{"docs":{},"df":0,"t":{"docs":{"158":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"r":{"docs":{"190":{"tf":1.0},"72":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.4142135623730951}},"df":4}}}}},"m":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}},"a":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{"169":{"tf":1.0},"175":{"tf":1.0}},"df":2}}},"s":{"docs":{},"df":0,"i":{"docs":{"191":{"tf":1.0},"199":{"tf":1.0}},"df":2}}},"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{"100":{"tf":1.0},"101":{"tf":1.0},"102":{"tf":1.0},"108":{"tf":1.4142135623730951},"109":{"tf":1.0},"110":{"tf":1.0},"112":{"tf":1.7320508075688772},"12":{"tf":1.0},"120":{"tf":1.0},"122":{"tf":1.4142135623730951},"123":{"tf":2.0},"125":{"tf":2.449489742783178},"126":{"tf":1.4142135623730951},"127":{"tf":1.4142135623730951},"13":{"tf":1.0},"14":{"tf":1.0},"142":{"tf":1.0},"151":{"tf":1.0},"157":{"tf":1.0},"158":{"tf":2.449489742783178},"16":{"tf":1.4142135623730951},"160":{"tf":1.4142135623730951},"163":{"tf":1.0},"165":{"tf":1.7320508075688772},"166":{"tf":1.0},"168":{"tf":1.4142135623730951},"17":{"tf":1.4142135623730951},"171":{"tf":1.4142135623730951},"172":{"tf":1.4142135623730951},"173":{"tf":1.4142135623730951},"174":{"tf":2.0},"175":{"tf":2.8284271247461903},"176":{"tf":1.0},"179":{"tf":1.0},"181":{"tf":1.0},"182":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.0},"187":{"tf":1.4142135623730951},"188":{"tf":1.4142135623730951},"191":{"tf":1.4142135623730951},"24":{"tf":1.0},"26":{"tf":1.0},"28":{"tf":1.4142135623730951},"29":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"60":{"tf":1.4142135623730951},"63":{"tf":1.0},"64":{"tf":1.7320508075688772},"69":{"tf":1.4142135623730951},"72":{"tf":2.0},"78":{"tf":1.0},"80":{"tf":1.0},"9":{"tf":1.0},"92":{"tf":1.4142135623730951},"93":{"tf":2.0},"94":{"tf":1.0},"96":{"tf":1.0},"99":{"tf":1.0}},"df":60,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"188":{"tf":1.0}},"df":1}}}}},"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"132":{"tf":2.23606797749979},"133":{"tf":1.7320508075688772},"134":{"tf":3.4641016151377544},"135":{"tf":1.4142135623730951},"136":{"tf":2.449489742783178},"137":{"tf":3.1622776601683795},"138":{"tf":2.23606797749979},"139":{"tf":1.0},"140":{"tf":1.0},"156":{"tf":1.0},"169":{"tf":1.0},"17":{"tf":1.4142135623730951},"170":{"tf":1.0},"21":{"tf":1.0},"86":{"tf":1.0},"91":{"tf":1.0}},"df":16}}}}},"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"113":{"tf":1.0},"158":{"tf":1.0},"166":{"tf":1.4142135623730951},"169":{"tf":1.0},"171":{"tf":1.0},"175":{"tf":1.0},"33":{"tf":1.0}},"df":7}}},"e":{"docs":{"117":{"tf":1.0},"120":{"tf":1.0},"128":{"tf":1.0},"90":{"tf":1.0}},"df":4},"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"4":{"tf":1.4142135623730951},"5":{"tf":1.0}},"df":2}}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"15":{"tf":1.0},"177":{"tf":1.0},"21":{"tf":1.0},"42":{"tf":1.0},"43":{"tf":1.7320508075688772},"44":{"tf":1.4142135623730951},"53":{"tf":2.23606797749979},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"63":{"tf":2.23606797749979},"64":{"tf":2.449489742783178},"68":{"tf":3.0}},"df":12}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"63":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.4142135623730951}},"df":3}}},"i":{"docs":{},"df":0,"t":{"docs":{"161":{"tf":1.0},"53":{"tf":1.0}},"df":2}},"o":{"docs":{},"df":0,"n":{"docs":{"114":{"tf":1.0},"126":{"tf":1.4142135623730951},"129":{"tf":1.0},"130":{"tf":1.0},"131":{"tf":1.0},"132":{"tf":1.0},"141":{"tf":1.0},"142":{"tf":1.0},"15":{"tf":1.0},"157":{"tf":1.4142135623730951},"160":{"tf":1.0},"161":{"tf":1.0},"166":{"tf":1.0},"169":{"tf":1.0},"4":{"tf":1.0},"69":{"tf":1.7320508075688772},"71":{"tf":1.0},"78":{"tf":1.0},"9":{"tf":1.0},"90":{"tf":1.0}},"df":20,"l":{"docs":{},"df":0,"i":{"docs":{"165":{"tf":1.0},"175":{"tf":1.0},"66":{"tf":1.0},"78":{"tf":1.0}},"df":4}}}},"u":{"docs":{},"df":0,"n":{"docs":{"115":{"tf":1.0},"196":{"tf":1.0},"27":{"tf":1.0},"32":{"tf":1.0},"35":{"tf":1.0},"69":{"tf":1.0},"86":{"tf":1.0}},"df":7}}},"p":{"docs":{},"df":0,"a":{"docs":{"72":{"tf":1.0}},"df":1,"r":{"docs":{"103":{"tf":1.0},"124":{"tf":1.0},"132":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0}},"df":5},"s":{"docs":{},"df":0,"s":{"docs":{"11":{"tf":1.0},"70":{"tf":1.0}},"df":2}},"t":{"docs":{"166":{"tf":1.0},"173":{"tf":1.4142135623730951},"174":{"tf":1.0},"20":{"tf":1.0},"30":{"tf":1.0},"35":{"tf":1.0}},"df":6}},"i":{"docs":{},"df":0,"l":{"docs":{"102":{"tf":1.4142135623730951},"103":{"tf":1.7320508075688772},"110":{"tf":1.4142135623730951},"111":{"tf":1.0},"112":{"tf":1.0},"114":{"tf":1.0},"122":{"tf":1.0},"124":{"tf":1.4142135623730951},"125":{"tf":1.7320508075688772},"132":{"tf":1.0},"151":{"tf":2.23606797749979},"154":{"tf":1.0},"157":{"tf":1.4142135623730951},"158":{"tf":2.449489742783178},"159":{"tf":1.0},"160":{"tf":1.0},"162":{"tf":1.0},"163":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.4142135623730951},"168":{"tf":1.0},"171":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.7320508075688772},"175":{"tf":2.449489742783178},"176":{"tf":1.4142135623730951},"177":{"tf":1.4142135623730951},"178":{"tf":1.7320508075688772},"179":{"tf":1.0},"181":{"tf":1.0},"182":{"tf":1.4142135623730951},"183":{"tf":1.0},"19":{"tf":1.0},"38":{"tf":2.0},"4":{"tf":1.0},"50":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":2.23606797749979},"63":{"tf":2.0},"64":{"tf":1.0},"67":{"tf":1.7320508075688772},"72":{"tf":1.0},"78":{"tf":1.7320508075688772},"80":{"tf":1.0},"84":{"tf":1.4142135623730951},"91":{"tf":1.7320508075688772},"92":{"tf":1.7320508075688772},"93":{"tf":1.0}},"df":48,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{"178":{"tf":1.0}},"df":1}}}}},"/":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"k":{"docs":{"175":{"tf":1.0}},"df":1}}}}}}}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"62":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"62":{"tf":1.0}},"df":1}}}},"t":{"docs":{"112":{"tf":1.0},"133":{"tf":1.0},"160":{"tf":1.4142135623730951},"87":{"tf":1.0}},"df":4},"x":{"docs":{"113":{"tf":1.0},"115":{"tf":1.4142135623730951},"126":{"tf":1.0},"131":{"tf":1.0},"160":{"tf":1.0},"168":{"tf":1.0},"177":{"tf":1.0},"178":{"tf":1.0},"191":{"tf":1.0},"27":{"tf":1.0},"30":{"tf":1.0}},"df":11}},"i":{"docs":{},"df":0,"c":{"docs":{"124":{"tf":1.0},"151":{"tf":1.0}},"df":2}}},"o":{"docs":{},"df":0,"n":{"docs":{"113":{"tf":1.0},"115":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"129":{"tf":1.0},"158":{"tf":1.0},"192":{"tf":1.0},"21":{"tf":1.0},"39":{"tf":1.0},"86":{"tf":1.0},"87":{"tf":1.0}},"df":11}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{"5":{"tf":1.0}},"df":1}}}}}},"u":{"docs":{},"df":0,"t":{"docs":{"151":{"tf":1.0},"157":{"tf":1.0},"32":{"tf":1.0},"86":{"tf":1.0}},"df":4}}}},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"1":{"tf":1.0},"103":{"tf":1.0},"104":{"tf":1.0},"173":{"tf":1.0},"4":{"tf":1.0},"7":{"tf":1.0}},"df":6}},"r":{"docs":{},"df":0,"n":{"docs":{"38":{"tf":1.0},"80":{"tf":1.0}},"df":2}}},"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{"120":{"tf":1.4142135623730951},"121":{"tf":1.7320508075688772},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"128":{"tf":1.0},"129":{"tf":1.0},"130":{"tf":1.0},"131":{"tf":1.0},"165":{"tf":1.4142135623730951},"80":{"tf":1.7320508075688772}},"df":11}}}},"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"122":{"tf":1.4142135623730951},"133":{"tf":1.0},"136":{"tf":1.7320508075688772},"158":{"tf":2.0},"189":{"tf":1.0},"28":{"tf":1.0},"31":{"tf":1.0}},"df":7}}},"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"125":{"tf":1.0}},"df":1},"g":{"docs":{"40":{"tf":1.0},"63":{"tf":2.0},"64":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":1.0}},"df":5,"u":{"docs":{},"df":0,"r":{"docs":{"103":{"tf":2.0},"104":{"tf":1.4142135623730951},"106":{"tf":2.6457513110645907},"107":{"tf":1.7320508075688772},"108":{"tf":1.4142135623730951},"109":{"tf":1.0},"117":{"tf":1.0},"119":{"tf":1.0},"127":{"tf":2.0},"155":{"tf":1.0},"161":{"tf":1.0},"17":{"tf":1.0},"193":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.0},"31":{"tf":1.0},"53":{"tf":1.4142135623730951},"61":{"tf":1.0},"66":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"76":{"tf":1.7320508075688772},"81":{"tf":1.4142135623730951},"88":{"tf":2.0}},"df":24,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"(":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"m":{"docs":{"62":{"tf":1.0},"79":{"tf":1.0}},"df":2}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"119":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"11":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"29":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"53":{"tf":1.0},"64":{"tf":1.7320508075688772},"68":{"tf":2.23606797749979}},"df":9,"o":{"docs":{},"df":0,"r":{"docs":{"53":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"q":{"docs":{},"df":0,"u":{"docs":{"124":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"d":{"docs":{"115":{"tf":1.0},"122":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"160":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0}},"df":7,"e":{"docs":{},"df":0,"r":{"docs":{"75":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"t":{"docs":{"117":{"tf":1.0},"121":{"tf":1.0},"171":{"tf":1.0},"174":{"tf":1.0},"179":{"tf":1.0}},"df":5}}},"o":{"docs":{},"df":0,"l":{"docs":{"53":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.4142135623730951},"83":{"tf":1.0}},"df":7}},"t":{"docs":{"100":{"tf":1.0},"101":{"tf":1.0},"125":{"tf":1.0},"159":{"tf":2.0},"164":{"tf":1.0},"165":{"tf":1.4142135623730951},"168":{"tf":1.0},"83":{"tf":1.0}},"df":8,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"112":{"tf":1.0},"138":{"tf":1.0},"151":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"62":{"tf":1.0}},"df":6}}},"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{"191":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"76":{"tf":1.0}},"df":1,"t":{"docs":{"110":{"tf":1.0},"114":{"tf":1.0},"126":{"tf":1.0}},"df":3}}}},"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"115":{"tf":1.0},"126":{"tf":1.0},"146":{"tf":1.0}},"df":3,"o":{"docs":{},"df":0,"r":{"docs":{"142":{"tf":1.0},"69":{"tf":1.0}},"df":2}}}}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"11":{"tf":1.0},"160":{"tf":1.0}},"df":2}},"m":{"docs":{"105":{"tf":1.0},"110":{"tf":1.0},"146":{"tf":1.0},"172":{"tf":1.0},"76":{"tf":1.0}},"df":5}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.4142135623730951},"11":{"tf":1.0},"111":{"tf":1.4142135623730951},"112":{"tf":1.0},"125":{"tf":1.4142135623730951},"127":{"tf":1.4142135623730951},"133":{"tf":1.0},"144":{"tf":1.0},"166":{"tf":1.0},"37":{"tf":1.0},"53":{"tf":1.0},"56":{"tf":1.4142135623730951},"62":{"tf":2.449489742783178},"63":{"tf":1.0},"66":{"tf":1.0},"7":{"tf":1.0},"78":{"tf":1.0},"86":{"tf":1.0},"9":{"tf":1.4142135623730951},"99":{"tf":1.4142135623730951}},"df":20}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"126":{"tf":1.0},"44":{"tf":1.0},"53":{"tf":1.0},"61":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.4142135623730951},"8":{"tf":1.0}},"df":7}},"x":{"docs":{},"df":0,"t":{"docs":{"120":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"165":{"tf":1.0},"5":{"tf":1.0},"60":{"tf":1.0},"80":{"tf":1.0}},"df":8}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{"122":{"tf":1.0},"28":{"tf":1.0},"64":{"tf":2.0},"68":{"tf":2.0}},"df":4}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"108":{"tf":1.4142135623730951},"115":{"tf":1.4142135623730951}},"df":3}},"s":{"docs":{},"df":0,"t":{"docs":{"134":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"l":{"docs":{"103":{"tf":1.0},"107":{"tf":1.0},"130":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"166":{"tf":1.0},"24":{"tf":1.0},"28":{"tf":1.0},"44":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":2.23606797749979},"71":{"tf":1.0},"72":{"tf":1.0},"84":{"tf":1.7320508075688772},"86":{"tf":1.7320508075688772},"87":{"tf":1.0},"90":{"tf":1.0}},"df":18,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"’":{"docs":{"69":{"tf":1.0}},"df":1}}}}}}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"i":{"docs":{"107":{"tf":1.0},"109":{"tf":1.0},"34":{"tf":1.0},"60":{"tf":1.0},"77":{"tf":1.4142135623730951}},"df":5},"t":{"docs":{"142":{"tf":1.0},"30":{"tf":1.0},"84":{"tf":1.0}},"df":3}},"r":{"docs":{},"df":0,"s":{"docs":{"115":{"tf":1.0},"174":{"tf":1.0}},"df":2},"t":{"docs":{"110":{"tf":1.0},"127":{"tf":1.0},"165":{"tf":1.0},"168":{"tf":1.0},"175":{"tf":1.0}},"df":5}}}}},"o":{"docs":{},"df":0,"k":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"k":{"docs":{"2":{"tf":1.0}},"df":1}}}}},"l":{"docs":{"175":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"h":{"docs":{"173":{"tf":1.0}},"df":1}},"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"s":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{"173":{"tf":1.0}},"df":1}}}}}}}}}},"f":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"173":{"tf":1.7320508075688772}},"df":1,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"(":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"173":{"tf":1.0}},"df":1}}}}}}}}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"173":{"tf":3.0}},"df":1}}}}}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"130":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"8":{"tf":1.0},"80":{"tf":1.0}},"df":2}}}}},"p":{"docs":{},"df":0,"i":{"docs":{"112":{"tf":1.0},"126":{"tf":1.7320508075688772},"127":{"tf":1.0},"146":{"tf":1.4142135623730951},"177":{"tf":1.0}},"df":5}},"r":{"docs":{},"df":0,"e":{"docs":{"100":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"120":{"tf":1.4142135623730951},"123":{"tf":2.0},"124":{"tf":1.4142135623730951},"125":{"tf":1.4142135623730951},"129":{"tf":1.0},"131":{"tf":2.23606797749979},"132":{"tf":1.0},"133":{"tf":1.0},"16":{"tf":1.0},"174":{"tf":1.0},"35":{"tf":1.0},"60":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0},"66":{"tf":2.0},"67":{"tf":1.0},"69":{"tf":1.4142135623730951},"78":{"tf":1.0},"80":{"tf":2.0},"90":{"tf":1.4142135623730951}},"df":23,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"{":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}},"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"126":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"127":{"tf":1.4142135623730951}},"df":1}}}}}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"125":{"tf":1.0},"133":{"tf":1.0}},"df":2}}}}}}}}}}}}}}},"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"168":{"tf":1.0}},"df":1}},"m":{"docs":{},"df":0,"t":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0},"83":{"tf":1.0}},"df":2}}}}}}}}},"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"z":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"o":{"docs":{},"df":0,"f":{"docs":{"111":{"tf":1.0}},"df":1}}}}}}}}}}}},"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"x":{"docs":{},"df":0,"4":{"docs":{},"df":0,"0":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"64":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}}}}}},"p":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{"133":{"tf":1.0},"83":{"tf":1.0}},"df":2,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"v":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"92":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}},"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"v":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"165":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"{":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{"124":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"120":{"tf":1.0},"2":{"tf":1.0},"28":{"tf":1.0},"75":{"tf":1.0},"76":{"tf":1.0},"88":{"tf":1.0},"93":{"tf":1.0}},"df":7,"l":{"docs":{},"df":0,"i":{"docs":{"103":{"tf":1.0},"119":{"tf":1.0},"53":{"tf":1.4142135623730951},"68":{"tf":1.0},"96":{"tf":1.0}},"df":5}}}},"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"168":{"tf":1.0},"184":{"tf":1.0},"61":{"tf":1.0},"78":{"tf":1.0},"87":{"tf":1.0},"91":{"tf":1.0}},"df":6}}}}}},"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"191":{"tf":1.0},"67":{"tf":1.0},"77":{"tf":1.0}},"df":3}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{"100":{"tf":1.7320508075688772},"11":{"tf":1.0},"12":{"tf":1.0},"124":{"tf":2.0},"17":{"tf":1.0},"188":{"tf":1.4142135623730951},"19":{"tf":1.0},"190":{"tf":1.0},"2":{"tf":1.0},"36":{"tf":1.0},"38":{"tf":3.0},"43":{"tf":1.7320508075688772},"55":{"tf":1.0},"56":{"tf":1.0},"59":{"tf":1.7320508075688772},"60":{"tf":1.0},"61":{"tf":3.0},"63":{"tf":2.449489742783178},"64":{"tf":1.4142135623730951},"66":{"tf":2.0},"67":{"tf":3.1622776601683795},"68":{"tf":1.0},"69":{"tf":1.7320508075688772},"7":{"tf":1.0},"71":{"tf":1.4142135623730951},"72":{"tf":1.4142135623730951},"77":{"tf":1.4142135623730951},"78":{"tf":1.0},"79":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":2.23606797749979},"82":{"tf":1.4142135623730951},"84":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.4142135623730951}},"df":35,"_":{"docs":{},"df":0,"m":{"docs":{"100":{"tf":1.4142135623730951},"126":{"tf":1.0}},"df":2,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"m":{"docs":{"133":{"tf":1.0}},"df":1,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"w":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"125":{"tf":1.0},"133":{"tf":1.0}},"df":2,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"f":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{"123":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"_":{"docs":{"123":{"tf":1.0}},"df":1}}}}}}},"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{"126":{"tf":1.0},"131":{"tf":1.0}},"df":2}}}}},"{":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"127":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"100":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"k":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"{":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"71":{"tf":1.0}},"df":1}}}}}}},"s":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"72":{"tf":1.0},"81":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.0}},"df":1}}}}}}}}}}},"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"191":{"tf":1.0},"60":{"tf":1.0},"64":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.7320508075688772},"79":{"tf":1.0}},"df":8}}}}},"{":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"81":{"tf":1.0},"83":{"tf":1.0}},"df":2}}}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0}},"df":1,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{"77":{"tf":1.4142135623730951}},"df":1}}}}},"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"83":{"tf":1.0}},"df":1}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"n":{"docs":{"77":{"tf":1.0}},"df":1}}}}}}}},"{":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{"191":{"tf":1.0},"64":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{"110":{"tf":1.0},"111":{"tf":1.0},"112":{"tf":1.0},"123":{"tf":1.0},"153":{"tf":1.0},"187":{"tf":1.0},"189":{"tf":1.4142135623730951},"190":{"tf":1.0},"33":{"tf":1.0},"76":{"tf":1.0},"99":{"tf":1.0}},"df":11}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{},"df":0,"n":{"docs":{},"df":0,"’":{"docs":{},"df":0,"t":{"docs":{"126":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"t":{"docs":{"122":{"tf":1.4142135623730951},"128":{"tf":1.0},"72":{"tf":1.0},"80":{"tf":1.7320508075688772},"81":{"tf":2.449489742783178},"84":{"tf":1.7320508075688772}},"df":6,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"o":{"docs":{},"df":0,"k":{"docs":{"81":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"r":{"docs":{"122":{"tf":2.8284271247461903},"123":{"tf":2.8284271247461903},"124":{"tf":2.23606797749979},"125":{"tf":2.8284271247461903},"126":{"tf":2.6457513110645907},"64":{"tf":1.0},"83":{"tf":1.4142135623730951}},"df":7,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"c":{"docs":{},"df":0,"s":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"0":{"docs":{"126":{"tf":1.0}},"df":1},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"c":{"docs":{},"df":0,"s":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"126":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"_":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,"1":{"docs":{"124":{"tf":1.0}},"df":1}}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"c":{"docs":{"125":{"tf":1.0}},"df":1}}}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"c":{"docs":{"125":{"tf":1.0}},"df":1}}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"0":{"docs":{"124":{"tf":1.0}},"df":1}}}}}}}}}}}},"p":{"docs":{},"df":0,"l":{"docs":{"92":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"s":{"docs":{"115":{"tf":1.0},"91":{"tf":1.0}},"df":2}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"131":{"tf":1.0},"157":{"tf":1.0},"172":{"tf":1.0},"24":{"tf":1.0},"60":{"tf":1.0},"67":{"tf":1.0},"70":{"tf":1.0},"84":{"tf":1.0}},"df":8}}}},"p":{"docs":{"127":{"tf":1.4142135623730951},"72":{"tf":1.0},"76":{"tf":1.0}},"df":3,"u":{"docs":{"112":{"tf":1.0},"130":{"tf":1.0},"35":{"tf":1.0},"63":{"tf":2.449489742783178},"64":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"7":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.4142135623730951},"86":{"tf":1.4142135623730951}},"df":11}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{"31":{"tf":1.0},"46":{"tf":1.0},"78":{"tf":1.0},"83":{"tf":1.0}},"df":4}},"t":{"docs":{},"df":0,"e":{"docs":{"100":{"tf":1.0},"115":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.7320508075688772},"132":{"tf":1.4142135623730951},"133":{"tf":2.0},"14":{"tf":1.4142135623730951},"142":{"tf":2.449489742783178},"144":{"tf":1.4142135623730951},"147":{"tf":2.0},"148":{"tf":1.0},"151":{"tf":1.0},"158":{"tf":2.449489742783178},"16":{"tf":2.449489742783178},"160":{"tf":1.7320508075688772},"161":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"168":{"tf":1.4142135623730951},"17":{"tf":1.4142135623730951},"174":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.7320508075688772},"178":{"tf":1.4142135623730951},"179":{"tf":1.0},"180":{"tf":1.7320508075688772},"188":{"tf":2.6457513110645907},"191":{"tf":1.4142135623730951},"193":{"tf":1.4142135623730951},"195":{"tf":1.7320508075688772},"197":{"tf":1.7320508075688772},"60":{"tf":2.0},"67":{"tf":1.0},"69":{"tf":3.3166247903554},"70":{"tf":2.6457513110645907},"71":{"tf":1.0},"72":{"tf":1.4142135623730951},"76":{"tf":1.4142135623730951},"77":{"tf":1.4142135623730951},"78":{"tf":3.0},"80":{"tf":1.0},"82":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.7320508075688772},"92":{"tf":1.0}},"df":46,"s":{"docs":{},"df":0,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"133":{"tf":1.0},"78":{"tf":1.0}},"df":2}}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"100":{"tf":1.0},"104":{"tf":1.4142135623730951},"105":{"tf":1.4142135623730951},"117":{"tf":1.0},"122":{"tf":1.4142135623730951},"126":{"tf":1.0},"146":{"tf":1.0},"179":{"tf":1.0},"180":{"tf":1.7320508075688772},"184":{"tf":1.0},"188":{"tf":1.0},"20":{"tf":1.0},"44":{"tf":1.4142135623730951},"56":{"tf":1.0},"57":{"tf":1.4142135623730951},"61":{"tf":1.0},"63":{"tf":1.0},"67":{"tf":1.4142135623730951},"68":{"tf":1.0},"76":{"tf":1.0},"93":{"tf":1.0}},"df":21,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"105":{"tf":1.0}},"df":1}},"v":{"docs":{"9":{"tf":1.0}},"df":1}}}},"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"9":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"123":{"tf":3.0},"125":{"tf":2.23606797749979},"126":{"tf":2.0},"127":{"tf":1.7320508075688772},"128":{"tf":1.0},"131":{"tf":1.0},"133":{"tf":1.0},"64":{"tf":1.0},"78":{"tf":1.0}},"df":9,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"125":{"tf":2.0}},"df":1}}}}}}}}}},"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"162":{"tf":1.0},"38":{"tf":1.0},"4":{"tf":1.0},"61":{"tf":1.4142135623730951},"67":{"tf":1.0}},"df":5}}},"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"32":{"tf":1.0}},"df":1}}}},"d":{"docs":{},"df":0,"e":{"docs":{"71":{"tf":1.0}},"df":1}}},"w":{"docs":{"44":{"tf":1.0}},"df":1}},"s":{"docs":{"125":{"tf":2.0},"173":{"tf":1.7320508075688772}},"df":2,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"125":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"102":{"tf":1.0}},"df":1}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"125":{"tf":2.8284271247461903}},"df":1,"(":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"0":{"docs":{"125":{"tf":1.0}},"df":1}}}}}}},"<":{"docs":{},"df":0,"u":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"125":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}},"r":{"docs":{"91":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0}},"df":3},"t":{"docs":{},"df":0,"r":{"docs":{"168":{"tf":1.0}},"df":1,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{"168":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"168":{"tf":1.0}},"df":1}}}}}},"t":{"docs":{"76":{"tf":1.0}},"df":1,"i":{"docs":{"168":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.4142135623730951}},"df":3},"o":{"docs":{},"df":0,"r":{"docs":{"142":{"tf":1.0}},"df":1}},"y":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"173":{"tf":1.4142135623730951}},"df":1}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"173":{"tf":2.449489742783178}},"df":1}}}}}}},"p":{"docs":{},"df":0,"e":{"docs":{"174":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"139":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{"3":{"tf":1.0}},"df":1}}},"l":{"docs":{"20":{"tf":1.0},"59":{"tf":1.0}},"df":2},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":1.0},"110":{"tf":1.0},"126":{"tf":1.0},"130":{"tf":1.0},"131":{"tf":1.0},"158":{"tf":1.0},"170":{"tf":1.0},"189":{"tf":1.0},"2":{"tf":1.0},"62":{"tf":1.0},"75":{"tf":1.0},"78":{"tf":1.0},"90":{"tf":1.0}},"df":13}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"118":{"tf":1.4142135623730951},"27":{"tf":1.0},"61":{"tf":1.4142135623730951},"63":{"tf":1.0},"68":{"tf":1.0},"76":{"tf":1.0},"82":{"tf":1.0}},"df":7,"i":{"docs":{},"df":0,"s":{"docs":{"161":{"tf":1.0}},"df":1}}}}}}},"v":{"docs":{},"df":0,"r":{"docs":{"91":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0}},"df":3}},"x":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{"100":{"tf":1.0}},"df":1}}}},"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"100":{"tf":1.0}},"df":1}}}}}}},"y":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{"72":{"tf":1.4142135623730951}},"df":1}}}},"d":{"docs":{"154":{"tf":1.0},"83":{"tf":1.0}},"df":2,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"122":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"h":{"docs":{"144":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"a":{"docs":{"103":{"tf":1.0},"111":{"tf":1.4142135623730951},"112":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":1.4142135623730951},"123":{"tf":1.0},"126":{"tf":1.0},"132":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"168":{"tf":1.0},"172":{"tf":1.4142135623730951},"173":{"tf":1.7320508075688772},"183":{"tf":1.0},"188":{"tf":1.4142135623730951},"61":{"tf":1.0},"62":{"tf":1.7320508075688772},"66":{"tf":1.0},"69":{"tf":1.4142135623730951},"80":{"tf":1.4142135623730951},"86":{"tf":1.4142135623730951},"87":{"tf":1.0},"88":{"tf":2.0},"90":{"tf":1.0}},"df":24,"s":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"87":{"tf":1.0},"88":{"tf":1.0}},"df":2}}}}},"t":{"docs":{},"df":0,"y":{"docs":{},"df":0,"p":{"docs":{"173":{"tf":1.4142135623730951},"174":{"tf":1.0}},"df":2}}}},"e":{"docs":{"161":{"tf":1.0},"38":{"tf":1.0}},"df":2}},"y":{"docs":{"5":{"tf":1.0},"93":{"tf":1.0}},"df":2}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"158":{"tf":1.0},"190":{"tf":1.0}},"df":2,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"126":{"tf":1.4142135623730951},"128":{"tf":1.0}},"df":2}}}}},"l":{"docs":{"120":{"tf":1.0},"136":{"tf":1.4142135623730951},"137":{"tf":1.0},"19":{"tf":1.4142135623730951}},"df":4,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{"133":{"tf":1.0}},"df":1,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}}}}},"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"43":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"g":{"docs":{"136":{"tf":1.0},"187":{"tf":2.23606797749979},"188":{"tf":1.4142135623730951},"19":{"tf":1.0},"24":{"tf":2.0},"26":{"tf":1.4142135623730951},"27":{"tf":1.4142135623730951},"28":{"tf":1.4142135623730951},"29":{"tf":1.4142135623730951},"30":{"tf":2.0},"31":{"tf":2.0},"32":{"tf":1.4142135623730951},"33":{"tf":1.0},"34":{"tf":1.7320508075688772},"36":{"tf":1.0},"4":{"tf":1.4142135623730951},"43":{"tf":1.7320508075688772},"54":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":3.0},"68":{"tf":2.6457513110645907},"77":{"tf":1.7320508075688772},"78":{"tf":1.0},"81":{"tf":1.0},"91":{"tf":1.0}},"df":26,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"67":{"tf":1.0},"77":{"tf":1.0}},"df":2,"(":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"77":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"191":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.0},"77":{"tf":1.0},"81":{"tf":1.0}},"df":5}}}}}}}}}}}}}}}}}}}}}}}}}},"_":{"docs":{"62":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{"62":{"tf":1.0}},"df":1}}}}}},"f":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"62":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{"62":{"tf":1.0}},"df":1}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"62":{"tf":1.0}},"df":1}},"o":{"docs":{},"df":0,"c":{"docs":{"62":{"tf":1.0}},"df":1}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{"62":{"tf":1.0}},"df":1}}}}}}},"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"b":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"62":{"tf":1.0}},"df":1}}},"t":{"docs":{},"df":0,"y":{"docs":{},"df":0,"p":{"docs":{"62":{"tf":1.0}},"df":1}}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"62":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{"62":{"tf":1.0}},"df":1}}}},"g":{"docs":{"11":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.7320508075688772},"24":{"tf":1.4142135623730951},"26":{"tf":1.0},"27":{"tf":1.0},"28":{"tf":1.7320508075688772},"35":{"tf":1.0},"50":{"tf":1.0},"53":{"tf":1.0},"64":{"tf":1.4142135623730951},"68":{"tf":1.0},"77":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0}},"df":15},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{"187":{"tf":1.4142135623730951},"63":{"tf":1.0}},"df":2}}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"68":{"tf":1.0}},"df":1}}}}}}}}}}},"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"137":{"tf":1.0},"190":{"tf":1.0},"99":{"tf":1.0}},"df":3}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"133":{"tf":1.7320508075688772},"134":{"tf":1.4142135623730951},"158":{"tf":1.4142135623730951},"184":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.4142135623730951},"84":{"tf":1.4142135623730951}},"df":7}}},"o":{"docs":{},"df":0,"d":{"docs":{"63":{"tf":1.4142135623730951}},"df":1}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"160":{"tf":1.0}},"df":1}}}}},"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"153":{"tf":1.0},"168":{"tf":1.0},"70":{"tf":1.0}},"df":3}}},"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"113":{"tf":1.4142135623730951}},"df":1}}}},"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"142":{"tf":1.0},"151":{"tf":1.0},"164":{"tf":1.0},"166":{"tf":1.0},"17":{"tf":1.0},"173":{"tf":1.0},"183":{"tf":1.0},"187":{"tf":1.4142135623730951},"189":{"tf":1.0},"38":{"tf":1.0},"61":{"tf":1.4142135623730951},"63":{"tf":1.4142135623730951},"67":{"tf":1.0},"74":{"tf":1.0},"81":{"tf":1.0},"82":{"tf":1.7320508075688772},"92":{"tf":1.0}},"df":17,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{"68":{"tf":1.0},"82":{"tf":2.0}},"df":2,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"(":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"q":{"docs":{},"df":0,"n":{"docs":{"82":{"tf":1.0}},"df":1}}}}},"_":{"docs":{"62":{"tf":1.4142135623730951}},"df":1}}}}}}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"62":{"tf":1.0}},"df":1}}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.4142135623730951},"107":{"tf":1.4142135623730951},"112":{"tf":1.0},"113":{"tf":1.0},"114":{"tf":1.0},"115":{"tf":1.7320508075688772},"133":{"tf":1.0},"160":{"tf":1.0},"172":{"tf":1.4142135623730951},"173":{"tf":2.6457513110645907},"174":{"tf":1.0},"188":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.4142135623730951},"71":{"tf":1.0},"72":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"76":{"tf":1.4142135623730951},"78":{"tf":1.4142135623730951},"83":{"tf":1.0},"84":{"tf":1.0}},"df":24,"i":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0},"132":{"tf":1.0},"168":{"tf":1.0},"172":{"tf":1.7320508075688772},"173":{"tf":1.7320508075688772},"80":{"tf":1.0}},"df":6}}}},"m":{"docs":{},"df":0,"t":{"docs":{"63":{"tf":2.449489742783178}},"df":1,"/":{"docs":{},"df":0,"q":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{"63":{"tf":1.0}},"df":1}}}}},"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"t":{"docs":{"63":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"63":{"tf":1.0}},"df":1}}}}}}}}}}}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"71":{"tf":1.0},"72":{"tf":1.0}},"df":2}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{"68":{"tf":1.4142135623730951}},"df":1}}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{"84":{"tf":1.0}},"df":1}}}}}},"n":{"docs":{},"df":0,"y":{"docs":{},"df":0,"(":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}}}}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"12":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"13":{"tf":1.0},"133":{"tf":1.0},"134":{"tf":1.0},"138":{"tf":1.4142135623730951},"155":{"tf":1.0},"158":{"tf":1.4142135623730951},"161":{"tf":1.0},"168":{"tf":1.4142135623730951},"176":{"tf":1.0},"178":{"tf":1.4142135623730951},"179":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.4142135623730951},"188":{"tf":2.8284271247461903},"193":{"tf":1.0},"197":{"tf":1.0},"63":{"tf":1.4142135623730951},"64":{"tf":1.0},"68":{"tf":2.0},"77":{"tf":2.0},"78":{"tf":1.0},"81":{"tf":1.0}},"df":25}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{"190":{"tf":1.0}},"df":1,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"r":{"docs":{"80":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"164":{"tf":1.4142135623730951},"173":{"tf":1.0}},"df":2}}}}}}},"i":{"docs":{},"df":0,"v":{"docs":{"125":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{"104":{"tf":1.0}},"df":1}}}}}}}}}},"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"61":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{"104":{"tf":1.0},"124":{"tf":1.0},"175":{"tf":1.0},"199":{"tf":1.0}},"df":4},"p":{"docs":{},"df":0,"t":{"docs":{"190":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.0},"199":{"tf":1.0},"5":{"tf":1.0},"84":{"tf":1.0},"90":{"tf":1.0}},"df":8}}}}},"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{"103":{"tf":1.0},"107":{"tf":1.0},"108":{"tf":1.4142135623730951},"110":{"tf":1.0},"125":{"tf":1.0},"131":{"tf":1.0},"140":{"tf":1.0},"26":{"tf":1.0},"33":{"tf":1.0},"87":{"tf":1.0},"97":{"tf":1.0}},"df":11}},"r":{"docs":{"119":{"tf":1.0},"14":{"tf":1.0},"77":{"tf":1.0},"84":{"tf":1.4142135623730951}},"df":4}},"k":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{"4":{"tf":1.0},"86":{"tf":1.4142135623730951},"87":{"tf":1.0}},"df":3}}}},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"142":{"tf":1.0}},"df":1}}}}}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"68":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"l":{"docs":{"11":{"tf":1.0},"114":{"tf":1.0},"124":{"tf":1.4142135623730951},"131":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"163":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"196":{"tf":1.0},"197":{"tf":1.0},"2":{"tf":1.0},"29":{"tf":1.0},"5":{"tf":1.0},"60":{"tf":1.0},"7":{"tf":1.4142135623730951},"70":{"tf":1.0},"84":{"tf":1.0}},"df":20}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"137":{"tf":1.0},"28":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"87":{"tf":1.0}},"df":5}},"r":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"138":{"tf":1.0},"72":{"tf":1.0},"84":{"tf":1.0}},"df":3}}}}}},"v":{"docs":{"187":{"tf":1.4142135623730951},"40":{"tf":1.0},"50":{"tf":1.0},"78":{"tf":1.4142135623730951}},"df":4,"/":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"b":{"docs":{},"df":0,"/":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"1":{"docs":{},"df":0,"/":{"docs":{},"df":0,"0":{"docs":{},"df":0,"1":{"docs":{},"df":0,"8":{"docs":{"44":{"tf":1.7320508075688772}},"df":1}}}}}}},"<":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,">":{"docs":{},"df":0,"/":{"docs":{},"df":0,"<":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"44":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}},"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{"108":{"tf":1.0},"112":{"tf":1.0},"130":{"tf":1.0},"139":{"tf":1.4142135623730951},"156":{"tf":1.0},"187":{"tf":1.4142135623730951},"195":{"tf":1.0},"2":{"tf":2.0},"26":{"tf":1.0},"28":{"tf":1.7320508075688772},"29":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.4142135623730951},"33":{"tf":1.0},"34":{"tf":1.7320508075688772},"35":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"4":{"tf":1.0},"5":{"tf":1.0},"55":{"tf":1.0},"64":{"tf":1.0},"65":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"7":{"tf":1.4142135623730951},"72":{"tf":1.0},"8":{"tf":1.0},"86":{"tf":1.7320508075688772},"93":{"tf":1.0},"94":{"tf":1.0}},"df":31}}}},"i":{"docs":{},"df":0,"c":{"docs":{"100":{"tf":1.4142135623730951},"114":{"tf":1.0},"118":{"tf":1.4142135623730951},"127":{"tf":1.4142135623730951},"187":{"tf":1.4142135623730951},"19":{"tf":1.0},"199":{"tf":1.0},"24":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"35":{"tf":1.0},"44":{"tf":1.7320508075688772},"61":{"tf":1.4142135623730951},"62":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0},"66":{"tf":1.7320508075688772},"68":{"tf":1.7320508075688772},"77":{"tf":1.4142135623730951},"81":{"tf":1.0},"82":{"tf":1.0},"84":{"tf":2.0},"86":{"tf":1.0}},"df":22}}}},"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{"32":{"tf":1.0},"83":{"tf":1.0}},"df":2}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"9":{"tf":1.0}},"df":1}}}}},"d":{"docs":{},"df":0,"n":{"docs":{},"df":0,"’":{"docs":{},"df":0,"t":{"docs":{"108":{"tf":1.0},"123":{"tf":1.0},"53":{"tf":1.0}},"df":3}}}},"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"101":{"tf":1.0},"114":{"tf":1.4142135623730951},"119":{"tf":2.449489742783178},"12":{"tf":1.4142135623730951},"120":{"tf":1.7320508075688772},"134":{"tf":1.0},"138":{"tf":1.0},"155":{"tf":1.4142135623730951},"156":{"tf":1.0},"157":{"tf":1.0},"158":{"tf":1.0},"180":{"tf":1.4142135623730951},"181":{"tf":1.0},"182":{"tf":1.0},"186":{"tf":1.0},"19":{"tf":1.4142135623730951},"190":{"tf":1.0},"192":{"tf":1.0},"53":{"tf":1.4142135623730951},"60":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"68":{"tf":1.7320508075688772},"7":{"tf":1.7320508075688772},"80":{"tf":1.0},"84":{"tf":1.0}},"df":26}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"120":{"tf":1.0},"127":{"tf":1.0},"161":{"tf":1.0},"178":{"tf":1.0}},"df":4}}}}}}},"g":{"docs":{"7":{"tf":1.0}},"df":1,"i":{"docs":{},"df":0,"t":{"docs":{"115":{"tf":1.0},"127":{"tf":1.0},"151":{"tf":1.0}},"df":3}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{"93":{"tf":1.0}},"df":1}}},"p":{"docs":{"69":{"tf":1.0}},"df":1},"r":{"docs":{"109":{"tf":1.4142135623730951}},"df":1,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":1.0},"107":{"tf":1.7320508075688772},"108":{"tf":2.6457513110645907},"109":{"tf":3.0},"112":{"tf":1.4142135623730951},"114":{"tf":1.0},"34":{"tf":1.0},"88":{"tf":1.0}},"df":8,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}},"l":{"docs":{},"df":0,"i":{"docs":{"124":{"tf":1.0},"126":{"tf":1.0},"133":{"tf":1.0},"160":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"197":{"tf":1.0},"26":{"tf":1.0},"69":{"tf":1.0},"80":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":1.0}},"df":15},"y":{"docs":{},"df":0,"—":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{"84":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"177":{"tf":1.0},"178":{"tf":1.0},"56":{"tf":1.0},"64":{"tf":1.0}},"df":4}}}}}}},"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"106":{"tf":1.7320508075688772},"107":{"tf":1.4142135623730951},"108":{"tf":1.4142135623730951},"109":{"tf":1.4142135623730951},"123":{"tf":1.4142135623730951},"124":{"tf":1.4142135623730951},"187":{"tf":1.0},"189":{"tf":1.0},"69":{"tf":1.0}},"df":9}},"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"62":{"tf":1.7320508075688772},"83":{"tf":1.4142135623730951}},"df":2}}}}},"t":{"docs":{},"df":0,"r":{"docs":{"126":{"tf":1.0}},"df":1}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"44":{"tf":1.0},"5":{"tf":1.0},"53":{"tf":1.7320508075688772},"68":{"tf":1.7320508075688772},"69":{"tf":1.0},"70":{"tf":1.4142135623730951},"81":{"tf":1.0}},"df":7}}}}},"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"165":{"tf":1.0},"186":{"tf":1.0}},"df":2}}}},"k":{"docs":{"38":{"tf":1.0},"62":{"tf":1.0}},"df":2},"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"118":{"tf":1.4142135623730951},"64":{"tf":1.0},"68":{"tf":1.0},"86":{"tf":1.0}},"df":4}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"163":{"tf":1.0}},"df":1}},"g":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{"144":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.0},"175":{"tf":1.0},"42":{"tf":1.0},"50":{"tf":1.0},"78":{"tf":1.0},"9":{"tf":1.0}},"df":6}}}},"o":{"docs":{"40":{"tf":1.0}},"df":1}}}},"v":{"docs":{},"df":0,"e":{"docs":{"65":{"tf":1.0}},"df":1,"r":{"docs":{},"df":0,"g":{"docs":{"60":{"tf":1.0}},"df":1},"s":{"docs":{"84":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"76":{"tf":1.0}},"df":1}}}}}},"m":{"docs":{},"df":0,"a":{"docs":{"130":{"tf":1.0},"164":{"tf":1.0}},"df":2}},"n":{"docs":{},"df":0,"f":{"docs":{"43":{"tf":1.0}},"df":1}},"o":{"docs":{"108":{"tf":1.0},"5":{"tf":1.0},"86":{"tf":1.4142135623730951}},"df":3,"c":{"docs":{"100":{"tf":1.0}},"df":1,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"128":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.0},"163":{"tf":1.0},"165":{"tf":1.0},"183":{"tf":1.0},"199":{"tf":1.0},"24":{"tf":1.0},"27":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"78":{"tf":1.0}},"df":12}}}}}},"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"n":{"docs":{},"df":0,"’":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"187":{"tf":1.0},"2":{"tf":1.0},"70":{"tf":1.0},"72":{"tf":1.0},"83":{"tf":1.0},"92":{"tf":1.0}},"df":7}}}}},"n":{"docs":{},"df":0,"\'":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.4142135623730951},"187":{"tf":1.0},"188":{"tf":1.0}},"df":3}},"e":{"docs":{"103":{"tf":1.0},"126":{"tf":1.4142135623730951},"5":{"tf":1.0},"57":{"tf":1.0},"59":{"tf":1.0},"61":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0}},"df":9},"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"109":{"tf":2.8284271247461903}},"df":1}}}},"’":{"docs":{},"df":0,"t":{"docs":{"123":{"tf":1.0},"134":{"tf":1.0},"136":{"tf":1.0},"174":{"tf":1.0},"179":{"tf":1.0},"22":{"tf":1.0},"55":{"tf":1.0},"60":{"tf":1.0},"67":{"tf":1.0},"82":{"tf":1.0},"93":{"tf":1.4142135623730951}},"df":11}}},"u":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"68":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"a":{"docs":{"104":{"tf":1.0}},"df":1,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"104":{"tf":1.0}},"df":1}}}}}}}}}}},"w":{"docs":{},"df":0,"n":{"docs":{"112":{"tf":1.0},"127":{"tf":1.0},"146":{"tf":1.0},"151":{"tf":1.0},"63":{"tf":1.0},"72":{"tf":1.0}},"df":6,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"20":{"tf":1.0},"39":{"tf":1.0},"59":{"tf":1.4142135623730951}},"df":3}}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"187":{"tf":1.0},"77":{"tf":1.0}},"df":2}}}}},"z":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"187":{"tf":1.0}},"df":1}}}},"p":{"docs":{"127":{"tf":1.7320508075688772}},"df":1,".":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{"127":{"tf":1.4142135623730951}},"df":1}}}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"119":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{"155":{"tf":1.0}},"df":1,"n":{"docs":{"107":{"tf":1.4142135623730951},"108":{"tf":1.4142135623730951},"118":{"tf":1.0},"128":{"tf":1.0}},"df":4},"r":{"docs":{"115":{"tf":1.7320508075688772},"117":{"tf":1.0},"118":{"tf":1.7320508075688772},"165":{"tf":1.4142135623730951},"52":{"tf":1.4142135623730951},"53":{"tf":1.0},"93":{"tf":1.7320508075688772}},"df":7}}}},"o":{"docs":{},"df":0,"p":{"docs":{"126":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"p":{"docs":{"191":{"tf":1.4142135623730951}},"df":1}},"u":{"docs":{},"df":0,"e":{"docs":{"110":{"tf":1.0},"115":{"tf":1.0},"139":{"tf":1.0},"146":{"tf":1.0},"17":{"tf":1.0},"173":{"tf":1.0},"34":{"tf":1.0},"84":{"tf":1.0}},"df":8},"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"93":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"e":{"docs":{"126":{"tf":1.0},"127":{"tf":1.0},"63":{"tf":1.0},"68":{"tf":1.7320508075688772}},"df":4}}},"y":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"132":{"tf":1.4142135623730951},"14":{"tf":1.0},"17":{"tf":1.0},"180":{"tf":1.0}},"df":4}}}}},"e":{"docs":{"191":{"tf":1.4142135623730951}},"df":1,".":{"docs":{},"df":0,"g":{"docs":{"107":{"tf":1.0},"117":{"tf":2.0},"119":{"tf":1.0},"13":{"tf":1.0},"189":{"tf":1.4142135623730951},"190":{"tf":1.4142135623730951},"2":{"tf":1.0},"40":{"tf":1.0},"53":{"tf":1.0},"66":{"tf":1.7320508075688772},"77":{"tf":1.0},"80":{"tf":1.0}},"df":12}},"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{"162":{"tf":1.0},"38":{"tf":2.23606797749979},"43":{"tf":2.0},"46":{"tf":1.0},"47":{"tf":1.0},"49":{"tf":1.0},"61":{"tf":2.6457513110645907},"63":{"tf":1.4142135623730951},"64":{"tf":1.0},"67":{"tf":1.7320508075688772},"68":{"tf":1.7320508075688772}},"df":11,"/":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"/":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{"62":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{"64":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{"63":{"tf":1.7320508075688772}},"df":1}}}}},"m":{"docs":{},"df":0,"y":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{"162":{"tf":1.0}},"df":1}}}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"/":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{"63":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}},"h":{"docs":{},"df":0,"f":{"docs":{"38":{"tf":1.7320508075688772},"61":{"tf":1.0},"67":{"tf":1.7320508075688772}},"df":3,"/":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"/":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{"68":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}},"c":{"docs":{},"df":0,"h":{"docs":{"114":{"tf":1.0},"120":{"tf":1.0},"122":{"tf":1.4142135623730951},"123":{"tf":1.7320508075688772},"139":{"tf":1.0},"153":{"tf":1.4142135623730951},"158":{"tf":1.4142135623730951},"165":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"69":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.0},"80":{"tf":1.0},"96":{"tf":1.0},"99":{"tf":1.0}},"df":16}},"r":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"131":{"tf":1.0},"7":{"tf":1.4142135623730951},"72":{"tf":1.0},"87":{"tf":1.0}},"df":4}}}}},"s":{"docs":{},"df":0,"i":{"docs":{"105":{"tf":1.0},"115":{"tf":1.0},"21":{"tf":1.0},"33":{"tf":1.0},"50":{"tf":1.0},"70":{"tf":1.0}},"df":6,"e":{"docs":{},"df":0,"r":{"docs":{"103":{"tf":1.0},"160":{"tf":1.0},"168":{"tf":1.0},"178":{"tf":1.0},"19":{"tf":1.0},"2":{"tf":1.0},"78":{"tf":1.0},"93":{"tf":1.4142135623730951}},"df":8},"s":{"docs":{},"df":0,"t":{"docs":{"177":{"tf":1.0}},"df":1}}},"l":{"docs":{},"df":0,"i":{"docs":{"160":{"tf":1.0}},"df":1}}}}},"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{"63":{"tf":1.0},"77":{"tf":1.4142135623730951}},"df":2}},"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{"129":{"tf":1.0},"192":{"tf":1.0},"29":{"tf":1.0},"63":{"tf":1.0}},"df":4}}}}}}}},"d":{"docs":{},"df":0,"g":{"docs":{"122":{"tf":1.0},"127":{"tf":1.0},"53":{"tf":1.0}},"df":3},"i":{"docs":{},"df":0,"t":{"docs":{"4":{"tf":1.0},"58":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.0}},"df":4}},"u":{"docs":{},"df":0,"c":{"docs":{"36":{"tf":1.0}},"df":1}}},"f":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"o":{"docs":{},"df":0,"k":{"docs":{"83":{"tf":1.0}},"df":1}}}},"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"188":{"tf":1.0},"190":{"tf":1.0},"24":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0}},"df":5}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{"124":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"119":{"tf":1.0}},"df":1}}}}},"g":{"docs":{"155":{"tf":1.0}},"df":1},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"134":{"tf":2.0},"163":{"tf":1.0}},"df":2}}}}},"f":{"docs":{"62":{"tf":2.23606797749979}},"df":1,"/":{"docs":{},"df":0,"d":{"docs":{},"df":0,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"f":{"docs":{"30":{"tf":1.0}},"df":1}}}}}},"3":{"docs":{},"df":0,"2":{"docs":{"62":{"tf":1.4142135623730951}},"df":1}}},"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"190":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"124":{"tf":1.0},"173":{"tf":1.0}},"df":2}}}}}}},"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{"129":{"tf":2.0}},"df":1}}}},"e":{"docs":{},"df":0,"d":{"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.4142135623730951},"103":{"tf":1.0},"114":{"tf":1.7320508075688772},"115":{"tf":1.7320508075688772},"117":{"tf":1.0},"118":{"tf":1.4142135623730951},"12":{"tf":1.4142135623730951},"120":{"tf":1.4142135623730951},"121":{"tf":1.0},"122":{"tf":1.7320508075688772},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"130":{"tf":1.4142135623730951},"131":{"tf":1.0},"14":{"tf":1.0},"140":{"tf":1.0},"142":{"tf":1.0},"148":{"tf":1.0},"151":{"tf":1.0},"156":{"tf":1.0},"157":{"tf":1.0},"161":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"167":{"tf":1.0},"169":{"tf":1.0},"175":{"tf":1.0},"177":{"tf":1.0},"179":{"tf":1.0},"192":{"tf":1.0},"195":{"tf":1.0},"2":{"tf":1.7320508075688772},"22":{"tf":1.0},"24":{"tf":1.7320508075688772},"26":{"tf":1.4142135623730951},"27":{"tf":1.7320508075688772},"3":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.4142135623730951},"32":{"tf":1.7320508075688772},"33":{"tf":1.0},"4":{"tf":1.0},"49":{"tf":1.0},"5":{"tf":3.3166247903554},"54":{"tf":1.0},"56":{"tf":1.4142135623730951},"63":{"tf":1.4142135623730951},"64":{"tf":1.7320508075688772},"69":{"tf":1.7320508075688772},"70":{"tf":1.0},"72":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.0},"86":{"tf":1.7320508075688772}},"df":57,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"/":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"k":{"docs":{},"df":0,"/":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"u":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"2":{"docs":{},"df":0,"6":{"docs":{},"df":0,"9":{"docs":{"62":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{"58":{"tf":1.0},"59":{"tf":1.0},"67":{"tf":1.0}},"df":3}}}}}}}}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"5":{"tf":1.0}},"df":1}}}}}}}}}}},"i":{"docs":{},"df":0,"t":{"docs":{"124":{"tf":1.0},"137":{"tf":1.0},"180":{"tf":1.0}},"df":3}},"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"y":{"docs":{"80":{"tf":1.0}},"df":1}}},"t":{"docs":{"125":{"tf":1.0}},"df":1,"i":{"docs":{"127":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"l":{"docs":{"114":{"tf":1.0},"22":{"tf":1.4142135623730951},"54":{"tf":1.0},"55":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":2.449489742783178}},"df":6}}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"106":{"tf":1.4142135623730951},"107":{"tf":1.7320508075688772},"108":{"tf":2.6457513110645907},"109":{"tf":4.0},"112":{"tf":1.7320508075688772},"123":{"tf":1.0},"127":{"tf":1.4142135623730951},"142":{"tf":1.0},"151":{"tf":1.0},"158":{"tf":2.0},"187":{"tf":1.7320508075688772},"28":{"tf":1.0},"32":{"tf":1.0},"63":{"tf":1.0},"68":{"tf":2.23606797749979},"69":{"tf":1.0},"77":{"tf":2.449489742783178},"84":{"tf":1.4142135623730951}},"df":18,"e":{"docs":{},"df":0,"=":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,",":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"=":{"docs":{},"df":0,"n":{"docs":{"63":{"tf":1.7320508075688772},"64":{"tf":1.0},"68":{"tf":1.0}},"df":3}}}}}}}}}}}}}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"104":{"tf":1.4142135623730951},"142":{"tf":1.0},"155":{"tf":1.4142135623730951}},"df":3},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"28":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"160":{"tf":1.0}},"df":1}}}}}},"d":{"docs":{"108":{"tf":1.0},"115":{"tf":1.0},"133":{"tf":1.4142135623730951},"144":{"tf":1.0},"166":{"tf":1.0},"60":{"tf":1.0},"64":{"tf":1.0},"81":{"tf":1.0},"87":{"tf":1.0}},"df":9,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"62":{"tf":1.0}},"df":1}},"f":{"docs":{"158":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"84":{"tf":1.0}},"df":1}}}}}}},"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{"102":{"tf":1.0},"103":{"tf":1.0},"107":{"tf":1.0},"108":{"tf":1.7320508075688772},"109":{"tf":1.0},"110":{"tf":1.4142135623730951},"127":{"tf":1.0},"128":{"tf":1.0},"164":{"tf":1.0},"87":{"tf":1.0}},"df":10}}}},"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"130":{"tf":1.0},"97":{"tf":1.0}},"df":2}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"189":{"tf":1.0},"54":{"tf":1.0},"63":{"tf":1.0},"8":{"tf":1.0},"93":{"tf":1.0}},"df":5}}}},"s":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"103":{"tf":1.0},"114":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.4142135623730951},"127":{"tf":1.7320508075688772},"128":{"tf":1.0},"131":{"tf":1.0},"133":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.4142135623730951},"173":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"60":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.4142135623730951},"84":{"tf":1.0},"92":{"tf":1.0}},"df":21}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"114":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"128":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"78":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0}},"df":9}},"i":{"docs":{},"df":0,"r":{"docs":{"100":{"tf":1.0},"110":{"tf":1.0},"124":{"tf":1.0},"126":{"tf":1.0},"160":{"tf":1.0},"71":{"tf":1.0},"92":{"tf":1.0}},"df":7}},"r":{"docs":{},"df":0,"i":{"docs":{"121":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.4142135623730951},"133":{"tf":1.0},"134":{"tf":1.0},"191":{"tf":1.0},"60":{"tf":2.23606797749979},"62":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.7320508075688772},"79":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0}},"df":22}}},"u":{"docs":{},"df":0,"m":{"docs":{"109":{"tf":1.0},"154":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,"r":{"docs":{"163":{"tf":1.0}},"df":1}}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"114":{"tf":1.0},"13":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"2":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"80":{"tf":1.0}},"df":10}}}}}},"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"114":{"tf":1.0},"189":{"tf":1.0},"38":{"tf":1.0}},"df":3}},"i":{"docs":{},"df":0,"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0}},"df":1}}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"142":{"tf":1.4142135623730951},"155":{"tf":1.4142135623730951},"28":{"tf":1.0}},"df":3,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"154":{"tf":1.0}},"df":1}}}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"154":{"tf":1.0}},"df":1}}}}}}}}}}},"u":{"docs":{},"df":0,"r":{"docs":{"154":{"tf":1.0}},"df":1}}}},"g":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"125":{"tf":1.0}},"df":1}}}}},"r":{"docs":{"108":{"tf":2.6457513110645907}},"df":1,"o":{"docs":{},"df":0,"r":{"docs":{"103":{"tf":1.0},"110":{"tf":1.0},"115":{"tf":1.0},"122":{"tf":1.0},"126":{"tf":1.0},"133":{"tf":1.0},"139":{"tf":1.4142135623730951},"174":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"63":{"tf":1.4142135623730951},"75":{"tf":1.0},"80":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":14}}}},"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{"125":{"tf":1.0},"126":{"tf":1.0},"156":{"tf":1.0},"170":{"tf":1.0},"27":{"tf":1.0}},"df":5}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"24":{"tf":1.0},"28":{"tf":1.0}},"df":2}}}}}},"t":{"docs":{},"df":0,"c":{"docs":{"112":{"tf":1.0},"117":{"tf":1.0},"13":{"tf":1.0},"132":{"tf":1.0},"168":{"tf":1.0},"17":{"tf":1.0},"175":{"tf":1.0},"184":{"tf":1.0},"4":{"tf":1.0}},"df":9,"/":{"docs":{},"df":0,"u":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{},"df":0,"/":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,".":{"docs":{},"df":0,"d":{"docs":{},"df":0,"/":{"docs":{},"df":0,"7":{"docs":{},"df":0,"0":{"docs":{"44":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"u":{"docs":{"159":{"tf":1.0},"63":{"tf":1.0}},"df":2}}},"e":{"docs":{},"df":0,"n":{"docs":{"114":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.4142135623730951},"127":{"tf":1.0},"134":{"tf":1.0},"136":{"tf":1.0},"150":{"tf":1.0},"151":{"tf":1.0},"160":{"tf":1.0},"22":{"tf":1.0},"7":{"tf":1.0},"76":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.4142135623730951},"84":{"tf":1.0},"92":{"tf":1.0}},"df":18,"t":{"docs":{"28":{"tf":1.4142135623730951},"80":{"tf":1.4142135623730951}},"df":2,"u":{"docs":{"132":{"tf":1.0},"64":{"tf":1.0}},"df":2}}},"r":{"docs":{},"df":0,"y":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{"3":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"n":{"docs":{"1":{"tf":1.0},"186":{"tf":1.0}},"df":2}},"t":{"docs":{},"df":0,"h":{"docs":{"86":{"tf":1.4142135623730951},"98":{"tf":1.0}},"df":2}}}}},"i":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"166":{"tf":1.0}},"df":1}}}}}},"x":{"docs":{"49":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.0},"93":{"tf":1.0}},"df":2,"l":{"docs":{},"df":0,"i":{"docs":{"139":{"tf":1.0},"53":{"tf":1.0},"72":{"tf":1.0},"78":{"tf":1.0},"91":{"tf":1.0},"96":{"tf":1.0}},"df":6}}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"28":{"tf":1.0},"31":{"tf":1.0}},"df":2}},"p":{"docs":{},"df":0,"l":{"docs":{"102":{"tf":1.0},"103":{"tf":1.4142135623730951},"104":{"tf":1.4142135623730951},"106":{"tf":1.0},"107":{"tf":1.0},"109":{"tf":2.0},"111":{"tf":1.0},"118":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.7320508075688772},"127":{"tf":1.4142135623730951},"129":{"tf":1.0},"130":{"tf":1.4142135623730951},"131":{"tf":1.0},"136":{"tf":1.4142135623730951},"138":{"tf":1.4142135623730951},"146":{"tf":1.4142135623730951},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.7320508075688772},"161":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"168":{"tf":1.0},"169":{"tf":1.0},"170":{"tf":1.0},"173":{"tf":1.0},"178":{"tf":1.0},"188":{"tf":1.4142135623730951},"191":{"tf":1.0},"2":{"tf":1.0},"38":{"tf":1.0},"54":{"tf":1.0},"56":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":2.23606797749979},"64":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":1.0},"69":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951},"72":{"tf":1.7320508075688772},"76":{"tf":1.0},"78":{"tf":1.7320508075688772},"79":{"tf":1.4142135623730951},"80":{"tf":1.0},"81":{"tf":1.4142135623730951},"83":{"tf":1.0},"87":{"tf":1.0},"88":{"tf":1.0},"90":{"tf":1.0},"93":{"tf":1.0}},"df":57,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"93":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{"64":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0}},"df":3,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,"1":{"docs":{},"df":0,"1":{"docs":{"68":{"tf":1.0}},"df":1},"3":{"docs":{"68":{"tf":1.0}},"df":1},"5":{"docs":{},"df":0,":":{"docs":{},"df":0,"5":{"docs":{"77":{"tf":1.0}},"df":1}}}}}}}}}}}}}},"\\\\":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,"1":{"docs":{},"df":0,"3":{"docs":{"64":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"111":{"tf":1.0}},"df":1},"p":{"docs":{},"df":0,"t":{"docs":{"181":{"tf":1.0},"68":{"tf":1.0},"72":{"tf":1.0},"80":{"tf":4.795831523312719},"81":{"tf":2.23606797749979},"82":{"tf":3.1622776601683795},"83":{"tf":3.0},"84":{"tf":2.6457513110645907}},"df":8,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"83":{"tf":2.23606797749979}},"df":1}}}}}}}}},"s":{"docs":{},"df":0,"s":{"docs":{"139":{"tf":1.0}},"df":1}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"105":{"tf":1.4142135623730951},"5":{"tf":1.0}},"df":2}}}},"l":{"docs":{},"df":0,"u":{"docs":{},"df":0,"d":{"docs":{"14":{"tf":1.0},"188":{"tf":1.0}},"df":2},"s":{"docs":{"123":{"tf":1.0},"126":{"tf":1.7320508075688772},"136":{"tf":1.0},"137":{"tf":1.0}},"df":4}}}},"e":{"docs":{},"df":0,"c":{"docs":{"62":{"tf":1.0}},"df":1,"u":{"docs":{},"df":0,"t":{"docs":{"100":{"tf":1.0},"110":{"tf":1.0},"111":{"tf":1.0},"120":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"131":{"tf":1.0},"138":{"tf":1.7320508075688772},"161":{"tf":1.0},"162":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"178":{"tf":1.4142135623730951},"186":{"tf":1.0},"187":{"tf":1.0},"189":{"tf":1.0},"24":{"tf":1.0},"28":{"tf":1.4142135623730951},"62":{"tf":1.0},"63":{"tf":1.4142135623730951},"64":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"78":{"tf":1.4142135623730951},"80":{"tf":2.0},"84":{"tf":1.4142135623730951}},"df":27,"o":{"docs":{},"df":0,"r":{"docs":{"128":{"tf":1.0},"129":{"tf":1.0}},"df":2}}}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"136":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"112":{"tf":1.0},"113":{"tf":1.0},"127":{"tf":1.4142135623730951},"141":{"tf":1.0},"164":{"tf":1.0},"166":{"tf":1.0},"169":{"tf":1.0},"172":{"tf":1.0},"175":{"tf":1.4142135623730951},"44":{"tf":1.0},"70":{"tf":1.0},"74":{"tf":1.0},"84":{"tf":1.0},"94":{"tf":1.0}},"df":14}},"t":{"docs":{"191":{"tf":1.0},"63":{"tf":1.4142135623730951},"64":{"tf":1.7320508075688772},"67":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":2.0}},"df":6,"(":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"77":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}},"p":{"docs":{},"df":0,"(":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}},"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"117":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.7320508075688772}},"df":3}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"151":{"tf":1.0},"159":{"tf":1.0},"182":{"tf":1.0},"86":{"tf":1.0}},"df":4}},"n":{"docs":{},"df":0,"s":{"docs":{"189":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"i":{"docs":{"29":{"tf":1.0},"3":{"tf":1.0},"70":{"tf":1.0}},"df":3,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"156":{"tf":1.0}},"df":1}}}}}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"160":{"tf":1.0},"173":{"tf":1.0},"19":{"tf":1.0},"2":{"tf":1.0}},"df":4}},"n":{"docs":{"125":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"128":{"tf":1.0},"139":{"tf":1.4142135623730951},"164":{"tf":1.0}},"df":3,"l":{"docs":{},"df":0,"i":{"docs":{"125":{"tf":1.0},"158":{"tf":1.0},"78":{"tf":1.0}},"df":3}}}}}},"o":{"docs":{},"df":0,"r":{"docs":{"130":{"tf":1.0},"132":{"tf":1.0}},"df":2}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"191":{"tf":1.7320508075688772}},"df":1,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"191":{"tf":2.0}},"df":1}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"t":{"docs":{"160":{"tf":1.0},"182":{"tf":1.0},"84":{"tf":1.4142135623730951}},"df":3}},"s":{"docs":{"107":{"tf":1.0},"136":{"tf":1.0},"137":{"tf":1.0},"153":{"tf":1.0},"16":{"tf":1.0},"171":{"tf":1.0},"70":{"tf":1.0},"76":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":1.0},"88":{"tf":1.0},"96":{"tf":1.0}},"df":12}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"115":{"tf":1.0},"160":{"tf":1.4142135623730951},"78":{"tf":1.0}},"df":3}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"44":{"tf":1.0},"68":{"tf":1.0}},"df":2},"s":{"docs":{"142":{"tf":1.0},"150":{"tf":1.0},"24":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.0},"29":{"tf":1.4142135623730951},"31":{"tf":1.0},"34":{"tf":1.0}},"df":8}},"r":{"docs":{},"df":0,"n":{"docs":{"11":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"133":{"tf":1.0},"173":{"tf":1.4142135623730951},"174":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"179":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.0},"191":{"tf":1.0},"64":{"tf":1.0},"78":{"tf":1.0}},"df":14}}},"r":{"docs":{},"df":0,"a":{"docs":{"123":{"tf":1.0},"131":{"tf":1.0},"158":{"tf":1.0},"161":{"tf":1.0},"64":{"tf":1.0},"77":{"tf":1.0}},"df":6,"c":{"docs":{},"df":0,"t":{"docs":{"59":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"m":{"docs":{"126":{"tf":1.0},"128":{"tf":1.0},"160":{"tf":1.4142135623730951}},"df":3}}}}}},"f":{"docs":{"155":{"tf":2.0},"53":{"tf":2.449489742783178},"66":{"tf":1.4142135623730951}},"df":3,"3":{"docs":{},"df":0,"2":{"docs":{"191":{"tf":1.0}},"df":1}},"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"183":{"tf":1.0},"78":{"tf":1.0}},"df":2},"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"24":{"tf":1.0},"32":{"tf":1.0}},"df":2}}}},"t":{"docs":{"122":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"173":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"78":{"tf":1.0}},"df":7,"o":{"docs":{},"df":0,"r":{"docs":{"101":{"tf":1.4142135623730951},"137":{"tf":1.0}},"df":2}}}},"i":{"docs":{},"df":0,"l":{"docs":{"134":{"tf":1.0},"136":{"tf":1.0},"146":{"tf":1.0},"61":{"tf":1.0},"77":{"tf":1.0}},"df":5,"u":{"docs":{},"df":0,"r":{"docs":{"136":{"tf":1.4142135623730951}},"df":1}}},"r":{"docs":{"92":{"tf":1.0}},"df":1}},"k":{"docs":{},"df":0,"e":{"docs":{"125":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"s":{"docs":{"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"165":{"tf":2.0},"58":{"tf":1.4142135623730951}},"df":8,"e":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"100":{"tf":1.0}},"df":1}}}}}}}}}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"114":{"tf":1.0},"144":{"tf":1.0},"155":{"tf":1.0},"7":{"tf":1.0}},"df":4,"a":{"docs":{},"df":0,"r":{"docs":{"10":{"tf":1.0},"133":{"tf":1.0},"139":{"tf":1.0},"2":{"tf":1.0},"4":{"tf":1.4142135623730951},"65":{"tf":1.0}},"df":6}}}}}},"q":{"docs":{"167":{"tf":1.0},"5":{"tf":1.0}},"df":2},"r":{"docs":{"69":{"tf":1.0},"72":{"tf":1.0},"86":{"tf":1.0}},"df":3},"s":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"127":{"tf":1.0},"67":{"tf":1.0},"86":{"tf":1.0},"93":{"tf":1.0}},"df":4}}}},"t":{"docs":{"186":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"80":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"68":{"tf":1.0},"83":{"tf":1.0}},"df":2}}},"v":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"35":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"11":{"tf":1.0},"128":{"tf":1.0},"130":{"tf":1.0},"158":{"tf":3.0},"159":{"tf":1.0},"16":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"17":{"tf":1.0},"188":{"tf":1.7320508075688772},"195":{"tf":1.0},"2":{"tf":1.0},"29":{"tf":1.0},"31":{"tf":1.0},"35":{"tf":1.0},"77":{"tf":2.23606797749979},"80":{"tf":1.0},"84":{"tf":1.0}},"df":18,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{"133":{"tf":1.0}},"df":1,"_":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}},"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{"43":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"d":{"docs":{"174":{"tf":1.0}},"df":1},"l":{"docs":{"13":{"tf":1.0},"139":{"tf":1.0},"187":{"tf":1.0},"94":{"tf":1.0}},"df":4}},"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{"63":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"_":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"d":{"docs":{"124":{"tf":1.0}},"df":1}}}}}}},"w":{"docs":{"12":{"tf":1.0},"165":{"tf":1.0},"37":{"tf":1.0},"42":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":1.0},"68":{"tf":1.0},"87":{"tf":1.0},"98":{"tf":1.0}},"df":9}},"f":{"docs":{},"df":0,"i":{"docs":{"183":{"tf":1.0},"184":{"tf":1.0}},"df":2}},"i":{"docs":{},"df":0,"d":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{"55":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{"107":{"tf":1.0},"150":{"tf":1.0},"154":{"tf":1.0},"166":{"tf":1.0},"72":{"tf":1.4142135623730951},"73":{"tf":1.0},"74":{"tf":1.4142135623730951},"75":{"tf":1.4142135623730951},"83":{"tf":1.0},"91":{"tf":1.7320508075688772}},"df":10}}},"l":{"docs":{},"df":0,"e":{"docs":{"13":{"tf":1.0},"133":{"tf":1.0},"172":{"tf":1.0},"173":{"tf":2.0},"174":{"tf":2.23606797749979},"175":{"tf":1.0},"176":{"tf":1.0},"178":{"tf":1.0},"184":{"tf":1.4142135623730951},"199":{"tf":1.0},"20":{"tf":1.0},"44":{"tf":1.0},"53":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"61":{"tf":1.4142135623730951},"62":{"tf":2.449489742783178},"63":{"tf":1.4142135623730951},"64":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":2.6457513110645907},"73":{"tf":1.0},"74":{"tf":1.0},"77":{"tf":1.0},"84":{"tf":1.0}},"df":25,"(":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"s":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"/":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{"178":{"tf":1.0}},"df":1}}}}}}}}}}},":":{"docs":{},"df":0,"/":{"docs":{},"df":0,"/":{"docs":{},"df":0,"/":{"docs":{},"df":0,"t":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"/":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{"63":{"tf":1.0}},"df":1}}}}}}}}}}}},"l":{"docs":{"20":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0}},"df":3}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"127":{"tf":2.0},"133":{"tf":1.0},"166":{"tf":1.0},"173":{"tf":1.0},"175":{"tf":1.0},"178":{"tf":1.0},"78":{"tf":1.0}},"df":7}},"d":{"docs":{"162":{"tf":1.0},"163":{"tf":1.0},"188":{"tf":1.0},"3":{"tf":1.0},"38":{"tf":1.0},"5":{"tf":1.4142135623730951},"66":{"tf":1.0},"68":{"tf":1.7320508075688772},"69":{"tf":1.0},"71":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"78":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}},"df":15},"e":{"docs":{"35":{"tf":1.0}},"df":1},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{"123":{"tf":1.0},"49":{"tf":1.0},"63":{"tf":1.0}},"df":3}}}},"r":{"docs":{"158":{"tf":1.4142135623730951}},"df":1,"e":{"docs":{"122":{"tf":1.0},"123":{"tf":1.4142135623730951},"127":{"tf":1.4142135623730951},"83":{"tf":1.0}},"df":4},"m":{"docs":{},"df":0,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"114":{"tf":1.0},"115":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"84":{"tf":1.0}},"df":5}}}},"s":{"docs":{},"df":0,"t":{"docs":{"103":{"tf":1.0},"133":{"tf":1.0},"134":{"tf":1.0},"172":{"tf":1.0},"53":{"tf":1.0},"57":{"tf":1.0},"61":{"tf":1.0},"64":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951},"76":{"tf":1.0},"77":{"tf":1.0},"88":{"tf":1.0},"92":{"tf":1.0}},"df":14}}},"t":{"docs":{"187":{"tf":1.0},"78":{"tf":1.0}},"df":2},"x":{"docs":{"132":{"tf":1.0},"134":{"tf":1.4142135623730951},"135":{"tf":1.0},"137":{"tf":1.7320508075688772},"138":{"tf":1.0},"177":{"tf":1.0},"32":{"tf":1.0},"8":{"tf":1.0},"92":{"tf":1.0}},"df":9}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"137":{"tf":1.0},"174":{"tf":1.0},"180":{"tf":1.0},"190":{"tf":1.0},"20":{"tf":1.0},"62":{"tf":1.0},"64":{"tf":1.0},"77":{"tf":1.4142135623730951}},"df":8},"s":{"docs":{},"df":0,"h":{"docs":{"11":{"tf":1.0},"187":{"tf":1.7320508075688772},"188":{"tf":1.0},"189":{"tf":1.0},"28":{"tf":1.0},"35":{"tf":1.0},"54":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"66":{"tf":2.0},"67":{"tf":1.0},"68":{"tf":1.0},"72":{"tf":1.0},"86":{"tf":1.0},"87":{"tf":1.4142135623730951}},"df":15}},"v":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"117":{"tf":1.0}},"df":1}}}}},"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"154":{"tf":1.0},"173":{"tf":1.0},"84":{"tf":1.0}},"df":3}}}}},"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"103":{"tf":1.0},"11":{"tf":1.0},"155":{"tf":1.7320508075688772},"16":{"tf":1.0},"191":{"tf":2.449489742783178},"194":{"tf":1.4142135623730951},"38":{"tf":1.7320508075688772}},"df":7,".":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"191":{"tf":2.23606797749979}},"df":1,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}},".":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"p":{"docs":{"191":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"191":{"tf":1.0}},"df":1}},"q":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}}}}}}},"f":{"docs":{"191":{"tf":1.0}},"df":1,"(":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}}}}},"n":{"docs":{"100":{"tf":1.4142135623730951},"101":{"tf":1.4142135623730951},"102":{"tf":1.4142135623730951},"104":{"tf":2.0},"107":{"tf":2.23606797749979},"108":{"tf":2.23606797749979},"109":{"tf":2.8284271247461903},"112":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":1.4142135623730951},"123":{"tf":1.4142135623730951},"124":{"tf":1.4142135623730951},"125":{"tf":2.0},"126":{"tf":1.4142135623730951},"127":{"tf":2.0},"133":{"tf":2.0},"134":{"tf":1.0},"146":{"tf":1.7320508075688772},"153":{"tf":1.4142135623730951},"154":{"tf":1.7320508075688772},"155":{"tf":3.0},"158":{"tf":1.0},"159":{"tf":2.23606797749979},"165":{"tf":1.4142135623730951},"166":{"tf":2.0},"168":{"tf":1.0},"173":{"tf":1.4142135623730951},"178":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.0},"191":{"tf":1.4142135623730951},"60":{"tf":1.4142135623730951},"64":{"tf":1.4142135623730951},"67":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.7320508075688772},"79":{"tf":1.0},"80":{"tf":1.4142135623730951},"81":{"tf":1.4142135623730951},"82":{"tf":1.4142135623730951},"83":{"tf":1.4142135623730951},"84":{"tf":1.4142135623730951},"92":{"tf":1.4142135623730951},"93":{"tf":2.449489742783178},"98":{"tf":1.0},"99":{"tf":1.4142135623730951}},"df":48,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"83":{"tf":1.0}},"df":1}}}}}}}}}}}}},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{"78":{"tf":1.0}},"df":1}}}}}}}}}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":2.0}},"df":1}}}}}}}}}},"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{"129":{"tf":1.0},"55":{"tf":1.0}},"df":2,"s":{"docs":{"26":{"tf":1.0}},"df":1}}},"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"106":{"tf":2.0},"107":{"tf":1.0},"127":{"tf":1.0},"142":{"tf":1.0},"151":{"tf":1.0},"155":{"tf":1.0},"168":{"tf":1.0},"170":{"tf":1.0},"174":{"tf":1.0},"19":{"tf":1.0},"191":{"tf":1.0},"22":{"tf":1.0},"38":{"tf":1.4142135623730951},"41":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":1.7320508075688772},"61":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":1.4142135623730951},"69":{"tf":1.4142135623730951},"7":{"tf":1.0},"78":{"tf":1.0},"8":{"tf":1.4142135623730951},"80":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0},"9":{"tf":1.0},"93":{"tf":1.0}},"df":30}}}},"o":{"docs":{"104":{"tf":2.449489742783178},"105":{"tf":1.7320508075688772},"166":{"tf":3.0}},"df":3,"(":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{"168":{"tf":1.0}},"df":1}}}},"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{"104":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"1":{"docs":{},"df":0,"0":{"docs":{"104":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}},"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{"104":{"tf":2.0},"105":{"tf":1.7320508075688772}},"df":2}}}}},"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"154":{"tf":1.0},"188":{"tf":1.0}},"df":2}}}}}}},"r":{"docs":{},"df":0,"(":{"docs":{},"df":0,"i":{"docs":{},"df":0,"=":{"docs":{},"df":0,"0":{"docs":{"163":{"tf":1.0}},"df":1}}}},"c":{"docs":{"160":{"tf":1.0}},"df":1},"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"174":{"tf":1.0},"67":{"tf":1.0}},"df":2}}},"m":{"docs":{"120":{"tf":1.0},"183":{"tf":1.0},"78":{"tf":1.0}},"df":3,"a":{"docs":{},"df":0,"l":{"docs":{"158":{"tf":1.0}},"df":1},"t":{"docs":{"199":{"tf":1.0},"62":{"tf":1.0}},"df":2,"!":{"docs":{},"df":0,"(":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}}},"e":{"docs":{},"df":0,"r":{"docs":{"160":{"tf":1.0},"168":{"tf":1.0}},"df":2}}},"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{"92":{"tf":1.0}},"df":1}}},"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"64":{"tf":1.0}},"df":1}}}}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"132":{"tf":1.4142135623730951},"176":{"tf":1.0},"19":{"tf":1.0},"26":{"tf":1.0},"68":{"tf":1.0}},"df":5}},"r":{"docs":{"191":{"tf":2.0},"90":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.0}},"df":4}}},"p":{"docs":{},"df":0,"u":{"docs":{"61":{"tf":1.4142135623730951},"63":{"tf":1.0},"66":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951}},"df":4}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"137":{"tf":1.0}},"df":1}}}}},"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"k":{"docs":{"128":{"tf":1.4142135623730951}},"df":1}}}}}}},"e":{"docs":{},"df":0,"e":{"docs":{"132":{"tf":1.0},"142":{"tf":1.0},"146":{"tf":2.0},"9":{"tf":1.0}},"df":4,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"146":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{"130":{"tf":1.0},"170":{"tf":1.0}},"df":2}}},"z":{"docs":{"64":{"tf":1.0}},"df":1}},"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"11":{"tf":1.0},"122":{"tf":1.0},"76":{"tf":1.0},"88":{"tf":1.0}},"df":4},"t":{"docs":{"5":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"h":{"docs":{"67":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"179":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.4142135623730951},"195":{"tf":1.0},"69":{"tf":1.0}},"df":5}}}}},"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"94":{"tf":1.0}},"df":1}}}}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"7":{"tf":1.0},"99":{"tf":1.0}},"df":2}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{"124":{"tf":1.0},"151":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"176":{"tf":1.0},"191":{"tf":1.0},"192":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":1.0}},"df":9,"i":{"docs":{"22":{"tf":1.0}},"df":1}}},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"102":{"tf":1.0},"109":{"tf":1.4142135623730951},"110":{"tf":1.0},"112":{"tf":1.0},"117":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"127":{"tf":1.4142135623730951},"128":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"142":{"tf":1.0},"15":{"tf":1.0},"150":{"tf":1.4142135623730951},"151":{"tf":2.0},"157":{"tf":1.0},"159":{"tf":1.4142135623730951},"160":{"tf":1.7320508075688772},"163":{"tf":1.0},"165":{"tf":1.7320508075688772},"168":{"tf":1.4142135623730951},"170":{"tf":1.0},"172":{"tf":1.0},"173":{"tf":2.23606797749979},"182":{"tf":1.0},"183":{"tf":1.4142135623730951},"184":{"tf":2.23606797749979},"187":{"tf":1.0},"190":{"tf":1.7320508075688772},"191":{"tf":1.7320508075688772},"28":{"tf":1.0},"36":{"tf":1.0},"56":{"tf":1.0},"60":{"tf":1.4142135623730951},"64":{"tf":1.7320508075688772},"68":{"tf":1.0},"69":{"tf":1.4142135623730951},"7":{"tf":1.0},"70":{"tf":1.7320508075688772},"71":{"tf":1.4142135623730951},"72":{"tf":2.0},"73":{"tf":1.4142135623730951},"74":{"tf":1.4142135623730951},"75":{"tf":1.7320508075688772},"76":{"tf":2.23606797749979},"77":{"tf":1.0},"78":{"tf":1.7320508075688772},"80":{"tf":2.23606797749979},"82":{"tf":1.4142135623730951},"84":{"tf":1.4142135623730951},"88":{"tf":1.0},"93":{"tf":1.0}},"df":52}}}}}},"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"11":{"tf":1.4142135623730951},"160":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"69":{"tf":1.0}},"df":5,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"137":{"tf":1.0}},"df":1}}}}}}}},"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"159":{"tf":1.0},"166":{"tf":1.0}},"df":2}}}}},"g":{"docs":{},"df":0,"_":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"127":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"c":{"docs":{},"df":0,"s":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"174":{"tf":1.4142135623730951}},"df":1}}}}},"c":{"docs":{},"df":0,"c":{"docs":{"47":{"tf":1.0}},"df":1}},"d":{"docs":{},"df":0,"b":{"docs":{"187":{"tf":1.0},"19":{"tf":1.0},"24":{"tf":1.0},"27":{"tf":1.0},"31":{"tf":1.7320508075688772},"43":{"tf":3.1622776601683795},"46":{"tf":1.4142135623730951},"47":{"tf":1.0},"49":{"tf":1.4142135623730951},"64":{"tf":3.872983346207417},"68":{"tf":5.196152422706632},"77":{"tf":1.4142135623730951}},"df":12}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"102":{"tf":1.0},"107":{"tf":1.4142135623730951},"108":{"tf":1.0},"109":{"tf":1.0},"11":{"tf":1.0},"112":{"tf":1.0},"113":{"tf":1.4142135623730951},"12":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.0},"127":{"tf":1.4142135623730951},"131":{"tf":1.0},"136":{"tf":1.0},"147":{"tf":1.0},"151":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.4142135623730951},"17":{"tf":1.0},"172":{"tf":1.0},"174":{"tf":2.0},"176":{"tf":1.0},"178":{"tf":1.0},"184":{"tf":1.0},"188":{"tf":1.4142135623730951},"19":{"tf":1.0},"197":{"tf":1.0},"2":{"tf":1.0},"20":{"tf":1.0},"40":{"tf":1.7320508075688772},"56":{"tf":1.0},"57":{"tf":2.0},"6":{"tf":1.0},"62":{"tf":1.0},"67":{"tf":1.4142135623730951},"68":{"tf":1.0},"7":{"tf":1.0},"72":{"tf":1.7320508075688772},"76":{"tf":1.0},"84":{"tf":2.6457513110645907},"87":{"tf":1.0}},"df":42}}},"t":{"docs":{"93":{"tf":1.0}},"df":1,"_":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"109":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"92":{"tf":1.4142135623730951}},"df":1}}}}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"92":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}}}}}},"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{"44":{"tf":1.4142135623730951}},"df":1}}}}}},"h":{"docs":{},"df":0,"z":{"docs":{"12":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"t":{"docs":{"161":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"49":{"tf":1.0},"57":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"63":{"tf":1.0},"67":{"tf":1.0}},"df":9,"@":{"docs":{},"df":0,"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"u":{"docs":{},"df":0,"b":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,":":{"docs":{},"df":0,"k":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"l":{"docs":{"63":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"v":{"docs":{},"df":0,"e":{"docs":{"114":{"tf":1.0},"124":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":2.0},"128":{"tf":1.0},"160":{"tf":1.0},"163":{"tf":1.0},"190":{"tf":1.0},"69":{"tf":1.4142135623730951},"73":{"tf":1.0},"74":{"tf":1.0},"9":{"tf":1.0}},"df":12,"n":{"docs":{"107":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.0},"128":{"tf":1.0},"164":{"tf":1.0},"189":{"tf":1.0},"69":{"tf":1.0},"78":{"tf":1.0},"96":{"tf":1.0}},"df":9}}}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"88":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"64":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"103":{"tf":1.0},"132":{"tf":1.0},"133":{"tf":2.0},"134":{"tf":1.0},"139":{"tf":1.0},"17":{"tf":1.0},"94":{"tf":1.0},"98":{"tf":1.0},"99":{"tf":1.0}},"df":9,"_":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{"133":{"tf":1.4142135623730951}},"df":1}}}}}},"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{"133":{"tf":1.4142135623730951}},"df":1}}}}}}}},"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"192":{"tf":1.0}},"df":1}}}}}}},"n":{"docs":{},"df":0,"u":{"docs":{"21":{"tf":1.0},"49":{"tf":1.4142135623730951},"53":{"tf":1.0},"68":{"tf":1.0}},"df":4}},"o":{"docs":{"125":{"tf":1.0},"44":{"tf":1.0},"47":{"tf":1.0},"52":{"tf":1.0},"60":{"tf":1.0},"69":{"tf":1.4142135623730951},"72":{"tf":1.4142135623730951}},"df":7,"a":{"docs":{},"df":0,"l":{"docs":{"2":{"tf":1.0}},"df":1}},"e":{"docs":{"126":{"tf":1.0},"127":{"tf":1.0},"60":{"tf":1.0}},"df":3},"o":{"docs":{},"df":0,"d":{"docs":{"158":{"tf":1.0},"56":{"tf":1.0},"61":{"tf":1.0},"84":{"tf":1.0},"92":{"tf":1.0}},"df":5}}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"106":{"tf":1.4142135623730951},"107":{"tf":2.8284271247461903},"108":{"tf":2.23606797749979},"109":{"tf":2.0},"11":{"tf":1.0},"115":{"tf":1.0},"117":{"tf":1.0},"141":{"tf":1.0},"142":{"tf":1.4142135623730951},"153":{"tf":1.7320508075688772},"69":{"tf":1.4142135623730951},"76":{"tf":1.7320508075688772}},"df":12,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":1.0}},"df":3}}}}}},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{"76":{"tf":1.0}},"df":1}}}}}},"a":{"docs":{"127":{"tf":3.1622776601683795}},"df":1,".":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{},"df":0,"r":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{},"df":0,"r":{"docs":{},"df":0,"0":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}},"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"r":{"docs":{},"df":0,".":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"y":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"_":{"docs":{"127":{"tf":1.7320508075688772}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{"107":{"tf":1.4142135623730951},"108":{"tf":1.4142135623730951},"109":{"tf":2.8284271247461903},"112":{"tf":1.7320508075688772}},"df":4,"<":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{"109":{"tf":1.4142135623730951}},"df":1}}},"e":{"docs":{},"df":0,"n":{"docs":{"109":{"tf":3.0},"112":{"tf":1.0}},"df":2}}}}}}}}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"102":{"tf":1.4142135623730951}},"df":1}}}}},"l":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{"49":{"tf":1.0},"51":{"tf":1.0},"59":{"tf":1.0}},"df":3},"n":{"docs":{},"df":0,"t":{"docs":{"126":{"tf":1.0}},"df":1}},"p":{"docs":{},"df":0,"h":{"docs":{"78":{"tf":1.0}},"df":1,"i":{"docs":{},"df":0,"c":{"docs":{"86":{"tf":1.4142135623730951}},"df":1}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"121":{"tf":1.0},"126":{"tf":1.0},"187":{"tf":1.0},"70":{"tf":1.0}},"df":4,"e":{"docs":{},"df":0,"r":{"docs":{"125":{"tf":1.0},"189":{"tf":1.0}},"df":2}},"l":{"docs":{},"df":0,"i":{"docs":{"190":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"n":{"docs":{"59":{"tf":1.0}},"df":1}},"p":{"docs":{"44":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"5":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{"5":{"tf":1.0}},"df":1}},"w":{"docs":{"136":{"tf":1.4142135623730951},"138":{"tf":1.0}},"df":2}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{"1":{"tf":1.0},"115":{"tf":1.0},"120":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.4142135623730951},"124":{"tf":1.0},"125":{"tf":1.0},"128":{"tf":1.0},"159":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"166":{"tf":1.0},"173":{"tf":1.7320508075688772},"71":{"tf":1.0}},"df":14}}}}}},"i":{"docs":{"63":{"tf":1.0}},"df":1,"d":{"docs":{"151":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"141":{"tf":1.0}},"df":1}}}}}}},"y":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{"11":{"tf":1.0}},"df":1}}}}}}}},"h":{"docs":{"172":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"l":{"docs":{"114":{"tf":1.4142135623730951},"115":{"tf":2.449489742783178},"116":{"tf":1.0},"117":{"tf":2.0},"118":{"tf":1.4142135623730951},"119":{"tf":1.0},"129":{"tf":1.0},"141":{"tf":1.4142135623730951},"142":{"tf":1.7320508075688772},"144":{"tf":1.4142135623730951},"146":{"tf":1.4142135623730951},"147":{"tf":1.7320508075688772},"148":{"tf":1.4142135623730951},"150":{"tf":1.0},"153":{"tf":1.0},"155":{"tf":1.4142135623730951},"193":{"tf":1.0},"195":{"tf":1.0},"69":{"tf":2.0},"76":{"tf":1.4142135623730951}},"df":20,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}},"f":{"docs":{"184":{"tf":1.0}},"df":1,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"122":{"tf":1.0}},"df":1}}}},"t":{"docs":{"28":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":3.0},"78":{"tf":1.7320508075688772},"79":{"tf":1.0},"81":{"tf":1.0}},"df":6},"v":{"docs":{"189":{"tf":1.0}},"df":1}},"n":{"docs":{},"df":0,"d":{"docs":{"100":{"tf":1.0},"121":{"tf":1.0},"124":{"tf":1.0},"137":{"tf":1.0},"138":{"tf":1.0},"72":{"tf":1.0}},"df":6,"l":{"docs":{"127":{"tf":1.0},"133":{"tf":1.0},"139":{"tf":1.4142135623730951},"168":{"tf":1.0},"67":{"tf":1.0},"69":{"tf":1.0},"76":{"tf":1.0},"80":{"tf":1.0},"82":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":1.0},"96":{"tf":1.0}},"df":12,"e":{"docs":{},"df":0,"r":{"docs":{"120":{"tf":1.0},"122":{"tf":1.4142135623730951},"123":{"tf":1.0},"124":{"tf":1.0},"126":{"tf":1.7320508075688772},"127":{"tf":1.0},"64":{"tf":1.4142135623730951},"72":{"tf":1.0},"76":{"tf":1.0},"78":{"tf":1.4142135623730951},"80":{"tf":4.242640687119285},"81":{"tf":1.0},"82":{"tf":1.7320508075688772},"83":{"tf":2.23606797749979},"84":{"tf":3.4641016151377544}},"df":15}}}}},"p":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"107":{"tf":1.0},"120":{"tf":1.4142135623730951},"87":{"tf":1.0}},"df":3}},"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"123":{"tf":1.0},"163":{"tf":1.0},"83":{"tf":1.0}},"df":3}}}}},"r":{"docs":{},"df":0,"d":{"docs":{"137":{"tf":1.0},"138":{"tf":1.4142135623730951},"68":{"tf":1.0},"8":{"tf":1.0},"83":{"tf":1.0}},"df":5,"e":{"docs":{},"df":0,"r":{"docs":{"136":{"tf":1.0}},"df":1}},"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"62":{"tf":1.0},"68":{"tf":1.0},"83":{"tf":2.0}},"df":3,"(":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{"83":{"tf":1.0}},"df":1}}},"_":{"docs":{"62":{"tf":1.7320508075688772}},"df":1},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"62":{"tf":1.0}},"df":1}}}}}}}}}}}}}},"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"10":{"tf":1.0},"101":{"tf":1.4142135623730951},"102":{"tf":1.7320508075688772},"107":{"tf":1.7320508075688772},"108":{"tf":1.4142135623730951},"11":{"tf":1.0},"114":{"tf":2.23606797749979},"115":{"tf":1.4142135623730951},"117":{"tf":2.0},"119":{"tf":2.0},"124":{"tf":1.0},"130":{"tf":1.0},"14":{"tf":1.0},"141":{"tf":1.0},"164":{"tf":1.0},"166":{"tf":1.4142135623730951},"191":{"tf":1.0},"192":{"tf":1.0},"195":{"tf":1.0},"196":{"tf":1.0},"197":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.0},"27":{"tf":1.0},"30":{"tf":1.0},"32":{"tf":1.4142135623730951},"33":{"tf":1.0},"38":{"tf":1.7320508075688772},"53":{"tf":1.4142135623730951},"54":{"tf":2.0},"55":{"tf":1.0},"60":{"tf":1.0},"63":{"tf":1.4142135623730951},"65":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.7320508075688772},"70":{"tf":1.0},"77":{"tf":1.7320508075688772},"80":{"tf":1.4142135623730951},"81":{"tf":1.0},"86":{"tf":1.0},"88":{"tf":1.4142135623730951},"92":{"tf":1.4142135623730951},"94":{"tf":1.4142135623730951},"96":{"tf":1.0}},"df":48}}}}},"s":{"docs":{},"df":0,"h":{"docs":{"161":{"tf":1.0}},"df":1,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"132":{"tf":1.0},"17":{"tf":1.0}},"df":2}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"17":{"tf":1.0}},"df":1}}}}},"v":{"docs":{},"df":0,"e":{"docs":{"115":{"tf":1.0},"125":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.0},"86":{"tf":1.0}},"df":5,"n":{"docs":{},"df":0,"’":{"docs":{},"df":0,"t":{"docs":{"61":{"tf":1.0}},"df":1}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"133":{"tf":2.23606797749979},"46":{"tf":1.0},"63":{"tf":1.0},"68":{"tf":1.0}},"df":4,"e":{"docs":{},"df":0,"r":{"docs":{"11":{"tf":1.0},"172":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.0},"184":{"tf":2.0},"53":{"tf":1.4142135623730951},"62":{"tf":3.3166247903554},"68":{"tf":1.0}},"df":9}}},"p":{"docs":{"122":{"tf":1.0},"132":{"tf":1.4142135623730951},"133":{"tf":1.0},"134":{"tf":1.4142135623730951},"135":{"tf":1.0},"136":{"tf":1.0},"137":{"tf":1.0},"17":{"tf":1.0}},"df":8,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"132":{"tf":1.0},"134":{"tf":2.23606797749979},"136":{"tf":1.0},"139":{"tf":1.7320508075688772}},"df":4,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"134":{"tf":1.0}},"df":1}}}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{"134":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{"136":{"tf":1.0},"138":{"tf":1.0}},"df":2}}}}},":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"134":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"t":{"docs":{"125":{"tf":1.0}},"df":1}},"v":{"docs":{},"df":0,"i":{"docs":{"124":{"tf":1.0}},"df":1}}},"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{"63":{"tf":2.23606797749979},"64":{"tf":2.23606797749979},"67":{"tf":1.4142135623730951},"68":{"tf":1.7320508075688772},"76":{"tf":1.0},"77":{"tf":2.0}},"df":6,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"_":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"64":{"tf":1.0},"68":{"tf":1.0}},"df":2,"_":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"68":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"p":{"docs":{"120":{"tf":1.0},"191":{"tf":1.0},"5":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"92":{"tf":1.0},"98":{"tf":1.0}},"df":7,"f":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"67":{"tf":1.0}},"df":1}}}}}}},"n":{"docs":{},"df":0,"c":{"docs":{"63":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"e":{"docs":{"101":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.0},"160":{"tf":1.0},"173":{"tf":1.0},"176":{"tf":1.0},"183":{"tf":1.0},"196":{"tf":1.0},"198":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":1.0},"42":{"tf":1.0},"49":{"tf":1.0},"5":{"tf":1.0},"50":{"tf":1.0},"6":{"tf":1.0},"60":{"tf":1.4142135623730951},"69":{"tf":1.0},"75":{"tf":1.0},"84":{"tf":1.0}},"df":20,"’":{"docs":{"188":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0}},"df":4}}},"x":{"docs":{"62":{"tf":1.0},"83":{"tf":1.0}},"df":2}},"i":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2,"g":{"docs":{},"df":0,"h":{"docs":{"106":{"tf":3.0},"107":{"tf":2.449489742783178},"108":{"tf":2.23606797749979},"109":{"tf":2.0},"114":{"tf":1.0},"122":{"tf":1.0},"127":{"tf":1.0},"189":{"tf":1.0},"193":{"tf":1.0},"26":{"tf":1.0},"35":{"tf":1.0}},"df":11,"e":{"docs":{},"df":0,"r":{"docs":{"1":{"tf":1.0},"123":{"tf":1.0},"160":{"tf":1.0},"165":{"tf":1.4142135623730951},"76":{"tf":1.7320508075688772},"84":{"tf":1.0},"93":{"tf":1.0}},"df":7}},"l":{"docs":{},"df":0,"i":{"docs":{"19":{"tf":1.0},"31":{"tf":1.0},"5":{"tf":1.0},"70":{"tf":1.0}},"df":4,"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"t":{"docs":{"156":{"tf":1.0},"53":{"tf":1.0},"56":{"tf":1.0}},"df":3}}}}},"z":{"docs":{"109":{"tf":2.23606797749979},"112":{"tf":1.4142135623730951}},"df":2}}},"o":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"h":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"83":{"tf":1.0}},"df":1,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"o":{"docs":{},"df":0,"k":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}}}}},"{":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}},"t":{"docs":{"68":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"w":{"docs":{},"df":0,"d":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}}}}}},"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"b":{"docs":{},"df":0,"y":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"36":{"tf":1.0}},"df":1}}}}}},"l":{"docs":{},"df":0,"d":{"docs":{"126":{"tf":1.0},"134":{"tf":1.0},"190":{"tf":1.0},"95":{"tf":1.0}},"df":4}},"m":{"docs":{},"df":0,"e":{"docs":{"86":{"tf":1.0}},"df":1,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"45":{"tf":1.0}},"df":1}}}}}},"o":{"docs":{},"df":0,"d":{"docs":{"164":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"t":{"docs":{"177":{"tf":1.0},"178":{"tf":1.0},"22":{"tf":1.0},"24":{"tf":1.0},"27":{"tf":1.0},"32":{"tf":1.0},"63":{"tf":2.0},"77":{"tf":1.7320508075688772},"78":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.0}},"df":11,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}},"p":{"docs":{},"df":0,"p":{"docs":{"172":{"tf":1.0}},"df":1},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"n":{"docs":{"191":{"tf":1.4142135623730951},"64":{"tf":1.0}},"df":2,"!":{"docs":{},"df":0,"(":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"191":{"tf":1.0}},"df":1}}}}},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{"64":{"tf":1.4142135623730951},"67":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":1.0}},"df":4}}}}},"t":{"docs":{},"df":0,"h":{"docs":{"191":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"83":{"tf":1.0}},"df":1}}}}}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,":":{"docs":{},"df":0,"/":{"docs":{},"df":0,"/":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"d":{"docs":{},"df":0,".":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"g":{"docs":{},"df":0,"/":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"/":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"x":{"docs":{},"df":0,"y":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"/":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"s":{"docs":{},"df":0,".":{"docs":{},"df":0,"h":{"docs":{},"df":0,"t":{"docs":{},"df":0,"m":{"docs":{},"df":0,"l":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,":":{"docs":{},"df":0,"/":{"docs":{},"df":0,"/":{"docs":{},"df":0,"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"u":{"docs":{},"df":0,"b":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"/":{"docs":{},"df":0,"k":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"l":{"docs":{"57":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"58":{"tf":1.0},"59":{"tf":1.0},"62":{"tf":1.0},"67":{"tf":1.0}},"df":4}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{"38":{"tf":1.0}},"df":1}}}}}}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,".":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"t":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"/":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"k":{"docs":{"39":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{"187":{"tf":1.0}},"df":1}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"86":{"tf":1.0}},"df":1}}},"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"r":{"docs":{"87":{"tf":1.0}},"df":1}}}},"w":{"docs":{"13":{"tf":1.0},"70":{"tf":1.0}},"df":2}},"i":{"docs":{},"df":0,".":{"docs":{"115":{"tf":1.4142135623730951},"187":{"tf":1.0},"2":{"tf":1.4142135623730951},"63":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0},"87":{"tf":1.0},"9":{"tf":1.0}},"df":8},"/":{"docs":{},"df":0,"o":{"docs":{"103":{"tf":1.0},"13":{"tf":1.0},"146":{"tf":1.0},"5":{"tf":1.0},"77":{"tf":1.0},"86":{"tf":1.4142135623730951}},"df":6}},"1":{"docs":{},"df":0,"6":{"docs":{"82":{"tf":1.0}},"df":1}},"2":{"docs":{},"df":0,"c":{"docs":{"11":{"tf":1.0},"115":{"tf":1.0},"117":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}},"df":5}},"<":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"z":{"docs":{},"df":0,"e":{"docs":{},"df":0,"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"(":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,")":{"docs":{},"df":0,"/":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"z":{"docs":{},"df":0,"e":{"docs":{},"df":0,"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"(":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"[":{"docs":{},"df":0,"0":{"docs":{"163":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}},"c":{"docs":{"196":{"tf":1.0}},"df":1},"d":{"docs":{"31":{"tf":1.0},"34":{"tf":1.0},"36":{"tf":1.0},"44":{"tf":1.0}},"df":4,"e":{"docs":{},"df":0,"a":{"docs":{"190":{"tf":1.0},"84":{"tf":1.0}},"df":2},"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"28":{"tf":1.0},"66":{"tf":1.0}},"df":2}}}}}},"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"4":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"t":{"docs":{"178":{"tf":1.0}},"df":1}}}}}},"f":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{"157":{"tf":1.0},"158":{"tf":1.0}},"df":2}}}},"g":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"122":{"tf":1.0},"64":{"tf":1.0},"66":{"tf":1.0},"87":{"tf":1.0}},"df":4}}}},"i":{"docs":{},"df":0,"r":{"docs":{"158":{"tf":1.4142135623730951}},"df":1}},"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"g":{"docs":{"110":{"tf":1.0},"83":{"tf":1.0}},"df":2}},"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{"107":{"tf":1.0}},"df":1}}}}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"114":{"tf":1.0},"61":{"tf":1.0},"9":{"tf":1.0}},"df":3,"i":{"docs":{},"df":0,"n":{"docs":{"91":{"tf":1.0},"96":{"tf":1.0}},"df":2,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}},"m":{"docs":{"62":{"tf":1.0},"83":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{"123":{"tf":1.0},"126":{"tf":1.0},"68":{"tf":1.4142135623730951}},"df":3}}},"u":{"docs":{},"df":0,"t":{"docs":{"102":{"tf":1.0},"96":{"tf":1.0}},"df":2}}},"p":{"docs":{},"df":0,"l":{"docs":{"101":{"tf":1.0},"104":{"tf":1.0},"107":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":1.0},"117":{"tf":1.0},"125":{"tf":1.4142135623730951},"133":{"tf":1.4142135623730951},"146":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.4142135623730951},"155":{"tf":3.7416573867739413},"93":{"tf":1.0},"99":{"tf":1.0}},"df":14,"<":{"docs":{"155":{"tf":2.23606797749979}},"df":1,"e":{"docs":{},"df":0,"n":{"docs":{"109":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}},"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"113":{"tf":1.0},"115":{"tf":3.1622776601683795},"117":{"tf":1.7320508075688772},"118":{"tf":1.7320508075688772},"119":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.7320508075688772},"128":{"tf":1.0},"13":{"tf":1.0},"132":{"tf":2.23606797749979},"133":{"tf":2.0},"142":{"tf":1.0},"148":{"tf":1.4142135623730951},"150":{"tf":1.0},"153":{"tf":1.0},"155":{"tf":1.0},"163":{"tf":1.0},"165":{"tf":1.0},"195":{"tf":1.4142135623730951},"69":{"tf":1.0},"7":{"tf":1.0},"71":{"tf":1.0},"76":{"tf":1.0},"84":{"tf":1.0}},"df":25}}}}},"i":{"docs":{"80":{"tf":1.0}},"df":1,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"136":{"tf":1.0},"137":{"tf":1.0}},"df":2}}}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"101":{"tf":1.4142135623730951},"114":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.0},"133":{"tf":1.0},"163":{"tf":1.0},"55":{"tf":1.0},"60":{"tf":1.0},"62":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.0},"81":{"tf":1.0},"86":{"tf":1.0},"91":{"tf":1.0}},"df":14,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"92":{"tf":1.0}},"df":1}}}}}}},"s":{"docs":{},"df":0,"s":{"docs":{"110":{"tf":1.0},"136":{"tf":1.0},"76":{"tf":1.0}},"df":3}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"v":{"docs":{"166":{"tf":1.0},"3":{"tf":1.0},"83":{"tf":1.0}},"df":3}}}}},"n":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"109":{"tf":1.7320508075688772}},"df":1}}}},"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"160":{"tf":1.0}},"df":1}}}}}}}},"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"u":{"docs":{},"df":0,"d":{"docs":{"105":{"tf":1.0},"115":{"tf":1.0},"118":{"tf":1.0},"120":{"tf":1.0},"128":{"tf":1.0},"129":{"tf":1.4142135623730951},"130":{"tf":1.0},"131":{"tf":1.0},"137":{"tf":1.0},"138":{"tf":1.0},"158":{"tf":1.7320508075688772},"161":{"tf":1.0},"169":{"tf":1.0},"172":{"tf":1.0},"173":{"tf":1.4142135623730951},"174":{"tf":1.0},"175":{"tf":1.0},"184":{"tf":1.4142135623730951},"21":{"tf":1.0},"24":{"tf":1.0},"30":{"tf":1.0},"35":{"tf":1.0},"50":{"tf":1.0},"53":{"tf":1.0},"66":{"tf":1.4142135623730951},"68":{"tf":1.0},"69":{"tf":1.0},"72":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.4142135623730951}},"df":30}}},"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"160":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":1.0}},"df":1}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"134":{"tf":1.0},"137":{"tf":1.4142135623730951},"151":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.0},"190":{"tf":1.0}},"df":6}},"m":{"docs":{"122":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"122":{"tf":1.4142135623730951},"123":{"tf":1.0},"124":{"tf":1.4142135623730951}},"df":3,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"125":{"tf":1.0}},"df":1}}}}}}}}}}}},"u":{"docs":{},"df":0,"r":{"docs":{"110":{"tf":1.0}},"df":1}}},"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"114":{"tf":1.0},"120":{"tf":1.0},"94":{"tf":1.0}},"df":3}}}},"x":{"docs":{"163":{"tf":2.0},"62":{"tf":1.0},"78":{"tf":1.4142135623730951},"79":{"tf":1.7320508075688772}},"df":4}},"i":{"docs":{},"df":0,"c":{"docs":{"127":{"tf":1.0},"134":{"tf":1.4142135623730951},"16":{"tf":1.0},"164":{"tf":1.4142135623730951},"165":{"tf":1.7320508075688772},"44":{"tf":1.0},"60":{"tf":1.7320508075688772},"68":{"tf":1.0},"82":{"tf":1.7320508075688772},"9":{"tf":1.0}},"df":10},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"80":{"tf":1.0},"86":{"tf":1.0}},"df":2}}}}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{},"df":0,"u":{"docs":{"165":{"tf":1.0}},"df":1}}}}}},"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"64":{"tf":1.0},"68":{"tf":1.0}},"df":2}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"68":{"tf":1.0},"78":{"tf":1.0}},"df":2}}}},"o":{"docs":{"53":{"tf":3.0},"68":{"tf":4.0}},"df":2,"r":{"docs":{},"df":0,"m":{"docs":{"104":{"tf":1.0},"11":{"tf":1.0},"128":{"tf":1.0},"129":{"tf":1.0},"161":{"tf":1.4142135623730951},"187":{"tf":1.0},"198":{"tf":1.0},"20":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":1.0},"30":{"tf":1.0},"5":{"tf":1.0},"62":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.4142135623730951},"69":{"tf":1.4142135623730951},"77":{"tf":1.0},"78":{"tf":1.0},"86":{"tf":1.0}},"df":20}}}},"g":{"docs":{"136":{"tf":1.0}},"df":1},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"190":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"t":{"docs":{"100":{"tf":1.0},"17":{"tf":1.0},"72":{"tf":1.0}},"df":3,"(":{"docs":{},"df":0,"c":{"docs":{},"df":0,"x":{"docs":{"100":{"tf":1.0}},"df":1}}},":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"t":{"docs":{"100":{"tf":1.0}},"df":1}}}}}}}}},"i":{"docs":{"103":{"tf":1.0},"104":{"tf":1.0},"117":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"151":{"tf":1.0},"55":{"tf":1.0},"61":{"tf":1.4142135623730951},"62":{"tf":1.4142135623730951},"81":{"tf":1.0},"84":{"tf":1.0}},"df":11,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{"119":{"tf":1.0},"127":{"tf":1.7320508075688772}},"df":2}}}}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"134":{"tf":1.0},"151":{"tf":2.0},"160":{"tf":1.7320508075688772},"189":{"tf":1.0},"190":{"tf":3.0}},"df":5,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"160":{"tf":1.0}},"df":1}}}}}}}}}},"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"104":{"tf":1.4142135623730951},"190":{"tf":1.0}},"df":2}}},"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"103":{"tf":1.0},"106":{"tf":3.7416573867739413},"107":{"tf":3.0},"108":{"tf":3.1622776601683795},"109":{"tf":4.123105625617661},"11":{"tf":1.0},"110":{"tf":1.0},"111":{"tf":1.0},"112":{"tf":1.4142135623730951},"115":{"tf":1.0},"121":{"tf":1.4142135623730951},"122":{"tf":1.0},"127":{"tf":1.4142135623730951},"151":{"tf":1.0},"155":{"tf":2.23606797749979}},"df":15,"<":{"docs":{"155":{"tf":1.7320508075688772}},"df":1},"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,".":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"_":{"docs":{},"df":0,"z":{"docs":{"109":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"109":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"n":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}},"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}},"s":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":3.0}},"df":1,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,">":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"155":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"134":{"tf":1.0},"166":{"tf":1.4142135623730951},"61":{"tf":1.0}},"df":3}}},"i":{"docs":{},"df":0,"d":{"docs":{"109":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.7320508075688772},"127":{"tf":1.0},"171":{"tf":1.0},"179":{"tf":1.0},"181":{"tf":1.0},"80":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":9}},"n":{"docs":{"62":{"tf":1.0},"83":{"tf":1.0}},"df":2},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"21":{"tf":1.0},"24":{"tf":1.0},"28":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"62":{"tf":1.7320508075688772},"67":{"tf":1.0},"75":{"tf":1.0}},"df":8}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"114":{"tf":1.0},"19":{"tf":1.0},"21":{"tf":1.4142135623730951},"37":{"tf":1.0},"38":{"tf":1.4142135623730951},"39":{"tf":1.4142135623730951},"40":{"tf":1.7320508075688772},"42":{"tf":1.0},"43":{"tf":1.7320508075688772},"45":{"tf":1.0},"46":{"tf":2.23606797749979},"47":{"tf":1.7320508075688772},"49":{"tf":1.4142135623730951},"50":{"tf":1.7320508075688772},"52":{"tf":1.7320508075688772},"53":{"tf":1.0},"57":{"tf":1.4142135623730951},"61":{"tf":1.4142135623730951},"64":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951}},"df":21},"n":{"docs":{},"df":0,"c":{"docs":{"103":{"tf":1.0},"105":{"tf":1.4142135623730951},"118":{"tf":1.4142135623730951},"127":{"tf":1.4142135623730951},"166":{"tf":1.0},"188":{"tf":1.0},"67":{"tf":1.0},"93":{"tf":1.0},"96":{"tf":1.4142135623730951},"99":{"tf":1.0}},"df":10},"t":{"docs":{},"df":0,"i":{"docs":{"134":{"tf":1.0},"139":{"tf":1.0},"188":{"tf":1.0},"97":{"tf":1.0}},"df":4}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"100":{"tf":1.0},"108":{"tf":1.4142135623730951},"109":{"tf":1.0},"110":{"tf":1.0},"111":{"tf":1.0},"122":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.4142135623730951},"131":{"tf":1.0},"133":{"tf":1.0},"136":{"tf":1.0},"14":{"tf":1.0},"142":{"tf":1.0},"144":{"tf":1.0},"16":{"tf":1.0},"160":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"173":{"tf":1.0},"178":{"tf":1.0},"180":{"tf":1.0},"183":{"tf":1.0},"191":{"tf":1.0},"53":{"tf":1.0},"60":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951},"78":{"tf":1.0},"84":{"tf":1.0},"87":{"tf":1.4142135623730951},"88":{"tf":1.0},"92":{"tf":1.0},"99":{"tf":1.4142135623730951}},"df":36}}},"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"112":{"tf":1.0},"124":{"tf":2.23606797749979},"131":{"tf":1.0},"151":{"tf":1.0},"16":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"19":{"tf":1.0},"37":{"tf":1.0},"38":{"tf":1.0},"41":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"52":{"tf":1.0},"62":{"tf":1.7320508075688772},"64":{"tf":1.0},"69":{"tf":1.0},"78":{"tf":1.0},"8":{"tf":1.0},"80":{"tf":1.0},"83":{"tf":1.0}},"df":21}},"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"69":{"tf":1.0},"72":{"tf":1.0}},"df":2}}}}}}}},"t":{"docs":{"163":{"tf":1.0},"168":{"tf":1.7320508075688772},"173":{"tf":1.7320508075688772}},"df":3,"1":{"docs":{},"df":0,"6":{"docs":{},"df":0,"_":{"docs":{},"df":0,"t":{"docs":{"163":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"g":{"docs":{},"df":0,"r":{"docs":{"11":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"170":{"tf":1.0},"171":{"tf":1.0},"196":{"tf":1.0},"24":{"tf":1.0},"26":{"tf":1.4142135623730951},"27":{"tf":1.0},"31":{"tf":1.0},"34":{"tf":1.0},"80":{"tf":1.0}},"df":12}},"n":{"docs":{},"df":0,"d":{"docs":{"141":{"tf":1.0},"28":{"tf":1.0},"60":{"tf":1.0},"80":{"tf":1.0},"84":{"tf":1.0},"92":{"tf":1.0}},"df":6}},"r":{"docs":{"196":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"114":{"tf":1.0},"118":{"tf":1.0},"13":{"tf":1.0},"142":{"tf":1.0},"161":{"tf":1.0},"164":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"24":{"tf":1.0},"26":{"tf":1.0},"28":{"tf":1.0},"31":{"tf":1.0},"69":{"tf":1.0},"86":{"tf":1.4142135623730951},"88":{"tf":1.4142135623730951},"95":{"tf":1.0},"98":{"tf":1.0},"99":{"tf":1.0}},"df":18}}},"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"130":{"tf":1.0}},"df":1}}},"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{"103":{"tf":1.7320508075688772},"107":{"tf":1.4142135623730951},"108":{"tf":1.4142135623730951},"109":{"tf":1.7320508075688772},"11":{"tf":1.0},"110":{"tf":1.0},"112":{"tf":1.0},"117":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"13":{"tf":1.0},"142":{"tf":1.4142135623730951},"153":{"tf":1.7320508075688772},"173":{"tf":1.4142135623730951},"174":{"tf":1.4142135623730951},"175":{"tf":1.4142135623730951},"178":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"198":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.0},"30":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0},"60":{"tf":1.7320508075688772},"68":{"tf":1.7320508075688772},"86":{"tf":1.4142135623730951},"87":{"tf":1.0},"88":{"tf":1.0}},"df":33,"e":{"docs":{},"df":0,"/":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"k":{"docs":{"53":{"tf":2.0},"68":{"tf":1.4142135623730951}},"df":2,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"f":{"docs":{},"df":0,"g":{"docs":{"53":{"tf":1.4142135623730951},"68":{"tf":1.0}},"df":2}}}}}}}}}}}}}}},"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"125":{"tf":1.7320508075688772},"126":{"tf":1.4142135623730951},"127":{"tf":1.0}},"df":3}}},"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{"168":{"tf":1.0}},"df":1}}}},"n":{"docs":{"118":{"tf":1.0},"119":{"tf":1.0},"87":{"tf":1.0}},"df":3},"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"130":{"tf":1.0},"141":{"tf":1.0},"142":{"tf":1.0},"166":{"tf":1.4142135623730951},"168":{"tf":1.0},"170":{"tf":1.0},"181":{"tf":1.0}},"df":7}}}},"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"120":{"tf":1.7320508075688772},"121":{"tf":1.0},"122":{"tf":2.8284271247461903},"123":{"tf":3.605551275463989},"124":{"tf":2.23606797749979},"125":{"tf":2.0},"126":{"tf":2.0},"127":{"tf":3.0},"128":{"tf":1.0},"130":{"tf":1.0},"131":{"tf":1.0},"133":{"tf":1.0},"165":{"tf":2.23606797749979},"4":{"tf":1.0},"5":{"tf":1.4142135623730951},"62":{"tf":1.0},"69":{"tf":1.0},"80":{"tf":1.7320508075688772},"82":{"tf":1.0},"84":{"tf":5.477225575051661}},"df":20,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"125":{"tf":1.4142135623730951}},"df":1,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"125":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}},"f":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{"125":{"tf":1.0},"133":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"_":{"docs":{"133":{"tf":1.0}},"df":1},"c":{"docs":{"125":{"tf":1.4142135623730951},"126":{"tf":1.4142135623730951},"127":{"tf":2.8284271247461903}},"df":3}}}}}}}}},"s":{"docs":{},"df":0,"—":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"84":{"tf":1.0}},"df":1}}}}}}}}}}},"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"a":{"docs":{},"df":0,"f":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"<":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"a":{"docs":{},"df":0,"f":{"docs":{},"df":0,"1":{"docs":{},"df":0,">":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"76":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}},"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{"104":{"tf":1.0},"105":{"tf":1.4142135623730951}},"df":2,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"104":{"tf":1.0}},"df":1}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":1.0}},"df":1,"<":{"docs":{},"df":0,"n":{"docs":{"155":{"tf":1.4142135623730951}},"df":1}},"_":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"_":{"docs":{},"df":0,"z":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"109":{"tf":1.0},"112":{"tf":1.0}},"df":2}}}}}}}}}}},"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"n":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}},"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":1.0}},"df":1,"<":{"docs":{},"df":0,"n":{"docs":{"155":{"tf":1.4142135623730951}},"df":1}}}}}}}}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"70":{"tf":1.0}},"df":1,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"0":{"tf":1.0}},"df":1}}}}}}}}}},"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"80":{"tf":1.0},"83":{"tf":1.4142135623730951}},"df":4}}},"r":{"docs":{},"df":0,"i":{"docs":{"190":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"c":{"docs":{"136":{"tf":1.0},"80":{"tf":1.0}},"df":2},"k":{"docs":{"15":{"tf":1.0},"63":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":1.0},"83":{"tf":1.0}},"df":5},"l":{"docs":{},"df":0,"v":{"docs":{"16":{"tf":1.0},"168":{"tf":1.0},"19":{"tf":1.0},"64":{"tf":1.4142135623730951},"80":{"tf":1.4142135623730951}},"df":5}}}}},"o":{"docs":{},"df":0,"/":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"5":{"tf":1.0}},"df":1}}}}}}}}}},"r":{"docs":{},"df":0,"q":{"docs":{},"df":0,"n":{"docs":{"82":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}},"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}},"n":{"docs":{},"df":0,"\'":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0}},"df":1}},"’":{"docs":{},"df":0,"t":{"docs":{"102":{"tf":1.0},"72":{"tf":1.0}},"df":2}}},"r":{"docs":{"165":{"tf":1.4142135623730951}},"df":1},"s":{"docs":{},"df":0,"u":{"docs":{"169":{"tf":1.4142135623730951},"170":{"tf":1.4142135623730951},"32":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"8":{"tf":1.0},"80":{"tf":1.4142135623730951}},"df":7}}},"t":{"docs":{},"df":0,"\'":{"docs":{"80":{"tf":1.0},"84":{"tf":1.0}},"df":2},"e":{"docs":{},"df":0,"m":{"docs":{"100":{"tf":1.0},"160":{"tf":1.7320508075688772}},"df":2},"r":{"docs":{"163":{"tf":2.23606797749979},"189":{"tf":1.0}},"df":2}},"m":{"docs":{"78":{"tf":1.4142135623730951}},"df":1},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"138":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.0},"91":{"tf":1.0}},"df":4}}}},"’":{"docs":{"120":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.0},"126":{"tf":1.0},"130":{"tf":1.0},"133":{"tf":1.0},"134":{"tf":1.0},"137":{"tf":1.0},"158":{"tf":1.4142135623730951},"186":{"tf":1.0},"188":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":1.4142135623730951},"80":{"tf":1.4142135623730951},"82":{"tf":1.0},"86":{"tf":1.0},"92":{"tf":1.0}},"df":18}},"²":{"docs":{},"df":0,"c":{"docs":{"196":{"tf":1.0}},"df":1}}},"j":{"docs":{"24":{"tf":1.0},"35":{"tf":1.4142135623730951}},"df":2,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{"6":{"tf":1.0}},"df":1}}}}}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"123":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"b":{"docs":{"158":{"tf":1.0},"160":{"tf":1.0}},"df":2},"h":{"docs":{},"df":0,"n":{"docs":{"58":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"n":{"docs":{"86":{"tf":1.0}},"df":1}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"27":{"tf":1.0},"30":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.4142135623730951},"53":{"tf":1.0},"68":{"tf":1.0}},"df":7,"/":{"docs":{},"df":0,"s":{"docs":{},"df":0,"w":{"docs":{},"df":0,"d":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}}}}}}}},"k":{"docs":{"61":{"tf":1.0},"67":{"tf":1.0}},"df":2,"b":{"docs":{"12":{"tf":1.0}},"df":1,"/":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{"68":{"tf":1.4142135623730951}},"df":1}}}}},"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{"115":{"tf":1.0},"121":{"tf":1.0},"133":{"tf":1.0},"135":{"tf":1.0},"188":{"tf":1.0},"62":{"tf":1.0},"81":{"tf":1.0},"84":{"tf":1.4142135623730951}},"df":8}},"r":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"16":{"tf":1.0},"17":{"tf":1.0},"63":{"tf":2.0},"64":{"tf":1.0},"68":{"tf":1.0}},"df":5}}}},"y":{"docs":{"164":{"tf":1.0},"24":{"tf":1.0},"56":{"tf":1.0}},"df":3,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"86":{"tf":1.0}},"df":1}}}}},"w":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"78":{"tf":1.0}},"df":1}}}}}},"h":{"docs":{},"df":0,"z":{"docs":{"53":{"tf":2.449489742783178},"68":{"tf":2.449489742783178}},"df":2}},"i":{"docs":{},"df":0,"b":{"docs":{"11":{"tf":1.7320508075688772},"187":{"tf":1.0},"188":{"tf":1.0},"66":{"tf":2.0},"72":{"tf":1.0},"87":{"tf":1.4142135623730951}},"df":6,"i":{"docs":{"61":{"tf":1.0},"67":{"tf":1.0}},"df":2}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"88":{"tf":1.0}},"df":1}},"y":{"docs":{},"df":0,"t":{"docs":{"87":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"d":{"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"16":{"tf":1.0},"93":{"tf":1.0}},"df":4}},"t":{"docs":{"69":{"tf":1.0}},"df":1}},"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"122":{"tf":1.0},"125":{"tf":1.4142135623730951},"127":{"tf":1.0},"175":{"tf":1.0},"28":{"tf":1.0},"61":{"tf":1.0},"80":{"tf":1.0},"9":{"tf":1.0},"92":{"tf":1.0}},"df":9,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"g":{"docs":{"3":{"tf":1.4142135623730951}},"df":1}}}},"n":{"docs":{"151":{"tf":1.0},"153":{"tf":1.0},"35":{"tf":1.0},"64":{"tf":1.0},"86":{"tf":1.4142135623730951}},"df":5}}}}},"l":{"docs":{"44":{"tf":1.0}},"df":1,"3":{"docs":{},"df":0,"g":{"docs":{},"df":0,"d":{"docs":{},"df":0,"2":{"docs":{},"df":0,"0":{"docs":{"11":{"tf":1.0}},"df":1}}}}},"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"11":{"tf":1.0},"53":{"tf":1.0}},"df":2}}},"c":{"docs":{},"df":0,"k":{"docs":{"16":{"tf":1.0},"17":{"tf":1.0},"84":{"tf":1.0}},"df":3}},"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"16":{"tf":1.0},"160":{"tf":1.0},"168":{"tf":1.0},"175":{"tf":1.0},"181":{"tf":1.0},"2":{"tf":1.0},"4":{"tf":1.4142135623730951},"78":{"tf":1.0},"88":{"tf":1.4142135623730951}},"df":11}}}}},"p":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{"44":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0}},"df":3,"’":{"docs":{"19":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"g":{"docs":{"158":{"tf":1.0},"188":{"tf":1.0},"27":{"tf":1.0},"65":{"tf":1.0},"84":{"tf":1.0}},"df":5}},"s":{"docs":{},"df":0,"t":{"docs":{"108":{"tf":1.0},"126":{"tf":1.0},"53":{"tf":1.0},"77":{"tf":1.0},"96":{"tf":1.0}},"df":5,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"122":{"tf":1.7320508075688772},"123":{"tf":1.7320508075688772},"124":{"tf":1.7320508075688772},"125":{"tf":1.7320508075688772},"126":{"tf":1.7320508075688772},"127":{"tf":1.7320508075688772}},"df":6}}}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"123":{"tf":1.0}},"df":1}},"r":{"docs":{"120":{"tf":1.0},"127":{"tf":1.4142135623730951},"40":{"tf":1.0},"53":{"tf":1.0},"7":{"tf":1.4142135623730951}},"df":5},"s":{"docs":{},"df":0,"t":{"docs":{"46":{"tf":1.0},"59":{"tf":1.0}},"df":2}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"168":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"63":{"tf":1.0},"64":{"tf":1.7320508075688772}},"df":2}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"30":{"tf":1.0}},"df":1}}}}}}}},"y":{"docs":{"91":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{"114":{"tf":1.7320508075688772},"115":{"tf":1.0},"126":{"tf":1.0},"131":{"tf":1.0},"141":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.0},"27":{"tf":1.0},"76":{"tf":1.4142135623730951},"93":{"tf":1.0}},"df":10}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":2.23606797749979},"166":{"tf":2.449489742783178},"20":{"tf":1.0},"61":{"tf":1.4142135623730951}},"df":4,".":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{"133":{"tf":1.0}},"df":1}}}}},"s":{"docs":{"133":{"tf":1.0}},"df":1}}}}}},"z":{"docs":{},"df":0,"i":{"docs":{"81":{"tf":1.0}},"df":1}}},"c":{"docs":{},"df":0,"d":{"docs":{"118":{"tf":1.0}},"df":1}},"d":{"docs":{},"df":0,"r":{"docs":{"83":{"tf":1.4142135623730951}},"df":1}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"160":{"tf":1.0}},"df":1},"k":{"docs":{"136":{"tf":1.4142135623730951}},"df":1},"v":{"docs":{"75":{"tf":1.0},"87":{"tf":1.0}},"df":2}},"d":{"docs":{"11":{"tf":1.0},"118":{"tf":1.0},"69":{"tf":1.0},"70":{"tf":1.4142135623730951},"72":{"tf":1.0}},"df":5},"f":{"docs":{},"df":0,"t":{"docs":{"123":{"tf":1.0},"77":{"tf":1.4142135623730951},"78":{"tf":1.0}},"df":3}},"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"142":{"tf":1.0}},"df":1}}}},"n":{"docs":{"79":{"tf":1.0}},"df":1,"g":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{"125":{"tf":1.0},"61":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":1.0},"79":{"tf":1.0}},"df":5,"(":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"61":{"tf":1.0}},"df":1}}}}}}}},"s":{"docs":{},"df":0,"s":{"docs":{"108":{"tf":1.0},"115":{"tf":1.0},"130":{"tf":1.0}},"df":3}},"t":{"docs":{"127":{"tf":1.7320508075688772},"188":{"tf":1.0},"44":{"tf":1.0},"63":{"tf":1.4142135623730951},"77":{"tf":1.0}},"df":5,"’":{"docs":{"10":{"tf":1.0},"107":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":1.0},"127":{"tf":1.0},"173":{"tf":1.0},"60":{"tf":1.0},"63":{"tf":2.0},"64":{"tf":2.0},"65":{"tf":1.0},"68":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"90":{"tf":1.4142135623730951}},"df":15}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"1":{"tf":1.0},"117":{"tf":1.0},"122":{"tf":1.0},"158":{"tf":1.0},"16":{"tf":1.0},"160":{"tf":1.0},"165":{"tf":1.4142135623730951},"186":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":2.23606797749979},"189":{"tf":2.8284271247461903},"190":{"tf":3.1622776601683795},"193":{"tf":1.0},"197":{"tf":1.0},"26":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"71":{"tf":1.0},"76":{"tf":1.0}},"df":20},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"99":{"tf":1.0}},"df":1}}}}}},"i":{"docs":{},"df":0,"b":{"docs":{"180":{"tf":1.7320508075688772}},"df":1,".":{"docs":{},"df":0,"r":{"docs":{"158":{"tf":1.0}},"df":1}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"14":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"162":{"tf":1.4142135623730951},"17":{"tf":1.0}},"df":4}}},"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,".":{"docs":{},"df":0,"a":{"docs":{"178":{"tf":1.0}},"df":1}}}}},"m":{"docs":{"191":{"tf":1.0}},"df":1,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"{":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"p":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"129":{"tf":2.0},"13":{"tf":1.0},"14":{"tf":1.7320508075688772},"142":{"tf":1.0},"158":{"tf":1.0},"161":{"tf":1.0},"165":{"tf":1.0},"173":{"tf":1.7320508075688772},"174":{"tf":1.0},"175":{"tf":1.4142135623730951},"177":{"tf":1.4142135623730951},"178":{"tf":1.4142135623730951},"180":{"tf":1.4142135623730951},"184":{"tf":1.0},"191":{"tf":1.7320508075688772},"62":{"tf":1.0},"78":{"tf":1.4142135623730951}},"df":17},"y":{"docs":{},"df":0,".":{"docs":{},"df":0,"a":{"docs":{"175":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"l":{"docs":{"40":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"d":{"docs":{"15":{"tf":1.4142135623730951},"17":{"tf":1.0}},"df":2}}}},"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"9":{"tf":1.4142135623730951}},"df":1},"s":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0},"9":{"tf":2.449489742783178}},"df":3}}}},"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"t":{"docs":{"118":{"tf":1.0}},"df":1}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"115":{"tf":1.0},"159":{"tf":1.0},"178":{"tf":1.0}},"df":3}}},"n":{"docs":{},"df":0,"e":{"docs":{"127":{"tf":1.0},"15":{"tf":1.0},"28":{"tf":1.4142135623730951},"53":{"tf":1.4142135623730951},"62":{"tf":1.0},"64":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951},"72":{"tf":1.0},"78":{"tf":1.0}},"df":9,"a":{"docs":{},"df":0,"r":{"docs":{"191":{"tf":1.0},"87":{"tf":1.0}},"df":2}}},"k":{"docs":{"11":{"tf":1.0},"16":{"tf":1.0},"161":{"tf":1.0},"172":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.0},"184":{"tf":1.0},"20":{"tf":1.0},"24":{"tf":1.7320508075688772},"34":{"tf":1.4142135623730951},"35":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"53":{"tf":1.7320508075688772},"60":{"tf":1.4142135623730951},"61":{"tf":1.0},"68":{"tf":1.4142135623730951},"77":{"tf":1.0},"78":{"tf":1.7320508075688772},"9":{"tf":1.4142135623730951}},"df":20,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{"44":{"tf":1.0}},"df":1}}}},"/":{"docs":{},"df":0,"v":{"docs":{},"df":0,"2":{"docs":{"44":{"tf":1.4142135623730951}},"df":1,".":{"docs":{},"df":0,"1":{"docs":{"44":{"tf":1.0}},"df":1}}}}},"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"61":{"tf":1.0}},"df":1}}}}},"e":{"docs":{},"df":0,"r":{"docs":{"137":{"tf":1.0},"161":{"tf":1.0},"182":{"tf":1.0},"20":{"tf":1.4142135623730951},"62":{"tf":1.4142135623730951},"67":{"tf":1.0}},"df":6}}},"u":{"docs":{},"df":0,"x":{"docs":{"117":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"42":{"tf":1.0},"43":{"tf":1.0}},"df":5}}},"s":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"11":{"tf":1.0},"158":{"tf":1.4142135623730951},"160":{"tf":1.0},"19":{"tf":1.4142135623730951},"192":{"tf":1.0},"6":{"tf":1.0},"64":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":9}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{"104":{"tf":1.0},"127":{"tf":1.0},"158":{"tf":1.0},"167":{"tf":1.4142135623730951},"62":{"tf":1.4142135623730951},"88":{"tf":1.0}},"df":6}}},"v":{"docs":{},"df":0,"e":{"docs":{"137":{"tf":1.0},"87":{"tf":1.0}},"df":2}}},"l":{"docs":{},"df":0,"d":{"docs":{},"df":0,"b":{"docs":{"64":{"tf":1.4142135623730951}},"df":1}},"v":{"docs":{},"df":0,"m":{"docs":{"189":{"tf":1.0},"190":{"tf":1.4142135623730951},"21":{"tf":2.23606797749979},"39":{"tf":1.0},"62":{"tf":1.0}},"df":5,"’":{"docs":{"190":{"tf":1.0}},"df":1}}}},"m":{"docs":{},"df":0,"3":{"docs":{},"df":0,"s":{"docs":{},"df":0,"6":{"docs":{},"df":0,"9":{"docs":{},"df":0,"6":{"docs":{},"df":0,"5":{"docs":{"100":{"tf":1.0},"55":{"tf":1.0},"61":{"tf":1.4142135623730951},"63":{"tf":1.0},"81":{"tf":1.0}},"df":5,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"84":{"tf":1.0}},"df":1}}}}}}}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"100":{"tf":1.0}},"df":1}}}}}}}}}},"e":{"docs":{},"df":0,"v":{"docs":{},"df":0,"b":{"docs":{"63":{"tf":2.449489742783178},"64":{"tf":1.0},"68":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0}},"df":6}}}}}}}}},"a":{"docs":{"68":{"tf":2.449489742783178}},"df":1}},"o":{"docs":{"59":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"d":{"docs":{"122":{"tf":1.4142135623730951},"124":{"tf":1.0},"137":{"tf":1.0},"14":{"tf":1.7320508075688772},"62":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":3.7416573867739413},"72":{"tf":1.0},"83":{"tf":1.4142135623730951}},"df":10}},"c":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"112":{"tf":1.0},"136":{"tf":1.4142135623730951},"177":{"tf":1.0},"61":{"tf":1.7320508075688772},"63":{"tf":1.0},"66":{"tf":1.7320508075688772},"78":{"tf":1.0},"83":{"tf":1.4142135623730951},"87":{"tf":1.4142135623730951}},"df":9}},"k":{"docs":{"125":{"tf":1.0},"126":{"tf":3.0},"80":{"tf":1.0}},"df":3,"/":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"126":{"tf":1.0}},"df":1}}}}}}}}},"g":{"docs":{"77":{"tf":1.7320508075688772},"78":{"tf":1.4142135623730951}},"df":2,"i":{"docs":{},"df":0,"c":{"docs":{"151":{"tf":1.0},"161":{"tf":1.0},"87":{"tf":1.0}},"df":3}}},"n":{"docs":{},"df":0,"g":{"docs":{"113":{"tf":1.0},"126":{"tf":1.4142135623730951},"127":{"tf":1.0},"137":{"tf":1.0},"168":{"tf":1.4142135623730951},"63":{"tf":1.0},"87":{"tf":1.0}},"df":7,"e":{"docs":{},"df":0,"r":{"docs":{"110":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.4142135623730951},"127":{"tf":1.4142135623730951},"131":{"tf":1.0},"99":{"tf":1.0}},"df":6}}}},"o":{"docs":{},"df":0,"k":{"docs":{"108":{"tf":1.4142135623730951},"109":{"tf":1.0},"11":{"tf":1.0},"115":{"tf":1.0},"142":{"tf":1.0},"156":{"tf":1.0},"160":{"tf":1.0},"173":{"tf":2.0},"178":{"tf":1.0},"183":{"tf":1.0},"191":{"tf":1.4142135623730951},"60":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.4142135623730951},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"80":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":1.0},"87":{"tf":1.0},"88":{"tf":1.0},"90":{"tf":1.7320508075688772}},"df":24,"u":{"docs":{},"df":0,"p":{"docs":{"83":{"tf":1.0}},"df":1}}},"p":{"docs":{"121":{"tf":1.7320508075688772},"122":{"tf":1.4142135623730951},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.4142135623730951},"133":{"tf":1.4142135623730951},"134":{"tf":1.0},"165":{"tf":1.0},"189":{"tf":2.0},"191":{"tf":1.0},"60":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.4142135623730951},"71":{"tf":1.7320508075688772},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.7320508075688772},"78":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.0},"82":{"tf":1.0},"83":{"tf":1.4142135623730951}},"df":24}},"s":{"docs":{},"df":0,"s":{"docs":{"188":{"tf":1.0}},"df":1},"t":{"docs":{"74":{"tf":1.0}},"df":1}},"t":{"docs":{"108":{"tf":1.0},"123":{"tf":1.0},"127":{"tf":1.0},"138":{"tf":1.0},"190":{"tf":1.0},"70":{"tf":1.0},"72":{"tf":1.0},"84":{"tf":1.0}},"df":8},"w":{"docs":{"103":{"tf":1.0},"106":{"tf":2.449489742783178},"107":{"tf":2.23606797749979},"108":{"tf":2.0},"109":{"tf":1.4142135623730951},"117":{"tf":1.0},"122":{"tf":1.0},"128":{"tf":1.0},"190":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"71":{"tf":1.0}},"df":12,"e":{"docs":{},"df":0,"r":{"docs":{"137":{"tf":1.0},"197":{"tf":1.0},"87":{"tf":1.0}},"df":3},"s":{"docs":{},"df":0,"t":{"docs":{"122":{"tf":1.0}},"df":1}}}}},"r":{"docs":{"62":{"tf":1.4142135623730951},"83":{"tf":1.0}},"df":2},"s":{"docs":{"44":{"tf":1.0}},"df":1,"m":{"docs":{},"df":0,"3":{"docs":{},"df":0,"0":{"docs":{},"df":0,"3":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{},"df":0,"h":{"docs":{},"df":0,"c":{"docs":{"11":{"tf":1.4142135623730951}},"df":1}}}}}}}},"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"b":{"docs":{"44":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"120":{"tf":1.0},"61":{"tf":1.0},"96":{"tf":1.0}},"df":3}}}}},"x":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"122":{"tf":1.0}},"df":1}}}}}},"m":{"docs":{"100":{"tf":1.7320508075688772},"115":{"tf":1.0},"124":{"tf":1.0},"17":{"tf":1.0},"188":{"tf":1.7320508075688772},"19":{"tf":1.0},"190":{"tf":1.0},"2":{"tf":1.0},"38":{"tf":3.0},"43":{"tf":1.7320508075688772},"56":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":2.0},"60":{"tf":1.0},"64":{"tf":1.7320508075688772},"67":{"tf":1.7320508075688772},"69":{"tf":1.7320508075688772},"7":{"tf":1.0},"71":{"tf":1.4142135623730951},"72":{"tf":1.0},"77":{"tf":1.4142135623730951},"78":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":2.0},"82":{"tf":1.4142135623730951},"84":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.4142135623730951}},"df":28,"*":{"docs":{},"df":0,"n":{"docs":{"115":{"tf":1.0}},"df":1}},"+":{"docs":{},"df":0,"n":{"docs":{"115":{"tf":1.0}},"df":1}},"0":{"docs":{"124":{"tf":1.4142135623730951},"38":{"tf":1.4142135623730951},"61":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951}},"df":4},"1":{"docs":{"38":{"tf":1.0}},"df":1},"2":{"docs":{},"df":0,"3":{"docs":{"38":{"tf":1.0}},"df":1}},"3":{"docs":{"124":{"tf":1.0},"38":{"tf":1.0},"55":{"tf":1.0},"61":{"tf":1.7320508075688772},"63":{"tf":2.23606797749979},"64":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.0}},"df":11,"3":{"docs":{"38":{"tf":1.0}},"df":1,"f":{"docs":{"38":{"tf":1.0}},"df":1}},"5":{"docs":{},"df":0,"p":{"docs":{"38":{"tf":1.0}},"df":1,"f":{"docs":{"38":{"tf":1.0}},"df":1}}}},"4":{"docs":{"38":{"tf":1.0},"61":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.0},"72":{"tf":1.0}},"df":5,"f":{"docs":{"11":{"tf":1.0},"38":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.4142135623730951}},"df":6}},"7":{"docs":{"38":{"tf":1.0},"61":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.0}},"df":4,"f":{"docs":{"38":{"tf":1.0},"61":{"tf":1.0},"67":{"tf":1.0}},"df":3}},"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"105":{"tf":1.0},"106":{"tf":1.0},"107":{"tf":1.0},"112":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":2.6457513110645907},"64":{"tf":1.7320508075688772},"68":{"tf":1.0},"72":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0}},"df":14}}},"o":{"docs":{"41":{"tf":1.0}},"df":1},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"45":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"o":{"docs":{"100":{"tf":1.0},"113":{"tf":1.0},"157":{"tf":1.0},"160":{"tf":3.605551275463989}},"df":4}}},"d":{"docs":{},"df":0,"e":{"docs":{"119":{"tf":1.0},"67":{"tf":1.0},"88":{"tf":1.0}},"df":3}},"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"105":{"tf":1.0},"62":{"tf":1.0},"67":{"tf":1.0}},"df":3}},"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"11":{"tf":1.0},"118":{"tf":1.0}},"df":2}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.4142135623730951},"101":{"tf":1.0},"104":{"tf":1.0},"115":{"tf":1.0},"116":{"tf":1.0},"121":{"tf":1.4142135623730951},"122":{"tf":1.7320508075688772},"123":{"tf":1.7320508075688772},"124":{"tf":1.4142135623730951},"125":{"tf":1.4142135623730951},"126":{"tf":1.7320508075688772},"127":{"tf":2.0},"133":{"tf":1.0},"134":{"tf":1.0},"146":{"tf":1.0},"15":{"tf":1.4142135623730951},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"166":{"tf":2.0},"17":{"tf":1.0},"178":{"tf":1.0},"191":{"tf":1.4142135623730951},"60":{"tf":2.449489742783178},"62":{"tf":1.0},"64":{"tf":2.23606797749979},"67":{"tf":1.0},"68":{"tf":1.7320508075688772},"71":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.7320508075688772},"79":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0},"86":{"tf":1.0},"98":{"tf":1.0},"99":{"tf":1.0}},"df":40,"+":{"docs":{},"df":0,"0":{"docs":{},"df":0,"x":{"docs":{},"df":0,"4":{"docs":{"62":{"tf":1.0}},"df":1}}}},"l":{"docs":{},"df":0,"i":{"docs":{"77":{"tf":1.0},"8":{"tf":1.0}},"df":2}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"131":{"tf":1.0},"80":{"tf":1.0}},"df":2}}},"e":{"docs":{},"df":0,"n":{"docs":{"28":{"tf":1.0}},"df":1}}}}},"j":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"171":{"tf":1.0},"34":{"tf":1.0},"7":{"tf":1.0},"87":{"tf":1.0}},"df":4}}},"k":{"docs":{},"df":0,"e":{"docs":{"101":{"tf":1.0},"102":{"tf":1.0},"103":{"tf":1.0},"107":{"tf":1.0},"108":{"tf":1.0},"115":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.4142135623730951},"133":{"tf":1.0},"138":{"tf":1.0},"147":{"tf":1.0},"16":{"tf":1.0},"169":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"19":{"tf":1.0},"190":{"tf":1.0},"2":{"tf":1.0},"21":{"tf":1.0},"30":{"tf":1.0},"34":{"tf":1.0},"36":{"tf":1.0},"38":{"tf":1.0},"44":{"tf":1.0},"52":{"tf":1.0},"63":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":1.7320508075688772},"70":{"tf":1.0},"72":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.0},"9":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0},"98":{"tf":1.0},"99":{"tf":1.4142135623730951}},"df":39}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"13":{"tf":1.0},"24":{"tf":1.0},"87":{"tf":1.0}},"df":3}},"g":{"docs":{},"df":0,"l":{"docs":{"182":{"tf":1.4142135623730951}},"df":1}},"i":{"docs":{"120":{"tf":1.4142135623730951},"122":{"tf":1.0},"126":{"tf":1.0},"129":{"tf":1.0},"130":{"tf":1.0},"134":{"tf":1.0},"157":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"81":{"tf":1.0}},"df":10},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"11":{"tf":1.0},"163":{"tf":1.4142135623730951},"172":{"tf":1.4142135623730951},"174":{"tf":1.4142135623730951},"66":{"tf":1.0},"69":{"tf":1.0},"71":{"tf":1.0},"90":{"tf":1.4142135623730951},"93":{"tf":1.0}},"df":9}},"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"114":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"’":{"docs":{"73":{"tf":1.0},"74":{"tf":1.0},"90":{"tf":1.0}},"df":3}}}}}}}}}}},"p":{"docs":{"107":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.4142135623730951},"168":{"tf":1.0},"173":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.0},"28":{"tf":1.4142135623730951},"4":{"tf":1.0},"5":{"tf":1.4142135623730951},"66":{"tf":1.0},"69":{"tf":1.0},"71":{"tf":1.0},"86":{"tf":1.0},"87":{"tf":1.7320508075688772}},"df":16},"r":{"docs":{},"df":0,"k":{"docs":{"151":{"tf":1.4142135623730951},"165":{"tf":1.4142135623730951},"60":{"tf":1.0},"72":{"tf":1.0},"80":{"tf":1.0},"82":{"tf":1.0},"92":{"tf":1.4142135623730951}},"df":7,"e":{"docs":{},"df":0,"r":{"docs":{"111":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"59":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"z":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{"59":{"tf":1.0}},"df":1}}}}}}}},"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"119":{"tf":1.0},"136":{"tf":1.0},"158":{"tf":1.0},"53":{"tf":1.7320508075688772},"61":{"tf":1.0},"68":{"tf":1.4142135623730951}},"df":6}},"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"5":{"tf":1.0},"9":{"tf":1.4142135623730951}},"df":2}}},"h":{"docs":{"191":{"tf":1.0},"194":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"115":{"tf":1.0},"191":{"tf":1.0}},"df":2}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"107":{"tf":1.0},"88":{"tf":1.0}},"df":2}}}},"x":{"docs":{"163":{"tf":1.0}},"df":1,"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{"11":{"tf":1.4142135623730951},"137":{"tf":1.0},"87":{"tf":1.0}},"df":3}}}}},"y":{"docs":{},"df":0,"b":{"docs":{"138":{"tf":1.0}},"df":1}}},"c":{"docs":{},"df":0,"u":{"docs":{"12":{"tf":1.0},"129":{"tf":1.0},"191":{"tf":1.0},"24":{"tf":1.0},"28":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951}},"df":6,"x":{"docs":{},"df":0,"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{"36":{"tf":1.0}},"df":1}}}}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"101":{"tf":1.4142135623730951},"105":{"tf":1.0},"107":{"tf":1.0},"108":{"tf":1.0},"112":{"tf":1.0},"122":{"tf":1.4142135623730951},"126":{"tf":1.0},"13":{"tf":1.0},"134":{"tf":1.0},"137":{"tf":1.0},"164":{"tf":1.0},"175":{"tf":1.0},"177":{"tf":1.0},"53":{"tf":1.0},"72":{"tf":1.0},"75":{"tf":1.0},"98":{"tf":1.0}},"df":17,"t":{"docs":{"190":{"tf":1.0},"196":{"tf":1.0},"68":{"tf":1.0}},"df":3},"w":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"122":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"122":{"tf":1.0}},"df":1}}}},"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"123":{"tf":1.0},"77":{"tf":1.0},"80":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":4}}}},"e":{"docs":{},"df":0,"t":{"docs":{"166":{"tf":1.0}},"df":1}},"g":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"88":{"tf":1.0}},"df":1}}}}},"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"166":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"11":{"tf":1.0},"111":{"tf":1.0},"122":{"tf":1.4142135623730951},"123":{"tf":1.0},"124":{"tf":1.0},"128":{"tf":1.0},"13":{"tf":1.0},"132":{"tf":1.4142135623730951},"133":{"tf":2.23606797749979},"134":{"tf":1.0},"136":{"tf":2.0},"137":{"tf":2.6457513110645907},"14":{"tf":1.4142135623730951},"154":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.4142135623730951},"168":{"tf":1.0},"17":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.0},"20":{"tf":1.0},"28":{"tf":1.7320508075688772},"32":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.4142135623730951},"53":{"tf":1.0},"61":{"tf":2.23606797749979},"66":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":1.0},"69":{"tf":1.4142135623730951},"78":{"tf":1.0},"83":{"tf":2.0},"86":{"tf":1.4142135623730951},"87":{"tf":2.8284271247461903},"88":{"tf":1.4142135623730951},"95":{"tf":1.0}},"df":40},"y":{"docs":{},"df":0,".":{"docs":{},"df":0,"x":{"docs":{"61":{"tf":1.0},"67":{"tf":2.0},"68":{"tf":1.0}},"df":3}}}}}},"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"15":{"tf":1.0},"159":{"tf":1.0},"5":{"tf":1.4142135623730951},"9":{"tf":1.0}},"df":4}}}}},"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"179":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"128":{"tf":1.0},"188":{"tf":1.0},"29":{"tf":1.0},"63":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":1.7320508075688772},"78":{"tf":1.4142135623730951},"79":{"tf":1.4142135623730951}},"df":8}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{"62":{"tf":1.4142135623730951}},"df":1}}}},"l":{"docs":{"0":{"tf":1.0},"102":{"tf":1.0},"14":{"tf":1.4142135623730951},"187":{"tf":1.0},"20":{"tf":1.0},"5":{"tf":1.4142135623730951},"86":{"tf":1.0}},"df":7}},"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"101":{"tf":1.0},"102":{"tf":1.0},"105":{"tf":1.7320508075688772},"109":{"tf":1.0},"115":{"tf":1.4142135623730951},"118":{"tf":1.0},"134":{"tf":1.4142135623730951},"136":{"tf":1.4142135623730951},"137":{"tf":1.0},"142":{"tf":1.4142135623730951},"146":{"tf":1.4142135623730951},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":2.23606797749979},"163":{"tf":1.0},"165":{"tf":2.23606797749979},"92":{"tf":1.0},"95":{"tf":1.0}},"df":18}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"190":{"tf":1.0}},"df":1}}}}},"h":{"docs":{},"df":0,"z":{"docs":{"11":{"tf":1.0},"81":{"tf":1.0}},"df":2}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{"69":{"tf":2.8284271247461903},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0}},"df":4,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"0":{"tf":1.0},"106":{"tf":1.0},"11":{"tf":2.23606797749979},"141":{"tf":1.4142135623730951},"19":{"tf":1.0},"199":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.4142135623730951},"35":{"tf":1.0},"36":{"tf":1.0},"55":{"tf":1.0},"61":{"tf":1.4142135623730951},"63":{"tf":1.0},"66":{"tf":1.4142135623730951},"68":{"tf":1.0},"69":{"tf":1.0},"7":{"tf":1.4142135623730951},"86":{"tf":2.0},"87":{"tf":2.0}},"df":19,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"’":{"docs":{"195":{"tf":1.0},"197":{"tf":1.0},"28":{"tf":1.0}},"df":3}}}}}}}}}}},"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"t":{"docs":{"191":{"tf":1.0}},"df":1}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{"191":{"tf":1.0}},"df":1}}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"120":{"tf":1.4142135623730951},"32":{"tf":1.0}},"df":2}}}}}}}}}}}},"d":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{"72":{"tf":1.0}},"df":1}}},"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"71":{"tf":1.0},"77":{"tf":1.0}},"df":2}}}}}}}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"139":{"tf":1.0}},"df":1}}},"n":{"docs":{"163":{"tf":1.0}},"df":1,"d":{"docs":{"135":{"tf":1.0},"26":{"tf":1.0},"84":{"tf":1.0}},"df":3},"i":{"docs":{"11":{"tf":1.4142135623730951},"53":{"tf":1.0}},"df":2,"m":{"docs":{"104":{"tf":1.0},"78":{"tf":1.0}},"df":2,"u":{"docs":{},"df":0,"m":{"docs":{"19":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"63":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}},"s":{"docs":{"101":{"tf":1.0},"190":{"tf":1.0},"20":{"tf":1.0},"3":{"tf":1.0}},"df":4},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{"93":{"tf":1.0}},"df":1}}}},"t":{"docs":{"9":{"tf":1.0}},"df":1},"x":{"docs":{"2":{"tf":1.0}},"df":1}},"m":{"docs":{},"df":0,"u":{"docs":{"87":{"tf":1.4142135623730951}},"df":1}},"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"117":{"tf":1.0}},"df":1}},"d":{"docs":{"104":{"tf":1.0},"155":{"tf":1.0},"158":{"tf":1.4142135623730951}},"df":3,"e":{"docs":{"103":{"tf":1.0},"106":{"tf":1.4142135623730951},"108":{"tf":1.0},"109":{"tf":3.1622776601683795},"110":{"tf":1.7320508075688772},"112":{"tf":1.0},"117":{"tf":1.0},"64":{"tf":1.0},"72":{"tf":1.4142135623730951},"76":{"tf":1.0}},"df":10,"l":{"docs":{"12":{"tf":1.0},"124":{"tf":1.0},"130":{"tf":1.0},"63":{"tf":1.0}},"df":4},"r":{"docs":{},"df":0,"n":{"docs":{"26":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"f":{"docs":{"68":{"tf":1.0}},"df":1,"i":{"docs":{"102":{"tf":1.0},"103":{"tf":1.0},"107":{"tf":1.0},"124":{"tf":1.4142135623730951},"127":{"tf":1.0},"178":{"tf":1.0},"68":{"tf":1.0},"75":{"tf":2.0},"87":{"tf":1.0},"94":{"tf":1.0}},"df":10}}},"u":{"docs":{},"df":0,"l":{"docs":{"168":{"tf":1.0},"93":{"tf":1.0}},"df":2}}},"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"83":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"68":{"tf":2.0},"77":{"tf":1.0}},"df":2}}}}},"o":{"docs":{},"df":0,"d":{"docs":{"50":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"e":{"docs":{"11":{"tf":1.0},"112":{"tf":1.0},"117":{"tf":1.4142135623730951},"123":{"tf":1.0},"124":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"128":{"tf":1.0},"129":{"tf":1.0},"131":{"tf":1.4142135623730951},"137":{"tf":1.0},"154":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"163":{"tf":1.4142135623730951},"164":{"tf":1.0},"168":{"tf":1.0},"187":{"tf":1.0},"189":{"tf":1.0},"191":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"196":{"tf":1.0},"197":{"tf":1.0},"198":{"tf":1.0},"199":{"tf":1.0},"2":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":1.0},"60":{"tf":1.0},"62":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.4142135623730951},"70":{"tf":1.0},"71":{"tf":1.0},"77":{"tf":1.4142135623730951},"78":{"tf":1.0},"80":{"tf":1.7320508075688772},"84":{"tf":1.0},"86":{"tf":1.0},"92":{"tf":1.0},"99":{"tf":1.0}},"df":44}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"179":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"118":{"tf":1.0},"86":{"tf":1.0}},"df":2}}},"v":{"docs":{},"df":0,"e":{"docs":{"106":{"tf":1.7320508075688772},"111":{"tf":1.0},"112":{"tf":1.0},"125":{"tf":1.4142135623730951},"127":{"tf":2.23606797749979},"133":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0},"53":{"tf":1.4142135623730951},"64":{"tf":1.0},"69":{"tf":1.0}},"df":11},"t":{"docs":{"83":{"tf":1.0}},"df":1},"w":{"docs":{"62":{"tf":1.0},"83":{"tf":1.0}},"df":2}}},"r":{"docs":{"62":{"tf":1.0}},"df":1},"s":{"docs":{},"df":0,"p":{"docs":{"62":{"tf":1.0}},"df":1}},"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"108":{"tf":1.0},"184":{"tf":1.0},"63":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.0},"77":{"tf":1.0},"80":{"tf":1.0}},"df":7}},"l":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"123":{"tf":1.0},"131":{"tf":1.4142135623730951}},"df":2,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"43":{"tf":1.4142135623730951},"64":{"tf":1.4142135623730951},"68":{"tf":1.7320508075688772}},"df":3}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"30":{"tf":1.0},"80":{"tf":1.4142135623730951}},"df":2}}},"p":{"docs":{},"df":0,"l":{"docs":{"101":{"tf":1.0},"119":{"tf":1.0},"120":{"tf":1.0},"123":{"tf":1.4142135623730951},"124":{"tf":1.0},"125":{"tf":2.23606797749979},"126":{"tf":1.0},"130":{"tf":1.0},"131":{"tf":1.0},"148":{"tf":1.0},"158":{"tf":1.0},"164":{"tf":1.0},"76":{"tf":1.0},"80":{"tf":1.4142135623730951},"93":{"tf":1.0}},"df":15,"e":{"docs":{},"df":0,"x":{"docs":{"117":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"k":{"docs":{"130":{"tf":1.4142135623730951}},"df":1}}},"h":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"120":{"tf":1.0}},"df":1}}}}},"u":{"docs":{},"df":0,"d":{"docs":{"35":{"tf":1.0}},"df":1}}}}}},"t":{"docs":{"100":{"tf":1.4142135623730951},"101":{"tf":1.0},"102":{"tf":1.4142135623730951},"122":{"tf":2.0},"123":{"tf":1.4142135623730951},"124":{"tf":1.0},"125":{"tf":1.7320508075688772},"126":{"tf":1.0},"127":{"tf":1.7320508075688772},"128":{"tf":1.0},"133":{"tf":2.0},"134":{"tf":1.0},"155":{"tf":2.0},"164":{"tf":1.0},"165":{"tf":2.449489742783178},"173":{"tf":2.0},"71":{"tf":1.0},"76":{"tf":1.4142135623730951},"80":{"tf":2.449489742783178},"81":{"tf":1.7320508075688772},"84":{"tf":1.7320508075688772},"91":{"tf":1.0},"92":{"tf":2.23606797749979},"93":{"tf":2.6457513110645907},"98":{"tf":1.0},"99":{"tf":1.0}},"df":26,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"101":{"tf":1.0},"102":{"tf":1.0},"103":{"tf":1.0},"122":{"tf":1.0},"125":{"tf":1.7320508075688772},"126":{"tf":1.7320508075688772},"127":{"tf":1.4142135623730951},"164":{"tf":2.23606797749979},"80":{"tf":1.0},"92":{"tf":1.0},"94":{"tf":1.0},"96":{"tf":1.0},"98":{"tf":1.0}},"df":13}},"t":{"docs":{"125":{"tf":1.0}},"df":1}},"e":{"docs":{},"df":0,"x":{"docs":{"126":{"tf":3.0},"127":{"tf":3.1622776601683795},"130":{"tf":1.0}},"df":3,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"0":{"docs":{"126":{"tf":1.0}},"df":1}}}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"127":{"tf":1.7320508075688772}},"df":1}}}}}}}}}}}}}}}}}}}}}},"<":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"<":{"docs":{},"df":0,"u":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"126":{"tf":1.0}},"df":1}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"<":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"<":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"m":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"f":{"docs":{},"df":0,"4":{"docs":{},"df":0,"0":{"docs":{},"df":0,"5":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{"127":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"<":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"m":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"2":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"t":{"docs":{"126":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"126":{"tf":1.0}},"df":1}}}}},"v":{"docs":{"59":{"tf":1.0}},"df":1},"y":{"docs":{},"df":0,"_":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"127":{"tf":2.23606797749979}},"df":1,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"c":{"docs":{},"df":0,"s":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"127":{"tf":2.0}},"df":1}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"d":{"docs":{},"df":0,"p":{"docs":{},"df":0,".":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{"127":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,".":{"docs":{},"df":0,"a":{"docs":{"184":{"tf":1.0}},"df":1},"d":{"docs":{},"df":0,"l":{"docs":{"184":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"o":{"docs":{"184":{"tf":1.0}},"df":1}}}}}}}}},"n":{"docs":{"115":{"tf":1.0},"155":{"tf":2.8284271247461903},"166":{"tf":1.0},"68":{"tf":1.0}},"df":4,"/":{"docs":{},"df":0,"a":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}},"1":{"docs":{},"df":0,"0":{"docs":{"68":{"tf":1.0}},"df":1}},"3":{"docs":{"63":{"tf":1.0}},"df":1},"5":{"docs":{"67":{"tf":1.0},"81":{"tf":1.0}},"df":2},"6":{"docs":{"61":{"tf":1.0}},"df":1},"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{"191":{"tf":1.0}},"df":1}}}}}},"m":{"docs":{},"df":0,"e":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"11":{"tf":1.0},"141":{"tf":1.0},"142":{"tf":2.0},"144":{"tf":1.7320508075688772},"147":{"tf":1.7320508075688772},"160":{"tf":1.0},"173":{"tf":1.0},"178":{"tf":1.0},"180":{"tf":1.4142135623730951},"182":{"tf":1.0},"188":{"tf":1.4142135623730951},"190":{"tf":1.0},"20":{"tf":1.0},"55":{"tf":2.0},"57":{"tf":1.0},"58":{"tf":2.449489742783178},"61":{"tf":1.0},"63":{"tf":1.4142135623730951},"64":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"80":{"tf":1.0},"84":{"tf":1.0},"90":{"tf":1.0}},"df":26}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"v":{"docs":{"162":{"tf":1.0},"179":{"tf":1.0},"182":{"tf":1.0},"38":{"tf":1.0},"62":{"tf":1.0}},"df":5}},"u":{"docs":{},"df":0,"r":{"docs":{"54":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"136":{"tf":1.0}},"df":1}}}},"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"100":{"tf":1.0},"105":{"tf":1.0},"146":{"tf":1.0},"172":{"tf":1.4142135623730951},"175":{"tf":2.23606797749979},"62":{"tf":1.0}},"df":6}}}}}}},"e":{"docs":{},"df":0,"d":{"docs":{"103":{"tf":1.0},"108":{"tf":1.0},"119":{"tf":1.4142135623730951},"120":{"tf":1.0},"121":{"tf":1.0},"123":{"tf":1.7320508075688772},"124":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.4142135623730951},"127":{"tf":2.0},"128":{"tf":1.0},"131":{"tf":1.0},"132":{"tf":1.0},"133":{"tf":1.0},"136":{"tf":1.4142135623730951},"155":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"162":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"173":{"tf":1.0},"182":{"tf":1.0},"183":{"tf":1.4142135623730951},"184":{"tf":1.0},"188":{"tf":1.0},"191":{"tf":1.0},"20":{"tf":1.0},"31":{"tf":1.0},"40":{"tf":1.0},"46":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":1.4142135623730951},"55":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":1.4142135623730951},"64":{"tf":1.0},"66":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"70":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.7320508075688772},"77":{"tf":1.4142135623730951},"80":{"tf":1.4142135623730951},"84":{"tf":1.4142135623730951},"9":{"tf":1.0},"91":{"tf":1.0},"93":{"tf":1.0},"96":{"tf":1.0},"99":{"tf":1.4142135623730951}},"df":53,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"123":{"tf":1.0}},"df":1}}}}}}}},"g":{"docs":{"82":{"tf":1.0}},"df":1},"s":{"docs":{},"df":0,"t":{"docs":{"113":{"tf":1.4142135623730951},"125":{"tf":1.0},"84":{"tf":1.0}},"df":3}},"t":{"docs":{},"df":0,"w":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"k":{"docs":{"13":{"tf":1.0}},"df":1}}}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"112":{"tf":1.0},"123":{"tf":1.0},"126":{"tf":1.0},"133":{"tf":1.0},"134":{"tf":1.0},"138":{"tf":1.0},"139":{"tf":1.0},"5":{"tf":1.0},"80":{"tf":1.0}},"df":9}}},"w":{"docs":{"105":{"tf":1.0},"123":{"tf":1.0},"127":{"tf":1.0},"146":{"tf":1.0},"150":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.0},"173":{"tf":1.0},"180":{"tf":1.0},"20":{"tf":1.0},"53":{"tf":1.0},"56":{"tf":1.4142135623730951},"57":{"tf":1.4142135623730951},"62":{"tf":1.0},"67":{"tf":1.4142135623730951},"70":{"tf":1.0},"76":{"tf":1.4142135623730951},"8":{"tf":1.0},"80":{"tf":1.0},"93":{"tf":1.0}},"df":20,"(":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{"146":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":1.0}},"df":1}}}}}},"e":{"docs":{},"df":0,"r":{"docs":{"19":{"tf":1.4142135623730951},"38":{"tf":1.4142135623730951},"43":{"tf":1.7320508075688772},"68":{"tf":1.0}},"df":4}},"l":{"docs":{},"df":0,"i":{"docs":{"122":{"tf":1.0}},"df":1,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"s":{"docs":{},"df":0,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}},"t":{"docs":{},"df":0,"y":{"docs":{},"df":0,"p":{"docs":{"190":{"tf":1.0}},"df":1}}}},"x":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.0},"158":{"tf":1.0},"19":{"tf":1.0},"44":{"tf":1.0},"47":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":1.4142135623730951},"61":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":2.23606797749979},"68":{"tf":1.4142135623730951}},"df":11}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"142":{"tf":1.0},"187":{"tf":1.0},"70":{"tf":1.0}},"df":3}},"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"60":{"tf":1.0}},"df":1}}}}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"5":{"tf":1.0}},"df":1}}},"x":{"docs":{"63":{"tf":1.0}},"df":1}},"m":{"docs":{"21":{"tf":1.0}},"df":1},"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"191":{"tf":1.0},"60":{"tf":1.7320508075688772},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.7320508075688772},"78":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0}},"df":10}},"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{"183":{"tf":1.0},"184":{"tf":1.0},"82":{"tf":1.0}},"df":3}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"174":{"tf":1.0},"177":{"tf":1.0},"191":{"tf":1.0},"20":{"tf":1.0},"60":{"tf":1.7320508075688772},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":2.0},"78":{"tf":1.0},"79":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0}},"df":17}}}},"g":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{"63":{"tf":2.0},"64":{"tf":1.0},"68":{"tf":1.0}},"df":3}}}}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"61":{"tf":1.0}},"df":1}}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"124":{"tf":1.0}},"df":1}}},"n":{"docs":{"11":{"tf":1.0}},"df":1}}},"n":{"docs":{"100":{"tf":1.0},"122":{"tf":1.0},"146":{"tf":1.4142135623730951},"155":{"tf":1.0},"164":{"tf":1.0},"175":{"tf":1.0},"20":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"63":{"tf":1.0},"80":{"tf":2.0}},"df":11,"e":{"docs":{"125":{"tf":1.0},"127":{"tf":1.7320508075688772},"162":{"tf":1.4142135623730951},"190":{"tf":1.0},"38":{"tf":2.8284271247461903},"43":{"tf":2.0},"46":{"tf":1.0},"47":{"tf":1.0},"49":{"tf":1.0},"53":{"tf":1.4142135623730951},"61":{"tf":2.8284271247461903},"62":{"tf":1.0},"63":{"tf":2.449489742783178},"64":{"tf":1.7320508075688772},"67":{"tf":2.449489742783178},"68":{"tf":2.6457513110645907},"81":{"tf":1.0},"99":{"tf":1.0}},"df":18,"x":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"83":{"tf":1.4142135623730951}},"df":1}}}}}},"r":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"87":{"tf":1.0},"88":{"tf":1.0}},"df":2}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"126":{"tf":1.0},"13":{"tf":1.0},"53":{"tf":1.0},"64":{"tf":1.0},"69":{"tf":1.0}},"df":5}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"36":{"tf":1.0}},"df":1}}},"e":{"docs":{"102":{"tf":1.0},"107":{"tf":1.0},"108":{"tf":1.0},"123":{"tf":1.4142135623730951},"124":{"tf":1.0},"133":{"tf":1.0},"134":{"tf":1.0},"158":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.7320508075688772},"191":{"tf":1.0},"38":{"tf":1.0},"40":{"tf":1.0},"43":{"tf":1.7320508075688772},"44":{"tf":1.0},"46":{"tf":1.0},"53":{"tf":1.0},"61":{"tf":1.4142135623730951},"62":{"tf":1.7320508075688772},"63":{"tf":1.0},"64":{"tf":1.4142135623730951},"67":{"tf":2.0},"68":{"tf":2.0},"71":{"tf":1.0},"74":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.4142135623730951},"80":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0}},"df":30},"h":{"docs":{"71":{"tf":1.0},"77":{"tf":1.0},"86":{"tf":1.0},"94":{"tf":1.0}},"df":4},"i":{"docs":{},"df":0,"c":{"docs":{"101":{"tf":1.0},"92":{"tf":1.0}},"df":2}}},"w":{"docs":{"109":{"tf":1.4142135623730951},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.4142135623730951},"166":{"tf":1.0},"167":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.0},"188":{"tf":1.0},"41":{"tf":1.0},"44":{"tf":1.0},"53":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":1.4142135623730951},"64":{"tf":1.7320508075688772},"65":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":2.23606797749979},"78":{"tf":1.0},"92":{"tf":2.0},"93":{"tf":1.4142135623730951}},"df":22}},"r":{"docs":{},"df":0,"f":{"docs":{},"df":0,"5":{"docs":{},"df":0,"2":{"docs":{},"df":0,"8":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"87":{"tf":1.0},"88":{"tf":1.0}},"df":2}}}}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{"133":{"tf":1.0},"173":{"tf":1.0}},"df":2}},"m":{"docs":{"168":{"tf":1.0}},"df":1,"b":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"114":{"tf":1.0},"115":{"tf":1.4142135623730951},"120":{"tf":1.0},"128":{"tf":1.0},"154":{"tf":1.0},"158":{"tf":1.0},"166":{"tf":1.0},"17":{"tf":1.0},"189":{"tf":1.0},"191":{"tf":1.0},"194":{"tf":1.0},"44":{"tf":1.4142135623730951},"62":{"tf":1.4142135623730951},"67":{"tf":1.0},"69":{"tf":1.0},"95":{"tf":1.0}},"df":16,"(":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}},"e":{"docs":{},"df":0,"r":{"docs":{"72":{"tf":1.0}},"df":1}}},"t":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"115":{"tf":1.0}},"df":1}}}}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"127":{"tf":1.0}},"df":1}}},"x":{"docs":{},"df":0,"p":{"docs":{"36":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"j":{"docs":{},"df":0,"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{"21":{"tf":1.4142135623730951},"62":{"tf":1.4142135623730951},"83":{"tf":1.0}},"df":3}}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":2.0},"105":{"tf":1.0},"146":{"tf":1.7320508075688772},"161":{"tf":1.0},"73":{"tf":1.0},"76":{"tf":2.23606797749979},"97":{"tf":1.0}},"df":7}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"v":{"docs":{"136":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.0},"101":{"tf":1.0},"104":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.4142135623730951},"166":{"tf":1.0},"99":{"tf":1.0}},"df":8}}}}},"c":{"docs":{},"df":0,"c":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"84":{"tf":1.0}},"df":1}},"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{"187":{"tf":1.4142135623730951},"62":{"tf":1.0}},"df":2}},"r":{"docs":{"120":{"tf":1.0},"136":{"tf":1.0},"165":{"tf":1.4142135623730951},"92":{"tf":1.0}},"df":4}}}},"f":{"docs":{},"df":0,"f":{"docs":{"119":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{"114":{"tf":1.0},"129":{"tf":1.0},"168":{"tf":1.0},"69":{"tf":1.7320508075688772},"70":{"tf":1.0},"96":{"tf":1.0}},"df":6}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{"50":{"tf":1.0},"51":{"tf":1.0}},"df":2}}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"86":{"tf":1.7320508075688772}},"df":1}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"90":{"tf":1.0}},"df":1}}}}},"h":{"docs":{"75":{"tf":1.0}},"df":1},"k":{"docs":{"100":{"tf":1.0},"108":{"tf":1.7320508075688772}},"df":2,"(":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"83":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{},"df":0,".":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"108":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"l":{"docs":{},"df":0,"d":{"docs":{"53":{"tf":1.4142135623730951},"86":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,"r":{"docs":{"68":{"tf":1.4142135623730951},"78":{"tf":1.0}},"df":2}}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"61":{"tf":1.0},"81":{"tf":1.0}},"df":2}}},"n":{"docs":{"101":{"tf":1.0},"102":{"tf":1.0},"103":{"tf":1.4142135623730951},"105":{"tf":1.0},"117":{"tf":1.4142135623730951},"122":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.0},"127":{"tf":1.7320508075688772},"128":{"tf":1.0},"132":{"tf":1.0},"134":{"tf":1.0},"14":{"tf":1.0},"158":{"tf":1.0},"164":{"tf":1.4142135623730951},"168":{"tf":1.0},"173":{"tf":1.4142135623730951},"174":{"tf":1.0},"184":{"tf":1.0},"190":{"tf":1.0},"197":{"tf":1.0},"21":{"tf":1.0},"38":{"tf":1.4142135623730951},"49":{"tf":1.0},"53":{"tf":1.7320508075688772},"61":{"tf":1.4142135623730951},"63":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.7320508075688772},"68":{"tf":2.0},"69":{"tf":1.4142135623730951},"71":{"tf":1.0},"75":{"tf":1.7320508075688772},"77":{"tf":1.0},"78":{"tf":1.4142135623730951},"80":{"tf":1.7320508075688772},"87":{"tf":1.0},"92":{"tf":1.4142135623730951},"93":{"tf":1.0},"96":{"tf":1.4142135623730951},"97":{"tf":1.0}},"df":42,"_":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"(":{"docs":{},"df":0,"_":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}}}}}},"c":{"docs":{"100":{"tf":1.0},"127":{"tf":1.0},"133":{"tf":1.0},"68":{"tf":1.0},"78":{"tf":1.0},"93":{"tf":1.0},"99":{"tf":1.7320508075688772}},"df":7},"t":{"docs":{},"df":0,"o":{"docs":{"62":{"tf":1.0},"68":{"tf":1.0}},"df":2}}},"o":{"docs":{},"df":0,"m":{"docs":{"133":{"tf":1.0},"136":{"tf":2.23606797749979}},"df":2}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"130":{"tf":1.0},"27":{"tf":1.0},"33":{"tf":1.0},"50":{"tf":1.0},"53":{"tf":1.4142135623730951},"54":{"tf":1.0},"6":{"tf":1.0},"63":{"tf":1.0},"68":{"tf":1.0}},"df":9,"d":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"155":{"tf":1.7320508075688772}},"df":1}}}}},"g":{"docs":{},"df":0,"l":{"docs":{"86":{"tf":1.0}},"df":1}},"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"d":{"docs":{"19":{"tf":1.0},"191":{"tf":1.0},"24":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.7320508075688772},"31":{"tf":1.0},"43":{"tf":2.0},"44":{"tf":1.0},"46":{"tf":2.0},"47":{"tf":1.4142135623730951},"50":{"tf":1.7320508075688772},"52":{"tf":1.0},"53":{"tf":2.6457513110645907},"54":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":3.4641016151377544},"77":{"tf":2.0},"81":{"tf":1.0},"83":{"tf":1.4142135623730951}},"df":19,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"f":{"docs":{},"df":0,"g":{"docs":{"68":{"tf":1.7320508075688772}},"df":1}}},"g":{"docs":{},"df":0,"d":{"docs":{},"df":0,"b":{"docs":{"68":{"tf":2.6457513110645907}},"df":1}}}}}}}},"r":{"docs":{"103":{"tf":1.0},"11":{"tf":1.0},"114":{"tf":1.4142135623730951},"117":{"tf":1.4142135623730951},"124":{"tf":2.0},"125":{"tf":1.4142135623730951},"130":{"tf":1.0},"134":{"tf":1.7320508075688772},"136":{"tf":1.0},"137":{"tf":1.0},"138":{"tf":1.7320508075688772},"16":{"tf":1.0},"160":{"tf":1.4142135623730951},"191":{"tf":1.0},"194":{"tf":1.0},"69":{"tf":1.0},"77":{"tf":2.0},"78":{"tf":1.0},"79":{"tf":1.0},"80":{"tf":1.0},"83":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":22}},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{"190":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"164":{"tf":1.0}},"df":1}}}}},"t":{"docs":{"187":{"tf":1.0},"188":{"tf":1.7320508075688772},"189":{"tf":2.23606797749979},"190":{"tf":2.449489742783178},"78":{"tf":1.0}},"df":5,"i":{"docs":{},"df":0,"m":{"docs":{"112":{"tf":1.0},"186":{"tf":1.0},"187":{"tf":2.23606797749979},"188":{"tf":2.8284271247461903},"189":{"tf":1.7320508075688772},"190":{"tf":2.6457513110645907},"62":{"tf":1.0},"63":{"tf":1.0}},"df":8,"i":{"docs":{},"df":0,"s":{"docs":{"158":{"tf":1.0},"163":{"tf":1.0},"188":{"tf":1.0}},"df":3}}},"o":{"docs":{},"df":0,"n":{"docs":{"117":{"tf":1.0},"127":{"tf":2.0},"132":{"tf":1.0},"19":{"tf":1.0},"36":{"tf":1.0},"49":{"tf":1.0},"68":{"tf":1.4142135623730951},"99":{"tf":1.0}},"df":8,"<":{"docs":{},"df":0,"&":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{"127":{"tf":1.0}},"df":1}}}}}},"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{"127":{"tf":1.0}},"df":1}}}}},"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"99":{"tf":1.0}},"df":1}}}}}}}}}},"t":{"docs":{"100":{"tf":1.0},"99":{"tf":1.0}},"df":2}}}}}}},"r":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"120":{"tf":1.0},"124":{"tf":2.0},"166":{"tf":1.7320508075688772},"173":{"tf":1.4142135623730951},"20":{"tf":1.0},"28":{"tf":1.0},"63":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":1.0},"91":{"tf":1.0}},"df":10,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"x":{"docs":{"124":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}},"g":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"173":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"105":{"tf":1.0},"61":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951}},"df":3,"(":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{"61":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"61":{"tf":1.0}},"df":1}}}}}}}}},"s":{"docs":{"114":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"21":{"tf":1.0},"37":{"tf":1.0},"41":{"tf":1.0}},"df":6,"/":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{"62":{"tf":1.0}},"df":1}}}},"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"76":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"119":{"tf":1.0}},"df":1,"w":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{"127":{"tf":1.4142135623730951},"61":{"tf":1.0}},"df":2}}}}}}},"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"v":{"docs":{"125":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0}},"df":3}}}}},"t":{"docs":{"107":{"tf":1.0},"120":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":2.0},"128":{"tf":1.0},"133":{"tf":1.4142135623730951},"136":{"tf":1.4142135623730951},"160":{"tf":1.0},"163":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.0},"3":{"tf":1.7320508075688772},"53":{"tf":1.0},"63":{"tf":1.4142135623730951},"67":{"tf":1.0},"68":{"tf":2.0},"69":{"tf":1.0},"78":{"tf":1.0},"79":{"tf":1.4142135623730951},"88":{"tf":1.0},"91":{"tf":1.0},"93":{"tf":1.0}},"df":24,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"24":{"tf":1.0}},"df":1}}},"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"103":{"tf":1.0},"106":{"tf":2.449489742783178},"107":{"tf":2.23606797749979},"108":{"tf":2.449489742783178},"109":{"tf":2.6457513110645907},"11":{"tf":1.0},"110":{"tf":1.7320508075688772},"115":{"tf":1.0},"121":{"tf":1.7320508075688772},"127":{"tf":1.0},"155":{"tf":2.23606797749979},"174":{"tf":1.4142135623730951},"180":{"tf":1.0},"53":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":1.7320508075688772},"76":{"tf":1.0},"81":{"tf":1.0}},"df":18,"<":{"docs":{"155":{"tf":1.7320508075688772}},"df":1},"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"107":{"tf":1.4142135623730951},"108":{"tf":1.0}},"df":2}}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"109":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"n":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":2.8284271247461903}},"df":1,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,">":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"155":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"163":{"tf":1.0},"182":{"tf":1.0},"86":{"tf":1.0}},"df":3}}},"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"183":{"tf":1.0}},"df":1}}}}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"131":{"tf":1.0},"160":{"tf":1.0},"166":{"tf":1.0},"21":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"88":{"tf":1.4142135623730951},"93":{"tf":1.0}},"df":9,"a":{"docs":{},"df":0,"l":{"docs":{"13":{"tf":1.0}},"df":1}},"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"15":{"tf":1.0},"17":{"tf":1.0}},"df":2}}}},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"125":{"tf":1.4142135623730951},"127":{"tf":1.0},"128":{"tf":1.4142135623730951},"157":{"tf":1.0},"99":{"tf":1.0}},"df":5}}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"188":{"tf":2.23606797749979},"53":{"tf":1.0},"68":{"tf":1.0},"82":{"tf":1.7320508075688772}},"df":4}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.0}},"df":3}}}},"w":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"m":{"docs":{"70":{"tf":1.0}},"df":1}}}}}}}},"w":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{"101":{"tf":1.0},"103":{"tf":1.0},"164":{"tf":1.0},"96":{"tf":1.0},"98":{"tf":1.0}},"df":5}}}}}}}}},"p":{"docs":{"166":{"tf":3.1622776601683795},"72":{"tf":1.0},"76":{"tf":1.0},"81":{"tf":1.0},"93":{"tf":1.4142135623730951},"99":{"tf":1.0}},"df":6,".":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,".":{"docs":{},"df":0,"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,".":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"p":{"docs":{},"df":0,"w":{"docs":{},"df":0,"m":{"docs":{},"df":0,"0":{"docs":{"72":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}},"t":{"docs":{"81":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"0":{"docs":{"76":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"99":{"tf":1.0}},"df":1}}}}}}},"a":{"docs":{"154":{"tf":2.0},"155":{"tf":1.0}},"df":2,"0":{"docs":{"127":{"tf":1.7320508075688772},"153":{"tf":2.23606797749979},"154":{"tf":1.4142135623730951},"76":{"tf":1.0}},"df":4},"1":{"docs":{"127":{"tf":1.4142135623730951},"153":{"tf":2.23606797749979},"76":{"tf":1.0}},"df":3,"<":{"docs":{"155":{"tf":1.4142135623730951}},"df":1,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"<":{"docs":{},"df":0,"n":{"docs":{"155":{"tf":1.0}},"df":1}}}}}}},"n":{"docs":{"155":{"tf":2.0}},"df":1},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"<":{"docs":{},"df":0,"n":{"docs":{"155":{"tf":1.0}},"df":1}}}}}}}}}},"c":{"docs":{"142":{"tf":1.0},"147":{"tf":2.0},"195":{"tf":1.0},"69":{"tf":1.0},"76":{"tf":1.0}},"df":5,"k":{"docs":{"154":{"tf":1.0},"166":{"tf":1.7320508075688772},"68":{"tf":1.0},"86":{"tf":1.0}},"df":4,"a":{"docs":{},"df":0,"g":{"docs":{"178":{"tf":1.4142135623730951},"188":{"tf":1.0},"20":{"tf":1.0},"40":{"tf":1.0},"58":{"tf":1.0},"78":{"tf":1.0}},"df":6}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"43":{"tf":1.0}},"df":1}}}},"d":{"docs":{"166":{"tf":1.7320508075688772},"173":{"tf":1.0}},"df":2},"g":{"docs":{},"df":0,"e":{"docs":{"160":{"tf":1.0},"19":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.0},"37":{"tf":1.0},"9":{"tf":1.0}},"df":7}},"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"127":{"tf":1.0},"68":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":2.23606797749979},"78":{"tf":3.7416573867739413},"79":{"tf":2.0},"81":{"tf":1.0},"99":{"tf":1.4142135623730951}},"df":9,"_":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"78":{"tf":2.0}},"df":1}}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"191":{"tf":1.0},"60":{"tf":1.4142135623730951},"64":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.4142135623730951},"78":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.0}},"df":10}},"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{"60":{"tf":1.0},"78":{"tf":1.4142135623730951}},"df":2}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"77":{"tf":1.0},"79":{"tf":1.0}},"df":2}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{"78":{"tf":1.0}},"df":1}}}},"k":{"docs":{"60":{"tf":1.4142135623730951},"77":{"tf":1.4142135623730951},"78":{"tf":3.0},"79":{"tf":1.0}},"df":4}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"86":{"tf":1.0}},"df":1}}}},"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"142":{"tf":1.0},"151":{"tf":1.0},"155":{"tf":1.0}},"df":3}}}},"t":{"docs":{"103":{"tf":1.0},"11":{"tf":2.0},"117":{"tf":1.0},"119":{"tf":1.4142135623730951},"120":{"tf":1.7320508075688772},"121":{"tf":1.0},"133":{"tf":1.0},"134":{"tf":1.0},"138":{"tf":1.0},"14":{"tf":1.0},"160":{"tf":1.0},"164":{"tf":1.0},"171":{"tf":1.0},"173":{"tf":1.0},"179":{"tf":1.0},"183":{"tf":1.0},"22":{"tf":1.0},"59":{"tf":1.0},"60":{"tf":1.0},"69":{"tf":1.0},"78":{"tf":1.0},"84":{"tf":1.0}},"df":22,"i":{"docs":{"63":{"tf":1.0},"92":{"tf":1.0}},"df":2,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"124":{"tf":1.0},"188":{"tf":1.0},"189":{"tf":1.0},"2":{"tf":1.4142135623730951},"69":{"tf":1.7320508075688772},"72":{"tf":1.4142135623730951},"73":{"tf":1.7320508075688772},"74":{"tf":1.7320508075688772},"75":{"tf":1.0},"82":{"tf":1.0},"93":{"tf":1.0}},"df":11,"l":{"docs":{},"df":0,"i":{"docs":{"36":{"tf":1.0}},"df":1}}}}}}}}}},"s":{"docs":{},"df":0,"s":{"docs":{"122":{"tf":1.0},"125":{"tf":1.7320508075688772},"128":{"tf":1.0},"165":{"tf":1.0},"64":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.4142135623730951},"96":{"tf":1.0}},"df":8},"t":{"docs":{"61":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"h":{"docs":{"177":{"tf":1.0},"44":{"tf":1.4142135623730951},"49":{"tf":1.4142135623730951},"50":{"tf":1.7320508075688772}},"df":4},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"n":{"docs":{"104":{"tf":1.0},"131":{"tf":1.0},"140":{"tf":1.0},"141":{"tf":1.4142135623730951},"142":{"tf":1.0},"157":{"tf":1.0},"160":{"tf":1.4142135623730951},"163":{"tf":1.0},"97":{"tf":1.7320508075688772}},"df":9}}}}},"u":{"docs":{},"df":0,"s":{"docs":{"123":{"tf":1.0}},"df":1}}},"c":{"docs":{"13":{"tf":1.4142135623730951},"53":{"tf":1.0},"68":{"tf":3.0},"83":{"tf":1.4142135623730951},"86":{"tf":1.0}},"df":5},"d":{"docs":{},"df":0,"f":{"docs":{"87":{"tf":1.0},"88":{"tf":1.0}},"df":2}},"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"k":{"docs":{"68":{"tf":1.0}},"df":1}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"110":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{"3":{"tf":1.0}},"df":1}}},"r":{"docs":{"158":{"tf":1.0},"72":{"tf":1.0},"88":{"tf":1.4142135623730951}},"df":3,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"70":{"tf":1.0}},"df":1,"l":{"docs":{},"df":0,"i":{"docs":{"121":{"tf":1.0},"93":{"tf":1.0}},"df":2}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"m":{"docs":{"100":{"tf":1.0},"103":{"tf":1.0},"106":{"tf":1.7320508075688772},"110":{"tf":1.0},"114":{"tf":1.0},"121":{"tf":1.0},"151":{"tf":1.0},"160":{"tf":1.0},"165":{"tf":2.0},"174":{"tf":1.0},"191":{"tf":1.4142135623730951},"35":{"tf":1.0},"72":{"tf":1.0},"83":{"tf":1.0},"92":{"tf":1.4142135623730951}},"df":15}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"13":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"122":{"tf":1.4142135623730951},"128":{"tf":1.0}},"df":2}},"p":{"docs":{},"df":0,"h":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":2.6457513110645907},"112":{"tf":1.0}},"df":4,"e":{"docs":{},"df":0,"r":{"docs":{"100":{"tf":2.449489742783178},"103":{"tf":2.0},"106":{"tf":1.4142135623730951},"107":{"tf":1.0},"11":{"tf":1.0},"114":{"tf":1.4142135623730951},"115":{"tf":1.4142135623730951},"118":{"tf":1.0},"119":{"tf":1.4142135623730951},"121":{"tf":1.4142135623730951},"126":{"tf":1.0},"127":{"tf":3.1622776601683795},"146":{"tf":2.0},"150":{"tf":1.4142135623730951},"164":{"tf":1.4142135623730951},"165":{"tf":1.4142135623730951},"195":{"tf":1.4142135623730951},"197":{"tf":1.4142135623730951},"198":{"tf":1.0},"4":{"tf":1.0},"69":{"tf":2.6457513110645907},"7":{"tf":1.0},"71":{"tf":2.23606797749979},"72":{"tf":1.7320508075688772},"73":{"tf":1.0},"74":{"tf":1.0},"76":{"tf":2.23606797749979},"78":{"tf":1.0},"86":{"tf":2.23606797749979},"87":{"tf":1.0},"88":{"tf":2.0},"90":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0},"95":{"tf":2.23606797749979},"96":{"tf":1.7320508075688772},"99":{"tf":3.1622776601683795}},"df":37,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"(":{"docs":{"84":{"tf":1.0}},"df":1},"s":{"docs":{},"df":0,".":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"71":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"101":{"tf":1.0},"99":{"tf":1.4142135623730951}},"df":2}}}}}}}}}},":":{"docs":{},"df":0,":":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{"71":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"71":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"’":{"docs":{"69":{"tf":1.0}},"df":1}}}}}}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"166":{"tf":1.4142135623730951},"44":{"tf":1.7320508075688772},"53":{"tf":1.4142135623730951},"87":{"tf":1.0}},"df":4}},"t":{"docs":{"126":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.0}},"df":3}}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"<":{"docs":{"155":{"tf":1.7320508075688772}},"df":1}}}}}}}}}},"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"119":{"tf":1.0},"137":{"tf":1.0},"80":{"tf":1.0},"87":{"tf":1.4142135623730951}},"df":4}}}}},"i":{"docs":{"12":{"tf":1.0}},"df":1,"c":{"docs":{},"df":0,"k":{"docs":{"139":{"tf":1.0},"61":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.7320508075688772},"76":{"tf":1.0},"78":{"tf":1.0}},"df":6},"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"53":{"tf":1.0},"9":{"tf":1.0}},"df":2}}}},"d":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2},"e":{"docs":{},"df":0,"c":{"docs":{"173":{"tf":1.0},"86":{"tf":1.0},"92":{"tf":1.4142135623730951}},"df":3}},"n":{"docs":{"103":{"tf":1.7320508075688772},"106":{"tf":1.4142135623730951},"107":{"tf":2.0},"108":{"tf":2.0},"109":{"tf":3.0},"11":{"tf":1.4142135623730951},"110":{"tf":1.4142135623730951},"115":{"tf":1.0},"117":{"tf":1.0},"142":{"tf":2.6457513110645907},"146":{"tf":1.0},"153":{"tf":1.7320508075688772},"154":{"tf":3.3166247903554},"155":{"tf":3.1622776601683795},"69":{"tf":1.4142135623730951},"76":{"tf":2.449489742783178}},"df":16,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"n":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}},"<":{"docs":{},"df":0,"n":{"docs":{"155":{"tf":1.4142135623730951}},"df":1}},"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.4142135623730951}},"df":1}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":2.23606797749979}},"df":1}}}}},"p":{"docs":{},"df":0,"e":{"docs":{"174":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"35":{"tf":1.0}},"df":1}}}},"k":{"docs":{},"df":0,"g":{"docs":{"40":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"101":{"tf":1.0},"133":{"tf":1.0},"136":{"tf":1.0},"166":{"tf":1.0},"178":{"tf":1.4142135623730951},"61":{"tf":1.4142135623730951},"91":{"tf":1.0}},"df":7,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{"58":{"tf":1.0},"59":{"tf":1.0}},"df":2}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{"127":{"tf":1.4142135623730951},"53":{"tf":1.0},"68":{"tf":1.0},"80":{"tf":1.0},"84":{"tf":1.0}},"df":5}},"n":{"docs":{"125":{"tf":1.0}},"df":1},"t":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"m":{"docs":{"114":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.7320508075688772},"125":{"tf":1.0},"14":{"tf":1.0},"16":{"tf":1.4142135623730951},"162":{"tf":1.4142135623730951},"168":{"tf":1.0},"177":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.0},"31":{"tf":1.0}},"df":13}}}}},"y":{"docs":{"101":{"tf":1.0},"119":{"tf":1.0}},"df":2}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"174":{"tf":1.0},"53":{"tf":1.0},"6":{"tf":1.0},"84":{"tf":1.0},"9":{"tf":1.0}},"df":5,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"108":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"78":{"tf":1.0}},"df":1}}}},"l":{"docs":{"76":{"tf":1.4142135623730951}},"df":1},"u":{"docs":{"187":{"tf":1.0},"19":{"tf":1.0}},"df":2,"g":{"docs":{"44":{"tf":1.4142135623730951}},"df":1}}},"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"101":{"tf":1.0},"11":{"tf":1.0},"130":{"tf":1.0},"184":{"tf":1.0},"194":{"tf":1.4142135623730951},"38":{"tf":1.7320508075688772},"53":{"tf":1.0},"56":{"tf":1.0},"60":{"tf":1.4142135623730951},"62":{"tf":1.0},"64":{"tf":1.4142135623730951},"68":{"tf":1.0},"70":{"tf":1.0},"72":{"tf":1.0},"83":{"tf":1.0},"93":{"tf":1.0}},"df":16,"e":{"docs":{},"df":0,"r":{"docs":{"133":{"tf":2.0},"164":{"tf":2.449489742783178},"165":{"tf":1.0},"166":{"tf":1.0},"167":{"tf":1.4142135623730951},"173":{"tf":2.0},"192":{"tf":1.0},"83":{"tf":1.0}},"df":8}}}}},"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2,"a":{"docs":{},"df":0,"r":{"docs":{"34":{"tf":1.0},"54":{"tf":1.0}},"df":2}}}}},"r":{"docs":{},"df":0,"t":{"docs":{"11":{"tf":1.4142135623730951},"119":{"tf":1.0},"142":{"tf":1.0},"153":{"tf":1.4142135623730951},"154":{"tf":2.449489742783178},"175":{"tf":1.0},"47":{"tf":1.7320508075688772},"64":{"tf":1.4142135623730951},"68":{"tf":1.0},"76":{"tf":2.0},"88":{"tf":2.0}},"df":11,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"a":{"docs":{"154":{"tf":1.0}},"df":1}}},"a":{"docs":{"153":{"tf":1.4142135623730951},"76":{"tf":1.7320508075688772}},"df":2,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"76":{"tf":1.4142135623730951}},"df":1}}}}}}}},"b":{"docs":{},"df":0,"l":{"docs":{"114":{"tf":1.4142135623730951},"69":{"tf":1.0}},"df":2}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"153":{"tf":1.7320508075688772}},"df":1}}}},"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"87":{"tf":1.4142135623730951}},"df":1}}}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"82":{"tf":1.0},"84":{"tf":1.0},"92":{"tf":1.0}},"df":3},"x":{"docs":{"13":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"101":{"tf":1.0},"102":{"tf":1.0},"103":{"tf":1.0},"113":{"tf":1.0},"124":{"tf":1.0},"126":{"tf":1.0},"133":{"tf":1.0},"134":{"tf":1.0},"136":{"tf":1.4142135623730951},"146":{"tf":1.0},"158":{"tf":1.0},"186":{"tf":1.0},"2":{"tf":1.0},"72":{"tf":1.0},"80":{"tf":1.7320508075688772},"82":{"tf":1.0},"84":{"tf":1.4142135623730951}},"df":17}}}},"t":{"docs":{"161":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"102":{"tf":1.0},"114":{"tf":1.0},"115":{"tf":1.0},"127":{"tf":1.0},"134":{"tf":1.0},"136":{"tf":1.4142135623730951},"137":{"tf":1.0},"80":{"tf":1.0}},"df":8}}}}},"w":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"160":{"tf":1.4142135623730951},"163":{"tf":1.0},"166":{"tf":1.0},"75":{"tf":1.0},"76":{"tf":1.4142135623730951},"86":{"tf":1.0}},"df":6}}}},"r":{"docs":{"6":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"164":{"tf":1.0},"2":{"tf":1.0}},"df":2}}}}},"e":{"docs":{"125":{"tf":1.0},"69":{"tf":1.0}},"df":2,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{"11":{"tf":1.0},"124":{"tf":1.0},"66":{"tf":1.0}},"df":3}}},"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.0},"141":{"tf":1.0},"142":{"tf":1.0}},"df":3}}}},"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"123":{"tf":1.0},"84":{"tf":1.0}},"df":2,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"80":{"tf":1.0}},"df":1}},"v":{"docs":{"130":{"tf":1.0}},"df":1}}}}}},"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"53":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"x":{"docs":{"174":{"tf":1.0}},"df":1,"=":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"174":{"tf":1.0}},"df":1}}}}}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"157":{"tf":1.7320508075688772},"158":{"tf":1.0},"160":{"tf":1.7320508075688772}},"df":3}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"3":{"tf":1.0},"39":{"tf":1.0}},"df":2}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"161":{"tf":1.0},"175":{"tf":1.0},"93":{"tf":1.0}},"df":3}},"r":{"docs":{},"df":0,"v":{"docs":{"166":{"tf":1.0}},"df":1}}},"s":{"docs":{"69":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"29":{"tf":1.0},"31":{"tf":1.0},"67":{"tf":1.0},"71":{"tf":1.4142135623730951},"72":{"tf":1.0},"77":{"tf":1.0},"80":{"tf":1.0}},"df":7}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"103":{"tf":1.0},"127":{"tf":1.0},"14":{"tf":1.0},"155":{"tf":1.0},"163":{"tf":1.0},"80":{"tf":1.0},"84":{"tf":1.0},"87":{"tf":1.0}},"df":8}}},"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{"103":{"tf":1.0},"125":{"tf":1.0},"67":{"tf":1.4142135623730951},"80":{"tf":1.0}},"df":4}}}}},"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"34":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"t":{"docs":{"123":{"tf":1.0},"126":{"tf":1.0},"129":{"tf":1.0},"13":{"tf":1.4142135623730951},"130":{"tf":1.0},"131":{"tf":1.0},"158":{"tf":1.0},"16":{"tf":1.0},"165":{"tf":1.4142135623730951},"168":{"tf":1.4142135623730951},"173":{"tf":1.0}},"df":11}}},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{"190":{"tf":1.0},"86":{"tf":1.0}},"df":2}}}},"t":{"docs":{"161":{"tf":1.0},"166":{"tf":1.0},"187":{"tf":1.7320508075688772},"29":{"tf":1.0},"31":{"tf":1.0},"62":{"tf":1.7320508075688772},"63":{"tf":1.4142135623730951},"64":{"tf":2.0},"68":{"tf":1.7320508075688772},"79":{"tf":1.4142135623730951},"81":{"tf":1.0},"83":{"tf":1.4142135623730951}},"df":12,"l":{"docs":{},"df":0,"n":{"docs":{"104":{"tf":1.0},"191":{"tf":1.0}},"df":2,"!":{"docs":{},"df":0,"(":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"191":{"tf":1.0}},"df":1}}}}},"t":{"docs":{},"df":0,"h":{"docs":{"191":{"tf":1.4142135623730951}},"df":1}},"{":{"docs":{},"df":0,":":{"docs":{},"df":0,"p":{"docs":{"166":{"tf":2.23606797749979}},"df":1}}}}}}}}}},"o":{"docs":{},"df":0,"r":{"docs":{"3":{"tf":1.0},"40":{"tf":1.0}},"df":2,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"128":{"tf":1.0},"84":{"tf":1.7320508075688772}},"df":2}}}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"g":{"docs":{"44":{"tf":1.0}},"df":1}}}}}},"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"v":{"docs":{"136":{"tf":1.0}},"df":1}}}}},"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"160":{"tf":1.0},"163":{"tf":1.0}},"df":2}}},"e":{"docs":{"24":{"tf":2.23606797749979},"26":{"tf":2.0},"29":{"tf":1.0},"32":{"tf":1.4142135623730951},"33":{"tf":2.23606797749979},"34":{"tf":1.0},"36":{"tf":1.0}},"df":7},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{"121":{"tf":1.0},"123":{"tf":1.4142135623730951},"126":{"tf":1.0},"134":{"tf":1.0},"136":{"tf":1.0},"161":{"tf":1.0},"184":{"tf":1.0},"187":{"tf":1.0},"53":{"tf":1.0},"92":{"tf":1.7320508075688772},"93":{"tf":1.0},"98":{"tf":1.0}},"df":12}}}},"c":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{"78":{"tf":1.0}},"df":1}}}}}},"e":{"docs":{"134":{"tf":1.0},"68":{"tf":1.0}},"df":2,"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"160":{"tf":1.4142135623730951}},"df":1}}},"s":{"docs":{},"df":0,"s":{"docs":{"100":{"tf":1.0},"104":{"tf":1.0},"121":{"tf":1.0},"123":{"tf":1.7320508075688772},"131":{"tf":1.4142135623730951},"15":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"163":{"tf":1.0},"174":{"tf":1.0},"184":{"tf":1.0},"191":{"tf":1.0},"20":{"tf":1.0},"24":{"tf":1.4142135623730951},"29":{"tf":1.0},"49":{"tf":1.0},"53":{"tf":1.0},"54":{"tf":1.0},"55":{"tf":1.0},"60":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":2.0},"65":{"tf":1.4142135623730951},"67":{"tf":1.0},"68":{"tf":1.7320508075688772},"77":{"tf":1.0},"81":{"tf":1.0},"86":{"tf":1.4142135623730951},"87":{"tf":1.4142135623730951}},"df":30,"(":{"docs":{},"df":0,"*":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"163":{"tf":1.0}},"df":1}}},"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"[":{"docs":{},"df":0,"i":{"docs":{"163":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"121":{"tf":1.0}},"df":1}}}}}},"o":{"docs":{},"df":0,"r":{"docs":{"11":{"tf":1.0},"131":{"tf":1.0},"16":{"tf":1.0},"194":{"tf":1.0},"30":{"tf":1.0},"32":{"tf":1.0},"49":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.7320508075688772},"80":{"tf":1.4142135623730951},"83":{"tf":1.0},"86":{"tf":1.7320508075688772},"90":{"tf":1.0}},"df":13}}}}}},"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{"174":{"tf":1.0},"178":{"tf":1.0},"190":{"tf":1.0},"63":{"tf":1.0}},"df":4,"t":{"docs":{"114":{"tf":1.0}},"df":1}}}},"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"30":{"tf":1.0},"36":{"tf":1.0}},"df":2}}}}}},"i":{"docs":{},"df":0,"l":{"docs":{"187":{"tf":2.0},"188":{"tf":1.4142135623730951},"189":{"tf":1.0},"78":{"tf":2.23606797749979}},"df":4,"e":{"docs":{},"df":0,".":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{},"df":0,".":{"docs":{},"df":0,"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"188":{"tf":1.4142135623730951}},"df":1,"e":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{"188":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"187":{"tf":1.0},"190":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,".":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"190":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"g":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"103":{"tf":1.4142135623730951},"104":{"tf":1.0},"114":{"tf":1.0},"12":{"tf":2.0},"120":{"tf":2.0},"121":{"tf":1.4142135623730951},"122":{"tf":1.0},"132":{"tf":1.0},"133":{"tf":1.7320508075688772},"138":{"tf":1.0},"14":{"tf":1.4142135623730951},"16":{"tf":1.0},"186":{"tf":1.4142135623730951},"187":{"tf":1.0},"189":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.7320508075688772},"22":{"tf":1.0},"24":{"tf":1.4142135623730951},"27":{"tf":1.0},"28":{"tf":1.0},"3":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.4142135623730951},"4":{"tf":1.0},"43":{"tf":1.7320508075688772},"5":{"tf":1.4142135623730951},"53":{"tf":1.0},"54":{"tf":1.4142135623730951},"55":{"tf":1.0},"60":{"tf":3.0},"61":{"tf":1.0},"62":{"tf":2.23606797749979},"63":{"tf":2.0},"64":{"tf":2.23606797749979},"67":{"tf":1.0},"68":{"tf":3.0},"71":{"tf":1.0},"77":{"tf":2.23606797749979},"78":{"tf":2.23606797749979},"81":{"tf":1.0},"83":{"tf":2.23606797749979},"92":{"tf":1.0},"98":{"tf":1.0},"99":{"tf":1.0}},"df":48,"m":{"docs":{"11":{"tf":1.0},"114":{"tf":1.0},"167":{"tf":1.0},"199":{"tf":1.0},"36":{"tf":1.0},"84":{"tf":1.0}},"df":6,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"’":{"docs":{"165":{"tf":1.0}},"df":1}}}},"’":{"docs":{"15":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"170":{"tf":1.0}},"df":1}}}}},"j":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"169":{"tf":1.0},"170":{"tf":1.4142135623730951},"171":{"tf":1.0},"174":{"tf":1.4142135623730951},"175":{"tf":1.4142135623730951},"176":{"tf":1.4142135623730951},"177":{"tf":1.4142135623730951},"178":{"tf":1.4142135623730951},"179":{"tf":1.4142135623730951},"180":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.4142135623730951},"2":{"tf":1.0},"20":{"tf":1.4142135623730951},"40":{"tf":1.0},"50":{"tf":1.0},"55":{"tf":1.7320508075688772},"56":{"tf":2.0},"57":{"tf":2.0},"58":{"tf":2.0},"61":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.7320508075688772},"9":{"tf":1.0}},"df":24,".":{"docs":{},"df":0,"h":{"docs":{"184":{"tf":1.0}},"df":1}}}}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"24":{"tf":1.0}},"df":1},"s":{"docs":{"122":{"tf":1.0}},"df":1}}},"n":{"docs":{},"df":0,"e":{"docs":{"174":{"tf":1.0}},"df":1}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"177":{"tf":1.0},"80":{"tf":1.0}},"df":2,"l":{"docs":{},"df":0,"i":{"docs":{"103":{"tf":1.0},"104":{"tf":1.0},"80":{"tf":1.0}},"df":3}},"t":{"docs":{},"df":0,"i":{"docs":{"103":{"tf":1.0},"154":{"tf":1.0},"16":{"tf":1.0}},"df":3}}}}},"s":{"docs":{},"df":0,"e":{"docs":{"9":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"126":{"tf":1.0},"15":{"tf":1.0},"17":{"tf":1.0}},"df":3}}},"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"166":{"tf":1.0},"192":{"tf":1.0},"196":{"tf":1.0},"32":{"tf":1.0}},"df":4}}}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"1":{"tf":1.0},"114":{"tf":1.0},"115":{"tf":1.4142135623730951},"117":{"tf":1.4142135623730951},"118":{"tf":1.0},"120":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.7320508075688772},"125":{"tf":1.0},"126":{"tf":1.4142135623730951},"127":{"tf":1.0},"129":{"tf":1.0},"13":{"tf":1.4142135623730951},"130":{"tf":1.4142135623730951},"132":{"tf":1.0},"14":{"tf":1.4142135623730951},"142":{"tf":1.4142135623730951},"146":{"tf":1.4142135623730951},"147":{"tf":1.0},"148":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"151":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":2.23606797749979},"158":{"tf":1.4142135623730951},"16":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.4142135623730951},"163":{"tf":1.0},"164":{"tf":1.0},"166":{"tf":1.0},"168":{"tf":1.4142135623730951},"173":{"tf":1.4142135623730951},"175":{"tf":1.0},"178":{"tf":1.4142135623730951},"186":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.4142135623730951},"26":{"tf":1.0},"27":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"30":{"tf":1.0},"33":{"tf":1.0},"36":{"tf":1.0},"49":{"tf":1.0},"5":{"tf":1.0},"50":{"tf":1.4142135623730951},"60":{"tf":1.4142135623730951},"70":{"tf":1.4142135623730951},"77":{"tf":1.0},"80":{"tf":1.7320508075688772},"82":{"tf":1.0},"84":{"tf":1.0},"9":{"tf":1.4142135623730951},"93":{"tf":1.0}},"df":58}}}}},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"v":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"0":{"docs":{},"df":0,"x":{"docs":{},"df":0,"3":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"83":{"tf":1.0}},"df":1}}}}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"g":{"docs":{"101":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"u":{"docs":{},"df":0,"b":{"docs":{"104":{"tf":2.449489742783178},"107":{"tf":2.23606797749979},"108":{"tf":2.23606797749979},"109":{"tf":2.8284271247461903},"112":{"tf":1.0},"125":{"tf":1.4142135623730951},"146":{"tf":2.0},"153":{"tf":2.6457513110645907},"154":{"tf":2.23606797749979},"155":{"tf":4.47213595499958},"158":{"tf":1.4142135623730951},"173":{"tf":2.8284271247461903},"183":{"tf":1.0},"184":{"tf":1.0},"64":{"tf":1.0},"72":{"tf":1.0},"91":{"tf":2.0},"92":{"tf":2.0},"93":{"tf":3.0}},"df":19,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"173":{"tf":1.0},"98":{"tf":1.0}},"df":2,"l":{"docs":{},"df":0,"i":{"docs":{"170":{"tf":1.0}},"df":1}}}}}},"l":{"docs":{},"df":0,"l":{"docs":{"106":{"tf":2.449489742783178},"107":{"tf":2.23606797749979},"108":{"tf":2.0},"109":{"tf":1.4142135623730951},"188":{"tf":1.0},"72":{"tf":1.0},"8":{"tf":1.0}},"df":7,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"n":{"docs":{"155":{"tf":1.7320508075688772}},"df":1}}}},"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"109":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}},"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"109":{"tf":1.7320508075688772},"111":{"tf":1.0}},"df":2}}}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"109":{"tf":1.7320508075688772}},"df":1}}}}},"u":{"docs":{},"df":0,"p":{"docs":{"155":{"tf":1.7320508075688772}},"df":1}}}},"n":{"docs":{"60":{"tf":1.0}},"df":1},"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"7":{"tf":1.0}},"df":1}}}},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{"11":{"tf":1.0},"13":{"tf":1.0},"157":{"tf":1.0},"161":{"tf":1.0},"168":{"tf":1.0},"7":{"tf":1.0}},"df":6}}}},"s":{"docs":{},"df":0,"h":{"docs":{"134":{"tf":1.0},"83":{"tf":1.0}},"df":2,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{"155":{"tf":1.7320508075688772}},"df":1}}}}},"t":{"docs":{"101":{"tf":1.0},"123":{"tf":1.0},"183":{"tf":1.0},"61":{"tf":1.0},"76":{"tf":1.0},"78":{"tf":1.0},"82":{"tf":1.0}},"df":7}},"w":{"docs":{},"df":0,"m":{"docs":{"72":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"_":{"docs":{},"df":0,"2":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,".":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"w":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}},"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,".":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"w":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}},"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,".":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"w":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,".":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"w":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,".":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"y":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"r":{"docs":{"75":{"tf":1.0}},"df":1}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"0":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"73":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}},"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"w":{"docs":{"72":{"tf":1.0},"74":{"tf":1.0}},"df":2}}}}}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,".":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"w":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"0":{"docs":{"72":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"75":{"tf":1.0}},"df":1}}}},"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{"75":{"tf":1.0}},"df":1}}}}}}}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"75":{"tf":1.0}},"df":1}}}},"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{"75":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"0":{"docs":{"75":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"w":{"docs":{},"df":0,"m":{"docs":{},"df":0,"4":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"75":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}},"x":{"docs":{"166":{"tf":1.4142135623730951}},"df":1},"y":{"docs":{"166":{"tf":1.4142135623730951}},"df":1},"z":{"docs":{"166":{"tf":1.4142135623730951}},"df":1}},"q":{"docs":{"64":{"tf":1.0},"68":{"tf":1.0}},"df":2,"2":{"docs":{"49":{"tf":1.0}},"df":1},"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{"19":{"tf":1.0},"191":{"tf":1.0},"22":{"tf":1.4142135623730951},"43":{"tf":2.0},"46":{"tf":1.4142135623730951},"47":{"tf":1.4142135623730951},"51":{"tf":1.0},"54":{"tf":1.0},"55":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":4.69041575982343},"64":{"tf":3.3166247903554},"67":{"tf":1.7320508075688772},"68":{"tf":1.4142135623730951},"77":{"tf":2.8284271247461903},"79":{"tf":1.0},"81":{"tf":1.7320508075688772},"83":{"tf":1.4142135623730951}},"df":18}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"151":{"tf":1.4142135623730951},"91":{"tf":1.4142135623730951}},"df":2}}}}},"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"5":{"tf":1.0}},"df":1}}}}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"190":{"tf":1.0},"56":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.7320508075688772},"67":{"tf":1.0}},"df":5,"/":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"/":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,".":{"docs":{},"df":0,"z":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{"59":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}},"t":{"docs":{"127":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.7320508075688772}},"df":3}}}},"r":{"docs":{"155":{"tf":3.4641016151377544},"73":{"tf":1.0},"75":{"tf":1.4142135623730951}},"df":3,"0":{"docs":{"62":{"tf":1.7320508075688772},"83":{"tf":3.0}},"df":2},"1":{"docs":{"83":{"tf":1.0}},"df":1,"2":{"docs":{"83":{"tf":1.0}},"df":1}},"2":{"docs":{"83":{"tf":1.0}},"df":1},"3":{"docs":{"83":{"tf":1.0}},"df":1},"4":{"docs":{"62":{"tf":1.0}},"df":1},"7":{"docs":{"62":{"tf":1.4142135623730951}},"df":1},"_":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{"168":{"tf":1.0}},"df":1}}}},"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"103":{"tf":1.0},"122":{"tf":1.7320508075688772},"123":{"tf":1.4142135623730951},"80":{"tf":1.0}},"df":4}},"i":{"docs":{},"df":0,"s":{"docs":{"103":{"tf":1.0},"81":{"tf":1.0}},"df":2}},"m":{"docs":{"11":{"tf":1.0},"112":{"tf":1.0},"12":{"tf":1.4142135623730951},"61":{"tf":1.4142135623730951},"66":{"tf":2.449489742783178},"67":{"tf":1.0},"69":{"tf":1.0},"86":{"tf":1.7320508075688772},"87":{"tf":2.0},"92":{"tf":1.0}},"df":10,"/":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"13":{"tf":1.0}},"df":1}}}},"2":{"docs":{"61":{"tf":1.4142135623730951}},"df":1,"b":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"61":{"tf":1.7320508075688772}},"df":1}}}}},"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"17":{"tf":1.0}},"df":1}}},"g":{"docs":{"12":{"tf":1.4142135623730951},"30":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0},"78":{"tf":1.0},"87":{"tf":1.4142135623730951}},"df":6}},"r":{"docs":{},"df":0,"e":{"docs":{"165":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"b":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"12":{"tf":1.0}},"df":1}}}}}}},"t":{"docs":{},"df":0,"e":{"docs":{"11":{"tf":1.0},"68":{"tf":1.4142135623730951},"69":{"tf":1.0},"76":{"tf":2.23606797749979}},"df":4},"i":{"docs":{},"df":0,"o":{"docs":{"137":{"tf":1.0}},"df":1}}},"w":{"docs":{"146":{"tf":1.4142135623730951},"147":{"tf":1.0},"150":{"tf":1.0},"164":{"tf":1.4142135623730951},"165":{"tf":1.0},"166":{"tf":1.0},"173":{"tf":1.0},"62":{"tf":1.0},"76":{"tf":1.4142135623730951},"83":{"tf":1.0}},"df":10}},"e":{"docs":{"115":{"tf":1.0},"123":{"tf":1.0},"166":{"tf":1.0},"84":{"tf":1.7320508075688772},"87":{"tf":1.0},"91":{"tf":1.4142135623730951}},"df":6,")":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"62":{"tf":1.0}},"df":1}}}}}}},"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"107":{"tf":1.0},"53":{"tf":1.0},"64":{"tf":1.0},"81":{"tf":1.0}},"df":4}},"d":{"docs":{"101":{"tf":1.0},"109":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"127":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"199":{"tf":1.0},"28":{"tf":1.0},"3":{"tf":1.4142135623730951},"5":{"tf":1.0},"53":{"tf":1.0},"63":{"tf":1.0},"68":{"tf":1.4142135623730951},"7":{"tf":1.0},"70":{"tf":1.0},"73":{"tf":1.4142135623730951},"74":{"tf":1.0},"75":{"tf":1.4142135623730951},"83":{"tf":1.7320508075688772},"87":{"tf":1.0},"92":{"tf":2.0},"95":{"tf":1.7320508075688772}},"df":25,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"(":{"docs":{},"df":0,"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"102":{"tf":1.0}},"df":1}}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"s":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"121":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0}},"df":5}}}}}}}}}}},"p":{"docs":{},"df":0,"e":{"docs":{"101":{"tf":1.4142135623730951}},"df":1}}},"v":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0}},"df":1}}}}}}}},"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"163":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"r":{"docs":{"2":{"tf":1.4142135623730951}},"df":1}},"i":{"docs":{"104":{"tf":1.0},"115":{"tf":1.0}},"df":2},"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"j":{"docs":{"62":{"tf":1.4142135623730951}},"df":1}}}},"l":{"docs":{"112":{"tf":1.0},"119":{"tf":1.0},"128":{"tf":1.0},"130":{"tf":1.0},"138":{"tf":1.0},"165":{"tf":1.0},"30":{"tf":1.0},"32":{"tf":1.0},"63":{"tf":1.0},"65":{"tf":1.0},"81":{"tf":1.0},"87":{"tf":1.4142135623730951},"94":{"tf":1.0}},"df":13,"l":{"docs":{},"df":0,"i":{"docs":{"101":{"tf":1.4142135623730951},"125":{"tf":1.0},"62":{"tf":1.0},"75":{"tf":1.0}},"df":4},"o":{"docs":{},"df":0,"c":{"docs":{"134":{"tf":1.4142135623730951},"137":{"tf":1.0},"138":{"tf":1.7320508075688772}},"df":3}}}},"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"103":{"tf":1.0},"115":{"tf":1.0},"123":{"tf":1.4142135623730951},"137":{"tf":1.0},"60":{"tf":1.0},"67":{"tf":1.0},"7":{"tf":1.0},"84":{"tf":1.4142135623730951}},"df":8}}}},"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{"175":{"tf":1.0}},"df":1}}}}},"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"i":{"docs":{},"df":0,"v":{"docs":{"200":{"tf":1.0},"201":{"tf":1.0},"76":{"tf":1.0}},"df":3}},"n":{"docs":{},"df":0,"t":{"docs":{"19":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"141":{"tf":1.0},"171":{"tf":1.0},"173":{"tf":1.0},"187":{"tf":1.0},"19":{"tf":1.0},"190":{"tf":1.0},"70":{"tf":1.0}},"df":7}}}}},"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"155":{"tf":1.0}},"df":1}}}}}}}},"d":{"docs":{"77":{"tf":1.7320508075688772}},"df":1,"u":{"docs":{},"df":0,"c":{"docs":{"103":{"tf":1.0},"128":{"tf":1.0},"137":{"tf":1.0},"154":{"tf":1.0},"190":{"tf":1.0},"26":{"tf":1.0}},"df":6,"t":{"docs":{"188":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"80":{"tf":1.7320508075688772}},"df":1},"t":{"docs":{"80":{"tf":1.7320508075688772}},"df":1}}}}}},"x":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"142":{"tf":1.4142135623730951},"147":{"tf":1.4142135623730951}},"df":2}}}}}},"f":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"126":{"tf":1.4142135623730951},"127":{"tf":2.8284271247461903},"128":{"tf":1.0}},"df":3}}},"e":{"docs":{},"df":0,"r":{"docs":{"101":{"tf":1.7320508075688772},"102":{"tf":1.0},"112":{"tf":1.0},"122":{"tf":1.4142135623730951},"126":{"tf":1.4142135623730951},"127":{"tf":2.449489742783178},"128":{"tf":1.0},"158":{"tf":1.4142135623730951},"164":{"tf":2.23606797749979},"166":{"tf":1.7320508075688772},"173":{"tf":1.0},"174":{"tf":1.0},"176":{"tf":1.0},"196":{"tf":1.0},"66":{"tf":1.4142135623730951},"67":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"71":{"tf":1.0},"80":{"tf":1.0},"84":{"tf":1.0},"90":{"tf":1.4142135623730951},"93":{"tf":1.0},"95":{"tf":1.0},"96":{"tf":1.0},"98":{"tf":1.0}},"df":26}},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"134":{"tf":1.0},"62":{"tf":1.0}},"df":2}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{"62":{"tf":1.0},"67":{"tf":1.0}},"df":2}}}}},"g":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"114":{"tf":1.0}},"df":1,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"147":{"tf":1.0},"21":{"tf":1.0}},"df":2}}}}}}},"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"133":{"tf":1.0},"61":{"tf":1.7320508075688772},"66":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"87":{"tf":1.0}},"df":6}},"s":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.7320508075688772},"108":{"tf":1.0},"112":{"tf":1.7320508075688772},"117":{"tf":1.0},"142":{"tf":1.0},"144":{"tf":1.0},"147":{"tf":1.4142135623730951},"164":{"tf":1.4142135623730951},"165":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.0},"28":{"tf":1.4142135623730951},"32":{"tf":1.0},"69":{"tf":1.7320508075688772},"72":{"tf":1.4142135623730951},"73":{"tf":1.4142135623730951},"74":{"tf":1.7320508075688772},"75":{"tf":1.7320508075688772},"83":{"tf":1.7320508075688772},"88":{"tf":1.4142135623730951},"90":{"tf":2.23606797749979},"91":{"tf":1.0},"92":{"tf":1.0}},"df":24,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"93":{"tf":1.7320508075688772}},"df":1}}}}}}},"r":{"docs":{},"df":0,"y":{"docs":{},"df":0,"/":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{"64":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"128":{"tf":1.0},"130":{"tf":1.0},"160":{"tf":1.0},"180":{"tf":1.0}},"df":4,"l":{"docs":{},"df":0,"i":{"docs":{"120":{"tf":1.0}},"df":1}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"115":{"tf":1.0}},"df":1}}}}}},"l":{"docs":{"177":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"t":{"docs":{"191":{"tf":1.0}},"df":1},"x":{"docs":{"124":{"tf":1.0}},"df":1}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"126":{"tf":2.0},"146":{"tf":1.0},"159":{"tf":1.0},"187":{"tf":1.4142135623730951},"189":{"tf":1.4142135623730951},"190":{"tf":1.0},"50":{"tf":1.0},"53":{"tf":1.0},"62":{"tf":1.7320508075688772},"63":{"tf":1.4142135623730951},"78":{"tf":1.7320508075688772},"81":{"tf":1.0},"83":{"tf":1.0}},"df":13}},"v":{"docs":{"188":{"tf":1.0},"80":{"tf":1.0},"9":{"tf":1.0}},"df":3}},"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"35":{"tf":1.0},"95":{"tf":1.0}},"df":2}}}},"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"44":{"tf":1.4142135623730951},"90":{"tf":1.0}},"df":2,"_":{"docs":{},"df":0,"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"u":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}},"c":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"135":{"tf":1.0},"137":{"tf":1.0}},"df":2}}}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"127":{"tf":1.0},"65":{"tf":1.0},"87":{"tf":1.4142135623730951}},"df":3}}},"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"b":{"docs":{"67":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"t":{"docs":{"19":{"tf":1.0},"31":{"tf":1.0},"64":{"tf":2.23606797749979},"68":{"tf":2.23606797749979}},"df":4},"v":{"docs":{"158":{"tf":1.4142135623730951},"63":{"tf":1.0},"67":{"tf":1.0},"86":{"tf":1.0}},"df":4}}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"78":{"tf":1.0}},"df":1}},"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"112":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"124":{"tf":1.0}},"df":1}}}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"163":{"tf":1.0}},"df":1}}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{"126":{"tf":1.0},"127":{"tf":1.0},"55":{"tf":1.0},"63":{"tf":1.0}},"df":4,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"99":{"tf":1.0}},"df":1}}}}}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"137":{"tf":1.0},"53":{"tf":1.0},"62":{"tf":1.0},"68":{"tf":1.0},"8":{"tf":1.0}},"df":5}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"58":{"tf":1.0},"6":{"tf":1.4142135623730951},"8":{"tf":1.0}},"df":3}}}}}}},"r":{"docs":{"166":{"tf":1.0}},"df":1,"(":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{},"df":0,"(":{"docs":{},"df":0,"4":{"docs":{},"df":0,"0":{"docs":{},"df":0,"9":{"docs":{},"df":0,"6":{"docs":{"166":{"tf":1.0}},"df":1}}}},"n":{"docs":{"166":{"tf":2.0}},"df":1}}}}}}},"c":{"docs":{"166":{"tf":2.0},"173":{"tf":1.7320508075688772},"91":{"tf":1.4142135623730951},"92":{"tf":1.0},"93":{"tf":1.0}},"df":5},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"166":{"tf":2.449489742783178}},"df":1}}}}},"e":{"docs":{},"df":0,"s":{"docs":{"104":{"tf":1.4142135623730951},"105":{"tf":1.0},"106":{"tf":1.0},"91":{"tf":1.0}},"df":4,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"111":{"tf":1.0},"166":{"tf":1.4142135623730951}},"df":2}}}}}}},"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"53":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951},"8":{"tf":1.0},"84":{"tf":1.7320508075688772}},"df":4}}},"i":{"docs":{},"df":0,"r":{"docs":{"119":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":2.8284271247461903},"126":{"tf":1.0},"127":{"tf":1.0},"128":{"tf":1.0},"133":{"tf":1.0},"134":{"tf":1.0},"139":{"tf":1.4142135623730951},"14":{"tf":1.0},"146":{"tf":1.0},"15":{"tf":1.0},"150":{"tf":1.0},"155":{"tf":1.0},"159":{"tf":1.0},"161":{"tf":1.4142135623730951},"165":{"tf":1.4142135623730951},"166":{"tf":1.0},"169":{"tf":1.0},"184":{"tf":1.0},"2":{"tf":1.0},"20":{"tf":1.4142135623730951},"24":{"tf":1.0},"27":{"tf":1.0},"53":{"tf":1.0},"54":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.4142135623730951},"76":{"tf":1.7320508075688772},"77":{"tf":1.0},"80":{"tf":1.0}},"df":34}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"122":{"tf":1.0},"146":{"tf":1.0},"165":{"tf":1.4142135623730951},"62":{"tf":1.0},"64":{"tf":2.6457513110645907}},"df":5,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"125":{"tf":1.0}},"df":1}}}}}},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"83":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"+":{"docs":{},"df":0,"0":{"docs":{},"df":0,"x":{"docs":{},"df":0,"a":{"docs":{"83":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"106":{"tf":2.23606797749979},"107":{"tf":1.0},"108":{"tf":1.0}},"df":3}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{"108":{"tf":1.0},"114":{"tf":1.0},"127":{"tf":1.0},"128":{"tf":1.4142135623730951},"3":{"tf":1.4142135623730951},"5":{"tf":1.7320508075688772},"8":{"tf":1.0},"80":{"tf":1.0}},"df":8}}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"75":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{"165":{"tf":1.0},"80":{"tf":1.0},"87":{"tf":1.0}},"df":3}}}},"t":{"docs":{"157":{"tf":1.0},"180":{"tf":1.0},"183":{"tf":1.0},"99":{"tf":1.0}},"df":4,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"77":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"102":{"tf":1.0},"108":{"tf":1.0},"13":{"tf":1.0},"72":{"tf":1.0},"97":{"tf":1.0}},"df":5,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"12":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"102":{"tf":1.0},"108":{"tf":1.7320508075688772},"134":{"tf":1.4142135623730951},"136":{"tf":1.4142135623730951},"137":{"tf":1.0},"153":{"tf":1.0},"177":{"tf":1.0},"187":{"tf":1.7320508075688772},"53":{"tf":1.0},"68":{"tf":1.0},"78":{"tf":1.0},"79":{"tf":1.0},"80":{"tf":1.7320508075688772},"83":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":15,"<":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"108":{"tf":1.0}},"df":1}}}}}}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"173":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"i":{"docs":{"124":{"tf":1.0}},"df":1}},"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"n":{"docs":{"108":{"tf":2.6457513110645907},"112":{"tf":1.0},"122":{"tf":1.0},"126":{"tf":1.0},"134":{"tf":1.4142135623730951},"136":{"tf":1.4142135623730951},"146":{"tf":2.0},"153":{"tf":1.0},"38":{"tf":1.0},"73":{"tf":1.4142135623730951},"76":{"tf":1.0},"83":{"tf":1.4142135623730951}},"df":12}}}},"u":{"docs":{},"df":0,"s":{"docs":{"105":{"tf":1.0}},"df":1}},"v":{"docs":{"44":{"tf":1.4142135623730951}},"df":1,"i":{"docs":{},"df":0,"s":{"docs":{"53":{"tf":1.0},"68":{"tf":2.449489742783178}},"df":2,"i":{"docs":{},"df":0,"t":{"docs":{"7":{"tf":1.0}},"df":1}}}}}},"f":{"docs":{},"df":0,"c":{"docs":{"18":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"t":{"docs":{"189":{"tf":1.0},"20":{"tf":1.0},"52":{"tf":1.0},"61":{"tf":1.4142135623730951},"77":{"tf":1.4142135623730951},"88":{"tf":1.0},"93":{"tf":1.0}},"df":7}}},"s":{"docs":{},"df":0,"c":{"docs":{"30":{"tf":1.0},"35":{"tf":1.0}},"df":2},"e":{"docs":{"122":{"tf":1.0},"127":{"tf":1.0}},"df":2}}},"o":{"docs":{"92":{"tf":1.0},"93":{"tf":1.0}},"df":2,"<":{"docs":{},"df":0,"u":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"92":{"tf":1.0},"93":{"tf":1.0}},"df":2}}}},"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"35":{"tf":1.0}},"df":1}}}},"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{"188":{"tf":1.4142135623730951},"62":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951}},"df":3}}}},"l":{"docs":{},"df":0,"e":{"docs":{"119":{"tf":1.0}},"df":1}},"m":{"docs":{"12":{"tf":1.0},"187":{"tf":1.0},"189":{"tf":1.0},"86":{"tf":1.4142135623730951},"87":{"tf":1.4142135623730951}},"df":5},"o":{"docs":{},"df":0,"m":{"docs":{"110":{"tf":1.0}},"df":1},"t":{"docs":{"147":{"tf":1.0},"178":{"tf":1.0},"191":{"tf":1.4142135623730951},"44":{"tf":1.7320508075688772},"53":{"tf":1.4142135623730951},"61":{"tf":1.0},"68":{"tf":1.4142135623730951}},"df":7}},"s":{"docs":{},"df":0,"e":{"docs":{"77":{"tf":1.7320508075688772}},"df":1}},"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"183":{"tf":1.0},"81":{"tf":1.0}},"df":2}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"114":{"tf":1.0},"69":{"tf":1.0},"71":{"tf":1.0}},"df":3}}}},"w":{"docs":{"11":{"tf":1.0}},"df":1}},"s":{"docs":{"24":{"tf":1.4142135623730951},"26":{"tf":1.7320508075688772},"29":{"tf":1.0},"33":{"tf":1.4142135623730951}},"df":4,"/":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{"57":{"tf":1.0}},"df":1}}},"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"m":{"docs":{},"df":0,"t":{"docs":{},"df":0,".":{"docs":{},"df":0,"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"63":{"tf":1.0}},"df":1}}}}}}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"/":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"v":{"docs":{},"df":0,"7":{"docs":{},"df":0,"m":{"docs":{"63":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"2":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"5":{"tf":1.0}},"df":1}}}},"t":{"docs":{"188":{"tf":1.7320508075688772},"60":{"tf":1.0},"64":{"tf":1.4142135623730951},"67":{"tf":1.0},"76":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":1.0},"82":{"tf":1.0},"84":{"tf":1.0}},"df":9,"i":{"docs":{},"df":0,"c":{"docs":{"100":{"tf":1.4142135623730951},"128":{"tf":1.4142135623730951}},"df":2,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{},"df":0,"(":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"100":{"tf":1.0}},"df":1}}}}}}}}}}}}},"o":{"docs":{"130":{"tf":1.7320508075688772},"170":{"tf":1.7320508075688772}},"df":2,"s":{"docs":{},"df":0,"s":{"docs":{"130":{"tf":1.0}},"df":1}}},"t":{"docs":{"63":{"tf":1.7320508075688772}},"df":1}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{"109":{"tf":1.0},"173":{"tf":1.0},"44":{"tf":1.7320508075688772},"53":{"tf":1.0},"96":{"tf":1.0}},"df":5}},"n":{"docs":{"120":{"tf":1.4142135623730951},"121":{"tf":1.0},"123":{"tf":1.0},"128":{"tf":1.0},"130":{"tf":1.0},"136":{"tf":1.0},"14":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"177":{"tf":1.0},"189":{"tf":1.0},"19":{"tf":1.0},"191":{"tf":1.0},"194":{"tf":1.0},"22":{"tf":1.0},"31":{"tf":1.0},"4":{"tf":1.0},"44":{"tf":1.0},"53":{"tf":1.4142135623730951},"60":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":3.4641016151377544},"64":{"tf":2.23606797749979},"67":{"tf":2.0},"68":{"tf":3.0},"76":{"tf":1.0},"77":{"tf":3.0},"79":{"tf":1.4142135623730951},"81":{"tf":2.449489742783178},"83":{"tf":1.0}},"df":30,"_":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"k":{"docs":{"165":{"tf":1.4142135623730951}},"df":1}}}}},"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"63":{"tf":2.0},"68":{"tf":2.449489742783178}},"df":2}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"102":{"tf":1.0},"103":{"tf":1.0},"108":{"tf":1.4142135623730951},"110":{"tf":1.4142135623730951},"111":{"tf":1.0},"112":{"tf":1.0},"113":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.4142135623730951},"137":{"tf":1.0},"138":{"tf":1.4142135623730951},"15":{"tf":1.7320508075688772},"154":{"tf":1.0},"61":{"tf":1.0},"78":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0},"99":{"tf":1.0}},"df":18}}}},"s":{"docs":{},"df":0,"t":{"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.7320508075688772},"101":{"tf":1.0},"104":{"tf":1.0},"105":{"tf":1.0},"107":{"tf":1.0},"114":{"tf":1.0},"120":{"tf":1.0},"122":{"tf":1.4142135623730951},"125":{"tf":2.23606797749979},"126":{"tf":1.7320508075688772},"129":{"tf":1.0},"130":{"tf":1.4142135623730951},"133":{"tf":1.0},"136":{"tf":1.0},"139":{"tf":1.0},"14":{"tf":1.0},"140":{"tf":1.0},"141":{"tf":1.4142135623730951},"142":{"tf":1.0},"151":{"tf":1.0},"156":{"tf":1.4142135623730951},"157":{"tf":1.0},"158":{"tf":1.7320508075688772},"159":{"tf":1.7320508075688772},"160":{"tf":2.8284271247461903},"161":{"tf":1.4142135623730951},"162":{"tf":1.0},"163":{"tf":1.4142135623730951},"164":{"tf":2.0},"165":{"tf":1.4142135623730951},"166":{"tf":1.7320508075688772},"167":{"tf":2.0},"168":{"tf":2.0},"169":{"tf":1.0},"170":{"tf":1.7320508075688772},"171":{"tf":2.23606797749979},"172":{"tf":2.23606797749979},"173":{"tf":2.23606797749979},"174":{"tf":1.7320508075688772},"175":{"tf":1.7320508075688772},"176":{"tf":1.0},"177":{"tf":1.0},"178":{"tf":1.0},"179":{"tf":2.0},"180":{"tf":1.0},"181":{"tf":1.4142135623730951},"182":{"tf":1.7320508075688772},"183":{"tf":1.7320508075688772},"184":{"tf":2.23606797749979},"19":{"tf":1.0},"190":{"tf":1.0},"2":{"tf":2.0},"20":{"tf":1.0},"21":{"tf":1.0},"24":{"tf":1.0},"26":{"tf":1.4142135623730951},"29":{"tf":1.4142135623730951},"3":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.4142135623730951},"33":{"tf":1.0},"4":{"tf":1.7320508075688772},"5":{"tf":3.605551275463989},"56":{"tf":1.4142135623730951},"60":{"tf":1.4142135623730951},"61":{"tf":1.4142135623730951},"63":{"tf":1.0},"69":{"tf":1.0},"70":{"tf":1.0},"72":{"tf":1.0},"78":{"tf":1.7320508075688772},"80":{"tf":1.0},"88":{"tf":1.0},"91":{"tf":1.7320508075688772},"92":{"tf":1.0},"94":{"tf":1.0},"96":{"tf":1.0},"98":{"tf":1.0}},"df":79,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"e":{"docs":{},"df":0,"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"_":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"68":{"tf":1.0},"78":{"tf":1.0}},"df":2}}}}}}}}}}}},"f":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"183":{"tf":1.0},"184":{"tf":1.7320508075688772}},"df":2}}}}}},"c":{"docs":{"186":{"tf":1.0},"189":{"tf":1.0},"190":{"tf":1.0},"21":{"tf":1.0},"38":{"tf":1.7320508075688772},"62":{"tf":1.0}},"df":6},"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"g":{"docs":{"190":{"tf":1.4142135623730951}},"df":1}}}},"i":{"docs":{"24":{"tf":1.0},"33":{"tf":1.4142135623730951}},"df":2},"u":{"docs":{},"df":0,"p":{"docs":{"21":{"tf":1.0},"38":{"tf":2.8284271247461903},"39":{"tf":1.0},"61":{"tf":1.0},"67":{"tf":1.0}},"df":5}},"’":{"docs":{"103":{"tf":1.0},"109":{"tf":1.0},"164":{"tf":1.0},"173":{"tf":1.0},"5":{"tf":1.0}},"df":5}}}},"v":{"docs":{},"df":0,"r":{"docs":{"91":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0}},"df":3}},"w":{"docs":{},"df":0,"<":{"docs":{},"df":0,"u":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"92":{"tf":1.7320508075688772},"93":{"tf":1.7320508075688772}},"df":2}}}}}},"s":{"docs":{"174":{"tf":1.0},"190":{"tf":2.0},"43":{"tf":1.0},"64":{"tf":1.4142135623730951}},"df":4,"a":{"docs":{"9":{"tf":1.4142135623730951}},"df":1,"f":{"docs":{},"df":0,"e":{"docs":{"122":{"tf":1.0},"124":{"tf":1.7320508075688772},"125":{"tf":2.6457513110645907},"126":{"tf":2.449489742783178},"127":{"tf":2.0},"128":{"tf":1.0},"133":{"tf":1.0},"136":{"tf":1.0},"165":{"tf":1.0},"64":{"tf":1.0},"80":{"tf":2.0},"84":{"tf":1.4142135623730951},"92":{"tf":1.0},"93":{"tf":1.4142135623730951}},"df":14,"r":{"docs":{"168":{"tf":1.0}},"df":1},"t":{"docs":{},"df":0,"i":{"docs":{"1":{"tf":1.0},"120":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.0},"163":{"tf":1.0},"78":{"tf":1.4142135623730951}},"df":6}}}},"m":{"docs":{},"df":0,"e":{"docs":{"101":{"tf":1.0},"112":{"tf":1.0},"120":{"tf":1.0},"123":{"tf":1.4142135623730951},"125":{"tf":1.0},"131":{"tf":1.0},"133":{"tf":1.0},"139":{"tf":1.0},"148":{"tf":1.0},"155":{"tf":1.4142135623730951},"160":{"tf":1.4142135623730951},"164":{"tf":1.0},"165":{"tf":1.0},"173":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951},"61":{"tf":1.0},"65":{"tf":1.0},"67":{"tf":1.0},"69":{"tf":1.0},"7":{"tf":1.4142135623730951},"72":{"tf":1.0},"80":{"tf":1.7320508075688772},"84":{"tf":1.4142135623730951},"86":{"tf":1.0},"88":{"tf":1.0},"9":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0}},"df":29},"p":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0},"68":{"tf":1.0},"9":{"tf":1.0}},"df":3}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"125":{"tf":1.0}},"df":1}}}}}},"i":{"docs":{"101":{"tf":1.0},"126":{"tf":1.0}},"df":2}}}}},"v":{"docs":{},"df":0,"e":{"docs":{"86":{"tf":1.0}},"df":1}},"w":{"docs":{"127":{"tf":1.0},"131":{"tf":1.0}},"df":2}},"c":{"docs":{"76":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,".":{"docs":{},"df":0,"f":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"z":{"docs":{"76":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"76":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"80":{"tf":1.0}},"df":1}}}}}},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{"128":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"126":{"tf":1.0},"127":{"tf":1.0},"131":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"75":{"tf":1.0}},"df":6}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"67":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"161":{"tf":2.23606797749979},"175":{"tf":1.0},"176":{"tf":1.4142135623730951},"178":{"tf":1.0},"20":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0}},"df":7}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"155":{"tf":1.7320508075688772}},"df":1,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"s":{"docs":{"155":{"tf":3.1622776601683795}},"df":1}}}}}},"m":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"29":{"tf":1.0}},"df":1,"l":{"docs":{},"df":0,"i":{"docs":{"36":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"78":{"tf":1.0}},"df":1}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"11":{"tf":1.0},"122":{"tf":1.4142135623730951},"134":{"tf":1.0},"59":{"tf":1.0},"67":{"tf":1.0},"81":{"tf":1.4142135623730951},"88":{"tf":1.4142135623730951},"93":{"tf":1.0}},"df":8}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"11":{"tf":1.0},"123":{"tf":3.0},"125":{"tf":2.23606797749979},"126":{"tf":2.0},"127":{"tf":1.7320508075688772},"128":{"tf":1.0},"131":{"tf":1.0},"132":{"tf":1.0},"133":{"tf":1.4142135623730951},"157":{"tf":1.0},"186":{"tf":1.0},"188":{"tf":1.4142135623730951},"3":{"tf":1.4142135623730951},"44":{"tf":1.0},"47":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":1.7320508075688772},"54":{"tf":1.7320508075688772},"55":{"tf":1.0},"61":{"tf":2.23606797749979},"62":{"tf":3.1622776601683795},"64":{"tf":1.0},"65":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":3.0},"71":{"tf":1.0},"77":{"tf":1.4142135623730951},"8":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":1.0},"87":{"tf":1.0}},"df":32}}}},"u":{"docs":{},"df":0,"r":{"docs":{"17":{"tf":1.0}},"df":1}}},"e":{"docs":{"1":{"tf":1.0},"102":{"tf":1.0},"103":{"tf":1.0},"109":{"tf":1.0},"115":{"tf":1.0},"122":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"134":{"tf":1.0},"160":{"tf":1.0},"163":{"tf":1.0},"165":{"tf":1.4142135623730951},"188":{"tf":1.4142135623730951},"189":{"tf":1.0},"190":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"196":{"tf":1.0},"197":{"tf":1.0},"198":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":1.0},"53":{"tf":1.0},"55":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.7320508075688772},"68":{"tf":1.4142135623730951},"69":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.4142135623730951},"86":{"tf":1.0},"90":{"tf":1.0}},"df":38,"n":{"docs":{"103":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0}},"df":3}},"g":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"35":{"tf":1.0}},"df":1}}},"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"87":{"tf":1.0}},"df":1}}}}},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.4142135623730951},"157":{"tf":1.0},"158":{"tf":1.0},"161":{"tf":1.0},"53":{"tf":1.7320508075688772},"55":{"tf":1.0},"68":{"tf":1.7320508075688772},"76":{"tf":1.0},"86":{"tf":1.0}},"df":9}}},"f":{"docs":{"101":{"tf":1.4142135623730951},"104":{"tf":2.0},"107":{"tf":2.0},"108":{"tf":2.0},"109":{"tf":1.0},"133":{"tf":1.0},"146":{"tf":1.0},"155":{"tf":2.0},"93":{"tf":1.4142135623730951},"99":{"tf":1.0}},"df":10,"(":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{"146":{"tf":1.0}},"df":1}}}}}}},".":{"docs":{},"df":0,"0":{"docs":{"146":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"125":{"tf":1.4142135623730951}},"df":1}}}}},"a":{"docs":{"104":{"tf":1.4142135623730951}},"df":1},"b":{"docs":{"104":{"tf":1.4142135623730951}},"df":1},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"133":{"tf":1.0}},"df":1}}},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,".":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}},"p":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"v":{"docs":{},"df":0,"r":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}}},"r":{"docs":{},"df":0,"v":{"docs":{},"df":0,"r":{"docs":{},"df":0,".":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"u":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}},"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{"109":{"tf":2.449489742783178},"112":{"tf":1.0}},"df":2,".":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"y":{"docs":{},"df":0,"(":{"docs":{},"df":0,"|":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{"107":{"tf":2.0},"108":{"tf":1.7320508075688772},"109":{"tf":2.6457513110645907},"112":{"tf":1.0}},"df":4}},"r":{"docs":{"108":{"tf":1.0}},"df":1}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"108":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"108":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"108":{"tf":2.0}},"df":1}}}}}}}}}}}}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0}},"df":1}}}}}}}}}}}}},".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{"154":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"99":{"tf":1.0}},"df":1}}}}}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"80":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"36":{"tf":1.0}},"df":1}}}}}}}}},"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"63":{"tf":2.8284271247461903},"64":{"tf":1.0},"68":{"tf":2.8284271247461903},"77":{"tf":4.0},"78":{"tf":1.4142135623730951},"79":{"tf":1.4142135623730951},"81":{"tf":1.4142135623730951}},"df":7}}}}}},"n":{"docs":{},"df":0,"d":{"docs":{"103":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"88":{"tf":2.0}},"df":6},"s":{"docs":{"107":{"tf":1.0},"187":{"tf":1.0}},"df":2,"i":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.0},"151":{"tf":1.0}},"df":2}},"o":{"docs":{},"df":0,"r":{"docs":{"118":{"tf":1.0},"86":{"tf":1.0}},"df":2}}}},"p":{"docs":{"44":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"r":{"docs":{"125":{"tf":1.0},"53":{"tf":1.0},"56":{"tf":1.0},"68":{"tf":1.0}},"df":4}}},"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"151":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"g":{"docs":{"101":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"i":{"docs":{"34":{"tf":1.0},"69":{"tf":1.4142135623730951},"86":{"tf":1.0}},"df":3,"a":{"docs":{},"df":0,"l":{"docs":{"103":{"tf":1.0},"115":{"tf":1.0},"198":{"tf":1.0},"27":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0},"69":{"tf":1.0},"76":{"tf":2.0},"88":{"tf":1.4142135623730951},"99":{"tf":1.4142135623730951}},"df":10,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"0":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}},"_":{"docs":{},"df":0,"1":{"docs":{"101":{"tf":1.0},"99":{"tf":1.0}},"df":2,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"101":{"tf":1.0}},"df":1}}}}}}}}}},"2":{"docs":{"99":{"tf":1.0}},"df":1}},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"101":{"tf":1.7320508075688772},"98":{"tf":1.4142135623730951},"99":{"tf":1.7320508075688772}},"df":3,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"101":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}},"v":{"docs":{"2":{"tf":1.0},"68":{"tf":1.0},"88":{"tf":1.0}},"df":3,"e":{"docs":{},"df":0,"r":{"docs":{"31":{"tf":1.0},"64":{"tf":1.4142135623730951},"68":{"tf":1.0}},"df":3}},"i":{"docs":{},"df":0,"c":{"docs":{"82":{"tf":1.7320508075688772}},"df":1}}}},"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"53":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":2.0},"77":{"tf":1.7320508075688772}},"df":5}}}}},"t":{"docs":{"102":{"tf":1.0},"103":{"tf":1.0},"106":{"tf":1.0},"107":{"tf":3.1622776601683795},"108":{"tf":3.0},"109":{"tf":1.0},"110":{"tf":1.4142135623730951},"114":{"tf":1.0},"115":{"tf":1.0},"118":{"tf":1.4142135623730951},"122":{"tf":1.0},"127":{"tf":2.23606797749979},"132":{"tf":1.0},"137":{"tf":1.0},"139":{"tf":1.0},"141":{"tf":1.0},"15":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"166":{"tf":1.4142135623730951},"180":{"tf":1.0},"184":{"tf":1.0},"190":{"tf":1.0},"2":{"tf":1.0},"20":{"tf":1.0},"28":{"tf":1.4142135623730951},"32":{"tf":1.0},"53":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.4142135623730951},"69":{"tf":1.0},"72":{"tf":1.0},"74":{"tf":1.4142135623730951},"76":{"tf":1.7320508075688772},"77":{"tf":1.0},"80":{"tf":1.0},"84":{"tf":1.0}},"df":40,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}},"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}}}}}},"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"109":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}}}}}}}}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0}},"df":1}}}}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"108":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"93":{"tf":1.0}},"df":1,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}}}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"1":{"docs":{},"df":0,"h":{"docs":{},"df":0,"z":{"docs":{"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0}},"df":6}}}}}}}}}},"u":{"docs":{},"df":0,"p":{"docs":{"134":{"tf":1.0},"27":{"tf":1.0},"29":{"tf":1.0},"64":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":5,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"121":{"tf":1.0}},"df":1}}}}}}}},"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"102":{"tf":1.0}},"df":1}}}}}}}}}}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"19":{"tf":1.0},"5":{"tf":1.0},"56":{"tf":1.0},"77":{"tf":1.0}},"df":4}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"11":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"e":{"docs":{"121":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.0},"127":{"tf":2.0},"128":{"tf":1.4142135623730951},"2":{"tf":1.0},"21":{"tf":1.0},"80":{"tf":1.0},"95":{"tf":1.0}},"df":11}}},"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"66":{"tf":1.0},"90":{"tf":1.0}},"df":2}},"l":{"docs":{},"df":0,"l":{"docs":{"177":{"tf":1.0},"64":{"tf":1.0}},"df":2}}},"i":{"docs":{},"df":0,"p":{"docs":{"132":{"tf":1.0},"133":{"tf":1.0},"21":{"tf":1.0}},"df":3}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"126":{"tf":1.0},"128":{"tf":1.0}},"df":2}},"w":{"docs":{"127":{"tf":1.0},"44":{"tf":1.0},"54":{"tf":1.0},"62":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0},"75":{"tf":1.0},"83":{"tf":1.0}},"df":8,"n":{"docs":{"190":{"tf":1.0},"38":{"tf":1.0},"44":{"tf":1.0},"61":{"tf":1.0},"64":{"tf":1.0}},"df":5}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"k":{"docs":{"137":{"tf":1.0}},"df":1,"_":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"137":{"tf":1.0}},"df":1}}}}}}}}}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"k":{"docs":{"137":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"t":{"docs":{"146":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"126":{"tf":1.0}},"df":1}},"d":{"docs":{},"df":0,"e":{"docs":{"11":{"tf":1.0}},"df":1}},"g":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"11":{"tf":1.0},"122":{"tf":1.4142135623730951},"133":{"tf":1.0},"158":{"tf":1.0},"165":{"tf":3.605551275463989},"191":{"tf":1.0},"80":{"tf":1.0}},"df":7},"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"134":{"tf":1.4142135623730951},"172":{"tf":1.0},"173":{"tf":1.4142135623730951},"184":{"tf":1.0},"60":{"tf":1.0},"78":{"tf":1.0},"83":{"tf":1.0}},"df":7}}}},"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"87":{"tf":1.0}},"df":1}}}}}},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"91":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"86":{"tf":1.4142135623730951}},"df":1}}}}},"m":{"docs":{},"df":0,"d":{"docs":{"16":{"tf":1.0}},"df":1},"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"123":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.4142135623730951},"168":{"tf":1.0},"173":{"tf":1.0},"84":{"tf":1.7320508075688772},"86":{"tf":1.0},"96":{"tf":1.0}},"df":8,"l":{"docs":{},"df":0,"i":{"docs":{"106":{"tf":1.0},"114":{"tf":1.0},"158":{"tf":1.0},"164":{"tf":1.0},"84":{"tf":1.0},"88":{"tf":1.0}},"df":6}}}}}},"p":{"docs":{},"df":0,"l":{"docs":{"121":{"tf":1.0},"123":{"tf":1.0},"126":{"tf":1.0},"133":{"tf":1.0},"184":{"tf":1.0},"61":{"tf":1.0},"88":{"tf":1.0},"90":{"tf":1.0}},"df":8,"e":{"docs":{},"df":0,"r":{"docs":{"158":{"tf":1.0},"160":{"tf":1.0}},"df":2},"s":{"docs":{},"df":0,"t":{"docs":{"121":{"tf":1.0},"178":{"tf":1.0}},"df":2}}},"i":{"docs":{"158":{"tf":1.0},"168":{"tf":1.0},"184":{"tf":1.0},"78":{"tf":1.0}},"df":4,"c":{"docs":{"26":{"tf":1.0},"66":{"tf":1.0}},"df":2},"f":{"docs":{},"df":0,"i":{"docs":{"106":{"tf":1.0},"157":{"tf":1.0},"162":{"tf":1.0},"24":{"tf":1.0},"63":{"tf":1.0}},"df":5}}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"80":{"tf":1.0}},"df":1}}}}}},"n":{"docs":{"191":{"tf":1.0}},"df":1,"(":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,".":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}},"g":{"docs":{},"df":0,"l":{"docs":{"102":{"tf":1.0},"11":{"tf":1.4142135623730951},"112":{"tf":1.0},"114":{"tf":1.0},"121":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"131":{"tf":1.0},"133":{"tf":1.0},"151":{"tf":1.0},"178":{"tf":1.0},"196":{"tf":1.0},"2":{"tf":1.0},"66":{"tf":1.0},"68":{"tf":1.0},"74":{"tf":1.0},"76":{"tf":1.0},"78":{"tf":1.0},"86":{"tf":1.0},"99":{"tf":1.0}},"df":20,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.4142135623730951},"101":{"tf":1.4142135623730951},"127":{"tf":1.4142135623730951},"97":{"tf":1.4142135623730951}},"df":4}}}}}},"u":{"docs":{"191":{"tf":1.4142135623730951}},"df":1,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"191":{"tf":1.7320508075688772}},"df":1,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}},"t":{"docs":{"53":{"tf":1.0}},"df":1,"e":{"docs":{"199":{"tf":1.0}},"df":1},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"164":{"tf":1.0}},"df":1}}}},"z":{"docs":{},"df":0,"e":{"docs":{"112":{"tf":1.0},"113":{"tf":1.0},"123":{"tf":1.0},"133":{"tf":1.7320508075688772},"137":{"tf":2.0},"142":{"tf":1.0},"151":{"tf":1.0},"153":{"tf":1.0},"157":{"tf":1.0},"159":{"tf":1.0},"173":{"tf":1.0},"186":{"tf":1.0},"187":{"tf":1.4142135623730951},"188":{"tf":2.23606797749979},"189":{"tf":1.4142135623730951},"190":{"tf":2.23606797749979},"21":{"tf":1.0},"62":{"tf":3.0},"68":{"tf":2.8284271247461903},"78":{"tf":1.4142135623730951}},"df":20,"_":{"docs":{},"df":0,"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"<":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"111":{"tf":1.0}},"df":1}},"g":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"<":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"111":{"tf":1.0}},"df":1}}}}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"111":{"tf":1.0}},"df":1}}}}},"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"111":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}},"k":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{"64":{"tf":1.0},"68":{"tf":1.0},"92":{"tf":1.0}},"df":3}}},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{"165":{"tf":1.4142135623730951}},"df":1}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"16":{"tf":1.0}},"df":1}},"d":{"docs":{},"df":0,"e":{"docs":{"9":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"w":{"docs":{"187":{"tf":1.0},"77":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,"r":{"docs":{"163":{"tf":1.0}},"df":1}}}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{"151":{"tf":1.7320508075688772},"186":{"tf":1.0},"190":{"tf":1.0},"62":{"tf":1.0},"67":{"tf":1.0},"99":{"tf":1.4142135623730951}},"df":6,"e":{"docs":{},"df":0,"r":{"docs":{"187":{"tf":1.0},"190":{"tf":1.0}},"df":2}}}}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{"58":{"tf":1.0}},"df":1}}},"p":{"docs":{"131":{"tf":1.0}},"df":1}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"t":{"docs":{"59":{"tf":1.0},"83":{"tf":1.0}},"df":2}}}}}},"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"112":{"tf":1.0},"62":{"tf":1.0}},"df":2}}}}}},"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"t":{"docs":{},"df":0,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"102":{"tf":1.0},"103":{"tf":1.0},"114":{"tf":1.4142135623730951},"121":{"tf":1.0},"128":{"tf":1.0},"14":{"tf":1.0},"2":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.0},"27":{"tf":1.0},"28":{"tf":1.0},"72":{"tf":1.0},"80":{"tf":1.4142135623730951},"84":{"tf":1.0},"86":{"tf":1.4142135623730951},"87":{"tf":1.4142135623730951},"95":{"tf":1.4142135623730951},"97":{"tf":1.4142135623730951}},"df":18}}}}},"l":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"121":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"26":{"tf":1.0},"30":{"tf":1.0},"33":{"tf":1.0}},"df":6}},"v":{"docs":{"123":{"tf":1.0},"184":{"tf":1.0}},"df":2}},"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"4":{"docs":{},"df":0,"2":{"docs":{"133":{"tf":1.0},"134":{"tf":1.0}},"df":2}},"h":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{"127":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"99":{"tf":1.0}},"df":1}}}}}}}}}}},"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"127":{"tf":1.0}},"df":1}}},"t":{"docs":{},"df":0,"h":{"docs":{"125":{"tf":1.0},"127":{"tf":1.0},"3":{"tf":1.0},"44":{"tf":1.0},"63":{"tf":1.0},"83":{"tf":1.0},"86":{"tf":1.0},"87":{"tf":1.0}},"df":8},"i":{"docs":{},"df":0,"m":{"docs":{"119":{"tf":1.4142135623730951},"121":{"tf":1.0},"188":{"tf":1.0},"196":{"tf":1.0},"78":{"tf":1.0}},"df":5}}},"w":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"65":{"tf":1.0}},"df":1}}}}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"120":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.4142135623730951},"13":{"tf":1.0},"15":{"tf":1.0},"69":{"tf":2.0}},"df":4}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"104":{"tf":1.0},"96":{"tf":1.0}},"df":2}},"r":{"docs":{},"df":0,"c":{"docs":{"130":{"tf":1.0},"160":{"tf":1.0},"175":{"tf":1.0},"27":{"tf":1.0},"33":{"tf":1.0},"54":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.7320508075688772},"78":{"tf":1.0}},"df":11}}}},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"112":{"tf":1.0},"130":{"tf":1.0},"187":{"tf":1.0},"62":{"tf":1.0},"66":{"tf":1.0},"87":{"tf":1.7320508075688772}},"df":6}},"r":{"docs":{},"df":0,"s":{"docs":{"159":{"tf":1.0}},"df":1}},"w":{"docs":{},"df":0,"n":{"docs":{"15":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"114":{"tf":1.0},"122":{"tf":1.0},"124":{"tf":1.0},"13":{"tf":1.4142135623730951},"24":{"tf":1.0},"54":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"73":{"tf":1.0},"76":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0}},"df":12}},"f":{"docs":{"100":{"tf":1.0},"11":{"tf":1.0},"114":{"tf":1.0},"117":{"tf":1.0},"124":{"tf":1.0},"126":{"tf":1.0},"155":{"tf":1.4142135623730951},"164":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.4142135623730951},"183":{"tf":1.0},"192":{"tf":1.0},"193":{"tf":1.0},"29":{"tf":1.0},"31":{"tf":1.0},"41":{"tf":1.0},"5":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"72":{"tf":1.0},"78":{"tf":1.0},"82":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":24,"i":{"docs":{"115":{"tf":1.0},"166":{"tf":1.0},"19":{"tf":1.0},"63":{"tf":1.0},"77":{"tf":1.4142135623730951},"92":{"tf":1.0}},"df":6}}}},"e":{"docs":{},"df":0,"d":{"docs":{"117":{"tf":1.0},"189":{"tf":1.4142135623730951},"2":{"tf":1.0},"53":{"tf":2.0},"68":{"tf":2.0}},"df":5}},"n":{"docs":{},"df":0,"d":{"docs":{"86":{"tf":1.0}},"df":1}}},"i":{"docs":{"102":{"tf":1.0},"11":{"tf":1.0},"115":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.4142135623730951},"88":{"tf":1.7320508075688772}},"df":6,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"102":{"tf":1.0}},"df":1}}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"122":{"tf":1.0},"153":{"tf":1.0},"76":{"tf":1.0}},"df":3,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"153":{"tf":1.0}},"df":1}}}}}}}},"o":{"docs":{},"df":0,"t":{"docs":{"122":{"tf":1.0},"93":{"tf":1.0}},"df":2}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"93":{"tf":1.0}},"df":1}}}}},"q":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"191":{"tf":1.7320508075688772}},"df":1,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"f":{"docs":{"191":{"tf":1.0}},"df":1,"(":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"191":{"tf":1.4142135623730951}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"t":{"docs":{"191":{"tf":1.0}},"df":1}}}}}}}}},"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"/":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{"63":{"tf":1.0}},"df":1}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"/":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"/":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{"64":{"tf":1.0}},"df":1,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,"2":{"docs":{},"df":0,"5":{"docs":{},"df":0,"4":{"docs":{"64":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,".":{"docs":{},"df":0,"r":{"docs":{"60":{"tf":1.0}},"df":1,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,"1":{"docs":{},"df":0,"2":{"docs":{},"df":0,":":{"docs":{},"df":0,"1":{"docs":{},"df":0,"3":{"docs":{"79":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"t":{"docs":{"11":{"tf":1.0},"24":{"tf":1.0},"34":{"tf":1.4142135623730951},"44":{"tf":2.0},"53":{"tf":1.7320508075688772},"68":{"tf":1.4142135623730951},"69":{"tf":1.0},"77":{"tf":1.0},"93":{"tf":1.7320508075688772}},"df":9,".":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,"0":{"docs":{},"df":0,"x":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"_":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}}}}}},"1":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"93":{"tf":1.0}},"df":1}}}},"2":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"93":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"7":{"docs":{},"df":0,"2":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"5":{"docs":{},"df":0,"x":{"docs":{},"df":0,"x":{"docs":{"12":{"tf":1.0}},"df":1}}}}}}},"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"183":{"tf":1.0}},"df":1}},"l":{"docs":{"159":{"tf":1.0},"171":{"tf":1.0},"181":{"tf":1.0}},"df":3}},"c":{"docs":{},"df":0,"k":{"docs":{"134":{"tf":1.0},"137":{"tf":2.23606797749979},"15":{"tf":1.0},"17":{"tf":1.0},"187":{"tf":1.0},"5":{"tf":1.0},"61":{"tf":1.7320508075688772},"78":{"tf":1.0},"83":{"tf":1.0}},"df":9}},"g":{"docs":{},"df":0,"e":{"docs":{"16":{"tf":1.0}},"df":1}},"n":{"docs":{},"df":0,"d":{"docs":{"162":{"tf":1.0},"9":{"tf":1.0}},"df":2,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"114":{"tf":1.0},"13":{"tf":1.0},"133":{"tf":1.0},"14":{"tf":1.7320508075688772},"191":{"tf":1.7320508075688772},"20":{"tf":1.0},"30":{"tf":1.0},"60":{"tf":2.0},"62":{"tf":1.0},"70":{"tf":1.0},"78":{"tf":1.4142135623730951}},"df":11}}}}},"r":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":1.0},"106":{"tf":1.0},"127":{"tf":1.0},"133":{"tf":2.23606797749979},"156":{"tf":1.0},"188":{"tf":1.0},"5":{"tf":1.0},"55":{"tf":1.0},"56":{"tf":1.0},"62":{"tf":1.4142135623730951},"67":{"tf":1.4142135623730951},"68":{"tf":2.6457513110645907},"70":{"tf":1.7320508075688772},"77":{"tf":1.0}},"df":14,"e":{"docs":{},"df":0,"r":{"docs":{"104":{"tf":1.4142135623730951}},"df":1}},"u":{"docs":{},"df":0,"p":{"docs":{"64":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"e":{"docs":{"102":{"tf":1.0},"103":{"tf":1.4142135623730951},"104":{"tf":2.0},"105":{"tf":1.7320508075688772},"106":{"tf":1.4142135623730951},"107":{"tf":2.0},"108":{"tf":1.4142135623730951},"109":{"tf":2.0},"110":{"tf":2.0},"111":{"tf":1.4142135623730951},"112":{"tf":1.4142135623730951},"113":{"tf":1.0},"122":{"tf":1.7320508075688772},"123":{"tf":1.7320508075688772},"124":{"tf":1.7320508075688772},"125":{"tf":1.7320508075688772},"126":{"tf":2.0},"127":{"tf":2.0},"128":{"tf":1.0},"142":{"tf":1.4142135623730951},"146":{"tf":1.0},"155":{"tf":2.8284271247461903},"191":{"tf":1.0},"28":{"tf":1.0},"31":{"tf":1.0},"67":{"tf":1.0},"76":{"tf":1.4142135623730951},"81":{"tf":1.0},"83":{"tf":1.4142135623730951},"84":{"tf":1.0},"92":{"tf":1.0},"94":{"tf":1.0}},"df":32,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"158":{"tf":1.0},"160":{"tf":1.4142135623730951},"173":{"tf":1.0},"187":{"tf":1.4142135623730951},"78":{"tf":1.0},"80":{"tf":1.0}},"df":6}}}}},"i":{"docs":{},"df":0,"c":{"docs":{"100":{"tf":1.4142135623730951},"103":{"tf":1.4142135623730951},"122":{"tf":2.0},"123":{"tf":1.0},"124":{"tf":1.4142135623730951},"125":{"tf":2.6457513110645907},"126":{"tf":1.7320508075688772},"127":{"tf":2.0},"128":{"tf":1.7320508075688772},"133":{"tf":1.0},"134":{"tf":1.0},"137":{"tf":1.0},"153":{"tf":1.0},"159":{"tf":1.0},"161":{"tf":1.4142135623730951},"165":{"tf":1.0},"173":{"tf":1.0},"175":{"tf":2.0},"177":{"tf":1.0},"178":{"tf":1.7320508075688772},"180":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"76":{"tf":1.0},"80":{"tf":2.449489742783178},"81":{"tf":1.4142135623730951},"84":{"tf":1.4142135623730951},"92":{"tf":1.0},"93":{"tf":1.0},"98":{"tf":1.4142135623730951},"99":{"tf":1.0}},"df":31,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{"180":{"tf":1.0}},"df":1}}}}},"u":{"docs":{"108":{"tf":1.4142135623730951},"90":{"tf":1.0}},"df":2}},"y":{"docs":{"126":{"tf":1.0},"70":{"tf":1.0}},"df":2}},"d":{"docs":{"132":{"tf":1.4142135623730951},"133":{"tf":1.0},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"60":{"tf":1.0},"78":{"tf":1.0}},"df":6,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"168":{"tf":1.7320508075688772}},"df":1}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{"155":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"177":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"d":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"o":{"docs":{},"df":0,"f":{"docs":{"166":{"tf":1.0}},"df":1,"!":{"docs":{},"df":0,"(":{"docs":{},"df":0,"v":{"docs":{},"df":0,".":{"docs":{},"df":0,"i":{"docs":{"166":{"tf":1.0}},"df":1},"x":{"docs":{"166":{"tf":1.0}},"df":1},"z":{"docs":{"166":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}},"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{"63":{"tf":1.0},"77":{"tf":1.0}},"df":2}}},"i":{"docs":{},"df":0,"n":{"docs":{"63":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{"168":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"63":{"tf":1.0},"81":{"tf":1.4142135623730951}},"df":2,".":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0}},"df":1}}}}}},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}}}},"e":{"docs":{},"df":0,"p":{"docs":{"105":{"tf":1.0},"106":{"tf":1.7320508075688772},"174":{"tf":1.0},"175":{"tf":1.7320508075688772},"187":{"tf":1.0},"188":{"tf":1.0},"28":{"tf":1.0},"32":{"tf":1.0},"61":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.4142135623730951},"68":{"tf":2.8284271247461903},"69":{"tf":1.0},"84":{"tf":1.0}},"df":14,"i":{"docs":{"68":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{"123":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"159":{"tf":1.0},"164":{"tf":1.0},"170":{"tf":1.0},"80":{"tf":1.0},"92":{"tf":1.0}},"df":9}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"k":{"docs":{"53":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951}},"df":2}}}},"m":{"docs":{"34":{"tf":1.0}},"df":1,"3":{"docs":{},"df":0,"2":{"docs":{"34":{"tf":1.0}},"df":1,"f":{"docs":{},"df":0,"1":{"docs":{},"df":0,"0":{"docs":{},"df":0,"3":{"docs":{"11":{"tf":1.0}},"df":1}}},"3":{"docs":{"69":{"tf":1.0},"70":{"tf":1.0}},"df":2,"0":{"docs":{},"df":0,"3":{"docs":{},"df":0,"v":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"6":{"docs":{"11":{"tf":1.4142135623730951},"66":{"tf":1.0},"67":{"tf":1.0}},"df":3}}}}},"x":{"docs":{"69":{"tf":1.4142135623730951}},"df":1}},"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"38":{"tf":1.0},"44":{"tf":1.4142135623730951},"54":{"tf":1.0},"66":{"tf":1.0},"68":{"tf":1.4142135623730951},"69":{"tf":1.0},"7":{"tf":1.4142135623730951},"70":{"tf":1.0}},"df":8}}}}}}}}},"x":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}}}}}},"4":{"docs":{},"df":0,"0":{"docs":{},"df":0,"5":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"127":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},":":{"docs":{},"df":0,":":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"m":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"f":{"docs":{},"df":0,"4":{"docs":{},"df":0,"0":{"docs":{},"df":0,"5":{"docs":{"127":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}}},"8":{"docs":{"34":{"tf":1.0}},"df":1},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"11":{"tf":1.0},"34":{"tf":1.4142135623730951},"44":{"tf":1.0},"7":{"tf":1.0}},"df":4}}}}}}}}}}}}},"o":{"docs":{},"df":0,"p":{"docs":{"81":{"tf":1.0},"93":{"tf":1.0}},"df":2},"r":{"docs":{},"df":0,"e":{"docs":{"109":{"tf":1.4142135623730951},"112":{"tf":1.0},"122":{"tf":1.4142135623730951},"124":{"tf":1.4142135623730951},"127":{"tf":1.0},"134":{"tf":1.0},"137":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.0}},"df":9}}},"r":{"docs":{"168":{"tf":1.4142135623730951}},"df":1,"b":{"docs":{"62":{"tf":1.4142135623730951}},"df":1},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"26":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{"155":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"43":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"124":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"i":{"docs":{"164":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"g":{"docs":{"132":{"tf":1.0},"16":{"tf":1.0},"168":{"tf":1.7320508075688772},"62":{"tf":1.4142135623730951},"93":{"tf":1.0}},"df":5}},"p":{"docs":{"112":{"tf":1.0}},"df":1}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"105":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{"123":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"i":{"docs":{"133":{"tf":1.0}},"df":1}}}}},"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":1.4142135623730951},"107":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":3.0},"112":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"133":{"tf":1.0},"146":{"tf":1.4142135623730951},"153":{"tf":2.23606797749979},"154":{"tf":1.7320508075688772},"155":{"tf":2.8284271247461903},"166":{"tf":2.6457513110645907},"173":{"tf":2.23606797749979},"188":{"tf":1.0},"69":{"tf":1.0},"71":{"tf":1.4142135623730951},"76":{"tf":1.4142135623730951},"78":{"tf":1.0},"91":{"tf":1.7320508075688772},"92":{"tf":1.0},"93":{"tf":2.0},"99":{"tf":1.0}},"df":24,"\'":{"docs":{"166":{"tf":1.0}},"df":1},"u":{"docs":{},"df":0,"r":{"docs":{"100":{"tf":1.4142135623730951},"101":{"tf":1.4142135623730951},"105":{"tf":1.0},"107":{"tf":1.7320508075688772},"108":{"tf":1.0},"109":{"tf":1.4142135623730951},"112":{"tf":1.0},"113":{"tf":1.4142135623730951},"132":{"tf":1.0},"71":{"tf":1.0},"76":{"tf":1.7320508075688772},"91":{"tf":1.4142135623730951},"92":{"tf":1.0},"94":{"tf":1.0},"96":{"tf":1.0},"99":{"tf":2.23606797749979}},"df":16}}}}}},"u":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{"70":{"tf":1.0}},"df":1,"o":{"docs":{"24":{"tf":1.0},"26":{"tf":1.0},"29":{"tf":1.0},"39":{"tf":1.0}},"df":4,"/":{"docs":{},"df":0,"?":{"docs":{},"df":0,"s":{"docs":{},"df":0,"k":{"docs":{},"df":0,"u":{"docs":{},"df":0,"=":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,"&":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"=":{"docs":{},"df":0,"1":{"docs":{},"df":0,"6":{"docs":{"39":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}},"f":{"docs":{},"df":0,"f":{"docs":{"68":{"tf":1.0}},"df":1}}},"y":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{"78":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"b":{"docs":{"72":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.4142135623730951},"75":{"tf":1.4142135623730951}},"df":4,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"20":{"tf":1.0},"21":{"tf":1.0}},"df":2}}}}}}},"j":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"151":{"tf":1.0},"70":{"tf":1.0}},"df":2}}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"80":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"16":{"tf":1.0},"60":{"tf":1.0}},"df":2}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"55":{"tf":1.0}},"df":1}}}}}},"t":{"docs":{},"df":0,"l":{"docs":{"120":{"tf":1.0},"122":{"tf":1.0}},"df":2}}},"c":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"124":{"tf":1.0},"126":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,"d":{"docs":{"134":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"f":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"63":{"tf":1.0}},"df":1}}}}}}}}},"h":{"docs":{"0":{"tf":1.0},"11":{"tf":1.0},"114":{"tf":1.0},"115":{"tf":1.0},"117":{"tf":1.4142135623730951},"118":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":1.0},"126":{"tf":1.7320508075688772},"128":{"tf":1.0},"13":{"tf":1.0},"130":{"tf":1.0},"132":{"tf":1.0},"146":{"tf":1.0},"157":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"16":{"tf":1.0},"162":{"tf":1.0},"163":{"tf":1.0},"165":{"tf":1.0},"168":{"tf":1.4142135623730951},"169":{"tf":1.0},"170":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.4142135623730951},"176":{"tf":1.4142135623730951},"177":{"tf":1.0},"182":{"tf":1.0},"20":{"tf":1.4142135623730951},"24":{"tf":1.4142135623730951},"28":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.7320508075688772},"64":{"tf":1.0},"69":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.0},"86":{"tf":1.0},"87":{"tf":1.0}},"df":43}},"d":{"docs":{},"df":0,"o":{"docs":{"43":{"tf":2.0},"44":{"tf":1.0},"47":{"tf":1.7320508075688772},"53":{"tf":1.0}},"df":4}},"f":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"162":{"tf":1.0}},"df":1,"i":{"docs":{"124":{"tf":1.0}},"df":1}}}}},"g":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"62":{"tf":1.0}},"df":1}},"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"133":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":1.0},"7":{"tf":1.0}},"df":4}}}}},"i":{"docs":{},"df":0,"t":{"docs":{"121":{"tf":1.0},"69":{"tf":1.0}},"df":2,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"162":{"tf":1.0},"17":{"tf":1.0}},"df":2}}}}},"m":{"docs":{"163":{"tf":1.0}},"df":1,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{"125":{"tf":1.0}},"df":1}}}}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"186":{"tf":1.4142135623730951},"77":{"tf":1.4142135623730951}},"df":2}},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"11":{"tf":1.0},"124":{"tf":1.0},"129":{"tf":1.4142135623730951},"130":{"tf":1.0},"144":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"161":{"tf":1.0},"162":{"tf":1.0},"170":{"tf":1.0},"179":{"tf":1.0},"189":{"tf":1.0},"19":{"tf":1.4142135623730951},"190":{"tf":1.0},"191":{"tf":1.4142135623730951},"193":{"tf":1.0},"21":{"tf":1.4142135623730951},"24":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.4142135623730951},"32":{"tf":1.0},"34":{"tf":1.4142135623730951},"35":{"tf":1.4142135623730951},"36":{"tf":1.0},"38":{"tf":1.4142135623730951},"77":{"tf":1.0}},"df":28}}}}},"r":{"docs":{},"df":0,"e":{"docs":{"123":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"38":{"tf":1.0},"52":{"tf":1.0},"67":{"tf":1.0}},"df":7},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"86":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{"96":{"tf":1.0}},"df":1}}}}}},"v":{"docs":{},"df":0,"d":{"docs":{"197":{"tf":1.0},"72":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"84":{"tf":1.0}},"df":5,"2":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":1.0},"127":{"tf":1.4142135623730951},"147":{"tf":1.0},"197":{"tf":1.0},"72":{"tf":1.0},"84":{"tf":1.4142135623730951}},"df":8}}}}}}},"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"120":{"tf":1.0},"124":{"tf":1.0},"130":{"tf":1.0}},"df":3}},"d":{"docs":{"27":{"tf":1.0},"30":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0}},"df":5},"i":{"docs":{},"df":0,"m":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2},"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"63":{"tf":1.4142135623730951},"65":{"tf":1.0}},"df":2}}}}},"y":{"docs":{},"df":0,"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"164":{"tf":1.0},"182":{"tf":1.0},"187":{"tf":1.0},"61":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0}},"df":6}}},"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{"131":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"c":{"docs":{"103":{"tf":1.0},"125":{"tf":2.6457513110645907},"126":{"tf":1.7320508075688772},"127":{"tf":1.4142135623730951},"129":{"tf":1.0},"133":{"tf":1.0}},"df":6,"h":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"128":{"tf":1.0},"129":{"tf":1.0},"201":{"tf":1.0},"80":{"tf":1.0}},"df":4,"i":{"docs":{},"df":0,"s":{"docs":{"121":{"tf":1.0},"123":{"tf":1.4142135623730951},"126":{"tf":1.0},"130":{"tf":1.0},"131":{"tf":1.0}},"df":5}}}}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"x":{"docs":{"129":{"tf":1.0},"160":{"tf":1.4142135623730951},"176":{"tf":1.0}},"df":3}}}},"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{"76":{"tf":1.0}},"df":1,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"y":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"_":{"docs":{},"df":0,"1":{"docs":{},"df":0,"6":{"docs":{},"df":0,"m":{"docs":{},"df":0,"h":{"docs":{},"df":0,"z":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}},"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"f":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"y":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"_":{"docs":{},"df":0,"8":{"docs":{},"df":0,"0":{"docs":{},"df":0,"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"m":{"docs":{},"df":0,"h":{"docs":{},"df":0,"z":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"f":{"docs":{"117":{"tf":1.0}},"df":1},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"t":{"docs":{"13":{"tf":1.0},"78":{"tf":1.0}},"df":2}}}},"t":{"docs":{"71":{"tf":1.7320508075688772},"72":{"tf":1.0},"81":{"tf":1.0}},"df":3,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"k":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,"1":{"docs":{},"df":0,"2":{"docs":{},"df":0,"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}},"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{"90":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"r":{"docs":{"90":{"tf":1.0}},"df":1}},"v":{"docs":{},"df":0,"r":{"docs":{"90":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"v":{"docs":{},"df":0,"r":{"docs":{"90":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"m":{"docs":{"0":{"tf":1.0},"102":{"tf":1.0},"103":{"tf":1.4142135623730951},"105":{"tf":1.4142135623730951},"109":{"tf":1.0},"110":{"tf":1.0},"114":{"tf":1.7320508075688772},"117":{"tf":1.0},"119":{"tf":1.0},"12":{"tf":1.0},"120":{"tf":1.0},"123":{"tf":1.4142135623730951},"13":{"tf":1.7320508075688772},"130":{"tf":1.0},"131":{"tf":1.4142135623730951},"133":{"tf":1.0},"15":{"tf":1.0},"155":{"tf":1.0},"16":{"tf":1.0},"160":{"tf":1.7320508075688772},"161":{"tf":1.4142135623730951},"162":{"tf":1.0},"164":{"tf":1.0},"169":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.4142135623730951},"178":{"tf":1.0},"179":{"tf":1.4142135623730951},"180":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.4142135623730951},"19":{"tf":1.0},"199":{"tf":1.0},"22":{"tf":1.0},"24":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.4142135623730951},"4":{"tf":1.0},"43":{"tf":2.0},"62":{"tf":1.4142135623730951},"63":{"tf":2.449489742783178},"64":{"tf":1.7320508075688772},"68":{"tf":1.4142135623730951},"69":{"tf":1.4142135623730951},"70":{"tf":1.0},"77":{"tf":2.0},"78":{"tf":1.0},"79":{"tf":1.0},"80":{"tf":1.7320508075688772},"81":{"tf":1.7320508075688772},"83":{"tf":1.0},"86":{"tf":1.7320508075688772},"87":{"tf":1.0}},"df":57,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"93":{"tf":2.449489742783178}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"93":{"tf":1.7320508075688772}},"df":1}}}}}}}}}}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"69":{"tf":1.0},"71":{"tf":1.4142135623730951},"80":{"tf":2.0},"81":{"tf":2.0},"90":{"tf":1.0},"91":{"tf":1.7320508075688772},"92":{"tf":2.449489742783178}},"df":7,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"v":{"docs":{},"df":0,"r":{"docs":{"91":{"tf":1.0}},"df":1}}}}},".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{"71":{"tf":1.0}},"df":1}}}}}}}}},"v":{"docs":{},"df":0,"r":{"docs":{"92":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"92":{"tf":1.0}},"df":1}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"71":{"tf":1.0}},"df":1}}}}}}}}}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"71":{"tf":1.0}},"df":1}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"k":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"71":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,"1":{"docs":{},"df":0,"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"71":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}},"t":{"docs":{"126":{"tf":1.0},"165":{"tf":2.449489742783178}},"df":2,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"158":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"91":{"tf":1.0}},"df":4,"e":{"docs":{},"df":0,"—":{"docs":{},"df":0,"i":{"docs":{"84":{"tf":1.0}},"df":1}}}}},"g":{"docs":{},"df":0,"+":{"docs":{},"df":0,"=":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"44":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}},"i":{"docs":{},"df":0,"l":{"docs":{"61":{"tf":1.0},"67":{"tf":1.0},"81":{"tf":1.0}},"df":3}},"k":{"docs":{},"df":0,"e":{"docs":{"1":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":1.0},"11":{"tf":1.4142135623730951},"112":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.0},"126":{"tf":1.4142135623730951},"127":{"tf":1.0},"129":{"tf":1.0},"138":{"tf":1.0},"15":{"tf":1.0},"151":{"tf":1.0},"158":{"tf":1.0},"161":{"tf":1.0},"165":{"tf":1.0},"173":{"tf":1.0},"44":{"tf":1.0},"60":{"tf":1.0},"64":{"tf":1.0},"69":{"tf":1.0},"70":{"tf":1.0},"72":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.0},"77":{"tf":1.0},"88":{"tf":1.0}},"df":27,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"99":{"tf":1.4142135623730951}},"df":1,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"99":{"tf":1.0}},"df":1}}}}}}}}}}}},"n":{"docs":{"125":{"tf":1.0},"160":{"tf":1.0},"165":{"tf":1.0},"173":{"tf":1.0}},"df":4}}},"l":{"docs":{},"df":0,"k":{"docs":{"87":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"12":{"tf":1.0},"124":{"tf":1.0},"162":{"tf":1.4142135623730951},"171":{"tf":1.0},"177":{"tf":1.4142135623730951},"178":{"tf":1.0},"180":{"tf":1.0},"181":{"tf":1.0},"183":{"tf":1.0},"187":{"tf":1.0},"20":{"tf":1.0},"26":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"38":{"tf":3.0},"4":{"tf":1.0},"53":{"tf":1.4142135623730951},"55":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":3.605551275463989},"62":{"tf":1.0},"63":{"tf":1.4142135623730951},"64":{"tf":1.4142135623730951},"66":{"tf":1.4142135623730951},"67":{"tf":3.1622776601683795},"68":{"tf":2.6457513110645907},"84":{"tf":1.0}},"df":28,"(":{"docs":{"63":{"tf":1.0}},"df":1},".":{"docs":{},"df":0,"\'":{"docs":{},"df":0,"c":{"docs":{},"df":0,"f":{"docs":{},"df":0,"g":{"docs":{},"df":0,"(":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"(":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"190":{"tf":1.0},"68":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}}}}}},"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"v":{"docs":{},"df":0,"7":{"docs":{},"df":0,"m":{"docs":{"63":{"tf":1.0},"68":{"tf":1.0}},"df":2}}}}}}}}},"/":{"docs":{},"df":0,"$":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"/":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"/":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{"62":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"m":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"f":{"docs":{},"df":0,"3":{"docs":{},"df":0,"x":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"f":{"docs":{},"df":0,"g":{"docs":{"53":{"tf":1.7320508075688772},"68":{"tf":1.0}},"df":2}}}}}}}}}}}},"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"v":{"docs":{},"df":0,"6":{"docs":{},"df":0,"m":{"docs":{"162":{"tf":1.0}},"df":1}},"7":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{"68":{"tf":1.4142135623730951}},"df":1}},"m":{"docs":{"62":{"tf":1.0},"63":{"tf":1.7320508075688772},"64":{"tf":1.4142135623730951}},"df":3}}}}}}}}},"_":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"158":{"tf":1.0}},"df":1}}}},"o":{"docs":{"190":{"tf":1.0},"68":{"tf":1.0}},"df":2}}}}}},"s":{"docs":{},"df":0,"k":{"docs":{"128":{"tf":1.7320508075688772},"161":{"tf":1.0},"165":{"tf":1.4142135623730951},"70":{"tf":1.0},"86":{"tf":1.0}},"df":5}}},"c":{"docs":{},"df":0,"p":{"docs":{"64":{"tf":1.4142135623730951},"68":{"tf":1.0}},"df":2,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"3":{"docs":{},"df":0,"3":{"docs":{},"df":0,"3":{"docs":{},"df":0,"3":{"docs":{"64":{"tf":1.4142135623730951}},"df":1}}}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"5":{"tf":1.0}},"df":1}},"m":{"docs":{"8":{"tf":1.0}},"df":1}},"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"69":{"tf":1.0},"71":{"tf":1.0},"90":{"tf":1.0}},"df":3},"q":{"docs":{},"df":0,"u":{"docs":{"78":{"tf":1.0},"80":{"tf":1.0}},"df":2}}}}}},"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{"113":{"tf":1.0},"174":{"tf":1.0}},"df":2}}}},"l":{"docs":{},"df":0,"l":{"docs":{"125":{"tf":1.0},"162":{"tf":1.0},"166":{"tf":1.0},"180":{"tf":1.0},"183":{"tf":1.0},"44":{"tf":1.0},"63":{"tf":2.23606797749979},"64":{"tf":1.7320508075688772},"68":{"tf":1.0},"83":{"tf":1.0},"91":{"tf":1.0}},"df":11}},"m":{"docs":{},"df":0,"p":{"docs":{"75":{"tf":1.4142135623730951}},"df":1,"2":{"docs":{"75":{"tf":1.4142135623730951}},"df":1},"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"118":{"tf":1.0}},"df":1}}}}}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"190":{"tf":1.0},"20":{"tf":2.0},"40":{"tf":1.0},"56":{"tf":1.0},"57":{"tf":1.0},"59":{"tf":1.0},"61":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.4142135623730951},"77":{"tf":1.0}},"df":10}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"75":{"tf":1.0}},"df":1,"l":{"docs":{},"df":0,"i":{"docs":{"123":{"tf":1.0},"155":{"tf":1.0}},"df":2}}}}}}}}},"n":{"docs":{},"df":0,"d":{"docs":{"190":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"m":{"docs":{"12":{"tf":1.0},"189":{"tf":1.0},"192":{"tf":1.0},"9":{"tf":1.4142135623730951}},"df":4,"i":{"docs":{},"df":0,"n":{"docs":{"119":{"tf":1.0},"174":{"tf":1.0},"53":{"tf":1.0},"64":{"tf":2.0},"68":{"tf":1.7320508075688772},"77":{"tf":1.4142135623730951},"81":{"tf":1.0}},"df":7}}}},"s":{"docs":{},"df":0,"t":{"docs":{"117":{"tf":1.0},"133":{"tf":1.0},"19":{"tf":2.0},"191":{"tf":1.4142135623730951},"27":{"tf":1.0},"58":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.0}},"df":8}},"x":{"docs":{},"df":0,"a":{"docs":{"69":{"tf":1.0},"72":{"tf":1.0}},"df":2},"t":{"docs":{"160":{"tf":1.0},"188":{"tf":1.4142135623730951},"19":{"tf":1.0},"61":{"tf":1.4142135623730951},"62":{"tf":1.7320508075688772},"63":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951},"9":{"tf":1.0}},"df":8}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"k":{"docs":{"124":{"tf":1.0},"22":{"tf":1.0}},"df":2}},"t":{"docs":{},"df":0,"’":{"docs":{"127":{"tf":1.0},"131":{"tf":1.0},"132":{"tf":1.0},"184":{"tf":1.0},"188":{"tf":1.0},"47":{"tf":1.0},"52":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"64":{"tf":2.0},"71":{"tf":1.0},"72":{"tf":1.0},"8":{"tf":1.0},"91":{"tf":1.0}},"df":14,"d":{"docs":{"60":{"tf":1.0}},"df":1},"l":{"docs":{},"df":0,"l":{"docs":{"60":{"tf":1.0}},"df":1}}}}},"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"98":{"tf":1.0}},"df":1,".":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"98":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}},"m":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"v":{"docs":{"134":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"125":{"tf":1.4142135623730951},"126":{"tf":1.0},"127":{"tf":1.0},"159":{"tf":1.0}},"df":4}}},"’":{"docs":{"121":{"tf":1.4142135623730951},"187":{"tf":1.0},"188":{"tf":1.0},"189":{"tf":1.0},"50":{"tf":1.0},"66":{"tf":1.0},"71":{"tf":1.0},"75":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.0},"92":{"tf":1.4142135623730951}},"df":12,"r":{"docs":{"115":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"n":{"docs":{"69":{"tf":1.0}},"df":1,"g":{"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"156":{"tf":1.0},"165":{"tf":1.0},"192":{"tf":1.0},"2":{"tf":1.0},"53":{"tf":1.0},"63":{"tf":1.0},"73":{"tf":1.0},"76":{"tf":1.4142135623730951}},"df":10}},"r":{"docs":{},"df":0,"d":{"docs":{"63":{"tf":1.0},"92":{"tf":1.0}},"df":2}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"28":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"e":{"docs":{"115":{"tf":1.0},"188":{"tf":1.0},"20":{"tf":1.0},"3":{"tf":1.0},"44":{"tf":1.0},"53":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"78":{"tf":1.0},"84":{"tf":1.0}},"df":12}},"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"125":{"tf":1.0},"127":{"tf":1.0}},"df":2,"t":{"docs":{"106":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":2.23606797749979},"126":{"tf":2.6457513110645907},"127":{"tf":1.0},"13":{"tf":1.0},"130":{"tf":1.4142135623730951},"131":{"tf":1.4142135623730951},"15":{"tf":1.0},"78":{"tf":1.4142135623730951}},"df":11,"1":{"docs":{"93":{"tf":1.0}},"df":1},"2":{"docs":{"93":{"tf":1.0}},"df":1}}},"e":{"docs":{"116":{"tf":1.0},"117":{"tf":1.0},"189":{"tf":1.0},"68":{"tf":1.0}},"df":4},"s":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{"190":{"tf":2.449489742783178}},"df":1,"=":{"docs":{},"df":0,"1":{"docs":{},"df":0,"2":{"docs":{},"df":0,"3":{"docs":{"190":{"tf":1.0}},"df":1}}}}}}}}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"105":{"tf":1.0},"11":{"tf":1.4142135623730951},"110":{"tf":1.0},"122":{"tf":1.0},"14":{"tf":1.0},"176":{"tf":1.0},"187":{"tf":1.0},"26":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"32":{"tf":1.0},"54":{"tf":1.0},"86":{"tf":1.0},"92":{"tf":1.4142135623730951}},"df":14,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"99":{"tf":1.0}},"df":1}}}}}}}},"u":{"docs":{"136":{"tf":1.0},"80":{"tf":1.4142135623730951}},"df":2,"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"v":{"docs":{},"df":0,"6":{"docs":{"124":{"tf":1.0}},"df":1,"m":{"docs":{"162":{"tf":1.0},"38":{"tf":1.0},"61":{"tf":1.0},"67":{"tf":1.0}},"df":4}},"7":{"docs":{"124":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"m":{"docs":{"38":{"tf":1.7320508075688772},"61":{"tf":1.4142135623730951},"67":{"tf":2.0}},"df":3}},"m":{"docs":{"38":{"tf":1.0},"61":{"tf":2.23606797749979},"63":{"tf":1.0},"67":{"tf":1.0}},"df":4}},"8":{"docs":{},"df":0,"m":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"38":{"tf":1.0}},"df":1}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"38":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"76":{"tf":1.0}},"df":1,"/":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"49":{"tf":1.0}},"df":1}}}}}}}}},"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{"87":{"tf":1.0}},"df":1}}}}},"m":{"docs":{"127":{"tf":1.4142135623730951}},"df":1,".":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"1":{"docs":{},"df":0,".":{"docs":{},"df":0,"h":{"docs":{},"df":0,"z":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}}}},"2":{"docs":{"127":{"tf":1.4142135623730951}},"df":1},"e":{"docs":{"102":{"tf":1.0},"103":{"tf":1.4142135623730951},"108":{"tf":1.0},"110":{"tf":1.0},"111":{"tf":1.0},"112":{"tf":1.0},"120":{"tf":1.4142135623730951},"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.4142135623730951},"127":{"tf":2.0},"128":{"tf":1.7320508075688772},"129":{"tf":1.4142135623730951},"130":{"tf":1.4142135623730951},"138":{"tf":2.449489742783178},"151":{"tf":1.0},"154":{"tf":1.0},"157":{"tf":1.4142135623730951},"158":{"tf":1.7320508075688772},"159":{"tf":1.4142135623730951},"161":{"tf":1.4142135623730951},"164":{"tf":1.0},"166":{"tf":1.0},"173":{"tf":1.0},"175":{"tf":1.4142135623730951},"186":{"tf":1.0},"189":{"tf":1.0},"30":{"tf":1.0},"32":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.4142135623730951},"76":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.4142135623730951},"86":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.4142135623730951},"94":{"tf":1.0},"95":{"tf":1.0}},"df":42,"r":{"docs":{"11":{"tf":1.0},"119":{"tf":1.0},"122":{"tf":1.4142135623730951},"123":{"tf":1.7320508075688772},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":2.449489742783178},"130":{"tf":1.0},"146":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":1.4142135623730951},"90":{"tf":1.0}},"df":13,"(":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"0":{"docs":{"146":{"tf":1.0}},"df":1}}}}}}},"0":{"docs":{"146":{"tf":1.7320508075688772}},"df":1},"2":{"docs":{"84":{"tf":1.0}},"df":1,"a":{"docs":{"84":{"tf":1.4142135623730951}},"df":1}},"s":{"docs":{},"df":0,"/":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"n":{"docs":{"115":{"tf":1.0}},"df":1}}}}}}}}}}}}}},"p":{"docs":{"156":{"tf":1.0},"160":{"tf":1.0},"174":{"tf":1.4142135623730951},"77":{"tf":1.0}},"df":4},"v":{"docs":{},"df":0,"a":{"docs":{"69":{"tf":1.0}},"df":1}}},"l":{"docs":{},"df":0,";":{"docs":{},"df":0,"d":{"docs":{},"df":0,"r":{"docs":{"9":{"tf":1.0}},"df":1}}}},"m":{"docs":{},"df":0,"4":{"docs":{},"df":0,"c":{"docs":{},"df":0,"1":{"docs":{},"df":0,"2":{"docs":{},"df":0,"3":{"docs":{"69":{"tf":1.0},"72":{"tf":1.0}},"df":2,"x":{"docs":{"69":{"tf":1.0},"72":{"tf":1.4142135623730951},"73":{"tf":1.0},"74":{"tf":1.0}},"df":4,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"k":{"docs":{"72":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}},"_":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"76":{"tf":1.0}},"df":1,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"u":{"docs":{},"df":0,"d":{"docs":{"76":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"{":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"y":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"p":{"docs":{},"df":0,"/":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"p":{"docs":{"57":{"tf":1.0},"67":{"tf":1.0}},"df":2}}}}}},"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"86":{"tf":1.0}},"df":1}},"o":{"docs":{"155":{"tf":2.0},"61":{"tf":1.0}},"df":2}},"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"h":{"docs":{"101":{"tf":1.0},"119":{"tf":1.0},"183":{"tf":1.0}},"df":3}}}},"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"125":{"tf":1.7320508075688772}},"df":1}}},"l":{"docs":{},"df":0,"d":{"docs":{"182":{"tf":1.0},"80":{"tf":1.0}},"df":2}},"o":{"docs":{},"df":0,"k":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2},"l":{"docs":{"137":{"tf":1.0},"172":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.0},"184":{"tf":1.0},"19":{"tf":2.0},"21":{"tf":2.449489742783178},"24":{"tf":1.4142135623730951},"26":{"tf":1.0},"27":{"tf":1.0},"31":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"39":{"tf":1.4142135623730951},"45":{"tf":1.0},"49":{"tf":1.4142135623730951},"53":{"tf":1.0},"55":{"tf":1.0},"63":{"tf":1.0},"65":{"tf":1.0}},"df":20,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"19":{"tf":1.0},"21":{"tf":1.0},"30":{"tf":1.0},"61":{"tf":1.4142135623730951}},"df":4}}}}},"s":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"d":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"0":{"docs":{},"df":0,".":{"docs":{},"df":0,"1":{"docs":{},"df":0,"0":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"50":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"p":{"docs":{"147":{"tf":1.4142135623730951},"158":{"tf":1.0},"188":{"tf":2.0},"195":{"tf":1.0}},"df":4,"i":{"docs":{},"df":0,"c":{"docs":{"114":{"tf":1.0},"125":{"tf":1.0},"131":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}},"df":6}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"62":{"tf":1.0}},"df":1}}},"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"3":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"30":{"tf":1.7320508075688772},"86":{"tf":1.0}},"df":2,"3":{"docs":{},"df":0,"2":{"docs":{"30":{"tf":1.4142135623730951}},"df":1}}},"k":{"docs":{"112":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"128":{"tf":1.0},"67":{"tf":1.0},"81":{"tf":1.0},"98":{"tf":1.0}},"df":7,"e":{"docs":{},"df":0,"r":{"docs":{"169":{"tf":1.0},"170":{"tf":1.0},"8":{"tf":1.0}},"df":3}}}},"d":{"docs":{},"df":0,"e":{"docs":{"119":{"tf":1.0}},"df":1},"i":{"docs":{},"df":0,"t":{"docs":{"114":{"tf":1.0},"130":{"tf":1.0},"161":{"tf":1.0}},"df":3,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"161":{"tf":1.0}},"df":1}}}}}},"i":{"docs":{},"df":0,"t":{"docs":{"103":{"tf":1.0},"115":{"tf":2.6457513110645907},"117":{"tf":1.7320508075688772},"118":{"tf":1.7320508075688772},"125":{"tf":1.7320508075688772},"126":{"tf":1.0},"133":{"tf":1.0},"142":{"tf":1.7320508075688772},"148":{"tf":1.4142135623730951},"150":{"tf":1.0},"155":{"tf":2.449489742783178},"195":{"tf":1.0},"69":{"tf":1.0},"76":{"tf":1.7320508075688772}},"df":14}},"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"68":{"tf":1.4142135623730951}},"df":1}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"m":{"docs":{"160":{"tf":1.0},"168":{"tf":1.0},"183":{"tf":1.0},"80":{"tf":1.4142135623730951}},"df":4}}}},"i":{"docs":{},"df":0,"t":{"docs":{"105":{"tf":1.0},"109":{"tf":1.0},"110":{"tf":1.0},"122":{"tf":1.0}},"df":4}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"172":{"tf":1.4142135623730951},"173":{"tf":1.0},"6":{"tf":1.4142135623730951}},"df":3}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"76":{"tf":1.0}},"df":1,"t":{"docs":{"118":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":1.0}},"df":3}}}},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"27":{"tf":1.0},"53":{"tf":2.0},"63":{"tf":1.0},"68":{"tf":2.0}},"df":4}}}}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{"177":{"tf":1.0}},"df":1}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"103":{"tf":1.0}},"df":1}},"e":{"docs":{"106":{"tf":1.0},"158":{"tf":1.0}},"df":2}},"i":{"docs":{"103":{"tf":1.0},"110":{"tf":1.0},"137":{"tf":1.0},"139":{"tf":1.0},"187":{"tf":1.0},"190":{"tf":1.4142135623730951},"2":{"tf":1.0},"53":{"tf":1.4142135623730951},"54":{"tf":1.0},"79":{"tf":1.4142135623730951},"99":{"tf":1.0}},"df":11,"a":{"docs":{},"df":0,"l":{"docs":{"115":{"tf":1.0}},"df":1}},"c":{"docs":{},"df":0,"k":{"docs":{"187":{"tf":1.0}},"df":1,"i":{"docs":{"126":{"tf":1.0},"170":{"tf":1.0}},"df":2}}},"g":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"122":{"tf":1.0},"136":{"tf":1.0},"175":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":1.0},"83":{"tf":1.4142135623730951},"84":{"tf":1.4142135623730951}},"df":7}}}},"p":{"docs":{},"df":0,"l":{"docs":{"61":{"tf":1.4142135623730951}},"df":1}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"8":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"e":{"docs":{"100":{"tf":1.0},"131":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.4142135623730951},"187":{"tf":1.0}},"df":5},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"62":{"tf":1.4142135623730951}},"df":1}}}},"s":{"docs":{},"df":0,"t":{"docs":{"93":{"tf":1.0}},"df":1}}},"y":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"v":{"docs":{"136":{"tf":1.0}},"df":1}}}}}}}}},"t":{"docs":{},"df":0,"l":{"docs":{"5":{"tf":1.0}},"df":1}},"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{"146":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"n":{"docs":{"105":{"tf":1.0},"109":{"tf":1.0},"126":{"tf":1.0},"13":{"tf":1.0},"158":{"tf":1.0},"16":{"tf":1.0},"68":{"tf":1.0},"70":{"tf":1.0}},"df":8}},"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"55":{"tf":1.0}},"df":1}}}}},"w":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"122":{"tf":1.0}},"df":1}}},"o":{"docs":{"101":{"tf":1.4142135623730951},"104":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"123":{"tf":1.0},"131":{"tf":1.0},"132":{"tf":1.0},"134":{"tf":1.0},"160":{"tf":1.0},"166":{"tf":1.7320508075688772},"168":{"tf":1.0},"171":{"tf":1.0},"179":{"tf":1.0},"190":{"tf":1.4142135623730951},"53":{"tf":1.0},"61":{"tf":1.0},"64":{"tf":1.0},"75":{"tf":1.0},"87":{"tf":1.4142135623730951},"92":{"tf":1.0},"96":{"tf":1.0}},"df":21}},"y":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"103":{"tf":1.4142135623730951},"104":{"tf":1.0},"105":{"tf":1.7320508075688772},"109":{"tf":1.4142135623730951},"11":{"tf":1.0},"110":{"tf":1.0},"111":{"tf":1.4142135623730951},"112":{"tf":1.7320508075688772},"113":{"tf":1.0},"115":{"tf":1.4142135623730951},"117":{"tf":2.0},"118":{"tf":1.4142135623730951},"124":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.4142135623730951},"127":{"tf":1.0},"134":{"tf":1.4142135623730951},"142":{"tf":2.23606797749979},"146":{"tf":1.4142135623730951},"148":{"tf":1.4142135623730951},"150":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":2.23606797749979},"165":{"tf":1.0},"166":{"tf":2.23606797749979},"168":{"tf":3.0},"172":{"tf":1.0},"173":{"tf":2.23606797749979},"174":{"tf":1.0},"180":{"tf":1.4142135623730951},"61":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":1.0},"69":{"tf":1.0},"73":{"tf":1.0},"80":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":38,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{"173":{"tf":1.0}},"df":1}}},"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{"134":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":1.4142135623730951}},"df":1}}},"i":{"docs":{},"df":0,"c":{"docs":{"107":{"tf":1.0},"114":{"tf":1.0},"115":{"tf":1.0},"117":{"tf":1.0},"118":{"tf":1.0},"121":{"tf":1.0},"130":{"tf":1.0},"131":{"tf":1.0},"173":{"tf":1.4142135623730951},"174":{"tf":1.0},"32":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.0},"76":{"tf":1.0},"80":{"tf":1.0},"84":{"tf":1.0},"86":{"tf":1.0},"87":{"tf":1.0},"90":{"tf":1.0}},"df":19}},"o":{"docs":{"8":{"tf":1.0}},"df":1}}}},"u":{"docs":{"166":{"tf":1.4142135623730951}},"df":1,".":{"docs":{},"df":0,"i":{"docs":{"166":{"tf":1.0}},"df":1},"x":{"docs":{"166":{"tf":1.0}},"df":1},"z":{"docs":{"166":{"tf":1.0}},"df":1}},"1":{"docs":{},"df":0,"6":{"docs":{"166":{"tf":2.8284271247461903}},"df":1}},"3":{"docs":{},"df":0,"2":{"docs":{"100":{"tf":1.0},"101":{"tf":1.4142135623730951},"104":{"tf":2.0},"122":{"tf":1.0},"123":{"tf":1.0},"126":{"tf":1.0},"159":{"tf":1.0},"168":{"tf":1.7320508075688772},"80":{"tf":1.4142135623730951},"81":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.4142135623730951},"91":{"tf":2.0},"92":{"tf":1.0},"93":{"tf":1.4142135623730951}},"df":15}},"6":{"docs":{},"df":0,"4":{"docs":{"168":{"tf":1.0}},"df":1}},"8":{"docs":{"133":{"tf":1.7320508075688772},"134":{"tf":1.4142135623730951},"154":{"tf":1.4142135623730951},"166":{"tf":2.0}},"df":4},"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"5":{"tf":1.4142135623730951},"76":{"tf":1.7320508075688772}},"df":2}}},"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{"40":{"tf":1.0},"43":{"tf":1.4142135623730951}},"df":2}}}}},"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{"44":{"tf":1.0},"53":{"tf":1.0}},"df":2,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"m":{"docs":{"44":{"tf":1.0}},"df":1}}}}}},"h":{"docs":{"75":{"tf":1.0}},"df":1},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"_":{"docs":{},"df":0,"t":{"docs":{"75":{"tf":1.4142135623730951}},"df":1}}}}}}},"l":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"137":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"53":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951},"98":{"tf":1.0}},"df":3}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{"166":{"tf":1.0}},"df":1}}}}},"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"75":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"m":{"docs":{"63":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951}},"df":2},"n":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"104":{"tf":1.0},"109":{"tf":1.4142135623730951}},"df":2}}}}}}}},"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"107":{"tf":1.0},"122":{"tf":1.0},"78":{"tf":1.0},"80":{"tf":1.4142135623730951},"83":{"tf":1.0}},"df":5}}},"r":{"docs":{"117":{"tf":1.0},"147":{"tf":1.0},"164":{"tf":1.0},"28":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0},"9":{"tf":2.0}},"df":7,"l":{"docs":{},"df":0,"i":{"docs":{"108":{"tf":1.0},"164":{"tf":1.0},"76":{"tf":1.0}},"df":3}},"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"144":{"tf":1.0}},"df":1}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"160":{"tf":1.0},"183":{"tf":1.0},"192":{"tf":1.0},"77":{"tf":1.0}},"df":4}}}}}}}},"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"146":{"tf":1.0},"151":{"tf":1.0}},"df":3}}}}}},"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"5":{"tf":1.0}},"df":1}}}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{"94":{"tf":1.0}},"df":1}}}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{"68":{"tf":1.0},"82":{"tf":1.0}},"df":2}}}}},"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"166":{"tf":1.0}},"df":1}},"t":{"docs":{"117":{"tf":1.0},"188":{"tf":1.0},"194":{"tf":1.0},"87":{"tf":1.0}},"df":4},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{"200":{"tf":1.0},"201":{"tf":1.0}},"df":2}}}},"x":{"docs":{"62":{"tf":1.0}},"df":1}},"k":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"n":{"docs":{"62":{"tf":1.4142135623730951}},"df":1}}}}},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"78":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"k":{"docs":{"122":{"tf":1.0},"26":{"tf":1.0},"86":{"tf":1.0}},"df":3},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"35":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"126":{"tf":1.4142135623730951}},"df":1}}}},"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"187":{"tf":1.4142135623730951},"188":{"tf":1.0}},"df":2}}}}},"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{"44":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"189":{"tf":1.7320508075688772}},"df":1}}},"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"f":{"docs":{"101":{"tf":1.4142135623730951},"122":{"tf":2.0},"123":{"tf":1.7320508075688772},"125":{"tf":3.3166247903554},"126":{"tf":1.7320508075688772},"133":{"tf":2.0},"164":{"tf":1.0},"165":{"tf":2.23606797749979},"173":{"tf":1.0},"64":{"tf":1.0},"72":{"tf":1.7320508075688772},"80":{"tf":1.7320508075688772},"83":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":2.449489742783178},"93":{"tf":1.7320508075688772},"98":{"tf":1.4142135623730951},"99":{"tf":2.0}},"df":18,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"125":{"tf":1.0},"126":{"tf":1.4142135623730951}},"df":2,"l":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"125":{"tf":1.0}},"df":1}}},"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{},"df":0,"(":{"docs":{},"df":0,"0":{"docs":{},"df":0,"x":{"docs":{},"df":0,"2":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{},"df":0,"_":{"docs":{},"df":0,"0":{"docs":{},"df":0,"1":{"docs":{},"df":0,"0":{"docs":{},"df":0,"0":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}},"<":{"docs":{},"df":0,"u":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"125":{"tf":1.0}},"df":1}},"s":{"docs":{"133":{"tf":1.0}},"df":1}}}}}}}}}},"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{"168":{"tf":1.4142135623730951}},"df":1}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"133":{"tf":1.0}},"df":1}}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"123":{"tf":1.4142135623730951},"127":{"tf":1.0},"165":{"tf":1.4142135623730951},"71":{"tf":1.0},"77":{"tf":1.0}},"df":5}}},"u":{"docs":{},"df":0,"s":{"docs":{"158":{"tf":1.0},"78":{"tf":1.0}},"df":2}},"w":{"docs":{},"df":0,"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{"127":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"d":{"docs":{"78":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"127":{"tf":1.7320508075688772},"136":{"tf":1.0},"191":{"tf":1.0}},"df":3}}}},"z":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{"59":{"tf":1.0}},"df":1}}}},"p":{"docs":{"108":{"tf":1.0},"115":{"tf":1.0},"12":{"tf":1.0},"120":{"tf":1.0},"125":{"tf":1.0},"133":{"tf":1.0},"137":{"tf":1.0},"139":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.4142135623730951},"3":{"tf":1.4142135623730951},"64":{"tf":1.0},"68":{"tf":1.4142135623730951},"72":{"tf":1.0},"76":{"tf":2.23606797749979},"87":{"tf":1.4142135623730951},"90":{"tf":1.0},"93":{"tf":1.0},"99":{"tf":1.0}},"df":19,"/":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{},"df":0,"n":{"docs":{"72":{"tf":1.0}},"df":1}}}}},"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"67":{"tf":1.0}},"df":4}}},"f":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"134":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"n":{"docs":{"64":{"tf":1.0},"87":{"tf":1.0}},"df":2}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"87":{"tf":1.0}},"df":1}}}},"s":{"docs":{"0":{"tf":1.0},"100":{"tf":1.4142135623730951},"101":{"tf":1.0},"103":{"tf":1.7320508075688772},"104":{"tf":1.7320508075688772},"107":{"tf":1.0},"108":{"tf":1.4142135623730951},"109":{"tf":2.23606797749979},"111":{"tf":1.4142135623730951},"112":{"tf":1.0},"113":{"tf":1.4142135623730951},"115":{"tf":2.0},"117":{"tf":1.4142135623730951},"119":{"tf":1.0},"12":{"tf":1.4142135623730951},"122":{"tf":1.4142135623730951},"123":{"tf":2.0},"124":{"tf":2.0},"125":{"tf":3.0},"126":{"tf":3.3166247903554},"127":{"tf":4.358898943540674},"128":{"tf":1.7320508075688772},"129":{"tf":1.0},"130":{"tf":1.0},"131":{"tf":1.4142135623730951},"132":{"tf":1.7320508075688772},"133":{"tf":4.123105625617661},"134":{"tf":1.7320508075688772},"136":{"tf":1.7320508075688772},"137":{"tf":1.7320508075688772},"138":{"tf":1.0},"14":{"tf":1.7320508075688772},"140":{"tf":1.0},"141":{"tf":1.0},"142":{"tf":1.0},"144":{"tf":1.0},"15":{"tf":1.0},"151":{"tf":1.0},"155":{"tf":1.7320508075688772},"156":{"tf":1.4142135623730951},"157":{"tf":1.7320508075688772},"158":{"tf":2.0},"159":{"tf":1.4142135623730951},"16":{"tf":1.0},"160":{"tf":1.7320508075688772},"161":{"tf":1.7320508075688772},"162":{"tf":1.4142135623730951},"163":{"tf":1.4142135623730951},"164":{"tf":2.0},"165":{"tf":2.0},"166":{"tf":2.449489742783178},"167":{"tf":1.4142135623730951},"168":{"tf":1.0},"169":{"tf":1.0},"17":{"tf":1.7320508075688772},"170":{"tf":1.0},"171":{"tf":1.7320508075688772},"172":{"tf":1.0},"173":{"tf":2.23606797749979},"174":{"tf":2.449489742783178},"175":{"tf":1.7320508075688772},"176":{"tf":1.4142135623730951},"177":{"tf":1.4142135623730951},"178":{"tf":1.0},"179":{"tf":1.4142135623730951},"181":{"tf":1.4142135623730951},"182":{"tf":1.0},"183":{"tf":1.7320508075688772},"184":{"tf":1.4142135623730951},"187":{"tf":1.7320508075688772},"188":{"tf":1.4142135623730951},"189":{"tf":1.0},"19":{"tf":1.7320508075688772},"190":{"tf":3.0},"191":{"tf":2.23606797749979},"192":{"tf":1.0},"197":{"tf":1.0},"199":{"tf":1.0},"2":{"tf":1.7320508075688772},"20":{"tf":1.0},"21":{"tf":1.7320508075688772},"22":{"tf":1.4142135623730951},"27":{"tf":1.0},"29":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0},"34":{"tf":1.0},"38":{"tf":1.4142135623730951},"4":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"43":{"tf":1.7320508075688772},"44":{"tf":2.0},"45":{"tf":1.0},"46":{"tf":1.0},"50":{"tf":1.0},"53":{"tf":2.6457513110645907},"54":{"tf":1.4142135623730951},"55":{"tf":1.4142135623730951},"56":{"tf":1.0},"59":{"tf":1.0},"60":{"tf":3.0},"61":{"tf":1.7320508075688772},"62":{"tf":2.23606797749979},"63":{"tf":3.0},"64":{"tf":2.6457513110645907},"66":{"tf":1.4142135623730951},"67":{"tf":2.0},"68":{"tf":3.605551275463989},"69":{"tf":2.23606797749979},"7":{"tf":1.0},"70":{"tf":1.0},"71":{"tf":2.23606797749979},"72":{"tf":2.8284271247461903},"75":{"tf":1.7320508075688772},"76":{"tf":2.449489742783178},"77":{"tf":3.7416573867739413},"78":{"tf":3.605551275463989},"79":{"tf":1.7320508075688772},"80":{"tf":2.449489742783178},"81":{"tf":2.6457513110645907},"82":{"tf":1.0},"83":{"tf":2.449489742783178},"84":{"tf":2.8284271247461903},"86":{"tf":1.4142135623730951},"87":{"tf":1.7320508075688772},"88":{"tf":1.0},"9":{"tf":1.4142135623730951},"91":{"tf":1.0},"92":{"tf":1.4142135623730951},"93":{"tf":1.0},"95":{"tf":1.0},"99":{"tf":1.0}},"df":135,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"115":{"tf":1.0}},"df":1}},"g":{"docs":{"13":{"tf":1.0},"137":{"tf":2.0},"174":{"tf":1.0},"188":{"tf":1.0},"38":{"tf":1.0}},"df":5,"e":{"docs":{},"df":0,"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"62":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"t":{"docs":{"11":{"tf":1.0}},"df":1}}},"b":{"docs":{"11":{"tf":2.23606797749979},"33":{"tf":1.0},"5":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":2.0}},"df":5},"e":{"docs":{},"df":0,"r":{"docs":{"11":{"tf":1.4142135623730951},"114":{"tf":1.0},"116":{"tf":1.0},"117":{"tf":1.0},"119":{"tf":1.0},"133":{"tf":1.7320508075688772},"155":{"tf":1.0},"158":{"tf":1.4142135623730951},"160":{"tf":1.0},"44":{"tf":1.4142135623730951},"53":{"tf":1.0},"69":{"tf":1.0},"76":{"tf":1.0},"78":{"tf":1.4142135623730951},"83":{"tf":1.0},"93":{"tf":1.7320508075688772}},"df":16,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"r":{"docs":{},"df":0,"w":{"docs":{"44":{"tf":1.0}},"df":1}}},"y":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,":":{"docs":{},"df":0,"r":{"docs":{},"df":0,"w":{"docs":{"44":{"tf":1.0}},"df":1}}}}}}},"’":{"docs":{"174":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"z":{"docs":{"133":{"tf":1.0},"159":{"tf":1.0}},"df":2}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"102":{"tf":1.0},"120":{"tf":1.0},"122":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"13":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"180":{"tf":1.0},"186":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.0},"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.4142135623730951},"63":{"tf":1.0},"84":{"tf":1.0}},"df":18}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"168":{"tf":1.0},"178":{"tf":1.0}},"df":2}}}},"v":{"docs":{"166":{"tf":2.23606797749979},"30":{"tf":1.0},"35":{"tf":1.0},"38":{"tf":1.4142135623730951},"49":{"tf":1.0},"50":{"tf":1.0},"62":{"tf":1.0}},"df":7,".":{"docs":{},"df":0,"i":{"docs":{"166":{"tf":1.7320508075688772}},"df":1},"x":{"docs":{"166":{"tf":2.0}},"df":1},"z":{"docs":{"166":{"tf":1.7320508075688772}},"df":1}},"0":{"docs":{},"df":0,".":{"docs":{},"df":0,"1":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"63":{"tf":1.0}},"df":1}},"0":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"19":{"tf":1.0}},"df":1}}}},"4":{"docs":{},"df":0,".":{"docs":{},"df":0,"x":{"docs":{"134":{"tf":1.4142135623730951}},"df":1}}},"5":{"docs":{},"df":0,".":{"docs":{},"df":0,"x":{"docs":{"100":{"tf":1.0}},"df":1}}},"9":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"19":{"tf":1.0}},"df":1}}}}},"1":{"docs":{},"df":0,"5":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}},"2":{"docs":{"53":{"tf":2.449489742783178},"68":{"tf":2.0}},"df":2,".":{"docs":{},"df":0,"0":{"docs":{"9":{"tf":1.0}},"df":1},"c":{"docs":{},"df":0,"f":{"docs":{},"df":0,"g":{"docs":{"53":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951}},"df":2}}}},"7":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2}},"4":{"docs":{},"df":0,".":{"docs":{},"df":0,"0":{"docs":{"9":{"tf":1.4142135623730951}},"df":1}}},"a":{"docs":{},"df":0,"l":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2,"i":{"docs":{},"df":0,"d":{"docs":{"125":{"tf":1.0},"72":{"tf":1.0},"87":{"tf":1.0}},"df":3}},"u":{"docs":{"107":{"tf":1.4142135623730951},"108":{"tf":1.0},"112":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.4142135623730951},"127":{"tf":1.4142135623730951},"151":{"tf":1.0},"164":{"tf":1.4142135623730951},"165":{"tf":1.0},"168":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.0},"190":{"tf":1.4142135623730951},"28":{"tf":1.0},"61":{"tf":1.4142135623730951},"62":{"tf":1.7320508075688772},"72":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.4142135623730951},"80":{"tf":1.0},"81":{"tf":1.0},"82":{"tf":1.4142135623730951},"83":{"tf":2.23606797749979},"90":{"tf":1.7320508075688772}},"df":24}},"r":{"docs":{},"df":0,"i":{"docs":{"114":{"tf":1.0},"70":{"tf":1.0}},"df":2,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"122":{"tf":1.7320508075688772},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.7320508075688772},"127":{"tf":2.23606797749979},"128":{"tf":1.0},"134":{"tf":1.0},"137":{"tf":1.0},"160":{"tf":1.0},"165":{"tf":2.0},"166":{"tf":1.0},"187":{"tf":1.4142135623730951},"28":{"tf":1.0},"31":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"61":{"tf":1.7320508075688772},"62":{"tf":1.4142135623730951},"75":{"tf":1.0},"80":{"tf":2.6457513110645907},"81":{"tf":1.0},"84":{"tf":1.0},"87":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.4142135623730951},"98":{"tf":1.7320508075688772},"99":{"tf":1.0}},"df":28}},"n":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"22":{"tf":1.0},"63":{"tf":1.0}},"df":4}}},"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"11":{"tf":1.0},"156":{"tf":1.0},"157":{"tf":1.0},"160":{"tf":1.0},"31":{"tf":1.0},"36":{"tf":1.0},"84":{"tf":1.0}},"df":7}}},"o":{"docs":{},"df":0,"u":{"docs":{"117":{"tf":1.4142135623730951},"118":{"tf":1.0},"119":{"tf":1.0},"120":{"tf":1.0},"129":{"tf":1.0},"13":{"tf":1.0},"140":{"tf":1.0},"157":{"tf":1.0},"163":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.0},"28":{"tf":1.0},"30":{"tf":1.0},"35":{"tf":1.0},"69":{"tf":1.4142135623730951},"73":{"tf":1.0},"74":{"tf":1.0}},"df":17}}}}},"e":{"docs":{},"df":0,"c":{"docs":{"132":{"tf":1.0},"17":{"tf":1.0}},"df":2,".":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{"136":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"1":{"docs":{"136":{"tf":1.0}},"df":1}}}}}}}}}},":":{"docs":{},"df":0,":":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"133":{"tf":1.0},"134":{"tf":1.0}},"df":2}}}}},"<":{"docs":{},"df":0,"_":{"docs":{"134":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"134":{"tf":1.0},"189":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.0},"84":{"tf":1.0}},"df":5,"_":{"docs":{},"df":0,"t":{"docs":{"188":{"tf":1.4142135623730951},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"68":{"tf":1.4142135623730951}},"df":4}}}}}},"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"114":{"tf":1.0},"192":{"tf":1.0},"7":{"tf":1.4142135623730951},"84":{"tf":1.0}},"df":4}}}},"r":{"docs":{},"df":0,"i":{"docs":{"114":{"tf":1.0},"115":{"tf":1.0},"125":{"tf":1.4142135623730951},"151":{"tf":1.0},"157":{"tf":1.0},"159":{"tf":1.0},"163":{"tf":1.0},"184":{"tf":1.0},"72":{"tf":1.0},"8":{"tf":1.0},"91":{"tf":1.0},"94":{"tf":1.0}},"df":12,"f":{"docs":{},"df":0,"i":{"docs":{"49":{"tf":1.0},"50":{"tf":1.0},"68":{"tf":1.4142135623730951},"84":{"tf":1.0},"93":{"tf":1.0}},"df":5}}},"s":{"docs":{},"df":0,"a":{"docs":{"168":{"tf":1.0}},"df":1,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"31":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0}},"df":3}}}},"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.0},"134":{"tf":1.4142135623730951},"166":{"tf":1.0},"183":{"tf":1.0},"19":{"tf":2.6457513110645907},"21":{"tf":1.0},"38":{"tf":1.0},"46":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"62":{"tf":2.23606797749979},"64":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":2.23606797749979},"84":{"tf":1.0}},"df":17}}}}}},"i":{"docs":{},"df":0,"a":{"docs":{"114":{"tf":1.0},"117":{"tf":2.23606797749979},"118":{"tf":1.0},"119":{"tf":1.0},"127":{"tf":1.4142135623730951},"176":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"34":{"tf":1.0},"80":{"tf":1.0},"86":{"tf":1.0}},"df":11},"c":{"docs":{},"df":0,"e":{"docs":{"168":{"tf":1.0}},"df":1}},"d":{"docs":{"53":{"tf":1.0},"68":{"tf":1.0}},"df":2,"e":{"docs":{},"df":0,"o":{"docs":{"193":{"tf":1.0},"195":{"tf":1.0},"197":{"tf":1.0},"72":{"tf":1.0},"86":{"tf":1.0}},"df":5}}},"e":{"docs":{},"df":0,"w":{"docs":{"199":{"tf":1.4142135623730951}},"df":1}},"r":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"139":{"tf":1.0},"87":{"tf":1.0}},"df":2}}}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"124":{"tf":1.0},"98":{"tf":1.0}},"df":2}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"24":{"tf":1.0},"26":{"tf":1.0},"29":{"tf":1.0},"39":{"tf":1.4142135623730951}},"df":4}}}}},"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"165":{"tf":1.4142135623730951},"168":{"tf":1.0},"173":{"tf":1.0},"184":{"tf":1.0}},"df":4}},"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":2.8284271247461903},"92":{"tf":1.7320508075688772},"95":{"tf":1.0}},"df":3,"e":{"docs":{},"df":0,"_":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"92":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,":":{"docs":{},"df":0,":":{"docs":{},"df":0,"{":{"docs":{},"df":0,"r":{"docs":{},"df":0,"w":{"docs":{"92":{"tf":1.0},"93":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}}}}},"t":{"docs":{"11":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"g":{"docs":{"11":{"tf":1.0},"53":{"tf":1.0},"68":{"tf":1.0}},"df":3}}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"6":{"tf":1.0}},"df":1}}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"k":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{"86":{"tf":1.0}},"df":1}}}}}},"w":{"docs":{"107":{"tf":2.0},"108":{"tf":2.0},"109":{"tf":2.6457513110645907},"112":{"tf":1.0},"127":{"tf":1.7320508075688772},"74":{"tf":1.4142135623730951},"75":{"tf":1.7320508075688772}},"df":7,".":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"u":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"z":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"s":{"docs":{},"df":0,"(":{"docs":{},"df":0,"6":{"docs":{},"df":0,"4":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}},".":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{"109":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"n":{"docs":{"109":{"tf":1.4142135623730951}},"df":1}}}}}}}}},"g":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{},"df":0,"s":{"docs":{},"df":0,"y":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"0":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"72":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.0}},"df":3}}}}}}}}}}}}}}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{},"df":0,"_":{"docs":{},"df":0,"z":{"docs":{"109":{"tf":1.0},"112":{"tf":1.0}},"df":2}}}}}},"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"_":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"109":{"tf":1.0}},"df":1}}}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}},"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}}}}}}}}}}}}}}}}}}}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"s":{"docs":{},"df":0,"(":{"docs":{},"df":0,"2":{"docs":{},"df":0,"6":{"docs":{},"df":0,"3":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}}}}},"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"r":{"docs":{},"df":0,"1":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"c":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0}},"df":1}}}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}},"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,".":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"(":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"_":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0}},"df":2}}}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"h":{"docs":{"109":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}}}}}}}}}}}},"p":{"docs":{},"df":0,"w":{"docs":{},"df":0,"m":{"docs":{},"df":0,"4":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"(":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"72":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}},"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"126":{"tf":1.4142135623730951},"165":{"tf":1.4142135623730951},"64":{"tf":1.4142135623730951},"68":{"tf":1.0}},"df":4}},"l":{"docs":{},"df":0,"k":{"docs":{"105":{"tf":1.0},"110":{"tf":1.0},"54":{"tf":1.0}},"df":3}},"n":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":1.0},"106":{"tf":1.4142135623730951},"11":{"tf":1.0},"125":{"tf":1.0},"132":{"tf":1.0},"160":{"tf":1.0},"180":{"tf":1.0},"183":{"tf":1.0},"188":{"tf":1.0},"190":{"tf":1.4142135623730951},"191":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.4142135623730951},"64":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"70":{"tf":1.0},"9":{"tf":1.0},"92":{"tf":1.0}},"df":21}},"r":{"docs":{},"df":0,"n":{"docs":{"64":{"tf":1.4142135623730951},"78":{"tf":1.0}},"df":2}},"s":{"docs":{},"df":0,"n":{"docs":{},"df":0,"\'":{"docs":{},"df":0,"t":{"docs":{"127":{"tf":1.0}},"df":1}}},"t":{"docs":{"108":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"130":{"tf":1.0}},"df":1,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"53":{"tf":1.4142135623730951},"68":{"tf":1.0}},"df":2}}}}}}}},"y":{"docs":{"101":{"tf":1.0},"104":{"tf":1.0},"105":{"tf":1.0},"109":{"tf":1.4142135623730951},"114":{"tf":1.4142135623730951},"15":{"tf":1.0},"155":{"tf":1.0},"189":{"tf":1.0},"190":{"tf":1.0},"60":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"84":{"tf":1.4142135623730951},"9":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.4142135623730951}},"df":18}},"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.4142135623730951}},"df":1}}},"e":{"docs":{},"df":0,"\'":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{"127":{"tf":1.4142135623730951}},"df":1}},"v":{"docs":{"127":{"tf":1.0}},"df":1}},"b":{"docs":{"20":{"tf":1.0}},"df":1,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"11":{"tf":1.0},"129":{"tf":1.0},"51":{"tf":1.0}},"df":3}}}},"l":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"0":{"tf":1.0},"8":{"tf":1.0}},"df":2}}},"l":{"docs":{"114":{"tf":1.0},"115":{"tf":1.4142135623730951},"123":{"tf":1.0},"130":{"tf":1.0},"146":{"tf":1.0},"16":{"tf":1.0},"160":{"tf":1.0},"69":{"tf":1.4142135623730951},"86":{"tf":1.0},"96":{"tf":1.4142135623730951}},"df":10}},"’":{"docs":{},"df":0,"d":{"docs":{"123":{"tf":1.0},"75":{"tf":1.0},"91":{"tf":1.0}},"df":3},"l":{"docs":{},"df":0,"l":{"docs":{"10":{"tf":1.0},"125":{"tf":1.0},"127":{"tf":1.7320508075688772},"131":{"tf":1.0},"132":{"tf":1.0},"133":{"tf":1.0},"19":{"tf":1.7320508075688772},"40":{"tf":1.0},"53":{"tf":1.0},"54":{"tf":1.0},"55":{"tf":1.4142135623730951},"56":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0},"65":{"tf":1.0},"66":{"tf":1.4142135623730951},"67":{"tf":1.7320508075688772},"68":{"tf":1.4142135623730951},"99":{"tf":1.0}},"df":19}},"r":{"docs":{"122":{"tf":1.0},"123":{"tf":1.4142135623730951},"126":{"tf":1.4142135623730951},"69":{"tf":1.0},"72":{"tf":1.7320508075688772}},"df":5},"v":{"docs":{"112":{"tf":1.0},"122":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.4142135623730951},"72":{"tf":1.0},"92":{"tf":1.4142135623730951}},"df":6}}},"f":{"docs":{},"df":0,"i":{"docs":{"127":{"tf":1.0},"165":{"tf":1.0}},"df":2}},"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"20":{"tf":1.0}},"df":1}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{"122":{"tf":1.0}},"df":1}},"’":{"docs":{"137":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{"115":{"tf":1.0}},"df":1}},"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{"120":{"tf":1.4142135623730951},"55":{"tf":1.0}},"df":2}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{"139":{"tf":1.0},"84":{"tf":1.0}},"df":2}}},"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"102":{"tf":1.4142135623730951},"123":{"tf":1.0},"134":{"tf":1.0},"137":{"tf":1.0},"164":{"tf":1.0},"168":{"tf":1.0},"190":{"tf":1.0},"88":{"tf":1.0},"92":{"tf":1.0}},"df":9}}}},"w":{"docs":{"127":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{},"df":0,"!":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0}},"df":1}}}}}}},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{"165":{"tf":1.0}},"df":1}}}}}}},"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{"113":{"tf":1.0},"114":{"tf":1.0},"98":{"tf":1.0}},"df":3}},"s":{"docs":{},"df":0,"e":{"docs":{"62":{"tf":1.4142135623730951}},"df":1}}}},"i":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{"12":{"tf":1.0},"130":{"tf":1.0},"27":{"tf":1.0},"30":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0},"63":{"tf":1.0}},"df":7},"t":{"docs":{},"df":0,"h":{"docs":{"90":{"tf":1.0}},"df":1}}},"k":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{"114":{"tf":1.4142135623730951},"97":{"tf":1.0}},"df":2}}}}}}},"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"174":{"tf":1.0},"39":{"tf":1.0},"41":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0}},"df":5}}}},"r":{"docs":{},"df":0,"e":{"docs":{"27":{"tf":1.0},"34":{"tf":1.0},"77":{"tf":1.0}},"df":3}},"s":{"docs":{},"df":0,"h":{"docs":{"161":{"tf":1.0},"75":{"tf":1.0},"86":{"tf":1.0}},"df":3}},"t":{"docs":{},"df":0,"h":{"docs":{},"df":0,"_":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"<":{"docs":{},"df":0,"n":{"docs":{"155":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"<":{"docs":{},"df":0,"n":{"docs":{"155":{"tf":1.4142135623730951}},"df":1}}}}}}}}}}}}}},"{":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,",":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"}":{"docs":{},"df":0,"_":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{"133":{"tf":1.0},"173":{"tf":1.0},"196":{"tf":1.0},"64":{"tf":1.0},"7":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"77":{"tf":1.0},"80":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}},"df":10}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"105":{"tf":1.4142135623730951},"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.4142135623730951},"126":{"tf":1.0},"128":{"tf":1.0},"133":{"tf":1.0},"14":{"tf":1.0},"155":{"tf":1.0},"173":{"tf":1.0},"188":{"tf":1.4142135623730951},"191":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.0},"38":{"tf":1.0},"44":{"tf":1.0},"54":{"tf":1.0},"64":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.4142135623730951},"80":{"tf":1.0}},"df":25}}}}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"\'":{"docs":{},"df":0,"t":{"docs":{"101":{"tf":1.0}},"df":1}},"’":{"docs":{},"df":0,"t":{"docs":{"122":{"tf":1.0},"125":{"tf":1.0},"15":{"tf":1.0},"187":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":1.0},"60":{"tf":1.0},"64":{"tf":1.4142135623730951},"70":{"tf":1.0},"72":{"tf":1.0},"78":{"tf":1.0},"83":{"tf":1.4142135623730951}},"df":12}}},"r":{"docs":{},"df":0,"d":{"docs":{"11":{"tf":1.0},"55":{"tf":1.0},"88":{"tf":1.4142135623730951}},"df":3},"k":{"docs":{"10":{"tf":1.0},"101":{"tf":1.4142135623730951},"102":{"tf":1.0},"114":{"tf":1.0},"126":{"tf":1.0},"160":{"tf":1.0},"170":{"tf":1.0},"19":{"tf":1.0},"26":{"tf":1.0},"30":{"tf":1.0},"33":{"tf":1.4142135623730951},"34":{"tf":1.0},"5":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":2.0},"63":{"tf":1.4142135623730951},"68":{"tf":1.0},"70":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.0},"8":{"tf":1.0},"83":{"tf":1.4142135623730951},"88":{"tf":1.0},"9":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0}},"df":26,"f":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"26":{"tf":1.0}},"df":1}}}}},"l":{"docs":{},"df":0,"d":{"docs":{"63":{"tf":1.4142135623730951},"64":{"tf":2.0},"68":{"tf":1.4142135623730951},"69":{"tf":1.0},"77":{"tf":2.0},"86":{"tf":1.0},"94":{"tf":1.0}},"df":7,"!":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"64":{"tf":1.4142135623730951},"67":{"tf":1.0},"68":{"tf":1.0},"77":{"tf":1.0}},"df":4}}}}}}}}},"\\\\":{"docs":{},"df":0,"r":{"docs":{},"df":0,"\\\\":{"docs":{},"df":0,"n":{"docs":{},"df":0,"\\"":{"docs":{},"df":0,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"i":{"docs":{"121":{"tf":1.0},"93":{"tf":1.0}},"df":2}},"s":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"h":{"docs":{"123":{"tf":1.0},"158":{"tf":1.0},"160":{"tf":1.0},"163":{"tf":1.0},"165":{"tf":1.0}},"df":5}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"123":{"tf":1.0},"126":{"tf":1.0},"150":{"tf":1.0},"171":{"tf":1.0},"76":{"tf":1.4142135623730951},"80":{"tf":1.4142135623730951},"93":{"tf":1.0},"99":{"tf":1.0}},"df":8,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"125":{"tf":1.0},"142":{"tf":1.0},"146":{"tf":1.4142135623730951},"69":{"tf":1.4142135623730951}},"df":4}}}}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{"107":{"tf":1.4142135623730951},"108":{"tf":1.0},"114":{"tf":1.0},"12":{"tf":1.0},"120":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":1.0},"123":{"tf":1.4142135623730951},"124":{"tf":1.4142135623730951},"130":{"tf":1.0},"141":{"tf":1.4142135623730951},"156":{"tf":1.0},"159":{"tf":1.0},"164":{"tf":1.4142135623730951},"165":{"tf":1.4142135623730951},"17":{"tf":1.0},"174":{"tf":1.0},"183":{"tf":1.0},"2":{"tf":1.0},"28":{"tf":1.4142135623730951},"54":{"tf":1.0},"55":{"tf":1.0},"72":{"tf":1.0},"74":{"tf":1.4142135623730951},"75":{"tf":1.4142135623730951},"77":{"tf":1.4142135623730951},"87":{"tf":1.4142135623730951},"88":{"tf":2.0},"92":{"tf":2.6457513110645907},"94":{"tf":1.0},"95":{"tf":1.4142135623730951}},"df":31,"!":{"docs":{},"df":0,"(":{"docs":{},"df":0,"h":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0}},"df":1}}}}}}}}},"_":{"docs":{},"df":0,"b":{"docs":{},"df":0,"y":{"docs":{},"df":0,"t":{"docs":{"69":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"s":{"docs":{},"df":0,"(":{"docs":{},"df":0,"&":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"121":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}}},"v":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0}},"df":1}}}}}}}},"l":{"docs":{},"df":0,"n":{"docs":{},"df":0,"!":{"docs":{},"df":0,"(":{"docs":{},"df":0,"h":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"83":{"tf":1.0}},"df":1}}}}}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"76":{"tf":1.0}},"df":1}}}}}}}},"r":{"docs":{"2":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"126":{"tf":1.0},"127":{"tf":1.0},"147":{"tf":1.0},"173":{"tf":1.0},"176":{"tf":1.0},"4":{"tf":1.0},"69":{"tf":1.0},"72":{"tf":1.0},"9":{"tf":1.0},"93":{"tf":1.0}},"df":10}}}}},"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"75":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"e":{"docs":{"108":{"tf":1.0}},"df":1}}}}},"x":{"docs":{"100":{"tf":1.4142135623730951},"104":{"tf":1.4142135623730951},"107":{"tf":1.0},"108":{"tf":1.0},"134":{"tf":1.0},"166":{"tf":3.1622776601683795},"173":{"tf":1.7320508075688772},"68":{"tf":2.23606797749979},"71":{"tf":1.0}},"df":9,"8":{"docs":{},"df":0,"6":{"docs":{},"df":0,"_":{"docs":{},"df":0,"6":{"docs":{},"df":0,"4":{"docs":{"21":{"tf":1.0}},"df":1}}}}},"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"g":{"docs":{},"df":0,"o":{"docs":{"162":{"tf":1.0}},"df":1}}}},"m":{"docs":{},"df":0,"l":{"docs":{"199":{"tf":1.0}},"df":1}},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"50":{"tf":1.0}},"df":1}}},"s":{"docs":{},"df":0,"r":{"docs":{"83":{"tf":1.0}},"df":1}}},"s":{"docs":{"133":{"tf":1.0},"134":{"tf":1.4142135623730951},"79":{"tf":1.0}},"df":3,".":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"79":{"tf":1.0}},"df":1}}},"p":{"docs":{},"df":0,"u":{"docs":{},"df":0,"s":{"docs":{},"df":0,"h":{"docs":{},"df":0,"(":{"docs":{},"df":0,"4":{"docs":{},"df":0,"2":{"docs":{"133":{"tf":1.0}},"df":1,")":{"docs":{},"df":0,".":{"docs":{},"df":0,"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"w":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"134":{"tf":1.0}},"df":1}}}}}}}}}}}}}}}},"[":{"docs":{},"df":0,"i":{"docs":{"79":{"tf":1.0}},"df":1}}}},"y":{"docs":{"166":{"tf":3.4641016151377544},"173":{"tf":1.7320508075688772},"68":{"tf":1.0}},"df":3,"e":{"docs":{"187":{"tf":1.0}},"df":1,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"86":{"tf":1.0}},"df":1}}}}}}}},"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{"130":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"\'":{"docs":{},"df":0,"l":{"docs":{},"df":0,"l":{"docs":{"68":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"_":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"180":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"f":{"docs":{"162":{"tf":1.0},"50":{"tf":1.0}},"df":2}}}}},"’":{"docs":{},"df":0,"d":{"docs":{"158":{"tf":1.0}},"df":1},"l":{"docs":{},"df":0,"l":{"docs":{"132":{"tf":1.0},"133":{"tf":1.0},"134":{"tf":1.0},"136":{"tf":1.4142135623730951},"188":{"tf":1.0},"189":{"tf":1.0},"43":{"tf":1.7320508075688772},"52":{"tf":1.0},"53":{"tf":1.0},"64":{"tf":1.0},"69":{"tf":1.0},"77":{"tf":1.4142135623730951},"81":{"tf":1.0},"83":{"tf":1.4142135623730951},"90":{"tf":1.0}},"df":15}},"r":{"docs":{"124":{"tf":1.0},"179":{"tf":1.0},"50":{"tf":1.0},"64":{"tf":1.0},"7":{"tf":1.0},"70":{"tf":1.4142135623730951}},"df":6},"v":{"docs":{"50":{"tf":1.0}},"df":1}}}}},"z":{"docs":{"107":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":1.7320508075688772},"137":{"tf":1.0},"166":{"tf":3.7416573867739413},"188":{"tf":1.4142135623730951},"190":{"tf":2.0}},"df":7,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"y":{"docs":{},"df":0,"r":{"docs":{"170":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"o":{"docs":{"111":{"tf":1.0},"112":{"tf":1.4142135623730951},"113":{"tf":1.0},"142":{"tf":1.0},"153":{"tf":1.4142135623730951},"187":{"tf":1.0},"189":{"tf":1.0},"190":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.4142135623730951},"82":{"tf":1.0}},"df":11}}},"i":{"docs":{},"df":0,"p":{"docs":{"163":{"tf":1.0},"59":{"tf":1.0}},"df":2}},"s":{"docs":{},"df":0,"t":{"docs":{"142":{"tf":1.0}},"df":1}}}}},"breadcrumbs":{"root":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"111":{"tf":1.4142135623730951},"112":{"tf":1.0},"113":{"tf":1.0},"125":{"tf":1.0}},"df":4}}}}}}},"c":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"124":{"tf":1.0},"147":{"tf":1.0},"163":{"tf":1.0},"165":{"tf":1.0},"72":{"tf":1.0},"92":{"tf":1.0}},"df":6}}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{"166":{"tf":1.0}},"df":1}}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{"133":{"tf":1.0}},"df":1}}}},"p":{"docs":{},"df":0,"i":{"docs":{"181":{"tf":1.0}},"df":1},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"x":{"docs":{"192":{"tf":1.4142135623730951},"193":{"tf":1.0},"194":{"tf":1.0},"195":{"tf":1.0},"196":{"tf":1.0},"197":{"tf":1.0},"198":{"tf":1.0},"199":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":1.0}},"df":10}}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"119":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"91":{"tf":1.0}},"df":1}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"144":{"tf":1.0},"151":{"tf":1.0}},"df":2}}}}}}},"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"71":{"tf":1.0}},"df":1}}}}}}}}},"m":{"docs":{"22":{"tf":1.0},"49":{"tf":1.0}},"df":2},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"163":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"4":{"tf":1.0}},"df":1}}}}}},"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"124":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"89":{"tf":1.4142135623730951},"90":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0}},"df":5}}}}}},"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"174":{"tf":1.0}},"df":1}}}}}}},"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{"14":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"21":{"tf":1.0},"39":{"tf":1.0}},"df":2}}}}}},"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"70":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"k":{"docs":{"3":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0}},"df":3}},"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"94":{"tf":1.0},"95":{"tf":1.0},"96":{"tf":1.4142135623730951}},"df":3}}}}},"s":{"docs":{},"df":0,"p":{"docs":{"193":{"tf":1.0}},"df":1}},"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{"161":{"tf":1.0},"169":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"178":{"tf":1.0},"181":{"tf":1.0}},"df":7,".":{"docs":{},"df":0,"r":{"docs":{"176":{"tf":1.0}},"df":1}}}}}}},"c":{"docs":{"144":{"tf":1.0},"146":{"tf":1.0},"147":{"tf":1.0},"148":{"tf":1.0},"150":{"tf":1.0},"151":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0},"156":{"tf":1.4142135623730951},"157":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"162":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"167":{"tf":1.0},"171":{"tf":1.4142135623730951},"172":{"tf":1.0},"173":{"tf":1.4142135623730951},"174":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"178":{"tf":1.0},"179":{"tf":1.4142135623730951},"180":{"tf":1.0},"181":{"tf":1.4142135623730951},"182":{"tf":1.0},"183":{"tf":1.4142135623730951},"184":{"tf":1.0},"91":{"tf":1.0}},"df":36,"/":{"docs":{},"df":0,"c":{"docs":{"175":{"tf":1.0},"178":{"tf":1.0}},"df":2}},"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"’":{"docs":{},"df":0,"t":{"docs":{"98":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"g":{"docs":{},"df":0,"o":{"docs":{"20":{"tf":1.0},"21":{"tf":1.0},"39":{"tf":1.0},"40":{"tf":1.0},"57":{"tf":1.0}},"df":5}}},"s":{"docs":{},"df":0,"e":{"docs":{"138":{"tf":1.0}},"df":1}}},"c":{"docs":{"178":{"tf":1.0}},"df":1},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"94":{"tf":1.0},"95":{"tf":1.0},"96":{"tf":1.4142135623730951}},"df":3}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"142":{"tf":1.4142135623730951}},"df":1}}}}}}},"i":{"docs":{},"df":0,"p":{"docs":{"27":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{"158":{"tf":1.0},"175":{"tf":1.0},"178":{"tf":1.0},"29":{"tf":1.0}},"df":4}},"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"132":{"tf":1.4142135623730951},"133":{"tf":1.0},"134":{"tf":1.0},"135":{"tf":1.0},"136":{"tf":1.0},"137":{"tf":1.0},"138":{"tf":1.0},"139":{"tf":1.0}},"df":8}}}}},"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"110":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"162":{"tf":1.0},"61":{"tf":1.0}},"df":5}},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"t":{"docs":{"159":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{"120":{"tf":1.4142135623730951},"121":{"tf":1.4142135623730951},"122":{"tf":1.0},"123":{"tf":1.0},"124":{"tf":1.0},"125":{"tf":1.0},"126":{"tf":1.0},"127":{"tf":1.0},"128":{"tf":1.0},"129":{"tf":1.0},"130":{"tf":1.0},"131":{"tf":1.0}},"df":12}}}},"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"67":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"150":{"tf":1.0}},"df":1}}}}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"t":{"docs":{"184":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"108":{"tf":1.4142135623730951},"109":{"tf":1.0},"110":{"tf":1.0}},"df":3}}},"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"8":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{"131":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"t":{"docs":{"111":{"tf":1.4142135623730951},"112":{"tf":1.0},"113":{"tf":1.0}},"df":3}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{"144":{"tf":1.4142135623730951},"147":{"tf":1.0},"178":{"tf":1.0},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0}},"df":7}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"56":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"123":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"162":{"tf":1.0},"61":{"tf":1.0}},"df":2}}}},"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"150":{"tf":1.0}},"df":1}}}},"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{"102":{"tf":1.0},"122":{"tf":1.0}},"df":2,"t":{"docs":{},"df":0,"y":{"docs":{},"df":0,"p":{"docs":{"173":{"tf":1.0}},"df":1}}}}}},"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{"23":{"tf":1.0},"25":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0}},"df":4,"g":{"docs":{"27":{"tf":1.0},"28":{"tf":1.0},"31":{"tf":1.0}},"df":3}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"151":{"tf":1.0}},"df":1}}},"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"153":{"tf":1.0},"82":{"tf":1.0}},"df":2}}}},"i":{"docs":{},"df":0,"n":{"docs":{"172":{"tf":1.0}},"df":1}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"188":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{"108":{"tf":1.4142135623730951},"109":{"tf":1.0},"110":{"tf":1.0},"140":{"tf":1.4142135623730951},"141":{"tf":1.4142135623730951},"142":{"tf":1.4142135623730951},"143":{"tf":1.0},"144":{"tf":1.0},"145":{"tf":1.0},"146":{"tf":1.0},"147":{"tf":1.0},"148":{"tf":1.0},"149":{"tf":1.0},"150":{"tf":1.0},"151":{"tf":1.0},"152":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0}},"df":19}}},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"146":{"tf":1.0}},"df":1}}}}}}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{"156":{"tf":1.4142135623730951},"157":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"162":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"167":{"tf":1.0}},"df":12}}}}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{"25":{"tf":1.0}},"df":1,"r":{"docs":{"118":{"tf":1.0},"52":{"tf":1.0}},"df":2}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{"49":{"tf":1.0}},"df":1}},"s":{"docs":{"139":{"tf":1.0}},"df":1}},"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{"129":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"d":{"docs":{"1":{"tf":1.0},"115":{"tf":1.0},"116":{"tf":1.0},"148":{"tf":1.0},"156":{"tf":1.4142135623730951},"157":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"162":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"167":{"tf":1.0},"23":{"tf":1.0}},"df":17}}}},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"155":{"tf":1.0}},"df":1}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0}},"df":3}}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"154":{"tf":1.4142135623730951}},"df":1}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"136":{"tf":1.0}},"df":1}}}},"x":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{"79":{"tf":1.0},"81":{"tf":1.0}},"df":2}}}},"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"80":{"tf":1.4142135623730951},"81":{"tf":1.0},"82":{"tf":1.4142135623730951},"83":{"tf":1.0}},"df":4}}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"100":{"tf":1.0}},"df":1}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{"150":{"tf":1.0},"29":{"tf":1.0}},"df":2}},"r":{"docs":{},"df":0,"n":{"docs":{"177":{"tf":1.0},"183":{"tf":1.0}},"df":2}}}}}},"f":{"docs":{},"df":0,"3":{"docs":{"11":{"tf":1.0}},"df":1},"a":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"83":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"89":{"tf":1.4142135623730951},"90":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0}},"df":5}}}},"p":{"docs":{},"df":0,"u":{"docs":{"194":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"e":{"docs":{"146":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"110":{"tf":1.0},"173":{"tf":1.0},"191":{"tf":1.4142135623730951}},"df":3}}}}}}}},"g":{"docs":{},"df":0,"d":{"docs":{},"df":0,"b":{"docs":{"31":{"tf":1.0},"49":{"tf":1.0}},"df":2}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"174":{"tf":1.0},"20":{"tf":1.0},"40":{"tf":1.0},"57":{"tf":1.0}},"df":4}}},"t":{"docs":{"54":{"tf":1.4142135623730951},"55":{"tf":1.0},"56":{"tf":1.0},"57":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0},"65":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.0},"79":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":1.0},"82":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0}},"df":31}},"i":{"docs":{},"df":0,"t":{"docs":{"20":{"tf":1.0},"58":{"tf":1.0}},"df":2}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"122":{"tf":1.0},"94":{"tf":1.0},"98":{"tf":1.0}},"df":3}}},"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"192":{"tf":1.4142135623730951},"193":{"tf":1.0},"194":{"tf":1.0},"195":{"tf":1.0},"196":{"tf":1.0},"197":{"tf":1.0},"198":{"tf":1.0},"199":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":1.0}},"df":10}}}}}}},"n":{"docs":{},"df":0,"u":{"docs":{"31":{"tf":1.0}},"df":1}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"152":{"tf":1.4142135623730951},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0}},"df":4}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"184":{"tf":1.0}},"df":1}}}}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{"103":{"tf":1.4142135623730951},"104":{"tf":1.0},"105":{"tf":1.0},"106":{"tf":1.0},"107":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":1.0},"110":{"tf":1.0},"111":{"tf":1.0},"112":{"tf":1.0},"113":{"tf":1.0}},"df":11}}}}}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"115":{"tf":1.0},"116":{"tf":1.0},"117":{"tf":1.0},"141":{"tf":1.4142135623730951},"142":{"tf":1.4142135623730951},"143":{"tf":1.0},"144":{"tf":1.0},"145":{"tf":1.0},"146":{"tf":1.0},"147":{"tf":1.4142135623730951},"148":{"tf":1.7320508075688772},"149":{"tf":1.0},"150":{"tf":1.0},"151":{"tf":1.0},"152":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0},"195":{"tf":1.0},"76":{"tf":1.0}},"df":20},"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{"136":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{"82":{"tf":1.0},"83":{"tf":1.0}},"df":2}}}}},"r":{"docs":{},"df":0,"d":{"docs":{"83":{"tf":1.0}},"df":1,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"10":{"tf":1.4142135623730951},"102":{"tf":1.0},"107":{"tf":1.0},"11":{"tf":1.0},"65":{"tf":1.4142135623730951},"66":{"tf":1.4142135623730951},"67":{"tf":1.0},"68":{"tf":1.0}},"df":8}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"134":{"tf":1.0}},"df":1}}}}}}},"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"46":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{"13":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"2":{"docs":{},"df":0,"c":{"docs":{"196":{"tf":1.0}},"df":1}},"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"117":{"tf":1.0},"148":{"tf":1.0}},"df":2}}}}}}}},"n":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"151":{"tf":1.4142135623730951}},"df":1}}},"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"62":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"37":{"tf":1.4142135623730951},"38":{"tf":1.0},"39":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"42":{"tf":1.0},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.4142135623730951},"47":{"tf":1.4142135623730951},"48":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":1.7320508075688772}},"df":17}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"150":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"41":{"tf":1.0}},"df":1}}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{"152":{"tf":1.0},"172":{"tf":1.0},"174":{"tf":1.0}},"df":3}}},"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"145":{"tf":1.4142135623730951},"146":{"tf":1.0},"147":{"tf":1.0},"148":{"tf":1.0},"168":{"tf":1.4142135623730951},"169":{"tf":1.4142135623730951},"170":{"tf":1.4142135623730951},"171":{"tf":1.0},"172":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"178":{"tf":1.0},"179":{"tf":1.0},"180":{"tf":1.0},"181":{"tf":1.0},"182":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.0}},"df":21}}}},"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"84":{"tf":1.4142135623730951}},"df":1}}}}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.0},"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"2":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"38":{"tf":1.0},"39":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"42":{"tf":1.0},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0},"47":{"tf":1.0},"48":{"tf":1.0},"49":{"tf":1.0},"5":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0},"52":{"tf":1.0},"53":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}},"df":54}}}}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"163":{"tf":1.0}},"df":1}}}},"j":{"docs":{"35":{"tf":1.0}},"df":1},"k":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"66":{"tf":1.0}},"df":1}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"100":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{"15":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"87":{"tf":1.0}},"df":1}}},"k":{"docs":{"184":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"52":{"tf":1.0}},"df":5},"u":{"docs":{},"df":0,"x":{"docs":{"42":{"tf":1.4142135623730951},"43":{"tf":1.0},"44":{"tf":1.0}},"df":3}}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{"171":{"tf":1.4142135623730951},"172":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"178":{"tf":1.0},"179":{"tf":1.4142135623730951},"180":{"tf":1.0},"181":{"tf":1.0},"182":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.0}},"df":14}}}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"106":{"tf":1.4142135623730951},"107":{"tf":1.0}},"df":2}}},"o":{"docs":{"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"47":{"tf":1.0}},"df":3},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"47":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"o":{"docs":{"160":{"tf":1.0}},"df":1}}},"p":{"docs":{"69":{"tf":1.4142135623730951},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.0},"76":{"tf":1.0},"88":{"tf":1.0}},"df":9},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"9":{"tf":1.0}},"df":1}}},"h":{"docs":{"191":{"tf":1.4142135623730951}},"df":1}}},"c":{"docs":{},"df":0,"u":{"docs":{"36":{"tf":1.0}},"df":1}},"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"10":{"tf":1.0}},"df":1}},"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"136":{"tf":1.0},"137":{"tf":1.0},"69":{"tf":1.4142135623730951},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.0},"76":{"tf":1.0},"87":{"tf":1.0},"88":{"tf":1.0}},"df":12}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"14":{"tf":1.0}},"df":1}},"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"146":{"tf":1.0},"151":{"tf":1.0},"154":{"tf":1.0}},"df":3}}}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{"71":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"75":{"tf":1.0}},"df":1}}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{"131":{"tf":1.0}},"df":1}}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"122":{"tf":1.0},"94":{"tf":1.0}},"df":2}}},"e":{"docs":{},"df":0,"x":{"docs":{"126":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{"143":{"tf":1.4142135623730951},"144":{"tf":1.7320508075688772}},"df":2}}},"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"113":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{"182":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{"12":{"tf":1.4142135623730951},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"191":{"tf":1.0}},"df":8}}}},"n":{"docs":{"56":{"tf":1.0}},"df":1,"e":{"docs":{"49":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{"135":{"tf":1.0}},"df":1}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"27":{"tf":1.0}},"df":1,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"d":{"docs":{"27":{"tf":1.0},"50":{"tf":1.0}},"df":2}}}},"r":{"docs":{"130":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"186":{"tf":1.4142135623730951},"187":{"tf":1.4142135623730951},"188":{"tf":1.4142135623730951},"189":{"tf":1.4142135623730951},"190":{"tf":1.4142135623730951}},"df":5}}}},"s":{"docs":{"41":{"tf":1.0}},"df":1},"u":{"docs":{},"df":0,"t":{"docs":{"136":{"tf":1.0}},"df":1}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"17":{"tf":1.0},"24":{"tf":1.0},"60":{"tf":1.0}},"df":3}}}}}}}},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{"147":{"tf":1.0},"197":{"tf":1.0},"72":{"tf":1.0}},"df":3,"k":{"docs":{"166":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"g":{"docs":{"43":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"78":{"tf":1.4142135623730951},"79":{"tf":1.0}},"df":2}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":1.0}},"df":1}}}}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"n":{"docs":{"140":{"tf":1.4142135623730951},"141":{"tf":1.4142135623730951},"142":{"tf":1.4142135623730951},"143":{"tf":1.0},"144":{"tf":1.0},"145":{"tf":1.0},"146":{"tf":1.0},"147":{"tf":1.0},"148":{"tf":1.0},"149":{"tf":1.0},"150":{"tf":1.0},"151":{"tf":1.0},"152":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0}},"df":16}}}}}},"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"m":{"docs":{"191":{"tf":1.4142135623730951}},"df":1}}}},"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"100":{"tf":1.0},"101":{"tf":1.0},"102":{"tf":1.0},"106":{"tf":1.4142135623730951},"107":{"tf":1.0},"127":{"tf":1.0},"72":{"tf":1.0},"85":{"tf":1.4142135623730951},"86":{"tf":1.4142135623730951},"87":{"tf":1.0},"88":{"tf":1.4142135623730951},"89":{"tf":1.0},"90":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0},"94":{"tf":1.0},"95":{"tf":1.0},"96":{"tf":1.0},"97":{"tf":1.0},"98":{"tf":1.0},"99":{"tf":1.0}},"df":22}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{"153":{"tf":1.4142135623730951},"154":{"tf":1.7320508075688772},"155":{"tf":1.4142135623730951}},"df":3}},"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"164":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"t":{"docs":{"154":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"114":{"tf":1.4142135623730951},"115":{"tf":1.0},"116":{"tf":1.0},"117":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0}},"df":6}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"149":{"tf":1.4142135623730951},"150":{"tf":1.0},"151":{"tf":1.0}},"df":3}}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"157":{"tf":1.0}},"df":1}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"4":{"tf":1.0}},"df":1}}}}}}}}},"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"e":{"docs":{"26":{"tf":1.0},"29":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0}},"df":4}},"g":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"104":{"tf":1.4142135623730951},"105":{"tf":1.0},"56":{"tf":1.0},"60":{"tf":1.0}},"df":4}}}},"j":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"180":{"tf":1.0},"184":{"tf":1.0}},"df":2}}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"146":{"tf":1.0},"154":{"tf":1.0}},"df":2}}}}}},"q":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{"22":{"tf":1.0},"51":{"tf":1.0},"55":{"tf":1.4142135623730951},"56":{"tf":1.0},"57":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0}},"df":12}}}},"r":{"docs":{},"df":0,"e":{"docs":{"9":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"d":{"docs":{"73":{"tf":1.0}},"df":1},"l":{"docs":{"130":{"tf":1.0},"87":{"tf":1.0}},"df":2}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"152":{"tf":1.0}},"df":1}}}}}}},"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"147":{"tf":1.4142135623730951}},"df":1}}}}}},"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"164":{"tf":1.0}},"df":1}}},"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"147":{"tf":1.0},"69":{"tf":1.4142135623730951},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.0},"76":{"tf":1.0},"90":{"tf":1.0}},"df":10}}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0}},"df":1}}}}}}},"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{"167":{"tf":1.0},"5":{"tf":1.0}},"df":2}}}}}},"s":{"docs":{"26":{"tf":1.0},"29":{"tf":1.0}},"df":2},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"128":{"tf":1.0}},"df":1}},"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"170":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{"44":{"tf":1.0},"95":{"tf":1.0}},"df":2}},"n":{"docs":{"63":{"tf":1.0}},"df":1,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"15":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"t":{"docs":{"1":{"tf":1.0},"12":{"tf":1.0},"171":{"tf":1.4142135623730951},"172":{"tf":1.0},"173":{"tf":1.0},"174":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.4142135623730951},"177":{"tf":1.0},"178":{"tf":1.0},"179":{"tf":1.4142135623730951},"180":{"tf":1.0},"181":{"tf":1.0},"182":{"tf":1.0},"183":{"tf":1.0},"184":{"tf":1.0},"23":{"tf":1.0},"38":{"tf":1.0},"56":{"tf":1.0},"89":{"tf":1.0},"90":{"tf":1.0},"91":{"tf":1.0},"92":{"tf":1.0},"93":{"tf":1.0},"99":{"tf":1.0}},"df":25,"i":{"docs":{"33":{"tf":1.0},"93":{"tf":1.0}},"df":2}}}}},"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"110":{"tf":1.0}},"df":1}}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"2":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"176":{"tf":1.0}},"df":1}}}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"123":{"tf":1.0}},"df":1}}}}},"e":{"docs":{"18":{"tf":1.0}},"df":1},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"158":{"tf":1.0}},"df":1}}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"77":{"tf":1.4142135623730951}},"df":1}}}}}},"n":{"docs":{},"df":0,"d":{"docs":{"125":{"tf":1.0}},"df":1}},"t":{"docs":{"180":{"tf":1.0}},"df":1}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{"127":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"100":{"tf":1.0},"101":{"tf":1.0},"102":{"tf":1.0},"97":{"tf":1.4142135623730951},"98":{"tf":1.0},"99":{"tf":1.0}},"df":6}}}}}}},"z":{"docs":{},"df":0,"e":{"docs":{"112":{"tf":1.0},"153":{"tf":1.0},"159":{"tf":1.0},"186":{"tf":1.4142135623730951},"187":{"tf":1.0},"188":{"tf":1.0},"189":{"tf":1.0},"190":{"tf":1.4142135623730951}},"df":8}}},"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"t":{"docs":{},"df":0,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"25":{"tf":1.0}},"df":1}}}}}},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"87":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{"41":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"d":{"docs":{"186":{"tf":1.4142135623730951},"187":{"tf":1.0},"188":{"tf":1.0},"189":{"tf":1.4142135623730951},"190":{"tf":1.0}},"df":5}}},"i":{"docs":{"198":{"tf":1.0}},"df":1}},"t":{"docs":{"34":{"tf":1.0},"52":{"tf":1.0}},"df":2,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"56":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"t":{"docs":{"54":{"tf":1.4142135623730951},"55":{"tf":1.0},"56":{"tf":1.0},"57":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"60":{"tf":1.0},"61":{"tf":1.0},"62":{"tf":1.0},"63":{"tf":1.0},"64":{"tf":1.0},"65":{"tf":1.0},"66":{"tf":1.0},"67":{"tf":1.0},"68":{"tf":1.0},"69":{"tf":1.0},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"73":{"tf":1.0},"74":{"tf":1.0},"75":{"tf":1.0},"76":{"tf":1.0},"77":{"tf":1.0},"78":{"tf":1.0},"79":{"tf":1.0},"80":{"tf":1.0},"81":{"tf":1.0},"82":{"tf":1.0},"83":{"tf":1.0},"84":{"tf":1.0}},"df":31}},"t":{"docs":{},"df":0,"e":{"docs":{"106":{"tf":1.4142135623730951},"107":{"tf":1.0},"109":{"tf":1.0},"155":{"tf":1.4142135623730951},"94":{"tf":1.0}},"df":5},"i":{"docs":{},"df":0,"c":{"docs":{"103":{"tf":1.4142135623730951},"104":{"tf":1.0},"105":{"tf":1.0},"106":{"tf":1.0},"107":{"tf":1.0},"108":{"tf":1.0},"109":{"tf":1.0},"110":{"tf":1.0},"111":{"tf":1.0},"112":{"tf":1.0},"113":{"tf":1.0}},"df":11}}}},"m":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"f":{"docs":{},"df":0,"3":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"11":{"tf":1.0}},"df":1}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"105":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"29":{"tf":1.0}},"df":1}}}}},"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"16":{"tf":1.0}},"df":1}}}}},"p":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"100":{"tf":1.0}},"df":1}}}}}},"v":{"docs":{},"df":0,"d":{"docs":{"199":{"tf":1.0}},"df":1}},"y":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"125":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{"130":{"tf":1.0},"161":{"tf":1.0},"169":{"tf":1.0},"177":{"tf":1.0},"22":{"tf":1.0}},"df":5}}}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{"110":{"tf":1.0},"130":{"tf":1.0},"138":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0}},"df":5}},"p":{"docs":{"156":{"tf":1.4142135623730951},"157":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"162":{"tf":1.0},"163":{"tf":1.0},"164":{"tf":1.0},"165":{"tf":1.0},"166":{"tf":1.0},"167":{"tf":1.0}},"df":12}},"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.4142135623730951},"26":{"tf":1.0},"27":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"46":{"tf":1.0},"47":{"tf":1.0}},"df":21,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"38":{"tf":1.0}},"df":1}}}}}}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"185":{"tf":1.4142135623730951},"186":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.0},"189":{"tf":1.0},"190":{"tf":1.0},"191":{"tf":1.0}},"df":7}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"30":{"tf":1.0}},"df":1}}}},"d":{"docs":{},"df":0,"e":{"docs":{"135":{"tf":1.0}},"df":1,"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{"186":{"tf":1.4142135623730951},"187":{"tf":1.0},"188":{"tf":1.0},"189":{"tf":1.0},"190":{"tf":1.0}},"df":5}}}}},"i":{"docs":{},"df":0,"t":{"docs":{"148":{"tf":1.4142135623730951},"150":{"tf":1.0}},"df":2}},"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"6":{"tf":1.0}},"df":1}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"102":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"177":{"tf":1.0}},"df":1}}}}}},"y":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"105":{"tf":1.0},"109":{"tf":1.0},"112":{"tf":1.0},"146":{"tf":1.0},"148":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0},"166":{"tf":1.0}},"df":9,"s":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":1.4142135623730951},"105":{"tf":1.0}},"df":2}}}}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"200":{"tf":1.0}},"df":1}}},"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{"44":{"tf":1.0}},"df":1}}},"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"185":{"tf":1.4142135623730951},"186":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.0},"189":{"tf":1.0},"190":{"tf":1.0},"191":{"tf":1.0}},"df":7}}}}},"p":{"docs":{"180":{"tf":1.0}},"df":1},"s":{"docs":{"133":{"tf":1.0},"134":{"tf":1.0},"139":{"tf":1.0},"150":{"tf":1.0},"57":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"7":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"9":{"tf":1.0},"98":{"tf":1.0}},"df":12,"a":{"docs":{},"df":0,"g":{"docs":{"137":{"tf":1.0}},"df":1},"r":{"docs":{},"df":0,"t":{"docs":{"201":{"tf":1.0}},"df":1}}},"b":{"docs":{"52":{"tf":1.0}},"df":1},"e":{"docs":{},"df":0,"r":{"docs":{"116":{"tf":1.0}},"df":1}}}},"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{"98":{"tf":1.0}},"df":1}}}}}}}},"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"53":{"tf":1.4142135623730951}},"df":1}}}}},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"29":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0},"92":{"tf":1.0}},"df":2}}}}}},"s":{"docs":{"163":{"tf":1.0},"164":{"tf":1.0}},"df":2}},"w":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"48":{"tf":1.4142135623730951},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0},"52":{"tf":1.0}},"df":5}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"173":{"tf":1.0}},"df":1,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"146":{"tf":1.0},"93":{"tf":1.0}},"df":2}}}}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{"74":{"tf":1.0}},"df":1}}}}},"z":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{"111":{"tf":1.4142135623730951},"112":{"tf":1.4142135623730951},"113":{"tf":1.0},"153":{"tf":1.0}},"df":4}}},"s":{"docs":{},"df":0,"t":{"docs":{"153":{"tf":1.0}},"df":1}}}}},"title":{"root":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"111":{"tf":1.0},"125":{"tf":1.0}},"df":2}}}}}}},"c":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"124":{"tf":1.0},"147":{"tf":1.0},"163":{"tf":1.0},"165":{"tf":1.0},"72":{"tf":1.0},"92":{"tf":1.0}},"df":6}}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{"166":{"tf":1.0}},"df":1}}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{"133":{"tf":1.0}},"df":1}}}},"p":{"docs":{},"df":0,"i":{"docs":{"181":{"tf":1.0}},"df":1},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"x":{"docs":{"192":{"tf":1.0}},"df":1}}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"119":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{"91":{"tf":1.0}},"df":1}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"144":{"tf":1.0},"151":{"tf":1.0}},"df":2}}}}}}},"r":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"71":{"tf":1.0}},"df":1}}}}}}}}},"m":{"docs":{"22":{"tf":1.0},"49":{"tf":1.0}},"df":2},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"y":{"docs":{"163":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"4":{"tf":1.0}},"df":1}}}}}},"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{"124":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"89":{"tf":1.0}},"df":1}}}}}},"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"174":{"tf":1.0}},"df":1}}}}}}},"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{"14":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"21":{"tf":1.0},"39":{"tf":1.0}},"df":2}}}}}},"o":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"70":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"k":{"docs":{"3":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0}},"df":3}},"r":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"96":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"p":{"docs":{"193":{"tf":1.0}},"df":1}},"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{},"df":0,"d":{"docs":{"161":{"tf":1.0},"169":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0},"178":{"tf":1.0},"181":{"tf":1.0}},"df":7,".":{"docs":{},"df":0,"r":{"docs":{"176":{"tf":1.0}},"df":1}}}}}}},"c":{"docs":{"144":{"tf":1.0},"146":{"tf":1.0},"147":{"tf":1.0},"148":{"tf":1.0},"150":{"tf":1.0},"151":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0},"156":{"tf":1.0},"171":{"tf":1.0},"173":{"tf":1.0},"179":{"tf":1.0},"181":{"tf":1.0},"183":{"tf":1.0},"91":{"tf":1.0}},"df":16,"/":{"docs":{},"df":0,"c":{"docs":{"175":{"tf":1.0},"178":{"tf":1.0}},"df":2}},"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"’":{"docs":{},"df":0,"t":{"docs":{"98":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"g":{"docs":{},"df":0,"o":{"docs":{"20":{"tf":1.0},"21":{"tf":1.0},"39":{"tf":1.0},"40":{"tf":1.0},"57":{"tf":1.0}},"df":5}}},"s":{"docs":{},"df":0,"e":{"docs":{"138":{"tf":1.0}},"df":1}}},"c":{"docs":{"178":{"tf":1.0}},"df":1},"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"96":{"tf":1.0}},"df":1}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"142":{"tf":1.0}},"df":1}}}}}}},"i":{"docs":{},"df":0,"p":{"docs":{"27":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"e":{"docs":{"158":{"tf":1.0},"175":{"tf":1.0},"178":{"tf":1.0},"29":{"tf":1.0}},"df":4}},"l":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"132":{"tf":1.0}},"df":1}}}}},"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"110":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"162":{"tf":1.0},"61":{"tf":1.0}},"df":5}},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"81":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"t":{"docs":{"159":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"r":{"docs":{"120":{"tf":1.0},"121":{"tf":1.0}},"df":2}}}},"f":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{"67":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"150":{"tf":1.0}},"df":1}}}}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"t":{"docs":{"184":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"108":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"8":{"tf":1.0}},"df":1}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{"131":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"t":{"docs":{"111":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{"144":{"tf":1.4142135623730951},"147":{"tf":1.0},"178":{"tf":1.0},"70":{"tf":1.0},"71":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0}},"df":7}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"56":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"123":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"162":{"tf":1.0},"61":{"tf":1.0}},"df":2}}}},"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"150":{"tf":1.0}},"df":1}}}},"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"a":{"docs":{"102":{"tf":1.0},"122":{"tf":1.0}},"df":2,"t":{"docs":{},"df":0,"y":{"docs":{},"df":0,"p":{"docs":{"173":{"tf":1.0}},"df":1}}}}}},"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"u":{"docs":{},"df":0,"g":{"docs":{"23":{"tf":1.0},"25":{"tf":1.0},"64":{"tf":1.0},"68":{"tf":1.0}},"df":4,"g":{"docs":{"27":{"tf":1.0},"28":{"tf":1.0},"31":{"tf":1.0}},"df":3}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"151":{"tf":1.0}},"df":1}}},"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"153":{"tf":1.0},"82":{"tf":1.0}},"df":2}}}},"i":{"docs":{},"df":0,"n":{"docs":{"172":{"tf":1.0}},"df":1}}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"188":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"n":{"docs":{"108":{"tf":1.0},"140":{"tf":1.0},"141":{"tf":1.0},"142":{"tf":1.0}},"df":4}}},"t":{"docs":{},"df":0,"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"146":{"tf":1.0}},"df":1}}}}}}}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{"156":{"tf":1.0}},"df":1}}}}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{"25":{"tf":1.0}},"df":1,"r":{"docs":{"118":{"tf":1.0},"52":{"tf":1.0}},"df":2}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"i":{"docs":{"49":{"tf":1.0}},"df":1}},"s":{"docs":{"139":{"tf":1.0}},"df":1}},"m":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{"129":{"tf":1.0}},"df":1}}}},"e":{"docs":{},"df":0,"d":{"docs":{"1":{"tf":1.0},"115":{"tf":1.0},"116":{"tf":1.0},"148":{"tf":1.0},"156":{"tf":1.0},"23":{"tf":1.0}},"df":6}}}},"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"155":{"tf":1.0}},"df":1}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0}},"df":3}}}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"s":{"docs":{"154":{"tf":1.4142135623730951}},"df":1}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"136":{"tf":1.0}},"df":1}}}},"x":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{"79":{"tf":1.0},"81":{"tf":1.0}},"df":2}}}},"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"80":{"tf":1.0},"82":{"tf":1.0}},"df":2}}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"u":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"100":{"tf":1.0}},"df":1}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"s":{"docs":{"150":{"tf":1.0},"29":{"tf":1.0}},"df":2}},"r":{"docs":{},"df":0,"n":{"docs":{"177":{"tf":1.0},"183":{"tf":1.0}},"df":2}}}}}},"f":{"docs":{},"df":0,"3":{"docs":{"11":{"tf":1.0}},"df":1},"a":{"docs":{},"df":0,"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{"83":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"89":{"tf":1.0}},"df":1}}}},"p":{"docs":{},"df":0,"u":{"docs":{"194":{"tf":1.0}},"df":1}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"e":{"docs":{"146":{"tf":1.0}},"df":1}}},"u":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"110":{"tf":1.0},"173":{"tf":1.0},"191":{"tf":1.0}},"df":3}}}}}}}},"g":{"docs":{},"df":0,"d":{"docs":{},"df":0,"b":{"docs":{"31":{"tf":1.0},"49":{"tf":1.0}},"df":2}},"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"174":{"tf":1.0},"20":{"tf":1.0},"40":{"tf":1.0},"57":{"tf":1.0}},"df":4}}},"t":{"docs":{"54":{"tf":1.0}},"df":1}},"i":{"docs":{},"df":0,"t":{"docs":{"20":{"tf":1.0},"58":{"tf":1.0}},"df":2}},"l":{"docs":{},"df":0,"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"122":{"tf":1.0},"94":{"tf":1.0},"98":{"tf":1.0}},"df":3}}},"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"192":{"tf":1.0}},"df":1}}}}}}},"n":{"docs":{},"df":0,"u":{"docs":{"31":{"tf":1.0}},"df":1}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"152":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"184":{"tf":1.0}},"df":1}}}}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{"103":{"tf":1.0}},"df":1}}}}}}}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"115":{"tf":1.0},"116":{"tf":1.0},"117":{"tf":1.0},"141":{"tf":1.0},"142":{"tf":1.0},"147":{"tf":1.0},"148":{"tf":1.4142135623730951},"195":{"tf":1.0},"76":{"tf":1.0}},"df":9},"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"l":{"docs":{"136":{"tf":1.0}},"df":1,"e":{"docs":{},"df":0,"r":{"docs":{"82":{"tf":1.0},"83":{"tf":1.0}},"df":2}}}}},"r":{"docs":{},"df":0,"d":{"docs":{"83":{"tf":1.0}},"df":1,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"10":{"tf":1.0},"102":{"tf":1.0},"107":{"tf":1.0},"65":{"tf":1.0},"66":{"tf":1.0}},"df":5}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"134":{"tf":1.0}},"df":1}}}}}}},"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"46":{"tf":1.0}},"df":1}}}}}},"s":{"docs":{},"df":0,"t":{"docs":{"13":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"2":{"docs":{},"df":0,"c":{"docs":{"196":{"tf":1.0}},"df":1}},"m":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"117":{"tf":1.0},"148":{"tf":1.0}},"df":2}}}}}}}},"n":{"docs":{},"df":0,"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"151":{"tf":1.4142135623730951}},"df":1}}},"s":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"62":{"tf":1.0}},"df":1}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"37":{"tf":1.0},"46":{"tf":1.0},"47":{"tf":1.0},"53":{"tf":1.0}},"df":4}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"d":{"docs":{"150":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"41":{"tf":1.0}},"df":1}}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"f":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{"152":{"tf":1.0},"172":{"tf":1.0},"174":{"tf":1.0}},"df":3}}},"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"145":{"tf":1.0},"168":{"tf":1.0},"169":{"tf":1.0},"170":{"tf":1.0}},"df":4}}}},"r":{"docs":{},"df":0,"u":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"84":{"tf":1.0}},"df":1}}}}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"u":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"0":{"tf":1.0}},"df":1}}}}}}}},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"163":{"tf":1.0}},"df":1}}}},"j":{"docs":{"35":{"tf":1.0}},"df":1},"k":{"docs":{},"df":0,"n":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"66":{"tf":1.0}},"df":1}}}},"l":{"docs":{},"df":0,"i":{"docs":{},"df":0,"b":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"100":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{"15":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"87":{"tf":1.0}},"df":1}}},"k":{"docs":{"184":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"52":{"tf":1.0}},"df":5},"u":{"docs":{},"df":0,"x":{"docs":{"42":{"tf":1.0}},"df":1}}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"l":{"docs":{"171":{"tf":1.0},"179":{"tf":1.0}},"df":2}}}}},"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"106":{"tf":1.0}},"df":1}}},"o":{"docs":{"45":{"tf":1.0}},"df":1},"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"47":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"o":{"docs":{"160":{"tf":1.0}},"df":1}}},"p":{"docs":{"69":{"tf":1.0},"88":{"tf":1.0}},"df":2},"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"9":{"tf":1.0}},"df":1}}},"h":{"docs":{"191":{"tf":1.0}},"df":1}}},"c":{"docs":{},"df":0,"u":{"docs":{"36":{"tf":1.0}},"df":1}},"e":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"10":{"tf":1.0}},"df":1}},"m":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"136":{"tf":1.0},"137":{"tf":1.0},"69":{"tf":1.0},"87":{"tf":1.0},"88":{"tf":1.0}},"df":5}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"14":{"tf":1.0}},"df":1}},"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"d":{"docs":{"146":{"tf":1.0},"151":{"tf":1.0},"154":{"tf":1.0}},"df":3}}}}},"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{"71":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"75":{"tf":1.0}},"df":1}}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"l":{"docs":{"131":{"tf":1.0}},"df":1}}}}},"t":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"122":{"tf":1.0},"94":{"tf":1.0}},"df":2}}},"e":{"docs":{},"df":0,"x":{"docs":{"126":{"tf":1.0}},"df":1}}}}},"n":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{"143":{"tf":1.0},"144":{"tf":1.4142135623730951}},"df":2}}},"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"113":{"tf":1.0}},"df":1}}},"o":{"docs":{},"df":0,"_":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{"182":{"tf":1.0}},"df":1}}}}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"d":{"docs":{"12":{"tf":1.0},"191":{"tf":1.0}},"df":2}}}},"n":{"docs":{"56":{"tf":1.0}},"df":1,"e":{"docs":{"49":{"tf":1.0}},"df":1}}}},"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{"135":{"tf":1.0}},"df":1}},"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{"27":{"tf":1.0}},"df":1,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"d":{"docs":{"27":{"tf":1.0},"50":{"tf":1.0}},"df":2}}}},"r":{"docs":{"130":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"186":{"tf":1.0},"187":{"tf":1.0},"188":{"tf":1.0},"189":{"tf":1.0},"190":{"tf":1.0}},"df":5}}}},"s":{"docs":{"41":{"tf":1.0}},"df":1},"u":{"docs":{},"df":0,"t":{"docs":{"136":{"tf":1.0}},"df":1}},"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"e":{"docs":{},"df":0,"w":{"docs":{"17":{"tf":1.0},"24":{"tf":1.0},"60":{"tf":1.0}},"df":3}}}}}}}},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{"147":{"tf":1.0},"197":{"tf":1.0},"72":{"tf":1.0}},"df":3,"k":{"docs":{"166":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"g":{"docs":{"43":{"tf":1.0}},"df":1}}}},"n":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"k":{"docs":{"78":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"155":{"tf":1.0}},"df":1}}}}},"t":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"n":{"docs":{"140":{"tf":1.0},"141":{"tf":1.0},"142":{"tf":1.0}},"df":3}}}}}},"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"f":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"m":{"docs":{"191":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"h":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"106":{"tf":1.0},"127":{"tf":1.0},"72":{"tf":1.0},"85":{"tf":1.0},"86":{"tf":1.0},"88":{"tf":1.0}},"df":6}}}}}}},"i":{"docs":{},"df":0,"n":{"docs":{"153":{"tf":1.4142135623730951},"154":{"tf":1.7320508075688772},"155":{"tf":1.4142135623730951}},"df":3}},"o":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"164":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"t":{"docs":{"154":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{"114":{"tf":1.0}},"df":1}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"149":{"tf":1.0}},"df":1}}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{"157":{"tf":1.0}},"df":1}}}}}}}}},"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"q":{"docs":{},"df":0,"u":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"i":{"docs":{},"df":0,"t":{"docs":{"4":{"tf":1.0}},"df":1}}}}}}}}},"o":{"docs":{},"df":0,"b":{"docs":{},"df":0,"e":{"docs":{"26":{"tf":1.0},"29":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0}},"df":4}},"g":{"docs":{},"df":0,"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"m":{"docs":{"104":{"tf":1.0},"56":{"tf":1.0},"60":{"tf":1.0}},"df":3}}}},"j":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"180":{"tf":1.0},"184":{"tf":1.0}},"df":2}}}},"v":{"docs":{},"df":0,"i":{"docs":{},"df":0,"d":{"docs":{"146":{"tf":1.0},"154":{"tf":1.0}},"df":2}}}}}},"q":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{},"df":0,"u":{"docs":{"22":{"tf":1.0},"51":{"tf":1.0},"55":{"tf":1.0}},"df":3}}}},"r":{"docs":{},"df":0,"e":{"docs":{"9":{"tf":1.0}},"df":1,"a":{"docs":{},"df":0,"d":{"docs":{"73":{"tf":1.0}},"df":1},"l":{"docs":{"130":{"tf":1.0},"87":{"tf":1.0}},"df":2}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"m":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{"152":{"tf":1.0}},"df":1}}}}}}},"e":{"docs":{},"df":0,"x":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"147":{"tf":1.4142135623730951}},"df":1}}}}}},"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"164":{"tf":1.0}},"df":1}}},"g":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"147":{"tf":1.0},"69":{"tf":1.0},"90":{"tf":1.0}},"df":3}}}},"p":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{},"df":0,"s":{"docs":{},"df":0,"e":{"docs":{},"df":0,"n":{"docs":{},"df":0,"t":{"docs":{"107":{"tf":1.0}},"df":1}}}}}}},"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"u":{"docs":{},"df":0,"r":{"docs":{},"df":0,"c":{"docs":{"167":{"tf":1.0},"5":{"tf":1.0}},"df":2}}}}}},"s":{"docs":{"26":{"tf":1.0},"29":{"tf":1.0}},"df":2},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"128":{"tf":1.0}},"df":1}},"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"s":{"docs":{"170":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{"44":{"tf":1.0},"95":{"tf":1.0}},"df":2}},"n":{"docs":{"63":{"tf":1.0}},"df":1,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{"15":{"tf":1.0}},"df":1}}}},"s":{"docs":{},"df":0,"t":{"docs":{"1":{"tf":1.0},"12":{"tf":1.0},"171":{"tf":1.0},"176":{"tf":1.0},"179":{"tf":1.0},"23":{"tf":1.0},"38":{"tf":1.0},"56":{"tf":1.0},"99":{"tf":1.0}},"df":9,"i":{"docs":{"33":{"tf":1.0},"93":{"tf":1.0}},"df":2}}}}},"s":{"docs":{},"df":0,"a":{"docs":{},"df":0,"f":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{"110":{"tf":1.0}},"df":1}}}}},"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"2":{"tf":1.0}},"df":1}}},"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"p":{"docs":{},"df":0,"t":{"docs":{"176":{"tf":1.0}},"df":1}}}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"123":{"tf":1.0}},"df":1}}}}},"e":{"docs":{"18":{"tf":1.0}},"df":1},"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"t":{"docs":{"158":{"tf":1.0}},"df":1}}}},"m":{"docs":{},"df":0,"i":{"docs":{},"df":0,"h":{"docs":{},"df":0,"o":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"77":{"tf":1.0}},"df":1}}}}}},"n":{"docs":{},"df":0,"d":{"docs":{"125":{"tf":1.0}},"df":1}},"t":{"docs":{"180":{"tf":1.0}},"df":1}},"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"e":{"docs":{"127":{"tf":1.0}},"df":1}}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{"97":{"tf":1.0}},"df":1}}}}}}},"z":{"docs":{},"df":0,"e":{"docs":{"112":{"tf":1.0},"153":{"tf":1.0},"159":{"tf":1.0},"186":{"tf":1.0},"190":{"tf":1.0}},"df":5}}},"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"t":{"docs":{},"df":0,"w":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{"25":{"tf":1.0}},"df":1}}}}}},"p":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{"87":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"c":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{"41":{"tf":1.0}},"df":1}}},"e":{"docs":{},"df":0,"d":{"docs":{"186":{"tf":1.0},"189":{"tf":1.0}},"df":2}}},"i":{"docs":{"198":{"tf":1.0}},"df":1}},"t":{"docs":{"34":{"tf":1.0},"52":{"tf":1.0}},"df":2,"a":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"d":{"docs":{"56":{"tf":1.0}},"df":1}}}}},"r":{"docs":{},"df":0,"t":{"docs":{"54":{"tf":1.0}},"df":1}},"t":{"docs":{},"df":0,"e":{"docs":{"106":{"tf":1.0},"109":{"tf":1.0},"155":{"tf":1.4142135623730951},"94":{"tf":1.0}},"df":4},"i":{"docs":{},"df":0,"c":{"docs":{"103":{"tf":1.0}},"df":1}}}},"m":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{},"df":0,"f":{"docs":{},"df":0,"3":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"c":{"docs":{},"df":0,"o":{"docs":{},"df":0,"v":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"11":{"tf":1.0}},"df":1}}}}}}}}}}}}}},"r":{"docs":{},"df":0,"o":{"docs":{},"df":0,"n":{"docs":{},"df":0,"g":{"docs":{"105":{"tf":1.0}},"df":1}}}},"u":{"docs":{},"df":0,"d":{"docs":{},"df":0,"i":{"docs":{},"df":0,"o":{"docs":{"29":{"tf":1.0}},"df":1}}}}},"u":{"docs":{},"df":0,"m":{"docs":{},"df":0,"m":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{"16":{"tf":1.0}},"df":1}}}}},"p":{"docs":{},"df":0,"p":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"100":{"tf":1.0}},"df":1}}}}}},"v":{"docs":{},"df":0,"d":{"docs":{"199":{"tf":1.0}},"df":1}},"y":{"docs":{},"df":0,"n":{"docs":{},"df":0,"c":{"docs":{"125":{"tf":1.0}},"df":1}},"s":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{},"df":0,"m":{"docs":{"130":{"tf":1.0},"161":{"tf":1.0},"169":{"tf":1.0},"177":{"tf":1.0},"22":{"tf":1.0}},"df":5}}}}}},"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"m":{"docs":{},"df":0,"e":{"docs":{"110":{"tf":1.0},"130":{"tf":1.0},"138":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0}},"df":5}},"p":{"docs":{"156":{"tf":1.0}},"df":1}},"o":{"docs":{},"df":0,"o":{"docs":{},"df":0,"l":{"docs":{"19":{"tf":1.0},"23":{"tf":1.0},"25":{"tf":1.0},"37":{"tf":1.0},"46":{"tf":1.0},"47":{"tf":1.0}},"df":6,"c":{"docs":{},"df":0,"h":{"docs":{},"df":0,"a":{"docs":{},"df":0,"i":{"docs":{},"df":0,"n":{"docs":{"38":{"tf":1.0}},"df":1}}}}}}},"p":{"docs":{},"df":0,"i":{"docs":{},"df":0,"c":{"docs":{"185":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"3":{"docs":{},"df":0,"2":{"docs":{"30":{"tf":1.0}},"df":1}}}},"d":{"docs":{},"df":0,"e":{"docs":{"135":{"tf":1.0}},"df":1,"o":{"docs":{},"df":0,"f":{"docs":{},"df":0,"f":{"docs":{"186":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"t":{"docs":{"148":{"tf":1.4142135623730951},"150":{"tf":1.0}},"df":2}},"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"6":{"tf":1.0}},"df":1}}}}}},"e":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{"102":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"g":{"docs":{},"df":0,"g":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"177":{"tf":1.0}},"df":1}}}}}},"y":{"docs":{},"df":0,"p":{"docs":{},"df":0,"e":{"docs":{"105":{"tf":1.0},"109":{"tf":1.0},"112":{"tf":1.0},"146":{"tf":1.0},"148":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"155":{"tf":1.0},"166":{"tf":1.0}},"df":9,"s":{"docs":{},"df":0,"t":{"docs":{"104":{"tf":1.0}},"df":1}}}}}},"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"200":{"tf":1.0}},"df":1}}},"d":{"docs":{},"df":0,"e":{"docs":{},"df":0,"v":{"docs":{"44":{"tf":1.0}},"df":1}}},"n":{"docs":{},"df":0,"s":{"docs":{},"df":0,"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"t":{"docs":{"185":{"tf":1.0}},"df":1}}}}},"p":{"docs":{"180":{"tf":1.0}},"df":1},"s":{"docs":{"133":{"tf":1.0},"134":{"tf":1.0},"139":{"tf":1.0},"150":{"tf":1.0},"57":{"tf":1.0},"58":{"tf":1.0},"59":{"tf":1.0},"7":{"tf":1.0},"72":{"tf":1.0},"76":{"tf":1.0},"9":{"tf":1.0},"98":{"tf":1.0}},"df":12,"a":{"docs":{},"df":0,"g":{"docs":{"137":{"tf":1.0}},"df":1},"r":{"docs":{},"df":0,"t":{"docs":{"201":{"tf":1.0}},"df":1}}},"b":{"docs":{"52":{"tf":1.0}},"df":1},"e":{"docs":{},"df":0,"r":{"docs":{"116":{"tf":1.0}},"df":1}}}},"v":{"docs":{},"df":0,"a":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"a":{"docs":{},"df":0,"b":{"docs":{},"df":0,"l":{"docs":{},"df":0,"e":{"docs":{},"df":0,"(":{"docs":{"98":{"tf":1.0}},"df":1}}}}}}}},"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"i":{"docs":{},"df":0,"f":{"docs":{},"df":0,"i":{"docs":{"53":{"tf":1.0}},"df":1}}}}},"i":{"docs":{},"df":0,"s":{"docs":{},"df":0,"u":{"docs":{},"df":0,"a":{"docs":{},"df":0,"l":{"docs":{"29":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"l":{"docs":{},"df":0,"a":{"docs":{},"df":0,"t":{"docs":{},"df":0,"i":{"docs":{},"df":0,"l":{"docs":{"165":{"tf":1.0},"92":{"tf":1.0}},"df":2}}}}}},"s":{"docs":{"163":{"tf":1.0},"164":{"tf":1.0}},"df":2}},"w":{"docs":{},"df":0,"c":{"docs":{},"df":0,"e":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.0}},"df":1}}},"i":{"docs":{},"df":0,"n":{"docs":{},"df":0,"d":{"docs":{},"df":0,"o":{"docs":{},"df":0,"w":{"docs":{"48":{"tf":1.0}},"df":1}}}}},"o":{"docs":{},"df":0,"r":{"docs":{},"df":0,"s":{"docs":{},"df":0,"t":{"docs":{"138":{"tf":1.0}},"df":1}}}},"r":{"docs":{},"df":0,"a":{"docs":{},"df":0,"p":{"docs":{"173":{"tf":1.0}},"df":1,"p":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{"146":{"tf":1.0},"93":{"tf":1.0}},"df":2}}}}},"i":{"docs":{},"df":0,"t":{"docs":{},"df":0,"e":{"docs":{"74":{"tf":1.0}},"df":1}}}}},"z":{"docs":{},"df":0,"e":{"docs":{},"df":0,"r":{"docs":{},"df":0,"o":{"docs":{"111":{"tf":1.0},"112":{"tf":1.0},"153":{"tf":1.0}},"df":3}}},"s":{"docs":{},"df":0,"t":{"docs":{"153":{"tf":1.0}},"df":1}}}}}},"documentStore":{"save":true,"docs":{"0":{"body":"Welcome to The Embedded Rust Book: An introductory book about using the Rust\\nProgramming Language on “Bare Metal” embedded systems, such as Microcontrollers.","breadcrumbs":"Introduction » Introduction","id":"0","title":"Introduction"},"1":{"body":"Embedded Rust is for everyone who wants to do embedded programming while taking advantage of the higher-level concepts and safety guarantees the Rust language provides.\\n(See also Who Rust Is For)","breadcrumbs":"Introduction » Who Embedded Rust is For","id":"1","title":"Who Embedded Rust is For"},"10":{"body":"Let’s get familiar with the hardware we’ll be working with.","breadcrumbs":"Introduction » Hardware » Meet Your Hardware","id":"10","title":"Meet Your Hardware"},"100":{"body":"Although we created our own Peripherals structure above, it is not necessary to do this for your code. the cortex_m crate contains a macro called singleton!() that will perform this action for you. use cortex_m::singleton; fn main() { // OK if `main` is executed only once let x: &\'static mut bool = singleton!(: bool = false).unwrap();\\n} cortex_m docs Additionally, if you use cortex-m-rtic, the entire process of defining and obtaining these peripherals are abstracted for you, and you are instead handed a Peripherals structure that contains a non- Option version of all of the items you define. // cortex-m-rtic v0.5.x\\n#[rtic::app(device = lm3s6965, peripherals = true)]\\nconst APP: () = { #[init] fn init(cx: init::Context) { static mut X: u32 = 0; // Cortex-M peripherals let core: cortex_m::Peripherals = cx.core; // Device specific peripherals let device: lm3s6965::Peripherals = cx.device; }\\n}","breadcrumbs":"Peripherals » Singletons » Existing library support","id":"100","title":"Existing library support"},"101":{"body":"But how do these Singletons make a noticeable difference in how our Rust code works? impl SerialPort { const SER_PORT_SPEED_REG: *mut u32 = 0x4000_1000 as _; fn read_speed( &self // <------ This is really, really important ) -> u32 { unsafe { ptr::read_volatile(Self::SER_PORT_SPEED_REG) } }\\n} There are two important factors in play here: Because we are using a singleton, there is only one way or place to obtain a SerialPort structure To call the read_speed() method, we must have ownership or a reference to a SerialPort structure These two factors put together means that it is only possible to access the hardware if we have appropriately satisfied the borrow checker, meaning that at no point do we have multiple mutable references to the same hardware! fn main() { // missing reference to `self`! Won\'t work. // SerialPort::read_speed(); let serial_1 = unsafe { PERIPHERALS.take_serial() }; // you can only read what you have access to let _ = serial_1.read_speed();\\n}","breadcrumbs":"Peripherals » Singletons » But why?","id":"101","title":"But why?"},"102":{"body":"Additionally, because some references are mutable, and some are immutable, it becomes possible to see whether a function or method could potentially modify the state of the hardware. For example, This is allowed to change hardware settings: fn setup_spi_port( spi: &mut SpiPort, cs_pin: &mut GpioPin\\n) -> Result<()> { // ...\\n} This isn’t: fn read_button(gpio: &GpioPin) -> bool { // ...\\n} This allows us to enforce whether code should or should not make changes to hardware at compile time, rather than at runtime. As a note, this generally only works across one application, but for bare metal systems, our software will be compiled into a single application, so this is not usually a restriction.","breadcrumbs":"Peripherals » Singletons » Treat your hardware like data","id":"102","title":"Treat your hardware like data"},"103":{"body":"Rust’s type system prevents data races at compile time (see Send and Sync traits). The type system can also be used to check other properties at\\ncompile time; reducing the need for runtime checks in some cases. When applied to embedded programs these static checks can be used, for\\nexample, to enforce that configuration of I/O interfaces is done properly. For\\ninstance, one can design an API where it is only possible to initialize a serial\\ninterface by first configuring the pins that will be used by the interface. One can also statically check that operations, like setting a pin low, can only\\nbe performed on correctly configured peripherals. For example, trying to change\\nthe output state of a pin configured in floating input mode would raise a\\ncompile error. And, as seen in the previous chapter, the concept of ownership can be applied\\nto peripherals to ensure that only certain parts of a program can modify a\\nperipheral. This access control makes software easier to reason about\\ncompared to the alternative of treating peripherals as global mutable state.","breadcrumbs":"Static Guarantees » Static Guarantees","id":"103","title":"Static Guarantees"},"104":{"body":"The concept of typestates describes the encoding of information about the current state of an object into the type of that object. Although this can sound a little arcane, if you have used the Builder Pattern in Rust, you have already started using Typestate Programming! pub mod foo_module { #[derive(Debug)] pub struct Foo { inner: u32, } pub struct FooBuilder { a: u32, b: u32, } impl FooBuilder { pub fn new(starter: u32) -> Self { Self { a: starter, b: starter, } } pub fn double_a(self) -> Self { Self { a: self.a * 2, b: self.b, } } pub fn into_foo(self) -> Foo { Foo { inner: self.a + self.b, } } }\\n} fn main() { let x = foo_module::FooBuilder::new(10) .double_a() .into_foo(); println!(\\"{:#?}\\", x);\\n} In this example, there is no direct way to create a Foo object. We must create a FooBuilder, and properly initialize it before we can obtain the Foo object we want. This minimal example encodes two states: FooBuilder, which represents an “unconfigured”, or “configuration in process” state Foo, which represents a “configured”, or “ready to use” state.","breadcrumbs":"Static Guarantees » Typestate Programming » Typestate Programming","id":"104","title":"Typestate Programming"},"105":{"body":"Because Rust has a Strong Type System, there is no easy way to magically create an instance of Foo, or to turn a FooBuilder into a Foo without calling the into_foo() method. Additionally, calling the into_foo() method consumes the original FooBuilder structure, meaning it can not be reused without the creation of a new instance. This allows us to represent the states of our system as types, and to include the necessary actions for state transitions into the methods that exchange one type for another. By creating a FooBuilder, and exchanging it for a Foo object, we have walked through the steps of a basic state machine.","breadcrumbs":"Static Guarantees » Typestate Programming » Strong Types","id":"105","title":"Strong Types"},"106":{"body":"The peripherals of a microcontroller can be thought of as set of state machines. For example, the configuration of a simplified GPIO pin could be represented as the following tree of states: Disabled Enabled Configured as Output Output: High Output: Low Configured as Input Input: High Resistance Input: Pulled Low Input: Pulled High If the peripheral starts in the Disabled mode, to move to the Input: High Resistance mode, we must perform the following steps: Disabled Enabled Configured as Input Input: High Resistance If we wanted to move from Input: High Resistance to Input: Pulled Low, we must perform the following steps: Input: High Resistance Input: Pulled Low Similarly, if we want to move a GPIO pin from configured as Input: Pulled Low to Output: High, we must perform the following steps: Input: Pulled Low Configured as Input Configured as Output Output: High","breadcrumbs":"Static Guarantees » Peripherals as State Machines » Peripherals as State Machines","id":"106","title":"Peripherals as State Machines"},"107":{"body":"Typically the states listed above are set by writing values to given registers mapped to a GPIO peripheral. Let’s define an imaginary GPIO Configuration Register to illustrate this: Name Bit Number(s) Value Meaning Notes enable 0 0 disabled Disables the GPIO 1 enabled Enables the GPIO direction 1 0 input Sets the direction to Input 1 output Sets the direction to Output input_mode 2..3 00 hi-z Sets the input as high resistance 01 pull-low Input pin is pulled low 10 pull-high Input pin is pulled high 11 n/a Invalid state. Do not set output_mode 4 0 set-low Output pin is driven low 1 set-high Output pin is driven high input_status 5 x in-val 0 if input is < 1.5v, 1 if input >= 1.5v We could expose the following structure in Rust to control this GPIO: /// GPIO interface\\nstruct GpioConfig { /// GPIO Configuration structure generated by svd2rust periph: GPIO_CONFIG,\\n} impl GpioConfig { pub fn set_enable(&mut self, is_enabled: bool) { self.periph.modify(|_r, w| { w.enable().set_bit(is_enabled) }); } pub fn set_direction(&mut self, is_output: bool) { self.periph.modify(|_r, w| { w.direction().set_bit(is_output) }); } pub fn set_input_mode(&mut self, variant: InputMode) { self.periph.modify(|_r, w| { w.input_mode().variant(variant) }); } pub fn set_output_mode(&mut self, is_high: bool) { self.periph.modify(|_r, w| { w.output_mode.set_bit(is_high) }); } pub fn get_input_status(&self) -> bool { self.periph.read().input_status().bit_is_set() }\\n} However, this would allow us to modify certain registers that do not make sense. For example, what happens if we set the output_mode field when our GPIO is configured as an input? In general, use of this structure would allow us to reach states not defined by our state machine above: e.g. an output that is pulled low, or an input that is set high. For some hardware, this may not matter. On other hardware, it could cause unexpected or undefined behavior! Although this interface is convenient to write, it doesn’t enforce the design contracts set out by our hardware implementation.","breadcrumbs":"Static Guarantees » Peripherals as State Machines » Hardware Representation","id":"107","title":"Hardware Representation"},"108":{"body":"In our last chapter, we wrote an interface that didn’t enforce design contracts. Let’s take another look at our imaginary GPIO configuration register: Name Bit Number(s) Value Meaning Notes enable 0 0 disabled Disables the GPIO 1 enabled Enables the GPIO direction 1 0 input Sets the direction to Input 1 output Sets the direction to Output input_mode 2..3 00 hi-z Sets the input as high resistance 01 pull-low Input pin is pulled low 10 pull-high Input pin is pulled high 11 n/a Invalid state. Do not set output_mode 4 0 set-low Output pin is driven low 1 set-high Output pin is driven high input_status 5 x in-val 0 if input is < 1.5v, 1 if input >= 1.5v If we instead checked the state before making use of the underlying hardware, enforcing our design contracts at runtime, we might write code that looks like this instead: /// GPIO interface\\nstruct GpioConfig { /// GPIO Configuration structure generated by svd2rust periph: GPIO_CONFIG,\\n} impl GpioConfig { pub fn set_enable(&mut self, is_enabled: bool) { self.periph.modify(|_r, w| { w.enable().set_bit(is_enabled) }); } pub fn set_direction(&mut self, is_output: bool) -> Result<(), ()> { if self.periph.read().enable().bit_is_clear() { // Must be enabled to set direction return Err(()); } self.periph.modify(|r, w| { w.direction().set_bit(is_output) }); Ok(()) } pub fn set_input_mode(&mut self, variant: InputMode) -> Result<(), ()> { if self.periph.read().enable().bit_is_clear() { // Must be enabled to set input mode return Err(()); } if self.periph.read().direction().bit_is_set() { // Direction must be input return Err(()); } self.periph.modify(|_r, w| { w.input_mode().variant(variant) }); Ok(()) } pub fn set_output_status(&mut self, is_high: bool) -> Result<(), ()> { if self.periph.read().enable().bit_is_clear() { // Must be enabled to set output status return Err(()); } if self.periph.read().direction().bit_is_clear() { // Direction must be output return Err(()); } self.periph.modify(|_r, w| { w.output_mode.set_bit(is_high) }); Ok(()) } pub fn get_input_status(&self) -> Result { if self.periph.read().enable().bit_is_clear() { // Must be enabled to get status return Err(()); } if self.periph.read().direction().bit_is_set() { // Direction must be input return Err(()); } Ok(self.periph.read().input_status().bit_is_set()) }\\n} Because we need to enforce the restrictions on the hardware, we end up doing a lot of runtime checking which wastes time and resources, and this code will be much less pleasant for the developer to use.","breadcrumbs":"Static Guarantees » Design Contracts » Design Contracts","id":"108","title":"Design Contracts"},"109":{"body":"But what if instead, we used Rust’s type system to enforce the state transition rules? Take this example: /// GPIO interface\\nstruct GpioConfig { /// GPIO Configuration structure generated by svd2rust periph: GPIO_CONFIG, enabled: ENABLED, direction: DIRECTION, mode: MODE,\\n} // Type states for MODE in GpioConfig\\nstruct Disabled;\\nstruct Enabled;\\nstruct Output;\\nstruct Input;\\nstruct PulledLow;\\nstruct PulledHigh;\\nstruct HighZ;\\nstruct DontCare; /// These functions may be used on any GPIO Pin\\nimpl GpioConfig { pub fn into_disabled(self) -> GpioConfig { self.periph.modify(|_r, w| w.enable.disabled()); GpioConfig { periph: self.periph, enabled: Disabled, direction: DontCare, mode: DontCare, } } pub fn into_enabled_input(self) -> GpioConfig { self.periph.modify(|_r, w| { w.enable.enabled() .direction.input() .input_mode.high_z() }); GpioConfig { periph: self.periph, enabled: Enabled, direction: Input, mode: HighZ, } } pub fn into_enabled_output(self) -> GpioConfig { self.periph.modify(|_r, w| { w.enable.enabled() .direction.output() .input_mode.set_high() }); GpioConfig { periph: self.periph, enabled: Enabled, direction: Output, mode: DontCare, } }\\n} /// This function may be used on an Output Pin\\nimpl GpioConfig { pub fn set_bit(&mut self, set_high: bool) { self.periph.modify(|_r, w| w.output_mode.set_bit(set_high)); }\\n} /// These methods may be used on any enabled input GPIO\\nimpl GpioConfig { pub fn bit_is_set(&self) -> bool { self.periph.read().input_status.bit_is_set() } pub fn into_input_high_z(self) -> GpioConfig { self.periph.modify(|_r, w| w.input_mode().high_z()); GpioConfig { periph: self.periph, enabled: Enabled, direction: Input, mode: HighZ, } } pub fn into_input_pull_down(self) -> GpioConfig { self.periph.modify(|_r, w| w.input_mode().pull_low()); GpioConfig { periph: self.periph, enabled: Enabled, direction: Input, mode: PulledLow, } } pub fn into_input_pull_up(self) -> GpioConfig { self.periph.modify(|_r, w| w.input_mode().pull_high()); GpioConfig { periph: self.periph, enabled: Enabled, direction: Input, mode: PulledHigh, } }\\n} Now let’s see what the code using this would look like: /* * Example 1: Unconfigured to High-Z input */\\nlet pin: GpioConfig = get_gpio(); // Can\'t do this, pin isn\'t enabled!\\n// pin.into_input_pull_down(); // Now turn the pin from unconfigured to a high-z input\\nlet input_pin = pin.into_enabled_input(); // Read from the pin\\nlet pin_state = input_pin.bit_is_set(); // Can\'t do this, input pins don\'t have this interface!\\n// input_pin.set_bit(true); /* * Example 2: High-Z input to Pulled Low input */\\nlet pulled_low = input_pin.into_input_pull_down();\\nlet pin_state = pulled_low.bit_is_set(); /* * Example 3: Pulled Low input to Output, set high */\\nlet output_pin = pulled_low.into_enabled_output();\\noutput_pin.set_bit(true); // Can\'t do this, output pins don\'t have this interface!\\n// output_pin.into_input_pull_down(); This is definitely a convenient way to store the state of the pin, but why do it this way? Why is this better than storing the state as an enum inside of our GpioConfig structure?","breadcrumbs":"Static Guarantees » Design Contracts » Type States","id":"109","title":"Type States"},"11":{"body":"What does this board contain? A STM32F303VCT6 microcontroller. This microcontroller has A single-core ARM Cortex-M4F processor with hardware support for single-precision floating point\\noperations and a maximum clock frequency of 72 MHz. 256 KiB of “Flash” memory. (1 KiB = 10 24 bytes) 48 KiB of RAM. A variety of integrated peripherals such as timers, I2C, SPI and USART. General purpose Input Output (GPIO) and other types of pins accessible through the two rows of headers along side the board. A Mini-USB interface accessible through the USB port labeled “USB USER”. An accelerometer as part of the LSM303DLHC chip. A magnetometer as part of the LSM303DLHC chip. A gyroscope as part of the L3GD20 chip. 8 user LEDs arranged in the shape of a compass. A second microcontroller: a STM32F103. This microcontroller is actually part of an on-board programmer / debugger and is connected to the Mini-USB port named “USB ST-LINK”. For a more detailed list of features and further specifications of the board take a look at the STMicroelectronics website. A word of caution: be careful if you want to apply external signals to the board. The microcontroller STM32F303VCT6 pins take a nominal voltage of 3.3 volts. For further information consult the 6.2 Absolute maximum ratings section in the manual","breadcrumbs":"Introduction » Hardware » STM32F3DISCOVERY (the “F3”)","id":"11","title":"STM32F3DISCOVERY (the “F3”)"},"110":{"body":"Because we are enforcing our design constraints entirely at compile time, this incurs no runtime cost. It is impossible to set an output mode when you have a pin in an input mode. Instead, you must walk through the states by converting it to an output pin, and then setting the output mode. Because of this, there is no runtime penalty due to checking the current state before executing a function. Also, because these states are enforced by the type system, there is no longer room for errors by consumers of this interface. If they try to perform an illegal state transition, the code will not compile!","breadcrumbs":"Static Guarantees » Design Contracts » Compile Time Functional Safety","id":"110","title":"Compile Time Functional Safety"},"111":{"body":"Type states are also an excellent example of Zero Cost Abstractions - the ability to move certain behaviors to compile time execution or analysis. These type states contain no actual data, and are instead used as markers. Since they contain no data, they have no actual representation in memory at runtime: use core::mem::size_of; let _ = size_of::(); // == 0\\nlet _ = size_of::(); // == 0\\nlet _ = size_of::(); // == 0\\nlet _ = size_of::>(); // == 0","breadcrumbs":"Static Guarantees » Zero Cost Abstractions » Zero Cost Abstractions","id":"111","title":"Zero Cost Abstractions"},"112":{"body":"struct Enabled; Structures defined like this are called Zero Sized Types, as they contain no actual data. Although these types act “real” at compile time - you can copy them, move them, take references to them, etc., however the optimizer will completely strip them away. In this snippet of code: pub fn into_input_high_z(self) -> GpioConfig { self.periph.modify(|_r, w| w.input_mode().high_z()); GpioConfig { periph: self.periph, enabled: Enabled, direction: Input, mode: HighZ, }\\n} The GpioConfig we return never exists at runtime. Calling this function will generally boil down to a single assembly instruction - storing a constant register value to a register location. This means that the type state interface we’ve developed is a zero cost abstraction - it uses no more CPU, RAM, or code space tracking the state of GpioConfig, and renders to the same machine code as a direct register access.","breadcrumbs":"Static Guarantees » Zero Cost Abstractions » Zero Sized Types","id":"112","title":"Zero Sized Types"},"113":{"body":"In general, these abstractions may be nested as deeply as you would like. As long as all components used are zero sized types, the whole structure will not exist at runtime. For complex or deeply nested structures, it may be tedious to define all possible combinations of state. In these cases, macros may be used to generate all implementations.","breadcrumbs":"Static Guarantees » Zero Cost Abstractions » Nesting","id":"113","title":"Nesting"},"114":{"body":"In embedded environments portability is a very important topic: Every vendor and even each family from a single manufacturer offers different peripherals and capabilities and similarly the ways to interact with the peripherals will vary. A common way to equalize such differences is via a layer called Hardware Abstraction layer or HAL. Hardware abstractions are sets of routines in software that emulate some platform-specific details, giving programs direct access to the hardware resources. They often allow programmers to write device-independent, high performance applications by providing standard operating system (OS) calls to hardware. Wikipedia: Hardware Abstraction Layer Embedded systems are a bit special in this regard since we typically do not have operating systems and user installable software but firmware images which are compiled as a whole as well as a number of other constraints. So while the traditional approach as defined by Wikipedia could potentially work it is likely not the most productive approach to ensure portability. How do we do this in Rust? Enter embedded-hal…","breadcrumbs":"Portability » Portability","id":"114","title":"Portability"},"115":{"body":"In a nutshell it is a set of traits which define implementation contracts between HAL implementations, drivers and applications (or firmwares). Those contracts include both capabilities (i.e. if a trait is implemented for a certain type, the HAL implementation provides a certain capability) and methods (i.e. if you can construct a type implementing a trait it is guaranteed that you have the methods specified in the trait available). A typical layering might look like this: Some of the defined traits in embedded-hal are: GPIO (input and output pins) Serial communication I2C SPI Timers/Countdowns Analog Digital Conversion The main reason for having the embedded-hal traits and crates implementing and using them is to keep complexity in check. If you consider that an application might have to implement the use of the peripheral in the hardware as well as the application and potentially drivers for additional hardware components, then it should be easy to see that the re-usability is very limited. Expressed mathematically, if M is the number of peripheral HAL implementations and N the number of drivers then if we were to reinvent the wheel for every application then we would end up with M*N implementations while by using the API provided by the embedded-hal traits will make the implementation complexity approach M+N. Of course there’re additional benefits to be had, such as less trial-and-error due to a well-defined and ready-to-use APIs.","breadcrumbs":"Portability » What is embedded-hal?","id":"115","title":"What is embedded-hal?"},"116":{"body":"As said above there are three main users of the HAL:","breadcrumbs":"Portability » Users of the embedded-hal","id":"116","title":"Users of the embedded-hal"},"117":{"body":"A HAL implementation provides the interfacing between the hardware and the users of the HAL traits. Typical implementations consist of three parts: One or more hardware specific types Functions to create and initialize such a type, often providing various configuration options (speed, operation mode, use pins, etc.) one or more trait impl of embedded-hal traits for that type Such a HAL implementation can come in various flavours: Via low-level hardware access, e.g. via registers Via operating system, e.g. by using the sysfs under Linux Via adapter, e.g. a mock of types for unit testing Via driver for hardware adapters, e.g. I2C multiplexer or GPIO expander","breadcrumbs":"Portability » HAL implementation","id":"117","title":"HAL implementation"},"118":{"body":"A driver implements a set of custom functionality for an internal or external component, connected to a peripheral implementing the embedded-hal traits. Typical examples for such drivers include various sensors (temperature, magnetometer, accelerometer, light), display devices (LED arrays, LCD displays) and actuators (motors, transmitters). A driver has to be initialized with an instance of type that implements a certain trait of the embedded-hal which is ensured via trait bound and provides its own type instance with a custom set of methods allowing to interact with the driven device.","breadcrumbs":"Portability » Driver","id":"118","title":"Driver"},"119":{"body":"The application binds the various parts together and ensures that the desired functionality is achieved. When porting between different systems, this is the part which requires the most adaptation efforts, since the application needs to correctly initialize the real hardware via the HAL implementation and the initialisation of different hardware differs, sometimes drastically so. Also the user choice often plays a big role, since components can be physically connected to different terminals, hardware buses sometimes need external hardware to match the configuration or there are different trade-offs to be made in the use of internal peripherals (e.g. multiple timers with different capabilities are available or peripherals conflict with others).","breadcrumbs":"Portability » Application","id":"119","title":"Application"},"12":{"body":"The term Embedded Programming is used for a wide range of different classes of programming.\\nRanging from programming 8-Bit MCUs (like the ST72325xx)\\nwith just a few KB of RAM and ROM, up to systems like the Raspberry Pi\\n( Model B 3+) which has a 32/64-bit\\n4-core Cortex-A53 @ 1.4 GHz and 1GB of RAM. Different restrictions/limitations will apply when writing code\\ndepending on what kind of target and use case you have. There are two general Embedded Programming classifications:","breadcrumbs":"Introduction » no_std » A no_std Rust Environment","id":"12","title":"A no_std Rust Environment"},"120":{"body":"Concurrency happens whenever different parts of your program might execute\\nat different times or out of order. In an embedded context, this includes: interrupt handlers, which run whenever the associated interrupt happens, various forms of multithreading, where your microprocessor regularly swaps\\nbetween parts of your program, and in some systems, multiple-core microprocessors, where each core can be\\nindependently running a different part of your program at the same time. Since many embedded programs need to deal with interrupts, concurrency will\\nusually come up sooner or later, and it’s also where many subtle and difficult\\nbugs can occur. Luckily, Rust provides a number of abstractions and safety\\nguarantees to help us write correct code.","breadcrumbs":"Concurrency » Concurrency","id":"120","title":"Concurrency"},"121":{"body":"The simplest concurrency for an embedded program is no concurrency: your\\nsoftware consists of a single main loop which just keeps running, and there\\nare no interrupts at all. Sometimes this is perfectly suited to the problem\\nat hand! Typically your loop will read some inputs, perform some processing,\\nand write some outputs. #[entry]\\nfn main() { let peripherals = setup_peripherals(); loop { let inputs = read_inputs(&peripherals); let outputs = process(inputs); write_outputs(&peripherals, outputs); }\\n} Since there’s no concurrency, there’s no need to worry about sharing data\\nbetween parts of your program or synchronising access to peripherals. If\\nyou can get away with such a simple approach this can be a great solution.","breadcrumbs":"Concurrency » No Concurrency","id":"121","title":"No Concurrency"},"122":{"body":"Unlike non-embedded Rust, we will not usually have the luxury of creating\\nheap allocations and passing references to that data into a newly-created\\nthread. Instead, our interrupt handlers might be called at any time and must\\nknow how to access whatever shared memory we are using. At the lowest level,\\nthis means we must have statically allocated mutable memory, which\\nboth the interrupt handler and the main code can refer to. In Rust, such static mut variables are always unsafe to read or write,\\nbecause without taking special care, you might trigger a race condition,\\nwhere your access to the variable is interrupted halfway through by an\\ninterrupt which also accesses that variable. For an example of how this behaviour can cause subtle errors in your code,\\nconsider an embedded program which counts rising edges of some input signal\\nin each one-second period (a frequency counter): static mut COUNTER: u32 = 0; #[entry]\\nfn main() -> ! { set_timer_1hz(); let mut last_state = false; loop { let state = read_signal_level(); if state && !last_state { // DANGER - Not actually safe! Could cause data races. unsafe { COUNTER += 1 }; } last_state = state; }\\n} #[interrupt]\\nfn timer() { unsafe { COUNTER = 0; }\\n} Each second, the timer interrupt sets the counter back to 0. Meanwhile, the\\nmain loop continually measures the signal, and incremements the counter when\\nit sees a change from low to high. We’ve had to use unsafe to access COUNTER, as it’s static mut, and that means we’re promising the compiler\\nwe won’t cause any undefined behaviour. Can you spot the race condition? The\\nincrement on COUNTER is not guaranteed to be atomic — in fact, on most\\nembedded platforms, it will be split into a load, then the increment, then\\na store. If the interrupt fired after the load but before the store, the\\nreset back to 0 would be ignored after the interrupt returns — and we would\\ncount twice as many transitions for that period.","breadcrumbs":"Concurrency » Global Mutable Data","id":"122","title":"Global Mutable Data"},"123":{"body":"So, what can we do about data races? A simple approach is to use critical\\nsections, a context where interrupts are disabled. By wrapping the access to COUNTER in main in a critical section, we can be sure the timer interrupt\\nwill not fire until we’re finished incrementing COUNTER: static mut COUNTER: u32 = 0; #[entry]\\nfn main() -> ! { set_timer_1hz(); let mut last_state = false; loop { let state = read_signal_level(); if state && !last_state { // New critical section ensures synchronised access to COUNTER cortex_m::interrupt::free(|_| { unsafe { COUNTER += 1 }; }); } last_state = state; }\\n} #[interrupt]\\nfn timer() { unsafe { COUNTER = 0; }\\n} In this example, we use cortex_m::interrupt::free, but other platforms will\\nhave similar mechanisms for executing code in a critical section. This is also\\nthe same as disabling interrupts, running some code, and then re-enabling\\ninterrupts. Note we didn’t need to put a critical section inside the timer interrupt,\\nfor two reasons: Writing 0 to COUNTER can’t be affected by a race since we don’t read it It will never be interrupted by the main thread anyway If COUNTER was being shared by multiple interrupt handlers that might preempt each other, then each one might require a critical section as well. This solves our immediate problem, but we’re still left writing a lot of unsafe code which we need to carefully reason about, and we might be using critical sections needlessly. Since each critical section temporarily pauses interrupt processing, there is an associated cost of some extra code size and higher interrupt latency and jitter (interrupts may take longer to be processed, and the time until they are processed will be more variable). Whether this is a problem depends on your system, but in general, we’d like to avoid it. It’s worth noting that while a critical section guarantees no interrupts will\\nfire, it does not provide an exclusivity guarantee on multi-core systems! The\\nother core could be happily accessing the same memory as your core, even\\nwithout interrupts. You will need stronger synchronisation primitives if you\\nare using multiple cores.","breadcrumbs":"Concurrency » Critical Sections","id":"123","title":"Critical Sections"},"124":{"body":"On some platforms, special atomic instructions are available, which provide\\nguarantees about read-modify-write operations. Specifically for Cortex-M: thumbv6\\n(Cortex-M0, Cortex-M0+) only provide atomic load and store instructions,\\nwhile thumbv7 (Cortex-M3 and above) provide full Compare and Swap (CAS)\\ninstructions. These CAS instructions give an alternative to the heavy-handed\\ndisabling of all interrupts: we can attempt the increment, it will succeed most\\nof the time, but if it was interrupted it will automatically retry the entire\\nincrement operation. These atomic operations are safe even across multiple\\ncores. use core::sync::atomic::{AtomicUsize, Ordering}; static COUNTER: AtomicUsize = AtomicUsize::new(0); #[entry]\\nfn main() -> ! { set_timer_1hz(); let mut last_state = false; loop { let state = read_signal_level(); if state && !last_state { // Use `fetch_add` to atomically add 1 to COUNTER COUNTER.fetch_add(1, Ordering::Relaxed); } last_state = state; }\\n} #[interrupt]\\nfn timer() { // Use `store` to write 0 directly to COUNTER COUNTER.store(0, Ordering::Relaxed)\\n} This time COUNTER is a safe static variable. Thanks to the AtomicUsize\\ntype COUNTER can be safely modified from both the interrupt handler and the\\nmain thread without disabling interrupts. When possible, this is a better\\nsolution — but it may not be supported on your platform. A note on Ordering: this affects how the compiler and hardware may reorder\\ninstructions, and also has consequences on cache visibility. Assuming that the\\ntarget is a single core platform Relaxed is sufficient and the most efficient\\nchoice in this particular case. Stricter ordering will cause the compiler to\\nemit memory barriers around the atomic operations; depending on what you’re\\nusing atomics for you may or may not need this! The precise details of the\\natomic model are complicated and best described elsewhere. For more details on atomics and ordering, see the nomicon.","breadcrumbs":"Concurrency » Atomic Access","id":"124","title":"Atomic Access"},"125":{"body":"None of the above solutions are especially satisfactory. They require unsafe\\nblocks which must be very carefully checked and are not ergonomic. Surely we\\ncan do better in Rust! We can abstract our counter into a safe interface which can be safely used\\nanywhere else in our code. For this example, we’ll use the critical-section\\ncounter, but you could do something very similar with atomics. use core::cell::UnsafeCell;\\nuse cortex_m::interrupt; // Our counter is just a wrapper around UnsafeCell, which is the heart\\n// of interior mutability in Rust. By using interior mutability, we can have\\n// COUNTER be `static` instead of `static mut`, but still able to mutate\\n// its counter value.\\nstruct CSCounter(UnsafeCell); const CS_COUNTER_INIT: CSCounter = CSCounter(UnsafeCell::new(0)); impl CSCounter { pub fn reset(&self, _cs: &interrupt::CriticalSection) { // By requiring a CriticalSection be passed in, we know we must // be operating inside a CriticalSection, and so can confidently // use this unsafe block (required to call UnsafeCell::get). unsafe { *self.0.get() = 0 }; } pub fn increment(&self, _cs: &interrupt::CriticalSection) { unsafe { *self.0.get() += 1 }; }\\n} // Required to allow static CSCounter. See explanation below.\\nunsafe impl Sync for CSCounter {} // COUNTER is no longer `mut` as it uses interior mutability;\\n// therefore it also no longer requires unsafe blocks to access.\\nstatic COUNTER: CSCounter = CS_COUNTER_INIT; #[entry]\\nfn main() -> ! { set_timer_1hz(); let mut last_state = false; loop { let state = read_signal_level(); if state && !last_state { // No unsafe here! interrupt::free(|cs| COUNTER.increment(cs)); } last_state = state; }\\n} #[interrupt]\\nfn timer() { // We do need to enter a critical section here just to obtain a valid // cs token, even though we know no other interrupt could pre-empt // this one. interrupt::free(|cs| COUNTER.reset(cs)); // We could use unsafe code to generate a fake CriticalSection if we // really wanted to, avoiding the overhead: // let cs = unsafe { interrupt::CriticalSection::new() };\\n} We’ve moved our unsafe code to inside our carefully-planned abstraction,\\nand now our application code does not contain any unsafe blocks. This design requires that the application pass a CriticalSection token in:\\nthese tokens are only safely generated by interrupt::free, so by requiring\\none be passed in, we ensure we are operating inside a critical section, without\\nhaving to actually do the lock ourselves. This guarantee is provided statically\\nby the compiler: there won’t be any runtime overhead associated with cs.\\nIf we had multiple counters, they could all be given the same cs, without\\nrequiring multiple nested critical sections. This also brings up an important topic for concurrency in Rust: the Send and Sync traits. To summarise the Rust book, a type is Send\\nwhen it can safely be moved to another thread, while it is Sync when\\nit can be safely shared between multiple threads. In an embedded context,\\nwe consider interrupts to be executing in a separate thread to the application\\ncode, so variables accessed by both an interrupt and the main code must be\\nSync. For most types in Rust, both of these traits are automatically derived for you\\nby the compiler. However, because CSCounter contains an UnsafeCell, it is\\nnot Sync, and therefore we could not make a static CSCounter: static\\nvariables must be Sync, since they can be accessed by multiple threads. To tell the compiler we have taken care that the CSCounter is in fact safe\\nto share between threads, we implement the Sync trait explicitly. As with the\\nprevious use of critical sections, this is only safe on single-core platforms:\\nwith multiple cores, you would need to go to greater lengths to ensure safety.","breadcrumbs":"Concurrency » Abstractions, Send, and Sync","id":"125","title":"Abstractions, Send, and Sync"},"126":{"body":"We’ve created a useful abstraction specific to our counter problem, but\\nthere are many common abstractions used for concurrency. One such synchronisation primitive is a mutex, short for mutual exclusion.\\nThese constructs ensure exclusive access to a variable, such as our counter. A\\nthread can attempt to lock (or acquire) the mutex, and either succeeds\\nimmediately, or blocks waiting for the lock to be acquired, or returns an error\\nthat the mutex could not be locked. While that thread holds the lock, it is\\ngranted access to the protected data. When the thread is done, it unlocks (or releases) the mutex, allowing another thread to lock it. In Rust, we would\\nusually implement the unlock using the Drop trait to ensure it is always\\nreleased when the mutex goes out of scope. Using a mutex with interrupt handlers can be tricky: it is not normally\\nacceptable for the interrupt handler to block, and it would be especially\\ndisastrous for it to block waiting for the main thread to release a lock,\\nsince we would then deadlock (the main thread will never release the lock\\nbecause execution stays in the interrupt handler). Deadlocking is not\\nconsidered unsafe: it is possible even in safe Rust. To avoid this behaviour entirely, we could implement a mutex which requires\\na critical section to lock, just like our counter example. So long as the\\ncritical section must last as long as the lock, we can be sure we have\\nexclusive access to the wrapped variable without even needing to track\\nthe lock/unlock state of the mutex. This is in fact done for us in the cortex_m crate! We could have written\\nour counter using it: use core::cell::Cell;\\nuse cortex_m::interrupt::Mutex; static COUNTER: Mutex> = Mutex::new(Cell::new(0)); #[entry]\\nfn main() -> ! { set_timer_1hz(); let mut last_state = false; loop { let state = read_signal_level(); if state && !last_state { interrupt::free(|cs| COUNTER.borrow(cs).set(COUNTER.borrow(cs).get() + 1)); } last_state = state; }\\n} #[interrupt]\\nfn timer() { // We still need to enter a critical section here to satisfy the Mutex. interrupt::free(|cs| COUNTER.borrow(cs).set(0));\\n} We’re now using Cell, which along with its sibling RefCell is used to\\nprovide safe interior mutability. We’ve already seen UnsafeCell which is\\nthe bottom layer of interior mutability in Rust: it allows you to obtain\\nmultiple mutable references to its value, but only with unsafe code. A Cell\\nis like an UnsafeCell but it provides a safe interface: it only permits\\ntaking a copy of the current value or replacing it, not taking a reference,\\nand since it is not Sync, it cannot be shared between threads. These\\nconstraints mean it’s safe to use, but we couldn’t use it directly in a static variable as a static must be Sync. So why does the example above work? The Mutex implements Sync for any T which is Send — such as a Cell. It can do this safely because it only\\ngives access to its contents during a critical section. We’re therefore able\\nto get a safe counter with no unsafe code at all! This is great for simple types like the u32 of our counter, but what about\\nmore complex types which are not Copy? An extremely common example in an\\nembedded context is a peripheral struct, which generally is not Copy.\\nFor that, we can turn to RefCell.","breadcrumbs":"Concurrency » Mutexes","id":"126","title":"Mutexes"},"127":{"body":"Device crates generated using svd2rust and similar abstractions provide\\nsafe access to peripherals by enforcing that only one instance of the\\nperipheral struct can exist at a time. This ensures safety, but makes it\\ndifficult to access a peripheral from both the main thread and an interrupt\\nhandler. To safely share peripheral access, we can use the Mutex we saw before. We’ll\\nalso need to use RefCell, which uses a runtime check to ensure only one\\nreference to a peripheral is given out at a time. This has more overhead than\\nthe plain Cell, but since we are giving out references rather than copies,\\nwe must be sure only one exists at a time. Finally, we’ll also have to account for somehow moving the peripheral into\\nthe shared variable after it has been initialised in the main code. To do\\nthis we can use the Option type, initialised to None and later set to\\nthe instance of the peripheral. use core::cell::RefCell;\\nuse cortex_m::interrupt::{self, Mutex};\\nuse stm32f4::stm32f405; static MY_GPIO: Mutex>> = Mutex::new(RefCell::new(None)); #[entry]\\nfn main() -> ! { // Obtain the peripheral singletons and configure it. // This example is from an svd2rust-generated crate, but // most embedded device crates will be similar. let dp = stm32f405::Peripherals::take().unwrap(); let gpioa = &dp.GPIOA; // Some sort of configuration function. // Assume it sets PA0 to an input and PA1 to an output. configure_gpio(gpioa); // Store the GPIOA in the mutex, moving it. interrupt::free(|cs| MY_GPIO.borrow(cs).replace(Some(dp.GPIOA))); // We can no longer use `gpioa` or `dp.GPIOA`, and instead have to // access it via the mutex. // Be careful to enable the interrupt only after setting MY_GPIO: // otherwise the interrupt might fire while it still contains None, // and as-written (with `unwrap()`), it would panic. set_timer_1hz(); let mut last_state = false; loop { // We\'ll now read state as a digital input, via the mutex let state = interrupt::free(|cs| { let gpioa = MY_GPIO.borrow(cs).borrow(); gpioa.as_ref().unwrap().idr.read().idr0().bit_is_set() }); if state && !last_state { // Set PA1 high if we\'ve seen a rising edge on PA0. interrupt::free(|cs| { let gpioa = MY_GPIO.borrow(cs).borrow(); gpioa.as_ref().unwrap().odr.modify(|_, w| w.odr1().set_bit()); }); } last_state = state; }\\n} #[interrupt]\\nfn timer() { // This time in the interrupt we\'ll just clear PA0. interrupt::free(|cs| { // We can use `unwrap()` because we know the interrupt wasn\'t enabled // until after MY_GPIO was set; otherwise we should handle the potential // for a None value. let gpioa = MY_GPIO.borrow(cs).borrow(); gpioa.as_ref().unwrap().odr.modify(|_, w| w.odr1().clear_bit()); });\\n} That’s quite a lot to take in, so let’s break down the important lines. static MY_GPIO: Mutex>> = Mutex::new(RefCell::new(None)); Our shared variable is now a Mutex around a RefCell which contains an Option. The Mutex ensures we only have access during a critical section,\\nand therefore makes the variable Sync, even though a plain RefCell would not\\nbe Sync. The RefCell gives us interior mutability with references, which\\nwe’ll need to use our GPIOA. The Option lets us initialise this variable\\nto something empty, and only later actually move the variable in. We cannot\\naccess the peripheral singleton statically, only at runtime, so this is\\nrequired. interrupt::free(|cs| MY_GPIO.borrow(cs).replace(Some(dp.GPIOA))); Inside a critical section we can call borrow() on the mutex, which gives us\\na reference to the RefCell. We then call replace() to move our new value\\ninto the RefCell. interrupt::free(|cs| { let gpioa = MY_GPIO.borrow(cs).borrow(); gpioa.as_ref().unwrap().odr.modify(|_, w| w.odr1().set_bit());\\n}); Finally, we use MY_GPIO in a safe and concurrent fashion. The critical section\\nprevents the interrupt firing as usual, and lets us borrow the mutex. The RefCell then gives us an &Option, and tracks how long it remains\\nborrowed - once that reference goes out of scope, the RefCell will be updated\\nto indicate it is no longer borrowed. Since we can’t move the GPIOA out of the &Option, we need to convert it to\\nan &Option<&GPIOA> with as_ref(), which we can finally unwrap() to obtain\\nthe &GPIOA which lets us modify the peripheral. If we need a mutable reference to a shared resource, then borrow_mut and deref_mut\\nshould be used instead. The following code shows an example using the TIM2 timer. use core::cell::RefCell;\\nuse core::ops::DerefMut;\\nuse cortex_m::interrupt::{self, Mutex};\\nuse cortex_m::asm::wfi;\\nuse stm32f4::stm32f405; static G_TIM: Mutex>>> = Mutex::new(RefCell::new(None)); #[entry]\\nfn main() -> ! { let mut cp = cm::Peripherals::take().unwrap(); let dp = stm32f405::Peripherals::take().unwrap(); // Some sort of timer configuration function. // Assume it configures the TIM2 timer, its NVIC interrupt, // and finally starts the timer. let tim = configure_timer_interrupt(&mut cp, dp); interrupt::free(|cs| { G_TIM.borrow(cs).replace(Some(tim)); }); loop { wfi(); }\\n} #[interrupt]\\nfn timer() { interrupt::free(|cs| { if let Some(ref mut tim)) = G_TIM.borrow(cs).borrow_mut().deref_mut() { tim.start(1.hz()); } });\\n} Whew! This is safe, but it is also a little unwieldy. Is there anything else\\nwe can do?","breadcrumbs":"Concurrency » Sharing Peripherals","id":"127","title":"Sharing Peripherals"},"128":{"body":"One alternative is the RTIC framework, short for Real Time Interrupt-driven Concurrency. It\\nenforces static priorities and tracks accesses to static mut variables\\n(“resources”) to statically ensure that shared resources are always accessed\\nsafely, without requiring the overhead of always entering critical sections and\\nusing reference counting (as in RefCell). This has a number of advantages such\\nas guaranteeing no deadlocks and giving extremely low time and memory overhead. RTIC comes with as asynchronous executor, so your software tasks are async functions where\\nyou can use async APIs in addition to regular synchronous APIs. The framework also includes other features like message passing, which reduces\\nthe need for explicit shared state, and the ability to schedule tasks to run at\\na given time, which can be used to implement periodic tasks.\\nCheck out the documentation for more information!","breadcrumbs":"Concurrency » RTIC","id":"128","title":"RTIC"},"129":{"body":"Embassy is an ecosystem of libraries which focus on using the async / await syntax\\nincluded in Rust for concurrency. The core of embassy is its asynchronous executor\\nwhich supports most common MCU architectures. embassy also takes a battery-included approach and offers many other components, for example: Time library Various HAL libraries which also provide the time library support. embassy-sync for synchronization primitives You can check the website and the book for more\\ninformation.","breadcrumbs":"Concurrency » Embassy","id":"129","title":"Embassy"},"13":{"body":"These kinds of environments are close to a normal PC environment.\\nWhat this means is that you are provided with a System Interface E.G. POSIX\\nthat provides you with primitives to interact with various systems, such as file systems, networking, memory management, threads, etc.\\nStandard libraries in turn usually depend on these primitives to implement their functionality.\\nYou may also have some sort of sysroot and restrictions on RAM/ROM-usage, and perhaps some\\nspecial HW or I/Os. Overall it feels like coding on a special-purpose PC environment.","breadcrumbs":"Introduction » no_std » Hosted Environments","id":"13","title":"Hosted Environments"},"130":{"body":"Another common model for embedded concurrency is the real-time operating system\\n(RTOS). While currently less well explored in Rust, they are widely used in\\ntraditional embedded development. Open source examples include FreeRTOS and ChibiOS. These RTOSs provide support for running multiple application threads\\nwhich the CPU swaps between, either when the threads yield control (called\\ncooperative multitasking) or based on a regular timer or interrupts (preemptive\\nmultitasking). The RTOS typically provide mutexes and other synchronisation\\nprimitives, and often interoperate with hardware features such as DMA engines. At the time of writing, there are not many Rust RTOS examples to point to,\\nbut it’s an interesting area so watch this space!","breadcrumbs":"Concurrency » Real Time Operating Systems","id":"130","title":"Real Time Operating Systems"},"131":{"body":"It is becoming more common to have two or more cores in embedded processors,\\nwhich adds an extra layer of complexity to concurrency. All the examples using\\na critical section (including the cortex_m::interrupt::Mutex) assume the only\\nother execution thread is the interrupt thread, but on a multi-core system\\nthat’s no longer true. Instead, we’ll need synchronisation primitives designed\\nfor multiple cores (also called SMP, for symmetric multi-processing). These typically use the atomic instructions we saw earlier, since the\\nprocessing system will ensure that atomicity is maintained over all cores. Covering these topics in detail is currently beyond the scope of this book,\\nbut the general patterns are the same as for the single-core case.","breadcrumbs":"Concurrency » Multiple Cores","id":"131","title":"Multiple Cores"},"132":{"body":"Eventually you’ll want to use dynamic data structures (AKA collections) in your\\nprogram. std provides a set of common collections: Vec, String, HashMap, etc. All the collections implemented in std use a global dynamic\\nmemory allocator (AKA the heap). As core is, by definition, free of memory allocations these implementations\\nare not available there, but they can be found in the alloc crate\\nthat’s shipped with the compiler. If you need collections, a heap allocated implementation is not your only\\noption. You can also use fixed capacity collections; one such implementation\\ncan be found in the heapless crate. In this section, we’ll explore and compare these two implementations.","breadcrumbs":"Collections » Collections","id":"132","title":"Collections"},"133":{"body":"The alloc crate is shipped with the standard Rust distribution. To import the\\ncrate you can directly use it without declaring it as a dependency in your Cargo.toml file. #![feature(alloc)] extern crate alloc; use alloc::vec::Vec; To be able to use any collection you’ll first need use the global_allocator\\nattribute to declare the global allocator your program will use. It’s required\\nthat the allocator you select implements the GlobalAlloc trait. For completeness and to keep this section as self-contained as possible we’ll\\nimplement a simple bump pointer allocator and use that as the global allocator.\\nHowever, we strongly suggest you use a battle tested allocator from crates.io\\nin your program instead of this allocator. // Bump pointer allocator implementation use core::alloc::{GlobalAlloc, Layout};\\nuse core::cell::UnsafeCell;\\nuse core::ptr; use cortex_m::interrupt; // Bump pointer allocator for *single* core systems\\nstruct BumpPointerAlloc { head: UnsafeCell, end: usize,\\n} unsafe impl Sync for BumpPointerAlloc {} unsafe impl GlobalAlloc for BumpPointerAlloc { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { // `interrupt::free` is a critical section that makes our allocator safe // to use from within interrupts interrupt::free(|_| { let head = self.head.get(); let size = layout.size(); let align = layout.align(); let align_mask = !(align - 1); // move start up to the next alignment boundary let start = (*head + align - 1) & align_mask; if start + size > self.end { // a null pointer signal an Out Of Memory condition ptr::null_mut() } else { *head = start + size; start as *mut u8 } }) } unsafe fn dealloc(&self, _: *mut u8, _: Layout) { // this allocator never deallocates memory }\\n} // Declaration of the global memory allocator\\n// NOTE the user must ensure that the memory region `[0x2000_0100, 0x2000_0200]`\\n// is not used by other parts of the program\\n#[global_allocator]\\nstatic HEAP: BumpPointerAlloc = BumpPointerAlloc { head: UnsafeCell::new(0x2000_0100), end: 0x2000_0200,\\n}; Apart from selecting a global allocator the user will also have to define how\\nOut Of Memory (OOM) errors are handled using the unstable alloc_error_handler attribute. #![feature(alloc_error_handler)] use cortex_m::asm; #[alloc_error_handler]\\nfn on_oom(_layout: Layout) -> ! { asm::bkpt(); loop {}\\n} Once all that is in place, the user can finally use the collections in alloc. #[entry]\\nfn main() -> ! { let mut xs = Vec::new(); xs.push(42); assert!(xs.pop(), Some(42)); loop { // .. }\\n} If you have used the collections in the std crate then these will be familiar\\nas they are exact same implementation.","breadcrumbs":"Collections » Using alloc","id":"133","title":"Using alloc"},"134":{"body":"heapless requires no setup as its collections don’t depend on a global memory\\nallocator. Just use its collections and proceed to instantiate them: // heapless version: v0.4.x\\nuse heapless::Vec;\\nuse heapless::consts::*; #[entry]\\nfn main() -> ! { let mut xs: Vec<_, U8> = Vec::new(); xs.push(42).unwrap(); assert_eq!(xs.pop(), Some(42)); loop {}\\n} You’ll note two differences between these collections and the ones in alloc. First, you have to declare upfront the capacity of the collection. heapless\\ncollections never reallocate and have fixed capacities; this capacity is part of\\nthe type signature of the collection. In this case we have declared that xs\\nhas a capacity of 8 elements that is the vector can, at most, hold 8 elements.\\nThis is indicated by the U8 (see typenum) in the type signature. Second, the push method, and many other methods, return a Result. Since the heapless collections have fixed capacity all operations that insert elements\\ninto the collection can potentially fail. The API reflects this problem by\\nreturning a Result indicating whether the operation succeeded or not. In\\ncontrast, alloc collections will reallocate themselves on the heap to increase\\ntheir capacity. As of version v0.4.x all heapless collections store all their elements inline.\\nThis means that an operation like let x = heapless::Vec::new(); will allocate\\nthe collection on the stack, but it’s also possible to allocate the collection\\non a static variable, or even on the heap ( Box>).","breadcrumbs":"Collections » Using heapless","id":"134","title":"Using heapless"},"135":{"body":"Keep these in mind when choosing between heap allocated, relocatable collections\\nand fixed capacity collections.","breadcrumbs":"Collections » Trade-offs","id":"135","title":"Trade-offs"},"136":{"body":"With heap allocations Out Of Memory is always a possibility and can occur in\\nany place where a collection may need to grow: for example, all alloc::Vec.push invocations can potentially generate an OOM condition. Thus\\nsome operations can implicitly fail. Some alloc collections expose try_reserve methods that let you check for potential OOM conditions when\\ngrowing the collection but you need be proactive about using them. If you exclusively use heapless collections and you don’t use a memory\\nallocator for anything else then an OOM condition is impossible. Instead, you’ll\\nhave to deal with collections running out of capacity on a case by case basis.\\nThat is you’ll have deal with all the Results returned by methods like Vec.push. OOM failures can be harder to debug than say unwrap-ing on all Results\\nreturned by heapless::Vec.push because the observed location of failure may not match with the location of the cause of the problem. For example, even vec.reserve(1) can trigger an OOM if the allocator is nearly exhausted because\\nsome other collection was leaking memory (memory leaks are possible in safe\\nRust).","breadcrumbs":"Collections » Out Of Memory and error handling","id":"136","title":"Out Of Memory and error handling"},"137":{"body":"Reasoning about memory usage of heap allocated collections is hard because the\\ncapacity of long lived collections can change at runtime. Some operations may\\nimplicitly reallocate the collection increasing its memory usage, and some\\ncollections expose methods like shrink_to_fit that can potentially reduce the\\nmemory used by the collection – ultimately, it’s up to the allocator to decide\\nwhether to actually shrink the memory allocation or not. Additionally, the\\nallocator may have to deal with memory fragmentation which can increase the apparent memory usage. On the other hand if you exclusively use fixed capacity collections, store\\nmost of them in static variables and set a maximum size for the call stack\\nthen the linker will detect if you try to use more memory than what’s physically\\navailable. Furthermore, fixed capacity collections allocated on the stack will be reported\\nby -Z emit-stack-sizes flag which means that tools that analyze stack usage\\n(like stack-sizes) will include them in their analysis. However, fixed capacity collections can not be shrunk which can result in\\nlower load factors (the ratio between the size of the collection and its\\ncapacity) than what relocatable collections can achieve.","breadcrumbs":"Collections » Memory usage","id":"137","title":"Memory usage"},"138":{"body":"If you are building time sensitive applications or hard real time applications\\nthen you care, maybe a lot, about the worst case execution time of the different\\nparts of your program. The alloc collections can reallocate so the WCET of operations that may grow\\nthe collection will also include the time it takes to reallocate the collection,\\nwhich itself depends on the runtime capacity of the collection. This makes it\\nhard to determine the WCET of, for example, the alloc::Vec.push operation as\\nit depends on both the allocator being used and its runtime capacity. On the other hand fixed capacity collections never reallocate so all operations\\nhave a predictable execution time. For example, heapless::Vec.push executes in\\nconstant time.","breadcrumbs":"Collections » Worst Case Execution Time (WCET)","id":"138","title":"Worst Case Execution Time (WCET)"},"139":{"body":"alloc requires setting up a global allocator whereas heapless does not.\\nHowever, heapless requires you to pick the capacity of each collection that\\nyou instantiate. The alloc API will be familiar to virtually every Rust developer. The heapless API tries to closely mimic the alloc API but it will never be\\nexactly the same due to its explicit error handling – some developers may feel\\nthe explicit error handling is excessive or too cumbersome.","breadcrumbs":"Collections » Ease of use","id":"139","title":"Ease of use"},"14":{"body":"In a bare metal environment no code has been loaded before your program.\\nWithout the software provided by an OS we can not load the standard library.\\nInstead the program, along with the crates it uses, can only use the hardware (bare metal) to run.\\nTo prevent rust from loading the standard library use no_std.\\nThe platform-agnostic parts of the standard library are available through libcore.\\nlibcore also excludes things which are not always desirable in an embedded environment.\\nOne of these things is a memory allocator for dynamic memory allocation.\\nIf you require this or any other functionalities there are often crates which provide these.","breadcrumbs":"Introduction » no_std » Bare Metal Environments","id":"14","title":"Bare Metal Environments"},"140":{"body":"This chapter aims to collect various useful design patterns for embedded Rust.","breadcrumbs":"Design Patterns » Design Patterns","id":"140","title":"Design Patterns"},"141":{"body":"This is a set of common and recommended patterns for writing hardware\\nabstraction layers (HALs) for microcontrollers in Rust. These patterns are\\nintended to be used in addition to the existing Rust API Guidelines when\\nwriting HALs for microcontrollers. Checklist Naming Interoperability Predictability GPIO","breadcrumbs":"Design Patterns » HALs » HAL Design Patterns","id":"141","title":"HAL Design Patterns"},"142":{"body":"Naming (crate aligns with Rust naming conventions) The crate is named appropriately ( C-CRATE-NAME) Interoperability (crate interacts nicely with other library functionality) Wrapper types provide a destructor method ( C-FREE) HALs reexport their register access crate ( C-REEXPORT-PAC) Types implement the embedded-hal traits ( C-HAL-TRAITS) Predictability (crate enables legible code that acts how it looks) Constructors are used instead of extension traits ( C-CTOR) GPIO Interfaces (GPIO Interfaces follow a common pattern) Pin types are zero-sized by default ( C-ZST-PIN) Pin types provide methods to erase pin and port ( C-ERASED-PIN) Pin state should be encoded as type parameters ( C-PIN-STATE)","breadcrumbs":"Design Patterns » HALs » Checklist » HAL Design Patterns Checklist","id":"142","title":"HAL Design Patterns Checklist"},"143":{"body":"","breadcrumbs":"Design Patterns » HALs » Naming » Naming","id":"143","title":"Naming"},"144":{"body":"HAL crates should be named after the chip or family of chips they aim to\\nsupport. Their name should end with -hal to distinguish them from register\\naccess crates. The name should not contain underscores (use dashes instead).","breadcrumbs":"Design Patterns » HALs » Naming » The crate is named appropriately (C-CRATE-NAME)","id":"144","title":"The crate is named appropriately (C-CRATE-NAME)"},"145":{"body":"","breadcrumbs":"Design Patterns » HALs » Interoperability » Interoperability","id":"145","title":"Interoperability"},"146":{"body":"Any non- Copy wrapper type provided by the HAL should provide a free method\\nthat consumes the wrapper and returns back the raw peripheral (and possibly\\nother objects) it was created from. The method should shut down and reset the peripheral if necessary. Calling new\\nwith the raw peripheral returned by free should not fail due to an unexpected\\nstate of the peripheral. If the HAL type requires other non- Copy objects to be constructed (for example\\nI/O pins), any such object should be released and returned by free as well. free should return a tuple in that case. For example: #![allow(unused)] fn main() { pub struct TIMER0;\\npub struct Timer(TIMER0); impl Timer { pub fn new(periph: TIMER0) -> Self { Self(periph) } pub fn free(self) -> TIMER0 { self.0 }\\n} }","breadcrumbs":"Design Patterns » HALs » Interoperability » Wrapper types provide a destructor method (C-FREE)","id":"146","title":"Wrapper types provide a destructor method (C-FREE)"},"147":{"body":"HALs can be written on top of svd2rust-generated PACs, or on top of other\\ncrates that provide raw register access. HALs should always reexport the\\nregister access crate they are based on in their crate root. A PAC should be reexported under the name pac, regardless of the actual name\\nof the crate, as the name of the HAL should already make it clear what PAC is\\nbeing accessed.","breadcrumbs":"Design Patterns » HALs » Interoperability » HALs reexport their register access crate (C-REEXPORT-PAC)","id":"147","title":"HALs reexport their register access crate (C-REEXPORT-PAC)"},"148":{"body":"Types provided by the HAL should implement all applicable traits provided by the embedded-hal crate. Multiple traits may be implemented for the same type.","breadcrumbs":"Design Patterns » HALs » Interoperability » Types implement the embedded-hal traits (C-HAL-TRAITS)","id":"148","title":"Types implement the embedded-hal traits (C-HAL-TRAITS)"},"149":{"body":"","breadcrumbs":"Design Patterns » HALs » Predictability » Predictability","id":"149","title":"Predictability"},"15":{"body":"As mentioned before using libstd requires some sort of system integration, but this is not only because libstd is just providing a common way of accessing OS abstractions, it also provides a runtime.\\nThis runtime, among other things, takes care of setting up stack overflow protection, processing command line arguments,\\nand spawning the main thread before a program’s main function is invoked. This runtime also won’t be available in a no_std environment.","breadcrumbs":"Introduction » no_std » The libstd Runtime","id":"15","title":"The libstd Runtime"},"150":{"body":"All peripherals to which the HAL adds functionality should be wrapped in a new\\ntype, even if no additional fields are required for that functionality. Extension traits implemented for the raw peripheral should be avoided.","breadcrumbs":"Design Patterns » HALs » Predictability » Constructors are used instead of extension traits (C-CTOR)","id":"150","title":"Constructors are used instead of extension traits (C-CTOR)"},"151":{"body":"The Rust compiler does not by default perform full inlining across crate\\nboundaries. As embedded applications are sensitive to unexpected code size\\nincreases, #[inline] should be used to guide the compiler as follows: All “small” functions should be marked #[inline]. What qualifies as “small”\\nis subjective, but generally all functions that are expected to compile down\\nto single-digit instruction sequences qualify as small. Functions that are very likely to take constant values as parameters should be\\nmarked as #[inline]. This enables the compiler to compute even complicated\\ninitialization logic at compile time, provided the function inputs are known.","breadcrumbs":"Design Patterns » HALs » Predictability » Methods are decorated with #[inline] where appropriate (C-INLINE)","id":"151","title":"Methods are decorated with #[inline] where appropriate (C-INLINE)"},"152":{"body":"","breadcrumbs":"Design Patterns » HALs » GPIO » Recommendations for GPIO Interfaces","id":"152","title":"Recommendations for GPIO Interfaces"},"153":{"body":"GPIO Interfaces exposed by the HAL should provide dedicated zero-sized types for\\neach pin on every interface or port, resulting in a zero-cost GPIO abstraction\\nwhen all pin assignments are statically known. Each GPIO Interface or Port should implement a split method returning a\\nstruct with every pin. Example: #![allow(unused)] fn main() {\\npub struct PA0;\\npub struct PA1;\\n// ... pub struct PortA; impl PortA { pub fn split(self) -> PortAPins { PortAPins { pa0: PA0, pa1: PA1, // ... } }\\n} pub struct PortAPins { pub pa0: PA0, pub pa1: PA1, // ...\\n} }","breadcrumbs":"Design Patterns » HALs » GPIO » Pin types are zero-sized by default (C-ZST-PIN)","id":"153","title":"Pin types are zero-sized by default (C-ZST-PIN)"},"154":{"body":"Pins should provide type erasure methods that move their properties from\\ncompile time to runtime, and allow more flexibility in applications. Example: #![allow(unused)] fn main() {\\n/// Port A, pin 0.\\npub struct PA0; impl PA0 { pub fn erase_pin(self) -> PA { PA { pin: 0 } }\\n} /// A pin on port A.\\npub struct PA { /// The pin number. pin: u8,\\n} impl PA { pub fn erase_port(self) -> Pin { Pin { port: Port::A, pin: self.pin, } }\\n} pub struct Pin { port: Port, pin: u8, // (these fields can be packed to reduce the memory footprint)\\n} enum Port { A, B, C, D,\\n} }","breadcrumbs":"Design Patterns » HALs » GPIO » Pin types provide methods to erase pin and port (C-ERASED-PIN)","id":"154","title":"Pin types provide methods to erase pin and port (C-ERASED-PIN)"},"155":{"body":"Pins may be configured as input or output with different characteristics\\ndepending on the chip or family. This state should be encoded in the type system\\nto prevent use of pins in incorrect states. Additional, chip-specific state (eg. drive strength) may also be encoded in this\\nway, using additional type parameters. Methods for changing the pin state should be provided as into_input and into_output methods. Additionally, with_{input,output}_state methods should be provided that\\ntemporarily reconfigure a pin in a different state without moving it. The following methods should be provided for every pin type (that is, both\\nerased and non-erased pin types should provide the same API): pub fn into_input(self, input: N) -> Pin pub fn into_output(self, output: N) -> Pin pub fn with_input_state( &mut self, input: N, f: impl FnOnce(&mut PA1) -> R,\\n) -> R pub fn with_output_state( &mut self, output: N, f: impl FnOnce(&mut PA1) -> R,\\n) -> R Pin state should be bounded by sealed traits. Users of the HAL should have no\\nneed to add their own state. The traits can provide HAL-specific methods\\nrequired to implement the pin state API. Example: #![allow(unused)] fn main() { use std::marker::PhantomData;\\nmod sealed { pub trait Sealed {}\\n} pub trait PinState: sealed::Sealed {}\\npub trait OutputState: sealed::Sealed {}\\npub trait InputState: sealed::Sealed { // ...\\n} pub struct Output { _p: PhantomData,\\n} impl PinState for Output {}\\nimpl sealed::Sealed for Output {} pub struct PushPull;\\npub struct OpenDrain; impl OutputState for PushPull {}\\nimpl OutputState for OpenDrain {}\\nimpl sealed::Sealed for PushPull {}\\nimpl sealed::Sealed for OpenDrain {} pub struct Input { _p: PhantomData,\\n} impl PinState for Input {}\\nimpl sealed::Sealed for Input {} pub struct Floating;\\npub struct PullUp;\\npub struct PullDown; impl InputState for Floating {}\\nimpl InputState for PullUp {}\\nimpl InputState for PullDown {}\\nimpl sealed::Sealed for Floating {}\\nimpl sealed::Sealed for PullUp {}\\nimpl sealed::Sealed for PullDown {} pub struct PA1 { _p: PhantomData,\\n} impl PA1 { pub fn into_input(self, input: N) -> PA1> { todo!() } pub fn into_output(self, output: N) -> PA1> { todo!() } pub fn with_input_state( &mut self, input: N, f: impl FnOnce(&mut PA1) -> R, ) -> R { todo!() } pub fn with_output_state( &mut self, output: N, f: impl FnOnce(&mut PA1) -> R, ) -> R { todo!() }\\n} // Same for `PA` and `Pin`, and other pin types. }","breadcrumbs":"Design Patterns » HALs » GPIO » Pin state should be encoded as type parameters (C-PIN-STATE)","id":"155","title":"Pin state should be encoded as type parameters (C-PIN-STATE)"},"156":{"body":"This chapter collects a variety of tips that might be useful to experienced\\nembedded C developers looking to start writing Rust. It will especially\\nhighlight how things you might already be used to in C are different in Rust.","breadcrumbs":"Tips for embedded C developers » Tips for embedded C developers","id":"156","title":"Tips for embedded C developers"},"157":{"body":"In embedded C it is very common to use the preprocessor for a variety of\\npurposes, such as: Compile-time selection of code blocks with #ifdef Compile-time array sizes and computations Macros to simplify common patterns (to avoid function call overhead) In Rust there is no preprocessor, and so many of these use cases are addressed\\ndifferently. In the rest of this section we cover various alternatives to\\nusing the preprocessor.","breadcrumbs":"Tips for embedded C developers » Preprocessor","id":"157","title":"Preprocessor"},"158":{"body":"The closest match to #ifdef ... #endif in Rust are Cargo features. These\\nare a little more formal than the C preprocessor: all possible features are\\nexplicitly listed per crate, and can only be either on or off. Features are\\nturned on when you list a crate as a dependency, and are additive: if any crate\\nin your dependency tree enables a feature for another crate, that feature will\\nbe enabled for all users of that crate. For example, you might have a crate which provides a library of signal\\nprocessing primitives. Each one might take some extra time to compile or\\ndeclare some large table of constants which you’d like to avoid. You could\\ndeclare a Cargo feature for each component in your Cargo.toml: [features]\\nFIR = []\\nIIR = [] Then, in your code, use #[cfg(feature=\\"FIR\\")] to control what is included. #![allow(unused)] fn main() {\\n/// In your top-level lib.rs #[cfg(feature=\\"FIR\\")]\\npub mod fir; #[cfg(feature=\\"IIR\\")]\\npub mod iir; } You can similarly include code blocks only if a feature is not enabled, or if\\nany combination of features are or are not enabled. Additionally, Rust provides a number of automatically-set conditions you can\\nuse, such as target_arch to select different code based on architecture. For\\nfull details of the conditional compilation support, refer to the conditional compilation chapter of the Rust reference. The conditional compilation will only apply to the next statement or block. If\\na block can not be used in the current scope then the cfg attribute will\\nneed to be used multiple times. It’s worth noting that most of the time it is\\nbetter to simply include all the code and allow the compiler to remove dead\\ncode when optimising: it’s simpler for you and your users, and in general the\\ncompiler will do a good job of removing unused code.","breadcrumbs":"Tips for embedded C developers » Compile-Time Code Selection","id":"158","title":"Compile-Time Code Selection"},"159":{"body":"Rust supports const fn, functions which are guaranteed to be evaluable at\\ncompile-time and can therefore be used where constants are required, such as\\nin the size of arrays. This can be used alongside features mentioned above,\\nfor example: #![allow(unused)] fn main() {\\nconst fn array_size() -> usize { #[cfg(feature=\\"use_more_ram\\")] { 1024 } #[cfg(not(feature=\\"use_more_ram\\"))] { 128 }\\n} static BUF: [u32; array_size()] = [0u32; array_size()]; } These are new to stable Rust as of 1.31, so documentation is still sparse. The\\nfunctionality available to const fn is also very limited at the time of\\nwriting; in future Rust releases it is expected to expand on what is permitted\\nin a const fn.","breadcrumbs":"Tips for embedded C developers » Compile-Time Sizes and Computation","id":"159","title":"Compile-Time Sizes and Computation"},"16":{"body":"#![no_std] is a crate-level attribute that indicates that the crate will link to the core-crate instead of the std-crate.\\nThe libcore crate in turn is a platform-agnostic subset of the std crate\\nwhich makes no assumptions about the system the program will run on.\\nAs such, it provides APIs for language primitives like floats, strings and slices, as well as APIs that expose processor features\\nlike atomic operations and SIMD instructions. However it lacks APIs for anything that involves platform integration.\\nBecause of these properties no_std and libcore code can be used for any kind of\\nbootstrapping (stage 0) code like bootloaders, firmware or kernels.","breadcrumbs":"Introduction » no_std » Summary","id":"16","title":"Summary"},"160":{"body":"Rust provides an extremely powerful macro system. While the C preprocessor\\noperates almost directly on the text of your source code, the Rust macro system\\noperates at a higher level. There are two varieties of Rust macro: macros by\\nexample and procedural macros. The former are simpler and most common; they\\nlook like function calls and can expand to a complete expression, statement,\\nitem, or pattern. Procedural macros are more complex but permit extremely\\npowerful additions to the Rust language: they can transform arbitrary Rust\\nsyntax into new Rust syntax. In general, where you might have used a C preprocessor macro, you probably want\\nto see if a macro-by-example can do the job instead. They can be defined in\\nyour crate and easily used by your own crate or exported for other users. Be\\naware that since they must expand to complete expressions, statements, items,\\nor patterns, some use cases of C preprocessor macros will not work, for example\\na macro that expands to part of a variable name or an incomplete set of items\\nin a list. As with Cargo features, it is worth considering if you even need the macro. In\\nmany cases a regular function is easier to understand and will be inlined to\\nthe same code as a macro. The #[inline] and #[inline(always)] attributes\\ngive you further control over this process, although care should be taken here\\nas well — the compiler will automatically inline functions from the same crate\\nwhere appropriate, so forcing it to do so inappropriately might actually lead\\nto decreased performance. Explaining the entire Rust macro system is out of scope for this tips page, so\\nyou are encouraged to consult the Rust documentation for full details.","breadcrumbs":"Tips for embedded C developers » Macros","id":"160","title":"Macros"},"161":{"body":"Most Rust crates are built using Cargo (although it is not required). This\\ntakes care of many difficult problems with traditional build systems. However,\\nyou may wish to customise the build process. Cargo provides build.rs\\nscripts for this purpose. They are Rust scripts which can interact with the\\nCargo build system as required. Common use cases for build scripts include: provide build-time information, for example statically embedding the build\\ndate or Git commit hash into your executable generate linker scripts at build time depending on selected features or other\\nlogic change the Cargo build configuration add extra static libraries to link against At present there is no support for post-build scripts, which you might\\ntraditionally have used for tasks like automatic generation of binaries from\\nthe build objects or printing build information.","breadcrumbs":"Tips for embedded C developers » Build System","id":"161","title":"Build System"},"162":{"body":"Using Cargo for your build system also simplifies cross-compiling. In most\\ncases it suffices to tell Cargo --target thumbv6m-none-eabi and find a\\nsuitable executable in target/thumbv6m-none-eabi/debug/myapp. For platforms not natively supported by Rust, you will need to build libcore\\nfor that target yourself. On such platforms, Xargo can be used as a stand-in\\nfor Cargo which automatically builds libcore for you.","breadcrumbs":"Tips for embedded C developers » Cross-Compiling","id":"162","title":"Cross-Compiling"},"163":{"body":"In C you are probably used to accessing arrays directly by their index: int16_t arr[16];\\nint i;\\nfor(i=0; iRTOS interoperability: Zephyr Project We are collecting examples and use cases for this on our issue tracker in issue #62.","breadcrumbs":"Interoperability » Interoperability with RTOSs","id":"170","title":"Interoperability with RTOSs"},"171":{"body":"Using C or C++ inside of a Rust project consists of two major parts: Wrapping the exposed C API for use with Rust Building your C or C++ code to be integrated with the Rust code As C++ does not have a stable ABI for the Rust compiler to target, it is recommended to use the C ABI when combining Rust with C or C++.","breadcrumbs":"Interoperability » A little C with your Rust » A little C with your Rust","id":"171","title":"A little C with your Rust"},"172":{"body":"Before consuming C or C++ code from Rust, it is necessary to define (in Rust) what data types and function signatures exist in the linked code. In C or C++, you would include a header ( .h or .hpp) file which defines this data. In Rust, it is necessary to either manually translate these definitions to Rust, or use a tool to generate these definitions. First, we will cover manually translating these definitions from C/C++ to Rust.","breadcrumbs":"Interoperability » A little C with your Rust » Defining the interface","id":"172","title":"Defining the interface"},"173":{"body":"Typically, libraries written in C or C++ will provide a header file defining all types and functions used in public interfaces. An example file may look like this: /* File: cool.h */\\ntypedef struct CoolStruct { int x; int y;\\n} CoolStruct; void cool_function(int i, char c, CoolStruct* cs); When translated to Rust, this interface would look as such: /* File: cool_bindings.rs */\\n#[repr(C)]\\npub struct CoolStruct { pub x: cty::c_int, pub y: cty::c_int,\\n} extern \\"C\\" { pub fn cool_function( i: cty::c_int, c: cty::c_char, cs: *mut CoolStruct );\\n} Let’s take a look at this definition one piece at a time, to explain each of the parts. #[repr(C)]\\npub struct CoolStruct { ... } By default, Rust does not guarantee order, padding, or the size of data included in a struct. In order to guarantee compatibility with C code, we include the #[repr(C)] attribute, which instructs the Rust compiler to always use the same rules C does for organizing data within a struct. pub x: cty::c_int,\\npub y: cty::c_int, Due to the flexibility of how C or C++ defines an int or char, it is recommended to use primitive data types defined in cty, which will map types from C to types in Rust. extern \\"C\\" { pub fn cool_function( ... ); } This statement defines the signature of a function that uses the C ABI, called cool_function. By defining the signature without defining the body of the function, the definition of this function will need to be provided elsewhere, or linked into the final library or binary from a static library. i: cty::c_int, c: cty::c_char, cs: *mut CoolStruct Similar to our datatype above, we define the datatypes of the function arguments using C-compatible definitions. We also retain the same argument names, for clarity. We have one new type here, *mut CoolStruct. As C does not have a concept of Rust’s references, which would look like this: &mut CoolStruct, we instead have a raw pointer. As dereferencing this pointer is unsafe, and the pointer may in fact be a null pointer, care must be taken to ensure the guarantees typical of Rust when interacting with C or C++ code.","breadcrumbs":"Interoperability » A little C with your Rust » Wrapping C functions and Datatypes","id":"173","title":"Wrapping C functions and Datatypes"},"174":{"body":"Rather than manually generating these interfaces, which may be tedious and error prone, there is a tool called bindgen which will perform these conversions automatically. For instructions of the usage of bindgen, please refer to the bindgen user’s manual, however the typical process consists of the following: Gather all C or C++ headers defining interfaces or datatypes you would like to use with Rust. Write a bindings.h file, which #include \\"...\\"’s each of the files you gathered in step one. Feed this bindings.h file, along with any compilation flags used to compile\\nyour code into bindgen. Tip: use Builder.ctypes_prefix(\\"cty\\") / --ctypes-prefix=cty and Builder.use_core() / --use-core to make the generated code #![no_std] compatible. bindgen will produce the generated Rust code to the output of the terminal window. This output may be piped to a file in your project, such as bindings.rs. You may use this file in your Rust project to interact with C/C++ code compiled and linked as an external library. Tip: don’t forget to use the cty crate if your types in the generated bindings are prefixed with cty.","breadcrumbs":"Interoperability » A little C with your Rust » Automatically generating the interface","id":"174","title":"Automatically generating the interface"},"175":{"body":"As the Rust compiler does not directly know how to compile C or C++ code (or code from any other language, which presents a C interface), it is necessary to compile your non-Rust code ahead of time. For embedded projects, this most commonly means compiling the C/C++ code to a static archive (such as cool-library.a), which can then be combined with your Rust code at the final linking step. If the library you would like to use is already distributed as a static archive, it is not necessary to rebuild your code. Just convert the provided interface header file as described above, and include the static archive at compile/link time. If your code exists as a source project, it will be necessary to compile your C/C++ code to a static library, either by triggering your existing build system (such as make, CMake, etc.), or by porting the necessary compilation steps to use a tool called the cc crate. For both of these steps, it is necessary to use a build.rs script.","breadcrumbs":"Interoperability » A little C with your Rust » Building your C/C++ code","id":"175","title":"Building your C/C++ code"},"176":{"body":"A build.rs script is a file written in Rust syntax, that is executed on your compilation machine, AFTER dependencies of your project have been built, but BEFORE your project is built. The full reference may be found here. build.rs scripts are useful for generating code (such as via bindgen), calling out to external build systems such as Make, or directly compiling C/C++ through use of the cc crate.","breadcrumbs":"Interoperability » A little C with your Rust » Rust build.rs build scripts","id":"176","title":"Rust build.rs build scripts"},"177":{"body":"For projects with complex external projects or build systems, it may be easiest to use std::process::Command to “shell out” to your other build systems by traversing relative paths, calling a fixed command (such as make library), and then copying the resulting static library to the proper location in the target build directory. While your crate may be targeting a no_std embedded platform, your build.rs executes only on machines compiling your crate. This means you may use any Rust crates which will run on your compilation host.","breadcrumbs":"Interoperability » A little C with your Rust » Triggering external build systems","id":"177","title":"Triggering external build systems"},"178":{"body":"For projects with limited dependencies or complexity, or for projects where it is difficult to modify the build system to produce a static library (rather than a final binary or executable), it may be easier to instead utilize the cc crate, which provides an idiomatic Rust interface to the compiler provided by the host. In the simplest case of compiling a single C file as a dependency to a static library, an example build.rs script using the cc crate would look like this: fn main() { cc::Build::new() .file(\\"src/foo.c\\") .compile(\\"foo\\");\\n} The build.rs is placed at the root of the package. Then cargo build will compile and execute it before the build of the package. A static archive named libfoo.a is generated and placed in the target directory.","breadcrumbs":"Interoperability » A little C with your Rust » Building C/C++ code with the cc crate","id":"178","title":"Building C/C++ code with the cc crate"},"179":{"body":"Using Rust code inside a C or C++ project mostly consists of two parts. Creating a C-friendly API in Rust Embedding your Rust project into an external build system Apart from cargo and meson, most build systems don’t have native Rust support.\\nSo you’re most likely best off just using cargo for compiling your crate and\\nany dependencies.","breadcrumbs":"Interoperability » A little Rust with your C » A little Rust with your C","id":"179","title":"A little Rust with your C"},"18":{"body":"RFC-1184","breadcrumbs":"Introduction » no_std » See Also","id":"18","title":"See Also"},"180":{"body":"Create a new cargo project as usual. There are flags to tell cargo to emit a systems library, instead of\\nits regular rust target.\\nThis also allows you to set a different output name for your library,\\nif you want it to differ from the rest of your crate. [lib]\\nname = \\"your_crate\\"\\ncrate-type = [\\"cdylib\\"] # Creates dynamic lib\\n# crate-type = [\\"staticlib\\"] # Creates static lib","breadcrumbs":"Interoperability » A little Rust with your C » Setting up a project","id":"180","title":"Setting up a project"},"181":{"body":"Because C++ has no stable ABI for the Rust compiler to target, we use C for\\nany interoperability between different languages. This is no exception when using Rust\\ninside of C and C++ code.","breadcrumbs":"Interoperability » A little Rust with your C » Building a C API","id":"181","title":"Building a C API"},"182":{"body":"The Rust compiler mangles symbol names differently than native code linkers expect.\\nAs such, any function that Rust exports to be used outside of Rust needs to be told\\nnot to be mangled by the compiler.","breadcrumbs":"Interoperability » A little Rust with your C » #[no_mangle]","id":"182","title":"#[no_mangle]"},"183":{"body":"By default, any function you write in Rust will use the\\nRust ABI (which is also not stabilized).\\nInstead, when building outwards facing FFI APIs we need to\\ntell the compiler to use the system ABI. Depending on your platform, you might want to target a specific ABI version, which are\\ndocumented here. Putting these parts together, you get a function that looks roughly like this. #[no_mangle]\\npub extern \\"C\\" fn rust_function() { } Just as when using C code in your Rust project you now need to transform data\\nfrom and to a form that the rest of the application will understand.","breadcrumbs":"Interoperability » A little Rust with your C » extern \\"C\\"","id":"183","title":"extern \\"C\\""},"184":{"body":"So then, that’s one half of the problem solved.\\nHow do you use this now? This very much depends on your project and/or build system cargo will create a my_lib.so/ my_lib.dll or my_lib.a file,\\ndepending on your platform and settings. This library can simply be linked\\nby your build system. However, calling a Rust function from C requires a header file to declare\\nthe function signatures. Every function in your Rust-ffi API needs to have a corresponding header function. #[no_mangle]\\npub extern \\"C\\" fn rust_function() {} would then become void rust_function(); etc. There is a tool to automate this process,\\ncalled cbindgen which analyses your Rust code\\nand then generates headers for your C and C++ projects from it. At this point, using the Rust functions from C\\nis as simple as including the header and calling them! #include \\"my-rust-project.h\\"\\nrust_function();","breadcrumbs":"Interoperability » A little Rust with your C » Linking and greater project context.","id":"184","title":"Linking and greater project context."},"185":{"body":"","breadcrumbs":"Unsorted topics » Unsorted topics","id":"185","title":"Unsorted topics"},"186":{"body":"Everyone wants their program to be super fast and super small but it’s usually\\nnot possible to have both characteristics. This section discusses the\\ndifferent optimization levels that rustc provides and how they affect the\\nexecution time and binary size of a program.","breadcrumbs":"Unsorted topics » Optimizations: The speed size tradeoff » Optimizations: the speed size tradeoff","id":"186","title":"Optimizations: the speed size tradeoff"},"187":{"body":"This is the default. When you call cargo build you use the development (AKA dev) profile. This profile is optimized for debugging so it enables debug\\ninformation and does not enable any optimizations, i.e. it uses -C opt-level = 0. At least for bare metal development, debuginfo is zero cost in the sense that it\\nwon’t occupy space in Flash / ROM so we actually recommend that you enable\\ndebuginfo in the release profile – it is disabled by default. That will let you\\nuse breakpoints when debugging release builds. [profile.release]\\n# symbols are nice and they don\'t increase the size on Flash\\ndebug = true No optimizations is great for debugging because stepping through the code feels\\nlike you are executing the program statement by statement, plus you can print\\nstack variables and function arguments in GDB. When the code is optimized, trying\\nto print variables results in $0 = being printed. The biggest downside of the dev profile is that the resulting binary will be\\nhuge and slow. The size is usually more of a problem because unoptimized\\nbinaries can occupy dozens of KiB of Flash, which your target device may not\\nhave – the result: your unoptimized binary doesn’t fit in your device! Can we have smaller, debugger friendly binaries? Yes, there’s a trick.","breadcrumbs":"Unsorted topics » Optimizations: The speed size tradeoff » No optimizations","id":"187","title":"No optimizations"},"188":{"body":"There’s a Cargo feature named profile-overrides that lets you\\noverride the optimization level of dependencies. You can use that feature to\\noptimize all dependencies for size while keeping the top crate unoptimized and\\ndebugger friendly. Beware that generic code can sometimes be optimized alongside the crate where it\\nis instantiated, rather than the crate where it is defined. If you create an\\ninstance of a generic struct in your application and find that it pulls in code\\nwith a large footprint, it may be that increasing the optimisation level of the\\nrelevant dependencies has no effect. Here’s an example: # Cargo.toml\\n[package]\\nname = \\"app\\"\\n# .. [profile.dev.package.\\"*\\"] # +\\nopt-level = \\"z\\" # + Without the override: $ cargo size --bin app -- -A\\napp :\\nsection size addr\\n.vector_table 1024 0x8000000\\n.text 9060 0x8000400\\n.rodata 1708 0x8002780\\n.data 0 0x20000000\\n.bss 4 0x20000000 With the override: $ cargo size --bin app -- -A\\napp :\\nsection size addr\\n.vector_table 1024 0x8000000\\n.text 3490 0x8000400\\n.rodata 1100 0x80011c0\\n.data 0 0x20000000\\n.bss 4 0x20000000 That’s a 6 KiB reduction in Flash usage without any loss in the debuggability of\\nthe top crate. If you step into a dependency then you’ll start seeing those messages again but it’s usually the case that you want\\nto debug the top crate and not the dependencies. And if you do need to debug a\\ndependency then you can use the profile-overrides feature to exclude a\\nparticular dependency from being optimized. See example below: # .. # don\'t optimize the `cortex-m-rt` crate\\n[profile.dev.package.cortex-m-rt] # +\\nopt-level = 0 # + # but do optimize all the other dependencies\\n[profile.dev.package.\\"*\\"]\\ncodegen-units = 1 # better optimizations\\nopt-level = \\"z\\" Now the top crate and cortex-m-rt are debugger friendly!","breadcrumbs":"Unsorted topics » Optimizations: The speed size tradeoff » Optimizing dependencies","id":"188","title":"Optimizing dependencies"},"189":{"body":"As of 2018-09-18 rustc supports three “optimize for speed” levels: opt-level = 1, 2 and 3. When you run cargo build --release you are using the release\\nprofile which defaults to opt-level = 3. Both opt-level = 2 and 3 optimize for speed at the expense of binary size,\\nbut level 3 does more vectorization and inlining than level 2. In\\nparticular, you’ll see that at opt-level equal to or greater than 2 LLVM will\\nunroll loops. Loop unrolling has a rather high cost in terms of Flash / ROM\\n(e.g. from 26 bytes to 194 for a zero this array loop) but can also halve the\\nexecution time given the right conditions (e.g. number of iterations is big\\nenough). Currently there’s no way to disable loop unrolling in opt-level = 2 and 3 so\\nif you can’t afford its cost you should optimize your program for size.","breadcrumbs":"Unsorted topics » Optimizations: The speed size tradeoff » Optimize for speed","id":"189","title":"Optimize for speed"},"19":{"body":"Dealing with microcontrollers involves using several different tools as we’ll be\\ndealing with an architecture different than your laptop’s and we’ll have to run\\nand debug programs on a remote device. We’ll use all the tools listed below. Any recent version should work when a\\nminimum version is not specified, but we have listed the versions we have\\ntested. Rust 1.31, 1.31-beta, or a newer toolchain PLUS ARM Cortex-M compilation\\nsupport. cargo-binutils ~0.1.4 qemu-system-arm. Tested versions: 3.0.0 OpenOCD >=0.8. Tested versions: v0.9.0 and v0.10.0 GDB with ARM support. Version 7.12 or newer highly recommended. Tested\\nversions: 7.10, 7.11, 7.12 and 8.1 cargo-generate or git.\\nThese tools are optional but will make it easier to follow along with the book. The text below explains why we are using these tools. Installation instructions\\ncan be found on the next page.","breadcrumbs":"Introduction » Tooling » Tooling","id":"19","title":"Tooling"},"190":{"body":"As of 2018-09-18 rustc supports two “optimize for size” levels: opt-level = \\"s\\" and \\"z\\". These names were inherited from clang / LLVM and are not too\\ndescriptive but \\"z\\" is meant to give the idea that it produces smaller\\nbinaries than \\"s\\". If you want your release binaries to be optimized for size then change the profile.release.opt-level setting in Cargo.toml as shown below. [profile.release]\\n# or \\"z\\"\\nopt-level = \\"s\\" These two optimization levels greatly reduce LLVM’s inline threshold, a metric\\nused to decide whether to inline a function or not. One of Rust principles are\\nzero cost abstractions; these abstractions tend to use a lot of newtypes and\\nsmall functions to hold invariants (e.g. functions that borrow an inner value\\nlike deref, as_ref) so a low inline threshold can make LLVM miss\\noptimization opportunities (e.g. eliminate dead branches, inline calls to\\nclosures). When optimizing for size you may want to try increasing the inline threshold to\\nsee if that has any effect on the binary size. The recommended way to change the\\ninline threshold is to append the -C inline-threshold flag to the other\\nrustflags in .cargo/config.toml. # .cargo/config.toml\\n# this assumes that you are using the cortex-m-quickstart template\\n[target.\'cfg(all(target_arch = \\"arm\\", target_os = \\"none\\"))\']\\nrustflags = [ # .. \\"-C\\", \\"inline-threshold=123\\", # +\\n] What value to use? As of 1.29.0 these are the inline thresholds that the\\ndifferent optimization levels use: opt-level = 3 uses 275 opt-level = 2 uses 225 opt-level = \\"s\\" uses 75 opt-level = \\"z\\" uses 25 You should try 225 and 275 when optimizing for size.","breadcrumbs":"Unsorted topics » Optimizations: The speed size tradeoff » Optimize for size","id":"190","title":"Optimize for size"},"191":{"body":"If you want to perform math related functionality like calculating the squareroot or\\nthe exponential of a number and you have the full standard library available, your code\\nmight look like this: //! Some mathematical functions with standard support available fn main() { let float: f32 = 4.82832; let floored_float = float.floor(); let sqrt_of_four = floored_float.sqrt(); let sinus_of_four = floored_float.sin(); let exponential_of_four = floored_float.exp(); println!(\\"Floored test float {} to {}\\", float, floored_float); println!(\\"The square root of {} is {}\\", floored_float, sqrt_of_four); println!(\\"The sinus of four is {}\\", sinus_of_four); println!( \\"The exponential of four to the base e is {}\\", exponential_of_four )\\n} Without standard library support, these functions are not available.\\nAn external crate like libm can be used instead. The example code\\nwould then look like this: #![no_main]\\n#![no_std] use panic_halt as _; use cortex_m_rt::entry;\\nuse cortex_m_semihosting::{debug, hprintln};\\nuse libm::{exp, floorf, sin, sqrtf}; #[entry]\\nfn main() -> ! { let float = 4.82832; let floored_float = floorf(float); let sqrt_of_four = sqrtf(floored_float); let sinus_of_four = sin(floored_float.into()); let exponential_of_four = exp(floored_float.into()); hprintln!(\\"Floored test float {} to {}\\", float, floored_float).unwrap(); hprintln!(\\"The square root of {} is {}\\", floored_float, sqrt_of_four).unwrap(); hprintln!(\\"The sinus of four is {}\\", sinus_of_four).unwrap(); hprintln!( \\"The exponential of four to the base e is {}\\", exponential_of_four ) .unwrap(); // exit QEMU // NOTE do not run this on hardware; it can corrupt OpenOCD state // debug::exit(debug::EXIT_SUCCESS); loop {}\\n} If you need to perform more complex operations like DSP signal processing or advanced linear\\nalgebra on your MCU, the following crates might help you CMSIS DSP library binding constgebra micromath microfft nalgebra","breadcrumbs":"Unsorted topics » Performing Math Functionality » Performing math functionality with #[no_std]","id":"191","title":"Performing math functionality with #[no_std]"},"192":{"body":"The embedded ecosystem is full of different protocols, hardware components and\\nvendor-specific things that use their own terms and abbreviations. This Glossary\\nattempts to list them with pointers for understanding them better.","breadcrumbs":"Appendix A: Glossary » Appendix A: Glossary","id":"192","title":"Appendix A: Glossary"},"193":{"body":"A Board Support Crate provides a high level interface configured for a specific\\nboard. It usually depends on a HAL crate.\\nThere is a more detailed description on the memory-mapped registers page\\nor for a broader overview see this video.","breadcrumbs":"Appendix A: Glossary » BSP","id":"193","title":"BSP"},"194":{"body":"Floating-point Unit. A ‘math processor’ running only operations on floating-point numbers.","breadcrumbs":"Appendix A: Glossary » FPU","id":"194","title":"FPU"},"195":{"body":"A Hardware Abstraction Layer crate provides a developer friendly interface to a microcontroller’s\\nfeatures and peripherals. It is usually implemented on top of a Peripheral Access Crate (PAC).\\nIt may also implement traits from the embedded-hal crate.\\nThere is a more detailed description on the memory-mapped registers page\\nor for a broader overview see this video.","breadcrumbs":"Appendix A: Glossary » HAL","id":"195","title":"HAL"},"196":{"body":"Sometimes referred to as I²C or Inter-IC. It is a protocol meant for hardware communication\\nwithin a single integrated circuit. See here for more details","breadcrumbs":"Appendix A: Glossary » I2C","id":"196","title":"I2C"},"197":{"body":"A Peripheral Access Crate provides access to a microcontroller’s peripherals. It is one of\\nthe lower level crates and is usually generated directly from the provided SVD, often\\nusing svd2rust. The Hardware Abstraction Layer\\nwould usually depend on this crate.\\nThere is a more detailed description on the memory-mapped registers page\\nor for a broader overview see this video.","breadcrumbs":"Appendix A: Glossary » PAC","id":"197","title":"PAC"},"198":{"body":"Serial Peripheral Interface. See here for more information.","breadcrumbs":"Appendix A: Glossary » SPI","id":"198","title":"SPI"},"199":{"body":"System View Description is an XML file format used to describe the programmers view of a\\nmicrocontroller device. You can read more about it on the ARM CMSIS documentation site.","breadcrumbs":"Appendix A: Glossary » SVD","id":"199","title":"SVD"},"2":{"body":"The goals of this book are: Get developers up to speed with embedded Rust development. i.e. How to set\\nup a development environment. Share current best practices about using Rust for embedded development. i.e.\\nHow to best use Rust language features to write more correct embedded\\nsoftware. Serve as a cookbook in some cases. e.g. How do I mix C and Rust in a single\\nproject? This book tries to be as general as possible but to make things easier for both\\nthe readers and the writers it uses the ARM Cortex-M architecture in all its\\nexamples. However, the book doesn’t assume that the reader is familiar with this\\nparticular architecture and explains details particular to this architecture\\nwhere required.","breadcrumbs":"Introduction » Scope","id":"2","title":"Scope"},"20":{"body":"Bare metal programs are non-standard ( no_std) Rust programs that require some\\nadjustments to the linking process in order to get the memory layout of the program\\nright. This requires some additional files (like linker scripts) and\\nsettings (like linker flags). We have packaged those for you in a template\\nsuch that you only need to fill in the missing information (such as the project name and the\\ncharacteristics of your target hardware). Our template is compatible with cargo-generate: a Cargo subcommand for\\ncreating new Cargo projects from templates. You can also download the\\ntemplate using git, curl, wget, or your web browser.","breadcrumbs":"Introduction » Tooling » cargo-generate OR git","id":"20","title":"cargo-generate OR git"},"200":{"body":"Universal asynchronous receiver-transmitter. See here for more information.","breadcrumbs":"Appendix A: Glossary » UART","id":"200","title":"UART"},"201":{"body":"Universal synchronous and asynchronous receiver-transmitter. See here for more information.","breadcrumbs":"Appendix A: Glossary » USART","id":"201","title":"USART"},"21":{"body":"cargo-binutils is a collection of Cargo subcommands that make it easy to use\\nthe LLVM tools that are shipped with the Rust toolchain. These tools include the\\nLLVM versions of objdump, nm and size and are used for inspecting\\nbinaries. The advantage of using these tools over GNU binutils is that (a) installing the\\nLLVM tools is the same one-command installation ( rustup component add llvm-tools) regardless of your OS and (b) tools like objdump support\\nall the architectures that rustc supports – from ARM to x86_64 – because\\nthey both share the same LLVM backend.","breadcrumbs":"Introduction » Tooling » cargo-binutils","id":"21","title":"cargo-binutils"},"22":{"body":"QEMU is an emulator. In this case we use the variant that can fully emulate ARM\\nsystems. We use QEMU to run embedded programs on the host. Thanks to this you\\ncan follow some parts of this book even if you don’t have any hardware with you!","breadcrumbs":"Introduction » Tooling » qemu-system-arm","id":"22","title":"qemu-system-arm"},"23":{"body":"","breadcrumbs":"Introduction » Tooling » Tooling for Embedded Rust Debugging","id":"23","title":"Tooling for Embedded Rust Debugging"},"24":{"body":"Debugging embedded systems in Rust requires specialized tools including software to manage the debugging process, debuggers to inspect and control program execution, and hardware probes to facilitate interaction between the host and the embedded device. This document outlines essential software tools like Probe-rs and OpenOCD, which simplify and support the debugging process, alongside prominent debuggers such as GDB and the Probe-rs Visual Studio Code extension. Additionally, it covers key hardware probes such as Rusty-probe, ST-Link, J-Link, and MCU-Link, which are integral for effective debugging and programming of embedded devices.","breadcrumbs":"Introduction » Tooling » Overview","id":"24","title":"Overview"},"25":{"body":"","breadcrumbs":"Introduction » Tooling » Software that drives debugging tools","id":"25","title":"Software that drives debugging tools"},"26":{"body":"Probe-rs is a modern, Rust-focused software designed to work with debuggers in embedded systems. Unlike OpenOCD, Probe-rs is built with simplicity in mind and aims to reduce the configuration burden often found in other debugging solutions. It supports various probes and targets, providing a high-level interface for interacting with embedded hardware. Probe-rs integrates directly with Rust tooling, and integrates with Visual Studio Code through its extension, allowing developers to streamline their debugging workflow.","breadcrumbs":"Introduction » Tooling » Probe-rs","id":"26","title":"Probe-rs"},"27":{"body":"OpenOCD is an open-source software tool used for debugging, testing, and programming embedded systems. It provides an interface between the host system and embedded hardware, supporting various transport layers like JTAG and SWD (Serial Wire Debug). OpenOCD integrates with GDB, which is a debugger. OpenOCD is widely supported, with extensive documentation and a large community, but may require complex configuration, especially for custom embedded setups.","breadcrumbs":"Introduction » Tooling » OpenOCD (Open On-Chip Debugger)","id":"27","title":"OpenOCD (Open On-Chip Debugger)"},"28":{"body":"A debugger allows developers to inspect and control the execution of a program in order to identify and correct errors or bugs. It provides functionalities such as setting breakpoints, stepping through code line by line, and examining the values of variables and memory states. Debuggers are essential for thorough software development and maintenance, enabling developers to ensure that their code behaves as intended under various conditions. Debuggers know how to: Interact with the memory mapped registers. Set Breakpoints/Watchpoints. Read and write to the memory mapped registers. Detect when the MCU has been halted for a debug event. Continue MCU execution after a debug event has been encountered. Erase and write to the microcontroller’s FLASH.","breadcrumbs":"Introduction » Tooling » Debuggers","id":"28","title":"Debuggers"},"29":{"body":"Probe-rs has a Visual Studio Code extension, providing a seamless debugging experience without extensive setup. Through this connection, developers can use Rust-specific features like pretty printing and detailed error messages, ensuring that their debugging process aligns with the Rust ecosystem.","breadcrumbs":"Introduction » Tooling » Probe-rs Visual Studio Code Extension","id":"29","title":"Probe-rs Visual Studio Code Extension"},"3":{"body":"This book caters towards people with either some embedded background or some Rust background, however we believe\\neverybody curious about embedded Rust programming can get something out of this book. For those without any prior knowledge\\nwe suggest you read the “Assumptions and Prerequisites” section and catch up on missing knowledge to get more out of the book\\nand improve your reading experience. You can check out the “Other Resources” section to find resources on topics\\nyou might want to catch up on.","breadcrumbs":"Introduction » Who This Book is For","id":"3","title":"Who This Book is For"},"30":{"body":"TRACE32 is a professional debugging and tracing solution developed by Lauterbach for embedded systems. It supports a wide range of processor architectures, including ARM and RISC-V, and connects to target hardware via JTAG, SWD, and various trace interfaces. TRACE32 provides advanced debugging capabilities such as multicore debugging, complex breakpoints, and real-time trace analysis. It works with standard ELF/DWARF debug information, making it compatible with Rust binaries built using conventional toolchains.","breadcrumbs":"Introduction » Tooling » TRACE32","id":"30","title":"TRACE32"},"31":{"body":"GDB is a versatile debugging tool that allows developers to examine the state of programs while they run or after they crash. For embedded Rust, GDB connects to the target system via OpenOCD or other debugging servers to interact with the embedded code. GDB is highly configurable and supports features like remote debugging, variable inspection, and conditional breakpoints. It can be used on a variety of platforms, and has extensive support for Rust-specific debugging needs, such as pretty printing and integration with IDEs.","breadcrumbs":"Introduction » Tooling » GDB (GNU Debugger)","id":"31","title":"GDB (GNU Debugger)"},"32":{"body":"A hardware probe is a device used in the development and debugging of embedded systems to facilitate communication between a host computer and the target embedded device. It typically supports protocols like JTAG or SWD, enabling it to program, debug, and analyze the microcontroller or microprocessor on the embedded system. Hardware probes are crucial for developers to set breakpoints, step through code, and inspect memory and processor registers, effectively allowing them to diagnose and fix issues in real-time.","breadcrumbs":"Introduction » Tooling » Probes","id":"32","title":"Probes"},"33":{"body":"Rusty-probe is an open-sourced USB-based hardware debugging probe designed to work with probe-rs. The combination of Rusty-Probe and probe-rs provides an easy-to-use, cost-effective solution for developers working with embedded Rust applications.","breadcrumbs":"Introduction » Tooling » Rusty-probe","id":"33","title":"Rusty-probe"},"34":{"body":"The ST-Link is a popular debugging and programming probe developed by STMicroelectronics primarily for their STM32 and STM8 microcontroller series. It supports both debugging and programming via JTAG or SWD (Serial Wire Debug) interfaces. ST-Link is widely used due to its direct support from STMicroelectronics’ extensive range of development boards and its integration into major IDEs, making it a convenient choice for developers working with STM microcontrollers.","breadcrumbs":"Introduction » Tooling » ST-Link","id":"34","title":"ST-Link"},"35":{"body":"J-Link, developed by SEGGER Microcontroller, is a robust and versatile debugger supporting a wide range of CPU cores and devices beyond just ARM, such as RISC-V. Known for its high performance and reliability, J-Link supports various communication interfaces, including JTAG, SWD, and fine-pitch JTAG interfaces. It is favored for its advanced features like unlimited breakpoints in flash memory and its compatibility with a multitude of development environments.","breadcrumbs":"Introduction » Tooling » J-Link","id":"35","title":"J-Link"},"36":{"body":"MCU-Link is a debugging probe that also functions as a programmer, provided by NXP Semiconductors. It supports a variety of ARM Cortex microcontrollers and interfaces seamlessly with development tools like MCUXpresso IDE. MCU-Link is particularly notable for its versatility and affordability, making it an accessible option for hobbyists, educators, and professional developers alike.","breadcrumbs":"Introduction » Tooling » MCU-Link","id":"36","title":"MCU-Link"},"37":{"body":"This page contains OS-agnostic installation instructions for a few of the tools:","breadcrumbs":"Introduction » Installation » Installing the tools","id":"37","title":"Installing the tools"},"38":{"body":"Install rustup by following the instructions at https://rustup.rs. NOTE Make sure you have a compiler version equal to or newer than 1.31. rustc -V should return a date newer than the one shown below. $ rustc -V\\nrustc 1.31.1 (b6c32da9b 2018-12-18) For bandwidth and disk usage concerns the default installation only supports\\nnative compilation. To add cross compilation support for the ARM Cortex-M\\narchitectures choose one of the following compilation targets. For the STM32F3DISCOVERY\\nboard used for the examples in this book, use the thumbv7em-none-eabihf target. Find the best Cortex-M for you. Cortex-M0, M0+, and M1 (ARMv6-M architecture): rustup target add thumbv6m-none-eabi Cortex-M3 (ARMv7-M architecture): rustup target add thumbv7m-none-eabi Cortex-M4 and M7 without hardware floating point (ARMv7E-M architecture): rustup target add thumbv7em-none-eabi Cortex-M4F and M7F with hardware floating point (ARMv7E-M architecture): rustup target add thumbv7em-none-eabihf Cortex-M23 (ARMv8-M architecture): rustup target add thumbv8m.base-none-eabi Cortex-M33 and M35P (ARMv8-M architecture): rustup target add thumbv8m.main-none-eabi Cortex-M33F and M35PF with hardware floating point (ARMv8-M architecture): rustup target add thumbv8m.main-none-eabihf","breadcrumbs":"Introduction » Installation » Rust Toolchain","id":"38","title":"Rust Toolchain"},"39":{"body":"cargo install cargo-binutils rustup component add llvm-tools WINDOWS: prerequisite C++ Build Tools for Visual Studio 2019 is installed. https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=16","breadcrumbs":"Introduction » Installation » cargo-binutils","id":"39","title":"cargo-binutils"},"4":{"body":"You are comfortable using the Rust Programming Language, and have written,\\nrun, and debugged Rust applications on a desktop environment. You should also\\nbe familiar with the idioms of the 2018 edition as this book targets\\nRust 2018. You are comfortable developing and debugging embedded systems in another\\nlanguage such as C, C++, or Ada, and are familiar with concepts such as: Cross Compilation Memory Mapped Peripherals Interrupts Common interfaces such as I2C, SPI, Serial, etc.","breadcrumbs":"Introduction » Assumptions and Prerequisites","id":"4","title":"Assumptions and Prerequisites"},"40":{"body":"We’ll use this later to generate a project from a template. cargo install cargo-generate Note: on some Linux distros (e.g. Ubuntu) you may need to install the packages libssl-dev and pkg-config prior to installing cargo-generate.","breadcrumbs":"Introduction » Installation » cargo-generate","id":"40","title":"cargo-generate"},"41":{"body":"Now follow the instructions specific to the OS you are using: Linux Windows macOS","breadcrumbs":"Introduction » Installation » OS-Specific Instructions","id":"41","title":"OS-Specific Instructions"},"42":{"body":"Here are the installation commands for a few Linux distributions.","breadcrumbs":"Introduction » Installation » Linux » Linux","id":"42","title":"Linux"},"43":{"body":"Ubuntu 18.04 or newer / Debian stretch or newer NOTE gdb-multiarch is the GDB command you’ll use to debug your ARM\\nCortex-M programs sudo apt install gdb-multiarch openocd qemu-system-arm Ubuntu 14.04 and 16.04 NOTE arm-none-eabi-gdb is the GDB command you’ll use to debug your ARM\\nCortex-M programs sudo apt install gdb-arm-none-eabi openocd qemu-system-arm Fedora 27 or newer sudo dnf install gdb openocd qemu-system-arm Arch Linux NOTE arm-none-eabi-gdb is the GDB command you’ll use to debug ARM\\nCortex-M programs sudo pacman -S arm-none-eabi-gdb qemu-system-arm openocd","breadcrumbs":"Introduction » Installation » Linux » Packages","id":"43","title":"Packages"},"44":{"body":"This rule lets you use OpenOCD with the Discovery board without root privilege. Create the file /etc/udev/rules.d/70-st-link.rules with the contents shown below. # STM32F3DISCOVERY rev A/B - ST-LINK/V2\\nATTRS{idVendor}==\\"0483\\", ATTRS{idProduct}==\\"3748\\", TAG+=\\"uaccess\\" # STM32F3DISCOVERY rev C+ - ST-LINK/V2-1\\nATTRS{idVendor}==\\"0483\\", ATTRS{idProduct}==\\"374b\\", TAG+=\\"uaccess\\" Then reload all the udev rules with: sudo udevadm control --reload-rules If you had the board plugged to your laptop, unplug it and then plug it again. You can check the permissions by running this command: lsusb Which should show something like (..)\\nBus 001 Device 018: ID 0483:374b STMicroelectronics ST-LINK/V2.1\\n(..) Take note of the bus and device numbers. Use those numbers to create a path like /dev/bus/usb//. Then use this path like so: ls -l /dev/bus/usb/001/018 crw-------+ 1 root root 189, 17 Sep 13 12:34 /dev/bus/usb/001/018 getfacl /dev/bus/usb/001/018 | grep user user::rw-\\nuser:you:rw- The + appended to permissions indicates the existence of an extended\\npermission. The getfacl command tells the user you can make use of\\nthis device. Now, go to the next section.","breadcrumbs":"Introduction » Installation » Linux » udev rules","id":"44","title":"udev rules"},"45":{"body":"All the tools can be installed using Homebrew or MacPorts:","breadcrumbs":"Introduction » Installation » MacOS » macOS","id":"45","title":"macOS"},"46":{"body":"$ # GDB\\n$ brew install arm-none-eabi-gdb $ # OpenOCD\\n$ brew install openocd $ # QEMU\\n$ brew install qemu NOTE If OpenOCD crashes you may need to install the latest version using: $ brew install --HEAD openocd","breadcrumbs":"Introduction » Installation » MacOS » Install tools with Homebrew","id":"46","title":"Install tools with Homebrew"},"47":{"body":"$ # GDB\\n$ sudo port install arm-none-eabi-gcc $ # OpenOCD\\n$ sudo port install openocd $ # QEMU\\n$ sudo port install qemu That’s all! Go to the next section.","breadcrumbs":"Introduction » Installation » MacOS » Install tools with MacPorts","id":"47","title":"Install tools with MacPorts"},"48":{"body":"","breadcrumbs":"Introduction » Installation » Windows » Windows","id":"48","title":"Windows"},"49":{"body":"ARM provides .exe installers for Windows. Grab one from here, and follow the instructions.\\nJust before the installation process finishes tick/select the “Add path to environment variable”\\noption. Then verify that the tools are in your %PATH%: $ arm-none-eabi-gdb -v\\nGNU gdb (GNU Tools for Arm Embedded Processors 7-2018-q2-update) 8.1.0.20180315-git\\n(..)","breadcrumbs":"Introduction » Installation » Windows » arm-none-eabi-gdb","id":"49","title":"arm-none-eabi-gdb"},"5":{"body":"If you are unfamiliar with anything mentioned above or if you want more information about a specific topic mentioned in this book you might find some of these resources helpful. Topic Resource Description Rust Rust Book If you are not yet comfortable with Rust, we highly suggest reading this book. Rust, Embedded Discovery Book If you have never done any embedded programming, this book might be a better start Rust, Embedded Embedded Rust Bookshelf Here you can find several other resources provided by Rust’s Embedded Working Group. Rust, Embedded Embedonomicon The nitty gritty details when doing embedded programming in Rust. Rust, Embedded embedded FAQ Frequently asked questions about Rust in an embedded context. Rust, Embedded Comprehensive Rust 🦀: Bare Metal Teaching material for a 4-day class on bare-metal Rust development Interrupts Interrupt - Memory-mapped IO/Peripherals Memory-mapped I/O - SPI, UART, RS232, USB, I2C, TTL Stack Exchange about SPI, UART, and other interfaces -","breadcrumbs":"Introduction » Other Resources","id":"5","title":"Other Resources"},"50":{"body":"There’s no official binary release of OpenOCD for Windows but if you’re not in the mood to compile\\nit yourself, the xPack project provides a binary distribution, here. Follow the\\nprovided installation instructions. Then update your %PATH% environment variable to\\ninclude the path where the binaries were installed. ( C:\\\\Users\\\\USERNAME\\\\AppData\\\\Roaming\\\\xPacks\\\\@xpack-dev-tools\\\\openocd\\\\0.10.0-13.1\\\\.content\\\\bin\\\\,\\nif you’ve been using the easy install) Verify that OpenOCD is in your %PATH% with: $ openocd -v\\nOpen On-Chip Debugger 0.10.0\\n(..)","breadcrumbs":"Introduction » Installation » Windows » OpenOCD","id":"50","title":"OpenOCD"},"51":{"body":"Grab QEMU from the official website.","breadcrumbs":"Introduction » Installation » Windows » QEMU","id":"51","title":"QEMU"},"52":{"body":"You’ll also need to install this USB driver or OpenOCD won’t work. Follow the installer\\ninstructions and make sure you install the right version (32-bit or 64-bit) of the driver. That’s all! Go to the next section.","breadcrumbs":"Introduction » Installation » Windows » ST-LINK USB driver","id":"52","title":"ST-LINK USB driver"},"53":{"body":"In this section we check that some of the required tools / drivers have been\\ncorrectly installed and configured. Connect your laptop / PC to the discovery board using a Mini-USB USB cable. The\\ndiscovery board has two USB connectors; use the one labeled “USB ST-LINK” that\\nsits on the center of the edge of the board. Also check that the ST-LINK header is populated. See the picture below; the\\nST-LINK header is highlighted. Now run the following command: openocd -f interface/stlink.cfg -f target/stm32f3x.cfg NOTE: Old versions of openocd, including the 0.10.0 release from 2017, do\\nnot contain the new (and preferable) interface/stlink.cfg file; instead you\\nmay need to use interface/stlink-v2.cfg or interface/stlink-v2-1.cfg. You should get the following output and the program should block the console: Open On-Chip Debugger 0.10.0\\nLicensed under GNU GPL v2\\nFor bug reports, read http://openocd.org/doc/doxygen/bugs.html\\nInfo : auto-selecting first available session transport \\"hla_swd\\". To override use \'transport select \'.\\nadapter speed: 1000 kHz\\nadapter_nsrst_delay: 100\\nInfo : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD\\nnone separate\\nInfo : Unable to match requested speed 1000 kHz, using 950 kHz\\nInfo : Unable to match requested speed 1000 kHz, using 950 kHz\\nInfo : clock speed 950 kHz\\nInfo : STLINK v2 JTAG v27 API v2 SWIM v15 VID 0x0483 PID 0x374B\\nInfo : using stlink api v2\\nInfo : Target voltage: 2.919881\\nInfo : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints The contents may not match exactly but you should get the last line about\\nbreakpoints and watchpoints. If you got it then terminate the OpenOCD process\\nand move to the next section. If you didn’t get the “breakpoints” line then try one of the following commands. openocd -f interface/stlink-v2.cfg -f target/stm32f3x.cfg openocd -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg If one of those commands works it means you got an old hardware revision of the\\ndiscovery board. That won’t be a problem but commit that fact to memory as\\nyou’ll need to configure things a bit differently later on. You can move to the next section. If none of the commands work as a normal user then try to run them with root\\npermission (e.g. sudo openocd ..). If the commands do work with root\\npermission then check that the udev rules have been correctly set. If you have reached this point and OpenOCD is not working please open an issue\\nand we’ll help you out!","breadcrumbs":"Introduction » Installation » Verify Installation » Verify Installation","id":"53","title":"Verify Installation"},"54":{"body":"In this section we’ll walk you through the process of writing, building,\\nflashing and debugging embedded programs. You will be able to try most of the\\nexamples without any special hardware as we will show you the basics using\\nQEMU, a popular open-source hardware emulator. The only section where hardware\\nis required is, naturally enough, the Hardware section,\\nwhere we use OpenOCD to program an STM32F3DISCOVERY.","breadcrumbs":"Getting started » Getting Started","id":"54","title":"Getting Started"},"55":{"body":"We’ll start writing a program for the LM3S6965, a Cortex-M3 microcontroller.\\nWe have chosen this as our initial target because it can be emulated using QEMU\\nso you don’t need to fiddle with hardware in this section and we can focus on\\nthe tooling and the development process. IMPORTANT\\nWe’ll use the name “app” for the project name in this tutorial.\\nWhenever you see the word “app” you should replace it with the name you selected\\nfor your project. Or, you could also name your project “app” and avoid the\\nsubstitutions.","breadcrumbs":"Getting started » QEMU » QEMU","id":"55","title":"QEMU"},"56":{"body":"We’ll use the cortex-m-quickstart project template to generate a new\\nproject from it. The created project will contain a barebone application: a good\\nstarting point for a new embedded rust application. In addition, the project will\\ncontain an examples directory, with several separate applications, highlighting\\nsome of the key embedded rust functionality.","breadcrumbs":"Getting started » QEMU » Creating a non standard Rust program","id":"56","title":"Creating a non standard Rust program"},"57":{"body":"First install cargo-generate cargo install cargo-generate Then generate a new project cargo generate --git https://github.com/knurling-rs/app-template Project Name: app Creating project called `app`... Done! New project created /tmp/app cd app","breadcrumbs":"Getting started » QEMU » Using cargo-generate","id":"57","title":"Using cargo-generate"},"58":{"body":"Clone the repository git clone https://github.com/rust-embedded/cortex-m-quickstart app\\ncd app And then fill in the placeholders in the Cargo.toml file [package]\\nauthors = [\\"{{authors}}\\"] # \\"{{authors}}\\" -> \\"John Smith\\"\\nedition = \\"2018\\"\\nname = \\"{{project-name}}\\" # \\"{{project-name}}\\" -> \\"app\\"\\nversion = \\"0.1.0\\" # .. [[bin]]\\nname = \\"{{project-name}}\\" # \\"{{project-name}}\\" -> \\"app\\"\\ntest = false\\nbench = false","breadcrumbs":"Getting started » QEMU » Using git","id":"58","title":"Using git"},"59":{"body":"Grab the latest snapshot of the cortex-m-quickstart template and extract it. curl -LO https://github.com/rust-embedded/cortex-m-quickstart/archive/master.zip\\nunzip master.zip\\nmv cortex-m-quickstart-master app\\ncd app Or you can browse to cortex-m-quickstart, click the green “Clone or\\ndownload” button and then click “Download ZIP”. Then fill in the placeholders in the Cargo.toml file as done in the second\\npart of the “Using git” version.","breadcrumbs":"Getting started » QEMU » Using neither","id":"59","title":"Using neither"},"6":{"body":"This book has been translated by generous volunteers. If you would like your\\ntranslation listed here, please open a PR to add it. Japanese\\n( repository) Chinese\\n( repository)","breadcrumbs":"Introduction » Translations","id":"6","title":"Translations"},"60":{"body":"For convenience here are the most important parts of the source code in src/main.rs: #![no_std]\\n#![no_main] use panic_halt as _; use cortex_m_rt::entry; #[entry]\\nfn main() -> ! { loop { // your code goes here }\\n} This program is a bit different from a standard Rust program so let’s take a\\ncloser look. #![no_std] indicates that this program will not link to the standard crate, std. Instead it will link to its subset: the core crate. #![no_main] indicates that this program won’t use the standard main\\ninterface that most Rust programs use. The main (no pun intended) reason to go\\nwith no_main is that using the main interface in no_std context requires\\nnightly. use panic_halt as _;. This crate provides a panic_handler that defines\\nthe panicking behavior of the program. We will cover this in more detail in the Panicking chapter of the book. #[entry] is an attribute provided by the cortex-m-rt crate that’s used\\nto mark the entry point of the program. As we are not using the standard main\\ninterface we need another way to indicate the entry point of the program and\\nthat’d be #[entry]. fn main() -> !. Our program will be the only process running on the target\\nhardware so we don’t want it to end! We use a divergent function (the -> !\\nbit in the function signature) to ensure at compile time that’ll be the case.","breadcrumbs":"Getting started » QEMU » Program Overview","id":"60","title":"Program Overview"},"61":{"body":"First of all we will need the memory layout for the target microcontroller, the\\nLM3S6965 in our case. Otherwise the build will fail to link the image. Create a\\nfile named memory.x at the root of the project and paste the following content: MEMORY\\n{ /* NOTE 1 K = 1 KiBi = 1024 bytes */ /* TODO Adjust these memory regions to match your device memory layout */ /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */ FLASH : ORIGIN = 0x00000000, LENGTH = 256K RAM : ORIGIN = 0x20000000, LENGTH = 64K\\n} /* This is where the call stack will be allocated. */\\n/* The stack is of the full descending type. */\\n/* You may want to use this variable to locate the call stack and static variables in different memory regions. Below is shown the default value */\\n/* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ /* You can use this symbol to customize the location of the .text section */\\n/* If omitted the .text section will be placed right after the .vector_table section */\\n/* This is required only on microcontrollers that store some configuration right after the vector table */\\n/* _stext = ORIGIN(FLASH) + 0x400; */ /* Example of putting non-initialized variables into custom RAM locations. */\\n/* This assumes you have defined a region RAM2 above, and in the Rust sources added the attribute `#[link_section = \\".ram2bss\\"]` to the data you want to place there. */\\n/* Note that the section will not be zero-initialized by the runtime! */\\n/* SECTIONS { .ram2bss (NOLOAD) : ALIGN(4) { *(.ram2bss); . = ALIGN(4); } > RAM2 } INSERT AFTER .bss;\\n*/ The next step is to cross compile the program for the Cortex-M3 architecture.\\nThat’s as simple as running cargo build --target $TRIPLE if you know what the\\ncompilation target ( $TRIPLE) should be. Luckily, the .cargo/config.toml in the\\ntemplate has the answer: tail -n6 .cargo/config.toml [build]\\n# Pick ONE of these compilation targets\\n# target = \\"thumbv6m-none-eabi\\" # Cortex-M0 and Cortex-M0+\\ntarget = \\"thumbv7m-none-eabi\\" # Cortex-M3\\n# target = \\"thumbv7em-none-eabi\\" # Cortex-M4 and Cortex-M7 (no FPU)\\n# target = \\"thumbv7em-none-eabihf\\" # Cortex-M4F and Cortex-M7F (with FPU) To cross compile for the Cortex-M3 architecture we have to use thumbv7m-none-eabi. That target is not automatically installed when installing\\nthe Rust toolchain, it would now be a good time to add that target to the toolchain,\\nif you haven’t done it yet: rustup target add thumbv7m-none-eabi Since the thumbv7m-none-eabi compilation target has been set as the default in\\nyour .cargo/config.toml file, the two commands below do the same: cargo build --target thumbv7m-none-eabi\\ncargo build","breadcrumbs":"Getting started » QEMU » Cross compiling","id":"61","title":"Cross compiling"},"62":{"body":"Now we have a non-native ELF binary in target/thumbv7m-none-eabi/debug/app. We\\ncan inspect it using cargo-binutils. With cargo-readobj we can print the ELF headers to confirm that this is an ARM\\nbinary. cargo readobj --bin app -- --file-headers Note that: --bin app is sugar for inspect the binary at target/$TRIPLE/debug/app --bin app will also (re)compile the binary, if necessary ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2\'s complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0x0 Type: EXEC (Executable file) Machine: ARM Version: 0x1 Entry point address: 0x405 Start of program headers: 52 (bytes into file) Start of section headers: 153204 (bytes into file) Flags: 0x5000200 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 2 Size of section headers: 40 (bytes) Number of section headers: 19 Section header string table index: 18 cargo-size can print the size of the linker sections of the binary. cargo size --bin app --release -- -A we use --release to inspect the optimized version app :\\nsection size addr\\n.vector_table 1024 0x0\\n.text 92 0x400\\n.rodata 0 0x45c\\n.data 0 0x20000000\\n.bss 0 0x20000000\\n.debug_str 2958 0x0\\n.debug_loc 19 0x0\\n.debug_abbrev 567 0x0\\n.debug_info 4929 0x0\\n.debug_ranges 40 0x0\\n.debug_macinfo 1 0x0\\n.debug_pubnames 2035 0x0\\n.debug_pubtypes 1892 0x0\\n.ARM.attributes 46 0x0\\n.debug_frame 100 0x0\\n.debug_line 867 0x0\\nTotal 14570 A refresher on ELF linker sections .text contains the program instructions .rodata contains constant values like strings .data contains statically allocated variables whose initial values are not zero .bss also contains statically allocated variables whose initial values are zero .vector_table is a non-standard section that we use to store the vector\\n(interrupt) table .ARM.attributes and the .debug_* sections contain metadata and will not be loaded onto the target when flashing the binary. IMPORTANT: ELF files contain metadata like debug information so their size\\non disk does not accurately reflect the space the program will occupy when\\nflashed on a device. Always use cargo-size to check how big a binary really\\nis. cargo-objdump can be used to disassemble the binary. cargo objdump --bin app --release -- --disassemble --no-show-raw-insn --print-imm-hex NOTE if the above command complains about Unknown command line argument see\\nthe following bug report: https://github.com/rust-embedded/book/issues/269 NOTE this output can differ on your system. New versions of rustc, LLVM\\nand libraries can generate different assembly. We truncated some of the instructions\\nto keep the snippet small. app: file format ELF32-arm-little Disassembly of section .text:\\nmain: 400: bl #0x256 404: b #-0x4 Reset: 406: bl #0x24e 40a: movw r0, #0x0 < .. truncated any more instructions .. > DefaultHandler_: 656: b #-0x4 UsageFault: 657: strb r7, [r4, #0x3] DefaultPreInit: 658: bx lr __pre_init: 659: strb r7, [r0, #0x1] __nop: 65a: bx lr HardFaultTrampoline: 65c: mrs r0, msp 660: b #-0x2 HardFault_: 662: b #-0x4 HardFault: 663: ","breadcrumbs":"Getting started » QEMU » Inspecting","id":"62","title":"Inspecting"},"63":{"body":"Next, let’s see how to run an embedded program on QEMU! This time we’ll use the hello example which actually does something. By default, this example uses [defmt]\\nand RTT to print text. NOTE defmt is a third-party dependency (i.e. non-core) widely used in the\\nEmbedded Rust ecosystem. In order to read and decode the messages produced by defmt in the host, we need to\\nswitch the RTT transport output to semihosting. When using real hardware this requires\\na debug session but when using QEMU this Just Works. Let’s switch the dependencies: cargo remove defmt-rtt\\ncargo add defmt-semihosting Open src/lib.rs and replace use defmt_rtt as _; by use defmt_semihosting as _; Now we can build the example: cargo build --bin hello The output binary will be located at target/thumbv7m-none-eabi/debug/hello. To run this binary on QEMU, the following command would be usually enough: qemu-system-arm \\\\ -cpu cortex-m3 \\\\ -machine lm3s6965evb \\\\ -nographic \\\\ -semihosting-config enable=on,target=native \\\\ -kernel target/thumbv7m-none-eabi/debug/hello In our case, since we use defmt, the host will not be able to decode the output. Instead, we\\nwill need a tool by Ferrous Systems named qemu-run: git clone git@github.com:knurling-rs/defmt.git\\ncd defmt/qemu-run/\\ncargo run -- --machine lm3s6965evb ../qemu-rs/target/thumbv7m-none-eabi/debug/hello Hello, world! The command should successfully exit (exit code = 0) after printing the text. On\\n*nix you can check that with the following command: echo $? 0 Let’s break down that QEMU command: qemu-system-arm. This is the QEMU emulator. There are a few variants of\\nthese QEMU binaries; this one does full system emulation of ARM machines\\nhence the name. -cpu cortex-m3. This tells QEMU to emulate a Cortex-M3 CPU. Specifying the\\nCPU model lets us catch some miscompilation errors: for example, running a\\nprogram compiled for the Cortex-M4F, which has a hardware FPU, will make QEMU\\nerror during its execution. -machine lm3s6965evb. This tells QEMU to emulate the LM3S6965EVB, an\\nevaluation board that contains a LM3S6965 microcontroller. -nographic. This tells QEMU to not launch its GUI. -semihosting-config (..). This tells QEMU to enable semihosting. Semihosting\\nlets the emulated device, among other things, use the host stdout, stderr and\\nstdin and create files on the host. -kernel $file. This tells QEMU which binary to load and run on the emulated\\nmachine. Typing out that long QEMU command is too much work! We can set a custom runner\\nto simplify the process. .cargo/config.toml has a commented out runner that invokes\\nQEMU; let’s uncomment it: head -n3 .cargo/config.toml [target.thumbv7m-none-eabi]\\n# uncomment this to make `cargo run` execute programs on QEMU\\nrunner = \\"qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel\\" This runner only applies to the thumbv7m-none-eabi target, which is our\\ndefault compilation target. Now cargo run will compile the program and run it\\non QEMU: cargo run --example hello --release Compiling app v0.1.0 (file:///tmp/app) Finished release [optimized + debuginfo] target(s) in 0.26s Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel target/thumbv7m-none-eabi/release/examples/hello`\\nHello, world!","breadcrumbs":"Getting started » QEMU » Running","id":"63","title":"Running"},"64":{"body":"Debugging is critical to embedded development. Let’s see how it’s done. Debugging an embedded device involves remote debugging as the program that we\\nwant to debug won’t be running on the machine that’s running the debugger\\nprogram (GDB or LLDB). Remote debugging involves a client and a server. In a QEMU setup, the client\\nwill be a GDB (or LLDB) process and the server will be the QEMU process that’s\\nalso running the embedded program. In this section we’ll use the hello example we already compiled. The first debugging step is to launch QEMU in debugging mode: qemu-system-arm \\\\ -cpu cortex-m3 \\\\ -machine lm3s6965evb \\\\ -nographic \\\\ -semihosting-config enable=on,target=native \\\\ -gdb tcp::3333 \\\\ -S \\\\ -kernel target/thumbv7m-none-eabi/debug/examples/hello This command won’t print anything to the console and will block the terminal. We\\nhave passed two extra flags this time: -gdb tcp::3333. This tells QEMU to wait for a GDB connection on TCP\\nport 3333. -S. This tells QEMU to freeze the machine at startup. Without this the\\nprogram would have reached the end of main before we had a chance to launch\\nthe debugger! Next we launch GDB in another terminal and tell it to load the debug symbols of\\nthe example: gdb-multiarch -q target/thumbv7m-none-eabi/debug/examples/hello NOTE: you might need another version of gdb instead of gdb-multiarch depending\\non which one you installed in the installation chapter. This could also be arm-none-eabi-gdb or just gdb. Then within the GDB shell we connect to QEMU, which is waiting for a connection\\non TCP port 3333. target remote :3333 Remote debugging using :3333\\nReset () at $REGISTRY/cortex-m-rt-0.6.1/src/lib.rs:473\\n473 pub unsafe extern \\"C\\" fn Reset() -> ! { You’ll see that the process is halted and that the program counter is pointing\\nto a function named Reset. That is the reset handler: what Cortex-M cores\\nexecute upon booting. Note that on some setup, instead of displaying the line Reset () at $REGISTRY/cortex-m-rt-0.6.1/src/lib.rs:473 as shown above, gdb may print some warnings like : core::num::bignum::Big32x40::mul_small () at src/libcore/num/bignum.rs:254 src/libcore/num/bignum.rs: No such file or directory. That’s a known glitch. You can safely ignore those warnings, you’re most likely at Reset(). This reset handler will eventually call our main function. Let’s skip all the\\nway there using a breakpoint and the continue command. To set the breakpoint, let’s first take a look where we would like to break in our code, with the list command. list main This will show the source code, from the file examples/hello.rs. 6 use panic_halt as _;\\n7\\n8 use cortex_m_rt::entry;\\n9 use cortex_m_semihosting::{debug, hprintln};\\n10\\n11 #[entry]\\n12 fn main() -> ! {\\n13 hprintln!(\\"Hello, world!\\").unwrap();\\n14\\n15 // exit QEMU We would like to add a breakpoint just before the “Hello, world!”, which is on line 13. We do that with the break command: break 13 We can now instruct gdb to run up to our main function, with the continue command: continue Continuing. Breakpoint 1, hello::__cortex_m_rt_main () at examples\\\\hello.rs:13\\n13 hprintln!(\\"Hello, world!\\").unwrap(); We are now close to the code that prints “Hello, world!”. Let’s move forward\\nusing the next command. next 16 debug::exit(debug::EXIT_SUCCESS); At this point you should see “Hello, world!” printed on the terminal that’s\\nrunning qemu-system-arm. $ qemu-system-arm (..)\\nHello, world! Calling next again will terminate the QEMU process. next [Inferior 1 (Remote target) exited normally] You can now exit the GDB session. quit","breadcrumbs":"Getting started » QEMU » Debugging","id":"64","title":"Debugging"},"65":{"body":"By now you should be somewhat familiar with the tooling and the development\\nprocess. In this section we’ll switch to real hardware; the process will remain\\nlargely the same. Let’s dive in.","breadcrumbs":"Getting started » Hardware » Hardware","id":"65","title":"Hardware"},"66":{"body":"Before we begin you need to identify some characteristics of the target device\\nas these will be used to configure the project: The ARM core. e.g. Cortex-M3. Does the ARM core include an FPU? Cortex-M4 F and Cortex-M7 F cores do. How much Flash memory and RAM does the target device have? e.g. 256 KiB of\\nFlash and 32 KiB of RAM. Where are Flash memory and RAM mapped in the address space? e.g. RAM is\\ncommonly located at address 0x2000_0000. You can find this information in the data sheet or the reference manual of your\\ndevice. In this section we’ll be using our reference hardware, the STM32F3DISCOVERY.\\nThis board contains an STM32F303VCT6 microcontroller. This microcontroller has: A Cortex-M4F core that includes a single precision FPU 256 KiB of Flash located at address 0x0800_0000. 40 KiB of RAM located at address 0x2000_0000. (There’s another RAM region but\\nfor simplicity we’ll ignore it).","breadcrumbs":"Getting started » Hardware » Know your hardware","id":"66","title":"Know your hardware"},"67":{"body":"We’ll start from scratch with a fresh template instance. Refer to the previous section on QEMU for a refresher on how to do this without cargo-generate. $ cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart Project Name: app Creating project called `app`... Done! New project created /tmp/app $ cd app Step number one is to set a default compilation target in .cargo/config.toml. tail -n5 .cargo/config.toml # Pick ONE of these compilation targets\\n# target = \\"thumbv6m-none-eabi\\" # Cortex-M0 and Cortex-M0+\\n# target = \\"thumbv7m-none-eabi\\" # Cortex-M3\\n# target = \\"thumbv7em-none-eabi\\" # Cortex-M4 and Cortex-M7 (no FPU)\\ntarget = \\"thumbv7em-none-eabihf\\" # Cortex-M4F and Cortex-M7F (with FPU) We’ll use thumbv7em-none-eabihf as that covers the Cortex-M4F core. NOTE: As you may remember from the previous chapter, we have to install\\nall targets and this is a new one. So don’t forget to run the installation\\nprocess rustup target add thumbv7em-none-eabihf for this target. The second step is to enter the memory region information into the memory.x\\nfile. $ cat memory.x\\n/* Linker script for the STM32F303VCT6 */\\nMEMORY\\n{ /* NOTE 1 K = 1 KiBi = 1024 bytes */ FLASH : ORIGIN = 0x08000000, LENGTH = 256K RAM : ORIGIN = 0x20000000, LENGTH = 40K\\n} NOTE: If you for some reason changed the memory.x file after you had made\\nthe first build of a specific build target, then do cargo clean before cargo build, because cargo build may not track updates of memory.x. We’ll start with the hello example again, but first we have to make a small\\nchange. In examples/hello.rs, make sure the debug::exit() call is commented out or\\nremoved. It is used only for running in QEMU. #[entry]\\nfn main() -> ! { hprintln!(\\"Hello, world!\\").unwrap(); // exit QEMU // NOTE do not run this on hardware; it can corrupt OpenOCD state // debug::exit(debug::EXIT_SUCCESS); loop {}\\n} You can now cross compile programs using cargo build\\nand inspect the binaries using cargo-binutils as you did before. The cortex-m-rt crate handles all the magic required to get your chip running,\\nas helpfully, pretty much all Cortex-M CPUs boot in the same fashion. cargo build --example hello","breadcrumbs":"Getting started » Hardware » Configuring","id":"67","title":"Configuring"},"68":{"body":"Debugging will look a bit different. In fact, the first steps can look different\\ndepending on the target device. In this section we’ll show the steps required to\\ndebug a program running on the STM32F3DISCOVERY. This is meant to serve as a\\nreference; for device specific information about debugging check out the\\nDebugonomicon. As before we’ll do remote debugging and the client will be a GDB process. This\\ntime, however, the server will be OpenOCD. As done during the verify section connect the discovery board to your laptop /\\nPC and check that the ST-LINK header is populated. On a terminal run openocd to connect to the ST-LINK on the discovery board.\\nRun this command from the root of the template; openocd will pick up the openocd.cfg file which indicates which interface file and target file to use. cat openocd.cfg # Sample OpenOCD configuration for the STM32F3DISCOVERY development board # Depending on the hardware revision you got you\'ll have to pick ONE of these\\n# interfaces. At any time only one interface should be commented out. # Revision C (newer revision)\\nsource [find interface/stlink.cfg] # Revision A and B (older revisions)\\n# source [find interface/stlink-v2.cfg] source [find target/stm32f3x.cfg] NOTE If you found out that you have an older revision of the discovery\\nboard during the verify section then you should modify the openocd.cfg\\nfile at this point to use interface/stlink-v2.cfg. $ openocd\\nOpen On-Chip Debugger 0.10.0\\nLicensed under GNU GPL v2\\nFor bug reports, read http://openocd.org/doc/doxygen/bugs.html\\nInfo : auto-selecting first available session transport \\"hla_swd\\". To override use \'transport select \'.\\nadapter speed: 1000 kHz\\nadapter_nsrst_delay: 100\\nInfo : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD\\nnone separate\\nInfo : Unable to match requested speed 1000 kHz, using 950 kHz\\nInfo : Unable to match requested speed 1000 kHz, using 950 kHz\\nInfo : clock speed 950 kHz\\nInfo : STLINK v2 JTAG v27 API v2 SWIM v15 VID 0x0483 PID 0x374B\\nInfo : using stlink api v2\\nInfo : Target voltage: 2.913879\\nInfo : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints On another terminal run GDB, also from the root of the template. gdb-multiarch -q target/thumbv7em-none-eabihf/debug/examples/hello NOTE: like before you might need another version of gdb instead of gdb-multiarch depending\\non which one you installed in the installation chapter. This could also be arm-none-eabi-gdb or just gdb. Next connect GDB to OpenOCD, which is waiting for a TCP connection on port 3333. (gdb) target remote :3333\\nRemote debugging using :3333\\n0x00000000 in ?? () Now proceed to flash (load) the program onto the microcontroller using the load command. (gdb) load\\nLoading section .vector_table, size 0x400 lma 0x8000000\\nLoading section .text, size 0x1518 lma 0x8000400\\nLoading section .rodata, size 0x414 lma 0x8001918\\nStart address 0x08000400, load size 7468\\nTransfer rate: 13 KB/sec, 2489 bytes/write. The program is now loaded. This program uses semihosting so before we do any\\nsemihosting call we have to tell OpenOCD to enable semihosting. You can send\\ncommands to OpenOCD using the monitor command. (gdb) monitor arm semihosting enable\\nsemihosting is enabled You can see all the OpenOCD commands by invoking the monitor help command. Like before we can skip all the way to main using a breakpoint and the continue command. (gdb) break main\\nBreakpoint 1 at 0x8000490: file examples/hello.rs, line 11.\\nNote: automatically using hardware breakpoints for read-only addresses. (gdb) continue\\nContinuing. Breakpoint 1, hello::__cortex_m_rt_main_trampoline () at examples/hello.rs:11\\n11 #[entry] NOTE If GDB blocks the terminal instead of hitting the breakpoint after\\nyou issue the continue command above, you might want to double check that\\nthe memory region information in the memory.x file is correctly set up\\nfor your device (both the starts and lengths). Step into the main function with step. (gdb) step\\nhalted: PC: 0x08000496\\nhello::__cortex_m_rt_main () at examples/hello.rs:13\\n13 hprintln!(\\"Hello, world!\\").unwrap(); After advancing the program with next you should see “Hello, world!” printed on the OpenOCD console,\\namong other stuff. $ openocd\\n(..)\\nInfo : halted: PC: 0x08000502\\nHello, world!\\nInfo : halted: PC: 0x080004ac\\nInfo : halted: PC: 0x080004ae\\nInfo : halted: PC: 0x080004b0\\nInfo : halted: PC: 0x080004b4\\nInfo : halted: PC: 0x080004b8\\nInfo : halted: PC: 0x080004bc The message is only displayed once as the program is about to enter the infinite loop defined in line 19: loop {} You can now exit GDB using the quit command. (gdb) quit\\nA debugging session is active. Inferior 1 [Remote target] will be detached. Quit anyway? (y or n) Debugging now requires a few more steps so we have packed all those steps into a\\nsingle GDB script named openocd.gdb. The file was created during the cargo generate step, and should work without any modifications. Let’s have a peek: cat openocd.gdb target extended-remote :3333 # print demangled symbols\\nset print asm-demangle on # detect unhandled exceptions, hard faults and panics\\nbreak DefaultHandler\\nbreak HardFault\\nbreak rust_begin_unwind monitor arm semihosting enable load # start the process but immediately halt the processor\\nstepi Now running -x openocd.gdb target/thumbv7em-none-eabihf/debug/examples/hello will immediately connect GDB to\\nOpenOCD, enable semihosting, load the program and start the process. Alternatively, you can turn -x openocd.gdb into a custom runner to make cargo run build a program and start a GDB session. This runner is included\\nin .cargo/config.toml but it’s commented out. head -n10 .cargo/config.toml [target.thumbv7m-none-eabi]\\n# uncomment this to make `cargo run` execute programs on QEMU\\n# runner = \\"qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel\\" [target.\'cfg(all(target_arch = \\"arm\\", target_os = \\"none\\"))\']\\n# uncomment ONE of these three option to make `cargo run` start a GDB session\\n# which option to pick depends on your system\\nrunner = \\"arm-none-eabi-gdb -x openocd.gdb\\"\\n# runner = \\"gdb-multiarch -x openocd.gdb\\"\\n# runner = \\"gdb -x openocd.gdb\\" $ cargo run --example hello\\n(..)\\nLoading section .vector_table, size 0x400 lma 0x8000000\\nLoading section .text, size 0x1e70 lma 0x8000400\\nLoading section .rodata, size 0x61c lma 0x8002270\\nStart address 0x800144e, load size 10380\\nTransfer rate: 17 KB/sec, 3460 bytes/write.\\n(gdb)","breadcrumbs":"Getting started » Hardware » Debugging","id":"68","title":"Debugging"},"69":{"body":"Embedded systems can only get so far by executing normal Rust code and moving data around in RAM. If we want to get any information into or out of our system (be that blinking an LED, detecting a button press or communicating with an off-chip peripheral on some sort of bus) we’re going to have to dip into the world of Peripherals and their ‘memory mapped registers’. You may well find that the code you need to access the peripherals in your micro-controller has already been written, at one of the following levels: Micro-architecture Crate - This sort of crate handles any useful routines common to the processor core your microcontroller is using, as well as any peripherals that are common to all micro-controllers that use that particular type of processor core. For example the cortex-m crate gives you functions to enable and disable interrupts, which are the same for all Cortex-M based micro-controllers. It also gives you access to the ‘SysTick’ peripheral included with all Cortex-M based micro-controllers. Peripheral Access Crate (PAC) - This sort of crate is a thin wrapper over the various memory-wrapper registers defined for your particular part-number of micro-controller you are using. For example, tm4c123x for the Texas Instruments Tiva-C TM4C123 series, or stm32f30x for the ST-Micro STM32F30x series. Here, you’ll be interacting with the registers directly, following each peripheral’s operating instructions given in your micro-controller’s Technical Reference Manual. HAL Crate - These crates offer a more user-friendly API for your particular processor, often by implementing some common traits defined in embedded-hal. For example, this crate might offer a Serial struct, with a constructor that takes an appropriate set of GPIO pins and a baud rate, and offers some sort of write_byte function for sending data. See the chapter on Portability for more information on embedded-hal. Board Crate - These crates go one step further than a HAL Crate by pre-configuring various peripherals and GPIO pins to suit the specific developer kit or board you are using, such as stm32f3-discovery for the STM32F3DISCOVERY board.","breadcrumbs":"Getting started » Memory-mapped Registers » Memory Mapped Registers","id":"69","title":"Memory Mapped Registers"},"7":{"body":"This book generally assumes that you’re reading it front-to-back. Later\\nchapters build on concepts in earlier chapters, and earlier chapters may\\nnot dig into details on a topic, revisiting the topic in a later chapter. This book will be using the STM32F3DISCOVERY development board from\\nSTMicroelectronics for the majority of the examples contained within. This board\\nis based on the ARM Cortex-M architecture, and while basic functionality is\\nthe same across most CPUs based on this architecture, peripherals and other\\nimplementation details of Microcontrollers are different between different\\nvendors, and often even different between Microcontroller families from the same\\nvendor. For this reason, we suggest purchasing the STM32F3DISCOVERY development board\\nfor the purpose of following the examples in this book.","breadcrumbs":"Introduction » How to Use This Book","id":"7","title":"How to Use This Book"},"70":{"body":"A board crate is the perfect starting point, if you’re new to embedded Rust. They nicely abstract the HW details that might be overwhelming when starting studying this subject, and makes standard tasks easy, like turning a LED on or off. The functionality it exposes varies a lot between boards. Since this book aims at staying hardware agnostic, the board crates won’t be covered by this book. If you want to experiment with the STM32F3DISCOVERY board, it is highly recommended to take a look at the stm32f3-discovery board crate, which provides functionality to blink the board LEDs, access its compass, bluetooth and more. The Discovery book offers a great introduction to the use of a board crate. But if you’re working on a system that doesn’t yet have dedicated board crate, or you need functionality not provided by existing crates, read on as we start from the bottom, with the micro-architecture crates.","breadcrumbs":"Getting started » Memory-mapped Registers » Board Crate","id":"70","title":"Board Crate"},"71":{"body":"Let’s look at the SysTick peripheral that’s common to all Cortex-M based micro-controllers. We can find a pretty low-level API in the cortex-m crate, and we can use it like this: #![no_std]\\n#![no_main]\\nuse cortex_m::peripheral::{syst, Peripherals};\\nuse cortex_m_rt::entry;\\nuse panic_halt as _; #[entry]\\nfn main() -> ! { let peripherals = Peripherals::take().unwrap(); let mut systick = peripherals.SYST; systick.set_clock_source(syst::SystClkSource::Core); systick.set_reload(1_000); systick.clear_current(); systick.enable_counter(); while !systick.has_wrapped() { // Loop } loop {}\\n} The functions on the SYST struct map pretty closely to the functionality defined by the ARM Technical Reference Manual for this peripheral. There’s nothing in this API about ‘delaying for X milliseconds’ - we have to crudely implement that ourselves using a while loop. Note that we can’t access our SYST struct until we have called Peripherals::take() - this is a special routine that guarantees that there is only one SYST structure in our entire program. For more on that, see the Peripherals section.","breadcrumbs":"Getting started » Memory-mapped Registers » Micro-architecture crate","id":"71","title":"Micro-architecture crate"},"72":{"body":"We won’t get very far with our embedded software development if we restrict ourselves to only the basic peripherals included with every Cortex-M. At some point, we’re going to need to write some code that’s specific to the particular micro-controller we’re using. In this example, let’s assume we have an Texas Instruments TM4C123 - a middling 80MHz Cortex-M4 with 256 KiB of Flash. We’re going to pull in the tm4c123x crate to make use of this chip. #![no_std]\\n#![no_main] use panic_halt as _; // panic handler use cortex_m_rt::entry;\\nuse tm4c123x; #[entry]\\npub fn init() -> (Delay, Leds) { let cp = cortex_m::Peripherals::take().unwrap(); let p = tm4c123x::Peripherals::take().unwrap(); let pwm = p.PWM0; pwm.ctl.write(|w| w.globalsync0().clear_bit()); // Mode = 1 => Count up/down mode pwm._2_ctl.write(|w| w.enable().set_bit().mode().set_bit()); pwm._2_gena.write(|w| w.actcmpau().zero().actcmpad().one()); // 528 cycles (264 up and down) = 4 loops per video line (2112 cycles) pwm._2_load.write(|w| unsafe { w.load().bits(263) }); pwm._2_cmpa.write(|w| unsafe { w.compa().bits(64) }); pwm.enable.write(|w| w.pwm4en().set_bit());\\n} We’ve accessed the PWM0 peripheral in exactly the same way as we accessed the SYST peripheral earlier, except we called tm4c123x::Peripherals::take(). As this crate was auto-generated using svd2rust, the access functions for our register fields take a closure, rather than a numeric argument. While this looks like a lot of code, the Rust compiler can use it to perform a bunch of checks for us, but then generate machine-code which is pretty close to hand-written assembler! Where the auto-generated code isn’t able to determine that all possible arguments to a particular accessor function are valid (for example, if the SVD defines the register as 32-bit but doesn’t say if some of those 32-bit values have a special meaning), then the function is marked as unsafe. We can see this in the example above when setting the load and compa sub-fields using the bits() function.","breadcrumbs":"Getting started » Memory-mapped Registers » Using a Peripheral Access Crate (PAC)","id":"72","title":"Using a Peripheral Access Crate (PAC)"},"73":{"body":"The read() function returns an object which gives read-only access to the various sub-fields within this register, as defined by the manufacturer’s SVD file for this chip. You can find all the functions available on special R return type for this particular register, in this particular peripheral, on this particular chip, in the tm4c123x documentation. if pwm.ctl.read().globalsync0().is_set() { // Do a thing\\n}","breadcrumbs":"Getting started » Memory-mapped Registers » Reading","id":"73","title":"Reading"},"74":{"body":"The write() function takes a closure with a single argument. Typically we call this w. This argument then gives read-write access to the various sub-fields within this register, as defined by the manufacturer’s SVD file for this chip. Again, you can find all the functions available on the ‘w’ for this particular register, in this particular peripheral, on this particular chip, in the tm4c123x documentation. Note that all of the sub-fields that we do not set will be set to a default value for us - any existing content in the register will be lost. pwm.ctl.write(|w| w.globalsync0().clear_bit());","breadcrumbs":"Getting started » Memory-mapped Registers » Writing","id":"74","title":"Writing"},"75":{"body":"If we wish to change only one particular sub-field in this register and leave the other sub-fields unchanged, we can use the modify function. This function takes a closure with two arguments - one for reading and one for writing. Typically we call these r and w respectively. The r argument can be used to inspect the current contents of the register, and the w argument can be used to modify the register contents. pwm.ctl.modify(|r, w| w.globalsync0().clear_bit()); The modify function really shows the power of closures here. In C, we’d have to read into some temporary value, modify the correct bits and then write the value back. This means there’s considerable scope for error: uint32_t temp = pwm0.ctl.read();\\ntemp |= PWM0_CTL_GLOBALSYNC0;\\npwm0.ctl.write(temp);\\nuint32_t temp2 = pwm0.enable.read();\\ntemp2 |= PWM0_ENABLE_PWM4EN;\\npwm0.enable.write(temp); // Uh oh! Wrong variable!","breadcrumbs":"Getting started » Memory-mapped Registers » Modifying","id":"75","title":"Modifying"},"76":{"body":"The HAL crate for a chip typically works by implementing a custom Trait for the raw structures exposed by the PAC. Often this trait will define a function called constrain() for single peripherals or split() for things like GPIO ports with multiple pins. This function will consume the underlying raw peripheral structure and return a new object with a higher-level API. This API may also do things like have the Serial port new function require a borrow on some Clock structure, which can only be generated by calling the function which configures the PLLs and sets up all the clock frequencies. In this way, it is statically impossible to create a Serial port object without first having configured the clock rates, or for the Serial port object to misconvert the baud rate into clock ticks. Some crates even define special traits for the states each GPIO pin can be in, requiring the user to put a pin into the correct state (say, by selecting the appropriate Alternate Function Mode) before passing the pin into Peripheral. All with no run-time cost! Let’s see an example: #![no_std]\\n#![no_main] use panic_halt as _; // panic handler use cortex_m_rt::entry;\\nuse tm4c123x_hal as hal;\\nuse tm4c123x_hal::prelude::*;\\nuse tm4c123x_hal::serial::{NewlineMode, Serial};\\nuse tm4c123x_hal::sysctl; #[entry]\\nfn main() -> ! { let p = hal::Peripherals::take().unwrap(); let cp = hal::CorePeripherals::take().unwrap(); // Wrap up the SYSCTL struct into an object with a higher-layer API let mut sc = p.SYSCTL.constrain(); // Pick our oscillation settings sc.clock_setup.oscillator = sysctl::Oscillator::Main( sysctl::CrystalFrequency::_16mhz, sysctl::SystemClock::UsePll(sysctl::PllOutputFrequency::_80_00mhz), ); // Configure the PLL with those settings let clocks = sc.clock_setup.freeze(); // Wrap up the GPIO_PORTA struct into an object with a higher-layer API. // Note it needs to borrow `sc.power_control` so it can power up the GPIO // peripheral automatically. let mut porta = p.GPIO_PORTA.split(&sc.power_control); // Activate the UART. let uart = Serial::uart0( p.UART0, // The transmit pin porta .pa1 .into_af_push_pull::(&mut porta.control), // The receive pin porta .pa0 .into_af_push_pull::(&mut porta.control), // No RTS or CTS required (), (), // The baud rate 115200_u32.bps(), // Output handling NewlineMode::SwapLFtoCRLF, // We need the clock rates to calculate the baud rate divisors &clocks, // We need this to power up the UART peripheral &sc.power_control, ); loop { writeln!(uart, \\"Hello, World!\\\\r\\\\n\\").unwrap(); }\\n}","breadcrumbs":"Getting started » Memory-mapped Registers » Using a HAL crate","id":"76","title":"Using a HAL crate"},"77":{"body":"Semihosting is a mechanism that lets embedded devices do I/O on the host and is\\nmainly used to log messages to the host console. Semihosting requires a debug\\nsession and pretty much nothing else (no extra wires!) so it’s super convenient\\nto use. The downside is that it’s super slow: each write operation can take\\nseveral milliseconds depending on the hardware debugger (e.g. ST-Link) you use. The cortex-m-semihosting crate provides an API to do semihosting operations\\non Cortex-M devices. The program below is the semihosting version of “Hello,\\nworld!”: #![no_main]\\n#![no_std] use panic_halt as _; use cortex_m_rt::entry;\\nuse cortex_m_semihosting::hprintln; #[entry]\\nfn main() -> ! { hprintln!(\\"Hello, world!\\").unwrap(); loop {}\\n} If you run this program on hardware you’ll see the “Hello, world!” message\\nwithin the OpenOCD logs. $ openocd\\n(..)\\nHello, world!\\n(..) You do need to enable semihosting in OpenOCD from GDB first: (gdb) monitor arm semihosting enable\\nsemihosting is enabled QEMU understands semihosting operations so the above program will also work with qemu-system-arm without having to start a debug session. Note that you’ll\\nneed to pass the -semihosting-config flag to QEMU to enable semihosting\\nsupport; these flags are already included in the .cargo/config.toml file of the\\ntemplate. $ # this program will block the terminal\\n$ cargo run Running `qemu-system-arm (..)\\nHello, world! There’s also an exit semihosting operation that can be used to terminate the\\nQEMU process. Important: do not use debug::exit on hardware; this function\\ncan corrupt your OpenOCD session and you will not be able to debug more programs\\nuntil you restart it. #![no_main]\\n#![no_std] use panic_halt as _; use cortex_m_rt::entry;\\nuse cortex_m_semihosting::debug; #[entry]\\nfn main() -> ! { let roses = \\"blue\\"; if roses == \\"red\\" { debug::exit(debug::EXIT_SUCCESS); } else { debug::exit(debug::EXIT_FAILURE); } loop {}\\n} $ cargo run Running `qemu-system-arm (..) $ echo $?\\n1 One last tip: you can set the panicking behavior to exit(EXIT_FAILURE). This\\nwill let you write no_std run-pass tests that you can run on QEMU. For convenience, the panic-semihosting crate has an “exit” feature that when\\nenabled invokes exit(EXIT_FAILURE) after logging the panic message to the host\\nstderr. #![no_main]\\n#![no_std] use panic_semihosting as _; // features = [\\"exit\\"] use cortex_m_rt::entry;\\nuse cortex_m_semihosting::debug; #[entry]\\nfn main() -> ! { let roses = \\"blue\\"; assert_eq!(roses, \\"red\\"); loop {}\\n} $ cargo run Running `qemu-system-arm (..)\\npanicked at \'assertion failed: `(left == right)` left: `\\"blue\\"`, right: `\\"red\\"`\', examples/hello.rs:15:5 $ echo $?\\n1 NOTE: To enable this feature on panic-semihosting, edit your Cargo.toml dependencies section where panic-semihosting is specified with: panic-semihosting = { version = \\"VERSION\\", features = [\\"exit\\"] } where VERSION is the version desired. For more information on dependencies\\nfeatures check the specifying dependencies section of the Cargo book.","breadcrumbs":"Getting started » Semihosting » Semihosting","id":"77","title":"Semihosting"},"78":{"body":"Panicking is a core part of the Rust language. Built-in operations like indexing\\nare runtime checked for memory safety. When out of bounds indexing is attempted\\nthis results in a panic. In the standard library panicking has a defined behavior: it unwinds the stack\\nof the panicking thread, unless the user opted for aborting the program on\\npanics. In programs without standard library, however, the panicking behavior is left\\nundefined. A behavior can be chosen by declaring a #[panic_handler] function.\\nThis function must appear exactly once in the dependency graph of a program,\\nand must have the following signature: fn(&PanicInfo) -> !, where PanicInfo\\nis a struct containing information about the location of the panic. Given that embedded systems range from user facing to safety critical (cannot\\ncrash) there’s no one size fits all panicking behavior but there are plenty of\\ncommonly used behaviors. These common behaviors have been packaged into crates\\nthat define the #[panic_handler] function. Some examples include: panic-abort. A panic causes the abort instruction to be executed. panic-halt. A panic causes the program, or the current thread, to halt by\\nentering an infinite loop. panic-itm. The panicking message is logged using the ITM, an ARM Cortex-M\\nspecific peripheral. panic-semihosting. The panicking message is logged to the host using the\\nsemihosting technique. You may be able to find even more crates searching for the panic-handler\\nkeyword on crates.io. A program can pick one of these behaviors simply by linking to the corresponding\\ncrate. The fact that the panicking behavior is expressed in the source of\\nan application as a single line of code is not only useful as documentation but\\ncan also be used to change the panicking behavior according to the compilation\\nprofile. For example: #![no_main]\\n#![no_std] // dev profile: easier to debug panics; can put a breakpoint on `rust_begin_unwind`\\n#[cfg(debug_assertions)]\\nuse panic_halt as _; // release profile: minimize the binary size of the application\\n#[cfg(not(debug_assertions))]\\nuse panic_abort as _; // .. In this example the crate links to the panic-halt crate when built with the\\ndev profile ( cargo build), but links to the panic-abort crate when built\\nwith the release profile ( cargo build --release). The use panic_abort as _; form of the use statement is used to ensure the panic_abort panic handler is\\nincluded in our final executable while making it clear to the compiler that we won’t explicitly use anything from\\nthe crate. Without the as _ rename, the compiler would warn that we have an unused import.\\nSometimes you might see extern crate panic_abort instead, which is an older style used before the\\n2018 edition of Rust, and should now only be used for “sysroot” crates (those distributed with Rust itself) such\\nas proc_macro, alloc, std, and test.","breadcrumbs":"Getting started » Panicking » Panicking","id":"78","title":"Panicking"},"79":{"body":"Here’s an example that tries to index an array beyond its length. The operation\\nresults in a panic. #![no_main]\\n#![no_std] use panic_semihosting as _; use cortex_m_rt::entry; #[entry]\\nfn main() -> ! { let xs = [0, 1, 2]; let i = xs.len(); let _y = xs[i]; // out of bounds access loop {}\\n} This example chose the panic-semihosting behavior which prints the panic\\nmessage to the host console using semihosting. $ cargo run Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb (..)\\npanicked at \'index out of bounds: the len is 3 but the index is 4\', src/main.rs:12:13 You can try changing the behavior to panic-halt and confirm that no message is\\nprinted in that case.","breadcrumbs":"Getting started » Panicking » An example","id":"79","title":"An example"},"8":{"body":"The work on this book is coordinated in this repository and is mainly\\ndeveloped by the resources team. If you have trouble following the instructions in this book or find that some\\nsection of the book is not clear enough or hard to follow then that’s a bug and\\nit should be reported in the issue tracker of this book. Pull requests fixing typos and adding new content are very welcome!","breadcrumbs":"Introduction » Contributing to This Book","id":"8","title":"Contributing to This Book"},"80":{"body":"Exceptions, and interrupts, are a hardware mechanism by which the processor\\nhandles asynchronous events and fatal errors (e.g. executing an invalid\\ninstruction). Exceptions imply preemption and involve exception handlers,\\nsubroutines executed in response to the signal that triggered the event. The cortex-m-rt crate provides an exception attribute to declare exception\\nhandlers. // Exception handler for the SysTick (System Timer) exception\\n#[exception]\\nfn SysTick() { // ..\\n} Other than the exception attribute exception handlers look like plain\\nfunctions but there’s one more difference: exception handlers can not be\\ncalled by software. Following the previous example, the statement SysTick();\\nwould result in a compilation error. This behavior is pretty much intended and it’s required to provide a feature: static mut variables declared inside exception handlers are safe to use. #[exception]\\nfn SysTick() { static mut COUNT: u32 = 0; // `COUNT` has transformed to type `&mut u32` and it\'s safe to use *COUNT += 1;\\n} As you may know, using static mut variables in a function makes it non-reentrant. It’s undefined behavior to call a non-reentrant function,\\ndirectly or indirectly, from more than one exception / interrupt handler or from main and one or more exception / interrupt handlers. Safe Rust must never result in undefined behavior so non-reentrant functions\\nmust be marked as unsafe. Yet I just told that exception handlers can safely\\nuse static mut variables. How is this possible? This is possible because exception handlers can not be called by software thus reentrancy is not\\npossible. These handlers are called by the hardware itself which is assumed to be physically non-concurrent. As a result, in the context of exception handlers in embedded systems, the absence of concurrent invocations of the same handler ensures that there are no reentrancy issues, even if the handler uses static mutable variables. In a multicore system, where multiple processor cores are executing code concurrently, the potential for reentrancy issues becomes relevant again, even within exception handlers. While each core may have its own set of exception handlers, there can still be scenarios where multiple cores attempt to execute the same exception handler simultaneously. To address this concern in a multicore environment, proper synchronization mechanisms need to be employed within the exception handlers to ensure that access to shared resources is properly coordinated among the cores. This typically involves the use of techniques such as locks, semaphores, or atomic operations to prevent data races and maintain data integrity Note that the exception attribute transforms definitions of static variables\\ninside the function by wrapping them into unsafe blocks and providing us\\nwith new appropriate variables of type &mut of the same name.\\nThus we can dereference the reference via * to access the values of the variables without\\nneeding to wrap them in an unsafe block.","breadcrumbs":"Getting started » Exceptions » Exceptions","id":"80","title":"Exceptions"},"81":{"body":"Here’s an example that uses the system timer to raise a SysTick exception\\nroughly every second. The SysTick exception handler keeps track of how many\\ntimes it has been called in the COUNT variable and then prints the value of COUNT to the host console using semihosting. NOTE: You can run this example on any Cortex-M device; you can also run it\\non QEMU #![deny(unsafe_code)]\\n#![no_main]\\n#![no_std] use panic_halt as _; use core::fmt::Write; use cortex_m::peripheral::syst::SystClkSource;\\nuse cortex_m_rt::{entry, exception};\\nuse cortex_m_semihosting::{ debug, hio::{self, HostStream},\\n}; #[entry]\\nfn main() -> ! { let p = cortex_m::Peripherals::take().unwrap(); let mut syst = p.SYST; // configures the system timer to trigger a SysTick exception every second syst.set_clock_source(SystClkSource::Core); // this is configured for the LM3S6965 which has a default CPU clock of 12 MHz syst.set_reload(12_000_000); syst.clear_current(); syst.enable_counter(); syst.enable_interrupt(); loop {}\\n} #[exception]\\nfn SysTick() { static mut COUNT: u32 = 0; static mut STDOUT: Option = None; *COUNT += 1; // Lazy initialization if STDOUT.is_none() { *STDOUT = hio::hstdout().ok(); } if let Some(hstdout) = STDOUT.as_mut() { write!(hstdout, \\"{}\\", *COUNT).ok(); } // IMPORTANT omit this `if` block if running on real hardware or your // debugger will end in an inconsistent state if *COUNT == 9 { // This will terminate the QEMU process debug::exit(debug::EXIT_SUCCESS); }\\n} tail -n5 Cargo.toml [dependencies]\\ncortex-m = \\"0.5.7\\"\\ncortex-m-rt = \\"0.6.3\\"\\npanic-halt = \\"0.2.0\\"\\ncortex-m-semihosting = \\"0.3.1\\" $ cargo run --release Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb (..)\\n123456789 If you run this on the Discovery board you’ll see the output on the OpenOCD\\nconsole. Also, the program will not stop when the count reaches 9.","breadcrumbs":"Getting started » Exceptions » A complete example","id":"81","title":"A complete example"},"82":{"body":"What the exception attribute actually does is override the default exception\\nhandler for a specific exception. If you don’t override the handler for a\\nparticular exception it will be handled by the DefaultHandler function, which\\ndefaults to: fn DefaultHandler() { loop {}\\n} This function is provided by the cortex-m-rt crate and marked as #[no_mangle] so you can put a breakpoint on “DefaultHandler” and catch unhandled exceptions. It’s possible to override this DefaultHandler using the exception attribute: #[exception]\\nfn DefaultHandler(irqn: i16) { // custom default handler\\n} The irqn argument indicates which exception is being serviced. A negative\\nvalue indicates that a Cortex-M exception is being serviced; and zero or a\\npositive value indicate that a device specific exception, AKA interrupt, is\\nbeing serviced.","breadcrumbs":"Getting started » Exceptions » The default exception handler","id":"82","title":"The default exception handler"},"83":{"body":"The HardFault exception is a bit special. This exception is fired when the\\nprogram enters an invalid state so its handler can not return as that could\\nresult in undefined behavior. Also, the runtime crate does a bit of work before\\nthe user defined HardFault handler is invoked to improve debuggability. The result is that the HardFault handler must have the following signature: fn(&ExceptionFrame) -> !. The argument of the handler is a pointer to\\nregisters that were pushed into the stack by the exception. These registers are\\na snapshot of the processor state at the moment the exception was triggered and\\nare useful to diagnose a hard fault. Here’s an example that performs an illegal operation: a read to a nonexistent\\nmemory location. NOTE: This program won’t work, i.e. it won’t crash, on QEMU because qemu-system-arm -machine lm3s6965evb doesn’t check memory loads and will\\nhappily return 0 on reads to invalid memory. #![no_main]\\n#![no_std] use panic_halt as _; use core::fmt::Write;\\nuse core::ptr; use cortex_m_rt::{entry, exception, ExceptionFrame};\\nuse cortex_m_semihosting::hio; #[entry]\\nfn main() -> ! { // read a nonexistent memory location unsafe { ptr::read_volatile(0x3FFF_0000 as *const u32); } loop {}\\n} #[exception]\\nfn HardFault(ef: &ExceptionFrame) -> ! { if let Ok(mut hstdout) = hio::hstdout() { writeln!(hstdout, \\"{:#?}\\", ef).ok(); } loop {}\\n} The HardFault handler prints the ExceptionFrame value. If you run this\\nyou’ll see something like this on the OpenOCD console. $ openocd\\n(..)\\nExceptionFrame { r0: 0x3fff0000, r1: 0x00000003, r2: 0x080032e8, r3: 0x00000000, r12: 0x00000000, lr: 0x080016df, pc: 0x080016e2, xpsr: 0x61000000,\\n} The pc value is the value of the Program Counter at the time of the exception\\nand it points to the instruction that triggered the exception. If you look at the disassembly of the program: $ cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex\\n(..)\\nResetTrampoline: 8000942: movw r0, #0xfffe 8000946: movt r0, #0x3fff 800094a: ldr r0, [r0] 800094c: b #-0x4 You can lookup the value of the program counter 0x0800094a in the disassembly.\\nYou’ll see that a load operation ( ldr r0, [r0] ) caused the exception.\\nThe r0 field of ExceptionFrame will tell you the value of register r0\\nwas 0x3fff_fffe at that time.","breadcrumbs":"Getting started » Exceptions » The hard fault handler","id":"83","title":"The hard fault handler"},"84":{"body":"Interrupts differ from exceptions in a variety of ways but their operation and\\nuse is largely similar and they are also handled by the same interrupt\\ncontroller. Whereas exceptions are defined by the Cortex-M architecture,\\ninterrupts are always vendor (and often even chip) specific implementations,\\nboth in naming and functionality. Interrupts do allow for a lot of flexibility which needs to be accounted for\\nwhen attempting to use them in an advanced way. We will not cover those uses in\\nthis book, however it is a good idea to keep the following in mind: Interrupts have programmable priorities which determine their handlers’ execution order Interrupts can nest and preempt, i.e. execution of an interrupt handler might be interrupted by another higher-priority interrupt In general the reason causing the interrupt to trigger needs to be cleared to prevent re-entering the interrupt handler endlessly The general initialization steps at runtime are always the same: Setup the peripheral(s) to generate interrupts requests at the desired occasions Set the desired priority of the interrupt handler in the interrupt controller Enable the interrupt handler in the interrupt controller Similarly to exceptions, the cortex-m-rt crate exposes an interrupt attribute for declaring interrupt handlers. However, this\\nattribute is only available when the device feature is enabled. That said, this attribute is not intended to be used directly—doing\\nso will result in a compilation error. Instead, you should use the re-exported version of the interrupt attribute provided by the device crate (usually generated using svd2rust).\\nThis ensures that the compiler can verify that the interrupt actually exists on the target device. The list of available interrupts—and\\ntheir position in the interrupt vector table—is typically auto-generated from an SVD file by svd2rust. use lm3s6965::interrupt; // Re-exported attribute from the device crate // Interrupt handler for the Timer2 interrupt\\n#[interrupt]\\nfn TIMER2A() { // .. // Clear reason for the generated interrupt request\\n} Interrupt handlers look like plain functions (except for the lack of arguments)\\nsimilar to exception handlers. However they can not be called directly by other\\nparts of the firmware due to the special calling conventions. It is however\\npossible to generate interrupt requests in software to trigger a diversion to\\nthe interrupt handler. Similar to exception handlers it is also possible to declare static mut\\nvariables inside the interrupt handlers for safe state keeping. #[interrupt]\\nfn TIMER2A() { static mut COUNT: u32 = 0; // `COUNT` has type `&mut u32` and it\'s safe to use *COUNT += 1;\\n} For a more detailed description about the mechanisms demonstrated here please\\nrefer to the exceptions section.","breadcrumbs":"Getting started » Interrupts » Interrupts","id":"84","title":"Interrupts"},"85":{"body":"","breadcrumbs":"Peripherals » Peripherals","id":"85","title":"Peripherals"},"86":{"body":"Most Microcontrollers have more than just a CPU, RAM, or Flash Memory - they contain sections of silicon which are used for interacting with systems outside of the microcontroller, as well as directly and indirectly interacting with their surroundings in the world via sensors, motor controllers, or human interfaces such as a display or keyboard. These components are collectively known as Peripherals. These peripherals are useful because they allow a developer to offload processing to them, avoiding having to handle everything in software. Similar to how a desktop developer would offload graphics processing to a video card, embedded developers can offload some tasks to peripherals allowing the CPU to spend its time doing something else important, or doing nothing in order to save power. If you look at the main circuit board in an old-fashioned home computer from the 1970s or 1980s (and actually, the desktop PCs of yesterday are not so far removed from the embedded systems of today) you would expect to see: A processor A RAM chip A ROM chip An I/O controller The RAM chip, ROM chip and I/O controller (the peripheral in this system) would be joined to the processor through a series of parallel traces known as a ‘bus’. This bus carries address information, which selects which device on the bus the processor wishes to communicate with, and a data bus which carries the actual data. In our embedded microcontrollers, the same principles apply - it’s just that everything is packed on to a single piece of silicon. However, unlike graphics cards, which typically have a Software API like Vulkan, Metal, or OpenGL, peripherals are exposed to our Microcontroller with a hardware interface, which is mapped to a chunk of the memory.","breadcrumbs":"Peripherals » What are Peripherals?","id":"86","title":"What are Peripherals?"},"87":{"body":"On a microcontroller, writing some data to some other arbitrary address, such as 0x4000_0000 or 0x0000_0000, may also be a completely valid action. On a desktop system, access to memory is tightly controlled by the MMU, or Memory Management Unit. This component has two major responsibilities: enforcing access permission to sections of memory (preventing one process from reading or modifying the memory of another process); and re-mapping segments of the physical memory to virtual memory ranges used in software. Microcontrollers do not typically have an MMU, and instead only use real physical addresses in software. Although 32 bit microcontrollers have a real and linear address space from 0x0000_0000, and 0xFFFF_FFFF, they generally only use a few hundred kilobytes of that range for actual memory. This leaves a significant amount of address space remaining. In earlier chapters, we were talking about RAM being located at address 0x2000_0000. If our RAM was 64 KiB long (i.e. with a maximum address of 0xFFFF) then addresses 0x2000_0000 to 0x2000_FFFF would correspond to our RAM. When we write to a variable which lives at address 0x2000_1234, what happens internally is that some logic detects the upper portion of the address (0x2000 in this example) and then activates the RAM so that it can act upon the lower portion of the address (0x1234 in this case). On a Cortex-M we also have our Flash ROM mapped in at address 0x0000_0000 up to, say, address 0x0007_FFFF (if we have a 512 KiB Flash ROM). Rather than ignore all remaining space between these two regions, Microcontroller designers instead mapped the interface for peripherals in certain memory locations. This ends up looking something like this: Nordic nRF52832 Datasheet (pdf)","breadcrumbs":"Peripherals » Linear and Real Memory Space","id":"87","title":"Linear and Real Memory Space"},"88":{"body":"Interaction with these peripherals is simple at a first glance - write the right data to the correct address. For example, sending a 32 bit word over a serial port could be as direct as writing that 32 bit word to a certain memory address. The Serial Port Peripheral would then take over and send out the data automatically. Configuration of these peripherals works similarly. Instead of calling a function to configure a peripheral, a chunk of memory is exposed which serves as the hardware API. Write 0x8000_0000 to a SPI Frequency Configuration Register, and the SPI port will send data at 8 Megabits per second. Write 0x0200_0000 to the same address, and the SPI port will send data at 125 Kilobits per second. These configuration registers look a little bit like this: Nordic nRF52832 Datasheet (pdf) This interface is how interactions with the hardware are made, no matter what language is used, whether that language is Assembly, C, or Rust.","breadcrumbs":"Peripherals » Memory Mapped Peripherals","id":"88","title":"Memory Mapped Peripherals"},"89":{"body":"","breadcrumbs":"Peripherals » A first attempt in Rust » A First Attempt","id":"89","title":"A First Attempt"},"9":{"body":"This book is distributed under the following licenses: The code samples and free-standing Cargo projects contained within this book are licensed under the terms of both the MIT License and the Apache License v2.0. The written prose, pictures and diagrams contained within this book are licensed under the terms of the Creative Commons CC-BY-SA v4.0 license. TL;DR: If you want to use our text or images in your work, you need to: Give the appropriate credit (i.e. mention this book on your slide, and provide a link to the relevant page) Provide a link to the CC-BY-SA v4.0 licence Indicate if you have changed the material in any way, and make any changes to our material available under the same licence Also, please do let us know if you find this book useful!","breadcrumbs":"Introduction » Re-using this material","id":"9","title":"Re-using this material"},"90":{"body":"Let’s look at the ‘SysTick’ peripheral - a simple timer which comes with every Cortex-M processor core. Typically you’ll be looking these up in the chip manufacturer’s data sheet or Technical Reference Manual, but this example is common to all ARM Cortex-M cores, let’s look in the ARM reference manual. We see there are four registers: Offset Name Description Width 0x00 SYST_CSR Control and Status Register 32 bits 0x04 SYST_RVR Reload Value Register 32 bits 0x08 SYST_CVR Current Value Register 32 bits 0x0C SYST_CALIB Calibration Value Register 32 bits","breadcrumbs":"Peripherals » A first attempt in Rust » The Registers","id":"90","title":"The Registers"},"91":{"body":"In Rust, we can represent a collection of registers in exactly the same way as we do in C - with a struct. #[repr(C)]\\nstruct SysTick { pub csr: u32, pub rvr: u32, pub cvr: u32, pub calib: u32,\\n} The qualifier #[repr(C)] tells the Rust compiler to lay this structure out like a C compiler would. That’s very important, as Rust allows structure fields to be re-ordered, while C does not. You can imagine the debugging we’d have to do if these fields were silently re-arranged by the compiler! With this qualifier in place, we have our four 32-bit fields which correspond to the table above. But of course, this struct is of no use by itself - we need a variable. let systick = 0xE000_E010 as *mut SysTick;\\nlet time = unsafe { (*systick).cvr };","breadcrumbs":"Peripherals » A first attempt in Rust » The C Approach","id":"91","title":"The C Approach"},"92":{"body":"Now, there are a couple of problems with the approach above. We have to use unsafe every time we want to access our Peripheral. We’ve got no way of specifying which registers are read-only or read-write. Any piece of code anywhere in your program could access the hardware\\nthrough this structure. Most importantly, it doesn’t actually work… Now, the problem is that compilers are clever. If you make two writes to the same piece of RAM, one after the other, the compiler can notice this and just skip the first write entirely. In C, we can mark variables as volatile to ensure that every read or write occurs as intended. In Rust, we instead mark the accesses as volatile, not the variable. let systick = unsafe { &mut *(0xE000_E010 as *mut SysTick) };\\nlet time = unsafe { core::ptr::read_volatile(&mut systick.cvr) }; So, we’ve fixed one of our four problems, but now we have even more unsafe code! Fortunately, there’s a third party crate which can help - volatile_register. use volatile_register::{RW, RO}; #[repr(C)]\\nstruct SysTick { pub csr: RW, pub rvr: RW, pub cvr: RW, pub calib: RO,\\n} fn get_systick() -> &\'static mut SysTick { unsafe { &mut *(0xE000_E010 as *mut SysTick) }\\n} fn get_time() -> u32 { let systick = get_systick(); systick.cvr.read()\\n} Now, the volatile accesses are performed automatically through the read and write methods. It’s still unsafe to perform writes, but to be fair, hardware is a bunch of mutable state and there’s no way for the compiler to know whether these writes are actually safe, so this is a good default position.","breadcrumbs":"Peripherals » A first attempt in Rust » Volatile Accesses","id":"92","title":"Volatile Accesses"},"93":{"body":"We need to wrap this struct up into a higher-layer API that is safe for our users to call. As the driver author, we manually verify the unsafe code is correct, and then present a safe API for our users so they don’t have to worry about it (provided they trust us to get it right!). One example might be: use volatile_register::{RW, RO}; pub struct SystemTimer { p: &\'static mut RegisterBlock\\n} #[repr(C)]\\nstruct RegisterBlock { pub csr: RW, pub rvr: RW, pub cvr: RW, pub calib: RO,\\n} impl SystemTimer { pub fn new() -> SystemTimer { SystemTimer { p: unsafe { &mut *(0xE000_E010 as *mut RegisterBlock) } } } pub fn get_time(&self) -> u32 { self.p.cvr.read() } pub fn set_reload(&mut self, reload_value: u32) { unsafe { self.p.rvr.write(reload_value) } }\\n} pub fn example_usage() -> String { let mut st = SystemTimer::new(); st.set_reload(0x00FF_FFFF); format!(\\"Time is now 0x{:08x}\\", st.get_time())\\n} Now, the problem with this approach is that the following code is perfectly acceptable to the compiler: fn thread1() { let mut st = SystemTimer::new(); st.set_reload(2000);\\n} fn thread2() { let mut st = SystemTimer::new(); st.set_reload(1000);\\n} Our &mut self argument to the set_reload function checks that there are no other references to that particular SystemTimer struct, but they don’t stop the user creating a second SystemTimer which points to the exact same peripheral! Code written in this fashion will work if the author is diligent enough to spot all of these ‘duplicate’ driver instances, but once the code is spread out over multiple modules, drivers, developers, and days, it gets easier and easier to make these kinds of mistakes.","breadcrumbs":"Peripherals » A first attempt in Rust » The Rusty Wrapper","id":"93","title":"The Rusty Wrapper"},"94":{"body":"Unfortunately, hardware is basically nothing but mutable global state, which can feel very frightening for a Rust developer. Hardware exists independently from the structures of the code we write, and can be modified at any time by the real world.","breadcrumbs":"Peripherals » The Borrow Checker » Mutable Global State","id":"94","title":"Mutable Global State"},"95":{"body":"How can we reliably interact with these peripherals? Always use volatile methods to read or write to peripheral memory, as it can change at any time In software, we should be able to share any number of read-only accesses to these peripherals If some software should have read-write access to a peripheral, it should hold the only reference to that peripheral","breadcrumbs":"Peripherals » The Borrow Checker » What should our rules be?","id":"95","title":"What should our rules be?"},"96":{"body":"The last two of these rules sound suspiciously similar to what the Borrow Checker does already! Imagine if we could pass around ownership of these peripherals, or offer immutable or mutable references to them? Well, we can, but for the Borrow Checker, we need to have exactly one instance of each peripheral, so Rust can handle this correctly. Well, luckily in the hardware, there is only one instance of any given peripheral, but how can we expose that in the structure of our code?","breadcrumbs":"Peripherals » The Borrow Checker » The Borrow Checker","id":"96","title":"The Borrow Checker"},"97":{"body":"In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. Wikipedia: Singleton Pattern","breadcrumbs":"Peripherals » Singletons » Singletons","id":"97","title":"Singletons"},"98":{"body":"We could make everything a public static, like this static mut THE_SERIAL_PORT: SerialPort = SerialPort; fn main() { let _ = unsafe { THE_SERIAL_PORT.read_speed(); };\\n} But this has a few problems. It is a mutable global variable, and in Rust, these are always unsafe to interact with. These variables are also visible across your whole program, which means the borrow checker is unable to help you track references and ownership of these variables.","breadcrumbs":"Peripherals » Singletons » But why can’t we just use global variable(s)?","id":"98","title":"But why can’t we just use global variable(s)?"},"99":{"body":"Instead of just making our peripheral a global variable, we might instead decide to make a structure, in this case called PERIPHERALS, which contains an Option for each of our peripherals. struct Peripherals { serial: Option,\\n}\\nimpl Peripherals { fn take_serial(&mut self) -> SerialPort { let p = replace(&mut self.serial, None); p.unwrap() }\\n}\\nstatic mut PERIPHERALS: Peripherals = Peripherals { serial: Some(SerialPort),\\n}; This structure allows us to obtain a single instance of our peripheral. If we try to call take_serial() more than once, our code will panic! fn main() { let serial_1 = unsafe { PERIPHERALS.take_serial() }; // This panics! // let serial_2 = unsafe { PERIPHERALS.take_serial() };\\n} Although interacting with this structure is unsafe, once we have the SerialPort it contained, we no longer need to use unsafe, or the PERIPHERALS structure at all. This has a small runtime overhead because we must wrap the SerialPort structure in an option, and we’ll need to call take_serial() once, however this small up-front cost allows us to leverage the borrow checker throughout the rest of our program.","breadcrumbs":"Peripherals » Singletons » How do we do this in Rust?","id":"99","title":"How do we do this in Rust?"}},"docInfo":{"0":{"body":16,"breadcrumbs":2,"title":1},"1":{"body":17,"breadcrumbs":3,"title":2},"10":{"body":5,"breadcrumbs":4,"title":2},"100":{"body":84,"breadcrumbs":5,"title":3},"101":{"body":78,"breadcrumbs":2,"title":0},"102":{"body":57,"breadcrumbs":5,"title":3},"103":{"body":100,"breadcrumbs":4,"title":2},"104":{"body":106,"breadcrumbs":6,"title":2},"105":{"body":57,"breadcrumbs":6,"title":2},"106":{"body":93,"breadcrumbs":8,"title":3},"107":{"body":211,"breadcrumbs":7,"title":2},"108":{"body":233,"breadcrumbs":6,"title":2},"109":{"body":287,"breadcrumbs":6,"title":2},"11":{"body":139,"breadcrumbs":4,"title":2},"110":{"body":51,"breadcrumbs":8,"title":4},"111":{"body":45,"breadcrumbs":8,"title":3},"112":{"body":90,"breadcrumbs":8,"title":3},"113":{"body":28,"breadcrumbs":6,"title":1},"114":{"body":99,"breadcrumbs":2,"title":1},"115":{"body":130,"breadcrumbs":3,"title":2},"116":{"body":5,"breadcrumbs":4,"title":3},"117":{"body":80,"breadcrumbs":3,"title":2},"118":{"body":57,"breadcrumbs":2,"title":1},"119":{"body":66,"breadcrumbs":2,"title":1},"12":{"body":51,"breadcrumbs":5,"title":3},"120":{"body":72,"breadcrumbs":2,"title":1},"121":{"body":57,"breadcrumbs":2,"title":1},"122":{"body":183,"breadcrumbs":4,"title":3},"123":{"body":196,"breadcrumbs":3,"title":2},"124":{"body":172,"breadcrumbs":3,"title":2},"125":{"body":322,"breadcrumbs":4,"title":3},"126":{"body":282,"breadcrumbs":2,"title":1},"127":{"body":421,"breadcrumbs":3,"title":2},"128":{"body":88,"breadcrumbs":2,"title":1},"129":{"body":46,"breadcrumbs":2,"title":1},"13":{"body":49,"breadcrumbs":4,"title":2},"130":{"body":72,"breadcrumbs":5,"title":4},"131":{"body":69,"breadcrumbs":3,"title":2},"132":{"body":64,"breadcrumbs":2,"title":1},"133":{"body":236,"breadcrumbs":3,"title":2},"134":{"body":130,"breadcrumbs":3,"title":2},"135":{"body":11,"breadcrumbs":3,"title":2},"136":{"body":96,"breadcrumbs":5,"title":4},"137":{"body":108,"breadcrumbs":3,"title":2},"138":{"body":64,"breadcrumbs":6,"title":5},"139":{"body":42,"breadcrumbs":3,"title":2},"14":{"body":57,"breadcrumbs":5,"title":3},"140":{"body":9,"breadcrumbs":4,"title":2},"141":{"body":27,"breadcrumbs":6,"title":3},"142":{"body":88,"breadcrumbs":8,"title":4},"143":{"body":0,"breadcrumbs":5,"title":1},"144":{"body":21,"breadcrumbs":10,"title":6},"145":{"body":0,"breadcrumbs":5,"title":1},"146":{"body":78,"breadcrumbs":11,"title":7},"147":{"body":38,"breadcrumbs":12,"title":8},"148":{"body":15,"breadcrumbs":12,"title":8},"149":{"body":0,"breadcrumbs":5,"title":1},"15":{"body":43,"breadcrumbs":4,"title":2},"150":{"body":18,"breadcrumbs":11,"title":7},"151":{"body":59,"breadcrumbs":10,"title":6},"152":{"body":0,"breadcrumbs":7,"title":3},"153":{"body":65,"breadcrumbs":12,"title":8},"154":{"body":70,"breadcrumbs":14,"title":10},"155":{"body":286,"breadcrumbs":12,"title":8},"156":{"body":21,"breadcrumbs":8,"title":4},"157":{"body":42,"breadcrumbs":5,"title":1},"158":{"body":157,"breadcrumbs":8,"title":4},"159":{"body":62,"breadcrumbs":8,"title":4},"16":{"body":61,"breadcrumbs":3,"title":1},"160":{"body":156,"breadcrumbs":5,"title":1},"161":{"body":85,"breadcrumbs":6,"title":2},"162":{"body":39,"breadcrumbs":6,"title":2},"163":{"body":88,"breadcrumbs":8,"title":4},"164":{"body":101,"breadcrumbs":7,"title":3},"165":{"body":200,"breadcrumbs":6,"title":2},"166":{"body":301,"breadcrumbs":7,"title":3},"167":{"body":18,"breadcrumbs":5,"title":1},"168":{"body":120,"breadcrumbs":2,"title":1},"169":{"body":22,"breadcrumbs":4,"title":3},"17":{"body":52,"breadcrumbs":3,"title":1},"170":{"body":33,"breadcrumbs":3,"title":2},"171":{"body":37,"breadcrumbs":7,"title":3},"172":{"body":42,"breadcrumbs":6,"title":2},"173":{"body":215,"breadcrumbs":8,"title":4},"174":{"body":102,"breadcrumbs":7,"title":3},"175":{"body":92,"breadcrumbs":7,"title":3},"176":{"body":41,"breadcrumbs":8,"title":4},"177":{"body":48,"breadcrumbs":8,"title":4},"178":{"body":67,"breadcrumbs":9,"title":5},"179":{"body":38,"breadcrumbs":7,"title":3},"18":{"body":2,"breadcrumbs":3,"title":1},"180":{"body":40,"breadcrumbs":7,"title":3},"181":{"body":19,"breadcrumbs":7,"title":3},"182":{"body":21,"breadcrumbs":5,"title":1},"183":{"body":54,"breadcrumbs":6,"title":2},"184":{"body":82,"breadcrumbs":8,"title":4},"185":{"body":0,"breadcrumbs":4,"title":2},"186":{"body":24,"breadcrumbs":10,"title":4},"187":{"body":120,"breadcrumbs":7,"title":1},"188":{"body":183,"breadcrumbs":8,"title":2},"189":{"body":94,"breadcrumbs":8,"title":2},"19":{"body":93,"breadcrumbs":3,"title":1},"190":{"body":166,"breadcrumbs":8,"title":2},"191":{"body":149,"breadcrumbs":9,"title":4},"192":{"body":19,"breadcrumbs":4,"title":2},"193":{"body":25,"breadcrumbs":3,"title":1},"194":{"body":10,"breadcrumbs":3,"title":1},"195":{"body":34,"breadcrumbs":3,"title":1},"196":{"body":17,"breadcrumbs":3,"title":1},"197":{"body":35,"breadcrumbs":3,"title":1},"198":{"body":7,"breadcrumbs":3,"title":1},"199":{"body":18,"breadcrumbs":3,"title":1},"2":{"body":69,"breadcrumbs":2,"title":1},"20":{"body":58,"breadcrumbs":5,"title":3},"200":{"body":8,"breadcrumbs":3,"title":1},"201":{"body":9,"breadcrumbs":3,"title":1},"21":{"body":57,"breadcrumbs":4,"title":2},"22":{"body":22,"breadcrumbs":5,"title":3},"23":{"body":0,"breadcrumbs":6,"title":4},"24":{"body":68,"breadcrumbs":3,"title":1},"25":{"body":0,"breadcrumbs":6,"title":4},"26":{"body":53,"breadcrumbs":4,"title":2},"27":{"body":45,"breadcrumbs":6,"title":4},"28":{"body":70,"breadcrumbs":3,"title":1},"29":{"body":31,"breadcrumbs":8,"title":6},"3":{"body":46,"breadcrumbs":2,"title":1},"30":{"body":54,"breadcrumbs":3,"title":1},"31":{"body":49,"breadcrumbs":5,"title":3},"32":{"body":49,"breadcrumbs":3,"title":1},"33":{"body":29,"breadcrumbs":4,"title":2},"34":{"body":46,"breadcrumbs":4,"title":2},"35":{"body":47,"breadcrumbs":4,"title":2},"36":{"body":34,"breadcrumbs":4,"title":2},"37":{"body":8,"breadcrumbs":4,"title":2},"38":{"body":158,"breadcrumbs":4,"title":2},"39":{"body":22,"breadcrumbs":4,"title":2},"4":{"body":47,"breadcrumbs":3,"title":2},"40":{"body":26,"breadcrumbs":4,"title":2},"41":{"body":9,"breadcrumbs":5,"title":3},"42":{"body":6,"breadcrumbs":4,"title":1},"43":{"body":93,"breadcrumbs":4,"title":1},"44":{"body":113,"breadcrumbs":5,"title":2},"45":{"body":5,"breadcrumbs":4,"title":1},"46":{"body":27,"breadcrumbs":6,"title":3},"47":{"body":22,"breadcrumbs":6,"title":3},"48":{"body":0,"breadcrumbs":4,"title":1},"49":{"body":41,"breadcrumbs":7,"title":4},"5":{"body":105,"breadcrumbs":2,"title":1},"50":{"body":45,"breadcrumbs":4,"title":1},"51":{"body":4,"breadcrumbs":4,"title":1},"52":{"body":25,"breadcrumbs":7,"title":4},"53":{"body":271,"breadcrumbs":6,"title":2},"54":{"body":36,"breadcrumbs":4,"title":2},"55":{"body":44,"breadcrumbs":4,"title":1},"56":{"body":35,"breadcrumbs":8,"title":5},"57":{"body":31,"breadcrumbs":6,"title":3},"58":{"body":42,"breadcrumbs":5,"title":2},"59":{"body":46,"breadcrumbs":4,"title":1},"6":{"body":15,"breadcrumbs":2,"title":1},"60":{"body":130,"breadcrumbs":5,"title":2},"61":{"body":253,"breadcrumbs":5,"title":2},"62":{"body":391,"breadcrumbs":4,"title":1},"63":{"body":349,"breadcrumbs":4,"title":1},"64":{"body":358,"breadcrumbs":4,"title":1},"65":{"body":17,"breadcrumbs":4,"title":1},"66":{"body":95,"breadcrumbs":5,"title":2},"67":{"body":233,"breadcrumbs":4,"title":1},"68":{"body":708,"breadcrumbs":4,"title":1},"69":{"body":211,"breadcrumbs":8,"title":3},"7":{"body":69,"breadcrumbs":3,"title":2},"70":{"body":86,"breadcrumbs":7,"title":2},"71":{"body":89,"breadcrumbs":8,"title":3},"72":{"body":183,"breadcrumbs":10,"title":5},"73":{"body":34,"breadcrumbs":6,"title":1},"74":{"body":50,"breadcrumbs":6,"title":1},"75":{"body":83,"breadcrumbs":6,"title":1},"76":{"body":221,"breadcrumbs":8,"title":3},"77":{"body":289,"breadcrumbs":4,"title":1},"78":{"body":265,"breadcrumbs":4,"title":1},"79":{"body":72,"breadcrumbs":4,"title":1},"8":{"body":34,"breadcrumbs":3,"title":2},"80":{"body":287,"breadcrumbs":4,"title":1},"81":{"body":165,"breadcrumbs":5,"title":2},"82":{"body":74,"breadcrumbs":6,"title":3},"83":{"body":216,"breadcrumbs":6,"title":3},"84":{"body":252,"breadcrumbs":4,"title":1},"85":{"body":0,"breadcrumbs":2,"title":1},"86":{"body":156,"breadcrumbs":2,"title":1},"87":{"body":162,"breadcrumbs":5,"title":4},"88":{"body":97,"breadcrumbs":4,"title":3},"89":{"body":0,"breadcrumbs":6,"title":2},"9":{"body":79,"breadcrumbs":4,"title":3},"90":{"body":68,"breadcrumbs":5,"title":1},"91":{"body":74,"breadcrumbs":6,"title":2},"92":{"body":153,"breadcrumbs":6,"title":2},"93":{"body":158,"breadcrumbs":6,"title":2},"94":{"body":22,"breadcrumbs":6,"title":3},"95":{"body":27,"breadcrumbs":4,"title":1},"96":{"body":40,"breadcrumbs":5,"title":2},"97":{"body":15,"breadcrumbs":3,"title":1},"98":{"body":36,"breadcrumbs":6,"title":4},"99":{"body":96,"breadcrumbs":3,"title":1}},"length":202},"lang":"English"}}')); \ No newline at end of file diff --git a/typ/mdbook/assets/toc-7ac66f26.js_part1 b/typ/mdbook/assets/toc-7ac66f26.js_part1 new file mode 100644 index 00000000..6184feb7 --- /dev/null +++ b/typ/mdbook/assets/toc-7ac66f26.js_part1 @@ -0,0 +1,11 @@ +// Populate the sidebar +// +// This is a script, and not included directly in the page, to control the total size of the book. +// The TOC contains an entry for each page, so if each page includes a copy of the TOC, +// the total size of the page becomes O(n**2). +class MDBookSidebarScrollbox extends HTMLElement { + constructor() { + super(); + } + connectedCallback() { + this.innerHTML = ' \ No newline at end of file diff --git a/typ/mdbook/assets/toc-7ac66f26.js_part2 b/typ/mdbook/assets/toc-7ac66f26.js_part2 new file mode 100644 index 00000000..1ead2f71 --- /dev/null +++ b/typ/mdbook/assets/toc-7ac66f26.js_part2 @@ -0,0 +1,445 @@ +'; + // Set the current, active page, and reveal it if it's hidden + let current_page = document.location.href.toString().split('#')[0].split('?')[0]; + if (current_page.endsWith('/')) { + current_page += 'index.html'; + } + const links = Array.prototype.slice.call(this.querySelectorAll('a')); + const l = links.length; + for (let i = 0; i < l; ++i) { + const link = links[i]; + const href = link.getAttribute('href'); + if (href && !href.startsWith('#') && !/^(?:[a-z+]+:)?\/\//.test(href)) { + link.href = path_to_root + href; + } + // The 'index' page is supposed to alias the first chapter in the book. + // Check both with and without the '.html' suffix to be robust against pretty URLs + if (link.href.replace(/\.html$/, '') === current_page.replace(/\.html$/, '') + || i === 0 + && path_to_root === '' + && current_page.endsWith('/index.html')) { + link.classList.add('active'); + let parent = link.parentElement; + while (parent) { + if (parent.tagName === 'LI' && parent.classList.contains('chapter-item')) { + parent.classList.add('expanded'); + } + parent = parent.parentElement; + } + } + } + // Track and set sidebar scroll position + this.addEventListener('click', e => { + if (e.target.tagName === 'A') { + const clientRect = e.target.getBoundingClientRect(); + const sidebarRect = this.getBoundingClientRect(); + sessionStorage.setItem('sidebar-scroll-offset', clientRect.top - sidebarRect.top); + } + }, { passive: true }); + const sidebarScrollOffset = sessionStorage.getItem('sidebar-scroll-offset'); + sessionStorage.removeItem('sidebar-scroll-offset'); + if (sidebarScrollOffset !== null) { + // preserve sidebar scroll position when navigating via links within sidebar + const activeSection = this.querySelector('.active'); + if (activeSection) { + const clientRect = activeSection.getBoundingClientRect(); + const sidebarRect = this.getBoundingClientRect(); + const currentOffset = clientRect.top - sidebarRect.top; + this.scrollTop += currentOffset - parseFloat(sidebarScrollOffset); + } + } else { + // scroll sidebar to current active section when navigating via + // 'next/previous chapter' buttons + const activeSection = document.querySelector('#mdbook-sidebar .active'); + if (activeSection) { + activeSection.scrollIntoView({ block: 'center' }); + } + } + // Toggle buttons + const sidebarAnchorToggles = document.querySelectorAll('.chapter-fold-toggle'); + function toggleSection(ev) { + ev.currentTarget.parentElement.parentElement.classList.toggle('expanded'); + } + Array.from(sidebarAnchorToggles).forEach(el => { + el.addEventListener('click', toggleSection); + }); + } +} +window.customElements.define('mdbook-sidebar-scrollbox', MDBookSidebarScrollbox); + + +// --------------------------------------------------------------------------- +// Support for dynamically adding headers to the sidebar. + +(function() { + // This is used to detect which direction the page has scrolled since the + // last scroll event. + let lastKnownScrollPosition = 0; + // This is the threshold in px from the top of the screen where it will + // consider a header the "current" header when scrolling down. + const defaultDownThreshold = 150; + // Same as defaultDownThreshold, except when scrolling up. + const defaultUpThreshold = 300; + // The threshold is a virtual horizontal line on the screen where it + // considers the "current" header to be above the line. The threshold is + // modified dynamically to handle headers that are near the bottom of the + // screen, and to slightly offset the behavior when scrolling up vs down. + let threshold = defaultDownThreshold; + // This is used to disable updates while scrolling. This is needed when + // clicking the header in the sidebar, which triggers a scroll event. It + // is somewhat finicky to detect when the scroll has finished, so this + // uses a relatively dumb system of disabling scroll updates for a short + // time after the click. + let disableScroll = false; + // Array of header elements on the page. + let headers; + // Array of li elements that are initially collapsed headers in the sidebar. + // I'm not sure why eslint seems to have a false positive here. + // eslint-disable-next-line prefer-const + let headerToggles = []; + // This is a debugging tool for the threshold which you can enable in the console. + let thresholdDebug = false; + + // Updates the threshold based on the scroll position. + function updateThreshold() { + const scrollTop = window.pageYOffset || document.documentElement.scrollTop; + const windowHeight = window.innerHeight; + const documentHeight = document.documentElement.scrollHeight; + + // The number of pixels below the viewport, at most documentHeight. + // This is used to push the threshold down to the bottom of the page + // as the user scrolls towards the bottom. + const pixelsBelow = Math.max(0, documentHeight - (scrollTop + windowHeight)); + // The number of pixels above the viewport, at least defaultDownThreshold. + // Similar to pixelsBelow, this is used to push the threshold back towards + // the top when reaching the top of the page. + const pixelsAbove = Math.max(0, defaultDownThreshold - scrollTop); + // How much the threshold should be offset once it gets close to the + // bottom of the page. + const bottomAdd = Math.max(0, windowHeight - pixelsBelow - defaultDownThreshold); + let adjustedBottomAdd = bottomAdd; + + // Adjusts bottomAdd for a small document. The calculation above + // assumes the document is at least twice the windowheight in size. If + // it is less than that, then bottomAdd needs to be shrunk + // proportional to the difference in size. + if (documentHeight < windowHeight * 2) { + const maxPixelsBelow = documentHeight - windowHeight; + const t = 1 - pixelsBelow / Math.max(1, maxPixelsBelow); + const clamp = Math.max(0, Math.min(1, t)); + adjustedBottomAdd *= clamp; + } + + let scrollingDown = true; + if (scrollTop < lastKnownScrollPosition) { + scrollingDown = false; + } + + if (scrollingDown) { + // When scrolling down, move the threshold up towards the default + // downwards threshold position. If near the bottom of the page, + // adjustedBottomAdd will offset the threshold towards the bottom + // of the page. + const amountScrolledDown = scrollTop - lastKnownScrollPosition; + const adjustedDefault = defaultDownThreshold + adjustedBottomAdd; + threshold = Math.max(adjustedDefault, threshold - amountScrolledDown); + } else { + // When scrolling up, move the threshold down towards the default + // upwards threshold position. If near the bottom of the page, + // quickly transition the threshold back up where it normally + // belongs. + const amountScrolledUp = lastKnownScrollPosition - scrollTop; + const adjustedDefault = defaultUpThreshold - pixelsAbove + + Math.max(0, adjustedBottomAdd - defaultDownThreshold); + threshold = Math.min(adjustedDefault, threshold + amountScrolledUp); + } + + if (documentHeight <= windowHeight) { + threshold = 0; + } + + if (thresholdDebug) { + const id = 'mdbook-threshold-debug-data'; + let data = document.getElementById(id); + if (data === null) { + data = document.createElement('div'); + data.id = id; + data.style.cssText = ` + position: fixed; + top: 50px; + right: 10px; + background-color: 0xeeeeee; + z-index: 9999; + pointer-events: none; + `; + document.body.appendChild(data); + } + data.innerHTML = ` + + + + + + + + + + +
documentHeight${documentHeight.toFixed(1)}
windowHeight${windowHeight.toFixed(1)}
scrollTop${scrollTop.toFixed(1)}
pixelsAbove${pixelsAbove.toFixed(1)}
pixelsBelow${pixelsBelow.toFixed(1)}
bottomAdd${bottomAdd.toFixed(1)}
adjustedBottomAdd${adjustedBottomAdd.toFixed(1)}
scrollingDown${scrollingDown}
threshold${threshold.toFixed(1)}
+ `; + drawDebugLine(); + } + + lastKnownScrollPosition = scrollTop; + } + + function drawDebugLine() { + if (!document.body) { + return; + } + const id = 'mdbook-threshold-debug-line'; + const existingLine = document.getElementById(id); + if (existingLine) { + existingLine.remove(); + } + const line = document.createElement('div'); + line.id = id; + line.style.cssText = ` + position: fixed; + top: ${threshold}px; + left: 0; + width: 100vw; + height: 2px; + background-color: red; + z-index: 9999; + pointer-events: none; + `; + document.body.appendChild(line); + } + + function mdbookEnableThresholdDebug() { + thresholdDebug = true; + updateThreshold(); + drawDebugLine(); + } + + window.mdbookEnableThresholdDebug = mdbookEnableThresholdDebug; + + // Updates which headers in the sidebar should be expanded. If the current + // header is inside a collapsed group, then it, and all its parents should + // be expanded. + function updateHeaderExpanded(currentA) { + // Add expanded to all header-item li ancestors. + let current = currentA.parentElement; + while (current) { + if (current.tagName === 'LI' && current.classList.contains('header-item')) { + current.classList.add('expanded'); + } + current = current.parentElement; + } + } + + // Updates which header is marked as the "current" header in the sidebar. + // This is done with a virtual Y threshold, where headers at or below + // that line will be considered the current one. + function updateCurrentHeader() { + if (!headers || !headers.length) { + return; + } + + // Reset the classes, which will be rebuilt below. + const els = document.getElementsByClassName('current-header'); + for (const el of els) { + el.classList.remove('current-header'); + } + for (const toggle of headerToggles) { + toggle.classList.remove('expanded'); + } + + // Find the last header that is above the threshold. + let lastHeader = null; + for (const header of headers) { + const rect = header.getBoundingClientRect(); + if (rect.top <= threshold) { + lastHeader = header; + } else { + break; + } + } + if (lastHeader === null) { + lastHeader = headers[0]; + const rect = lastHeader.getBoundingClientRect(); + const windowHeight = window.innerHeight; + if (rect.top >= windowHeight) { + return; + } + } + + // Get the anchor in the summary. + const href = '#' + lastHeader.id; + const a = [...document.querySelectorAll('.header-in-summary')] + .find(element => element.getAttribute('href') === href); + if (!a) { + return; + } + + a.classList.add('current-header'); + + updateHeaderExpanded(a); + } + + // Updates which header is "current" based on the threshold line. + function reloadCurrentHeader() { + if (disableScroll) { + return; + } + updateThreshold(); + updateCurrentHeader(); + } + + + // When clicking on a header in the sidebar, this adjusts the threshold so + // that it is located next to the header. This is so that header becomes + // "current". + function headerThresholdClick(event) { + // See disableScroll description why this is done. + disableScroll = true; + setTimeout(() => { + disableScroll = false; + }, 100); + // requestAnimationFrame is used to delay the update of the "current" + // header until after the scroll is done, and the header is in the new + // position. + requestAnimationFrame(() => { + requestAnimationFrame(() => { + // Closest is needed because if it has child elements like . + const a = event.target.closest('a'); + const href = a.getAttribute('href'); + const targetId = href.substring(1); + const targetElement = document.getElementById(targetId); + if (targetElement) { + threshold = targetElement.getBoundingClientRect().bottom; + updateCurrentHeader(); + } + }); + }); + } + + // Takes the nodes from the given head and copies them over to the + // destination, along with some filtering. + function filterHeader(source, dest) { + const clone = source.cloneNode(true); + clone.querySelectorAll('mark').forEach(mark => { + mark.replaceWith(...mark.childNodes); + }); + dest.append(...clone.childNodes); + } + + // Scans page for headers and adds them to the sidebar. + document.addEventListener('DOMContentLoaded', function() { + const activeSection = document.querySelector('#mdbook-sidebar .active'); + if (activeSection === null) { + return; + } + + const main = document.getElementsByTagName('main')[0]; + headers = Array.from(main.querySelectorAll('h2, h3, h4, h5, h6')) + .filter(h => h.id !== '' && h.children.length && h.children[0].tagName === 'A'); + + if (headers.length === 0) { + return; + } + + // Build a tree of headers in the sidebar. + + const stack = []; + + const firstLevel = parseInt(headers[0].tagName.charAt(1)); + for (let i = 1; i < firstLevel; i++) { + const ol = document.createElement('ol'); + ol.classList.add('section'); + if (stack.length > 0) { + stack[stack.length - 1].ol.appendChild(ol); + } + stack.push({level: i + 1, ol: ol}); + } + + // The level where it will start folding deeply nested headers. + const foldLevel = 3; + + for (let i = 0; i < headers.length; i++) { + const header = headers[i]; + const level = parseInt(header.tagName.charAt(1)); + + const currentLevel = stack[stack.length - 1].level; + if (level > currentLevel) { + // Begin nesting to this level. + for (let nextLevel = currentLevel + 1; nextLevel <= level; nextLevel++) { + const ol = document.createElement('ol'); + ol.classList.add('section'); + const last = stack[stack.length - 1]; + const lastChild = last.ol.lastChild; + // Handle the case where jumping more than one nesting + // level, which doesn't have a list item to place this new + // list inside of. + if (lastChild) { + lastChild.appendChild(ol); + } else { + last.ol.appendChild(ol); + } + stack.push({level: nextLevel, ol: ol}); + } + } else if (level < currentLevel) { + while (stack.length > 1 && stack[stack.length - 1].level > level) { + stack.pop(); + } + } + + const li = document.createElement('li'); + li.classList.add('header-item'); + li.classList.add('expanded'); + if (level < foldLevel) { + li.classList.add('expanded'); + } + const span = document.createElement('span'); + span.classList.add('chapter-link-wrapper'); + const a = document.createElement('a'); + span.appendChild(a); + a.href = '#' + header.id; + a.classList.add('header-in-summary'); + filterHeader(header.children[0], a); + a.addEventListener('click', headerThresholdClick); + const nextHeader = headers[i + 1]; + if (nextHeader !== undefined) { + const nextLevel = parseInt(nextHeader.tagName.charAt(1)); + if (nextLevel > level && level >= foldLevel) { + const toggle = document.createElement('a'); + toggle.classList.add('chapter-fold-toggle'); + toggle.classList.add('header-toggle'); + toggle.addEventListener('click', () => { + li.classList.toggle('expanded'); + }); + const toggleDiv = document.createElement('div'); + toggleDiv.textContent = '❱'; + toggle.appendChild(toggleDiv); + span.appendChild(toggle); + headerToggles.push(li); + } + } + li.appendChild(span); + + const currentParent = stack[stack.length - 1]; + currentParent.ol.appendChild(li); + } + + const onThisPage = document.createElement('div'); + onThisPage.classList.add('on-this-page'); + onThisPage.append(stack[0].ol); + const activeItemSpan = activeSection.parentElement; + activeItemSpan.after(onThisPage); + }); + + document.addEventListener('DOMContentLoaded', reloadCurrentHeader); + document.addEventListener('scroll', reloadCurrentHeader, { passive: true }); +})(); + diff --git a/typ/mdbook/assets/tomorrow-night-4c0ae647.css b/typ/mdbook/assets/tomorrow-night-4c0ae647.css new file mode 100644 index 00000000..11752b8a --- /dev/null +++ b/typ/mdbook/assets/tomorrow-night-4c0ae647.css @@ -0,0 +1,104 @@ +/* Tomorrow Night Theme */ +/* https://github.com/jmblog/color-themes-for-highlightjs */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* https://github.com/jmblog/color-themes-for-highlightjs */ + +/* Tomorrow Comment */ +.hljs-comment { + color: #969896; +} + +/* Tomorrow Red */ +.hljs-variable, +.hljs-attribute, +.hljs-attr, +.hljs-tag, +.hljs-regexp, +.ruby .hljs-constant, +.xml .hljs-tag .hljs-title, +.xml .hljs-pi, +.xml .hljs-doctype, +.html .hljs-doctype, +.css .hljs-id, +.css .hljs-class, +.css .hljs-pseudo { + color: #cc6666; +} + +/* Tomorrow Orange */ +.hljs-number, +.hljs-preprocessor, +.hljs-pragma, +.hljs-built_in, +.hljs-literal, +.hljs-params, +.hljs-constant { + color: #de935f; +} + +/* Tomorrow Yellow */ +.ruby .hljs-class .hljs-title, +.css .hljs-rule .hljs-attribute { + color: #f0c674; +} + +/* Tomorrow Green */ +.hljs-string, +.hljs-value, +.hljs-inheritance, +.hljs-header, +.hljs-name, +.ruby .hljs-symbol, +.xml .hljs-cdata { + color: #b5bd68; +} + +/* Tomorrow Aqua */ +.hljs-title, +.hljs-section, +.css .hljs-hexcolor { + color: #8abeb7; +} + +/* Tomorrow Blue */ +.hljs-function, +.python .hljs-decorator, +.python .hljs-title, +.ruby .hljs-function .hljs-title, +.ruby .hljs-title .hljs-keyword, +.perl .hljs-sub, +.javascript .hljs-title, +.coffeescript .hljs-title { + color: #81a2be; +} + +/* Tomorrow Purple */ +.hljs-keyword, +.javascript .hljs-function { + color: #b294bb; +} + +.hljs { + display: block; + overflow-x: auto; + background: #1d1f21; + color: #c5c8c6; +} + +.coffeescript .javascript, +.javascript .xml, +.tex .hljs-formula, +.xml .javascript, +.xml .vbscript, +.xml .css, +.xml .hljs-cdata { + opacity: 0.5; +} + +.hljs-addition { + color: #718c00; +} + +.hljs-deletion { + color: #c82829; +} diff --git a/typ/mdbook/book.typ b/typ/mdbook/book.typ new file mode 100644 index 00000000..3f5b5450 --- /dev/null +++ b/typ/mdbook/book.typ @@ -0,0 +1,450 @@ +#import "icons.typ": builtin-icon +#import "scripts.typ": builtin-script + +#let lbl(path) = label(path.replace("/","-")) + +#let to-string(content) = { + if content.has("text") { + content.text + } else if content.has("children") { + content.children.map(to-string).join("") + } else if content.has("body") { + to-string(content.body) + } else if content == [] { + " " + } +} + +#let elem-to-string(content) = { + if content == none { + "" + } else if content.has("children") { + content.children.map(elem-to-string).join("") + } else if content.has("tag") { + let attrs = "" + if content.has("attrs") { + for (k, v) in content.attrs { + attrs = attrs+" "+k+"=\""+v+"\"" + } + } + "<"+content.tag+attrs+">"+elem-to-string(content.body)+"" + } else { + to-string(content) + } +} + +#let html_head_common(pth) = { + html.link(rel: "stylesheet", href: pth+"css/variables-8adf115d.css") + html.link(rel: "stylesheet", href: pth+"css/general-e96d0476.css") + html.link(rel: "stylesheet", href: pth+"css/chrome-d279d366.css") + html.link(rel: "stylesheet", href: pth+"css/print-9e4910d8.css", media: "print") + // Fonts + html.link(rel: "stylesheet", href: pth+"fonts/fonts-9644e21d.css") +} + +#let html_head(title, root_pth, lang-list: true) = html.head({ + html.meta(charset: "utf-8") + html.title(title) + + html.meta(name: "description", content:"") + html.meta(name: "viewport", content: "width=device-width, initial-scale=1") + html.meta(name: "theme-color", content: "#ffffff") + + // Custom HTML head + html.link(rel: "icon", href: root_pth+"favicon-de23e50b.svg") + html.elem("link", attrs: (rel: "shortcut icon", href: root_pth+"favicon-8114d1fc.png")) + html_head_common(root_pth) + + if lang-list { + html.style("#language-list { left: auto; right: 10px; } #language-list a { color: inherit; }") + } + + // Highlight.js Stylesheets + html.link(rel: "stylesheet", id: "mdbook-highlight-css", href: root_pth+"highlight-493f70e1.css") + html.link(rel: "stylesheet", id: "mdbook-tomorrow-night-css", href: root_pth+"tomorrow-night-4c0ae647.css") + html.link(rel: "stylesheet", id: "mdbook-ayu-highlight-css", href: root_pth+"ayu-highlight-3fdfc3ac.css") + + // Provide site root and default themes to javascript + builtin-script("provide-themes", root_pth: root_pth) +}) + +#let help_container() = html.div(id: "mdbook-help-container", + html.div(id: "mdbook-help-popup", { + html.h2(class: "mdbook-help-title")[Keyboard shortcuts] + html.div({ + html.p[Press #html.kbd[←] or #html.kbd[→] to navigate between chapters] + html.p[Press #html.kbd[S] or #html.kbd[/] to search in the book] + html.p[Press #html.kbd[?] to show this help] + html.p[Press #html.kbd[Esc] to hide this help] + }) + }) +) + +#let body_header() = { + // Work around some values being stored in localStorage wrapped in quotes + builtin-script("quote-workaround") + // Set the theme before any content is loaded, prevents flash + builtin-script("init-theme") + html.input(type: "checkbox", id: "mdbook-sidebar-toggle-anchor", class: "hidden") + // Hide / unhide sidebar before it is displayed + builtin-script("hide-sidebar") +} + +#let icon_templates() = { + html.template(id: "fa-eye", builtin-icon("eye")) + html.template(id: "fa-eye-slash", builtin-icon("eye-slash")) + html.template(id: "fa-copy", builtin-icon("copy")) + html.template(id: "fa-play", builtin-icon("play")) + html.template(id: "fa-clock-rotate-left", builtin-icon("clock-rotate-left")) +} + +#let footer_scripts(pth) = { + html.script("window.playground_copyable = true;") + html.script(src: pth+"elasticlunr-ef4e11c1.min.js") + html.script(src: pth+"mark-09e88c2c.min.js") + html.script(src: pth+"searcher-09f2665d.js") + html.script(src: pth+"clipboard-1626706a.min.js") + html.script(src: pth+"highlight-abc7f01d.js") + html.script(src: pth+"book-609e4cb8.js") +} + +#let source_array(sources) = { + let items = () + for (path, src) in sources.pairs() { + items.push((path, src.at("content"), src.at("title"))) + let sub = src.at("sub", default: none) + if sub != none { + for (path, src) in sub.pairs() { + items.push((path, src.at("content"), src.at("title"))) + let sub = src.at("sub", default: none) + if sub != none { + for (path, src) in sub.pairs() { + items.push((path, src.at("content"), src.at("title"))) + } + } + } + } + } + items +} + +#let page_header(data, pth) = { + let root_pth = data.root_prefix+pth + html.div(id: "mdbook-menu-bar-hover-placeholder") + html.div(id: "mdbook-menu-bar", class: ("menu-bar", "sticky"), { + html.div(class: "left-buttons", { + let attrs = (id: "mdbook-sidebar-toggle", class: "icon-button", title: "Toggle Table of Contents", aria-label: "Toggle Table of Contents", aria-controls: "mdbook-sidebar") + attrs.insert("for", "mdbook-sidebar-toggle-anchor") + html.elem("label", attrs: attrs, builtin-icon("bars")) + html.button(id: "mdbook-theme-toggle", class: "icon-button", type: "button", title: "Change theme", aria-label: "Change theme", aria-haspopup: true, aria-expanded: false, aria-controls: "mdbook-theme-list", builtin-icon("paintbrush")) + html.ul(id: "mdbook-theme-list", class: "theme-popup", aria-label: "Themes", role: "menu", { + let themes = ( + default_theme: "Auto", + light: "Light", + rust: "Rust", + coal: "Coal", + navy: "Navy", + ayu: "Ayu", + ) + for (id, name) in themes.pairs() { + html.li(role: none, + html.button(role: "menuitem", class: "theme", id: "mdbook-theme-"+id, name) + ) + } + }) + html.button(id: "mdbook-search-toggle", class: "icon-button", type: "button", title: "Search (`/`)", aria-label: "Toggle Searchbar", aria-expanded: false, aria-keyshortcuts: "/ s", aria-controls: "mdbook-searchbar", builtin-icon("search")) + }) + html.h1(class: "menu-title", data.book_title) + html.div(class: "right-buttons", { + if data.multilingual { + html.button(id: "language-toggle", class: "icon-button", type: "button", title: "Change language", aria-label: "Change language", aria-haspopup: true, aria-expanded: false, aria-controls: "language-list", builtin-icon("globe")) + html.ul(id: "language-list", class: "theme-popup", aria-label: "Languages", role: "menu", + for (l, name) in data.languages { + html.li(role: none, + html.a(role: "menuitem", class: "theme", id: "lang-"+l, name, href: root_pth+if l == data.default_lang { + "" + } else { + l+"/" + }+"index.html")) + } + ) + builtin-script("show-language-list") + } + html.a(href: root_pth+"book_"+data.lang+".pdf", title: "PDF version of this book", aria-label: "PDF", builtin-icon("pdf", id: "book-pdf")) + if data.git != none { + html.a(href: data.git, title: "Git repository", aria-label: "Git repository", builtin-icon("github")) + } + }) + }) + html.div(id: "mdbook-search-wrapper", class: "hidden", { + html.form(id: "mdbook-searchbar-outer", class: "searchbar-outer", + html.div(class: "search-wrapper", { + html.input(type: "search", id: "mdbook-searchbar", name: "searchbar", placeholder: "Search this book ...", aria-controls: "mdbook-searchresults-outer", aria-describedby: "searchresults-header") + html.div(class: "spinner-wrapper", builtin-icon("spinner", id: "fa-spin")) + }) + ) + html.div(id: "mdbook-searchresults-outer", class: "searchresults-outer hidden", { + html.div(id: "mdbook-searchresults-header", class: "searchresults-header") + html.ul(id: "mdbook-searchresults") + }) + }) + + // Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM + builtin-script("apply-aria") +} + +#let sidebar(depth) = html.nav(id: "mdbook-sidebar", class: "sidebar", aria-label: "Table of contents", { + html.elem("mdbook-sidebar-scrollbox", attrs:(class: "sidebar-scrollbox")) + html.noscript({ + let pth = (("../",)*depth).join("") + html.iframe(class: "sidebar-iframe-outer", src: pth+"toc.html") + }) + html.div(id: "mdbook-sidebar-resize-handle", class:"sidebar-resize-handle", + html.div(class: "sidebar-resize-indicator") + ) +}) +#let toc_tree(sources, prefix: "") = html.ol(class: "chapter", { + let num = (0,) + for (path, src) in sources.pairs() { + let d = 0 + num = num.slice(0, d+1) + num.at(d) = num.at(d) + 1 + html.li(class: ("chapter-item", "expanded"), html.span(class: "chapter-link-wrapper", + html.a(href: prefix+path+".html", target: "_parent", [#html.strong(aria-hidden: true, num.map(i => [#i.]).join[]) #src.at("title")]) + )) + if "sub" in src { + html.ol(class: "section", { + num.push(0) + for (path, src) in src.at("sub").pairs() { + let d = 1 + num = num.slice(0, d+1) + num.at(d) = num.at(d) + 1 + html.li(class: ("chapter-item", "expanded"), html.span(class: "chapter-link-wrapper", + html.a(href: prefix+path+".html", target: "_parent", [#html.strong(aria-hidden: true, num.map(i => [#i.]).join[]) #src.at("title")]) + )) + if "sub" in src { + html.ol(class: "section", { + num.push(0) + for (path, src) in src.at("sub").pairs() { + let d = 2 + num = num.slice(0, d+1) + num.at(d) = num.at(d) + 1 + html.li(class: ("chapter-item", "expanded"), html.span(class: "chapter-link-wrapper", + html.a(href: prefix+path+".html", target: "_parent", [#html.strong(aria-hidden: true, num.map(i => [#i.]).join[]) #src.at("title")]) + )) + } + }) + } + } + }) + } + } +}) +#let toc(tree, out, data) = document(out, + html.html(lang: data.lang, class: "light", dir: ltr, { + html.head({ + html.meta(charset: "utf-8") + html.meta(name:"robots", content: "noindex") + html.meta(name: "viewport", content: "width=device-width, initial-scale=1") + html.meta(name: "theme-color", content: "#ffffff") + html_head_common(data.root_prefix) + html.title() + }) + html.body(class: "sidebar-iframe-inner", tree) + }) +) + +// Navigation buttons +#let nav_buttons(pth, prev, next, wide: false) = html.nav(class: if wide { "nav-wide-wrapper" } else { "nav-wrapper" }, aria-label: "Page navigation", { + let c = if wide { "nav-chapters" } else { "mobile-nav-chapters" } + if prev != none { + html.a(rel: "prev", href: pth+prev+".html", class: c + " previous", title: "Previous chapter", aria-label: "Previous chapter", aria-keyshortcuts: "Left", builtin-icon("left")) + } + if next != none { + html.a(rel: "next", href: pth+next+".html", class: c + " next", title: "Next chapter", aria-label: "Next chapter", aria-keyshortcuts: "Right", builtin-icon("right")) + } +}) + +#let book_page( + source, + out, + data, + title, + depth, + sidebar, + prev_path, + next_path, +) = document(out, + html.html(lang: data.lang, class: ("light", "sidebar-visible"), dir: ltr, { + let pth = (("../",)*depth).join("") + let root_pth = data.root_prefix+pth + html_head(to-string(title) + " - " + data.book_title, root_pth, lang-list: data.multilingual) + // Start loading toc.js asap + html.script(src: pth+"toc-7ac66f26_"+data.lang+".js") + html.body({ + help_container() + html.div(id: "mdbook-body-container", { + body_header() + sidebar + html.div(id: "mdbook-page-wrapper", class: "page-wrapper", { + html.div(class: "page", { + page_header(data, pth) + html.div(id: "mdbook-content", class: "content", { + html.main(source) + nav_buttons(pth, prev_path, next_path) + }) + }) + nav_buttons(pth, prev_path, next_path, wide: true) + }) + icon_templates() + footer_scripts(root_pth) + }) + }) + }) +) + +#let asset_list = ( + "ayu-highlight-3fdfc3ac.css", + "book-609e4cb8.js", + "clipboard-1626706a.min.js", + "css/chrome-d279d366.css", + "css/general-e96d0476.css", + "css/print-9e4910d8.css", + "css/variables-8adf115d.css", + "elasticlunr-ef4e11c1.min.js", + "favicon-8114d1fc.png", + "favicon-de23e50b.svg", + "fonts/fonts-9644e21d.css", + "fonts/OPEN-SANS-LICENSE.txt", + "fonts/open-sans-v17-all-charsets-300-7736aa35.woff2", + "fonts/open-sans-v17-all-charsets-300italic-2c7b95c0.woff2", + "fonts/open-sans-v17-all-charsets-600-486c6759.woff2", + "fonts/open-sans-v17-all-charsets-600italic-1a3e8659.woff2", + "fonts/open-sans-v17-all-charsets-700-c22fe8c7.woff2", + "fonts/open-sans-v17-all-charsets-700italic-238ae959.woff2", + "fonts/open-sans-v17-all-charsets-800-3d2c812a.woff2", + "fonts/open-sans-v17-all-charsets-800italic-ba1521ec.woff2", + "fonts/open-sans-v17-all-charsets-italic-6c9463f7.woff2", + "fonts/open-sans-v17-all-charsets-regular-2e3b1d34.woff2", + "fonts/SOURCE-CODE-PRO-LICENSE.txt", + "fonts/source-code-pro-v11-all-charsets-500-2bdd9410.woff2", + "highlight-493f70e1.css", + "highlight-abc7f01d.js", + "mark-09e88c2c.min.js", + "searcher-09f2665d.js", + "searchindex-8ec871e3.js", + "tomorrow-night-4c0ae647.css", +) + +#let html_book( + sources, + data, +) = { + let sa = source_array(sources) + if data.is_root { + for path in asset_list { + asset(path, read("assets/"+path, encoding: none)) + } + } + asset(data.prefix+"toc-7ac66f26_"+data.lang+".js", read("assets/"+"toc-7ac66f26.js_part1")+elem-to-string(toc_tree(sources, prefix: data.prefix))+read("assets/"+"toc-7ac66f26.js_part2")) + + toc(toc_tree(sources), data.prefix+"toc.html", data) + for (i, (path, source, title)) in sa.enumerate() { + let (prev_path, _, _) = if i > 0 { sa.at(i - 1) } else { (none, none, none) } + let (next_path, _, _) = sa.at(i + 1, default: (none, none, none)) + let out = data.prefix+path + ".html" + let depth = path.split("/").len() - 1 + [ + #book_page(source, out, data, title, depth, sidebar(depth), prev_path, next_path) #lbl(path) + ] + if i == 0 { + let depth = 0 + book_page(source, data.prefix+"index.html", data, title, depth, sidebar(depth), prev_path, next_path) + } + } +} + +#let pdf_book(title_page, sources) = { + import "@preview/codly:1.3.0": * + import "@preview/codly-languages:0.1.10": * + show: codly-init.with() + codly( + languages: codly-languages + (console: codly-languages.shell), + number-format: none, + fill: luma(250), + zebra-fill: luma(245) + ) + + let sa = source_array(sources) + set par(justify: true) + set heading(numbering: "1.") + show heading.where(level: 1): it => { pagebreak();it } + + show link: it => { text(fill: blue, it) } + + title_page + + outline(depth: 3) + let part = "main" + + set page(numbering: "1", number-align: right + top) + + for (path, source, _) in sa { + let offset = path.split("/").len() - 1 + if path.ends-with("/index") { + offset = offset - 1 + } + if part == "main" and path.starts-with("appendix/") { + path = "appendix" + counter(heading).update(0) + set heading(numbering: "A.1.", offset: offset+1) + source + } else { + set heading(offset: offset+1) + source + } + } +} + +#let book( + tgt, + sources, + lang, + languages, + default_lang: "en", + book_title: "The Book", + title_page: none, + git: none, +) = { + let is_root = lang == default_lang + let data = ( + lang: lang, + languages: languages, + is_root: is_root, + multilingual: languages.keys().len() > 1, + prefix: if is_root { "" } else { lang+"/" }, + root_prefix: if is_root { + "" + } else { + "../" + }, + book_title: book_title, + git: git, + default_lang: default_lang, + ) + if tgt == "pdf" { + pdf_book( + if title_page == none [ + #v(1fr) + #align(center, text(size: 40pt, [#book_title\ (#data.languages.at(data.lang))])) + #v(1fr) + ] else { title_page }, + sources, + ) + } else if tgt == "html" { + html_book( + sources, + data, + ) + } +} diff --git a/typ/mdbook/code.typ b/typ/mdbook/code.typ new file mode 100644 index 00000000..edb38dde --- /dev/null +++ b/typ/mdbook/code.typ @@ -0,0 +1,39 @@ +#import "@preview/codly:1.3.0": codly + +#let insert-code( + full_code, + tgt: "html", + lang: "rust", + block: true, + anchor: none, + lines: none, + offset: 0, + line-numbers: false, +) = { + let offset = offset + let code = if type(anchor) == str { + let lines = full_code.split("\n") + let left = lines.position(l => { regex("ANCHOR:\s+"+anchor) in l }) + offset = offset + left + let right = lines.position(l => { regex("ANCHOR_END:\s+"+anchor) in l }) + lines.slice(left+1, right).join("\n") + } else if type(lines) == int { + offset = offset + lines - 1 + full_code.split("\n").at(lines - 1) + } else if type(lines) == array { + offset = offset + lines.at(0) - 1 + full_code.split("\n").slice(lines.at(0) - 1, lines.at(1)).join("\n") + } else { + full_code + } + if tgt == "pdf" { + if line-numbers { + codly(number-format: numbering.with("1")) + } + codly(offset: offset) + raw(code, lang: lang, block: block) + codly(number-format: none) + } else { + raw(code, lang: lang, block: block) + } +} diff --git a/typ/mdbook/icons.typ b/typ/mdbook/icons.typ new file mode 100644 index 00000000..e1658863 --- /dev/null +++ b/typ/mdbook/icons.typ @@ -0,0 +1,74 @@ +#let icons = ( + bars: ( + "0 0 448 512", + "M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z" + ), + paintbrush: ( + "0 0 576 512", + "M371.3 367.1c27.3-3.9 51.9-19.4 67.2-42.9L600.2 74.1c12.6-19.5 9.4-45.3-7.6-61.2S549.7-4.4 531.1 9.6L294.4 187.2c-24 18-38.2 46.1-38.4 76.1L371.3 367.1zm-19.6 25.4l-116-104.4C175.9 290.3 128 339.6 128 400c0 3.9 .2 7.8 .6 11.6c1.8 17.5-10.2 36.4-27.8 36.4H96c-17.7 0-32 14.3-32 32s14.3 32 32 32H240c61.9 0 112-50.1 112-112c0-2.5-.1-5-.2-7.5z" + ), + search: ( + "0 0 512 512", + "M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352c79.5 0 144-64.5 144-144s-64.5-144-144-144S64 128.5 64 208s64.5 144 144 144z" + ), + globe: ( + "0 0 512 512", + "M351.9 280l-190.9 0c2.9 64.5 17.2 123.9 37.5 167.4 11.4 24.5 23.7 41.8 35.1 52.4 11.2 10.5 18.9 12.2 22.9 12.2s11.7-1.7 22.9-12.2c11.4-10.6 23.7-28 35.1-52.4 20.3-43.5 34.6-102.9 37.5-167.4zM160.9 232l190.9 0C349 167.5 334.7 108.1 314.4 64.6 303 40.2 290.7 22.8 279.3 12.2 268.1 1.7 260.4 0 256.4 0s-11.7 1.7-22.9 12.2c-11.4 10.6-23.7 28-35.1 52.4-20.3 43.5-34.6 102.9-37.5 167.4zm-48 0C116.4 146.4 138.5 66.9 170.8 14.7 78.7 47.3 10.9 131.2 1.5 232l111.4 0zM1.5 280c9.4 100.8 77.2 184.7 169.3 217.3-32.3-52.2-54.4-131.7-57.9-217.3L1.5 280zm398.4 0c-3.5 85.6-25.6 165.1-57.9 217.3 92.1-32.7 159.9-116.5 169.3-217.3l-111.4 0zm111.4-48C501.9 131.2 434.1 47.3 342 14.7 374.3 66.9 396.4 146.4 399.9 232l111.4 0z" + ), + pdf: ( + "0 0 576 512", + "M208 48L96 48c-8.8 0-16 7.2-16 16l0 384c0 8.8 7.2 16 16 16l80 0 0 48-80 0c-35.3 0-64-28.7-64-64L32 64C32 28.7 60.7 0 96 0L229.5 0c17 0 33.3 6.7 45.3 18.7L397.3 141.3c12 12 18.7 28.3 18.7 45.3l0 149.5-48 0 0-128-88 0c-39.8 0-72-32.2-72-72l0-88zM348.1 160L256 67.9 256 136c0 13.3 10.7 24 24 24l68.1 0zM240 380l32 0c33.1 0 60 26.9 60 60s-26.9 60-60 60l-12 0 0 28c0 11-9 20-20 20s-20-9-20-20l0-128c0-11 9-20 20-20zm32 80c11 0 20-9 20-20s-9-20-20-20l-12 0 0 40 12 0zm96-80l32 0c28.7 0 52 23.3 52 52l0 64c0 28.7-23.3 52-52 52l-32 0c-11 0-20-9-20-20l0-128c0-11 9-20 20-20zm32 128c6.6 0 12-5.4 12-12l0-64c0-6.6-5.4-12-12-12l-12 0 0 88 12 0zm76-108c0-11 9-20 20-20l48 0c11 0 20 9 20 20s-9 20-20 20l-28 0 0 24 28 0c11 0 20 9 20 20s-9 20-20 20l-28 0 0 44c0 11-9 20-20 20s-20-9-20-20l0-128z" + ), + github: ( + "0 0 496 512", "M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z" + ), + spinner: ( + "0 0 512 512", + "M304 48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zm0 416c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM48 304c26.5 0 48-21.5 48-48s-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48zm464-48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM142.9 437c18.7-18.7 18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zm0-294.2c18.7-18.7 18.7-49.1 0-67.9S93.7 56.2 75 75s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zM369.1 437c18.7 18.7 49.1 18.7 67.9 0s18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9z" + ), + left: ( + "0 0 320 512", + "M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z" + ), + right: ( + "0 0 320 512", + "M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z" + ), + eye: ( + "0 0 576 512", + "M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z", + ), + eye-slash: ( + "0 0 640 512", + "M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z", + ), + copy: ( + "0 0 512 512", + "M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z" + ), + play: ( + "0 0 384 512", + "M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80V432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z" + ), + clock-rotate-left: ( + "0 0 512 512", + "M75 75L41 41C25.9 25.9 0 36.6 0 57.9V168c0 13.3 10.7 24 24 24H134.1c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24V256c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65V152c0-13.3-10.7-24-24-24z" + ) +) + +#let builtin-icon(name, class: "fa-svg", id: none) = { + assert(name in icons, message: "Missing icon `"+name+"`") + let (viewBox, path) = icons.at(name) + html.span( + class: class, + ..(if id != none { (id: id) }), + html.elem( + "svg", + attrs: ( + xmlns: "http://www.w3.org/2000/svg", + viewBox: viewBox + ), + html.elem("path", attrs: (d: path)), + ) + ) +} \ No newline at end of file diff --git a/typ/mdbook/lib.typ b/typ/mdbook/lib.typ new file mode 100644 index 00000000..f2df11d7 --- /dev/null +++ b/typ/mdbook/lib.typ @@ -0,0 +1,2 @@ +#import "book.typ": book, lbl +#import "code.typ": insert-code \ No newline at end of file diff --git a/typ/mdbook/scripts.typ b/typ/mdbook/scripts.typ new file mode 100644 index 00000000..c4043bfb --- /dev/null +++ b/typ/mdbook/scripts.typ @@ -0,0 +1,72 @@ + +#let builtin-script(name, ..attrs) = { + let s = if name == "provide-themes" { + let root_pth = attrs.at("root_pth") + " + const path_to_root = \""+root_pth+"\"; + const default_light_theme = \"light\"; + const default_dark_theme = \"navy\"; + window.path_to_searchindex_js = \""+root_pth+"searchindex-8ec871e3.js\"; + " + } else if name == "quote-workaround" { + " + try { + let theme = localStorage.getItem('mdbook-theme'); + let sidebar = localStorage.getItem('mdbook-sidebar'); + + if (theme.startsWith('\"') && theme.endsWith('\"')) { + localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1)); + } + + if (sidebar.startsWith('\"') && sidebar.endsWith('\"')) { + localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1)); + } + } catch (e) { } + " + } else if name == "init-theme" { + " + const default_theme = window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? default_dark_theme : default_light_theme; + let theme; + try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } + if (theme === null || theme === undefined) { theme = default_theme; } + const html = document.documentElement; + html.classList.remove('light') + html.classList.add(theme); + html.classList.add(\"js\"); + " + } else if name == "hide-sidebar" { + " + let sidebar = null; + const sidebar_toggle = document.getElementById(\"mdbook-sidebar-toggle-anchor\"); + if (document.body.clientWidth >= 1080) { + try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } + sidebar = sidebar || 'visible'; + } else { + sidebar = 'hidden'; + sidebar_toggle.checked = false; + } + if (sidebar === 'visible') { + sidebar_toggle.checked = true; + } else { + html.classList.remove('sidebar-visible'); + } + " + } else if name == "apply-aria" { + " + document.getElementById('mdbook-sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); + document.getElementById('mdbook-sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); + Array.from(document.querySelectorAll('#mdbook-sidebar a')).forEach(function(link) { + link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1); + }); + " + } else if name == "show-language-list" { + " + let langToggle = document.getElementById(\"language-toggle\"); + let langList = document.getElementById(\"language-list\"); + langToggle.addEventListener(\"click\", (event) => { + langList.style.display = langList.style.display == \"block\" ? \"none\" : \"block\"; + }); + " + } + html.script(s) +} \ No newline at end of file diff --git a/typ/mdbook/typst.toml b/typ/mdbook/typst.toml new file mode 100644 index 00000000..2a1eada7 --- /dev/null +++ b/typ/mdbook/typst.toml @@ -0,0 +1,15 @@ +[package] +name = "typbook" +version = "0.1.0" +entrypoint = "lib.typ" +authors = ["Andrey Zgarbul "] +license = "MPL-2.0" +description = "Generate `mdBook` like books and documentation" +repository = "https://github.com/burrbull/typbook" +keywords = ["html", "web", "mdbook", "documentation"] +categories = ["components", "model", "utility"] +compiler = "0.15.0" + +[template] +path = "template" +entrypoint = "main.typ" diff --git a/typ/peripherals/a-first-attempt.typ b/typ/peripherals/a-first-attempt.typ new file mode 100644 index 00000000..8e8cc0b2 --- /dev/null +++ b/typ/peripherals/a-first-attempt.typ @@ -0,0 +1,471 @@ +#import "../config.typ": * + +#h1((en: [A First Attempt], + de: [Ein erster Versuch in Rust], + ja: [最初の試み], + zh: [Rust尝鲜], +), offset: whole) + += #tr(( + en: [The Registers], + de: [Die Register], + ja: [レジスタ], + zh: [寄存器], +)) + +#let url_arm = "http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/Babieigh.html" +#tr(( +en: [ + Let's look at the 'SysTick' peripheral - a simple timer which comes with + every Cortex-M processor core. Typically you'll be looking these up in + the chip manufacturer's data sheet or _Technical Reference Manual_, + but this example is common to all ARM Cortex-M cores, let's look in the + #link(url_arm)[ARM reference manual]. + We see there are four registers: +], +de: [ + Betrachten wir die „SysTick"-Peripherie -- einen einfachen Timer, der in + jedem Cortex-M-Prozessorkern enthalten ist. Normalerweise würde man + hierfür im Datenblatt des Chip-Herstellers oder im _Technical + Reference Manual_ nachschlagen; da dieses Beispiel jedoch für alle + ARM-Cortex-M-Kerne gilt, werfen wir einen Blick in das + #link(url_arm)[ARM-Referenzhandbuch]. + Wir sehen, dass es vier Register gibt: +], +ja: [ + `SysTick` ペリフェラルを見ていきましょう。 `SysTick` + はCortex-Mプロセッサ・コアに搭載されているシンプルなタイマーです。 + 通常は、チップメーカーのデータシートや_テクニカルリファレンスマニュアル_でこれらのペリフェラルの情報を調べることができるのですが、この例においては全てのARM + Cortex-Mコアで共通のものですので、今回は#link("http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/Babieigh.html")[ARMリファレンスマニュアル]を見てみましょう。 + そこには4つのレジスタが載っています。 +], +zh: [ + 让我们看下 'SysTick' 外设 - + 一个简单的计时器,它存在于每个Cortex-M处理器内核中。通常你能在芯片厂商的数据手册或者_技术参考手册_中看到它们,但是下面的例子对所有ARM + Cortex-M核心都是通用的,让我们看下#link(url_arm)[ARM参考手册]。我们能看到这里有四个寄存器: +])) + +#let _32bits = tr(( + en: [32 bits], + ja: [32ビット], +), default: [32 bits]) + +#figure( + kind: table, + table( + columns: 4, + align: (auto,auto,auto,auto,), + table.header( + tr(( + en: [Offset], + de: [Offset], + ja: [オフセット], + zh: [Offset], + )), + tr(( + en: [Name], + de: [Name], + ja: [名前], + zh: [Name], + )), + tr(( + en: [Description], + de: [Beschreibung], + ja: [説明], + zh: [Description], + )), + tr(( + en: [Width], + de: [Breite], + ja: [幅], + zh: [Width], + )), + ), + [0x00], [SYST_CSR], + tr(( + en: [Control and Status Register], + de: [Steuerung und Status Register], + ja: [制御およびステータスレジスタ], + zh: [控制和状态寄存器], + )), + _32bits, + [0x04], [SYST_RVR], + tr(( + en: [Reload Value Register], + de: [Wert-Register neu laden], + ja: [リロード値レジスタ], + zh: [重装载值寄存器], + )), + _32bits, + [0x08], [SYST_CVR], + tr(( + en: [Current Value Register], + de: [Register für den aktuellen Wert], + ja: [現在値レジスタ], + zh: [当前值寄存器], + )), + _32bits, + [0x0C], [SYST_CALIB], + tr(( + en: [Calibration Value Register], + de: [Kalibrierwert-Register], + ja: [キャリブレーション値レジスタ], + zh: [校准值寄存器], + )), + _32bits, + ) +) + += #tr(( + en: [The C Approach], + de: [Der C-Ansatz], + ja: [Cアプローチ], + zh: [C语言风格的方法(The C Approach)], +)) + +#tr(( +en: [ + In Rust, we can represent a collection of registers in exactly the same + way as we do in C - with a `struct`. +], +de: [ + In Rust können wir eine Sammlung von Registern auf genau dieselbe Weise + darstellen wie in C -- mit einem `struct`. +], +ja: [ + Rustでも、`struct`を使ってCと同じ方法でレジスタの集合を正確に表現することができます。 +], +zh: [ + 在Rust中,我们可以像C语言一样,用一个 `struct` 表示一组寄存器。 +])) + +```rust +#[repr(C)] +struct SysTick { + pub csr: u32, + pub rvr: u32, + pub cvr: u32, + pub calib: u32, +} +``` + +#tr(( +en: [ + The qualifier `#[repr(C)]` tells the Rust compiler to lay this structure + out like a C compiler would. That's very important, as Rust allows + structure fields to be re-ordered, while C does not. You can imagine the + debugging we'd have to do if these fields were silently re-arranged by + the compiler! With this qualifier in place, we have our four 32-bit + fields which correspond to the table above. But of course, this `struct` + is of no use by itself - we need a variable. +], +de: [ + Der Qualifizierer `#[repr(C)]` weist den Rust-Compiler an, diese + Struktur wie ein C-Compiler anzulegen. Das ist sehr wichtig, da Rust die + Neuordnung von Strukturfeldern zulässt, C jedoch nicht. Sie können sich + vorstellen, wie viel Debugging wir durchführen müssten, wenn diese + Felder vom Compiler stillschweigend neu angeordnet würden! Mit diesem + Qualifizierer verfügen wir über unsere vier 32-Bit-Felder, die der + obigen Tabelle entsprechen. Aber diese „Struktur" allein nützt natürlich + nichts -- wir brauchen eine Variable. +], +ja: [ + `#[repr(C)]`修飾子はRustコンパイラ対して、この構造体をCコンパイラと同じようにメモリにレイアウトするように指示します。 + これはとても重要なことです。なぜならRustでは、Cにおいては行われない構造体のフィールドの並び替えが許されているためです。 + コンパイラによって暗黙のうちに構造体のフィールドが並び替えられることにより、デバッグをするはめになることは想像できるでしょう! + この修飾子を置くことで、4つの32ビットの各フィールドは上記のテーブルに対応付けられます。 + ただしもちろん、この`struct`はそれ自体では何の役にも立ちません。次のように変数として使う必要があります。 +], +zh: [ + 告诉Rust编译器像C编译器一样去布局这个结构体。这非常重要,因为Rust允许结构体字段被重新排序,而C语言不允许。你可以想象下如果这些字段被编译器悄悄地重新排了序,在调试时会给我们带来多大的麻烦!有了这个限定符,我们就有了与上表对应的四个32位的字段。但当然,这个 + `struct` 本身没什么用处 - 我们需要一个变量。 +])) + +```rust +let systick = 0xE000_E010 as *mut SysTick; +let time = unsafe { (*systick).cvr }; +``` + += #tr(( + en: [Volatile Accesses], + de: [Volatile-Zugriffe], + ja: [volatileアクセス], + zh: [volatile访问(Volatile Accesses)], +)) + +#tr(( +en: [ + Now, there are a couple of problems with the approach above. + + We have to use unsafe every time we want to access our Peripheral. + + We've got no way of specifying which registers are read-only or + read-write. + + Any piece of code anywhere in your program could access the hardware + through this structure. + + Most importantly, it doesn't actually work… +], +de: [ + Nun gibt es bei dem oben genannten Ansatz einige Probleme. + + Wir müssen `unsafe` verwenden, wann immer wir auf unsere Peripherie + zugreifen wollen. + + Wir haben keine Möglichkeit festzulegen, welche Register nur lesbar + oder sowohl les- als auch schreibbar sind. + + Jeder Code-Abschnitt an beliebiger Stelle Ihres Programms könnte über + diese Struktur auf die Hardware zugreifen. + + Vor allem aber funktioniert es eigentlich nicht … +], +ja: [ + 上記のやり方には、いくつか問題があります。 + + ペリフェラルにアクセスするためには毎回アンセーフを使わなくてはなりません。 + + どのレジスタが読み取り専用でどのレジスタが読み書き可能かを指定する方法がありません。 + + プログラム内のどのコードからでもこの構造体を通してハードウェアにアクセスできてしまいます。 + + 最も大事なことは、このコードは実際には動作しないということです… +], +zh: [ + 现在,上面的方法有一堆问题。 + + 每次想要访问外设,不得不使用unsafe 。 + + 无法指定哪个寄存器是只读的或者读写的。 + + 程序中任何地方的任何一段代码都可以通过这个结构体访问硬件。 + + 最重要的是,实际上它并不能工作。 +])) + +#tr(( +en: [ + Now, the problem is that compilers are clever. If you make two writes to + the same piece of RAM, one after the other, the compiler can notice this + and just skip the first write entirely. In C, we can mark variables as + `volatile` to ensure that every read or write occurs as intended. In + Rust, we instead mark the _accesses_ as volatile, not the variable. +], +de: [ + Das Problem ist nun, dass Compiler clever sind. Wenn man zwei + Schreibzugriffe nacheinander auf denselben Speicherbereich durchführt, + kann der Compiler dies erkennen und den ersten Schreibvorgang einfach + komplett überspringen. In C können wir Variablen als `volatile` + kennzeichnen, um sicherzustellen, dass jeder Lese- oder Schreibvorgang + wie vorgesehen ausgeführt wird. In Rust hingegen kennzeichnen wir die + _Zugriffe_ als volatile, nicht die Variable. +], +ja: [ + ここで問題となるのは、コンパイラが賢いということです。 + 同じRAMに相次いで2回書き込むと、コンパイラはこれに気づき、最初の書き込みを完全にスキップします。 + Cでは、全ての読み書きが意図した通りに行われることを保証するために、`volatile`型修飾子を変数につけることができます。 + Rustでは、変数ではなく_アクセス_に対してvolatileをつけます。 +], +zh: [ + 现在的问题是编译器很聪明。如果你往RAM同个地方写两次,一个接着一个,编译器会注意到这个行为,且完全跳过第一个写入操作。在C语言中,我们能标记变量为`volatile`去确保每个读或写操作按所想的那样发生。在Rust中,我们将_访问_操作标记为易变的(volatile),而不是将变量标记为volatile。 +])) + +```rust +let systick = unsafe { &mut *(0xE000_E010 as *mut SysTick) }; +let time = unsafe { core::ptr::read_volatile(&mut systick.cvr) }; +``` + +#let ln_volatile = link("https://crates.io/crates/volatile_register")[`volatile_register`] +#tr(( +en: [ + So, we've fixed one of our four problems, but now we have even more + `unsafe` code! Fortunately, there's a third party crate which can help - #ln_volatile. +], +de: [ + Wir haben also eines unserer vier Probleme gelöst, aber jetzt haben wir + noch mehr `unsafe`-Code! Glücklicherweise gibt es ein Crate eines + Drittanbieters, das hierbei helfen kann -- #ln_volatile. +], +ja: [ + これで4つの問題のうち1つを直せました。しかし、さらに`unsafe`なコードがあります! + 幸いなことに、これに対処できるサードパーティ製のクレート#ln_volatile;があります。 +], +zh: [ + 这样,我们已经修复了一个问题,但是现在我们有了更多的 `unsafe` + 代码!幸运的是,有个第三方的crate可以帮助到我们 - + #ln_volatile +])) + +```rust +use volatile_register::{RW, RO}; + +#[repr(C)] +struct SysTick { + pub csr: RW, + pub rvr: RW, + pub cvr: RW, + pub calib: RO, +} + +fn get_systick() -> &'static mut SysTick { + unsafe { &mut *(0xE000_E010 as *mut SysTick) } +} + +fn get_time() -> u32 { + let systick = get_systick(); + systick.cvr.read() +} +``` + +#tr(( +en: [ + Now, the volatile accesses are performed automatically through the + `read` and `write` methods. It's still `unsafe` to perform writes, but + to be fair, hardware is a bunch of mutable state and there's no way for + the compiler to know whether these writes are actually safe, so this is + a good default position. +], +de: [ + Die volatilen Zugriffe erfolgen nun automatisch über die Methoden `read` + und `write`. Schreibzugriffe sind zwar weiterhin als `unsafe` + eingestuft, doch fairerweise muss man sagen, dass Hardware im Grunde aus + veränderlichem Zustand besteht und der Compiler nicht wissen kann, ob + diese Schreibvorgänge tatsächlich sicher sind; daher ist dies eine + sinnvolle Standardeinstellung. +], +ja: [ + これで`read`と`write`メソッドを通してvolatileアクセスが自動的に行われるようになりました。 + 書き込みを実行するのはまだ`unsafe`です。しかし、公平を期するために言うと、ハードウェアは変更可能な状態の集まりであるため、それらへの書き込みが実際に安全なのかどうか、をコンパイラが知る方法はないのです。そのため、これは基本姿勢としては悪くないでしょう。 +], +zh: [ + 现在通过`read`和`write`方法,volatile + accesses可以被自动执行。执行写操作仍然是 `unsafe` + 的,但是公平地讲,硬件有一堆可变的状态,对于编译器来说没有办法知道是否这些写操作是真正安全的,因此默认就这样是个不错的选择。 +])) + += #tr(( + en: [The Rusty Wrapper], + de: [Der Rusty Wrapper], + ja: [Rustのラッパ], + zh: [Rust风格的封装], +)) + +#tr(( +en: [ + We need to wrap this `struct` up into a higher-layer API that is safe + for our users to call. As the driver author, we manually verify the + unsafe code is correct, and then present a safe API for our users so + they don't have to worry about it (provided they trust us to get it + right!). +], +de: [ + Wir müssen diese `struct` in eine API der höheren Ebene verpacken, deren + Aufruf für unsere Nutzer sicher ist. Als Treiberentwickler überprüfen + wir manuell die Korrektheit des `unsafe`-Codes und stellen unseren + Nutzern dann eine sichere API zur Verfügung, sodass sie sich darum nicht + kümmern müssen (vorausgesetzt, sie vertrauen darauf, dass wir alles + richtig gemacht haben!). +], +ja: [ + ユーザが安全に呼び出せるように、この`struct`を高レイヤーのAPIでラップする必要があります。 + ドライバの作者として、アンセーフなコードが正しいことを手動で検証し、ユーザがそのドライバを使用する上で心配することがないように安全なAPIとして提供します。(ユーザは提供されたものが正しいと信頼しています!) +], +zh: [ + 我们需要把这个`struct`封装进一个更高抽象的API中,这个API对于用户来说,可以安全地调用。作为驱动的作者,我们亲手验证不安全的代码是否正确,然后为我们的用户提供一个safe的API,因此用户们不必担心它(让他们相信我们不会出错!)。 +])) + +#tr(( +en: [ + One example might be: +], +de: [ + Ein Beispiel hierfür wäre: +], +ja: [ + 一例を挙げます。 +], +zh: [ + 有可能可以这样写: +])) + +```rust +use volatile_register::{RW, RO}; + +pub struct SystemTimer { + p: &'static mut RegisterBlock +} + +#[repr(C)] +struct RegisterBlock { + pub csr: RW, + pub rvr: RW, + pub cvr: RW, + pub calib: RO, +} + +impl SystemTimer { + pub fn new() -> SystemTimer { + SystemTimer { + p: unsafe { &mut *(0xE000_E010 as *mut RegisterBlock) } + } + } + + pub fn get_time(&self) -> u32 { + self.p.cvr.read() + } + + pub fn set_reload(&mut self, reload_value: u32) { + unsafe { self.p.rvr.write(reload_value) } + } +} + +pub fn example_usage() -> String { + let mut st = SystemTimer::new(); + st.set_reload(0x00FF_FFFF); + format!("Time is now 0x{:08x}", st.get_time()) +} +``` + +#tr(( +en: [ + Now, the problem with this approach is that the following code is + perfectly acceptable to the compiler: +], +de: [ + Das Problem bei diesem Ansatz ist nun, dass der folgende Code für den + Compiler völlig zulässig ist: +], +ja: [ + このやり方の問題は、次のコードがコンパイラに完全に受け入れられることです。 +], +zh: [ + 现在,这种方法带来的问题是,下列的代码完全可以被编译器接受: +])) + +```rust +fn thread1() { + let mut st = SystemTimer::new(); + st.set_reload(2000); +} + +fn thread2() { + let mut st = SystemTimer::new(); + st.set_reload(1000); +} +``` + +#tr(( +en: [ + Our `&mut self` argument to the `set_reload` function checks that there + are no other references to _that_ particular `SystemTimer` struct, + but they don't stop the user creating a second `SystemTimer` which + points to the exact same peripheral! Code written in this fashion will + work if the author is diligent enough to spot all of these 'duplicate' + driver instances, but once the code is spread out over multiple modules, + drivers, developers, and days, it gets easier and easier to make these + kinds of mistakes. +], +de: [ + Das `&mut self`-Argument der Funktion `set_reload` stellt zwar sicher, + dass keine weiteren Referenzen auf _genau diese_ + `SystemTimer`-Struktur existieren, verhindert jedoch nicht, dass der + Benutzer einen zweiten `SystemTimer` erstellt, der auf dieselbe + Peripherieeinheit verweist. Auf diese Weise geschriebener Code + funktioniert zwar, sofern der Autor sorgfältig genug ist, all diese + „doppelten" Treiberinstanzen zu erkennen; sobald sich der Code jedoch + über mehrere Module, Treiber, Entwickler und Zeiträume hinweg erstreckt, + schleichen sich derartige Fehler immer leichter ein. +], +ja: [ + `set_reload`関数に`&mut self`引数を渡すことで、_その_インスタンスの`SystemTimer`構造体に対する他の参照がないことを確認しますが、全く同じペリフェラルを指す2つ目の`SystemTimer`構造体をユーザが作ることは止められません! + このように書かれたコードは、作者がこれらの「重複した」ドライバのインスタンスを全て見つけるのに十分に熱心であれば動作するでしょうが、一度コードが複数のモジュール、ドライバ、開発者、そして日に渡って分散すると、この種の間違いがどんどん入り込みやすくなっていきます。 +], +zh: [ + 虽然 `set_reload` 函数的 `&mut self` + 参数保证了没有引用到其它的`SystemTimer`结构体,但是不能阻止用户去创造第二个`SystemTimer`,其指向同个外设!如果作者足够努力的话,他能发现所有这些'重复的'驱动实例,那么按这种方式写的代码就可以工作,但是一旦代码被散播一段时间,散播给多个模块,驱动,开发者,它会越来越容易触发此类错误。 +])) diff --git a/typ/peripherals/borrowck.typ b/typ/peripherals/borrowck.typ new file mode 100644 index 00000000..0337fb1b --- /dev/null +++ b/typ/peripherals/borrowck.typ @@ -0,0 +1,130 @@ +#import "../config.typ": * + +#h1((en: [Mutable Global State], + de: [Veränderbarer globaler Zustand], + ja: [ミュータブルでグローバルな状態], + zh: [可变的全局状态], +), offset: whole) + +#tr(( +en: [ + Unfortunately, hardware is basically nothing but mutable global state, + which can feel very frightening for a Rust developer. Hardware exists + independently from the structures of the code we write, and can be + modified at any time by the real world. +], +de: [ + Leider ist Hardware im Grunde nichts anderes als veränderbarer globaler + Zustand, was auf einen Rust-Entwickler sehr beängstigend wirken kann. + Hardware existiert unabhängig von den Strukturen des Codes, den wir + schreiben, und kann jederzeit durch die reale Welt verändert werden. +], +ja: [ + 残念ながら、ハードウェアは基本的にミュータブルでグローバルな状態に他なりません。これはRustの開発者にとって非常に恐ろしいことです。 + ハードウェアは書かれたコードの構造とは独立して存在しており、現実の世界からいつでも変更される可能性があります。 +], +zh: [ + 不幸的是,硬件本质上是个可变的全局状态,Rust开发者可能会对此感到很害怕。因为硬件独立于我们所写的代码的结构,能被真实世界在任何时候改变。 +])) + += #tr(( + en: [What should our rules be?], + de: [Wie sollten unsere Regeln sein?], + ja: [何をルールとするべきか?], + zh: [我们应该遵循什么规则?], +)) + +#tr(( +en: [ + How can we reliably interact with these peripherals? + + Always use `volatile` methods to read or write to peripheral memory, + as it can change at any time + + In software, we should be able to share any number of read-only + accesses to these peripherals + + If some software should have read-write access to a peripheral, it + should hold the only reference to that peripheral +], +de: [ + Wie können wir zuverlässig mit diesen Peripheriegeräten interagieren? + + Verwenden Sie stets `volatile`-Methoden für Lese- oder Schreibzugriffe + auf Peripheriespeicher, da sich dieser jederzeit ändern kann. + + Auf Softwareebene sollten wir in der Lage sein, eine beliebige Anzahl + von Lesezugriffen auf diese Peripheriegeräte bereitzustellen. + + Wenn eine Software Lese- und Schreibzugriff auf ein Peripheriegerät + haben soll, sollte sie die einzige Referenz auf dieses Peripheriegerät + besitzen. +], +ja: [ + どうすればこれらのペリフェラルと確実にやり取りできるのでしょう? + + いつ変化するかわからないペリフェラルメモリの読み書きには、常に`volatile`メソッドを使用してください + + ソフトウェアでは、これらのペリフェラルへの読み取り専用アクセスをいくつでも共有できるでしょう + + あるソフトウェアがあるペリフェラルに読み書きのアクセスをするならば、そのソフトウェアは、ペリフェラルへの唯一の参照を持つべきです +], +zh: [ + 我们如何才能做到可靠地与这些外设交互? + + 总是使用 `volatile` 方法去读或者写外设存储器。因为它随时会改变。 + + 在软件中,我们应该能共享任何数量的关于这些外设的只读访问 + + 如果某个软件可以读写一个外设,它应该保有对那个外设的唯一引用。 +])) + += #tr(( + en: [The Borrow Checker], + de: [Der Borrow-Checker], + ja: [借用チェッカ], + zh: [借用检查器], +)) + +#tr(( +en: [ + The last two of these rules sound suspiciously similar to what the + Borrow Checker does already! +], +de: [ + Die letzten beiden dieser Regeln klingen verdächtig ähnlich wie das, was + der Borrow Checker bereits tut! +], +ja: [ + さきほどのルールの最後の2つは、借用チェッカが行っていることに怪しいくらいよく似ています。 +], +zh: [ + 这些规则最后两个听起来与借用检查器在做的事情很像! +])) + +#tr(( +en: [ + Imagine if we could pass around ownership of these peripherals, or offer + immutable or mutable references to them? +], +de: [ + Stellen Sie sich vor, wir könnten die Besitzrechte an diesen + Peripheriegeräten weitergeben oder unveränderliche bzw. veränderliche + Referenzen darauf anbieten? +], +ja: [ + ペリフェラルの所有権を譲渡したり、ペリフェラルへのイミュータブルまたはミュータブルな参照を提供したりできるのか、を想像してみてください。 +], +zh: [ + 思考一下,我们是否可以传递这些外设的所有权,或者提供对它们的可变或者不可变的引用? +])) + +#tr(( +en: [ + Well, we can, but for the Borrow Checker, we need to have exactly one + instance of each peripheral, so Rust can handle this correctly. Well, + luckily in the hardware, there is only one instance of any given + peripheral, but how can we expose that in the structure of our code? +], +de: [ + Nun, das ist möglich, aber für den Borrow Checker benötigen wir genau + eine Instanz jedes Peripheriegeräts, damit Rust dies korrekt verarbeiten + kann. Glücklicherweise existiert in der Hardware nur eine Instanz jedes + Peripheriegeräts, aber wie können wir dies in der Struktur unseres Codes + sichtbar machen? +], +ja: [ + それは可能です。ただし、借用チェッカが正しくペリフェラルの所有権や参照を扱うためには、各ペリフェラルが持つインスタンスはただ1つにする必要があります。そうすれば、Rustはこれを正しく扱えます。 + 幸いなことにハードウェアにおいて、任意のペリフェラルのインスタンスは1つだけしかありません。しかし、どうすればそれをコードの構造として明確にできるでしょうか? +], +zh: [ + 我们当然可以,但是对于借用检查器来说,每个外设只有一个实例的话,Rust才可以正确地处理这件事。幸运的是,在硬件中,任何给定的外设,只有一个实例,但是我们该如何将它暴露在代码的结构中呢? +])) diff --git a/typ/peripherals/index.typ b/typ/peripherals/index.typ new file mode 100644 index 00000000..7efd7908 --- /dev/null +++ b/typ/peripherals/index.typ @@ -0,0 +1,338 @@ +#import "../config.typ": * + +#h1((en: [Peripherals], + de: [Peripheriegeräte], + ja: [ペリフェラル], + zh: [外设], +)) + + += #tr(( + en: [What are Peripherals?], + de: [Was sind Peripheriegeräte?], + ja: [ペリフェラルとは何か?], + zh: [什么是外设?], +)) + +#tr(( +en: [ + Most Microcontrollers have more than just a CPU, RAM, or Flash Memory - + they contain sections of silicon which are used for interacting with + systems outside of the microcontroller, as well as directly and + indirectly interacting with their surroundings in the world via sensors, + motor controllers, or human interfaces such as a display or keyboard. + These components are collectively known as Peripherals. +], +de: [ + Die meisten Mikrocontroller verfügen über mehr als nur eine CPU, einen + RAM oder einen Flash-Speicher -- sie enthalten Siliziumabschnitte, die + für die Interaktion mit Systemen außerhalb des Mikrocontrollers sowie + für die direkte und indirekte Interaktion mit ihrer Umgebung in der Welt + über Sensoren, Motorsteuerungen oder menschliche Schnittstellen wie ein + Display oder eine Tastatur verwendet werden. Diese Komponenten werden + zusammenfassend als Peripheriegeräte bezeichnet. +], +ja: [ + ほとんどのマイクロコントローラはCPUやRAM、フラッシュメモリ以外のものを持っています。マイクロコントローラはシリコン上に専用のセクションを持っており、そのセクションは、マイクロコントローラの外のシステムとやり取りしたり、センサーやモーターコントローラ、またはディスプレイもしくはキーボードのようなヒューマンインタフェースによって世界中の周囲環境と直接的または間接的にやり取りするために使用されます。それらのコンポーネントはまとめてペリフェラルと呼ばれています。 +], +zh: [ + 大多数微处理器不仅仅有一个CPU,RAM,或者Flash存储器 - + 它们还包含被用来与微处理器的外部系统进行交互的硅片部分,通过传感器,电机控制器,或者人机接口比如一个显示器或者键盘直接和间接地与周遭世界交互。这些组件统称为外设。 +])) + +#tr(( +en: [ + These peripherals are useful because they allow a developer to offload + processing to them, avoiding having to handle everything in software. + Similar to how a desktop developer would offload graphics processing to + a video card, embedded developers can offload some tasks to peripherals + allowing the CPU to spend its time doing something else important, or + doing nothing in order to save power. +], +de: [ + Diese Peripheriegeräte sind nützlich, weil sie es einem Entwickler + ermöglichen, die Verarbeitung auf sie auszulagern, sodass er sich nicht + um alles in der Software kümmern muss. Ähnlich wie ein + Desktop-Entwickler die Grafikverarbeitung auf eine Grafikkarte verlagern + würde, können Embedded-Entwickler einige Aufgaben auf Peripheriegeräte + verlagern, sodass die CPU ihre Zeit mit anderen wichtigen Dingen + verbringen oder gar nichts tun kann, um Strom zu sparen. +], +ja: [ + これらのペリフェラルは有用です。なぜならば、開発者はペリフェラルに処理をオフロードすることが可能になるため、全ての処理をソフトウェアで行う必要がなくなります。デスクトップ開発者がグラフィック処理をビデオカードにオフロードするのと同じように、組込み開発者は一部のタスクをペリフェラルにオフロードして、CPUの時間を他の重要なことに使ったり、電力を節約するために何もしないようにすることができます。 +], +zh: [ + 这些外设很有用,因为它们允许一个开发者将处理工作交给它们来做,避免了必须在软件中处理每件事。就像一个桌面开发者如何将图形处理工作让给一个显卡那样,嵌入式开发者能将一些任务让给外设去做,让CPU可以把时间放在做其它更重要的事上,或者为了省电啥事也不做。 +])) + +#tr(( +en: [ + If you look at the main circuit board in an old-fashioned home computer + from the 1970s or 1980s (and actually, the desktop PCs of yesterday are + not so far removed from the embedded systems of today) you would expect + to see: + - A processor + - A RAM chip + - A ROM chip + - An I/O controller +], +de: [ + Wenn Sie sich die Hauptplatine eines altmodischen Heimcomputers aus den + 1970er oder 1980er Jahren ansehen (und tatsächlich sind die Desktop-PCs + von gestern nicht so weit von den eingebetteten Systemen von heute + entfernt), würden Sie Folgendes erwarten: + - Einen Prozessor + - Einen RAM-Chip + - Einen ROM-Chip + - Einen Ein-/Ausgabe-Controller +], +ja: [ + 1970年代か1980年代の旧式の家庭用コンピュータのメイン回路基板を見れば(実際に、旧式のデスクトップPCは今日の組込みシステムとさほど違いません)、次のものを目にするはずです。 + - プロセッサ + - RAMチップ + - ROMチップ + - I/Oコントローラ +], +zh: [ + 如果你看向来自1970s或者1980s的旧型号的家庭电脑的主板(其实,昨日的桌面PCs与今日的嵌入式系统没太大区别),你将看到: + - 一个处理器 + - 一个RAM芯片 + - 一个ROM芯片 + - 一个I/O控制器 +])) + +#tr(( +en: [ + The RAM chip, ROM chip and I/O controller (the peripheral in this + system) would be joined to the processor through a series of parallel + traces known as a 'bus'. This bus carries address information, which + selects which device on the bus the processor wishes to communicate + with, and a data bus which carries the actual data. In our embedded + microcontrollers, the same principles apply - it's just that everything + is packed on to a single piece of silicon. +], +de: [ + Der RAM-Chip, der ROM-Chip und der I/O-Controller (das Peripheriegerät + in diesem System) wären über eine Reihe paralleler Leiterbahnen, die als + „Bus" bekannt sind, mit dem Prozessor verbunden. Dieser Bus trägt + Adressinformationen, die auswählen, mit welchem ​​Gerät auf dem Bus der + Prozessor kommunizieren möchte, und einen Datenbus, der die eigentlichen + Daten überträgt. In unseren eingebetteten Mikrocontrollern gelten die + gleichen Prinzipien -- nur dass alles auf einem einzigen Stück Silizium + untergebracht ist. +], +ja: [ + RAMチップ、ROMチップ、I/Oコントローラ(このシステムのペリフェラル)は「バス」として知られる一連の並列な配線を通してプロセッサに接続されているでしょう。アドレスバスは、プロセッサがバス上のどのデバイスと通信したいかを選択するアドレス情報を運び、データバスは、実際のデータを運びます。組込みマイクロコントローラにおいても、同じ原理が適用されます。それは全てが1つのシリコン片に詰め込まれているということです。 +], +zh: [ + RAM芯片,ROM芯片和I/O控制器(这个系统中的外设)会通过一系列并行的迹(traces)又被称为一个"总线"被加进处理器中。地址总线搬运地址信息,其用来选择处理器希望跟总线上哪个设备通信,还有一个用来搬运实际数据的数据总线。在我们的嵌入式微控制器中,应用了相同的概念 + \- 只是所有的东西被打包到一片硅片上。 +])) + +#tr(( +en: [ + However, unlike graphics cards, which typically have a Software API like + Vulkan, Metal, or OpenGL, peripherals are exposed to our Microcontroller + with a hardware interface, which is mapped to a chunk of the memory. +], +de: [ + Im Gegensatz zu Grafikkarten, die normalerweise über eine Software-API + wie Vulkan, Metal oder OpenGL verfügen, werden Peripheriegeräte unserem + Mikrocontroller über eine Hardwareschnittstelle zugänglich gemacht, die + einem Teil des Speichers zugeordnet ist. +], +ja: [ + しかしながら、VulkanやMetal、OpenGLなどのソフトウェアのAPIを通常持つグラフィックカードとは異なり、ペリフェラルはメモリチャンクにマッピングされたハードウェアインターフェースとしてマイクロコントローラに公開されています。 +], +zh: [ + 然而,不像显卡,显卡通常有像是Vulkan,Metal,或者OpenGL这样的一个软件API。外设暴露给微控制器的是一个硬件接口,其被映射到一块存储区域。 +])) + += #tr(( + en: [Linear and Real Memory Space], + de: [Linearer und realer Speicherraum], + ja: [線形な実メモリ空間], + zh: [线性的物理存储空间], +)) + +#tr(( +en: [ + On a microcontroller, writing some data to some other arbitrary address, + such as `0x4000_0000` or `0x0000_0000`, may also be a completely valid + action. +], +de: [ + Bei einem Mikrocontroller kann auch das Schreiben von Daten an eine + beliebige andere Adresse -- etwa `0x4000_0000` oder `0x0000_0000` -- ein + völlig zulässiger Vorgang sein. +], +ja: [ + マイクロコントローラでは、`0x4000_0000`や`0x0000_0000`のような任意のアドレスにデータを書き込むことは、完全に正当な行為でしょう。 +], +zh: [ + 在一个微控制器上,随便往一些地址写一些数据,比如 `0x4000_0000` 或者 + `0x0000_0000`,可能也是一个完全有效的动作。 +])) + +#tr(( +en: [ + On a desktop system, access to memory is tightly controlled by the MMU, + or Memory Management Unit. This component has two major + responsibilities: enforcing access permission to sections of memory + (preventing one process from reading or modifying the memory of another + process); and re-mapping segments of the physical memory to virtual + memory ranges used in software. Microcontrollers do not typically have + an MMU, and instead only use real physical addresses in software. +], +de: [ + Auf einem Desktop-System wird der Speicherzugriff streng von der MMU + (Memory Management Unit, Speicherverwaltungseinheit) kontrolliert. Diese + Komponente hat zwei Hauptaufgaben: die Durchsetzung von + Zugriffsberechtigungen für Speicherbereiche (um zu verhindern, dass ein + Prozess den Speicher eines anderen Prozesses liest oder verändert) sowie + die Abbildung von Segmenten des physischen Speichers auf virtuelle + Speicherbereiche, die von der Software genutzt werden. Mikrocontroller + verfügen in der Regel nicht über eine MMU; stattdessen verwendet die + Software dort ausschließlich reale physische Adressen. +], +ja: [ + デスクトップシステムでは、メモリアクセスはMMU(メモリ管理ユニット)によって厳密に制御されています。このコンポーネントは2つの主な役割を持っています。メモリのセクションへのアクセス権限の強制(あるプロセスが別のプロセスのメモリを読み出したり変更したりできないようにする)、そして物理メモリのセグメントをソフトウェアで使用される仮想メモリ範囲に再マッピングすることです。マイクロコントローラは通常はMMUを持たず、代わりにソフトウェアで物理アドレスのみを使用します。 +], +zh: [ + 在一个桌面系统上,访问内存被MMU,或者内存管理单元紧紧地控制着。这个组件有两个主要责任: + 对部分内存加入访问权限(防止一个进程读取或者修改另一个进程的内存);重映射物理内存的段到软件中使用的虚拟内存范围上。微控制器通常没有一个MMU,反而在软件中只使用真实的物理地址。 +])) + +#tr(( +en: [ + Although 32 bit microcontrollers have a real and linear address space + from `0x0000_0000`, and `0xFFFF_FFFF`, they generally only use a few + hundred kilobytes of that range for actual memory. This leaves a + significant amount of address space remaining. In earlier chapters, we + were talking about RAM being located at address `0x2000_0000`. If our + RAM was 64 KiB long (i.e.~with a maximum address of 0xFFFF) then + addresses `0x2000_0000` to `0x2000_FFFF` would correspond to our RAM. + When we write to a variable which lives at address `0x2000_1234`, what + happens internally is that some logic detects the upper portion of the + address (0x2000 in this example) and then activates the RAM so that it + can act upon the lower portion of the address (0x1234 in this case). On + a Cortex-M we also have our Flash ROM mapped in at address `0x0000_0000` + up to, say, address `0x0007_FFFF` (if we have a 512 KiB Flash ROM). + Rather than ignore all remaining space between these two regions, + Microcontroller designers instead mapped the interface for peripherals + in certain memory locations. This ends up looking something like this: +], +de: [ + Obwohl 32-Bit-Mikrocontroller über einen echten, linearen Adressraum von + `0x0000_0000` bis `0xFFFF_FFFF` verfügen, nutzen sie für den + eigentlichen Speicher meist nur einige hundert Kilobyte dieses Bereichs. + Dadurch bleibt ein beträchtlicher Teil des Adressraums ungenutzt. In + früheren Kapiteln war die Rede davon, dass sich der RAM an der Adresse + `0x2000_0000` befindet. Wäre unser RAM 64 KiB groß (d.~h. mit einer + maximalen Adresse von 0xFFFF), so entsprächen die Adressen `0x2000_0000` + bis `0x2000_FFFF` diesem Speicherbereich. Wenn wir in eine Variable + schreiben, die an der Adresse `0x2000_1234` liegt, geschieht intern + Folgendes: Eine Logikeinheit erkennt den oberen Teil der Adresse (in + diesem Beispiel `0x2000`) und aktiviert den RAM, sodass dieser auf den + unteren Teil der Adresse (in diesem Fall `0x1234`) reagieren kann. Bei + einem Cortex-M-System ist zudem das Flash-ROM eingeblendet -- etwa im + Bereich von `0x0000_0000` bis `0x0007_FFFF` (bei einem + 512-KiB-Flash-ROM). Anstatt den gesamten verbleibenden Raum zwischen + diesen beiden Bereichen ungenutzt zu lassen, haben die Entwickler der + Mikrocontroller die Schnittstellen für Peripheriegeräte bestimmten + Speicheradressen zugeordnet. Das Ergebnis sieht dann ungefähr so ​​aus: +], +ja: [ + 32ビットマイクロコントローラは`0x0000_0000`から`0xFFFF_FFFF`の線形な実アドレス空間を持ちますが、それらは大抵の場合、実際のメモリのためにはその範囲の数百キロバイトしか使用しません。これにより、かなりの量のアドレス空間が残ります。前の章では、RAMが`0x2000_0000`のアドレスに配置されていることについて話しました。もしもRAMが64KiBの長さなら(すなわち、最大アドレスが0xFFFF)、`0x2000_0000`から`0x2000_FFFF`がRAMのアドレスに対応します。`0x2000_1234`のアドレスにある変数に書き込むと、内部ではアドレスの上位部分(この例では0x2000)を検出し、アドレスの下位部分(この例では0x1234)に作用できるようにRAMをアクティブにします。Cortex-Mにおいては、フラッシュROMも`0x0000_0000`から`0x0007_FFFF`のアドレスにマッピングされています(512KiBのフラッシュROMが載っている場合)。これら2つの領域の間に残るスペースを全て無視するのではなく、代わりにマイクロコントローラの設計者は特定のメモリ配置にペリフェラルのインターフェースをマッピングしました。これは次のようなものになります。 +], +zh: [ + 虽然32位微控制器有一个从`0x0000_0000`到`0xFFFF_FFFF`的线性的物理地址空间,但是它们通常只使用几百KiB的实际内存。有相当大部分的地址空间保留着。在早期的章节中,我们说到RAM被放置在地址`0x2000_0000`处。如果我们的RAM是64KiB大小(i.e.~最大地址为0xFFFF),那么地址 + `0x2000_0000`到`0x2000_FFFF`与我们的RAM有关。当我们写入一个位于地址`0x2000_1234`的变量时,内部发生的是,一些逻辑发现了地址的上部(这个例子里是0x2000),然后激活RAM,以便能操作地址的下部(这个例子里是0x1234)。在一个Cortex-M上,我们也也会把Flash + ROM映射进地址 `0x000_0000` 到地址 `0x0007_FFFF` 上 (如果我们有一个512KiB + Flash + ROM)。微控制器设计者没有忽略这两个区域间的所有剩余空间,反而将外设的接口映射到这些地址上。最后看起来像这样: +])) + +#box(image("../assets/nrf52-memory-map.png")) + +#link("http://infocenter.nordicsemi.com/pdf/nRF52832_PS_v1.1.pdf")[Nordic nRF52832 Datasheet (pdf)] + += #tr(( + en: [Memory Mapped Peripherals], + de: [Im Speicher abgebildete Peripheriegeräte], + ja: [メモリマップド・ペリフェラル], + zh: [存储映射的外设], +)) + +#tr(( +en: [ + Interaction with these peripherals is simple at a first glance - write + the right data to the correct address. For example, sending a 32 bit + word over a serial port could be as direct as writing that 32 bit word + to a certain memory address. The Serial Port Peripheral would then take + over and send out the data automatically. +], +de: [ + Die Interaktion mit diesen Peripheriegeräten ist auf den ersten Blick + einfach: Schreiben Sie die richtigen Daten an die richtige Adresse. + Beispielsweise könnte das Senden eines 32-Bit-Worts über eine serielle + Schnittstelle genauso direkt sein wie das Schreiben dieses 32-Bit-Worts + an eine bestimmte Speicheradresse. Das Serial-Port-Peripheriegerät würde + dann übernehmen und die Daten automatisch versenden. +], +ja: [ + 一見すると、これらのペリフェラルとのやり取りは簡単です。正しいデータを正しいアドレスに書き込むだけです。例えば、32ビットワードをシリアルポート上で送信することは、32ビットワードを特定のメモリアドレスに書き込むことと同じくらい直接的になり得ます。シリアルポート・ペリフェラルは自動的にデータを引き受けて送信します。 +], +zh: [ + 乍一看,与这些外设交互很简单 - + 将正确的数据写入正确的地址。比如,在一个串行端口上发送一个32位字,可以直接把那个32位字写入某个存储地址。串行端口外设然后能自动获取和发出数据。 +])) + +#tr(( +en: [ + Configuration of these peripherals works similarly. Instead of calling a + function to configure a peripheral, a chunk of memory is exposed which + serves as the hardware API. Write `0x8000_0000` to a SPI Frequency + Configuration Register, and the SPI port will send data at 8 Megabits + per second. Write `0x0200_0000` to the same address, and the SPI port + will send data at 125 Kilobits per second. These configuration registers + look a little bit like this: +], +de: [ + Die Konfiguration dieser Peripheriegeräte funktioniert ähnlich. Anstatt + eine Funktion zum Konfigurieren eines Peripheriegeräts aufzurufen, wird + ein Teil des Speichers verfügbar gemacht, der als Hardware-API dient. + Schreiben Sie „0x8000_0000" in ein SPI-Frequenzkonfigurationsregister, + und der SPI-Port sendet Daten mit 8 Megabit pro Sekunde. Schreiben Sie + „0x0200_0000" an dieselbe Adresse und der SPI-Port sendet Daten mit 125 + Kilobit pro Sekunde. Diese Konfigurationsregister sehen in etwa so aus: +], +ja: [ + これらのペリフェラルの設定についても同じように動作します。ペリフェラルの設定をするための関数を呼ぶ代わりに、ハードウェアAPIとして機能するメモリチャンクが公開されます。`0x8000_0000`をSPI周波数の設定レジスタに書き込むと、SPIポートは8Mbpsでデータを送信するようになります。`0x0200_0000`を同じアドレスに書き込むと、SPIは125Kbpsでデータを送信するようになります。これらの設定レジスタをちょっとだけ見てみます。 +], +zh: [ + 这些外设的配置工作相似。不是调用一个函数去配置一个外设,而是暴露一块地址空间作为硬件API。向一个SPI频率控制寄存器写入 + `0x8000_0000`,SPI端口将会按照每秒8MB的速度发送数据。向同个地址写入 + `0x0200_0000`,SPI端口将会按照每秒125KiB的速度发送数据。这些配置寄存器看起来有点像这个: +])) + +#box(image("../assets/nrf52-spi-frequency-register.png")) + +#link("http://infocenter.nordicsemi.com/pdf/nRF52832_PS_v1.1.pdf")[Nordic nRF52832 Datasheet (pdf)] + +#tr(( +en: [ + This interface is how interactions with the hardware are made, no matter + what language is used, whether that language is Assembly, C, or Rust. +], +de: [ + Über diese Schnittstelle erfolgen die Interaktionen mit der Hardware, + unabhängig davon, welche Sprache verwendet wird -- sei es Assembler, C + oder Rust. +], +ja: [ + アセンブリ言語やC言語、Rustなど、どの言語が使われようとも、このインターフェースがどのように作用するかはハードウェアによって定められています。 +], +zh: [ + 这个接口是关于如何与硬件交互的,其与被使用的语言无关,无论这个语言是汇编,C,或者Rust。 +])) diff --git a/typ/peripherals/singletons.typ b/typ/peripherals/singletons.typ new file mode 100644 index 00000000..21a626a7 --- /dev/null +++ b/typ/peripherals/singletons.typ @@ -0,0 +1,515 @@ +#import "../config.typ": * + +#h1((en: [Singletons], + de: [Singletons], + ja: [シングルトン], + zh: [单例], +), offset: whole) + +#quote(block: true)[ +#tr(( +en: [ + In software engineering, the singleton pattern is a software design + pattern that restricts the instantiation of a class to one object. +], +de: [ + In der Softwaretechnik ist das Singleton-Muster ein Entwurfsmuster, das + die Instanziierung einer Klasse auf ein einziges Objekt beschränkt. +], +ja: [ + ソフトウェア工学において、シングルトン・パターンはクラスのインスタンス化を1つのオブジェクトに制限するデザインパターンです。 +], +zh: [ + 在软件工程中,单例模式是一个软件设计模式,其限制了一个类到一个对象的实例化。 +])) + +#let url_singleton = "https://en.wikipedia.org/wiki/Singleton_pattern" +#tr(( +en: [ + _Wikipedia: #link(url_singleton)[Singleton Pattern]_ +], +de: [ + _Wikipedia: #link(url_singleton)[Singleton-Muster]_ +], +ja: [ + _Wikipedia: #link(url_singleton)[Singleton Pattern]_ +], +zh: [ + _Wikipedia: #link(url_singleton)[Singleton Pattern]_ +])) +] + += #tr(( + en: [But why can't we just use global variable(s)?], + de: [Aber warum können wir nicht einfach globale Variable(n) verwenden?], + ja: [なぜグローバル変数は使えないのか?], + zh: [为什么不可以使用全局变量?], +)) + +#tr(( +en: [ + We could make everything a public static, like this +], +de: [ + Wir könnten alles als „public static" definieren, etwa so: +], +ja: [ + このように、全てをパブリックかつスタティックにすることができます。 +], +zh: [ + 可以像这样,我们可以使每个东西都变成公共静态的(public static): +])) + +```rust +static mut THE_SERIAL_PORT: SerialPort = SerialPort; + +fn main() { + let _ = unsafe { + THE_SERIAL_PORT.read_speed(); + }; +} +``` + +#tr(( +en: [ + But this has a few problems. It is a mutable global variable, and in + Rust, these are always unsafe to interact with. These variables are also + visible across your whole program, which means the borrow checker is + unable to help you track references and ownership of these variables. +], +de: [ + Dies bringt jedoch einige Probleme mit sich. Es handelt sich um eine + veränderbare globale Variable, und der Zugriff auf solche Variablen ist + in Rust stets „unsafe". Zudem sind diese Variablen im gesamten Programm + sichtbar, was bedeutet, dass der Borrow Checker nicht dabei helfen kann, + die Referenzen und die Ownership dieser Variablen zu verfolgen. +], +ja: [ + しかし、これにはいくつか問題があります。 + これはミュータブルなグローバル変数であり、Rustにおいては、これらとやり取りするのは常にアンセーフです。 + これらの変数はプログラムの全体を通して見えることになり、つまりそれは借用チェッカがこれらの変数の参照や所有権を追跡するのに役立たなくなることを意味します。 +], +zh: [ + 但是这个带来了一些问题。它是一个可变的全局变量,在Rust,与这些变量交互总是unsafe的。这些变量在你所有的程序间也是可见的,意味着借用检查器不能帮你跟踪这些变量的引用和所有权。 +])) + += #tr(( + en: [How do we do this in Rust?], + de: [Wie machen wir das in Rust?], + ja: [Rustではどうするか?], + zh: [在Rust中要怎么做?], +)) + +#tr(( +en: [ + Instead of just making our peripheral a global variable, we might + instead decide to make a structure, in this case called `PERIPHERALS`, + which contains an `Option` for each of our peripherals. +], +de: [ + Anstatt unser Peripheriegerät einfach als globale Variable zu + definieren, könnten wir uns stattdessen dazu entschließen, eine Struktur + -- in diesem Fall mit dem Namen `PERIPHERALS` -- zu erstellen, die für + jedes unserer Peripheriegeräte ein `Option` enthält. +], +ja: [ + 単にペリフェラルをグローバル変数にする代わりに、各ペリフェラル毎に`Option`を含む`PERIPHERALS`と呼ばれるグローバル変数を作ることにします。 +], +zh: [ + 与其只是让我们的外设变成一个全局变量,我们不如创造一个结构体,在这个例子里其被叫做 + `PERIPHERALS`,这个全局变量对于我们的每个外设,它都有一个与之对应的 + `Option` . +])) + +```rust +struct Peripherals { + serial: Option, +} +impl Peripherals { + fn take_serial(&mut self) -> SerialPort { + let p = replace(&mut self.serial, None); + p.unwrap() + } +} +static mut PERIPHERALS: Peripherals = Peripherals { + serial: Some(SerialPort), +}; +``` + +#tr(( +en: [ + This structure allows us to obtain a single instance of our peripheral. + If we try to call `take_serial()` more than once, our code will panic! +], +de: [ + Diese Struktur ermöglicht es uns, eine einzelne Instanz unserer + Peripheriekomponente zu erhalten. Wenn wir versuchen, `take_serial()` + mehr als einmal aufzurufen, wird unser Code eine Panic auslösen! +], +ja: [ + この構造体によって、ペリフェラルの唯一のインスタンスが取得できるようになります。 + もしも`take_serial()`を複数回呼び出そうとすれば、コードはパニックするでしょう。 +], +zh: [ + 这个结构体允许我们获得一个外设的实例。如果我们尝试调用`take_serial()`获得多个实例,我们的代码将会抛出运行时恐慌(panic)! +])) + +#raw(block: true, lang: "rust", +"fn main() { + let serial_1 = unsafe { PERIPHERALS.take_serial() }; + // " + ts(( + en: "This panics!", + de: "Dies loest eine panic aus!", + ja: "これはパニックします!", + zh: "这里造成运行时恐慌!", + )) + " + // let serial_2 = unsafe { PERIPHERALS.take_serial() }; +} +") + +#tr(( +en: [ + Although interacting with this structure is `unsafe`, once we have the + `SerialPort` it contained, we no longer need to use `unsafe`, or the + `PERIPHERALS` structure at all. +], +de: [ + Obwohl die Interaktion mit dieser Struktur als `unsafe` gilt, benötigen + wir -- sobald wir über die darin enthaltene `SerialPort`-Instanz + verfügen -- weder `unsafe`-Code noch die `PERIPHERALS`-Struktur selbst. +], +ja: [ + この構造体とのやり取りは`unsafe`にはなりますが、一度この構造体に含まれる`SerialPort`を取得してしまえばもう`unsafe`や`PERIPHERALS`構造体を使う必要は全くありません。 +], +zh: [ + 虽然与这个结构体交互是`unsafe`,然而一旦我们获得了它包含的 + `SerialPort`,我们将不再需要使用`unsafe`,或者`PERIPHERALS`结构体。 +])) + +#tr(( +en: [ + This has a small runtime overhead because we must wrap the `SerialPort` + structure in an option, and we'll need to call `take_serial()` once, + however this small up-front cost allows us to leverage the borrow + checker throughout the rest of our program. +], +de: [ + Dies bringt einen geringen Laufzeit-Overhead mit sich, da wir die + `SerialPort`-Struktur in eine `Option` einbetten und einmalig + `take_serial()` aufrufen müssen; dieser geringe anfängliche Aufwand + ermöglicht es uns jedoch, den Borrow-Checker im weiteren Verlauf des + Programms voll zu nutzen. +], +ja: [ + この方法では、オプション型の中に`SerialPort`構造体をラップし、`take_serial()`を一度コールする必要があるため、実行時に小さなオーバーヘッドとなります。 + しかし、この少々のコストを前払いすることで、残りのプログラムで借用チェッカを利用できるようになるのです。 +], +zh: [ + 这个带来了少量的运行时开销,因为我们必须打包 `SerialPort` + 结构体进一个option中,且我们将需要调用一次 + `take_serial()`,但是这种少量的前期成本,能使我们在接下来的程序中使用借用检查器(borrow + checker) 。 +])) + += #tr(( + en: [Existing library support], + de: [Vorhandene Bibliotheksunterstützung], + ja: [既存のライブラリによるサポート], + zh: [已存在的库支持], +)) + +#tr(( +en: [ + Although we created our own `Peripherals` structure above, it is not + necessary to do this for your code. the `cortex_m` crate contains a + macro called `singleton!()` that will perform this action for you. +], +de: [ + Obwohl wir oben unsere eigene `Peripherals`-Struktur erstellt haben, ist + dies für Ihren Code nicht erforderlich; das `cortex_m`-Crate enthält ein + Makro namens `singleton!()`, das diese Aufgabe für Sie übernimmt. +], +ja: [ + 上記のコードでは`Peripherals`構造体を作りましたが、あなたのコードでも同じようにする必要はありません。 + `cortex_m`クレートはこれと同様のことをしてくれる`singleton!()`と呼ばれるマクロを含んでいます。 +], +zh: [ + 虽然我们在上面生成了我们自己的 `Peripherals` + 结构体,但这并不是必须的。`cortex_m` crate 包含一个被叫做 `singleton!()` + 的宏,它可以为你完成这个任务。 +])) + +#raw(block: true, lang: "rust", +"use cortex_m::singleton; + +fn main() { + // " + ts(( + en: "OK if `main` is executed only once", + de: "In Ordnung, wenn `main` nur einmal ausgefuehrt wird.", + ja: "`main`が一度だけしか実行されなければOKです", + zh: "OK 如果 `main` 只被执行一次", + )) + " + let x: &'static mut bool = + singleton!(: bool = false).unwrap(); +} +") + +#let url_sinmacro = "https://docs.rs/cortex-m/latest/cortex_m/macro.singleton.html" +#tr(( + en: link(url_sinmacro)[cortex_m docs], + de: link(url_sinmacro)[cortex_m Dokumente], +)) + +#let ln_rtic = link("https://github.com/rtic-rs/cortex-m-rtic")[`cortex-m-rtic`] +#tr(( +en: [ + Additionally, if you use #ln_rtic, the + entire process of defining and obtaining these peripherals are + abstracted for you, and you are instead handed a `Peripherals` structure + that contains a non-`Option` version of all of the items you define. +], +de: [ + Wenn Sie zudem #ln_rtic + verwenden, wird der gesamte Prozess der Definition und Bereitstellung + dieser Peripheriekomponenten für Sie abstrahiert; stattdessen erhalten + Sie eine `Peripherals`-Struktur, die eine Version aller von Ihnen + definierten Elemente enthält, die nicht als `Option` vorliegen. +], +zh: [ + 另外,如果你使用 + #ln_rtic,它将获取和定义这些外设的整个过程抽象了出来,你将获得一个`Peripherals`结构体,其包含了所有你定义了的项的一个非 + `Option` 的版本。 +])) + + +#raw(block: true, lang: "rust", +"// cortex-m-rtic v0.5.x +#[rtic::app(device = lm3s6965, peripherals = true)] +const APP: () = { + #[init] + fn init(cx: init::Context) { + static mut X: u32 = 0; + + // " + ts(( + en: "Cortex-M peripherals", + de: "Cortex-M-Peripherie", + zh: "Cortex-M外设", + )) + " + let core: cortex_m::Peripherals = cx.core; + + // " + ts(( + en: "Device specific peripherals", + de: "Geraetespezifische Peripheriegeraete", + zh: "设备特定的外设", + )) + " + let device: lm3s6965::Peripherals = cx.device; + } +} +") + += #tr(( + en: [But why?], + de: [Aber warum?], + ja: [しかしなぜ?], + zh: [为什么?], +)) + +#tr(( +en: [ + But how do these Singletons make a noticeable difference in how our Rust + code works? +], +de: [ + Aber wie bewirken diese Singletons einen spürbaren Unterschied in der + Funktionsweise unseres Rust-Codes? +], +ja: [ + しかし、これらのシングルトンがRustのコードの動作にどのような顕著な違いをもたらすのでしょうか? +], +zh: [ + 但是这些单例模式是如何使我们的Rust代码在工作方式上产生很大不同的? +])) + +#raw(block: true, lang: "rust", +"impl SerialPort { + const SER_PORT_SPEED_REG: *mut u32 = 0x4000_1000 as _; + + fn read_speed( + &self // " + ts(( + en: "<------ This is really, really important", + de: "<------ Das ist wirklich, wirklich wichtig.", + ja: "<------ これは本当に、本当に重要です。", + zh: "<------ 这个真的真的很重要", + )) + " + ) -> u32 { + unsafe { + ptr::read_volatile(Self::SER_PORT_SPEED_REG) + } + } +} +") + +#tr(( +en: [ + There are two important factors in play here: + - Because we are using a singleton, there is only one way or place to + obtain a `SerialPort` structure + - To call the `read_speed()` method, we must have ownership or a + reference to a `SerialPort` structure +], +de: [ + Hier spielen zwei wichtige Faktoren eine Rolle: + - Da wir ein Singleton verwenden, gibt es nur eine Möglichkeit bzw. + einen Ort, um eine `SerialPort`-Struktur zu erhalten. + - Um die Methode `read_speed()` aufzurufen, benötigen wir den Besitz + einer `SerialPort`-Struktur oder eine Referenz darauf. +], +ja: [ + ここには2つの重要な要素があります。 + - シングルトンを使用しているため、`SerialPort`構造体の取得手段や場所は1つだけになります。 + - `read_speed()`メソッドを呼ぶためには、`SerialPort`構造体の所有権もしくは参照を持つ必要があります。 +], +zh: [ + 这里有两个重要因素: + - 因为我们正在使用一个单例模式,所以我们只有一种方法或者地方去获得一个 + `SerialPort` 结构体。 + - 为了调用 `read_speed()` 方法,我们必须拥有一个 `SerialPort` + 结构体的所有权或者一个引用。 +])) + +#tr(( +en: [ + These two factors put together means that it is only possible to access + the hardware if we have appropriately satisfied the borrow checker, + meaning that at no point do we have multiple mutable references to the + same hardware! +], +de: [ + Zusammengenommen bedeuten diese beiden Faktoren, dass ein Zugriff auf + die Hardware nur möglich ist, wenn wir die Anforderungen des + Borrow-Checkers ordnungsgemäß erfüllt haben -- das heißt, dass zu keinem + Zeitpunkt mehrere veränderbare Referenzen auf dieselbe Hardware + existieren! +], +ja: [ + これらの2つの要素をまとめると、借用チェッカを適切に満たしている場合のみハードウェアにアクセスできることを意味します。つまり、同じハードウェアに対して複数のミュータブルな参照を持つことはありません。 +], +zh: [ + 这两个因素放在一起意味着,只有当我们满足了借用检查器的条件时,我们才有可能访问硬件,也意味着在任何时候不可能存在多个对同一个硬件的可变引用(&mut)! +])) + +#raw(block: true, lang: "rust", +"fn main() { + // " + ts(( + en: "missing reference to `self`! Won't work.", + de: "Verweis auf `self` fehlt! Das wird nicht funktionieren.", + ja: "`self`への参照が見つかりません。これはうまく動きません。", + zh: "缺少对`self`的引用!将不会工作。", + )) + " + // SerialPort::read_speed(); + + let serial_1 = unsafe { PERIPHERALS.take_serial() }; + + // " + ts(( + en: "you can only read what you have access to", + de: "Sie koennen nur lesen, worauf Sie Zugriff haben", + ja: "アクセスできるものだけ読み出すことができます。", + zh: "你只能读取你有权访问的内容", + )) + " + let _ = serial_1.read_speed(); +} +") + += #tr(( + en: [Treat your hardware like data], + de: [Behandle deine Hardware wie Daten], + ja: [ハードウェアをデータのように扱う], + zh: [像对待数据一样对待硬件], +)) + +#tr(( +en: [ + Additionally, because some references are mutable, and some are + immutable, it becomes possible to see whether a function or method could + potentially modify the state of the hardware. For example, +], +de: [ + Da es zudem sowohl veränderbare als auch unveränderbare Referenzen gibt, + lässt sich erkennen, ob eine Funktion oder Methode potenziell den + Zustand der Hardware ändern könnte. Zum Beispiel: +], +ja: [ + 加えて、いくつかの参照はミュータブルで、またいくつかはイミュータブルなため、関数またはメソッドがハードウェアの状態を変更できるかどうかを確認することが可能になります。 +], +zh: [ + 另外,因为一些引用是可变的,一些是不可变的,就可以知道一个函数或者方法是否有能力修改硬件的状态。比如, +])) + +#tr(( +en: [ + This is allowed to change hardware settings: +], +de: [ + Dies darf Hardware-Einstellungen ändern: +], +ja: [ + この関数はハードウェアの設定を変更できます。 +], +zh: [ + 这个函数可以改变硬件的配置: +])) + +```rust +fn setup_spi_port( + spi: &mut SpiPort, + cs_pin: &mut GpioPin +) -> Result<()> { + // ... +} +``` + +#tr(( +en: [ + This isn't: +], +de: [ + Das nicht: +], +ja: [ + このメソッドは変更できません。 +], +zh: [ + 这个不行: +])) + +```rust +fn read_button(gpio: &GpioPin) -> bool { + // ... +} +``` + +#tr(( +en: [ + This allows us to enforce whether code should or should not make changes + to hardware at *compile time*, rather than at runtime. As a note, + this generally only works across one application, but for bare metal + systems, our software will be compiled into a single application, so + this is not usually a restriction. +], +de: [ + Dies ermöglicht es uns, bereits zur *Kompilierzeit* -- und nicht + erst zur Laufzeit -- festzulegen, ob Code Änderungen an der Hardware + vornehmen darf oder nicht. Zu beachten ist, dass dies im Allgemeinen nur + innerhalb einer einzelnen Anwendung funktioniert; da unsere Software für + Bare-Metal-Systeme jedoch als eine einzige Anwendung kompiliert wird, + stellt dies üblicherweise keine Einschränkung dar. +], +ja: [ + + これにより、実行時ではなく*コンパイル時に*コードがハードウェアを変更するかどうかを強制できます。 + 注意点としては、通常この強制はひとつのアプリケーション内でのみ機能します。ベアメタルシステムにおいては、ソフトウェアはひとつのアプリケーションにコンパイルされるため、これは一般的には制約にはなりません。 + +], +zh: [ + 这允许我们在*编译时*而不是运行时强制代码是否应该或者不应该对硬件进行修改。要注意,这通常在只有一个应用的情况下起作用,但是对于裸机系统来说,我们的软件将被编译进一个单一应用中,因此这通常不是一个限制。 +])) diff --git a/typ/portability/index.typ b/typ/portability/index.typ new file mode 100644 index 00000000..061365d5 --- /dev/null +++ b/typ/portability/index.typ @@ -0,0 +1,482 @@ +#import "../config.typ": * + +#h1((en: [Portability], + de: [Portabilität], + ja: [移植性], + zh: [可移植性], +)) + + +#tr(( +en: [ + In embedded environments portability is a very important topic: Every + vendor and even each family from a single manufacturer offers different + peripherals and capabilities and similarly the ways to interact with the + peripherals will vary. +], +de: [ + In eingebetteten Systemen ist Portabilität ein sehr wichtiges Thema: + Jeder Hersteller und sogar jede Produktfamilie eines einzelnen + Herstellers bietet unterschiedliche Peripheriegeräte und Funktionen an, + und dementsprechend variieren auch die Interaktionsmöglichkeiten mit den + Peripheriegeräten. +], +ja: [ + 組込み環境においては、移植性は非常に重要なトピックです。1つのメーカから、それぞれのベンダや各プロダクトファミリが、異なるペリフェラルや機能を提供します、 + 異なるペリフェラルでは、ペリフェラルとやり取りする方法も異なります。 +], +zh: [ + 在嵌入式环境中,可移植性是一个非常重要的主题: + 每个供应商甚至同个制造商的不同系列间,都提供了不同的外设和功能。同样地,与外设交互的方式也将会不一样。 +])) + +#tr(( +en: [ + A common way to equalize such differences is via a layer called Hardware + Abstraction layer or *HAL*. +], +de: [ + Eine gängige Methode, diese Unterschiede auszugleichen, ist die + sogenannte Hardware-Abstraktionsschicht (HAL). +], +ja: [ + このような違いを吸収する一般的な方法は、ハードウェア抽象化レイヤまたは*HAL*と呼ばれるレイヤを導入することです。 +], +zh: [ + 通过一个被叫做硬件抽象层或者*HAL*的层去均等化这种差异是一种常见的方法。 +])) + +#quote(block: true)[ +#tr(( +en: [ + Hardware abstractions are sets of routines in software that emulate some + platform-specific details, giving programs direct access to the hardware + resources. +], +de: [ + Hardware-Abstraktionen sind Sammlungen von Software-Routinen, die + bestimmte plattformspezifische Details emulieren und Programmen so + direkten Zugriff auf die Hardwareressourcen ermöglichen. +], +ja: [ + ハードウェア抽象化は、プラットフォーム固有の細部をエミュレーションして、プログラムにハードウェアリソースへ直接アクセスする方法を提供する、ソフトウェアの一連のルーチンです。 +], +zh: [ + 在软件中硬件抽象是一组函数,其模仿了一些平台特定的细节,让程序可以直接访问硬件资源。 +])) + +#tr(( +en: [ + They often allow programmers to write device-independent, high + performance applications by providing standard operating system (OS) + calls to hardware. +], +de: [ + Sie ermöglichen es Programmierern häufig, geräteunabhängige + Hochleistungsanwendungen zu schreiben, indem sie standardisierte + Betriebssystemaufrufe für den Hardwarezugriff bereitstellen. +], +ja: [ + それらのルーチンがハードウェアへのオペレーティングシステム(OS)コールを提供することで、プログラマは、デイバスに依存せず、高性能なアプリケーションを書くことができます。 +], +zh: [ + 通过向硬件提供标准的操作系统(OS)调用,它可以让程序员编写独立于设备的高性能应用。 +])) + +#let url_hal = "https://en.wikipedia.org/wiki/Hardware_abstraction" +#tr(( + en: [_Wikipedia: #link(url_hal)[Hardware Abstraction Layer]_], + de: [_Wikipedia: #link(url_hal)[Hardware Abstraction Layer]_], + ja: [_Wikipedia: #link(url_hal)[ハードウェア抽象化レイヤ]_], + zh: [_Wikipedia: #link(url_hal)[Hardware Abstraction Layer]_], +)) +] + +#tr(( +en: [ + Embedded systems are a bit special in this regard since we typically do + not have operating systems and user installable software but firmware + images which are compiled as a whole as well as a number of other + constraints. So while the traditional approach as defined by Wikipedia + could potentially work it is likely not the most productive approach to + ensure portability. +], +de: [ + Eingebettete Systeme nehmen hier eine Sonderstellung ein, da wir es + typischerweise nicht mit Betriebssystemen und vom Benutzer + installierbarer Software zu tun haben, sondern mit Firmware-Images, die + als Ganzes kompiliert werden -- und zudem mit einer Reihe weiterer + Einschränkungen konfrontiert sind. Der klassische, auf Wikipedia + beschriebene Ansatz könnte zwar theoretisch funktionieren, ist aber + wahrscheinlich nicht der effizienteste Weg, um Portabilität zu + gewährleisten. +], +ja: [ + 組込みシステムは、通常オペレーティングシステムを使わず、ユーザがインストールできるソフトウェアもありません。 + 全体として1つにコンパイルされたファームウェアイメージであり、様々な制約を持つ、という点が特殊です。 + そのため、Wikipediaで定義されている従来のアプローチでもうまく機能する可能性はありますが、移植性を確保するための最も有効なアプローチではない可能性があります。 +], +zh: [ + 在这方面,嵌入式系统有点特别,因为通常没有操作系统和用户可安装的软件,而只有固件镜像,其作为一个整体被编译且伴着许多约束。因此虽然维基百科定义的传统方法可能有用,但是它不是确保可移植性最有效的方法。 +])) + +#let ln_hal = link("https://crates.io/crates/embedded-hal")[embedded-hal] +#tr(( +en: [ + How do we do this in Rust? Enter *#ln_hal*… +], +de: [ + Wie gehen wir dabei in Rust vor? Hier kommt *#ln_hal* ins Spiel… +], +ja: [ + Rustではどうするのでしょうか?*embedded-hal*を見ていきましょう。 +], +zh: [ + 在Rust中我们要怎么实现这个目标呢?让我们进入*embedded-hal*… +])) + +== #tr(( + en: [What is #ln_hal?], + de: [Was ist #ln_hal?], + ja: [embedded-halとは?], + zh: [什么是embedded-hal?], +)) + +#tr(( +en: [ + In a nutshell it is a set of traits which define implementation + contracts between *HAL implementations*, *drivers* and + *applications (or firmwares)*. Those contracts include both + capabilities (i.e.~if a trait is implemented for a certain type, the + *HAL implementation* provides a certain capability) and methods + (i.e.~if you can construct a type implementing a trait it is guaranteed + that you have the methods specified in the trait available). +], +de: [ + Kurz gesagt handelt es sich um eine Reihe von Merkmalen, die + Implementierungsverträge zwischen *HAL-Implementierungen*, + *Treibern* und *Anwendungen (oder Firmware)* definieren. + Diese Verträge umfassen sowohl Fähigkeiten (d.~h., wenn ein Merkmal für + einen bestimmten Typ implementiert ist, stellt die + *HAL-Implementierung* eine bestimmte Fähigkeit bereit) als auch + Methoden (d.~h., wenn ein Typ, der ein Merkmal implementiert, erstellt + werden kann, ist garantiert, dass die im Merkmal spezifizierten Methoden + verfügbar sind). +], +ja: [ + 一言で言えば、*HAL実装*、*ドライバ*、*アプリケーションまたはファームウェア*間の実装規約を定義するトレイトの集まりのことです。 + それらの規約は、機能(ある型にトレイトが実装されていれば、*HAL実装*はそのトレイトの機能を提供します)とメソッド(あるトレイトを実装している型のオブジェクトを作成できれば、そのトレイトに含まれるメソッドが利用可能であることが保証されます)を含んでいます。 +], +zh: [ + 简而言之,它是一组traits,其定义了*HAL + implementations*,*驱动*,*应用(或者固件)* + 之间的实现约定(implementation + contracts)。这些约定包括功能(即约定,如果为某个类型实现了某个trait,*HAL + implementation*就提供了某个功能)和方法(即,如果构造一个实现了某个trait的类型,约定保障类型肯定有在trait中指定的方法)。 +])) + +#tr(( +en: [ + A typical layering might look like this: +], +de: [ + Ein typischer Schichtaufbau könnte wie folgt aussehen: +], +ja: [ + 典型的なレイヤ構造は、次のようになります。 +], +zh: [ + 典型的分层可能如下所示: +])) + +#box(image("../assets/rust_layers.svg")) + +#tr(( +en: [ + Some of the defined traits in *#ln_hal* are: + - GPIO (input and output pins) + - Serial communication + - I2C + - SPI + - Timers/Countdowns + - Analog Digital Conversion +], +de: [ + Einige der in *#ln_hal* definierten Traits sind: + - GPIO (Eingangs- und Ausgangspins) + - Serielle Kommunikation + - I2C + - SPI + - Timers/Countdowns + - Analog-Digital-Umsetzung +], +ja: [ + *embedded-hal*で定義されているいくつかのトレイトを示します。 + - GPIO(入出力ピン) + - シリアル通信 + - I2C + - SPI + - タイマ/カウントダウン + - アナログデジタル変換 +], +zh: [ + 一些在*embedded-hal*中被定义的traits: + - GPIO (input and output pins) + - Serial communication + - I2C + - SPI + - Timers/Countdowns + - Analog Digital Conversion +])) + +#tr(( +en: [ + The main reason for having the *embedded-hal* traits and crates + implementing and using them is to keep complexity in check. If you + consider that an application might have to implement the use of the + peripheral in the hardware as well as the application and potentially + drivers for additional hardware components, then it should be easy to + see that the re-usability is very limited. Expressed mathematically, if + *M* is the number of peripheral HAL implementations and + *N* the number of drivers then if we were to reinvent the wheel + for every application then we would end up with *M\*N* + implementations while by using the _API_ provided by the *#ln_hal* + traits will make the implementation complexity approach *M+N*. Of + course there're additional benefits to be had, such as less + trial-and-error due to a well-defined and ready-to-use APIs. +], +de: [ + Der Hauptgrund für die Existenz der *embedded-hal*-Traits und der + sie implementierenden sowie nutzenden Crates liegt darin, die + Komplexität beherrschbar zu halten. Bedenkt man, dass eine Anwendung + sowohl die Nutzung der Hardware-Peripherie als auch die eigentliche + Anwendungslogik sowie möglicherweise Treiber für zusätzliche + Hardwarekomponenten implementieren muss, wird schnell klar, dass die + Wiederverwendbarkeit stark eingeschränkt ist. Mathematisch ausgedrückt: + Wenn *M* die Anzahl der HAL-Implementierungen für + Peripheriegeräte und *N* die Anzahl der Treiber ist, würde man -- + müsste man für jede Anwendung das Rad neu erfinden -- bei *M × N* + Implementierungen landen; durch die Verwendung der von den *#ln_hal*-Traits + bereitgestellten API nähert sich die Implementierungskomplexität + hingegen *M + N* an. Natürlich ergeben sich daraus weitere + Vorteile, wie etwa ein geringerer Aufwand durch „Trial-and-Error" dank + wohldefinierter und sofort einsatzbereiter APIs. +], +ja: [ + *embedded-hal*トレイトと、それらを実装して使用するクレートを持つ主な理由は、複雑さを抑えることです。 + アプリケーションがハードウェアのペリフェラルを使うコードだけでなく、追加するハードウェアコンポーネントのドライバを実装しなければならない場合を考えると、再利用性は非常に制限されます。 + 数学的に表現すると、*M*がペリフェラルHAL実装の数で、*N*がドライバの数とするならば、全てのアプリケーションで車輪の再発明を行うことになります。 + その結果、*M\*N*の実装が必要になります。 + 一方、*embedded-hal*トレイトで提供されるAPIを使うことで、実装の複雑さは*M+N*になるでしょう。 + もちろん、明確に定義されたすぐに利用可能なAPIによって試行錯誤を減らすなど、他にも利点があります。 +], +zh: [ + 使用*embedded-hal* + traits和依赖*embedded-hal*的crates的主要原因是为了控制复杂性。如果发现一个应用可能必须要实现对硬件外设的使用,以及需要实现应用程序和其它硬件组件间潜在的驱动,那么其应该很容易被看作是可复用性有限的。用数学语言来说就是,如果*M*是外设HAL + implementations的数量,*N*是驱动的数量,那么如果我们要为每个应用重新发明轮子我们最终会有*M\*N*个实现,然而通过使用*embedded-hal*的traits提供的 + _API_ 将会使实现复杂性变成*M+N* + 。当然还有其它好处,比如由于API定义良好,开箱即用,导致试错减少。 +])) + +== #tr(( + en: [Users of the #ln_hal], + de: [Nutzer von #ln_hal], + ja: [embedded-halのユーザ], + zh: [embedded-hal的用户], +)) + +#tr(( +en: [ + As said above there are three main users of the HAL: +], +de: [ + Wie bereits erwähnt, gibt es drei Hauptnutzer einer HAL: +], +ja: [ + 上記のように、HALには主に3つのユーザがいます。 +], +zh: [ + 像上面所说的,HAL有三个主要用户: +])) + +=== #tr(( + en: [HAL implementation], + de: [HAL-Implementierung], + ja: [HAL実装], + zh: [HAL implementation], +)) + +#tr(( +en: [ + A HAL implementation provides the interfacing between the hardware and + the users of the HAL traits. Typical implementations consist of three + parts: + - One or more hardware specific types + - Functions to create and initialize such a type, + often providing various configuration options + (speed, operation mode, use pins, etc.) + - one or more `trait` `impl` of *#ln_hal* traits for that type +], +de: [ + Eine HAL-Implementierung stellt die Schnittstelle zwischen der Hardware + und den Nutzern der HAL-Traits bereit. Typische Implementierungen + bestehen aus drei Teilen: + - Ein oder mehrere hardwarespezifische Typen + - Funktionen zum Erstellen und Initialisieren eines solchen Typs, die + häufig verschiedene Konfigurationsoptionen (Geschwindigkeit, + Betriebsmodus, verwendete Pins usw.) bereitstellen. + - eine oder mehrere `trait`-Implementierungen (`impl`) von + *#ln_hal*-Traits für diesen Typ +], +ja: [ + HAL実装は、ハードウェアとHALトレイトのユーザとの間のインタフェースを実装します。典型的な実装では、3つの部分から構成されます。 + - 1つ以上のハードウェア固有の型 + - そのような型のオブジェクトを作成し、初期化する関数。多くの場合、様々な設定オプションを提供しています(速度、動作モード、使用ピンなど) + - 1つ以上のその型に対する*embedded-hal*の`trait` `impl` +], +zh: [ + HAL implentation提供硬件和HAL + traits的用户之间的接口。典型的实现由三部分组成: + - 一个或者多个硬件特定的类型 + - 生成和初始化这个类型的函数,函数经常提供不同的配置选项(速度,操作模式,使用的管脚,etc 。) + - 与这个类型有关的一个或者多个 *embedded-hal* traits 的 `trait` + `impl` +])) + +#tr(( +en: [ + Such a *HAL implementation* can come in various flavours: + - Via low-level hardware access, e.g.~via registers + - Via operating system, e.g.~by using the `sysfs` under Linux + - Via adapter, e.g.~a mock of types for unit testing + - Via driver for hardware adapters, e.g.~I2C multiplexer or GPIO expander +], +de: [ + Eine solche *HAL-Implementierung* kann in verschiedenen + Ausprägungen vorliegen: + - Über hardwarenahen Zugriff, z. B. über Register + - Über das Betriebssystem, z. B. durch Verwendung von `sysfs` unter Linux + - Über einen Adapter, z. B. ein Mock von Typen für Unit-Tests + - Via-Treiber für Hardware-Adapter, z. B. I2C-Multiplexer oder GPIO-Expander +], +ja: [ + このような*HAL実装*は、様々な種類があります。 + - 低レベルのハードウェアアクセスによるもの、例えばレジスタ + - オペレーティングシステムによるもの、例えばLinuxの`sysfs`の使用 + - アダプタによるもの、例えばユニットテストのための型のモック + - ハードウェアアダプタ用のドライバによるもの、例えばI2CマルチプレクサやGPIOエキスパンダ +], +zh: [ + 这样的一个 *HAL implementation* 可以有多个方法来实现: + - 通过低级硬件访问,比如通过寄存器。 + - 通过操作系统,比如通过使用Linux下的 `sysfs` + - 通过适配器,比如一个与单元测试有关的类型的仿真 + - 通过相关硬件适配器的驱动,e.g.~I2C多路复用器或者GPIO扩展器(I2C multiplexer or GPIO expander) +])) + +=== #tr(( + en: [Driver], + de: [Treiber], + ja: [ドライバ], + zh: [驱动], +)) + +#tr(( +en: [ + A driver implements a set of custom functionality for an internal or + external component, connected to a peripheral implementing the + #ln_hal traits. + Typical examples for such drivers include various sensors (temperature, + magnetometer, accelerometer, light), display devices (LED arrays, LCD + displays) and actuators (motors, transmitters). +], +de: [ + Ein Treiber implementiert eine Reihe benutzerdefinierter Funktionen für + eine interne oder externe Komponente, die mit einem Peripheriegerät + verbunden ist, das die #ln_hal;-Traits + implementiert. Typische Beispiele für solche Treiber sind verschiedene + Sensoren (Temperatur-, Magnetometer-, Beschleunigungs- und + Lichtsensoren), Anzeigegeräte (LED-Arrays, LCD-Displays) und Aktoren + (Motoren, Sender). +], +ja: [ + ドライバは、embedded-halトレイトを実装しているペリフェラルに接続されている、内部または外部コンポーネントに対するカスタム機能を実装します。 + そのようなドライバの典型的な例は、様々なセンサ(温度、磁気、加速度、輝度)、ディスプレイデバイス(LEDアレイ、LCDディスプレイ)や、アクチュエータ(モータ、トランスミッタ)を含みます。 +], +zh: [ + 驱动为一个外部或者内部组件实现了一组自定义的功能,被连接到一个实现了embedded-hal + traits的外设上。这种驱动的典型的例子包括多种传感器(温度计,磁力计,加速度计,光照计),显示设备(LED阵列,LCD显示屏)和执行器(电机,发送器)。 +])) + +#tr(( +en: [ + A driver has to be initialized with an instance of type that implements + a certain `trait` of the #ln_hal which is + ensured via trait bound and provides its own type instance with a custom + set of methods allowing to interact with the driven device. +], +de: [ + Ein Treiber muss mit einer Instanz eines Typs initialisiert werden, der + ein bestimmtes `Trait` von + #ln_hal + implementiert. Dies wird durch Trait-Bound sichergestellt. Der Treiber + stellt eine eigene Typinstanz mit einem benutzerdefinierten Satz von + Methoden bereit, die die Interaktion mit dem angesteuerten Gerät +], +ja: [ + ドライバは、embedded-halの特定のトレイトを実装する型のインスタンスと共に初期化する必要があります。 + そのトレイトは、トレイト境界により保証され、駆動するデバイスとやり取りできるインスタンスをカスタムメソッドと共に提供します。 +], +zh: [ + 必须使用实现了embedded-hal的某个`trait`的类型的实例来初始化驱动,这是通过trait + bound来确保的,驱动也提供了它自己的类型实例,这个实例具有一组自定义的方法,这些方法允许与被驱动的设备交互。 + +])) + +=== #tr(( + en: [Application], + de: [Anwendung], + ja: [アプリケーション], + zh: [应用], +)) + +#tr(( +en: [ + The application binds the various parts together and ensures that the + desired functionality is achieved. When porting between different + systems, this is the part which requires the most adaptation efforts, + since the application needs to correctly initialize the real hardware + via the HAL implementation and the initialisation of different hardware + differs, sometimes drastically so. Also the user choice often plays a + big role, since components can be physically connected to different + terminals, hardware buses sometimes need external hardware to match the + configuration or there are different trade-offs to be made in the use of + internal peripherals (e.g.~multiple timers with different capabilities + are available or peripherals conflict with others). +], +de: [ + Die Anwendung verknüpft die verschiedenen Komponenten miteinander und + stellt sicher, dass die gewünschte Funktionalität erreicht wird. Bei der + Portierung zwischen verschiedenen Systemen ist dies der Teil, der den + größten Anpassungsaufwand erfordert, da die Anwendung die eigentliche + Hardware über die HAL-Implementierung korrekt initialisieren muss -- und + die Initialisierung unterschiedlicher Hardware variiert, bisweilen sogar + drastisch. Zudem spielen oft anwenderspezifische Entscheidungen eine + wichtige Rolle: Komponenten können physisch an unterschiedliche + Anschlüsse angebunden sein, Hardware-Busse erfordern mitunter externe + Hardware zur Konfigurationsanpassung, oder es müssen Abwägungen bei der + Nutzung interner Peripherie getroffen werden (etwa wenn mehrere Timer + mit unterschiedlichen Fähigkeiten zur Verfügung stehen oder Konflikte + zwischen verschiedenen Peripherieeinheiten auftreten). +], +ja: [ + アプリケーションは、様々な部品を結合し、必要な機能が確実に実現できるようにします。 + 別システムに移植する際、アプリケーションは最も適合作業が求められる部分です。アプリケーションは、HAL実装を通じて、実際のハードウェアを初期化する必要があるからです。 + 異なるハードウェアの初期化は、極端に異なる場合があります。 + ユーザの選択は、多くの場合、大きな影響があります。 + コンポーネントが別の端子に物理的に接続されたり、ハードウェアバスが機器構成を満たすために外部ハードウェアを必要とする場合があったり、内部ペリフェラルを使えるようにするための異なるトレードオフがあったりします。例えば、異なる機能を持つ複数のタイマが利用可能であること、や、ペリフェラルが他のペリフェラルと競合すること、です。 +], +zh: [ + 应用把多个部分结合在一起并确保需要的功能被实现。当在不同的系统间移植时,这部分的适配是花费最多精力的地方,因为应用需要通过HAL + implementation正确地初始化真实的硬件,而且不同硬件的初始化也不相同,甚至有时候差别非常大。用户的选择也在其中扮演了非常重大的角色,因为组件能被物理连接到不同的端口,硬件总线有时候需要外部硬件去匹配配置,或者用户在内部外设的使用上有不同的考量。 +])) diff --git a/typ/start/exceptions.typ b/typ/start/exceptions.typ new file mode 100644 index 00000000..b834be37 --- /dev/null +++ b/typ/start/exceptions.typ @@ -0,0 +1,773 @@ +#import "../config.typ": * + +#h1((en: [Exceptions], + de: [Ausnahmen (Exceptions)], + ja: [例外], + zh: [异常], +), offset: whole) + + +#tr(( +en: [ + Exceptions, and interrupts, are a hardware mechanism by which the + processor handles asynchronous events and fatal errors (e.g.~executing + an invalid instruction). Exceptions imply preemption and involve + exception handlers, subroutines executed in response to the signal that + triggered the event. +], +de: [ + Ausnahmen und Interrupts sind ein Hardwaremechanismus, mit dem der + Prozessor asynchrone Ereignisse und schwerwiegende Fehler (z. B. die + Ausführung einer ungültigen Anweisung) behandelt. Ausnahmen implizieren + Präemption und erfordern Ausnahmebehandlungsroutinen, die als Reaktion + auf das auslösende Signal ausgeführt werden. +], +ja: [ + 例外と割り込みは、プロセッサが非同期イベントと致命的なエラー(例えば、不正な命令の実行)を扱うためのハードウェアの仕組みです。 + 例外はプリエンプションを意味し、例外ハンドラを呼び出します。例外ハンドラは、イベントを引き起こした信号に応答して実行されるサブルーチンです。 +], +zh: [ + 异常和中断,是处理器用来处理异步事件和致命错误(e.g.~执行一个无效的指令)的一种硬件机制。异常意味着抢占并涉及到异常处理程序,即响应触发事件的信号的子程序。 +])) + +#let ln_ex = link("https://docs.rs/cortex-m-rt-macros/latest/cortex_m_rt_macros/attr.exception.html")[`exception`] +#tr(( +en: [ + The `cortex-m-rt` crate provides an #ln_ex attribute to declare exception handlers. +], +de: [ + Die `cortex-m-rt`-Crate bietet das Attribut #ln_ex zur Deklaration von Ausnahmebehandlungsroutinen. +], +ja: [ + `cortex-m-rt`クレートは、例外ハンドラを宣言するために、#ln_ex;アトリビュートを提供しています。 +], +zh: [ + `cortex-m-rt` crate提供了一个 #ln_ex 属性去声明异常处理程序。 +])) + +#raw(block: true, lang: "rust", +"// " + ts(( + en: "Exception handler for the SysTick (System Timer) exception", + de: "Ausnahmebehandlungsroutine fuer die SysTick-Ausnahme (System-Timer)", + ja: "SysTick(システムタイマ)例外のための例外ハンドラ", + zh: "SysTick (System计时器)异常的异常处理函数", + )) + " +#[exception] +fn SysTick() { + // .. +} +") + +#tr(( +en: [ + Other than the `exception` attribute exception handlers look like plain + functions but there's one more difference: `exception` handlers can + _not_ be called by software. Following the previous example, the + statement `SysTick();` would result in a compilation error. +], +de: [ + Abgesehen vom `exception`-Attribut sehen Exception-Handler wie + gewöhnliche Funktionen aus, doch es gibt noch einen weiteren + Unterschied: `exception`-Handler können _nicht_ per Software + aufgerufen werden. Bezogen auf das vorherige Beispiel würde die + Anweisung `SysTick();` zu einem Kompilierfehler führen. +], +ja: [ + `exception`属性の他は、例外ハンドラは普通の関数のように見えます。しかし、もう1つ違いがあります。 + `exception`ハンドラはソフトウェアから呼び出すことが_できません_。前述の例では、`SysTick();`というステートメントは、 + コンパイルエラーになります。 +], +zh: [ + 除了 `exception` + 属性,异常处理函数看起来和普通函数一样,但是有一个很大的不同: + `exception` 处理函数 _不能_ 被软件调用。在先前的例子中,语句 + `SysTick();` 将会导致一个编译错误。 +])) + +#tr(( +en: [ + This behavior is pretty much intended and it's required to provide a + feature: `static mut` variables declared _inside_ `exception` + handlers are _safe_ to use. +], +de: [ + Dieses Verhalten ist durchaus beabsichtigt und notwendig, um eine + bestimmte Eigenschaft zu gewährleisten: `static mut`-Variablen, die + _innerhalb_ von `exception`-Handlern deklariert werden, sind + _sicher_ in der Verwendung. +], +ja: [ + この動作は、非常に意図的なものです。 + これは`exception`ハンドラ_内_で宣言された`static mut`変数の利用を_安全_にする、という機能を提供するためのものです。 +], +zh: [ + 这么做是有目的的,因为异常处理函数必须具有一个特性: + 在异常处理函数中被声明为`static mut`的变量能被安全(safe)地使用。 +])) + +#raw(block: true, lang: "rust", +"#[exception] +fn SysTick() { + static mut COUNT: u32 = 0; + // " + ts(( + en: "`COUNT` has transformed to type `&mut u32` and it's safe to use", + de: "`COUNT` wurde in den Typ `&mut u32` umgewandelt und ist sicher in der + // Verwendung.", + ja: "`COUNT`は`&mut u32`の型をもっており、その利用は安全です", + zh: "`COUNT` 被转换到了 `&mut u32` 类型且它用起来是安全的", + )) + " + *COUNT += 1; +") + +#let url_re = "https://en.wikipedia.org/wiki/Reentrancy_(computing)" +#tr(( +en: [ + As you may know, using `static mut` variables in a function makes it + #link(url_re)[_non-reentrant_]. + It's undefined behavior to call a non-reentrant function, directly or + indirectly, from more than one exception / interrupt handler or from + `main` and one or more exception / interrupt handlers. +], +de: [ + Wie Ihnen vielleicht bekannt ist, führt die Verwendung von + `static mut`-Variablen in einer Funktion dazu, dass diese + #link(url_re)[_nicht wiedereintrittsfähig_] + ist. Es stellt undefiniertes Verhalten dar, eine nicht + wiedereintrittsfähige Funktion direkt oder indirekt aus mehr als einem + Ausnahme- oder Interrupt-Handler oder aus `main` und einem oder mehreren + Ausnahme- oder Interrupt-Handlern heraus aufzurufen. +], +ja: [ + ご存知かもしれませんが、`static mut`変数を関数内で使うことは、その関数を_再入不可能_にします。 + 直接的または間接的に、複数の例外・割り込みハンドラから、もしくは、`main`と1つ以上の例外・割り込みハンドラから、 + 再進入不可能な関数を呼び出すことは、未定義動作です。 +], +zh: [ + 就像你可能已经知道的那样,在一个函数里使用`static mut`变量,会让函数变成#link(url_re)[_非可重入函数(non-reentrancy)_]。从多个异常/中断处理函数,或者从`main`函数和多个异常/中断处理函数中,直接或者间接地调用一个非可重入(non-reentrancy)函数是未定义的行为。 +])) + +#tr(( +en: [ + Safe Rust must never result in undefined behavior so non-reentrant + functions must be marked as `unsafe`. Yet I just told that `exception` + handlers can safely use `static mut` variables. How is this possible? + This is possible because `exception` handlers can _not_ be called + by software thus reentrancy is not possible. These handlers are called + by the hardware itself which is assumed to be physically non-concurrent. +], +de: [ + Safe Rust darf niemals zu undefiniertem Verhalten führen; daher müssen + nicht-wiedereintrittsfähige Funktionen als `unsafe` gekennzeichnet + werden. Dennoch habe ich gerade erwähnt, dass Ausnahme-Handler + (`exception handlers`) sicher `static mut`-Variablen verwenden können. + Wie ist das möglich? Dies ist möglich, da Ausnahme-Handler _nicht_ + per Software aufgerufen werden können und somit kein Wiedereintritt + (Reentrancy) stattfinden kann. Diese Handler werden von der Hardware + selbst aufgerufen, bei der davon ausgegangen wird, dass sie physisch + keine Nebenläufigkeit aufweist. +], +ja: [ + #todoupd("ja") + 安全なRustは、決して未定義動作になりません。そのため、再入不可能な関数は、`unsafe`とマークされなければなりません。 + それでも、`exception`ハンドラは`static mut`な変数を安全に使える、と述べました。これが可能なのは、どうしてでしょうか。 + `exception`ハンドラはソフトウェアから呼び出すことが_できない_ため、再入する可能性はありません。だから、安全に使えるのです。 +], +zh: [ + #todoupd("zh") + 安全的Rust不能导致未定义的行为出现,所以非可重入函数必须被标记为 + `unsafe`。然而,我刚说了`exception`处理函数能安全地使用`static mut`变量。这怎么可能?因为`exception`处理函数 + _不_ 能被软件调用因此重入(reentrancy)不会发生,所以这才变得可能。 +])) + +#tr(( +en: [ + As a result, in the context of exception handlers in embedded systems, + the absence of concurrent invocations of the same handler ensures that + there are no reentrancy issues, even if the handler uses static mutable + variables. +], +de: [ + Im Kontext von Ausnahme-Handlern in eingebetteten Systemen stellt das + Ausbleiben gleichzeitiger Aufrufe desselben Handlers folglich sicher, + dass keine Probleme mit der Wiedereintrittsfähigkeit auftreten -- selbst + dann nicht, wenn der Handler veränderbare statische Variablen verwendet +])) + +#tr(( +en: [ + In a multicore system, where multiple processor cores are executing code + concurrently, the potential for reentrancy issues becomes relevant + again, even within exception handlers. While each core may have its own + set of exception handlers, there can still be scenarios where multiple + cores attempt to execute the same exception handler simultaneously. \ + To address this concern in a multicore environment, proper synchronization + mechanisms need to be employed within the exception handlers to ensure + that access to shared resources is properly coordinated among the cores. + This typically involves the use of techniques such as locks, semaphores, + or atomic operations to prevent data races and maintain data integrity +], +de: [ + In einem Multicore-System, in dem mehrere Prozessorkerne gleichzeitig + Code ausführen, gewinnt die Problematik der Wiedereintrittsfähigkeit + (Reentrancy) erneut an Bedeutung -- selbst innerhalb von + Exception-Handlern. Auch wenn jeder Kern über eigene Exception-Handler + verfügen mag, kann es dennoch zu Situationen kommen, in denen mehrere + Kerne versuchen, denselben Exception-Handler simultan auszuführen. Um + dieser Herausforderung in einer Multicore-Umgebung zu begegnen, müssen + innerhalb der Exception-Handler geeignete Synchronisationsmechanismen + eingesetzt werden; so wird sichergestellt, dass der Zugriff auf + gemeinsam genutzte Ressourcen zwischen den Kernen korrekt koordiniert + wird. Dies geschieht typischerweise durch den Einsatz von Techniken wie + Locks, Semaphoren oder atomaren Operationen, um Race Conditions zu + vermeiden und die Datenintegrität zu wahren. +])) + +#quote(block: true)[ +#tr(( +en: [ + Note that the `exception` attribute transforms definitions of static + variables inside the function by wrapping them into `unsafe` blocks and + providing us with new appropriate variables of type `&mut` of the same + name. Thus we can dereference the reference via `*` to access the values + of the variables without needing to wrap them in an `unsafe` block. +], +de: [ + Beachten Sie, dass das Attribut `exception` Definitionen statischer + Variablen innerhalb der Funktion umwandelt, indem es sie in + `unsafe`-Blöcke einschließt und uns neue, passende Variablen des Typs + `&mut` mit demselben Namen zur Verfügung stellt. Auf diese Weise können + wir die Referenz mittels `*` dereferenzieren, um auf die Werte der + Variablen zuzugreifen, ohne sie selbst in einen `unsafe`-Block + einschließen zu müssen. +], +zh: [ + 注意,`exception`属性,通过将静态变量封装进`unsafe`块中并为我们提供了名字相同的,类型为 + `&mut` 的,合适的新变量,转换了函数中静态变量的定义。因此我们可以通过 + `*` 解引用访问变量的值而不需要将它们打包进一个 `unsafe` 块中。 +])) +] + += #tr(( + en: [A complete example], + de: [Ein vollständiges Beispiel], + ja: [完全な例], + zh: [一个完整的例子], +)) + +#tr(( +en: [ + Here's an example that uses the system timer to raise a `SysTick` + exception roughly every second. The `SysTick` exception handler keeps + track of how many times it has been called in the `COUNT` variable and + then prints the value of `COUNT` to the host console using semihosting. + of the variables without needing to wrap them in an `unsafe` block. +], +de: [ + Hier ist ein Beispiel, das den System-Timer verwendet, um etwa jede + Sekunde eine `SysTick`-Exception auszulösen. Der + `SysTick`-Exception-Handler protokolliert in der Variablen `COUNT`, wie + oft er aufgerufen wurde, und gibt anschließend den Wert von `COUNT` + mittels Semihosting auf der Host-Konsole aus. +], +ja: [ + `SysTick`例外を大体1秒毎に発生させるシステムタイマの例を使います。 + `SysTick`例外ハンドラは、呼び出された回数を`COUNT`変数に記録し、 + セミホスティングを使ってホストコンソールに`COUNT`の値を出力します。 +], +zh: [ + 这里有个例子,使用系统计时器大概每秒抛出一个 `SysTick` + 异常。异常处理函数使用 `COUNT` + 变量追踪它自己被调用了多少次,然后使用半主机模式(semihosting)打印 + `COUNT` 的值到主机控制台上。 +])) + +#quote(block: true)[ +#tr(( +en: [ + *NOTE*: You can run this example on any Cortex-M device; you can + also run it on QEMU +], +de: [ + *HINWEIS*: Sie können dieses Beispiel auf jedem Cortex-M-Gerät + ausführen; es lässt sich auch unter QEMU ausführen. +], +ja: [ + *注記*:この例は、どのCortex-Mデバイスでも実行できます。QEMU上でも実行可能です。 +], +zh: [ + *注意*: 你能在任何Cortex-M设备上运行这个例子;你也能在QEMU运行它。 +])) +] + +#raw(block: true, lang: "rust", +"#![deny(unsafe_code)] +#![no_main] +#![no_std] + +use panic_halt as _; + +use core::fmt::Write; + +use cortex_m::peripheral::syst::SystClkSource; +use cortex_m_rt::{entry, exception}; +use cortex_m_semihosting::{ + debug, + hio::{self, HostStream}, +}; + +#[entry] +fn main() -> ! { + let p = cortex_m::Peripherals::take().unwrap(); + let mut syst = p.SYST; + + // " + ts(( + en: "configures the system timer to trigger a SysTick exception every second", + de: "konfiguriert den System-Timer so, dass er jede Sekunde eine SysTick- + // Exception ausloest", + ja: "毎秒SysTick例外を起こすためのシステムタイマを設定します", + zh: "配置系统的计时器每秒去触发一个SysTick异常", + )) + " + syst.set_clock_source(SystClkSource::Core); + // " + ts(( + en: "this is configured for the LM3S6965 which has a default CPU clock of 12 MHz", + de: "Dies ist für den LM3S6965 konfiguriert, der einen Standard-CPU-Takt von + // 12 MHz hat", + ja: "デフォルトのCPUクロックが12MHzのLM3S6965向けの設定です", + zh: "这是关于LM3S6965的配置,其有一个12MHz的默认CPU时钟", + )) + " + syst.set_reload(12_000_000); + syst.clear_current(); + syst.enable_counter(); + syst.enable_interrupt(); + + loop {} +} + +#[exception] +fn SysTick() { + static mut COUNT: u32 = 0; + static mut STDOUT: Option = None; + + *COUNT += 1; + + // " + ts(( + en: "Lazy initialization", + de: "Verzoegerte Initialisierung", + ja: "遅延初期化", + zh: "惰性初始化(Lazy initialization)", + )) + " + if STDOUT.is_none() { + *STDOUT = hio::hstdout().ok(); + } + + if let Some(hstdout) = STDOUT.as_mut() { + write!(hstdout, \"{}\", *COUNT).ok(); + } + + // " + ts(( + en: "IMPORTANT omit this `if` block if running on real hardware or your + // debugger will end in an inconsistent state", + de: "WICHTIG: Lassen Sie diesen `if`-Block weg, wenn Sie das Programm auf + // echter Hardware ausfuehren, da sich Ihr Debugger sonst in + // einem inkonsistenten Zustand befinden wird.", + ja: "重要。実際のハードウェアで実行するときは`if`ブロックを削除して下さい。そうでなければ、 + // デバッガが不整合な状態に陥るでしょう。", + zh: "重要信息 如果运行在真正的硬件上,去掉这个 `if` 块, + // 否则你的调试器将会以一种不一致的状态结束" + )) + " + if *COUNT == 9 { + // " + ts(( + en: "This will terminate the QEMU process", + de: "Dies beendet den QEMU-Prozess.", + ja: "QEMUプロセスを終了します", + zh: "这将终结QEMU进程", + )) + " + debug::exit(debug::EXIT_SUCCESS); + } +} +") + +```console +tail -n5 Cargo.toml +``` + +```toml +[dependencies] +cortex-m = "0.5.7" +cortex-m-rt = "0.6.3" +panic-halt = "0.2.0" +cortex-m-semihosting = "0.3.1" +``` + +```text +$ cargo run --release + Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb (..) +123456789 +``` + +#tr(( +en: [ + If you run this on the Discovery board you'll see the output on the + OpenOCD console. Also, the program will _not_ stop when the count + reaches 9. +], +de: [ + Wenn Sie dies auf dem Discovery-Board ausführen, sehen Sie die Ausgabe + in der OpenOCD-Konsole. Außerdem hält das Programm _nicht_ an, wenn + der Zählerstand 9 erreicht. +], +ja: [ + Discoveryボードでこのコードを実行すると、OpenOCDコンソールに出力を確認できるでしょう。 + プログラムは、カウントが9に到達しても停止_しません_。 +], +zh: [ + 如果你在Discovery开发板上运行这个例子,你将会在OpenOCD控制台上看到输出。还有,当计数到达9的时候,程序将 _会_ 停止。 +])) + += #tr(( + en: [The default exception handler], + de: [Der Standard-Exception-Handler], + ja: [デフォルト例外ハンドラ], + zh: [默认异常处理函数], +)) + +#tr(( +en: [ + What the `exception` attribute actually does is _override_ the + default exception handler for a specific exception. If you don't + override the handler for a particular exception it will be handled by + the `DefaultHandler` function, which defaults to: +], +de: [ + Das `exception`-Attribut bewirkt eigentlich, dass der + Standard-Exception-Handler für eine bestimmte Exception + _überschrieben_ wird. Wenn Sie den Handler für eine bestimmte + Exception nicht überschreiben, wird sie von der Funktion + `DefaultHandler` behandelt, die standardmäßig Folgendes tut: +], +ja: [ + `exception`アトリビュートが実際に行っていることは、特定の例外を処理するデフォルト例外ハンドラの_オーバーライド_です。 + 特定の例外について、ハンドラをオーバーライドしない場合、`DefaultHandler`関数がその例外を処理します。 + DefaultHandler関数は下記の通りです。 +], +zh: [ + `exception` 属性真正做的是,_覆盖_ + 了一个特定异常的默认异常处理函数。如果你不覆盖一个特定异常的处理函数,它将会被 + `DefaultHandler` 函数处理,其默认的是: +])) + +```rust +fn DefaultHandler() { + loop {} +} +``` + +#tr(( +en: [ + This function is provided by the `cortex-m-rt` crate and marked as + `#[no_mangle]` so you can put a breakpoint on "DefaultHandler" and catch + _unhandled_ exceptions. +], +de: [ + Diese Funktion wird vom `cortex-m-rt`-Crate bereitgestellt und ist mit + `#[no_mangle]` markiert, sodass Sie einen Breakpoint auf + „DefaultHandler" setzen und _unbehandelte_ Exceptions abfangen + können. +], +ja: [ + この関数は、`cortex-m-rt`クレートによって提供されており、`#[no_mangle]`とマークされています。 + そのため、「DefaultHandler」にブレイクポイントを設定することができ、_未処理の_例外を捕捉することができます。 +], +zh: [ + 这个函数是 `cortex-m-rt` crate提供的,且被标记为 `#[no_mangle]` + 因此你能在 "DefaultHandler" 上放置一个断点并捕获 _unhandled_ 异常。 +])) + +#tr(( +en: [ + It's possible to override this `DefaultHandler` using the `exception` + attribute: +], +de: [ + Es ist möglich, diesen `DefaultHandler` mithilfe des + `exception`-Attributs zu überschreiben: +], +ja: [ + `exception`アトリビュートを使うことで、`DefaultHandler`をオーバーライドできます。 +], +zh: [ + 可以使用 `exception` 属性覆盖这个 `DefaultHandler`: +])) + +#raw(block: true, lang: "rust", +"#[exception] +fn DefaultHandler(irqn: i16) { + // " + ts(( + en: "custom default handler", + de: "benutzerdefinierter Standard-Handler", + ja: "カスタムデフォルトハンドラ", + zh: "自定义默认处理函数", + )) + " +} +") + +#tr(( +en: [ + The `irqn` argument indicates which exception is being serviced. A + negative value indicates that a Cortex-M exception is being serviced; + and zero or a positive value indicate that a device specific exception, + AKA interrupt, is being serviced. +], +de: [ + Das Argument `irqn` gibt an, welche Exception gerade bearbeitet wird. + Ein negativer Wert zeigt an, dass eine Cortex-M-Exception bearbeitet + wird, während ein Wert von null oder ein positiver Wert darauf hinweist, + dass eine gerätespezifische Exception -- auch als Interrupt bezeichnet + -- bearbeitet wird. +], +ja: [ + `irqn`引数は、どの例外が処理されているかを示します。負の値は、Cortex-Mの例外が処理されていることを意味します。 + ゼロまたは正の値は、デバイス固有の例外、すなわち、割り込みが処理されていること、を示しています。 +], +zh: [ + `irqn` 参数指出了被服务的是哪个异常。一个负数值指出了被服务的是一个Cortex-M异常;0或者一个正数值指出了被服务的是一个设备特定的异常,也就是中断。 +])) + += #tr(( + en: [The hard fault handler], + de: [Der "Schwere Fehler"-Handler], + ja: [ハードフォールトハンドラ], + zh: [硬错误(Hard Fault)处理函数], +)) + +#tr(( +en: [ + The `HardFault` exception is a bit special. This exception is fired when + the program enters an invalid state so its handler can _not_ return + as that could result in undefined behavior. Also, the runtime crate does + a bit of work before the user defined `HardFault` handler is invoked to + improve debuggability. +], +de: [ + Die `HardFault`-Exception nimmt eine Sonderstellung ein. Sie wird + ausgelöst, wenn das Programm in einen ungültigen Zustand gerät; daher + darf ihr Handler nicht zurückkehren, da dies zu undefiniertem Verhalten + führen könnte. Zudem führt die Runtime-Crate einige Vorarbeiten durch, + bevor der benutzerdefinierte `HardFault`-Handler aufgerufen wird, um die + Fehlersuche (Debugging) zu erleichtern. +], +ja: [ + `HardFault`例外は、少し特別です。この例外は、プログラムが不正な状態になった場合に発生します。 + そのため、このハンドラはリターンすることができず、未定義動作を引き起こす可能性があります。 + ランタイムクレートは、デバッグ性を向上するために、ユーザ定義の`HardFault`ハンドラが呼び出される前に、少し仕事をします。 +], +zh: [ + `HardFault`异常有点特别。当程序进入一个无法工作的状态时,这个异常被触发,因此它的处理函数 + _不能_ 返回,因为这么做可能导致一个未定义的行为。在用户定义的 + `HardFault` + 处理函数被调用之前,运行时crate还做了一些工作以改进调试功能。 +])) + +#tr(( +en: [ + The result is that the `HardFault` handler must have the following + signature: `fn(&ExceptionFrame) -> !`. The argument of the handler is a + pointer to registers that were pushed into the stack by the exception. + These registers are a snapshot of the processor state at the moment the + exception was triggered and are useful to diagnose a hard fault. +], +de: [ + Daraus ergibt sich, dass der `HardFault`-Handler folgende Signatur + aufweisen muss: `fn(&ExceptionFrame) -> !`. Das Argument des Handlers + ist ein Zeiger auf Register, die beim Auftreten der Exception auf den + Stack gesichert wurden. Diese Register stellen eine Momentaufnahme des + Prozessorzustands zum Zeitpunkt der Auslösung der Exception dar und sind + für die Diagnose eines Hard Faults hilfreich. +], +ja: [ + その結果、`HardFault`ハンドラは、`fn(&ExceptionFrame) -> !`のシグネチャを持つ必要があります。 + ハンドラの引数は、例外によってスタックにプッシュされたレジスタへのポインタです。 + これらのレジスタは、例外が発生した瞬間のプロセッサステートのスナップショットで、ハードフォールトの原因を突き止めるのに便利です。 +], +zh: [ + 结果是,`HardFault`处理函数必须有下列的签名: `fn(&ExceptionFrame) -> !` + 。处理函数的参数是一个指针,它指向被异常推入栈中的寄存器。这些寄存器是异常被触发那刻,处理器状态的一个记录,能被用来分析一个硬错误。 +])) + +#tr(( +en: [ + Here's an example that performs an illegal operation: a read to a + nonexistent memory location. +], +de: [ + Hier ist ein Beispiel für eine unzulässige Operation: der Lesezugriff + auf eine nicht existierende Speicheradresse. +], +ja: [ + 不正な操作を行う例を示します。存在しないメモリ位置への読み込みです。 +], +zh: [ + 这里有个执行不合法操作的案例: 读取一个不存在的存储位置。 +])) + +#quote(block: true)[ +#tr(( +en: [ + *NOTE*: This program won't work, i.e.~it won't crash, on QEMU + because `qemu-system-arm -machine lm3s6965evb` doesn't check memory + loads and will happily return `0`on reads to invalid memory. +], +de: [ + *HINWEIS*: Dieses Programm wird unter QEMU nicht fehlschlagen + (d.~h. es stürzt nicht ab), da `qemu-system-arm -machine lm3s6965evb` + keine Überprüfung von Speicherzugriffen durchführt und beim Lesen von + ungültigem Speicher problemlos den Wert `0` zurückgibt. +], +ja: [ + *注記*:このプログラムは、QEMU上ではうまく動きません。つまり、クラッシュしません。 + `qemu-system-arm -machine lm3s6965evb`はメモリの読み込みをチェックしないため、 + 無効なメモリを読み込むと、幸いにも、`0`を返します。 +], +zh: [ + *注意*: 这个程序在QEMU上不能起作用,i.e.~它不会崩溃,因为 + `qemu-system-arm -machine lm3s6965evb` + 不对读取存储的操作进行检查,且读取无效存储时将会开心地返回 `0`。 +])) +] + + +#raw(block: true, lang: "rust", +"#![no_main] +#![no_std] + +use panic_halt as _; + +use core::fmt::Write; +use core::ptr; + +use cortex_m_rt::{entry, exception, ExceptionFrame}; +use cortex_m_semihosting::hio; + +#[entry] +fn main() -> ! { + // " + ts(( + en: "read a nonexistent memory location", + de: "liest einen nicht existierenden Speicherbereich", + ja: "存在しないメモリ位置を読み込みます", + zh: "读取一个无效的存储位置", + )) + " + unsafe { + ptr::read_volatile(0x3FFF_0000 as *const u32); + } + + loop {} +} + +#[exception] +fn HardFault(ef: &ExceptionFrame) -> ! { + if let Ok(mut hstdout) = hio::hstdout() { + writeln!(hstdout, \"{:#?}\", ef).ok(); + } + + loop {} +} +") + +#tr(( +en: [ + The `HardFault` handler prints the `ExceptionFrame` value. If you run + this you'll see something like this on the OpenOCD console. +], +de: [ + Der `HardFault`-Handler gibt den Wert des `ExceptionFrame` aus. Wenn Sie + dies ausführen, sehen Sie auf der OpenOCD-Konsole eine Ausgabe wie diese. +], +ja: [ + `HardFault`ハンドラは、`ExceptionFrame`の値を表示します。実行すると、 + OpenOCDコンソールに次のような表示が見えるでしょう。 +], +zh: [ + `HardFault`处理函数打印了`ExceptionFrame`值。如果你运行这个,你将会看到下面的东西打印到OpenOCD控制台上。 +])) + +```text +$ openocd +(..) +ExceptionFrame { + r0: 0x3fff0000, + r1: 0x00000003, + r2: 0x080032e8, + r3: 0x00000000, + r12: 0x00000000, + lr: 0x080016df, + pc: 0x080016e2, + xpsr: 0x61000000, +} +``` + +#tr(( +en: [ + The `pc` value is the value of the Program Counter at the time of the + exception and it points to the instruction that triggered the exception. +], +de: [ + Der Wert `pc` ist der Wert des Programmzählers zum Zeitpunkt der + Ausnahme und verweist auf die Anweisung, die die Ausnahme ausgelöst hat. +], +ja: [ + `pc`の値は、例外発生時のプログラムカウンタの値で、例外を引き起こした命令を指しています。 +], +zh: [ + `pc`值是异常时程序计数器(Program Counter)的值,它指向触发了异常的指令。 +])) + +#tr(( +en: [ + If you look at the disassembly of the program: +], +de: [ + Wenn Sie sich den Disassembler des Programms ansehen: +], +ja: [ + プログラムのディスアセンブル結果を見ます。 +], +zh: [ + 如果你看向程序的反汇编: +])) + +```text +$ cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex +(..) +ResetTrampoline: + 8000942: movw r0, #0xfffe + 8000946: movt r0, #0x3fff + 800094a: ldr r0, [r0] + 800094c: b #-0x4 +``` + +#tr(( +en: [ + You can lookup the value of the program counter `0x0800094a` in the + disassembly. You'll see that a load operation (`ldr r0, [r0]` ) caused + the exception. The `r0` field of `ExceptionFrame` will tell you the + value of register `r0` was `0x3fff_fffe` at that time. +], +de: [ + Den Wert des Programmzählers `0x0800094a` können Sie in der + Disassemblierung nachschlagen. + + Sie werden sehen, dass eine Ladeoperation (`ldr r0, [r0]`) die Ausnahme + verursacht hat. + + Das Feld `r0` von `ExceptionFrame` gibt an, dass der Wert des Registers + `r0` zu diesem Zeitpunkt `0x3fff_fffe` war. +], +ja: [ + #todoupd("ja") + ロード命令(`ldr r0, [r0]`)が例外を発生させたことがわかります。そして、この時の`r0`レジスタの値は、 + `0x3fff_fffe`です。この値は、`ExceptionFrame`の`r0`フィールドと一致します。 +], +zh: [ + 你可以在反汇编中搜索程序计数器`0x0800094a`的值。你将会看到一个读取操作(`ldr r0, [r0]`)导致了异常。`ExceptionFrame`的`r0`字段将告诉你,那时寄存器`r0`的值是`0x3fff_fffe` + 。 +])) diff --git a/typ/start/hardware.typ b/typ/start/hardware.typ new file mode 100644 index 00000000..92216d3c --- /dev/null +++ b/typ/start/hardware.typ @@ -0,0 +1,908 @@ +#import "../config.typ": * + +#h1((en: [Hardware], + de: [Hardware], + ja: [ハードウェア], + zh: [硬件], +)) + + +#tr(( +en: [ + By now you should be somewhat familiar with the tooling and the + development process. In this section we'll switch to real hardware; the + process will remain largely the same. Let's dive in. +], +de: [ + Mittlerweile sollten Sie mit den Werkzeugen und dem Entwicklungsprozess + einigermaßen vertraut sein. In diesem Abschnitt wechseln wir zur echten + Hardware; der Prozess bleibt im Großen und Ganzen gleich. Tauchen wir ein. +], +ja: [ + ここまでで、ツールと開発プロセスにある程度慣れたはずです。このセクションでは、実際のハードウェアに切り替えます。 + 開発プロセスは、ほとんど同じままです。飛び込みましょう。 +], +zh: [ + 现在你应该有点熟悉工具和开发过程了。在这部分我们将切换到真正的硬件上;步骤非常相似。让我们深入下去。 +])) + += #tr(( + en: [Know your hardware], + de: [Kennen Sie Ihre Hardware], + ja: [ハードウェアを知る], + zh: [认识你的硬件] +)) + +#tr(( +en: [ + Before we begin you need to identify some characteristics of the target + device as these will be used to configure the project: + - The ARM core. e.g.~Cortex-M3. + - Does the ARM core include an FPU? Cortex-M4#[*F*] and + Cortex-M7#[*F*] cores do. + - How much Flash memory and RAM does the target device have? e.g.~256 + KiB of Flash and 32 KiB of RAM. + - Where are Flash memory and RAM mapped in the address space? e.g.~RAM + is commonly located at address `0x2000_0000`. +], +de: [ + Bevor wir beginnen, müssen Sie einige Eigenschaften des Zielgeräts + identifizieren da diese zur Konfiguration des Projekts verwendet werden: + - Der ARM-Kern, z.B. Cortex-M3. + - Enthält der ARM-Kern eine FPU? Cortex-M4#[*F*] und + Cortex-M7#[*F*]-Kerne tun dies. + - Wie viel Flash-Speicher und RAM hat das Zielgerät? z.B. 256 KiB von + Flash und 32 KiB RAM. + - Wo werden Flash-Speicher und RAM im Adressraum abgebildet? zB RAM ist + befindet sich üblicherweise an der Adresse `0x2000_0000`. +], +ja: [ + 始める前に、プロジェクトの設定に利用するターゲットデバイスのいくつかの特徴を確認する必要があります。 + - ARMコア、例えばCortex-M3です。 + - そのARMコアはFPUを搭載していますか?Cortex-M4#[*F*]とCortex-M7#[*F*]は、搭載しています。 + - ターゲットデバイスに搭載されているフラッシュメモリとRAMの容量はいくらですか? + 例えば、フラッシュは256KiBでRAMは32KiBです。 + - フラッシュメモリとRAMは、アドレス空間のどこにマッピングされていますか? + 例えば、RAMは、通常`0x2000_0000`番地に位置します。 +], +zh: [ + 在我们开始之前,你需要了解下你的目标设备的一些特性,因为你将用它们来配置项目: + - ARM 内核。比如 Cortex-M3 。 + - ARM 内核包括一个FPU吗?Cortex-M4#[*F*]和Cortex-M7#[*F*]有。 + - 目标设备有多少Flash和RAM?比如 256KiB的Flash和32KiB的RAM。 + - Flash和RAM映射在地址空间的什么位置?比如 RAM通常位于 `0x2000_0000` 地址处。 +])) + +#tr(( +en: [ + You can find this information in the data sheet or the reference manual + of your device. +], +de: [ + Diese Informationen finden Sie im Datenblatt oder im Referenzhandbuch + Ihres/Ihrer Microcontrollers/Microcontrollerplatine. +], +ja: [ + これらの情報は、デバイスのデータシートかリファレンスマニュアルに掲載されています。 +], +zh: [ + 你可以在你的设备的数据手册和参考手册上找到这些信息。 +])) + +#tr(( +en: [ + In this section we'll be using our reference hardware, the + STM32F3DISCOVERY. This board contains an STM32F303VCT6 microcontroller. + This microcontroller has: + - A Cortex-M4F core that includes a single precision FPU + - 256 KiB of Flash located at address 0x0800_0000. + - 40 KiB of RAM located at address 0x2000_0000. (There's another RAM + region but for simplicity we'll ignore it). +], +de: [ + In diesem Abschnitt verwenden wir unsere Referenzhardware, die + STM32F3DISCOVERY. Diese Platine enthält einen Mikrocontroller + STM32F303VCT6. Dieser Mikrocontroller verfügt über: + - Ein Cortex-M4F-Kern, der eine einzelne Präzisions-FPU enthält + - 256 KiB Flash befinden sich an der Adresse 0x0800_0000. + - 440 KiB RAM an der Adresse 0x2000_0000. (Es gibt noch eine weitere + RAM-Region, aber der Einfachheit halber ignorieren wir das). +], +ja: [ + このセクションでは、私たちのリファレンスハードウェアであるSTM32F3DISCOVERYを使用します。 + このボードは、STM32F303VCT6マイクロコントローラを1つ搭載しています。このマイクロコントローラは以下のものを持っています。 + - 単精度FPUを含むCortex-M4Fコアが1つ + - 0x0800_0000番地に配置された256KiBのフラッシュメモリ + - 0x2000_0000番地に配置された40KiBのRAM。(別のRAM領域もありますが、説明の簡単化のため、取り扱 +], +zh: [ + 这部分,要使用我们的参考硬件,STM32F3DISCOVERY。这个板子包含一个STM32F303VCT6微控制器。这个微控制器拥有: + - 一个Cortex-M4F核心,它包含一个单精度FPU。 + - 位于 0x0800_0000 地址的256KiB的Flash。 + - 位于 0x2000_0000 地址的40KiB的RAM。(这里还有其它的RAM区域,但是为了方便起见,我们将忽略它)。 +])) + += #tr(( + en: [Configuring], + de: [Konfigurieren], + ja: [設定], + zh: [配置], +)) + +#tr(( +en: [ + We'll start from scratch with a fresh template instance. Refer to the + #link()[previous section on QEMU] for a refresher on how to do this without `cargo-generate`. +], +de: [ + Wir beginnen bei Null mit einer neuen Vorlageninstanz. Zur Auffrischung + siehe #link()[vorheriger Abschnitt zu QEMU], wie man das ohne `cargo-generate` macht. +], +ja: [ + テンプレートの新しいインスタンスを使って、スクラッチから書いていきましょう。 + `cargo-generate`を使用しない方法については、#link()[前セクションのQEMU]を参照して下さい。 +], +zh: [ + 我们将使用一个新的模板实例从零开始。对于新手,请参考#link()[先前的QEMU]章节,了解如何在没有`cargo-generate`的情况下完成配置。 +])) + +```text +$ cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart + Project Name: app + Creating project called `app`... + Done! New project created /tmp/app + +$ cd app +``` + +#tr(( +en: [ + Step number one is to set a default compilation target in `.cargo/config.toml`. +], +de: [ + Schritt Nummer eins besteht darin, ein Standardkompilierungsziel in + `.cargo/config.toml` festzulegen. +], +ja: [ + 第一ステップは、`.cargo/config`にデフォルトコンパイルターゲットを設定することです。 +], +zh: [ + 第一步是在`.cargo/config.toml`中设置一个默认编译目标。 +])) + +```console +tail -n5 .cargo/config.toml +``` + +#let _and_ = ts(( + en: " and ", + ja: "および" +), default: " and ") +#raw(block: true, lang: "toml", +"# " + ts(( + en: "Pick ONE of these compilation targets", + de: "Waehlen Sie EINES von diesen Kompilierungszielen aus", + ja: "以下のコンパイルターゲットから1つを選びます" + )) + " +# target = \"thumbv6m-none-eabi\" # Cortex-M0"+_and_+"Cortex-M0+ +# target = \"thumbv7m-none-eabi\" # Cortex-M3 +# target = \"thumbv7em-none-eabi\" # Cortex-M4"+_and_+"Cortex-M7 (no FPU) +target = \"thumbv7em-none-eabihf\" # Cortex-M4F"+_and_+"Cortex-M7F (with FPU) +") + +#tr(( +en: [ + We'll use `thumbv7em-none-eabihf` as that covers the Cortex-M4F core. +], +de: [ + Wir verwenden `thumbv7em-none-eabihf`, da es den Cortex-M4F-Kern abdeckt. +], +ja: [ + Cortex-M4Fコアを対象とするものとして、`thumbv7em-none-eabihf`を使います。 +], +zh: [ + 我们将使用 `thumbv7em-none-eabihf`,因为它包括了Cortex-M4F内核. +])) + +#quote(block: true, tr(( +en: [ + *NOTE*: As you may remember from the previous chapter, we have to + install all targets and this is a new one. So don't forget to run the + installation process `rustup target add thumbv7em-none-eabihf` for + this target. +], +de: [ + *HINWEIS*: Wie Sie sich vielleicht aus dem vorherigen + Kapitel erinnern, müssen wir alle Ziele installieren, dies ist ein + neues Ziel. Vergessen Sie also nicht, die Installationsprozess + `rustup target add thumbv7em-none-eabihf` für dieses Ziel auszuführen. +], +zh: [ + *注意*:你可能还记得先前的章节,我们必须要安装所有的目标平台,这个平台是一个新的. + 所以,不要忘了为这个平台运行安装步骤 + `rustup target add thumbv7em-none-eabihf` . +]))) + +#tr(( +en: [ + The second step is to enter the memory region information into the `memory.x` file. +], +de: [ + Der zweite Schritt besteht darin, die Speicherbereichsinformationen in die Datei `memory.x` einzugeben +], +ja: [ + 第二ステップは、`memory.x`ファイルにメモリ領域の情報を入力することです。 +], +zh: [ + 第二步是将存储区域信息(memory region information)输入`memory.x`。 +])) + +```text +$ cat memory.x +/* Linker script for the STM32F303VCT6 */ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + FLASH : ORIGIN = 0x08000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 40K +} +``` + +#quote(block: true, tr(( +en: [ + *NOTE*: If you for some reason changed the `memory.x` file after + you had made the first build of a specific build target, then do + `cargo clean` before `cargo build`, because `cargo build` may not track + updates of `memory.x`. +], +de: [ + *NOTE*: Wenn Sie aus irgendeinem Grund die Datei `memory.x` + geändert haben, nachdem Sie den ersten Build für ein bestimmtes + Build-Ziel erstellt haben, dann führen Sie `cargo clean` vor + `cargo build` aus, da `cargo build` keine Änderungen von `memory.x` verfolgt. +], +zh: [ + *注意*:如果你因为某些理由,在对某个编译目标首次编译后,改变了`memory.x`文件,需要在`cargo build`之前执行`cargo clean`。因为`cargo build`可能不会跟踪`memory.x`的更新。 +]))) + +#tr(( +en: [ + We'll start with the hello example again, but first we have to make a + small change. +], +de: [ + Wir beginnen noch einmal mit dem Hallo-Beispiel, aber zuerst müssen wir + eine kleine Änderung vornehmen. +], +zh: [ + 我们将再次使用hello示例作为开始,但是首先我们必须做一个小改变。 +])) + +#tr(( +en: [ + In `examples/hello.rs`, make sure the `debug::exit()` call is commented + out or removed. It is used only for running in QEMU. +], +de: [ + Stellen Sie in `examples/hello.rs`sicher, daß `debug::exit()` auskommentiert + oder entfernt wurde. Es wird nur zum Ausführen in QEMU verwendet. +], +ja: [ + `debug::exit()`の呼び出しが、コメントアウトされているか削除されていることを確認して下さい。 + これは、QEMUで実行する時のみ、使用します。 +], +zh: [ + 在`examples/hello.rs`中,确保`debug::exit()`调用被注释掉了或者移除掉了。它只能用于在QEMU中运行的情况。 +])) + +#raw(block: true, lang: "rust", +"#[entry] +fn main() -> ! { + hprintln!(\"Hello, world!\").unwrap(); + + // " + ts(( + en: "exit QEMU + // NOTE do not run this on hardware; it can corrupt OpenOCD state + // debug::exit(debug::EXIT_SUCCESS);", + de: "exit QEMU + // HINWEIS: Fuehren Sie dies nicht auf der Hardware aus; es kann den + // OpenOCD-Zustand beschaedigen. + // debug::exit(debug::EXIT_SUCCESS);", + ja: "QEMUを終了する + // 注記、ハードウェア上で実行しないで下さい。OpenOCDの状態を破壊する可能性があります。 + // debug::exit(debug::EXIT_SUCCESS);", + zh: "退出 QEMU + // 注意 不要在硬件上运行这个;它会打破OpenOCD的状态", + )) + " + + loop {} +} +") + +#tr(( +en: [ + You can now cross compile programs using `cargo build` and inspect the + binaries using `cargo-binutils` as you did before. The `cortex-m-rt` + crate handles all the magic required to get your chip running, as + helpfully, pretty much all Cortex-M CPUs boot in the same fashion. +], +de: [ + Sie können nun Programme mittels `cargo build` cross-kompilieren und die + Binärdateien mit `cargo-binutils` untersuchen, genau wie zuvor. Das + `cortex-m-rt`-Crate übernimmt die gesamte für den Betrieb des Chips + erforderliche „Magie", da erfreulicherweise so gut wie alle + Cortex-M-CPUs auf die gleiche Weise booten. +], +ja: [ + これまでやってきた通り、`cargo build`でプログラムをクロスコンパイルし、 + `cargo-binutils`でバイナリを調べることができます。 + `cortex-m-rt`クレートは、チップを動作させるために必要な、全てのおまじないを処理します。 + 便利なことに、ほとんど全てのCortex-M CPUが同じ方法で起動します。 +], +zh: [ + 你可以像你之前做的一样,使用`cargo build`检查编译程序,使用`cargo-binutils`观察二进制项。`cortex-m-rt`库可以处理所有让芯片运行起来所需的魔法,几乎所有的Cortex-M + CPUs都按同样的方式启动。 +])) + +```console +cargo build --example hello +``` + += #tr(( + en: [Debugging], + de: [Fehlerbehebung (Debugging)], + ja: [デバッグ], + zh: [调试], +)) + +#let url_dn = "https://github.com/rust-embedded/debugonomicon" +#tr(( +en: [ + Debugging will look a bit different. In fact, the first steps can look + different depending on the target device. In this section we'll show the + steps required to debug a program running on the STM32F3DISCOVERY. This + is meant to serve as a reference; for device specific information about + debugging check out #link(url_dn)[the Debugonomicon]. +], +de: [ + Das Debugging gestaltet sich etwas anders. Tatsächlich können sich + bereits die ersten Schritte je nach Zielgerät unterscheiden. In diesem + Abschnitt zeigen wir die Schritte, die zum Debuggen eines auf dem + STM32F3DISCOVERY laufenden Programms erforderlich sind. Dies soll als + Referenz dienen; für gerätespezifische Informationen zum Debugging + konsultieren Sie bitte #link(url_dn)[das Debugonomicon]. +], +ja: [ + デバッグ方法は少し違います。実際、最初のステップは、ターゲットデバイスによって異なります。 + このセクションでは、STM32F3DISCOVERY上で実行しているプログラムをデバッグするために必要となる手順を説明します。 + これは、参考の役目を果たします。デバイス固有のデバッグ情報は、 + #link(url_dn)[the Debugonomicon]を参照して下さい。 +], +zh: [ + 调试会看起来有点不一样。事实上,取决于不同的目标设备,第一步可能看起来不一样。在这个章节里,我们将展示,调试一个在STM32F3DISCOVERY上运行的程序,所需要的步骤。这作为一个参考。关于调试有关的设备特定的信息,可以看#link(url_dn)[the Debugonomicon]。 +])) + +#tr(( +en: [ + As before we'll do remote debugging and the client will be a GDB + process. This time, however, the server will be OpenOCD. +], +de: [ + Wie zuvor führen wir Remote-Debugging durch, wobei der Client ein + GDB-Prozess ist. Diesmal ist der Server jedoch OpenOCD. +], +ja: [ + 以前と同様に、リモートデバッグを行います。クライアントがGDBプロセスであることも同様です。 + しかし、今回、サーバはOpenOCDになります。 +], +zh: [ + 像之前一样,我们将进行远程调试,客户端将是一个GDB进程。不同的是,OpenOCD将是服务器。 +])) + +#tr(( +en: [ + As done during the #link()[verify] section + connect the discovery board to your laptop / PC and check that the + ST-LINK header is populated. +], +de: [ + Verbinden Sie, wie im Abschnitt + "#link()[Die Installation überprüfen]" + beschrieben, das Discovery Board mit Ihrem Laptop/PC und prüfen Sie, ob + der ST-LINK-Header ausgefüllt ist. +], +ja: [ + #link()[インストールの確認]セクションでやったように、ノートPCまたはPCをdiscoveryボードに接続し、 + ST-LINKヘッダが設定されていることを確認して下さい。 +], +zh: [ + 像是在#link()[安装验证]中做的那样,把你的笔记本/个人电脑和discovery开发板连接起来,检查ST-LINK的短路帽是否被安装了。 +])) + +#tr(( +en: [ + On a terminal run `openocd` to connect to the ST-LINK on the discovery + board. Run this command from the root of the template; `openocd` will + pick up the `openocd.cfg` file which indicates which interface file and + target file to use. +], +de: [ + Führen Sie in einem Terminal `openocd` aus, um eine Verbindung zum + ST-LINK auf dem Discovery-Board herzustellen. Führen Sie diesen Befehl + im Stammverzeichnis der Vorlage aus; `openocd` greift dabei auf die + Datei `openocd.cfg` zu, in der festgelegt ist, welche Schnittstellen- + und Zieldateien verwendet werden sollen. +], +ja: [ + discoveryボードのST-LINKに接続するために、端末で`openocd`を実行して下さい。 + このコマンドは、テンプレートプロジェクトのルートディレクトリから実行して下さい。 + `openocd`は、どのインタフェースファイルとターゲットファイルを使うか、が記述されている`openocd.cfg`ファイルを見つけます。 +], +zh: [ + 在一个终端上运行 `openocd` 连接到你的开发板上的 ST-LINK + 。从模板的根目录运行这个命令;`openocd` 将会选择 `openocd.cfg` + 文件,它指出了所使用的接口文件(interface file)和目标文件(target file)。 +])) + +```console +cat openocd.cfg +``` + +#raw(block: true, lang: "text", +"# " + ts(( + en: "Sample OpenOCD configuration for the STM32F3DISCOVERY development board + +# Depending on the hardware revision you got you'll have to pick ONE of these +# interfaces. At any time only one interface should be commented out. + +# Revision C (newer revision)", + de: "Beispiel-OpenOCD-Konfiguration für das STM32F3DISCOVERY-Entwicklungsboard + +# Je nach der vorliegenden Hardware-Revision muessen Sie eine dieser +# Schnittstellen auswaehlen. Es sollte jeweils nur eine Schnittstelle +# auskommentiert sein. + +# Revision C (neuere Revision)", + ja: "STM32F3DISCOVERY開発ボード用のOpenOCD設定サンプル + +# 持っているハードウェアのリビジョンに応じて、これらのインタフェースのうち、1つを選んで下さい。 +# 常に、1つのインタフェースがコメントアウトされているべきです。 + +# リビジョンC (新しいリビジョン)", + )) + " +source [find interface/stlink.cfg] + +# " + ts(( + en: "Revision A and B (older revisions)", + de: "Revision A and B (aeltere Revisionen)", + ja: "リビジョンAとB(古いリビジョン)", + )) + " +# source [find interface/stlink-v2.cfg] + +source [find target/stm32f3x.cfg] +") + +#quote(block: true, tr(( +en: [ + *NOTE*: If you found out that you have an older revision of the + discovery board during the #link()[verify] + section then you should modify the `openocd.cfg` file at this point to + use `interface/stlink-v2.cfg`. +], +de: [ + *HINWEIS* Falls Sie im Abschnitt + "#link()[Die Installation überprüfen]" + feststellen, dass Sie eine ältere Revision des Discovery-Boards + besitzen, sollten Sie an dieser Stelle die Datei `openocd.cfg` so + anpassen, dass `interface/stlink-v2.cfg` verwendet wird. +], +ja: [ + *注記* + #link()[インストールの確認]セクションで、古いバージョンのdiscoveryボードを持っていることが判明している場合、 + `interface/stlink-v2.cfg`を使うように`openocd.cfg`ファイルを修正する必要があります。 +], +zh: [ + *注意* + 如果你在#link()[安装验证]章节中,发现你的discovery开发板是一个更旧的版本,那么你应该修改你的 + `openocd.cfg` 文件,注释掉 `interface/stlink.cfg`,让它去使用 + `interface/stlink-v2.cfg` 。 +]))) + +```text +$ openocd +Open On-Chip Debugger 0.10.0 +Licensed under GNU GPL v2 +For bug reports, read + http://openocd.org/doc/doxygen/bugs.html +Info : auto-selecting first available session transport "hla_swd". To override use 'transport select '. +adapter speed: 1000 kHz +adapter_nsrst_delay: 100 +Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD +none separate +Info : Unable to match requested speed 1000 kHz, using 950 kHz +Info : Unable to match requested speed 1000 kHz, using 950 kHz +Info : clock speed 950 kHz +Info : STLINK v2 JTAG v27 API v2 SWIM v15 VID 0x0483 PID 0x374B +Info : using stlink api v2 +Info : Target voltage: 2.913879 +Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints +``` + +#tr(( +en: [ + On another terminal run GDB, also from the root of the template. +], +de: [ + Starten Sie in einem weiteren Terminal GDB, ebenfalls vom + Stammverzeichnis des Templates aus. +], +ja: [ + 別の端末で、GDBを実行します。こちらも、テンプレートプロジェクトのルートディレクトから実行して下さい。 +])) + +```text +gdb-multiarch -q target/thumbv7em-none-eabihf/debug/examples/hello +``` + +#tr(( +en: [ + *NOTE*: like before you might need another version of gdb instead + of `gdb-multiarch` depending on which one you installed in the + installation chapter. This could also be `arm-none-eabi-gdb` or just `gdb`. +], +de: [ + *HINWEIS*: Wie bereits erwähnt, benötigen Sie möglicherweise + anstelle von `gdb-multiarch` eine andere Version von gdb, je nachdem, + welche Version Sie im Installationskapitel installiert haben. Dies + könnte beispielsweise `arm-none-eabi-gdb` oder einfach `gdb` sein. +], +zh: [ + *注意*: + 像之前一样,你可能需要另一个版本的gdb而不是`gdb-multiarch`,取决于你在之前的章节安装了什么工具。这也可能使用的是`arm-none-eabi-gdb`或者只是`gdb` +])) + +#tr(( +en: [ + Next connect GDB to OpenOCD, which is waiting for a TCP connection on port 3333. +], +de: [ + Verbinden Sie nun GDB mit OpenOCD, das auf eine TCP-Verbindung an Port 3333 wartet. +], +ja: [ + 次に、TCP 3333ポートで接続待ちしているOpenOCDに、GDBを接続します。 +], +zh: [ + 接下来把GDB连接到OpenOCD,它正在等待一个在端口3333上的TCP链接。 +])) + +```console +(gdb) target remote :3333 +Remote debugging using :3333 +0x00000000 in ?? () +``` + +#tr(( +en: [ + Now proceed to _flash_ (load) the program onto the microcontroller + using the `load` command. +], +de: [ + Fahren Sie nun damit fort, das Programm mithilfe des Befehls `load` auf + den Mikrocontroller zu _flashen_ (zu laden). +], +ja: [ + それでは、`load`コマンドを使って、マイクロコントローラにプログラムを_書き込んで_下さい。 +], +zh: [ + 接下来使用`load`命令,继续 _flash_(加载) 程序到微控制器上。 +])) + +```console +(gdb) load +Loading section .vector_table, size 0x400 lma 0x8000000 +Loading section .text, size 0x1518 lma 0x8000400 +Loading section .rodata, size 0x414 lma 0x8001918 +Start address 0x08000400, load size 7468 +Transfer rate: 13 KB/sec, 2489 bytes/write. +``` + +#tr(( +en: [ + The program is now loaded. This program uses semihosting so before we do + any semihosting call we have to tell OpenOCD to enable semihosting. You + can send commands to OpenOCD using the `monitor` command. +], +de: [ + Das Programm ist nun geladen. Da dieses Programm Semihosting verwendet, + müssen wir OpenOCD anweisen, Semihosting zu aktivieren, bevor wir einen + entsprechenden Aufruf tätigen. Befehle können mithilfe des Befehls + `monitor` an OpenOCD gesendet werden. +], +ja: [ + プログラムがロードされました。このプログラムはセミホスティングを使用します。そこで、 + セミホスティングを呼び出して何かを行う前に、OpenOCDにセミホスティングを有効にするように、 + 指示する必要があります。 +], +zh: [ + 程序现在被加载了。这个程序使用半主机模式,因此在我们调用半主机模式之前,我们必须告诉OpenOCD使能半主机。你可以使用 + `monitor` 命令,发送命令给OpenOCD 。 +])) + +```console +(gdb) monitor arm semihosting enable +semihosting is enabled +``` + +#quote(block: true, tr(( +en: [ + You can see all the OpenOCD commands by invoking the `monitor help` command. +], +de: [ + Sie können sich alle OpenOCD-Befehle anzeigen lassen, indem Sie den + Befehl `monitor help` aufrufen. +], +ja: [ + `monitor help`コマンドを実行することで、全てのOpenOCDコマンドを見ることができます。 +], +zh: [ + 通过调用 `monitor help` 命令,你能看到所有的OpenOCD命令。 +]))) + +#tr(( +en: [ + Like before we can skip all the way to `main` using a breakpoint and the + `continue` command. +], +de: [ + Wie zuvor können wir mithilfe eines Breakpoints und des Befehls + `continue` direkt zu `main` springen. +], +ja: [ + 以前のように、ブレイクポイントと`continue`コマンドを使用することで、`main`までスキップすることができます。 +], +zh: [ + 像我们之前一样,使用一个断点和 `continue` 命令我们可以跳过所有的步骤到 + `main` 。 +])) + +```console +(gdb) break main +Breakpoint 1 at 0x8000490: file examples/hello.rs, line 11. +Note: automatically using hardware breakpoints for read-only addresses. + +(gdb) continue +Continuing. + +Breakpoint 1, hello::__cortex_m_rt_main_trampoline () at examples/hello.rs:11 +11 #[entry] +``` + +#quote(block: true, tr(( +en: [ + *NOTE* If GDB blocks the terminal instead of hitting the + breakpoint after you issue the `continue` command above, you might want + to double check that the memory region information in the `memory.x` + file is correctly set up for your device (both the starts _and_ lengths). +], +de: [ + *HINWEIS* Falls GDB das Terminal blockiert, anstatt am Haltepunkt + (Breakpoint) anzuhalten, nachdem Sie den oben genannten Befehl + `continue` eingegeben haben, sollten Sie überprüfen, ob die Angaben zum + Speicherbereich in der Datei `memory.x` für Ihr Gerät korrekt + konfiguriert sind (sowohl die Startadressen _als auch_ die Längen). +], +zh: [ + *注意* + 如果在你使用了上面的`continue`命令后,GDB阻塞住了终端而不是停在了断点处,你可能需要检查下`memory.x`文件中的存储分区的信息,对于你的设备来说是否被正确的设置了起始位置*和*大小 +。 +]))) + +#tr(( +en: [ + Step into the main function with `step`. +], +de: [ + Springen Sie mit `step` in die main-Funktion. +], +zh: [ + 使用`step`步进main函数里。 +])) + +```console +(gdb) step +halted: PC: 0x08000496 +hello::__cortex_m_rt_main () at examples/hello.rs:13 +13 hprintln!("Hello, world!").unwrap(); +``` + +#tr(( +en: [ + After advancing the program with `next` you should see "Hello, world!" + printed on the OpenOCD console, among other stuff. +], +de: [ + Nachdem Sie das Programm mit `next` weitergeführt haben, sollten Sie + unter anderem „Hello, world!" auf der OpenOCD-Konsole ausgegeben sehen. +], +ja: [ + #todoupd("ja") + この時点で、OpenOCDコンソールに、他のものと入り混じって「Hello, + world!」と表示されるはずです。 +], +zh: [ + 在使用了`next`让函数继续执行之后,你应该看到 "Hello, world!" + 被打印到了OpenOCD控制台上。 +])) + +```console +$ openocd +(..) +Info : halted: PC: 0x08000502 +Hello, world! +Info : halted: PC: 0x080004ac +Info : halted: PC: 0x080004ae +Info : halted: PC: 0x080004b0 +Info : halted: PC: 0x080004b4 +Info : halted: PC: 0x080004b8 +Info : halted: PC: 0x080004bc +``` + +#tr(( +en: [ + The message is only displayed once as the program is about to enter the + infinite loop defined in line 19: `loop {}` +], +de: [ + Die Meldung wird nur einmal angezeigt, kurz bevor das Programm in die in + Zeile 19 definierte Endlosschleife eintritt: `loop {}` +], +zh: [ + 消息只打印一次,然后进入定义在19行的无限循环中: `loop {}` +])) + +#tr(( +en: [ + You can now exit GDB using the `quit` command. +], +de: [ + Sie können GDB nun mit dem Befehl `quit` beenden. +], +zh: [ + 使用 `quit` 命令,你现在可以退出 GDB 了。 +])) + +```console +(gdb) quit +A debugging session is active. + + Inferior 1 [Remote target] will be detached. + +Quit anyway? (y or n) +``` + +#tr(( +en: [ + Debugging now requires a few more steps so we have packed all those + steps into a single GDB script named `openocd.gdb`. The file was created + during the `cargo generate` step, and should work without any + modifications. Let's have a peek: +], +de: [ + Das Debugging erfordert nun einige zusätzliche Schritte; daher haben wir + all diese Schritte in einem einzigen GDB-Skript namens `openocd.gdb` + zusammengefasst. Die Datei wurde während des Schritts `cargo generate` + erstellt und sollte ohne Änderungen funktionieren. Werfen wir einen Blick darauf: +], +zh: [ + 现在调试比之前多了点步骤,因此我们要把所有步骤打包进一个名为 + `openocd.gdb` 的GDB脚本中。这个文件在 `cargo generate` + 步骤中被生成,因此不需要任何修改了。让我们看一下: +])) + +```console +cat openocd.gdb +``` + +```text +target extended-remote :3333 + +# print demangled symbols +set print asm-demangle on + +# detect unhandled exceptions, hard faults and panics +break DefaultHandler +break HardFault +break rust_begin_unwind + +monitor arm semihosting enable + +load + +# start the process but immediately halt the processor +stepi +``` +#let cmd_gdb_hello = ` -x openocd.gdb target/thumbv7em-none-eabihf/debug/examples/hello` +#tr(( +en: [ + Now running #cmd_gdb_hello + will immediately connect GDB to OpenOCD, enable semihosting, load the + program and start the process. +], +de: [ + Wenn Sie nun den Befehl #cmd_gdb_hello + ausführen, verbindet sich GDB sofort mit OpenOCD, aktiviert Semihosting, + lädt das Programm und startet den Prozess. +], +ja: [ + #cmd_gdb_hello;を実行することで、GDBはすぐにOpenOCDに接続し、 + セミホスティングを有効化し、プログラムをロードした上で、プロセスを開始します。 +], +zh: [ + 现在运行 #cmd_gdb_hello + 将会立即把GDB和OpenOCD连接起来,使能半主机,加载程序和启动进程。 +])) + +#tr(( +en: [ + Alternatively, you can turn ` -x openocd.gdb` into a custom runner + to make `cargo run` build a program _and_ start a GDB session. This + runner is included in `.cargo/config.toml` but it's commented out. +], +de: [ + Alternativ können Sie ` -x openocd.gdb` als benutzerdefinierten + Runner einrichten, sodass `cargo run` das Programm baut _und_ eine + GDB-Sitzung startet. Dieser Runner ist bereits in der Datei + `.cargo/config.toml` enthalten, jedoch auskommentiert. +], +ja: [ + 別の方法として、` -x openocd.gdb`をカスタムランナーにして、`cargo run`でプログラムをビルドし、 + _さらに_GDBセッションを開始することもできます。このランナーは、`.cargo/config`に含まれていますが、 + コメントアウトされています。 +], +zh: [ + 另外,你能将 ` -x openocd.gdb` 放进一个自定义的 runner 中,使 + `cargo run` 能编译程序并启动一个GDB会话。这个 runner 在 + `.cargo/config.toml` 中,但是它被注释掉了。 +])) + +```console +head -n10 .cargo/config.toml +``` + +#raw(block: true, lang: "toml", +"[target.thumbv7m-none-eabi] +# " + ts(( + en: "uncomment this to make `cargo run` execute programs on QEMU", + de: "Dies auskommentieren, damit `cargo run` Programme auf QEMU ausfuehrt.", + ja: "ここのコメントアウトを外すと、`cargo run`はQEMUでプログラムを実行します", + zh: "uncomment this to make `cargo run` execute programs on QEMU", + )) + " +# runner = \"qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel\" + +[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))'] +# " + ts(( + en: "uncomment ONE of these three option to make `cargo run` start a GDB session +# which option to pick depends on your system", + de: "Heben Sie die Auskommentierung einer dieser drei Optionen auf, damit +# `cargo run` eine GDB-Sitzung startet. +# Welche Option Sie waehlen sollten, haengt von Ihrem System ab.", + ja: "3つの選択肢のうち、1つのコメントアウトを外すと、`cargo run`はGDBセッションを開始します。 +# どの選択肢を使うか、は対象システムによって異なります。", + zh: "uncomment ONE of these three option to make `cargo run` start a GDB session +# which option to pick depends on your system", + )) + " +runner = \"arm-none-eabi-gdb -x openocd.gdb\" +# runner = \"gdb-multiarch -x openocd.gdb\" +# runner = \"gdb -x openocd.gdb\" +") + +```text +$ cargo run --example hello +(..) +Loading section .vector_table, size 0x400 lma 0x8000000 +Loading section .text, size 0x1e70 lma 0x8000400 +Loading section .rodata, size 0x61c lma 0x8002270 +Start address 0x800144e, load size 10380 +Transfer rate: 17 KB/sec, 3460 bytes/write. +(gdb) +``` diff --git a/typ/start/index.typ b/typ/start/index.typ new file mode 100644 index 00000000..a6e039e0 --- /dev/null +++ b/typ/start/index.typ @@ -0,0 +1,38 @@ +#import "../config.typ": * + +#h1((en: [Getting Started], + de: [Erste Schritte], + ja: [入門], + zh: [开始], +)) + + +#let ln_f3 = link("http://www.st.com/en/evaluation-tools/stm32f3discovery.html")[STM32F3DISCOVERY] +#tr(( +en: [ + In this section we'll walk you through the process of writing, building, + flashing and debugging embedded programs. You will be able to try most + of the examples without any special hardware as we will show you the + basics using QEMU, a popular open-source hardware emulator. The only + section where hardware is required is, naturally enough, the + #link()[Hardware] section, where we use OpenOCD to + program an #ln_f3. +], +de: [ + In diesem Abschnitt führen wir Sie Schritt für Schritt durch den Prozess + des Schreibens, Kompilierens, Flashen und Debuggens von + Embedded-Programmen. Sie können die meisten der Beispiele ohne spezielle + Hardware ausprobieren, da wir Ihnen die Grundlagen mithilfe von QEMU, + einem beliebten Open-Source-Hardware-Emulator, vermitteln. Der einzige + Abschnitt, in dem Hardware erforderlich ist, ist natürlich der Abschnitt + #link()[Hardware], wo wir OpenOCD verwenden, um ein + #ln_f3 zu programmieren. +], +ja: [ + このセクションでは、組込みプログラムを書いて、ビルドして、フラッシュに書き込み、デバッグする、という一連のプロセスを説明します。 + ほとんどの例を特別なハードウェアなしで試すことができます。有名なオープンソースハードウェアエミュレータであるQEMUを使うからです。 + ハードウェアが必要となる唯一のセクションは、当然ながら、OpenOCDを使って#ln_f3;にプログラムする#link()[Hardware]セクションです。 +], +zh: [ + 在这部分里,你将会经历编写,编译,烧录和调试嵌入式程序。大多数的例子都不需要特定的硬件就可以试试,因为我们将要向你展示一个开源硬件仿真器,QEMU的基本使用。唯一需要硬件的部分,那就是,#link()[硬件]那一章,我们会使用OpenOCD去编程一个#ln_f3。 +])) \ No newline at end of file diff --git a/typ/start/interrupts.typ b/typ/start/interrupts.typ new file mode 100644 index 00000000..9b90475a --- /dev/null +++ b/typ/start/interrupts.typ @@ -0,0 +1,247 @@ +#import "../config.typ": * + +#h1((en: [Interrupts], + de: [Interrupts], + ja: [割り込み], + zh: [中断], +), offset: whole) + +#tr(( +en: [ + Interrupts differ from exceptions in a variety of ways but their + operation and use is largely similar and they are also handled by the + same interrupt controller. Whereas exceptions are defined by the + Cortex-M architecture, interrupts are always vendor (and often even + chip) specific implementations, both in naming and functionality. +], +de: [ + Interrupts unterscheiden sich in vielerlei Hinsicht von Exceptions; ihre + Funktionsweise und Verwendung sind jedoch weitgehend ähnlich, und sie + werden zudem von demselben Interrupt-Controller verwaltet. Während + Exceptions durch die Cortex-M-Architektur definiert sind, handelt es + sich bei Interrupts -- sowohl hinsichtlich der Benennung als auch der + Funktionalität -- stets um herstellerspezifische (und oft sogar + chip-spezifische) Implementierungen. +], +ja: [ + 割り込みは様々な点で例外と違いますが、その動作と使用方法は、ほとんど同じで、同じ割り込みコントローラによって処理されます。 + 例外がCortex-Mアーキテクチャで定義されているのに対し、割り込みは、命名と機能との両方において、常にベンダ(もっと言うとチップ)固有の実装です。 +], +zh: [ + 虽然中断和异常在很多方面都不一样,但是它们的操作和使用几乎是一样的,且它们也能被同一个中断控制器处理。然而异常是由Cortex-M微架构定义的,中断在命名和功能上总是由特定厂商(经常甚至是芯片)实现的。 +])) + +#tr(( +en: [ + Interrupts do allow for a lot of flexibility which needs to be accounted + for when attempting to use them in an advanced way. We will not cover + those uses in this book, however it is a good idea to keep the following + in mind: + - Interrupts have programmable priorities which determine their + handlers' execution order + - Interrupts can nest and preempt, i.e.~execution of an interrupt + handler might be interrupted by another higher-priority interrupt + - In general the reason causing the interrupt to trigger needs to be + cleared to prevent re-entering the interrupt handler endlessly +], +de: [ + Interrupts bieten ein hohes Maß an Flexibilität, das bei einer + fortgeschrittenen Nutzung berücksichtigt werden muss. Wir werden diese + Anwendungsfälle in diesem Buch zwar nicht behandeln, dennoch ist es + ratsam, Folgendes zu beachten: + - Interrupts verfügen über programmierbare Prioritäten, die die + Ausführungsreihenfolge ihrer Behandlungsroutinen bestimmen. + - Interrupts können geschachtelt werden und einander unterbrechen + (Preemption); das heißt, die Ausführung eines Interrupt-Handlers kann + durch einen anderen Interrupt mit höherer Priorität unterbrochen werden. + - Im Allgemeinen muss die Ursache für die Auslösung des Interrupts + beseitigt werden, um zu verhindern, dass der Interrupt-Handler endlos + erneut aufgerufen wird. +], +ja: [ + 割り込みは、高度な使い方をしようとする時に必要とされる様々な柔軟性を考慮に入れています。 + 本書では、そのような高度な使い方は対象外です。しかし、次の点に留意することをお勧めします。 + - 割り込みは、ハンドラの実行順序を決めるプログラム可能な優先度を持ちます。 + - 割り込みは、ネストとプリエンプションが可能です。つまり、割り込みハンドラの実行は、より優先度の高い割り込みに割り込まれる場合があります。 + - 通常、割り込み要因は、割り込みハンドラが無限に再呼び出しされないようにするため、クリアされる必要があります。 +], +zh: [ + 中断提供了更多的灵活性,当尝试用一种高级的方法使用它们时,我们需要对这种灵活性进行解释。但我们将不会在这本书里涵盖这些内容,最好把下面的东西记在心里: + - 中断有可以编程的优先级,其决定了它们的处理函数的执行顺序。 + - 中断能嵌套且抢占,i.e.~一个中断处理函数的执行可以被其它更高优先级的中断打断。 + - 通常需要清除掉导致中断被触发的原因,避免无限地再次进入中断处理函数。 +])) + +#tr(( +en: [ + The general initialization steps at runtime are always the same: + - Setup the peripheral(s) to generate interrupts requests at the desired occasions + - Set the desired priority of the interrupt handler in the interrupt controller + - Enable the interrupt handler in the interrupt controller +], +de: [ + Die allgemeinen Initialisierungsschritte zur Laufzeit sind immer gleich: + - Konfigurieren Sie die Peripheriekomponente(n) so, dass + Interrupt-Anforderungen zu den gewünschten Zeitpunkten ausgelöst werden. + - Legen Sie die gewünschte Priorität des Interrupt-Handlers im + Interrupt-Controller fest. + - Aktivieren Sie den Interrupt-Handler im Interrupt-Controller. +], +ja: [ + ランタイムでの一般的な初期化手順は、常に同じです。 + - 必要な時に割り込み要求を起こすように、ペリフェラルを設定します + - 割り込みコントローラで割り込みハンドラの優先度をセットします + - 割り込みコントローラで割り込みハンドラを有効化します +], +zh: [ + 运行时的初始化步骤总是相同的: + - 设置外设在想要的事件发生时产生中断请求 + - 在中断控制器中设置需要的中断处理函数的优先级 + - 在中断控制器中使能中断处理函数 +])) + +#let ln_int = link("https://docs.rs/cortex-m-rt-macros/0.1.5/cortex_m_rt_macros/attr.interrupt.html")[`interrupt`] +#tr(( +en: [ + Similarly to exceptions, the cortex-m-rt crate exposes an #ln_int + attribute for declaring interrupt handlers. However, this attribute is + only available when the device feature is enabled. That said, this + attribute is not intended to be used directly---doing so will result in + a compilation error. +], +de: [ + Ähnlich wie bei Exceptions stellt das `cortex-m-rt`-Crate ein + #ln_int;-Attribut zur Deklaration von Interrupt-Handlern bereit. + Dieses Attribut steht jedoch nur zur Verfügung, + wenn das Device-Feature aktiviert ist. Es ist + allerdings nicht für die direkte Verwendung vorgesehen; eine solche + würde zu einem Kompilierfehler führen. +], +ja: [ + 例外と同様に、例外ハンドラを宣言するために、`cortex-m-rt`クレートは、#ln_int;属性を提供しています。 + 利用可能な割り込み(そして割り込みハンドラテーブルでの配置)は、通常、`svd2rust`を使ってSVDから自動生成されます。 +], +zh: [ + #todoupd("zh") + 与异常相似,`cortex-m-rt` + crate提供了一个#ln_int;属性去声明中断处理函数。可用的中断(及它们在中断向量表中的位置)通常由`svd2rust`从一个SVD描述文件自动地生成。 +])) + +#tr(( +en: [ + Instead, you should use the re-exported version of the interrupt + attribute provided by the device crate (usually generated using + svd2rust). This ensures that the compiler can verify that the interrupt + actually exists on the target device. The list of available + interrupts---and their position in the interrupt vector table---is + typically auto-generated from an SVD file by svd2rust. +], +de: [ + Stattdessen sollten Sie die vom Device-Crate (das üblicherweise mit + `svd2rust` generiert wird) bereitgestellte, re-exportierte Version des + `interrupt`-Attributs verwenden. Dies stellt sicher, dass der Compiler + überprüfen kann, ob der Interrupt auf dem Zielgerät tatsächlich + existiert. Die Liste der verfügbaren Interrupts -- sowie deren Position + in der Interrupt-Vektortabelle -- wird typischerweise von `svd2rust` + automatisch aus einer SVD-Datei generiert. +])) + +#raw(block: true, lang: "rust", +"rust +use lm3s6965::interrupt; // " + ts(( + en: "Re-exported attribute from the device crate", + de: "Aus dem Device-Crate zurueck-exportiertes Attribut" + )) + " + +// " + ts(( + en: "Interrupt handler for the Timer2 interrupt", + de: "Interrupt-Handler fuer den Timer2-Interrupt", + ja: "タイマ2割り込みの割り込みハンドラ", + zh: "Timer2中断的中断处理函数", + )) + " +#[interrupt] +fn TIMER2A() { + // .. + // " + ts(( + en: "Clear reason for the generated interrupt request", + de: "Eindeutiger Grund fuer die generierte Interrupt-Anforderung", + ja: "発生した割り込み要求の原因をクリアします", + zh: "清除生成中断请求的原因", + )) + " +} +") + +#tr(( +en: [ + Interrupt handlers look like plain functions (except for the lack of + arguments) similar to exception handlers. However they can not be called + directly by other parts of the firmware due to the special calling + conventions. It is however possible to generate interrupt requests in + software to trigger a diversion to the interrupt handler. +], +de: [ + Interrupt-Handler ähneln -- abgesehen vom Fehlen von Argumenten -- + gewöhnlichen Funktionen, ganz wie Exception-Handler. Aufgrund spezieller + Aufrufkonventionen können sie jedoch nicht direkt von anderen Teilen der + Firmware aufgerufen werden. Es ist allerdings möglich, + Interrupt-Anforderungen per Software zu erzeugen, um einen Sprung zum + Interrupt-Handler auszulösen. +], +ja: [ + 割り込みハンドラは、通常の関数のように見え、例外ハンドラに似ています(引数がないことを除いて)。 + しかし、割り込みハンドラは、特別な呼び出し規約のため、ファームウェアの他の部分から直接呼び出すことができません。 + ソフトウェアで割り込み要求を起こし、割り込みハンドラへの転送を発生させることは可能です。 +], +zh: [ + 中断处理函数和异常处理函数一样看起来像是普通的函数(除了没有入参)。然而由于特殊的调用规定,它不能被固件的其它部分直接调用。然而,可以在软件中生成中断请求,转移到中断处理函数中。 +])) + +#tr(( +en: [ + Similar to exception handlers it is also possible to declare + `static mut` variables inside the interrupt handlers for _safe_ state keeping. +], +de: [ + Ähnlich wie bei Exception-Handlern ist es auch hier möglich, + `static mut`-Variablen innerhalb der Interrupt-Handler zu deklarieren, + um den Zustand auf _sichere_ Weise zu speichern. +], +ja: [ + 例外ハンドラと同様に、割り込みハンドラ内で`static mut`変数を宣言し、状態を_安全_に保持することができます。 +], +zh: [ + 与异常处理函数一样,也能在中断处理函数中声明`static mut`变量且保持 + _safe_ 状态。 +])) + +#raw(block: true, lang: "rust", +"#[interrupt] +fn TIMER2A() { + static mut COUNT: u32 = 0; + + // " + ts(( + en: "`COUNT` has type `&mut u32` and it's safe to use", + de: "`COUNT` hat den Typ `&mut u32` und ist sicher zu verwenden.", + ja: "`COUNT`は`&mut u32`の型を持っており、その使用は安全です", + zh: "`COUNT` 的类型是 `&mut u32` 且它用起来安全", + )) + " + *COUNT += 1; +} +") + +#tr(( +en: [ + For a more detailed description about the mechanisms demonstrated here + please refer to the #link()[exceptions section]. +], +de: [ + Für eine detailliertere Beschreibung der hier veranschaulichten + Mechanismen konsultieren Sie bitte den + #link()[Abschnitt zu Ausnahmen]. +], +ja: [ + ここで示した仕組みの詳細については、#link()[例外セクション]を参照して下さい。 +], +zh: [ + 关于这里所说的机制的更多细节描述,请参考#link()[异常章节]。 +])) diff --git a/typ/start/panicking.typ b/typ/start/panicking.typ new file mode 100644 index 00000000..f0c31b78 --- /dev/null +++ b/typ/start/panicking.typ @@ -0,0 +1,352 @@ +#import "../config.typ": * + +#h1((en: [Panicking], + de: [In Panik geraten], + ja: [パニック], + zh: [运行时恐慌(Panicking)], +), offset: whole) + + +#tr(( +en: [ + Panicking is a core part of the Rust language. Built-in operations like + indexing are runtime checked for memory safety. When out of bounds + indexing is attempted this results in a panic. +], +de: [ + Das Auslösen einer Panik ist ein wesentlicher Bestandteil der Sprache + Rust. Eingebaute Operationen wie der Zugriff per Index werden zur + Laufzeit auf Speichersicherheit überprüft. Erfolgt ein Zugriff außerhalb + der zulässigen Grenzen, führt dies zu einer Panik. +], +ja: [ + パニックはRustのコア部分です。インデックス操作のような言語組込みの操作は、メモリ安全性をランタイム時に検査されます。 + 範囲外のインデックスにアクセスしようとすると、パニックが発生します。 +], +zh: [ + 运行时恐慌是Rust语言的一个核心部分。像是索引这样的内建的操作为了存储安全性是运行时检查的。当尝试越界索引时,这会导致运行时恐慌(panic)。 +])) + +#tr(( +en: [ + In the standard library panicking has a defined behavior: it unwinds the + stack of the panicking thread, unless the user opted for aborting the + program on panics. +], +de: [ + In der Standardbibliothek ist das Verhalten bei einer Panik definiert: + Der Stack des betroffenen Threads wird abgewickelt (Stack Unwinding), es + sei denn, der Benutzer hat sich für einen Programmabbruch im Falle einer + Panik entschieden. +], +ja: [ + 標準ライブラリでは、パニックは定義された動作です。ユーザがパニック発生時にプログラムをアボートする選択をしない限り、 + パニックを起こしたスレッドのスタックを巻き戻します。 +], +zh: [ + 在标准库中,运行时恐慌的行为被定义成:展开(unwinds)恐慌的线程的栈,除非用户自己选择在恐慌时终止程序。 +])) + +#let ln_info = link("https://doc.rust-lang.org/core/panic/struct.PanicInfo.html")[`PanicInfo`] +#tr(( +en: [ + In programs without standard library, however, the panicking behavior is + left undefined. A behavior can be chosen by declaring a + `#[panic_handler]` function. This function must appear exactly + _once_ in the dependency graph of a program, and must have the + following signature: `fn(&PanicInfo) -> !`, where #ln_info + is a struct containing information about the location of the panic. +], +de: [ + In Programmen ohne Standardbibliothek ist das Verhalten bei einer Panik + hingegen nicht definiert. Ein Verhalten lässt sich durch die Deklaration + einer `#[panic_handler]`-Funktion festlegen. Diese Funktion muss im + Abhängigkeitsgraphen des Programms genau _einmal_ vorkommen und + folgende Signatur aufweisen: `fn(&PanicInfo) -> !`, wobei #ln_info + eine Struktur ist, die Informationen über den Ort des Panic enthält. +], +ja: [ + しかし、非標準のプログラムでは、パニック時の挙動は、未定義のままです。`#[panic_handler]`関数を宣言することにより、 + 挙動を選択することができます。この関数は、プログラムの依存関係グラフに、*1回だけ*現れる必要があります。 + そして、 `fn(&PanicInfo) -> !`のシグネチャを持つ必要があります。 + ここで、#ln_info;は、パニックした位置情報を含む構造体です。 +], +zh: [ + 然而在没有标准库的程序中,运行时恐慌的行为是未被定义了的。通过声明一个 + `#[panic_handler]` 函数可以选择一个运行时恐慌的行为。 + + 这个函数在一个程序的依赖图中必须只出现一次,且必须有这样的签名: + `fn(&PanicInfo) -> !`,`PanicInfo`是一个包含关于发生运行时恐慌的位置信息的结构体。 +])) + +#let ln_abort = link("https://crates.io/crates/panic-abort")[`panic-abort`] +#let ln_halt = link("https://crates.io/crates/panic-halt")[`panic-halt`] +#let ln_itm = link("https://crates.io/crates/panic-itm")[`panic-itm`] +#let ln_sh = link("https://crates.io/crates/panic-semihosting")[`panic-semihosting`] +#tr(( +en: [ + Given that embedded systems range from user facing to safety critical + (cannot crash) there's no one size fits all panicking behavior but there + are plenty of commonly used behaviors. These common behaviors have been + packaged into crates that define the `#[panic_handler]` function. Some + examples include: + - #ln_abort. A panic causes the abort instruction to be executed. + - #ln_halt. A panic causes the program, or the current thread, to halt by entering an infinite loop. + - #ln_itm. The panicking message is logged using the ITM, an ARM Cortex-M specific peripheral. + - #ln_sh. The panicking message is logged to the host using the semihosting technique. +], +de: [ + Da das Spektrum eingebetteter Systeme von anwenderorientierten bis hin + zu sicherheitskritischen Anwendungen (bei denen ein Absturz + ausgeschlossen sein muss) reicht, gibt es kein universelles Verhalten im + Fehlerfall („Panic"); es existieren jedoch zahlreiche gängige Ansätze. + Diese verbreiteten Verhaltensweisen wurden in Crates zusammengefasst, + die die Funktion `#[panic_handler]` definieren. Zu den Beispielen + gehören: + - #ln_abort. Eine Panic bewirkt die Ausführung der Abbruchanweisung. + - #ln_halt. Ein Panic bewirkt, dass das Programm oder der aktuelle + Thread anhält, indem es bzw. er in eine Endlosschleife eintritt. + - #ln_itm. Die Panik-Meldung wird mithilfe des ITM protokolliert -- einer für ARM + Cortex-M spezifischen Peripheriekomponente. + - #ln_sh. Die Panik-Meldung wird mithilfe der Semihosting-Technik + auf dem Host protokolliert. +], +ja: [ + 組込みシステムは、ユーザとやり取りするものから、安全性が重要な(クラッシュできない)ものまであります。 + そのため、全てのパニック時動作に対応できる唯一のものはありませんが、よく利用される挙動がたくさんあります。 + これらの一般的な挙動が、`#[panic_handler]`関数を定義するクレートにまとめられています。 + いくつか、例を挙げます。 + - #ln_abort。パニックが発生すると、アボート命令を実行します。 + - #ln_halt。パニックが発生すると、プログラム、または、現在のスレッドは、無限ループに入ることで停止します。 + - #ln_itm。パニック発生時のメッセージは、ARM + Cortex-M固有のペリフェラルであるITMを使ってログ出力されます。 + - #ln_sh。パニック発生時のメッセージは、セミホスティングを使ってログ出力されます。 +], +zh: [ + 鉴于嵌入式系统的范围从面向用户的系统到安全关键系统,没有一个运行时恐慌行为能满足所有场景,但是有许多常用的行为。这些常用的行为已经被打包进了一些crates中,这些crates中定义了 + `#[panic_handler]`函数。比如: + - #ln_abort. + 这个运行时恐慌会导致终止指令被执行。 + - #ln_halt. + 这个运行时恐慌会导致程序,或者现在的线程,通过进入一个无限循环中而挂起。 + - #ln_itm. + 运行时恐慌的信息会被ITM记录,ITM是一个ARM Cortex-M的特殊的外设。 + - #ln_sh. + 使用半主机技术,运行时恐慌的信息被记录到主机上。 + +])) + +#let ln_handler = link("https://crates.io/keywords/panic-handler")[`panic-handler`] +#tr(( +en: [ + You may be able to find even more crates searching for the + #ln_handler keyword on crates.io. +], +de: [ + Möglicherweise findest du noch mehr Crates, wenn du auf crates.io nach + dem Schlüsselwort #ln_handler suchst. +], +ja: [ + crates.ioで#ln_handler;をキーワードに検索することで、さらにクレートを見つけることができます。 +], +zh: [ + 在crates.io上搜索 + #ln_handler,你甚至可以找到更多的crates。 +])) + +#tr(( +en: [ + A program can pick one of these behaviors simply by linking to the + corresponding crate. The fact that the panicking behavior is expressed + in the source of an application as a single line of code is not only + useful as documentation but can also be used to change the panicking + behavior according to the compilation profile. For example: +], +de: [ + Ein Programm kann eines dieser Verhalten einfach dadurch auswählen, dass + es das entsprechende Crate einbindet. Dass das Verhalten im Fehlerfall + (Panic-Verhalten) im Quellcode einer Anwendung als einzelne Codezeile + ausgedrückt wird, ist nicht nur als Dokumentation nützlich, sondern + ermöglicht es auch, dieses Verhalten je nach Kompilierungsprofil + anzupassen. Zum Beispiel: +], +ja: [ + プログラムは、対応するクレートとリンクすることで、これらの挙動の中から1つを選びます。 + パニック時の挙動がアプリケーションソースコードの中で単一行で表現されていることは、ドキュメントとして有用なだけでなく、 + パニック時の挙動をコンパイル時のプロファイルで変更にする時にも利用できます。 + 例えば +], +zh: [ + 仅仅通过链接到相关的crate中,一个程序就可以简单地从这些行为中选择一个运行时恐慌行为。将运行时恐慌的行为作为一行代码放进一个应用的源码中,不仅仅是因为可以作为文档使用,而且能根据编译配置改变运行时恐慌的行为。比如: +])) + +#raw(block: true, lang: "rust", +"#![no_main] +#![no_std] + +// " + ts(( + en: "dev profile: easier to debug panics; can put a breakpoint on `rust_begin_unwind`", + de: "dev-Profil: einfacheres Debuggen von Panics; man kann einen Breakpoint bei +// `rust_begin_unwind` setzen.", + ja: "開発プロファイル:パニックのデバッグを容易にします。`rust_begin_unwind`にブレイクポイントを置くことを可能にします。", + zh: "dev配置: 更容易调试运行时恐慌; 可以在 `rust_begin_unwind` 上放一个断点" + )) + " +#[cfg(debug_assertions)] +use panic_halt as _; + +// " + ts(( + en: "release profile: minimize the binary size of the application", + de: "Release-Profil: Minimierung der Binaergroesse der Anwendung", + ja: "リリースプロファイル:アプリケーションのバイナリサイズを最小化します。", + zh: "release配置: 最小化应用的二进制文件的大小", + )) + " +#[cfg(not(debug_assertions))] +use panic_abort as _; + +// .. +") + +#tr(( +en: [ + In this example the crate links to the `panic-halt` crate when built + with the dev profile (`cargo build`), but links to the `panic-abort` + crate when built with the release profile (`cargo build --release`). +], +de: [ + In diesem Beispiel verlinkt der Crate beim Bauen mit dem Dev-Profil + (`cargo build`) auf den `panic-halt`-Crate, beim Bauen mit dem + Release-Profil (`cargo build --release`) hingegen auf den + `panic-abort`-Crate. +], +ja: [ + #todoupd("ja") + この例では、開発プロファイルでビルド(`cargo build`)した時は、`panic-halt`クレートとリンクします。 + しかし、リリースプロファイルでビルド(`cargo build --release`)した時は、`panic-abort`クレートとリンクします。 +], +zh: [ + 在这个例子里,当使用dev配置编译的时候(`cargo build`),crate链接到 + `panic-halt` + crate上,但是当使用release配置编译时(`cargo build --release`),crate链接到`panic-abort` + crate上。 +])) + +#quote(block: true)[ +#tr(( +en: [ + The `use panic_abort as _;` form of the `use` statement is used to + ensure the `panic_abort` panic handler is included in our final + executable while making it clear to the compiler that we won't + explicitly use anything from the crate. Without the `as _` rename, the + compiler would warn that we have an unused import. Sometimes you might + see `extern crate panic_abort` instead, which is an older style used + before the 2018 edition of Rust, and should now only be used for + "sysroot" crates (those distributed with Rust itself) such as + `proc_macro`, `alloc`, `std`, and `test`. +], +de: [ + Die `use panic_abort as _;`-Variante der `use`-Anweisung wird verwendet, + um sicherzustellen, dass der `panic_abort`-Panic-Handler in die fertige + ausführbare Datei aufgenommen wird, während dem Compiler gleichzeitig + signalisiert wird, dass wir nichts aus diesem Crate explizit verwenden + werden. Ohne die Umbenennung mittels `as _` würde der Compiler eine + Warnung wegen eines ungenutzten Imports ausgeben. Gelegentlich stößt man + stattdessen auf `extern crate panic_abort`\; dabei handelt es sich um + einen älteren Stil, der vor der Rust-Edition 2018 üblich war und heute + nur noch für sogenannte „sysroot"-Crates (die gemeinsam mit Rust selbst + ausgeliefert werden) -- wie etwa `proc_macro`, `alloc`, `std` und `test` + -- verwendet werden sollte. +], +zh: [ + `use panic_abort as _` 形式的 `use` 语句,被用来确保 `panic_abort` + 运行时恐慌函数被包含进我们最终的可执行程序里,同时让编译器清楚地知道我们不会从这个crate显式地使用任何东西。没有 + `_` 重命名,编译器将会警告我们有一个未使用的导入。有时候你可能会看到 + `extern crate panic_abort`,这是Rust + 2018之前的版本使用的更旧的写法,现在应该只被用于 "sysroot" crates + (与Rust一起发布的crates),比如 `proc_macro`,`alloc`,`std` 和 `test` 。 +])) +] + += #tr(( + en: [An example], + de: [Ein Beispiel], + ja: [例], + zh: [一个例子], +)) + +#tr(( +en: [ + Here's an example that tries to index an array beyond its length. The + operation results in a panic. +], +de: [ + Hier ist ein Beispiel, das versucht, auf ein Array an einer Position + zuzugreifen, die über dessen Länge hinausgeht. Der Vorgang führt zu einer Panic. +], +ja: [ + 配列の長さを超えてアクセスしようとする例を示します。この操作はパニックを引き起こします。 +], +zh: [ + 这里有一个尝试越界访问数组的例子。操作的结果导致了一个运行时恐慌(panic)。 +])) + +#raw(block: true, lang: "rust", +"#![no_main] +#![no_std] + +use panic_semihosting as _; + +use cortex_m_rt::entry; + +#[entry] +fn main() -> ! { + let xs = [0, 1, 2]; + let i = xs.len(); + let _y = xs[i]; // " + ts(( + en: "out of bounds access", + de: "Zugriff ausserhalb der zulaessigen Grenzen", + ja: "範囲外アクセス", + zh: "out of bounds access" + )) + " + + loop {} +} +") + +#tr(( +en: [ + This example chose the `panic-semihosting` behavior which prints the + panic message to the host console using semihosting. +], +de: [ + Für dieses Beispiel wurde das Verhalten `panic-semihosting` gewählt, das + die Panic-Meldung mittels Semihosting auf der Host-Konsole ausgibt. +], +ja: [ + この例では、`panic-semihosting`の挙動を選択しており、パニックメッセージは、 + セミホスティングを使ってホストコンソールに出力されます。 +], +zh: [ + 这个例子选择了`panic-semihosting`行为,运行时恐慌的信息会被打印至使用了半主机模式的主机控制台上。 +])) + +```text +$ cargo run + Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb (..) +panicked at 'index out of bounds: the len is 3 but the index is 4', src/main.rs:12:13 +``` + +#tr(( +en: [ + You can try changing the behavior to `panic-halt` and confirm that no + message is printed in that case. +], +de: [ + Sie können versuchen, das Verhalten auf `panic-halt` zu ändern, und + bestätigen, dass in diesem Fall keine Meldung ausgegeben wird. +], +ja: [ + 挙動を`panic-halt`に変更し、その場合にメッセージが出力されないことを確認することができます。 +], +zh: [ + 你可以尝试将行为改成`panic-halt`,确保在这个案例里没有信息被打印。 +])) diff --git a/typ/start/qemu.typ b/typ/start/qemu.typ new file mode 100644 index 00000000..cfcd3c26 --- /dev/null +++ b/typ/start/qemu.typ @@ -0,0 +1,1552 @@ +#import "../config.typ": * + +#h1([QEMU], + offset: whole) + + +// TODO: check +#if lang == "de" [ + QEMU (von englisch „Quick Emulator") ist eine freie + Virtualisierungssoftware, die die gesamte Hardware eines Computers + emuliert und durch die dynamische Übersetzung der Prozessorinstruktionen + des Gastprozessors (englisch guest) in Instruktionen für den + Wirtprozessor (englisch host) eine sehr gute Ausführungsgeschwindigkeit + erreicht. + + URL: #link("https://www.qemu.org/") + + QEMU emuliert Systeme mit den folgenden Prozessorarchitekturen: + - 68K, + - Alpha, + - ARM (32- und 64-Bit), + - CHRIS, + - HPPA, + - LatticeMico32, + - m68K bzw. Coldfire, + - MicroBlaze, + - MIPS, + - Moxie, + - Nios2, + - OpenRISC, + - PC + - Power + - PowerNV + - PowerPC (32- und 64-Bit), + - RISC-V, + - S/390, + - SH-4, + - Sparc32/64, + - TILE-Gx, + - TriCore, + - Unicore, + - x86 (x86-32 und x86-64), + - Xtensa + + (Stand 2026). +] + +#let ln_lm3s6965 = link("http://www.ti.com/product/LM3S6965")[LM3S6965] +#let url_qemu = "https://wiki.qemu.org/Documentation/Platforms/ARM#Supported_in_qemu-system-arm" +#tr(( +en: [ + We'll start writing a program for the #ln_lm3s6965, a Cortex-M3 + microcontroller. We have chosen this as our initial target because it + #link(url_qemu)[can be emulated] + using QEMU so you don't need to fiddle with hardware in this section and + we can focus on the tooling and the development process. +], +de: [ + Wir beginnen mit der Entwicklung eines Programms für den + #ln_lm3s6965, einen ARM + Cortex-M3-Mikrocontroller. Wir haben diesen als unser erstes Ziel + ausgewählt, da er mit QEMU + #link(url_qemu)[emuliert werden kann], + sodass Sie sich in diesem Abschnitt nicht mit der Hardware beschäftigen + müssen und wir uns auf die Werkzeuge und den Entwicklungsprozess + konzentrieren können. +], +ja: [ + Cortex-M3マイクロコントローラの#ln_lm3s6965;用にプログラムを書くところから始めましょう。 + このLM3S6965を最初のターゲットとして選んだ理由は、QEMUを使ってエミュレーションできるからです。 + このセクションでは、ハードウェアをいじる必要がなく、ツールと開発プロセスに集中できます。 +], +zh: [ + 我们将开始为#ln_lm3s6965;编写程序,一个Cortex-M3微控制器。因为它能使用#link("https://wiki.qemu.org/Documentation/Platforms/ARM#Supported_in_qemu-system-arm")[QEMU仿真],所以我们选择它作为我们的第一个目标,本节中,不需要使用硬件,我们注意力可以集中在工具和开发过程上。 +])) + +#tr(( +en: [ + *IMPORTANT* We'll use the name "app" for the project name in this + tutorial. Whenever you see the word "app" you should replace it with the + name you selected for your project. Or, you could also name your project + "app" and avoid the substitutions. +], +de: [ + *WICHTIG* In dieser Anleitung verwenden wir den Namen „app" als + Projektnamen. Wann immer Sie das Wort „app" sehen, sollten Sie es durch + den Namen ersetzen, den Sie für Ihr Projekt gewählt haben. Alternativ + können Sie Ihr Projekt auch „app" nennen und so die Ersetzungen + vermeiden. +], +zh: [ + *重要* + 在这个引导里,我们将使用"app"这个名字来代指项目名。无论何时你看到单词"app",你应该用你选择的项目名来替代"app"。或者你也可以选择把你的项目命名为"app",避免要替换掉。 +])) + += #tr(( + en: [Creating a non standard Rust program], + de: [Erstellen eines nicht standardmäßigen Rust-Programms], + ja: [標準ライブラリを使わないRustプログラム], + zh: [生成一个非标准的 Rust program], +)) + +#let ln_quick = link("https://github.com/rust-embedded/cortex-m-quickstart")[`cortex-m-quickstart`] +#tr(( +en: [ + We'll use the #ln_quick + project template to generate a new project from it. The created project + will contain a barebone application: a good starting point for a new + embedded rust application. In addition, the project will contain an + `examples` directory, with several separate applications, highlighting + some of the key embedded rust functionality. +], +de: [ + Wir werden die Projektvorlage #ln_quick + verwenden, um daraus ein neues Projekt zu erstellen. Das erstellte + Projekt enthält eine Minimalanwendung: einen guten Ausgangspunkt für + eine neue Embedded-Rust-Anwendung. Darüber hinaus enthält das Projekt + ein Verzeichnis `examples` mit mehreren separaten Anwendungen, die + einige der wichtigsten Funktionen von Embedded Rust veranschaulichen. +], +zh: [ + 我们将使用#ln_quick;项目模板来生成一个新项目。生成的项目将包含一个最基本的应用:对于一个新的嵌入式rust应用来说,是一个很好的开始。另外,项目将包含一个`example`文件夹,文件夹中有许多独立的应用,突出了一些关键的嵌入式rust的功能。 +])) + +== #tr(( + en: [Using `cargo-generate`], + de: [Verwendung von `cargo-generate`], + zh: [使用 `cargo-generate`], +)) + +#tr(( +en: [ + First install cargo-generate +], +de: [ + Installieren Sie zunächst cargo-generate +], +zh: [ + 首先安装 cargo-generate +])) + +```console +cargo install cargo-generate +``` + +#tr(( +en: [ + Then generate a new project +], +de: [ + Erstellen Sie anschließend ein neues Projekt +], +zh: [ + 然后生成一个新项目 +])) + +```console +cargo generate --git https://github.com/knurling-rs/app-template +``` + +```text + Project Name: app + Creating project called `app`... + Done! New project created /tmp/app +``` + +```console +cd app +``` + +== #tr(( + en: [Using `git`], + de: [Verwendung von `git`], + zh: [使用 `git`], +)) + +#tr(( +en: [ + Clone the repository +], +de: [ + Das Repository klonen +], +zh: [ + 克隆仓库 +])) + +```console +git clone https://github.com/rust-embedded/cortex-m-quickstart app +cd app +``` + +#tr(( +en: [ + And then fill in the placeholders in the `Cargo.toml` file +], +de: [ + Und fülle dann die Platzhalter in der Datei `Cargo.toml` aus +], +zh: [ + 然后补充`Cargo.toml`文件中的占位符 +])) + +```toml +[package] +authors = ["{{authors}}"] # "{{authors}}" -> "John Smith" +edition = "2018" +name = "{{project-name}}" # "{{project-name}}" -> "app" +version = "0.1.0" + +# .. + +[[bin]] +name = "{{project-name}}" # "{{project-name}}" -> "app" +test = false +bench = false +``` + +== #tr(( + en: [Using neither], + de: [Keines von beiden verwenden], + zh: [要么使用], +)) + +#tr(( +en: [ + Grab the latest snapshot of the `cortex-m-quickstart` template and + extract it. +], +de: [ + Laden Sie den neuesten Snapshot der Vorlage `cortex-m-quickstart` + herunter und entpacken Sie ihn. +], +zh: [ + 抓取最新的 `cortex-m-quickstart` 模板,解压它。 +])) + +```console +curl -LO https://github.com/rust-embedded/cortex-m-quickstart/archive/master.zip +unzip master.zip +mv cortex-m-quickstart-master app +cd app +``` + +#tr(( +en: [ + Or you can browse to #ln_quick, click the green "Clone or download" button and then click "Download ZIP". +], +de: [ + Oder Sie navigieren zu #ln_quick, + klicken auf die grüne Schaltfläche „Clone or download" und anschließend auf „Download ZIP". +], +zh: [ + 或者你可以浏览#ln_quick,点击绿色的 + "Clone or download" 按钮,然后点击 "Download ZIP" 。 +])) + +#tr(( +en: [ + Then fill in the placeholders in the `Cargo.toml` file as done in the + second part of the "Using `git`" version. +], +de: [ + Füllen Sie anschließend die Platzhalter in der Datei `Cargo.toml` aus, + wie im zweiten Teil der Version „Verwendung von `git` beschrieben. +], +zh: [ + 然后像在 "使用 `git`" 那里的第二部分写的那样填充 `Cargo.toml` 。 +])) + += #tr(( + en: [Program Overview], + de: [Programmübersicht], + zh: [项目概览], +)) + +#tr(( +en: [ + For convenience here are the most important parts of the source code in `src/main.rs`: +], +de: [ + Der Einfachheit halber sind hier die wichtigsten Teile des Quellcodes in + `src/main.rs` aufgeführt: +], +zh: [ + 这是`src/main.rs`中源码最重要的部分。 +])) + +#raw(block: true, lang: "rust", +"#![no_std] +#![no_main] + +use panic_halt as _; + +use cortex_m_rt::entry; + +#[entry] +fn main() -> ! { + loop { + // " + ts(( + en: "your code goes here", + de: "Hier kommt Ihr Code hin.", + ja: "あなたのコードはここに書きます", + )) + " + } +} +") + +#tr(( +en: [ + This program is a bit different from a standard Rust program so let's + take a closer look. +], +de: [ + Dieses Programm unterscheidet sich ein wenig von einem typischen + Rust-Programm, schauen wir es uns also einmal genauer an. +], +zh: [ + 这个程序与标准Rust程序有一点不同,让我们走近点看看。 +])) + +#tr(( +en: [ + `#![no_std]` indicates that this program will _not_ link to the + standard crate, `std`. Instead it will link to its subset: the `core` crate. +], +de: [ + `#![no_std]` gibt an, dass dieses Programm _nicht_ mit der + Standard-Crate `std` verknüpft wird. Stattdessen wird es mit deren + Teilmenge verknüpft: der Crate `core`. +], +zh: [ + `#![no_std]`指出这个程序将 _不会_ + 链接标准crate`std`。反而它将会链接到它的子集: `core` crate。 +])) + +#tr(( +en: [ + `#![no_main]` indicates that this program won't use the standard `main` + interface that most Rust programs use. The main (no pun intended) reason + to go with `no_main` is that using the `main` interface in `no_std` + context requires nightly. +], +de: [ + `#![no_main]` gibt an, dass dieses Programm nicht die Standard-`main`- + Schnittstelle verwendet, die die meisten Rust-Programme nutzen. Der + Hauptgrund (kein Wortspiel beabsichtigt) für die Verwendung von + `no_main` ist, dass die Nutzung der `main`-Schnittstelle im + `no_std`-Kontext „Nightly" erfordert. +], +zh: [ + `#![no_main]`指出这个程序将不会使用标准的且被大多数Rust程序使用的`main`接口。使用`no_main`的主要理由是,在`no_std`上下文中使用`main`接口需要 + nightly 版的 Rust。 +])) + +#tr(( +en: [ + `use panic_halt as _;`. This crate provides a `panic_handler` that + defines the panicking behavior of the program. We will cover this in + more detail in the #link()[Panicking] chapter of the book. +], +de: [ + `use panic_halt as _;`. Diese Crate stellt einen `panic_handler` bereit, + der das Verhalten des Programms im Panikfall definiert. Wir werden + darauf im Kapitel #link()[In Panik geraten] des Buches + näher eingehen. +], +zh: [ + `use panic_halt as _;`。这个crate提供了一个`panic_handler`,它定义了程序陷入`panic`时的行为。我们将会在这本书的#link()[运行时恐慌(Panicking)]章节中覆盖更多的细节。 +])) + +#let ln_entry = link("https://docs.rs/cortex-m-rt-macros/latest/cortex_m_rt_macros/attr.entry.html")[`#[entry]`] +#let ln_rt = link("https://crates.io/crates/cortex-m-rt")[`cortex-m-rt`] +#tr(( +en: [ + #ln_entry is an attribute provided by the #ln_rt crate + that's used to mark the entry point of the program. As we are not using + the standard `main` interface we need another way to indicate the entry + point of the program and that'd be `#[entry]`. +], +de: [ + #ln_entry ist ein Attribut des + #ln_rt;-Crate, das dazu dient, den Einstiegspunkt des Programms zu kennzeichnen. Da wir + nicht die Standard-Schnittstelle `main` verwenden, benötigen wir eine + andere Möglichkeit, den Einstiegspunkt des Programms anzugeben, und das + wäre `#[entry]`. +], +zh: [ + #ln_entry 是一个由#ln_rt;提供的属性,它用来标记程序的入口。当我们不使用标准的`main`接口时,我们需要其它方法来指示程序的入口,那就是`#[entry]`。 +])) + +#let url_div = "https://doc.rust-lang.org/rust-by-example/fn/diverging.html" +#tr(( +en: [ + `fn main() -> !`. Our program will be the _only_ process running on + the target hardware so we don't want it to end! We use a + #link(url_div)[divergent function] + (the `-> !` bit in the function signature) to ensure at compile time + that'll be the case. +], +de: [ + `fn main() -> !`. Unser Programm wird der _einzige_ Prozess sein, + der auf der Zielhardware läuft, deshalb soll es nicht beendet werden! + Wir verwenden eine #link(url_div)[divergent function] + (das `-> !` in der Funktionssignatur), um bereits zur Kompilierungszeit + sicherzustellen, dass dies auch der Fall ist. +], +zh: [ + `fn main() -> !`。我们的程序将会是运行在目标板子上的 _唯一_ + 的进程,因此我们不想要它结束!我们使用一个#link(url_div)[发散函数] + (函数签名中的 `-> !` )来确保在编译时就是这么回事儿。 +])) + += #tr(( + en: [Cross compiling], + de: [Cross-Kompilierung], + zh: [交叉编译], +)) + +#tr(( +en: [ + First of all we will need the memory layout for the target + microcontroller, the LM3S6965 in our case. Otherwise the build will fail + to link the image. Create a file named `memory.x` at the root of the + project and paste the following content: +], +de: [ + Zunächst benötigen wir das Speicherlayout für den Ziel-Mikrocontroller, + in unserem Fall den LM3S6965. Andernfalls schlägt die Verknüpfung des + Images beim Build fehl. Erstellen Sie eine Datei mit dem Namen + `memory.x` im Stammverzeichnis des Projekts und fügen Sie den folgenden + Inhalt ein: +])) + +#raw(block: true, lang: "text", +"MEMORY +{ + /* " + ts(( + en: "NOTE 1 K = 1 KiBi = 1024 bytes */ + /* TODO Adjust these memory regions to match your device memory layout */ + /* These values correspond to the LM3S6965, one of the few devices + /* QEMU can emulate */", + de: "Hinweis: 1 K = 1 KiBi = 1024 bytes */ + /* TODO Passen Sie diese Speicherbereiche an das Speicherlayout Ihres Geräts an. */ + /* Diese Werte entsprechen dem LM3S6965, einem der wenigen Bausteine, die + QEMU emulieren kann */", + )) + " + FLASH : ORIGIN = 0x00000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 64K +} + +/* " + ts(( + en: "This is where the call stack will be allocated. */ +/* The stack is of the full descending type. */ +/* You may want to use this variable to locate the call stack and static + variables in different memory regions. Below is shown the default value */", + de: "Hier wird der Aufrufstapel zugewiesen. */ +/* Der Stapel ist vom Typ „vollständig absteigend“. */ +/* Möglicherweise möchten Sie diese Variable verwenden, um den Aufrufstapel und + statische Variablen in verschiedenen Speicherbereichen zu lokalisieren. + Nachstehend ist der Standardwert aufgeführt */" + )) + " +/* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ + +/* " + ts(( + en: "You can use this symbol to customize the location of the .text section */ +/* If omitted the .text section will be placed right after the .vector_table + section */ +/* This is required only on microcontrollers that store some configuration right + after the vector table */", + de: "Mit diesem Symbol können Sie den Speicherort des .text-Abschnitts anpassen. */ +/* Wird dies weggelassen, wird der .text-Abschnitt direkt nach dem .vector_table- + Abschnitt platziert */ +/* Dies ist nur bei Mikrocontrollern erforderlich, die bestimmte + Konfigurationsdaten direkthinter der Vektortabelle speichern */" + )) + " +/* _stext = ORIGIN(FLASH) + 0x400; */ + +/* " + ts(( + en: "Example of putting non-initialized variables into custom RAM locations. */ +/* This assumes you have defined a region RAM2 above, and in the Rust + sources added the attribute `#[link_section = \".ram2bss\"]` to the data + you want to place there. */ +/* Note that the section will not be zero-initialized by the runtime! */", + de: "Beispiel für die Zuweisung nicht initialisierter Variablen zu +benutzerdefinierten RAM-Speicherplätzen. */ +/* Dies setzt voraus, dass Sie oben einen Bereich namens „RAM2“ definiert und +in den Rust-Quelldateien das Attribut `#[link_section = „.ram2bss“]` zu den +Daten hinzugefügt haben, die Sie dort platzieren möchten. */ +/* Beachten Sie, dass der Bereich von der Laufzeitumgebung nicht auf Null +initialisiert wird! */" + )) + " +/* SECTIONS { + .ram2bss (NOLOAD) : ALIGN(4) { + *(.ram2bss); + . = ALIGN(4); + } > RAM2 + } INSERT AFTER .bss; +*/ +") + +#tr(( +en: [ + The next step is to _cross_ compile the program for the Cortex-M3 + architecture. That's as simple as running `cargo build --target $TRIPLE` + if you know what the compilation target (`$TRIPLE`) should be. Luckily, + the `.cargo/config.toml` in the template has the answer: +], +de: [ + Der nächste Schritt besteht darin, das Programm für die + Cortex-M3-Architektur _cross_ zu kompilieren. Das geht ganz einfach + mit dem Befehl `cargo build --target $TRIPLE`, sofern Sie wissen, wie + das Kompilierungsziel (`$TRIPLE`) lauten soll. Glücklicherweise finden + Sie die Antwort in der Datei `.cargo/config.toml` in der Vorlage: +], +zh: [ + 下一步是为Cortex-M3架构_交叉_编译程序。如果你知道编译目标(`$TRIPLE`)应该是什么,运行`cargo build --target $TRIPLE`就可以了。幸运地,模板中的`.cargo/config.toml`有这个答案: +])) + +```console +tail -n6 .cargo/config.toml +``` + +#let _and_ = tr(( + en: " and ", +), default: " and ") + +#raw(block: true, lang: "toml", +"[build] +# " + ts(( + en: "Pick ONE of these compilation targets", + de: "Waehlen Sie EINES dieser Kompilierungsziele aus", + )) + " +# target = \"thumbv6m-none-eabi\" # Cortex-M0"+_and_+"Cortex-M0+ +target = \"thumbv7m-none-eabi\" # Cortex-M3 +# target = \"thumbv7em-none-eabi\" # Cortex-M4"+_and_+"Cortex-M7 (no FPU) +# target = \"thumbv7em-none-eabihf\" # Cortex-M4F"+_and_+"Cortex-M7F (with FPU) +") + +#tr(( +en: [ + To cross compile for the Cortex-M3 architecture we have to use + `thumbv7m-none-eabi`. That target is not automatically installed when + installing the Rust toolchain, it would now be a good time to add that + target to the toolchain, if you haven't done it yet: +], +de: [ + Für die Cross-Kompilierung für die Cortex-M3-Architektur müssen wir + `thumbv7m-none-eabi` verwenden. Dieses Ziel wird bei der Installation + der Rust-Werkzeuge nicht automatisch installiert. Jetzt wäre ein guter + Zeitpunkt, dieses Ziel zu den Werkzeugen hinzuzufügen, falls Sie dies + noch nicht getan haben: +], +zh: [ + 为了交叉编译Cortex-M3架构我们不得不使用`thumbv7m-none-eabi`。当安装Rust工具时,target不会自动被安装,如果还没有添加,现在可以去添加那个target到工具链上。 +])) + +```console +rustup target add thumbv7m-none-eabi +``` + +#tr(( +en: [ + Since the `thumbv7m-none-eabi` compilation target has been set as the + default in your `.cargo/config.toml` file, the two commands below do the same: +], +de: [ + Da das Kompilierungsziel `thumbv7m-none-eabi` in Ihrer Datei + `.cargo/config.toml` als Standard festgelegt wurde, haben die beiden + folgenden Befehle dieselbe Wirkung: +], +zh: [ + 因为`thumbv7m-none-eabi`编译目标在你的`.cargo/config.toml`中被设置成默认值,下面的两个命令是一样的效果: +])) + +```console +cargo build --target thumbv7m-none-eabi +cargo build +``` + += #tr(( + en: [Inspecting], + de: [Überprüfen], + zh: [检查], +)) + +#tr(( +en: [ + Now we have a non-native ELF binary in + `target/thumbv7m-none-eabi/debug/app`. We can inspect it using + `cargo-binutils`. +], +de: [ + Nun haben wir eine nicht-native ELF-Binärdatei in + `target/thumbv7m-none-eabi/debug/app`. Wir können sie mit + `cargo-binutils` untersuchen. +], +zh: [ + 现在在`target/thumbv7m-none-eabi/debug/app`中有一个非主机环境的ELF二进制文件。我们能使用`cargo-binutils`检查它。 +])) + +#tr(( +en: [ + With `cargo-readobj` we can print the ELF headers to confirm that this + is an ARM binary. +], +de: [ + Mit `cargo-readobj` können wir die ELF-Header ausgeben, um zu + überprüfen, ob es sich um eine ARM- Binärdatei handelt. +], +zh: [ + 使用`cargo-readobj`我们能打印ELF头,确认这是一个ARM二进制。 +])) + +```console +cargo readobj --bin app -- --file-headers +``` + +#tr(( +en: [ + Note that: + - `--bin app` is sugar for inspect the binary at `target/$TRIPLE/debug/app` + - `--bin app` will also (re)compile the binary, if necessary +], +de: [ + Bitte beachten Sie: + - `--bin app` ist eine vereinfachte Schreibweise + für die Überprüfung der Binärdatei unter `target/$TRIPLE/debug/app` + - `--bin app` kompiliert die Binärdatei bei Bedarf auch (neu) +], +zh: [ + 注意: + - `--bin app` 是一个用来查看二进制项`target/$TRIPLE/debug/app`的语法糖 + - `--bin app` 需要时也会重新编译二进制项。 +])) + +```text +ELF Header: + Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 + Class: ELF32 + Data: 2's complement, little endian + Version: 1 (current) + OS/ABI: UNIX - System V + ABI Version: 0x0 + Type: EXEC (Executable file) + Machine: ARM + Version: 0x1 + Entry point address: 0x405 + Start of program headers: 52 (bytes into file) + Start of section headers: 153204 (bytes into file) + Flags: 0x5000200 + Size of this header: 52 (bytes) + Size of program headers: 32 (bytes) + Number of program headers: 2 + Size of section headers: 40 (bytes) + Number of section headers: 19 + Section header string table index: 18 +``` + +#tr(( +en: [ + `cargo-size` can print the size of the linker sections of the binary. +], +de: [ + Mit `cargo-size` lässt sich die Größe der Linker-Abschnitte der + Binärdatei anzeigen. +], +zh: [ + `cargo-size` 能打印二进制项的linker section的大小。 +])) + +```console +cargo size --bin app --release -- -A +``` + +#tr(( +en: [ + we use `--release` to inspect the optimized version +], +de: [ + Wir verwenden `--release`, um die optimierte Version zu überprüfen. +], +zh: [ + 我们使用`--release`查看优化后的版本 +])) + +```text +app : +section size addr +.vector_table 1024 0x0 +.text 92 0x400 +.rodata 0 0x45c +.data 0 0x20000000 +.bss 0 0x20000000 +.debug_str 2958 0x0 +.debug_loc 19 0x0 +.debug_abbrev 567 0x0 +.debug_info 4929 0x0 +.debug_ranges 40 0x0 +.debug_macinfo 1 0x0 +.debug_pubnames 2035 0x0 +.debug_pubtypes 1892 0x0 +.ARM.attributes 46 0x0 +.debug_frame 100 0x0 +.debug_line 867 0x0 +Total 14570 +``` + +#quote(block: true)[ +#tr(( +en: [ + A refresher on ELF linker sections + - `.text` contains the program instructions + - `.rodata` contains constant values like strings + - `.data` contains statically allocated variables whose initial values + are _not_ zero + - `.bss` also contains statically allocated variables whose initial + values _are_ zero + - `.vector_table` is a _non_-standard section that we use to store + the vector (interrupt) table + - `.ARM.attributes` and the `.debug_*` sections contain metadata and + will _not_ be loaded onto the target when flashing the binary. +], +de: [ + Eine Auffrischung zum Thema ELF-Linker-Abschnitte + - `.text` enthält die Programmbefehle + - `.rodata` enthält konstante Werte wie Zeichenfolgen + - `.data` enthält statisch zugewiesene Variablen, deren Anfangswerte + _nicht_ Null + - Die Datei `.bss` enthält außerdem statisch zugewiesene Variablen, + deren Anfangswerte _sind_ Null + - `.vector_table` ist ein _nicht_ standardmäßiger Abschnitt, in dem + wir den Vektor speichern (interrupt) table + - Die Abschnitte `.ARM.attributes` und `.debug_*` enthalten Metadaten + und werden _nicht_ beim Flashen der Binärdatei auf das Zielgerät + geladen werden. +], +zh: [ + ELF linker sections的复习 + - `.text` 包含程序指令 + - `.rodata` 包含像是字符串这样的常量 + - `.data` 包含静态分配的初始值_非_零的变量 + - `.bss` 也包含静态分配的初始值_是_零的变量 + - `.vector_table` 是一个我们用来存储向量(中断)表的_非_标准的section + - `.ARM.attributes` 和 `.debug_*` + sections包含元数据,当烧录二进制文件时,它们不会被加载到目标上。 +])) +] + +#tr(( +en: [ + *IMPORTANT*: ELF files contain metadata like debug information so + their _size on disk_ does _not_ accurately reflect the space + the program will occupy when flashed on a device. _Always_ use + `cargo-size` to check how big a binary really is. +], +de: [ + *WICHTIG*: ELF-Dateien enthalten Metadaten wie + Debug-Informationen, sodass ihre _Größe auf der Festplatte_ + _nicht_ genau den Speicherplatz widerspiegelt, den das Programm + beanspruchen wird, wenn es auf ein Gerät geflasht wird. Verwenden Sie + _immer_ `cargo-size`, um zu überprüfen, wie groß eine Binärdatei + tatsächlich ist. +], +zh: [ + *重要*: + ELF文件包含像是调试信息这样的元数据,因此它们在_硬盘上的尺寸_没有正确地反应处程序被烧录到设备上时将占据的空间的大小。要_一直_使用`cargo-size`检查一个二进制项的大小。 +])) + +#tr(( +en: [ +`cargo-objdump` can be used to disassemble the binary. +], +de: [ + Mit `cargo-objdump` lässt sich die Binärdatei disassemblieren. +], +zh: [ +`cargo-objdump` 能用来反编译二进制项。 +])) + +```console +cargo objdump --bin app --release -- --disassemble --no-show-raw-insn --print-imm-hex +``` + +#quote(block: true)[ +#let ln_issue269 = link("https://github.com/rust-embedded/book/issues/269") +#tr(( +en: [ + *NOTE* if the above command complains about + `Unknown command line argument` see the following bug report: #ln_issue269 +], +de: [ + *HINWEIS*: Falls der obige Befehl die Fehlermeldung „Unbekanntes + Befehlszeilenargument" ausgibt, siehe den folgenden Fehlerbericht: #ln_issue269 +], +zh: [ + *注意* 如果上面的命令抱怨 `Unknown command line argument` + 看下面的bug报告:#ln_issue269 +])) +] + +#quote(block: true)[ +#tr(( +en: [ + *NOTE* this output can differ on your system. New versions of + rustc, LLVM and libraries can generate different assembly. We truncated + some of the instructions to keep the snippet small. +], +de: [ + *HINWEIS* Diese Ausgabe kann auf Ihrem System abweichen. Neuere + Versionen von rustc, LLVM und Bibliotheken können unterschiedlichen + Assemblercode erzeugen. Wir haben einige der Befehle gekürzt, um den + Ausschnitt kurz zu halten. +], +zh: [ + *注意* 在你的系统上这个输出可能不一样。rustc, LLVM + 和库的新版本能产出不同的汇编。我们截取了一些指令 +])) +] + +```text +app: file format ELF32-arm-little + +Disassembly of section .text: +main: + 400: bl #0x256 + 404: b #-0x4 + +Reset: + 406: bl #0x24e + 40a: movw r0, #0x0 + < .. truncated any more instructions .. > + +DefaultHandler_: + 656: b #-0x4 + +UsageFault: + 657: strb r7, [r4, #0x3] + +DefaultPreInit: + 658: bx lr + +__pre_init: + 659: strb r7, [r0, #0x1] + +__nop: + 65a: bx lr + +HardFaultTrampoline: + 65c: mrs r0, msp + 660: b #-0x2 + +HardFault_: + 662: b #-0x4 + +HardFault: + 663: +``` + += #tr(( + en: [Running], + de: [Ausführen], + zh: [运行], +)) + +#tr(( +en: [ + Next, let's see how to run an embedded program on QEMU! This time we'll + use the `hello` example which actually does something. By default, this + example uses `[defmt]` and RTT to print text. +], +de: [ + Als Nächstes schauen wir uns an, wie man ein eingebettetes Programm auf + QEMU ausführt! Diesmal verwenden wir das `hello`-Beispiel, das + tatsächlich etwas tut. Standardmäßig nutzt dieses Beispiel `[defmt]` und + RTT, um Text auszugeben. +], +zh: [ + #todoupd("zh") + 接下来,让我们看一个嵌入式程序是如何在QEMU上运行的!此刻我们将使用 + `hello` 示例,来做些真正的事。 +])) + +#quote(block: true)[ +#tr(( +en: [ + *NOTE* `defmt` is a third-party dependency (i.e.~non-core) widely + used in the Embedded Rust ecosystem. +], +de: [ + *HINWEIS* `defmt` ist eine Abhängigkeit eines Drittanbieters + (d. h. keine Kernkomponente), die im Embedded-Rust-Ökosystem weit + verbreitet ist. +])) +] + +#tr(( +en: [ + In order to read and decode the messages produced by `defmt` in the + host, we need to switch the RTT transport output to semihosting. When + using real hardware this requires a debug session but when using QEMU + this Just Works. +], +de: [ + Um die von `defmt` im Host erzeugten Nachrichten lesen und entschlüsseln + zu können, müssen wir die RTT-Transportausgabe auf „Semihosting" + umstellen. Bei Verwendung von echter Hardware erfordert dies eine + Debug-Sitzung, bei Verwendung von QEMU funktioniert dies jedoch einfach + so. +])) + +#tr(( +en: [ + Let's switch the dependencies: +], +de: [ + Stellen wir die Abhängigkeiten um: +])) + +```console +cargo remove defmt-rtt +cargo add defmt-semihosting +``` + +#tr(( +en: [ + Open `src/lib.rs` and replace `use defmt_rtt as _;` by `use defmt_semihosting as _;` +], +de: [ + Öffnen Sie `src/lib.rs` und ersetzen Sie `use defmt_rtt as _;` durch + `use defmt_semihosting as _;`. +])) + +#tr(( +en: [ + Now we can build the example: +], +de: [ + Nun können wir das Beispiel kompilieren: +])) + +```console +cargo build --bin hello +``` + +#tr(( +en: [ + The output binary will be located at `target/thumbv7m-none-eabi/debug/hello`. +], +de: [ + Die ausgegebene Binärdatei befindet sich unter + `target/thumbv7m-none-eabi/debug/hello`. +])) + +#tr(( +en: [ + To run this binary on QEMU, the following command would be usually enough: +], +de: [ + Um diese Binärdatei unter QEMU auszuführen, reicht in der Regel der + folgende Befehl aus: +], +zh: [ + 为了在QEMU上运行这个二进制项,执行下列的命令: +])) + +```console +qemu-system-arm \ + -cpu cortex-m3 \ + -machine lm3s6965evb \ + -nographic \ + -semihosting-config enable=on,target=native \ + -kernel target/thumbv7m-none-eabi/debug/hello +``` + +#let ln_run = link("https://github.com/knurling-rs/defmt/tree/main/qemu-run/")[`qemu-run`] +#tr(( +en: [ + In our case, since we use `defmt`, the host will not be able to decode + the output. Instead, we will need a tool by Ferrous Systems named #ln_run: +], +de: [ + Da wir in unserem Fall `defmt` verwenden, kann der Host die Ausgabe + nicht dekodieren. Stattdessen benötigen wir ein Werkzeug von Ferrous + Systems namens #ln_run: +])) + +```console +git clone git@github.com:knurling-rs/defmt.git +cd defmt/qemu-run/ +cargo run -- --machine lm3s6965evb ../qemu-rs/target/thumbv7m-none-eabi/debug/hello +``` + +```text +Hello, world! +``` + +#tr(( +en: [ + The command should successfully exit (exit code = 0) after printing the + text. On \*nix you can check that with the following command: +], +de: [ + Der Befehl sollte nach der Ausgabe des Textes erfolgreich beendet werden + (Exit-Code = 0). Unter \*nix können Sie dies mit dem folgenden Befehl überprüfen: +])) + +```console +echo $? +``` + +```text +0 +``` + +#tr(( +en: [ + Let's break down that QEMU command: + - `qemu-system-arm`. This is the QEMU emulator. There are a few variants + of these QEMU binaries; this one does full _system_ emulation of + _ARM_ machines hence the name. + - `-cpu cortex-m3`. This tells QEMU to emulate a Cortex-M3 CPU. + Specifying the CPU model lets us catch some miscompilation errors: for + example, running a program compiled for the Cortex-M4F, which has a + hardware FPU, will make QEMU error during its execution. + - `-machine lm3s6965evb`. This tells QEMU to emulate the LM3S6965EVB, an + evaluation board that contains a LM3S6965 microcontroller. + - `-nographic`. This tells QEMU to not launch its GUI. + - `-semihosting-config (..)`. This tells QEMU to enable semihosting. + Semihosting lets the emulated device, among other things, use the host + stdout, stderr and stdin and create files on the host. + - `-kernel $file`. This tells QEMU which binary to load and run on the + emulated machine. +], +de: [ + Schauen wir uns diesen QEMU-Befehl einmal genauer an: + - `qemu-system-arm`. Dies ist der QEMU-Emulator. Es gibt einige + Varianten dieser QEMU-Binärdateien; diese hier führt eine vollständige + _System_-Emulation von _ARM_-Rechnern durch, daher der Name. + - `-cpu cortex-m3`. Damit wird QEMU angewiesen, eine Cortex-M3-CPU zu + emulieren. Durch die Angabe des CPU-Modells lassen sich einige + Kompilierungsfehler erkennen: Wenn man beispielsweise ein Programm + ausführt, das für den Cortex-M4F kompiliert wurde, der über eine + Hardware-FPU verfügt, löst dies bei QEMU während der Ausführung einen Fehler aus. + - `-machine lm3s6965evb`. Damit wird QEMU angewiesen, das LM3S6965EVB zu + emulieren, ein Evaluierungsboard, das einen LM3S6965-Mikrocontroller enthält. + - `-nographic`. Damit wird QEMU angewiesen, seine grafische + Benutzeroberfläche nicht zu starten. + - `-semihosting-config (..)`. Damit wird QEMU angewiesen, Semihosting zu + aktivieren. Semihosting ermöglicht es dem emulierten Gerät unter + anderem, die Host-Ausgabe (stdout), die Host-Fehlerausgabe (stderr) + und die Host-Eingabe (stdin) zu nutzen sowie Dateien auf dem Host zu erstellen. + - `-kernel $file`. Damit wird QEMU mitgeteilt, welche Binärdatei auf der + emulierten Maschine geladen und ausgeführt werden soll. +], +zh: [ + #todoupd("zh") + 让我们看看QEMU命令: + - `qemu-system-arm`。这是QEMU仿真器。这些QEMU二进制项有一些变体,这个仿真器能做ARM机器的全系统仿真。 + - `-cpu cortex-m3`。这告诉QEMU去仿真一个Cortex-M3 + CPU。指定CPU模型会让我们捕捉到一些误编译错误:比如,运行一个为Cortex-M4F编译的程序,它具有一个硬件FPU,在执行时将会使QEMU报错。 + - `-machine lm3s6965evb`。这告诉QEMU去仿真 + LM3S6965EVB,一个包含LM3S6965微控制器的评估板。 + - `-nographic`。这告诉QEMU不要启动它的GUI。 + - `-semihosting-config (..)`。这告诉QEMU使能半主机模式。半主机模式允许被仿真的设备,使用主机的stdout,stderr,和stdin,并在主机上创建文件。 + - `-kernel $file`。这告诉QEMU在仿真机器上加载和运行哪个二进制项。 + + 输入这么长的QEMU命令太费功夫了!我们可以设置一个自定义运行器(runner)简化步骤。`.cargo/config.toml` + 有一个被注释掉的,可以调用QEMU的运行器。让我们去掉注释。 +])) + +#tr(( +en: [ + Typing out that long QEMU command is too much work! We can set a custom + runner to simplify the process. `.cargo/config.toml` has a commented out + runner that invokes QEMU; let's uncomment it: +], +de: [ + Das Eintippen dieses langen QEMU-Befehls ist viel zu mühsam! Wir können + einen benutzerdefinierten Runner einrichten, um den Vorgang zu + vereinfachen. In der Datei `.cargo/config.toml` gibt es einen + auskommentierten Runner, der QEMU aufruft; entfernen wir die + Auskommentierung: +])) + +```console +head -n3 .cargo/config.toml +``` + +#raw(block: true, lang: "toml", +"[target.thumbv7m-none-eabi] +# " + ts(( + en: "uncomment this to make `cargo run` execute programs on QEMU", + de: "Entferne den Kommentar hier, damit `cargo run` Programme auf QEMU ausfuehrt", + ja: "`cargo run`で、プログラムをQEMUで実行するため、コメントアウトを外して下さい。", + )) + " +runner = \"qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel\" +") + +#tr(( +en: [ + This runner only applies to the `thumbv7m-none-eabi` target, which is + our default compilation target. Now `cargo run` will compile the program + and run it on QEMU: +], +de: [ + Dieser Runner gilt nur für das Ziel `thumbv7m-none-eabi`, das unser + Standard-Kompilierungsziel ist. Nun kompiliert `cargo run` das Programm + und führt es auf QEMU aus: +], +ja: [ + このランナーは、デフォルトのコンパイルターゲットである`thumbv7m-none-eabi`のみに適用されます。 + これで、`cargo run`はプログラムをコンパイルしてQEMUで実行します。 +], +zh: [ + 这个运行器只会应用于 `thumbv7m-none-eabi` + 目标,它是我们的默认编译目标。现在 `cargo run` + 将会编译程序且在QEMU上运行它。 +])) + +```console +cargo ru( + level: 2 + whole +)--release +``` + +```text + Compiling app v0.1.0 (file:///tmp/app) + Finished release [optimized + debuginfo] target(s) in 0.26s + Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel target/thumbv7m-none-eabi/release/examples/hello` +Hello, world! +``` + += #tr(( + en: [Debugging], + de: [Fehlerbehebung (Debugging)], + ja: [デバッグ], + zh: [调试], +)) + +#tr(( +en: [ + Debugging is critical to embedded development. Let's see how it's done. +], +de: [ + Das Debuggen ist für die Embedded-Entwicklung von entscheidender + Bedeutung. Schauen wir uns einmal an, wie es funktioniert. +], +ja: [ + デバッグは組込み開発にとって非常に重要です。どのように行うのか、見てみましょう。 +], +zh: [ + 对于嵌入式开发来说,调试非常重要。让我们来看下如何调试它。 +])) + +#tr(( +en: [ + Debugging an embedded device involves _remote_ debugging as the + program that we want to debug won't be running on the machine that's + running the debugger program (GDB or LLDB). +], +de: [ + Das Debuggen eines Embedded-Geräts erfolgt _remote_, da das + Programm, das wir debuggen möchten, nicht auf dem Rechner läuft, auf dem + das Debugger-Programm (GDB oder LLDB) ausgeführt wird. +], +ja: [ + 組込みデバイスのデバッグは、_リモート_デバッグを伴います。デバッグしたいプログラムは、 + デバッガプログラム(GDBまたはLLDB)を実行しているマシン上で実行されないためです。 +], +zh: [ + 因为我们想要调试的程序所运行的机器上并没有运行一个调试器程序(GDB或者LLDB),所以调试一个嵌入式设备就涉及到了 + _远程_ 调试 +])) + +#tr(( +en: [ + Remote debugging involves a client and a server. In a QEMU setup, the + client will be a GDB (or LLDB) process and the server will be the QEMU + process that's also running the embedded program. +], +de: [ + Beim Remote-Debugging sind ein Client und ein Server beteiligt. In einer + QEMU-Umgebung ist der Client ein GDB- (oder LLDB-)Prozess und der Server + der QEMU-Prozess, auf dem auch das eingebettete Programm läuft. +], +ja: [ + リモートデバッグは、クライアントとサーバからなります。QEMUのセットアップで、 + クライアントはGDB(またはLLDB)プロセスとなり、サーバは組込みプログラムを実行しているQEMUプロセスとなります。 +], +zh: [ + 远程调试涉及一个客户端和一个服务器。在QEMU的情况中,客户端将是一个GDB(或者LLDM)进程且服务器将会是运行着嵌入式程序的QEMU进程。 + +])) + +#tr(( +en: [ + In this section we'll use the `hello` example we already compiled. +], +de: [ + In diesem Abschnitt verwenden wir das bereits kompilierte Beispiel `hello`. +], +ja: [ + このセクションでは、コンパイル済みの`hello`の例を使用します。 +], +zh: [ + 在这部分,我们要使用我们已经编译的 `hello` 示例。 +])) + +#tr(( +en: [ + The first debugging step is to launch QEMU in debugging mode: +], +de: [ + Der erste Schritt beim Debuggen besteht darin, QEMU im Debugging-Modus zu starten: +], +ja: [ + 最初のデバッグステップは、QEMUをデバッグモードで起動することです。 +], +zh: [ + 调试的第一步是在调试模式中启动QEMU: +])) + +```console +qemu-system-arm \ + -cpu cortex-m3 \ + -machine lm3s6965evb \ + -nographic \ + -semihosting-config enable=on,target=native \ + -gdb tcp::3333 \ + -S \ + -kernel target/thumbv7m-none-eabi/debug/examples/hello +``` + +#tr(( +en: [ + This command won't print anything to the console and will block the + terminal. We have passed two extra flags this time: + - `-gdb tcp::3333`. This tells QEMU to wait for a GDB connection on TCP + port 3333. + - `-S`. This tells QEMU to freeze the machine at startup. Without this + the program would have reached the end of main before we had a chance + to launch the debugger! +], +de: [ + Dieser Befehl gibt nichts auf der Konsole aus und blockiert das + Terminal. Wir haben diesmal zwei zusätzliche Flags übergeben: + - `-gdb tcp::3333`. Damit wird QEMU angewiesen, auf eine GDB-Verbindung + über den TCP-Port 3333 zu warten. + - `-S`. Damit wird QEMU angewiesen, die Maschine beim Start + einzufrieren. Ohne diese Option hätte das Programm das Ende der + Funktion `main` erreicht, bevor wir die Gelegenheit gehabt hätten, den + Debugger zu starten! +], +ja: [ + このコマンドは、コンソールに何も表示せず、端末をブロックします。 + ここでは2つの追加フラグを渡しています。 + - `-gdb tcp::3333`。QEMUがTCPポート3333番で、GDBコネクションを待つようにします。 + - `-S`。QEMUが、起動時に、マシンをフリーズします。このフラグがないと、 + デバッガを起動する前に、プログラムがmain関数の終わりに到達してしまいます。 +], +zh: [ + 这个命令将不打印任何东西到调试台上,且将会阻塞住终端。此刻我们还传递了两个额外的标志。 + - `-gdb tcp::3333`。这告诉QEMU在3333的TCP端口上等待一个GDB连接。 + - `-S`。这告诉QEMU在启动时,冻结机器。没有这个,在我们有机会启动调试器之前,程序有可能已经到达了主程序的底部了! +])) + +#tr(( +en: [ + Next we launch GDB in another terminal and tell it to load the debug + symbols of the example: +], +de: [ + Als Nächstes starten wir GDB in einem anderen Terminal und weisen es an, + die Debug-Symbole des Beispiels zu laden: +], +ja: [ + 次に別の端末でGDBを起動し、`hello`の例のデバッグシンボルをロードします。 +], +zh: [ + 接下来我们在另一个终端启动GDB,且告诉它去加载示例的调试符号。 +])) + +```console +gdb-multiarch -q target/thumbv7m-none-eabi/debug/examples/hello +``` + +#tr(( +en: [ + *NOTE*: you might need another version of gdb instead of + `gdb-multiarch` depending on which one you installed in the installation + chapter. This could also be `arm-none-eabi-gdb` or just `gdb`. +], +de: [ + *HINWEIS*: Möglicherweise benötigen Sie anstelle von + `gdb-multiarch` eine andere Version von gdb, je nachdem, welche Sie im + Kapitel zur Installation installiert haben. Dies könnte auch + `arm-none-eabi-gdb` oder einfach nur `gdb` sein. +], +zh: [ + *注意*: 你可能需要另一个gdb版本而不是 + `gdb-multiarch`,取决于你在安装章节中安装了哪个。这个可能是 + `arm-none-eabi-gdb` 或者只是 `gdb`。 +])) + +#tr(( +en: [ + Then within the GDB shell we connect to QEMU, which is waiting for a + connection on TCP port 3333. +], +de: [ + Anschließend stellen wir innerhalb der GDB-Shell eine Verbindung zu QEMU + her, das auf dem TCP-Port 3333 auf eine Verbindung wartet. +], +zh: [ + 然后在GDB shell中,我们连接QEMU,QEMU正在等待一个在3333 + TCP端口上的连接。 +])) + +```console +target remote :3333 +``` + +```text +Remote debugging using :3333 +Reset () at $REGISTRY/cortex-m-rt-0.6.1/src/lib.rs:473 +473 pub unsafe extern "C" fn Reset() -> ! { +``` + +#tr(( +en: [ + You'll see that the process is halted and that the program counter is + pointing to a function named `Reset`. That is the reset handler: what + Cortex-M cores execute upon booting. +], +de: [ + Sie werden feststellen, dass der Prozess angehalten wurde und der + Programmzähler auf eine Funktion namens `Reset` zeigt. Das ist der + Reset-Handler: das, was Cortex-M-Kerne beim Booten ausführen. +], +zh: [ + 你将看到,进程被挂起了,程序计数器正指向一个名为 `Reset` 的函数。那是 + reset 句柄:Cortex-M 内核在启动时执行的中断函数。 +])) + +#quote(block: true)[ +#tr(( +en: [ + Note that on some setup, instead of displaying the line + `Reset () at $REGISTRY/cortex-m-rt-0.6.1/src/lib.rs:473` as shown above, + gdb may print some warnings like: +], +de: [ + Beachten Sie, dass gdb in manchen Konfigurationen anstelle der oben + gezeigten Zeile `Reset () at $REGISTRY/cortex-m-rt-0.6.1/src/lib.rs:473` + möglicherweise Warnungen wie die folgenden ausgibt: +], +zh: [ + 注意在一些配置中,可能不会像上面一样,显示`Reset() at $REGISTRY/cortex-m-rt-0.6.1/src/lib.rs:473`,gdb可能打印一些警告,比如: +])) + +`core::num::bignum::Big32x40::mul_small () at src/libcore/num/bignum.rs:254` +`src/libcore/num/bignum.rs: No such file or directory.` + +#tr(( +en: [ + That's a known glitch. You can safely ignore those warnings, you're most + likely at Reset(). +], +de: [ + Das ist ein bekannter Fehler. Sie können diese Warnungen getrost + ignorieren, da Sie sich höchstwahrscheinlich bei `Reset()` befinden. +], +zh: [ + 那是一个已知的小bug,你可以安全地忽略这些警告,你非常大可能已经进入Reset()了。 +])) +] + +#tr(( +en: [ + This reset handler will eventually call our main function. Let's skip + all the way there using a breakpoint and the `continue` command. To set + the breakpoint, let's first take a look where we would like to break in + our code, with the `list` command. +], +de: [ + Dieser Reset-Handler ruft schließlich unsere Hauptfunktion auf. Lassen + Sie uns den gesamten Weg dorthin mithilfe eines Haltepunkts und des + Befehls `continue` überspringen. Um den Haltepunkt zu setzen, schauen + wir uns zunächst mit dem Befehl `list` an, an welcher Stelle in unserem + Code wir anhalten möchten. +], +zh: [ + 这个reset句柄最终将调用我们的主函数,让我们使用一个断点和`continue`命令跳过所有的步骤。为了设置断点,让我们首先看下我们想要在我们代码哪里打断点,使用`list`指令 +])) + +```console +list main +``` + +#tr(( +en: [ + This will show the source code, from the file examples/hello.rs. +], +de: [ + Dadurch wird der Quellcode aus der Datei „examples/hello.rs" angezeigt. +], +zh: [ + 这将显示从examples/hello.rs文件来的源代码。 +])) + +```text +6 use panic_halt as _; +7 +8 use cortex_m_rt::entry; +9 use cortex_m_semihosting::{debug, hprintln}; +10 +11 #[entry] +12 fn main() -> ! { +13 hprintln!("Hello, world!").unwrap(); +14 +15 // exit QEMU +``` + +#tr(( +en: [ + We would like to add a breakpoint just before the "Hello, world!", which + is on line 13. We do that with the `break` command: +], +de: [ + Wir möchten einen Haltepunkt direkt vor „Hello, world!" setzen, das sich + in Zeile 13 befindet. Dazu verwenden wir den Befehl `break`: +], +zh: [ + 我们想要在"Hello, + world!"之前添加一个断点,在13行那里。我们可以使用`break`命令 +])) + +```console +break 13 +``` + +#tr(( +en: [ + We can now instruct gdb to run up to our main function, with the + `continue` command: +], +de: [ + Wir können gdb nun mit dem Befehl `continue` anweisen, bis zu unserer + Hauptfunktion weiterzulaufen: +], +zh: [ + 我们现在能使用`continue`命令指示gdb运行到我们的主函数。 +])) + +```console +continue +``` + +```text +Continuing. + +Breakpoint 1, hello::__cortex_m_rt_main () at examples\hello.rs:13 +13 hprintln!("Hello, world!").unwrap(); +``` + +#tr(( +en: [ + We are now close to the code that prints "Hello, world!". Let's move + forward using the `next` command. +], +de: [ + Wir sind nun fast bei dem Code angelangt, der „Hello, world!" ausgibt. + Machen wir weiter mit dem Befehl `next`. +], +ja: [ + 「Hello, world!」を表示するコードに近づいてきました。 + `next`コマンドを使って、先へ進みましょう。 +], +zh: [ + 我们现在靠近打印"Hello, world!"的代码。让我们使用`next`命令继续前进。 +])) + +```console +next +``` + +```text +16 debug::exit(debug::EXIT_SUCCESS); +``` + +#tr(( +en: [ + At this point you should see "Hello, world!" printed on the terminal + that's running `qemu-system-arm`. +], +de: [ + An dieser Stelle sollte auf dem Terminal, auf dem `qemu-system-arm` + läuft, „Hello, world!" angezeigt werden. +], +ja: [ + この時点で、`qemu-system-arm`を実行している端末に「Hello, + world」が表示されるはずです。 +], +zh: [ + 在这里,你应该看到 "Hello, world!" 被打印到正在运行 `qemu-system-arm` 的终端上。 +])) + +```text +$ qemu-system-arm (..) +Hello, world! +``` + +#tr(( +en: [ + Calling `next` again will terminate the QEMU process. +], +de: [ + Ein erneuter Aufruf von `next` beendet den QEMU-Prozess. +], +ja: [ + もう1度`next`を実行すると、QEMUプロセスが終了します。 +], +zh: [ + 再次调用`next`将会终止QEMU进程。 +])) + +```console +next +``` + +```text +[Inferior 1 (Remote target) exited normally] +``` + +#tr(( +en: [ + You can now exit the GDB session. +], +de: [ + Sie können die GDB-Sitzung nun beenden. +], +ja: [ + これでGDBセッションを終了できます。 +], +zh: [ + 你现在能退出GDB的会话了。 +])) + +```console +quit +``` diff --git a/typ/start/registers.typ b/typ/start/registers.typ new file mode 100644 index 00000000..1dad1b72 --- /dev/null +++ b/typ/start/registers.typ @@ -0,0 +1,826 @@ +#import "../config.typ": * + +#h1((en: [Memory Mapped Registers], + de: [Im Speicher abgebildete Register], + ja: [メモリマップドレジスタ], + zh: [存储映射的寄存器(Memory-Mapped Registers)], +), offset: whole, ) + + +#tr(( +en: [ + Embedded systems can only get so far by executing normal Rust code and + moving data around in RAM. If we want to get any information into or out + of our system (be that blinking an LED, detecting a button press or + communicating with an off-chip peripheral on some sort of bus) we're + going to have to dip into the world of Peripherals and their 'memory + mapped registers'. +], +de: [ + Bei eingebetteten Systemen stößt man mit der reinen Ausführung von + Standard-Rust-Code und dem Verschieben von Daten im Arbeitsspeicher + (RAM) irgendwann an Grenzen. Wenn wir Informationen in das System + einspeisen oder daraus ausgeben wollen -- sei es das Blinken einer LED, + das Erkennen eines Tastendrucks oder die Kommunikation mit einer + externen Peripheriekomponente über einen Bus --, müssen wir uns mit der + Welt der Peripherieeinheiten und deren „im Speicher abgebildeten + Registern" (memory-mapped registers) befassen. +], +ja: [ + 組込みシステムでは、通常のRustコードを実行し、データをRAM内で移動させるだけではたいしたことはできません。 + LEDの点滅やボタンの押下検出、もしくは、バス上のオフチップペリフェラルとの通信など、 + システムが情報を入出力するには、ペリフェラルとその「メモリマップドレジスタ」の世界に足を踏み入れる必要があります。 +], +zh: [ + 嵌入式系统想要继续执行下去,只有通过执行常规的Rust代码并在RAM间移动数据才行。如果我们想要获取或者发出信息(点亮一个LED,发现一个按钮按下或者在总线上与芯片外设通信),我们不得不深入了解外设和它们的"存储映射的寄存器"。 +])) + +#let ln_cortex = link("https://crates.io/crates/cortex-m")[cortex-m] +#let ln_tm4c123x = link("https://crates.io/crates/tm4c123x")[tm4c123x] +#let ln_f30x = link("https://crates.io/crates/stm32f30x")[stm32f30x] +#let ln_hal = link("https://crates.io/crates/embedded-hal")[embedded-hal] +#let ln_f3 = link("https://crates.io/crates/stm32f3-discovery")[stm32f3-discovery] +#tr(( +en: [ + You may well find that the code you need to access the peripherals in + your micro-controller has already been written, at one of the following + levels: + - Micro-architecture Crate - This sort of crate handles any useful + routines common to the processor core your microcontroller is using, + as well as any peripherals that are common to all micro-controllers + that use that particular type of processor core. For example the + #ln_cortex crate gives you + functions to enable and disable interrupts, which are the same for all + Cortex-M based micro-controllers. It also gives you access to the + 'SysTick' peripheral included with all Cortex-M based + micro-controllers. + - Peripheral Access Crate (PAC) - This sort of crate is a thin wrapper + over the various memory-wrapper registers defined for your particular + part-number of micro-controller you are using. For example, + #ln_tm4c123x for the Texas Instruments Tiva-C TM4C123 series, or + #ln_f30x for the ST-Micro STM32F30x series. + Here, you'll be interacting with the + registers directly, following each peripheral's operating instructions + given in your micro-controller's Technical Reference Manual. + - HAL Crate - These crates offer a more user-friendly API for your + particular processor, often by implementing some common traits defined + in #ln_hal. For + example, this crate might offer a `Serial` struct, with a constructor + that takes an appropriate set of GPIO pins and a baud rate, and offers + some sort of `write_byte` function for sending data. See the chapter + on #link()[Portability] for more information + on #ln_hal. + - Board Crate - These crates go one step further than a HAL Crate by + pre-configuring various peripherals and GPIO pins to suit the specific + developer kit or board you are using, such as #ln_f3 + for the STM32F3DISCOVERY board. +], +ja: [ + マイクロコントローラのペリフェラルにアクセスするためのコードが、次のいずれかのレベルで、既に書かれています。 + - マイクロアーキテクチャクレート。この種のクレートは、マイクロコントローラに搭載されているプロセッサコアで共通となる便利なルーチンを扱っています。 + また、特定のプロセッサコアを使用する全てのマイクロコントローラに共通のペリフェラルも取り扱います。 + 例えば、#ln_cortex;クレートは、割り込みの有効化と無効化を行う関数を提供しています。これは全てのCortex-Mベースマイクロコントローラで同じものです。 + #ln_cortex;クレートは、「SysTick」ペリフェラルへのアクセスも提供しています。このペリフェラルは、全てのCortex-Mベースマイクロコントローラに搭載されています。 + - ペリフェラルアクセスクレート(PAC)。この種のクレートは、薄いラッパーです。特定の型番のマイクロコントローラに対して定義されている、 + 様々なメモリマップドレジスタのラッパーを提供します。例えば、テキサスインスツルメンツのTiva-C + TM4C123シリーズ向けの#ln_tm4c123x;クレートや、 + STマイクロのSTM32F30xシリーズ向けの#ln_f30x;クレートです。マイクロコントローラのテクニカルリファレンスマニュアルに記載されている各ペリフェラルの操作手順に従って、 + レジスタと直接やり取りします。 + - HALクレート。これらのクレートは、特定のプロセッサに対して、よりユーザフレンドリなAPIを提供しています。#ln_hal;で定義されている共通のトレイトを使って実装されていることが多いです。 + 例えば、このクレートは、`Serial`構造体を提供しているでしょう。そのコンストラクタは、適切なGPIOピンの一式とボーレートを引数に取ります。そして、データを送信するための`write_byte`関数一式を提供します。 + #ln_hal;に関する詳細は、#link()[移植性]の章を参照して下さい。 + - ボードクレート。これらのクレートは、HALクレートのさらに一歩先を進んでいます。これらは、STM32F3DISCOVERYボード向けの#ln_f3;のように、 + 特定の開発キットやボード向けに、様々なペリフェラルとGPIOピンを事前に設定してあります。 +], +de: [ + Möglicherweise stellen Sie fest, dass der für den Zugriff auf die + Peripherie Ihres Mikrocontrollers erforderliche Code bereits auf einer + der folgenden Ebenen implementiert wurde: + - Mikroarchitektur-Crate -- Diese Art von Crate verwaltet alle + nützlichen Routinen, die dem Prozessorkern gemeinsam sind, den Ihr + Mikrocontroller verwendet, sowie alle Peripheriegeräte, die allen + Mikrocontrollern gemeinsam sind, die diesen bestimmten + Prozessorkerntyp verwenden. Das #ln_cortex - Crate bietet + Ihnen beispielsweise Funktionen zum Aktivieren und Deaktivieren von + Interrupts, die für alle Cortex-M-basierten Mikrocontroller gleich + sind. Außerdem erhalten Sie Zugriff auf die „SysTick"-Peripherie, die + in allen Cortex-M-basierten Mikrocontrollern enthalten ist. + - Peripheral Access Crate (PAC) -- Bei dieser Art von Crate handelt es + sich um einen schlanken Adapter (Wrapper) für die verschiedenen + Register, die für das spezifische Mikrocontroller-Modell definiert + sind, das Sie verwenden. Zum Beispiel, #ln_tm4c123x für die + Tiva-C-TM4C123-Serie von Texas Instruments oder #ln_f30x für die + STM32F30x-Serie von STMicroelectronics. Hierbei greifen Sie direkt auf + die Register zu und befolgen dabei die Betriebshinweise für die + jeweilige Peripherieeinheit, wie sie im technischen Referenzhandbuch + Ihres Mikrocontrollers beschrieben sind. + - HAL-Crate -- Diese Crates bieten eine benutzerfreundlichere API für + einen bestimmten Prozessor, häufig durch die Implementierung gängiger + Traits, die in #ln_hal definiert + sind. So könnte ein solches Crate beispielsweise eine + `Serial`-Struktur bereitstellen, deren Konstruktor eine geeignete + Kombination aus GPIO-Pins sowie eine Baudrate entgegennimmt und eine + Funktion wie `write_byte` zum Senden von Daten anbietet. Weitere + Informationen zu #ln_hal finden + Sie im Kapitel über #link()[Portabilität]. + - Board-Crate -- Diese Crates gehen noch einen Schritt weiter als + HAL-Crates, indem sie verschiedene Peripheriekomponenten und GPIO-Pins + passend für das jeweils verwendete Entwickler-Kit oder Board + vorkonfigurieren -- wie zum Beispiel + #ln_f3 für das STM32F3DISCOVERY-Board. +], +zh: [ + 你可能会发现,访问你的微控制器外设所需要的代码,已经存在于下面的某个抽象层中了。 + - Micro-architecture Crate(微架构库) - + 这个库拥有任何对于微控制器的处理器内核来说经常会用到的程序,也包括在这些微控制器中的通用外设。比如 + #ln_cortex + crate提供给你可以使能和关闭中断的函数,其对于所有的Cortex-M微控制器都是一样的。它也提供你访问'SysTick'外设的能力,在所有的Cortex-M微控制器中都包括了这个外设功能。 + - Peripheral Access Crate(PAC)(外设访问库) - + 这个库是对各种存储器封装的寄存器再进行的一次浅陋封装,特定于所使用的微控制器的产品号。比如,#ln_tm4c123x;针对TI的Tiva-C + TM4C123系列,#ln_f30x;针对ST的STM32F30x系列。这块,根据微控制器的技术手册写的每个外设操作指令,直接和寄存器交互。 + - HAL Crate - + 这些crates为你的处理器提供了一个更友好的API,通常是通过实现在#ln_hal;中定义的一些常用的traits来实现的。比如,这个crate可能提供一个`Serial`结构体,它的构造函数需要一组合适的GPIO端口和一个波特率,它为发送数据提供了 + `write_byte` 函数。查看 #link()[可移植性] + 可以看到更多关于 + #ln_hal 的信息。 + - Board Crate(开发板库) - + 这些Crate通过预配置不同的外设和GPIO管脚再进行了一层抽象以适配你正在使用的特定的开发者工具或者开发板,比如对于STM32F3DISCOVERY开发板来说,是#ln_f3 +])) + += #tr(( + en: [Board Crate], + de: [Board Crate], + zh: [开发板Crate (Board Crate)], +)) + +#tr(( +en: [ + A board crate is the perfect starting point, if you're new to embedded + Rust. They nicely abstract the HW details that might be overwhelming + when starting studying this subject, and makes standard tasks easy, like + turning a LED on or off. The functionality it exposes varies a lot + between boards. Since this book aims at staying hardware agnostic, the + board crates won't be covered by this book. +], +de: [ + Eine Board-Crate ist der ideale Ausgangspunkt für den Einstieg in + Embedded Rust. Sie abstrahiert auf angenehme Weise die Hardware-Details, + die Anfänger in diesem Bereich oft überfordern können, und erleichtert + Standardaufgaben wie das Ein- oder Ausschalten einer LED. Der + bereitgestellte Funktionsumfang variiert jedoch stark von Board zu + Board. Da dieses Buch hardwareunabhängig bleiben soll, werden + Board-Crates hier nicht behandelt. +], +zh: [ + 如果你是嵌入式Rust新手,board + crate是一个完美的开始。它们很好地抽象出了,在开始学习这个项目时,需要耗费心力了解的硬件细节,使得标准工作,像是打开或者关闭LED,变得简单。不同的板子间,它们提供的功能变化很大。因为这本书是不假设我们使用的是何种板子,所以这本书不会提到board + crate。 +])) + +#let url_disco = "https://rust-embedded.github.io/discovery/" +#tr(( +en: [ + If you want to experiment with the STM32F3DISCOVERY board, it is highly + recommended to take a look at the #ln_f3 + board crate, which provides functionality to blink the board LEDs, + access its compass, bluetooth and more. The + #link(url_disco)[Discovery] book + offers a great introduction to the use of a board crate. +], +de: [ + Wenn Sie mit dem STM32F3DISCOVERY-Board experimentieren möchten, ist es + sehr empfehlenswert, sich das #ln_f3;-Board-Crate + anzusehen; dieses bietet Funktionen, um die LEDs des Boards blinken zu + lassen sowie auf den Kompass, Bluetooth und mehr zuzugreifen. Das + #link(url_disco)[Discovery]-Buch bietet eine hervorragende + Einführung in die Verwendung eines Board-Crates. +], +zh: [ + 如果你想要用STM32F3DISCOVERY开发板做实验,强烈建议看一下#ln_f3;开发板crate,它提供了闪烁LEDs,访问它的指南针,蓝牙和其它的功能。#link(url_disco)[Discovery]书对于一个board + crate的用法提供一个很好的介绍。 +])) + +#tr(( +en: [ + But if you're working on a system that doesn't yet have dedicated board + crate, or you need functionality not provided by existing crates, read + on as we start from the bottom, with the micro-architecture crates. +], +de: [ + Wenn Sie jedoch an einem System arbeiten, für das es noch kein + dediziertes Board-Crate gibt, oder wenn Sie Funktionen benötigen, die + von vorhandenen Crates nicht abgedeckt werden, lesen Sie weiter: Wir + beginnen ganz unten, bei den Mikroarchitektur-Crates. +], +zh: [ + 但是如果你正在使用一个还没有提供专用的board + crate的系统,或者你需要的一些功能,现存的crates不提供,那我们需要从底层的微架构crates开始。 +])) + += #tr(( + en: [Micro-architecture crate], + de: [Mikroarchitektur-Crate], + zh: [Micro-architecture crate], +)) + +#tr(( +en: [ + Let's look at the SysTick peripheral that's common to all Cortex-M based + micro-controllers. We can find a pretty low-level API in the + #ln_cortex crate, and we can use it like this: +], +de: [ + Betrachten wir die SysTick-Peripherie, die allen Mikrocontrollern auf + Cortex-M-Basis gemeinsam ist. Im #ln_cortex;-Crate finden wir + eine recht hardwarenahe API, die sich folgendermaßen verwenden lässt: +], +ja: [ + 全てのCortex-Mマイクロコントローラで共通のSysTickペリフェラルから見ていきましょう。 + #ln_cortex;クレートにはかなり低レベルなAPIがあり、次のように使うことができます。 +], +zh: [ + 让我们看一下SysTick外设,SysTick外设存在于所有的Cortex-M微控制器中。我们能在#ln_cortex + crate中找到一个相当底层的API,我们能像这样使用它: +])) + +#raw(block: true, lang: "rust", +"#![no_std] +#![no_main] +use cortex_m::peripheral::{syst, Peripherals}; +use cortex_m_rt::entry; +use panic_halt as _; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take().unwrap(); + let mut systick = peripherals.SYST; + systick.set_clock_source(syst::SystClkSource::Core); + systick.set_reload(1_000); + systick.clear_current(); + systick.enable_counter(); + while !systick.has_wrapped() { + // " + ts(( + en: "Loop", + ja: "ループ", + )) + " + } + + loop {} +} +") + +#tr(( +en: [ + The functions on the `SYST` struct map pretty closely to the + functionality defined by the ARM Technical Reference Manual for this + peripheral. There's nothing in this API about 'delaying for X + milliseconds' - we have to crudely implement that ourselves using a + `while` loop. Note that we can't access our `SYST` struct until we have + called `Peripherals::take()` - this is a special routine that guarantees + that there is only one `SYST` structure in our entire program. For more + on that, see the #link()[Peripherals] section. +], +de: [ + Die Funktionen der `SYST`-Struktur entsprechen weitgehend der + Funktionalität, die im ARM Technical Reference Manual für diese + Peripherieeinheit definiert ist. Diese API bietet keine Möglichkeit, + eine Verzögerung von „X Millisekunden" direkt umzusetzen; wir müssen + dies stattdessen selbst auf einfache Weise mittels einer + `while`-Schleife implementieren. Beachten Sie, dass wir erst auf die + `SYST`-Struktur zugreifen können, nachdem wir `Peripherals::take()` + aufgerufen haben. Dabei handelt es sich um eine spezielle Routine, die + sicherstellt, dass im gesamten Programm nur eine einzige `SYST`-Instanz + existiert. Weitere Informationen dazu finden Sie im Abschnitt + "#link()[Peripherien]". +], +ja: [ + `SYST`構造体の関数は、ARMテクニカルリファレンスマニュアルにおいて、このペリフェラルに定義されている機能と非常によく似ています。 + 「Xミリ秒遅延」といった具合のAPIはありません。`while`ループを使って愚直に実装する必要があります。`Peripherals::take()`を呼び出すまでは、 + `SYST`構造体にアクセスできないことに注意して下さい。これは、プログラム全体で唯一の`SYST`構造体が存在することを保証する特別な手順です。 + 詳しくは、#link()[ペリフェラル]セクションをご覧下さい。 +], +zh: [ + `SYST`结构体上的功能,相当接近ARM技术手册为这个外设定义的功能。在这个API中没有关于 + '延迟X毫秒' 的功能 - 我们不得不通过使用一个 `while` + 循环来粗略地实现它。注意,我们调用了`Peripherals::take()`才能访问我们的`SYST`结构体 + - 这是一个特别的程序,保障了在我们的整个程序中只存在一个`SYST`结构体实例,更多的信息可以看#link()[外设]部分。 +])) + += #tr(( + en: [Using a Peripheral Access Crate (PAC)], + de: [Verwendung eines Peripheral Access Crate (PAC)], + ja: [ペリフェラルアクセスクレート(PAC)の使用], + zh: [使用一个外设访问Crate (PAC)], +)) + +#tr(( +en: [ + We won't get very far with our embedded software development if we + restrict ourselves to only the basic peripherals included with every + Cortex-M. At some point, we're going to need to write some code that's + specific to the particular micro-controller we're using. In this + example, let's assume we have an Texas Instruments TM4C123 - a middling + 80MHz Cortex-M4 with 256 KiB of Flash. We're going to pull in the + #ln_tm4c123x crate to make use of this chip. +], +de: [ + Bei der Entwicklung von Embedded-Software kommen wir nicht weit, wenn + wir uns auf die grundlegenden Peripheriekomponenten beschränken, die in + jedem Cortex-M enthalten sind. Irgendwann müssen wir Code schreiben, der + speziell auf den verwendeten Mikrocontroller zugeschnitten ist. Gehen + wir in diesem Beispiel davon aus, dass wir einen Texas Instruments + TM4C123 verwenden -- einen soliden 80-MHz-Cortex-M4 mit 256 KiB + Flash-Speicher. Um diesen Chip nutzen zu können, binden wir das + #ln_tm4c123x;-Crate ein. +], +ja: [ + 全てのCortex−Mに搭載されている基本的なペリフェラルのみに限定するのであれば、組込みソフトウェア開発はあまり進まないでしょう。 + どこかの時点で、使用している特定のマイクロコントローラ固有のコードを書く必要があります。今回の例では、テキサスインスツルメンツのTM4C123があるとしましょう。 + TM4C123はミドルレンジのマイクロコントローラで、80MHzのCortex-M4と256 + KiBのフラッシュメモリが搭載されています。 + このチップを利用するために、#ln_tm4c123x;クレートを取得します。 +], +zh: [ + 如果我们把自己只局限于每个Cortex-M拥有的基本外设,那我们的嵌入式软件开发将不会走得太远。我们准备需要写一些特定于我们正在使用的微控制器的代码。在这个例子里,让我们假设我们有一个TI的TM4C123 + - 一个有256KiB + Flash的中等规模的80MHz的Cortex-M4。我们用#ln_tm4c123x + crate去使用这个芯片。 +])) + +#raw(block: true, lang: "rust", +"#![no_std] +#![no_main] + +use panic_halt as _; // " + ts(( + en: "panic handler", + ja: "パニックハンドラ", + )) + " + +use cortex_m_rt::entry; +use tm4c123x; + +#[entry] +pub fn init() -> (Delay, Leds) { + let cp = cortex_m::Peripherals::take().unwrap(); + let p = tm4c123x::Peripherals::take().unwrap(); + + let pwm = p.PWM0; + pwm.ctl.write(|w| w.globalsync0().clear_bit()); + // " + ts(( + en: "Mode = 1 => Count up/down mode", + ja: "モード1は カウントアップ/ダウンモード", + )) + " + pwm._2_ctl.write(|w| w.enable().set_bit().mode().set_bit()); + pwm._2_gena.write(|w| w.actcmpau().zero().actcmpad().one()); + // " + ts(( + en: "528 cycles (264 up and down) = 4 loops per video line (2112 cycles)", + ja: "528サイクル(264カウントアップとカウントダウン)は、ビデオラインごとに4ループ(2112サイクル)", + )) + " + pwm._2_load.write(|w| unsafe { w.load().bits(263) }); + pwm._2_cmpa.write(|w| unsafe { w.compa().bits(64) }); + pwm.enable.write(|w| w.pwm4en().set_bit()); +} +") + +#let ln_svd2rust = link("https://crates.io/crates/svd2rust")[svd2rust] +#tr(( +en: [ + We've accessed the `PWM0` peripheral in exactly the same way as we + accessed the `SYST` peripheral earlier, except we called + `tm4c123x::Peripherals::take()`. As this crate was auto-generated using + #ln_svd2rust, the access + functions for our register fields take a closure, rather than a numeric + argument. While this looks like a lot of code, the Rust compiler can use + it to perform a bunch of checks for us, but then generate machine-code + which is pretty close to hand-written assembler! Where the + auto-generated code isn't able to determine that all possible arguments + to a particular accessor function are valid (for example, if the SVD + defines the register as 32-bit but doesn't say if some of those 32-bit + values have a special meaning), then the function is marked as `unsafe`. + We can see this in the example above when setting the `load` and `compa` + sub-fields using the `bits()` function. +], +de: [ + Wir haben auf die `PWM0`-Peripherie auf genau dieselbe Weise zugegriffen + wie zuvor auf die `SYST`-Peripherie, mit dem Unterschied, dass wir + `tm4c123x::Peripherals::take()` aufgerufen haben. Da dieses Crate + mithilfe von #ln_svd2rust + automatisch generiert wurde, erwarten die Zugriffsfunktionen für unsere + Registerfelder einen Closure anstelle eines numerischen Arguments. Auch + wenn dies nach viel Code aussieht, kann der Rust-Compiler ihn nutzen, um + eine Reihe von Prüfungen für uns durchzuführen und anschließend + Maschinencode zu erzeugen, der handgeschriebenem Assemblercode sehr + nahekommt! Wenn der automatisch generierte Code nicht feststellen kann, + ob alle möglichen Argumente für eine bestimmte Zugriffsfunktion gültig + sind (zum Beispiel, wenn die SVD das Register als 32-Bit-Register + definiert, aber nicht angibt, ob bestimmte dieser 32-Bit-Werte eine + besondere Bedeutung haben), wird die Funktion als `unsafe` markiert. + Dies lässt sich im obigen Beispiel beim Setzen der Unterfelder `load` + und `compa` mittels der Funktion `bits()` beobachten. +], +ja: [ + 先ほど`SYST`にアクセスした時と全く同じ方法で、`PWM0`ペリフェラルにアクセスします。違う点は、`tm4c123x::Peripherals::take()`を呼ぶことです。 + このクレートは、#link("https://crates.io/crates/svd2rust")[svd2rust]を使って自動生成されたものです。レジスタフィールドのアクセス関数は、数値の引数ではなく、クロージャを取ります。 + このコードは量が多いように見えますが、Rustコンパイラは一連のチェックを実行し、手書きのアセンブラに近いマシンコードを生成します。 + 自動生成されたコードが、特定のアクセサ関数への全引数が有効であることを判断できない場合、その関数は`unsafe`とマークされます。 + 例えば、SVDがレジスタを32ビットと定義しているが、それらの32ビット値の一部が特別な意味を持つかどうか、記述していない場合です。 + 上記の例では、`bits()`関数を使って`load`と`compa`サブフィールドを設定する時に、`unsafe`をマークしています。 +], +zh: [ + 我们访问 `PWM0` 外设的方法和我们之前访问 `SYST` + 的方法一样,除了我们调用的是 `tm4c123x::Peripherals::take()` + 之外。因为这个crate是使用#ln_svd2rust;自动生成的,访问我们寄存器位段的函数的参数是一个闭包,而不是一个数值参数。虽然这看起来像是有了更多的代码,但是Rust编译器能使用这个闭包为我们执行一系列检查,且产生的机器码十分接近手写的汇编码!如果自动生成的代码不能确保某个访问函数其所有可能的参数都能发挥作用(比如,如果寄存器被SVD定义为32位,但是没有说明某些32位值是否有特殊作用),那么该函数需要被标记为 + `unsafe` 。我们能在上面看到这样的例子,我们使用 `bits()` 函数设置 `load` 和 `compa` 子域。 +])) + +== #tr(( + en: [Reading], + de: [Lesen], + ja: [読み込み], + zh: [Reading], +)) + +#let url_struct_r = "https://docs.rs/tm4c123x/0.7.0/tm4c123x/pwm0/ctl/struct.R.html" +#tr(( +en: [ + The `read()` function returns an object which gives read-only access to + the various sub-fields within this register, as defined by the + manufacturer's SVD file for this chip. You can find all the functions + available on special `R` return type for this particular register, in + this particular peripheral, on this particular chip, in the + #link(url_struct_r)[tm4c123x documentation]. +], +de: [ + Die Funktion `read()` gibt ein Objekt zurück, das schreibgeschützten + Zugriff auf die verschiedenen Teilfelder dieses Registers gewährt -- + entsprechend der vom Hersteller für diesen Chip bereitgestellten + SVD-Datei. Alle für den speziellen Rückgabetyp `R` dieses spezifischen + Registers (innerhalb der jeweiligen Peripherieeinheit auf diesem Chip) + verfügbaren Funktionen finden Sie in der + #link(url_struct_r)[tm4c123x-Dokumentation]. +], +ja: [ + `read()`関数は、メーカーのSVDファイルで定義されている通り、レジスタ内の様々なサブフィールドに対して、読み込み専用のアクセスオブジェクトを返します。 + 特定チップ上にある、特定ペリフェラルの、特定レジスタに対して、固有の返り値`R`型があり、このR型で使える全ての関数は、#link(url_struct_r)[tm4c123xドキュメント]で見ることができます。 +], +zh: [ + `read()` + 函数返回一个对象,这个对象提供了对这个寄存器中不同子域的只读访问,由厂商提供的这个芯片的SVD文件定义。在 + #link(url_struct_r)[tm4c123x documentation] + 中你能找到在这个特别的返回类型 `R` + 上所有可用的函数,其与特定芯片中的特定外设的特定寄存器有关。 +])) + +#raw(block: true, lang: "rust", +"if pwm.ctl.read().globalsync0().is_set() { + // " + ts(( + en: "Do a thing", + de: "Tu etwas", + ja: "処理をする", + )) + " +} +") + +== #tr(( + en: [Writing], + de: [Schreiben], + ja: [書き込み], + zh: [Writing], +)) + +#let url_struct_w = "https://docs.rs/tm4c123x/0.7.0/tm4c123x/pwm0/ctl/struct.W.html" +#tr(( +en: [ + The `write()` function takes a closure with a single argument. Typically + we call this `w`. This argument then gives read-write access to the + various sub-fields within this register, as defined by the + manufacturer's SVD file for this chip. Again, you can find all the + functions available on the 'w' for this particular register, in this + particular peripheral, on this particular chip, in the + #link(url_struct_w)[tm4c123x documentation]. + Note that all of the sub-fields that we do not set will be set to a + default value for us - any existing content in the register will be lost. +], +de: [ + Die Funktion `write()` erwartet einen Closure mit einem einzelnen + Argument. Üblicherweise bezeichnen wir dieses als `w`. Dieses Argument + gewährt Lese- und Schreibzugriff auf die verschiedenen Teilfelder + innerhalb des Registers, wie sie in der SVD-Datei des Herstellers für + diesen Chip definiert sind. Auch hier gilt: Alle für `w` verfügbaren + Funktionen -- spezifisch für dieses Register, diese Peripherieeinheit + und diesen Chip -- finden Sie in der + #link(url_struct_w)[tm4c123x-Dokumentation]. + Beachten Sie, dass alle Teilfelder, die wir nicht explizit setzen, + automatisch auf einen Standardwert gesetzt werden; bereits vorhandene + Inhalte des Registers gehen dabei verloren. +], +ja: [ + `write()`関数は、単一引数のクロージャを取ります。通常は、この引数を`w`と呼びます。 + この引数は、チップメーカーがSVDファイルで定義している通り、様々なレジスタのサブフィールドへの読み書きアクセスを許可します。 + 特定チップ上にある、特定ペリフェラルの、特定レジスタに対して、`w`型で使える全ての関数も、#link(url_struct_w)[tm4c123xドキュメント]で見ることができます。 + 設定していない全てのサブフィールドは、デフォルト値に設定されます。レジスタの既存の内容は失われます。 +], +zh: [ + `write()`函数使用一个只有一个参数的闭包。通常我们把这个参数叫做 + `w`。然后这个参数提供对这个寄存器中不同的子域的读写访问,由厂商关于这个芯片的SVD文件提供。再一次,在 + #link(url_struct_w)[tm4c123x documentation] + 中你能找到 `W` + 所有可用的函数,其与特定芯片中的特定外设的特定寄存器有关。注意,所有我们没有设置的子域将会被设置成一个默认值 + - 将会丢失任何在这个寄存器中的现存的内容。 +])) + +```rust +pwm.ctl.write(|w| w.globalsync0().clear_bit()); +``` + +== #tr(( + en: [Modifying], + de: [Ändern], + ja: [修正], + zh: [Modifying], +)) + +#tr(( +en: [ + If we wish to change only one particular sub-field in this register and + leave the other sub-fields unchanged, we can use the `modify` function. + This function takes a closure with two arguments - one for reading and + one for writing. Typically we call these `r` and `w` respectively. The + `r` argument can be used to inspect the current contents of the + register, and the `w` argument can be used to modify the register contents. +], +de: [ + Wenn wir in diesem Register nur ein bestimmtes Teilfeld ändern und die + übrigen Teilfelder unverändert lassen möchten, können wir die Funktion + `modify` verwenden. Diese Funktion nimmt eine Closure mit zwei + Argumenten entgegen -- eines zum Lesen und eines zum Schreiben. + Üblicherweise bezeichnen wir diese als `r` beziehungsweise `w`. Das + Argument `r` dient dazu, den aktuellen Inhalt des Registers zu + betrachten, während das Argument `w` genutzt werden kann, um den + Registerinhalt zu ändern. +], +ja: [ + レジスタの特定のサブフィールドだけを変更して、残りのサブフィールドは変更したくない場合、`modify`関数を使えます。この関数は2引数のクロージャを取ります。 + 1つは読み込み用で、もう1つは書き込み用です。通常、これらの引数をそれぞれ、`r`と`w`と呼びます。 + `r`引数は、レジスタの現在の内容を調べるために使用されます。そして、`w`引数は、レジスタの内容を修正するために使用されます。 +], +zh: [ + 如果我们希望只改变这个寄存器中某个特定的子域而让其它子域不变,我们能使用`modify`函数。这个函数使用一个具有两个参数的闭包 + - 一个用来读取,一个用来写入。通常我们分别称它们为 `r` 和 `w` 。 `r` + 参数能被用来查看这个寄存器现在的内容,`w` 参数能被用来修改寄存器的内容。 +])) + +```rust +pwm.ctl.modify(|r, w| w.globalsync0().clear_bit()); +``` + +#tr(( +en: [ + The `modify` function really shows the power of closures here. In C, + we'd have to read into some temporary value, modify the correct bits and + then write the value back. This means there's considerable scope for error: +], +de: [ + Die Funktion `modify` veranschaulicht hier eindrucksvoll die + Leistungsfähigkeit von Closures. In C müssten wir den Wert zunächst in + eine temporäre Variable einlesen, die entsprechenden Bits ändern und den + Wert anschließend wieder zurückschreiben. Dies birgt ein erhebliches + Fehlerpotenzial: +], +ja: [ + `modify`関数は、クロージャの本領を発揮します。C言語では、一時変数に読み込み、正しいビットを修正してから、その値を書き戻す必要があります。 + これは、エラーが発生するかなりの余地があることを示しています。 +], +zh: [ + `modify` + 函数在这里真正展示了闭包的能量。在C中,我们经常需要读取一些临时值,修改成正确的比特,然后再把值写回。这意味着出现错误的范围非常大。 +])) + +#raw(block: true, lang: "c", +"uint32_t temp = pwm0.ctl.read(); +temp |= PWM0_CTL_GLOBALSYNC0; +pwm0.ctl.write(temp); +uint32_t temp2 = pwm0.enable.read(); +temp2 |= PWM0_ENABLE_PWM4EN; +pwm0.enable.write(temp); // " + ts(( + en: "Uh oh! Wrong variable!", + ja: "ああ!間違った変数です!", + zh: "哦 不! 错误的变量!", + )) + " +") + += #tr(( + en: [Using a HAL crate], + de: [Verwendung eines HAL-Crates], + ja: [HALクレートの使用], + zh: [使用一个HAL crate], +)) + +#tr(( +en: [ + The HAL crate for a chip typically works by implementing a custom Trait + for the raw structures exposed by the PAC. Often this trait will define + a function called `constrain()` for single peripherals or `split()` for + things like GPIO ports with multiple pins. This function will consume + the underlying raw peripheral structure and return a new object with a + higher-level API. This API may also do things like have the Serial port + `new` function require a borrow on some `Clock` structure, which can + only be generated by calling the function which configures the PLLs and + sets up all the clock frequencies. In this way, it is statically + impossible to create a Serial port object without first having + configured the clock rates, or for the Serial port object to misconvert + the baud rate into clock ticks. Some crates even define special traits + for the states each GPIO pin can be in, requiring the user to put a pin + into the correct state (say, by selecting the appropriate Alternate + Function Mode) before passing the pin into Peripheral. All with no + run-time cost! +], +de: [ + Ein HAL-Crate für einen Chip funktioniert typischerweise, indem es ein + spezifisches Trait für die vom PAC bereitgestellten Rohstrukturen + implementiert. Oft definiert dieses Trait eine Funktion namens + `constrain()` für einzelne Peripherieeinheiten oder `split()` für + Komponenten wie GPIO-Ports mit mehreren Pins. Diese Funktion übernimmt + die zugrundeliegende Rohstruktur der Peripherie und gibt ein neues + Objekt mit einer höherwertigen API zurück. Diese API kann zudem + sicherstellen, dass beispielsweise die `new`-Funktion für die serielle + Schnittstelle eine Referenz auf eine `Clock`-Struktur verlangt; eine + solche Struktur lässt sich nur durch den Aufruf der Funktion erzeugen, + welche die PLLs konfiguriert und sämtliche Taktfrequenzen einstellt. Auf + diese Weise ist es zur Kompilierzeit ausgeschlossen, ein Objekt für die + serielle Schnittstelle zu erzeugen, ohne zuvor die Taktraten + konfiguriert zu haben, oder dass das Objekt die Baudrate fehlerhaft in + Taktzyklen umrechnet. Manche Crates definieren sogar spezielle Traits + für die Zustände, die ein GPIO-Pin einnehmen kann; der Nutzer muss den + Pin dann in den korrekten Zustand versetzen (etwa durch Auswahl des + passenden Modus für alternative Funktionen), bevor er ihn an die + Peripherieeinheit übergibt. Und das alles ohne Laufzeitkosten! +], +ja: [ + あるチップ用のHALクレートは、典型的には、PACによって公開されている生の構造体に対して、カスタムトレイトを実装することで機能しています。 + 大抵、このトレイトは、単独のペリフェラルには`constrain()`関数を定義し、複数ピンを利用するGPIOポートのようなものには`split()`関数を定義します。 + この関数は、下層の生のペリフェラル構造体オブジェクトを消費し、より高レベルなAPIを備える新しいオブジェクトを返します。 + このAPIは、シリアルポートの`new`関数が、`Clock`構造体オブジェクトの借用を必要とするようなことをするかもしれません。Clock構造体オブジェクトは、 + PLLと全てのクロック周波数とを設定する関数呼び出しによってのみ、生成することが可能です。この方法では、最初にクロックレートを設定しないでシリアルポートオブジェクトを作成したり、 + シリアルポートオブジェクトがボーレートをクロック数に誤って変換するようなことは、静的に起こり得ません。 + 一部のクレートでは、各GPIOが取り得る状態のための特別なトレイトを定義することさえあります。このトレイトは、ペリフェラルにピンを渡す前に、 + ユーザがピンを正しい状態(例えば、適切なAlternate + Functionモードを選択することによって)にすることを求めます。 + これらは全て、ランタイムのコストを必要としません。 +], +zh: [ + 一个芯片的HAL + crate是通过为PAC暴露的基础结构体们实现一个自定义Trait来发挥作用的。经常这个trait将会为某个外设定义一个被称作 + `constrain()` + 的函数,或者为像是有多个管脚的GPIO端口这类东西定义一个`split()`函数。这个函数将会使用基础的外设结构体,然后返回一个具有更高抽象的API的新对象。这个API还可以做一些事,比如让Serial + port的 `new` + 函数变成需要某个`Clock`结构体的函数,这个结构体只能通过调用配置PLLs并设置所有的时钟频率的函数来生成。在这时,生成一个Serial + port对象而不先配置时钟速率是不可能的,对于Serial + port对象来说错误地将波特率转换为时钟滴答数也是不会发生的。一些crates甚至为每个GPIO管脚的状态定义了特定的 + traits,在把管脚传递进外设前,要求用户去把一个管脚设置成正确的状态(通过选择Alternate + Function模式) 。所有这些都没有运行时开销的! +])) + +#tr(( +en: [ + Let's see an example: +], +de: [ + Schauen wir uns ein Beispiel an: +], +ja: [ + 例を見てみましょう。 +], +zh: [ + 让我们看一个例子: +])) + +#raw(block: true, lang: "rust", +"#![no_std] +#![no_main] + +use panic_halt as _; // panic handler + +use cortex_m_rt::entry; +use tm4c123x_hal as hal; +use tm4c123x_hal::prelude::*; +use tm4c123x_hal::serial::{NewlineMode, Serial}; +use tm4c123x_hal::sysctl; + +#[entry] +fn main() -> ! { + let p = hal::Peripherals::take().unwrap(); + let cp = hal::CorePeripherals::take().unwrap(); + + // " + ts(( + en: "Wrap up the SYSCTL struct into an object with a higher-layer API", + de: "Kapseln Sie die SYSCTL-Struktur in einem Objekt mit einer API auf + // hoeherer Ebene.", + ja: "SYSCTL構造体をより高レイヤなAPIオブジェクトでラップします", + zh: "将SYSCTL结构体封装成一个有更高抽象API的对象", + )) + " + let mut sc = p.SYSCTL.constrain(); + // " + ts(( + en: "Pick our oscillation settings", + de: "Waehlen Sie unsere Oszillationseinstellungen aus.", + ja: "オシレータの設定値を選択します", + zh: "选择我们的晶振配置", + )) + " + sc.clock_setup.oscillator = sysctl::Oscillator::Main( + sysctl::CrystalFrequency::_16mhz, + sysctl::SystemClock::UsePll(sysctl::PllOutputFrequency::_80_00mhz), + ); + // " + ts(( + en: "Configure the PLL with those settings", + de: "Konfigurieren Sie die PLL mit diesen Einstellungen.", + ja: "PLLをそれらの設定値で設定します", + zh: "设置PLL", + )) + " + let clocks = sc.clock_setup.freeze(); + + // " + ts(( + en: "Wrap up the GPIO_PORTA struct into an object with a higher-layer API. + // Note it needs to borrow `sc.power_control` so it can power up the GPIO + // peripheral automatically.", + de: "Kapseln Sie die `GPIO_PORTA`-Struktur in einem Objekt mit einer API der + // hoeheren Ebene. + // Beachten Sie, dass es `sc.power_control` nutzen muss, um die + // Stromversorgung der GPIO-Peripherie automatisch zu aktivieren.", + ja: "GPIO_PORTA構造体をより高レイヤなAPIオブジェクトでラップします。 + // GPIOペリフェラルに自動的に電源を入れるために、 + // `sc.power_control`の借用が必要なことに留意して下さい。", + zh: "把GPIO_PORTA结构体封装成一个有更高抽象API的对象 + // 注意它需要借用 `sc.power_control` 因此它能自动开启GPIO外设。", + )) + " + let mut porta = p.GPIO_PORTA.split(&sc.power_control); + + // " + ts(( + en: "Activate the UART.", + de: "Aktivieren Sie den UART.", + ja: "UARTを起動します。", + zh: "激活UART", + )) + " + let uart = Serial::uart0( + p.UART0, + // " + ts(( + en: "The transmit pin", + de: "Der Sende-Pin", + ja: "送信ピン", + zh: "激活UART", + )) + " + porta + .pa1 + .into_af_push_pull::(&mut porta.control), + // " + ts(( + en: "The receive pin", + de: "Der Empfangs-Pin", + ja: "受信ピン", + zh: "接收管脚" + )) + " + porta + .pa0 + .into_af_push_pull::(&mut porta.control), + // " + ts(( + en: "No RTS or CTS required", + de: "Kein RTS oder CTS erforderlich", + ja: "RTSとCTSは必要としません", + zh: "不需要RTS或者CTS" + )) + " + (), + (), + // " + ts(( + en: "The baud rate", + de: "Die Baudrate", + ja: "ボーレート", + zh: "波特率", + )) + " + 115200_u32.bps(), + // " + ts(( + en: "Output handling", + de: "Ausgabeverarbeitung", + ja: "出力制御", + zh: "输出处理", + )) + " + NewlineMode::SwapLFtoCRLF, + // " + ts(( + en: "We need the clock rates to calculate the baud rate divisors", + de: "Wir benoetigen die Taktfrequenzen, um die Baudraten-Teiler zu + // berechnen.", + ja: "ボーレートの除数を計算するためにクロックレートが必要です", + zh: "我们需要时钟频率去计算波特率除法器(divisors)", + )) + " + &clocks, + // " + ts(( + en: "We need this to power up the UART peripheral", + de: "Wir benoetigen dies, um die UART-Peripherie zu aktivieren.", + ja: "UARTペリフェラルの電源を入れるために必要です", + zh: "我们需要这个去启动UART外设", + )) + " + &sc.power_control, + ); + + loop { + writeln!(uart, \"Hello, World!\\r\\n\").unwrap(); + } +} +") diff --git a/typ/start/semihosting.typ b/typ/start/semihosting.typ new file mode 100644 index 00000000..90beb2e2 --- /dev/null +++ b/typ/start/semihosting.typ @@ -0,0 +1,321 @@ +#import "../config.typ": * + +#h1((en: [Semihosting], + de: [Semihosting], + ja: [セミホスティング], + zh: [半主机模式], +), offset: whole) + +#tr(( +en: [ + Semihosting is a mechanism that lets embedded devices do I/O on the host + and is mainly used to log messages to the host console. Semihosting + requires a debug session and pretty much nothing else (no extra wires!) + so it's super convenient to use. The downside is that it's super slow: + each write operation can take several milliseconds depending on the + hardware debugger (e.g.~ST-Link) you use. +], +de: [ + Semihosting ist ein Mechanismus, der es eingebetteten Systemen + ermöglicht, Ein-/Ausgabeoperationen über den eigenen Rechner (Host) + durchzuführen; er wird hauptsächlich dazu genutzt, Meldungen auf der + Host-Konsole zu protokollieren. Da Semihosting lediglich eine + Debug-Sitzung und sonst so gut wie nichts (keine zusätzlichen Kabel!) + erfordert, ist es äußerst komfortabel in der Anwendung. Der Nachteil ist + jedoch die sehr geringe Geschwindigkeit: Je nach verwendetem + Hardware-Debugger (z. B. ST-Link) kann jeder Schreibvorgang mehrere + Millisekunden in Anspruch nehmen. +], +ja: [ + セミホスティングは、組込みデバイスがホスト上でI/Oを行う仕組みです。主に、ホストのコンソールにログ出力するために使われます。 + セミホスティングには、デバッグセッションが必要ですが、他には何も必要としません(追加の配線は不要です)。そのため、非常に便利です。 + 欠点は、非常に低速であることです。ハードウェアデバッガ(例えば、ST-Link)によっては、書き込み操作が数ミリ秒かかります。 +], +zh: [ + 半主机模式是一种可以让嵌入式设备在主机上进行I/O操作的的机制,主要被用来记录信息到主机控制台上。半主机模式需要一个debug会话,除此之外几乎没有其它要求了,因此它非常易于使用。缺点是它非常慢:每个写操作需要几毫秒的时间,其取决于你的硬件调试器(e.g.~ST-LINK)。 +])) + +#let ln_sh = link("https://crates.io/crates/cortex-m-semihosting")[`cortex-m-semihosting`] +#tr(( +en: [ + The #ln_sh crate provides an API to do semihosting + operations on Cortex-M devices. + The program below is the semihosting version of "Hello, world!": +], +de: [ + Das #ln_sh;-Crate + stellt eine API für Semihosting-Operationen auf Cortex-M-Geräten bereit. + Das folgende Programm ist die Semihosting-Version von „Hello, world!": +], +ja: [ + #ln_sh;クレートは、Cortex-Mデバイス上でセミホスティング操作をするためのAPIを提供します。 + 下のプログラムは、セミホスティングバージョンの「Hello, world!」です。 +], +zh: [ + #ln_sh crate 提供了一个API去在Cortex-M设备上执行半主机操作。下面的程序是"Hello, + world!"的半主机版本。 +])) + +```rust +#![no_main] +#![no_std] + +use panic_halt as _; + +use cortex_m_rt::entry; +use cortex_m_semihosting::hprintln; + +#[entry] +fn main() -> ! { + hprintln!("Hello, world!").unwrap(); + + loop {} +} +``` + +#tr(( +en: [ + If you run this program on hardware you'll see the "Hello, world!" + message within the OpenOCD logs. +], +de: [ + Wenn Sie dieses Programm auf der Hardware ausführen, sehen Sie die + Meldung „Hello, world!" in den OpenOCD-Protokollen. +], +ja: [ + このプログラムをハードウェア上で実行すると、OpenOCDのログに、「Hello + world!」のメッセージが表示されます。 +], +zh: [ + 如果你在硬件上运行这个程序,你将会在OpenOCD的logs中看到"Hello, + world!"信息。 +])) + +```text +$ openocd +(..) +Hello, world! +(..) +``` + +#tr(( +en: [ + You do need to enable semihosting in OpenOCD from GDB first: +], +de: [ + Sie müssen zunächst Semihosting in OpenOCD über GDB aktivieren: +], +ja: [ + 最初に、GDBからOpenOCDのセミホスティングを有効化する必要があります。 +], +zh: [ + 你首先需要从GDB使能OpenOCD中的半主机模式。 +])) + +```console +(gdb) monitor arm semihosting enable +semihosting is enabled +``` + +#tr(( +en: [ + QEMU understands semihosting operations so the above program will also + work with `qemu-system-arm` without having to start a debug session. + Note that you'll need to pass the `-semihosting-config` flag to QEMU to + enable semihosting support; these flags are already included in the + `.cargo/config.toml` file of the template. +], +de: [ + QEMU unterstützt Semihosting-Operationen, sodass das obige Programm auch + mit `qemu-system-arm` funktioniert, ohne dass eine Debug-Sitzung + gestartet werden muss. Beachten Sie, dass Sie QEMU die Option + `-semihosting-config` übergeben müssen, um die Semihosting-Unterstützung + zu aktivieren; diese Optionen sind bereits in der Datei + `.cargo/config.toml` der Vorlage enthalten. +], +ja: [ + QEMUはセミホスティング操作を理解しているため、上のプログラムは、デバッグセッションを開始していない`qemu-system-arm`でも動作します。 + セミホスティングサポートを有効化するため、QEMUに`-semihosting-config`フラグを渡す必要があることに注意して下さい。 + これらのフラグは、テンプレートの`.cargo/config`ファイルに既に含まれています。 +], +zh: [ + QEMU理解半主机操作,因此上面的程序不需要启动一个debug会话,也能在`qemu-system-arm`中工作。注意你需要传递`-semihosting-config`标志给QEMU去使能支持半主机模式;这些标识已经被包括在模板的`.cargo/config.toml`文件中了。 +])) + +#raw(block: true, lang: "text", +"$ # " + ts(( + en: "this program will block the terminal", + de: "Dieses Programm wird das Terminal blockieren.", + ja: "このプログラムは端末をブロックします", + )) + " +$ cargo run + Running `qemu-system-arm (..) +Hello, world! +") + +#tr(( +en: [ + There's also an `exit` semihosting operation that can be used to + terminate the QEMU process. Important: do *not* use `debug::exit` + on hardware; this function can corrupt your OpenOCD session and you will + not be able to debug more programs until you restart it. +], +de: [ + Es gibt auch eine `exit`-Semihosting-Operation, mit der sich der + QEMU-Prozess beenden lässt. Wichtig: Verwenden Sie `debug::exit` + *nicht* auf echter Hardware; diese Funktion kann Ihre + OpenOCD-Sitzung beschädigen, sodass Sie keine weiteren Programme mehr + debuggen können, bis Sie die Sitzung neu starten. +], +ja: [ + `exit`セミホスティング操作もあり、QEMUプロセスを終了するために使われます。 + 重要:ハードウェア上で`debug::exit`を*使用しない*で下さい。この関数は、OpenOCDセッションを破壊する可能性があり、 + OpenOCDを再起動しない限り、それ以上のプログラムのデバッグができなくなります。 +], +zh: [ + `exit`半主机操作也能被用于终止QEMU进程。重要:*不要*在硬件上使用`debug::exit`;这个函数会关闭你的OpenOCD对话,这样你就不能执行其它的程序调试操作了,除了重启它。 +])) + +```rust +#![no_main] +#![no_std] + +use panic_halt as _; + +use cortex_m_rt::entry; +use cortex_m_semihosting::debug; + +#[entry] +fn main() -> ! { + let roses = "blue"; + + if roses == "red" { + debug::exit(debug::EXIT_SUCCESS); + } else { + debug::exit(debug::EXIT_FAILURE); + } + + loop {} +} +``` + +```text +$ cargo run + Running `qemu-system-arm (..) + +$ echo $? +1 +``` + +#tr(( +en: [ + One last tip: you can set the panicking behavior to + `exit(EXIT_FAILURE)`. This will let you write `no_std` run-pass tests + that you can run on QEMU. +], +de: [ + Ein letzter Tipp: Du kannst das Verhalten bei einem Panic auf + `exit(EXIT_FAILURE)` einstellen. Dadurch lassen sich `no_std`-Tests + schreiben, die erfolgreich durchlaufen und unter QEMU ausgeführt werden + können. +], +ja: [ + 最後のヒント:パニック時の挙動を、`exit(EXIT_FAILURE)`に設定することができます。 + これで、QEMU上で実行できる`no_std`ランパステストを書くことができます。 + +], +zh: [ + 最后一个提示:你可以将运行时恐慌(panicking)的行为设置成 + `exit(EXIT_FAILURE)`。这会允许你编写可以在QEMU上运行通过的 `no_std` + 测试。 +])) + +#tr(( +en: [ + For convenience, the `panic-semihosting` crate has an "exit" feature + that when enabled invokes `exit(EXIT_FAILURE)` after logging the panic + message to the host stderr. +], +de: [ + Praktischerweise bietet der `panic-semihosting`-Crate ein „exit"-Feature + an; ist dieses aktiviert, wird `exit(EXIT_FAILURE)` aufgerufen, nachdem + die Panic-Meldung auf dem `stderr` des Hosts ausgegeben wurde. +], +ja: [ + 利便性のために、`panic-semihosting`クレートは、「exit」フィーチャを持っています。 + このフィーチャが有効化されていると、ホストの標準エラーにパニックメッセージをログ出力した後、`exit(EXIT_FAILURE)`を呼び出します。 +], +zh: [ + 为了方便,`panic-semihosting` crate有一个 "exit" + 特性。当它使能的时候,在主机stderr上打印恐慌(painc)信息后会调用 + `exit(EXIT_FAILURE)` 。 +])) + +```rust +#![no_main] +#![no_std] + +use panic_semihosting as _; // features = ["exit"] + +use cortex_m_rt::entry; +use cortex_m_semihosting::debug; + +#[entry] +fn main() -> ! { + let roses = "blue"; + + assert_eq!(roses, "red"); + + loop {} +} +``` + +```text +$ cargo run + Running `qemu-system-arm (..) +panicked at 'assertion failed: `(left == right)` + left: `"blue"`, + right: `"red"`', examples/hello.rs:15:5 + +$ echo $? +1 +``` + +#tr(( +en: [ + *NOTE*: To enable this feature on `panic-semihosting`, edit your + `Cargo.toml` dependencies section where `panic-semihosting` is specified + with: +], +de: [ + *HINWEIS*: Um diese Funktion für `panic-semihosting` zu + aktivieren, bearbeiten Sie den Abschnitt „dependencies" in Ihrer + `Cargo.toml`, in dem `panic-semihosting` wie folgt angegeben ist: +], +zh: [ + *注意*: + 为了在`panic-semihosting`上使能这个特性,编辑你的`Cargo.toml`依赖,`panic-semihosting`改写成: +])) + +```toml +panic-semihosting = { version = "VERSION", features = ["exit"] } +``` + +#let ln_spec_defs = link("https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html")[`specifying dependencies`] +#tr(( +en: [ + where `VERSION` is the version desired. For more information on + dependencies features check the + #ln_spec_defs + section of the Cargo book. +], +de: [ + wobei `VERSION` für die gewünschte Version steht. Weitere Informationen + zu Abhängigkeiten und Funktionen finden Sie im Abschnitt + "#ln_spec_defs" + des Cargo-Buchs. +], +zh: [ + `VERSION`是想要的版本。关于依赖features的更多信息查看Cargo + book的#ln_spec_defs;部分。 +])) diff --git a/typ/static-guarantees/design-contracts.typ b/typ/static-guarantees/design-contracts.typ new file mode 100644 index 00000000..7c4a7270 --- /dev/null +++ b/typ/static-guarantees/design-contracts.typ @@ -0,0 +1,514 @@ +#import "../config.typ": * + +#h1((en: [Design Contracts], + de: [Design-Verträge], + ja: [設計契約], + zh: [设计约定(design contracts)], +), offset: whole) + +#tr(( +en: [ + In our last chapter, we wrote an interface that _didn't_ enforce + design contracts. Let's take another look at our imaginary GPIO + configuration register: +], +de: [ + Im letzten Kapitel haben wir eine Schnittstelle geschrieben, die + _keine_ Design-Verträge (Design Contracts) durchsetzte. Werfen wir + noch einmal einen Blick auf unser fiktives GPIO-Konfigurationsregister: +], +ja: [ + 前回、設計契約を強制_しない_インタフェースを書きました。架空のGPIO設定レジスタをもう一度見てみましょう。 +], +zh: [ + 在我们的上个章节中,我们写了一个接口,但没有强制遵守设计约定。让我们再看下我们假想的GPIO配置寄存器: +])) + +#include "gpio-table.typ" + +#tr(( +en: [ + If we instead checked the state before making use of the underlying + hardware, enforcing our design contracts at runtime, we might write code + that looks like this instead: +], +de: [ + Wenn wir stattdessen den Zustand überprüfen würden, bevor wir die + zugrundeliegende Hardware nutzen, und dabei unsere Entwurfsverträge zur + Laufzeit durchsetzen würden, könnten wir stattdessen Code schreiben, der + wie folgt aussieht: +], +ja: [ + ハードウェアを使う前に状態をチェックし、実行時に設計契約を強制すると、コードは次のように書くことができます。 + +], +zh: [ + 如果在使用底层硬件之前检查硬件的状态,在运行时强制用户遵守设计约定,代码可能像这一样: +])) + +#raw(block: true, lang: "rust", +"/// " + ts(( + en: "GPIO interface", + de: "GPIO-Schnittstelle", + ja: "GPIOインタフェース", + zh: "GPIO接口", + )) + " +struct GpioConfig { + /// " + ts(( + en: "GPIO Configuration structure generated by svd2rust", + de: "Von svd2rust generierte GPIO-Konfigurationsstruktur", + ja: "svd2rustによって生成されたGPIO設定構造体", + zh: "由svd2rust生成的GPIO配制结构体" + )) + " + periph: GPIO_CONFIG, +} + +impl GpioConfig { + pub fn set_enable(&mut self, is_enabled: bool) { + self.periph.modify(|_r, w| { + w.enable().set_bit(is_enabled) + }); + } + + pub fn set_direction(&mut self, is_output: bool) -> Result<(), ()> { + if self.periph.read().enable().bit_is_clear() { + // " + ts(( + en: "Must be enabled to set direction", + de: "Muss aktiviert sein, um die Richtung festzulegen.", + ja: "方向を設定するには、有効化されてなければなりません", + zh: "必须被使能配置方向" + )) + " + return Err(()); + } + + self.periph.modify(|r, w| { + w.direction().set_bit(is_output) + }); + + Ok(()) + } + + pub fn set_input_mode(&mut self, variant: InputMode) -> Result<(), ()> { + if self.periph.read().enable().bit_is_clear() { + // " + ts(( + en: "Must be enabled to set input mode", + de: "Muss aktiviert sein, um den Eingabemodus festzulegen.", + ja: "入力モードを設定するには、有効化されてなければなりません", + zh: "必须被使能配置输入模式", + )) + " + return Err(()); + } + + if self.periph.read().direction().bit_is_set() { + // " + ts(( + en: "Direction must be input", + de: "Die Richtung muss input sein.", + ja: "方向は入力でなければなりません", + zh: "方向必须被设置成输入", + )) + " + return Err(()); + } + + self.periph.modify(|_r, w| { + w.input_mode().variant(variant) + }); + + Ok(()) + } + + pub fn set_output_status(&mut self, is_high: bool) -> Result<(), ()> { + if self.periph.read().enable().bit_is_clear() { + // " + ts(( + en: "Must be enabled to set output status", + de: "Muss aktiviert sein, um den Ausgangsstatus festzulegen.", + ja: "方向は入力でなければなりません", + zh: "设置输出状态必须被使能", + )) + " + return Err(()); + } + + if self.periph.read().direction().bit_is_clear() { + // " + ts(( + en: "Direction must be output", + de: "Die Richtung muss output sein.", + ja: "方向は出力でなければなりません", + zh: "方向必须是输出", + )) + " + return Err(()); + } + + self.periph.modify(|_r, w| { + w.output_mode.set_bit(is_high) + }); + + Ok(()) + } + + pub fn get_input_status(&self) -> Result { + if self.periph.read().enable().bit_is_clear() { + // " + ts(( + en: "Must be enabled to get status", + de: "Muss aktiviert sein, um den Status abzurufen.", + ja: "状態を取得するには、有効化されてなければなりません", + zh: "获取状态必须被使能", + )) + " + return Err(()); + } + + if self.periph.read().direction().bit_is_set() { + // " + ts(( + en: "Direction must be input", + de: "Die Richtung muss input sein.", + ja: "方向は入力でなければなりません", + zh: "方向必须是输入", + )) + " + return Err(()); + } + + Ok(self.periph.read().input_status().bit_is_set()) + } +} +") + +#tr(( +en: [ + Because we need to enforce the restrictions on the hardware, we end up + doing a lot of runtime checking which wastes time and resources, and + this code will be much less pleasant for the developer to use. +], +de: [ + Da wir die Hardware-Beschränkungen durchsetzen müssen, führen wir + letztlich zahlreiche Laufzeitüberprüfungen durch -- was Zeit und + Ressourcen verschwendet --, und der Code ist für Entwickler deutlich + weniger angenehm zu handhaben. +], +ja: [ + ハードウェアの制約を強制する必要があるため、時間とリソースを浪費する多くの実行時チェックを行うこととなり、開発者にとってこのコードは好ましくないです。 +], +zh: [ + 因为需要强制遵守硬件上的限制,所以最后做了很多运行时检查,它浪费了我们很多时间和资源,对于开发者来说,这个代码用起来就没那么愉快了。 +])) + += #tr(( + en: [Type States], + de: [Typzustände], + ja: [型状態], + zh: [类型状态(Type states)], +)) + +#tr(( +en: [ + But what if instead, we used Rust's type system to enforce the state + transition rules? Take this example: +], +de: [ + Was aber, wenn wir stattdessen das Typsystem von Rust nutzen würden, um + die Regeln für Zustandsübergänge durchzusetzen? Betrachten wir dieses + Beispiel: +], +ja: [ + しかし、代わりに、状態遷移の規則を強制するために、Rustの型システムを使うとどうなるでしょうか?この例を見て下さい。 +], +zh: [ + 但是,如果我们让Rust的类型系统去强制遵守状态转换的规则会怎样?看下这个例子: +])) + +#raw(block: true, lang: "rust", +"/// " + ts(( + en: "GPIO interface", + de: "GPIO-Schnittstelle", + ja: "GPIOインタフェース", + zh: "GPIO接口", + )) + " +struct GpioConfig { + /// " + ts(( + en: "GPIO Configuration structure generated by svd2rust", + de: "Von svd2rust generierte GPIO-Konfigurationsstruktur", + ja: "svd2rustによって生成されたGPIO設定構造体", + zh: "由svd2rust产生的GPIO配置结构体", + )) + " + periph: GPIO_CONFIG, + enabled: ENABLED, + direction: DIRECTION, + mode: MODE, +} + +// " + ts(( + en: "Type states for MODE in GpioConfig", + de: "Typzustaende fuer MODE in GpioConfig", + ja: "GpioConfigのMODEのための型状態", + zh: "GpioConfig中MODE的类型状态", + )) + " +struct Disabled; +struct Enabled; +struct Output; +struct Input; +struct PulledLow; +struct PulledHigh; +struct HighZ; +struct DontCare; + +/// " + ts(( + en: "These functions may be used on any GPIO Pin", + de: "Diese Funktionen koennen an jedem GPIO-Pin verwendet werden.", + ja: "これらの関数はどのGPIOピンにも使えます", + zh: "这些函数可能被用于所有的GPIO管脚", + )) + " +impl GpioConfig { + pub fn into_disabled(self) -> GpioConfig { + self.periph.modify(|_r, w| w.enable.disabled()); + GpioConfig { + periph: self.periph, + enabled: Disabled, + direction: DontCare, + mode: DontCare, + } + } + + pub fn into_enabled_input(self) -> GpioConfig { + self.periph.modify(|_r, w| { + w.enable.enabled() + .direction.input() + .input_mode.high_z() + }); + GpioConfig { + periph: self.periph, + enabled: Enabled, + direction: Input, + mode: HighZ, + } + } + + pub fn into_enabled_output(self) -> GpioConfig { + self.periph.modify(|_r, w| { + w.enable.enabled() + .direction.output() + .input_mode.set_high() + }); + GpioConfig { + periph: self.periph, + enabled: Enabled, + direction: Output, + mode: DontCare, + } + } +} + +/// " + ts(( + en: "This function may be used on an Output Pin", + de: "Diese Funktion kann fuer einen Ausgangspin verwendet werden.", + ja: "この関数はOutputピンに使用できます", + zh: "这个函数可能被用于一个输出管脚", + )) + " +impl GpioConfig { + pub fn set_bit(&mut self, set_high: bool) { + self.periph.modify(|_r, w| w.output_mode.set_bit(set_high)); + } +} + +/// " + ts(( + en: "These methods may be used on any enabled input GPIO", + de: "Diese Methoden koennen auf jedem aktivierten Eingangs-GPIO verwendet werden.", + ja: "これらのメソッドは、有効化された入力GPIOに使えます", + zh: "这些方法可能被用于任意一个使能的输入GPIO", + )) + " +impl GpioConfig { + pub fn bit_is_set(&self) -> bool { + self.periph.read().input_status.bit_is_set() + } + + pub fn into_input_high_z(self) -> GpioConfig { + self.periph.modify(|_r, w| w.input_mode().high_z()); + GpioConfig { + periph: self.periph, + enabled: Enabled, + direction: Input, + mode: HighZ, + } + } + + pub fn into_input_pull_down(self) -> GpioConfig { + self.periph.modify(|_r, w| w.input_mode().pull_low()); + GpioConfig { + periph: self.periph, + enabled: Enabled, + direction: Input, + mode: PulledLow, + } + } + + pub fn into_input_pull_up(self) -> GpioConfig { + self.periph.modify(|_r, w| w.input_mode().pull_high()); + GpioConfig { + periph: self.periph, + enabled: Enabled, + direction: Input, + mode: PulledHigh, + } + } +} +") + +#tr(( +en: [ + Now let's see what the code using this would look like: +], +de: [ + Schauen wir uns nun an, wie der Code aussehen würde, der dies verwendet: +], +ja: [ + それでは、これを使うコードがどのようになるか、見てみましょう。 +], +zh: [ + 现在让我们看下代码如何用这个API: +])) + +#raw(block: true, lang: "rust", +"/* + * " + ts(( + en: "Example 1: Unconfigured to High-Z input", + de: "Beispiel 1: Nicht konfiguriert als High-Z-Eingang", + ja: "例1:未設定から高抵抗入力", + zh: "案例 1: 从未配置到高阻输入", + )) + " + */ +let pin: GpioConfig = get_gpio(); + +// " + ts(( + en: "Can't do this, pin isn't enabled!", + de: "Das ist nicht moeglich, die PIN ist nicht aktiviert!", + ja: "これはできません、ピンが有効になっていません!", + zh: "不能这么做,pin没有被使能", + )) + " +// pin.into_input_pull_down(); + +// " + ts(( + en: "Now turn the pin from unconfigured to a high-z input", + de: "Schalten Sie den Pin nun von „unkonfiguriert“ auf einen hochohmigen Eingang + // (High-Z-Eingang) um.", + ja: "今度は、未設定から高抵抗入力に変えます", + zh: "现在把管脚从未配置变为高阻输入", + )) + " +let input_pin = pin.into_enabled_input(); + +// " + ts(( + en: "Read from the pin", + de: "Vom Pin lesen", + ja: "ピンから値を読みます", + zh: "从管脚读取", + )) + " +let pin_state = input_pin.bit_is_set(); + +// " + ts(( + en: "Can't do this, input pins don't have this interface!", + de: "Das ist nicht moeglich; Eingangs-Pins verfuegen nicht über diese + // Schnittstelle!", + ja: "これはできません、入力ピンはこのインタフェースを持っていません!", + zh: "不能这么做,输入管脚没有这个接口", + )) + " +// input_pin.set_bit(true); + +/* + * " + ts(( + en: "Example 2: High-Z input to Pulled Low input", + de: "Beispiel 2: Hochohmiger Eingang (High-Z) an auf Low-Pegel gezogenen Eingang", + ja: "例2:高抵抗入力からプルダウン入力", + zh: "案例 2: 高阻输入到下拉输入", + )) + " + */ +let pulled_low = input_pin.into_input_pull_down(); +let pin_state = pulled_low.bit_is_set(); + +/* + * " + ts(( + en: "Example 3: Pulled Low input to Output, set high", + de: "Beispiel 3: Eingang auf Low gezogen, Ausgang auf High gesetzt", + ja: "例3:プルダウン入力から出力、ハイを設定", + zh: "案例 3: 下拉输入到输出, 拉高", + )) + " + */ +let output_pin = pulled_low.into_enabled_output(); +output_pin.set_bit(true); + +// " + ts(( + en: "Can't do this, output pins don't have this interface!", + de: "Das geht nicht, Ausgangspins verfuegen nicht über diese Schnittstelle!", + ja: "これはできません、出力ピンはこのインタフェースを持っていません!", + zh: "不能这么做,输出管脚没有这个接口", + )) + " +// output_pin.into_input_pull_down(); +") + +#tr(( +en: [ + This is definitely a convenient way to store the state of the pin, but + why do it this way? Why is this better than storing the state as an + `enum` inside of our `GpioConfig` structure? +], +de: [ + Dies ist zweifellos eine praktische Möglichkeit, den Zustand des Pins zu + speichern, aber warum sollte man es auf diese Weise tun? Warum ist das + besser, als den Zustand als `enum` innerhalb unserer + `GpioConfig`-Struktur zu speichern? +], +ja: [ + これは間違いなく、ピンの状態を保存するのに便利な方法ですが、なぜこのようにするのでしょうか? + なぜ、`GpioConfig`構造体の中で、状態を`enum`として保存するより良い方法なのでしょうか? +], +zh: [ + 这绝对是存储管脚状态的便捷方法,但是为什么这么做?为什么这比把状态当成一个`enum`存在我们的`GpioConfig`结构体中更好? +])) + += #tr(( + en: [Compile Time Functional Safety], + de: [Funktionale Sicherheit zur Kompilierzeit], + ja: [コンパイル時の機能の安全性], + zh: [编译时功能安全(Functional Safety)], +)) + +#tr(( +en: [ + Because we are enforcing our design constraints entirely at compile + time, this incurs no runtime cost. It is impossible to set an output + mode when you have a pin in an input mode. Instead, you must walk + through the states by converting it to an output pin, and then setting + the output mode. Because of this, there is no runtime penalty due to + checking the current state before executing a function. +], +de: [ + Da wir unsere Designvorgaben vollständig zur Kompilierzeit durchsetzen, + entstehen keinerlei Laufzeitkosten. Es ist unmöglich, einen Ausgabemodus + einzustellen, solange sich ein Pin im Eingabemodus befindet. Stattdessen + muss man die Zustände durchlaufen, indem man den Pin zunächst in einen + Ausgangspin umwandelt und anschließend den Ausgabemodus festlegt. + Dadurch entfällt der Laufzeitaufwand für die Überprüfung des aktuellen + Zustands vor der Ausführung einer Funktion. +], +ja: [ + コンパイル時に、設計契約を完全に強制しているため、実行時コストはかかりません。入力方向のピンに対して、出力モードを設定することは不可能です。 + 代わりに、そのピンを出力ピンに変換してから、出力モードを設定することで、状態を辿る必要があります。 + このおかげで、関数実行前に現在の状態をチェックすることによる実行時ペナルティは、ありません。 +], +zh: [ + 因为我们在编译时完全强制遵守设计约定,这造成了没有运行时开销。当管脚处于输入模式时时,是不可能设置输出模式的。必须先把它设置成一个输出管脚,然后再设置输出模式。因为在执行一个函数前会检查现在的状态,因此没有运行时消耗。 +])) + +#tr(( +en: [ + Also, because these states are enforced by the type system, there is no + longer room for errors by consumers of this interface. If they try to + perform an illegal state transition, the code will not compile! +], +de: [ + Da diese Zustände zudem durch das Typsystem erzwungen werden, sind + Fehler bei der Verwendung dieser Schnittstelle ausgeschlossen. Versucht + der Nutzer einen unzulässigen Zustandsübergang, lässt sich der Code + nicht kompilieren! +], +ja: [ + 型システムによってこれらの状態が強制されるため、このインタフェースの利用者によるエラーの余地はもはや残っていません。 + もし利用者が不正な状態遷移をしようとすると、そのコードはコンパイルできません! +], +zh: [ + 也因为这些状态被类型系统强制遵守,因此没有为这个接口的使用者留太多的犯错余地。如果它们尝试执行一个非法的状态转换,代码将不会编译成功! +])) diff --git a/typ/static-guarantees/gpio-table.typ b/typ/static-guarantees/gpio-table.typ new file mode 100644 index 00000000..b1fb1985 --- /dev/null +++ b/typ/static-guarantees/gpio-table.typ @@ -0,0 +1,138 @@ +#import "../config.typ": * + +#figure( + kind: table, + table( + columns: (auto, auto, auto, auto, 1fr), + align: (x, y) => { + if x == 4 and y > 0 { + left + horizon + } else { + center + horizon + } + }, + table.header( + tr(( + en: [Name], + de: [Name], + ja: [名前], + zh: [名字], + )), + tr(( + en: [Bit Number(s)], + de: [Bit-Nummer], + ja: [ビットフィールド], + zh: [位数(s)], + )), + tr(( + en: [Value], + de: [Wert], + ja: [値], + zh: [值], + )), + tr(( + en: [Meaning], + de: [Bedeutung], + ja: [意味], + zh: [含义], + )), + tr(( + en: [Notes], + de: [Hinweise], + ja: [説明], + zh: [注释], + )), + ), + table.cell(rowspan: 2)[enable], table.cell(rowspan: 2)[0], + [0], [disabled], + tr(( + en: [Disables the GPIO], + de: [Deaktiviert den GPIO], + ja: [GPIOを無効にする], + zh: [关闭GPIO], + )), + + [1], [enabled], + tr(( + en: [Enables the GPIO], + de: [Aktiviert den GPIO], + ja: [GPIOを有効にする], + zh: [使能GPIO], + )), + + table.cell(rowspan: 2)[direction], table.cell(rowspan: 2)[1], + [0], [input], + tr(( + en: [Sets the direction to Input], + de: [Legt die Richtung auf „Eingang" fest.], + ja: [方向を入力に設定する], + zh: [方向设置成输入], + )), + + [1], [output], + tr(( + en: [Sets the direction to Output], + de: [Legt die Richtung auf „Ausgang" fest.], + ja: [方向を出力に設定する], + zh: [方向设置成输出], + )), + + table.cell(rowspan: 4)[input_mode], table.cell(rowspan: 4)[2..3], + [00], [hi-z], + tr(( + en: [Sets the input as high resistance], + de: [Setzt den Eingang auf hochohmig.], + ja: [入力を高抵抗に設定する], + zh: [输入设置为高阻态], + )), + + [01], [pull-low], + tr(( + en: [Input pin is pulled low], + de: [Der Eingangspin wird auf Low-Pegel gezogen.], + ja: [入力ピンはプルダウンになる], + zh: [下拉输入管脚], + )), + + [10], [pull-high], + tr(( + en: [Input pin is pulled high], + de: [Der Eingangspin wird auf High-Pegel gezogen], + ja: [入力ピンはプルアップになる], + zh: [上拉输入管脚], + )), + + [11], [n/a], + tr(( + en: [Invalid state. Do not set], + de: [Ungültiger Zustand. Nicht setzen.], + ja: [無効な状態。設定しないこと。], + zh: [无效状态。不要设置], + )), + + table.cell(rowspan: 2)[output_mode], table.cell(rowspan: 2)[4], + [0], [set-low], + tr(( + en: [Output pin is driven low], + de: [Der Ausgangspin wird auf Low-Pegel gesteuert.], + ja: [出力ピンをローにする], + zh: [把管脚设置成低电平], + )), + + [1], [set-high], + tr(( + en: [Output pin is driven high], + de: [Der Ausgangspin wird auf High-Pegel gesteuert.], + ja: [出力ピンをハイにする], + zh: [把管脚设置成高电平], + )), + + [input_status], [5], [x], [in-val], + tr(( + en: [0 if input is < 1.5v, 1 if input >= 1.5v], + de: [0, wenn der Eingang < 1,5 V ist; 1, wenn der Eingang ≥ 1,5 V ist.], + ja: [入力が1.5Vより低ければ0、1.5V以上であれば1], + zh: [如果输入 < 1.5v 为0,如果输入 >= 1.5v 为1], + )), + ) +) \ No newline at end of file diff --git a/typ/static-guarantees/index.typ b/typ/static-guarantees/index.typ new file mode 100644 index 00000000..cc9c084a --- /dev/null +++ b/typ/static-guarantees/index.typ @@ -0,0 +1,105 @@ +#import "../config.typ": * + +#h1((en: [Static Guarantees], + de: [Statische Garantien], + ja: [静的な保証], + zh: [静态保障], +)) + +#let ln_send = link("https://doc.rust-lang.org/core/marker/trait.Send.html")[`Send`] +#let ln_sync = link("https://doc.rust-lang.org/core/marker/trait.Sync.html")[`Sync`] +#tr(( +en: [ + Rust's type system prevents data races at compile time + (see #ln_send and #ln_sync traits). + The type system can also be used to check other properties at + compile time; reducing the need for runtime checks in some cases. +], +de: [ + Das Typsystem von Rust verhindert Data Races zur Kompilierzeit + (siehe die Traits #ln_send und #ln_sync). + Zudem lässt sich das Typsystem nutzen, um weitere Eigenschaften bereits + zur Kompilierzeit zu überprüfen, wodurch in einigen Fällen + Laufzeitprüfungen überflüssig werden. +], +ja: [ + コンパイル時にデータ競合を防ぐのは、Rustの型システムです(#ln_send;と#ln_sync;トレイトを参照)。 + この型システムは、コンパイル時に他のプロパティをチェックするためにも使用できます。 + その結果、実行時チェックの必要性を減らせる場合があります。 +], +zh: [ + Rust的类型系统可以在编译时防止数据竞争(看#ln_send;和#ln_sync;特性(traits))。也可以在编译时使用类型系统来完成一些检查工作;减少某些例子中对运行时检查的需要。 +])) + +#tr(( +en: [ + When applied to embedded programs these _static checks_ can be + used, for example, to enforce that configuration of I/O interfaces is + done properly. For instance, one can design an API where it is only + possible to initialize a serial interface by first configuring the pins + that will be used by the interface. +], +de: [ + Bei Embedded-Programmen lassen sich diese _statischen Prüfungen_ + beispielsweise nutzen, um sicherzustellen, dass die Konfiguration von + E/A-Schnittstellen korrekt erfolgt. So lässt sich etwa eine API + entwerfen, bei der die Initialisierung einer seriellen Schnittstelle nur + möglich ist, wenn zuvor die für diese Schnittstelle vorgesehenen Pins + konfiguriert wurden. +], +ja: [ + 組込みプログラムに適用する場合、これらの_静的なチェック_は、例えば、入出力インタフェースが正しく設定されていることを強制することができます。 + 例えば、使用されるピンを最初に設定することによってのみ、シリアルインタフェースを初期化できるようなAPI設計が可能です。 +], +zh: [ + 当应用到嵌入式程序时,这些_静态检查_能被用来,比如,强制按需配置I/O接口。例如,可以设计一个初始化串行接口的API,这个API只有在配置好接口需要的管脚后才可以被正确地使用。 +])) + +#tr(( +en: [ + One can also statically check that operations, like setting a pin low, + can only be performed on correctly configured peripherals. For example, + trying to change the output state of a pin configured in floating input + mode would raise a compile error. +], +de: [ + Zudem lässt sich statisch überprüfen, ob Operationen -- wie etwa das + Setzen eines Pins auf den Pegel „Low" -- nur an korrekt konfigurierten + Peripheriekomponenten ausgeführt werden. Der Versuch, den + Ausgangszustand eines Pins zu ändern, der als „Floating Input" (Eingang + mit undefiniertem Pegel) konfiguriert ist, würde beispielsweise zu einem + Kompilierfehler führen. +], +ja: [ + 正しく設定されたペリフェラルでのみ、ピンをローレベルにするというような操作ができることを、 + 静的にチェックすることも可能です。例えば、フローティング入力モードに設定されたピンの出力状態を変更しようとすると、 + コンパイルエラーが発生します。 +], +zh: [ + 也可以静态检查,是否是在正确配置了的外设上执行的操作,像是拉低一个管脚这种操作。比如尝试修改一个被配置成浮空输入模式的管脚的输出状态时,会触发一个编译时错误。 +])) + +#tr(( +en: [ + And, as seen in the previous chapter, the concept of ownership can be + applied to peripherals to ensure that only certain parts of a program + can modify a peripheral. This _access control_ makes software + easier to reason about compared to the alternative of treating + peripherals as global mutable state. +], +de: [ + Wie bereits im vorherigen Kapitel erläutert, lässt sich auch das Konzept + des „Ownership" (Besitzverhältnis) auf Peripheriekomponenten anwenden, + um sicherzustellen, dass nur bestimmte Programmteile diese modifizieren + können. Diese _Zugriffskontrolle_ erleichtert das Verständnis und + die Analyse der Software im Vergleich zu dem alternativen Ansatz, + Peripheriekomponenten als globalen, veränderbaren Zustand zu behandeln. +], +ja: [ + 以前の章で見た通り、所有権の概念はペリフェラルにも適用できます。所有権は、プログラムの特定部分のみがペリフェラルを変更することを保証します。 + この_アクセスコントロール_は、ペリフェラルをグローバルでミュータブルな状態として扱う代替案と比較して、 + ソフトウェアの解析をより簡単にします。 +], +zh: [ + 并且,像是在前面章节看到的,所有权的概念能被应用到外设上确保一个程序只有某些部分可以修改一个外设。与将这个外设当做全局可变的状态相比,_访问控制_(assess control)使得软件更容易推理。 +])) diff --git a/typ/static-guarantees/state-machines.typ b/typ/static-guarantees/state-machines.typ new file mode 100644 index 00000000..aa6c9dc9 --- /dev/null +++ b/typ/static-guarantees/state-machines.typ @@ -0,0 +1,305 @@ +#import "../config.typ": * + +#h1((en: [Peripherals as State Machines], + de: [Peripheriegeräte als Zustandsautomaten], + ja: [ステートマシンとしてのペリフェラル], + zh: [作为状态机的外设], +), offset: whole) + +#let url_pin = "https://en.wikipedia.org/wiki/General-purpose_input/output" +#tr(( +en: [ + The peripherals of a microcontroller can be thought of as set of state + machines. For example, the configuration of a simplified #link(url_pin)[GPIO pin] + could be represented as the following tree of states: + - Disabled + - Enabled + - Configured as Output + - Output: High + - Output: Low + - Configured as Input + - Input: High Resistance + - Input: Pulled Low + - Input: Pulled High +], +de: [ + Die Peripherie eines Mikrocontrollers lässt sich als eine Menge von + Zustandsautomaten auffassen. So ließe sich beispielsweise die + Konfiguration eines vereinfachten + #link(url_pin)[GPIO-Pins] + als der folgende Zustandsbaum darstellen: + - Deaktiviert + - Aktiviert + - Als Ausgang konfiguriert + - Ausgang: High + - Ausgang: Low + - Als Eingang konfiguriert + - Eingang: Hoher Widerstand + - Eingang: Auf Low-Pegel gezogen + - Eingang: Auf High-Pegel gezogen +], +ja: [ + マイクロコントローラのペリフェラルは、一連のステートマシンとして考えることができます。 + 例えば、簡略化された#link(url_pin)[GPIOピン]の設定は、次の状態ツリーとして表すことができます。 + - 無効 + - 有効 + - 出力として設定 + - 出力:ハイ + - 出力:ロー + - 入力として設定 + - 入力:高抵抗(訳注:ハイインピーダンス) + - 入力:プルダウン + - 入力:プルアップ +], +zh: [ + 一个微控制器的外设可以被想成是一组状态机。比如,一个简化的#link(url_pin)[GPIO管脚]的配置可以被表达成下列的状态树: + - 关闭 + - 使能 + - 配置成输出 + - 输出: 高 + - 输出: 低 + - 配置成输入 + - 输入: 高阻态 + - 输入: 下拉 + - 输入: 上拉 +])) + +#tr(( +en: [ + If the peripheral starts in the `Disabled` mode, to move to the + `Input: High Resistance` mode, we must perform the following steps: + + Disabled + + Enabled + + Configured as Input + + Input: High Resistance +], +de: [ + Wenn die Peripherieeinheit im Modus `Deaktiviert` startet, müssen wir + die folgenden Schritte ausführen, um in den Modus + `Eingang: Hoher Widerstand` zu ​​wechseln: + + Deaktiviert + + Aktiviert + + Als Eingang konfiguriert + + Eingang: Hoher Widerstand +], +ja: [ + このペリフェラルが`無効`モードから始まるとすると、`入力:高抵抗`モードに移行するには、次のステップを踏みます。 + + 無効 + + 有効 + + 入力として設定 + + 入力:高抵抗 +], +zh: [ + 如果外设开始于`关闭`模式,切换到`输入: 高阻态`模式,我们必须执行下面的步骤: + + 关闭 + + 使能 + + 配置成输入 + + 输入: 高阻态 +])) + +#tr(( +en: [ + If we wanted to move from `Input: High Resistance` to + `Input: Pulled Low`, we must perform the following steps: + + Input: High Resistance + + Input: Pulled Low +], +de: [ + Wenn wir von „Eingang: Hoher Widerstand" zu „Eingang: Auf Low-Pegel + gezogen" wechseln möchten, müssen wir die folgenden Schritte ausführen: + + Eingang: Hoher Widerstand 2. Eingang: Auf Low-Pegel gezogen +], +ja: [ + `入力:高抵抗`から`入力:プルダウン`へと移る場合、次のステップを実行しなければなりません。 + + 入力:高抵抗 + + 入力:プルダウン +], +zh: [ + 如果我们想要从`输入: 高阻态`切换到`输入: 下拉`,我们必须执行下列的步骤: + + 输入: 高阻抗 + + 输入: 下拉 +])) + +#tr(( +en: [ + Similarly, if we want to move a GPIO pin from configured as + `Input: Pulled Low` to `Output: High`, we must perform the following + steps: + + Input: Pulled Low + + Configured as Input + + Configured as Output + + Output: High +], +de: [ + Wenn wir einen GPIO-Pin von der Konfiguration „Eingang: Auf Low-Pegel + gezogen" auf „Ausgang: High" umstellen wollen, müssen wir ebenfalls die + folgenden Schritte ausführen: + + Eingang: Auf Low-Pegel gezogen + + Als Eingang konfiguriert + + Als Ausgang konfiguriert + + Ausgang: High +], +ja: [ + 同じように、`入力:プルダウン`と設定されているGPIOピンを、`出力:ハイ`にするには、次のステップを実行しなければなりません。 + + 入力:プルダウン + + 入力として設定 + + 出力として設定 + + 出力:ハイ +], +zh: [ + 同样地,如果我们想要把一个GPIO管脚从`输入: 下拉`切换到`输出: 高`,我们必须执行下列的步骤: + + 输入: 下拉 + + 配置成输入 + + 配置成输出 + + 输出: 高 +])) + += #tr(( + en: [Hardware Representation], + de: [Hardware-Darstellung], + ja: [ハードウェアの表現], + zh: [硬件表征(Hardware Representation)], +)) + +#tr(( +en: [ + Typically the states listed above are set by writing values to given + registers mapped to a GPIO peripheral. Let's define an imaginary GPIO + Configuration Register to illustrate this: +], +de: [ + Typischerweise werden die oben aufgeführten Zustände eingestellt, indem + Werte in bestimmte Register geschrieben werden, die einer + GPIO-Peripherieeinheit zugeordnet sind. Definieren wir zur + Veranschaulichung ein fiktives GPIO-Konfigurationsregister: +], +ja: [ + 通常、上記の状態は、GPIOペリフェラルに割り当てられたレジスタに値を書き込むことで設定できます。 + これを説明するために、架空のGPIO設定レジスタを定義しましょう。 +], +zh: [ + 通常,通过向映射到GPIO外设上的指定的寄存器中写入值可以配置上面列出的状态。让我们定义一个假想的GPIO配置寄存器来解释下它: +])) + +#include "gpio-table.typ" + +#tr(( +en: [ + We _could_ expose the following structure in Rust to control this GPIO: +], +de: [ + Wir _könnten_ die folgende Struktur in Rust bereitstellen, um diesen GPIO zu steuern: +], +ja: [ + このGPIOを制御するために、次のようなRustの構造体を公開することが + _できます_。 +], +zh: [ + _可以_ 在Rust中暴露下列的结构体来控制这个GPIO: +])) + +#raw(block: true, lang: "rust", +"/// " + ts(( + en: "GPIO interface", + de: "GPIO interface", + ja: "GPIOインタフェース", + zh: "GPIO接口", + )) + " +struct GpioConfig { + /// " + ts(( + en: "GPIO Configuration structure generated by svd2rust", + de: "Von svd2rust generierte GPIO-Konfigurationsstruktur", + ja: "svd2rustで生成されたGPIO設定構造体", + zh: "由svd2rust生成的GPIO配置结构体", + )) + " + periph: GPIO_CONFIG, +} + +impl GpioConfig { + pub fn set_enable(&mut self, is_enabled: bool) { + self.periph.modify(|_r, w| { + w.enable().set_bit(is_enabled) + }); + } + + pub fn set_direction(&mut self, is_output: bool) { + self.periph.modify(|_r, w| { + w.direction().set_bit(is_output) + }); + } + + pub fn set_input_mode(&mut self, variant: InputMode) { + self.periph.modify(|_r, w| { + w.input_mode().variant(variant) + }); + } + + pub fn set_output_mode(&mut self, is_high: bool) { + self.periph.modify(|_r, w| { + w.output_mode.set_bit(is_high) + }); + } + + pub fn get_input_status(&self) -> bool { + self.periph.read().input_status().bit_is_set() + } +} +") + +#tr(( +en: [ + However, this would allow us to modify certain registers that do not + make sense. For example, what happens if we set the `output_mode` field + when our GPIO is configured as an input? +], +de: [ + Dies würde uns jedoch erlauben, bestimmte Register zu verändern, was + keinen Sinn ergibt. Was passiert beispielsweise, wenn wir das Feld + `output_mode` setzen, während unser GPIO als Eingang konfiguriert ist? +], +ja: [ + しかし、この実装では、筋が通らないレジスタの修正が可能になってしまいます。例えば、GPIOを入力に設定している時に、`出力モード`を設定すると、どうなるのでしょう? +], +zh: [ + 然而,这会允许我们修改某些没有意义的寄存器。比如,如果当我们的GPIO被配置为输入时我们设置`output_mode`字段,将会发生什么? +])) + +#tr(( +en: [ + In general, use of this structure would allow us to reach states not + defined by our state machine above: e.g.~an output that is pulled low, + or an input that is set high. For some hardware, this may not matter. On + other hardware, it could cause unexpected or undefined behavior! +], +de: [ + Im Allgemeinen würde die Verwendung dieser Struktur es uns ermöglichen, + Zustände zu erreichen, die nicht durch unsere obige Zustandsmaschine + definiert sind: z. B. einen Ausgang, der auf LOW gesetzt wird, oder + einen Eingang, der auf HIGH gesetzt wird. Bei mancher Hardware mag dies + keine Rolle spielen. Bei anderer Hardware könnte es jedoch zu + unerwartetem oder undefiniertem Verhalten führen! +], +ja: [ + 通常、この構造体を利用すると、上のステートマシンで定義されていない状態に到達できてしまいます。 + 例えば、プルダウンの出力や、ハイに設定された入力、です。 +], +zh: [ + 通常使用这个结构体会允许我们访问到上面的状态机没有定义的状态:比如,一个被上拉的输出,或者一个被拉高的输入。对于一些硬件,这并没有关系。对另外一些硬件来说,这将会导致不可预期或者没有定义的行为! +])) + +#tr(( +en: [ + Although this interface is convenient to write, it doesn't enforce the + design contracts set out by our hardware implementation. +], +de: [ + Obwohl diese Schnittstelle bequem zu implementieren ist, erzwingt sie + nicht die in unserer Hardware-Implementierung festgelegten + Designvorgaben. +], +ja: [ + このインタフェースは書き込みには便利ですが、ハードウェア実装によって定められた設計の契約を強制しません。 +], +zh: [ + 虽然这个接口很方便写入,但是它没有强制我们遵守硬件实现所设的设计约定。 +])) diff --git a/typ/static-guarantees/typestate-programming.typ b/typ/static-guarantees/typestate-programming.typ new file mode 100644 index 00000000..70a5501e --- /dev/null +++ b/typ/static-guarantees/typestate-programming.typ @@ -0,0 +1,185 @@ +#import "../config.typ": * + +#h1((en: [Typestate Programming], + de: [Typgestützte Programmierung], + ja: [型状態プログラミング], + zh: [类型状态编程(Typestate Programming)], +), offset: whole) + +#let url_ts = "https://en.wikipedia.org/wiki/Typestate_analysis" +#let url_builders = "https://doc.rust-lang.org/1.0.0/style/ownership/builders.html" +#tr(( +en: [ + The concept of + #link(url_ts)[typestates] + describes the encoding of information about the current state of an + object into the type of that object. Although this can sound a little + arcane, if you have used the #link(url_builders)[Builder Pattern] + in Rust, you have already started using Typestate Programming! +], +de: [ + Das Konzept der #link(url_ts)[typestates] + beschreibt die Kodierung von Informationen über den aktuellen Zustand + eines Objekts direkt in dessen Typ. Auch wenn dies zunächst etwas + abstrakt oder kompliziert klingen mag: Wenn Sie in Rust bereits das + #link(url_builders)[Builder-Muster] + verwendet haben, sind Sie schon mit der Typestate-Programmierung in + Berührung gekommen! +], +ja: [ + #link(url_ts)[型状態]の概念は、オブジェクトの現在の状態に関する情報を、そのオブジェクトの型にエンコードすることを説明しています。 + これは、少し難解に思えますが、Rustの#link(url_builders)[ビルダーパターン]を使ったことがあるならば、既に型状態プログラミングを使い始めています。 +], +zh: [ + #link(url_ts)[typestates]的概念是指将有关对象当前状态的信息编码进该对象的类型中。虽然这听起来有点神秘,如果你在Rust中用过#link(url_builders))[建造者模式],你就已经开始使用类型状态编程了! +])) + + +```rust +pub mod foo_module { + #[derive(Debug)] + pub struct Foo { + inner: u32, + } + + pub struct FooBuilder { + a: u32, + b: u32, + } + + impl FooBuilder { + pub fn new(starter: u32) -> Self { + Self { + a: starter, + b: starter, + } + } + + pub fn double_a(self) -> Self { + Self { + a: self.a * 2, + b: self.b, + } + } + + pub fn into_foo(self) -> Foo { + Foo { + inner: self.a + self.b, + } + } + } +} + +fn main() { + let x = foo_module::FooBuilder::new(10) + .double_a() + .into_foo(); + + println!("{:#?}", x); +} +``` + +#tr(( +en: [ + In this example, there is no direct way to create a `Foo` object. We + must create a `FooBuilder`, and properly initialize it before we can + obtain the `Foo` object we want. +], +de: [ + In diesem Beispiel gibt es keine direkte Möglichkeit, ein `Foo`-Objekt + zu erstellen. Wir müssen einen `FooBuilder` erstellen und ihn korrekt + initialisieren, bevor wir das gewünschte `Foo`-Objekt erhalten können. +], +ja: [ + この例では、`Foo`オブジェクトを直接作る方法はありません。必要な`Foo`オブジェクトを取得する前に、`FooBuilder`を作り、正しく初期化しなければなりません。 +], +zh: [ + 在这个例子里,不能直接生成一个`Foo`对象。必须先生成一个`FooBuilder`,并且恰当地初始化`FooBuilder`后,才能获取到需要的`Foo`对象。 +])) + +#tr(( +en: [ + This minimal example encodes two states: + - `FooBuilder`, which represents an "unconfigured", or "configuration in + process" state + - `Foo`, which represents a "configured", or "ready to use" state. +], +de: [ + Dieses Minimalbeispiel kodiert zwei Zustände: + - `FooBuilder`, das einen „unkonfigurierten" Zustand oder einen Zustand + der „laufenden Konfiguration" repräsentiert + - `Foo`, das einen „konfigurierten" oder „einsatzbereiten" Zustand repräsentiert. +], +ja: [ + この最小限の例は、2つの状態をエンコードしています。 + - `FooBuilder`は、「未設定」もしくは「設定中」の状態を表現します。 + - `Foo`は、「設定済み」もしくは「使用準備完了」の状態を意味します。 +], +zh: [ + 这个最小的例子编码了两个状态: + - `FooBuilder`,其表示一个"没有被配置",或者"正在配置"状态 + - `Foo`,其表示了一个"被配置",或者"可以使用"状态。 +])) + += #tr(( + en: [Strong Types], + de: [Starke Typen], + ja: [強い型], + zh: [强类型], +)) + +#let url_strong = "https://en.wikipedia.org/wiki/Strong_and_weak_typing" +#tr(( +en: [ + Because Rust has a #link(url_strong)[Strong Type System], + there is no easy way to magically create an instance of `Foo`, or to + turn a `FooBuilder` into a `Foo` without calling the `into_foo()` + method. Additionally, calling the `into_foo()` method consumes the + original `FooBuilder` structure, meaning it can not be reused without + the creation of a new instance. +], +de: [ + Da Rust über ein + #link(url_strong)[starkes Typsystem] + verfügt, gibt es keine einfache Möglichkeit, auf magische Weise eine + Instanz von `Foo` zu erzeugen oder einen `FooBuilder` in ein `Foo` + umzuwandeln, ohne die Methode `into_foo()` aufzurufen. Zudem verbraucht + der Aufruf der Methode `into_foo()` die ursprüngliche + `FooBuilder`-Struktur; das bedeutet, dass sie nicht ohne die Erstellung + einer neuen Instanz wiederverwendet werden kann. +], +ja: [ + Rustは#link(url_strong)[強い型付けシステム]を持っています。`Foo`のインスタンスを魔法のように作成したり、 + `into_foo()`メソッドを呼び出すことなしに`FooBuilder`から`Foo`に変換したりする、簡単な方法はありません。 + さらに、`into_foo()`メソッドは、オリジナルの`FooBuilder`構造体を消費します。 + これは、新しいインスタンスを作成しないと、再利用ができないことを意味します。 +], +zh: [ + 因为Rust有一个#link(url_strong)[强类型系统],没有什么简单的方法可以奇迹般地生成一个`Foo`实例,也没有简单的方法可以不用调用`into_foo()`方法而把一个`FooBuilder`变成一个`Foo`。另外,调用`into_foo()`方法消费了最初的`FooBuilder`结构体,意味着不生成一个新的实例就不能被再次使用它。 +])) + +#tr(( +en: [ + This allows us to represent the states of our system as types, and to + include the necessary actions for state transitions into the methods + that exchange one type for another. By creating a `FooBuilder`, and + exchanging it for a `Foo` object, we have walked through the steps of a + basic state machine. +], +de: [ + Dies ermöglicht es uns, die Zustände unseres Systems als Typen + darzustellen und die für Zustandsübergänge erforderlichen Aktionen in + jene Methoden zu integrieren, die einen Typ gegen einen anderen + austauschen. Indem wir einen `FooBuilder` erstellen und diesen gegen ein + `Foo`-Objekt austauschen, haben wir die Schritte einer einfachen + Zustandsmaschine durchlaufen. +], +ja: [ + このことにより、システムの状態を型として表現することが可能になります。 + そして、状態遷移に必要なアクションを、ある型と別の型とを交換するメソッドに取り入れることができます。 + `FooBuilder`を作成し、`Foo`オブジェクトに交換することで、基本的なステートマシンのステップを見てきました。 +], +zh: [ + 这允许我们可以将系统的状态表示成类型,把状态转换必须的动作包括进转换两个类型的方法中。通过生成一个 + `FooBuilder`,转换成一个 `Foo` 对象,我们已经使用了一个基本的状态机。 +])) diff --git a/typ/static-guarantees/zero-cost-abstractions.typ b/typ/static-guarantees/zero-cost-abstractions.typ new file mode 100644 index 00000000..0c6aee63 --- /dev/null +++ b/typ/static-guarantees/zero-cost-abstractions.typ @@ -0,0 +1,182 @@ +#import "../config.typ": * + +#h1((en: [Zero Cost Abstractions], + de: [Abstraktionen ohne Kosten], + ja: [ゼロコスト抽象化], + zh: [零成本抽象], +), offset: whole) + +#tr(( +en: [ + Type states are also an excellent example of Zero Cost Abstractions - + the ability to move certain behaviors to compile time execution or + analysis. These type states contain no actual data, and are instead used + as markers. Since they contain no data, they have no actual + representation in memory at runtime: +], +de: [ + Typzustände (Type States) sind zudem ein hervorragendes Beispiel für + „Zero-Cost Abstractions" -- also die Möglichkeit, bestimmte + Verhaltensweisen in die Kompilierzeit zu verlagern (sei es zur + Ausführung oder zur Analyse). Diese Typzustände enthalten keine + eigentlichen Daten, sondern dienen als Markierungen. Da sie keine Daten + enthalten, besitzen sie zur Laufzeit keine tatsächliche Repräsentation + im Speicher: +], +ja: [ + 型状態はゼロコスト抽象化の優れた例でもあります。特定の動作を、コンパイル時の実行もしくは解析に移動する機能です。 + これらの型状態は、実際のデータを含んでおらず、代わりにマーカとして使われています。 + 型状態はデータを含んでいないため、実行時、メモリ内に実際のデータはありません。 +], +zh: [ + 类型状态是一个零成本抽象的杰出案例 - + 把某些行为移到编译时执行或者分析的能力。这些类型状态不包含真实的数据,只用来作为标记。因为它们不包含数据,在运行时它们在内存中不存在实际的表示。 +])) + +```rust +use core::mem::size_of; + +let _ = size_of::(); // == 0 +let _ = size_of::(); // == 0 +let _ = size_of::(); // == 0 +let _ = size_of::>(); // == 0 +``` + += #tr(( + en: [Zero Sized Types], + de: [Typen der Größe Null], + ja: [ゼロサイズの型], + zh: [零大小的类型(Zero Sized Types)], +)) + +```rust +struct Enabled; +``` + +#tr(( +en: [ + Structures defined like this are called Zero Sized Types, as they + contain no actual data. Although these types act "real" + at compile time - you can copy them, move them, + take references to them, etc., however + the optimizer will completely strip them away. +], +de: [ + Strukturen dieser Art werden als Null-Typen bezeichnet, da sie keine + tatsächlichen Daten enthalten. Obwohl sich diese Typen zur Kompilierzeit + „real" verhalten -- man kann sie kopieren, verschieben, Referenzen + darauf erstellen usw. --, werden sie vom Optimierer vollständig + entfernt. +], +ja: [ + 上記のように定義された構造体をゼロサイズの型、と呼びます。これは、実際のデータを含んでいません。 + これらの型は、コンパイル時には「実際に」機能します。例えば、コピーも、ムーブも、参照を取ることもできます。 + しかし、最適化はこれらを完全に取り除きます。 +], +zh: [ + 像这样定义的结构体被称为零大小的类型,因为它们不包含实际数据。虽然这些类型在编译时像是"真实的"(real) - 你可以拷贝它们,移动它们,引用它们,等等,然而优化器将会完全跳过它们。 +])) + +#tr(( +en: [ + In this snippet of code: +], +de: [ + In diesem Code-Ausschnitt: +], +ja: [ + 次のコードスニペットを見てください。 +], +zh: [ + 在这个代码片段里: +])) + +```rust +pub fn into_input_high_z(self) -> GpioConfig { + self.periph.modify(|_r, w| w.input_mode().high_z()); + GpioConfig { + periph: self.periph, + enabled: Enabled, + direction: Input, + mode: HighZ, + } +} +``` + +#tr(( +en: [ + The GpioConfig we return never exists at runtime. Calling this function + will generally boil down to a single assembly instruction - storing a + constant register value to a register location. This means that the type + state interface we've developed is a zero cost abstraction - it uses no + more CPU, RAM, or code space tracking the state of `GpioConfig`, and + renders to the same machine code as a direct register access. +], +de: [ + Das von uns zurückgegebene `GpioConfig`-Objekt existiert zur Laufzeit + nicht. Der Aufruf dieser Funktion läuft im Wesentlichen auf einen + einzigen Assembler-Befehl hinaus: das Speichern eines konstanten + Registerwerts an einer bestimmten Registeradresse. Das bedeutet, dass + die von uns entwickelte „Type-State"-Schnittstelle eine Abstraktion ohne + Laufzeitkosten (Zero-Cost-Abstraction) darstellt -- sie verbraucht weder + zusätzliche CPU- oder RAM-Ressourcen noch zusätzlichen Programmspeicher + für die Zustandsverwaltung von `GpioConfig` und führt zu demselben + Maschinencode wie ein direkter Registerzugriff. +], +ja: [ + 実行時、返り値のGpioConfigは、存在しません。この関数を呼び出すと、通常、1つのアセンブリ命令にまとめられます。 + そのアセンブリ命令は、定数のレジスタ値を、レジスタの位置へ格納します。 + これは、開発した型状態インタフェースが、ゼロコスト抽象化であることを意味します。 + `GpioConfig`の状態を追跡するために、余分なCPU、RAM、コード領域を使用せず、直接レジスタアクセスするのと同じ機械語を表します。 +], +zh: [ + 我们返回的GpioConfig在运行时并不存在。对这个函数的调用通常会被归纳为一条汇编指令 + - 把一个常量寄存器值存进一个寄存器里。这意味着我们开发的类型状态接口是一个零成本抽象 + - 它不会用更多的CPU,RAM,或者代码空间去跟踪`GpioConfig`的状态,会被渲染成和直接访问寄存器一样的机器码。 +])) + += #tr(( + en: [Nesting], + de: [Verschachtelung], + ja: [ネスト], + zh: [嵌套], +)) + +#tr(( +en: [ + In general, these abstractions may be nested as deeply as you would + like. As long as all components used are zero sized types, the whole + structure will not exist at runtime. +], +de: [ + Im Allgemeinen lassen sich diese Abstraktionen beliebig tief + verschachteln. Solange es sich bei allen verwendeten Komponenten um + Typen ohne Größe (Zero-Sized Types) handelt, existiert die gesamte + Struktur zur Laufzeit nicht. +], +ja: [ + 通常、これらの抽象化は、望み通りの深さでネストされます。使用される全てのコンポーネントが、ゼロサイズの型である限り、実行時には、構造体全体が存在しません。 +], +zh: [ + 通常,这些抽象可能会被深深地嵌套起来。一旦结构体使用的所有的组件是零大小类型的,整个结构体将不会在运行时存在。 +])) + +#tr(( +en: [ + For complex or deeply nested structures, it may be tedious to define all + possible combinations of state. In these cases, macros may be used to + generate all implementations. +], +de: [ + Bei komplexen oder tief verschachtelten Strukturen kann es mühsam sein, + alle möglichen Zustandskombinationen zu definieren. In solchen Fällen + lassen sich Makros verwenden, um sämtliche Implementierungen zu + generieren. +], +ja: [ + 複雑な構造体や深くネストした構造体については、全ての取り得る状態の組み合わせを定義することは、面倒です。 + このような場合、全ての実装を生成するために、マクロが利用できます。 +], +zh: [ + 对于复杂或者深度嵌套的结构体,定义所有可能的状态组合可能很乏味。在这些例子中,宏可能可以被用来生成所有的实现。 +])) diff --git a/typ/unsorted/index.typ b/typ/unsorted/index.typ new file mode 100644 index 00000000..513a8bd3 --- /dev/null +++ b/typ/unsorted/index.typ @@ -0,0 +1,8 @@ +#import "../config.typ": * + +#h1((en: [Unsorted topics], + de: [Unsortierte Themen], + ja: [未分類のトピック], + zh: [没有排序的主题], +)) + diff --git a/typ/unsorted/math.typ b/typ/unsorted/math.typ new file mode 100644 index 00000000..97f29e4c --- /dev/null +++ b/typ/unsorted/math.typ @@ -0,0 +1,128 @@ +#import "../config.typ": * + +#h1((en: [Performing math functionality with `#[no_std]`], + de: [Mathematische Funktionen mit `#[no_std]` nutzen], + zh: [在`#[no_std]`下执行数学运算], +), offset: whole) + +#tr(( +en: [ + If you want to perform math related functionality like calculating the + squareroot or the exponential of a number and you have the full standard + library available, your code might look like this: +], +de: [ + Wenn Sie mathematische Operationen durchführen möchten -- wie etwa die + Berechnung der Quadratwurzel aus der Exponentialfunktion einer Zahl -- + und Ihnen die vollständige Standardbibliothek zur Verfügung steht, + könnte Ihr Code folgendermaßen aussehen: +], +zh: [ + 如果你想要执行数学相关的函数,像是计算平方根或者一个数的指数并有完整的标准库支持,代码可能看起来像这样: +])) + +#raw(block: true, lang: "rust", +"//! " + ts(( + en: "Some mathematical functions with standard support available", + de: "Einige mathematische Funktionen mit Standardunterstützung verfügbar", + zh: "可用一些标准支持的数学函数", + )) + " + +fn main() { + let float: f32 = 4.82832; + let floored_float = float.floor(); + + let sqrt_of_four = floored_float.sqrt(); + + let sinus_of_four = floored_float.sin(); + + let exponential_of_four = floored_float.exp(); + println!(\"Floored test float {} to {}\", float, floored_float); + println!(\"The square root of {} is {}\", floored_float, sqrt_of_four); + println!(\"The sinus of four is {}\", sinus_of_four); + println!( + \"The exponential of four to the base e is {}\", + exponential_of_four + ) +} +") + +#let ln_libm = link("https://crates.io/crates/libm")[`libm`] +#tr(( +en: [ + Without standard library support, these functions are not available. An + external crate like #ln_libm can + be used instead. The example code would then look like this: +], +de: [ + Ohne Unterstützung durch die Standardbibliothek stehen diese Funktionen + nicht zur Verfügung. Stattdessen kann ein externes Crate wie + #ln_libm verwendet werden. Der + Beispielcode sähe dann folgendermaßen aus: +], +zh: [ + 没有标准库支持的时候,这些函数不可用。反而可以使用像是#ln_libm;这样一个外部库。示例的代码将会看起来像这样: +])) + +#raw(block: true, lang: "rust", +"#![no_main] +#![no_std] + +use panic_halt as _; + +use cortex_m_rt::entry; +use cortex_m_semihosting::{debug, hprintln}; +use libm::{exp, floorf, sin, sqrtf}; + +#[entry] +fn main() -> ! { + let float = 4.82832; + let floored_float = floorf(float); + + let sqrt_of_four = sqrtf(floored_float); + + let sinus_of_four = sin(floored_float.into()); + + let exponential_of_four = exp(floored_float.into()); + hprintln!(\"Floored test float {} to {}\", float, floored_float).unwrap(); + hprintln!(\"The square root of {} is {}\", floored_float, sqrt_of_four).unwrap(); + hprintln!(\"The sinus of four is {}\", sinus_of_four).unwrap(); + hprintln!( + \"The exponential of four to the base e is {}\", + exponential_of_four + ) + .unwrap(); + // " + ts(( + en: "exit QEMU + // NOTE do not run this on hardware; it can corrupt OpenOCD state", + de: "exit QEMU + // HINWEIS: Fuehren Sie dies nicht auf der Hardware aus; es kann den + // OpenOCD-Zustand beschaedigen.", + zh: "退出QEMU + // 注意不要在硬件上使用这个; 它能破坏OpenOCD的状态" + )) + " + // debug::exit(debug::EXIT_SUCCESS); + + loop {} +} +") + +#tr(( +en: [ + If you need to perform more complex operations like DSP signal + processing or advanced linear algebra on your MCU, the following crates + might help you +], +de: [ + Wenn Sie komplexere Operationen wie DSP-Signalverarbeitung oder + fortgeschrittene lineare Algebra auf Ihrem Mikrocontroller durchführen + müssen, könnten Ihnen die folgenden Crates weiterhelfen. +], +zh: [ + 如果需要在MCU上执行更复杂的操作,像是DSP信号处理或者更高级的线性代数,下列的crates可能可以帮到你 +])) +- #link("https://github.com/jacobrosenthal/cmsis-dsp-sys")[CMSIS DSP library binding] +- #link("https://crates.io/crates/constgebra")[`constgebra`] +- #link("https://github.com/tarcieri/micromath")[`micromath`] +- #link("https://crates.io/crates/microfft")[`microfft`] +- #link("https://github.com/dimforge/nalgebra")[`nalgebra`] diff --git a/typ/unsorted/speed-vs-size.typ b/typ/unsorted/speed-vs-size.typ new file mode 100644 index 00000000..b4d8186d --- /dev/null +++ b/typ/unsorted/speed-vs-size.typ @@ -0,0 +1,625 @@ +#import "../config.typ": * + +#h1((en: [Optimizations: the speed size tradeoff], + de: [Optimierungen: Der Kompromiss zwischen Geschwindigkeit und Größe], + ja: [最適化:速度とサイズのトレードオフ], + zh: [优化: 速度与大小之间的博弈], +), offset: whole) + +#tr(( +en: [ + Everyone wants their program to be super fast and super small but it's + usually not possible to have both characteristics. This section + discusses the different optimization levels that `rustc` provides and + how they affect the execution time and binary size of a program. +], +de: [ + Jeder möchte, dass sein Programm extrem schnell und extrem klein ist, + doch meist lassen sich nicht beide Eigenschaften zugleich verwirklichen. + Dieser Abschnitt behandelt die verschiedenen Optimierungsstufen von + `rustc` und deren Auswirkungen auf die Ausführungszeit sowie die Größe + der Binärdatei eines Programms. +], +ja: [ + 誰もがプログラムを超高速で超小さくしたいと願いますが、両方の特性を最大化することはできません。 + このセクションは、`rustc`が提供する異なる最適化レベルについて、どのようにプログラムの実行時間とバイナリサイズに影響するかを説明します。 +], +zh: [ + 每个人都想要程序变得即快又小,但是同时满足这两个条件是不可能的。这部分讨论`rustc`提供的不同的优化等级,和它们是如何影响执行时间和一个程序的二进制项的大小。 +])) + += #tr(( + en: [No optimizations], + de: [Keine Optimierungen], + ja: [最適化なし], + zh: [无优化], +)) + +#tr(( +en: [ + This is the default. When you call `cargo build` you use the development + (AKA `dev`) profile. This profile is optimized for debugging so it + enables debug information and does _not_ enable any optimizations, + i.e.~it uses `-C opt-level = 0`. +], +de: [ + Dies ist die Standardeinstellung. Wenn Sie `cargo build` aufrufen, wird + das Entwicklungs-Profil (auch bekannt als `dev`-Profil) verwendet. Da + dieses Profil für das Debugging optimiert ist, werden + Debug-Informationen aktiviert, jedoch _keinerlei_ Optimierungen + vorgenommen; es wird also `-C opt-level=0` verwendet. +], +ja: [ + これはデフォルトです。`cargo build`を実行する場合、開発(別名`dev`)プロファイルを使います。 + このプロファイルはデバッグに最適化されています。そのため、デバッグ情報が有効化されており、最適化は一切有効化されて_いません_。 + つまり、`-C opt-level = 0`を使用します。 +], +zh: [ + 这是默认的。当你调用`cargo build`时,你使用的是development(又叫`dev`)配置。这个配置优化的目的是为了调试,因此它使能了调试信息且_关闭_了所有优化,i.e.~它使用 + `-C opt-level = 0` 。 +])) + +#tr(( +en: [ + At least for bare metal development, debuginfo is zero cost in the sense + that it won't occupy space in Flash / ROM so we actually recommend that + you enable debuginfo in the release profile -- it is disabled by + default. That will let you use breakpoints when debugging release builds. +], +de: [ + Zumindest bei der Bare-Metal-Entwicklung verursachen Debug-Informationen + keine Kosten im Sinne von Speicherplatzbedarf im Flash- oder + ROM-Speicher. Daher empfehlen wir, Debug-Informationen auch im + Release-Profil zu aktivieren -- standardmäßig sind sie dort deaktiviert. + Dies ermöglicht Ihnen die Verwendung von Breakpoints beim Debuggen von + Release-Builds. +], +ja: [ + 少なくともベアメタルの開発では、デバッグ情報はある意味ゼロコストです。 + デバッグ情報は、Flash/ROMの容量を使いません。そのため、リリースプロファイルで、デフォルトで無効化されているデバッグ情報を有効化することをお勧めします。 + これにより、リリースビルドをデバッグする時、ブレイクポイントを使うことができます。 +], +zh: [ + 至少对于裸机开发来说,调试信息不会占用Flash/ROM中的空间,意味着在这种情况下,调试信息是零开销的,因此实际上我们推荐你在release配置中使能调试信息 + -- 默认它被关闭了。那会让你调试release版本的固件时可以使用断点。 +])) + +#raw(block: true, lang: "toml", +"[profile.release] +# " + ts(( + en: "symbols are nice and they don't increase the size on Flash", + de: "Symbole sind praktisch und vergroessern die Dateigroesse im Flash nicht", + ja: "シンボルは素晴らしく、Flashのサイズを増やしません", + zh: "调试符号很好且它们不会增加Flash上的大小", + )) + " +debug = true +") + +#tr(( +en: [ + No optimizations is great for debugging because stepping through the + code feels like you are executing the program statement by statement, + plus you can `print` stack variables and function arguments in GDB. When + the code is optimized, trying to print variables results in + `$0 = ` being printed. +], +de: [ + Der Verzicht auf Optimierungen ist ideal für das Debugging, da sich das + schrittweise Durchlaufen des Codes anfühlt, als würde man das Programm + Anweisung für Anweisung ausführen; zudem lassen sich Stack-Variablen und + Funktionsargumente in GDB per `print` ausgeben. Bei optimiertem Code + führt der Versuch, Variablen auszugeben, hingegen zur Meldung + `$0 = `. +], +ja: [ + 最適化しないことはデバッグでは重要です。コードをステップ実行する時、プログラムをステートメントごとに実行しているように感じられるからです。 + さらに、スタックの変数や関数の引数をGDBで`print`することができます。 + コードが最適化されると、変数を表示しようとしても、`$0 = `と表示されます。 +], +zh: [ + 无优化对于调试来说是最好的选择,因为单步调试代码感觉像是你正在逐条语句地执行程序,且你能在GDB中`print`栈变量和函数参数。当代码被优化了,尝试打印变量会导致`$0 = `被打印出来。 +])) + +#tr(( +en: [ + The biggest downside of the `dev` profile is that the resulting binary + will be huge and slow. The size is usually more of a problem because + unoptimized binaries can occupy dozens of KiB of Flash, which your + target device may not have -- the result: your unoptimized binary + doesn't fit in your device! +], +de: [ + Der größte Nachteil des `dev`-Profils besteht darin, dass die + resultierende Binärdatei sehr groß und langsam ist. Meist wiegt vor + allem die Größe schwer, da nicht optimierte Binärdateien Dutzende KiB an + Flash-Speicher belegen können -- Speicherplatz, über den das Zielgerät + womöglich gar nicht verfügt. Die Folge: Die nicht optimierte Binärdatei + passt nicht auf das Gerät! +], +ja: [ + `dev`プロファイルの最大の欠点は、バイナリが大きく、遅いことです。 + バイナリサイズは通常、より問題となります。最適化されていないバイナリは数十KiBもFlashを専有するからです。 + ターゲットデバイスは、数十KiBものFlashを持っていないかもしれず、最適化されていないバイナリは、デバイス内に納まりません。 +], +zh: [ + `dev`配置最大的缺点就是最终的二进制项将会变得巨大且缓慢。大小通常是一个更大的问题,因为未优化的二进制项会占据大量KiB的Flash,你的目标设备可能没这么多Flash + -- 结果: 你未优化的二进制项无法烧录进你的设备中! +])) + +#tr(( +en: [ + Can we have smaller, debugger friendly binaries? Yes, there's a trick. +], +de: [ + Gibt es eine Möglichkeit, kleinere und dennoch für das Debugging + geeignete Binärdateien zu erhalten? Ja, es gibt einen Trick. +], +ja: [ + デバッガで扱いやすい、小さなバイナリを作ることができるのでしょうか?できます。良いやり方があります。 +], +zh: [ + 我们可以有更小的,调试友好的二进制项吗?是的,这里有一个技巧。 +])) + +== #tr(( + en: [Optimizing dependencies], + de: [Optimierung der Abhängigkeiten], + ja: [依存関係の最適化], + zh: [优化依赖], +)) + +#let url_overrides = "https://doc.rust-lang.org/cargo/reference/profiles.html#overrides" +#tr(( +en: [ + There's a Cargo feature named #link(url_overrides)[`profile-overrides`] + that lets you override the optimization level of dependencies. You can + use that feature to optimize all dependencies for size while keeping the + top crate unoptimized and debugger friendly. +], +de: [ + Cargo bietet mit #link(url_overrides)[`Profil-Überschreibung`] + eine Funktion, mit der Sie den Optimierungsgrad von Abhängigkeiten + überschreiben können. So lassen sich alle Abhängigkeiten hinsichtlich + ihrer Größe optimieren, während die oberste Crate unoptimiert und + debuggfreundlich bleibt. +], +ja: [ + nightlyでは、#link(url_overrides)[`profile-overrides`]と呼ばれるCargoフィーチャがあります。これは、依存関係の最適化レベルをオーバーライドします。 + このフィーチャを使って、全ての依存クレートのサイズを最適化しながら、トップクレートを最適化しないでデバッガで扱いやすくすることができます。。 +], +zh: [ + 这里有个名为#link(url_overrides)[`profile-overrides`]的Cargo + feature,其可以让你覆盖依赖项的优化等级。你能使用这个feature去优化所有依赖的大小,而保持顶层的crate没有被优化以致调试起来友好。 +])) + +#tr(( +en: [ + Beware that generic code can sometimes be optimized alongside the crate + where it is instantiated, rather than the crate where it is defined. If + you create an instance of a generic struct in your application and find + that it pulls in code with a large footprint, it may be that increasing + the optimisation level of the relevant dependencies has no effect. +], +de: [ + Beachten Sie, dass generischer Code manchmal zusammen mit der Crate + optimiert werden kann, in der er instanziiert wird, anstatt mit der + Crate, in der er definiert ist. Wenn Sie in Ihrer Anwendung eine Instanz + einer generischen Struktur erstellen und feststellen, dass diese Code + mit großem Speicherbedarf einbindet, kann es sein, dass eine Erhöhung + des Optimierungsgrads der relevanten Abhängigkeiten keine Wirkung zeigt. +], +zh: [ + 需要知道,泛型代码有时是在它被实例化的库中被优化的,而不是它被定义的地方.如果你在你的应用中生成了一个泛型结构体的实例, + 并且发现它让代码体积变得更大,那可能是因为相关的依赖的优化等级的增加没有造成影响. +])) + +#tr(( +en: [ + Here's an example: +], +de: [ + Hier ist ein Beispiel: +], +ja: [ + 例を示します。 +], +zh: [ + 这是一个示例: +])) + +```toml +# Cargo.toml +[package] +name = "app" +# .. + +[profile.dev.package."*"] # + +opt-level = "z" # + +``` + +#tr(( +en: [ + Without the override: +], +de: [ + Ohne die Überschreibung: +], +ja: [ + オーバーライドなしでは、次の通りです。 +], +zh: [ + 没有覆盖: +])) + +```text +$ cargo size --bin app -- -A +app : +section size addr +.vector_table 1024 0x8000000 +.text 9060 0x8000400 +.rodata 1708 0x8002780 +.data 0 0x20000000 +.bss 4 0x20000000 +``` + +#tr(( +en: [ + With the override: +], +de: [ + Mit der Überschreibung +], +ja: [ + オーバーライドをすると、以下のようになります。 +], +zh: [ + 有覆盖: +])) + +```text +$ cargo size --bin app -- -A +app : +section size addr +.vector_table 1024 0x8000000 +.text 3490 0x8000400 +.rodata 1100 0x80011c0 +.data 0 0x20000000 +.bss 4 0x20000000 +``` + +#tr(( +en: [ + That's a 6 KiB reduction in Flash usage without any loss in the + debuggability of the top crate. If you step into a dependency then + you'll start seeing those `` messages again but + it's usually the case that you want to debug the top crate and not the + dependencies. And if you _do_ need to debug a dependency then you + can use the `profile-overrides` feature to exclude a particular + dependency from being optimized. See example below: +], +de: [ + Das bedeutet eine Verringerung des Flash-Speicherverbrauchs um 6 KiB, + ohne die Debug-Fähigkeit des Haupt-Crates zu beeinträchtigen. Wenn man + in eine Abhängigkeit hineinspringt, erscheinen zwar wieder die Meldungen + ``, doch in der Regel möchte man das Haupt-Crate + debuggen und nicht die Abhängigkeiten. Sollte es dennoch erforderlich + sein, eine Abhängigkeit zu debuggen, lässt sich die Funktion + `profile-overrides` nutzen, um diese spezifische Abhängigkeit von der + Optimierung auszunehmen. Siehe dazu das folgende Beispiel: +], +ja: [ + トップクレートのデバッグ性を失うことなしに、Flash使用量を6KiB減らしています。 + 依存クレートの中に足を踏み入れると、``のメッセージを目にするでしょう。 + しかし、依存クレートではなく、トップクレートをデバッグしたい場合がほとんどでしょう。 + 依存クレートをデバッグする必要が_ある_場合、特定の依存クレートを最適化から除外するために、`profile-overrides`フィーチャを使えます。 + 例えば、以下のようになります。 +], +zh: [ + 在Flash的使用上减少了6KiB,而不会损害顶层crate的可调试性。如果你步进一个依赖项,然后你将开始再次看到那些``信息,但是通常的情况下你只想调试顶层的crate而不是依赖项。如果你 + _需要_ 调试一个依赖项,那么你可以使用`profile-overrides` + feature去防止一个特定的依赖项被优化。看下面的例子: +])) + +#raw(block: true, lang: "toml", +"# .. + +# " + ts(( + en: "don't optimize the `cortex-m-rt` crate", + de: "Optimiere das `cortex-m-rt`-Crate nicht", + ja: "`cortex-m-rt`クレートは最適化しません", + zh: "不要优化`cortex-m-rt` crate", + )) + " +[profile.dev.package.cortex-m-rt] # + +opt-level = 0 # + + +# " + ts(( + en: "but do optimize all the other dependencies", + de: "optimieren Sie jedoch alle anderen Abhaengigkeiten", + ja: "しかし、他の依存クレートは最適化します", + zh: "但是优化所有其它依赖项", + )) + " +[profile.dev.package.\"*\"] +codegen-units = 1 # " + ts(( + en: "better optimizations", + )) + " +opt-level = \"z\" +") + +#tr(( +en: [ + Now the top crate and `cortex-m-rt` are debugger friendly! +], +de: [ + Jetzt sind das Top-Level-Crate und `cortex-m-rt` debuggerfreundlich! +], +ja: [ + これで、トップクレートと`cortex-m-rt`クレートはデバッガで扱いやすくなります! +], +zh: [ + 现在顶层的crate和`cortex-m-rt`对调试器很友好! +])) + += #tr(( + en: [Optimize for speed], + de: [Auf Geschwindigkeit optimieren], + ja: [速度の最適化], + zh: [优化速度], +)) + +#tr(( +en: [ + As of 2018-09-18 `rustc` supports three "optimize for speed" levels: + `opt-level = 1`, `2` and `3`. When you run `cargo build --release` you + are using the release profile which defaults to `opt-level = 3`. +], +de: [ + Seit dem 18.09.2018 unterstützt `rustc` drei Stufen der + Geschwindigkeitsoptimierung: `opt-level = 1`, `2` und `3`. Beim + Ausführen von `cargo build --release` wird das Release-Profil verwendet, + das standardmäßig auf `opt-level = 3` eingestellt ist. +], +ja: [ + 2018-09-18の`rustc`は、3つの「速度最適化」を提供しています。`opt-level = 1`、`2`と`3`です。 + `cargo build --release`を実行した時、デフォルトでは`opt-level = 3`のリリースプロファイルを使います。 +], +zh: [ + 自2018-09-18开始 `rustc` 支持三个 "优化速度" 的等级: `opt-level = 1`, + `2` 和 `3` 。当你运行 `cargo build --release` + 时,你正在使用的是release配置,其默认是 `opt-level = 3` 。 +])) + +#tr(( +en: [ + Both `opt-level = 2` and `3` optimize for speed at the expense of binary + size, but level `3` does more vectorization and inlining than level `2`. + In particular, you'll see that at `opt-level` equal to or greater than + `2` LLVM will unroll loops. Loop unrolling has a rather high cost in + terms of Flash / ROM (e.g.~from 26 bytes to 194 for a zero this array + loop) but can also halve the execution time given the right conditions + (e.g.~number of iterations is big enough). +], +de: [ + Sowohl `opt-level = 2` als auch `3` optimieren auf Geschwindigkeit + zulasten der Binärgröße; allerdings führt Stufe `3` mehr Vektorisierung + und Inlining durch als Stufe `2`. Insbesondere ist zu beobachten, dass + LLVM bei einem `opt-level` von 2 oder höher Schleifen entrollt („Loop + Unrolling"). Das Entrollen von Schleifen ist recht kostspielig im + Hinblick auf den Flash-/ROM-Speicherbedarf (z. B. Anstieg von 26 auf 194 + Bytes für eine Schleife zum Nullsetzen eines Arrays), kann aber unter + geeigneten Bedingungen (etwa bei einer ausreichend hohen Anzahl von + Iterationen) die Ausführungszeit halbieren. +], +ja: [ + `opt-level = 2`と`3`は、バイナリサイズを犠牲にして、速度を最適化します。レベル`3`はレベル`2`より、ベクトル化とインライン化を行います。 + 特に、`opt-level`が`2`以上の場合、LLVMがループを展開するのがわかるでしょう。 + ループ展開は、Flash/ROMの観点からはよりコストが高いです(例えば、配列のループをゼロにする場合、26バイトから194バイトまで増加します)。 + しかし、適切な条件では、実行時間が半分になります(例えば、イテレーションの回数が十分大きい場合)。 +], +zh: [ + `opt-level = 2` 和 `3` + 都以二进制项大小为代价优化速度,但是等级`3`比等级`2`做了更多的向量化和内联。特别是,你将看到在`opt-level`等于或者大于`2`时LLVM将展开循环。循环展开在 + Flash / ROM 方面的成本相当高(e.g.~from 26 bytes to 194 for a zero this + array loop)但是如果条件合适(迭代次数足够大),也可以将执行时间减半。 +])) + +#tr(( +en: [ + Currently there's no way to disable loop unrolling in `opt-level = 2` + and `3` so if you can't afford its cost you should optimize your program + for size. +], +de: [ + Derzeit gibt es keine Möglichkeit, das Entrollen von Schleifen bei + `opt-level = 2` und `3` zu deaktivieren; wenn Sie sich diesen + Speicheraufwand also nicht leisten können, sollten Sie Ihr Programm + stattdessen auf eine geringe Größe hin optimieren. +], +ja: [ + 現在、`opt-level = 2`と`3`でループ展開を無効化する方法はありません。 + ループ展開のコストを払うことができない場合、プログラムサイズの最適化をするべきです。 +], +zh: [ + 现在还没有办法在`opt-level = 2`和`3`的情况下关闭循环展开,因此如果你不能接受它的开销,你应该选择优化你的程序的大小。 +])) + += #tr(( + en: [Optimize for size], + de: [Nach Größe optimieren], + ja: [サイズの最適化], + zh: [优化大小], +)) + +#tr(( +en: [ + As of 2018-09-18 `rustc` supports two "optimize for size" levels: + `opt-level = "s"` and `"z"`. These names were inherited from clang / + LLVM and are not too descriptive but `"z"` is meant to give the idea + that it produces smaller binaries than `"s"`. +], +de: [ + Seit dem 18.09.2018 unterstützt `rustc` zwei Stufen zur + Größenoptimierung: `opt-level = "s"` und `"z"`. Diese Bezeichnungen + wurden von Clang/LLVM übernommen und sind nicht besonders + aussagekräftig; allerdings soll das `"z"` signalisieren, dass damit + kleinere Binärdateien erzeugt werden als mit `"s"`. +], +ja: [ + 2018-09-18の`rustc`は、2つの`サイズ最適化`を提供しています。`opt-level = "s"`と`"z"`です。 + これらの名前は、clang / LLVMから受け継いでおり、意味がわかりにくいです。 + `"z"`は、`"s"`より小さなバイナリを作る意図を意味します。 +], +zh: [ + 自2018-09-18开始`rustc`支持两个"优化大小"的等级: `opt-level = "s"` 和 + `"z"` 。这些名字传承自 clang / LLVM + 且不具有描述性,但是`"z"`意味着它产生的二进制文件比`"s"`更小。 +])) + +#tr(( +en: [ + If you want your release binaries to be optimized for size then change + the `profile.release.opt-level` setting in `Cargo.toml` as shown below. +], +de: [ + Wenn Ihre Release-Binärdateien hinsichtlich der Größe optimiert werden + sollen, ändern Sie die Einstellung `profile.release.opt-level` in der + Datei `Cargo.toml` wie unten dargestellt. +], +ja: [ + リリースバイナリのサイズを最適化したい場合、`Cargo.toml`の`profile.release.opt-level`設定を下記の通り変更します。 +], +zh: [ + 如果你想要发布一个优化了大小的二进制项,那么改变下面展示的`Cargo.toml`中的`profile.release.opt-level`配置。 +])) + +#raw(block: true, lang: "toml", +"[profile.release] +# " + ts(( + en: "or \"z\"", + de: "oder \"z\"", + ja: "または\"z\"", + )) + " +opt-level = \"s\" +") + +#tr(( +en: [ + These two optimization levels greatly reduce LLVM's inline threshold, a + metric used to decide whether to inline a function or not. One of Rust + principles are zero cost abstractions; these abstractions tend to use a + lot of newtypes and small functions to hold invariants (e.g.~functions + that borrow an inner value like `deref`, `as_ref`) so a low inline + threshold can make LLVM miss optimization opportunities (e.g.~eliminate + dead branches, inline calls to closures). +], +de: [ + Diese beiden Optimierungsstufen senken den Inline-Schwellenwert von LLVM + erheblich -- einen Kennwert, der darüber entscheidet, ob eine Funktion + „geinlined" (direkt an der Aufrufstelle eingebettet) wird oder nicht. + Eines der Prinzipien von Rust sind „Zero-Cost-Abstractions" + (Abstraktionen ohne Laufzeitkosten); diese nutzen häufig sogenannte + „Newtypes" und kleine Funktionen zur Wahrung von Invarianten (z. B. + Funktionen wie `deref` oder `as_ref`, die einen inneren Wert ausleihen). + Ein niedriger Inline-Schwellenwert kann daher dazu führen, dass LLVM + Optimierungsmöglichkeiten verpasst (etwa das Entfernen von nicht + erreichbaren Programmzweigen oder das Inlinen von Closure-Aufrufen). +], +ja: [ + これらの2つの最適化レベルは、LLVMのインラインしきい値を大幅に減らします。 + インラインしきい値は、関数をインライン化するか否かを決めるために使われる基準値です。 + Rustの原則の1つは、ゼロコスト抽象化です。 + これらの抽象化は、不変条件を保持するため、多くの新しい型と小さな関数を使う傾向にあります + (例えば、`deref`や`as_ref`のような内部の値を借用するための関数)。 + そのため、インラインしきい値を低くすると、LLVMが最適化の機会を失います + (例えば、不要な分岐を削除したり、クロージャをインライン呼び出しにする、など)。 +], +zh: [ + 这两个优化等级极大地减小了LLVM的内联阈值,一个用来决定是否内联或者不内联一个函数的度量。Rust其中一个概念是零成本抽象;这些抽象趋向于去使用许多新类型和小函数去保持不变量(e.g.~像是`deref`,`as_ref`这样借用内部值的函数)因此一个低内联阈值会使LLVM失去优化的机会(e.g.~去掉死分支(dead + branches),内联对闭包的调用)。 +])) + +#tr(( +en: [ +When optimizing for size you may want to try increasing the inline +threshold to see if that has any effect on the binary size. The +recommended way to change the inline threshold is to append the +`-C inline-threshold` flag to the other rustflags in +`.cargo/config.toml`. +], +de: [ + Bei der Optimierung auf eine geringe Binärgröße kann es sinnvoll sein, + den Inline-Schwellenwert zu erhöhen und zu prüfen, ob sich dies auf die + Größe der Binärdatei auswirkt. Die empfohlene Methode zur Änderung + dieses Schwellenwerts besteht darin, das Flag `-C inline-threshold` zu + den übrigen `rustflags` in der Datei `.cargo/config.toml` hinzuzufügen. +], +ja: [ + サイズの最適化を行っている時、バイナリサイズに影響があるかどうかを見るために、インラインしきい値を増やしたいかもしれません。 + インラインしきい値を変更するお勧めの方法は、`.cargo/config`内のrustflagsに`-C inline-threshold`フラグを追加することです。 +], +zh: [ + 当优化大小时,你可能想要尝试增加内联阈值去观察是否会对你的二进制项的大小有影响。推荐的改变内联阈值的方法是在`.cargo/config.toml`中往其它rustflags后插入`-C inline-threshold` +])) + +#raw(block: true, lang: "toml", +"# .cargo/config.toml +# " + ts(( + en: "this assumes that you are using the cortex-m-quickstart template", + de: "Dies setzt voraus, dass Sie die cortex-m-quickstart-Vorlage verwenden", + ja: "cortex-m-quickstartテンプレートを使っていることを想定しています", + zh: "这里假设你正在使用cortex-m-quickstart模板", + )) + " +[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))'] +rustflags = [ + # .. + \"-C\", \"inline-threshold=123\", # + +] +") + +#let url_opt_lvls = "https://github.com/rust-lang/rust/blob/1.29.0/src/librustc_codegen_llvm/back/write.rs#L2105-L2122" +#tr(( +en: [ + What value to use? + #link(url_opt_lvls)[As of 1.29.0 these are the inline thresholds that the different optimization levels use]: + - `opt-level = 3` uses 275 + - `opt-level = 2` uses 225 + - `opt-level = "s"` uses 75 + - `opt-level = "z"` uses 25 +], +de: [ + Welchen Wert verwenden? + #link(url_opt_lvls)[Ab Version 1.29.0 gelten für die verschiedenen Optimierungsstufen folgende Inline-Schwellenwerte]: + - `opt-level = 3` verwendet 275 + - `opt-level = 2` verwendet 225 + - `opt-level = "s"` verwendet 75 + - `opt-level = "z"` verwendet 25 +], +ja: [ + この値は何に使われるのでしょうか? + #link(url_opt_lvls)[1.29.0では、下記の値は、異なる最適化レベルで使われるインラインしきい値です] + - `opt-level = 3`は275を使います + - `opt-level = 2`は225を使います + - `opt-level = "s"`は75を使います + - `opt-level = "z"`は25を使います +], +zh: [ + 用什么值?#link(url_opt_lvls)[从1.29.0开始,这些是不同优化级别使用的内联阈值]: + - `opt-level = 3` 使用 275 + - `opt-level = 2` 使用 225 + - `opt-level = "s"` 使用 75 + - `opt-level = "z"` 使用 25 +])) + +#tr(( +en: [ + You should try `225` and `275` when optimizing for size. +], +de: [ + Du solltest `225` und `275` ausprobieren, wenn du auf die Größe + optimierst. +], +ja: [ + サイズの最適化をするときは、`225`と`275`を試してみるべきです。 +], +zh: [ + 当优化大小时,你应该尝试`225`和`275` 。 +]))